mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: no app restart required
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
import '../../../data/model/server/snippet.dart';
|
import '../../../data/model/server/snippet.dart';
|
||||||
@@ -41,37 +41,35 @@ extension DialogX on BuildContext {
|
|||||||
String? user,
|
String? user,
|
||||||
) async {
|
) async {
|
||||||
if (!mounted) return null;
|
if (!mounted) return null;
|
||||||
final s = S.of(this)!;
|
|
||||||
return await showRoundDialog<String>(
|
return await showRoundDialog<String>(
|
||||||
title: Text(user ?? s.pwd),
|
title: Text(user ?? l10n.pwd),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
type: TextInputType.visiblePassword,
|
type: TextInputType.visiblePassword,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
onSubmitted: (val) => pop(val.trim()),
|
onSubmitted: (val) => pop(val.trim()),
|
||||||
label: s.pwd,
|
label: l10n.pwd,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showSnippetDialog(
|
void showSnippetDialog(
|
||||||
S s,
|
|
||||||
void Function(Snippet s) onSelected,
|
void Function(Snippet s) onSelected,
|
||||||
) {
|
) {
|
||||||
if (Providers.snippet.snippets.isEmpty) {
|
if (Providers.snippet.snippets.isEmpty) {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
child: Text(s.noSavedSnippet),
|
child: Text(l10n.noSavedSnippet),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => pop(),
|
onPressed: () => pop(),
|
||||||
child: Text(s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
pop();
|
pop();
|
||||||
AppRoute.snippetEdit().go(this);
|
AppRoute.snippetEdit().go(this);
|
||||||
},
|
},
|
||||||
child: Text(s.add),
|
child: Text(l10n.add),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -80,7 +78,7 @@ extension DialogX on BuildContext {
|
|||||||
|
|
||||||
var snippet = Providers.snippet.snippets.first;
|
var snippet = Providers.snippet.snippets.first;
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
title: Text(s.choose),
|
title: Text(l10n.choose),
|
||||||
child: Picker(
|
child: Picker(
|
||||||
items: Providers.snippet.snippets.map((e) => Text(e.name)).toList(),
|
items: Providers.snippet.snippets.map((e) => Text(e.name)).toList(),
|
||||||
onSelected: (idx) => snippet = Providers.snippet.snippets[idx],
|
onSelected: (idx) => snippet = Providers.snippet.snippets[idx],
|
||||||
@@ -91,7 +89,7 @@ extension DialogX on BuildContext {
|
|||||||
pop();
|
pop();
|
||||||
onSelected(snippet);
|
onSelected(snippet);
|
||||||
},
|
},
|
||||||
child: Text(s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
7
lib/core/extension/context/locale.dart
Normal file
7
lib/core/extension/context/locale.dart
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
|
late S _s;
|
||||||
|
S get l10n => _s;
|
||||||
|
set l10n(S s) {
|
||||||
|
_s = s;
|
||||||
|
}
|
||||||
@@ -2,10 +2,10 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:r_upgrade/r_upgrade.dart';
|
import 'package:r_upgrade/r_upgrade.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/model/app/update.dart';
|
import 'package:toolbox/data/model/app/update.dart';
|
||||||
@@ -54,17 +54,15 @@ Future<void> doUpdate(BuildContext context, {bool force = false}) async {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final s = S.of(context);
|
|
||||||
|
|
||||||
final min = update.build.min.current;
|
final min = update.build.min.current;
|
||||||
|
|
||||||
if (min != null && min > BuildData.build) {
|
if (min != null && min > BuildData.build) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
child: Text(s?.updateTipTooLow(newest) ?? 'Update: $newest'),
|
child: Text(l10n.updateTipTooLow(newest)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _doUpdate(update, context, s),
|
onPressed: () => _doUpdate(update, context),
|
||||||
child: Text(s?.ok ?? 'Ok'),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -72,13 +70,13 @@ Future<void> doUpdate(BuildContext context, {bool force = false}) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.showSnackBarWithAction(
|
context.showSnackBarWithAction(
|
||||||
'${s?.updateTip(newest) ?? "Update: $newest"} \n${update.changelog.current}',
|
'${l10n.updateTip(newest)} \n${update.changelog.current}',
|
||||||
s?.update ?? 'Update',
|
l10n.update,
|
||||||
() => _doUpdate(update, context, s),
|
() => _doUpdate(update, context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _doUpdate(AppUpdate update, BuildContext context, S? s) async {
|
Future<void> _doUpdate(AppUpdate update, BuildContext context) async {
|
||||||
final url = update.url.current;
|
final url = update.url.current;
|
||||||
if (url == null) return;
|
if (url == null) return;
|
||||||
|
|
||||||
@@ -91,11 +89,11 @@ Future<void> _doUpdate(AppUpdate update, BuildContext context, S? s) async {
|
|||||||
await openUrl(url);
|
await openUrl(url);
|
||||||
} else {
|
} else {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
child: Text(s?.platformNotSupportUpdate ?? 'Unsupported platform'),
|
child: Text(l10n.platformNotSupportUpdate),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(s?.ok ?? 'Ok'),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'package:crypto/crypto.dart';
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ Future<bool> shareFiles(BuildContext context, List<String> filePaths) async {
|
|||||||
if (filePaths.length == 1) {
|
if (filePaths.length == 1) {
|
||||||
text = filePaths.first.split('/').last;
|
text = filePaths.first.split('/').last;
|
||||||
} else {
|
} else {
|
||||||
text = '${filePaths.length} ${S.of(context)!.files}';
|
text = '${filePaths.length} ${l10n.files}';
|
||||||
}
|
}
|
||||||
Providers.app.moveBg = false;
|
Providers.app.moveBg = false;
|
||||||
// ignore: deprecated_member_use
|
// ignore: deprecated_member_use
|
||||||
|
|||||||
@@ -5,23 +5,23 @@ class _RebuildNode implements ValueListenable<Null> {
|
|||||||
final List<VoidCallback> _listeners = [];
|
final List<VoidCallback> _listeners = [];
|
||||||
|
|
||||||
_RebuildNode();
|
_RebuildNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void addListener(VoidCallback listener) {
|
void addListener(VoidCallback listener) {
|
||||||
_listeners.add(listener);
|
_listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void removeListener(VoidCallback listener) {
|
void removeListener(VoidCallback listener) {
|
||||||
_listeners.remove(listener);
|
_listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rebuild() {
|
void rebuild() {
|
||||||
for (var listener in _listeners) {
|
for (var listener in _listeners) {
|
||||||
listener();
|
listener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Null get value => null;
|
Null get value => null;
|
||||||
}
|
}
|
||||||
@@ -30,4 +30,4 @@ class RebuildNodes {
|
|||||||
const RebuildNodes._();
|
const RebuildNodes._();
|
||||||
|
|
||||||
static final _RebuildNode app = _RebuildNode();
|
static final _RebuildNode app = _RebuildNode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
|
|
||||||
enum ServerTabMenuType {
|
enum ServerTabMenuType {
|
||||||
terminal,
|
terminal,
|
||||||
@@ -27,20 +27,20 @@ enum ServerTabMenuType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String text(S s) {
|
String get toStr {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case ServerTabMenuType.sftp:
|
case ServerTabMenuType.sftp:
|
||||||
return 'SFTP';
|
return 'SFTP';
|
||||||
case ServerTabMenuType.snippet:
|
case ServerTabMenuType.snippet:
|
||||||
return s.snippet;
|
return l10n.snippet;
|
||||||
case ServerTabMenuType.pkg:
|
case ServerTabMenuType.pkg:
|
||||||
return s.pkg;
|
return l10n.pkg;
|
||||||
case ServerTabMenuType.docker:
|
case ServerTabMenuType.docker:
|
||||||
return 'Docker';
|
return 'Docker';
|
||||||
case ServerTabMenuType.process:
|
case ServerTabMenuType.process:
|
||||||
return s.process;
|
return l10n.process;
|
||||||
case ServerTabMenuType.terminal:
|
case ServerTabMenuType.terminal:
|
||||||
return s.terminal;
|
return l10n.terminal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,26 +89,26 @@ enum DockerMenuType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String text(S s) {
|
String get toStr {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case DockerMenuType.start:
|
case DockerMenuType.start:
|
||||||
return s.start;
|
return l10n.start;
|
||||||
case DockerMenuType.stop:
|
case DockerMenuType.stop:
|
||||||
return s.stop;
|
return l10n.stop;
|
||||||
case DockerMenuType.restart:
|
case DockerMenuType.restart:
|
||||||
return s.restart;
|
return l10n.restart;
|
||||||
case DockerMenuType.rm:
|
case DockerMenuType.rm:
|
||||||
return s.delete;
|
return l10n.delete;
|
||||||
case DockerMenuType.logs:
|
case DockerMenuType.logs:
|
||||||
return s.log;
|
return l10n.log;
|
||||||
case DockerMenuType.terminal:
|
case DockerMenuType.terminal:
|
||||||
return s.terminal;
|
return l10n.terminal;
|
||||||
// case DockerMenuType.stats:
|
// case DockerMenuType.stats:
|
||||||
// return s.stats;
|
// return s.stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenuItem<DockerMenuType> build(S s) => _build(this, icon, text(s));
|
PopupMenuItem<DockerMenuType> get widget => _build(this, icon, toStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenuItem<T> _build<T>(T t, IconData icon, String text) {
|
PopupMenuItem<T> _build<T>(T t, IconData icon, String text) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/data/model/server/server_status.dart';
|
import 'package:toolbox/data/model/server/server_status.dart';
|
||||||
|
|
||||||
part 'net_view.g.dart';
|
part 'net_view.g.dart';
|
||||||
@@ -13,14 +13,14 @@ enum NetViewType {
|
|||||||
@HiveField(2)
|
@HiveField(2)
|
||||||
traffic;
|
traffic;
|
||||||
|
|
||||||
String l10n(S s) {
|
String get toStr {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case NetViewType.conn:
|
case NetViewType.conn:
|
||||||
return s.conn;
|
return l10n.conn;
|
||||||
case NetViewType.traffic:
|
case NetViewType.traffic:
|
||||||
return s.traffic;
|
return l10n.traffic;
|
||||||
case NetViewType.speed:
|
case NetViewType.speed:
|
||||||
return s.speed;
|
return l10n.speed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:xterm/core.dart';
|
import 'package:xterm/core.dart';
|
||||||
|
|
||||||
part 'virtual_key.g.dart';
|
part 'virtual_key.g.dart';
|
||||||
@@ -148,12 +148,12 @@ enum VirtKey {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String? help(S s) {
|
String? get help {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case VirtKey.sftp:
|
case VirtKey.sftp:
|
||||||
return s.virtKeyHelpSFTP;
|
return l10n.virtKeyHelpSFTP;
|
||||||
case VirtKey.clipboard:
|
case VirtKey.clipboard:
|
||||||
return s.virtKeyHelpClipboard;
|
return l10n.virtKeyHelpClipboard;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/core/utils/rebuild.dart';
|
import 'package:toolbox/core/utils/rebuild.dart';
|
||||||
@@ -25,34 +25,33 @@ class BackupPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context)!;
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(s.backupAndRestore, style: UIs.textSize18),
|
title: Text(l10n.backupAndRestore, style: UIs.textSize18),
|
||||||
),
|
),
|
||||||
body: _buildBody(context, s),
|
body: _buildBody(context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(BuildContext context, S s) {
|
Widget _buildBody(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
if (isMacOS || isIOS) _buildIcloudSync(context, s),
|
if (isMacOS || isIOS) _buildIcloudSync(context),
|
||||||
UIs.height13,
|
UIs.height13,
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(37),
|
padding: const EdgeInsets.all(37),
|
||||||
child: Text(
|
child: Text(
|
||||||
s.backupTip,
|
l10n.backupTip,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
UIs.height77,
|
UIs.height77,
|
||||||
_buildCard(
|
_buildCard(
|
||||||
s.restore,
|
l10n.restore,
|
||||||
Icons.download,
|
Icons.download,
|
||||||
() => _onRestore(context, s),
|
() => _onRestore(context),
|
||||||
),
|
),
|
||||||
UIs.height13,
|
UIs.height13,
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@@ -61,7 +60,7 @@ class BackupPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
UIs.height13,
|
UIs.height13,
|
||||||
_buildCard(
|
_buildCard(
|
||||||
s.backup,
|
l10n.backup,
|
||||||
Icons.save,
|
Icons.save,
|
||||||
() async {
|
() async {
|
||||||
await Backup.backup();
|
await Backup.backup();
|
||||||
@@ -96,7 +95,7 @@ class BackupPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildIcloudSync(BuildContext context, S s) {
|
Widget _buildIcloudSync(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -121,19 +120,19 @@ class BackupPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onRestore(BuildContext context, S s) async {
|
Future<void> _onRestore(BuildContext context) async {
|
||||||
final path = await pickOneFile();
|
final path = await pickOneFile();
|
||||||
if (path == null) return;
|
if (path == null) return;
|
||||||
|
|
||||||
final file = File(path);
|
final file = File(path);
|
||||||
if (!await file.exists()) {
|
if (!await file.exists()) {
|
||||||
context.showSnackBar(s.fileNotExist(path));
|
context.showSnackBar(l10n.fileNotExist(path));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final text = await file.readAsString();
|
final text = await file.readAsString();
|
||||||
if (text.isEmpty) {
|
if (text.isEmpty) {
|
||||||
context.showSnackBar(s.fieldMustNotEmpty);
|
context.showSnackBar(l10n.fieldMustNotEmpty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,17 +140,17 @@ class BackupPage extends StatelessWidget {
|
|||||||
context.showLoadingDialog();
|
context.showLoadingDialog();
|
||||||
final backup = await compute(Backup.fromJsonString, text.trim());
|
final backup = await compute(Backup.fromJsonString, text.trim());
|
||||||
if (backupFormatVersion != backup.version) {
|
if (backupFormatVersion != backup.version) {
|
||||||
context.showSnackBar(s.backupVersionNotMatch);
|
context.showSnackBar(l10n.backupVersionNotMatch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(s.restore),
|
title: Text(l10n.restore),
|
||||||
child: Text(s.restoreSureWithDate(backup.date)),
|
child: Text(l10n.restoreSureWithDate(backup.date)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -159,7 +158,7 @@ class BackupPage extends StatelessWidget {
|
|||||||
context.pop();
|
context.pop();
|
||||||
RebuildNodes.app.rebuild();
|
RebuildNodes.app.rebuild();
|
||||||
},
|
},
|
||||||
child: Text(s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
import 'package:toolbox/data/model/docker/image.dart';
|
import 'package:toolbox/data/model/docker/image.dart';
|
||||||
@@ -33,7 +33,6 @@ class DockerManagePage extends StatefulWidget {
|
|||||||
|
|
||||||
class _DockerManagePageState extends State<DockerManagePage> {
|
class _DockerManagePageState extends State<DockerManagePage> {
|
||||||
final _textController = TextEditingController();
|
final _textController = TextEditingController();
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@@ -42,12 +41,6 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
_textController.dispose();
|
_textController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -103,27 +96,27 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
final nameCtrl = TextEditingController();
|
final nameCtrl = TextEditingController();
|
||||||
final argsCtrl = TextEditingController();
|
final argsCtrl = TextEditingController();
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.newContainer),
|
title: Text(l10n.newContainer),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Input(
|
Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
label: _s.image,
|
label: l10n.image,
|
||||||
hint: 'xxx:1.1',
|
hint: 'xxx:1.1',
|
||||||
controller: imageCtrl,
|
controller: imageCtrl,
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
controller: nameCtrl,
|
controller: nameCtrl,
|
||||||
label: _s.containerName,
|
label: l10n.containerName,
|
||||||
hint: 'xxx',
|
hint: 'xxx',
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
controller: argsCtrl,
|
controller: argsCtrl,
|
||||||
label: _s.extraArgs,
|
label: l10n.extraArgs,
|
||||||
hint: '-p 2222:22 -v ~/.xxx/:/xxx',
|
hint: '-p 2222:22 -v ~/.xxx/:/xxx',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -131,7 +124,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -144,7 +137,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -152,12 +145,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
Future<void> _showAddCmdPreview(String cmd) async {
|
Future<void> _showAddCmdPreview(String cmd) async {
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.preview),
|
title: Text(l10n.preview),
|
||||||
child: Text(cmd),
|
child: Text(cmd),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -166,10 +159,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
final result = await Providers.docker.run(cmd);
|
final result = await Providers.docker.run(cmd);
|
||||||
context.pop();
|
context.pop();
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.showSnackBar(result.message ?? _s.unknownError);
|
context.showSnackBar(result.message ?? l10n.unknownError);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(_s.run),
|
child: Text(l10n.run),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -200,7 +193,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
size: 37,
|
size: 37,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 27),
|
const SizedBox(height: 27),
|
||||||
Text(Providers.docker.error?.message ?? _s.unknownError),
|
Text(Providers.docker.error?.message ?? l10n.unknownError),
|
||||||
const SizedBox(height: 27),
|
const SizedBox(height: 27),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(17),
|
padding: const EdgeInsets.all(17),
|
||||||
@@ -230,9 +223,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
Widget _buildImage() {
|
Widget _buildImage() {
|
||||||
final items = <Widget>[
|
final items = <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.imagesList),
|
title: Text(l10n.imagesList),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
_s.dockerImagesFmt(Providers.docker.images!.length),
|
l10n.dockerImagesFmt(Providers.docker.images!.length),
|
||||||
style: UIs.textGrey,
|
style: UIs.textGrey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -256,12 +249,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
void _showImageRmDialog(DockerImage e) {
|
void _showImageRmDialog(DockerImage e) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(e.repo)),
|
child: Text(l10n.sureDelete(e.repo)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -270,10 +263,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
'docker rmi ${e.id} -f',
|
'docker rmi ${e.id} -f',
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.showSnackBar(result.message ?? _s.unknownError);
|
context.showSnackBar(result.message ?? l10n.unknownError);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(_s.ok, style: UIs.textRed),
|
child: Text(l10n.ok, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -299,14 +292,14 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
switch (err.type) {
|
switch (err.type) {
|
||||||
case DockerErrType.notInstalled:
|
case DockerErrType.notInstalled:
|
||||||
return UrlText(
|
return UrlText(
|
||||||
text: _s.installDockerWithUrl,
|
text: l10n.installDockerWithUrl,
|
||||||
replace: _s.install,
|
replace: l10n.install,
|
||||||
);
|
);
|
||||||
case DockerErrType.noClient:
|
case DockerErrType.noClient:
|
||||||
return Text(_s.waitConnection);
|
return Text(l10n.waitConnection);
|
||||||
case DockerErrType.invalidVersion:
|
case DockerErrType.invalidVersion:
|
||||||
return UrlText(
|
return UrlText(
|
||||||
text: _s.invalidVersionHelp(Urls.appHelp),
|
text: l10n.invalidVersionHelp(Urls.appHelp),
|
||||||
replace: 'Github',
|
replace: 'Github',
|
||||||
);
|
);
|
||||||
case DockerErrType.parseImages:
|
case DockerErrType.parseImages:
|
||||||
@@ -330,8 +323,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(Providers.docker.edition ?? _s.unknown),
|
Text(Providers.docker.edition ?? l10n.unknown),
|
||||||
Text(Providers.docker.version ?? _s.unknown),
|
Text(Providers.docker.version ?? l10n.unknown),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -340,7 +333,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
Widget _buildPs() {
|
Widget _buildPs() {
|
||||||
final items = <Widget>[
|
final items = <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.containerStatus),
|
title: Text(l10n.containerStatus),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
_buildPsCardSubtitle(Providers.docker.items!),
|
_buildPsCardSubtitle(Providers.docker.items!),
|
||||||
style: UIs.textGrey,
|
style: UIs.textGrey,
|
||||||
@@ -367,17 +360,13 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
Widget _buildMoreBtn(DockerPsItem dItem) {
|
Widget _buildMoreBtn(DockerPsItem dItem) {
|
||||||
return PopupMenu(
|
return PopupMenu(
|
||||||
items: DockerMenuType.items(dItem.running)
|
items: DockerMenuType.items(dItem.running).map((e) => e.widget).toList(),
|
||||||
.map(
|
|
||||||
(e) => e.build(_s),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
onSelected: (DockerMenuType item) async {
|
onSelected: (DockerMenuType item) async {
|
||||||
switch (item) {
|
switch (item) {
|
||||||
case DockerMenuType.rm:
|
case DockerMenuType.rm:
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(dItem.name)),
|
child: Text(l10n.sureDelete(dItem.name)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -386,7 +375,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
await Providers.docker.delete(dItem.containerId);
|
await Providers.docker.delete(dItem.containerId);
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -421,7 +410,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
// case DockerMenuType.stats:
|
// case DockerMenuType.stats:
|
||||||
// showRoundDialog(
|
// showRoundDialog(
|
||||||
// context: context,
|
// context: context,
|
||||||
// title: Text(_s.stats),
|
// title: Text(l10n.stats),
|
||||||
// child: Text(
|
// child: Text(
|
||||||
// 'CPU: ${dItem.cpu}\n'
|
// 'CPU: ${dItem.cpu}\n'
|
||||||
// 'Mem: ${dItem.mem}\n'
|
// 'Mem: ${dItem.mem}\n'
|
||||||
@@ -431,7 +420,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
// actions: [
|
// actions: [
|
||||||
// TextButton(
|
// TextButton(
|
||||||
// onPressed: () => context.pop(),
|
// onPressed: () => context.pop(),
|
||||||
// child: Text(_s.ok),
|
// child: Text(l10n.ok),
|
||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// );
|
// );
|
||||||
@@ -445,9 +434,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
final runningCount = running.where((element) => element.running).length;
|
final runningCount = running.where((element) => element.running).length;
|
||||||
final stoped = running.length - runningCount;
|
final stoped = running.length - runningCount;
|
||||||
if (stoped == 0) {
|
if (stoped == 0) {
|
||||||
return _s.dockerStatusRunningFmt(runningCount);
|
return l10n.dockerStatusRunningFmt(runningCount);
|
||||||
}
|
}
|
||||||
return _s.dockerStatusRunningAndStoppedFmt(runningCount, stoped);
|
return l10n.dockerStatusRunningAndStoppedFmt(runningCount, stoped);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEditHost() {
|
Widget _buildEditHost() {
|
||||||
@@ -456,7 +445,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
children.add(Padding(
|
children.add(Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(17, 17, 17, 0),
|
padding: const EdgeInsets.fromLTRB(17, 17, 17, 0),
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.dockerEmptyRunningItems,
|
l10n.dockerEmptyRunningItems,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
@@ -464,7 +453,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
children.add(
|
children.add(
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _showEditHostDialog,
|
onPressed: _showEditHostDialog,
|
||||||
child: Text(_s.dockerEditHost),
|
child: Text(l10n.dockerEditHost),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Column(
|
return Column(
|
||||||
@@ -477,7 +466,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
final host = Stores.docker.fetch(id) ?? 'unix:///run/user/1000/docker.sock';
|
final host = Stores.docker.fetch(id) ?? 'unix:///run/user/1000/docker.sock';
|
||||||
final ctrl = TextEditingController(text: host);
|
final ctrl = TextEditingController(text: host);
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.dockerEditHost),
|
title: Text(l10n.dockerEditHost),
|
||||||
child: Input(
|
child: Input(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
controller: ctrl,
|
controller: ctrl,
|
||||||
@@ -486,7 +475,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _onSaveDockerHost(ctrl.text),
|
onPressed: () => _onSaveDockerHost(ctrl.text),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:code_text_field/code_text_field.dart';
|
import 'package:code_text_field/code_text_field.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:flutter_highlight/theme_map.dart';
|
import 'package:flutter_highlight/theme_map.dart';
|
||||||
import 'package:flutter_highlight/themes/a11y-light.dart';
|
import 'package:flutter_highlight/themes/a11y-light.dart';
|
||||||
import 'package:flutter_highlight/themes/monokai.dart';
|
import 'package:flutter_highlight/themes/monokai.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
import 'package:toolbox/data/res/highlight.dart';
|
import 'package:toolbox/data/res/highlight.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -47,7 +47,6 @@ class _EditorPageState extends State<EditorPage> {
|
|||||||
|
|
||||||
late CodeController _controller;
|
late CodeController _controller;
|
||||||
late Map<String, TextStyle> _codeTheme;
|
late Map<String, TextStyle> _codeTheme;
|
||||||
late S _s;
|
|
||||||
late final _textStyle =
|
late final _textStyle =
|
||||||
TextStyle(fontSize: Stores.setting.editorFontSize.fetch());
|
TextStyle(fontSize: Stores.setting.editorFontSize.fetch());
|
||||||
|
|
||||||
@@ -77,7 +76,6 @@ class _EditorPageState extends State<EditorPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
|
|
||||||
if (context.isDark) {
|
if (context.isDark) {
|
||||||
_codeTheme =
|
_codeTheme =
|
||||||
@@ -126,8 +124,8 @@ class _EditorPageState extends State<EditorPage> {
|
|||||||
return CustomAppBar(
|
return CustomAppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: TwoLineText(
|
title: TwoLineText(
|
||||||
up: widget.title ?? getFileName(widget.path) ?? _s.unknown,
|
up: widget.title ?? getFileName(widget.path) ?? l10n.unknown,
|
||||||
down: _s.editor,
|
down: l10n.editor,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
PopupMenuButton<String>(
|
PopupMenuButton<String>(
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import 'dart:math';
|
|||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:circle_chart/circle_chart.dart';
|
import 'package:circle_chart/circle_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
import 'package:toolbox/data/model/server/disk.dart';
|
import 'package:toolbox/data/model/server/disk.dart';
|
||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
@@ -31,7 +31,6 @@ class FullScreenPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
||||||
late S _s;
|
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late ThemeData _theme;
|
late ThemeData _theme;
|
||||||
late Timer _timer;
|
late Timer _timer;
|
||||||
@@ -63,7 +62,6 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_theme = Theme.of(context);
|
_theme = Theme.of(context);
|
||||||
}
|
}
|
||||||
@@ -131,7 +129,7 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
|||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => AppRoute.serverEdit().go(context),
|
onPressed: () => AppRoute.serverEdit().go(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.addAServer,
|
l10n.addAServer,
|
||||||
style: const TextStyle(fontSize: 27),
|
style: const TextStyle(fontSize: 27),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
@@ -143,7 +141,7 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
|||||||
final id = pro.serverOrder[idx];
|
final id = pro.serverOrder[idx];
|
||||||
final s = pro.servers[id];
|
final s = pro.servers[id];
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return Center(child: Text(_s.noClient));
|
return Center(child: Text(l10n.noClient));
|
||||||
}
|
}
|
||||||
return _buildRealServerCard(s.status, s.state, s.spi);
|
return _buildRealServerCard(s.status, s.state, s.spi);
|
||||||
},
|
},
|
||||||
@@ -272,25 +270,25 @@ class _FullScreenPageState extends State<FullScreenPage> with AfterLayoutMixin {
|
|||||||
) {
|
) {
|
||||||
switch (cs) {
|
switch (cs) {
|
||||||
case ServerState.disconnected:
|
case ServerState.disconnected:
|
||||||
return _s.disconnected;
|
return l10n.disconnected;
|
||||||
case ServerState.connected:
|
case ServerState.connected:
|
||||||
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
||||||
final items = [tempStr, upTime];
|
final items = [tempStr, upTime];
|
||||||
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
||||||
if (str.isEmpty) return _s.serverTabLoading;
|
if (str.isEmpty) return l10n.serverTabLoading;
|
||||||
return str;
|
return str;
|
||||||
case ServerState.connecting:
|
case ServerState.connecting:
|
||||||
return _s.serverTabConnecting;
|
return l10n.serverTabConnecting;
|
||||||
case ServerState.failed:
|
case ServerState.failed:
|
||||||
if (failedInfo == null) {
|
if (failedInfo == null) {
|
||||||
return _s.serverTabFailed;
|
return l10n.serverTabFailed;
|
||||||
}
|
}
|
||||||
if (failedInfo.contains('encypted')) {
|
if (failedInfo.contains('encypted')) {
|
||||||
return _s.serverTabPlzSave;
|
return l10n.serverTabPlzSave;
|
||||||
}
|
}
|
||||||
return failedInfo;
|
return failedInfo;
|
||||||
default:
|
default:
|
||||||
return _s.serverTabUnkown;
|
return l10n.serverTabUnkown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:get_it/get_it.dart';
|
|||||||
import 'package:toolbox/core/channel/bg_run.dart';
|
import 'package:toolbox/core/channel/bg_run.dart';
|
||||||
import 'package:toolbox/core/channel/home_widget.dart';
|
import 'package:toolbox/core/channel/home_widget.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/utils/platform/auth.dart';
|
import 'package:toolbox/core/utils/platform/auth.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/res/github_id.dart';
|
import 'package:toolbox/data/res/github_id.dart';
|
||||||
@@ -44,7 +45,6 @@ class _HomePageState extends State<HomePage>
|
|||||||
late final PageController _pageController;
|
late final PageController _pageController;
|
||||||
|
|
||||||
final _selectIndex = ValueNotifier(0);
|
final _selectIndex = ValueNotifier(0);
|
||||||
late S _s;
|
|
||||||
|
|
||||||
bool _switchingPage = false;
|
bool _switchingPage = false;
|
||||||
bool _isAuthing = false;
|
bool _isAuthing = false;
|
||||||
@@ -65,7 +65,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
l10n = S.of(context)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -133,7 +133,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
final actions = <Widget>[
|
final actions = <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.developer_mode, size: 23),
|
icon: const Icon(Icons.developer_mode, size: 23),
|
||||||
tooltip: _s.debug,
|
tooltip: l10n.debug,
|
||||||
onPressed: () => AppRoute.debug().go(context),
|
onPressed: () => AppRoute.debug().go(context),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -182,12 +182,12 @@ class _HomePageState extends State<HomePage>
|
|||||||
destinations: [
|
destinations: [
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: const Icon(Icons.cloud_outlined),
|
icon: const Icon(Icons.cloud_outlined),
|
||||||
label: _s.server,
|
label: l10n.server,
|
||||||
selectedIcon: const Icon(Icons.cloud),
|
selectedIcon: const Icon(Icons.cloud),
|
||||||
),
|
),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: const Icon(Icons.snippet_folder_outlined),
|
icon: const Icon(Icons.snippet_folder_outlined),
|
||||||
label: _s.snippet,
|
label: l10n.snippet,
|
||||||
selectedIcon: const Icon(Icons.snippet_folder),
|
selectedIcon: const Icon(Icons.snippet_folder),
|
||||||
),
|
),
|
||||||
const NavigationDestination(
|
const NavigationDestination(
|
||||||
@@ -232,28 +232,28 @@ class _HomePageState extends State<HomePage>
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
title: Text(_s.setting),
|
title: Text(l10n.setting),
|
||||||
onTap: () => AppRoute.settings().go(context),
|
onTap: () => AppRoute.settings().go(context),
|
||||||
onLongPress: _onLongPressSetting,
|
onLongPress: _onLongPressSetting,
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.vpn_key),
|
leading: const Icon(Icons.vpn_key),
|
||||||
title: Text(_s.privateKey),
|
title: Text(l10n.privateKey),
|
||||||
onTap: () => AppRoute.keyList().go(context),
|
onTap: () => AppRoute.keyList().go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.file_open),
|
leading: const Icon(Icons.file_open),
|
||||||
title: Text(_s.files),
|
title: Text(l10n.files),
|
||||||
onTap: () => AppRoute.localStorage().go(context),
|
onTap: () => AppRoute.localStorage().go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.import_export),
|
leading: const Icon(Icons.import_export),
|
||||||
title: Text(_s.backupAndRestore),
|
title: Text(l10n.backupAndRestore),
|
||||||
onTap: () => AppRoute.backup().go(context),
|
onTap: () => AppRoute.backup().go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.text_snippet),
|
leading: const Icon(Icons.text_snippet),
|
||||||
title: Text('${_s.about} & ${_s.feedback}'),
|
title: Text('${l10n.about} & ${l10n.feedback}'),
|
||||||
onTap: _showAboutDialog,
|
onTap: _showAboutDialog,
|
||||||
)
|
)
|
||||||
].map((e) => RoundRectCard(e)).toList(),
|
].map((e) => RoundRectCard(e)).toList(),
|
||||||
@@ -263,7 +263,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
|
|
||||||
void _showAboutDialog() {
|
void _showAboutDialog() {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.about),
|
title: Text(l10n.about),
|
||||||
child: _buildAboutContent(),
|
child: _buildAboutContent(),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -272,11 +272,11 @@ class _HomePageState extends State<HomePage>
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => openUrl(Urls.appHelp),
|
onPressed: () => openUrl(Urls.appHelp),
|
||||||
child: Text(_s.feedback),
|
child: Text(l10n.feedback),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => showLicensePage(context: context),
|
onPressed: () => showLicensePage(context: context),
|
||||||
child: Text(_s.license),
|
child: Text(l10n.license),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -289,12 +289,12 @@ class _HomePageState extends State<HomePage>
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
UrlText(
|
UrlText(
|
||||||
text: _s.madeWithLove(Urls.myGithub),
|
text: l10n.madeWithLove(Urls.myGithub),
|
||||||
replace: 'lollipopkit',
|
replace: 'lollipopkit',
|
||||||
),
|
),
|
||||||
UIs.height13,
|
UIs.height13,
|
||||||
// Use [UrlText] for same text style
|
// Use [UrlText] for same text style
|
||||||
Text(_s.aboutThanks),
|
Text(l10n.aboutThanks),
|
||||||
UIs.height13,
|
UIs.height13,
|
||||||
const Text('Contributors:'),
|
const Text('Contributors:'),
|
||||||
...GithubIds.contributors.map(
|
...GithubIds.contributors.map(
|
||||||
@@ -365,7 +365,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
final result = await AppRoute.editor(
|
final result = await AppRoute.editor(
|
||||||
text: text,
|
text: text,
|
||||||
langCode: 'json',
|
langCode: 'json',
|
||||||
title: _s.setting,
|
title: l10n.setting,
|
||||||
).go(context);
|
).go(context);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
return;
|
return;
|
||||||
@@ -380,8 +380,8 @@ class _HomePageState extends State<HomePage>
|
|||||||
}
|
}
|
||||||
} catch (e, trace) {
|
} catch (e, trace) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text('${_s.save}:\n$e'),
|
child: Text('${l10n.save}:\n$e'),
|
||||||
);
|
);
|
||||||
Loggers.app.warning('Update json settings failed', e, trace);
|
Loggers.app.warning('Update json settings failed', e, trace);
|
||||||
}
|
}
|
||||||
@@ -391,7 +391,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
if (Stores.setting.useBioAuth.fetch()) {
|
if (Stores.setting.useBioAuth.fetch()) {
|
||||||
if (!_isAuthing) {
|
if (!_isAuthing) {
|
||||||
_isAuthing = true;
|
_isAuthing = true;
|
||||||
BioAuth.auth(_s.authRequired).then(
|
BioAuth.auth(l10n.authRequired).then(
|
||||||
(val) {
|
(val) {
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case AuthResult.success:
|
case AuthResult.success:
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
@@ -31,8 +31,6 @@ class _PingPageState extends State<PingPage>
|
|||||||
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
||||||
late TextEditingController _textEditingController;
|
late TextEditingController _textEditingController;
|
||||||
final _results = ValueNotifier(<PingResult>[]);
|
final _results = ValueNotifier(<PingResult>[]);
|
||||||
late S _s;
|
|
||||||
|
|
||||||
bool get isInit => _results.value.isEmpty;
|
bool get isInit => _results.value.isEmpty;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -41,12 +39,6 @@ class _PingPageState extends State<PingPage>
|
|||||||
_textEditingController = TextEditingController(text: '');
|
_textEditingController = TextEditingController(text: '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@@ -71,16 +63,16 @@ class _PingPageState extends State<PingPage>
|
|||||||
heroTag: 'ping',
|
heroTag: 'ping',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.choose),
|
title: Text(l10n.choose),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
controller: _textEditingController,
|
controller: _textEditingController,
|
||||||
hint: _s.inputDomainHere,
|
hint: l10n.inputDomainHere,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
onSubmitted: (_) => _doPing(),
|
onSubmitted: (_) => _doPing(),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(onPressed: _doPing, child: Text(_s.ok)),
|
TextButton(onPressed: _doPing, child: Text(l10n.ok)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -94,12 +86,12 @@ class _PingPageState extends State<PingPage>
|
|||||||
await doPing();
|
await doPing();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(e.toString()),
|
onPressed: () => copy2Clipboard(e.toString()),
|
||||||
child: Text(_s.copy),
|
child: Text(l10n.copy),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -111,7 +103,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
if (isInit) {
|
if (isInit) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.noResult,
|
l10n.noResult,
|
||||||
style: const TextStyle(fontSize: 18),
|
style: const TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -125,8 +117,8 @@ class _PingPageState extends State<PingPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildResultItem(PingResult result) {
|
Widget _buildResultItem(PingResult result) {
|
||||||
final unknown = _s.unknown;
|
final unknown = l10n.unknown;
|
||||||
final ms = _s.ms;
|
final ms = l10n.ms;
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||||
@@ -143,7 +135,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
style: UIs.textSize11,
|
style: UIs.textSize11,
|
||||||
),
|
),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
'${_s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? _s.unknown} $ms',
|
'${l10n.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? l10n.unknown} $ms',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
@@ -156,13 +148,13 @@ class _PingPageState extends State<PingPage>
|
|||||||
String _buildPingSummary(PingResult result, String unknown, String ms) {
|
String _buildPingSummary(PingResult result, String unknown, String ms) {
|
||||||
final ip = result.ip ?? unknown;
|
final ip = result.ip ?? unknown;
|
||||||
if (result.results == null || result.results!.isEmpty) {
|
if (result.results == null || result.results!.isEmpty) {
|
||||||
return '$ip - ${_s.noResult}';
|
return '$ip - ${l10n.noResult}';
|
||||||
}
|
}
|
||||||
final ttl = result.results?.first.ttl ?? unknown;
|
final ttl = result.results?.first.ttl ?? unknown;
|
||||||
final loss = result.statistic?.loss ?? unknown;
|
final loss = result.statistic?.loss ?? unknown;
|
||||||
final min = result.statistic?.min ?? unknown;
|
final min = result.statistic?.min ?? unknown;
|
||||||
final max = result.statistic?.max ?? unknown;
|
final max = result.statistic?.max ?? unknown;
|
||||||
return '$ip\n${_s.ttl}: $ttl, ${_s.loss}: $loss%\n${_s.min}: $min $ms, ${_s.max}: $max $ms';
|
return '$ip\n${l10n.ttl}: $ttl, ${l10n.loss}: $loss%\n${l10n.min}: $min $ms, ${l10n.max}: $max $ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> doPing() async {
|
Future<void> doPing() async {
|
||||||
@@ -170,18 +162,18 @@ class _PingPageState extends State<PingPage>
|
|||||||
_results.value.clear();
|
_results.value.clear();
|
||||||
final target = _textEditingController.text.trim();
|
final target = _textEditingController.text.trim();
|
||||||
if (target.isEmpty) {
|
if (target.isEmpty) {
|
||||||
context.showSnackBar(_s.pingInputIP);
|
context.showSnackBar(l10n.pingInputIP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Providers.server.servers.isEmpty) {
|
if (Providers.server.servers.isEmpty) {
|
||||||
context.showSnackBar(_s.pingNoServer);
|
context.showSnackBar(l10n.pingNoServer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// avoid ping command injection
|
/// avoid ping command injection
|
||||||
if (!targetReg.hasMatch(target)) {
|
if (!targetReg.hasMatch(target)) {
|
||||||
context.showSnackBar(_s.pingInputIP);
|
context.showSnackBar(l10n.pingInputIP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'dart:io';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/numx.dart';
|
import 'package:toolbox/core/extension/numx.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
@@ -38,7 +38,6 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
final _pwdNode = FocusNode();
|
final _pwdNode = FocusNode();
|
||||||
|
|
||||||
late FocusScopeNode _focusScope;
|
late FocusScopeNode _focusScope;
|
||||||
late S _s;
|
|
||||||
|
|
||||||
Widget? _loading;
|
Widget? _loading;
|
||||||
|
|
||||||
@@ -73,7 +72,6 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_focusScope = FocusScope.of(context);
|
_focusScope = FocusScope.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,11 +87,11 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
PreferredSizeWidget _buildAppBar() {
|
PreferredSizeWidget _buildAppBar() {
|
||||||
final actions = [
|
final actions = [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: _s.delete,
|
tooltip: l10n.delete,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(widget.pki!.id)),
|
child: Text(l10n.sureDelete(widget.pki!.id)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -102,7 +100,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.ok,
|
l10n.ok,
|
||||||
style: UIs.textRed,
|
style: UIs.textRed,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -113,20 +111,20 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
)
|
)
|
||||||
];
|
];
|
||||||
return CustomAppBar(
|
return CustomAppBar(
|
||||||
title: Text(_s.edit, style: UIs.textSize18),
|
title: Text(l10n.edit, style: UIs.textSize18),
|
||||||
actions: widget.pki == null ? null : actions,
|
actions: widget.pki == null ? null : actions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFAB() {
|
Widget _buildFAB() {
|
||||||
return FloatingActionButton(
|
return FloatingActionButton(
|
||||||
tooltip: _s.save,
|
tooltip: l10n.save,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final name = _nameController.text;
|
final name = _nameController.text;
|
||||||
final key = _keyController.text.trim();
|
final key = _keyController.text.trim();
|
||||||
final pwd = _pwdController.text;
|
final pwd = _pwdController.text;
|
||||||
if (name.isEmpty || key.isEmpty) {
|
if (name.isEmpty || key.isEmpty) {
|
||||||
context.showSnackBar(_s.fieldMustNotEmpty);
|
context.showSnackBar(l10n.fieldMustNotEmpty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
@@ -165,7 +163,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _nameNode,
|
node: _nameNode,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_keyNode),
|
onSubmitted: (_) => _focusScope.requestFocus(_keyNode),
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
icon: Icons.info,
|
icon: Icons.info,
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
@@ -175,26 +173,26 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _keyNode,
|
node: _keyNode,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_pwdNode),
|
onSubmitted: (_) => _focusScope.requestFocus(_pwdNode),
|
||||||
label: _s.privateKey,
|
label: l10n.privateKey,
|
||||||
icon: Icons.vpn_key,
|
icon: Icons.vpn_key,
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final path = await pickOneFile();
|
final path = await pickOneFile();
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
context.showSnackBar(_s.fieldMustNotEmpty);
|
context.showSnackBar(l10n.fieldMustNotEmpty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final file = File(path);
|
final file = File(path);
|
||||||
if (!file.existsSync()) {
|
if (!file.existsSync()) {
|
||||||
context.showSnackBar(_s.fileNotExist(path));
|
context.showSnackBar(l10n.fileNotExist(path));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final size = (await file.stat()).size;
|
final size = (await file.stat()).size;
|
||||||
if (size > Miscs.privateKeyMaxSize) {
|
if (size > Miscs.privateKeyMaxSize) {
|
||||||
context.showSnackBar(
|
context.showSnackBar(
|
||||||
_s.fileTooLarge(
|
l10n.fileTooLarge(
|
||||||
path,
|
path,
|
||||||
size.convertBytes,
|
size.convertBytes,
|
||||||
Miscs.privateKeyMaxSize.convertBytes,
|
Miscs.privateKeyMaxSize.convertBytes,
|
||||||
@@ -205,14 +203,14 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
|||||||
|
|
||||||
_keyController.text = await file.readAsString();
|
_keyController.text = await file.readAsString();
|
||||||
},
|
},
|
||||||
child: Text(_s.pickFile),
|
child: Text(l10n.pickFile),
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
controller: _pwdController,
|
controller: _pwdController,
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _pwdNode,
|
node: _pwdNode,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
label: _s.pwd,
|
label: l10n.pwd,
|
||||||
icon: Icons.password,
|
icon: Icons.password,
|
||||||
),
|
),
|
||||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import 'dart:io';
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/core/utils/platform/path.dart';
|
import 'package:toolbox/core/utils/platform/path.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -26,19 +26,11 @@ class PrivateKeysListPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _PrivateKeyListState extends State<PrivateKeysListPage>
|
class _PrivateKeyListState extends State<PrivateKeysListPage>
|
||||||
with AfterLayoutMixin {
|
with AfterLayoutMixin {
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.privateKey, style: UIs.textSize18),
|
title: Text(l10n.privateKey, style: UIs.textSize18),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
@@ -53,7 +45,7 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
|||||||
builder: (_, key, __) {
|
builder: (_, key, __) {
|
||||||
if (key.pkis.isEmpty) {
|
if (key.pkis.isEmpty) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(_s.noSavedPrivateKey),
|
child: Text(l10n.noSavedPrivateKey),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
@@ -71,7 +63,7 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(item.id),
|
title: Text(item.id),
|
||||||
subtitle: Text(item.type ?? _s.unknown, style: UIs.textGrey),
|
subtitle: Text(item.type ?? l10n.unknown, style: UIs.textGrey),
|
||||||
onTap: () => AppRoute.keyEdit(pki: item).go(context),
|
onTap: () => AppRoute.keyEdit(pki: item).go(context),
|
||||||
trailing: const Icon(Icons.edit),
|
trailing: const Icon(Icons.edit),
|
||||||
),
|
),
|
||||||
@@ -94,19 +86,19 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
|||||||
key: idRsaFile.readAsStringSync(),
|
key: idRsaFile.readAsStringSync(),
|
||||||
);
|
);
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.addSystemPrivateKeyTip),
|
child: Text(l10n.addSystemPrivateKeyTip),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
AppRoute.keyEdit(pki: sysPk).go(context);
|
AppRoute.keyEdit(pki: sysPk).go(context);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:dartssh2/dartssh2.dart';
|
import 'package:dartssh2/dartssh2.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
@@ -28,7 +28,6 @@ class ProcessPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProcessPageState extends State<ProcessPage> {
|
class _ProcessPageState extends State<ProcessPage> {
|
||||||
late S _s;
|
|
||||||
late Timer _timer;
|
late Timer _timer;
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
|
|
||||||
@@ -55,7 +54,6 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +61,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
if (mounted) {
|
if (mounted) {
|
||||||
final result = await _client?.run(AppShellFuncType.process.exec).string;
|
final result = await _client?.run(AppShellFuncType.process.exec).string;
|
||||||
if (result == null || result.isEmpty) {
|
if (result == null || result.isEmpty) {
|
||||||
context.showSnackBar(_s.noResult);
|
context.showSnackBar(l10n.noResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_result = PsResult.parse(result, sort: _procSortMode);
|
_result = PsResult.parse(result, sort: _procSortMode);
|
||||||
@@ -110,12 +108,12 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
actions.add(IconButton(
|
actions.add(IconButton(
|
||||||
icon: const Icon(Icons.error),
|
icon: const Icon(Icons.error),
|
||||||
onPressed: () => context.showRoundDialog(
|
onPressed: () => context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: SingleChildScrollView(child: Text(_result.error!)),
|
child: SingleChildScrollView(child: Text(_result.error!)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(_result.error!),
|
onPressed: () => copy2Clipboard(_result.error!),
|
||||||
child: Text(_s.copy),
|
child: Text(l10n.copy),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -134,7 +132,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: TwoLineText(up: widget.spi.name, down: _s.process),
|
title: TwoLineText(up: widget.spi.name, down: l10n.process),
|
||||||
actions: actions,
|
actions: actions,
|
||||||
),
|
),
|
||||||
body: child,
|
body: child,
|
||||||
@@ -162,8 +160,8 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
onTap: () => _lastFocusId = proc.pid,
|
onTap: () => _lastFocusId = proc.pid,
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureStop(proc.pid)),
|
child: Text(l10n.sureStop(proc.pid)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -171,7 +169,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
|||||||
await _refresh();
|
await _refresh();
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
import 'package:toolbox/data/model/server/cpu.dart';
|
import 'package:toolbox/data/model/server/cpu.dart';
|
||||||
import 'package:toolbox/data/model/server/net_speed.dart';
|
import 'package:toolbox/data/model/server/net_speed.dart';
|
||||||
@@ -34,7 +34,6 @@ class ServerDetailPage extends StatefulWidget {
|
|||||||
class _ServerDetailPageState extends State<ServerDetailPage>
|
class _ServerDetailPageState extends State<ServerDetailPage>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late S _s;
|
|
||||||
final Order<String> _cardsOrder = [];
|
final Order<String> _cardsOrder = [];
|
||||||
|
|
||||||
late final _textFactor = Stores.setting.textFactor.fetch();
|
late final _textFactor = Stores.setting.textFactor.fetch();
|
||||||
@@ -58,7 +57,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -74,7 +72,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
if (s == null) {
|
if (s == null) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Text(_s.noClient),
|
child: Text(l10n.noClient),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -108,7 +106,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
itemCount: buildFuncs ? _cardsOrder.length + 1 : _cardsOrder.length,
|
itemCount: buildFuncs ? _cardsOrder.length + 1 : _cardsOrder.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index == 0 && buildFuncs) {
|
if (index == 0 && buildFuncs) {
|
||||||
return ServerFuncBtns(spi: widget.spi, s: _s, iconSize: 19);
|
return ServerFuncBtns(spi: widget.spi, iconSize: 19);
|
||||||
}
|
}
|
||||||
if (buildFuncs) index--;
|
if (buildFuncs) index--;
|
||||||
return _cardBuildMap[_cardsOrder[index]]?.call(si.status);
|
return _cardBuildMap[_cardsOrder[index]]?.call(si.status);
|
||||||
@@ -369,7 +367,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
if (ns.devices.isEmpty) {
|
if (ns.devices.isEmpty) {
|
||||||
children.add(Center(
|
children.add(Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.noInterface,
|
l10n.noInterface,
|
||||||
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
|
|
||||||
@@ -40,7 +40,6 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
final _usernameFocus = FocusNode();
|
final _usernameFocus = FocusNode();
|
||||||
|
|
||||||
late FocusScopeNode _focusScope;
|
late FocusScopeNode _focusScope;
|
||||||
late S _s;
|
|
||||||
|
|
||||||
final _keyIdx = ValueNotifier<int?>(null);
|
final _keyIdx = ValueNotifier<int?>(null);
|
||||||
final _autoConnect = ValueNotifier(true);
|
final _autoConnect = ValueNotifier(true);
|
||||||
@@ -95,7 +94,6 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_focusScope = FocusScope.of(context);
|
_focusScope = FocusScope.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +110,8 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
final delBtn = IconButton(
|
final delBtn = IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureToDeleteServer(widget.spi!.name)),
|
child: Text(l10n.sureToDeleteServer(widget.spi!.name)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -121,7 +119,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
context.pop(true);
|
context.pop(true);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok, style: UIs.textRed),
|
child: Text(l10n.ok, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -130,7 +128,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
);
|
);
|
||||||
final actions = widget.spi != null ? [delBtn] : null;
|
final actions = widget.spi != null ? [delBtn] : null;
|
||||||
return CustomAppBar(
|
return CustomAppBar(
|
||||||
title: Text(_s.edit, style: UIs.textSize18),
|
title: Text(l10n.edit, style: UIs.textSize18),
|
||||||
actions: actions,
|
actions: actions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -143,8 +141,8 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _nameFocus,
|
node: _nameFocus,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_ipFocus),
|
onSubmitted: (_) => _focusScope.requestFocus(_ipFocus),
|
||||||
hint: _s.exampleName,
|
hint: l10n.exampleName,
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
icon: Icons.info,
|
icon: Icons.info,
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
@@ -152,7 +150,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_portFocus),
|
onSubmitted: (_) => _focusScope.requestFocus(_portFocus),
|
||||||
node: _ipFocus,
|
node: _ipFocus,
|
||||||
label: _s.host,
|
label: l10n.host,
|
||||||
icon: Icons.computer,
|
icon: Icons.computer,
|
||||||
hint: 'example.com',
|
hint: 'example.com',
|
||||||
),
|
),
|
||||||
@@ -161,7 +159,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
type: TextInputType.number,
|
type: TextInputType.number,
|
||||||
node: _portFocus,
|
node: _portFocus,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus),
|
onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus),
|
||||||
label: _s.port,
|
label: l10n.port,
|
||||||
icon: Icons.format_list_numbered,
|
icon: Icons.format_list_numbered,
|
||||||
hint: '22',
|
hint: '22',
|
||||||
),
|
),
|
||||||
@@ -170,7 +168,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _usernameFocus,
|
node: _usernameFocus,
|
||||||
onSubmitted: (_) => _focusScope.requestFocus(_alterUrlFocus),
|
onSubmitted: (_) => _focusScope.requestFocus(_alterUrlFocus),
|
||||||
label: _s.user,
|
label: l10n.user,
|
||||||
icon: Icons.account_box,
|
icon: Icons.account_box,
|
||||||
hint: 'root',
|
hint: 'root',
|
||||||
),
|
),
|
||||||
@@ -178,20 +176,19 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
controller: _altUrlController,
|
controller: _altUrlController,
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
node: _alterUrlFocus,
|
node: _alterUrlFocus,
|
||||||
label: _s.alterUrl,
|
label: l10n.alterUrl,
|
||||||
icon: Icons.computer,
|
icon: Icons.computer,
|
||||||
hint: 'user@ip:port',
|
hint: 'user@ip:port',
|
||||||
),
|
),
|
||||||
TagEditor(
|
TagEditor(
|
||||||
tags: _tags,
|
tags: _tags,
|
||||||
onChanged: (p0) => _tags = p0,
|
onChanged: (p0) => _tags = p0,
|
||||||
s: _s,
|
|
||||||
allTags: [...Providers.server.tags],
|
allTags: [...Providers.server.tags],
|
||||||
onRenameTag: Providers.server.renameTag,
|
onRenameTag: Providers.server.renameTag,
|
||||||
),
|
),
|
||||||
_buildAuth(),
|
_buildAuth(),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.autoConnect),
|
title: Text(l10n.autoConnect),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _autoConnect,
|
listenable: _autoConnect,
|
||||||
build: () => Switch(
|
build: () => Switch(
|
||||||
@@ -215,7 +212,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
|
|
||||||
Widget _buildAuth() {
|
Widget _buildAuth() {
|
||||||
final switch_ = ListTile(
|
final switch_ = ListTile(
|
||||||
title: Text(_s.keyAuth),
|
title: Text(l10n.keyAuth),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _keyIdx,
|
listenable: _keyIdx,
|
||||||
build: () => Switch(
|
build: () => Switch(
|
||||||
@@ -243,9 +240,9 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
controller: _passwordController,
|
controller: _passwordController,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
label: _s.pwd,
|
label: l10n.pwd,
|
||||||
icon: Icons.password,
|
icon: Icons.password,
|
||||||
hint: _s.pwd,
|
hint: l10n.pwd,
|
||||||
onSubmitted: (_) => _onSave(),
|
onSubmitted: (_) => _onSave(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -267,7 +264,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
),
|
),
|
||||||
title: Text(e.id, textAlign: TextAlign.start),
|
title: Text(e.id, textAlign: TextAlign.start),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
e.type ?? _s.unknown,
|
e.type ?? l10n.unknown,
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
style: UIs.textGrey,
|
style: UIs.textGrey,
|
||||||
),
|
),
|
||||||
@@ -276,7 +273,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
});
|
});
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.addPrivateKey),
|
title: Text(l10n.addPrivateKey),
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
@@ -319,21 +316,21 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
|
|
||||||
void _onSave() async {
|
void _onSave() async {
|
||||||
if (_ipController.text == '') {
|
if (_ipController.text == '') {
|
||||||
context.showSnackBar(_s.plzEnterHost);
|
context.showSnackBar(l10n.plzEnterHost);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_keyIdx.value == null && _passwordController.text == '') {
|
if (_keyIdx.value == null && _passwordController.text == '') {
|
||||||
final cancel = await context.showRoundDialog<bool>(
|
final cancel = await context.showRoundDialog<bool>(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureNoPwd),
|
child: Text(l10n.sureNoPwd),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(false),
|
onPressed: () => context.pop(false),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(true),
|
onPressed: () => context.pop(true),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -343,7 +340,7 @@ class _ServerEditPageState extends State<ServerEditPage> {
|
|||||||
}
|
}
|
||||||
// If [_pubKeyIndex] is -1, it means that the user has not selected
|
// If [_pubKeyIndex] is -1, it means that the user has not selected
|
||||||
if (_keyIdx.value == -1) {
|
if (_keyIdx.value == -1) {
|
||||||
context.showSnackBar(_s.plzSelectKey);
|
context.showSnackBar(l10n.plzSelectKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_usernameController.text.isEmpty) {
|
if (_usernameController.text.isEmpty) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:circle_chart/circle_chart.dart';
|
import 'package:circle_chart/circle_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/media_queryx.dart';
|
import 'package:toolbox/core/extension/media_queryx.dart';
|
||||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
@@ -36,7 +36,6 @@ class ServerPage extends StatefulWidget {
|
|||||||
class _ServerPageState extends State<ServerPage>
|
class _ServerPageState extends State<ServerPage>
|
||||||
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late S _s;
|
|
||||||
|
|
||||||
final _flipedCardIds = <String>{};
|
final _flipedCardIds = <String>{};
|
||||||
|
|
||||||
@@ -48,7 +47,6 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_useDoubleColumn = _media.useDoubleColumn;
|
_useDoubleColumn = _media.useDoubleColumn;
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -58,7 +56,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () => AppRoute.serverEdit().go(context),
|
onPressed: () => AppRoute.serverEdit().go(context),
|
||||||
tooltip: _s.addAServer,
|
tooltip: l10n.addAServer,
|
||||||
heroTag: 'server',
|
heroTag: 'server',
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
),
|
),
|
||||||
@@ -74,7 +72,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
if (pro.serverOrder.isEmpty) {
|
if (pro.serverOrder.isEmpty) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.serverTabEmpty,
|
l10n.serverTabEmpty,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -108,7 +106,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
_tag = p0;
|
_tag = p0;
|
||||||
}),
|
}),
|
||||||
initTag: _tag,
|
initTag: _tag,
|
||||||
all: _s.all,
|
all: l10n.all,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +292,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
!Stores.setting.serverTabUseOldUI.fetch())
|
!Stores.setting.serverTabUseOldUI.fetch())
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 27,
|
height: 27,
|
||||||
child: ServerFuncBtns(spi: spi, s: _s),
|
child: ServerFuncBtns(spi: spi),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -318,7 +316,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (Stores.setting.serverTabUseOldUI.fetch()) {
|
} else if (Stores.setting.serverTabUseOldUI.fetch()) {
|
||||||
rightCorner = ServerFuncBtnsTopRight(spi: spi, s: _s);
|
rightCorner = ServerFuncBtnsTopRight(spi: spi);
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||||
@@ -361,7 +359,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => _showFailReason(ss),
|
onTap: () => _showFailReason(ss),
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.viewErr,
|
l10n.viewErr,
|
||||||
style: UIs.textSize11Grey,
|
style: UIs.textSize11Grey,
|
||||||
textScaleFactor: 1.0,
|
textScaleFactor: 1.0,
|
||||||
),
|
),
|
||||||
@@ -376,14 +374,14 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
|
|
||||||
void _showFailReason(ServerStatus ss) {
|
void _showFailReason(ServerStatus ss) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Text(ss.failedInfo ?? _s.unknownError),
|
child: Text(ss.failedInfo ?? l10n.unknownError),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(ss.failedInfo!),
|
onPressed: () => copy2Clipboard(ss.failedInfo!),
|
||||||
child: Text(_s.copy),
|
child: Text(l10n.copy),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -478,25 +476,25 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
) {
|
) {
|
||||||
switch (cs) {
|
switch (cs) {
|
||||||
case ServerState.disconnected:
|
case ServerState.disconnected:
|
||||||
return _s.disconnected;
|
return l10n.disconnected;
|
||||||
case ServerState.finished:
|
case ServerState.finished:
|
||||||
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
||||||
final items = [tempStr, upTime];
|
final items = [tempStr, upTime];
|
||||||
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
||||||
if (str.isEmpty) return _s.noResult;
|
if (str.isEmpty) return l10n.noResult;
|
||||||
return str;
|
return str;
|
||||||
case ServerState.loading:
|
case ServerState.loading:
|
||||||
return _s.serverTabLoading;
|
return l10n.serverTabLoading;
|
||||||
case ServerState.connected:
|
case ServerState.connected:
|
||||||
return _s.connected;
|
return l10n.connected;
|
||||||
case ServerState.connecting:
|
case ServerState.connecting:
|
||||||
return _s.serverTabConnecting;
|
return l10n.serverTabConnecting;
|
||||||
case ServerState.failed:
|
case ServerState.failed:
|
||||||
if (failedInfo == null) {
|
if (failedInfo == null) {
|
||||||
return _s.serverTabFailed;
|
return l10n.serverTabFailed;
|
||||||
}
|
}
|
||||||
if (failedInfo.contains('encypted')) {
|
if (failedInfo.contains('encypted')) {
|
||||||
return _s.serverTabPlzSave;
|
return l10n.serverTabPlzSave;
|
||||||
}
|
}
|
||||||
return failedInfo;
|
return failedInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
import 'package:toolbox/view/widget/custom_appbar.dart';
|
import 'package:toolbox/view/widget/custom_appbar.dart';
|
||||||
@@ -20,15 +20,8 @@ class AndroidSettingsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
||||||
late S _s;
|
|
||||||
late SharedPreferences _sp;
|
late SharedPreferences _sp;
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -53,7 +46,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
|||||||
|
|
||||||
Widget _buildBgRun() {
|
Widget _buildBgRun() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.bgRun),
|
title: Text(l10n.bgRun),
|
||||||
trailing: StoreSwitch(prop: Stores.setting.bgRun),
|
trailing: StoreSwitch(prop: Stores.setting.bgRun),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -69,7 +62,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
|||||||
map.forEach((key, value) {
|
map.forEach((key, value) {
|
||||||
_sp.setString(key, value);
|
_sp.setString(key, value);
|
||||||
});
|
});
|
||||||
context.showSnackBar(_s.success);
|
context.showSnackBar(l10n.success);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showSnackBar(e.toString());
|
context.showSnackBar(e.toString());
|
||||||
}
|
}
|
||||||
@@ -77,7 +70,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
|||||||
|
|
||||||
Widget _buildAndroidWidgetSharedPreference() {
|
Widget _buildAndroidWidgetSharedPreference() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.homeWidgetUrlConfig),
|
title: Text(l10n.homeWidgetUrlConfig),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
final data = <String, String>{};
|
final data = <String, String>{};
|
||||||
@@ -89,7 +82,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
|||||||
});
|
});
|
||||||
final ctrl = TextEditingController(text: json.encode(data));
|
final ctrl = TextEditingController(text: json.encode(data));
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.homeWidgetUrlConfig),
|
title: Text(l10n.homeWidgetUrlConfig),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
controller: ctrl,
|
controller: ctrl,
|
||||||
@@ -103,7 +96,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
_saveWidgetSP(ctrl.text, data);
|
_saveWidgetSP(ctrl.text, data);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:flutter_highlight/theme_map.dart';
|
import 'package:flutter_highlight/theme_map.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/colorx.dart';
|
import 'package:toolbox/core/extension/colorx.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/locale.dart';
|
import 'package:toolbox/core/extension/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
@@ -53,8 +54,6 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
final _netViewTypeKey = GlobalKey<PopupMenuButtonState<NetViewType>>();
|
final _netViewTypeKey = GlobalKey<PopupMenuButtonState<NetViewType>>();
|
||||||
final _setting = Stores.setting;
|
final _setting = Stores.setting;
|
||||||
|
|
||||||
late S _s;
|
|
||||||
|
|
||||||
final _selectedColorValue = ValueNotifier(0);
|
final _selectedColorValue = ValueNotifier(0);
|
||||||
final _nightMode = ValueNotifier(0);
|
final _nightMode = ValueNotifier(0);
|
||||||
final _maxRetryCount = ValueNotifier(0);
|
final _maxRetryCount = ValueNotifier(0);
|
||||||
@@ -71,10 +70,9 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
final localeSettingVal = _setting.locale.fetch();
|
final localeSettingVal = _setting.locale.fetch();
|
||||||
if (localeSettingVal.isEmpty) {
|
if (localeSettingVal.isEmpty) {
|
||||||
_localeCode.value = _s.localeName;
|
_localeCode.value = l10n.localeName;
|
||||||
} else {
|
} else {
|
||||||
_localeCode.value = localeSettingVal;
|
_localeCode.value = localeSettingVal;
|
||||||
}
|
}
|
||||||
@@ -100,26 +98,27 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.setting),
|
title: Text(l10n.setting),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.showRoundDialog(
|
onPressed: () => context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(_s.all)),
|
child: Text(l10n.sureDelete(l10n.all)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_setting.box.deleteAll(_setting.box.keys);
|
_setting.box.deleteAll(_setting.box.keys);
|
||||||
context.pop();
|
context.pop();
|
||||||
context.showSnackBar(_s.success);
|
context.showSnackBar(l10n.success);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok, style: const TextStyle(color: Colors.red)),
|
child:
|
||||||
|
Text(l10n.ok, style: const TextStyle(color: Colors.red)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// onDoubleTap: () => context.showRoundDialog(
|
// onDoubleTap: () => context.showRoundDialog(
|
||||||
// title: Text(_s.attention),
|
// title: Text(l10n.attention),
|
||||||
// child: Text(_s.sureDelete(_s.all)),
|
// child: Text(l10n.sureDelete(l10n.all)),
|
||||||
// actions: [
|
// actions: [
|
||||||
// TextButton(
|
// TextButton(
|
||||||
// onPressed: () {
|
// onPressed: () {
|
||||||
@@ -130,9 +129,9 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
// Stores.snippet.box.deleteFromDisk();
|
// Stores.snippet.box.deleteFromDisk();
|
||||||
// Stores.key.box.deleteFromDisk();
|
// Stores.key.box.deleteFromDisk();
|
||||||
// context.pop();
|
// context.pop();
|
||||||
// context.showSnackBar(_s.success);
|
// context.showSnackBar(l10n.success);
|
||||||
// },
|
// },
|
||||||
// child: Text(_s.ok, style: const TextStyle(color: Colors.red)),
|
// child: Text(l10n.ok, style: const TextStyle(color: Colors.red)),
|
||||||
// ),
|
// ),
|
||||||
// ],
|
// ],
|
||||||
// ),
|
// ),
|
||||||
@@ -145,13 +144,13 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
children: [
|
children: [
|
||||||
_buildTitle('App'),
|
_buildTitle('App'),
|
||||||
_buildApp(),
|
_buildApp(),
|
||||||
_buildTitle(_s.server),
|
_buildTitle(l10n.server),
|
||||||
_buildServer(),
|
_buildServer(),
|
||||||
_buildTitle('SSH'),
|
_buildTitle('SSH'),
|
||||||
_buildSSH(),
|
_buildSSH(),
|
||||||
_buildTitle(_s.editor),
|
_buildTitle(l10n.editor),
|
||||||
_buildEditor(),
|
_buildEditor(),
|
||||||
_buildTitle(_s.fullScreen),
|
_buildTitle(l10n.fullScreen),
|
||||||
_buildFullScreen(),
|
_buildFullScreen(),
|
||||||
const SizedBox(height: 37),
|
const SizedBox(height: 37),
|
||||||
],
|
],
|
||||||
@@ -247,15 +246,15 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
String display;
|
String display;
|
||||||
if (app.newestBuild != null) {
|
if (app.newestBuild != null) {
|
||||||
if (app.newestBuild! > BuildData.build) {
|
if (app.newestBuild! > BuildData.build) {
|
||||||
display = _s.versionHaveUpdate(app.newestBuild!);
|
display = l10n.versionHaveUpdate(app.newestBuild!);
|
||||||
} else {
|
} else {
|
||||||
display = _s.versionUpdated(BuildData.build);
|
display = l10n.versionUpdated(BuildData.build);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
display = _s.versionUnknownUpdate(BuildData.build);
|
display = l10n.versionUnknownUpdate(BuildData.build);
|
||||||
}
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.autoCheckUpdate),
|
title: Text(l10n.autoCheckUpdate),
|
||||||
subtitle: Text(display, style: UIs.textGrey),
|
subtitle: Text(display, style: UIs.textGrey),
|
||||||
onTap: () => doUpdate(ctx, force: true),
|
onTap: () => doUpdate(ctx, force: true),
|
||||||
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
|
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
|
||||||
@@ -269,17 +268,17 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
10,
|
10,
|
||||||
(index) => PopupMenuItem(
|
(index) => PopupMenuItem(
|
||||||
value: index,
|
value: index,
|
||||||
child: Text('$index ${_s.second}'),
|
child: Text('$index ${l10n.second}'),
|
||||||
),
|
),
|
||||||
growable: false,
|
growable: false,
|
||||||
).toList();
|
).toList();
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.updateServerStatusInterval,
|
l10n.updateServerStatusInterval,
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
_s.willTakEeffectImmediately,
|
l10n.willTakEeffectImmediately,
|
||||||
style: UIs.textGrey,
|
style: UIs.textGrey,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -296,11 +295,11 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_setting.serverStatusUpdateInterval.put(val);
|
_setting.serverStatusUpdateInterval.put(val);
|
||||||
Providers.server.startAutoRefresh();
|
Providers.server.startAutoRefresh();
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
context.showSnackBar(_s.updateIntervalEqual0);
|
context.showSnackBar(l10n.updateIntervalEqual0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'${_updateInterval.value} ${_s.second}',
|
'${_updateInterval.value} ${l10n.second}',
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -317,17 +316,17 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
width: 27,
|
width: 27,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(_s.primaryColorSeed),
|
title: Text(l10n.primaryColorSeed),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final ctrl = TextEditingController(text: primaryColor.toHex);
|
final ctrl = TextEditingController(text: primaryColor.toHex);
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.primaryColorSeed),
|
title: Text(l10n.primaryColorSeed),
|
||||||
child: StatefulBuilder(builder: (context, setState) {
|
child: StatefulBuilder(builder: (context, setState) {
|
||||||
final children = <Widget>[
|
final children = <Widget>[
|
||||||
/// Plugin [dynamic_color] is not supported on iOS
|
/// Plugin [dynamic_color] is not supported on iOS
|
||||||
if (!isIOS)
|
if (!isIOS)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.followSystem),
|
title: Text(l10n.followSystem),
|
||||||
trailing: StoreSwitch(
|
trailing: StoreSwitch(
|
||||||
prop: _setting.useSystemPrimaryColor,
|
prop: _setting.useSystemPrimaryColor,
|
||||||
func: (_) => setState(() {}),
|
func: (_) => setState(() {}),
|
||||||
@@ -356,7 +355,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _onSaveColor(ctrl.text),
|
onPressed: () => _onSaveColor(ctrl.text),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@@ -366,7 +365,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
void _onSaveColor(String s) {
|
void _onSaveColor(String s) {
|
||||||
final color = s.hexToColor;
|
final color = s.hexToColor;
|
||||||
if (color == null) {
|
if (color == null) {
|
||||||
context.showSnackBar(_s.failed);
|
context.showSnackBar(l10n.failed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_selectedColorValue.value = color.value;
|
_selectedColorValue.value = color.value;
|
||||||
@@ -388,7 +387,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
// return ListTile(
|
// return ListTile(
|
||||||
// title: Text(
|
// title: Text(
|
||||||
// _s.launchPage,
|
// l10n.launchPage,
|
||||||
// ),
|
// ),
|
||||||
// onTap: () {
|
// onTap: () {
|
||||||
// _startPageKey.currentState?.showButtonMenu();
|
// _startPageKey.currentState?.showButtonMenu();
|
||||||
@@ -421,16 +420,17 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
10,
|
10,
|
||||||
(index) => PopupMenuItem(
|
(index) => PopupMenuItem(
|
||||||
value: index,
|
value: index,
|
||||||
child: Text('$index ${_s.times}'),
|
child: Text('$index ${l10n.times}'),
|
||||||
),
|
),
|
||||||
growable: false,
|
growable: false,
|
||||||
).toList();
|
).toList();
|
||||||
final help =
|
final help = _maxRetryCount.value == 0
|
||||||
_maxRetryCount.value == 0 ? _s.maxRetryCountEqual0 : _s.canPullRefresh;
|
? l10n.maxRetryCountEqual0
|
||||||
|
: l10n.canPullRefresh;
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.maxRetryCount,
|
l10n.maxRetryCount,
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
),
|
),
|
||||||
subtitle: Text(help, style: UIs.textGrey),
|
subtitle: Text(help, style: UIs.textGrey),
|
||||||
@@ -447,7 +447,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_setting.maxRetryCount.put(_maxRetryCount.value);
|
_setting.maxRetryCount.put(_maxRetryCount.value);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'${_maxRetryCount.value} ${_s.times}',
|
'${_maxRetryCount.value} ${l10n.times}',
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -471,7 +471,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.themeMode,
|
l10n.themeMode,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_themeKey.currentState?.showButtonMenu();
|
_themeKey.currentState?.showButtonMenu();
|
||||||
@@ -486,7 +486,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_nightMode.value = idx;
|
_nightMode.value = idx;
|
||||||
_setting.themeMode.put(_nightMode.value);
|
_setting.themeMode.put(_nightMode.value);
|
||||||
|
|
||||||
RebuildNodes.app.rebuild();
|
RebuildNodes.app.rebuild();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
_buildThemeModeStr(_nightMode.value),
|
_buildThemeModeStr(_nightMode.value),
|
||||||
@@ -500,39 +500,39 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
String _buildThemeModeStr(int n) {
|
String _buildThemeModeStr(int n) {
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
return _s.light;
|
return l10n.light;
|
||||||
case 2:
|
case 2:
|
||||||
return _s.dark;
|
return l10n.dark;
|
||||||
case 3:
|
case 3:
|
||||||
return 'AMOLED';
|
return 'AMOLED';
|
||||||
default:
|
default:
|
||||||
return _s.auto;
|
return l10n.auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFont() {
|
Widget _buildFont() {
|
||||||
final fontName = getFileName(_setting.fontPath.fetch());
|
final fontName = getFileName(_setting.fontPath.fetch());
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.font),
|
title: Text(l10n.font),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
fontName ?? _s.notSelected,
|
fontName ?? l10n.notSelected,
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.font),
|
title: Text(l10n.font),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async => await _pickFontFile(),
|
onPressed: () async => await _pickFontFile(),
|
||||||
child: Text(_s.pickFile),
|
child: Text(l10n.pickFile),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_setting.fontPath.delete();
|
_setting.fontPath.delete();
|
||||||
context.pop();
|
context.pop();
|
||||||
RebuildNodes.app.rebuild();
|
RebuildNodes.app.rebuild();
|
||||||
},
|
},
|
||||||
child: Text(_s.clear),
|
child: Text(l10n.clear),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -554,17 +554,17 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.pop();
|
context.pop();
|
||||||
RebuildNodes.app.rebuild();
|
RebuildNodes.app.rebuild();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.showSnackBar(_s.failed);
|
context.showSnackBar(l10n.failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTermFontSize() {
|
Widget _buildTermFontSize() {
|
||||||
return ValueBuilder(
|
return ValueBuilder(
|
||||||
listenable: _termFontSize,
|
listenable: _termFontSize,
|
||||||
build: () => ListTile(
|
build: () => ListTile(
|
||||||
title: Text(_s.fontSize),
|
title: Text(l10n.fontSize),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
_termFontSize.value.toString(),
|
_termFontSize.value.toString(),
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
@@ -577,8 +577,8 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
// Widget _buildDiskIgnorePath() {
|
// Widget _buildDiskIgnorePath() {
|
||||||
// final paths = _setting.diskIgnorePath.fetch();
|
// final paths = _setting.diskIgnorePath.fetch();
|
||||||
// return ListTile(
|
// return ListTile(
|
||||||
// title: Text(_s.diskIgnorePath),
|
// title: Text(l10n.diskIgnorePath),
|
||||||
// trailing: Text(_s.edit, style: textSize15),
|
// trailing: Text(l10n.edit, style: textSize15),
|
||||||
// onTap: () {
|
// onTap: () {
|
||||||
// final ctrller = TextEditingController(text: json.encode(paths));
|
// final ctrller = TextEditingController(text: json.encode(paths));
|
||||||
// void onSubmit() {
|
// void onSubmit() {
|
||||||
@@ -586,7 +586,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
// final list = List<String>.from(json.decode(ctrller.text));
|
// final list = List<String>.from(json.decode(ctrller.text));
|
||||||
// _setting.diskIgnorePath.put(list);
|
// _setting.diskIgnorePath.put(list);
|
||||||
// context.pop();
|
// context.pop();
|
||||||
// showSnackBar(context, Text(_s.success));
|
// showSnackBar(context, Text(l10n.success));
|
||||||
// } catch (e) {
|
// } catch (e) {
|
||||||
// showSnackBar(context, Text(e.toString()));
|
// showSnackBar(context, Text(e.toString()));
|
||||||
// }
|
// }
|
||||||
@@ -594,7 +594,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
// showRoundDialog(
|
// showRoundDialog(
|
||||||
// context: context,
|
// context: context,
|
||||||
// title: Text(_s.diskIgnorePath),
|
// title: Text(l10n.diskIgnorePath),
|
||||||
// child: Input(
|
// child: Input(
|
||||||
// autoFocus: true,
|
// autoFocus: true,
|
||||||
// controller: ctrller,
|
// controller: ctrller,
|
||||||
@@ -604,7 +604,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
// onSubmitted: (_) => onSubmit(),
|
// onSubmitted: (_) => onSubmit(),
|
||||||
// ),
|
// ),
|
||||||
// actions: [
|
// actions: [
|
||||||
// TextButton(onPressed: onSubmit, child: Text(_s.ok)),
|
// TextButton(onPressed: onSubmit, child: Text(l10n.ok)),
|
||||||
// ],
|
// ],
|
||||||
// );
|
// );
|
||||||
// },
|
// },
|
||||||
@@ -621,7 +621,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.language),
|
title: Text(l10n.language),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_localeKey.currentState?.showButtonMenu();
|
_localeKey.currentState?.showButtonMenu();
|
||||||
},
|
},
|
||||||
@@ -634,10 +634,10 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
onSelected: (String idx) {
|
onSelected: (String idx) {
|
||||||
_localeCode.value = idx;
|
_localeCode.value = idx;
|
||||||
_setting.locale.put(idx);
|
_setting.locale.put(idx);
|
||||||
RebuildNodes.app.rebuild();
|
RebuildNodes.app.rebuild();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.languageName,
|
l10n.languageName,
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -647,7 +647,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildSSHVirtualKeyAutoOff() {
|
Widget _buildSSHVirtualKeyAutoOff() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.sshVirtualKeyAutoOff),
|
title: Text(l10n.sshVirtualKeyAutoOff),
|
||||||
subtitle: const Text('Ctrl & Alt', style: UIs.textGrey),
|
subtitle: const Text('Ctrl & Alt', style: UIs.textGrey),
|
||||||
trailing: StoreSwitch(prop: _setting.sshVirtualKeyAutoOff),
|
trailing: StoreSwitch(prop: _setting.sshVirtualKeyAutoOff),
|
||||||
);
|
);
|
||||||
@@ -663,7 +663,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${_s.light} ${_s.theme.toLowerCase()}'),
|
title: Text('${l10n.light} ${l10n.theme.toLowerCase()}'),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _editorTheme,
|
listenable: _editorTheme,
|
||||||
build: () => PopupMenuButton(
|
build: () => PopupMenuButton(
|
||||||
@@ -696,7 +696,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${_s.dark} ${_s.theme.toLowerCase()}'),
|
title: Text('${l10n.dark} ${l10n.theme.toLowerCase()}'),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _editorDarkTheme,
|
listenable: _editorDarkTheme,
|
||||||
build: () => PopupMenuButton(
|
build: () => PopupMenuButton(
|
||||||
@@ -721,19 +721,18 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildFullScreenSwitch() {
|
Widget _buildFullScreenSwitch() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.fullScreen),
|
title: Text(l10n.fullScreen),
|
||||||
trailing: StoreSwitch(
|
trailing: StoreSwitch(
|
||||||
prop: _setting.fullScreen,
|
prop: _setting.fullScreen,
|
||||||
func: (_) =>
|
func: (_) => RebuildNodes.app.rebuild(),
|
||||||
RebuildNodes.app.rebuild(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFullScreenJitter() {
|
Widget _buildFullScreenJitter() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.fullScreenJitter),
|
title: Text(l10n.fullScreenJitter),
|
||||||
subtitle: Text(_s.fullScreenJitterHelp, style: UIs.textGrey),
|
subtitle: Text(l10n.fullScreenJitterHelp, style: UIs.textGrey),
|
||||||
trailing: StoreSwitch(prop: _setting.fullScreenJitter),
|
trailing: StoreSwitch(prop: _setting.fullScreenJitter),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -748,7 +747,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.rotateAngel),
|
title: Text(l10n.rotateAngel),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_rotateQuarterKey.currentState?.showButtonMenu();
|
_rotateQuarterKey.currentState?.showButtonMenu();
|
||||||
},
|
},
|
||||||
@@ -798,8 +797,8 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.keyboardType),
|
title: Text(l10n.keyboardType),
|
||||||
subtitle: Text(_s.keyboardCompatibility, style: UIs.textGrey),
|
subtitle: Text(l10n.keyboardCompatibility, style: UIs.textGrey),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _keyboardType,
|
listenable: _keyboardType,
|
||||||
build: () => PopupMenuButton<int>(
|
build: () => PopupMenuButton<int>(
|
||||||
@@ -824,7 +823,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildSSHVirtKeys() {
|
Widget _buildSSHVirtKeys() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.editVirtKeys),
|
title: Text(l10n.editVirtKeys),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () => AppRoute.sshVirtKeySetting().go(context),
|
onTap: () => AppRoute.sshVirtKeySetting().go(context),
|
||||||
);
|
);
|
||||||
@@ -834,11 +833,11 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
final items = NetViewType.values
|
final items = NetViewType.values
|
||||||
.map((e) => PopupMenuItem(
|
.map((e) => PopupMenuItem(
|
||||||
value: e,
|
value: e,
|
||||||
child: Text(e.l10n(_s)),
|
child: Text(e.toStr),
|
||||||
))
|
))
|
||||||
.toList();
|
.toList();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.netViewType),
|
title: Text(l10n.netViewType),
|
||||||
trailing: ValueBuilder(
|
trailing: ValueBuilder(
|
||||||
listenable: _netViewType,
|
listenable: _netViewType,
|
||||||
build: () => PopupMenuButton<NetViewType>(
|
build: () => PopupMenuButton<NetViewType>(
|
||||||
@@ -850,7 +849,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_setting.netViewType.put(idx);
|
_setting.netViewType.put(idx);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
_netViewType.value.l10n(_s),
|
_netViewType.value.toStr,
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -863,18 +862,18 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildDeleteServers() {
|
Widget _buildDeleteServers() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.deleteServers),
|
title: Text(l10n.deleteServers),
|
||||||
trailing: const Icon(Icons.delete_forever),
|
trailing: const Icon(Icons.delete_forever),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final all = Stores.server.box.keys.map(
|
final all = Stores.server.box.keys.map(
|
||||||
(e) => TextButton(
|
(e) => TextButton(
|
||||||
onPressed: () => context.showRoundDialog(
|
onPressed: () => context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(e)),
|
child: Text(l10n.sureDelete(e)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Providers.server.delServer(e),
|
onPressed: () => Providers.server.delServer(e),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -882,7 +881,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
context.showRoundDialog<List<String>>(
|
context.showRoundDialog<List<String>>(
|
||||||
title: Text(_s.choose),
|
title: Text(l10n.choose),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -896,30 +895,30 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildMoveOutServerFuncBtns() {
|
Widget _buildMoveOutServerFuncBtns() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.moveOutServerFuncBtns),
|
title: Text(l10n.moveOutServerFuncBtns),
|
||||||
subtitle: Text(_s.moveOutServerFuncBtnsHelp, style: UIs.textSize13Grey),
|
subtitle: Text(l10n.moveOutServerFuncBtnsHelp, style: UIs.textSize13Grey),
|
||||||
trailing: StoreSwitch(prop: _setting.moveOutServerTabFuncBtns),
|
trailing: StoreSwitch(prop: _setting.moveOutServerTabFuncBtns),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildServerOrder() {
|
Widget _buildServerOrder() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.serverOrder),
|
title: Text(l10n.serverOrder),
|
||||||
subtitle: Text('${_s.serverOrder} / ${_s.serverDetailOrder}',
|
subtitle: Text('${l10n.serverOrder} / ${l10n.serverDetailOrder}',
|
||||||
style: UIs.textGrey),
|
style: UIs.textGrey),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () => context.showRoundDialog(
|
onTap: () => context.showRoundDialog(
|
||||||
title: Text(_s.choose),
|
title: Text(l10n.choose),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.serverOrder),
|
title: Text(l10n.serverOrder),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () => AppRoute.serverOrder().go(context),
|
onTap: () => AppRoute.serverOrder().go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(_s.serverDetailOrder),
|
title: Text(l10n.serverDetailOrder),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () => AppRoute.serverDetailOrder().go(context),
|
onTap: () => AppRoute.serverDetailOrder().go(context),
|
||||||
),
|
),
|
||||||
@@ -933,7 +932,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
return ValueBuilder(
|
return ValueBuilder(
|
||||||
listenable: _editorFontSize,
|
listenable: _editorFontSize,
|
||||||
build: () => ListTile(
|
build: () => ListTile(
|
||||||
title: Text(_s.fontSize),
|
title: Text(l10n.fontSize),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
_editorFontSize.value.toString(),
|
_editorFontSize.value.toString(),
|
||||||
style: UIs.textSize15,
|
style: UIs.textSize15,
|
||||||
@@ -954,7 +953,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
final fontSize = double.tryParse(ctrller.text);
|
final fontSize = double.tryParse(ctrller.text);
|
||||||
if (fontSize == null) {
|
if (fontSize == null) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.failed),
|
title: Text(l10n.failed),
|
||||||
child: Text('Parsed failed: ${ctrller.text}'),
|
child: Text('Parsed failed: ${ctrller.text}'),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -964,7 +963,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.fontSize),
|
title: Text(l10n.fontSize),
|
||||||
child: Input(
|
child: Input(
|
||||||
controller: ctrller,
|
controller: ctrller,
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
@@ -975,7 +974,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: onSave,
|
onPressed: onSave,
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -984,14 +983,14 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
Widget _buildSftpRmrfDir() {
|
Widget _buildSftpRmrfDir() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: const Text('rm -rf'),
|
title: const Text('rm -rf'),
|
||||||
subtitle: Text(_s.sftpRmrfDirSummary, style: UIs.textGrey),
|
subtitle: Text(l10n.sftpRmrfDirSummary, style: UIs.textGrey),
|
||||||
trailing: StoreSwitch(prop: _setting.sftpRmrfDir),
|
trailing: StoreSwitch(prop: _setting.sftpRmrfDir),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widget _buildDoubleColumnServersPage() {
|
// Widget _buildDoubleColumnServersPage() {
|
||||||
// return ListTile(
|
// return ListTile(
|
||||||
// title: Text(_s.doubleColumnMode),
|
// title: Text(l10n.doubleColumnMode),
|
||||||
// trailing: StoreSwitch(prop: _setting.doubleColumnServersPage),
|
// trailing: StoreSwitch(prop: _setting.doubleColumnServersPage),
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
@@ -1000,16 +999,16 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
return FutureWidget<bool>(
|
return FutureWidget<bool>(
|
||||||
future: BioAuth.isAvail,
|
future: BioAuth.isAvail,
|
||||||
loading: ListTile(
|
loading: ListTile(
|
||||||
title: Text(_s.bioAuth),
|
title: Text(l10n.bioAuth),
|
||||||
subtitle: Text(_s.serverTabLoading, style: UIs.textGrey),
|
subtitle: Text(l10n.serverTabLoading, style: UIs.textGrey),
|
||||||
),
|
),
|
||||||
error: (e, __) => ListTile(
|
error: (e, __) => ListTile(
|
||||||
title: Text(_s.bioAuth),
|
title: Text(l10n.bioAuth),
|
||||||
subtitle: Text('${_s.failed}: $e', style: UIs.textGrey),
|
subtitle: Text('${l10n.failed}: $e', style: UIs.textGrey),
|
||||||
),
|
),
|
||||||
success: (can) {
|
success: (can) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.bioAuth),
|
title: Text(l10n.bioAuth),
|
||||||
subtitle: can
|
subtitle: can
|
||||||
? null
|
? null
|
||||||
: const Text('Error: Bio auth is not available',
|
: const Text('Error: Bio auth is not available',
|
||||||
@@ -1023,7 +1022,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Only auth when turn off (val == false)
|
// Only auth when turn off (val == false)
|
||||||
final result = await BioAuth.auth(_s.authRequired);
|
final result = await BioAuth.auth(l10n.authRequired);
|
||||||
// If failed, turn on again
|
// If failed, turn on again
|
||||||
if (result != AuthResult.success) {
|
if (result != AuthResult.success) {
|
||||||
Stores.setting.useBioAuth.put(true);
|
Stores.setting.useBioAuth.put(true);
|
||||||
@@ -1039,7 +1038,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
|
|
||||||
Widget _buildPlatformSetting() {
|
Widget _buildPlatformSetting() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${OS.type} ${_s.setting}'),
|
title: Text('${OS.type} ${l10n.setting}'),
|
||||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
switch (OS.type) {
|
switch (OS.type) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
import 'package:toolbox/core/utils/misc.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
@@ -24,18 +24,10 @@ class IOSSettingsPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
||||||
late S _s;
|
|
||||||
|
|
||||||
final _pushToken = ValueNotifier<String?>(null);
|
final _pushToken = ValueNotifier<String?>(null);
|
||||||
|
|
||||||
final wc = WatchConnectivity();
|
final wc = WatchConnectivity();
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -55,9 +47,7 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
|
|
||||||
Widget _buildPushToken() {
|
Widget _buildPushToken() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(l10n.pushToken),
|
||||||
_s.pushToken,
|
|
||||||
),
|
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.copy),
|
icon: const Icon(Icons.copy),
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
@@ -65,21 +55,21 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_pushToken.value != null) {
|
if (_pushToken.value != null) {
|
||||||
copy2Clipboard(_pushToken.value!);
|
copy2Clipboard(_pushToken.value!);
|
||||||
context.showSnackBar(_s.success);
|
context.showSnackBar(l10n.success);
|
||||||
} else {
|
} else {
|
||||||
context.showSnackBar(_s.getPushTokenFailed);
|
context.showSnackBar(l10n.getPushTokenFailed);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
subtitle: FutureWidget<String?>(
|
subtitle: FutureWidget<String?>(
|
||||||
future: getToken(),
|
future: getToken(),
|
||||||
loading: Text(_s.gettingToken),
|
loading: Text(l10n.gettingToken),
|
||||||
error: (error, trace) => Text('${_s.error}: $error'),
|
error: (error, trace) => Text('${l10n.error}: $error'),
|
||||||
noData: Text(_s.nullToken),
|
noData: Text(l10n.nullToken),
|
||||||
success: (text) {
|
success: (text) {
|
||||||
_pushToken.value = text;
|
_pushToken.value = text;
|
||||||
return Text(
|
return Text(
|
||||||
text ?? _s.nullToken,
|
text ?? l10n.nullToken,
|
||||||
style: UIs.textGrey,
|
style: UIs.textGrey,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
@@ -91,8 +81,8 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
|
|
||||||
Widget _buildAutoUpdateHomeWidget() {
|
Widget _buildAutoUpdateHomeWidget() {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(_s.autoUpdateHomeWidget),
|
title: Text(l10n.autoUpdateHomeWidget),
|
||||||
subtitle: Text(_s.whenOpenApp, style: UIs.textGrey),
|
subtitle: Text(l10n.whenOpenApp, style: UIs.textGrey),
|
||||||
trailing: StoreSwitch(prop: Stores.setting.autoUpdateHomeWidget),
|
trailing: StoreSwitch(prop: Stores.setting.autoUpdateHomeWidget),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -110,14 +100,14 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
Loggers.app.warning('WatchOS error', e, trace);
|
Loggers.app.warning('WatchOS error', e, trace);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: const Text('Watch app'),
|
title: const Text('Watch app'),
|
||||||
subtitle: Text('${_s.error}: $e', style: UIs.textGrey),
|
subtitle: Text('${l10n.error}: $e', style: UIs.textGrey),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
success: (ctx) {
|
success: (ctx) {
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: const Text('Watch app'),
|
title: const Text('Watch app'),
|
||||||
subtitle: Text(_s.watchNotPaired, style: UIs.textGrey),
|
subtitle: Text(l10n.watchNotPaired, style: UIs.textGrey),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
@@ -146,8 +136,8 @@ class _IOSSettingsPageState extends State<IOSSettingsPage> {
|
|||||||
await wc.updateApplicationContext(newCtx);
|
await wc.updateApplicationContext(newCtx);
|
||||||
} catch (e, trace) {
|
} catch (e, trace) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text('${_s.save}:\n$e'),
|
child: Text('${l10n.save}:\n$e'),
|
||||||
);
|
);
|
||||||
Loggers.app.warning('Update watch config failed', e, trace);
|
Loggers.app.warning('Update watch config failed', e, trace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
|
||||||
import '../../../core/extension/order.dart';
|
import '../../../core/extension/order.dart';
|
||||||
@@ -16,14 +16,6 @@ class ServerDetailOrderPage extends StatefulWidget {
|
|||||||
class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
||||||
final Order<String> _cardsOrder = [];
|
final Order<String> _cardsOrder = [];
|
||||||
|
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -34,7 +26,7 @@ class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.serverOrder),
|
title: Text(l10n.serverOrder),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -15,19 +15,11 @@ class ServerOrderPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ServerOrderPageState extends State<ServerOrderPage> {
|
class _ServerOrderPageState extends State<ServerOrderPage> {
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.serverOrder),
|
title: Text(l10n.serverOrder),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
);
|
);
|
||||||
@@ -35,7 +27,7 @@ class _ServerOrderPageState extends State<ServerOrderPage> {
|
|||||||
|
|
||||||
Widget _buildBody() {
|
Widget _buildBody() {
|
||||||
if (Providers.server.serverOrder.isEmpty) {
|
if (Providers.server.serverOrder.isEmpty) {
|
||||||
return Center(child: Text(_s.noServerAvailable));
|
return Center(child: Text(l10n.noServerAvailable));
|
||||||
}
|
}
|
||||||
return ReorderableListView.builder(
|
return ReorderableListView.builder(
|
||||||
footer: const SizedBox(height: 77),
|
footer: const SizedBox(height: 77),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
@@ -18,19 +18,11 @@ class SSHVirtKeySettingPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.editVirtKeys),
|
title: Text(l10n.editVirtKeys),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
);
|
);
|
||||||
@@ -48,7 +40,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
|||||||
padding: const EdgeInsets.all(7),
|
padding: const EdgeInsets.all(7),
|
||||||
itemBuilder: (_, idx) {
|
itemBuilder: (_, idx) {
|
||||||
final key = allKeys[idx];
|
final key = allKeys[idx];
|
||||||
final help = key.help(_s);
|
final help = key.help;
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
key: ValueKey(idx),
|
key: ValueKey(idx),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -62,7 +54,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
|||||||
itemCount: allKeys.length,
|
itemCount: allKeys.length,
|
||||||
onReorder: (o, n) {
|
onReorder: (o, n) {
|
||||||
if (o >= keys.length || n >= keys.length) {
|
if (o >= keys.length || n >= keys.length) {
|
||||||
context.showSnackBar(_s.disabled);
|
context.showSnackBar(l10n.disabled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keys.moveByItem(keys, o, n, property: Stores.setting.sshVirtKeys);
|
keys.moveByItem(keys, o, n, property: Stores.setting.sshVirtKeys);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
@@ -27,8 +27,6 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
final _noteController = TextEditingController();
|
final _noteController = TextEditingController();
|
||||||
final _scriptNode = FocusNode();
|
final _scriptNode = FocusNode();
|
||||||
|
|
||||||
late S _s;
|
|
||||||
|
|
||||||
List<String> _tags = [];
|
List<String> _tags = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -39,17 +37,11 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
_scriptNode.dispose();
|
_scriptNode.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.edit, style: UIs.textSize18),
|
title: Text(l10n.edit, style: UIs.textSize18),
|
||||||
actions: _buildAppBarActions(),
|
actions: _buildAppBarActions(),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
@@ -67,7 +59,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
Providers.snippet.del(widget.snippet!);
|
Providers.snippet.del(widget.snippet!);
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
tooltip: _s.delete,
|
tooltip: l10n.delete,
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
@@ -81,7 +73,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
final name = _nameController.text;
|
final name = _nameController.text;
|
||||||
final script = _scriptController.text;
|
final script = _scriptController.text;
|
||||||
if (name.isEmpty || script.isEmpty) {
|
if (name.isEmpty || script.isEmpty) {
|
||||||
context.showSnackBar(_s.fieldMustNotEmpty);
|
context.showSnackBar(l10n.fieldMustNotEmpty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final note = _noteController.text;
|
final note = _noteController.text;
|
||||||
@@ -110,7 +102,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
controller: _nameController,
|
controller: _nameController,
|
||||||
type: TextInputType.text,
|
type: TextInputType.text,
|
||||||
onSubmitted: (_) => FocusScope.of(context).requestFocus(_scriptNode),
|
onSubmitted: (_) => FocusScope.of(context).requestFocus(_scriptNode),
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
icon: Icons.info,
|
icon: Icons.info,
|
||||||
),
|
),
|
||||||
Input(
|
Input(
|
||||||
@@ -118,7 +110,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
minLines: 3,
|
minLines: 3,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
type: TextInputType.multiline,
|
type: TextInputType.multiline,
|
||||||
label: _s.note,
|
label: l10n.note,
|
||||||
icon: Icons.note,
|
icon: Icons.note,
|
||||||
),
|
),
|
||||||
TagEditor(
|
TagEditor(
|
||||||
@@ -126,7 +118,6 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
onChanged: (p0) => setState(() {
|
onChanged: (p0) => setState(() {
|
||||||
_tags = p0;
|
_tags = p0;
|
||||||
}),
|
}),
|
||||||
s: _s,
|
|
||||||
allTags: [...Providers.server.tags],
|
allTags: [...Providers.server.tags],
|
||||||
onRenameTag: (old, n) => setState(() {
|
onRenameTag: (old, n) => setState(() {
|
||||||
Providers.server.renameTag(old, n);
|
Providers.server.renameTag(old, n);
|
||||||
@@ -138,7 +129,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
minLines: 3,
|
minLines: 3,
|
||||||
maxLines: 10,
|
maxLines: 10,
|
||||||
type: TextInputType.multiline,
|
type: TextInputType.multiline,
|
||||||
label: _s.snippet,
|
label: l10n.snippet,
|
||||||
icon: Icons.code,
|
icon: Icons.code,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/order.dart';
|
import 'package:toolbox/core/extension/order.dart';
|
||||||
import 'package:toolbox/data/res/provider.dart';
|
import 'package:toolbox/data/res/provider.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -23,7 +23,6 @@ class SnippetListPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SnippetListPageState extends State<SnippetListPage> {
|
class _SnippetListPageState extends State<SnippetListPage> {
|
||||||
late S _s;
|
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
|
|
||||||
String? _tag;
|
String? _tag;
|
||||||
@@ -31,7 +30,6 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +50,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
builder: (_, provider, __) {
|
builder: (_, provider, __) {
|
||||||
if (provider.snippets.isEmpty) {
|
if (provider.snippets.isEmpty) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(_s.noSavedSnippet),
|
child: Text(l10n.noSavedSnippet),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +75,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
tags: provider.tags,
|
tags: provider.tags,
|
||||||
onTagChanged: (tag) => setState(() => _tag = tag),
|
onTagChanged: (tag) => setState(() => _tag = tag),
|
||||||
initTag: _tag,
|
initTag: _tag,
|
||||||
all: _s.all,
|
all: l10n.all,
|
||||||
width: _media.size.width,
|
width: _media.size.width,
|
||||||
),
|
),
|
||||||
footer: UIs.height77,
|
footer: UIs.height77,
|
||||||
@@ -148,12 +146,12 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
results,
|
results,
|
||||||
).entries.map((e) => '${e.key}:\n${e.value}').join('\n');
|
).entries.map((e) => '${e.key}:\n${e.value}').join('\n');
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.result),
|
title: Text(l10n.result),
|
||||||
child: Text(result),
|
child: Text(result),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(result),
|
onPressed: () => copy2Clipboard(result),
|
||||||
child: Text(_s.copy),
|
child: Text(l10n.copy),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import 'package:dartssh2/dartssh2.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
@@ -43,7 +43,6 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
final List<List<VirtKey>> _virtKeysList = [];
|
final List<List<VirtKey>> _virtKeysList = [];
|
||||||
|
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late S _s;
|
|
||||||
late TerminalStyle _terminalStyle;
|
late TerminalStyle _terminalStyle;
|
||||||
late TerminalTheme _terminalTheme;
|
late TerminalTheme _terminalTheme;
|
||||||
late TextInputType _keyboardType;
|
late TextInputType _keyboardType;
|
||||||
@@ -88,7 +87,6 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_isDark = context.isDark;
|
_isDark = context.isDark;
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_s = S.of(context)!;
|
|
||||||
_terminalTheme = _isDark ? TerminalThemes.dark : TerminalThemes.light;
|
_terminalTheme = _isDark ? TerminalThemes.dark : TerminalThemes.light;
|
||||||
|
|
||||||
// Because the virtual keyboard only displayed on mobile devices
|
// Because the virtual keyboard only displayed on mobile devices
|
||||||
@@ -252,7 +250,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VirtualKeyFunc.snippet:
|
case VirtualKeyFunc.snippet:
|
||||||
context.showSnippetDialog(_s, (s) {
|
context.showSnippetDialog((s) {
|
||||||
_terminal.textInput(s.script);
|
_terminal.textInput(s.script);
|
||||||
_terminal.keyInput(TerminalKey.enter);
|
_terminal.keyInput(TerminalKey.enter);
|
||||||
});
|
});
|
||||||
@@ -269,7 +267,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
final initPath = cmds[idx + 1].toString();
|
final initPath = cmds[idx + 1].toString();
|
||||||
if (initPath.isEmpty || !initPath.startsWith('/')) {
|
if (initPath.isEmpty || !initPath.startsWith('/')) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: const Text('Failed to get current path'),
|
child: const Text('Failed to get current path'),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -401,8 +399,8 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
_write('\n\nConnection lost\r\n');
|
_write('\n\nConnection lost\r\n');
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text('${_s.disconnected}\n${_s.goBackQ}'),
|
child: Text('${l10n.disconnected}\n${l10n.goBackQ}'),
|
||||||
barrierDismiss: false,
|
barrierDismiss: false,
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -412,7 +410,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/data/model/sftp/req.dart';
|
import 'package:toolbox/data/model/sftp/req.dart';
|
||||||
import 'package:toolbox/data/res/misc.dart';
|
import 'package:toolbox/data/res/misc.dart';
|
||||||
@@ -37,7 +37,6 @@ class LocalStoragePage extends StatefulWidget {
|
|||||||
|
|
||||||
class _LocalStoragePageState extends State<LocalStoragePage> {
|
class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||||
LocalPath? _path;
|
LocalPath? _path;
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -55,12 +54,6 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -74,7 +67,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(_s.files),
|
title: Text(l10n.files),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.downloading),
|
icon: const Icon(Icons.downloading),
|
||||||
@@ -96,7 +89,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
(_path?.path ?? _s.loadingFiles).omitStartStr(),
|
(_path?.path ?? l10n.loadingFiles).omitStartStr(),
|
||||||
_buildBtns(),
|
_buildBtns(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -200,7 +193,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
_showRenameDialog(file);
|
_showRenameDialog(file);
|
||||||
},
|
},
|
||||||
title: Text(_s.rename),
|
title: Text(l10n.rename),
|
||||||
leading: const Icon(Icons.abc),
|
leading: const Icon(Icons.abc),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -208,7 +201,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
_showDeleteDialog(file);
|
_showDeleteDialog(file);
|
||||||
},
|
},
|
||||||
title: Text(_s.delete),
|
title: Text(l10n.delete),
|
||||||
leading: const Icon(Icons.delete),
|
leading: const Icon(Icons.delete),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -220,7 +213,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
final fileName = file.path.split('/').last;
|
final fileName = file.path.split('/').last;
|
||||||
if (widget.isPickFile) {
|
if (widget.isPickFile) {
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.pickFile),
|
title: Text(l10n.pickFile),
|
||||||
child: Text(fileName),
|
child: Text(fileName),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -228,7 +221,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
context.pop(file.path);
|
context.pop(file.path);
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
return;
|
return;
|
||||||
@@ -239,14 +232,14 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.edit),
|
leading: const Icon(Icons.edit),
|
||||||
title: Text(_s.edit),
|
title: Text(l10n.edit),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
final stat = await file.stat();
|
final stat = await file.stat();
|
||||||
if (stat.size > Miscs.editorMaxSize) {
|
if (stat.size > Miscs.editorMaxSize) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.fileTooLarge(fileName, stat.size, '1m')),
|
child: Text(l10n.fileTooLarge(fileName, stat.size, '1m')),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -256,14 +249,14 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
final f = File(file.absolute.path);
|
final f = File(file.absolute.path);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
f.writeAsString(result);
|
f.writeAsString(result);
|
||||||
context.showSnackBar(_s.saved);
|
context.showSnackBar(l10n.saved);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.abc),
|
leading: const Icon(Icons.abc),
|
||||||
title: Text(_s.rename),
|
title: Text(l10n.rename),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
_showRenameDialog(file);
|
_showRenameDialog(file);
|
||||||
@@ -271,7 +264,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete),
|
leading: const Icon(Icons.delete),
|
||||||
title: Text(_s.delete),
|
title: Text(l10n.delete),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
_showDeleteDialog(file);
|
_showDeleteDialog(file);
|
||||||
@@ -279,20 +272,20 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.upload),
|
leading: const Icon(Icons.upload),
|
||||||
title: Text(_s.upload),
|
title: Text(l10n.upload),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
final ids = Providers.server.serverOrder;
|
final ids = Providers.server.serverOrder;
|
||||||
var idx = 0;
|
var idx = 0;
|
||||||
await context.showRoundDialog(
|
await context.showRoundDialog(
|
||||||
title: Text(_s.server),
|
title: Text(l10n.server),
|
||||||
child: Picker(
|
child: Picker(
|
||||||
items: ids.map((e) => Text(e)).toList(),
|
items: ids.map((e) => Text(e)).toList(),
|
||||||
onSelected: (idx_) => idx = idx_,
|
onSelected: (idx_) => idx = idx_,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(), child: Text(_s.ok)),
|
onPressed: () => context.pop(), child: Text(l10n.ok)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final id = ids[idx];
|
final id = ids[idx];
|
||||||
@@ -313,12 +306,12 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
file.absolute.path,
|
file.absolute.path,
|
||||||
SftpReqType.upload,
|
SftpReqType.upload,
|
||||||
));
|
));
|
||||||
context.showSnackBar(_s.added2List);
|
context.showSnackBar(l10n.added2List);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.open_in_new),
|
leading: const Icon(Icons.open_in_new),
|
||||||
title: Text(_s.open),
|
title: Text(l10n.open),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
shareFiles(context, [file.absolute.path]);
|
shareFiles(context, [file.absolute.path]);
|
||||||
},
|
},
|
||||||
@@ -331,7 +324,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
void _showRenameDialog(FileSystemEntity file) {
|
void _showRenameDialog(FileSystemEntity file) {
|
||||||
final fileName = file.path.split('/').last;
|
final fileName = file.path.split('/').last;
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.rename),
|
title: Text(l10n.rename),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
controller: TextEditingController(text: fileName),
|
controller: TextEditingController(text: fileName),
|
||||||
@@ -341,7 +334,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
try {
|
try {
|
||||||
file.renameSync(newPath);
|
file.renameSync(newPath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showSnackBar('${_s.failed}:\n$e');
|
context.showSnackBar('${l10n.failed}:\n$e');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,12 +347,12 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
void _showDeleteDialog(FileSystemEntity file) {
|
void _showDeleteDialog(FileSystemEntity file) {
|
||||||
final fileName = file.path.split('/').last;
|
final fileName = file.path.split('/').last;
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.delete),
|
title: Text(l10n.delete),
|
||||||
child: Text(_s.sureDelete(fileName)),
|
child: Text(l10n.sureDelete(fileName)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -367,12 +360,12 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
|||||||
try {
|
try {
|
||||||
file.deleteSync(recursive: true);
|
file.deleteSync(recursive: true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showSnackBar('${_s.failed}:\n$e');
|
context.showSnackBar('${l10n.failed}:\n$e');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import 'dart:async';
|
|||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
import 'package:dartssh2/dartssh2.dart';
|
import 'package:dartssh2/dartssh2.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/sftpfile.dart';
|
import 'package:toolbox/core/extension/sftpfile.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
@@ -49,14 +49,11 @@ class SftpPage extends StatefulWidget {
|
|||||||
class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
||||||
final SftpBrowserStatus _status = SftpBrowserStatus();
|
final SftpBrowserStatus _status = SftpBrowserStatus();
|
||||||
|
|
||||||
late S _s;
|
|
||||||
|
|
||||||
SSHClient? _client;
|
SSHClient? _client;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -130,7 +127,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
(_status.path?.path ?? _s.loadingFiles).omitStartStr(),
|
(_status.path?.path ?? l10n.loadingFiles).omitStartStr(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: children,
|
children: children,
|
||||||
@@ -150,12 +147,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.open_in_new),
|
leading: const Icon(Icons.open_in_new),
|
||||||
title: Text(_s.system),
|
title: Text(l10n.system),
|
||||||
onTap: () => context.pop(1),
|
onTap: () => context.pop(1),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.folder),
|
leading: const Icon(Icons.folder),
|
||||||
title: Text(_s.inner),
|
title: Text(l10n.inner),
|
||||||
onTap: () => context.pop(0),
|
onTap: () => context.pop(0),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -199,11 +196,11 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.folder),
|
leading: const Icon(Icons.folder),
|
||||||
title: Text(_s.createFolder),
|
title: Text(l10n.createFolder),
|
||||||
onTap: () => _mkdir(context)),
|
onTap: () => _mkdir(context)),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.insert_drive_file),
|
leading: const Icon(Icons.insert_drive_file),
|
||||||
title: Text(_s.createFile),
|
title: Text(l10n.createFile),
|
||||||
onTap: () => _newFile(context)),
|
onTap: () => _newFile(context)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -217,7 +214,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final p = await context.showRoundDialog<String>(
|
final p = await context.showRoundDialog<String>(
|
||||||
title: Text(_s.goto),
|
title: Text(l10n.goto),
|
||||||
child: Autocomplete<String>(
|
child: Autocomplete<String>(
|
||||||
optionsBuilder: (val) {
|
optionsBuilder: (val) {
|
||||||
if (!Stores.setting.recordHistory.fetch()) {
|
if (!Stores.setting.recordHistory.fetch()) {
|
||||||
@@ -231,7 +228,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
return Input(
|
return Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.abc,
|
icon: Icons.abc,
|
||||||
label: _s.path,
|
label: l10n.path,
|
||||||
node: node,
|
node: node,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
onSubmitted: (value) => context.pop(value),
|
onSubmitted: (value) => context.pop(value),
|
||||||
@@ -318,12 +315,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
final children = [
|
final children = [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.delete),
|
leading: const Icon(Icons.delete),
|
||||||
title: Text(_s.delete),
|
title: Text(l10n.delete),
|
||||||
onTap: () => _delete(context, file),
|
onTap: () => _delete(context, file),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.abc),
|
leading: const Icon(Icons.abc),
|
||||||
title: Text(_s.rename),
|
title: Text(l10n.rename),
|
||||||
onTap: () => _rename(context, file),
|
onTap: () => _rename(context, file),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -331,19 +328,19 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
children.addAll([
|
children.addAll([
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.edit),
|
leading: const Icon(Icons.edit),
|
||||||
title: Text(_s.edit),
|
title: Text(l10n.edit),
|
||||||
onTap: () => _edit(context, file),
|
onTap: () => _edit(context, file),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.download),
|
leading: const Icon(Icons.download),
|
||||||
title: Text(_s.download),
|
title: Text(l10n.download),
|
||||||
onTap: () => _download(context, file),
|
onTap: () => _download(context, file),
|
||||||
),
|
),
|
||||||
// Only show decompress option when the file is a compressed file
|
// Only show decompress option when the file is a compressed file
|
||||||
if (_canDecompress(file.filename))
|
if (_canDecompress(file.filename))
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.folder_zip),
|
leading: const Icon(Icons.folder_zip),
|
||||||
title: Text(_s.decompress),
|
title: Text(l10n.decompress),
|
||||||
onTap: () => _decompress(context, file),
|
onTap: () => _decompress(context, file),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
@@ -359,7 +356,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
Future<void> _edit(BuildContext context, SftpName name) async {
|
Future<void> _edit(BuildContext context, SftpName name) async {
|
||||||
final size = name.attr.size;
|
final size = name.attr.size;
|
||||||
if (size == null || size > Miscs.editorMaxSize) {
|
if (size == null || size > Miscs.editorMaxSize) {
|
||||||
context.showSnackBar(_s.fileTooLarge(
|
context.showSnackBar(l10n.fileTooLarge(
|
||||||
name.filename,
|
name.filename,
|
||||||
size ?? 0,
|
size ?? 0,
|
||||||
Miscs.editorMaxSize,
|
Miscs.editorMaxSize,
|
||||||
@@ -386,18 +383,18 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
if (result != null && result) {
|
if (result != null && result) {
|
||||||
Providers.sftp
|
Providers.sftp
|
||||||
.add(SftpReq(req.spi, remotePath, localPath, SftpReqType.upload));
|
.add(SftpReq(req.spi, remotePath, localPath, SftpReqType.upload));
|
||||||
context.showSnackBar(_s.added2List);
|
context.showSnackBar(l10n.added2List);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _download(BuildContext context, SftpName name) {
|
void _download(BuildContext context, SftpName name) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
child: Text('${l10n.dl2Local(name.filename)}\n${l10n.keepForeground}'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -415,7 +412,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
|
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(_s.download),
|
child: Text(l10n.download),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -425,16 +422,16 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final isDir = file.attr.isDirectory;
|
final isDir = file.attr.isDirectory;
|
||||||
final useRmrf = Stores.setting.sftpRmrfDir.fetch();
|
final useRmrf = Stores.setting.sftpRmrfDir.fetch();
|
||||||
final dirText = (isDir && !useRmrf) ? '\n${_s.sureDirEmpty}' : '';
|
final dirText = (isDir && !useRmrf) ? '\n${l10n.sureDirEmpty}' : '';
|
||||||
final text = '${_s.sureDelete(file.filename)}$dirText';
|
final text = '${l10n.sureDelete(file.filename)}$dirText';
|
||||||
final child = Text(text);
|
final child = Text(text);
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
child: child,
|
child: child,
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -453,12 +450,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.pop();
|
context.pop();
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -466,7 +463,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
}
|
}
|
||||||
_listDir();
|
_listDir();
|
||||||
},
|
},
|
||||||
child: Text(_s.delete, style: UIs.textRed),
|
child: Text(l10n.delete, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -476,27 +473,27 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.createFolder),
|
title: Text(l10n.createFolder),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.folder,
|
icon: Icons.folder,
|
||||||
controller: textController,
|
controller: textController,
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(l10n.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
child: Text(_s.fieldMustNotEmpty),
|
child: Text(l10n.fieldMustNotEmpty),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -507,7 +504,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
_listDir();
|
_listDir();
|
||||||
},
|
},
|
||||||
child: Text(_s.ok, style: UIs.textRed),
|
child: Text(l10n.ok, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -517,24 +514,24 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.createFile),
|
title: Text(l10n.createFile),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.insert_drive_file,
|
icon: Icons.insert_drive_file,
|
||||||
controller: textController,
|
controller: textController,
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.fieldMustNotEmpty),
|
child: Text(l10n.fieldMustNotEmpty),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -547,7 +544,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
_listDir();
|
_listDir();
|
||||||
},
|
},
|
||||||
child: Text(_s.ok, style: UIs.textRed),
|
child: Text(l10n.ok, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -557,25 +554,25 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.rename),
|
title: Text(l10n.rename),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.abc,
|
icon: Icons.abc,
|
||||||
controller: textController,
|
controller: textController,
|
||||||
label: _s.name,
|
label: l10n.name,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(onPressed: () => context.pop(), child: Text(_s.cancel)),
|
TextButton(onPressed: () => context.pop(), child: Text(l10n.cancel)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.fieldMustNotEmpty),
|
child: Text(l10n.fieldMustNotEmpty),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -585,7 +582,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
context.pop();
|
context.pop();
|
||||||
_listDir();
|
_listDir();
|
||||||
},
|
},
|
||||||
child: Text(_s.rename, style: UIs.textRed),
|
child: Text(l10n.rename, style: UIs.textRed),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -597,12 +594,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
final cmd = _getDecompressCmd(absPath);
|
final cmd = _getDecompressCmd(absPath);
|
||||||
if (cmd == null) {
|
if (cmd == null) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text('Unsupport file: ${name.filename}'),
|
child: Text('Unsupport file: ${name.filename}'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -664,12 +661,12 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
|
|||||||
Future.delayed(
|
Future.delayed(
|
||||||
const Duration(milliseconds: 177),
|
const Duration(milliseconds: 177),
|
||||||
() => context.showRoundDialog(
|
() => context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/datetime.dart';
|
import 'package:toolbox/core/extension/datetime.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
@@ -23,19 +23,11 @@ class SftpMissionPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SftpMissionPageState extends State<SftpMissionPage> {
|
class _SftpMissionPageState extends State<SftpMissionPage> {
|
||||||
late S _s;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
_s = S.of(context)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: Text(_s.mission, style: UIs.textSize18),
|
title: Text(l10n.mission, style: UIs.textSize18),
|
||||||
),
|
),
|
||||||
body: _buildBody(),
|
body: _buildBody(),
|
||||||
);
|
);
|
||||||
@@ -45,7 +37,7 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
|||||||
return Consumer<SftpProvider>(builder: (__, pro, _) {
|
return Consumer<SftpProvider>(builder: (__, pro, _) {
|
||||||
if (pro.status.isEmpty) {
|
if (pro.status.isEmpty) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(_s.noTask),
|
child: Text(l10n.noTask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
@@ -63,8 +55,8 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
|||||||
switch (status.status) {
|
switch (status.status) {
|
||||||
case SftpWorkerStatus.finished:
|
case SftpWorkerStatus.finished:
|
||||||
final time = status.spentTime.toString();
|
final time = status.spentTime.toString();
|
||||||
final str = '${_s.finished} ${_s.spentTime(
|
final str = '${l10n.finished} ${l10n.spentTime(
|
||||||
time == 'null' ? _s.unknown : (time.substring(0, time.length - 7)),
|
time == 'null' ? l10n.unknown : (time.substring(0, time.length - 7)),
|
||||||
)}';
|
)}';
|
||||||
return _wrapInCard(
|
return _wrapInCard(
|
||||||
status: status,
|
status: status,
|
||||||
@@ -91,29 +83,29 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
|||||||
final size = (status.size ?? 0).convertBytes;
|
final size = (status.size ?? 0).convertBytes;
|
||||||
return _wrapInCard(
|
return _wrapInCard(
|
||||||
status: status,
|
status: status,
|
||||||
subtitle: _s.percentOfSize(percentStr, size),
|
subtitle: l10n.percentOfSize(percentStr, size),
|
||||||
trailing: _buildDelete(status.fileName, status.id),
|
trailing: _buildDelete(status.fileName, status.id),
|
||||||
);
|
);
|
||||||
case SftpWorkerStatus.preparing:
|
case SftpWorkerStatus.preparing:
|
||||||
return _wrapInCard(
|
return _wrapInCard(
|
||||||
status: status,
|
status: status,
|
||||||
subtitle: _s.sftpDlPrepare,
|
subtitle: l10n.sftpDlPrepare,
|
||||||
trailing: _buildDelete(status.fileName, status.id),
|
trailing: _buildDelete(status.fileName, status.id),
|
||||||
);
|
);
|
||||||
case SftpWorkerStatus.sshConnectted:
|
case SftpWorkerStatus.sshConnectted:
|
||||||
return _wrapInCard(
|
return _wrapInCard(
|
||||||
status: status,
|
status: status,
|
||||||
subtitle: _s.sftpSSHConnected,
|
subtitle: l10n.sftpSSHConnected,
|
||||||
trailing: _buildDelete(status.fileName, status.id),
|
trailing: _buildDelete(status.fileName, status.id),
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return _wrapInCard(
|
return _wrapInCard(
|
||||||
status: status,
|
status: status,
|
||||||
subtitle: _s.unknown,
|
subtitle: l10n.unknown,
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
onPressed: () => context.showRoundDialog(
|
onPressed: () => context.showRoundDialog(
|
||||||
title: Text(_s.error),
|
title: Text(l10n.error),
|
||||||
child: Text((status.error ?? _s.unknown).toString()),
|
child: Text((status.error ?? l10n.unknown).toString()),
|
||||||
),
|
),
|
||||||
icon: const Icon(Icons.error),
|
icon: const Icon(Icons.error),
|
||||||
),
|
),
|
||||||
@@ -144,15 +136,15 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
|||||||
Widget _buildDelete(String name, int id) {
|
Widget _buildDelete(String name, int id) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () => context.showRoundDialog(
|
onPressed: () => context.showRoundDialog(
|
||||||
title: Text(_s.attention),
|
title: Text(l10n.attention),
|
||||||
child: Text(_s.sureDelete(name)),
|
child: Text(l10n.sureDelete(name)),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Providers.sftp.cancel(id);
|
Providers.sftp.cancel(id);
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
import 'package:toolbox/core/extension/ssh_client.dart';
|
import 'package:toolbox/core/extension/ssh_client.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
@@ -25,12 +25,10 @@ import 'tag.dart';
|
|||||||
|
|
||||||
class ServerFuncBtnsTopRight extends StatelessWidget {
|
class ServerFuncBtnsTopRight extends StatelessWidget {
|
||||||
final ServerPrivateInfo spi;
|
final ServerPrivateInfo spi;
|
||||||
final S s;
|
|
||||||
|
|
||||||
const ServerFuncBtnsTopRight({
|
const ServerFuncBtnsTopRight({
|
||||||
super.key,
|
super.key,
|
||||||
required this.spi,
|
required this.spi,
|
||||||
required this.s,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -45,13 +43,13 @@ class ServerFuncBtnsTopRight extends StatelessWidget {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
Text(e.text(s)),
|
Text(e.toStr),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||||
onSelected: (val) => _onTapMoreBtns(val, spi, context, s),
|
onSelected: (val) => _onTapMoreBtns(val, spi, context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,12 +58,10 @@ class ServerFuncBtns extends StatelessWidget {
|
|||||||
const ServerFuncBtns({
|
const ServerFuncBtns({
|
||||||
super.key,
|
super.key,
|
||||||
required this.spi,
|
required this.spi,
|
||||||
required this.s,
|
|
||||||
this.iconSize,
|
this.iconSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
final ServerPrivateInfo spi;
|
final ServerPrivateInfo spi;
|
||||||
final S s;
|
|
||||||
final double? iconSize;
|
final double? iconSize;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -74,7 +70,7 @@ class ServerFuncBtns extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: ServerTabMenuType.values
|
children: ServerTabMenuType.values
|
||||||
.map((e) => IconButton(
|
.map((e) => IconButton(
|
||||||
onPressed: () => _onTapMoreBtns(e, spi, context, s),
|
onPressed: () => _onTapMoreBtns(e, spi, context),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
tooltip: e.name,
|
tooltip: e.name,
|
||||||
icon: Icon(e.icon, size: iconSize ?? 15),
|
icon: Icon(e.icon, size: iconSize ?? 15),
|
||||||
@@ -88,16 +84,15 @@ void _onTapMoreBtns(
|
|||||||
ServerTabMenuType value,
|
ServerTabMenuType value,
|
||||||
ServerPrivateInfo spi,
|
ServerPrivateInfo spi,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
S s,
|
|
||||||
) async {
|
) async {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case ServerTabMenuType.pkg:
|
case ServerTabMenuType.pkg:
|
||||||
_onPkg(context, s, spi);
|
_onPkg(context, spi);
|
||||||
break;
|
break;
|
||||||
case ServerTabMenuType.sftp:
|
case ServerTabMenuType.sftp:
|
||||||
AppRoute.sftp(spi: spi).checkGo(
|
AppRoute.sftp(spi: spi).checkGo(
|
||||||
context: context,
|
context: context,
|
||||||
check: () => _checkClient(context, spi.id, s.waitConnection),
|
check: () => _checkClient(context, spi.id),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ServerTabMenuType.snippet:
|
case ServerTabMenuType.snippet:
|
||||||
@@ -114,12 +109,12 @@ void _onTapMoreBtns(
|
|||||||
final result = await Providers.server.runSnippets(spi.id, snippets);
|
final result = await Providers.server.runSnippets(spi.id, snippets);
|
||||||
if (result != null && result.isNotEmpty) {
|
if (result != null && result.isNotEmpty) {
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(s.result),
|
title: Text(l10n.result),
|
||||||
child: Text(result),
|
child: Text(result),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => copy2Clipboard(result),
|
onPressed: () => copy2Clipboard(result),
|
||||||
child: Text(s.copy),
|
child: Text(l10n.copy),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -128,13 +123,13 @@ void _onTapMoreBtns(
|
|||||||
case ServerTabMenuType.docker:
|
case ServerTabMenuType.docker:
|
||||||
AppRoute.docker(spi: spi).checkGo(
|
AppRoute.docker(spi: spi).checkGo(
|
||||||
context: context,
|
context: context,
|
||||||
check: () => _checkClient(context, spi.id, s.waitConnection),
|
check: () => _checkClient(context, spi.id),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ServerTabMenuType.process:
|
case ServerTabMenuType.process:
|
||||||
AppRoute.process(spi: spi).checkGo(
|
AppRoute.process(spi: spi).checkGo(
|
||||||
context: context,
|
context: context,
|
||||||
check: () => _checkClient(context, spi.id, s.waitConnection),
|
check: () => _checkClient(context, spi.id),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ServerTabMenuType.terminal:
|
case ServerTabMenuType.terminal:
|
||||||
@@ -192,19 +187,19 @@ Future<void> _gotoSSH(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _checkClient(BuildContext context, String id, String msg) {
|
bool _checkClient(BuildContext context, String id) {
|
||||||
final server = Providers.server.servers[id];
|
final server = Providers.server.servers[id];
|
||||||
if (server == null || server.client == null) {
|
if (server == null || server.client == null) {
|
||||||
context.showSnackBar(msg);
|
context.showSnackBar(l10n.waitConnection);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onPkg(BuildContext context, S s, ServerPrivateInfo spi) async {
|
Future<void> _onPkg(BuildContext context, ServerPrivateInfo spi) async {
|
||||||
final server = spi.findServer;
|
final server = spi.findServer;
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
context.showSnackBar(s.noClient);
|
context.showSnackBar(l10n.noClient);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final sys = server.status.sysVer;
|
final sys = server.status.sysVer;
|
||||||
@@ -232,13 +227,13 @@ Future<void> _onPkg(BuildContext context, S s, ServerPrivateInfo spi) async {
|
|||||||
final result = await server.client?.run(listCmd).string;
|
final result = await server.client?.run(listCmd).string;
|
||||||
context.pop();
|
context.pop();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
context.showSnackBar(s.noResult);
|
context.showSnackBar(l10n.noResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final list = pkg?.updateListRemoveUnused(result.split('\n'));
|
final list = pkg?.updateListRemoveUnused(result.split('\n'));
|
||||||
final upgradeable = list?.map((e) => UpgradePkgInfo(e, pkg)).toList();
|
final upgradeable = list?.map((e) => UpgradePkgInfo(e, pkg)).toList();
|
||||||
if (upgradeable == null || upgradeable.isEmpty) {
|
if (upgradeable == null || upgradeable.isEmpty) {
|
||||||
context.showSnackBar(s.noUpdateAvailable);
|
context.showSnackBar(l10n.noUpdateAvailable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final args = upgradeable.map((e) => e.package).join(' ');
|
final args = upgradeable.map((e) => e.package).join(' ');
|
||||||
@@ -247,14 +242,14 @@ Future<void> _onPkg(BuildContext context, S s, ServerPrivateInfo spi) async {
|
|||||||
|
|
||||||
// Confirm upgrade
|
// Confirm upgrade
|
||||||
final gotoUpgrade = await context.showRoundDialog<bool>(
|
final gotoUpgrade = await context.showRoundDialog<bool>(
|
||||||
title: Text(s.attention),
|
title: Text(l10n.attention),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Text('${s.foundNUpdate(upgradeable.length)}\n\n$upgradeCmd'),
|
child: Text('${l10n.foundNUpdate(upgradeable.length)}\n\n$upgradeCmd'),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(true),
|
onPressed: () => context.pop(true),
|
||||||
child: Text(s.update),
|
child: Text(l10n.update),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -263,6 +258,6 @@ Future<void> _onPkg(BuildContext context, S s, ServerPrivateInfo spi) async {
|
|||||||
|
|
||||||
AppRoute.ssh(spi: spi, initCmd: upgradeCmd).checkGo(
|
AppRoute.ssh(spi: spi, initCmd: upgradeCmd).checkGo(
|
||||||
context: context,
|
context: context,
|
||||||
check: () => _checkClient(context, spi.id, s.waitConnection),
|
check: () => _checkClient(context, spi.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|
||||||
|
|
||||||
import '../../data/model/app/tag_pickable.dart';
|
import '../../data/model/app/tag_pickable.dart';
|
||||||
import '../../data/res/color.dart';
|
import '../../data/res/color.dart';
|
||||||
@@ -39,7 +39,6 @@ class TagBtn extends StatelessWidget {
|
|||||||
|
|
||||||
class TagEditor extends StatefulWidget {
|
class TagEditor extends StatefulWidget {
|
||||||
final List<String> tags;
|
final List<String> tags;
|
||||||
final S s;
|
|
||||||
final void Function(List<String>)? onChanged;
|
final void Function(List<String>)? onChanged;
|
||||||
final void Function(String old, String new_)? onRenameTag;
|
final void Function(String old, String new_)? onRenameTag;
|
||||||
final List<String> allTags;
|
final List<String> allTags;
|
||||||
@@ -47,7 +46,6 @@ class TagEditor extends StatefulWidget {
|
|||||||
const TagEditor({
|
const TagEditor({
|
||||||
super.key,
|
super.key,
|
||||||
required this.tags,
|
required this.tags,
|
||||||
required this.s,
|
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.onRenameTag,
|
this.onRenameTag,
|
||||||
this.allTags = const <String>[],
|
this.allTags = const <String>[],
|
||||||
@@ -78,7 +76,7 @@ class _TagEditorState extends State<TagEditor> {
|
|||||||
|
|
||||||
/// Add vertical divider if suggestions.length > 0
|
/// Add vertical divider if suggestions.length > 0
|
||||||
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
final counts = tags.length + suggestionLen + (suggestionLen == 0 ? 0 : 1);
|
||||||
if (counts == 0) return Text(widget.s.tag);
|
if (counts == 0) return Text(l10n.tag);
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxHeight: _kTagBtnHeight),
|
constraints: const BoxConstraints(maxHeight: _kTagBtnHeight),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
@@ -134,12 +132,12 @@ class _TagEditorState extends State<TagEditor> {
|
|||||||
void _showAddTagDialog() {
|
void _showAddTagDialog() {
|
||||||
final textEditingController = TextEditingController();
|
final textEditingController = TextEditingController();
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(widget.s.add),
|
title: Text(l10n.add),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.tag,
|
icon: Icons.tag,
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
hint: widget.s.tag,
|
hint: l10n.tag,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -149,7 +147,7 @@ class _TagEditorState extends State<TagEditor> {
|
|||||||
widget.onChanged?.call(widget.tags);
|
widget.onChanged?.call(widget.tags);
|
||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
child: Text(widget.s.add),
|
child: Text(l10n.add),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -158,12 +156,12 @@ class _TagEditorState extends State<TagEditor> {
|
|||||||
void _showRenameDialog(String tag) {
|
void _showRenameDialog(String tag) {
|
||||||
final textEditingController = TextEditingController(text: tag);
|
final textEditingController = TextEditingController(text: tag);
|
||||||
context.showRoundDialog(
|
context.showRoundDialog(
|
||||||
title: Text(widget.s.rename),
|
title: Text(l10n.rename),
|
||||||
child: Input(
|
child: Input(
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
icon: Icons.abc,
|
icon: Icons.abc,
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
hint: widget.s.tag,
|
hint: l10n.tag,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -174,7 +172,7 @@ class _TagEditorState extends State<TagEditor> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
},
|
},
|
||||||
child: Text(widget.s.rename),
|
child: Text(l10n.rename),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -196,14 +194,12 @@ class TagPicker<T extends TagPickable> extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TagPickerState<T extends TagPickable> extends State<TagPicker<T>> {
|
class _TagPickerState<T extends TagPickable> extends State<TagPicker<T>> {
|
||||||
late S _s;
|
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
final List<T> _selected = [];
|
final List<T> _selected = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +207,7 @@ class _TagPickerState<T extends TagPickable> extends State<TagPicker<T>> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final children = <Widget>[];
|
final children = <Widget>[];
|
||||||
if (widget.tags.isNotEmpty) {
|
if (widget.tags.isNotEmpty) {
|
||||||
children.add(Text(_s.tag));
|
children.add(Text(l10n.tag));
|
||||||
children.add(UIs.height13);
|
children.add(UIs.height13);
|
||||||
children.add(SizedBox(
|
children.add(SizedBox(
|
||||||
height: _kTagBtnHeight,
|
height: _kTagBtnHeight,
|
||||||
@@ -220,7 +216,7 @@ class _TagPickerState<T extends TagPickable> extends State<TagPicker<T>> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (widget.items.isNotEmpty) {
|
if (widget.items.isNotEmpty) {
|
||||||
children.add(Text(_s.all));
|
children.add(Text(l10n.all));
|
||||||
children.add(UIs.height13);
|
children.add(UIs.height13);
|
||||||
children.add(SizedBox(
|
children.add(SizedBox(
|
||||||
height: _kTagBtnHeight,
|
height: _kTagBtnHeight,
|
||||||
@@ -229,15 +225,15 @@ class _TagPickerState<T extends TagPickable> extends State<TagPicker<T>> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
final child = widget.tags.isEmpty && widget.items.isEmpty
|
final child = widget.tags.isEmpty && widget.items.isEmpty
|
||||||
? Text(_s.noOptions)
|
? Text(l10n.noOptions)
|
||||||
: Column(mainAxisSize: MainAxisSize.min, children: children);
|
: Column(mainAxisSize: MainAxisSize.min, children: children);
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text(_s.choose),
|
title: Text(l10n.choose),
|
||||||
content: child,
|
content: child,
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(_selected),
|
onPressed: () => context.pop(_selected),
|
||||||
child: Text(_s.ok),
|
child: Text(l10n.ok),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user