diff --git a/lib/data/model/docker/image.dart b/lib/data/model/docker/image.dart index 1af89011..143d0a08 100644 --- a/lib/data/model/docker/image.dart +++ b/lib/data/model/docker/image.dart @@ -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 { ); } } - diff --git a/lib/data/provider/docker.dart b/lib/data/provider/docker.dart index 796c932e..e539c5d0 100644 --- a/lib/data/provider/docker.dart +++ b/lib/data/provider/docker.dart @@ -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); diff --git a/lib/view/page/apt.dart b/lib/view/page/apt.dart index 459a8384..d504bd92 100644 --- a/lib/view/page/apt.dart +++ b/lib/view/page/apt.dart @@ -59,23 +59,28 @@ class _AptManagePageState extends State } _aptProvider.init( - si.client!, - si.status.sysVer.dist, - () => - scrollController.jumpTo(scrollController.position.maxScrollExtent), - () => scrollControllerUpdate - .jumpTo(scrollController.position.maxScrollExtent), - onPwdRequest, - widget.spi.user); + si.client!, + si.status.sysVer.dist, + () => scrollController.jumpTo(scrollController.position.maxScrollExtent), + () => scrollControllerUpdate + .jumpTo(scrollController.position.maxScrollExtent), + onPwdRequest, + widget.spi.user, + ); _aptProvider.refreshInstalled(); } void onSubmitted() { if (textController.text == '') { - showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)), - ]); + showRoundDialog( + context, + s.attention, + Text(s.fieldMustNotEmpty), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)), + ], + ); return; } Navigator.of(context).pop(); @@ -84,31 +89,32 @@ class _AptManagePageState extends State Future onPwdRequest() async { if (!mounted) return ''; await showRoundDialog( - context, - widget.spi.user, - TextField( - controller: textController, - keyboardType: TextInputType.visiblePassword, - obscureText: true, - onSubmitted: (_) => onSubmitted(), - decoration: InputDecoration( - labelText: s.pwd, - ), + context, + widget.spi.user, + TextField( + controller: textController, + keyboardType: TextInputType.visiblePassword, + obscureText: true, + onSubmitted: (_) => onSubmitted(), + decoration: InputDecoration( + labelText: s.pwd, ), - [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }, - child: Text(s.cancel)), - TextButton( - onPressed: () => onSubmitted(), - child: Text( - s.ok, - style: const TextStyle(color: Colors.red), - )), - ]); + ), + [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + child: Text(s.cancel)), + TextButton( + onPressed: () => onSubmitted(), + child: Text( + s.ok, + style: const TextStyle(color: Colors.red), + )), + ], + ); return textController.text.trim(); } @@ -138,11 +144,12 @@ class _AptManagePageState extends State padding: const EdgeInsets.all(17), child: RoundRectCard( SingleChildScrollView( - padding: const EdgeInsets.all(17), - child: Text( - apt.error!, - textAlign: TextAlign.center, - )), + padding: const EdgeInsets.all(17), + child: Text( + apt.error!, + textAlign: TextAlign.center, + ), + ), ), ), ), @@ -154,17 +161,17 @@ class _AptManagePageState extends State } if (apt.updateLog != null && apt.upgradeable == null) { return SizedBox( - height: _media.size.height - - _media.padding.top - - _media.padding.bottom, - child: ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: SingleChildScrollView( - padding: const EdgeInsets.all(18), - controller: scrollControllerUpdate, - child: Text(apt.updateLog!), - ), - )); + height: + _media.size.height - _media.padding.top - _media.padding.bottom, + child: ConstrainedBox( + constraints: const BoxConstraints.expand(), + child: SingleChildScrollView( + padding: const EdgeInsets.all(18), + controller: scrollControllerUpdate, + child: Text(apt.updateLog!), + ), + ), + ); } return ListView( padding: const EdgeInsets.all(13), @@ -216,23 +223,25 @@ class _AptManagePageState extends State SizedBox( height: _media.size.height * 0.73, child: ListView( - controller: scrollController, - children: apt.upgradeable! - .map((e) => _buildUpdateItem(e, apt)) - .toList()), + controller: scrollController, + children: apt.upgradeable! + .map((e) => _buildUpdateItem(e, apt)) + .toList(), + ), ) ] : [ SizedBox( - height: _media.size.height * 0.7, - child: ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: SingleChildScrollView( - padding: const EdgeInsets.all(18), - controller: scrollController, - child: Text(apt.upgradeLog!), - ), - )) + height: _media.size.height * 0.7, + child: ConstrainedBox( + constraints: const BoxConstraints.expand(), + child: SingleChildScrollView( + padding: const EdgeInsets.all(18), + controller: scrollController, + child: Text(apt.upgradeLog!), + ), + ), + ) ], ) ], diff --git a/lib/view/page/backup.dart b/lib/view/page/backup.dart index 92e989fe..2be5bec4 100644 --- a/lib/view/page/backup.dart +++ b/lib/view/page/backup.dart @@ -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,60 +95,66 @@ class BackupPage extends StatelessWidget { Future _showExportDialog(BuildContext context, S s) async { final exportFieldController = TextEditingController() - ..text = _diyEncrtpt(json.encode(Backup( - backupFormatVersion, - DateTime.now().toString().split('.').first, - server.fetch(), - snippet.fetch(), - privateKey.fetch(), - setting.primaryColor.fetch() ?? Colors.pinkAccent.value, - setting.serverStatusUpdateInterval.fetch() ?? 2, - setting.launchPage.fetch() ?? 0, - ))); - await showRoundDialog( - context, - s.export, - TextField( - decoration: const InputDecoration( - labelText: 'JSON', + ..text = _diyEncrtpt( + json.encode( + Backup( + backupFormatVersion, + DateTime.now().toString().split('.').first, + server.fetch(), + snippet.fetch(), + privateKey.fetch(), + setting.primaryColor.fetch() ?? Colors.pinkAccent.value, + setting.serverStatusUpdateInterval.fetch() ?? 2, + setting.launchPage.fetch() ?? 0, ), - maxLines: 7, - controller: exportFieldController, ), - [ - TextButton( - child: Text(s.copy), - onPressed: () { - Clipboard.setData( - ClipboardData(text: exportFieldController.text)); - Navigator.pop(context); - }, - ), - ]); + ); + await showRoundDialog( + context, + s.export, + TextField( + decoration: const InputDecoration( + labelText: 'JSON', + ), + maxLines: 7, + controller: exportFieldController, + ), + [ + TextButton( + child: Text(s.copy), + onPressed: () { + Clipboard.setData(ClipboardData(text: exportFieldController.text)); + Navigator.pop(context); + }, + ), + ], + ); } Future _showImportDialog(BuildContext context, S s) async { final importFieldController = TextEditingController(); await showRoundDialog( - context, - s.import, - TextField( - decoration: const InputDecoration( - labelText: 'JSON', - ), - maxLines: 3, - controller: importFieldController, + context, + s.import, + TextField( + decoration: const InputDecoration( + labelText: 'JSON', ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), - TextButton( - onPressed: () async => - await _import(importFieldController.text.trim(), context, s), - child: const Text('GO'), - ) - ]); + maxLines: 3, + controller: importFieldController, + ), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), + TextButton( + onPressed: () async => + await _import(importFieldController.text.trim(), context, s), + child: const Text('GO'), + ) + ], + ); } Future _import(String text, BuildContext context, S s) async { @@ -165,32 +175,36 @@ class BackupPage extends StatelessWidget { } await showRoundDialog( - context, s.attention, Text(s.restoreSureWithDate(backup.date)), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel), - ), - TextButton( - onPressed: () async { - for (final s in backup.snippets) { - snippet.put(s); - } - for (final s in backup.spis) { - server.put(s); - } - for (final s in backup.keys) { - privateKey.put(s); - } - setting.primaryColor.put(backup.primaryColor); - setting.serverStatusUpdateInterval - .put(backup.serverStatusUpdateInterval); - setting.launchPage.put(backup.launchPage); - Navigator.of(context).pop(); - showSnackBar(context, Text(s.restoreSuccess)); - }, - child: Text(s.ok), - ), - ]); + context, + s.attention, + Text(s.restoreSureWithDate(backup.date)), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), + TextButton( + onPressed: () async { + for (final s in backup.snippets) { + snippet.put(s); + } + for (final s in backup.spis) { + server.put(s); + } + for (final s in backup.keys) { + privateKey.put(s); + } + setting.primaryColor.put(backup.primaryColor); + setting.serverStatusUpdateInterval + .put(backup.serverStatusUpdateInterval); + setting.launchPage.put(backup.launchPage); + Navigator.of(context).pop(); + showSnackBar(context, Text(s.restoreSuccess)); + }, + child: Text(s.ok), + ), + ], + ); } catch (e) { showSnackBar(context, Text(s.invalidJson)); return; diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index 10ff7c2b..a37cfda7 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -45,14 +45,17 @@ class _ConvertPageState extends State super.build(context); return Scaffold( body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 7), - controller: ScrollController(), - child: Column(children: [ + padding: const EdgeInsets.symmetric(horizontal: 7), + controller: ScrollController(), + child: Column( + children: [ const SizedBox(height: 13), _buildInputTop(), _buildTypeOption(), _buildResult(), - ])), + ], + ), + ), floatingActionButton: FloatingActionButton( onPressed: () { try { @@ -119,7 +122,8 @@ class _ConvertPageState extends State ), 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 crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(typeOption[_typeOptionIndex], - textScaleFactor: 1.0, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w500, - color: primaryColor)), + Text( + typeOption[_typeOptionIndex], + textScaleFactor: 1.0, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w500, + color: primaryColor), + ), Text( s.currentMode, textScaleFactor: 1.0, @@ -153,15 +159,17 @@ class _ConvertPageState extends State ), ), children: typeOption - .map((e) => ListTile( - title: Text( - e, - style: TextStyle( - color: _theme.textTheme.bodyText2?.color?.withAlpha(177), - ), + .map( + (e) => ListTile( + title: Text( + e, + style: TextStyle( + color: _theme.textTheme.bodyText2?.color?.withAlpha(177), ), - trailing: _buildRadio(typeOption.indexOf(e)), - )) + ), + trailing: _buildRadio(typeOption.indexOf(e)), + ), + ) .toList(), ), ); diff --git a/lib/view/page/debug.dart b/lib/view/page/debug.dart index 0f357782..1f2d03de 100644 --- a/lib/view/page/debug.dart +++ b/lib/view/page/debug.dart @@ -13,8 +13,10 @@ class _DebugPageState extends State { @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 { fontWeight: FontWeight.bold, ), child: SingleChildScrollView( - child: Consumer(builder: (_, debug, __) { - return Column( + child: Consumer( + builder: (_, debug, __) { + return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: debug.widgets); - }), + children: debug.widgets, + ); + }, + ), ), ), ); diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index 228d8f86..50d307fc 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -66,8 +66,9 @@ class _DockerManagePageState extends State { title: TwoLineText(up: 'Docker', down: widget.spi.name), actions: [ IconButton( - onPressed: () => docker.refresh(), - icon: const Icon(Icons.refresh)) + onPressed: () => docker.refresh(), + icon: const Icon(Icons.refresh), + ) ], ), body: _buildMain(docker), @@ -124,8 +125,13 @@ class _DockerManagePageState extends State { 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), ) @@ -191,31 +197,34 @@ class _DockerManagePageState extends State { Future onPwdRequest() async { if (!mounted) return ''; await showRoundDialog( - context, - widget.spi.user, - TextField( - controller: textController, - keyboardType: TextInputType.visiblePassword, - obscureText: true, - onSubmitted: (_) => onSubmitted(), - decoration: InputDecoration( - labelText: s.pwd, + context, + widget.spi.user, + TextField( + controller: textController, + keyboardType: TextInputType.visiblePassword, + obscureText: true, + onSubmitted: (_) => onSubmitted(), + decoration: InputDecoration( + labelText: s.pwd, + ), + ), + [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + child: Text(s.cancel), + ), + TextButton( + onPressed: () => onSubmitted(), + child: Text( + s.ok, + style: const TextStyle(color: Colors.red), ), ), - [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }, - child: Text(s.cancel)), - TextButton( - onPressed: () => onSubmitted(), - child: Text( - s.ok, - style: const TextStyle(color: Colors.red), - )), - ]); + ], + ); return textController.text.trim(); } @@ -264,30 +273,29 @@ class _DockerManagePageState extends State { return const SizedBox(); } return ExpansionTile( - title: Text(s.imagesList), - subtitle: Text( - s.dockerImagesFmt(docker.images!.length), - style: greyTextStyle, - ), - children: docker.images! - .map( - (e) => ListTile( - title: Text(e.repo), - subtitle: Text('${e.tag} - ${e.size}'), - trailing: IconButton( - icon: const Icon(Icons.delete), - onPressed: () async { - final result = await _docker.run('docker rmi ${e.id} -f'); - if (result != null) { - showSnackBar( - context, Text(getErrMsg(result) ?? s.unknownError)); - } - }, + title: Text(s.imagesList), + subtitle: Text( + s.dockerImagesFmt(docker.images!.length), + style: greyTextStyle, + ), + children: docker.images! + .map( + (e) => ListTile( + title: Text(e.repo), + subtitle: Text('${e.tag} - ${e.size}'), + trailing: IconButton( + icon: const Icon(Icons.delete), + onPressed: () async { + final result = await _docker.run('docker rmi ${e.id} -f'); + if (result != null) { + showSnackBar( + context, Text(getErrMsg(result) ?? s.unknownError)); + } + }, + ), ), - ), - ) - .toList(), - ); + ) + .toList()); } Widget _buildLoading(DockerProvider docker) { @@ -318,8 +326,9 @@ class _DockerManagePageState extends State { textAlign: TextAlign.center, ), TextButton( - onPressed: () => _showEditHostDialog(docker), - child: Text(s.dockerEditHost)) + onPressed: () => _showEditHostDialog(docker), + child: Text(s.dockerEditHost), + ) ], ), ); @@ -342,8 +351,9 @@ class _DockerManagePageState extends State { ), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), ], ); } @@ -399,14 +409,16 @@ class _DockerManagePageState extends State { return ExpansionTile( title: Text(s.containerStatus), subtitle: Text(_buildSubtitle(running), style: greyTextStyle), - children: running.map((item) { - return ListTile( - title: Text(item.image), - subtitle: Text(item.status), - trailing: - _buildMoreBtn(item.running, item.containerId, docker.isBusy), - ); - }).toList(), + children: running.map( + (item) { + return ListTile( + title: Text(item.image), + subtitle: Text(item.status), + trailing: + _buildMoreBtn(item.running, item.containerId, docker.isBusy), + ); + }, + ).toList(), ); } diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index 744fdb76..af68f026 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -134,12 +134,15 @@ class _MyHomePageState extends State height: 50, width: isSelected ? width : width - 17, decoration: BoxDecoration( - color: isSelected - ? isDarkMode - ? Colors.white12 - : Colors.black.withOpacity(0.07) - : Colors.transparent, - borderRadius: const BorderRadius.all(Radius.circular(50))), + color: isSelected + ? isDarkMode + ? Colors.white12 + : Colors.black.withOpacity(0.07) + : Colors.transparent, + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + ), child: IconButton( icon: Icon(item.icon), tooltip: tabTitleName(context, idx), @@ -158,18 +161,21 @@ class _MyHomePageState extends State Widget _buildBottom(BuildContext context) { return SafeArea( - child: Container( - height: 56, - padding: const EdgeInsets.only(left: 8, top: 4, bottom: 4, right: 8), - width: _width, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: tabItems.map((item) { - int itemIndex = tabItems.indexOf(item); - return _buildItem(itemIndex, item, _selectIndex == itemIndex); - }).toList(), + child: Container( + height: 56, + padding: const EdgeInsets.only(left: 8, top: 4, bottom: 4, right: 8), + width: _width, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: tabItems.map( + (item) { + int itemIndex = tabItems.indexOf(item); + return _buildItem(itemIndex, item, _selectIndex == itemIndex); + }, + ).toList(), + ), ), - )); + ); } Widget _buildDrawer() { @@ -217,18 +223,25 @@ class _MyHomePageState extends State leading: const Icon(Icons.info), title: Text(s.feedback), onTap: () => showRoundDialog( - context, s.feedback, Text(s.feedbackOnGithub), [ - TextButton( + context, + s.feedback, + Text(s.feedbackOnGithub), + [ + TextButton( onPressed: () => Clipboard.setData( const ClipboardData(text: issueUrl)), - child: Text(s.copy)), - TextButton( + child: Text(s.copy), + ), + TextButton( onPressed: () => openUrl(issueUrl), - child: Text(s.feedback)), - TextButton( + 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), @@ -271,10 +284,11 @@ class _MyHomePageState extends State alignment: Alignment.center, children: [ ConstrainedBox( - constraints: const BoxConstraints(maxHeight: 53, maxWidth: 53), - child: Container( - color: primaryColor, - )), + constraints: const BoxConstraints(maxHeight: 53, maxWidth: 53), + child: Container( + color: primaryColor, + ), + ), ConstrainedBox( constraints: const BoxConstraints(maxHeight: 83, maxWidth: 83), child: appIcon, diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 432eb6cd..d71bf4f9 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -51,8 +51,9 @@ class _PingPageState extends State super.build(context); return Scaffold( body: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 7), - child: Column(children: [ + padding: const EdgeInsets.symmetric(horizontal: 7), + child: Column( + children: [ const SizedBox(height: 13), buildInput(context, _textEditingController, hint: s.inputDomainHere, @@ -69,7 +70,9 @@ class _PingPageState extends State return _buildResultItem(result); }), ), - ])), + ], + ), + ), floatingActionButton: FloatingActionButton( heroTag: 'ping fab', onPressed: () { @@ -87,19 +90,30 @@ class _PingPageState extends State Widget _buildResultItem(PingResult result) { final unknown = s.unknown; final ms = s.ms; - return RoundRectCard(ListTile( - contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), - title: Text(result.serverName, + return RoundRectCard( + ListTile( + contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), + title: Text( + result.serverName, style: TextStyle( - fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor)), - subtitle: Text( - _buildPingSummary(result, unknown, ms), - style: summaryTextStyle, - ), - trailing: Text( + 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) { diff --git a/lib/view/page/private_key/edit.dart b/lib/view/page/private_key/edit.dart index fc932904..96e0c0b4 100644 --- a/lib/view/page/private_key/edit.dart +++ b/lib/view/page/private_key/edit.dart @@ -51,17 +51,20 @@ class _PrivateKeyEditPageState extends State @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [ - widget.info != null - ? IconButton( - tooltip: s.delete, - onPressed: () { - _provider.delInfo(widget.info!); - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.delete)) - : const SizedBox() - ]), + appBar: AppBar( + title: Text(s.edit, style: textSize18), + actions: [ + widget.info != null + ? IconButton( + tooltip: s.delete, + onPressed: () { + _provider.delInfo(widget.info!); + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.delete)) + : const SizedBox() + ], + ), body: ListView( padding: const EdgeInsets.all(13), children: [ diff --git a/lib/view/page/private_key/list.dart b/lib/view/page/private_key/list.dart index 1dc1f9e5..90df02d8 100644 --- a/lib/view/page/private_key/list.dart +++ b/lib/view/page/private_key/list.dart @@ -51,19 +51,22 @@ class _PrivateKeyListState extends State { textAlign: TextAlign.center, ), TextButton( - onPressed: () => AppRoute( - PrivateKeyEditPage(info: key.infos[idx]), - 'private key edit page') - .go(context), - child: Text( - s.edit, - style: _textStyle, - )) + onPressed: () => AppRoute( + PrivateKeyEditPage(info: key.infos[idx]), + 'private key edit page') + .go(context), + child: Text( + s.edit, + style: _textStyle, + ), + ) ], ), )); }) - : Center(child: Text(s.noSavedPrivateKey)); + : Center( + child: Text(s.noSavedPrivateKey), + ); }, ), floatingActionButton: FloatingActionButton( diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 56c2bd1a..9cbf2388 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -37,8 +37,9 @@ class _ServerDetailPageState extends State Widget build(BuildContext context) { return Consumer(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, + ), ); }); } @@ -211,8 +212,9 @@ class _ServerDetailPageState extends State _buildMemExplain( (ss.memory.cache * mb).convertBytes, pColor.withAlpha(77)), _buildMemExplain( - ((ss.memory.total - ss.memory.used) * mb).convertBytes, - progressColor.resolve(context)) + ((ss.memory.total - ss.memory.used) * mb).convertBytes, + progressColor.resolve(context), + ) ], ), const SizedBox( @@ -363,11 +365,12 @@ class _ServerDetailPageState extends State textScaleFactor: 1.0), ), SizedBox( - width: _media.size.width / 4, - child: Text(ns.speedOut(device: device), - style: textSize11, - textAlign: TextAlign.right, - textScaleFactor: 1.0)) + width: _media.size.width / 4, + child: Text(ns.speedOut(device: device), + style: textSize11, + textAlign: TextAlign.right, + textScaleFactor: 1.0), + ) ], ), ); diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index e3659357..33f2fff9 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -63,30 +63,40 @@ class _ServerEditPageState extends State with AfterLayoutMixin { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [ - widget.spi != null - ? IconButton( - onPressed: () { - showRoundDialog(context, s.attention, - Text(s.sureToDeleteServer(widget.spi!.name)), [ - TextButton( - onPressed: () { - _serverProvider.delServer(widget.spi!); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }, - child: Text( - s.ok, - style: const TextStyle(color: Colors.red), - )), - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)) - ]); - }, - icon: const Icon(Icons.delete)) - : const SizedBox() - ]), + appBar: AppBar( + title: Text(s.edit, style: textSize18), + actions: [ + widget.spi != null + ? IconButton( + onPressed: () { + showRoundDialog( + context, + s.attention, + Text(s.sureToDeleteServer(widget.spi!.name)), + [ + TextButton( + onPressed: () { + _serverProvider.delServer(widget.spi!); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + }, + child: Text( + s.ok, + style: const TextStyle(color: Colors.red), + ), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ) + ], + ); + }, + icon: const Icon(Icons.delete), + ) + : const SizedBox() + ], + ), body: SingleChildScrollView( padding: const EdgeInsets.all(17), child: Column( @@ -148,42 +158,47 @@ class _ServerEditPageState extends State with AfterLayoutMixin { ) : const SizedBox(), usePublicKey - ? Consumer(builder: (_, key, __) { - for (var item in key.infos) { - if (item.id == widget.spi?.pubKeyId) { - _pubKeyIndex ??= key.infos.indexOf(item); + ? Consumer( + builder: (_, key, __) { + for (var item in key.infos) { + if (item.id == widget.spi?.pubKeyId) { + _pubKeyIndex ??= key.infos.indexOf(item); + } } - } - final tiles = key.infos - .map( - (e) => ListTile( - contentPadding: EdgeInsets.zero, - title: Text(e.id, textAlign: TextAlign.start), - trailing: _buildRadio(key.infos.indexOf(e), e)), - ) - .toList(); - tiles.add(ListTile( - title: Text(s.addPrivateKey), - contentPadding: EdgeInsets.zero, - trailing: IconButton( - icon: const Icon(Icons.add), - onPressed: () => AppRoute(const PrivateKeyEditPage(), - 'private key edit page') - .go(context), - ), - )); - return ExpansionTile( - textColor: primaryColor, - iconColor: primaryColor, - tilePadding: EdgeInsets.zero, - childrenPadding: EdgeInsets.zero, - title: Text( - s.choosePrivateKey, - style: const TextStyle(fontSize: 14), - ), - children: tiles, - ); - }) + final tiles = key.infos + .map( + (e) => ListTile( + contentPadding: EdgeInsets.zero, + title: Text(e.id, textAlign: TextAlign.start), + trailing: _buildRadio(key.infos.indexOf(e), e)), + ) + .toList(); + tiles.add( + ListTile( + title: Text(s.addPrivateKey), + contentPadding: EdgeInsets.zero, + trailing: IconButton( + icon: const Icon(Icons.add), + onPressed: () => AppRoute( + const PrivateKeyEditPage(), + 'private key edit page') + .go(context), + ), + ), + ); + return ExpansionTile( + textColor: primaryColor, + iconColor: primaryColor, + tilePadding: EdgeInsets.zero, + childrenPadding: EdgeInsets.zero, + title: Text( + s.choosePrivateKey, + style: const TextStyle(fontSize: 14), + ), + children: tiles, + ); + }, + ) : const SizedBox() ], ), @@ -197,18 +212,19 @@ class _ServerEditPageState extends State with AfterLayoutMixin { } if (!usePublicKey && passwordController.text == '') { final cancel = await showRoundDialog( - context, - s.attention, - Text(s.sureNoPwd), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(s.ok)), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(s.cancel)) - ], - barrierDismiss: false); + context, + s.attention, + Text(s.sureNoPwd), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text(s.ok)), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text(s.cancel)) + ], + barrierDismiss: false, + ); if (cancel ?? true) { return; } @@ -230,12 +246,13 @@ class _ServerEditPageState extends State with AfterLayoutMixin { final authorization = passwordController.text; final spi = ServerPrivateInfo( - name: nameController.text, - ip: ipController.text, - port: int.parse(portController.text), - user: usernameController.text, - pwd: authorization, - pubKeyId: usePublicKey ? _keyInfo!.id : null); + name: nameController.text, + ip: ipController.text, + port: int.parse(portController.text), + user: usernameController.text, + pwd: authorization, + pubKeyId: usePublicKey ? _keyInfo!.id : null, + ); if (widget.spi == null) { _serverProvider.addServer(spi); diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 14638cab..f5e7c316 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -55,30 +55,32 @@ class _ServerPageState extends State @override Widget build(BuildContext context) { super.build(context); - final child = Consumer(builder: (_, pro, __) { - if (pro.servers.isEmpty) { - return Center( - child: Text( - s.serverTabEmpty, - textAlign: TextAlign.center, + final child = Consumer( + builder: (_, pro, __) { + if (pro.servers.isEmpty) { + return Center( + child: Text( + s.serverTabEmpty, + textAlign: TextAlign.center, + ), + ); + } + return ListView.separated( + padding: const EdgeInsets.all(7), + controller: ScrollController(), + itemBuilder: (ctx, idx) { + if (idx == pro.servers.length) { + return SizedBox(height: _media.padding.bottom); + } + return _buildEachServerCard(pro.servers[idx]); + }, + itemCount: pro.servers.length + 1, + separatorBuilder: (_, __) => const SizedBox( + height: 3, ), ); - } - return ListView.separated( - padding: const EdgeInsets.all(7), - controller: ScrollController(), - itemBuilder: (ctx, idx) { - if (idx == pro.servers.length) { - return SizedBox(height: _media.padding.bottom); - } - return _buildEachServerCard(pro.servers[idx]); - }, - itemCount: pro.servers.length + 1, - separatorBuilder: (_, __) => const SizedBox( - height: 3, - ), - ); - }); + }, + ); return Scaffold( body: child, floatingActionButton: FloatingActionButton( @@ -102,9 +104,10 @@ class _ServerPageState extends State 'Edit server info page') .go(context), child: Padding( - padding: const EdgeInsets.all(13), - child: _buildRealServerCard( - si.status, si.info.name, si.connectionState, si.info)), + padding: const EdgeInsets.all(13), + child: _buildRealServerCard( + si.status, si.info.name, si.connectionState, si.info), + ), onTap: () => AppRoute(ServerDetailPage('${si.info.ip}:${si.info.port}'), 'server detail page') .go(context), diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index a40d8762..c30b6493 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -71,18 +71,19 @@ class _SettingPageState extends State { } Widget _buildCheckUpdate() { - return Consumer(builder: (_, app, __) { - String display; - if (app.newestBuild != null) { - if (app.newestBuild! > BuildData.build) { - display = s.versionHaveUpdate(app.newestBuild!); + return Consumer( + builder: (_, app, __) { + String display; + if (app.newestBuild != null) { + if (app.newestBuild! > BuildData.build) { + display = s.versionHaveUpdate(app.newestBuild!); + } else { + display = s.versionUpdated(BuildData.build); + } } else { - display = s.versionUpdated(BuildData.build); + display = s.versionUnknownUpdate(BuildData.build); } - } else { - display = s.versionUnknownUpdate(BuildData.build); - } - return ListTile( + return ListTile( contentPadding: roundRectCardPadding, trailing: const Icon(Icons.keyboard_arrow_right), title: Text( @@ -90,8 +91,10 @@ class _SettingPageState extends State { style: textSize13, textAlign: TextAlign.start, ), - onTap: () => doUpdate(context, force: true)); - }); + onTap: () => doUpdate(context, force: true), + ); + }, + ); } Widget _buildUpdateInterval() { @@ -147,24 +150,22 @@ class _SettingPageState extends State { Widget _buildAppColorPreview() { return ExpansionTile( - textColor: priColor, - tilePadding: roundRectCardPadding, - childrenPadding: roundRectCardPadding, - trailing: ClipOval( - child: Container( - color: priColor, - height: 27, - width: 27, - ), + textColor: priColor, + tilePadding: roundRectCardPadding, + childrenPadding: roundRectCardPadding, + trailing: ClipOval( + child: Container( + color: priColor, + height: 27, + width: 27, ), - title: Text( - s.appPrimaryColor, - style: textSize13, - ), - children: [ - _buildAppColorPicker(priColor), - _buildColorPickerConfirmBtn() - ]); + ), + title: Text( + s.appPrimaryColor, + style: textSize13, + ), + children: [_buildAppColorPicker(priColor), _buildColorPickerConfirmBtn()], + ); } Widget _buildAppColorPicker(Color selected) { @@ -204,16 +205,18 @@ class _SettingPageState extends State { ), ), children: tabs - .map((e) => ListTile( - contentPadding: EdgeInsets.zero, - title: Text( - tabTitleName(context, tabs.indexOf(e)), - style: TextStyle( - fontSize: 14, - color: _theme.textTheme.bodyText2!.color!.withAlpha(177)), - ), - trailing: _buildRadio(tabs.indexOf(e)), - )) + .map( + (e) => ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + tabTitleName(context, tabs.indexOf(e)), + style: TextStyle( + fontSize: 14, + color: _theme.textTheme.bodyText2!.color!.withAlpha(177)), + ), + trailing: _buildRadio(tabs.indexOf(e)), + ), + ) .toList(), ); } diff --git a/lib/view/page/sftp/downloaded.dart b/lib/view/page/sftp/downloaded.dart index cb76ba2f..83e4c5e1 100644 --- a/lib/view/page/sftp/downloaded.dart +++ b/lib/view/page/sftp/downloaded.dart @@ -141,18 +141,21 @@ class _SFTPDownloadedPageState extends State { void showFileActionDialog(FileSystemEntity file) { final fileName = file.path.split('/').last; showRoundDialog( - context, - s.choose, - Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - leading: const Icon(Icons.delete), - title: Text(s.delete), - onTap: () { - Navigator.of(context).pop(); - showRoundDialog( - context, s.sureDelete(fileName), const SizedBox(), [ + context, + s.choose, + Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + leading: const Icon(Icons.delete), + title: Text(s.delete), + onTap: () { + Navigator.of(context).pop(); + showRoundDialog( + context, + s.sureDelete(fileName), + const SizedBox(), + [ TextButton( onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel)), @@ -164,21 +167,24 @@ class _SFTPDownloadedPageState extends State { }, child: Text(s.ok), ), - ]); - }, - ), - ListTile( - leading: const Icon(Icons.open_in_new), - title: Text(s.open), - onTap: () { - shareFiles(context, [file.absolute.path]); - }), - ], - ), - [ - TextButton( - onPressed: (() => Navigator.of(context).pop()), - child: Text(s.close)) - ]); + ], + ); + }, + ), + ListTile( + leading: const Icon(Icons.open_in_new), + title: Text(s.open), + onTap: () { + shareFiles(context, [file.absolute.path]); + }, + ), + ], + ), + [ + TextButton( + onPressed: (() => Navigator.of(context).pop()), + child: Text(s.close)) + ], + ); } } diff --git a/lib/view/page/sftp/downloading.dart b/lib/view/page/sftp/downloading.dart index 2e68282a..bd5461cb 100644 --- a/lib/view/page/sftp/downloading.dart +++ b/lib/view/page/sftp/downloading.dart @@ -58,16 +58,18 @@ class _SFTPDownloadingPageState extends State { Widget _wrapInCard(SftpDownloadStatus status, String? subtitle, {Widget? trailing}) { - return RoundRectCard(ListTile( - title: Text(status.fileName), - subtitle: subtitle == null - ? null - : Text( - subtitle, - style: grey, - ), - trailing: trailing, - )); + return RoundRectCard( + ListTile( + title: Text(status.fileName), + subtitle: subtitle == null + ? null + : Text( + subtitle, + style: grey, + ), + trailing: trailing, + ), + ); } Widget _buildItem(SftpDownloadStatus status) { @@ -77,11 +79,14 @@ class _SFTPDownloadingPageState extends State { switch (status.status) { case SftpWorkerStatus.finished: final time = status.spentTime.toString(); - 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))); + 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), + ), + ); case SftpWorkerStatus.downloading: return _wrapInCard( status, @@ -94,11 +99,14 @@ class _SFTPDownloadingPageState extends State { case SftpWorkerStatus.sshConnectted: return _wrapInCard(status, s.sftpSSHConnected, trailing: loadingIcon); default: - return _wrapInCard(status, s.unknown, - trailing: const Icon( - Icons.error, - size: 40, - )); + return _wrapInCard( + status, + s.unknown, + trailing: const Icon( + Icons.error, + size: 40, + ), + ); } } } diff --git a/lib/view/page/sftp/view.dart b/lib/view/page/sftp/view.dart index 927877bd..6fbb075c 100644 --- a/lib/view/page/sftp/view.dart +++ b/lib/view/page/sftp/view.dart @@ -55,34 +55,36 @@ class _SFTPPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - centerTitle: true, - title: TwoLineText(up: 'SFTP', down: widget.spi.name), - actions: [ - IconButton( - onPressed: (() => showRoundDialog( - context, - s.choose, - Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - leading: const Icon(Icons.folder), - title: Text(s.createFolder), - onTap: () => mkdir(context)), - ListTile( - leading: const Icon(Icons.insert_drive_file), - title: Text(s.createFile), - onTap: () => newFile(context)), - ], - ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.close)) - ])), - icon: const Icon(Icons.add), - ) - ]), + centerTitle: true, + title: TwoLineText(up: 'SFTP', down: widget.spi.name), + actions: [ + IconButton( + onPressed: (() => showRoundDialog( + context, + s.choose, + Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + leading: const Icon(Icons.folder), + title: Text(s.createFolder), + onTap: () => mkdir(context)), + ListTile( + leading: const Icon(Icons.insert_drive_file), + title: Text(s.createFile), + onTap: () => newFile(context)), + ], + ), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.close)) + ], + )), + icon: const Icon(Icons.add), + ) + ], + ), body: _buildFileView(), ); } @@ -121,85 +123,90 @@ class _SFTPPageState extends State { return centerCircleLoading; } else { return RefreshIndicator( - child: FadeIn( - key: Key(_status.spi!.name + _status.path!.path), - child: ListView.builder( - itemCount: _status.files!.length + 1, - controller: _scrollController, - itemBuilder: (context, index) { - if (index == 0) { - return _buildDestSelector(); - } - final file = _status.files![index - 1]; - final isDir = file.attr.isDirectory; - return ListTile( - leading: Icon(isDir ? Icons.folder : Icons.insert_drive_file), - title: Text(file.filename), - trailing: Text( - DateTime.fromMillisecondsSinceEpoch( - (file.attr.modifyTime ?? 0) * 1000) - .toString() - .replaceFirst('.000', ''), - style: const TextStyle(color: Colors.grey), - ), - subtitle: - isDir ? null : Text((file.attr.size ?? 0).convertBytes), - onTap: () { - if (isDir) { - _status.path?.update(file.filename); - listDir(path: _status.path?.path); - } else { - onItemPress(context, file, true); - } - }, - onLongPress: () => onItemPress(context, file, false), - ); - }, - ), + child: FadeIn( + key: Key(_status.spi!.name + _status.path!.path), + child: ListView.builder( + itemCount: _status.files!.length + 1, + controller: _scrollController, + itemBuilder: (context, index) { + if (index == 0) { + return _buildDestSelector(); + } + final file = _status.files![index - 1]; + final isDir = file.attr.isDirectory; + return ListTile( + leading: Icon(isDir ? Icons.folder : Icons.insert_drive_file), + title: Text(file.filename), + trailing: Text( + DateTime.fromMillisecondsSinceEpoch( + (file.attr.modifyTime ?? 0) * 1000) + .toString() + .replaceFirst('.000', ''), + style: const TextStyle(color: Colors.grey), + ), + subtitle: + isDir ? null : Text((file.attr.size ?? 0).convertBytes), + onTap: () { + if (isDir) { + _status.path?.update(file.filename); + listDir(path: _status.path?.path); + } else { + onItemPress(context, file, true); + } + }, + onLongPress: () => onItemPress(context, file, false), + ); + }, ), - onRefresh: () => listDir(path: _status.path?.path)); + ), + onRefresh: () => listDir(path: _status.path?.path), + ); } } void onItemPress(BuildContext context, SftpName file, bool showDownload) { showRoundDialog( - context, - s.choose, - Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - leading: const Icon(Icons.delete), - title: Text(s.delete), - onTap: () => delete(context, file), - ), - ListTile( - leading: const Icon(Icons.edit), - title: Text(s.rename), - onTap: () => rename(context, file), - ), - showDownload - ? ListTile( - leading: const Icon(Icons.download), - title: Text(s.download), - onTap: () => download(context, file), - ) - : const SizedBox() - ], - ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)) - ]); + context, + s.choose, + Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + leading: const Icon(Icons.delete), + title: Text(s.delete), + onTap: () => delete(context, file), + ), + ListTile( + leading: const Icon(Icons.edit), + title: Text(s.rename), + onTap: () => rename(context, file), + ), + showDownload + ? ListTile( + leading: const Icon(Icons.download), + title: Text(s.download), + onTap: () => download(context, file), + ) + : const SizedBox() + ], + ), + [ + TextButton( + 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}'), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel)), - TextButton( + showRoundDialog( + context, + s.download, + Text('${s.dl2Local(name.filename)}\n${s.keepForeground}'), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel)), + TextButton( onPressed: () async { Navigator.of(context).pop(); final prePath = _status.path!.path; @@ -207,36 +214,56 @@ class _SFTPPageState extends State { prePath + (prePath.endsWith('/') ? '' : '/') + name.filename; final local = '${(await sftpDownloadDir).path}$remotePath'; final pubKeyId = _status.spi!.pubKeyId; + locator().add( - DownloadItem(_status.spi!, remotePath, local), - key: pubKeyId == null - ? null - : locator().get(pubKeyId).privateKey); + DownloadItem( + _status.spi!, + remotePath, + local, + ), + key: pubKeyId == null + ? null + : locator().get(pubKeyId).privateKey, + ); + Navigator.of(context).pop(); - showRoundDialog(context, s.goSftpDlPage, const SizedBox(), [ - TextButton( + showRoundDialog( + context, + s.goSftpDlPage, + const SizedBox(), + [ + TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), - TextButton( + 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)), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('Cancel')), - TextButton( + showRoundDialog( + context, + s.attention, + Text(s.sureDelete(file.filename)), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Cancel')), + TextButton( onPressed: () { _status.client!.remove(file.filename); Navigator.of(context).pop(); @@ -245,126 +272,149 @@ class _SFTPPageState extends State { child: Text( s.delete, style: const TextStyle(color: Colors.red), - )), - ]); + ), + ), + ], + ); } void mkdir(BuildContext context) { Navigator.of(context).pop(); final textController = TextEditingController(); showRoundDialog( - context, - s.createFolder, - TextField( - controller: textController, - decoration: InputDecoration( - labelText: s.name, + context, + s.createFolder, + TextField( + controller: textController, + decoration: InputDecoration( + labelText: s.name, + ), + ), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), + TextButton( + onPressed: () { + if (textController.text == '') { + showRoundDialog( + context, + s.attention, + Text(s.fieldMustNotEmpty), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.ok)), + ], + ); + return; + } + _status.client! + .mkdir('${_status.path!.path}/${textController.text}'); + Navigator.of(context).pop(); + listDir(); + }, + child: Text( + s.ok, + style: const TextStyle(color: Colors.red), ), ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), - TextButton( - onPressed: () { - if (textController.text == '') { - showRoundDialog( - context, s.attention, Text(s.fieldMustNotEmpty), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.ok)), - ]); - return; - } - _status.client! - .mkdir('${_status.path!.path}/${textController.text}'); - Navigator.of(context).pop(); - listDir(); - }, - child: Text( - s.ok, - style: const TextStyle(color: Colors.red), - )), - ]); + ], + ); } void newFile(BuildContext context) { Navigator.of(context).pop(); final textController = TextEditingController(); showRoundDialog( - context, - s.createFile, - TextField( - controller: textController, - decoration: InputDecoration( - labelText: s.name, + context, + s.createFile, + TextField( + controller: textController, + decoration: InputDecoration( + labelText: s.name, + ), + ), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), + TextButton( + onPressed: () async { + if (textController.text == '') { + showRoundDialog( + context, + s.attention, + Text(s.fieldMustNotEmpty), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.ok), + ), + ], + ); + return; + } + (await _status.client! + .open('${_status.path!.path}/${textController.text}')) + .writeBytes(Uint8List(0)); + Navigator.of(context).pop(); + listDir(); + }, + child: Text( + s.ok, + style: const TextStyle(color: Colors.red), ), ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), - TextButton( - onPressed: () async { - if (textController.text == '') { - showRoundDialog( - context, s.attention, Text(s.fieldMustNotEmpty), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.ok)), - ]); - return; - } - (await _status.client! - .open('${_status.path!.path}/${textController.text}')) - .writeBytes(Uint8List(0)); - Navigator.of(context).pop(); - listDir(); - }, - child: Text( - s.ok, - style: const TextStyle(color: Colors.red), - )), - ]); + ], + ); } void rename(BuildContext context, SftpName file) { Navigator.of(context).pop(); final textController = TextEditingController(); showRoundDialog( - context, - s.rename, - TextField( - controller: textController, - decoration: InputDecoration( - labelText: s.name, + context, + s.rename, + TextField( + controller: textController, + decoration: InputDecoration( + labelText: s.name, + ), + ), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel)), + TextButton( + onPressed: () async { + if (textController.text == '') { + showRoundDialog( + context, + s.attention, + Text(s.fieldMustNotEmpty), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.ok), + ), + ], + ); + return; + } + await _status.client!.rename(file.filename, textController.text); + Navigator.of(context).pop(); + listDir(); + }, + child: Text( + s.rename, + style: const TextStyle(color: Colors.red), ), ), - [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.cancel)), - TextButton( - onPressed: () async { - if (textController.text == '') { - showRoundDialog( - context, s.attention, Text(s.fieldMustNotEmpty), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(s.ok)), - ]); - return; - } - await _status.client! - .rename(file.filename, textController.text); - Navigator.of(context).pop(); - listDir(); - }, - child: Text( - s.rename, - style: const TextStyle(color: Colors.red), - )), - ]); + ], + ); } Future listDir({String? path, SSHClient? client}) async { @@ -388,10 +438,17 @@ class _SFTPPageState extends State { }); } } catch (e) { - await showRoundDialog(context, s.error, Text(e.toString()), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)) - ]); + await showRoundDialog( + context, + s.error, + Text(e.toString()), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.ok), + ) + ], + ); if (_status.path!.undo()) { await listDir(); } @@ -420,11 +477,12 @@ class _SFTPPageState extends State { _status.selected = true; _status.path = AbsolutePath('/'); listDir( - client: locator() - .servers - .firstWhere((s) => s.info == spi) - .client, - path: '/'); + client: locator() + .servers + .firstWhere((s) => s.info == spi) + .client, + path: '/', + ); }, ); } diff --git a/lib/view/page/snippet/edit.dart b/lib/view/page/snippet/edit.dart index 50696674..5eaf2374 100644 --- a/lib/view/page/snippet/edit.dart +++ b/lib/view/page/snippet/edit.dart @@ -41,17 +41,20 @@ class _SnippetEditPageState extends State @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(s.edit, style: textSize18), actions: [ - widget.snippet != null - ? IconButton( - onPressed: () { - _provider.del(widget.snippet!); - Navigator.of(context).pop(); - }, - tooltip: s.delete, - icon: const Icon(Icons.delete)) - : const SizedBox() - ]), + appBar: AppBar( + title: Text(s.edit, style: textSize18), + actions: [ + widget.snippet != null + ? IconButton( + onPressed: () { + _provider.del(widget.snippet!); + Navigator.of(context).pop(); + }, + tooltip: s.delete, + icon: const Icon(Icons.delete)) + : const SizedBox() + ], + ), body: ListView( padding: const EdgeInsets.all(13), children: [ diff --git a/lib/view/page/snippet/list.dart b/lib/view/page/snippet/list.dart index f53ed5d1..73a81608 100644 --- a/lib/view/page/snippet/list.dart +++ b/lib/view/page/snippet/list.dart @@ -59,107 +59,135 @@ class _SnippetListPageState extends State { itemCount: key.snippets.length, itemExtent: 57, itemBuilder: (context, idx) { - return RoundRectCard(Padding( - padding: roundRectCardPadding, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - key.snippets[idx].name, - textAlign: TextAlign.center, - ), - Row(children: [ - TextButton( - onPressed: () => AppRoute( - SnippetEditPage( - snippet: key.snippets[idx]), - 'snippet edit page') - .go(context), - child: Text( - s.edit, - style: _textStyle, - )), - TextButton( - onPressed: () { - final snippet = key.snippets[idx]; - if (widget.spi == null) { - _showRunDialog(snippet); - return; - } - run(context, snippet); - }, - child: Text( - s.run, - style: _textStyle, - )) - ]) - ], + return RoundRectCard( + Padding( + padding: roundRectCardPadding, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + key.snippets[idx].name, + textAlign: TextAlign.center, + ), + Row( + children: [ + TextButton( + onPressed: () => AppRoute( + SnippetEditPage( + snippet: key.snippets[idx]), + 'snippet edit page') + .go(context), + child: Text( + s.edit, + style: _textStyle, + ), + ), + TextButton( + onPressed: () { + final snippet = key.snippets[idx]; + if (widget.spi == null) { + _showRunDialog(snippet); + return; + } + run(context, snippet); + }, + 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(builder: (_, provider, __) { - 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, + showRoundDialog( + context, + s.chooseDestination, + Consumer( + builder: (_, provider, __) { + 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), + ) + ], ), - 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), - ) - ])); - }), [ - TextButton( - onPressed: () async => run(context, snippet), child: Text(s.run)), - TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel)), - ]); + ); + }, + ), + [ + TextButton( + onPressed: () async => run(context, snippet), + child: Text(s.run), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.cancel), + ), + ], + ); } Future run(BuildContext context, Snippet snippet) async { final result = await locator() .runSnippet(widget.spi ?? _selectedIndex, snippet); if (result != null) { - showRoundDialog(context, s.result, - Text(result, style: const TextStyle(fontSize: 13)), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.close)) - ]); + showRoundDialog( + context, + s.result, + Text(result, style: const TextStyle(fontSize: 13)), + [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(s.close), + ) + ], + ); } } }