migrate: material 3
This commit is contained in:
@@ -141,10 +141,9 @@ class BackupPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
await showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.restoreSureWithDate(backup.date)),
|
||||
[
|
||||
context: context,
|
||||
child: Text(s.restoreSureWithDate(backup.date)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(s.cancel),
|
||||
@@ -165,10 +164,9 @@ class BackupPage extends StatelessWidget {
|
||||
}
|
||||
context.pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
s.attention,
|
||||
Text(s.restoreSuccess),
|
||||
[
|
||||
context: context,
|
||||
child: Text(s.restoreSuccess),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => rebuildAll(context),
|
||||
child: Text(s.restart),
|
||||
|
||||
@@ -124,7 +124,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
onPressed: () => Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: _textEditingControllerResult.text == ''
|
||||
? ' '
|
||||
? ''
|
||||
: _textEditingControllerResult.text,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -89,9 +89,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
final nameCtrl = TextEditingController();
|
||||
final argsCtrl = TextEditingController();
|
||||
await showRoundDialog(
|
||||
context,
|
||||
_s.newContainer,
|
||||
Column(
|
||||
context: context,
|
||||
title: Text(_s.newContainer),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
@@ -118,7 +118,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -142,10 +142,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
|
||||
Future<void> _showAddCmdPreview(String cmd) async {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
_s.preview,
|
||||
Text(cmd),
|
||||
[
|
||||
context: context,
|
||||
title: Text(_s.preview),
|
||||
child: Text(cmd),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -186,12 +186,16 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
|
||||
void onSubmitted() {
|
||||
if (_textController.text == '') {
|
||||
showRoundDialog(context, _s.attention, Text(_s.fieldMustNotEmpty), [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
]);
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
child: Text(_s.fieldMustNotEmpty),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
return;
|
||||
}
|
||||
context.pop();
|
||||
@@ -200,9 +204,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Future<String> onPwdRequest() async {
|
||||
if (!mounted) return '';
|
||||
await showRoundDialog(
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(widget.spi.user),
|
||||
child: TextField(
|
||||
controller: _textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
@@ -211,7 +215,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
labelText: _s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
@@ -290,10 +294,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () async {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.sureDelete(e.repo)),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.sureDelete(e.repo)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -366,9 +369,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
|
||||
Future<void> _showEditHostDialog() async {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
_s.dockerEditHost,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(_s.dockerEditHost),
|
||||
child: TextField(
|
||||
maxLines: 1,
|
||||
autocorrect: false,
|
||||
controller:
|
||||
@@ -379,7 +382,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -473,10 +476,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
switch (item) {
|
||||
case DockerMenuItems.rm:
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.sureDelete(dItem.name)),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.sureDelete(dItem.name)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
|
||||
@@ -5,17 +5,15 @@ import 'package:get_it/get_it.dart';
|
||||
import 'package:toolbox/core/utils/navigator.dart';
|
||||
import 'package:toolbox/data/provider/app.dart';
|
||||
import 'package:toolbox/data/res/misc.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../core/analysis.dart';
|
||||
import '../../core/route.dart';
|
||||
import '../../core/update.dart';
|
||||
import '../../core/utils/platform.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../data/model/app/dynamic_color.dart';
|
||||
import '../../data/model/app/navigation_item.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/build_data.dart';
|
||||
import '../../data/res/tab.dart';
|
||||
import '../../data/res/ui.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
@@ -31,9 +29,6 @@ import 'setting.dart';
|
||||
import 'sftp/downloaded.dart';
|
||||
import 'snippet/list.dart';
|
||||
|
||||
final _bottomItemOverlayColor =
|
||||
DynamicColor(Colors.black.withOpacity(0.07), Colors.white12);
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -52,7 +47,6 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
late final PageController _pageController;
|
||||
|
||||
late int _selectIndex;
|
||||
late double _width;
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
@@ -67,7 +61,6 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_s = S.of(context)!;
|
||||
_width = MediaQuery.of(context).size.width;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -135,33 +128,35 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBottomBar(BuildContext context){
|
||||
Widget _buildBottomBar(BuildContext context) {
|
||||
return NavigationBar(
|
||||
selectedIndex: _selectIndex,
|
||||
animationDuration: const Duration(milliseconds: 250),
|
||||
onDestinationSelected: (int index) {
|
||||
setState(() {
|
||||
_selectIndex = index;
|
||||
_pageController.animateToPage(index,
|
||||
duration: const Duration(milliseconds: 677),
|
||||
curve: Curves.fastLinearToSlowEaseIn);
|
||||
_pageController.animateToPage(
|
||||
index,
|
||||
duration: const Duration(milliseconds: 677),
|
||||
curve: Curves.fastLinearToSlowEaseIn,
|
||||
);
|
||||
});
|
||||
},
|
||||
elevation: 0.47,
|
||||
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
||||
destinations: const [
|
||||
destinations: [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.cloud_outlined),
|
||||
label: 'Server',
|
||||
selectedIcon: Icon(Icons.cloud),
|
||||
icon: const Icon(Icons.cloud_outlined),
|
||||
label: _s.server,
|
||||
selectedIcon: const Icon(Icons.cloud),
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.code),
|
||||
label: 'Convert',
|
||||
icon: const Icon(Icons.code),
|
||||
label: _s.convert,
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.leak_add),
|
||||
label: 'Ping',
|
||||
selectedIcon: Icon(Icons.leak_add_outlined),
|
||||
icon: const Icon(Icons.leak_add),
|
||||
label: _s.ping,
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -169,16 +164,16 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
|
||||
Widget _buildDrawer() {
|
||||
return Drawer(
|
||||
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildIcon(),
|
||||
TextButton(
|
||||
onPressed: () => showRoundDialog(
|
||||
context,
|
||||
_versionStr,
|
||||
const Text(BuildData.buildAt),
|
||||
[],
|
||||
context: context,
|
||||
title: Text(_versionStr),
|
||||
child: const Text(BuildData.buildAt),
|
||||
),
|
||||
child: Text(
|
||||
'${BuildData.name}\n$_versionStr',
|
||||
@@ -190,7 +185,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
height: MediaQuery.of(context).size.height * 0.07,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 29),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 13),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
@@ -224,10 +219,9 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
leading: const Icon(Icons.info),
|
||||
title: Text(_s.feedback),
|
||||
onTap: () => showRoundDialog(
|
||||
context,
|
||||
_s.feedback,
|
||||
Text(_s.feedbackOnGithub),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.feedbackOnGithub),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => openUrl(issueUrl),
|
||||
child: Text(_s.feedback),
|
||||
@@ -250,9 +244,9 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
title: Text(_s.about),
|
||||
onTap: () {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.about,
|
||||
Column(
|
||||
context: context,
|
||||
title: Text(_s.about),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -271,7 +265,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
)
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => showLicensePage(context: context),
|
||||
child: Text(_s.license),
|
||||
@@ -284,7 +278,7 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -72,10 +72,9 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
void onSubmitted() {
|
||||
if (_textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.fieldMustNotEmpty),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
@@ -90,9 +89,9 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
Future<String> onPwdRequest() async {
|
||||
if (!mounted) return '';
|
||||
await showRoundDialog(
|
||||
context,
|
||||
widget.spi.user,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(widget.spi.user),
|
||||
child: TextField(
|
||||
controller: _textController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
@@ -101,7 +100,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
labelText: _s.pwd,
|
||||
),
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
@@ -234,10 +233,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
}();
|
||||
return ListTile(
|
||||
title: Text(info.package),
|
||||
subtitle: Text(
|
||||
t,
|
||||
style: grey
|
||||
),
|
||||
subtitle: Text(t, style: grey),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +68,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.sureToDeleteServer(widget.spi!.name)),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.sureToDeleteServer(widget.spi!.name)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_serverProvider.delServer(widget.spi!.id);
|
||||
@@ -148,10 +147,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
hint: 'root',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
width7,
|
||||
Row(
|
||||
children: [
|
||||
Text(_s.keyAuth),
|
||||
width13,
|
||||
Switch(
|
||||
value: usePublicKey,
|
||||
onChanged: (val) => setState(() => usePublicKey = val),
|
||||
@@ -228,10 +228,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
}
|
||||
if (!usePublicKey && _passwordController.text == '') {
|
||||
final cancel = await showRoundDialog<bool>(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.sureNoPwd),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.sureNoPwd),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(false),
|
||||
child: Text(_s.ok),
|
||||
|
||||
@@ -166,12 +166,16 @@ class _ServerPageState extends State<ServerPage>
|
||||
hasError
|
||||
? GestureDetector(
|
||||
onTap: () => showRoundDialog(
|
||||
context, _s.error, Text(ss.failedInfo ?? ''), []),
|
||||
context: context,
|
||||
title: Text(_s.error),
|
||||
child: Text(ss.failedInfo ?? ''),
|
||||
),
|
||||
child: Text(
|
||||
_s.clickSee,
|
||||
style: style,
|
||||
textScaleFactor: 1.0,
|
||||
))
|
||||
),
|
||||
)
|
||||
: Text(topRightStr, style: style, textScaleFactor: 1.0),
|
||||
const SizedBox(width: 9),
|
||||
_buildSSHBtn(spi),
|
||||
@@ -218,15 +222,15 @@ class _ServerPageState extends State<ServerPage>
|
||||
onTap: () async {
|
||||
if (_settingStore.firstTimeUseSshTerm.fetch()!) {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
UrlText(
|
||||
context: context,
|
||||
child: UrlText(
|
||||
text: _s.sshTip(issueUrl),
|
||||
replace: 'Github Issue',
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_settingStore.firstTimeUseSshTerm.put(false);
|
||||
context.pop();
|
||||
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
||||
},
|
||||
@@ -234,7 +238,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
)
|
||||
],
|
||||
);
|
||||
_settingStore.firstTimeUseSshTerm.put(false);
|
||||
} else {
|
||||
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
||||
}
|
||||
@@ -269,13 +272,11 @@ class _ServerPageState extends State<ServerPage>
|
||||
break;
|
||||
case ServerTabMenuItems.snippet:
|
||||
showSnippetDialog(context, _s, (s) async {
|
||||
final result =
|
||||
await locator<ServerProvider>().runSnippet(spi.id, s);
|
||||
final result = await _serverProvider.runSnippet(spi.id, s);
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.result,
|
||||
Text(result ?? _s.error, style: textSize13),
|
||||
[
|
||||
context: context,
|
||||
child: Text(result ?? _s.error, style: textSize13),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/data/model/app/tab.dart';
|
||||
|
||||
import '../../core/utils/misc.dart';
|
||||
import '../../core/utils/platform.dart';
|
||||
@@ -15,7 +16,6 @@ import '../../data/provider/server.dart';
|
||||
import '../../data/res/build_data.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/path.dart';
|
||||
import '../../data/res/tab.dart';
|
||||
import '../../data/res/ui.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../locator.dart';
|
||||
@@ -39,8 +39,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
late int _launchPageIdx;
|
||||
late int _termThemeIdx;
|
||||
late int _nightMode;
|
||||
late double _maxRetryCount;
|
||||
late double _updateInterval;
|
||||
late int _maxRetryCount;
|
||||
late int _updateInterval;
|
||||
|
||||
String? _pushToken;
|
||||
|
||||
@@ -59,8 +59,8 @@ class _SettingPageState extends State<SettingPage> {
|
||||
_launchPageIdx = _setting.launchPage.fetch()!;
|
||||
_termThemeIdx = _setting.termColorIdx.fetch()!;
|
||||
_nightMode = _setting.themeMode.fetch()!;
|
||||
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!.toDouble();
|
||||
_maxRetryCount = _setting.maxRetryCount.fetch()!.toDouble();
|
||||
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!;
|
||||
_maxRetryCount = _setting.maxRetryCount.fetch()!;
|
||||
_selectedColorValue = _setting.primaryColor.fetch()!;
|
||||
}
|
||||
|
||||
@@ -175,8 +175,15 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}
|
||||
|
||||
Widget _buildUpdateInterval() {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
final items = List.generate(
|
||||
10,
|
||||
(index) => PopupMenuItem(
|
||||
value: index,
|
||||
child: Text('$index ${_s.second}'),
|
||||
),
|
||||
growable: false,
|
||||
).toList();
|
||||
return ListTile(
|
||||
title: Text(
|
||||
_s.updateServerStatusInterval,
|
||||
),
|
||||
@@ -184,48 +191,27 @@ class _SettingPageState extends State<SettingPage> {
|
||||
_s.willTakEeffectImmediately,
|
||||
style: grey,
|
||||
),
|
||||
trailing: Text(
|
||||
'${_updateInterval.toInt()} ${_s.second}',
|
||||
trailing: buildPopuopMenu<int>(
|
||||
items: items,
|
||||
onSelected: (val) {
|
||||
setState(() {
|
||||
_updateInterval = val;
|
||||
});
|
||||
_setting.serverStatusUpdateInterval.put(_updateInterval.toInt());
|
||||
_serverProvider.startAutoRefresh();
|
||||
if (val == 0) {
|
||||
showSnackBar(context, Text(_s.updateIntervalEqual0));
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'${_updateInterval.toInt()} ${_s.second}',
|
||||
),
|
||||
),
|
||||
children: [
|
||||
Slider(
|
||||
thumbColor: primaryColor,
|
||||
activeColor: primaryColor.withOpacity(0.7),
|
||||
min: 0,
|
||||
max: 10,
|
||||
value: _updateInterval,
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
_updateInterval = newValue;
|
||||
});
|
||||
},
|
||||
onChangeEnd: (val) {
|
||||
_setting.serverStatusUpdateInterval.put(val.toInt());
|
||||
_serverProvider.startAutoRefresh();
|
||||
},
|
||||
label: '${_updateInterval.toInt()} ${_s.second}',
|
||||
divisions: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
_updateInterval == 0.0
|
||||
? Text(
|
||||
_s.updateIntervalEqual0,
|
||||
style: grey,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 13,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppColorPreview() {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
return ListTile(
|
||||
trailing: ClipOval(
|
||||
child: Container(
|
||||
color: primaryColor,
|
||||
@@ -236,188 +222,146 @@ class _SettingPageState extends State<SettingPage> {
|
||||
title: Text(
|
||||
_s.appPrimaryColor,
|
||||
),
|
||||
children: [_buildAppColorPicker(), _buildColorPickerConfirmBtn()],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAppColorPicker() {
|
||||
return MaterialColorPicker(
|
||||
shrinkWrap: true,
|
||||
allowShades: false,
|
||||
onMainColorChange: (ColorSwatch<dynamic>? color) {
|
||||
if(color == null) return;
|
||||
_selectedColorValue = color.value;
|
||||
onTap: () async {
|
||||
await showRoundDialog(
|
||||
context: context,
|
||||
child: MaterialColorPicker(
|
||||
shrinkWrap: true,
|
||||
allowShades: true,
|
||||
onColorChange: (color) {
|
||||
_selectedColorValue = color.value;
|
||||
},
|
||||
selectedColor: primaryColor,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_setting.primaryColor.put(_selectedColorValue);
|
||||
Navigator.pop(context);
|
||||
_showRestartSnackbar();
|
||||
},
|
||||
child: Text(_s.ok),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
selectedColor: primaryColor,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildColorPickerConfirmBtn() {
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.save),
|
||||
onPressed: (() {
|
||||
_setting.primaryColor.put(_selectedColorValue);
|
||||
_showRestartSnackbar();
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLaunchPage() {
|
||||
return ExpansionTile(
|
||||
childrenPadding: const EdgeInsets.only(left: 17, right: 7),
|
||||
textColor: primaryColor,
|
||||
final items = AppTab.values
|
||||
.map(
|
||||
(e) => PopupMenuItem(
|
||||
value: e.index,
|
||||
child: Text(tabTitleName(context, e.index)),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return ListTile(
|
||||
title: Text(
|
||||
_s.launchPage,
|
||||
),
|
||||
trailing: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||
child: Text(
|
||||
tabTitleName(context, _launchPageIdx),
|
||||
textAlign: TextAlign.right,
|
||||
trailing: buildPopuopMenu<int>(
|
||||
items: items,
|
||||
onSelected: (idx) {
|
||||
setState(() {
|
||||
_launchPageIdx = idx;
|
||||
});
|
||||
_setting.launchPage.put(_launchPageIdx);
|
||||
},
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||
child: Text(
|
||||
tabTitleName(context, _launchPageIdx),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
),
|
||||
),
|
||||
children: tabs
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
tabTitleName(context, tabs.indexOf(e)),
|
||||
),
|
||||
trailing: _buildRadio(tabs.indexOf(e)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Radio _buildRadio(int index) {
|
||||
return Radio<int>(
|
||||
value: index,
|
||||
groupValue: _launchPageIdx,
|
||||
onChanged: (int? value) {
|
||||
setState(() {
|
||||
_launchPageIdx = value!;
|
||||
_setting.launchPage.put(value);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTermTheme() {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
childrenPadding: const EdgeInsets.only(left: 17),
|
||||
title: Text(
|
||||
_s.termTheme,
|
||||
),
|
||||
trailing: Text(
|
||||
TerminalColorsPlatform.values[_termThemeIdx].name,
|
||||
),
|
||||
children: _buildTermThemeRadioList(),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildTermThemeRadioList() {
|
||||
return TerminalColorsPlatform.values
|
||||
final items = TerminalColorsPlatform.values
|
||||
.map(
|
||||
(e) => ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
e.name,
|
||||
),
|
||||
trailing: _buildTermThemeRadio(e),
|
||||
(e) => PopupMenuItem<int>(
|
||||
value: e.index,
|
||||
child: Text(e.name),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
Radio _buildTermThemeRadio(TerminalColorsPlatform platform) {
|
||||
return Radio<int>(
|
||||
value: platform.index,
|
||||
groupValue: _termThemeIdx,
|
||||
onChanged: (int? value) {
|
||||
setState(() {
|
||||
value ??= 0;
|
||||
_termThemeIdx = value!;
|
||||
_setting.termColorIdx.put(value!);
|
||||
});
|
||||
},
|
||||
return ListTile(
|
||||
title: Text(
|
||||
_s.termTheme,
|
||||
),
|
||||
trailing: buildPopuopMenu<int>(
|
||||
items: items,
|
||||
onSelected: (idx) {
|
||||
setState(() {
|
||||
_termThemeIdx = idx;
|
||||
});
|
||||
_setting.termColorIdx.put(idx);
|
||||
},
|
||||
child: Text(
|
||||
TerminalColorsPlatform.values[_termThemeIdx].name,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMaxRetry() {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
final items = List.generate(
|
||||
10,
|
||||
(index) => PopupMenuItem(
|
||||
value: index,
|
||||
child: Text('$index ${_s.times}'),
|
||||
),
|
||||
growable: false,
|
||||
).toList();
|
||||
final help =
|
||||
_maxRetryCount == 0 ? _s.maxRetryCountEqual0 : _s.canPullRefresh;
|
||||
return ListTile(
|
||||
title: Text(
|
||||
_s.maxRetryCount,
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
trailing: Text(
|
||||
'${_maxRetryCount.toInt()} ${_s.times}',
|
||||
trailing: buildPopuopMenu<int>(
|
||||
items: items,
|
||||
onSelected: (val) {
|
||||
setState(() {
|
||||
_maxRetryCount = val;
|
||||
});
|
||||
_setting.maxRetryCount.put(_maxRetryCount);
|
||||
},
|
||||
child: Text(
|
||||
'${_maxRetryCount.toInt()} ${_s.times}',
|
||||
),
|
||||
),
|
||||
children: [
|
||||
Slider(
|
||||
thumbColor: primaryColor,
|
||||
activeColor: primaryColor.withOpacity(0.7),
|
||||
min: 0,
|
||||
max: 10,
|
||||
value: _maxRetryCount,
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
_maxRetryCount = newValue;
|
||||
});
|
||||
},
|
||||
onChangeEnd: (val) {
|
||||
_setting.maxRetryCount.put(val.toInt());
|
||||
},
|
||||
label: '${_maxRetryCount.toInt()} ${_s.times}',
|
||||
divisions: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
_maxRetryCount == 0.0
|
||||
? Text(
|
||||
_s.maxRetryCountEqual0,
|
||||
style: grey,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 13,
|
||||
)
|
||||
],
|
||||
subtitle: Text(help, style: grey),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildThemeMode() {
|
||||
return ExpansionTile(
|
||||
textColor: primaryColor,
|
||||
final items = ThemeMode.values.map(
|
||||
(e) {
|
||||
final str = _buildThemeModeStr(e.index);
|
||||
return PopupMenuItem(
|
||||
value: e.index,
|
||||
child: Text(str),
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
return ListTile(
|
||||
title: Text(
|
||||
_s.themeMode,
|
||||
),
|
||||
trailing: Text(
|
||||
_buildThemeModeStr(_nightMode),
|
||||
trailing: buildPopuopMenu<int>(
|
||||
items: items,
|
||||
onSelected: (idx) {
|
||||
_nightMode = idx;
|
||||
_setting.themeMode.put(_nightMode);
|
||||
},
|
||||
child: Text(_buildThemeModeStr(_nightMode)),
|
||||
),
|
||||
children: [
|
||||
Slider(
|
||||
thumbColor: primaryColor,
|
||||
activeColor: primaryColor.withOpacity(0.7),
|
||||
min: 0,
|
||||
max: 2,
|
||||
value: _nightMode.toDouble(),
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
_nightMode = newValue.toInt();
|
||||
});
|
||||
},
|
||||
onChangeEnd: (val) {
|
||||
_setting.themeMode.put(val.toInt());
|
||||
},
|
||||
label: _buildThemeModeStr(_nightMode),
|
||||
divisions: 2,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -467,27 +411,30 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}
|
||||
|
||||
Widget _buildFont() {
|
||||
return ExpansionTile(
|
||||
return ListTile(
|
||||
title: Text(_s.chooseFontFile),
|
||||
trailing: Text(getFileName(_setting.fontPath.fetch()) ?? _s.notSelected),
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async => _pickFontFile(),
|
||||
child: Text(_s.pickFile),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => setState(() {
|
||||
_setting.fontPath.delete();
|
||||
_showRestartSnackbar();
|
||||
}),
|
||||
child: Text(_s.clear),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
onTap: () {
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async => await _pickFontFile(),
|
||||
child: Text(_s.pickFile),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => setState(() {
|
||||
_setting.fontPath.delete();
|
||||
_showRestartSnackbar();
|
||||
}),
|
||||
child: Text(_s.clear),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,9 +136,8 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
void showFileActionDialog(FileSystemEntity file) {
|
||||
final fileName = file.path.split('/').last;
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.choose,
|
||||
Column(
|
||||
context: context,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
@@ -147,10 +146,9 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
onTap: () {
|
||||
context.pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.sureDelete(fileName),
|
||||
const SizedBox(),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.sureDelete(fileName)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -176,7 +174,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: (() => context.pop()),
|
||||
child: Text(_s.close),
|
||||
|
||||
@@ -98,9 +98,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
),
|
||||
IconButton(
|
||||
onPressed: (() => showRoundDialog(
|
||||
context,
|
||||
_s.choose,
|
||||
Column(
|
||||
context: context,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
@@ -113,7 +112,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
onTap: () => newFile(context)),
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.close),
|
||||
@@ -126,9 +125,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () async {
|
||||
final p = await showRoundDialog<String?>(
|
||||
context,
|
||||
_s.goto,
|
||||
Column(
|
||||
context: context,
|
||||
title: Text(_s.goto),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
@@ -140,7 +139,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -254,9 +253,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
|
||||
void onItemPress(BuildContext context, SftpName file, bool showDownload) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.choose,
|
||||
Column(
|
||||
context: context,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
@@ -278,7 +276,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -289,10 +287,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
|
||||
void download(BuildContext context, SftpName name) {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.download,
|
||||
Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
||||
[
|
||||
context: context,
|
||||
child: Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -326,12 +323,13 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
void delete(BuildContext context, SftpName file) {
|
||||
context.pop();
|
||||
final isDir = file.attr.isDirectory;
|
||||
final dirText = isDir ? '\n${_s.sureDirEmpty}' : '';
|
||||
final text = '${_s.sureDelete(file.filename)}$dirText';
|
||||
final child = Text(text);
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(
|
||||
'${_s.sureDelete(file.filename)}${isDir ? '\n${_s.sureDirEmpty}' : ''}'),
|
||||
[
|
||||
context: context,
|
||||
child: child,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -339,8 +337,11 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
showRoundDialog(context, 'Waiting...', centerSizedLoading, [],
|
||||
barrierDismiss: false);
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
child: centerSizedLoading,
|
||||
barrierDismiss: false,
|
||||
);
|
||||
final remotePath = _getRemotePath(file);
|
||||
try {
|
||||
if (file.attr.isDirectory) {
|
||||
@@ -352,10 +353,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
} catch (e) {
|
||||
context.pop();
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(e.toString()),
|
||||
[
|
||||
context: context,
|
||||
title: Text(_s.error),
|
||||
child: Text(e.toString()),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
@@ -379,15 +380,15 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
context.pop();
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.createFolder,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(_s.createFolder),
|
||||
child: TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -396,10 +397,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
onPressed: () {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.fieldMustNotEmpty),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
@@ -426,15 +426,15 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
context.pop();
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.createFile,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(_s.createFile),
|
||||
child: TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.cancel),
|
||||
@@ -443,10 +443,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.fieldMustNotEmpty),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
@@ -474,24 +473,23 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
context.pop();
|
||||
final textController = TextEditingController();
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.rename,
|
||||
TextField(
|
||||
context: context,
|
||||
title: Text(_s.rename),
|
||||
child: TextField(
|
||||
controller: textController,
|
||||
decoration: InputDecoration(
|
||||
labelText: _s.name,
|
||||
),
|
||||
),
|
||||
[
|
||||
actions: [
|
||||
TextButton(onPressed: () => context.pop(), child: Text(_s.cancel)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (textController.text == '') {
|
||||
showRoundDialog(
|
||||
context,
|
||||
_s.attention,
|
||||
Text(_s.fieldMustNotEmpty),
|
||||
[
|
||||
context: context,
|
||||
child: Text(_s.fieldMustNotEmpty),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
@@ -540,10 +538,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
}
|
||||
} catch (e) {
|
||||
await showRoundDialog(
|
||||
context,
|
||||
_s.error,
|
||||
Text(e.toString()),
|
||||
[
|
||||
context: context,
|
||||
title: Text(_s.error),
|
||||
child: Text(e.toString()),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
|
||||
Reference in New Issue
Block a user