mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
migrate: material 3
This commit is contained in:
@@ -183,6 +183,12 @@ abstract class S {
|
|||||||
/// **'Run in backgroud'**
|
/// **'Run in backgroud'**
|
||||||
String get bgRun;
|
String get bgRun;
|
||||||
|
|
||||||
|
/// No description provided for @canPullRefresh.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'You can pull to refresh.'**
|
||||||
|
String get canPullRefresh;
|
||||||
|
|
||||||
/// No description provided for @cancel.
|
/// No description provided for @cancel.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class SEn extends S {
|
|||||||
@override
|
@override
|
||||||
String get bgRun => 'Run in backgroud';
|
String get bgRun => 'Run in backgroud';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get canPullRefresh => 'You can pull to refresh.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get cancel => 'Cancel';
|
String get cancel => 'Cancel';
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class SZh extends S {
|
|||||||
@override
|
@override
|
||||||
String get bgRun => '后台运行';
|
String get bgRun => '后台运行';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get canPullRefresh => '可以下拉刷新';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get cancel => '取消';
|
String get cancel => '取消';
|
||||||
|
|
||||||
|
|||||||
@@ -359,7 +359,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 284;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -367,7 +367,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.280;
|
MARKETING_VERSION = 1.0.284;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -490,7 +490,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 284;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -498,7 +498,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.280;
|
MARKETING_VERSION = 1.0.284;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -515,7 +515,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 280;
|
CURRENT_PROJECT_VERSION = 284;
|
||||||
DEVELOPMENT_TEAM = BA88US33G6;
|
DEVELOPMENT_TEAM = BA88US33G6;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||||
@@ -523,7 +523,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.280;
|
MARKETING_VERSION = 1.0.284;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
import '/core/extension/colorx.dart';
|
|
||||||
import 'core/utils/ui.dart';
|
import 'core/utils/ui.dart';
|
||||||
import 'data/res/build_data.dart';
|
import 'data/res/build_data.dart';
|
||||||
import 'data/res/color.dart';
|
import 'data/res/color.dart';
|
||||||
|
|||||||
@@ -53,10 +53,9 @@ Future<void> doUpdate(BuildContext context, {bool force = false}) async {
|
|||||||
|
|
||||||
if (update.build.min.current! > BuildData.build) {
|
if (update.build.min.current! > BuildData.build) {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
s.attention,
|
child: Text(s.updateTipTooLow(newest)),
|
||||||
Text(s.updateTipTooLow(newest)),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => _doUpdate(url, context, s),
|
onPressed: () => _doUpdate(url, context, s),
|
||||||
child: Text(s.ok),
|
child: Text(s.ok),
|
||||||
@@ -84,11 +83,15 @@ Future<void> _doUpdate(String url, BuildContext context, S s) async {
|
|||||||
} else if (isIOS) {
|
} else if (isIOS) {
|
||||||
await RUpgrade.upgradeFromAppStore('1586449703');
|
await RUpgrade.upgradeFromAppStore('1586449703');
|
||||||
} else {
|
} else {
|
||||||
showRoundDialog(context, s.attention, Text(s.platformNotSupportUpdate), [
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
child: Text(s.platformNotSupportUpdate),
|
||||||
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(s.ok),
|
child: Text(s.ok),
|
||||||
)
|
)
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:toolbox/core/utils/navigator.dart';
|
import 'package:toolbox/core/utils/navigator.dart';
|
||||||
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../../data/model/server/snippet.dart';
|
import '../../data/model/server/snippet.dart';
|
||||||
@@ -25,8 +26,12 @@ bool isDarkMode(BuildContext context) =>
|
|||||||
void showSnackBar(BuildContext context, Widget child) =>
|
void showSnackBar(BuildContext context, Widget child) =>
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: child));
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: child));
|
||||||
|
|
||||||
void showSnackBarWithAction(BuildContext context, String content, String action,
|
void showSnackBarWithAction(
|
||||||
GestureTapCallback onTap) {
|
BuildContext context,
|
||||||
|
String content,
|
||||||
|
String action,
|
||||||
|
GestureTapCallback onTap,
|
||||||
|
) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
content: Text(content),
|
content: Text(content),
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
@@ -41,24 +46,33 @@ Future<bool> openUrl(String url) async {
|
|||||||
return await launchUrl(url.uri, mode: LaunchMode.externalApplication);
|
return await launchUrl(url.uri, mode: LaunchMode.externalApplication);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<T?>? showRoundDialog<T>(
|
Future<T?>? showRoundDialog<T>({
|
||||||
BuildContext context, String title, Widget child, List<Widget> actions,
|
required BuildContext context,
|
||||||
{EdgeInsets? padding, bool barrierDismiss = true}) {
|
Widget? child,
|
||||||
|
List<Widget>? actions,
|
||||||
|
Widget? title,
|
||||||
|
EdgeInsets? padding,
|
||||||
|
bool barrierDismiss = true,
|
||||||
|
}) {
|
||||||
return showDialog<T>(
|
return showDialog<T>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: barrierDismiss,
|
barrierDismissible: barrierDismiss,
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
return CardDialog(
|
return CardDialog(
|
||||||
title: Text(title),
|
title: title,
|
||||||
content: child,
|
content: child,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildSwitch(BuildContext context, StoreProperty<bool> prop,
|
Widget buildSwitch(
|
||||||
{Function(bool)? func}) {
|
BuildContext context,
|
||||||
|
StoreProperty<bool> prop, {
|
||||||
|
Function(bool)? func,
|
||||||
|
}) {
|
||||||
return ValueListenableBuilder(
|
return ValueListenableBuilder(
|
||||||
valueListenable: prop.listenable(),
|
valueListenable: prop.listenable(),
|
||||||
builder: (context, bool value, widget) {
|
builder: (context, bool value, widget) {
|
||||||
@@ -75,27 +89,26 @@ Widget buildSwitch(BuildContext context, StoreProperty<bool> prop,
|
|||||||
void setTransparentNavigationBar(BuildContext context) {
|
void setTransparentNavigationBar(BuildContext context) {
|
||||||
if (isAndroid) {
|
if (isAndroid) {
|
||||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||||
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
|
SystemChrome.setSystemUIOverlayStyle(
|
||||||
|
const SystemUiOverlayStyle(
|
||||||
systemNavigationBarColor: Colors.transparent,
|
systemNavigationBarColor: Colors.transparent,
|
||||||
systemNavigationBarContrastEnforced: true));
|
systemNavigationBarContrastEnforced: true),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPopuopMenu(
|
Widget buildPopuopMenu<T>({
|
||||||
{required List<PopupMenuEntry> items,
|
required List<PopupMenuEntry<T>> items,
|
||||||
required Function(dynamic) onSelected}) {
|
required void Function(T) onSelected,
|
||||||
return PopupMenuButton(
|
Widget child = popMenuChild,
|
||||||
|
EdgeInsetsGeometry? padding,
|
||||||
|
}) {
|
||||||
|
return PopupMenuButton<T>(
|
||||||
itemBuilder: (_) => items,
|
itemBuilder: (_) => items,
|
||||||
onSelected: onSelected,
|
onSelected: onSelected,
|
||||||
padding: EdgeInsets.zero,
|
padding: padding ?? EdgeInsets.zero,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||||
child: const Padding(
|
child: child,
|
||||||
padding: EdgeInsets.only(left: 7),
|
|
||||||
child: Icon(
|
|
||||||
Icons.more_vert,
|
|
||||||
size: 21,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,14 +136,16 @@ Future<void> loadFontFile(String? localPath) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showSnippetDialog(
|
void showSnippetDialog(
|
||||||
BuildContext context, S s, Function(Snippet s) onSelected) {
|
BuildContext context,
|
||||||
|
S s,
|
||||||
|
Function(Snippet s) onSelected,
|
||||||
|
) {
|
||||||
final provider = locator<SnippetProvider>();
|
final provider = locator<SnippetProvider>();
|
||||||
if (provider.snippets.isEmpty) {
|
if (provider.snippets.isEmpty) {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
s.attention,
|
child: Text(s.noSavedSnippet),
|
||||||
Text(s.noSavedSnippet),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: Text(s.ok),
|
child: Text(s.ok),
|
||||||
@@ -149,13 +164,13 @@ void showSnippetDialog(
|
|||||||
|
|
||||||
var snippet = provider.snippets.first;
|
var snippet = provider.snippets.first;
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
s.choose,
|
title: Text(s.chooseDestination),
|
||||||
buildPicker(
|
child: buildPicker(
|
||||||
provider.snippets.map((e) => Text(e.name)).toList(),
|
provider.snippets.map((e) => Text(e.name)).toList(),
|
||||||
(idx) => snippet = provider.snippets[idx],
|
(idx) => snippet = provider.snippets[idx],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class NavigationItem {
|
|
||||||
final IconData icon;
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
NavigationItem(this.icon, this.title);
|
|
||||||
}
|
|
||||||
1
lib/data/model/app/tab.dart
Normal file
1
lib/data/model/app/tab.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
enum AppTab { servers, encode, ping }
|
||||||
@@ -58,10 +58,9 @@ class PkgProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
final result = await _update();_parse(result);
|
final result = await _update();
|
||||||
try {
|
_parse(result);
|
||||||
|
try {} catch (e) {
|
||||||
} catch (e) {
|
|
||||||
error = '[Server Raw]:\n$result\n[App Error]:\n$e';
|
error = '[Server Raw]:\n$result\n[App Error]:\n$e';
|
||||||
} finally {
|
} finally {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -70,11 +69,8 @@ class PkgProvider extends BusyProvider {
|
|||||||
|
|
||||||
void _parse(String? raw) {
|
void _parse(String? raw) {
|
||||||
if (raw == null) return;
|
if (raw == null) return;
|
||||||
final list = type
|
final list = type?.updateListRemoveUnused(raw.split('\n'));
|
||||||
?.updateListRemoveUnused(raw.split('\n'));
|
upgradeable = list?.map((e) => UpgradePkgInfo(e, type)).toList();
|
||||||
upgradeable = list
|
|
||||||
?.map((e) => UpgradePkgInfo(e, type))
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> _update() async {
|
Future<String?> _update() async {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'dart:async';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import '../../core/build_mode.dart';
|
|
||||||
import '../../core/extension/uint8list.dart';
|
import '../../core/extension/uint8list.dart';
|
||||||
import '../../core/provider_base.dart';
|
import '../../core/provider_base.dart';
|
||||||
import '../../core/utils/server.dart';
|
import '../../core/utils/server.dart';
|
||||||
@@ -182,9 +181,6 @@ class ServerProvider extends BusyProvider {
|
|||||||
s.state = ServerState.failed;
|
s.state = ServerState.failed;
|
||||||
s.status.failedInfo = e.toString();
|
s.status.failedInfo = e.toString();
|
||||||
_logger.warning(e);
|
_logger.warning(e);
|
||||||
if (BuildMode.isDebug) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 280;
|
static const int build = 284;
|
||||||
static const String engine = "3.7.11";
|
static const String engine = "3.7.11";
|
||||||
static const String buildAt = "2023-04-27 18:10:45.464081";
|
static const String buildAt = "2023-05-07 00:52:57.124037";
|
||||||
static const int modifications = 4;
|
static const int modifications = 23;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:toolbox/data/model/app/navigation_item.dart';
|
|
||||||
|
|
||||||
final List<String> tabs = ['Servers', 'En/Decode', 'Ping'];
|
|
||||||
final List<NavigationItem> tabItems = [
|
|
||||||
NavigationItem(Icons.cloud, 'Server'),
|
|
||||||
NavigationItem(Icons.code, 'Convert'),
|
|
||||||
NavigationItem(Icons.leak_add, 'Ping'),
|
|
||||||
];
|
|
||||||
@@ -23,3 +23,11 @@ const roundRectCardPadding = EdgeInsets.symmetric(horizontal: 17, vertical: 13);
|
|||||||
const height13 = SizedBox(height: 13);
|
const height13 = SizedBox(height: 13);
|
||||||
const width13 = SizedBox(width: 13);
|
const width13 = SizedBox(width: 13);
|
||||||
const width7 = SizedBox(width: 7);
|
const width7 = SizedBox(width: 7);
|
||||||
|
|
||||||
|
const popMenuChild = Padding(
|
||||||
|
padding: EdgeInsets.only(left: 7),
|
||||||
|
child: Icon(
|
||||||
|
Icons.more_vert,
|
||||||
|
size: 21,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
|
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
|
||||||
"backupVersionNotMatch": "Backup version is not match.",
|
"backupVersionNotMatch": "Backup version is not match.",
|
||||||
"bgRun": "Run in backgroud",
|
"bgRun": "Run in backgroud",
|
||||||
|
"canPullRefresh": "You can pull to refresh.",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"choose": "Choose",
|
"choose": "Choose",
|
||||||
"chooseDestination": "Choose destination",
|
"chooseDestination": "Choose destination",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
|
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
|
||||||
"backupVersionNotMatch": "备份版本不匹配,无法恢复",
|
"backupVersionNotMatch": "备份版本不匹配,无法恢复",
|
||||||
"bgRun": "后台运行",
|
"bgRun": "后台运行",
|
||||||
|
"canPullRefresh": "可以下拉刷新",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"choose": "选择",
|
"choose": "选择",
|
||||||
"chooseDestination": "选择目标",
|
"chooseDestination": "选择目标",
|
||||||
|
|||||||
@@ -141,10 +141,9 @@ class BackupPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
s.attention,
|
child: Text(s.restoreSureWithDate(backup.date)),
|
||||||
Text(s.restoreSureWithDate(backup.date)),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(s.cancel),
|
child: Text(s.cancel),
|
||||||
@@ -165,10 +164,9 @@ class BackupPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
context.pop();
|
context.pop();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
s.attention,
|
child: Text(s.restoreSuccess),
|
||||||
Text(s.restoreSuccess),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => rebuildAll(context),
|
onPressed: () => rebuildAll(context),
|
||||||
child: Text(s.restart),
|
child: Text(s.restart),
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
onPressed: () => Clipboard.setData(
|
onPressed: () => Clipboard.setData(
|
||||||
ClipboardData(
|
ClipboardData(
|
||||||
text: _textEditingControllerResult.text == ''
|
text: _textEditingControllerResult.text == ''
|
||||||
? ' '
|
? ''
|
||||||
: _textEditingControllerResult.text,
|
: _textEditingControllerResult.text,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
final nameCtrl = TextEditingController();
|
final nameCtrl = TextEditingController();
|
||||||
final argsCtrl = TextEditingController();
|
final argsCtrl = TextEditingController();
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.newContainer,
|
title: Text(_s.newContainer),
|
||||||
Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
@@ -118,7 +118,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -142,10 +142,10 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
Future<void> _showAddCmdPreview(String cmd) async {
|
Future<void> _showAddCmdPreview(String cmd) async {
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.preview,
|
title: Text(_s.preview),
|
||||||
Text(cmd),
|
child: Text(cmd),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -186,12 +186,16 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
void onSubmitted() {
|
void onSubmitted() {
|
||||||
if (_textController.text == '') {
|
if (_textController.text == '') {
|
||||||
showRoundDialog(context, _s.attention, Text(_s.fieldMustNotEmpty), [
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
child: Text(_s.fieldMustNotEmpty),
|
||||||
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
),
|
),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.pop();
|
context.pop();
|
||||||
@@ -200,9 +204,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
Future<String> onPwdRequest() async {
|
Future<String> onPwdRequest() async {
|
||||||
if (!mounted) return '';
|
if (!mounted) return '';
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
widget.spi.user,
|
title: Text(widget.spi.user),
|
||||||
TextField(
|
child: TextField(
|
||||||
controller: _textController,
|
controller: _textController,
|
||||||
keyboardType: TextInputType.visiblePassword,
|
keyboardType: TextInputType.visiblePassword,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
@@ -211,7 +215,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
labelText: _s.pwd,
|
labelText: _s.pwd,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
@@ -290,10 +294,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.sureDelete(e.repo)),
|
||||||
Text(_s.sureDelete(e.repo)),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -366,9 +369,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
|
|
||||||
Future<void> _showEditHostDialog() async {
|
Future<void> _showEditHostDialog() async {
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.dockerEditHost,
|
title: Text(_s.dockerEditHost),
|
||||||
TextField(
|
child: TextField(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
controller:
|
controller:
|
||||||
@@ -379,7 +382,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -473,10 +476,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
switch (item) {
|
switch (item) {
|
||||||
case DockerMenuItems.rm:
|
case DockerMenuItems.rm:
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.sureDelete(dItem.name)),
|
||||||
Text(_s.sureDelete(dItem.name)),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
|
|||||||
@@ -5,17 +5,15 @@ import 'package:get_it/get_it.dart';
|
|||||||
import 'package:toolbox/core/utils/navigator.dart';
|
import 'package:toolbox/core/utils/navigator.dart';
|
||||||
import 'package:toolbox/data/provider/app.dart';
|
import 'package:toolbox/data/provider/app.dart';
|
||||||
import 'package:toolbox/data/res/misc.dart';
|
import 'package:toolbox/data/res/misc.dart';
|
||||||
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
|
||||||
import '../../core/analysis.dart';
|
import '../../core/analysis.dart';
|
||||||
import '../../core/route.dart';
|
import '../../core/route.dart';
|
||||||
import '../../core/update.dart';
|
import '../../core/update.dart';
|
||||||
import '../../core/utils/platform.dart';
|
import '../../core/utils/platform.dart';
|
||||||
import '../../core/utils/ui.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/provider/server.dart';
|
||||||
import '../../data/res/build_data.dart';
|
import '../../data/res/build_data.dart';
|
||||||
import '../../data/res/tab.dart';
|
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
import '../../data/res/url.dart';
|
import '../../data/res/url.dart';
|
||||||
import '../../data/store/setting.dart';
|
import '../../data/store/setting.dart';
|
||||||
@@ -31,9 +29,6 @@ import 'setting.dart';
|
|||||||
import 'sftp/downloaded.dart';
|
import 'sftp/downloaded.dart';
|
||||||
import 'snippet/list.dart';
|
import 'snippet/list.dart';
|
||||||
|
|
||||||
final _bottomItemOverlayColor =
|
|
||||||
DynamicColor(Colors.black.withOpacity(0.07), Colors.white12);
|
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class MyHomePage extends StatefulWidget {
|
||||||
const MyHomePage({Key? key}) : super(key: key);
|
const MyHomePage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@@ -52,7 +47,6 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
late final PageController _pageController;
|
late final PageController _pageController;
|
||||||
|
|
||||||
late int _selectIndex;
|
late int _selectIndex;
|
||||||
late double _width;
|
|
||||||
late S _s;
|
late S _s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -67,7 +61,6 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_s = S.of(context)!;
|
_s = S.of(context)!;
|
||||||
_width = MediaQuery.of(context).size.width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -135,33 +128,35 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBottomBar(BuildContext context){
|
Widget _buildBottomBar(BuildContext context) {
|
||||||
return NavigationBar(
|
return NavigationBar(
|
||||||
selectedIndex: _selectIndex,
|
selectedIndex: _selectIndex,
|
||||||
animationDuration: const Duration(milliseconds: 250),
|
animationDuration: const Duration(milliseconds: 250),
|
||||||
onDestinationSelected: (int index) {
|
onDestinationSelected: (int index) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectIndex = index;
|
_selectIndex = index;
|
||||||
_pageController.animateToPage(index,
|
_pageController.animateToPage(
|
||||||
|
index,
|
||||||
duration: const Duration(milliseconds: 677),
|
duration: const Duration(milliseconds: 677),
|
||||||
curve: Curves.fastLinearToSlowEaseIn);
|
curve: Curves.fastLinearToSlowEaseIn,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
elevation: 0.47,
|
||||||
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
||||||
destinations: const [
|
destinations: [
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.cloud_outlined),
|
icon: const Icon(Icons.cloud_outlined),
|
||||||
label: 'Server',
|
label: _s.server,
|
||||||
selectedIcon: Icon(Icons.cloud),
|
selectedIcon: const Icon(Icons.cloud),
|
||||||
),
|
),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.code),
|
icon: const Icon(Icons.code),
|
||||||
label: 'Convert',
|
label: _s.convert,
|
||||||
),
|
),
|
||||||
NavigationDestination(
|
NavigationDestination(
|
||||||
icon: Icon(Icons.leak_add),
|
icon: const Icon(Icons.leak_add),
|
||||||
label: 'Ping',
|
label: _s.ping,
|
||||||
selectedIcon: Icon(Icons.leak_add_outlined),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -169,16 +164,16 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
|
|
||||||
Widget _buildDrawer() {
|
Widget _buildDrawer() {
|
||||||
return Drawer(
|
return Drawer(
|
||||||
|
surfaceTintColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildIcon(),
|
_buildIcon(),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => showRoundDialog(
|
onPressed: () => showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_versionStr,
|
title: Text(_versionStr),
|
||||||
const Text(BuildData.buildAt),
|
child: const Text(BuildData.buildAt),
|
||||||
[],
|
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${BuildData.name}\n$_versionStr',
|
'${BuildData.name}\n$_versionStr',
|
||||||
@@ -190,7 +185,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
height: MediaQuery.of(context).size.height * 0.07,
|
height: MediaQuery.of(context).size.height * 0.07,
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 29),
|
padding: const EdgeInsets.symmetric(horizontal: 13),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -224,10 +219,9 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
leading: const Icon(Icons.info),
|
leading: const Icon(Icons.info),
|
||||||
title: Text(_s.feedback),
|
title: Text(_s.feedback),
|
||||||
onTap: () => showRoundDialog(
|
onTap: () => showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.feedback,
|
child: Text(_s.feedbackOnGithub),
|
||||||
Text(_s.feedbackOnGithub),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => openUrl(issueUrl),
|
onPressed: () => openUrl(issueUrl),
|
||||||
child: Text(_s.feedback),
|
child: Text(_s.feedback),
|
||||||
@@ -250,9 +244,9 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
title: Text(_s.about),
|
title: Text(_s.about),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.about,
|
title: Text(_s.about),
|
||||||
Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -271,7 +265,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => showLicensePage(context: context),
|
onPressed: () => showLicensePage(context: context),
|
||||||
child: Text(_s.license),
|
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() {
|
void onSubmitted() {
|
||||||
if (_textController.text == '') {
|
if (_textController.text == '') {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.fieldMustNotEmpty),
|
||||||
Text(_s.fieldMustNotEmpty),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
@@ -90,9 +89,9 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
Future<String> onPwdRequest() async {
|
Future<String> onPwdRequest() async {
|
||||||
if (!mounted) return '';
|
if (!mounted) return '';
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
widget.spi.user,
|
title: Text(widget.spi.user),
|
||||||
TextField(
|
child: TextField(
|
||||||
controller: _textController,
|
controller: _textController,
|
||||||
keyboardType: TextInputType.visiblePassword,
|
keyboardType: TextInputType.visiblePassword,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
@@ -101,7 +100,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
labelText: _s.pwd,
|
labelText: _s.pwd,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
@@ -234,10 +233,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
}();
|
}();
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(info.package),
|
title: Text(info.package),
|
||||||
subtitle: Text(
|
subtitle: Text(t, style: grey),
|
||||||
t,
|
|
||||||
style: grey
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,10 +68,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.sureToDeleteServer(widget.spi!.name)),
|
||||||
Text(_s.sureToDeleteServer(widget.spi!.name)),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_serverProvider.delServer(widget.spi!.id);
|
_serverProvider.delServer(widget.spi!.id);
|
||||||
@@ -148,10 +147,11 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
hint: 'root',
|
hint: 'root',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 7),
|
width7,
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(_s.keyAuth),
|
Text(_s.keyAuth),
|
||||||
|
width13,
|
||||||
Switch(
|
Switch(
|
||||||
value: usePublicKey,
|
value: usePublicKey,
|
||||||
onChanged: (val) => setState(() => usePublicKey = val),
|
onChanged: (val) => setState(() => usePublicKey = val),
|
||||||
@@ -228,10 +228,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
}
|
}
|
||||||
if (!usePublicKey && _passwordController.text == '') {
|
if (!usePublicKey && _passwordController.text == '') {
|
||||||
final cancel = await showRoundDialog<bool>(
|
final cancel = await showRoundDialog<bool>(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.sureNoPwd),
|
||||||
Text(_s.sureNoPwd),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(false),
|
onPressed: () => context.pop(false),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
|
|||||||
@@ -166,12 +166,16 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
hasError
|
hasError
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onTap: () => showRoundDialog(
|
onTap: () => showRoundDialog(
|
||||||
context, _s.error, Text(ss.failedInfo ?? ''), []),
|
context: context,
|
||||||
|
title: Text(_s.error),
|
||||||
|
child: Text(ss.failedInfo ?? ''),
|
||||||
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
_s.clickSee,
|
_s.clickSee,
|
||||||
style: style,
|
style: style,
|
||||||
textScaleFactor: 1.0,
|
textScaleFactor: 1.0,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
: Text(topRightStr, style: style, textScaleFactor: 1.0),
|
: Text(topRightStr, style: style, textScaleFactor: 1.0),
|
||||||
const SizedBox(width: 9),
|
const SizedBox(width: 9),
|
||||||
_buildSSHBtn(spi),
|
_buildSSHBtn(spi),
|
||||||
@@ -218,15 +222,15 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (_settingStore.firstTimeUseSshTerm.fetch()!) {
|
if (_settingStore.firstTimeUseSshTerm.fetch()!) {
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: UrlText(
|
||||||
UrlText(
|
|
||||||
text: _s.sshTip(issueUrl),
|
text: _s.sshTip(issueUrl),
|
||||||
replace: 'Github Issue',
|
replace: 'Github Issue',
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
_settingStore.firstTimeUseSshTerm.put(false);
|
||||||
context.pop();
|
context.pop();
|
||||||
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
||||||
},
|
},
|
||||||
@@ -234,7 +238,6 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
_settingStore.firstTimeUseSshTerm.put(false);
|
|
||||||
} else {
|
} else {
|
||||||
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
AppRoute(SSHPage(spi: spi), 'ssh page').go(context);
|
||||||
}
|
}
|
||||||
@@ -269,13 +272,11 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
break;
|
break;
|
||||||
case ServerTabMenuItems.snippet:
|
case ServerTabMenuItems.snippet:
|
||||||
showSnippetDialog(context, _s, (s) async {
|
showSnippetDialog(context, _s, (s) async {
|
||||||
final result =
|
final result = await _serverProvider.runSnippet(spi.id, s);
|
||||||
await locator<ServerProvider>().runSnippet(spi.id, s);
|
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.result,
|
child: Text(result ?? _s.error, style: textSize13),
|
||||||
Text(result ?? _s.error, style: textSize13),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:toolbox/data/model/app/tab.dart';
|
||||||
|
|
||||||
import '../../core/utils/misc.dart';
|
import '../../core/utils/misc.dart';
|
||||||
import '../../core/utils/platform.dart';
|
import '../../core/utils/platform.dart';
|
||||||
@@ -15,7 +16,6 @@ import '../../data/provider/server.dart';
|
|||||||
import '../../data/res/build_data.dart';
|
import '../../data/res/build_data.dart';
|
||||||
import '../../data/res/color.dart';
|
import '../../data/res/color.dart';
|
||||||
import '../../data/res/path.dart';
|
import '../../data/res/path.dart';
|
||||||
import '../../data/res/tab.dart';
|
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
import '../../data/store/setting.dart';
|
import '../../data/store/setting.dart';
|
||||||
import '../../locator.dart';
|
import '../../locator.dart';
|
||||||
@@ -39,8 +39,8 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
late int _launchPageIdx;
|
late int _launchPageIdx;
|
||||||
late int _termThemeIdx;
|
late int _termThemeIdx;
|
||||||
late int _nightMode;
|
late int _nightMode;
|
||||||
late double _maxRetryCount;
|
late int _maxRetryCount;
|
||||||
late double _updateInterval;
|
late int _updateInterval;
|
||||||
|
|
||||||
String? _pushToken;
|
String? _pushToken;
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_launchPageIdx = _setting.launchPage.fetch()!;
|
_launchPageIdx = _setting.launchPage.fetch()!;
|
||||||
_termThemeIdx = _setting.termColorIdx.fetch()!;
|
_termThemeIdx = _setting.termColorIdx.fetch()!;
|
||||||
_nightMode = _setting.themeMode.fetch()!;
|
_nightMode = _setting.themeMode.fetch()!;
|
||||||
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!.toDouble();
|
_updateInterval = _setting.serverStatusUpdateInterval.fetch()!;
|
||||||
_maxRetryCount = _setting.maxRetryCount.fetch()!.toDouble();
|
_maxRetryCount = _setting.maxRetryCount.fetch()!;
|
||||||
_selectedColorValue = _setting.primaryColor.fetch()!;
|
_selectedColorValue = _setting.primaryColor.fetch()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +175,15 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUpdateInterval() {
|
Widget _buildUpdateInterval() {
|
||||||
return ExpansionTile(
|
final items = List.generate(
|
||||||
textColor: primaryColor,
|
10,
|
||||||
|
(index) => PopupMenuItem(
|
||||||
|
value: index,
|
||||||
|
child: Text('$index ${_s.second}'),
|
||||||
|
),
|
||||||
|
growable: false,
|
||||||
|
).toList();
|
||||||
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.updateServerStatusInterval,
|
_s.updateServerStatusInterval,
|
||||||
),
|
),
|
||||||
@@ -184,48 +191,27 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_s.willTakEeffectImmediately,
|
_s.willTakEeffectImmediately,
|
||||||
style: grey,
|
style: grey,
|
||||||
),
|
),
|
||||||
trailing: Text(
|
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}',
|
'${_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() {
|
Widget _buildAppColorPreview() {
|
||||||
return ExpansionTile(
|
return ListTile(
|
||||||
textColor: primaryColor,
|
|
||||||
trailing: ClipOval(
|
trailing: ClipOval(
|
||||||
child: Container(
|
child: Container(
|
||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
@@ -236,188 +222,146 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
title: Text(
|
title: Text(
|
||||||
_s.appPrimaryColor,
|
_s.appPrimaryColor,
|
||||||
),
|
),
|
||||||
children: [_buildAppColorPicker(), _buildColorPickerConfirmBtn()],
|
onTap: () async {
|
||||||
);
|
await showRoundDialog(
|
||||||
}
|
context: context,
|
||||||
|
child: MaterialColorPicker(
|
||||||
Widget _buildAppColorPicker() {
|
|
||||||
return MaterialColorPicker(
|
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
allowShades: false,
|
allowShades: true,
|
||||||
onMainColorChange: (ColorSwatch<dynamic>? color) {
|
onColorChange: (color) {
|
||||||
if(color == null) return;
|
|
||||||
_selectedColorValue = color.value;
|
_selectedColorValue = color.value;
|
||||||
},
|
},
|
||||||
selectedColor: primaryColor,
|
selectedColor: primaryColor,
|
||||||
);
|
),
|
||||||
}
|
actions: [
|
||||||
|
TextButton(
|
||||||
Widget _buildColorPickerConfirmBtn() {
|
onPressed: () {
|
||||||
return IconButton(
|
|
||||||
icon: const Icon(Icons.save),
|
|
||||||
onPressed: (() {
|
|
||||||
_setting.primaryColor.put(_selectedColorValue);
|
_setting.primaryColor.put(_selectedColorValue);
|
||||||
|
Navigator.pop(context);
|
||||||
_showRestartSnackbar();
|
_showRestartSnackbar();
|
||||||
}),
|
},
|
||||||
|
child: Text(_s.ok),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLaunchPage() {
|
Widget _buildLaunchPage() {
|
||||||
return ExpansionTile(
|
final items = AppTab.values
|
||||||
childrenPadding: const EdgeInsets.only(left: 17, right: 7),
|
.map(
|
||||||
textColor: primaryColor,
|
(e) => PopupMenuItem(
|
||||||
|
value: e.index,
|
||||||
|
child: Text(tabTitleName(context, e.index)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.launchPage,
|
_s.launchPage,
|
||||||
),
|
),
|
||||||
trailing: ConstrainedBox(
|
trailing: buildPopuopMenu<int>(
|
||||||
|
items: items,
|
||||||
|
onSelected: (idx) {
|
||||||
|
setState(() {
|
||||||
|
_launchPageIdx = idx;
|
||||||
|
});
|
||||||
|
_setting.launchPage.put(_launchPageIdx);
|
||||||
|
},
|
||||||
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||||
child: Text(
|
child: Text(
|
||||||
tabTitleName(context, _launchPageIdx),
|
tabTitleName(context, _launchPageIdx),
|
||||||
textAlign: TextAlign.right,
|
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() {
|
Widget _buildTermTheme() {
|
||||||
return ExpansionTile(
|
final items = TerminalColorsPlatform.values
|
||||||
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
|
|
||||||
.map(
|
.map(
|
||||||
(e) => ListTile(
|
(e) => PopupMenuItem<int>(
|
||||||
contentPadding: EdgeInsets.zero,
|
value: e.index,
|
||||||
title: Text(
|
child: Text(e.name),
|
||||||
e.name,
|
|
||||||
),
|
|
||||||
trailing: _buildTermThemeRadio(e),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
Radio _buildTermThemeRadio(TerminalColorsPlatform platform) {
|
_s.termTheme,
|
||||||
return Radio<int>(
|
),
|
||||||
value: platform.index,
|
trailing: buildPopuopMenu<int>(
|
||||||
groupValue: _termThemeIdx,
|
items: items,
|
||||||
onChanged: (int? value) {
|
onSelected: (idx) {
|
||||||
setState(() {
|
setState(() {
|
||||||
value ??= 0;
|
_termThemeIdx = idx;
|
||||||
_termThemeIdx = value!;
|
|
||||||
_setting.termColorIdx.put(value!);
|
|
||||||
});
|
});
|
||||||
|
_setting.termColorIdx.put(idx);
|
||||||
},
|
},
|
||||||
|
child: Text(
|
||||||
|
TerminalColorsPlatform.values[_termThemeIdx].name,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMaxRetry() {
|
Widget _buildMaxRetry() {
|
||||||
return ExpansionTile(
|
final items = List.generate(
|
||||||
textColor: primaryColor,
|
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(
|
title: Text(
|
||||||
_s.maxRetryCount,
|
_s.maxRetryCount,
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
),
|
),
|
||||||
trailing: Text(
|
trailing: buildPopuopMenu<int>(
|
||||||
|
items: items,
|
||||||
|
onSelected: (val) {
|
||||||
|
setState(() {
|
||||||
|
_maxRetryCount = val;
|
||||||
|
});
|
||||||
|
_setting.maxRetryCount.put(_maxRetryCount);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
'${_maxRetryCount.toInt()} ${_s.times}',
|
'${_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(
|
subtitle: Text(help, style: grey),
|
||||||
height: 3,
|
|
||||||
),
|
|
||||||
_maxRetryCount == 0.0
|
|
||||||
? Text(
|
|
||||||
_s.maxRetryCountEqual0,
|
|
||||||
style: grey,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
: const SizedBox(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 13,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildThemeMode() {
|
Widget _buildThemeMode() {
|
||||||
return ExpansionTile(
|
final items = ThemeMode.values.map(
|
||||||
textColor: primaryColor,
|
(e) {
|
||||||
|
final str = _buildThemeModeStr(e.index);
|
||||||
|
return PopupMenuItem(
|
||||||
|
value: e.index,
|
||||||
|
child: Text(str),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).toList();
|
||||||
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
_s.themeMode,
|
_s.themeMode,
|
||||||
),
|
),
|
||||||
trailing: Text(
|
trailing: buildPopuopMenu<int>(
|
||||||
_buildThemeModeStr(_nightMode),
|
items: items,
|
||||||
),
|
onSelected: (idx) {
|
||||||
children: [
|
_nightMode = idx;
|
||||||
Slider(
|
_setting.themeMode.put(_nightMode);
|
||||||
thumbColor: primaryColor,
|
|
||||||
activeColor: primaryColor.withOpacity(0.7),
|
|
||||||
min: 0,
|
|
||||||
max: 2,
|
|
||||||
value: _nightMode.toDouble(),
|
|
||||||
onChanged: (newValue) {
|
|
||||||
setState(() {
|
|
||||||
_nightMode = newValue.toInt();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onChangeEnd: (val) {
|
child: Text(_buildThemeModeStr(_nightMode)),
|
||||||
_setting.themeMode.put(val.toInt());
|
|
||||||
},
|
|
||||||
label: _buildThemeModeStr(_nightMode),
|
|
||||||
divisions: 2,
|
|
||||||
),
|
),
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,15 +411,17 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFont() {
|
Widget _buildFont() {
|
||||||
return ExpansionTile(
|
return ListTile(
|
||||||
title: Text(_s.chooseFontFile),
|
title: Text(_s.chooseFontFile),
|
||||||
trailing: Text(getFileName(_setting.fontPath.fetch()) ?? _s.notSelected),
|
trailing: Text(getFileName(_setting.fontPath.fetch()) ?? _s.notSelected),
|
||||||
children: [
|
onTap: () {
|
||||||
Row(
|
showRoundDialog(
|
||||||
|
context: context,
|
||||||
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async => _pickFontFile(),
|
onPressed: () async => await _pickFontFile(),
|
||||||
child: Text(_s.pickFile),
|
child: Text(_s.pickFile),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -486,8 +432,9 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
child: Text(_s.clear),
|
child: Text(_s.clear),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,9 +136,8 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
|||||||
void showFileActionDialog(FileSystemEntity file) {
|
void showFileActionDialog(FileSystemEntity file) {
|
||||||
final fileName = file.path.split('/').last;
|
final fileName = file.path.split('/').last;
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.choose,
|
child: Column(
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -147,10 +146,9 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
context.pop();
|
context.pop();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.sureDelete(fileName),
|
child: Text(_s.sureDelete(fileName)),
|
||||||
const SizedBox(),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -176,7 +174,7 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: (() => context.pop()),
|
onPressed: (() => context.pop()),
|
||||||
child: Text(_s.close),
|
child: Text(_s.close),
|
||||||
|
|||||||
@@ -98,9 +98,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: (() => showRoundDialog(
|
onPressed: (() => showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.choose,
|
child: Column(
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -113,7 +112,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
onTap: () => newFile(context)),
|
onTap: () => newFile(context)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.close),
|
child: Text(_s.close),
|
||||||
@@ -126,9 +125,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final p = await showRoundDialog<String?>(
|
final p = await showRoundDialog<String?>(
|
||||||
context,
|
context: context,
|
||||||
_s.goto,
|
title: Text(_s.goto),
|
||||||
Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
@@ -140,7 +139,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -254,9 +253,8 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
|
|
||||||
void onItemPress(BuildContext context, SftpName file, bool showDownload) {
|
void onItemPress(BuildContext context, SftpName file, bool showDownload) {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.choose,
|
child: Column(
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -278,7 +276,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
: const SizedBox()
|
: const SizedBox()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -289,10 +287,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
|
|
||||||
void download(BuildContext context, SftpName name) {
|
void download(BuildContext context, SftpName name) {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.download,
|
child: Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
||||||
Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -326,12 +323,13 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
void delete(BuildContext context, SftpName file) {
|
void delete(BuildContext context, SftpName file) {
|
||||||
context.pop();
|
context.pop();
|
||||||
final isDir = file.attr.isDirectory;
|
final isDir = file.attr.isDirectory;
|
||||||
|
final dirText = isDir ? '\n${_s.sureDirEmpty}' : '';
|
||||||
|
final text = '${_s.sureDelete(file.filename)}$dirText';
|
||||||
|
final child = Text(text);
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: child,
|
||||||
Text(
|
actions: [
|
||||||
'${_s.sureDelete(file.filename)}${isDir ? '\n${_s.sureDirEmpty}' : ''}'),
|
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -339,8 +337,11 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
context.pop();
|
context.pop();
|
||||||
showRoundDialog(context, 'Waiting...', centerSizedLoading, [],
|
showRoundDialog(
|
||||||
barrierDismiss: false);
|
context: context,
|
||||||
|
child: centerSizedLoading,
|
||||||
|
barrierDismiss: false,
|
||||||
|
);
|
||||||
final remotePath = _getRemotePath(file);
|
final remotePath = _getRemotePath(file);
|
||||||
try {
|
try {
|
||||||
if (file.attr.isDirectory) {
|
if (file.attr.isDirectory) {
|
||||||
@@ -352,10 +353,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.pop();
|
context.pop();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
title: Text(_s.error),
|
||||||
Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
@@ -379,15 +380,15 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.createFolder,
|
title: Text(_s.createFolder),
|
||||||
TextField(
|
child: TextField(
|
||||||
controller: textController,
|
controller: textController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: _s.name,
|
labelText: _s.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -396,10 +397,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.fieldMustNotEmpty),
|
||||||
Text(_s.fieldMustNotEmpty),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
@@ -426,15 +426,15 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.createFile,
|
title: Text(_s.createFile),
|
||||||
TextField(
|
child: TextField(
|
||||||
controller: textController,
|
controller: textController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: _s.name,
|
labelText: _s.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.cancel),
|
child: Text(_s.cancel),
|
||||||
@@ -443,10 +443,9 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.fieldMustNotEmpty),
|
||||||
Text(_s.fieldMustNotEmpty),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
@@ -474,24 +473,23 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
context.pop();
|
context.pop();
|
||||||
final textController = TextEditingController();
|
final textController = TextEditingController();
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.rename,
|
title: Text(_s.rename),
|
||||||
TextField(
|
child: TextField(
|
||||||
controller: textController,
|
controller: textController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: _s.name,
|
labelText: _s.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
[
|
actions: [
|
||||||
TextButton(onPressed: () => context.pop(), child: Text(_s.cancel)),
|
TextButton(onPressed: () => context.pop(), child: Text(_s.cancel)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (textController.text == '') {
|
if (textController.text == '') {
|
||||||
showRoundDialog(
|
showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.attention,
|
child: Text(_s.fieldMustNotEmpty),
|
||||||
Text(_s.fieldMustNotEmpty),
|
actions: [
|
||||||
[
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
@@ -540,10 +538,10 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context: context,
|
||||||
_s.error,
|
title: Text(_s.error),
|
||||||
Text(e.toString()),
|
child: Text(e.toString()),
|
||||||
[
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => context.pop(),
|
onPressed: () => context.pop(),
|
||||||
child: Text(_s.ok),
|
child: Text(_s.ok),
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ class CardDialog extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
contentPadding: padding ?? const EdgeInsets.fromLTRB(24, 17, 24, 7),
|
contentPadding: padding,
|
||||||
|
actionsPadding: const EdgeInsets.all(7),
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
borderRadius: BorderRadius.all(Radius.circular(20.0)),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
Widget buildPicker(List<Widget> items, Function(int idx) onSelected) {
|
Widget buildPicker(
|
||||||
|
List<Widget> items,
|
||||||
|
Function(int idx) onSelected, {
|
||||||
|
double height = 157,
|
||||||
|
}) {
|
||||||
|
final pad = (height - 37) / 2;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 111,
|
height: height,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 36,
|
top: pad,
|
||||||
bottom: 36,
|
bottom: pad,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -20,7 +25,7 @@ Widget buildPicker(List<Widget> items, Function(int idx) onSelected) {
|
|||||||
),
|
),
|
||||||
ListWheelScrollView.useDelegate(
|
ListWheelScrollView.useDelegate(
|
||||||
itemExtent: 37,
|
itemExtent: 37,
|
||||||
diameterRatio: 1.2,
|
diameterRatio: 2.7,
|
||||||
controller: FixedExtentScrollController(initialItem: 0),
|
controller: FixedExtentScrollController(initialItem: 0),
|
||||||
onSelectedItemChanged: (idx) => onSelected(idx),
|
onSelectedItemChanged: (idx) => onSelected(idx),
|
||||||
physics: const FixedExtentScrollPhysics(),
|
physics: const FixedExtentScrollPhysics(),
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RoundRectCard extends StatelessWidget {
|
class RoundRectCard extends StatelessWidget {
|
||||||
const RoundRectCard(this.child, {Key? key}) : super(key: key);
|
const RoundRectCard(this.child, {Key? key, this.color}) : super(key: key);
|
||||||
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
final Color? color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Card(
|
||||||
|
key: key,
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
|
color: color,
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(17))),
|
borderRadius: BorderRadius.all(Radius.circular(17)),
|
||||||
|
),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user