mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
fix: can't quit app
This commit is contained in:
@@ -6,6 +6,7 @@ import 'package:toolbox/data/model/apt/upgrade_pkg_info.dart';
|
||||
import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/provider/apt.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
@@ -26,18 +27,17 @@ class AptManagePage extends StatefulWidget {
|
||||
class _AptManagePageState extends State<AptManagePage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late MediaQueryData _media;
|
||||
final greyStyle = const TextStyle(color: Colors.grey);
|
||||
final scrollController = ScrollController();
|
||||
final scrollControllerUpdate = ScrollController();
|
||||
final textController = TextEditingController();
|
||||
final _scrollController = ScrollController();
|
||||
final _scrollControllerUpdate = ScrollController();
|
||||
final _textController = TextEditingController();
|
||||
final _aptProvider = locator<AptProvider>();
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_media = MediaQuery.of(context);
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -53,7 +53,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
.servers
|
||||
.firstWhere((e) => e.info == widget.spi);
|
||||
if (si.client == null) {
|
||||
showSnackBar(context, Text(s.waitConnection));
|
||||
showSnackBar(context, Text(_s.waitConnection));
|
||||
Navigator.of(context).pop();
|
||||
return;
|
||||
}
|
||||
@@ -61,9 +61,10 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
_aptProvider.init(
|
||||
si.client!,
|
||||
si.status.sysVer.dist,
|
||||
() => scrollController.jumpTo(scrollController.position.maxScrollExtent),
|
||||
() => scrollControllerUpdate
|
||||
.jumpTo(scrollController.position.maxScrollExtent),
|
||||
() =>
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent),
|
||||
() => _scrollControllerUpdate
|
||||
.jumpTo(_scrollController.position.maxScrollExtent),
|
||||
onPwdRequest,
|
||||
widget.spi.user,
|
||||
);
|
||||
@@ -71,14 +72,14 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
if (textController.text == '') {
|
||||
if (_textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(_s.ok)),
|
||||
],
|
||||
);
|
||||
return;
|
||||
@@ -92,12 +93,12 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
controller: textController,
|
||||
controller: _textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
decoration: InputDecoration(
|
||||
labelText: s.pwd,
|
||||
labelText: _s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
@@ -106,16 +107,16 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel)),
|
||||
child: Text(_s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
_s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
)),
|
||||
],
|
||||
);
|
||||
return textController.text.trim();
|
||||
return _textController.text.trim();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -167,7 +168,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(18),
|
||||
controller: scrollControllerUpdate,
|
||||
controller: _scrollControllerUpdate,
|
||||
child: Text(apt.updateLog!),
|
||||
),
|
||||
),
|
||||
@@ -180,7 +181,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
padding: const EdgeInsets.all(17),
|
||||
child: UrlText(
|
||||
text:
|
||||
'${s.experimentalFeature}\n${s.reportBugsOnGithubIssue(issueUrl)}',
|
||||
'${_s.experimentalFeature}\n${_s.reportBugsOnGithubIssue(issueUrl)}',
|
||||
replace: 'Github Issue',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@@ -196,7 +197,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
if (apt.upgradeable!.isEmpty) {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
s.noUpdateAvailable,
|
||||
_s.noUpdateAvailable,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
subtitle: const Text('>_<', textAlign: TextAlign.center),
|
||||
@@ -206,24 +207,24 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ExpansionTile(
|
||||
title: Text(s.foundNUpdate(apt.upgradeable!.length)),
|
||||
title: Text(_s.foundNUpdate(apt.upgradeable!.length)),
|
||||
subtitle: Text(
|
||||
apt.upgradeable!.map((e) => e.package).join(', '),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: greyStyle,
|
||||
style: grey,
|
||||
),
|
||||
children: apt.upgradeLog == null
|
||||
? [
|
||||
TextButton(
|
||||
child: Text(s.updateAll),
|
||||
child: Text(_s.updateAll),
|
||||
onPressed: () {
|
||||
apt.upgrade();
|
||||
}),
|
||||
SizedBox(
|
||||
height: _media.size.height * 0.73,
|
||||
child: ListView(
|
||||
controller: scrollController,
|
||||
controller: _scrollController,
|
||||
children: apt.upgradeable!
|
||||
.map((e) => _buildUpdateItem(e, apt))
|
||||
.toList(),
|
||||
@@ -237,7 +238,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
constraints: const BoxConstraints.expand(),
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(18),
|
||||
controller: scrollController,
|
||||
controller: _scrollController,
|
||||
child: Text(apt.upgradeLog!),
|
||||
),
|
||||
),
|
||||
@@ -253,7 +254,7 @@ class _AptManagePageState extends State<AptManagePage>
|
||||
title: Text(info.package),
|
||||
subtitle: Text(
|
||||
'${info.nowVersion} -> ${info.newVersion}',
|
||||
style: greyStyle,
|
||||
style: grey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ const backupFormatVersion = 1;
|
||||
class BackupPage extends StatelessWidget {
|
||||
BackupPage({Key? key}) : super(key: key);
|
||||
|
||||
final setting = locator<SettingStore>();
|
||||
final server = locator<ServerStore>();
|
||||
final snippet = locator<SnippetStore>();
|
||||
final privateKey = locator<PrivateKeyStore>();
|
||||
final _setting = locator<SettingStore>();
|
||||
final _server = locator<ServerStore>();
|
||||
final _snippet = locator<SnippetStore>();
|
||||
final _privateKey = locator<PrivateKeyStore>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -100,12 +100,12 @@ class BackupPage extends StatelessWidget {
|
||||
Backup(
|
||||
backupFormatVersion,
|
||||
DateTime.now().toString().split('.').first,
|
||||
server.fetch(),
|
||||
snippet.fetch(),
|
||||
privateKey.fetch(),
|
||||
setting.primaryColor.fetch() ?? Colors.pinkAccent.value,
|
||||
setting.serverStatusUpdateInterval.fetch() ?? 2,
|
||||
setting.launchPage.fetch() ?? 0,
|
||||
_server.fetch(),
|
||||
_snippet.fetch(),
|
||||
_privateKey.fetch(),
|
||||
_setting.primaryColor.fetch() ?? Colors.pinkAccent.value,
|
||||
_setting.serverStatusUpdateInterval.fetch() ?? 2,
|
||||
_setting.launchPage.fetch() ?? 0,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -186,18 +186,18 @@ class BackupPage extends StatelessWidget {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
for (final s in backup.snippets) {
|
||||
snippet.put(s);
|
||||
_snippet.put(s);
|
||||
}
|
||||
for (final s in backup.spis) {
|
||||
server.put(s);
|
||||
_server.put(s);
|
||||
}
|
||||
for (final s in backup.keys) {
|
||||
privateKey.put(s);
|
||||
_privateKey.put(s);
|
||||
}
|
||||
setting.primaryColor.put(backup.primaryColor);
|
||||
setting.serverStatusUpdateInterval
|
||||
_setting.primaryColor.put(backup.primaryColor);
|
||||
_setting.serverStatusUpdateInterval
|
||||
.put(backup.serverStatusUpdateInterval);
|
||||
setting.launchPage.put(backup.launchPage);
|
||||
_setting.launchPage.put(backup.launchPage);
|
||||
Navigator.of(context).pop();
|
||||
showSnackBar(context, Text(s.restoreSuccess));
|
||||
},
|
||||
|
||||
@@ -21,7 +21,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
late TextEditingController _textEditingControllerResult;
|
||||
late MediaQueryData _media;
|
||||
late ThemeData _theme;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
int _typeOptionIndex = 0;
|
||||
|
||||
@@ -37,7 +37,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
super.didChangeDependencies();
|
||||
_media = MediaQuery.of(context);
|
||||
_theme = Theme.of(context);
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -65,7 +65,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
showSnackBar(context, Text('Error: \n$e'));
|
||||
}
|
||||
},
|
||||
tooltip: s.convert,
|
||||
tooltip: _s.convert,
|
||||
heroTag: 'convert fab',
|
||||
child: const Icon(Icons.send),
|
||||
),
|
||||
@@ -84,7 +84,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
case 3:
|
||||
return Uri.decodeFull(text);
|
||||
default:
|
||||
return s.unkownConvertMode;
|
||||
return _s.unkownConvertMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +96,8 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
}
|
||||
|
||||
Widget _buildTypeOption() {
|
||||
final decode = s.decode;
|
||||
final encode = s.encode;
|
||||
final decode = _s.decode;
|
||||
final encode = _s.encode;
|
||||
final List<String> typeOption = [
|
||||
'Base64 $decode',
|
||||
'Base64 $encode',
|
||||
@@ -113,7 +113,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||
child: Icon(Icons.change_circle, semanticLabel: s.upsideDown),
|
||||
child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown),
|
||||
onPressed: () {
|
||||
final temp = _textEditingController.text;
|
||||
_textEditingController.text = _textEditingControllerResult.text;
|
||||
@@ -124,7 +124,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(primaryColor),
|
||||
),
|
||||
child: Icon(Icons.copy, semanticLabel: s.copy),
|
||||
child: Icon(Icons.copy, semanticLabel: _s.copy),
|
||||
onPressed: () => Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: _textEditingControllerResult.text == ''
|
||||
@@ -150,7 +150,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
color: primaryColor),
|
||||
),
|
||||
Text(
|
||||
s.currentMode,
|
||||
_s.currentMode,
|
||||
textScaleFactor: 1.0,
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(fontSize: 9.0, color: Colors.grey),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:toolbox/data/model/server/server_private_info.dart';
|
||||
import 'package:toolbox/data/provider/docker.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/error.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/data/res/url.dart';
|
||||
import 'package:toolbox/data/store/docker.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
@@ -26,9 +27,8 @@ class DockerManagePage extends StatefulWidget {
|
||||
|
||||
class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final _docker = locator<DockerProvider>();
|
||||
final greyTextStyle = const TextStyle(color: Colors.grey);
|
||||
final textController = TextEditingController();
|
||||
late S s;
|
||||
final _textController = TextEditingController();
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -39,7 +39,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -50,7 +50,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
.firstWhere((element) => element.info == widget.spi)
|
||||
.client;
|
||||
if (client == null) {
|
||||
showSnackBar(context, Text(s.noClient));
|
||||
showSnackBar(context, Text(_s.noClient));
|
||||
Navigator.of(context).pop();
|
||||
return;
|
||||
}
|
||||
@@ -90,14 +90,14 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final argsCtrl = TextEditingController();
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.newContainer,
|
||||
_s.newContainer,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.dockerImage, hintText: 'ubuntu:22.10'),
|
||||
labelText: _s.dockerImage, hintText: 'ubuntu:22.10'),
|
||||
controller: imageCtrl,
|
||||
autocorrect: false,
|
||||
),
|
||||
@@ -105,14 +105,15 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
keyboardType: TextInputType.text,
|
||||
controller: nameCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.dockerContainerName, hintText: 'ubuntu22'),
|
||||
labelText: _s.dockerContainerName, hintText: 'ubuntu22'),
|
||||
autocorrect: false,
|
||||
),
|
||||
TextField(
|
||||
keyboardType: TextInputType.text,
|
||||
controller: argsCtrl,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.extraArgs, hintText: '-p 2222:22 -v ~/.xxx/:/xxx'),
|
||||
labelText: _s.extraArgs,
|
||||
hintText: '-p 2222:22 -v ~/.xxx/:/xxx'),
|
||||
autocorrect: false,
|
||||
),
|
||||
],
|
||||
@@ -120,7 +121,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
@@ -133,7 +134,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -142,22 +143,22 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Future<void> _showAddCmdPreview(String cmd) async {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.preview,
|
||||
_s.preview,
|
||||
Text(cmd),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
final result = await _docker.run(cmd);
|
||||
if (result != null) {
|
||||
showSnackBar(context, Text(getErrMsg(result) ?? s.unknownError));
|
||||
showSnackBar(context, Text(getErrMsg(result) ?? _s.unknownError));
|
||||
}
|
||||
},
|
||||
child: Text(s.run),
|
||||
child: Text(_s.run),
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -184,10 +185,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(context, s.attention, Text(s.fieldMustNotEmpty), [
|
||||
if (_textController.text == '') {
|
||||
showRoundDialog(context, _s.attention, Text(_s.fieldMustNotEmpty), [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)),
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(_s.ok)),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
@@ -200,12 +201,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
controller: textController,
|
||||
controller: _textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => onSubmitted(),
|
||||
decoration: InputDecoration(
|
||||
labelText: s.pwd,
|
||||
labelText: _s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
@@ -214,18 +215,18 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => onSubmitted(),
|
||||
child: Text(
|
||||
s.ok,
|
||||
_s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
return textController.text.trim();
|
||||
return _textController.text.trim();
|
||||
}
|
||||
|
||||
Widget _buildMain(DockerProvider docker) {
|
||||
@@ -260,7 +261,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
padding: const EdgeInsets.all(7),
|
||||
children: [
|
||||
_buildLoading(docker),
|
||||
_buildVersion(docker.edition ?? s.unknown, docker.version ?? s.unknown),
|
||||
_buildVersion(
|
||||
docker.edition ?? _s.unknown, docker.version ?? _s.unknown),
|
||||
_buildPsItems(running, docker),
|
||||
_buildImages(docker),
|
||||
_buildEditHost(running, docker),
|
||||
@@ -273,10 +275,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
return const SizedBox();
|
||||
}
|
||||
return ExpansionTile(
|
||||
title: Text(s.imagesList),
|
||||
title: Text(_s.imagesList),
|
||||
subtitle: Text(
|
||||
s.dockerImagesFmt(docker.images!.length),
|
||||
style: greyTextStyle,
|
||||
_s.dockerImagesFmt(docker.images!.length),
|
||||
style: grey,
|
||||
),
|
||||
children: docker.images!
|
||||
.map(
|
||||
@@ -289,7 +291,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final result = await _docker.run('docker rmi ${e.id} -f');
|
||||
if (result != null) {
|
||||
showSnackBar(
|
||||
context, Text(getErrMsg(result) ?? s.unknownError));
|
||||
context, Text(getErrMsg(result) ?? _s.unknownError));
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -322,12 +324,12 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
s.dockerEmptyRunningItems,
|
||||
_s.dockerEmptyRunningItems,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => _showEditHostDialog(docker),
|
||||
child: Text(s.dockerEditHost),
|
||||
child: Text(_s.dockerEditHost),
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -337,7 +339,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Future<void> _showEditHostDialog(DockerProvider docker) async {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.dockerEditHost,
|
||||
_s.dockerEditHost,
|
||||
TextField(
|
||||
maxLines: 1,
|
||||
autocorrect: false,
|
||||
@@ -352,7 +354,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -362,16 +364,16 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
var errStr = '';
|
||||
switch (err.type) {
|
||||
case DockerErrType.noClient:
|
||||
errStr = s.noClient;
|
||||
errStr = _s.noClient;
|
||||
break;
|
||||
case DockerErrType.notInstalled:
|
||||
errStr = s.dockerNotInstalled;
|
||||
errStr = _s.dockerNotInstalled;
|
||||
break;
|
||||
case DockerErrType.invalidVersion:
|
||||
errStr = s.invalidVersion;
|
||||
errStr = _s.invalidVersion;
|
||||
break;
|
||||
default:
|
||||
errStr = err.message ?? s.unknown;
|
||||
errStr = err.message ?? _s.unknown;
|
||||
}
|
||||
return Text(errStr);
|
||||
}
|
||||
@@ -380,18 +382,18 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
switch (err.type) {
|
||||
case DockerErrType.notInstalled:
|
||||
return UrlText(
|
||||
text: s.installDockerWithUrl,
|
||||
replace: s.install,
|
||||
text: _s.installDockerWithUrl,
|
||||
replace: _s.install,
|
||||
);
|
||||
case DockerErrType.noClient:
|
||||
return Text(s.waitConnection);
|
||||
return Text(_s.waitConnection);
|
||||
case DockerErrType.invalidVersion:
|
||||
return UrlText(
|
||||
text: s.invalidVersionHelp(issueUrl),
|
||||
text: _s.invalidVersionHelp(issueUrl),
|
||||
replace: 'Github',
|
||||
);
|
||||
default:
|
||||
return Text(s.unknownError);
|
||||
return Text(_s.unknownError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,8 +409,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
|
||||
Widget _buildPsItems(List<DockerPsItem> running, DockerProvider docker) {
|
||||
return ExpansionTile(
|
||||
title: Text(s.containerStatus),
|
||||
subtitle: Text(_buildSubtitle(running), style: greyTextStyle),
|
||||
title: Text(_s.containerStatus),
|
||||
subtitle: Text(_buildSubtitle(running), style: grey),
|
||||
children: running.map(
|
||||
(item) {
|
||||
return ListTile(
|
||||
@@ -437,7 +439,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
],
|
||||
onSelected: (value) {
|
||||
if (busy) {
|
||||
showSnackBar(context, Text(s.isBusy));
|
||||
showSnackBar(context, Text(_s.isBusy));
|
||||
return;
|
||||
}
|
||||
final item = value as DropdownBtnItem;
|
||||
@@ -460,8 +462,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final runningCount = running.where((element) => element.running).length;
|
||||
final stoped = running.length - runningCount;
|
||||
if (stoped == 0) {
|
||||
return s.dockerStatusRunningFmt(runningCount);
|
||||
return _s.dockerStatusRunningFmt(runningCount);
|
||||
}
|
||||
return s.dockerStatusRunningAndStoppedFmt(runningCount, stoped);
|
||||
return _s.dockerStatusRunningAndStoppedFmt(runningCount, stoped);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
late final PageController _pageController;
|
||||
late int _selectIndex;
|
||||
late double _width;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -59,7 +59,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
_width = MediaQuery.of(context).size.width;
|
||||
}
|
||||
|
||||
@@ -84,20 +84,6 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return WillPopScope(
|
||||
child: _buildMain(context),
|
||||
onWillPop: () {
|
||||
final scaffold = Scaffold.of(context);
|
||||
if (scaffold.isDrawerOpen) {
|
||||
scaffold.closeDrawer();
|
||||
return Future.value(false);
|
||||
}
|
||||
return Future.value(true);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMain(BuildContext context) {
|
||||
return Scaffold(
|
||||
drawer: _buildDrawer(),
|
||||
appBar: AppBar(
|
||||
@@ -105,7 +91,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.developer_mode, size: 23),
|
||||
tooltip: s.debug,
|
||||
tooltip: _s.debug,
|
||||
onPressed: () =>
|
||||
AppRoute(const DebugPage(), 'Debug Page').go(context),
|
||||
),
|
||||
@@ -126,7 +112,6 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
}
|
||||
|
||||
Widget _buildItem(int idx, NavigationItem item, bool isSelected) {
|
||||
bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
||||
final width = _width / tabItems.length;
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 377),
|
||||
@@ -135,7 +120,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
width: isSelected ? width : width - 17,
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? isDarkMode
|
||||
? isDarkMode(context)
|
||||
? Colors.white12
|
||||
: Colors.black.withOpacity(0.07)
|
||||
: Colors.transparent,
|
||||
@@ -195,57 +180,57 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.settings),
|
||||
title: Text(s.setting),
|
||||
title: Text(_s.setting),
|
||||
onTap: () =>
|
||||
AppRoute(const SettingPage(), 'Setting').go(context),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.vpn_key),
|
||||
title: Text(s.privateKey),
|
||||
title: Text(_s.privateKey),
|
||||
onTap: () => AppRoute(
|
||||
const StoredPrivateKeysPage(), 'private key list')
|
||||
.go(context),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.download),
|
||||
title: Text(s.download),
|
||||
title: Text(_s.download),
|
||||
onTap: () =>
|
||||
AppRoute(const SFTPDownloadedPage(), 'snippet list')
|
||||
.go(context),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.import_export),
|
||||
title: Text(s.backup),
|
||||
title: Text(_s.backup),
|
||||
onTap: () =>
|
||||
AppRoute(BackupPage(), 'backup page').go(context),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.info),
|
||||
title: Text(s.feedback),
|
||||
title: Text(_s.feedback),
|
||||
onTap: () => showRoundDialog(
|
||||
context,
|
||||
s.feedback,
|
||||
Text(s.feedbackOnGithub),
|
||||
_s.feedback,
|
||||
Text(_s.feedbackOnGithub),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Clipboard.setData(
|
||||
const ClipboardData(text: issueUrl)),
|
||||
child: Text(s.copy),
|
||||
child: Text(_s.copy),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => openUrl(issueUrl),
|
||||
child: Text(s.feedback),
|
||||
child: Text(_s.feedback),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close),
|
||||
child: Text(_s.close),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.snippet_folder),
|
||||
title: Text(s.snippet),
|
||||
title: Text(_s.snippet),
|
||||
onTap: () => AppRoute(const SnippetListPage(), 'snippet list')
|
||||
.go(context),
|
||||
),
|
||||
@@ -256,9 +241,10 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
applicationIcon: _buildIcon(),
|
||||
aboutBoxChildren: [
|
||||
UrlText(
|
||||
text: s.madeWithLove(myGithub), replace: 'lollipopkit'),
|
||||
text: _s.madeWithLove(myGithub),
|
||||
replace: 'lollipopkit'),
|
||||
UrlText(
|
||||
text: s.aboutThanks,
|
||||
text: _s.aboutThanks,
|
||||
),
|
||||
const UrlText(
|
||||
text: rainSunMeGithub,
|
||||
@@ -269,7 +255,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
replace: 'fecture',
|
||||
)
|
||||
],
|
||||
child: Text(s.license),
|
||||
child: Text(_s.license),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:toolbox/core/utils.dart';
|
||||
import 'package:toolbox/data/model/server/ping_result.dart';
|
||||
import 'package:toolbox/data/provider/server.dart';
|
||||
import 'package:toolbox/data/res/color.dart';
|
||||
import 'package:toolbox/data/res/font_style.dart';
|
||||
import 'package:toolbox/generated/l10n.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
@@ -29,9 +30,6 @@ class _PingPageState extends State<PingPage>
|
||||
final List<PingResult> _results = [];
|
||||
final _serverProvider = locator<ServerProvider>();
|
||||
late S s;
|
||||
static const summaryTextStyle = TextStyle(
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -103,7 +101,7 @@ class _PingPageState extends State<PingPage>
|
||||
),
|
||||
subtitle: Text(
|
||||
_buildPingSummary(result, unknown, ms),
|
||||
style: summaryTextStyle,
|
||||
style: textSize11,
|
||||
),
|
||||
trailing: Text(
|
||||
'${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms',
|
||||
|
||||
@@ -21,42 +21,42 @@ class PrivateKeyEditPage extends StatefulWidget {
|
||||
|
||||
class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
with AfterLayoutMixin {
|
||||
final nameController = TextEditingController();
|
||||
final keyController = TextEditingController();
|
||||
final pwdController = TextEditingController();
|
||||
final nameNode = FocusNode();
|
||||
final keyNode = FocusNode();
|
||||
final pwdNode = FocusNode();
|
||||
|
||||
late FocusScopeNode focusScope;
|
||||
final _nameController = TextEditingController();
|
||||
final _keyController = TextEditingController();
|
||||
final _pwdController = TextEditingController();
|
||||
final _nameNode = FocusNode();
|
||||
final _keyNode = FocusNode();
|
||||
final _pwdNode = FocusNode();
|
||||
|
||||
late FocusScopeNode _focusScope;
|
||||
late PrivateKeyProvider _provider;
|
||||
late Widget loading;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
Widget _loading = const SizedBox();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_provider = locator<PrivateKeyProvider>();
|
||||
loading = const SizedBox();
|
||||
_loading = const SizedBox();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
focusScope = FocusScope.of(context);
|
||||
_s = S.of(context);
|
||||
_focusScope = FocusScope.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.info != null
|
||||
? IconButton(
|
||||
tooltip: s.delete,
|
||||
tooltip: _s.delete,
|
||||
onPressed: () {
|
||||
_provider.delInfo(widget.info!);
|
||||
Navigator.of(context).pop();
|
||||
@@ -69,48 +69,48 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
TextField(
|
||||
controller: nameController,
|
||||
controller: _nameController,
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: nameNode,
|
||||
onSubmitted: (_) => focusScope.requestFocus(keyNode),
|
||||
decoration: buildDecoration(s.name, icon: Icons.info),
|
||||
focusNode: _nameNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_keyNode),
|
||||
decoration: buildDecoration(_s.name, icon: Icons.info),
|
||||
),
|
||||
TextField(
|
||||
controller: keyController,
|
||||
controller: _keyController,
|
||||
autocorrect: false,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: keyNode,
|
||||
onSubmitted: (_) => focusScope.requestFocus(pwdNode),
|
||||
focusNode: _keyNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_pwdNode),
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(s.privateKey, icon: Icons.vpn_key),
|
||||
decoration: buildDecoration(_s.privateKey, icon: Icons.vpn_key),
|
||||
),
|
||||
TextField(
|
||||
controller: pwdController,
|
||||
controller: _pwdController,
|
||||
autocorrect: false,
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: pwdNode,
|
||||
focusNode: _pwdNode,
|
||||
obscureText: true,
|
||||
decoration: buildDecoration(s.pwd, icon: Icons.password),
|
||||
decoration: buildDecoration(_s.pwd, icon: Icons.password),
|
||||
),
|
||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||
loading
|
||||
_loading
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
tooltip: s.save,
|
||||
tooltip: _s.save,
|
||||
onPressed: () async {
|
||||
final name = nameController.text;
|
||||
final key = keyController.text.trim();
|
||||
final pwd = pwdController.text;
|
||||
final name = _nameController.text;
|
||||
final key = _keyController.text.trim();
|
||||
final pwd = _pwdController.text;
|
||||
if (name.isEmpty || key.isEmpty) {
|
||||
showSnackBar(context, Text(s.fieldMustNotEmpty));
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
setState(() {
|
||||
loading = const SizedBox(
|
||||
_loading = const SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
@@ -126,7 +126,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
haveErr = true;
|
||||
} finally {
|
||||
setState(() {
|
||||
loading = const SizedBox();
|
||||
_loading = const SizedBox();
|
||||
});
|
||||
}
|
||||
if (haveErr) return;
|
||||
@@ -145,9 +145,9 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
@override
|
||||
void afterFirstLayout(BuildContext context) {
|
||||
if (widget.info != null) {
|
||||
nameController.text = widget.info!.id;
|
||||
keyController.text = widget.info!.privateKey;
|
||||
pwdController.text = widget.info!.password;
|
||||
_nameController.text = widget.info!.id;
|
||||
_keyController.text = widget.info!.privateKey;
|
||||
_pwdController.text = widget.info!.password;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,20 +17,19 @@ class StoredPrivateKeysPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
||||
final _textStyle = TextStyle(color: primaryColor);
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.privateKey, style: textSize18),
|
||||
title: Text(_s.privateKey, style: textSize18),
|
||||
),
|
||||
body: Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
@@ -55,17 +54,14 @@ class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
||||
PrivateKeyEditPage(info: key.infos[idx]),
|
||||
'private key edit page')
|
||||
.go(context),
|
||||
child: Text(
|
||||
s.edit,
|
||||
style: _textStyle,
|
||||
),
|
||||
child: Text(_s.edit),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
})
|
||||
: Center(
|
||||
child: Text(s.noSavedPrivateKey),
|
||||
child: Text(_s.noSavedPrivateKey),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -24,13 +24,13 @@ class ServerDetailPage extends StatefulWidget {
|
||||
class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late MediaQueryData _media;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_media = MediaQuery.of(context);
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -315,7 +315,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
if (ns.devices.isEmpty) {
|
||||
children.add(Center(
|
||||
child: Text(
|
||||
s.noInterface,
|
||||
_s.noInterface,
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||
),
|
||||
));
|
||||
|
||||
@@ -25,25 +25,21 @@ class ServerEditPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
final nameController = TextEditingController();
|
||||
final ipController = TextEditingController();
|
||||
final portController = TextEditingController();
|
||||
final usernameController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final keyController = TextEditingController();
|
||||
final nameFocus = FocusNode();
|
||||
final ipFocus = FocusNode();
|
||||
final portFocus = FocusNode();
|
||||
final usernameFocus = FocusNode();
|
||||
|
||||
late FocusScopeNode focusScope;
|
||||
final _nameController = TextEditingController();
|
||||
final _ipController = TextEditingController();
|
||||
final _portController = TextEditingController();
|
||||
final _usernameController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final _nameFocus = FocusNode();
|
||||
final _ipFocus = FocusNode();
|
||||
final _portFocus = FocusNode();
|
||||
final _usernameFocus = FocusNode();
|
||||
|
||||
late FocusScopeNode _focusScope;
|
||||
late ServerProvider _serverProvider;
|
||||
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
bool usePublicKey = false;
|
||||
|
||||
int? _pubKeyIndex;
|
||||
PrivateKeyInfo? _keyInfo;
|
||||
|
||||
@@ -56,23 +52,23 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
focusScope = FocusScope.of(context);
|
||||
_s = S.of(context);
|
||||
_focusScope = FocusScope.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.spi != null
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.sureToDeleteServer(widget.spi!.name)),
|
||||
_s.attention,
|
||||
Text(_s.sureToDeleteServer(widget.spi!.name)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -81,13 +77,13 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
s.ok,
|
||||
_s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -104,44 +100,44 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextField(
|
||||
controller: nameController,
|
||||
controller: _nameController,
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: nameFocus,
|
||||
onSubmitted: (_) => focusScope.requestFocus(ipFocus),
|
||||
decoration: buildDecoration(s.name,
|
||||
icon: Icons.info, hint: s.exampleName),
|
||||
focusNode: _nameFocus,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_ipFocus),
|
||||
decoration: buildDecoration(_s.name,
|
||||
icon: Icons.info, hint: _s.exampleName),
|
||||
),
|
||||
TextField(
|
||||
controller: ipController,
|
||||
controller: _ipController,
|
||||
keyboardType: TextInputType.text,
|
||||
onSubmitted: (_) => focusScope.requestFocus(portFocus),
|
||||
focusNode: ipFocus,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_portFocus),
|
||||
focusNode: _ipFocus,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(s.host,
|
||||
decoration: buildDecoration(_s.host,
|
||||
icon: Icons.storage, hint: 'example.com'),
|
||||
),
|
||||
TextField(
|
||||
controller: portController,
|
||||
controller: _portController,
|
||||
keyboardType: TextInputType.number,
|
||||
focusNode: portFocus,
|
||||
onSubmitted: (_) => focusScope.requestFocus(usernameFocus),
|
||||
decoration: buildDecoration(s.port,
|
||||
focusNode: _portFocus,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_usernameFocus),
|
||||
decoration: buildDecoration(_s.port,
|
||||
icon: Icons.format_list_numbered, hint: '22'),
|
||||
),
|
||||
TextField(
|
||||
controller: usernameController,
|
||||
controller: _usernameController,
|
||||
keyboardType: TextInputType.text,
|
||||
focusNode: usernameFocus,
|
||||
focusNode: _usernameFocus,
|
||||
autocorrect: false,
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(s.user,
|
||||
decoration: buildDecoration(_s.user,
|
||||
icon: Icons.account_box, hint: 'root'),
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
Row(
|
||||
children: [
|
||||
Text(s.keyAuth),
|
||||
Text(_s.keyAuth),
|
||||
Switch(
|
||||
value: usePublicKey,
|
||||
onChanged: (val) => setState(() => usePublicKey = val)),
|
||||
@@ -149,11 +145,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
),
|
||||
!usePublicKey
|
||||
? TextField(
|
||||
controller: passwordController,
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: buildDecoration(s.pwd,
|
||||
icon: Icons.password, hint: s.pwd),
|
||||
decoration: buildDecoration(_s.pwd,
|
||||
icon: Icons.password, hint: _s.pwd),
|
||||
onSubmitted: (_) => {},
|
||||
)
|
||||
: const SizedBox(),
|
||||
@@ -175,7 +171,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
.toList();
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(s.addPrivateKey),
|
||||
title: Text(_s.addPrivateKey),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
@@ -192,7 +188,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
tilePadding: EdgeInsets.zero,
|
||||
childrenPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
s.choosePrivateKey,
|
||||
_s.choosePrivateKey,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
children: tiles,
|
||||
@@ -206,22 +202,22 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.send),
|
||||
onPressed: () async {
|
||||
if (ipController.text == '') {
|
||||
showSnackBar(context, Text(s.plzEnterHost));
|
||||
if (_ipController.text == '') {
|
||||
showSnackBar(context, Text(_s.plzEnterHost));
|
||||
return;
|
||||
}
|
||||
if (!usePublicKey && passwordController.text == '') {
|
||||
if (!usePublicKey && _passwordController.text == '') {
|
||||
final cancel = await showRoundDialog<bool>(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.sureNoPwd),
|
||||
_s.attention,
|
||||
Text(_s.sureNoPwd),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: Text(s.ok)),
|
||||
child: Text(_s.ok)),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: Text(s.cancel))
|
||||
child: Text(_s.cancel))
|
||||
],
|
||||
barrierDismiss: false,
|
||||
);
|
||||
@@ -230,26 +226,26 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
}
|
||||
}
|
||||
if (usePublicKey && _pubKeyIndex == -1) {
|
||||
showSnackBar(context, Text(s.plzSelectKey));
|
||||
showSnackBar(context, Text(_s.plzSelectKey));
|
||||
return;
|
||||
}
|
||||
if (usernameController.text == '') {
|
||||
usernameController.text = 'root';
|
||||
if (_usernameController.text == '') {
|
||||
_usernameController.text = 'root';
|
||||
}
|
||||
if (portController.text == '') {
|
||||
portController.text = '22';
|
||||
if (_portController.text == '') {
|
||||
_portController.text = '22';
|
||||
}
|
||||
|
||||
if (widget.spi != null && widget.spi!.pubKeyId != null) {
|
||||
_keyInfo ??= locator<PrivateKeyStore>().get(widget.spi!.pubKeyId!);
|
||||
}
|
||||
|
||||
final authorization = passwordController.text;
|
||||
final authorization = _passwordController.text;
|
||||
final spi = ServerPrivateInfo(
|
||||
name: nameController.text,
|
||||
ip: ipController.text,
|
||||
port: int.parse(portController.text),
|
||||
user: usernameController.text,
|
||||
name: _nameController.text,
|
||||
ip: _ipController.text,
|
||||
port: int.parse(_portController.text),
|
||||
user: _usernameController.text,
|
||||
pwd: authorization,
|
||||
pubKeyId: usePublicKey ? _keyInfo!.id : null,
|
||||
);
|
||||
@@ -282,12 +278,12 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
@override
|
||||
void afterFirstLayout(BuildContext context) {
|
||||
if (widget.spi != null) {
|
||||
nameController.text = widget.spi?.name ?? '';
|
||||
ipController.text = widget.spi?.ip ?? '';
|
||||
portController.text = (widget.spi?.port ?? 22).toString();
|
||||
usernameController.text = widget.spi?.user ?? '';
|
||||
_nameController.text = widget.spi?.name ?? '';
|
||||
_ipController.text = widget.spi?.ip ?? '';
|
||||
_portController.text = (widget.spi?.port ?? 22).toString();
|
||||
_usernameController.text = widget.spi?.user ?? '';
|
||||
if (widget.spi?.pubKeyId == null) {
|
||||
passwordController.text = widget.spi?.pwd ?? '';
|
||||
_passwordController.text = widget.spi?.pwd ?? '';
|
||||
} else {
|
||||
usePublicKey = true;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
late MediaQueryData _media;
|
||||
late ThemeData _theme;
|
||||
late Color _primaryColor;
|
||||
|
||||
late ServerProvider _serverProvider;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -49,7 +48,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
_media = MediaQuery.of(context);
|
||||
_theme = Theme.of(context);
|
||||
_primaryColor = primaryColor;
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -60,7 +59,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
if (pro.servers.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
s.serverTabEmpty,
|
||||
_s.serverTabEmpty,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
@@ -87,7 +86,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
onPressed: () =>
|
||||
AppRoute(const ServerEditPage(), 'Add server info page')
|
||||
.go(context),
|
||||
tooltip: s.addAServer,
|
||||
tooltip: _s.addAServer,
|
||||
heroTag: 'server page fab',
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
@@ -155,8 +154,8 @@ class _ServerPageState extends State<ServerPage>
|
||||
hasError
|
||||
? GestureDetector(
|
||||
onTap: () => showRoundDialog(
|
||||
context, s.error, Text(ss.failedInfo ?? ''), []),
|
||||
child: Text(s.clickSee, style: style))
|
||||
context, _s.error, Text(ss.failedInfo ?? ''), []),
|
||||
child: Text(_s.clickSee, style: style))
|
||||
: Text(topRightStr, style: style, textScaleFactor: 1.0),
|
||||
_buildMoreBtn(spi),
|
||||
],
|
||||
@@ -248,11 +247,11 @@ class _ServerPageState extends State<ServerPage>
|
||||
String? failedInfo) {
|
||||
switch (cs) {
|
||||
case ServerConnectionState.disconnected:
|
||||
return s.disconnected;
|
||||
return _s.disconnected;
|
||||
case ServerConnectionState.connected:
|
||||
if (temp == '') {
|
||||
if (upTime == '') {
|
||||
return s.serverTabLoading;
|
||||
return _s.serverTabLoading;
|
||||
} else {
|
||||
return upTime;
|
||||
}
|
||||
@@ -264,17 +263,17 @@ class _ServerPageState extends State<ServerPage>
|
||||
}
|
||||
}
|
||||
case ServerConnectionState.connecting:
|
||||
return s.serverTabConnecting;
|
||||
return _s.serverTabConnecting;
|
||||
case ServerConnectionState.failed:
|
||||
if (failedInfo == null) {
|
||||
return s.serverTabFailed;
|
||||
return _s.serverTabFailed;
|
||||
}
|
||||
if (failedInfo.contains('encypted')) {
|
||||
return s.serverTabPlzSave;
|
||||
return _s.serverTabPlzSave;
|
||||
}
|
||||
return failedInfo;
|
||||
default:
|
||||
return s.serverTabUnkown;
|
||||
return _s.serverTabUnkown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
late final ServerProvider _serverProvider;
|
||||
late MediaQueryData _media;
|
||||
late ThemeData _theme;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
var _intervalValue = 0.0;
|
||||
|
||||
@@ -40,7 +40,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
priColor = primaryColor;
|
||||
_media = MediaQuery.of(context);
|
||||
_theme = Theme.of(context);
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -56,7 +56,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.setting),
|
||||
title: Text(_s.setting),
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(17),
|
||||
@@ -76,12 +76,12 @@ class _SettingPageState extends State<SettingPage> {
|
||||
String display;
|
||||
if (app.newestBuild != null) {
|
||||
if (app.newestBuild! > BuildData.build) {
|
||||
display = s.versionHaveUpdate(app.newestBuild!);
|
||||
display = _s.versionHaveUpdate(app.newestBuild!);
|
||||
} else {
|
||||
display = s.versionUpdated(BuildData.build);
|
||||
display = _s.versionUpdated(BuildData.build);
|
||||
}
|
||||
} else {
|
||||
display = s.versionUnknownUpdate(BuildData.build);
|
||||
display = _s.versionUnknownUpdate(BuildData.build);
|
||||
}
|
||||
return ListTile(
|
||||
contentPadding: roundRectCardPadding,
|
||||
@@ -103,15 +103,15 @@ class _SettingPageState extends State<SettingPage> {
|
||||
childrenPadding: roundRectCardPadding,
|
||||
textColor: priColor,
|
||||
title: Text(
|
||||
s.updateServerStatusInterval,
|
||||
_s.updateServerStatusInterval,
|
||||
style: textSize13,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
subtitle: Text(
|
||||
s.willTakEeffectImmediately,
|
||||
_s.willTakEeffectImmediately,
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||
),
|
||||
trailing: Text('${_intervalValue.toInt()} ${s.second}'),
|
||||
trailing: Text('${_intervalValue.toInt()} ${_s.second}'),
|
||||
children: [
|
||||
Slider(
|
||||
thumbColor: priColor,
|
||||
@@ -128,7 +128,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
_store.serverStatusUpdateInterval.put(val.toInt());
|
||||
_serverProvider.startAutoRefresh();
|
||||
},
|
||||
label: '${_intervalValue.toInt()} ${s.second}',
|
||||
label: '${_intervalValue.toInt()} ${_s.second}',
|
||||
divisions: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
@@ -136,7 +136,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
),
|
||||
_intervalValue == 0.0
|
||||
? Text(
|
||||
s.updateIntervalEqual0,
|
||||
_s.updateIntervalEqual0,
|
||||
style: const TextStyle(color: Colors.grey, fontSize: 12),
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
@@ -161,7 +161,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
s.appPrimaryColor,
|
||||
_s.appPrimaryColor,
|
||||
style: textSize13,
|
||||
),
|
||||
children: [_buildAppColorPicker(priColor), _buildColorPickerConfirmBtn()],
|
||||
@@ -193,7 +193,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
tilePadding: roundRectCardPadding,
|
||||
childrenPadding: roundRectCardPadding,
|
||||
title: Text(
|
||||
s.launchPage,
|
||||
_s.launchPage,
|
||||
style: textSize13,
|
||||
),
|
||||
trailing: ConstrainedBox(
|
||||
|
||||
@@ -23,8 +23,7 @@ class SFTPDownloadedPage extends StatefulWidget {
|
||||
class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
PathWithPrefix? _path;
|
||||
String? _prefixPath;
|
||||
late S s;
|
||||
late ThemeData _theme;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -39,15 +38,14 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_theme = Theme.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.download),
|
||||
title: Text(_s.download),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.downloading),
|
||||
@@ -68,7 +66,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: (() {
|
||||
if (_path!.path == _prefixPath) {
|
||||
showSnackBar(context, Text(s.alreadyLastDir));
|
||||
showSnackBar(context, Text(_s.alreadyLastDir));
|
||||
return;
|
||||
}
|
||||
_path!.update('..');
|
||||
@@ -80,18 +78,13 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
}
|
||||
|
||||
Widget _buildPath() {
|
||||
final color = _theme.scaffoldBackgroundColor;
|
||||
return Container(
|
||||
color: color,
|
||||
padding: const EdgeInsets.fromLTRB(11, 7, 11, 11),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Divider(),
|
||||
(_path?.path ?? s.loadingFiles).omitStartStr(
|
||||
style: TextStyle(
|
||||
color: color.isBrightColor ? Colors.black : Colors.white),
|
||||
)
|
||||
(_path?.path ?? _s.loadingFiles).omitStartStr(),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -142,30 +135,30 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
final fileName = file.path.split('/').last;
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.choose,
|
||||
_s.choose,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.delete),
|
||||
title: Text(s.delete),
|
||||
title: Text(_s.delete),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.sureDelete(fileName),
|
||||
_s.sureDelete(fileName),
|
||||
const SizedBox(),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(_s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
file.deleteSync();
|
||||
setState(() {});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -173,7 +166,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.open_in_new),
|
||||
title: Text(s.open),
|
||||
title: Text(_s.open),
|
||||
onTap: () {
|
||||
shareFiles(context, [file.absolute.path]);
|
||||
},
|
||||
@@ -183,7 +176,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: (() => Navigator.of(context).pop()),
|
||||
child: Text(s.close))
|
||||
child: Text(_s.close))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ class SFTPDownloadingPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -30,7 +30,7 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
s.download,
|
||||
_s.download,
|
||||
style: textSize18,
|
||||
),
|
||||
),
|
||||
@@ -42,7 +42,7 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
return Consumer<SftpDownloadProvider>(builder: (__, pro, _) {
|
||||
if (pro.status.isEmpty) {
|
||||
return Center(
|
||||
child: Text(s.sftpNoDownloadTask),
|
||||
child: Text(_s.sftpNoDownloadTask),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
@@ -81,7 +81,7 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
final time = status.spentTime.toString();
|
||||
return _wrapInCard(
|
||||
status,
|
||||
'${s.downloadFinished} ${s.spentTime(time == 'null' ? s.unknown : (time.substring(0, time.length - 7)))}',
|
||||
'${_s.downloadFinished} ${_s.spentTime(time == 'null' ? _s.unknown : (time.substring(0, time.length - 7)))}',
|
||||
trailing: IconButton(
|
||||
onPressed: () => shareFiles(context, [status.item.localPath]),
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
@@ -90,18 +90,18 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
case SftpWorkerStatus.downloading:
|
||||
return _wrapInCard(
|
||||
status,
|
||||
s.downloadStatus((status.progress ?? 0.0).toStringAsFixed(2),
|
||||
_s.downloadStatus((status.progress ?? 0.0).toStringAsFixed(2),
|
||||
(status.size ?? 0).convertBytes),
|
||||
trailing:
|
||||
CircularProgressIndicator(value: (status.progress ?? 0) / 100));
|
||||
case SftpWorkerStatus.preparing:
|
||||
return _wrapInCard(status, s.sftpDlPrepare, trailing: loadingIcon);
|
||||
return _wrapInCard(status, _s.sftpDlPrepare, trailing: loadingIcon);
|
||||
case SftpWorkerStatus.sshConnectted:
|
||||
return _wrapInCard(status, s.sftpSSHConnected, trailing: loadingIcon);
|
||||
return _wrapInCard(status, _s.sftpSSHConnected, trailing: loadingIcon);
|
||||
default:
|
||||
return _wrapInCard(
|
||||
status,
|
||||
s.unknown,
|
||||
_s.unknown,
|
||||
trailing: const Icon(
|
||||
Icons.error,
|
||||
size: 40,
|
||||
|
||||
@@ -35,13 +35,13 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
late MediaQueryData _media;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_media = MediaQuery.of(context);
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -61,24 +61,24 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
IconButton(
|
||||
onPressed: (() => showRoundDialog(
|
||||
context,
|
||||
s.choose,
|
||||
_s.choose,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.folder),
|
||||
title: Text(s.createFolder),
|
||||
title: Text(_s.createFolder),
|
||||
onTap: () => mkdir(context)),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.insert_drive_file),
|
||||
title: Text(s.createFile),
|
||||
title: Text(_s.createFile),
|
||||
onTap: () => newFile(context)),
|
||||
],
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close))
|
||||
child: Text(_s.close))
|
||||
],
|
||||
)),
|
||||
icon: const Icon(Icons.add),
|
||||
@@ -167,24 +167,24 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
void onItemPress(BuildContext context, SftpName file, bool showDownload) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.choose,
|
||||
_s.choose,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.delete),
|
||||
title: Text(s.delete),
|
||||
title: Text(_s.delete),
|
||||
onTap: () => delete(context, file),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.edit),
|
||||
title: Text(s.rename),
|
||||
title: Text(_s.rename),
|
||||
onTap: () => rename(context, file),
|
||||
),
|
||||
showDownload
|
||||
? ListTile(
|
||||
leading: const Icon(Icons.download),
|
||||
title: Text(s.download),
|
||||
title: Text(_s.download),
|
||||
onTap: () => download(context, file),
|
||||
)
|
||||
: const SizedBox()
|
||||
@@ -192,7 +192,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(), child: Text(s.cancel))
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(_s.cancel))
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -200,12 +201,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
void download(BuildContext context, SftpName name) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.download,
|
||||
Text('${s.dl2Local(name.filename)}\n${s.keepForeground}'),
|
||||
_s.download,
|
||||
Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(_s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
@@ -229,12 +230,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.goSftpDlPage,
|
||||
_s.goSftpDlPage,
|
||||
const SizedBox(),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
@@ -242,12 +243,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
AppRoute(const SFTPDownloadingPage(), 'sftp downloading')
|
||||
.go(context);
|
||||
},
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Text(s.download),
|
||||
child: Text(_s.download),
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -257,8 +258,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
Navigator.of(context).pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.sureDelete(file.filename)),
|
||||
_s.attention,
|
||||
Text(_s.sureDelete(file.filename)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
@@ -270,7 +271,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
listDir();
|
||||
},
|
||||
child: Text(
|
||||
s.delete,
|
||||
_s.delete,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
@@ -283,29 +284,29 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.createFolder,
|
||||
_s.createFolder,
|
||||
TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.name,
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok)),
|
||||
child: Text(_s.ok)),
|
||||
],
|
||||
);
|
||||
return;
|
||||
@@ -316,7 +317,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
listDir();
|
||||
},
|
||||
child: Text(
|
||||
s.ok,
|
||||
_s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
@@ -329,29 +330,29 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.createFile,
|
||||
_s.createFile,
|
||||
TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.name,
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -364,7 +365,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
listDir();
|
||||
},
|
||||
child: Text(
|
||||
s.ok,
|
||||
_s.ok,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
@@ -377,28 +378,28 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.rename,
|
||||
_s.rename,
|
||||
TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: s.name,
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel)),
|
||||
child: Text(_s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.fieldMustNotEmpty),
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -409,7 +410,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
listDir();
|
||||
},
|
||||
child: Text(
|
||||
s.rename,
|
||||
_s.rename,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
@@ -440,12 +441,12 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
} catch (e) {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.error,
|
||||
_s.error,
|
||||
Text(e.toString()),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.ok),
|
||||
child: Text(_s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
@@ -458,7 +459,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
Widget _buildDestSelector() {
|
||||
final str = _status.path?.path;
|
||||
return ExpansionTile(
|
||||
title: Text(_status.spi?.name ?? s.chooseDestination),
|
||||
title: Text(_status.spi?.name ?? _s.chooseDestination),
|
||||
subtitle: _status.selected
|
||||
? str!.omitStartStr(style: const TextStyle(color: Colors.grey))
|
||||
: null,
|
||||
|
||||
@@ -19,12 +19,12 @@ class SnippetEditPage extends StatefulWidget {
|
||||
|
||||
class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
with AfterLayoutMixin {
|
||||
final nameController = TextEditingController();
|
||||
final scriptController = TextEditingController();
|
||||
final scriptNode = FocusNode();
|
||||
final _nameController = TextEditingController();
|
||||
final _scriptController = TextEditingController();
|
||||
final _scriptNode = FocusNode();
|
||||
|
||||
late SnippetProvider _provider;
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -35,14 +35,14 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.edit, style: textSize18),
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.snippet != null
|
||||
? IconButton(
|
||||
@@ -50,7 +50,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
_provider.del(widget.snippet!);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
tooltip: s.delete,
|
||||
tooltip: _s.delete,
|
||||
icon: const Icon(Icons.delete))
|
||||
: const SizedBox()
|
||||
],
|
||||
@@ -59,30 +59,31 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
TextField(
|
||||
controller: nameController,
|
||||
controller: _nameController,
|
||||
keyboardType: TextInputType.text,
|
||||
onSubmitted: (_) => FocusScope.of(context).requestFocus(scriptNode),
|
||||
decoration: buildDecoration(s.name, icon: Icons.info),
|
||||
onSubmitted: (_) =>
|
||||
FocusScope.of(context).requestFocus(_scriptNode),
|
||||
decoration: buildDecoration(_s.name, icon: Icons.info),
|
||||
),
|
||||
TextField(
|
||||
controller: scriptController,
|
||||
controller: _scriptController,
|
||||
autocorrect: false,
|
||||
focusNode: scriptNode,
|
||||
focusNode: _scriptNode,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
keyboardType: TextInputType.text,
|
||||
enableSuggestions: false,
|
||||
decoration: buildDecoration(s.snippet, icon: Icons.code),
|
||||
decoration: buildDecoration(_s.snippet, icon: Icons.code),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.send),
|
||||
onPressed: () {
|
||||
final name = nameController.text;
|
||||
final script = scriptController.text;
|
||||
final name = _nameController.text;
|
||||
final script = _scriptController.text;
|
||||
if (name.isEmpty || script.isEmpty) {
|
||||
showSnackBar(context, Text(s.fieldMustNotEmpty));
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
final snippet = Snippet(name, script);
|
||||
@@ -100,8 +101,8 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
@override
|
||||
void afterFirstLayout(BuildContext context) {
|
||||
if (widget.snippet != null) {
|
||||
nameController.text = widget.snippet!.name;
|
||||
scriptController.text = widget.snippet!.script;
|
||||
_nameController.text = widget.snippet!.name;
|
||||
_scriptController.text = widget.snippet!.script;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,19 +27,19 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
|
||||
final _textStyle = TextStyle(color: primaryColor);
|
||||
|
||||
late S s;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
s = S.of(context);
|
||||
_s = S.of(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.snippet, style: textSize18),
|
||||
title: Text(_s.snippet, style: textSize18),
|
||||
),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
@@ -79,7 +79,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
'snippet edit page')
|
||||
.go(context),
|
||||
child: Text(
|
||||
s.edit,
|
||||
_s.edit,
|
||||
style: _textStyle,
|
||||
),
|
||||
),
|
||||
@@ -93,7 +93,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
run(context, snippet);
|
||||
},
|
||||
child: Text(
|
||||
s.run,
|
||||
_s.run,
|
||||
style: _textStyle,
|
||||
),
|
||||
)
|
||||
@@ -106,7 +106,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
},
|
||||
)
|
||||
: Center(
|
||||
child: Text(s.noSavedSnippet),
|
||||
child: Text(_s.noSavedSnippet),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -115,11 +115,11 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
void _showRunDialog(Snippet snippet) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.chooseDestination,
|
||||
_s.chooseDestination,
|
||||
Consumer<ServerProvider>(
|
||||
builder: (_, provider, __) {
|
||||
if (provider.servers.isEmpty) {
|
||||
return Text(s.noServerAvailable);
|
||||
return Text(_s.noServerAvailable);
|
||||
}
|
||||
_selectedIndex = provider.servers.first.info;
|
||||
return SizedBox(
|
||||
@@ -163,11 +163,11 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () async => run(context, snippet),
|
||||
child: Text(s.run),
|
||||
child: Text(_s.run),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.cancel),
|
||||
child: Text(_s.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -179,12 +179,12 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
||||
if (result != null) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.result,
|
||||
_s.result,
|
||||
Text(result, style: const TextStyle(fontSize: 13)),
|
||||
[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(s.close),
|
||||
child: Text(_s.close),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user