optimization: desktop UI (#747)

This commit is contained in:
lollipopkit🏳️‍⚧️
2025-05-13 04:57:37 +08:00
committed by GitHub
parent e520929411
commit 8627ff823f
52 changed files with 2459 additions and 1990 deletions

View File

@@ -13,13 +13,22 @@ import 'package:server_box/data/model/server/private_key_info.dart';
const _format = 'text/plain';
class PrivateKeyEditPage extends StatefulWidget {
const PrivateKeyEditPage({super.key, this.pki});
final class PrivateKeyEditPageArgs {
final PrivateKeyInfo? pki;
const PrivateKeyEditPageArgs({this.pki});
}
class PrivateKeyEditPage extends StatefulWidget {
final PrivateKeyEditPageArgs? args;
const PrivateKeyEditPage({super.key, this.args});
@override
State<PrivateKeyEditPage> createState() => _PrivateKeyEditPageState();
static const route = AppRoute(
page: PrivateKeyEditPage.new,
path: '/private_key/edit',
);
}
class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
@@ -34,6 +43,8 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
final _loading = ValueNotifier<Widget?>(null);
PrivateKeyInfo? get pki => widget.args?.pki;
@override
void dispose() {
super.dispose();
@@ -49,9 +60,10 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
@override
void initState() {
super.initState();
if (widget.pki != null) {
_nameController.text = widget.pki!.id;
_keyController.text = widget.pki!.key;
final pki = this.pki;
if (pki != null) {
_nameController.text = pki.id;
_keyController.text = pki.key;
} else {
Clipboard.getData(_format).then((value) {
if (value == null) return;
@@ -79,31 +91,34 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
}
CustomAppBar _buildAppBar() {
final actions = [
IconButton(
tooltip: libL10n.delete,
onPressed: () {
context.showRoundDialog(
title: libL10n.attention,
child: Text(libL10n.askContinue(
'${libL10n.delete} ${l10n.privateKey}(${widget.pki!.id})',
)),
actions: Btn.ok(
onTap: () {
PrivateKeyProvider.delete(widget.pki!);
context.pop();
context.pop();
final pki = this.pki;
final actions = pki != null
? [
IconButton(
tooltip: libL10n.delete,
onPressed: () {
context.showRoundDialog(
title: libL10n.attention,
child: Text(libL10n.askContinue(
'${libL10n.delete} ${l10n.privateKey}(${pki.id})',
)),
actions: Btn.ok(
onTap: () {
PrivateKeyProvider.delete(pki);
context.pop();
context.pop();
},
red: true,
).toList,
);
},
red: true,
).toList,
);
},
icon: const Icon(Icons.delete),
)
];
icon: const Icon(Icons.delete),
)
]
: null;
return CustomAppBar(
title: Text(libL10n.edit),
actions: widget.pki == null ? null : actions,
actions: actions,
);
}
@@ -120,8 +135,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
}
Widget _buildBody() {
return ListView(
padding: const EdgeInsets.all(13),
return AutoMultiList(
children: [
Input(
autoFocus: true,
@@ -204,7 +218,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
try {
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
final pki = PrivateKeyInfo(id: name, key: decrypted);
final originPki = widget.pki;
final originPki = this.pki;
if (originPki != null) {
PrivateKeyProvider.update(originPki, pki);
} else {

View File

@@ -6,26 +6,30 @@ import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/res/store.dart';
import 'package:server_box/core/route.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/provider/private_key.dart';
import 'package:server_box/view/page/private_key/edit.dart';
class PrivateKeysListPage extends StatefulWidget {
const PrivateKeysListPage({super.key});
@override
State<PrivateKeysListPage> createState() => _PrivateKeyListState();
static const route = AppRouteNoArg(
page: PrivateKeysListPage.new,
path: '/private_key',
);
}
class _PrivateKeyListState extends State<PrivateKeysListPage>
with AfterLayoutMixin {
class _PrivateKeyListState extends State<PrivateKeysListPage> with AfterLayoutMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => AppRoutes.keyEdit().go(context),
onPressed: () => PrivateKeyEditPage.route.go(context),
),
);
}
@@ -36,33 +40,33 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
if (pkis.isEmpty) {
return Center(child: Text(libL10n.empty));
}
return ListView.builder(
padding: const EdgeInsets.all(13),
itemCount: pkis.length,
itemBuilder: (context, idx) {
final item = pkis[idx];
return CardX(
child: ListTile(
leading: Text(
'#$idx',
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
title: Text(item.id),
subtitle: Text(item.type ?? l10n.unknown, style: UIs.textGrey),
onTap: () => AppRoutes.keyEdit(pki: item).go(context),
trailing: const Icon(Icons.edit),
),
);
},
);
final children = pkis.map(_buildKeyItem).toList();
return AutoMultiList(children: children);
},
);
}
void autoAddSystemPriavteKey() {
Widget _buildKeyItem(PrivateKeyInfo item) {
return ListTile(
title: Text(item.id),
subtitle: Text(item.type ?? l10n.unknown, style: UIs.textGrey),
onTap: () => PrivateKeyEditPage.route.go(
context,
args: PrivateKeyEditPageArgs(pki: item),
),
trailing: const Icon(Icons.edit),
).cardx;
}
@override
FutureOr<void> afterFirstLayout(BuildContext context) {
_autoAddSystemPriavteKey();
}
}
extension on _PrivateKeyListState {
void _autoAddSystemPriavteKey() async {
// Only trigger on desktop platform and no private key saved
if (isDesktop && Stores.snippet.box.keys.isEmpty) {
final home = Pfs.homeDir;
@@ -71,21 +75,19 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
if (!idRsaFile.existsSync()) return;
final sysPk = PrivateKeyInfo(
id: 'system',
key: idRsaFile.readAsStringSync(),
key: await idRsaFile.readAsString(),
);
context.showRoundDialog(
title: libL10n.attention,
child: Text(l10n.addSystemPrivateKeyTip),
actions: Btn.ok(onTap: () {
context.pop();
AppRoutes.keyEdit(pki: sysPk).go(context);
PrivateKeyEditPage.route.go(
context,
args: PrivateKeyEditPageArgs(pki: sysPk),
);
}).toList,
);
}
}
@override
FutureOr<void> afterFirstLayout(BuildContext context) {
autoAddSystemPriavteKey();
}
}