mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fmt
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
final _dockerImageReg = RegExp(r'(\S+) +(\S+) +(\S+) +(.+) +(\S+)');
|
||||
|
||||
class DockerImage {
|
||||
final String repo;
|
||||
final String tag;
|
||||
@@ -44,4 +45,3 @@ class DockerImage {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class DockerProvider extends BusyProvider {
|
||||
final verRaw = await client!.run('docker version'.withLangExport).string;
|
||||
if (verRaw.contains(_dockerNotFound)) {
|
||||
error = DockerErr(type: DockerErrType.notInstalled);
|
||||
notifyListeners();
|
||||
setBusyState(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ class DockerProvider extends BusyProvider {
|
||||
}
|
||||
|
||||
try {
|
||||
setBusyState();
|
||||
final cmd = _wrap(_dockerPS);
|
||||
|
||||
// run docker ps
|
||||
@@ -97,7 +98,7 @@ class DockerProvider extends BusyProvider {
|
||||
error = DockerErr(type: DockerErrType.unknown, message: e.toString());
|
||||
rethrow;
|
||||
} finally {
|
||||
notifyListeners();
|
||||
setBusyState(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +146,8 @@ class DockerProvider extends BusyProvider {
|
||||
|
||||
if (code != 0) {
|
||||
setBusyState(false);
|
||||
return DockerErr(type: DockerErrType.unknown, message: errs.join('\n').trim());
|
||||
return DockerErr(
|
||||
type: DockerErrType.unknown, message: errs.join('\n').trim());
|
||||
}
|
||||
await refresh();
|
||||
setBusyState(false);
|
||||
|
||||
@@ -61,21 +61,26 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
_aptProvider.init(
|
||||
si.client!,
|
||||
si.status.sysVer.dist,
|
||||
() =>
|
||||
scrollController.jumpTo(scrollController.position.maxScrollExtent),
|
||||
() => scrollController.jumpTo(scrollController.position.maxScrollExtent),
|
||||
() => scrollControllerUpdate
|
||||
.jumpTo(scrollController.position.maxScrollExtent),
|
||||
onPwdRequest,
|
||||
widget.spi.user);
|
||||
widget.spi.user,
|
||||
);
|
||||
_aptProvider.refreshInstalled();
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
]);
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
@@ -108,7 +113,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
],
|
||||
);
|
||||
return textController.text.trim();
|
||||
}
|
||||
|
||||
@@ -142,7 +148,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
child: Text(
|
||||
apt.error!,
|
||||
textAlign: TextAlign.center,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -154,9 +161,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
}
|
||||
if (apt.updateLog != null && apt.upgradeable == null) {
|
||||
return SizedBox(
|
||||
height: _media.size.height -
|
||||
_media.padding.top -
|
||||
_media.padding.bottom,
|
||||
height:
|
||||
_media.size.height - _media.padding.top - _media.padding.bottom,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: SingleChildScrollView(
|
||||
@@ -164,7 +170,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
controller: scrollControllerUpdate,
|
||||
child: Text(apt.updateLog!),
|
||||
),
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
@@ -219,7 +226,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
controller: scrollController,
|
||||
children: apt.upgradeable!
|
||||
.map((e) => _buildUpdateItem(e, apt))
|
||||
.toList()),
|
||||
.toList(),
|
||||
),
|
||||
)
|
||||
]
|
||||
: [
|
||||
@@ -232,7 +240,8 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
controller: scrollController,
|
||||
child: Text(apt.upgradeLog!),
|
||||
),
|
||||
))
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
|
||||
@@ -54,8 +54,12 @@ class BackupPage extends StatelessWidget {
|
||||
const SizedBox(height: 7),
|
||||
const Divider(),
|
||||
const SizedBox(height: 7),
|
||||
_buildCard(s.backup, Icons.file_upload, media,
|
||||
() => _showExportDialog(context, s))
|
||||
_buildCard(
|
||||
s.backup,
|
||||
Icons.file_upload,
|
||||
media,
|
||||
() => _showExportDialog(context, s),
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
@@ -91,7 +95,9 @@ class BackupPage extends StatelessWidget {
|
||||
|
||||
Future<void> _showExportDialog(BuildContext context, S s) async {
|
||||
final exportFieldController = TextEditingController()
|
||||
..text = _diyEncrtpt(json.encode(Backup(
|
||||
..text = _diyEncrtpt(
|
||||
json.encode(
|
||||
Backup(
|
||||
backupFormatVersion,
|
||||
DateTime.now().toString().split('.').first,
|
||||
server.fetch(),
|
||||
@@ -100,7 +106,9 @@ class BackupPage extends StatelessWidget {
|
||||
setting.primaryColor.fetch() ?? Colors.pinkAccent.value,
|
||||
setting.serverStatusUpdateInterval.fetch() ?? 2,
|
||||
setting.launchPage.fetch() ?? 0,
|
||||
)));
|
||||
),
|
||||
),
|
||||
);
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.export,
|
||||
@@ -115,12 +123,12 @@ class BackupPage extends StatelessWidget {
|
||||
TextButton(
|
||||
child: Text(s.copy),
|
||||
onPressed: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: exportFieldController.text));
|
||||
Clipboard.setData(ClipboardData(text: exportFieldController.text));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
]);
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showImportDialog(BuildContext context, S s) async {
|
||||
@@ -138,13 +146,15 @@ class BackupPage extends StatelessWidget {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async =>
|
||||
await _import(importFieldController.text.trim(), context, s),
|
||||
child: const Text('GO'),
|
||||
)
|
||||
]);
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _import(String text, BuildContext context, S s) async {
|
||||
@@ -165,7 +175,10 @@ class BackupPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
await showRoundDialog(
|
||||
context, s.attention, Text(s.restoreSureWithDate(backup.date)), [
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.restoreSureWithDate(backup.date)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
@@ -190,7 +203,8 @@ class BackupPage extends StatelessWidget {
|
||||
},
|
||||
child: Text(s.ok),
|
||||
),
|
||||
]);
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
showSnackBar(context, Text(s.invalidJson));
|
||||
return;
|
||||
|
||||
@@ -47,12 +47,15 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||
controller: ScrollController(),
|
||||
child: Column(children: [
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 13),
|
||||
_buildInputTop(),
|
||||
_buildTypeOption(),
|
||||
_buildResult(),
|
||||
])),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
try {
|
||||
@@ -119,7 +122,8 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor),
|
||||
),
|
||||
child: Icon(Icons.copy, semanticLabel: s.copy),
|
||||
onPressed: () => Clipboard.setData(
|
||||
ClipboardData(
|
||||
@@ -136,13 +140,15 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(typeOption[_typeOptionIndex],
|
||||
Text(
|
||||
typeOption[_typeOptionIndex],
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primaryColor)),
|
||||
color: primaryColor),
|
||||
),
|
||||
Text(
|
||||
s.currentMode,
|
||||
textScaleFactor: 1.0,
|
||||
@@ -153,7 +159,8 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
),
|
||||
),
|
||||
children: typeOption
|
||||
.map((e) => ListTile(
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
title: Text(
|
||||
e,
|
||||
style: TextStyle(
|
||||
@@ -161,7 +168,8 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
),
|
||||
),
|
||||
trailing: _buildRadio(typeOption.indexOf(e)),
|
||||
))
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,8 +13,10 @@ class _DebugPageState extends State<DebugPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar:
|
||||
AppBar(title: const Text('App log'), backgroundColor: Colors.black),
|
||||
appBar: AppBar(
|
||||
title: const Text('App log'),
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
body: _buildTerminal(context),
|
||||
backgroundColor: Colors.black,
|
||||
);
|
||||
@@ -31,12 +33,15 @@ class _DebugPageState extends State<DebugPage> {
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Consumer<DebugProvider>(builder: (_, debug, __) {
|
||||
child: Consumer<DebugProvider>(
|
||||
builder: (_, debug, __) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: debug.widgets);
|
||||
}),
|
||||
children: debug.widgets,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -67,7 +67,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => docker.refresh(),
|
||||
icon: const Icon(Icons.refresh))
|
||||
icon: const Icon(Icons.refresh),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: _buildMain(docker),
|
||||
@@ -124,8 +125,13 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
await _showAddCmdPreview(_buildAddCmd(imageCtrl.text.trim(),
|
||||
nameCtrl.text.trim(), argsCtrl.text.trim()));
|
||||
await _showAddCmdPreview(
|
||||
_buildAddCmd(
|
||||
imageCtrl.text.trim(),
|
||||
nameCtrl.text.trim(),
|
||||
argsCtrl.text.trim(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(s.ok),
|
||||
)
|
||||
@@ -208,14 +214,17 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
return textController.text.trim();
|
||||
}
|
||||
|
||||
@@ -286,8 +295,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
.toList());
|
||||
}
|
||||
|
||||
Widget _buildLoading(DockerProvider docker) {
|
||||
@@ -319,7 +327,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => _showEditHostDialog(docker),
|
||||
child: Text(s.dockerEditHost))
|
||||
child: Text(s.dockerEditHost),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -343,7 +352,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -399,14 +409,16 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
return ExpansionTile(
|
||||
title: Text(s.containerStatus),
|
||||
subtitle: Text(_buildSubtitle(running), style: greyTextStyle),
|
||||
children: running.map((item) {
|
||||
children: running.map(
|
||||
(item) {
|
||||
return ListTile(
|
||||
title: Text(item.image),
|
||||
subtitle: Text(item.status),
|
||||
trailing:
|
||||
_buildMoreBtn(item.running, item.containerId, docker.isBusy),
|
||||
);
|
||||
}).toList(),
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,10 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
? Colors.white12
|
||||
: Colors.black.withOpacity(0.07)
|
||||
: Colors.transparent,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(50))),
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(50),
|
||||
),
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(item.icon),
|
||||
tooltip: tabTitleName(context, idx),
|
||||
@@ -164,12 +167,15 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
width: _width,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: tabItems.map((item) {
|
||||
children: tabItems.map(
|
||||
(item) {
|
||||
int itemIndex = tabItems.indexOf(item);
|
||||
return _buildItem(itemIndex, item, _selectIndex == itemIndex);
|
||||
}).toList(),
|
||||
},
|
||||
).toList(),
|
||||
),
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDrawer() {
|
||||
@@ -217,18 +223,25 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
leading: const Icon(Icons.info),
|
||||
title: Text(s.feedback),
|
||||
onTap: () => showRoundDialog(
|
||||
context, s.feedback, Text(s.feedbackOnGithub), [
|
||||
context,
|
||||
s.feedback,
|
||||
Text(s.feedbackOnGithub),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Clipboard.setData(
|
||||
const ClipboardData(text: issueUrl)),
|
||||
child: Text(s.copy)),
|
||||
child: Text(s.copy),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => openUrl(issueUrl),
|
||||
child: Text(s.feedback)),
|
||||
child: Text(s.feedback),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close))
|
||||
]),
|
||||
child: Text(s.close),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.snippet_folder),
|
||||
@@ -274,7 +287,8 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
constraints: const BoxConstraints(maxHeight: 53, maxWidth: 53),
|
||||
child: Container(
|
||||
color: primaryColor,
|
||||
)),
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxHeight: 83, maxWidth: 83),
|
||||
child: appIcon,
|
||||
|
||||
@@ -52,7 +52,8 @@ class _PingPageState extends State<PingPage>
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||
child: Column(children: [
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 13),
|
||||
buildInput(context, _textEditingController,
|
||||
hint: s.inputDomainHere,
|
||||
@@ -69,7 +70,9 @@ class _PingPageState extends State<PingPage>
|
||||
return _buildResultItem(result);
|
||||
}),
|
||||
),
|
||||
])),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
heroTag: 'ping fab',
|
||||
onPressed: () {
|
||||
@@ -87,19 +90,30 @@ class _PingPageState extends State<PingPage>
|
||||
Widget _buildResultItem(PingResult result) {
|
||||
final unknown = s.unknown;
|
||||
final ms = s.ms;
|
||||
return RoundRectCard(ListTile(
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||
title: Text(result.serverName,
|
||||
title: Text(
|
||||
result.serverName,
|
||||
style: TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor)),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
_buildPingSummary(result, unknown, ms),
|
||||
style: summaryTextStyle,
|
||||
),
|
||||
trailing: Text(
|
||||
'${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms',
|
||||
style: TextStyle(fontSize: 14, color: primaryColor)),
|
||||
));
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _buildPingSummary(PingResult result, String unknown, String ms) {
|
||||
|
||||
@@ -51,7 +51,9 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.info != null
|
||||
? IconButton(
|
||||
tooltip: s.delete,
|
||||
@@ -61,7 +63,8 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
: const SizedBox()
|
||||
]),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
|
||||
@@ -58,12 +58,15 @@ class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
||||
child: Text(
|
||||
s.edit,
|
||||
style: _textStyle,
|
||||
))
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
})
|
||||
: Center(child: Text(s.noSavedPrivateKey));
|
||||
: Center(
|
||||
child: Text(s.noSavedPrivateKey),
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
|
||||
@@ -37,8 +37,9 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||
return _buildMainPage(
|
||||
provider.servers
|
||||
.firstWhere((e) => '${e.info.ip}:${e.info.port}' == widget.id),
|
||||
provider.servers.firstWhere(
|
||||
(e) => '${e.info.ip}:${e.info.port}' == widget.id,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -212,7 +213,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
(ss.memory.cache * mb).convertBytes, pColor.withAlpha(77)),
|
||||
_buildMemExplain(
|
||||
((ss.memory.total - ss.memory.used) * mb).convertBytes,
|
||||
progressColor.resolve(context))
|
||||
progressColor.resolve(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
@@ -367,7 +369,8 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
child: Text(ns.speedOut(device: device),
|
||||
style: textSize11,
|
||||
textAlign: TextAlign.right,
|
||||
textScaleFactor: 1.0))
|
||||
textScaleFactor: 1.0),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -63,12 +63,17 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.spi != null
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
showRoundDialog(context, s.attention,
|
||||
Text(s.sureToDeleteServer(widget.spi!.name)), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.sureToDeleteServer(widget.spi!.name)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_serverProvider.delServer(widget.spi!);
|
||||
@@ -78,15 +83,20 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel))
|
||||
]);
|
||||
child: Text(s.cancel),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
icon: const Icon(Icons.delete),
|
||||
)
|
||||
: const SizedBox()
|
||||
]),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: Column(
|
||||
@@ -148,7 +158,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
)
|
||||
: const SizedBox(),
|
||||
usePublicKey
|
||||
? Consumer<PrivateKeyProvider>(builder: (_, key, __) {
|
||||
? Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
for (var item in key.infos) {
|
||||
if (item.id == widget.spi?.pubKeyId) {
|
||||
_pubKeyIndex ??= key.infos.indexOf(item);
|
||||
@@ -162,16 +173,19 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
trailing: _buildRadio(key.infos.indexOf(e), e)),
|
||||
)
|
||||
.toList();
|
||||
tiles.add(ListTile(
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(s.addPrivateKey),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: () => AppRoute(const PrivateKeyEditPage(),
|
||||
onPressed: () => AppRoute(
|
||||
const PrivateKeyEditPage(),
|
||||
'private key edit page')
|
||||
.go(context),
|
||||
),
|
||||
));
|
||||
),
|
||||
);
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
iconColor: primaryColor,
|
||||
@@ -183,7 +197,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
),
|
||||
children: tiles,
|
||||
);
|
||||
})
|
||||
},
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
@@ -208,7 +223,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: Text(s.cancel))
|
||||
],
|
||||
barrierDismiss: false);
|
||||
barrierDismiss: false,
|
||||
);
|
||||
if (cancel ?? true) {
|
||||
return;
|
||||
}
|
||||
@@ -235,7 +251,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
port: int.parse(portController.text),
|
||||
user: usernameController.text,
|
||||
pwd: authorization,
|
||||
pubKeyId: usePublicKey ? _keyInfo!.id : null);
|
||||
pubKeyId: usePublicKey ? _keyInfo!.id : null,
|
||||
);
|
||||
|
||||
if (widget.spi == null) {
|
||||
_serverProvider.addServer(spi);
|
||||
|
||||
@@ -55,7 +55,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final child = Consumer<ServerProvider>(builder: (_, pro, __) {
|
||||
final child = Consumer<ServerProvider>(
|
||||
builder: (_, pro, __) {
|
||||
if (pro.servers.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
@@ -78,7 +79,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
height: 3,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
return Scaffold(
|
||||
body: child,
|
||||
floatingActionButton: FloatingActionButton(
|
||||
@@ -104,7 +106,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(13),
|
||||
child: _buildRealServerCard(
|
||||
si.status, si.info.name, si.connectionState, si.info)),
|
||||
si.status, si.info.name, si.connectionState, si.info),
|
||||
),
|
||||
onTap: () => AppRoute(ServerDetailPage('${si.info.ip}:${si.info.port}'),
|
||||
'server detail page')
|
||||
.go(context),
|
||||
|
||||
@@ -71,7 +71,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}
|
||||
|
||||
Widget _buildCheckUpdate() {
|
||||
return Consumer<AppProvider>(builder: (_, app, __) {
|
||||
return Consumer<AppProvider>(
|
||||
builder: (_, app, __) {
|
||||
String display;
|
||||
if (app.newestBuild != null) {
|
||||
if (app.newestBuild! > BuildData.build) {
|
||||
@@ -90,8 +91,10 @@ class _SettingPageState extends State<SettingPage> {
|
||||
style: textSize13,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
onTap: () => doUpdate(context, force: true));
|
||||
});
|
||||
onTap: () => doUpdate(context, force: true),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildUpdateInterval() {
|
||||
@@ -161,10 +164,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
s.appPrimaryColor,
|
||||
style: textSize13,
|
||||
),
|
||||
children: [
|
||||
_buildAppColorPicker(priColor),
|
||||
_buildColorPickerConfirmBtn()
|
||||
]);
|
||||
children: [_buildAppColorPicker(priColor), _buildColorPickerConfirmBtn()],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppColorPicker(Color selected) {
|
||||
@@ -204,7 +205,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
),
|
||||
),
|
||||
children: tabs
|
||||
.map((e) => ListTile(
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
tabTitleName(context, tabs.indexOf(e)),
|
||||
@@ -213,7 +215,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
color: _theme.textTheme.bodyText2!.color!.withAlpha(177)),
|
||||
),
|
||||
trailing: _buildRadio(tabs.indexOf(e)),
|
||||
))
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,10 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(
|
||||
context, s.sureDelete(fileName), const SizedBox(), [
|
||||
context,
|
||||
s.sureDelete(fileName),
|
||||
const SizedBox(),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
@@ -164,7 +167,8 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
},
|
||||
child: Text(s.ok),
|
||||
),
|
||||
]);
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
@@ -172,13 +176,15 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
title: Text(s.open),
|
||||
onTap: () {
|
||||
shareFiles(context, [file.absolute.path]);
|
||||
}),
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: (() => Navigator.of(context).pop()),
|
||||
child: Text(s.close))
|
||||
]);
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
|
||||
Widget _wrapInCard(SftpDownloadStatus status, String? subtitle,
|
||||
{Widget? trailing}) {
|
||||
return RoundRectCard(ListTile(
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
title: Text(status.fileName),
|
||||
subtitle: subtitle == null
|
||||
? null
|
||||
@@ -67,7 +68,8 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
style: grey,
|
||||
),
|
||||
trailing: trailing,
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildItem(SftpDownloadStatus status) {
|
||||
@@ -77,11 +79,14 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
switch (status.status) {
|
||||
case SftpWorkerStatus.finished:
|
||||
final time = status.spentTime.toString();
|
||||
return _wrapInCard(status,
|
||||
return _wrapInCard(
|
||||
status,
|
||||
'${s.downloadFinished} ${s.spentTime(time == 'null' ? s.unknown : (time.substring(0, time.length - 7)))}',
|
||||
trailing: IconButton(
|
||||
onPressed: () => shareFiles(context, [status.item.localPath]),
|
||||
icon: const Icon(Icons.open_in_new)));
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
),
|
||||
);
|
||||
case SftpWorkerStatus.downloading:
|
||||
return _wrapInCard(
|
||||
status,
|
||||
@@ -94,11 +99,14 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
case SftpWorkerStatus.sshConnectted:
|
||||
return _wrapInCard(status, s.sftpSSHConnected, trailing: loadingIcon);
|
||||
default:
|
||||
return _wrapInCard(status, s.unknown,
|
||||
return _wrapInCard(
|
||||
status,
|
||||
s.unknown,
|
||||
trailing: const Icon(
|
||||
Icons.error,
|
||||
size: 40,
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close))
|
||||
])),
|
||||
],
|
||||
)),
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
]),
|
||||
],
|
||||
),
|
||||
body: _buildFileView(),
|
||||
);
|
||||
}
|
||||
@@ -157,7 +159,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
},
|
||||
),
|
||||
),
|
||||
onRefresh: () => listDir(path: _status.path?.path));
|
||||
onRefresh: () => listDir(path: _status.path?.path),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,16 +192,20 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel))
|
||||
]);
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void download(BuildContext context, SftpName name) {
|
||||
showRoundDialog(context, s.download,
|
||||
Text('${s.dl2Local(name.filename)}\n${s.keepForeground}'), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.download,
|
||||
Text('${s.dl2Local(name.filename)}\n${s.keepForeground}'),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel)),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
@@ -207,32 +214,52 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
prePath + (prePath.endsWith('/') ? '' : '/') + name.filename;
|
||||
final local = '${(await sftpDownloadDir).path}$remotePath';
|
||||
final pubKeyId = _status.spi!.pubKeyId;
|
||||
|
||||
locator<SftpDownloadProvider>().add(
|
||||
DownloadItem(_status.spi!, remotePath, local),
|
||||
DownloadItem(
|
||||
_status.spi!,
|
||||
remotePath,
|
||||
local,
|
||||
),
|
||||
key: pubKeyId == null
|
||||
? null
|
||||
: locator<PrivateKeyStore>().get(pubKeyId).privateKey);
|
||||
: locator<PrivateKeyStore>().get(pubKeyId).privateKey,
|
||||
);
|
||||
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(context, s.goSftpDlPage, const SizedBox(), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.goSftpDlPage,
|
||||
const SizedBox(),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
AppRoute(const SFTPDownloadingPage(), 'sftp downloading')
|
||||
.go(context);
|
||||
},
|
||||
child: Text(s.ok))
|
||||
]);
|
||||
child: Text(s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Text(s.download))
|
||||
]);
|
||||
child: Text(s.download),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void delete(BuildContext context, SftpName file) {
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(context, s.attention, Text(s.sureDelete(file.filename)), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.sureDelete(file.filename)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel')),
|
||||
@@ -245,8 +272,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
child: Text(
|
||||
s.delete,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void mkdir(BuildContext context) {
|
||||
@@ -264,16 +293,21 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok)),
|
||||
]);
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
_status.client!
|
||||
@@ -284,8 +318,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void newFile(BuildContext context) {
|
||||
@@ -303,16 +339,22 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok)),
|
||||
]);
|
||||
child: Text(s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
(await _status.client!
|
||||
@@ -324,8 +366,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
child: Text(
|
||||
s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void rename(BuildContext context, SftpName file) {
|
||||
@@ -348,23 +392,29 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok)),
|
||||
]);
|
||||
child: Text(s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
await _status.client!
|
||||
.rename(file.filename, textController.text);
|
||||
await _status.client!.rename(file.filename, textController.text);
|
||||
Navigator.of(context).pop();
|
||||
listDir();
|
||||
},
|
||||
child: Text(
|
||||
s.rename,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
]);
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> listDir({String? path, SSHClient? client}) async {
|
||||
@@ -388,10 +438,17 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
await showRoundDialog(context, s.error, Text(e.toString()), [
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.error,
|
||||
Text(e.toString()),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok))
|
||||
]);
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
if (_status.path!.undo()) {
|
||||
await listDir();
|
||||
}
|
||||
@@ -424,7 +481,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
.servers
|
||||
.firstWhere((s) => s.info == spi)
|
||||
.client,
|
||||
path: '/');
|
||||
path: '/',
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.snippet != null
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
@@ -51,7 +53,8 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
tooltip: s.delete,
|
||||
icon: const Icon(Icons.delete))
|
||||
: const SizedBox()
|
||||
]),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
|
||||
@@ -59,7 +59,8 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
itemCount: key.snippets.length,
|
||||
itemExtent: 57,
|
||||
itemBuilder: (context, idx) {
|
||||
return RoundRectCard(Padding(
|
||||
return RoundRectCard(
|
||||
Padding(
|
||||
padding: roundRectCardPadding,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@@ -69,7 +70,8 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
key.snippets[idx].name,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Row(children: [
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => AppRoute(
|
||||
SnippetEditPage(
|
||||
@@ -79,7 +81,8 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
child: Text(
|
||||
s.edit,
|
||||
style: _textStyle,
|
||||
)),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final snippet = key.snippets[idx];
|
||||
@@ -92,27 +95,37 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
child: Text(
|
||||
s.run,
|
||||
style: _textStyle,
|
||||
))
|
||||
])
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
})
|
||||
: Center(child: Text(s.noSavedSnippet));
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Center(
|
||||
child: Text(s.noSavedSnippet),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showRunDialog(Snippet snippet) {
|
||||
showRoundDialog(context, s.chooseDestination,
|
||||
Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.chooseDestination,
|
||||
Consumer<ServerProvider>(
|
||||
builder: (_, provider, __) {
|
||||
if (provider.servers.isEmpty) {
|
||||
return Text(s.noServerAvailable);
|
||||
}
|
||||
_selectedIndex = provider.servers.first.info;
|
||||
return SizedBox(
|
||||
height: 111,
|
||||
child: Stack(children: [
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: 36,
|
||||
bottom: 36,
|
||||
@@ -142,24 +155,39 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
),
|
||||
childCount: provider.servers.length),
|
||||
)
|
||||
]));
|
||||
}), [
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () async => run(context, snippet), child: Text(s.run)),
|
||||
onPressed: () async => run(context, snippet),
|
||||
child: Text(s.run),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel)),
|
||||
]);
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> run(BuildContext context, Snippet snippet) async {
|
||||
final result = await locator<ServerProvider>()
|
||||
.runSnippet(widget.spi ?? _selectedIndex, snippet);
|
||||
if (result != null) {
|
||||
showRoundDialog(context, s.result,
|
||||
Text(result, style: const TextStyle(fontSize: 13)), [
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.result,
|
||||
Text(result, style: const TextStyle(fontSize: 13)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.close))
|
||||
]);
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user