rollback: write script to /dev/shm (#474)

This commit is contained in:
lollipopkit🏳️‍⚧️
2024-07-21 17:58:14 +08:00
committed by GitHub
parent b0936c5e6e
commit 255abe8b11
25 changed files with 226 additions and 211 deletions

View File

@@ -305,6 +305,8 @@ class BackupPage extends StatelessWidget {
final url = TextEditingController(text: Stores.setting.webdavUrl.fetch());
final user = TextEditingController(text: Stores.setting.webdavUser.fetch());
final pwd = TextEditingController(text: Stores.setting.webdavPwd.fetch());
final nodeUser = FocusNode();
final nodePwd = FocusNode();
final result = await context.showRoundDialog<bool>(
title: 'WebDAV',
child: Column(
@@ -314,14 +316,19 @@ class BackupPage extends StatelessWidget {
label: 'URL',
hint: 'https://example.com/webdav/',
controller: url,
onSubmitted: (p0) => FocusScope.of(context).requestFocus(nodeUser),
),
Input(
label: l10n.user,
controller: user,
node: nodeUser,
onSubmitted: (p0) => FocusScope.of(context).requestFocus(nodePwd),
),
Input(
label: l10n.pwd,
controller: pwd,
node: nodePwd,
onSubmitted: (_) => context.pop(true),
),
],
),

View File

@@ -118,32 +118,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
Widget _buildFAB() {
return FloatingActionButton(
tooltip: l10n.save,
onPressed: () async {
final name = _nameController.text;
final key = _standardizeLineSeparators(_keyController.text.trim());
final pwd = _pwdController.text;
if (name.isEmpty || key.isEmpty) {
context.showSnackBar(l10n.fieldMustNotEmpty);
return;
}
FocusScope.of(context).unfocus();
_loading.value = UIs.centerSizedLoading;
try {
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
final pki = PrivateKeyInfo(id: name, key: decrypted);
if (widget.pki != null) {
Pros.key.update(widget.pki!, pki);
} else {
Pros.key.add(pki);
}
} catch (e) {
context.showSnackBar(e.toString());
rethrow;
} finally {
_loading.value = null;
}
context.pop();
},
onPressed: _onTapSave,
child: const Icon(Icons.save),
);
}
@@ -206,6 +181,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
obscureText: true,
label: l10n.pwd,
icon: Icons.password,
onSubmitted: (_) => _onTapSave(),
),
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
ValBuilder(
@@ -215,4 +191,31 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
],
);
}
void _onTapSave() async {
final name = _nameController.text;
final key = _standardizeLineSeparators(_keyController.text.trim());
final pwd = _pwdController.text;
if (name.isEmpty || key.isEmpty) {
context.showSnackBar(l10n.fieldMustNotEmpty);
return;
}
FocusScope.of(context).unfocus();
_loading.value = UIs.centerSizedLoading;
try {
final decrypted = await Computer.shared.start(decyptPem, [key, pwd]);
final pki = PrivateKeyInfo(id: name, key: decrypted);
if (widget.pki != null) {
Pros.key.update(widget.pki!, pki);
} else {
Pros.key.add(pki);
}
} catch (e) {
context.showSnackBar(e.toString());
rethrow;
} finally {
_loading.value = null;
}
context.pop();
}
}

View File

@@ -52,7 +52,7 @@ class _ProcessPageState extends State<ProcessPage> {
Future<void> _refresh() async {
if (mounted) {
final result =
await _client?.run(ShellFunc.process.exec(widget.spi.id)).string;
await _client?.run(ShellFunc.process.exec).string;
if (result == null || result.isEmpty) {
context.showSnackBar(l10n.noResult);
return;

View File

@@ -174,6 +174,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
Widget _buildForm() {
final children = [
_buildWriteScriptTip(),
Input(
autoFocus: true,
controller: _nameController,
@@ -638,4 +639,19 @@ class _ServerEditPageState extends State<ServerEditPage> {
context.pop();
}
Widget _buildWriteScriptTip() {
return ListTile(
leading: const Icon(Icons.tips_and_updates).paddingOnly(left: 13),
title: Text(l10n.attention),
onTap: () {
context.showRoundDialog(
title: l10n.attention,
child: SimpleMarkdown(data: l10n.writeScriptTip),
actions: Btns.oks(onTap: () => context.pop(true)),
);
},
trailing: const Icon(Icons.keyboard_arrow_right),
).cardx;
}
}

View File

@@ -356,7 +356,7 @@ class _ServerPageState extends State<ServerPage>
Stores.setting.showSuspendTip.put(false);
}
srv.client?.execWithPwd(
ShellFunc.suspend.exec(srv.id),
ShellFunc.suspend.exec,
context: context,
id: srv.id,
);
@@ -370,7 +370,7 @@ class _ServerPageState extends State<ServerPage>
IconTextBtn(
onPressed: () => _askFor(
func: () => srv.client?.execWithPwd(
ShellFunc.shutdown.exec(srv.id),
ShellFunc.shutdown.exec,
context: context,
id: srv.id,
),
@@ -383,7 +383,7 @@ class _ServerPageState extends State<ServerPage>
IconTextBtn(
onPressed: () => _askFor(
func: () => srv.client?.execWithPwd(
ShellFunc.reboot.exec(srv.id),
ShellFunc.reboot.exec,
context: context,
id: srv.id,
),

View File

@@ -581,6 +581,35 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _mkdir() {
context.pop();
final textController = TextEditingController();
void onSubmitted() async {
if (textController.text.isEmpty) {
context.showRoundDialog(
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final dir = '${_status.path!.path}/${textController.text}';
await _status.client!.mkdir(dir);
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.createFolder);
}
}
context.showRoundDialog(
title: l10n.createFolder,
child: Input(
@@ -588,6 +617,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
icon: Icons.folder,
controller: textController,
label: l10n.name,
onSubmitted: (_) => onSubmitted(),
),
actions: [
TextButton(
@@ -595,33 +625,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
child: Text(l10n.cancel),
),
TextButton(
onPressed: () async {
if (textController.text.isEmpty) {
context.showRoundDialog(
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final dir = '${_status.path!.path}/${textController.text}';
await _status.client!.mkdir(dir);
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.createFolder);
}
},
onPressed: onSubmitted,
child: Text(l10n.ok, style: UIs.textRed),
),
],
@@ -631,6 +635,36 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _newFile() {
context.pop();
final textController = TextEditingController();
void onSubmitted() async {
if (textController.text.isEmpty) {
context.showRoundDialog(
title: l10n.attention,
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final path = '${_status.path!.path}/${textController.text}';
await _client!.run('touch "$path"');
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.createFile);
}
}
context.showRoundDialog(
title: l10n.createFile,
child: Input(
@@ -638,37 +672,11 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
icon: Icons.insert_drive_file,
controller: textController,
label: l10n.name,
onSubmitted: (_) => onSubmitted(),
),
actions: [
TextButton(
onPressed: () async {
if (textController.text.isEmpty) {
context.showRoundDialog(
title: l10n.attention,
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final path = '${_status.path!.path}/${textController.text}';
await _client!.run('touch "$path"');
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.createFile);
}
},
onPressed: onSubmitted,
child: Text(l10n.ok, style: UIs.textRed),
),
],
@@ -678,6 +686,36 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
void _rename(SftpName file) {
context.pop();
final textController = TextEditingController(text: file.filename);
void onSubmitted() async {
if (textController.text.isEmpty) {
context.showRoundDialog(
title: l10n.attention,
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final newName = textController.text;
await _status.client?.rename(file.filename, newName);
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.rename);
}
}
context.showRoundDialog(
title: l10n.rename,
child: Input(
@@ -685,38 +723,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
icon: Icons.abc,
controller: textController,
label: l10n.name,
onSubmitted: (_) => onSubmitted(),
),
actions: [
TextButton(onPressed: () => context.pop(), child: Text(l10n.cancel)),
TextButton(
onPressed: () async {
if (textController.text.isEmpty) {
context.showRoundDialog(
title: l10n.attention,
child: Text(l10n.fieldMustNotEmpty),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(l10n.ok),
),
],
);
return;
}
context.pop();
try {
await context.showLoadingDialog(
fn: () async {
final newName = textController.text;
await _status.client?.rename(file.filename, newName);
},
onErr: (e, s) {},
);
_listDir();
} catch (e, s) {
context.showErrDialog(e: e, s: s, operation: l10n.rename);
}
},
onPressed: onSubmitted,
child: Text(l10n.rename, style: UIs.textRed),
),
],