mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: seq settings (#273)
This commit is contained in:
@@ -28,20 +28,26 @@ abstract final class ICloud {
|
|||||||
String? localPath,
|
String? localPath,
|
||||||
}) async {
|
}) async {
|
||||||
final completer = Completer<ICloudErr?>();
|
final completer = Completer<ICloudErr?>();
|
||||||
await ICloudStorage.upload(
|
try {
|
||||||
containerId: _containerId,
|
await ICloudStorage.upload(
|
||||||
filePath: localPath ?? '${await Paths.doc}/$relativePath',
|
containerId: _containerId,
|
||||||
destinationRelativePath: relativePath,
|
filePath: localPath ?? '${await Paths.doc}/$relativePath',
|
||||||
onProgress: (stream) {
|
destinationRelativePath: relativePath,
|
||||||
stream.listen(
|
onProgress: (stream) {
|
||||||
null,
|
stream.listen(
|
||||||
onDone: () => completer.complete(null),
|
null,
|
||||||
onError: (e) => completer.complete(
|
onDone: () => completer.complete(null),
|
||||||
ICloudErr(type: ICloudErrType.generic, message: '$e'),
|
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;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +58,14 @@ abstract final class ICloud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> delete(String relativePath) async {
|
static Future<void> delete(String relativePath) async {
|
||||||
await ICloudStorage.delete(
|
try {
|
||||||
containerId: _containerId,
|
await ICloudStorage.delete(
|
||||||
relativePath: relativePath,
|
containerId: _containerId,
|
||||||
);
|
relativePath: relativePath,
|
||||||
|
);
|
||||||
|
} catch (e, s) {
|
||||||
|
_logger.warning('Delete $relativePath failed', e, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download file from iCloud
|
/// Download file from iCloud
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ abstract final class GithubIds {
|
|||||||
// Thanks
|
// Thanks
|
||||||
// If you want to change your Github ID, please open an issue.
|
// If you want to change your Github ID, please open an issue.
|
||||||
static const contributors = <GhId>{
|
static const contributors = <GhId>{
|
||||||
|
'PaperCube',
|
||||||
'its-tom',
|
'its-tom',
|
||||||
'azkadev',
|
'azkadev',
|
||||||
'kalashnikov',
|
'kalashnikov',
|
||||||
@@ -57,5 +58,6 @@ abstract final class GithubIds {
|
|||||||
'bxoooooo',
|
'bxoooooo',
|
||||||
'KatharsisKing',
|
'KatharsisKing',
|
||||||
'mervinniu',
|
'mervinniu',
|
||||||
|
'L-Super',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class SettingStore extends PersistentStore {
|
|||||||
late final termFontSize = property('termFontSize', 13.0);
|
late final termFontSize = property('termFontSize', 13.0);
|
||||||
|
|
||||||
// Locale
|
// Locale
|
||||||
late final locale = property<String>('locale', '');
|
late final locale = property('locale', '');
|
||||||
|
|
||||||
// SSH virtual key (ctrl | alt) auto turn off
|
// SSH virtual key (ctrl | alt) auto turn off
|
||||||
late final sshVirtualKeyAutoOff = property('sshVirtualKeyAutoOff', true);
|
late final sshVirtualKeyAutoOff = property('sshVirtualKeyAutoOff', true);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
|
|
||||||
late FocusScopeNode _focusScope;
|
late FocusScopeNode _focusScope;
|
||||||
|
|
||||||
Widget? _loading;
|
final _loading = ValueNotifier<Widget?>(null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -134,9 +134,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
setState(() {
|
_loading.value = UIs.centerSizedLoading;
|
||||||
_loading = UIs.centerSizedLoading;
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
|
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
|
||||||
final pki = PrivateKeyInfo(id: name, key: decrypted);
|
final pki = PrivateKeyInfo(id: name, key: decrypted);
|
||||||
@@ -149,9 +147,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
context.showSnackBar(e.toString());
|
context.showSnackBar(e.toString());
|
||||||
rethrow;
|
rethrow;
|
||||||
} finally {
|
} finally {
|
||||||
setState(() {
|
_loading.value = null;
|
||||||
_loading = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
@@ -219,7 +215,10 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
icon: Icons.password,
|
icon: Icons.password,
|
||||||
),
|
),
|
||||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||||
_loading ?? UIs.placeholder,
|
ValueListenableBuilder(
|
||||||
|
valueListenable: _loading,
|
||||||
|
builder: (_, val, __) => val ?? UIs.placeholder,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_buildSSHVirtualKeyAutoOff(),
|
_buildSSHVirtualKeyAutoOff(),
|
||||||
// Use hardware keyboard on desktop, so there is no need to set it
|
// Use hardware keyboard on desktop, so there is no need to set it
|
||||||
if (isMobile) _buildKeyboardType(),
|
if (isMobile) _buildKeyboardType(),
|
||||||
_buildSSHVirtKeys(),
|
if (isMobile) _buildSSHVirtKeys(),
|
||||||
].map((e) => CardX(child: e)).toList(),
|
].map((e) => CardX(child: e)).toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class ServerDetailOrderPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
||||||
|
final prop = Stores.setting.detailCardOrder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -28,36 +30,36 @@ class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody() {
|
Widget _buildBody() {
|
||||||
final keys_ = Stores.setting.detailCardOrder.fetch();
|
return ValueListenableBuilder(
|
||||||
final keys = <String>[];
|
valueListenable: prop.listenable(),
|
||||||
for (final key in keys_) {
|
builder: (_, vals, __) {
|
||||||
keys.add(key);
|
final keys = List<String>.from(vals);
|
||||||
}
|
final disabled =
|
||||||
final disabled =
|
Defaults.detailCardOrder.where((e) => !keys.contains(e)).toList();
|
||||||
Defaults.detailCardOrder.where((e) => !keys.contains(e)).toList();
|
final allKeys = [...keys, ...disabled];
|
||||||
final allKeys = [...keys, ...disabled];
|
return ReorderableListView.builder(
|
||||||
return ReorderableListView.builder(
|
padding: const EdgeInsets.all(7),
|
||||||
padding: const EdgeInsets.all(7),
|
itemBuilder: (_, idx) {
|
||||||
itemBuilder: (_, idx) {
|
final key = allKeys[idx];
|
||||||
final key = allKeys[idx];
|
return CardX(
|
||||||
return CardX(
|
key: ValueKey(idx),
|
||||||
key: ValueKey(idx),
|
child: ListTile(
|
||||||
child: ListTile(
|
title: Text(key),
|
||||||
title: Text(key),
|
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
||||||
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
trailing: isDesktop ? null : const Icon(Icons.drag_handle),
|
||||||
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<ServerDetailOrderPage> {
|
|||||||
} else {
|
} else {
|
||||||
keys.remove(key);
|
keys.remove(key);
|
||||||
}
|
}
|
||||||
Stores.setting.detailCardOrder.put(keys);
|
prop.put(keys);
|
||||||
setState(() {});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class ServerFuncBtnsOrderPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ServerDetailOrderPageState extends State<ServerFuncBtnsOrderPage> {
|
class _ServerDetailOrderPageState extends State<ServerFuncBtnsOrderPage> {
|
||||||
|
final prop = Stores.setting.serverFuncBtns;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -28,38 +30,38 @@ class _ServerDetailOrderPageState extends State<ServerFuncBtnsOrderPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody() {
|
Widget _buildBody() {
|
||||||
final keys_ = Stores.setting.serverFuncBtns.fetch();
|
return ValueListenableBuilder(
|
||||||
final keys = <int>[];
|
valueListenable: prop.listenable(),
|
||||||
for (final key in keys_) {
|
builder: (_, vals, __) {
|
||||||
keys.add(key);
|
final keys = List<int>.from(vals);
|
||||||
}
|
final disabled = ServerFuncBtn.values
|
||||||
final disabled = ServerFuncBtn.values
|
.map((e) => e.index)
|
||||||
.map((e) => e.index)
|
.where((e) => !keys.contains(e))
|
||||||
.where((e) => !keys.contains(e))
|
.toList();
|
||||||
.toList();
|
final allKeys = [...keys, ...disabled];
|
||||||
final allKeys = [...keys, ...disabled];
|
return ReorderableListView.builder(
|
||||||
return ReorderableListView.builder(
|
padding: const EdgeInsets.all(7),
|
||||||
padding: const EdgeInsets.all(7),
|
itemBuilder: (_, idx) {
|
||||||
itemBuilder: (_, idx) {
|
final key = allKeys[idx];
|
||||||
final key = allKeys[idx];
|
return CardX(
|
||||||
return CardX(
|
key: ValueKey(idx),
|
||||||
key: ValueKey(idx),
|
child: ListTile(
|
||||||
child: ListTile(
|
title: Text(ServerFuncBtn.values[key].toStr),
|
||||||
title: Text(ServerFuncBtn.values[key].toStr),
|
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
||||||
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
trailing: isDesktop ? null : const Icon(Icons.drag_handle),
|
||||||
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<ServerFuncBtnsOrderPage> {
|
|||||||
} else {
|
} else {
|
||||||
keys.remove(key);
|
keys.remove(key);
|
||||||
}
|
}
|
||||||
Stores.setting.serverFuncBtns.put(keys);
|
prop.put(keys);
|
||||||
setState(() {});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class SSHVirtKeySettingPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
||||||
|
final prop = Stores.setting.sshVirtKeys;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -29,41 +31,41 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody() {
|
Widget _buildBody() {
|
||||||
final keys_ = Stores.setting.sshVirtKeys.fetch();
|
return ValueListenableBuilder(
|
||||||
final keys = <int>[];
|
valueListenable: prop.listenable(),
|
||||||
for (final key in keys_) {
|
builder: (_, vals, __) {
|
||||||
keys.add(key);
|
final keys = List<int>.from(vals);
|
||||||
}
|
final disabled = VirtKey.values
|
||||||
final disabled = VirtKey.values
|
.map((e) => e.index)
|
||||||
.map((e) => e.index)
|
.where((e) => !keys.contains(e))
|
||||||
.where((e) => !keys.contains(e))
|
.toList();
|
||||||
.toList();
|
final allKeys = [...keys, ...disabled];
|
||||||
final allKeys = [...keys, ...disabled];
|
return ReorderableListView.builder(
|
||||||
return ReorderableListView.builder(
|
padding: const EdgeInsets.all(7),
|
||||||
padding: const EdgeInsets.all(7),
|
itemBuilder: (_, idx) {
|
||||||
itemBuilder: (_, idx) {
|
final key = allKeys[idx];
|
||||||
final key = allKeys[idx];
|
final item = VirtKey.values[key];
|
||||||
final item = VirtKey.values[key];
|
final help = item.help;
|
||||||
final help = item.help;
|
return CardX(
|
||||||
return CardX(
|
key: ValueKey(idx),
|
||||||
key: ValueKey(idx),
|
child: ListTile(
|
||||||
child: ListTile(
|
title: _buildTitle(item),
|
||||||
title: _buildTitle(item),
|
subtitle: help == null ? null : Text(help, style: UIs.textGrey),
|
||||||
subtitle: help == null ? null : Text(help, style: UIs.textGrey),
|
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
||||||
leading: _buildCheckBox(keys, key, idx, idx < keys.length),
|
trailing: isDesktop ? null : const Icon(Icons.drag_handle),
|
||||||
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<SSHVirtKeySettingPage> {
|
|||||||
} else {
|
} else {
|
||||||
keys.remove(key);
|
keys.remove(key);
|
||||||
}
|
}
|
||||||
Stores.setting.sshVirtKeys.put(keys);
|
prop.put(keys);
|
||||||
setState(() {});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user