diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index d647a84c..57a97dfb 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -183,6 +183,12 @@ abstract class S { /// **'Run in backgroud'** 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. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index 67f0e8fc..bbbd27d9 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -49,6 +49,9 @@ class SEn extends S { @override String get bgRun => 'Run in backgroud'; + @override + String get canPullRefresh => 'You can pull to refresh.'; + @override String get cancel => 'Cancel'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index d70c4af4..afb62d22 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -49,6 +49,9 @@ class SZh extends S { @override String get bgRun => '后台运行'; + @override + String get canPullRefresh => '可以下拉刷新'; + @override String get cancel => '取消'; diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 35088205..403ff15d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -359,7 +359,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 280; + CURRENT_PROJECT_VERSION = 284; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -367,7 +367,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.280; + MARKETING_VERSION = 1.0.284; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -490,7 +490,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 280; + CURRENT_PROJECT_VERSION = 284; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -498,7 +498,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.280; + MARKETING_VERSION = 1.0.284; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -515,7 +515,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 280; + CURRENT_PROJECT_VERSION = 284; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -523,7 +523,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.280; + MARKETING_VERSION = 1.0.284; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/app.dart b/lib/app.dart index 9007d2d9..ce7503ab 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '/core/extension/colorx.dart'; import 'core/utils/ui.dart'; import 'data/res/build_data.dart'; import 'data/res/color.dart'; diff --git a/lib/core/update.dart b/lib/core/update.dart index ee7c2a34..5610022f 100644 --- a/lib/core/update.dart +++ b/lib/core/update.dart @@ -53,10 +53,9 @@ Future doUpdate(BuildContext context, {bool force = false}) async { if (update.build.min.current! > BuildData.build) { showRoundDialog( - context, - s.attention, - Text(s.updateTipTooLow(newest)), - [ + context: context, + child: Text(s.updateTipTooLow(newest)), + actions: [ TextButton( onPressed: () => _doUpdate(url, context, s), child: Text(s.ok), @@ -84,11 +83,15 @@ Future _doUpdate(String url, BuildContext context, S s) async { } else if (isIOS) { await RUpgrade.upgradeFromAppStore('1586449703'); } else { - showRoundDialog(context, s.attention, Text(s.platformNotSupportUpdate), [ - TextButton( - onPressed: () => context.pop(), - child: Text(s.ok), - ) - ]); + showRoundDialog( + context: context, + child: Text(s.platformNotSupportUpdate), + actions: [ + TextButton( + onPressed: () => context.pop(), + child: Text(s.ok), + ) + ], + ); } } diff --git a/lib/core/utils/ui.dart b/lib/core/utils/ui.dart index 0a2c789a..eb05bbd8 100644 --- a/lib/core/utils/ui.dart +++ b/lib/core/utils/ui.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:toolbox/core/utils/navigator.dart'; +import 'package:toolbox/data/res/ui.dart'; import 'package:url_launcher/url_launcher.dart'; import '../../data/model/server/snippet.dart'; @@ -25,8 +26,12 @@ bool isDarkMode(BuildContext context) => void showSnackBar(BuildContext context, Widget child) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: child)); -void showSnackBarWithAction(BuildContext context, String content, String action, - GestureTapCallback onTap) { +void showSnackBarWithAction( + BuildContext context, + String content, + String action, + GestureTapCallback onTap, +) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(content), behavior: SnackBarBehavior.floating, @@ -41,24 +46,33 @@ Future openUrl(String url) async { return await launchUrl(url.uri, mode: LaunchMode.externalApplication); } -Future? showRoundDialog( - BuildContext context, String title, Widget child, List actions, - {EdgeInsets? padding, bool barrierDismiss = true}) { +Future? showRoundDialog({ + required BuildContext context, + Widget? child, + List? actions, + Widget? title, + EdgeInsets? padding, + bool barrierDismiss = true, +}) { return showDialog( - context: context, - barrierDismissible: barrierDismiss, - builder: (ctx) { - return CardDialog( - title: Text(title), - content: child, - actions: actions, - padding: padding, - ); - }); + context: context, + barrierDismissible: barrierDismiss, + builder: (ctx) { + return CardDialog( + title: title, + content: child, + actions: actions, + padding: padding, + ); + }, + ); } -Widget buildSwitch(BuildContext context, StoreProperty prop, - {Function(bool)? func}) { +Widget buildSwitch( + BuildContext context, + StoreProperty prop, { + Function(bool)? func, +}) { return ValueListenableBuilder( valueListenable: prop.listenable(), builder: (context, bool value, widget) { @@ -75,27 +89,26 @@ Widget buildSwitch(BuildContext context, StoreProperty prop, void setTransparentNavigationBar(BuildContext context) { if (isAndroid) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( - systemNavigationBarColor: Colors.transparent, - systemNavigationBarContrastEnforced: true)); + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + systemNavigationBarContrastEnforced: true), + ); } } -Widget buildPopuopMenu( - {required List items, - required Function(dynamic) onSelected}) { - return PopupMenuButton( +Widget buildPopuopMenu({ + required List> items, + required void Function(T) onSelected, + Widget child = popMenuChild, + EdgeInsetsGeometry? padding, +}) { + return PopupMenuButton( itemBuilder: (_) => items, onSelected: onSelected, - padding: EdgeInsets.zero, + padding: padding ?? EdgeInsets.zero, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), - child: const Padding( - padding: EdgeInsets.only(left: 7), - child: Icon( - Icons.more_vert, - size: 21, - ), - ), + child: child, ); } @@ -123,14 +136,16 @@ Future loadFontFile(String? localPath) async { } void showSnippetDialog( - BuildContext context, S s, Function(Snippet s) onSelected) { + BuildContext context, + S s, + Function(Snippet s) onSelected, +) { final provider = locator(); if (provider.snippets.isEmpty) { showRoundDialog( - context, - s.attention, - Text(s.noSavedSnippet), - [ + context: context, + child: Text(s.noSavedSnippet), + actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(s.ok), @@ -149,13 +164,13 @@ void showSnippetDialog( var snippet = provider.snippets.first; showRoundDialog( - context, - s.choose, - buildPicker( + context: context, + title: Text(s.chooseDestination), + child: buildPicker( provider.snippets.map((e) => Text(e.name)).toList(), (idx) => snippet = provider.snippets[idx], ), - [ + actions: [ TextButton( onPressed: () async { context.pop(); diff --git a/lib/data/model/app/navigation_item.dart b/lib/data/model/app/navigation_item.dart deleted file mode 100644 index d59683ec..00000000 --- a/lib/data/model/app/navigation_item.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:flutter/material.dart'; - -class NavigationItem { - final IconData icon; - final String title; - - NavigationItem(this.icon, this.title); -} diff --git a/lib/data/model/app/tab.dart b/lib/data/model/app/tab.dart new file mode 100644 index 00000000..31f2aaa1 --- /dev/null +++ b/lib/data/model/app/tab.dart @@ -0,0 +1 @@ +enum AppTab { servers, encode, ping } diff --git a/lib/data/provider/pkg.dart b/lib/data/provider/pkg.dart index 6aa807e4..facb08ec 100644 --- a/lib/data/provider/pkg.dart +++ b/lib/data/provider/pkg.dart @@ -58,10 +58,9 @@ class PkgProvider extends BusyProvider { } Future refresh() async { - final result = await _update();_parse(result); - try { - - } catch (e) { + final result = await _update(); + _parse(result); + try {} catch (e) { error = '[Server Raw]:\n$result\n[App Error]:\n$e'; } finally { notifyListeners(); @@ -70,11 +69,8 @@ class PkgProvider extends BusyProvider { void _parse(String? raw) { if (raw == null) return; - final list = type - ?.updateListRemoveUnused(raw.split('\n')); - upgradeable = list - ?.map((e) => UpgradePkgInfo(e, type)) - .toList(); + final list = type?.updateListRemoveUnused(raw.split('\n')); + upgradeable = list?.map((e) => UpgradePkgInfo(e, type)).toList(); } Future _update() async { diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index be2f6514..8703d494 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import '../../core/build_mode.dart'; import '../../core/extension/uint8list.dart'; import '../../core/provider_base.dart'; import '../../core/utils/server.dart'; @@ -182,9 +181,6 @@ class ServerProvider extends BusyProvider { s.state = ServerState.failed; s.status.failedInfo = e.toString(); _logger.warning(e); - if (BuildMode.isDebug) { - rethrow; - } } finally { notifyListeners(); } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index d0c035f1..288fb470 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,8 +2,8 @@ class BuildData { 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 buildAt = "2023-04-27 18:10:45.464081"; - static const int modifications = 4; + static const String buildAt = "2023-05-07 00:52:57.124037"; + static const int modifications = 23; } diff --git a/lib/data/res/tab.dart b/lib/data/res/tab.dart deleted file mode 100644 index 004e937d..00000000 --- a/lib/data/res/tab.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:toolbox/data/model/app/navigation_item.dart'; - -final List tabs = ['Servers', 'En/Decode', 'Ping']; -final List tabItems = [ - NavigationItem(Icons.cloud, 'Server'), - NavigationItem(Icons.code, 'Convert'), - NavigationItem(Icons.leak_add, 'Ping'), -]; diff --git a/lib/data/res/ui.dart b/lib/data/res/ui.dart index 0aa5577a..ed113833 100644 --- a/lib/data/res/ui.dart +++ b/lib/data/res/ui.dart @@ -23,3 +23,11 @@ const roundRectCardPadding = EdgeInsets.symmetric(horizontal: 17, vertical: 13); const height13 = SizedBox(height: 13); const width13 = SizedBox(width: 13); const width7 = SizedBox(width: 7); + +const popMenuChild = Padding( + padding: EdgeInsets.only(left: 7), + child: Icon( + Icons.more_vert, + size: 21, + ), +); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 73601691..89b5941b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -14,6 +14,7 @@ "backupTip": "The exported data is simply encrypted. \nPlease keep it safe.", "backupVersionNotMatch": "Backup version is not match.", "bgRun": "Run in backgroud", + "canPullRefresh": "You can pull to refresh.", "cancel": "Cancel", "choose": "Choose", "chooseDestination": "Choose destination", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 6aab4fd8..c00f82b8 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -14,6 +14,7 @@ "backupTip": "导出的数据仅进行了简单加密,请妥善保管。", "backupVersionNotMatch": "备份版本不匹配,无法恢复", "bgRun": "后台运行", + "canPullRefresh": "可以下拉刷新", "cancel": "取消", "choose": "选择", "chooseDestination": "选择目标", diff --git a/lib/view/page/backup.dart b/lib/view/page/backup.dart index ae9db9b6..1f1b0489 100644 --- a/lib/view/page/backup.dart +++ b/lib/view/page/backup.dart @@ -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), diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index a757de80..0ae73ba9 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -124,7 +124,7 @@ class _ConvertPageState extends State onPressed: () => Clipboard.setData( ClipboardData( text: _textEditingControllerResult.text == '' - ? ' ' + ? '' : _textEditingControllerResult.text, ), ), diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index 093be7f5..3551b587 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -89,9 +89,9 @@ class _DockerManagePageState extends State { 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 { ), ], ), - [ + actions: [ TextButton( onPressed: () => context.pop(), child: Text(_s.cancel), @@ -142,10 +142,10 @@ class _DockerManagePageState extends State { Future _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 { 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 { Future 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 { labelText: _s.pwd, ), ), - [ + actions: [ TextButton( onPressed: () { context.pop(); @@ -290,10 +294,9 @@ class _DockerManagePageState extends State { 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 { Future _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 { context.pop(); }, ), - [ + actions: [ TextButton( onPressed: () => context.pop(), child: Text(_s.cancel), @@ -473,10 +476,9 @@ class _DockerManagePageState extends State { 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(); diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index 1e5933b0..da21ee85 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -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 late final PageController _pageController; late int _selectIndex; - late double _width; late S _s; @override @@ -67,7 +61,6 @@ class _MyHomePageState extends State void didChangeDependencies() { super.didChangeDependencies(); _s = S.of(context)!; - _width = MediaQuery.of(context).size.width; } @override @@ -135,33 +128,35 @@ class _MyHomePageState extends State ); } - 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 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 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 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 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 ) ], ), - [ + actions: [ TextButton( onPressed: () => showLicensePage(context: context), child: Text(_s.license), @@ -284,7 +278,7 @@ class _MyHomePageState extends State ); }, ) - ], + ].map((e) => RoundRectCard(e)).toList(), ), ), ], diff --git a/lib/view/page/pkg.dart b/lib/view/page/pkg.dart index 2364132f..a394f15c 100644 --- a/lib/view/page/pkg.dart +++ b/lib/view/page/pkg.dart @@ -72,10 +72,9 @@ class _PkgManagePageState extends State 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 Future 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 labelText: _s.pwd, ), ), - [ + actions: [ TextButton( onPressed: () { context.pop(); @@ -234,10 +233,7 @@ class _PkgManagePageState extends State }(); return ListTile( title: Text(info.package), - subtitle: Text( - t, - style: grey - ), + subtitle: Text(t, style: grey), ); } } diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 9302ec67..52565e95 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -68,10 +68,9 @@ class _ServerEditPageState extends State 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 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 with AfterLayoutMixin { } if (!usePublicKey && _passwordController.text == '') { final cancel = await showRoundDialog( - context, - _s.attention, - Text(_s.sureNoPwd), - [ + context: context, + child: Text(_s.sureNoPwd), + actions: [ TextButton( onPressed: () => context.pop(false), child: Text(_s.ok), diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 620c4b2e..4a17f5b1 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -166,12 +166,16 @@ class _ServerPageState extends State 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 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 ) ], ); - _settingStore.firstTimeUseSshTerm.put(false); } else { AppRoute(SSHPage(spi: spi), 'ssh page').go(context); } @@ -269,13 +272,11 @@ class _ServerPageState extends State break; case ServerTabMenuItems.snippet: showSnippetDialog(context, _s, (s) async { - final result = - await locator().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), diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index e08ae230..c12ba084 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -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 { 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 { _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 { } 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 { _s.willTakEeffectImmediately, style: grey, ), - trailing: Text( - '${_updateInterval.toInt()} ${_s.second}', + trailing: buildPopuopMenu( + 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 { title: Text( _s.appPrimaryColor, ), - children: [_buildAppColorPicker(), _buildColorPickerConfirmBtn()], - ); - } - - Widget _buildAppColorPicker() { - return MaterialColorPicker( - shrinkWrap: true, - allowShades: false, - onMainColorChange: (ColorSwatch? 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( + 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( - 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 _buildTermThemeRadioList() { - return TerminalColorsPlatform.values + final items = TerminalColorsPlatform.values .map( - (e) => ListTile( - contentPadding: EdgeInsets.zero, - title: Text( - e.name, - ), - trailing: _buildTermThemeRadio(e), + (e) => PopupMenuItem( + value: e.index, + child: Text(e.name), ), ) .toList(); - } - - Radio _buildTermThemeRadio(TerminalColorsPlatform platform) { - return Radio( - 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( + 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( + 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( + 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 { } 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), + ) + ], + ), + ); + }, ); } diff --git a/lib/view/page/sftp/downloaded.dart b/lib/view/page/sftp/downloaded.dart index f49790c1..768a1bc1 100644 --- a/lib/view/page/sftp/downloaded.dart +++ b/lib/view/page/sftp/downloaded.dart @@ -136,9 +136,8 @@ class _SFTPDownloadedPageState extends State { 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 { 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 { ), ], ), - [ + actions: [ TextButton( onPressed: (() => context.pop()), child: Text(_s.close), diff --git a/lib/view/page/sftp/view.dart b/lib/view/page/sftp/view.dart index d41698cb..1cbcea6b 100644 --- a/lib/view/page/sftp/view.dart +++ b/lib/view/page/sftp/view.dart @@ -98,9 +98,8 @@ class _SFTPPageState extends State { ), IconButton( onPressed: (() => showRoundDialog( - context, - _s.choose, - Column( + context: context, + child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( @@ -113,7 +112,7 @@ class _SFTPPageState extends State { onTap: () => newFile(context)), ], ), - [ + actions: [ TextButton( onPressed: () => context.pop(), child: Text(_s.close), @@ -126,9 +125,9 @@ class _SFTPPageState extends State { padding: const EdgeInsets.all(0), onPressed: () async { final p = await showRoundDialog( - 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 { ), ], ), - [ + actions: [ TextButton( onPressed: () => context.pop(), child: Text(_s.cancel), @@ -254,9 +253,8 @@ class _SFTPPageState extends State { 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 { : const SizedBox() ], ), - [ + actions: [ TextButton( onPressed: () => context.pop(), child: Text(_s.cancel), @@ -289,10 +287,9 @@ class _SFTPPageState extends State { 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 { 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 { 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 { } 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 { 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 { 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 { 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 { 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 { 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 { } } 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), diff --git a/lib/view/widget/card_dialog.dart b/lib/view/widget/card_dialog.dart index b4d34819..35255c6a 100644 --- a/lib/view/widget/card_dialog.dart +++ b/lib/view/widget/card_dialog.dart @@ -13,7 +13,8 @@ class CardDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - contentPadding: padding ?? const EdgeInsets.fromLTRB(24, 17, 24, 7), + contentPadding: padding, + actionsPadding: const EdgeInsets.all(7), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(20.0)), ), diff --git a/lib/view/widget/picker.dart b/lib/view/widget/picker.dart index 9bfef1de..9163b33d 100644 --- a/lib/view/widget/picker.dart +++ b/lib/view/widget/picker.dart @@ -1,13 +1,18 @@ import 'package:flutter/material.dart'; -Widget buildPicker(List items, Function(int idx) onSelected) { +Widget buildPicker( + List items, + Function(int idx) onSelected, { + double height = 157, +}) { + final pad = (height - 37) / 2; return SizedBox( - height: 111, + height: height, child: Stack( children: [ Positioned( - top: 36, - bottom: 36, + top: pad, + bottom: pad, left: 0, right: 0, child: Container( @@ -20,7 +25,7 @@ Widget buildPicker(List items, Function(int idx) onSelected) { ), ListWheelScrollView.useDelegate( itemExtent: 37, - diameterRatio: 1.2, + diameterRatio: 2.7, controller: FixedExtentScrollController(initialItem: 0), onSelectedItemChanged: (idx) => onSelected(idx), physics: const FixedExtentScrollPhysics(), diff --git a/lib/view/widget/round_rect_card.dart b/lib/view/widget/round_rect_card.dart index dc4aaafe..16a35b41 100644 --- a/lib/view/widget/round_rect_card.dart +++ b/lib/view/widget/round_rect_card.dart @@ -1,16 +1,20 @@ import 'package:flutter/material.dart'; 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 Color? color; @override Widget build(BuildContext context) { return Card( + key: key, clipBehavior: Clip.antiAlias, + color: color, shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(17))), + borderRadius: BorderRadius.all(Radius.circular(17)), + ), child: child, ); }