make running snippet more convenient

This commit is contained in:
lollipopkit
2023-01-27 23:06:47 +08:00
parent b6ab4b7fde
commit 913ce312de
11 changed files with 148 additions and 63 deletions

View File

@@ -24,12 +24,11 @@ class DropdownBtnItem {
}
class ServerTabMenuItems {
static const List<DropdownBtnItem> firstItems = [sftp, snippet, pkg, docker];
static const List<DropdownBtnItem> firstItems = [sftp, pkg, docker];
static const List<DropdownBtnItem> secondItems = [edit];
static const sftp =
DropdownBtnItem(text: 'SFTP', icon: Icons.insert_drive_file);
static const snippet = DropdownBtnItem(text: 'Snippet', icon: Icons.label);
static const pkg =
DropdownBtnItem(text: 'Pkg', icon: Icons.system_security_update);
static const docker =

View File

@@ -301,12 +301,13 @@ class ServerProvider extends BusyProvider {
info.status.memory = mem;
}
Future<String?> runSnippet(ServerPrivateInfo spi, Snippet snippet) async {
return await _servers
.firstWhere((element) => element.info == spi)
.client!
.run(snippet.script)
.string;
Future<String?> runSnippet(String id, Snippet snippet) async {
final client =
_servers.firstWhere((element) => element.info.id == id).client;
if (client == null) {
return null;
}
return await client.run(snippet.script).string;
}
}

View File

@@ -61,6 +61,7 @@ class MessageLookup extends MessageLookupByLibrary {
"aboutThanks": MessageLookupByLibrary.simpleMessage(
"\nAll rights reserved.\n\nThanks to the following people who participated in the test."),
"addAServer": MessageLookupByLibrary.simpleMessage("add a server"),
"addOne": MessageLookupByLibrary.simpleMessage("Add one"),
"addPrivateKey":
MessageLookupByLibrary.simpleMessage("Add private key"),
"alreadyLastDir":

View File

@@ -61,6 +61,7 @@ class MessageLookup extends MessageLookupByLibrary {
"aboutThanks":
MessageLookupByLibrary.simpleMessage("\n保留所有权利。\n\n感谢以下参与软件测试的各位。"),
"addAServer": MessageLookupByLibrary.simpleMessage("添加服务器"),
"addOne": MessageLookupByLibrary.simpleMessage("前去新增"),
"addPrivateKey": MessageLookupByLibrary.simpleMessage("添加一个私钥"),
"alreadyLastDir": MessageLookupByLibrary.simpleMessage("已经是最上层目录了"),
"appPrimaryColor": MessageLookupByLibrary.simpleMessage("App主要色"),

View File

@@ -1520,6 +1520,16 @@ class S {
args: [],
);
}
/// `Add one`
String get addOne {
return Intl.message(
'Add one',
name: 'addOne',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@@ -145,5 +145,6 @@
"path": "Path",
"goto": "Go to",
"showDistLogo": "Show distribution logo",
"onServerDetailPage": "On server detail page"
"onServerDetailPage": "On server detail page",
"addOne": "Add one"
}

View File

@@ -145,5 +145,6 @@
"path": "路径",
"goto": "前往",
"showDistLogo": "显示发行版 Logo",
"onServerDetailPage": "在服务器详情页"
"onServerDetailPage": "在服务器详情页",
"addOne": "前去新增"
}

View File

@@ -10,7 +10,9 @@ import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/server_status.dart';
import 'package:toolbox/data/provider/server.dart';
import 'package:toolbox/data/provider/snippet.dart';
import 'package:toolbox/data/res/color.dart';
import 'package:toolbox/data/res/font_style.dart';
import 'package:toolbox/generated/l10n.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/view/page/pkg.dart';
@@ -18,7 +20,8 @@ import 'package:toolbox/view/page/docker.dart';
import 'package:toolbox/view/page/server/detail.dart';
import 'package:toolbox/view/page/server/edit.dart';
import 'package:toolbox/view/page/sftp/view.dart';
import 'package:toolbox/view/page/snippet/list.dart';
import 'package:toolbox/view/page/snippet/edit.dart';
import 'package:toolbox/view/widget/picker.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
class ServerPage extends StatefulWidget {
@@ -157,6 +160,8 @@ class _ServerPageState extends State<ServerPage>
context, _s.error, Text(ss.failedInfo ?? ''), []),
child: Text(_s.clickSee, style: style))
: Text(topRightStr, style: style, textScaleFactor: 1.0),
const SizedBox(width: 7),
_buildSnippetBtn(spi),
_buildMoreBtn(spi),
],
)
@@ -191,6 +196,63 @@ class _ServerPageState extends State<ServerPage>
);
}
Widget _buildSnippetBtn(ServerPrivateInfo spi) {
return GestureDetector(
child: const Icon(Icons.play_arrow),
onTap: () {
final provider = locator<SnippetProvider>();
if (provider.snippets.isEmpty) {
showRoundDialog(
context,
_s.attention,
Text(_s.noSavedSnippet),
[
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(_s.ok),
),
TextButton(
onPressed: () =>
AppRoute(const SnippetEditPage(), 'edit snippet')
.go(context),
child: Text(_s.addOne),
)
],
);
return;
}
var snippet = provider.snippets.first;
showRoundDialog(
context,
_s.choose,
buildPicker(provider.snippets.map((e) => Text(e.name)).toList(),
(idx) => snippet = provider.snippets[idx]),
[
TextButton(
onPressed: () async {
Navigator.of(context).pop();
final result =
await locator<ServerProvider>().runSnippet(spi.id, snippet);
showRoundDialog(
context,
_s.result,
Text(result ?? _s.error, style: textSize13),
[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(_s.ok))
],
);
},
child: Text(_s.run),
)
],
);
},
);
}
Widget _buildMoreBtn(ServerPrivateInfo spi) {
return buildPopuopMenu(
items: <PopupMenuEntry>[
@@ -217,9 +279,6 @@ class _ServerPageState extends State<ServerPage>
case ServerTabMenuItems.sftp:
AppRoute(SFTPPage(spi), 'SFTP').go(context);
break;
case ServerTabMenuItems.snippet:
AppRoute(SnippetListPage(spi: spi), 'snippet list').go(context);
break;
case ServerTabMenuItems.edit:
AppRoute(ServerEditPage(spi: spi), 'Edit server info').go(context);
break;

View File

@@ -23,7 +23,7 @@ class SettingPage extends StatefulWidget {
}
class _SettingPageState extends State<SettingPage> {
late SettingStore _setting;
late final SettingStore _setting;
late int _selectedColorValue;
late int _launchPageIdx;
late Color priColor;
@@ -32,7 +32,7 @@ class _SettingPageState extends State<SettingPage> {
late ThemeData _theme;
late S _s;
var _intervalValue = 0.0;
var _updateInterval = 5.0;
@override
void didChangeDependencies() {
@@ -49,7 +49,7 @@ class _SettingPageState extends State<SettingPage> {
_serverProvider = locator<ServerProvider>();
_setting = locator<SettingStore>();
_launchPageIdx = _setting.launchPage.fetch()!;
_intervalValue = _setting.serverStatusUpdateInterval.fetch()!.toDouble();
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!.toDouble();
}
@override
@@ -126,30 +126,30 @@ class _SettingPageState extends State<SettingPage> {
_s.willTakEeffectImmediately,
style: textSize13Grey,
),
trailing: Text('${_intervalValue.toInt()} ${_s.second}'),
trailing: Text('${_updateInterval.toInt()} ${_s.second}'),
children: [
Slider(
thumbColor: priColor,
activeColor: priColor.withOpacity(0.7),
min: 0,
max: 10,
value: _intervalValue,
value: _updateInterval,
onChanged: (newValue) {
setState(() {
_intervalValue = newValue;
_updateInterval = newValue;
});
},
onChangeEnd: (val) {
_setting.serverStatusUpdateInterval.put(val.toInt());
_serverProvider.startAutoRefresh();
},
label: '${_intervalValue.toInt()} ${_s.second}',
label: '${_updateInterval.toInt()} ${_s.second}',
divisions: 10,
),
const SizedBox(
height: 3,
),
_intervalValue == 0.0
_updateInterval == 0.0
? Text(
_s.updateIntervalEqual0,
style: const TextStyle(color: Colors.grey, fontSize: 12),

View File

@@ -12,6 +12,7 @@ import 'package:toolbox/data/res/padding.dart';
import 'package:toolbox/generated/l10n.dart';
import 'package:toolbox/locator.dart';
import 'package:toolbox/view/page/snippet/edit.dart';
import 'package:toolbox/view/widget/picker.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
class SnippetListPage extends StatefulWidget {
@@ -23,7 +24,7 @@ class SnippetListPage extends StatefulWidget {
}
class _SnippetListPageState extends State<SnippetListPage> {
late ServerPrivateInfo _selectedIndex;
late ServerPrivateInfo _selectedSpi;
final _textStyle = TextStyle(color: primaryColor);
@@ -121,48 +122,23 @@ class _SnippetListPageState extends State<SnippetListPage> {
if (provider.servers.isEmpty) {
return Text(_s.noServerAvailable);
}
_selectedIndex = provider.servers.first.info;
return SizedBox(
height: 111,
child: Stack(
children: [
Positioned(
top: 36,
bottom: 36,
left: 0,
right: 0,
child: Container(
height: 37,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(7)),
color: Colors.black12,
),
),
),
ListWheelScrollView.useDelegate(
itemExtent: 37,
diameterRatio: 1.2,
controller: FixedExtentScrollController(initialItem: 0),
onSelectedItemChanged: (idx) =>
_selectedIndex = provider.servers[idx].info,
physics: const FixedExtentScrollPhysics(),
childDelegate: ListWheelChildBuilderDelegate(
builder: (context, index) => Center(
child: Text(
provider.servers[index].info.name,
textAlign: TextAlign.center,
),
),
childCount: provider.servers.length),
)
],
),
);
_selectedSpi = provider.servers.first.info;
return buildPicker(
provider.servers
.map((e) => Text(
e.info.name,
textAlign: TextAlign.center,
))
.toList(),
(idx) => _selectedSpi = provider.servers[idx].info);
},
),
[
TextButton(
onPressed: () async => run(context, snippet),
onPressed: () async {
Navigator.of(context).pop();
run(context, snippet);
},
child: Text(_s.run),
),
TextButton(
@@ -174,8 +150,8 @@ class _SnippetListPageState extends State<SnippetListPage> {
}
Future<void> run(BuildContext context, Snippet snippet) async {
final result = await locator<ServerProvider>()
.runSnippet(widget.spi ?? _selectedIndex, snippet);
final id = (widget.spi ?? _selectedSpi).id;
final result = await locator<ServerProvider>().runSnippet(id, snippet);
if (result != null) {
showRoundDialog(
context,

View File

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
Widget buildPicker(List<Widget> items, Function(int idx) onSelected) {
return SizedBox(
height: 111,
child: Stack(
children: [
Positioned(
top: 36,
bottom: 36,
left: 0,
right: 0,
child: Container(
height: 37,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(7)),
color: Colors.black12,
),
),
),
ListWheelScrollView.useDelegate(
itemExtent: 37,
diameterRatio: 1.2,
controller: FixedExtentScrollController(initialItem: 0),
onSelectedItemChanged: (idx) => onSelected(idx),
physics: const FixedExtentScrollPhysics(),
childDelegate: ListWheelChildBuilderDelegate(
builder: (context, index) => Center(
child: items[index],
),
childCount: items.length),
)
],
),
);
}