diff --git a/lib/core/utils/sync/icloud.dart b/lib/core/utils/sync/icloud.dart index 2f67d6508..8928c1614 100644 --- a/lib/core/utils/sync/icloud.dart +++ b/lib/core/utils/sync/icloud.dart @@ -28,20 +28,26 @@ abstract final class ICloud { String? localPath, }) async { final completer = Completer(); - await ICloudStorage.upload( - containerId: _containerId, - filePath: localPath ?? '${await Paths.doc}/$relativePath', - destinationRelativePath: relativePath, - onProgress: (stream) { - stream.listen( - null, - onDone: () => completer.complete(null), - onError: (e) => completer.complete( - ICloudErr(type: ICloudErrType.generic, message: '$e'), - ), - ); - }, - ); + try { + await ICloudStorage.upload( + containerId: _containerId, + filePath: localPath ?? '${await Paths.doc}/$relativePath', + destinationRelativePath: relativePath, + onProgress: (stream) { + stream.listen( + null, + onDone: () => completer.complete(null), + onError: (e) => completer.complete( + ICloudErr(type: ICloudErrType.generic, message: '$e'), + ), + ); + }, + ); + } catch (e, s) { + _logger.warning('Upload $relativePath failed', e, s); + completer.complete(ICloudErr(type: ICloudErrType.generic, message: '$e')); + } + return completer.future; } @@ -52,10 +58,14 @@ abstract final class ICloud { } static Future delete(String relativePath) async { - await ICloudStorage.delete( - containerId: _containerId, - relativePath: relativePath, - ); + try { + await ICloudStorage.delete( + containerId: _containerId, + relativePath: relativePath, + ); + } catch (e, s) { + _logger.warning('Delete $relativePath failed', e, s); + } } /// Download file from iCloud diff --git a/lib/data/res/github_id.dart b/lib/data/res/github_id.dart index d9cd48138..574f08537 100644 --- a/lib/data/res/github_id.dart +++ b/lib/data/res/github_id.dart @@ -4,6 +4,7 @@ abstract final class GithubIds { // Thanks // If you want to change your Github ID, please open an issue. static const contributors = { + 'PaperCube', 'its-tom', 'azkadev', 'kalashnikov', @@ -57,5 +58,6 @@ abstract final class GithubIds { 'bxoooooo', 'KatharsisKing', 'mervinniu', + 'L-Super', }; } diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 680e053cb..0691c1c62 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -100,7 +100,7 @@ class SettingStore extends PersistentStore { late final termFontSize = property('termFontSize', 13.0); // Locale - late final locale = property('locale', ''); + late final locale = property('locale', ''); // SSH virtual key (ctrl | alt) auto turn off late final sshVirtualKeyAutoOff = property('sshVirtualKeyAutoOff', true); diff --git a/lib/view/page/private_key/edit.dart b/lib/view/page/private_key/edit.dart index 8ba6ada5e..9ba9edc5c 100644 --- a/lib/view/page/private_key/edit.dart +++ b/lib/view/page/private_key/edit.dart @@ -39,7 +39,7 @@ class _PrivateKeyEditPageState extends State { late FocusScopeNode _focusScope; - Widget? _loading; + final _loading = ValueNotifier(null); @override void initState() { @@ -134,9 +134,7 @@ class _PrivateKeyEditPageState extends State { return; } FocusScope.of(context).unfocus(); - setState(() { - _loading = UIs.centerSizedLoading; - }); + _loading.value = UIs.centerSizedLoading; try { final decrypted = await Computer.shared.start(decyptPem, [key, pwd]); final pki = PrivateKeyInfo(id: name, key: decrypted); @@ -149,9 +147,7 @@ class _PrivateKeyEditPageState extends State { context.showSnackBar(e.toString()); rethrow; } finally { - setState(() { - _loading = null; - }); + _loading.value = null; } context.pop(); }, @@ -219,7 +215,10 @@ class _PrivateKeyEditPageState extends State { icon: Icons.password, ), SizedBox(height: MediaQuery.of(context).size.height * 0.1), - _loading ?? UIs.placeholder, + ValueListenableBuilder( + valueListenable: _loading, + builder: (_, val, __) => val ?? UIs.placeholder, + ), ], ); } diff --git a/lib/view/page/setting/entry.dart b/lib/view/page/setting/entry.dart index 824c75e47..7405bcc7f 100644 --- a/lib/view/page/setting/entry.dart +++ b/lib/view/page/setting/entry.dart @@ -227,7 +227,7 @@ class _SettingPageState extends State { _buildSSHVirtualKeyAutoOff(), // Use hardware keyboard on desktop, so there is no need to set it if (isMobile) _buildKeyboardType(), - _buildSSHVirtKeys(), + if (isMobile) _buildSSHVirtKeys(), ].map((e) => CardX(child: e)).toList(), ); } diff --git a/lib/view/page/setting/seq/srv_detail_seq.dart b/lib/view/page/setting/seq/srv_detail_seq.dart index 5601ce6a3..b78a8356c 100644 --- a/lib/view/page/setting/seq/srv_detail_seq.dart +++ b/lib/view/page/setting/seq/srv_detail_seq.dart @@ -17,6 +17,8 @@ class ServerDetailOrderPage extends StatefulWidget { } class _ServerDetailOrderPageState extends State { + final prop = Stores.setting.detailCardOrder; + @override Widget build(BuildContext context) { return Scaffold( @@ -28,36 +30,36 @@ class _ServerDetailOrderPageState extends State { } Widget _buildBody() { - final keys_ = Stores.setting.detailCardOrder.fetch(); - final keys = []; - for (final key in keys_) { - keys.add(key); - } - final disabled = - Defaults.detailCardOrder.where((e) => !keys.contains(e)).toList(); - final allKeys = [...keys, ...disabled]; - return ReorderableListView.builder( - padding: const EdgeInsets.all(7), - itemBuilder: (_, idx) { - final key = allKeys[idx]; - return CardX( - key: ValueKey(idx), - child: ListTile( - title: Text(key), - leading: _buildCheckBox(keys, key, idx, idx < keys.length), - trailing: isDesktop ? null : const Icon(Icons.drag_handle), - ), + return ValueListenableBuilder( + valueListenable: prop.listenable(), + builder: (_, vals, __) { + final keys = List.from(vals); + final disabled = + Defaults.detailCardOrder.where((e) => !keys.contains(e)).toList(); + final allKeys = [...keys, ...disabled]; + return ReorderableListView.builder( + padding: const EdgeInsets.all(7), + itemBuilder: (_, idx) { + final key = allKeys[idx]; + return CardX( + key: ValueKey(idx), + child: ListTile( + title: Text(key), + leading: _buildCheckBox(keys, key, idx, idx < keys.length), + trailing: isDesktop ? null : const Icon(Icons.drag_handle), + ), + ); + }, + itemCount: allKeys.length, + onReorder: (o, n) { + if (o >= keys.length || n >= keys.length) { + context.showSnackBar(l10n.disabled); + return; + } + keys.moveByItem(keys, o, n, property: prop); + }, ); }, - itemCount: allKeys.length, - onReorder: (o, n) { - if (o >= keys.length || n >= keys.length) { - context.showSnackBar(l10n.disabled); - return; - } - keys.moveByItem(keys, o, n, property: Stores.setting.detailCardOrder); - setState(() {}); - }, ); } @@ -75,8 +77,7 @@ class _ServerDetailOrderPageState extends State { } else { keys.remove(key); } - Stores.setting.detailCardOrder.put(keys); - setState(() {}); + prop.put(keys); }, ); } diff --git a/lib/view/page/setting/seq/srv_func_seq.dart b/lib/view/page/setting/seq/srv_func_seq.dart index 6d502b0ad..3c275a5b8 100644 --- a/lib/view/page/setting/seq/srv_func_seq.dart +++ b/lib/view/page/setting/seq/srv_func_seq.dart @@ -17,6 +17,8 @@ class ServerFuncBtnsOrderPage extends StatefulWidget { } class _ServerDetailOrderPageState extends State { + final prop = Stores.setting.serverFuncBtns; + @override Widget build(BuildContext context) { return Scaffold( @@ -28,38 +30,38 @@ class _ServerDetailOrderPageState extends State { } Widget _buildBody() { - final keys_ = Stores.setting.serverFuncBtns.fetch(); - final keys = []; - for (final key in keys_) { - keys.add(key); - } - final disabled = ServerFuncBtn.values - .map((e) => e.index) - .where((e) => !keys.contains(e)) - .toList(); - final allKeys = [...keys, ...disabled]; - return ReorderableListView.builder( - padding: const EdgeInsets.all(7), - itemBuilder: (_, idx) { - final key = allKeys[idx]; - return CardX( - key: ValueKey(idx), - child: ListTile( - title: Text(ServerFuncBtn.values[key].toStr), - leading: _buildCheckBox(keys, key, idx, idx < keys.length), - trailing: isDesktop ? null : const Icon(Icons.drag_handle), - ), + return ValueListenableBuilder( + valueListenable: prop.listenable(), + builder: (_, vals, __) { + final keys = List.from(vals); + final disabled = ServerFuncBtn.values + .map((e) => e.index) + .where((e) => !keys.contains(e)) + .toList(); + final allKeys = [...keys, ...disabled]; + return ReorderableListView.builder( + padding: const EdgeInsets.all(7), + itemBuilder: (_, idx) { + final key = allKeys[idx]; + return CardX( + key: ValueKey(idx), + child: ListTile( + title: Text(ServerFuncBtn.values[key].toStr), + leading: _buildCheckBox(keys, key, idx, idx < keys.length), + trailing: isDesktop ? null : const Icon(Icons.drag_handle), + ), + ); + }, + itemCount: allKeys.length, + onReorder: (o, n) { + if (o >= keys.length || n >= keys.length) { + context.showSnackBar(l10n.disabled); + return; + } + keys.moveByItem(keys, o, n, property: prop); + }, ); }, - itemCount: allKeys.length, - onReorder: (o, n) { - if (o >= keys.length || n >= keys.length) { - context.showSnackBar(l10n.disabled); - return; - } - keys.moveByItem(keys, o, n, property: Stores.setting.serverFuncBtns); - setState(() {}); - }, ); } @@ -82,8 +84,7 @@ class _ServerDetailOrderPageState extends State { } else { keys.remove(key); } - Stores.setting.serverFuncBtns.put(keys); - setState(() {}); + prop.put(keys); }, ); } diff --git a/lib/view/page/setting/seq/virt_key.dart b/lib/view/page/setting/seq/virt_key.dart index 894b8ae84..4b64ce7af 100644 --- a/lib/view/page/setting/seq/virt_key.dart +++ b/lib/view/page/setting/seq/virt_key.dart @@ -18,6 +18,8 @@ class SSHVirtKeySettingPage extends StatefulWidget { } class _SSHVirtKeySettingPageState extends State { + final prop = Stores.setting.sshVirtKeys; + @override Widget build(BuildContext context) { return Scaffold( @@ -29,41 +31,41 @@ class _SSHVirtKeySettingPageState extends State { } Widget _buildBody() { - final keys_ = Stores.setting.sshVirtKeys.fetch(); - final keys = []; - for (final key in keys_) { - keys.add(key); - } - final disabled = VirtKey.values - .map((e) => e.index) - .where((e) => !keys.contains(e)) - .toList(); - final allKeys = [...keys, ...disabled]; - return ReorderableListView.builder( - padding: const EdgeInsets.all(7), - itemBuilder: (_, idx) { - final key = allKeys[idx]; - final item = VirtKey.values[key]; - final help = item.help; - return CardX( - key: ValueKey(idx), - child: ListTile( - title: _buildTitle(item), - subtitle: help == null ? null : Text(help, style: UIs.textGrey), - leading: _buildCheckBox(keys, key, idx, idx < keys.length), - trailing: isDesktop ? null : const Icon(Icons.drag_handle), - ), + return ValueListenableBuilder( + valueListenable: prop.listenable(), + builder: (_, vals, __) { + final keys = List.from(vals); + final disabled = VirtKey.values + .map((e) => e.index) + .where((e) => !keys.contains(e)) + .toList(); + final allKeys = [...keys, ...disabled]; + return ReorderableListView.builder( + padding: const EdgeInsets.all(7), + itemBuilder: (_, idx) { + final key = allKeys[idx]; + final item = VirtKey.values[key]; + final help = item.help; + return CardX( + key: ValueKey(idx), + child: ListTile( + title: _buildTitle(item), + subtitle: help == null ? null : Text(help, style: UIs.textGrey), + leading: _buildCheckBox(keys, key, idx, idx < keys.length), + trailing: isDesktop ? null : const Icon(Icons.drag_handle), + ), + ); + }, + itemCount: allKeys.length, + onReorder: (o, n) { + if (o >= keys.length || n >= keys.length) { + context.showSnackBar(l10n.disabled); + return; + } + keys.moveByItem(keys, o, n, property: prop); + }, ); }, - itemCount: allKeys.length, - onReorder: (o, n) { - if (o >= keys.length || n >= keys.length) { - context.showSnackBar(l10n.disabled); - return; - } - keys.moveByItem(keys, o, n, property: Stores.setting.sshVirtKeys); - setState(() {}); - }, ); } @@ -93,8 +95,7 @@ class _SSHVirtKeySettingPageState extends State { } else { keys.remove(key); } - Stores.setting.sshVirtKeys.put(keys); - setState(() {}); + prop.put(keys); }, ); }