opt. & new: icons

This commit is contained in:
lollipopkit
2024-04-26 00:39:03 +08:00
parent 3ccb61fba2
commit 3237d9eb21
20 changed files with 254 additions and 171 deletions

View File

@@ -672,7 +672,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -682,7 +682,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -808,7 +808,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -818,7 +818,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -836,7 +836,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -846,7 +846,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -867,7 +867,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -880,7 +880,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -906,7 +906,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -919,7 +919,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -942,7 +942,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -955,7 +955,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -978,7 +978,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -990,7 +990,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -1019,7 +1019,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1031,7 +1031,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;
@@ -1057,7 +1057,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1069,7 +1069,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;

View File

@@ -7,6 +7,7 @@ import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/choice_chip.dart';
import 'package:toolbox/view/widget/tag.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../data/res/ui.dart';
import '../../../view/widget/input_field.dart';
@@ -180,9 +181,9 @@ extension DialogX on BuildContext {
),
const Divider(),
SingleChildScrollView(
child: ValueListenableBuilder(
valueListenable: tag,
builder: (_, val, __) {
child: ValBuilder(
listenable: tag,
builder: (val) {
final items = itemsBuilder(val);
return Choice<T>(
onChanged: (value) => vals = value,

View File

@@ -2,9 +2,9 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 872;
static const int build = 873;
static const String engine = "3.19.5";
static const String buildAt = "2024-04-23 15:08:31";
static const int modifications = 4;
static const String buildAt = "2024-04-23 17:37:20";
static const int modifications = 2;
static const int script = 45;
}

View File

@@ -12,9 +12,9 @@ final class _AppBar extends CustomAppBar {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: selectIndex,
builder: (_, idx, __) {
return ValBuilder(
listenable: selectIndex,
builder: (idx) {
if (idx == AppTab.ssh.index) {
return SizedBox(
height: CustomAppBar.barHeight ??

View File

@@ -31,6 +31,7 @@ import 'package:toolbox/data/res/url.dart';
import 'package:toolbox/view/widget/appbar.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/markdown.dart';
import 'package:toolbox/view/widget/val_builder.dart';
part 'appbar.dart';

View File

@@ -12,6 +12,7 @@ import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/view/widget/input_field.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../core/utils/server.dart';
import '../../../data/model/server/private_key_info.dart';
@@ -215,9 +216,9 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
icon: Icons.password,
),
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
ValueListenableBuilder(
valueListenable: _loading,
builder: (_, val, __) => val ?? UIs.placeholder,
ValBuilder(
listenable: _loading,
builder: (val) => val ?? UIs.placeholder,
),
],
);

View File

@@ -19,6 +19,7 @@ import 'package:toolbox/view/widget/kv_row.dart';
import 'package:toolbox/view/widget/percent_circle.dart';
import 'package:toolbox/view/widget/row.dart';
import 'package:toolbox/view/widget/two_line_text.dart';
import 'package:toolbox/view/widget/val_builder.dart';
final class PvePage extends StatefulWidget {
final ServerPrivateInfo spi;
@@ -64,9 +65,9 @@ final class _PvePageState extends State<PvePage> {
appBar: CustomAppBar(
title: TwoLineText(up: 'PVE', down: widget.spi.name),
actions: [
ValueListenableBuilder(
valueListenable: _pve.err,
builder: (_, val, __) => val == null
ValBuilder(
listenable: _pve.err,
builder: (val) => val == null
? UIs.placeholder
: IconBtn(
icon: Icons.refresh,
@@ -79,9 +80,9 @@ final class _PvePageState extends State<PvePage> {
),
],
),
body: ValueListenableBuilder(
valueListenable: _pve.err,
builder: (_, val, __) {
body: ValBuilder(
listenable: _pve.err,
builder: (val) {
if (val != null) {
_timer?.cancel();
return Padding(
@@ -91,9 +92,9 @@ final class _PvePageState extends State<PvePage> {
),
);
}
return ValueListenableBuilder(
valueListenable: _pve.data,
builder: (_, val, __) {
return ValBuilder(
listenable: _pve.data,
builder: (val) {
return _buildBody(val);
},
);

View File

@@ -20,6 +20,7 @@ import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/expand_tile.dart';
import 'package:toolbox/view/widget/kv_row.dart';
import 'package:toolbox/view/widget/server_func_btns.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../../core/extension/numx.dart';
import '../../../../core/route.dart';
@@ -573,9 +574,9 @@ class _ServerDetailPageState extends State<ServerDetailPage>
children: [
Text(l10n.net),
UIs.width13,
ValueListenableBuilder(
valueListenable: _netSortType,
builder: (_, val, __) => InkWell(
ValBuilder(
listenable: _netSortType,
builder: (val) => InkWell(
onTap: () => _netSortType.value = val.next,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 377),

View File

@@ -466,7 +466,10 @@ class _ServerEditPageState extends State<ServerEditPage> {
));
return CardX(
child: ExpandTile(
leading: const Icon(Icons.map),
leading: const Padding(
padding: EdgeInsets.only(left: 10),
child: Icon(Icons.map),
),
initiallyExpanded: _jumpServer.value != null,
title: Text(l10n.jumpServer),
children: children,

View File

@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_highlight/theme_map.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:provider/provider.dart';
import 'package:toolbox/core/build_mode.dart';
import 'package:toolbox/core/extension/colorx.dart';
@@ -19,6 +20,7 @@ import 'package:toolbox/data/res/rebuild.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/expand_tile.dart';
import 'package:toolbox/view/widget/markdown.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../core/persistant_store.dart';
import '../../../core/route.dart';
@@ -36,6 +38,8 @@ import '../../widget/input_field.dart';
import '../../widget/cardx.dart';
import '../../widget/store_switch.dart';
const _kIconSize = 23.0;
class SettingPage extends StatefulWidget {
const SettingPage({super.key});
@@ -195,27 +199,28 @@ class _SettingPageState extends State<SettingPage> {
}
Widget _buildCheckUpdate() {
return Consumer<AppProvider>(
builder: (ctx, app, __) {
String display;
if (app.newestBuild != null) {
if (app.newestBuild! > BuildData.build) {
display = l10n.versionHaveUpdate(app.newestBuild!);
return ListTile(
leading: const Icon(Icons.update),
title: Text(l10n.autoCheckUpdate),
subtitle: Consumer<AppProvider>(
builder: (ctx, app, __) {
String display;
if (app.newestBuild != null) {
if (app.newestBuild! > BuildData.build) {
display = l10n.versionHaveUpdate(app.newestBuild!);
} else {
display = l10n.versionUpdated(BuildData.build);
}
} else {
display = l10n.versionUpdated(BuildData.build);
display = l10n.versionUnknownUpdate(BuildData.build);
}
} else {
display = l10n.versionUnknownUpdate(BuildData.build);
}
return ListTile(
title: Text(l10n.autoCheckUpdate),
subtitle: Text(display, style: UIs.textGrey),
onTap: () => Funcs.throttle(
() => doUpdate(ctx, force: BuildMode.isDebug),
),
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
);
},
return Text(display, style: UIs.textGrey);
},
),
onTap: () => Funcs.throttle(
() => doUpdate(context, force: BuildMode.isDebug),
),
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
);
}
@@ -238,9 +243,9 @@ class _SettingPageState extends State<SettingPage> {
_setting.serverStatusUpdateInterval.put(val);
}
},
trailing: ValueListenableBuilder(
valueListenable: _setting.serverStatusUpdateInterval.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.serverStatusUpdateInterval.listenable(),
builder: (val) => Text(
'$val ${l10n.second}',
style: UIs.text15,
),
@@ -250,14 +255,11 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildAppColor() {
return ListTile(
trailing: ClipOval(
child: Container(
color: primaryColor,
height: 27,
width: 27,
),
),
leading: const Icon(Icons.colorize),
title: Text(l10n.primaryColorSeed),
trailing: ClipOval(
child: Container(color: primaryColor, height: 27, width: 27),
),
onTap: () async {
final ctrl = TextEditingController(text: primaryColor.toHex);
await context.showRoundDialog(
@@ -360,9 +362,9 @@ class _SettingPageState extends State<SettingPage> {
// }
Widget _buildMaxRetry() {
return ValueListenableBuilder(
valueListenable: _setting.maxRetryCount.listenable(),
builder: (_, val, __) => ListTile(
return ValBuilder(
listenable: _setting.maxRetryCount.listenable(),
builder: (val) => ListTile(
title: Text(
l10n.maxRetryCount,
textAlign: TextAlign.start,
@@ -392,9 +394,8 @@ class _SettingPageState extends State<SettingPage> {
// Issue #57
final len = ThemeMode.values.length;
return ListTile(
title: Text(
l10n.themeMode,
),
leading: const Icon(MingCute.moon_stars_fill),
title: Text(l10n.themeMode),
onTap: () async {
final selected = await context.showPickSingleDialog(
items: List.generate(len + 2, (index) => index),
@@ -406,9 +407,9 @@ class _SettingPageState extends State<SettingPage> {
RebuildNodes.app.rebuild();
}
},
trailing: ValueListenableBuilder(
valueListenable: _setting.themeMode.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.themeMode.listenable(),
builder: (val) => Text(
_buildThemeModeStr(val),
style: UIs.text15,
),
@@ -434,6 +435,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildFont() {
final fontName = getFileName(_setting.fontPath.fetch());
return ListTile(
leading: const Icon(MingCute.font_fill),
title: Text(l10n.font),
trailing: Text(
fontName ?? l10n.notSelected,
@@ -483,11 +485,12 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildTermFontSize() {
return ListTile(
leading: const Icon(MingCute.font_size_line),
title: Text(l10n.fontSize),
subtitle: Text(l10n.termFontSizeTip, style: UIs.textGrey),
trailing: ValueListenableBuilder(
valueListenable: _setting.termFontSize.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.termFontSize.listenable(),
builder: (val) => Text(
val.toString(),
style: UIs.text15,
),
@@ -535,6 +538,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildLocale() {
return ListTile(
leading: const Icon(IonIcons.language),
title: Text(l10n.language),
onTap: () async {
final selected = await context.showPickSingleDialog(
@@ -548,9 +552,9 @@ class _SettingPageState extends State<SettingPage> {
RebuildNodes.app.rebuild();
}
},
trailing: ValueListenableBuilder(
valueListenable: _setting.locale.listenable(),
builder: (_, ___, __) => Text(
trailing: ListenBuilder(
listenable: _setting.locale.listenable(),
builder: () => Text(
l10n.languageName,
style: UIs.text15,
),
@@ -560,6 +564,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSSHVirtualKeyAutoOff() {
return ListTile(
leading: const Icon(MingCute.hotkey_fill),
title: Text(l10n.sshVirtualKeyAutoOff),
subtitle: const Text('Ctrl & Alt', style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.sshVirtualKeyAutoOff),
@@ -568,10 +573,11 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildEditorTheme() {
return ListTile(
leading: const Icon(MingCute.sun_fill),
title: Text('${l10n.light} ${l10n.theme.toLowerCase()}'),
trailing: ValueListenableBuilder(
valueListenable: _setting.editorTheme.listenable(),
builder: (_, val, __) => Text(val, style: UIs.text15),
trailing: ValBuilder(
listenable: _setting.editorTheme.listenable(),
builder: (val) => Text(val, style: UIs.text15),
),
onTap: () async {
final selected = await context.showPickSingleDialog(
@@ -588,10 +594,11 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildEditorDarkTheme() {
return ListTile(
leading: const Icon(MingCute.moon_stars_fill),
title: Text('${l10n.dark} ${l10n.theme.toLowerCase()}'),
trailing: ValueListenableBuilder(
valueListenable: _setting.editorDarkTheme.listenable(),
builder: (_, val, __) => Text(val, style: UIs.text15),
trailing: ValBuilder(
listenable: _setting.editorDarkTheme.listenable(),
builder: (val) => Text(val, style: UIs.text15),
),
onTap: () async {
final selected = await context.showPickSingleDialog(
@@ -608,6 +615,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildFullScreenSwitch() {
return ListTile(
leading: const Icon(Bootstrap.phone_landscape_fill),
title: Text(l10n.fullScreen),
subtitle: Text(l10n.fullScreenTip, style: UIs.textGrey),
trailing: StoreSwitch(
@@ -619,6 +627,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildFullScreenJitter() {
return ListTile(
leading: const Icon(AntDesign.shake_outline),
title: Text(l10n.fullScreenJitter),
subtitle: Text(l10n.fullScreenJitterHelp, style: UIs.textGrey),
trailing: StoreSwitch(
@@ -673,6 +682,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSSHVirtKeys() {
return ListTile(
leading: const Icon(BoxIcons.bxs_keyboard),
title: Text(l10n.editVirtKeys),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () => AppRoute.sshVirtKeySetting().go(context),
@@ -691,6 +701,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSftpOpenLastPath() {
return ListTile(
leading: const Icon(MingCute.history_line),
title: Text(l10n.openLastPath),
subtitle: Text(l10n.openLastPathTip, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.sftpOpenLastPath),
@@ -699,6 +710,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSftpShowFoldersFirst() {
return ListTile(
leading: const Icon(MingCute.folder_fill),
title: Text(l10n.sftpShowFoldersFirst),
trailing: StoreSwitch(prop: _setting.sftpShowFoldersFirst),
);
@@ -706,10 +718,11 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildNetViewType() {
return ListTile(
leading: const Icon(ZondIcons.network, size: _kIconSize),
title: Text(l10n.netViewType),
trailing: ValueListenableBuilder(
valueListenable: _setting.netViewType.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.netViewType.listenable(),
builder: (val) => Text(
val.toStr,
style: UIs.text15,
),
@@ -730,7 +743,8 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildDeleteServers() {
return ListTile(
title: Text(l10n.deleteServers),
trailing: const Icon(Icons.delete_forever),
leading: const Icon(Icons.delete_forever),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () async {
context.showRoundDialog<List<String>>(
title: Text(l10n.choose),
@@ -775,9 +789,9 @@ class _SettingPageState extends State<SettingPage> {
return ListTile(
title: Text(l10n.textScaler),
subtitle: Text(l10n.textScalerTip, style: UIs.textGrey),
trailing: ValueListenableBuilder(
valueListenable: _setting.textFactor.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.textFactor.listenable(),
builder: (val) => Text(
val.toString(),
style: UIs.text15,
),
@@ -815,6 +829,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildServerFuncBtns() {
return ExpandTile(
leading: const Icon(TeenyIcons.button, size: _kIconSize),
title: Text(l10n.serverFuncBtns),
children: [
_buildServerFuncBtnsSwitch(),
@@ -841,6 +856,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildServerSeq() {
return ListTile(
leading: const Icon(OctIcons.sort_desc, size: _kIconSize),
title: Text(l10n.serverOrder),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () => AppRoute.serverOrder().go(context),
@@ -849,6 +865,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildServerDetailCardSeq() {
return ListTile(
leading: const Icon(OctIcons.sort_desc, size: _kIconSize),
title: Text(l10n.serverDetailOrder),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () => AppRoute.serverDetailOrder().go(context),
@@ -857,10 +874,11 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildEditorFontSize() {
return ListTile(
leading: const Icon(MingCute.font_size_line),
title: Text(l10n.fontSize),
trailing: ValueListenableBuilder(
valueListenable: _setting.editorFontSize.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.editorFontSize.listenable(),
builder: (val) => Text(
val.toString(),
style: UIs.text15,
),
@@ -904,6 +922,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildSftpRmrDir() {
return ListTile(
leading: const Icon(MingCute.delete_2_fill),
title: const Text('rm -r'),
subtitle: Text(l10n.sftpRmrDirSummary, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.sftpRmrDir),
@@ -926,6 +945,7 @@ class _SettingPageState extends State<SettingPage> {
};
if (func == null) return null;
return ListTile(
leading: const Icon(Icons.phone_android),
title: Text('${OS.type} ${l10n.setting}'),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () => func(context),
@@ -934,6 +954,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildEditorHighlight() {
return ListTile(
leading: const Icon(MingCute.code_line, size: _kIconSize),
title: Text(l10n.highlight),
subtitle: Text(l10n.editorHighlightTip, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.editorHighlight),
@@ -950,6 +971,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildUsePodman() {
return ListTile(
leading: const Icon(IonIcons.logo_docker),
title: Text(l10n.usePodmanByDefault),
trailing: StoreSwitch(prop: _setting.usePodman),
);
@@ -957,6 +979,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildContainerTrySudo() {
return ListTile(
leading: const Icon(Clarity.administrator_solid),
title: Text(l10n.trySudo),
subtitle: Text(l10n.containerTrySudoTip, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.containerTrySudo),
@@ -973,6 +996,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildContainerParseStat() {
return ListTile(
leading: const Icon(IonIcons.stats_chart, size: _kIconSize),
title: Text(l10n.parseContainerStats),
subtitle: Text(l10n.parseContainerStatsTip, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.containerParseStat),
@@ -981,6 +1005,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildServerMore() {
return ExpandTile(
leading: const Icon(MingCute.more_3_fill),
title: Text(l10n.more),
children: [
_buildRememberPwdInMem(),
@@ -1016,10 +1041,11 @@ class _SettingPageState extends State<SettingPage> {
}
return ListTile(
leading: const Icon(MingCute.moon_stars_fill, size: _kIconSize),
title: Text(l10n.theme),
trailing: ValueListenableBuilder(
valueListenable: _setting.termTheme.listenable(),
builder: (_, val, __) => Text(
trailing: ValBuilder(
listenable: _setting.termTheme.listenable(),
builder: (val) => Text(
index2Str(val),
style: UIs.text15,
),
@@ -1039,6 +1065,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildAppMore() {
return ExpandTile(
leading: const Icon(MingCute.more_3_fill),
title: Text(l10n.more),
children: [
if (isAndroid || isIOS) _buildCollectUsage(),
@@ -1065,6 +1092,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildCpuView() {
return ExpandTile(
leading: const Icon(OctIcons.cpu, size: _kIconSize),
title: Text('CPU ${l10n.view}'),
children: [
ListTile(
@@ -1082,6 +1110,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildEditorWrap() {
return ListTile(
leading: const Icon(MingCute.align_center_line),
title: Text(l10n.softWrap),
trailing: StoreSwitch(prop: _setting.editorSoftWrap),
);

View File

@@ -3,6 +3,7 @@ import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/data/model/app/server_detail_card.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../../core/extension/order.dart';
import '../../../widget/appbar.dart';
@@ -29,9 +30,9 @@ class _ServerDetailOrderPageState extends State<ServerDetailOrderPage> {
}
Widget _buildBody() {
return ValueListenableBuilder(
valueListenable: prop.listenable(),
builder: (_, keys, __) {
return ValBuilder(
listenable: prop.listenable(),
builder: (keys) {
final disabled =
ServerDetailCards.names.where((e) => !keys.contains(e)).toList();
final allKeys = [...keys, ...disabled];

View File

@@ -4,6 +4,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
import 'package:toolbox/data/model/app/menu/server_func.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../../core/extension/order.dart';
import '../../../widget/appbar.dart';
@@ -30,9 +31,9 @@ class _ServerDetailOrderPageState extends State<ServerFuncBtnsOrderPage> {
}
Widget _buildBody() {
return ValueListenableBuilder(
valueListenable: prop.listenable(),
builder: (_, keys, __) {
return ValBuilder(
listenable: prop.listenable(),
builder: (keys) {
final disabled = ServerFuncBtn.values
.map((e) => e.index)
.where((e) => !keys.contains(e))

View File

@@ -9,6 +9,7 @@ import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/store_switch.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../widget/appbar.dart';
@@ -48,9 +49,9 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
}
Widget _buildBody() {
return ValueListenableBuilder(
valueListenable: prop.listenable(),
builder: (_, keys, __) {
return ValBuilder(
listenable: prop.listenable(),
builder: (keys) {
final disabled = VirtKey.values
.map((e) => e.index)
.where((e) => !keys.contains(e))

View File

@@ -9,6 +9,7 @@ import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/input_field.dart';
import 'package:toolbox/view/widget/markdown.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../data/model/server/snippet.dart';
import '../../../data/res/ui.dart';
@@ -132,9 +133,9 @@ class _SnippetEditPageState extends State<SnippetEditPage>
label: l10n.note,
icon: Icons.note,
),
ValueListenableBuilder(
valueListenable: _tags,
builder: (_, vals, __) {
ValBuilder(
listenable: _tags,
builder: (vals) {
return TagEditor(
tags: _tags.value,
onChanged: (p0) => setState(() {
@@ -164,33 +165,34 @@ class _SnippetEditPageState extends State<SnippetEditPage>
Widget _buildAutoRunOn() {
return CardX(
child: ValueListenableBuilder(
valueListenable: _autoRunOn,
builder: (_, vals, __) {
return ListTile(
leading: const Icon(Icons.settings_remote, size: 19),
title: Text(l10n.autoRun),
trailing: const Icon(Icons.keyboard_arrow_right),
subtitle: vals.isEmpty
? null
: Text(
vals.join(', '),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
onTap: () async {
vals.removeWhere((e) => !Pros.server.serverOrder.contains(e));
final serverIds = await context.showPickDialog(
items: Pros.server.serverOrder,
initial: vals,
);
if (serverIds != null) {
_autoRunOn.value = serverIds;
}
},
);
},
));
child: ValBuilder(
listenable: _autoRunOn,
builder: (vals) {
return ListTile(
leading: const Icon(Icons.settings_remote, size: 19),
title: Text(l10n.autoRun),
trailing: const Icon(Icons.keyboard_arrow_right),
subtitle: vals.isEmpty
? null
: Text(
vals.join(', '),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
onTap: () async {
vals.removeWhere((e) => !Pros.server.serverOrder.contains(e));
final serverIds = await context.showPickDialog(
items: Pros.server.serverOrder,
initial: vals,
);
if (serverIds != null) {
_autoRunOn.value = serverIds;
}
},
);
},
),
);
}
Widget _buildTip() {

View File

@@ -13,6 +13,7 @@ import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/view/widget/input_field.dart';
import 'package:toolbox/view/widget/omit_start_text.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../core/extension/numx.dart';
import '../../../core/route.dart';
@@ -76,9 +77,9 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
icon: const Icon(Icons.downloading),
onPressed: () => AppRoute.sftpMission().go(context),
),
ValueListenableBuilder<_SortType>(
valueListenable: _sortType,
builder: (context, value, child) {
ValBuilder<_SortType>(
listenable: _sortType,
builder: (value) {
return PopupMenuButton<_SortType>(
icon: const Icon(Icons.sort),
itemBuilder: (context) {
@@ -107,9 +108,9 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
),
body: FadeIn(
key: UniqueKey(),
child: ValueListenableBuilder(
valueListenable: _sortType,
builder: (_, val, __) {
child: ValBuilder(
listenable: _sortType,
builder: (val) {
return _buildBody();
},
),

View File

@@ -17,6 +17,7 @@ import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/widget/omit_start_text.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../../core/extension/numx.dart';
import '../../../core/route.dart';
@@ -72,9 +73,9 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
icon: const Icon(Icons.downloading),
onPressed: () => AppRoute.sftpMission().go(context),
),
ValueListenableBuilder(
valueListenable: _sortOption,
builder: (context, value, child) {
ValBuilder(
listenable: _sortOption,
builder: (value) {
return PopupMenuButton<_SortType>(
icon: const Icon(Icons.sort),
itemBuilder: (context) {
@@ -294,11 +295,13 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
return RefreshIndicator(
child: FadeIn(
key: Key(widget.spi.name + _status.path!.path),
child: ValueListenableBuilder(
valueListenable: _sortOption,
builder: (_, sortOption, __) {
final files = sortOption.sortBy
.sort(_status.files!, reversed: sortOption.reversed);
child: ValBuilder(
listenable: _sortOption,
builder: (sortOption) {
final files = sortOption.sortBy.sort(
_status.files!,
reversed: sortOption.reversed,
);
return ListView.builder(
itemCount: files.length,
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3),

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../core/persistant_store.dart';
@@ -22,9 +23,9 @@ class StoreSwitch extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: prop.listenable(),
builder: (context, bool value, widget) {
return ValBuilder(
listenable: prop.listenable(),
builder: (value) {
return Switch(
value: value,
onChanged: (value) async {

View File

@@ -5,6 +5,7 @@ import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/res/ui.dart';
import 'package:toolbox/view/widget/input_field.dart';
import 'package:toolbox/view/widget/cardx.dart';
import 'package:toolbox/view/widget/val_builder.dart';
import '../../data/res/color.dart';
@@ -196,9 +197,9 @@ class TagSwitcher extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: tags,
builder: (_, vals, __) {
return ValBuilder(
listenable: tags,
builder: (vals) {
if (vals.isEmpty) return UIs.placeholder;
final items = <String?>[null, ...vals];
return Container(

View File

@@ -0,0 +1,35 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
final class ValBuilder<T> extends ValueListenableBuilder<T> {
ValBuilder({
super.key,
required ValueListenable<T> listenable,
required Widget Function(T) builder,
}) : super(
valueListenable: listenable,
builder: (_, val, __) => builder(val),
);
}
final class ValChildBuilder<T> extends ValueListenableBuilder<T> {
ValChildBuilder({
super.key,
required ValueListenable<T> listenable,
required Widget Function(T, Widget?) builder,
super.child,
}) : super(
valueListenable: listenable,
builder: (_, val, child) => builder(val, child),
);
}
final class ListenBuilder extends ListenableBuilder {
ListenBuilder({
super.key,
required super.listenable,
required Widget Function() builder,
}) : super(
builder: (_, __) => builder(),
);
}

View File

@@ -471,7 +471,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -481,7 +481,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -608,7 +608,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Server Box";
@@ -618,7 +618,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -638,7 +638,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 872;
CURRENT_PROJECT_VERSION = 873;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6;
INFOPLIST_FILE = Runner/Info.plist;
@@ -649,7 +649,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.872;
MARKETING_VERSION = 1.0.873;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "Server Box";
PROVISIONING_PROFILE_SPECIFIER = "";