diff --git a/.vscode/settings.json b/.vscode/settings.json index f80add36..c0d42415 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,8 @@ }, "search.exclude": { "**/.fvm": true - } + }, + "git.ignoredRepositories": [ + ".fvm" + ], } \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 971f5be3..96397d60 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -356,7 +356,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -364,7 +364,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.201; + MARKETING_VERSION = 1.0.205; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -486,7 +486,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -494,7 +494,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.201; + MARKETING_VERSION = 1.0.205; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -510,7 +510,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -518,7 +518,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.201; + MARKETING_VERSION = 1.0.205; 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 abea82ae..631007b0 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,13 +1,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:toolbox/core/extension/colorx.dart'; -import 'package:toolbox/data/res/build_data.dart'; -import 'package:toolbox/data/store/setting.dart'; -import 'package:toolbox/generated/l10n.dart'; -import 'package:toolbox/locator.dart'; -import 'package:toolbox/view/page/home.dart'; +import '/core/extension/colorx.dart'; import 'core/utils/ui.dart'; +import 'data/res/build_data.dart'; +import 'data/res/color.dart'; +import 'data/store/setting.dart'; +import 'generated/l10n.dart'; +import 'locator.dart'; +import 'view/page/home.dart'; class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @@ -16,65 +17,64 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { setTransparentNavigationBar(context); return ValueListenableBuilder( - valueListenable: locator().primaryColor.listenable(), - builder: (_, value, __) { - final primaryColor = Color(value); - final textStyle = TextStyle(color: primaryColor); - final materialColor = primaryColor.materialStateColor; - final materialColorAlpha = - primaryColor.withOpacity(0.7).materialStateColor; - return MaterialApp( - localizationsDelegates: const [ - S.delegate, - ...GlobalMaterialLocalizations.delegates, - ], - supportedLocales: S.delegate.supportedLocales, - title: BuildData.name, - theme: ThemeData( - primaryColor: primaryColor, - appBarTheme: AppBarTheme(backgroundColor: primaryColor), - floatingActionButtonTheme: - FloatingActionButtonThemeData(backgroundColor: primaryColor), - iconTheme: IconThemeData(color: primaryColor), - primaryIconTheme: IconThemeData(color: primaryColor), - switchTheme: SwitchThemeData( - thumbColor: materialColor, - trackColor: materialColorAlpha, - ), - buttonTheme: ButtonThemeData(splashColor: primaryColor), - inputDecorationTheme: InputDecorationTheme( - labelStyle: textStyle, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor), - ), - ), - radioTheme: RadioThemeData( - fillColor: materialColor, - ), - ), - darkTheme: ThemeData.dark().copyWith( - primaryColor: primaryColor, - floatingActionButtonTheme: - FloatingActionButtonThemeData(backgroundColor: primaryColor), - iconTheme: IconThemeData(color: primaryColor), - primaryIconTheme: IconThemeData(color: primaryColor), - switchTheme: SwitchThemeData( - thumbColor: materialColor, - trackColor: materialColorAlpha, - ), - buttonTheme: ButtonThemeData(splashColor: primaryColor), - inputDecorationTheme: InputDecorationTheme( - labelStyle: textStyle, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor), - ), - ), - radioTheme: RadioThemeData( - fillColor: materialColor, - ), - ), - home: MyHomePage(primaryColor: primaryColor), - ); - }); + valueListenable: locator().primaryColor.listenable(), + builder: (_, colorValue, __) { + primaryColor = Color(colorValue); + + final textStyle = TextStyle(color: primaryColor); + final materialColor = primaryColor.materialStateColor; + final materialColorAlpha = + primaryColor.withOpacity(0.7).materialStateColor; + final fabTheme = + FloatingActionButtonThemeData(backgroundColor: primaryColor); + final switchTheme = SwitchThemeData( + thumbColor: materialColor, + trackColor: materialColorAlpha, + ); + final appBarTheme = AppBarTheme(backgroundColor: primaryColor); + final iconTheme = IconThemeData(color: primaryColor); + final inputDecorationTheme = InputDecorationTheme( + labelStyle: textStyle, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor), + ), + ); + final radioTheme = RadioThemeData( + fillColor: materialColor, + ); + + return MaterialApp( + localizationsDelegates: const [ + S.delegate, + ...GlobalMaterialLocalizations.delegates, + ], + supportedLocales: S.delegate.supportedLocales, + title: BuildData.name, + theme: ThemeData( + useMaterial3: false, + primaryColor: primaryColor, + primarySwatch: primaryColor.materialColor, + appBarTheme: appBarTheme, + floatingActionButtonTheme: fabTheme, + iconTheme: iconTheme, + primaryIconTheme: iconTheme, + switchTheme: switchTheme, + inputDecorationTheme: inputDecorationTheme, + radioTheme: radioTheme, + ), + darkTheme: ThemeData.dark().copyWith( + useMaterial3: false, + primaryColor: primaryColor, + floatingActionButtonTheme: fabTheme, + iconTheme: iconTheme, + primaryIconTheme: iconTheme, + switchTheme: switchTheme, + inputDecorationTheme: inputDecorationTheme, + radioTheme: radioTheme, + ), + home: MyHomePage(primaryColor: primaryColor), + ); + }, + ); } } diff --git a/lib/core/extension/colorx.dart b/lib/core/extension/colorx.dart index 8dc0e151..0f96c909 100644 --- a/lib/core/extension/colorx.dart +++ b/lib/core/extension/colorx.dart @@ -24,4 +24,17 @@ extension ColorX on Color { return null; }); } + + MaterialColor get materialColor => MaterialColor(value, { + 50: withOpacity(0.05), + 100: withOpacity(0.1), + 200: withOpacity(0.2), + 300: withOpacity(0.3), + 400: withOpacity(0.4), + 500: withOpacity(0.5), + 600: withOpacity(0.6), + 700: withOpacity(0.7), + 800: withOpacity(0.8), + 900: withOpacity(0.9), + }); } diff --git a/lib/core/update.dart b/lib/core/update.dart index 8774f766..f255d29a 100644 --- a/lib/core/update.dart +++ b/lib/core/update.dart @@ -56,10 +56,17 @@ Future doUpdate(BuildContext context, {bool force = false}) async { final s = S.of(context); if (update.min > BuildData.build) { - showRoundDialog(context, s.attention, Text(s.updateTipTooLow(newest)), [ - TextButton( - onPressed: () => _doUpdate(update, context, s), child: Text(s.ok)) - ]); + showRoundDialog( + context, + s.attention, + Text(s.updateTipTooLow(newest)), + [ + TextButton( + onPressed: () => _doUpdate(update, context, s), + child: Text(s.ok), + ) + ], + ); return; } @@ -73,14 +80,19 @@ Future doUpdate(BuildContext context, {bool force = false}) async { Future _doUpdate(AppUpdate update, BuildContext context, S s) async { if (Platform.isAndroid) { - await RUpgrade.upgrade(update.android, - fileName: update.android.split('/').last, isAutoRequestInstall: true); + await RUpgrade.upgrade( + update.android, + fileName: update.android.split('/').last, + isAutoRequestInstall: true, + ); } else if (Platform.isIOS) { await RUpgrade.upgradeFromAppStore('1586449703'); } else { showRoundDialog(context, s.attention, Text(s.platformNotSupportUpdate), [ TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(s.ok)) + onPressed: () => Navigator.of(context).pop(), + child: Text(s.ok), + ) ]); } } diff --git a/lib/data/model/app/dynamic_color.dart b/lib/data/model/app/dynamic_color.dart new file mode 100644 index 00000000..334a9ef1 --- /dev/null +++ b/lib/data/model/app/dynamic_color.dart @@ -0,0 +1,15 @@ +import 'package:flutter/widgets.dart'; + +import '../../../core/utils/ui.dart'; + +class DynamicColor { + /// 白天模式显示的颜色 + Color light; + + /// 暗黑模式显示的颜色 + Color dark; + + DynamicColor(this.light, this.dark); + + Color resolve(BuildContext context) => isDarkMode(context) ? dark : light; +} diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 5940c763..cd56cc2b 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -275,4 +275,4 @@ class _TryLimiter { void resetTryTimes(String id) { _triedTimes[id] = 0; } -} \ No newline at end of file +} diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index d99829e3..c455377e 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 203; + static const int build = 205; static const String engine = "Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (8 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n"; - static const String buildAt = "2023-02-01 12:58:12.944187"; - static const int modifications = 13; + static const String buildAt = "2023-02-01 14:57:28.662965"; + static const int modifications = 5; } diff --git a/lib/data/res/color.dart b/lib/data/res/color.dart index 5efd6f56..a7af2b1d 100644 --- a/lib/data/res/color.dart +++ b/lib/data/res/color.dart @@ -1,18 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:toolbox/data/store/setting.dart'; +import 'package:toolbox/locator.dart'; -import '../../core/utils/ui.dart'; +import '../model/app/dynamic_color.dart'; -class DynamicColor { - /// 白天模式显示的颜色 - Color light; +Color primaryColor = Color(locator().primaryColor.fetch()!); - /// 暗黑模式显示的颜色 - Color dark; - - DynamicColor(this.light, this.dark); - - resolve(BuildContext context) => isDarkMode(context) ? dark : light; -} - -final mainColor = DynamicColor(Colors.black87, Colors.white70); +final contentColor = DynamicColor(Colors.black87, Colors.white70); +final bgColor = DynamicColor(Colors.white, Colors.black); final progressColor = DynamicColor(Colors.grey.shade100, Colors.white10); diff --git a/lib/locator.dart b/lib/locator.dart index dcc9e3d2..e6416e1f 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -1,20 +1,20 @@ import 'package:get_it/get_it.dart'; -import 'package:toolbox/data/provider/app.dart'; -import 'package:toolbox/data/provider/pkg.dart'; -import 'package:toolbox/data/provider/debug.dart'; -import 'package:toolbox/data/provider/docker.dart'; -import 'package:toolbox/data/provider/private_key.dart'; -import 'package:toolbox/data/provider/server.dart'; -import 'package:toolbox/data/provider/sftp_download.dart'; -import 'package:toolbox/data/provider/snippet.dart'; -import 'package:toolbox/data/service/app.dart'; -import 'package:toolbox/data/store/docker.dart'; -import 'package:toolbox/data/store/private_key.dart'; -import 'package:toolbox/data/store/server.dart'; -import 'package:toolbox/data/store/setting.dart'; -import 'package:toolbox/data/store/snippet.dart'; +import 'data/provider/app.dart'; +import 'data/provider/debug.dart'; +import 'data/provider/docker.dart'; +import 'data/provider/pkg.dart'; +import 'data/provider/private_key.dart'; +import 'data/provider/server.dart'; +import 'data/provider/sftp_download.dart'; +import 'data/provider/snippet.dart'; import 'data/provider/virtual_keyboard.dart'; +import 'data/service/app.dart'; +import 'data/store/docker.dart'; +import 'data/store/private_key.dart'; +import 'data/store/server.dart'; +import 'data/store/setting.dart'; +import 'data/store/snippet.dart'; GetIt locator = GetIt.instance; diff --git a/lib/view/page/backup.dart b/lib/view/page/backup.dart index 9b2b7510..ea936eed 100644 --- a/lib/view/page/backup.dart +++ b/lib/view/page/backup.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:toolbox/data/res/color.dart'; import '../../core/extension/colorx.dart'; import '../../core/utils/ui.dart'; @@ -15,7 +16,6 @@ import '../../data/store/setting.dart'; import '../../data/store/snippet.dart'; import '../../generated/l10n.dart'; import '../../locator.dart'; -import '../widget/primary_color.dart'; const backupFormatVersion = 1; @@ -68,32 +68,28 @@ class BackupPage extends StatelessWidget { Widget _buildCard(String text, IconData icon, MediaQueryData media, FutureOr Function() onTap) { - return PrimaryColor( - builder: ((context, pColor) { - final textColor = pColor.isBrightColor ? Colors.black : Colors.white; - return GestureDetector( - onTap: onTap, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(37), color: pColor), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icon, - color: textColor, - ), - const SizedBox(width: 7), - Text(text, style: TextStyle(color: textColor)), - ], + final textColor = primaryColor.isBrightColor ? Colors.black : Colors.white; + return GestureDetector( + onTap: onTap, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(37), color: primaryColor), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + icon, + color: textColor, ), - ), + const SizedBox(width: 7), + Text(text, style: TextStyle(color: textColor)), + ], ), - ); - }), + ), + ), ); } diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index 46784e4d..444ed724 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../core/utils/ui.dart'; +import '../../data/res/color.dart'; import '../../generated/l10n.dart'; import '../widget/input_field.dart'; -import '../widget/primary_color.dart'; import '../widget/round_rect_card.dart'; class ConvertPage extends StatefulWidget { @@ -105,78 +105,72 @@ class _ConvertPageState extends State 'URL $encode', 'URL $decode' ]; - return PrimaryColor(builder: (context, primaryColor) { - return RoundRectCard( - ExpansionTile( - tilePadding: const EdgeInsets.only(left: 7, right: 27), - childrenPadding: EdgeInsets.zero, - title: Row( - children: [ - TextButton( - style: ButtonStyle( - foregroundColor: MaterialStateProperty.all(primaryColor)), - child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown), - onPressed: () { - final temp = _textEditingController.text; - _textEditingController.text = - _textEditingControllerResult.text; - _textEditingControllerResult.text = temp; - }, + return RoundRectCard( + ExpansionTile( + tilePadding: const EdgeInsets.only(left: 7, right: 27), + childrenPadding: EdgeInsets.zero, + title: Row( + children: [ + TextButton( + child: Icon(Icons.change_circle, semanticLabel: _s.upsideDown), + onPressed: () { + final temp = _textEditingController.text; + _textEditingController.text = _textEditingControllerResult.text; + _textEditingControllerResult.text = temp; + }, + ), + TextButton( + child: Icon(Icons.copy, semanticLabel: _s.copy), + onPressed: () => Clipboard.setData( + ClipboardData( + text: _textEditingControllerResult.text == '' + ? ' ' + : _textEditingControllerResult.text, + ), ), - TextButton( - style: ButtonStyle( - foregroundColor: MaterialStateProperty.all(primaryColor), - ), - child: Icon(Icons.copy, semanticLabel: _s.copy), - onPressed: () => Clipboard.setData( - ClipboardData( - text: _textEditingControllerResult.text == '' - ? ' ' - : _textEditingControllerResult.text), + ) + ], + ), + trailing: ConstrainedBox( + constraints: BoxConstraints(maxWidth: _media.size.width * 0.35), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + typeOption[_typeOptionIndex], + textScaleFactor: 1.0, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w500, + color: primaryColor, ), + ), + Text( + _s.currentMode, + textScaleFactor: 1.0, + textAlign: TextAlign.right, + style: const TextStyle(fontSize: 9.0, color: Colors.grey), ) ], ), - trailing: ConstrainedBox( - constraints: BoxConstraints(maxWidth: _media.size.width * 0.35), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - typeOption[_typeOptionIndex], - textScaleFactor: 1.0, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w500, - color: primaryColor), - ), - Text( - _s.currentMode, - textScaleFactor: 1.0, - textAlign: TextAlign.right, - style: const TextStyle(fontSize: 9.0, color: Colors.grey), - ) - ], - ), - ), - children: typeOption - .map( - (e) => ListTile( - title: Text( - e, - style: TextStyle( - color: _theme.textTheme.bodyMedium?.color?.withAlpha(177), - ), - ), - trailing: _buildRadio(typeOption.indexOf(e)), - ), - ) - .toList(), ), - ); - }); + children: typeOption + .map( + (e) => ListTile( + title: Text( + e, + style: TextStyle( + color: _theme.textTheme.bodyMedium?.color?.withAlpha(177), + ), + ), + trailing: _buildRadio(typeOption.indexOf(e)), + ), + ) + .toList(), + ), + ); } Widget _buildResult() { diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index 4482dfba..ed22fb04 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -190,7 +190,9 @@ class _DockerManagePageState extends State { if (_textController.text == '') { showRoundDialog(context, _s.attention, Text(_s.fieldMustNotEmpty), [ TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(_s.ok)), + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.ok), + ), ]); return; } diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index 7f855bf0..d551f746 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -7,6 +7,7 @@ import '../../core/analysis.dart'; import '../../core/route.dart'; import '../../core/update.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'; @@ -28,6 +29,9 @@ 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, required this.primaryColor}) : super(key: key); final Color primaryColor; @@ -112,7 +116,7 @@ class _MyHomePageState extends State ); } - Widget _buildItem(int idx, NavigationItem item, bool isSelected) { + Widget _buildBottomItem(int idx, NavigationItem item, bool isSelected) { final width = _width / tabItems.length; return AnimatedContainer( duration: const Duration(milliseconds: 377), @@ -121,9 +125,7 @@ class _MyHomePageState extends State width: isSelected ? width : width - 17, decoration: BoxDecoration( color: isSelected - ? isDarkMode(context) - ? Colors.white12 - : Colors.black.withOpacity(0.07) + ? _bottomItemOverlayColor.resolve(context) : Colors.transparent, borderRadius: const BorderRadius.all( Radius.circular(50), @@ -156,7 +158,8 @@ class _MyHomePageState extends State children: tabItems.map( (item) { int itemIndex = tabItems.indexOf(item); - return _buildItem(itemIndex, item, _selectIndex == itemIndex); + return _buildBottomItem( + itemIndex, item, _selectIndex == itemIndex,); }, ).toList(), ), @@ -179,7 +182,6 @@ class _MyHomePageState extends State ), child: Text( '${BuildData.name}\n$_versionStr', - style: TextStyle(color: widget.primaryColor), textAlign: TextAlign.center, ), ), @@ -225,11 +227,6 @@ class _MyHomePageState extends State _s.feedback, Text(_s.feedbackOnGithub), [ - TextButton( - onPressed: () => Clipboard.setData( - const ClipboardData(text: issueUrl)), - child: Text(_s.copy), - ), TextButton( onPressed: () => openUrl(issueUrl), child: Text(_s.feedback), diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index d349ff50..9acf22dd 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -1,14 +1,17 @@ +import 'dart:async'; + +import 'package:after_layout/after_layout.dart'; import 'package:flutter/material.dart'; import '../../core/extension/uint8list.dart'; import '../../core/utils/ui.dart'; import '../../data/model/server/ping_result.dart'; import '../../data/provider/server.dart'; +import '../../data/res/color.dart'; import '../../data/res/font_style.dart'; import '../../generated/l10n.dart'; import '../../locator.dart'; import '../widget/input_field.dart'; -import '../widget/primary_color.dart'; import '../widget/round_rect_card.dart'; final doaminReg = @@ -25,7 +28,7 @@ class PingPage extends StatefulWidget { } class _PingPageState extends State - with AutomaticKeepAliveClientMixin { + with AutomaticKeepAliveClientMixin, AfterLayoutMixin { late TextEditingController _textEditingController; late MediaQueryData _media; final List _results = []; @@ -54,20 +57,24 @@ class _PingPageState extends State child: Column( children: [ const SizedBox(height: 13), - buildInput(context, _textEditingController, - hint: s.inputDomainHere, - maxLines: 1, - onSubmitted: (_) => doPing()), + buildInput( + context, + _textEditingController, + hint: s.inputDomainHere, + maxLines: 1, + onSubmitted: (_) => doPing(), + ), SizedBox( width: double.infinity, height: _media.size.height * 0.6, child: ListView.builder( - controller: ScrollController(), - itemCount: _results.length, - itemBuilder: (context, index) { - final result = _results[index]; - return _buildResultItem(result); - }), + controller: ScrollController(), + itemCount: _results.length, + itemBuilder: (context, index) { + final result = _results[index]; + return _buildResultItem(result); + }, + ), ), ], ), @@ -89,34 +96,29 @@ class _PingPageState extends State Widget _buildResultItem(PingResult result) { final unknown = s.unknown; final ms = s.ms; - return PrimaryColor( - builder: ((context, primaryColor) { - return RoundRectCard( - ListTile( - contentPadding: - const EdgeInsets.symmetric(vertical: 7, horizontal: 17), - title: Text( - result.serverName, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: primaryColor, - ), - ), - subtitle: Text( - _buildPingSummary(result, unknown, ms), - style: textSize11, - ), - trailing: Text( - '${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms', - style: TextStyle( - fontSize: 14, - color: primaryColor, - ), - ), + return RoundRectCard( + ListTile( + contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), + title: Text( + result.serverName, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: primaryColor, ), - ); - }), + ), + subtitle: Text( + _buildPingSummary(result, unknown, ms), + style: textSize11, + ), + trailing: Text( + '${s.pingAvg}${result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown} $ms', + style: TextStyle( + fontSize: 14, + color: primaryColor, + ), + ), + ), ); } @@ -169,4 +171,10 @@ class _PingPageState extends State @override bool get wantKeepAlive => true; + + @override + Future> afterFirstLayout(BuildContext context) async { + await _serverProvider.loadLocalData(); + await _serverProvider.refreshData(); + } } diff --git a/lib/view/page/pkg.dart b/lib/view/page/pkg.dart index 01bd2e5f..67bb39be 100644 --- a/lib/view/page/pkg.dart +++ b/lib/view/page/pkg.dart @@ -78,7 +78,9 @@ class _PkgManagePageState extends State Text(_s.fieldMustNotEmpty), [ TextButton( - onPressed: () => Navigator.of(context).pop(), child: Text(_s.ok)), + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.ok), + ), ], ); return; @@ -108,11 +110,12 @@ class _PkgManagePageState extends State }, child: Text(_s.cancel)), TextButton( - onPressed: () => onSubmitted(), - child: Text( - _s.ok, - style: const TextStyle(color: Colors.red), - )), + onPressed: () => onSubmitted(), + child: Text( + _s.ok, + style: const TextStyle(color: Colors.red), + ), + ), ], ); return _textController.text.trim(); @@ -203,10 +206,11 @@ class _PkgManagePageState extends State children: apt.upgradeLog == null ? [ TextButton( - child: Text(_s.updateAll), - onPressed: () { - apt.upgrade(); - }), + child: Text(_s.updateAll), + onPressed: () { + apt.upgrade(); + }, + ), ...apt.upgradeable!.map((e) => _buildUpdateItem(e, apt)).toList() ] : [ diff --git a/lib/view/page/private_key/list.dart b/lib/view/page/private_key/list.dart index e9f8a5fd..e9e7ce46 100644 --- a/lib/view/page/private_key/list.dart +++ b/lib/view/page/private_key/list.dart @@ -47,9 +47,9 @@ class _PrivateKeyListState extends State { ), trailing: TextButton( onPressed: () => AppRoute( - PrivateKeyEditPage(info: key.infos[idx]), - 'private key edit page') - .go(context), + PrivateKeyEditPage(info: key.infos[idx]), + 'private key edit page', + ).go(context), child: Text(_s.edit), ), ), diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index c8c4b64b..fb6b2382 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -14,7 +14,6 @@ import '../../../data/res/sizedbox.dart'; import '../../../data/store/setting.dart'; import '../../../generated/l10n.dart'; import '../../../locator.dart'; -import '../../widget/primary_color.dart'; import '../../widget/round_rect_card.dart'; class ServerDetailPage extends StatefulWidget { @@ -174,14 +173,12 @@ class _ServerDetailPageState extends State Widget _buildProgress(double percent) { if (percent > 100) percent = 100; final percentWithinOne = percent / 100; - return PrimaryColor(builder: (context, primaryColor) { - return LinearProgressIndicator( - value: percentWithinOne, - minHeight: 7, - backgroundColor: progressColor.resolve(context), - color: primaryColor, - ); - }); + return LinearProgressIndicator( + value: percentWithinOne, + minHeight: 7, + backgroundColor: progressColor.resolve(context), + color: primaryColor, + ); } Widget _buildUpTimeAndSys(ServerStatus ss) { diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 9e7dae73..f8f7e783 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -8,12 +8,12 @@ import '../../../data/model/server/private_key_info.dart'; import '../../../data/model/server/server_private_info.dart'; import '../../../data/provider/private_key.dart'; import '../../../data/provider/server.dart'; +import '../../../data/res/color.dart'; import '../../../data/res/font_style.dart'; import '../../../data/store/private_key.dart'; import '../../../generated/l10n.dart'; import '../../../locator.dart'; import '../../widget/input_decoration.dart'; -import '../../widget/primary_color.dart'; import '../private_key/edit.dart'; class ServerEditPage extends StatefulWidget { @@ -200,19 +200,17 @@ class _ServerEditPageState extends State with AfterLayoutMixin { ), ), ); - return PrimaryColor(builder: ((context, primaryColor) { - return ExpansionTile( - textColor: primaryColor, - iconColor: primaryColor, - tilePadding: EdgeInsets.zero, - childrenPadding: EdgeInsets.zero, - title: Text( - _s.choosePrivateKey, - style: const TextStyle(fontSize: 14), - ), - children: tiles, - ); - })); + return ExpansionTile( + textColor: primaryColor, + iconColor: primaryColor, + tilePadding: EdgeInsets.zero, + childrenPadding: EdgeInsets.zero, + title: Text( + _s.choosePrivateKey, + style: const TextStyle(fontSize: 14), + ), + children: tiles, + ); }, ) : const SizedBox() @@ -233,11 +231,13 @@ class _ServerEditPageState extends State with AfterLayoutMixin { Text(_s.sureNoPwd), [ TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(_s.ok)), + onPressed: () => Navigator.of(context).pop(false), + child: Text(_s.ok), + ), TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(_s.cancel)) + onPressed: () => Navigator.of(context).pop(true), + child: Text(_s.cancel), + ) ], barrierDismiss: false, ); diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 3684e372..31a8b68d 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -11,6 +11,7 @@ import '../../../data/model/server/server_private_info.dart'; import '../../../data/model/server/server_status.dart'; import '../../../data/provider/server.dart'; import '../../../data/provider/snippet.dart'; +import '../../../data/res/color.dart'; import '../../../data/res/font_style.dart'; import '../../../data/res/menu.dart'; import '../../../data/res/url.dart'; @@ -19,7 +20,6 @@ import '../../../generated/l10n.dart'; import '../../../locator.dart'; import '../../widget/dropdown_menu.dart'; import '../../widget/picker.dart'; -import '../../widget/primary_color.dart'; import '../../widget/round_rect_card.dart'; import '../../widget/url_text.dart'; import '../docker.dart'; @@ -162,7 +162,11 @@ class _ServerPageState extends State ? GestureDetector( onTap: () => showRoundDialog( context, _s.error, Text(ss.failedInfo ?? ''), []), - child: Text(_s.clickSee, style: style, textScaleFactor: 1.0,)) + child: Text( + _s.clickSee, + style: style, + textScaleFactor: 1.0, + )) : Text(topRightStr, style: style, textScaleFactor: 1.0), const SizedBox(width: 9), _buildSSHBtn(spi), @@ -352,16 +356,12 @@ class _ServerPageState extends State child: Stack( children: [ Center( - child: PrimaryColor( - builder: (context, primaryColor) { - return CircleChart( - progressColor: primaryColor, - progressNumber: percent, - maxNumber: 100, - width: 53, - height: 53, - ); - }, + child: CircleChart( + progressColor: primaryColor, + progressNumber: percent, + maxNumber: 100, + width: 53, + height: 53, ), ), Positioned.fill( @@ -415,8 +415,7 @@ class _ServerPageState extends State TextButton( onPressed: () async { Navigator.of(context).pop(); - final result = - await locator().runSnippet(id, snippet); + final result = await _serverProvider.runSnippet(id, snippet); showRoundDialog( context, _s.result, diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index 75dd8ad3..557838dd 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -7,12 +7,12 @@ import '../../core/utils/ui.dart'; import '../../data/provider/app.dart'; import '../../data/provider/server.dart'; import '../../data/res/build_data.dart'; +import '../../data/res/color.dart'; import '../../data/res/font_style.dart'; import '../../data/res/tab.dart'; import '../../data/store/setting.dart'; import '../../generated/l10n.dart'; import '../../locator.dart'; -import '../widget/primary_color.dart'; import '../widget/round_rect_card.dart'; class SettingPage extends StatefulWidget { @@ -56,19 +56,15 @@ class _SettingPageState extends State { appBar: AppBar( title: Text(_s.setting), ), - body: PrimaryColor( - builder: (context, primaryColor) { - return ListView( - padding: const EdgeInsets.all(17), - children: [ - _buildAppColorPreview(primaryColor), - _buildUpdateInterval(primaryColor), - _buildCheckUpdate(), - _buildLaunchPage(primaryColor), - _buildDistLogoSwitch(), - ].map((e) => RoundRectCard(e)).toList(), - ); - }, + body: ListView( + padding: const EdgeInsets.all(17), + children: [ + _buildAppColorPreview(), + _buildUpdateInterval(), + _buildCheckUpdate(), + _buildLaunchPage(), + _buildDistLogoSwitch(), + ].map((e) => RoundRectCard(e)).toList(), ), ); } @@ -113,9 +109,9 @@ class _SettingPageState extends State { ); } - Widget _buildUpdateInterval(Color priColor) { + Widget _buildUpdateInterval() { return ExpansionTile( - textColor: priColor, + textColor: primaryColor, title: Text( _s.updateServerStatusInterval, style: textSize13, @@ -128,8 +124,8 @@ class _SettingPageState extends State { trailing: Text('${_updateInterval.toInt()} ${_s.second}'), children: [ Slider( - thumbColor: priColor, - activeColor: priColor.withOpacity(0.7), + thumbColor: primaryColor, + activeColor: primaryColor.withOpacity(0.7), min: 0, max: 10, value: _updateInterval, @@ -162,12 +158,12 @@ class _SettingPageState extends State { ); } - Widget _buildAppColorPreview(Color priColor) { + Widget _buildAppColorPreview() { return ExpansionTile( - textColor: priColor, + textColor: primaryColor, trailing: ClipOval( child: Container( - color: priColor, + color: primaryColor, height: 27, width: 27, ), @@ -176,17 +172,18 @@ class _SettingPageState extends State { _s.appPrimaryColor, style: textSize13, ), - children: [_buildAppColorPicker(priColor), _buildColorPickerConfirmBtn()], + children: [_buildAppColorPicker(), _buildColorPickerConfirmBtn()], ); } - Widget _buildAppColorPicker(Color selected) { + Widget _buildAppColorPicker() { return MaterialColorPicker( - shrinkWrap: true, - onColorChange: (Color color) { - _selectedColorValue = color.value; - }, - selectedColor: selected); + shrinkWrap: true, + onColorChange: (Color color) { + _selectedColorValue = color.value; + }, + selectedColor: primaryColor, + ); } Widget _buildColorPickerConfirmBtn() { @@ -199,9 +196,10 @@ class _SettingPageState extends State { ); } - Widget _buildLaunchPage(Color priColor) { + Widget _buildLaunchPage() { return ExpansionTile( - textColor: priColor, + childrenPadding: const EdgeInsets.only(left: 17, right: 7), + textColor: primaryColor, title: Text( _s.launchPage, style: textSize13, @@ -222,7 +220,7 @@ class _SettingPageState extends State { tabTitleName(context, tabs.indexOf(e)), style: TextStyle( fontSize: 14, - color: _theme.textTheme.bodyMedium!.color!.withAlpha(177)), + color: _theme.textTheme.bodyMedium!.color!.withAlpha(177),), ), trailing: _buildRadio(tabs.indexOf(e)), ), diff --git a/lib/view/page/sftp/downloaded.dart b/lib/view/page/sftp/downloaded.dart index ad71ed0f..5d423032 100644 --- a/lib/view/page/sftp/downloaded.dart +++ b/lib/view/page/sftp/downloaded.dart @@ -151,8 +151,9 @@ class _SFTPDownloadedPageState extends State { const SizedBox(), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.cancel)), + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.cancel), + ), TextButton( onPressed: () { file.deleteSync(); @@ -176,8 +177,9 @@ class _SFTPDownloadedPageState extends State { ), [ TextButton( - onPressed: (() => Navigator.of(context).pop()), - child: Text(_s.close)) + onPressed: (() => Navigator.of(context).pop()), + child: Text(_s.close), + ) ], ); } diff --git a/lib/view/page/sftp/view.dart b/lib/view/page/sftp/view.dart index 44fdb1cd..2087f57c 100644 --- a/lib/view/page/sftp/view.dart +++ b/lib/view/page/sftp/view.dart @@ -113,8 +113,9 @@ class _SFTPPageState extends State { ), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.close)) + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.close), + ) ], )), icon: const Icon(Icons.add), @@ -140,8 +141,9 @@ class _SFTPPageState extends State { ), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.cancel)) + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.cancel), + ) ], ); @@ -277,8 +279,9 @@ class _SFTPPageState extends State { ), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.cancel)) + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.cancel), + ) ], ); } @@ -290,8 +293,9 @@ class _SFTPPageState extends State { Text('${_s.dl2Local(name.filename)}\n${_s.keepForeground}'), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.cancel)), + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.cancel), + ), TextButton( onPressed: () async { Navigator.of(context).pop(); @@ -328,8 +332,9 @@ class _SFTPPageState extends State { Text(_s.sureDelete(file.filename)), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('Cancel')), + onPressed: () => Navigator.of(context).pop(), + child: const Text('Cancel'), + ), TextButton( onPressed: () { _status.client!.remove(file.filename); @@ -371,8 +376,9 @@ class _SFTPPageState extends State { Text(_s.fieldMustNotEmpty), [ TextButton( - onPressed: () => Navigator.of(context).pop(), - child: Text(_s.ok)), + onPressed: () => Navigator.of(context).pop(), + child: Text(_s.ok), + ), ], ); return; diff --git a/lib/view/page/ssh.dart b/lib/view/page/ssh.dart index ec10c9a3..b14a2318 100644 --- a/lib/view/page/ssh.dart +++ b/lib/view/page/ssh.dart @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; +import 'package:toolbox/data/res/color.dart'; import 'package:xterm/xterm.dart'; import '../../core/utils/ui.dart'; @@ -15,7 +16,6 @@ import '../../data/provider/virtual_keyboard.dart'; import '../../data/res/terminal_theme.dart'; import '../../data/res/virtual_key.dart'; import '../../locator.dart'; -import '../widget/primary_color.dart'; class SSHPage extends StatefulWidget { final ServerPrivateInfo spi; @@ -156,15 +156,13 @@ class _SSHPageState extends State { color: isDark ? Colors.white : Colors.black, size: 17, ) - : PrimaryColor(builder: (context, color) { - return Text( - item.text, - style: TextStyle( - color: selected ? color : Colors.black, - fontSize: 17, - ), - ); - }); + : Text( + item.text, + style: TextStyle( + color: selected ? primaryColor : null, + fontSize: 17, + ), + ); return InkWell( onTap: () { diff --git a/lib/view/widget/dropdown_menu.dart b/lib/view/widget/dropdown_menu.dart index 839f6131..036c5a3c 100644 --- a/lib/view/widget/dropdown_menu.dart +++ b/lib/view/widget/dropdown_menu.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; +import '../../data/res/color.dart'; import '../../data/res/menu.dart'; import '../../generated/l10n.dart'; -import 'primary_color.dart'; class DropdownBtnItem { final String text; @@ -15,12 +15,10 @@ class DropdownBtnItem { Widget build(S s) => Row( children: [ - PrimaryColor(builder: (context, primaryColor) { - return Icon( - icon, - color: primaryColor, - ); - }), + Icon( + icon, + color: primaryColor, + ), const SizedBox( width: 10, ), diff --git a/lib/view/widget/input_decoration.dart b/lib/view/widget/input_decoration.dart index b7954ae0..58f3cf9c 100644 --- a/lib/view/widget/input_decoration.dart +++ b/lib/view/widget/input_decoration.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'primary_color.dart'; +import '../../data/res/color.dart'; InputDecoration buildDecoration(String label, {TextStyle? textStyle, IconData? icon, String? hint}) { @@ -8,11 +8,9 @@ InputDecoration buildDecoration(String label, labelText: label, labelStyle: textStyle, hintText: hint, - icon: PrimaryColor(builder: (context, primaryColor) { - return Icon( - icon, - color: primaryColor, - ); - }), + icon: Icon( + icon, + color: primaryColor, + ), ); } diff --git a/lib/view/widget/primary_color.dart b/lib/view/widget/primary_color.dart deleted file mode 100644 index 45052e0c..00000000 --- a/lib/view/widget/primary_color.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../data/store/setting.dart'; -import '../../locator.dart'; - -final _primaryColor = locator().primaryColor.listenable(); - -class PrimaryColor extends StatelessWidget { - final Widget Function(BuildContext context, Color primaryColor) builder; - - const PrimaryColor({Key? key, required this.builder}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - builder: (context, c, child) => builder(context, Color(c)), - valueListenable: _primaryColor, - ); - } -} diff --git a/lib/view/widget/url_text.dart b/lib/view/widget/url_text.dart index fe584a02..1c6ec11c 100644 --- a/lib/view/widget/url_text.dart +++ b/lib/view/widget/url_text.dart @@ -1,10 +1,13 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:toolbox/data/res/color.dart'; import '../../core/utils/ui.dart'; -const regUrl = - r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]*"; +final _reg = RegExp( + r"(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]*"); + +const _textStyle = TextStyle(); class UrlText extends StatelessWidget { final String text; @@ -12,18 +15,17 @@ class UrlText extends StatelessWidget { final TextAlign? textAlign; final TextStyle style; - const UrlText( - {Key? key, - required this.text, - this.replace, - this.textAlign, - this.style = const TextStyle()}) - : super(key: key); + const UrlText({ + Key? key, + required this.text, + this.replace, + this.textAlign, + this.style = _textStyle, + }) : super(key: key); - List _getTextSpans(bool isDarkMode) { + List _getTextSpans(Color c) { List widgets = []; - final reg = RegExp(regUrl); - Iterable matches = reg.allMatches(text); + Iterable matches = _reg.allMatches(text); List<_ResultMatch> resultMatches = <_ResultMatch>[]; int start = 0; @@ -54,16 +56,22 @@ class UrlText extends StatelessWidget { for (var result in resultMatches) { if (result.isUrl) { - widgets.add(_LinkTextSpan( + widgets.add( + _LinkTextSpan( replace: replace ?? result.text, text: result.text, - style: style.copyWith(color: Colors.blue))); + style: style.copyWith(color: primaryColor), + ), + ); } else { - widgets.add(TextSpan( + widgets.add( + TextSpan( text: result.text, style: style.copyWith( - color: isDarkMode ? Colors.white : Colors.black, - ))); + color: c, + ), + ), + ); } } return widgets; @@ -73,7 +81,7 @@ class UrlText extends StatelessWidget { Widget build(BuildContext context) { return RichText( textAlign: textAlign ?? TextAlign.start, - text: TextSpan(children: _getTextSpans(isDarkMode(context))), + text: TextSpan(children: _getTextSpans(contentColor.resolve(context))), ); } } @@ -81,12 +89,13 @@ class UrlText extends StatelessWidget { class _LinkTextSpan extends TextSpan { _LinkTextSpan({TextStyle? style, required String text, String? replace}) : super( - style: style, - text: replace, - recognizer: TapGestureRecognizer() - ..onTap = () { - openUrl(text); - }); + style: style, + text: replace, + recognizer: TapGestureRecognizer() + ..onTap = () { + openUrl(text); + }, + ); } class _ResultMatch {