opt.: backup

This commit is contained in:
lollipopkit
2023-09-13 13:05:19 +08:00
parent 9ce7138d9b
commit 269c2a0a10
37 changed files with 535 additions and 632 deletions

View File

@@ -1,20 +1,24 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:logging/logging.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/utils/backup.dart';
import 'package:toolbox/core/utils/icloud.dart';
import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/data/model/app/backup.dart';
import 'package:toolbox/data/res/path.dart';
import 'package:toolbox/view/widget/round_rect_card.dart';
import '../../core/utils/misc.dart';
import '../../core/utils/ui.dart';
import '../../data/res/ui.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
import '../widget/custom_appbar.dart';
import '../widget/store_switch.dart';
final _logger = Logger('Backup');
class BackupPage extends StatelessWidget {
BackupPage({Key? key}) : super(key: key);
@@ -62,7 +66,7 @@ class BackupPage extends StatelessWidget {
s.backup,
Icons.save,
() async {
await backup();
await Backup.backup();
await shareFiles(context, [await backupPath]);
},
)
@@ -103,53 +107,47 @@ class BackupPage extends StatelessWidget {
textAlign: TextAlign.center,
),
width13,
IconButton(
onPressed: () async {
showLoadingDialog(context);
await syncApple();
context.pop();
showRestartSnackbar(context, btn: s.restart, msg: s.icloudSynced);
},
icon: const Icon(Icons.sync)),
width13,
buildSwitch(context, _setting.icloudSync)
// Hive db only save data into local file after app exit,
// so this button is useless
// IconButton(
// onPressed: () async {
// showLoadingDialog(context);
// await ICloud.syncDb();
// context.pop();
// showRestartSnackbar(context, btn: s.restart, msg: s.icloudSynced);
// },
// icon: const Icon(Icons.sync)),
// width13,
StoreSwitch(prop: _setting.icloudSync)
],
);
}
Future<void> _onRestore(BuildContext context, S s) async {
final path = await pickOneFile();
if (path == null) {
showSnackBar(context, Text(s.notSelected));
return;
}
if (path == null) return;
final file = File(path);
if (!file.existsSync()) {
showSnackBar(context, Text(s.fileNotExist(path)));
if (!await file.exists()) {
context.showSnackBar(s.fileNotExist(path));
return;
}
final text = await file.readAsString();
_import(text, context, s);
}
Future<void> _import(String text, BuildContext context, S s) async {
if (text.isEmpty) {
showSnackBar(context, Text(s.fieldMustNotEmpty));
context.showSnackBar(s.fieldMustNotEmpty);
return;
}
await _importBackup(text, context, s);
}
Future<void> _importBackup(String raw, BuildContext context, S s) async {
try {
final backup = await decodeBackup(raw);
context.showLoadingDialog();
final backup = await compute(Backup.fromJsonString, text.trim());
if (backupFormatVersion != backup.version) {
showSnackBar(context, Text(s.backupVersionNotMatch));
context.showSnackBar(s.backupVersionNotMatch);
return;
}
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(s.restore),
child: Text(s.restoreSureWithDate(backup.date)),
actions: [
@@ -159,17 +157,19 @@ class BackupPage extends StatelessWidget {
),
TextButton(
onPressed: () async {
restore(backup);
backup.restore();
context.pop();
showRestartSnackbar(context, btn: s.restart, msg: s.needRestart);
context.showRestartSnackbar(btn: s.restart, msg: s.needRestart);
},
child: Text(s.ok),
),
],
);
} catch (e) {
showSnackBar(context, Text(e.toString()));
rethrow;
} catch (e, trace) {
_logger.warning('Import backup failed', e, trace);
context.showSnackBar(e.toString());
} finally {
context.pop();
}
}
}

View File

@@ -3,10 +3,10 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/view/widget/value_notifier.dart';
import '../../core/utils/ui.dart';
import '../widget/custom_appbar.dart';
import '../widget/input_field.dart';
import '../widget/popup_menu.dart';
@@ -74,7 +74,7 @@ class _ConvertPageState extends State<ConvertPage>
_textEditingControllerResult.text = doConvert();
FocusScope.of(context).requestFocus(FocusNode());
} catch (e) {
showSnackBar(context, Text('Error: \n$e'));
context.showSnackBar('Error: \n$e');
}
},
tooltip: _s.convert,

View File

@@ -6,7 +6,6 @@ import 'package:toolbox/core/route.dart';
import 'package:toolbox/data/model/docker/image.dart';
import 'package:toolbox/view/widget/input_field.dart';
import '../../core/utils/ui.dart';
import '../../data/model/docker/ps.dart';
import '../../data/model/server/server_private_info.dart';
import '../../data/provider/docker.dart';
@@ -60,7 +59,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
_docker.init(
client,
widget.spi.user,
(user) async => await showPwdDialog(context, user),
(user) async => await context.showPwdDialog(user),
widget.spi.id,
context,
);
@@ -76,7 +75,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
actions: [
IconButton(
onPressed: () async {
showLoadingDialog(context);
context.showLoadingDialog();
await _docker.refresh();
context.pop();
},
@@ -101,8 +100,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
final imageCtrl = TextEditingController();
final nameCtrl = TextEditingController();
final argsCtrl = TextEditingController();
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.newContainer),
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -151,8 +149,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
}
Future<void> _showAddCmdPreview(String cmd) async {
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.preview),
child: Text(cmd),
actions: [
@@ -163,11 +160,11 @@ class _DockerManagePageState extends State<DockerManagePage> {
TextButton(
onPressed: () async {
context.pop();
showLoadingDialog(context);
context.showLoadingDialog();
final result = await _docker.run(cmd);
context.pop();
if (result != null) {
showSnackBar(context, Text(result.message ?? _s.unknownError));
context.showSnackBar(result.message ?? _s.unknownError);
}
},
child: Text(_s.run),
@@ -261,8 +258,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
}
void _showImageRmDialog(DockerImage e) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(e.repo)),
actions: [
@@ -277,10 +273,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
'docker rmi ${e.id} -f',
);
if (result != null) {
showSnackBar(
context,
Text(result.message ?? _s.unknownError),
);
context.showSnackBar(result.message ?? _s.unknownError);
}
},
child: Text(_s.ok, style: textRed),
@@ -382,15 +375,14 @@ class _DockerManagePageState extends State<DockerManagePage> {
onSelected: (DockerMenuType item) async {
switch (item) {
case DockerMenuType.rm:
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(dItem.name)),
actions: [
TextButton(
onPressed: () async {
context.pop();
showLoadingDialog(context);
context.showLoadingDialog();
await _docker.delete(dItem.containerId);
context.pop();
},
@@ -400,17 +392,17 @@ class _DockerManagePageState extends State<DockerManagePage> {
);
break;
case DockerMenuType.start:
showLoadingDialog(context);
context.showLoadingDialog();
await _docker.start(dItem.containerId);
context.pop();
break;
case DockerMenuType.stop:
showLoadingDialog(context);
context.showLoadingDialog();
await _docker.stop(dItem.containerId);
context.pop();
break;
case DockerMenuType.restart:
showLoadingDialog(context);
context.showLoadingDialog();
await _docker.restart(dItem.containerId);
context.pop();
break;
@@ -484,8 +476,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
final id = widget.spi.id;
final host = _store.fetch(id) ?? 'unix:///run/user/1000/docker.sock';
final ctrl = TextEditingController(text: host);
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.dockerEditHost),
child: Input(
maxLines: 1,

View File

@@ -9,7 +9,6 @@ import 'package:flutter_highlight/themes/a11y-light.dart';
import 'package:flutter_highlight/themes/monokai.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/core/utils/ui.dart';
import 'package:toolbox/data/res/highlight.dart';
import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/locator.dart';
@@ -107,7 +106,7 @@ class _EditorPageState extends State<EditorPage> {
// If path is not null, then it's a file editor
// save the text and return true to pop the page
if (widget.path != null) {
showLoadingDialog(context);
context.showLoadingDialog();
await File(widget.path!).writeAsString(_controller.text);
context.pop();
context.pop(true);

View File

@@ -4,6 +4,7 @@ import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:get_it/get_it.dart';
import 'package:toolbox/core/extension/context.dart';
import '../../core/analysis.dart';
import '../../core/route.dart';
@@ -205,8 +206,7 @@ class _HomePageState extends State<HomePage>
children: [
_buildIcon(),
TextButton(
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_versionStr),
child: const Text(BuildData.buildAt),
),
@@ -265,8 +265,7 @@ class _HomePageState extends State<HomePage>
}
void _showAboutDialog() {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.about),
child: _buildAboutContent(),
actions: [
@@ -374,8 +373,7 @@ class _HomePageState extends State<HomePage>
final newSettings = json.decode(result) as Map<String, dynamic>;
_setting.box.putAll(newSettings);
} catch (e) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: Text('${_s.save}:\n$e'),
);

View File

@@ -8,7 +8,6 @@ import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/view/widget/value_notifier.dart';
import '../../core/extension/uint8list.dart';
import '../../core/utils/ui.dart';
import '../../data/model/server/ping_result.dart';
import '../../data/provider/server.dart';
import '../../data/res/color.dart';
@@ -71,8 +70,7 @@ class _PingPageState extends State<PingPage>
return FloatingActionButton(
heroTag: 'ping',
onPressed: () {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.choose),
child: Input(
autoFocus: true,
@@ -95,8 +93,7 @@ class _PingPageState extends State<PingPage>
try {
await doPing();
} catch (e) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: Text(e.toString()),
actions: [
@@ -173,18 +170,18 @@ class _PingPageState extends State<PingPage>
_results.value.clear();
final target = _textEditingController.text.trim();
if (target.isEmpty) {
showSnackBar(context, Text(_s.pingInputIP));
context.showSnackBar(_s.pingInputIP);
return;
}
if (_serverProvider.servers.isEmpty) {
showSnackBar(context, Text(_s.pingNoServer));
context.showSnackBar(_s.pingNoServer);
return;
}
/// avoid ping command injection
if (!targetReg.hasMatch(target)) {
showSnackBar(context, Text(_s.pingInputIP));
context.showSnackBar(_s.pingInputIP);
return;
}

View File

@@ -11,7 +11,6 @@ import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/view/widget/input_field.dart';
import '../../../core/utils/server.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/server/private_key_info.dart';
import '../../../data/provider/private_key.dart';
import '../../../data/res/ui.dart';
@@ -92,8 +91,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
IconButton(
tooltip: _s.delete,
onPressed: () {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(widget.pki!.id)),
actions: [
@@ -128,7 +126,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
final key = _keyController.text.trim();
final pwd = _pwdController.text;
if (name.isEmpty || key.isEmpty) {
showSnackBar(context, Text(_s.fieldMustNotEmpty));
context.showSnackBar(_s.fieldMustNotEmpty);
return;
}
FocusScope.of(context).unfocus();
@@ -144,7 +142,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
_provider.add(pki);
}
} catch (e) {
showSnackBar(context, Text(e.toString()));
context.showSnackBar(e.toString());
rethrow;
} finally {
setState(() {
@@ -184,25 +182,22 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
onPressed: () async {
final path = await pickOneFile();
if (path == null) {
showSnackBar(context, Text(_s.fieldMustNotEmpty));
context.showSnackBar(_s.fieldMustNotEmpty);
return;
}
final file = File(path);
if (!file.existsSync()) {
showSnackBar(context, Text(_s.fileNotExist(path)));
context.showSnackBar(_s.fileNotExist(path));
return;
}
final size = (await file.stat()).size;
if (size > privateKeyMaxSize) {
showSnackBar(
context,
Text(
_s.fileTooLarge(
path,
size.convertBytes,
privateKeyMaxSize.convertBytes,
),
context.showSnackBar(
_s.fileTooLarge(
path,
size.convertBytes,
privateKeyMaxSize.convertBytes,
),
);
return;

View File

@@ -5,7 +5,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/utils/ui.dart';
import 'package:toolbox/data/store/private_key.dart';
import 'package:toolbox/locator.dart';
@@ -94,8 +93,7 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
id: 'system',
key: idRsaFile.readAsStringSync(),
);
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.addSystemPrivateKeyTip),
actions: [

View File

@@ -7,7 +7,6 @@ import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/extension/uint8list.dart';
import 'package:toolbox/core/utils/misc.dart';
import '../../core/utils/ui.dart';
import '../../data/model/app/shell_func.dart';
import '../../data/model/server/proc.dart';
import '../../data/model/server/server_private_info.dart';
@@ -67,7 +66,7 @@ class _ProcessPageState extends State<ProcessPage> {
if (mounted) {
final result = await _client?.run(AppShellFuncType.process.exec).string;
if (result == null || result.isEmpty) {
showSnackBar(context, Text(_s.noResult));
context.showSnackBar(_s.noResult);
return;
}
_result = PsResult.parse(result, sort: _procSortMode);
@@ -113,8 +112,7 @@ class _ProcessPageState extends State<ProcessPage> {
if (_result.error != null) {
actions.add(IconButton(
icon: const Icon(Icons.error),
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_s.error),
child: SingleChildScrollView(child: Text(_result.error!)),
actions: [
@@ -166,8 +164,7 @@ class _ProcessPageState extends State<ProcessPage> {
trailing: _buildItemTrail(proc),
onTap: () => _lastFocusId = proc.pid,
onLongPress: () {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureStop(proc.pid)),
actions: [

View File

@@ -4,7 +4,6 @@ import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context.dart';
import '../../../core/route.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/server/private_key_info.dart';
import '../../../data/model/server/server_private_info.dart';
import '../../../data/provider/private_key.dart';
@@ -114,8 +113,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
PreferredSizeWidget _buildAppBar() {
final delBtn = IconButton(
onPressed: () {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureToDeleteServer(widget.spi!.name)),
actions: [
@@ -323,12 +321,11 @@ class _ServerEditPageState extends State<ServerEditPage> {
void _onSave() async {
if (_ipController.text == '') {
showSnackBar(context, Text(_s.plzEnterHost));
context.showSnackBar(_s.plzEnterHost);
return;
}
if (_keyIdx.value == null && _passwordController.text == '') {
final cancel = await showRoundDialog<bool>(
context: context,
final cancel = await context.showRoundDialog<bool>(
title: Text(_s.attention),
child: Text(_s.sureNoPwd),
actions: [
@@ -348,7 +345,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
}
// If [_pubKeyIndex] is -1, it means that the user has not selected
if (_keyIdx.value == -1) {
showSnackBar(context, Text(_s.plzSelectKey));
context.showSnackBar(_s.plzSelectKey);
return;
}
if (_usernameController.text.isEmpty) {

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:get_it/get_it.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/extension/media_queryx.dart';
import 'package:toolbox/core/extension/ssh_client.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
@@ -11,7 +12,6 @@ import 'package:toolbox/data/model/app/shell_func.dart';
import '../../../core/route.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/platform.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/app/net_view.dart';
import '../../../data/model/server/disk.dart';
import '../../../data/model/server/server.dart';
@@ -376,8 +376,7 @@ class _ServerPageState extends State<ServerPage>
}
void _showFailReason(ServerStatus ss) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: SingleChildScrollView(
child: Text(ss.failedInfo ?? _s.unknownError),

View File

@@ -16,7 +16,6 @@ import '../../../core/route.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/platform.dart';
import '../../../core/update.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/app/net_view.dart';
import '../../../data/provider/app.dart';
import '../../../data/provider/server.dart';
@@ -32,6 +31,7 @@ import '../../widget/custom_appbar.dart';
import '../../widget/future_widget.dart';
import '../../widget/input_field.dart';
import '../../widget/round_rect_card.dart';
import '../../widget/store_switch.dart';
import '../../widget/value_notifier.dart';
class SettingPage extends StatefulWidget {
@@ -43,7 +43,6 @@ class SettingPage extends StatefulWidget {
class _SettingPageState extends State<SettingPage> {
final _themeKey = GlobalKey<PopupMenuButtonState<int>>();
//final _startPageKey = GlobalKey<PopupMenuButtonState<int>>();
final _updateIntervalKey = GlobalKey<PopupMenuButtonState<int>>();
final _maxRetryKey = GlobalKey<PopupMenuButtonState<int>>();
final _localeKey = GlobalKey<PopupMenuButtonState<String>>();
@@ -59,7 +58,6 @@ class _SettingPageState extends State<SettingPage> {
late SharedPreferences _sp;
final _selectedColorValue = ValueNotifier(0);
final _launchPageIdx = ValueNotifier(0);
final _nightMode = ValueNotifier(0);
final _maxRetryCount = ValueNotifier(0);
final _updateInterval = ValueNotifier(0);
@@ -91,7 +89,6 @@ class _SettingPageState extends State<SettingPage> {
super.initState();
_serverProvider = locator<ServerProvider>();
_setting = locator<SettingStore>();
_launchPageIdx.value = _setting.launchPage.fetch();
_nightMode.value = _setting.themeMode.fetch();
_updateInterval.value = _setting.serverStatusUpdateInterval.fetch();
_maxRetryCount.value = _setting.maxRetryCount.fetch();
@@ -113,8 +110,7 @@ class _SettingPageState extends State<SettingPage> {
title: Text(_s.setting),
actions: [
IconButton(
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(_s.all)),
actions: [
@@ -122,7 +118,7 @@ class _SettingPageState extends State<SettingPage> {
onPressed: () {
_setting.box.deleteAll(_setting.box.keys);
context.pop();
showSnackBar(context, Text(_s.success));
context.showSnackBar(_s.success);
},
child: Text(_s.ok, style: const TextStyle(color: Colors.red)),
),
@@ -203,9 +199,9 @@ class _SettingPageState extends State<SettingPage> {
_buildNetViewType(),
_buildUpdateInterval(),
_buildMaxRetry(),
_buildDiskIgnorePath(),
//_buildDiskIgnorePath(),
_buildDeleteServers(),
if (isDesktop) _buildDoubleColumnServersPage(),
//if (isDesktop) _buildDoubleColumnServersPage(),
].map((e) => RoundRectCard(e)).toList(),
);
}
@@ -251,7 +247,7 @@ class _SettingPageState extends State<SettingPage> {
title: Text(_s.autoCheckUpdate),
subtitle: Text(display, style: grey),
onTap: () => doUpdate(ctx, force: true),
trailing: buildSwitch(context, _setting.autoCheckAppUpdate),
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
);
},
);
@@ -289,7 +285,7 @@ class _SettingPageState extends State<SettingPage> {
_setting.serverStatusUpdateInterval.put(val);
_serverProvider.startAutoRefresh();
if (val == 0) {
showSnackBar(context, Text(_s.updateIntervalEqual0));
context.showSnackBar(_s.updateIntervalEqual0);
}
},
child: Text(
@@ -313,8 +309,7 @@ class _SettingPageState extends State<SettingPage> {
title: Text(_s.primaryColorSeed),
onTap: () async {
final ctrl = TextEditingController(text: primaryColor.toHex);
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.primaryColorSeed),
child: StatefulBuilder(builder: (context, setState) {
final children = <Widget>[
@@ -322,9 +317,8 @@ class _SettingPageState extends State<SettingPage> {
if (!isIOS)
ListTile(
title: Text(_s.followSystem),
trailing: buildSwitch(
context,
_setting.useSystemPrimaryColor,
trailing: StoreSwitch(
prop: _setting.useSystemPrimaryColor,
func: (_) => setState(() {}),
),
)
@@ -361,14 +355,14 @@ class _SettingPageState extends State<SettingPage> {
void _onSaveColor(String s) {
final color = s.hexToColor;
if (color == null) {
showSnackBar(context, Text(_s.failed));
context.showSnackBar(_s.failed);
return;
}
_selectedColorValue.value = color.value;
_setting.primaryColor.put(_selectedColorValue.value);
primaryColor = color;
context.pop();
showRestartSnackbar(context, btn: _s.restart, msg: _s.needRestart);
context.showRestartSnackbar(btn: _s.restart, msg: _s.needRestart);
}
// Widget _buildLaunchPage() {
@@ -515,9 +509,9 @@ class _SettingPageState extends State<SettingPage> {
onPressed: () {
if (_pushToken.value != null) {
copy2Clipboard(_pushToken.value!);
showSnackBar(context, Text(_s.success));
context.showSnackBar(_s.success);
} else {
showSnackBar(context, Text(_s.getPushTokenFailed));
context.showSnackBar(_s.getPushTokenFailed);
}
},
),
@@ -548,8 +542,7 @@ class _SettingPageState extends State<SettingPage> {
style: textSize15,
),
onTap: () {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.font),
actions: [
TextButton(
@@ -560,8 +553,7 @@ class _SettingPageState extends State<SettingPage> {
onPressed: () {
_setting.fontPath.delete();
context.pop();
showRestartSnackbar(
context,
context.showRestartSnackbar(
btn: _s.restart,
msg: _s.needRestart,
);
@@ -588,16 +580,16 @@ class _SettingPageState extends State<SettingPage> {
}
context.pop();
showRestartSnackbar(context, btn: _s.restart, msg: _s.needRestart);
context.showRestartSnackbar(btn: _s.restart, msg: _s.needRestart);
return;
}
showSnackBar(context, Text(_s.failed));
context.showSnackBar(_s.failed);
}
Widget _buildBgRun() {
return ListTile(
title: Text(_s.bgRun),
trailing: buildSwitch(context, _setting.bgRun),
trailing: StoreSwitch(prop: _setting.bgRun),
);
}
@@ -615,42 +607,42 @@ class _SettingPageState extends State<SettingPage> {
);
}
Widget _buildDiskIgnorePath() {
final paths = _setting.diskIgnorePath.fetch();
return ListTile(
title: Text(_s.diskIgnorePath),
trailing: Text(_s.edit, style: textSize15),
onTap: () {
final ctrller = TextEditingController(text: json.encode(paths));
void onSubmit() {
try {
final list = List<String>.from(json.decode(ctrller.text));
_setting.diskIgnorePath.put(list);
context.pop();
showSnackBar(context, Text(_s.success));
} catch (e) {
showSnackBar(context, Text(e.toString()));
}
}
// Widget _buildDiskIgnorePath() {
// final paths = _setting.diskIgnorePath.fetch();
// return ListTile(
// title: Text(_s.diskIgnorePath),
// trailing: Text(_s.edit, style: textSize15),
// onTap: () {
// final ctrller = TextEditingController(text: json.encode(paths));
// void onSubmit() {
// try {
// final list = List<String>.from(json.decode(ctrller.text));
// _setting.diskIgnorePath.put(list);
// context.pop();
// showSnackBar(context, Text(_s.success));
// } catch (e) {
// showSnackBar(context, Text(e.toString()));
// }
// }
showRoundDialog(
context: context,
title: Text(_s.diskIgnorePath),
child: Input(
autoFocus: true,
controller: ctrller,
label: 'JSON',
type: TextInputType.visiblePassword,
maxLines: 3,
onSubmitted: (_) => onSubmit(),
),
actions: [
TextButton(onPressed: onSubmit, child: Text(_s.ok)),
],
);
},
);
}
// showRoundDialog(
// context: context,
// title: Text(_s.diskIgnorePath),
// child: Input(
// autoFocus: true,
// controller: ctrller,
// label: 'JSON',
// type: TextInputType.visiblePassword,
// maxLines: 3,
// onSubmitted: (_) => onSubmit(),
// ),
// actions: [
// TextButton(onPressed: onSubmit, child: Text(_s.ok)),
// ],
// );
// },
// );
// }
Widget _buildLocale() {
final items = S.supportedLocales
@@ -675,7 +667,7 @@ class _SettingPageState extends State<SettingPage> {
onSelected: (String idx) {
_localeCode.value = idx;
_setting.locale.put(idx);
showRestartSnackbar(context, btn: _s.restart, msg: _s.needRestart);
context.showRestartSnackbar(btn: _s.restart, msg: _s.needRestart);
},
child: Text(
_s.languageName,
@@ -690,7 +682,7 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(_s.sshVirtualKeyAutoOff),
subtitle: const Text('Ctrl & Alt', style: grey),
trailing: buildSwitch(context, _setting.sshVirtualKeyAutoOff),
trailing: StoreSwitch(prop: _setting.sshVirtualKeyAutoOff),
);
}
@@ -763,11 +755,9 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildFullScreenSwitch() {
return ListTile(
title: Text(_s.fullScreen),
trailing: buildSwitch(
context,
_setting.fullScreen,
func: (_) => showRestartSnackbar(
context,
trailing: StoreSwitch(
prop: _setting.fullScreen,
func: (_) => context.showRestartSnackbar(
btn: _s.restart,
msg: _s.needRestart,
),
@@ -779,7 +769,7 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(_s.fullScreenJitter),
subtitle: Text(_s.fullScreenJitterHelp, style: grey),
trailing: buildSwitch(context, _setting.fullScreenJitter),
trailing: StoreSwitch(prop: _setting.fullScreenJitter),
);
}
@@ -886,9 +876,9 @@ class _SettingPageState extends State<SettingPage> {
map.forEach((key, value) {
_sp.setString(key, value);
});
showSnackBar(context, Text(_s.success));
context.showSnackBar(_s.success);
} catch (e) {
showSnackBar(context, Text(e.toString()));
context.showSnackBar(e.toString());
}
}
@@ -905,8 +895,7 @@ class _SettingPageState extends State<SettingPage> {
}
});
final ctrl = TextEditingController(text: json.encode(data));
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.homeWidgetUrlConfig),
child: Input(
autoFocus: true,
@@ -964,7 +953,7 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(_s.autoUpdateHomeWidget),
subtitle: Text(_s.whenOpenApp, style: grey),
trailing: buildSwitch(context, _setting.autoUpdateHomeWidget),
trailing: StoreSwitch(prop: _setting.autoUpdateHomeWidget),
);
}
@@ -975,8 +964,7 @@ class _SettingPageState extends State<SettingPage> {
onTap: () async {
final all = locator<ServerStore>().box.keys.map(
(e) => TextButton(
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(e)),
actions: [
@@ -989,8 +977,7 @@ class _SettingPageState extends State<SettingPage> {
child: Text(e),
),
);
showRoundDialog<List<String>>(
context: context,
context.showRoundDialog<List<String>>(
title: Text(_s.choose),
child: SingleChildScrollView(
child: Column(
@@ -1007,7 +994,7 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(_s.moveOutServerFuncBtns),
subtitle: Text(_s.moveOutServerFuncBtnsHelp, style: textSize13Grey),
trailing: buildSwitch(context, _setting.moveOutServerTabFuncBtns),
trailing: StoreSwitch(prop: _setting.moveOutServerTabFuncBtns),
);
}
@@ -1051,8 +1038,7 @@ class _SettingPageState extends State<SettingPage> {
context.pop();
final fontSize = double.tryParse(ctrller.text);
if (fontSize == null) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.failed),
child: Text('Parsed failed: ${ctrller.text}'),
);
@@ -1062,8 +1048,7 @@ class _SettingPageState extends State<SettingPage> {
property.put(fontSize);
}
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.fontSize),
child: Input(
controller: ctrller,
@@ -1085,14 +1070,14 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(_s.sftpRmrfDir),
subtitle: Text(_s.sftpRmrfDirSummary, style: grey),
trailing: buildSwitch(context, _setting.sftpRmrfDir),
trailing: StoreSwitch(prop: _setting.sftpRmrfDir),
);
}
Widget _buildDoubleColumnServersPage() {
return ListTile(
title: Text(_s.doubleColumnMode),
trailing: buildSwitch(context, _setting.doubleColumnServersPage),
);
}
// Widget _buildDoubleColumnServersPage() {
// return ListTile(
// title: Text(_s.doubleColumnMode),
// trailing: StoreSwitch(prop: _setting.doubleColumnServersPage),
// );
// }
}

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/core/utils/ui.dart';
import 'package:toolbox/data/model/ssh/virtual_key.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/data/store/setting.dart';
@@ -64,7 +64,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
itemCount: allKeys.length,
onReorder: (o, n) {
if (o >= keys.length || n >= keys.length) {
showSnackBar(context, Text(_s.disabled));
context.showSnackBar(_s.disabled);
return;
}
keys.moveByItem(keys, o, n, property: _setting.sshVirtKeys);

View File

@@ -4,7 +4,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/view/widget/input_field.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/server/snippet.dart';
import '../../../data/provider/snippet.dart';
import '../../../data/res/ui.dart';
@@ -89,7 +88,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
final name = _nameController.text;
final script = _scriptController.text;
if (name.isEmpty || script.isEmpty) {
showSnackBar(context, Text(_s.fieldMustNotEmpty));
context.showSnackBar(_s.fieldMustNotEmpty);
return;
}
final note = _noteController.text;

View File

@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/context.dart';
import 'package:toolbox/core/extension/order.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/server/server.dart';
import '../../../data/model/server/snippet.dart';
import '../../../data/provider/server.dart';
@@ -151,8 +151,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
ids,
results,
).entries.map((e) => '${e.key}:\n${e.value}').join('\n');
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.result),
child: Text(result),
actions: [

View File

@@ -13,7 +13,6 @@ import 'package:xterm/xterm.dart';
import '../../core/route.dart';
import '../../core/utils/platform.dart';
import '../../core/utils/misc.dart';
import '../../core/utils/ui.dart';
import '../../core/utils/server.dart';
import '../../data/model/server/server_private_info.dart';
import '../../data/model/ssh/virtual_key.dart';
@@ -251,7 +250,7 @@ class _SSHPageState extends State<SSHPage> {
}
break;
case VirtualKeyFunc.snippet:
showSnippetDialog(context, _s, (s) {
context.showSnippetDialog(_s, (s) {
_terminal.textInput(s.script);
_terminal.keyInput(TerminalKey.enter);
});
@@ -267,8 +266,7 @@ class _SSHPageState extends State<SSHPage> {
final idx = cmds.lastIndexWhere((e) => e.toString().contains(echoPWD));
final initPath = cmds[idx + 1].toString();
if (initPath.isEmpty || !initPath.startsWith('/')) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: const Text('Failed to get current path'),
);
@@ -342,7 +340,7 @@ class _SSHPageState extends State<SSHPage> {
_setupDiscontinuityTimer();
if (_session == null) {
showSnackBar(context, const Text('Null session'));
context.showSnackBar('Null session');
return;
}
@@ -400,8 +398,7 @@ class _SSHPageState extends State<SSHPage> {
_discontinuityTimer?.cancel();
if (!mounted) return;
_write('\n\nConnection lost\r\n');
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text('${_s.disconnected}\n${_s.goBackQ}'),
barrierDismiss: false,

View File

@@ -16,7 +16,6 @@ import '../../../core/extension/numx.dart';
import '../../../core/extension/stringx.dart';
import '../../../core/route.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/app/path_with_prefix.dart';
import '../../../data/res/path.dart';
import '../../../data/res/ui.dart';
@@ -191,8 +190,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
}
Future<void> _showDirActionDialog(FileSystemEntity file) async {
showRoundDialog(
context: context,
context.showRoundDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -220,8 +218,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
Future<void> _showFileActionDialog(FileSystemEntity file) async {
final fileName = file.path.split('/').last;
if (widget.isPickFile) {
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.pickFile),
child: Text(fileName),
actions: [
@@ -235,8 +232,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
]);
return;
}
showRoundDialog(
context: context,
context.showRoundDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -247,8 +243,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
context.pop();
final stat = await file.stat();
if (stat.size > editorMaxSize) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.fileTooLarge(fileName, stat.size, '1m')),
);
@@ -260,7 +255,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
final f = File(file.absolute.path);
if (result != null) {
f.writeAsString(result);
showSnackBar(context, Text(_s.saved));
context.showSnackBar(_s.saved);
setState(() {});
}
},
@@ -289,8 +284,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
final serverProvider = locator<ServerProvider>();
final ids = serverProvider.serverOrder;
var idx = 0;
await showRoundDialog(
context: context,
await context.showRoundDialog(
title: Text(_s.server),
child: Picker(
items: ids.map((e) => Text(e)).toList(),
@@ -319,7 +313,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
file.absolute.path,
SftpReqType.upload,
));
showSnackBar(context, Text(_s.added2List));
context.showSnackBar(_s.added2List);
},
),
ListTile(
@@ -336,8 +330,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
void _showRenameDialog(FileSystemEntity file) {
final fileName = file.path.split('/').last;
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.rename),
child: Input(
autoFocus: true,
@@ -348,7 +341,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
try {
file.renameSync(newPath);
} catch (e) {
showSnackBar(context, Text('${_s.failed}:\n$e'));
context.showSnackBar('${_s.failed}:\n$e');
return;
}
@@ -360,8 +353,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
void _showDeleteDialog(FileSystemEntity file) {
final fileName = file.path.split('/').last;
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.delete),
child: Text(_s.sureDelete(fileName)),
actions: [
@@ -375,7 +367,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
try {
file.deleteSync(recursive: true);
} catch (e) {
showSnackBar(context, Text('${_s.failed}:\n$e'));
context.showSnackBar('${_s.failed}:\n$e');
return;
}
setState(() {});

View File

@@ -16,7 +16,6 @@ import '../../../core/extension/stringx.dart';
import '../../../core/route.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/platform.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/server/server_private_info.dart';
import '../../../data/model/sftp/absolute_path.dart';
import '../../../data/model/sftp/browser_status.dart';
@@ -153,23 +152,22 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
Widget _buildUploadBtn() {
return IconButton(
onPressed: () async {
final idx = await showRoundDialog(
context: context,
final idx = await context.showRoundDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.open_in_new),
title: Text(_s.system),
onTap: () => context.pop(1),
),
ListTile(
leading: const Icon(Icons.folder),
title: Text(_s.inner),
onTap: () => context.pop(0),
),
],
));
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.open_in_new),
title: Text(_s.system),
onTap: () => context.pop(1),
),
ListTile(
leading: const Icon(Icons.folder),
title: Text(_s.inner),
onTap: () => context.pop(0),
),
],
));
final path = await () async {
switch (idx) {
case 0:
@@ -186,7 +184,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
}
final remotePath = _status.path?.path;
if (remotePath == null) {
showSnackBar(context, const Text('remote path is null'));
context.showSnackBar('remote path is null');
return;
}
_sftp.add(
@@ -203,8 +201,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
Widget _buildAddBtn() {
return IconButton(
onPressed: (() => showRoundDialog(
context: context,
onPressed: (() => context.showRoundDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -227,8 +224,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
return IconButton(
padding: const EdgeInsets.all(0),
onPressed: () async {
final p = await showRoundDialog<String>(
context: context,
final p = await context.showRoundDialog<String>(
title: Text(_s.goto),
child: Autocomplete<String>(
optionsBuilder: (val) {
@@ -358,8 +354,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
),
]);
}
showRoundDialog(
context: context,
context.showRoundDialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: children,
@@ -370,13 +365,11 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
Future<void> _edit(BuildContext context, SftpName name) async {
final size = name.attr.size;
if (size == null || size > editorMaxSize) {
showSnackBar(
context,
Text(_s.fileTooLarge(
name.filename,
size ?? 0,
editorMaxSize,
)));
context.showSnackBar(_s.fileTooLarge(
name.filename,
size ?? 0,
editorMaxSize,
));
return;
}
context.pop();
@@ -391,20 +384,19 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
SftpReqType.download,
);
_sftp.add(req, completer: completer);
showLoadingDialog(context);
context.showLoadingDialog();
await completer.future;
context.pop();
final result = await AppRoute.editor(path: localPath).go<bool>(context);
if (result != null && result) {
_sftp.add(SftpReq(req.spi, remotePath, localPath, SftpReqType.upload));
showSnackBar(context, Text(_s.added2List));
context.showSnackBar(_s.added2List);
}
}
void _download(BuildContext context, SftpName name) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
actions: [
@@ -441,8 +433,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
final dirText = (isDir && !useRmrf) ? '\n${_s.sureDirEmpty}' : '';
final text = '${_s.sureDelete(file.filename)}$dirText';
final child = Text(text);
showRoundDialog(
context: context,
context.showRoundDialog(
child: child,
title: Text(_s.attention),
actions: [
@@ -453,7 +444,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
TextButton(
onPressed: () async {
context.pop();
showLoadingDialog(context);
context.showLoadingDialog();
final remotePath = _getRemotePath(file);
try {
if (useRmrf) {
@@ -466,8 +457,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
context.pop();
} catch (e) {
context.pop();
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: Text(e.toString()),
actions: [
@@ -490,8 +480,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _mkdir(BuildContext context) {
context.pop();
final textController = TextEditingController();
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.createFolder),
child: Input(
autoFocus: true,
@@ -507,8 +496,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
TextButton(
onPressed: () async {
if (textController.text == '') {
showRoundDialog(
context: context,
context.showRoundDialog(
child: Text(_s.fieldMustNotEmpty),
actions: [
TextButton(
@@ -533,8 +521,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _newFile(BuildContext context) {
context.pop();
final textController = TextEditingController();
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.createFile),
child: Input(
autoFocus: true,
@@ -546,8 +533,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
TextButton(
onPressed: () async {
if (textController.text == '') {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.fieldMustNotEmpty),
actions: [
@@ -561,7 +547,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
}
context.pop();
final path = '${_status.path!.path}/${textController.text}';
showLoadingDialog(context);
context.showLoadingDialog();
await _client!.run('touch "$path"');
context.pop();
_listDir();
@@ -575,8 +561,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _rename(BuildContext context, SftpName file) {
context.pop();
final textController = TextEditingController();
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.rename),
child: Input(
autoFocus: true,
@@ -589,8 +574,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
TextButton(
onPressed: () async {
if (textController.text == '') {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.fieldMustNotEmpty),
actions: [
@@ -617,8 +601,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
final absPath = _getRemotePath(name);
final cmd = _getDecompressCmd(absPath);
if (cmd == null) {
showRoundDialog(
context: context,
context.showRoundDialog(
title: Text(_s.error),
child: Text('Unsupport file: ${name.filename}'),
actions: [
@@ -630,7 +613,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
);
return;
}
showLoadingDialog(context);
context.showLoadingDialog();
await _client?.run(cmd);
context.pop();
_listDir();
@@ -647,7 +630,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
/// Only return true if the path is changed
Future<bool> _listDir({String? path, SSHClient? client}) async {
showLoadingDialog(context);
context.showLoadingDialog();
if (client != null) {
final sftpc = await client.sftp();
_status.client = sftpc;
@@ -681,12 +664,11 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
return false;
} catch (e, trace) {
context.pop();
_logger.warning('list dir failed', e, trace);
_logger.warning('List dir failed', e, trace);
await _backward();
Future.delayed(
const Duration(milliseconds: 177),
() => showRoundDialog(
context: context,
() => context.showRoundDialog(
title: Text(_s.error),
child: Text(e.toString()),
actions: [

View File

@@ -8,7 +8,6 @@ import 'package:toolbox/locator.dart';
import '../../../core/extension/numx.dart';
import '../../../core/utils/misc.dart';
import '../../../core/utils/ui.dart';
import '../../../data/model/sftp/req.dart';
import '../../../data/provider/sftp.dart';
import '../../../data/res/ui.dart';
@@ -111,8 +110,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
status: status,
subtitle: _s.unknown,
trailing: IconButton(
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_s.error),
child: Text((status.error ?? _s.unknown).toString()),
),
@@ -149,8 +147,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
Widget _buildDelete(String name, int id) {
return IconButton(
onPressed: () => showRoundDialog(
context: context,
onPressed: () => context.showRoundDialog(
title: Text(_s.attention),
child: Text(_s.sureDelete(name)),
actions: [