fix & opt

fix: cant ping when launch page is ping
fix: button text color not primaryColor
opt: getting primaryColor
This commit is contained in:
lollipopkit
2023-02-01 17:18:46 +08:00
parent 2faea10d61
commit 21ac323ed1
28 changed files with 445 additions and 423 deletions

View File

@@ -5,5 +5,8 @@
},
"search.exclude": {
"**/.fvm": true
}
},
"git.ignoredRepositories": [
".fvm"
],
}

View File

@@ -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";

View File

@@ -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<int>(
valueListenable: locator<SettingStore>().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<SettingStore>().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),
);
},
);
}
}

View File

@@ -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),
});
}

View File

@@ -56,10 +56,17 @@ Future<void> 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<void> doUpdate(BuildContext context, {bool force = false}) async {
Future<void> _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),
)
]);
}
}

View File

@@ -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;
}

View File

@@ -275,4 +275,4 @@ class _TryLimiter {
void resetTryTimes(String id) {
_triedTimes[id] = 0;
}
}
}

View File

@@ -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;
}

View File

@@ -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<SettingStore>().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);

View File

@@ -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;

View File

@@ -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)),
],
),
);
}),
),
),
);
}

View File

@@ -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<ConvertPage>
'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() {

View File

@@ -190,7 +190,9 @@ class _DockerManagePageState extends State<DockerManagePage> {
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;
}

View File

@@ -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<MyHomePage>
);
}
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<MyHomePage>
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<MyHomePage>
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<MyHomePage>
),
child: Text(
'${BuildData.name}\n$_versionStr',
style: TextStyle(color: widget.primaryColor),
textAlign: TextAlign.center,
),
),
@@ -225,11 +227,6 @@ class _MyHomePageState extends State<MyHomePage>
_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),

View File

@@ -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<PingPage>
with AutomaticKeepAliveClientMixin {
with AutomaticKeepAliveClientMixin, AfterLayoutMixin {
late TextEditingController _textEditingController;
late MediaQueryData _media;
final List<PingResult> _results = [];
@@ -54,20 +57,24 @@ class _PingPageState extends State<PingPage>
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<PingPage>
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<PingPage>
@override
bool get wantKeepAlive => true;
@override
Future<FutureOr<void>> afterFirstLayout(BuildContext context) async {
await _serverProvider.loadLocalData();
await _serverProvider.refreshData();
}
}

View File

@@ -78,7 +78,9 @@ class _PkgManagePageState extends State<PkgManagePage>
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<PkgManagePage>
},
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<PkgManagePage>
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()
]
: [

View File

@@ -47,9 +47,9 @@ class _PrivateKeyListState extends State<PrivateKeysListPage> {
),
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),
),
),

View File

@@ -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<ServerDetailPage>
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) {

View File

@@ -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<ServerEditPage> 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<ServerEditPage> 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,
);

View File

@@ -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<ServerPage>
? 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<ServerPage>
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<ServerPage>
TextButton(
onPressed: () async {
Navigator.of(context).pop();
final result =
await locator<ServerProvider>().runSnippet(id, snippet);
final result = await _serverProvider.runSnippet(id, snippet);
showRoundDialog(
context,
_s.result,

View File

@@ -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<SettingPage> {
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<SettingPage> {
);
}
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<SettingPage> {
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<SettingPage> {
);
}
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<SettingPage> {
_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<SettingPage> {
);
}
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<SettingPage> {
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)),
),

View File

@@ -151,8 +151,9 @@ class _SFTPDownloadedPageState extends State<SFTPDownloadedPage> {
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<SFTPDownloadedPage> {
),
[
TextButton(
onPressed: (() => Navigator.of(context).pop()),
child: Text(_s.close))
onPressed: (() => Navigator.of(context).pop()),
child: Text(_s.close),
)
],
);
}

View File

@@ -113,8 +113,9 @@ class _SFTPPageState extends State<SFTPPage> {
),
[
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<SFTPPage> {
),
[
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<SFTPPage> {
),
[
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<SFTPPage> {
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<SFTPPage> {
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<SFTPPage> {
Text(_s.fieldMustNotEmpty),
[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(_s.ok)),
onPressed: () => Navigator.of(context).pop(),
child: Text(_s.ok),
),
],
);
return;

View File

@@ -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<SSHPage> {
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: () {

View File

@@ -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,
),

View File

@@ -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,
),
);
}

View File

@@ -1,20 +0,0 @@
import 'package:flutter/material.dart';
import '../../data/store/setting.dart';
import '../../locator.dart';
final _primaryColor = locator<SettingStore>().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<int>(
builder: (context, c, child) => builder(context, Color(c)),
valueListenable: _primaryColor,
);
}
}

View File

@@ -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<InlineSpan> _getTextSpans(bool isDarkMode) {
List<InlineSpan> _getTextSpans(Color c) {
List<InlineSpan> widgets = <InlineSpan>[];
final reg = RegExp(regUrl);
Iterable<Match> matches = reg.allMatches(text);
Iterable<Match> 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 {