From 48271d9559f22e39df61ed92944567156a40fc9a Mon Sep 17 00:00:00 2001 From: GT610 Date: Tue, 2 Jun 2026 11:34:34 +0800 Subject: [PATCH 1/4] Extract fl_lib to avoid unused --- lib/app.dart | 8 +- lib/kit/core/build.dart | 22 + lib/kit/core/ext/datetime.dart | 7 + lib/kit/core/ext/obj.dart | 13 + lib/kit/core/ext/string.dart | 7 + lib/kit/core/ext/widget.dart | 22 + lib/kit/core/func.dart | 23 + lib/kit/core/logger.dart | 65 ++ lib/kit/core/platform.dart | 49 + lib/kit/core/rnode.dart | 112 ++ lib/kit/kit.dart | 22 + lib/kit/pages/debug_page.dart | 77 ++ lib/kit/provider/debug.dart | 65 ++ lib/kit/res/font.dart | 37 + lib/kit/res/ui.dart | 55 + lib/kit/widgets/appbar.dart | 57 + lib/kit/widgets/btn.dart | 277 +++++ lib/kit/widgets/card.dart | 32 + lib/kit/widgets/input.dart | 139 +++ lib/kit/widgets/loading.dart | 42 + lib/kit/widgets/text.dart | 19 + lib/kit/widgets/virtual_window_frame.dart | 81 ++ lib/main.dart | 5 +- lib/pages/builtin_instance_settings_page.dart | 6 +- lib/pages/components/settings_helpers.dart | 6 +- .../components/add_task_dialog.dart | 2 +- .../components/instance_dialog.dart | 14 +- lib/pages/remote_instance_settings_page.dart | 6 +- lib/pages/remote_instance_status_page.dart | 10 +- lib/pages/settings_page/settings_page.dart | 95 +- lib/utils/logging.dart | 3 +- linux/flutter/generated_plugin_registrant.cc | 4 - linux/flutter/generated_plugins.cmake | 1 - macos/Flutter/GeneratedPluginRegistrant.swift | 8 - packages/fl_lib | 1 - pubspec.lock | 976 +++--------------- pubspec.yaml | 4 +- .../flutter/generated_plugin_registrant.cc | 9 - windows/flutter/generated_plugins.cmake | 3 - 39 files changed, 1437 insertions(+), 947 deletions(-) create mode 100644 lib/kit/core/build.dart create mode 100644 lib/kit/core/ext/datetime.dart create mode 100644 lib/kit/core/ext/obj.dart create mode 100644 lib/kit/core/ext/string.dart create mode 100644 lib/kit/core/ext/widget.dart create mode 100644 lib/kit/core/func.dart create mode 100644 lib/kit/core/logger.dart create mode 100644 lib/kit/core/platform.dart create mode 100644 lib/kit/core/rnode.dart create mode 100644 lib/kit/kit.dart create mode 100644 lib/kit/pages/debug_page.dart create mode 100644 lib/kit/provider/debug.dart create mode 100644 lib/kit/res/font.dart create mode 100644 lib/kit/res/ui.dart create mode 100644 lib/kit/widgets/appbar.dart create mode 100644 lib/kit/widgets/btn.dart create mode 100644 lib/kit/widgets/card.dart create mode 100644 lib/kit/widgets/input.dart create mode 100644 lib/kit/widgets/loading.dart create mode 100644 lib/kit/widgets/text.dart create mode 100644 lib/kit/widgets/virtual_window_frame.dart delete mode 160000 packages/fl_lib diff --git a/lib/app.dart b/lib/app.dart index 2f48877..b09072d 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:fl_lib/fl_lib.dart' as fl; -import 'package:fl_lib/fl_lib.dart' show ChineseThemeData; +import 'kit/kit.dart' as kit; +import 'kit/kit.dart' show ChineseThemeData; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:window_manager/window_manager.dart'; @@ -60,7 +60,7 @@ class _ThemeProviderState extends State<_ThemeProvider> { locale: display.locale, localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, - builder: (context, child) => fl.VirtualWindowFrame( + builder: (context, child) => kit.VirtualWindowFrame( title: kAppName, showCaption: display.hideTitleBar, child: ClipRect(child: child ?? const SizedBox.shrink()), @@ -203,7 +203,7 @@ class _HomeWrapperState extends State<_HomeWrapper> with Loggable { @override Widget build(BuildContext context) { if (!_isInitialized) { - return Scaffold(body: Center(child: fl.SizedLoading.medium)); + return Scaffold(body: Center(child: kit.SizedLoading.medium)); } return const MainWindow(); } diff --git a/lib/kit/core/build.dart b/lib/kit/core/build.dart new file mode 100644 index 0000000..ac9f426 --- /dev/null +++ b/lib/kit/core/build.dart @@ -0,0 +1,22 @@ +enum BuildMode { + release, + debug, + profile, + ; + + static final isDebug = _buildMode == BuildMode.debug; + static final isProfile = _buildMode == BuildMode.profile; + static final isRelease = _buildMode == BuildMode.release; +} + +final _buildMode = () { + if (const bool.fromEnvironment('dart.vm.product')) { + return BuildMode.release; + } + var result = BuildMode.profile; + assert(() { + result = BuildMode.debug; + return true; + }()); + return result; +}(); diff --git a/lib/kit/core/ext/datetime.dart b/lib/kit/core/ext/datetime.dart new file mode 100644 index 0000000..35ac772 --- /dev/null +++ b/lib/kit/core/ext/datetime.dart @@ -0,0 +1,7 @@ +extension DateTimeX on DateTime { + String get hourMinute { + return '${hour.toString().padLeft(2, '0')}:${minute.toString().padLeft(2, '0')}'; + } + + static int get timestamp => DateTime.now().millisecondsSinceEpoch; +} diff --git a/lib/kit/core/ext/obj.dart b/lib/kit/core/ext/obj.dart new file mode 100644 index 0000000..09c25a3 --- /dev/null +++ b/lib/kit/core/ext/obj.dart @@ -0,0 +1,13 @@ +import '../rnode.dart'; + +extension ObjectX on T { + VNode get vn => VNode(this); +} + +extension ObjectXNullable on T? { + A? nullOr(A Function(T) f) => this != null ? f(this!) : null; + + VNode get vn => VNode(this); +} + +VNode nvn() => VNode(null); diff --git a/lib/kit/core/ext/string.dart b/lib/kit/core/ext/string.dart new file mode 100644 index 0000000..13be728 --- /dev/null +++ b/lib/kit/core/ext/string.dart @@ -0,0 +1,7 @@ +import 'package:url_launcher/url_launcher_string.dart'; + +extension StringX on String { + Future launchUrl() async { + return await launchUrlString(this); + } +} diff --git a/lib/kit/core/ext/widget.dart b/lib/kit/core/ext/widget.dart new file mode 100644 index 0000000..e8dd139 --- /dev/null +++ b/lib/kit/core/ext/widget.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +extension WidgetX on Widget { + Widget paddingAll(double value) => + Padding(padding: EdgeInsets.all(value), child: this); + + Widget paddingOnly({ + double left = 0, + double top = 0, + double right = 0, + double bottom = 0, + }) => + Padding( + padding: EdgeInsets.only( + left: left, + top: top, + right: right, + bottom: bottom, + ), + child: this, + ); +} diff --git a/lib/kit/core/func.dart b/lib/kit/core/func.dart new file mode 100644 index 0000000..0fdd7cc --- /dev/null +++ b/lib/kit/core/func.dart @@ -0,0 +1,23 @@ +import 'dart:async'; + +abstract final class Fns { + static const _defaultDurationTime = 377; + static const _defaultThrottleId = 'default'; + static final startTimeMap = {_defaultThrottleId: 0}; + + static FutureOr throttle( + FutureOr Function() func, { + String id = _defaultThrottleId, + int duration = _defaultDurationTime, + Function? continueClick, + }) async { + final currentTime = DateTime.now().millisecondsSinceEpoch; + if (currentTime - (startTimeMap[id] ?? 0) > duration) { + startTimeMap[id] = DateTime.now().millisecondsSinceEpoch; + return await func(); + } else { + continueClick?.call(); + return null; + } + } +} diff --git a/lib/kit/core/logger.dart b/lib/kit/core/logger.dart new file mode 100644 index 0000000..43d5dde --- /dev/null +++ b/lib/kit/core/logger.dart @@ -0,0 +1,65 @@ +import 'dart:io'; + +import 'package:logging/logging.dart'; + +import 'build.dart'; + +abstract final class Loggers { + static final root = Logger('Root'); + static final store = Logger('Store'); + static final route = Logger('Route'); + static final app = Logger('App'); + + static final sourceReg = RegExp(r'\((.+):(\d+):(\d+)\)'); + + static void log(Object message, {int skipFrames = 1}) { + final traceLines = StackTrace.current.toString().split('\n'); + + if (traceLines.length > skipFrames) { + final caller = traceLines[skipFrames]; + final match = sourceReg.firstMatch(caller); + if (match != null) { + String? file = match.group(1)?.replaceFirst('file://', ''); + final line = match.group(2); + if (file != null) { + final pwd = Directory.current.path; + if (file.startsWith(pwd)) { + file = file.substring(pwd.length + 1); + file = './$file'; + } + } + print('[$file:$line] $message'); + return; + } + } + print(message); + } +} + +void dprint(Object? msg, [Object? msg2, Object? msg3, Object? msg4]) { + if (!BuildMode.isDebug) return; + lprint(msg, msg2, msg3, msg4, 3); +} + +void lprint( + Object? msg, [ + Object? msg2, + Object? msg3, + Object? msg4, + int skipFrames = 2, +]) { + final sb = StringBuffer(); + sb.write(msg.toString()); + + if (msg2 != null) { + sb.write('\n$msg2'); + if (msg3 != null) { + sb.write('\n$msg3'); + if (msg4 != null) { + sb.write('\n$msg4'); + } + } + } + final str = sb.toString(); + Loggers.log(str, skipFrames: skipFrames); +} diff --git a/lib/kit/core/platform.dart b/lib/kit/core/platform.dart new file mode 100644 index 0000000..8b564fe --- /dev/null +++ b/lib/kit/core/platform.dart @@ -0,0 +1,49 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; + +enum Pfs { + android, + ios, + linux, + macos, + windows, + web, + fuchsia, + unknown; + + static final type = () { + if (kIsWeb) return web; + return switch (Platform.operatingSystem) { + 'android' => android, + 'ios' => ios, + 'linux' => linux, + 'macos' => macos, + 'windows' => windows, + 'fuchsia' => fuchsia, + _ => unknown, + }; + }(); + + static final String seperator = isWindows ? '\\' : '/'; + + static final String? homeDir = () { + final envVars = Platform.environment; + if (isMacOS || isLinux) { + return envVars['HOME']; + } else if (isWindows) { + return envVars['UserProfile']; + } + return null; + }(); +} + +final isAndroid = Pfs.type == Pfs.android; +final isIOS = Pfs.type == Pfs.ios; +final isLinux = Pfs.type == Pfs.linux; +final isMacOS = Pfs.type == Pfs.macos; +final isWindows = Pfs.type == Pfs.windows; +final isWeb = Pfs.type == Pfs.web; +final isMobile = Pfs.type == Pfs.ios || Pfs.type == Pfs.android; +final isDesktop = + Pfs.type == Pfs.linux || Pfs.type == Pfs.macos || Pfs.type == Pfs.windows; diff --git a/lib/kit/core/rnode.dart b/lib/kit/core/rnode.dart new file mode 100644 index 0000000..c1d7dbc --- /dev/null +++ b/lib/kit/core/rnode.dart @@ -0,0 +1,112 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class RNode implements ChangeNotifier { + final List _listeners = []; + + RNode(); + + @override + String toString() => 'RNode($hashCode)'; + + @override + void addListener(VoidCallback listener) { + _listeners.add(listener); + } + + @override + void removeListener(VoidCallback listener) { + _listeners.remove(listener); + } + + Future notify({bool delay = false}) async { + if (delay) await Future.delayed(const Duration(milliseconds: 277)); + for (final listener in _listeners) { + try { + listener(); + } catch (_) {} + } + } + + @override + void dispose() { + _listeners.clear(); + } + + @override + bool get hasListeners => _listeners.isNotEmpty; + + @override + void notifyListeners() { + notify(); + } +} + +extension RNodeX on RNode { + ListenBuilder listen(Widget Function() builder) { + return ListenBuilder(listenable: this, builder: builder); + } +} + +class VNode extends RNode implements ValueNotifier { + T _value; + + VNode(T value) : _value = value; + + @override + T get value => _value; + + @override + set value(T newVal) { + _value = newVal; + notify(); + } + + @override + String toString() => 'VNode($value)'; +} + +extension ValueListenableX on ValueListenable { + ValBuilder listenVal(Widget Function(T) builder) { + return ValBuilder(listenable: this, builder: builder); + } +} + +final class ValBuilder extends ValueListenableBuilder { + final ValueListenable listenable; + + ValBuilder({ + super.key, + required this.listenable, + required Widget Function(T) builder, + }) : super( + valueListenable: listenable, + builder: (_, val, _) => builder(val), + ); +} + +final class ListenBuilder extends ListenableBuilder { + ListenBuilder({ + super.key, + required super.listenable, + required Widget Function() builder, + }) : super(builder: (_, _) => builder()); +} + +final class EmptyListenable implements ValueListenable { + @override + void addListener(VoidCallback listener) {} + + @override + void removeListener(VoidCallback listener) {} + + @override + T? get value => null; + + const EmptyListenable(); +} + +abstract final class RNodes { + static final app = RNode(); + static final dark = VNode(false); +} diff --git a/lib/kit/kit.dart b/lib/kit/kit.dart new file mode 100644 index 0000000..fd07b76 --- /dev/null +++ b/lib/kit/kit.dart @@ -0,0 +1,22 @@ +library; + +export 'core/build.dart'; +export 'core/ext/datetime.dart'; +export 'core/ext/obj.dart'; +export 'core/ext/string.dart'; +export 'core/ext/widget.dart'; +export 'core/func.dart'; +export 'core/logger.dart'; +export 'core/platform.dart'; +export 'core/rnode.dart'; +export 'pages/debug_page.dart'; +export 'provider/debug.dart'; +export 'res/font.dart'; +export 'res/ui.dart'; +export 'widgets/appbar.dart'; +export 'widgets/btn.dart'; +export 'widgets/card.dart'; +export 'widgets/input.dart'; +export 'widgets/loading.dart'; +export 'widgets/text.dart'; +export 'widgets/virtual_window_frame.dart'; diff --git a/lib/kit/pages/debug_page.dart b/lib/kit/pages/debug_page.dart new file mode 100644 index 0000000..1f70f43 --- /dev/null +++ b/lib/kit/pages/debug_page.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; + +import '../provider/debug.dart'; +import '../res/ui.dart'; +import '../widgets/appbar.dart'; +import '../widgets/btn.dart'; + +class DebugPageArgs { + final String? title; + + const DebugPageArgs({this.title}); +} + +class DebugPage extends StatelessWidget { + final DebugPageArgs? args; + + const DebugPage({super.key, this.args}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + leading: IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon(Icons.arrow_back), + ), + title: Text( + args?.title ?? 'Log', + style: const TextStyle(fontSize: 17), + ), + actions: [ + const Btn.icon( + icon: Icon(Icons.copy, size: 23), + onTap: DebugProvider.copy, + ), + Btn.icon( + onTap: () { + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Clear logs?'), + actions: [ + Btn.ok( + onTap: () { + DebugProvider.clear(); + Navigator.of(ctx).pop(); + }, + ), + ], + ), + ); + }, + icon: const Icon(Icons.delete, size: 26), + ), + ], + ), + body: _buildTerminal(context), + ); + } + + Widget _buildTerminal(BuildContext context) { + return Container( + color: Colors.black, + child: ValueListenableBuilder>( + valueListenable: DebugProvider.widgets, + builder: (_, widgets, _) { + if (widgets.isEmpty) return UIs.placeholder; + return ListView.builder( + padding: const EdgeInsets.all(10), + itemCount: widgets.length, + itemBuilder: (_, index) => widgets[index], + ); + }, + ), + ); + } +} diff --git a/lib/kit/provider/debug.dart b/lib/kit/provider/debug.dart new file mode 100644 index 0000000..985359f --- /dev/null +++ b/lib/kit/provider/debug.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:logging/logging.dart'; + +import '../core/ext/datetime.dart'; +import '../core/ext/obj.dart'; +import '../res/ui.dart'; + +const _level2Color = { + 'INFO': Colors.cyan, + 'WARNING': Colors.yellow, + 'ERROR': Color(0xffbb2d6f), +}; + +final class DebugProvider { + static const int maxLines = 100; + static final widgets = [].vn; + static final lines = []; + + static void addLog(LogRecord record) { + final color = _level2Color[record.level.name] ?? Colors.blue; + final title = '[${DateTime.now().hourMinute}][${record.loggerName}]'; + final level = '[${record.level}]'; + final message = record.error == null + ? '\n${record.message}' + : '\n${record.message}: ${record.error}'; + lines.add('$title$level$message'); + widgets.value.add(Text.rich(TextSpan( + children: [ + TextSpan(text: title, style: TextStyle(color: color)), + TextSpan(text: level, style: TextStyle(color: color)), + TextSpan( + text: message, + style: const TextStyle(color: Colors.white), + ), + ], + ))); + if (record.stackTrace != null) { + widgets.value.add(SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Text( + '${record.stackTrace}', + style: const TextStyle(color: Colors.white), + ), + )); + } + widgets.value.add(UIs.height13); + if (widgets.value.length > maxLines) { + widgets.value.removeRange(0, widgets.value.length - maxLines); + } + widgets.notify(); + + if (lines.length > maxLines) { + lines.removeRange(0, lines.length - maxLines); + } + } + + static void clear() { + widgets.value.clear(); + lines.clear(); + widgets.notify(); + } + + static void copy() => Clipboard.setData(ClipboardData(text: lines.join('\n'))); +} diff --git a/lib/kit/res/font.dart b/lib/kit/res/font.dart new file mode 100644 index 0000000..ad81acc --- /dev/null +++ b/lib/kit/res/font.dart @@ -0,0 +1,37 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; + +import '../core/platform.dart'; + +const _fontFamilyFallback = [ + 'system-font', + 'sans-serif', + 'Microsoft YaHei', +]; + +extension ChineseTextTheme on TextTheme { + static final Typography _typography = Typography.material2021(); + + TextTheme _fixChinese(Brightness brightness) { + final newTextTheme = switch (brightness) { + Brightness.dark => + _typography.white.apply(fontFamilyFallback: _fontFamilyFallback), + Brightness.light => + _typography.black.apply(fontFamilyFallback: _fontFamilyFallback), + }; + return newTextTheme.merge(this); + } +} + +extension ChineseThemeData on ThemeData { + ThemeData get fixWindowsFont { + if (!isWindows) return this; + + return switch (Platform.localeName) { + final locale when locale.startsWith('zh') => + copyWith(textTheme: textTheme._fixChinese(brightness)), + _ => this, + }; + } +} diff --git a/lib/kit/res/ui.dart b/lib/kit/res/ui.dart new file mode 100644 index 0000000..fe449e0 --- /dev/null +++ b/lib/kit/res/ui.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +abstract final class UIs { + static const text11 = TextStyle(fontSize: 11); + static const text11Bold = TextStyle( + fontSize: 11, + fontWeight: FontWeight.w500, + ); + static const text11Grey = TextStyle(color: Colors.grey, fontSize: 11); + static const text12 = TextStyle(fontSize: 12); + static const text12Bold = TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + ); + static const text12Grey = TextStyle(color: Colors.grey, fontSize: 12); + static const text13 = TextStyle(fontSize: 13); + static const text13Bold = TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + ); + static const text13Grey = TextStyle(color: Colors.grey, fontSize: 13); + static const text15 = TextStyle(fontSize: 15); + static const text15Bold = TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + ); + static const text18 = TextStyle(fontSize: 18); + static const text27 = TextStyle(fontSize: 27); + static const textGrey = TextStyle(color: Colors.grey); + static const textRed = TextStyle(color: Colors.red); + + static const placeholder = SizedBox(); + static const height7 = SizedBox(height: 7); + static const height13 = SizedBox(height: 13); + static const height77 = SizedBox(height: 77); + static const width7 = SizedBox(width: 7); + static const width13 = SizedBox(width: 13); + + static Widget dot({Color? color, double? size}) => Container( + width: size ?? 7, + height: size ?? 7, + decoration: BoxDecoration( + color: color ?? primaryColor, + shape: BoxShape.circle, + ), + ); + + static const centerLoading = Padding( + padding: EdgeInsets.symmetric(vertical: 7), + child: Center(child: CircularProgressIndicator()), + ); + + static var colorSeed = const Color.fromARGB(255, 72, 15, 15); + static var primaryColor = colorSeed; +} diff --git a/lib/kit/widgets/appbar.dart b/lib/kit/widgets/appbar.dart new file mode 100644 index 0000000..41b16ea --- /dev/null +++ b/lib/kit/widgets/appbar.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:window_manager/window_manager.dart'; + +import '../core/platform.dart'; + +class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { + static final sysStatusBarHeight = isDesktop ? kWindowCaptionHeight : 0.0; + + const CustomAppBar({ + super.key, + this.title, + this.actions, + this.centerTitle = true, + this.leading, + this.backgroundColor, + this.bottom, + this.scrolledUnderElevation = 0, + this.surfaceTintColor = Colors.transparent, + }); + + final Widget? title; + final List? actions; + final bool? centerTitle; + final Widget? leading; + final Color? backgroundColor; + final PreferredSizeWidget? bottom; + final double scrolledUnderElevation; + final Color surfaceTintColor; + + @override + Widget build(BuildContext context) { + return AppBar( + key: key, + title: title, + actions: actions, + centerTitle: centerTitle, + leading: leading, + backgroundColor: backgroundColor, + toolbarHeight: appBarHeight, + bottom: bottom, + scrolledUnderElevation: scrolledUnderElevation, + surfaceTintColor: surfaceTintColor, + ); + } + + @override + Size get preferredSize { + return calcPreferredSize(bottomWidgetH: bottom?.preferredSize.height); + } + + static const double appBarHeight = kToolbarHeight - 10; + + static Size calcPreferredSize({double? bottomWidgetH}) { + bottomWidgetH ??= 0; + return Size.fromHeight(appBarHeight + bottomWidgetH); + } +} diff --git a/lib/kit/widgets/btn.dart b/lib/kit/widgets/btn.dart new file mode 100644 index 0000000..2ee0c07 --- /dev/null +++ b/lib/kit/widgets/btn.dart @@ -0,0 +1,277 @@ +import 'package:flutter/material.dart'; + +import '../res/ui.dart'; + +enum BtnType { + row, + text, + icon, + column, + elevated, +} + +Null _defaultOnTap() => null; + +const _kGap = 7.0; +const _kPadding = EdgeInsets.all(7); +const _kPlaceholderIcon = Icon(Icons.help_outline); +const _kBorderRadius = BorderRadius.all(Radius.circular(30)); + +final class Btn extends StatelessWidget { + final void Function()? onTap; + final void Function()? onLongTap; + final String text; + final Icon? icon; + final double? gap; + final TextStyle? textStyle; + final BtnType type; + final EdgeInsetsGeometry? padding; + final MainAxisAlignment? mainAxisAlignment; + final MainAxisSize? mainAxisSize; + final BorderRadius? borderRadius; + final Object? popVal; + + const Btn.text({ + super.key, + required this.text, + this.onTap = _defaultOnTap, + this.textStyle, + this.padding, + this.onLongTap, + }) : type = BtnType.text, + gap = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = null, + icon = null; + + const Btn.icon({ + super.key, + required this.icon, + this.text = '', + this.onTap = _defaultOnTap, + this.padding = _kPadding, + this.onLongTap, + }) : type = BtnType.icon, + gap = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = null, + textStyle = null; + + const Btn.column({ + super.key, + required this.text, + required this.icon, + this.onTap = _defaultOnTap, + this.gap, + this.textStyle, + this.padding = _kPadding, + this.mainAxisAlignment, + this.mainAxisSize, + this.borderRadius = _kBorderRadius, + this.onLongTap, + }) : type = BtnType.column, + popVal = null; + + const Btn.row({ + super.key, + required this.text, + required this.icon, + this.onTap = _defaultOnTap, + this.gap, + this.textStyle, + this.padding = _kPadding, + this.mainAxisAlignment, + this.mainAxisSize, + this.borderRadius = _kBorderRadius, + this.onLongTap, + }) : type = BtnType.row, + popVal = null; + + const Btn.tile({ + super.key, + required this.text, + required this.icon, + this.onTap = _defaultOnTap, + this.gap = 20, + this.textStyle = const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + ), + this.padding = const EdgeInsets.symmetric(vertical: 13, horizontal: 20), + this.mainAxisAlignment, + this.mainAxisSize, + this.borderRadius = const BorderRadius.all(Radius.circular(13)), + this.onLongTap, + }) : type = BtnType.row, + popVal = null; + + const Btn.elevated({ + super.key, + required this.text, + this.icon, + this.onTap = _defaultOnTap, + this.gap = 20, + this.textStyle, + this.padding = const EdgeInsets.symmetric(vertical: 13, horizontal: 20), + this.mainAxisAlignment, + this.mainAxisSize, + this.borderRadius = const BorderRadius.all(Radius.circular(13)), + this.onLongTap, + }) : type = BtnType.elevated, + popVal = null; + + const Btn.ok({ + super.key, + this.onTap = _defaultOnTap, + bool red = false, + this.onLongTap, + String? text, + }) : this.text = text ?? 'OK', + icon = null, + type = BtnType.text, + gap = null, + padding = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = true, + textStyle = red ? UIs.textRed : null; + + const Btn.cancel({ + super.key, + this.onTap = _defaultOnTap, + this.onLongTap, + String? text, + }) : this.text = text ?? 'Cancel', + icon = null, + type = BtnType.text, + gap = null, + padding = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = false, + textStyle = null; + + @override + Widget build(BuildContext context) => switch (type) { + BtnType.text => _text(context), + BtnType.icon => _icon(context), + BtnType.column => _column(context), + BtnType.row => _row(context), + BtnType.elevated => _elevated(context), + }; + + VoidCallback? _resolveOnTap(BuildContext c) { + if (onTap == _defaultOnTap) { + if (popVal != null) return () => Navigator.of(c).pop(popVal); + return () => Navigator.of(c).pop(); + } + return onTap; + } + + Widget _text(BuildContext context) { + return TextButton( + onPressed: _resolveOnTap(context), + onLongPress: onLongTap, + style: padding != null + ? ButtonStyle(padding: WidgetStateProperty.all(padding)) + : null, + child: Text(text, style: textStyle), + ); + } + + Widget _icon(BuildContext context) { + Widget child = Tooltip( + message: text, + child: icon ?? _kPlaceholderIcon, + ); + if (padding != null) child = Padding(padding: padding!, child: child); + return InkWell( + borderRadius: borderRadius ?? _kBorderRadius, + onTap: _resolveOnTap(context), + onLongPress: onLongTap, + child: child, + ); + } + + Widget _column(BuildContext context) { + Widget child = Column( + children: [ + icon ?? _kPlaceholderIcon, + SizedBox(height: gap ?? _kGap), + Text(text, style: textStyle), + ], + ); + if (padding != null) { + child = Padding(padding: padding!, child: child); + } + return InkWell( + borderRadius: borderRadius ?? _kBorderRadius, + onTap: _resolveOnTap(context), + onLongPress: onLongTap, + child: child, + ); + } + + Widget _row(BuildContext context) { + final isRTL = Directionality.of(context) == TextDirection.rtl; + final icon_ = icon ?? _kPlaceholderIcon; + final gap_ = SizedBox(width: gap ?? _kGap); + final text_ = Text(text, style: textStyle); + final children = isRTL ? [text_, gap_, icon_] : [icon_, gap_, text_]; + + Widget child = Row( + mainAxisAlignment: mainAxisAlignment ?? MainAxisAlignment.start, + mainAxisSize: mainAxisSize ?? MainAxisSize.max, + children: children, + ); + if (padding != null) { + child = Padding(padding: padding!, child: child); + } + return InkWell( + borderRadius: borderRadius ?? _kBorderRadius, + onTap: _resolveOnTap(context), + onLongPress: onLongTap, + child: child, + ); + } + + Widget _elevated(BuildContext context) { + final isRTL = Directionality.of(context) == TextDirection.rtl; + final btnStyle = ButtonStyle( + padding: WidgetStateProperty.all(padding), + shape: WidgetStateProperty.all( + RoundedRectangleBorder(borderRadius: borderRadius ?? _kBorderRadius), + ), + ); + final text_ = Text(text, style: textStyle); + + if (icon != null) { + final gap_ = SizedBox(width: gap ?? _kGap); + final children = isRTL ? [text_, gap_, icon!] : [icon!, gap_, text_]; + + return ElevatedButton( + onPressed: _resolveOnTap(context), + onLongPress: onLongTap, + style: btnStyle, + child: Row( + mainAxisAlignment: mainAxisAlignment ?? MainAxisAlignment.start, + mainAxisSize: mainAxisSize ?? MainAxisSize.max, + children: children, + ), + ); + } + + return ElevatedButton( + onPressed: _resolveOnTap(context), + onLongPress: onLongTap, + style: btnStyle, + child: text_, + ); + } +} diff --git a/lib/kit/widgets/card.dart b/lib/kit/widgets/card.dart new file mode 100644 index 0000000..57513c5 --- /dev/null +++ b/lib/kit/widgets/card.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +class CardX extends StatelessWidget { + final Widget child; + final Color? color; + final BorderRadius? radius; + final Clip clipBehavior; + + const CardX({ + super.key, + required this.child, + this.color, + this.radius, + this.clipBehavior = Clip.hardEdge, + }); + + static const borderRadius = BorderRadius.all(Radius.circular(13)); + + @override + Widget build(BuildContext context) { + return Card( + key: key, + clipBehavior: clipBehavior, + color: color, + shape: RoundedRectangleBorder( + borderRadius: radius ?? borderRadius, + ), + elevation: 0, + child: child, + ); + } +} diff --git a/lib/kit/widgets/input.dart b/lib/kit/widgets/input.dart new file mode 100644 index 0000000..5b63f56 --- /dev/null +++ b/lib/kit/widgets/input.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; + +import '../core/ext/widget.dart'; +import 'card.dart'; + +class Input extends StatefulWidget { + final TextEditingController? controller; + final int maxLines; + final int? minLines; + final String? hint; + final String? label; + final void Function(String)? onSubmitted; + final void Function(String)? onChanged; + final bool obscureText; + final Widget? suffix; + final IconData? icon; + final TextInputType? type; + final TextInputAction? action; + final FocusNode? node; + final bool autoCorrect; + final bool? suggestion; + final String? errorText; + final bool autoFocus; + final void Function(bool)? onViewPwdTap; + final bool noWrap; + final InputCounterWidgetBuilder? counterBuilder; + final void Function()? onTap; + final void Function(PointerDownEvent)? onTapOutside; + final EditableTextContextMenuBuilder? contextMenuBuilder; + final int? maxLength; + final bool? enabled; + + const Input({ + super.key, + this.controller, + this.maxLines = 1, + this.minLines, + this.hint, + this.label, + this.onSubmitted, + this.onChanged, + this.obscureText = false, + this.icon, + this.type, + this.action, + this.node, + this.autoCorrect = false, + this.suggestion, + this.errorText, + this.autoFocus = false, + this.onViewPwdTap, + this.noWrap = false, + this.suffix, + this.counterBuilder, + this.onTap, + this.onTapOutside, + this.contextMenuBuilder, + this.maxLength, + this.enabled, + }) : assert( + !(obscureText && suffix != null), + 'suffix != null && obscureText', + ); + + @override + State createState() => _InputState(); +} + +class _InputState extends State { + late bool _obscureText = widget.obscureText; + + @override + Widget build(BuildContext context) { + final icon = + widget.icon != null ? Icon(widget.icon!).paddingOnly(left: 5) : null; + final child = _buildField(icon); + + if (widget.noWrap) return child; + + return CardX( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 5), + child: child, + ), + ); + } + + Widget _buildField(Widget? icon) { + return TextField( + controller: widget.controller, + maxLines: widget.maxLines, + minLines: widget.minLines, + obscureText: _obscureText, + decoration: InputDecoration( + hintText: widget.hint, + labelText: widget.label, + errorText: widget.errorText, + border: InputBorder.none, + icon: icon, + suffixIcon: _buildSuffix(), + ), + keyboardType: widget.type, + textInputAction: widget.action, + focusNode: widget.node, + autocorrect: widget.autoCorrect, + enableSuggestions: widget.suggestion ?? true, + autofocus: widget.autoFocus, + onSubmitted: widget.onSubmitted, + onChanged: widget.onChanged, + buildCounter: widget.counterBuilder, + onTap: widget.onTap, + onTapOutside: widget.onTapOutside, + maxLength: widget.maxLength, + enabled: widget.enabled, + contextMenuBuilder: widget.contextMenuBuilder ?? + (context, state) => + AdaptiveTextSelectionToolbar.editableText( + editableTextState: state, + ), + ); + } + + Widget? _buildSuffix() { + if (widget.suffix != null) return widget.suffix!; + if (!widget.obscureText) return null; + + return IconButton( + icon: Icon( + _obscureText ? Icons.visibility : Icons.visibility_off, + ), + onPressed: () { + setState(() { + _obscureText = !_obscureText; + }); + widget.onViewPwdTap?.call(_obscureText); + }, + ); + } +} diff --git a/lib/kit/widgets/loading.dart b/lib/kit/widgets/loading.dart new file mode 100644 index 0000000..0f638d5 --- /dev/null +++ b/lib/kit/widgets/loading.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +import '../core/ext/widget.dart'; + +final class SizedLoading extends StatelessWidget { + final double size; + final double padding; + final Animation? valueColor; + final Widget Function(BuildContext context, Animation? valueColor) + builder; + + const SizedLoading( + this.size, { + this.padding = 7, + this.valueColor, + this.builder = linearBuilder, + super.key, + }); + + static Widget linearBuilder( + BuildContext context, + Animation? valueColor, + ) { + return LinearProgressIndicator( + valueColor: valueColor ?? + AlwaysStoppedAnimation(Theme.of(context).colorScheme.primary), + ); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: size - 2 * padding, + height: size - 2 * padding, + child: Center(child: builder(context, valueColor)).paddingAll(padding), + ).paddingAll(3); + } + + static const small = SizedLoading(25); + static const medium = SizedLoading(45); + static const large = SizedLoading(65); +} diff --git a/lib/kit/widgets/text.dart b/lib/kit/widgets/text.dart new file mode 100644 index 0000000..4e400f3 --- /dev/null +++ b/lib/kit/widgets/text.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +import '../res/ui.dart'; + +final class CenterGreyTitle extends StatelessWidget { + final String text; + + const CenterGreyTitle(this.text, {super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 23, bottom: 17), + child: Center( + child: Text(text, style: UIs.textGrey), + ), + ); + } +} diff --git a/lib/kit/widgets/virtual_window_frame.dart b/lib/kit/widgets/virtual_window_frame.dart new file mode 100644 index 0000000..384cce6 --- /dev/null +++ b/lib/kit/widgets/virtual_window_frame.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:window_manager/window_manager.dart' as wm; + +import '../core/platform.dart'; +import 'appbar.dart'; + +abstract final class WindowFrameConfig { + static bool _showCaption = true; + + static bool get showCaption => _showCaption && isDesktop; + + static void setShowCaption(bool value) { + _showCaption = value; + } +} + +class VirtualWindowFrame extends StatelessWidget { + final Widget child; + final String? title; + final bool showCaption; + + const VirtualWindowFrame({ + super.key, + required this.child, + this.title, + this.showCaption = true, + }); + + @override + Widget build(BuildContext context) { + final content = switch (CustomAppBar.sysStatusBarHeight) { + 0.0 => child, + _ when showCaption && WindowFrameConfig.showCaption => Column( + children: [ + _WindowCaption(title: title), + Expanded(child: child), + ], + ), + _ => child, + }; + return wm.VirtualWindowFrame(child: content); + } +} + +class _WindowCaption extends StatelessWidget { + final String? title; + + const _WindowCaption({this.title}); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Container( + color: theme.scaffoldBackgroundColor, + height: CustomAppBar.sysStatusBarHeight, + width: double.infinity, + child: Stack( + alignment: Alignment.center, + children: [ + if (title != null) + Material( + color: Colors.transparent, + child: Text( + title!, + style: TextStyle( + color: theme.colorScheme.onSurface, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ), + if (isLinux || isWindows) + wm.WindowCaption( + backgroundColor: Colors.transparent, + brightness: theme.brightness, + ) + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 1747bff..686a84f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:fl_lib/fl_lib.dart' as fl; +import 'package:shared_preferences/shared_preferences.dart'; import 'app.dart'; import 'models/settings.dart'; import 'services/protocol_integration_service.dart'; @@ -11,7 +11,8 @@ void main(List args) async { // Ensure all platform initializations are complete WidgetsFlutterBinding.ensureInitialized(); initializeAppLogging(); - await fl.PrefStore.shared.init(); + SharedPreferences.setPrefix(''); + await SharedPreferences.getInstance(); ProtocolIntegrationService().captureInitialArguments(args); diff --git a/lib/pages/builtin_instance_settings_page.dart b/lib/pages/builtin_instance_settings_page.dart index c590dff..a19ff50 100644 --- a/lib/pages/builtin_instance_settings_page.dart +++ b/lib/pages/builtin_instance_settings_page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:fl_lib/fl_lib.dart' as fl; +import '../kit/kit.dart' as kit; import 'package:provider/provider.dart'; import '../generated/l10n/l10n.dart'; @@ -252,7 +252,7 @@ class _BuiltinInstanceSettingsPageState ? const SizedBox( width: 16, height: 16, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : Text( l10n.saveAndApply, @@ -1365,7 +1365,7 @@ class _BuiltinInstanceSettingsPageState builder: (dialogContext) => AlertDialog( content: Row( children: [ - fl.SizedLoading.medium, + kit.SizedLoading.medium, const SizedBox(width: 16), Expanded(child: Text(message)), ], diff --git a/lib/pages/components/settings_helpers.dart b/lib/pages/components/settings_helpers.dart index 7d2238b..8a21258 100644 --- a/lib/pages/components/settings_helpers.dart +++ b/lib/pages/components/settings_helpers.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:fl_lib/fl_lib.dart' as fl; +import '../../kit/kit.dart' as kit; abstract class SettingsSection { String get title; @@ -33,7 +33,7 @@ mixin SettingsPageHelpers on State { .map( (child) => Padding( padding: const EdgeInsets.only(bottom: kSettingCardSpacing), - child: fl.CardX(child: child), + child: kit.CardX(child: child), ), ) .toList(growable: false), @@ -44,7 +44,7 @@ mixin SettingsPageHelpers on State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - fl.CenterGreyTitle(section.title), + kit.CenterGreyTitle(section.title), const SizedBox(height: 4), section.child, ], diff --git a/lib/pages/download_page/components/add_task_dialog.dart b/lib/pages/download_page/components/add_task_dialog.dart index eeadcbf..72029ea 100644 --- a/lib/pages/download_page/components/add_task_dialog.dart +++ b/lib/pages/download_page/components/add_task_dialog.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:file_picker/file_picker.dart'; -import 'package:fl_lib/fl_lib.dart'; +import '../../../kit/kit.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/lib/pages/instance_page/components/instance_dialog.dart b/lib/pages/instance_page/components/instance_dialog.dart index 835c4a0..c09ddb9 100644 --- a/lib/pages/instance_page/components/instance_dialog.dart +++ b/lib/pages/instance_page/components/instance_dialog.dart @@ -1,4 +1,4 @@ -import 'package:fl_lib/fl_lib.dart' as fl; +import '../../../kit/kit.dart' as kit; import 'package:flutter/material.dart'; import '../../../generated/l10n/l10n.dart'; @@ -317,7 +317,7 @@ class _InstanceDialogState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - fl.Input( + kit.Input( controller: _nameController, label: l10n.instanceName, hint: _nameHint(l10n), @@ -436,7 +436,7 @@ class _InstanceDialogState extends State { ], ), const SizedBox(height: _fieldSpacing), - fl.Input( + kit.Input( controller: _rpcPathController, label: l10n.rpcPath, hint: l10n.rpcPathTip, @@ -466,7 +466,7 @@ class _InstanceDialogState extends State { ), ], const SizedBox(height: _sectionSpacing), - fl.Input( + kit.Input( controller: _downloadDirController, label: l10n.defaultDownloadDir, hint: l10n.remoteDownloadDirHint, @@ -496,7 +496,7 @@ class _InstanceDialogState extends State { ? const SizedBox( width: 16, height: 16, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : const Icon(Icons.wifi_find_outlined), label: Text( @@ -511,9 +511,9 @@ class _InstanceDialogState extends State { Row( mainAxisSize: MainAxisSize.min, children: [ - fl.Btn.cancel(onTap: () => Navigator.of(context).pop()), + kit.Btn.cancel(onTap: () => Navigator.of(context).pop()), const SizedBox(width: 8), - fl.Btn.elevated( + kit.Btn.elevated( text: widget.instance == null ? l10n.add : l10n.save, onTap: _submit, ), diff --git a/lib/pages/remote_instance_settings_page.dart b/lib/pages/remote_instance_settings_page.dart index 001f91a..75b320a 100644 --- a/lib/pages/remote_instance_settings_page.dart +++ b/lib/pages/remote_instance_settings_page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:fl_lib/fl_lib.dart' as fl; +import '../kit/kit.dart' as kit; import '../generated/l10n/l10n.dart'; import '../models/aria2_instance.dart'; @@ -424,7 +424,7 @@ class _RemoteInstanceSettingsPageState extends State ? const SizedBox( width: 16, height: 16, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : Text(l10n.save), ), @@ -471,7 +471,7 @@ class _RemoteInstanceSettingsPageState extends State } if (_isLoading) { - return const Center(child: fl.SizedLoading.medium); + return const Center(child: kit.SizedLoading.medium); } if (_loadError != null) { diff --git a/lib/pages/remote_instance_status_page.dart b/lib/pages/remote_instance_status_page.dart index 7b4b412..43f2dbe 100644 --- a/lib/pages/remote_instance_status_page.dart +++ b/lib/pages/remote_instance_status_page.dart @@ -1,4 +1,4 @@ -import 'package:fl_lib/fl_lib.dart' as fl; +import '../kit/kit.dart' as kit; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -229,7 +229,7 @@ class _RemoteInstanceStatusPage extends State { ? const SizedBox( width: 18, height: 18, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : const Icon(Icons.refresh), tooltip: l10n.refresh, @@ -248,7 +248,7 @@ class _RemoteInstanceStatusPage extends State { Aria2Instance instance, ) { if (_isLoading && _snapshot == null) { - return const Center(child: fl.SizedLoading.large); + return const Center(child: kit.SizedLoading.large); } if (_loadError != null && _snapshot == null) { @@ -451,7 +451,7 @@ class _RemoteInstanceStatusPage extends State { ? const SizedBox( width: 16, height: 16, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : const Icon(Icons.save_outlined), label: Text(l10n.saveSession), @@ -470,7 +470,7 @@ class _RemoteInstanceStatusPage extends State { ? const SizedBox( width: 16, height: 16, - child: fl.SizedLoading.small, + child: kit.SizedLoading.small, ) : const Icon(Icons.delete_sweep_outlined), label: Text(l10n.purgeDownloadResults), diff --git a/lib/pages/settings_page/settings_page.dart b/lib/pages/settings_page/settings_page.dart index 22bbdbf..9464599 100644 --- a/lib/pages/settings_page/settings_page.dart +++ b/lib/pages/settings_page/settings_page.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:fl_lib/fl_lib.dart' as fl; +import '../../kit/kit.dart' as kit; import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; @@ -105,7 +105,7 @@ class _SettingsPageState extends State Widget build(BuildContext context) { super.build(context); if (_isLoading) { - return Scaffold(body: Center(child: fl.SizedLoading.medium)); + return Scaffold(body: Center(child: kit.SizedLoading.medium)); } final settings = Provider.of(context); @@ -185,7 +185,7 @@ class _SettingsPageState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - fl.CenterGreyTitle(section.title), + kit.CenterGreyTitle(section.title), section.child, ], ), @@ -325,7 +325,7 @@ class _SettingsPageState extends State value: settings.autoStart, onChanged: (value) => _setRunAtStartupPreference(value, settings), ), - fl.CardX( + kit.CardX( child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -335,7 +335,7 @@ class _SettingsPageState extends State title: Text(l10n.runMode, style: theme.textTheme.bodyLarge), subtitle: Text( _runModeDescription(settings.runMode, l10n), - style: fl.UIs.textGrey, + style: kit.UIs.textGrey, ), contentPadding: EdgeInsets.zero, ), @@ -404,7 +404,7 @@ class _SettingsPageState extends State children: [ Padding( padding: const EdgeInsets.fromLTRB(4, 0, 4, 10), - child: Text(l10n.setAsDefaultClientTip, style: fl.UIs.textGrey), + child: Text(l10n.setAsDefaultClientTip, style: kit.UIs.textGrey), ), _buildSettingsGroup([ _buildSwitchTile( @@ -487,7 +487,7 @@ class _SettingsPageState extends State '$kAppName\n' '${_versionLabel.isEmpty ? l10n.versionLoading : _versionLabel}', textAlign: TextAlign.center, - style: fl.UIs.text15, + style: kit.UIs.text15, ), const SizedBox(height: 13), SizedBox( @@ -521,10 +521,10 @@ class _SettingsPageState extends State ), ), const SizedBox(height: 13), - fl.CardX( + kit.CardX( child: Padding( padding: const EdgeInsets.all(13), - child: fl.SimpleMarkdown(data: _buildAboutMarkdown(l10n)), + child: _buildAboutRichText(context, l10n), ), ), ], @@ -532,22 +532,59 @@ class _SettingsPageState extends State ); } - String _buildAboutMarkdown(AppLocalizations l10n) { - final buffer = StringBuffer() - ..writeln(l10n.aboutProjectDescription) - ..writeln() - ..writeln('#### ${l10n.author}') - ..writeln(GithubIds.author.markdownLink) - ..writeln() - ..writeln() - ..writeln('#### ${l10n.contributors}') - ..writeln(GithubIds.contributors.map((id) => id.markdownLink).join(' ')) - ..writeln() - ..writeln() - ..writeln('#### ${l10n.participants}') - ..writeln(GithubIds.participants.map((id) => id.markdownLink).join(' ')); + Widget _buildAboutRichText(BuildContext context, AppLocalizations l10n) { + final linkColor = Theme.of(context).colorScheme.primary; - return buffer.toString().trim(); + Widget linkText(String text, String url) { + return GestureDetector( + onTap: () => launchUrl(Uri.parse(url)), + child: Text( + text, + style: TextStyle(color: linkColor, fontSize: 14), + ), + ); + } + + Widget section(String title, List children) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 6), + Wrap(spacing: 12, children: children), + const SizedBox(height: 16), + ], + ); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(l10n.aboutProjectDescription), + const SizedBox(height: 16), + if (GithubIds.author.isNotEmpty) + section(l10n.author, [ + linkText(GithubIds.author, GithubIds.author.url), + ]), + if (GithubIds.contributors.isNotEmpty) + section( + l10n.contributors, + GithubIds.contributors + .map((id) => linkText(id, id.url)) + .toList(), + ), + if (GithubIds.participants.isNotEmpty) + section( + l10n.participants, + GithubIds.participants + .map((id) => linkText(id, id.url)) + .toList(), + ), + ], + ); } Widget _buildAboutActionButton({ @@ -576,7 +613,7 @@ class _SettingsPageState extends State Widget? trailing, VoidCallback? onTap, }) { - return fl.CardX( + return kit.CardX( child: ListTile( title: DefaultTextStyle.merge( style: Theme.of(context).textTheme.bodyLarge, @@ -584,7 +621,7 @@ class _SettingsPageState extends State ), subtitle: subtitle == null ? null - : DefaultTextStyle.merge(style: fl.UIs.textGrey, child: subtitle), + : DefaultTextStyle.merge(style: kit.UIs.textGrey, child: subtitle), trailing: trailing, onTap: onTap, ), @@ -612,12 +649,12 @@ class _SettingsPageState extends State required Future Function(bool value) onChanged, bool enabled = true, }) { - return fl.CardX( + return kit.CardX( child: ListTile( title: Text(title), subtitle: subtitle == null ? null - : Text(subtitle, style: fl.UIs.textGrey), + : Text(subtitle, style: kit.UIs.textGrey), trailing: Switch.adaptive( value: value, onChanged: !enabled @@ -786,7 +823,7 @@ class _SettingsPageState extends State Navigator.of(context).push( MaterialPageRoute( builder: (_) => - fl.DebugPage(args: fl.DebugPageArgs(title: l10n.viewLogs)), + kit.DebugPage(args: kit.DebugPageArgs(title: l10n.viewLogs)), ), ); } diff --git a/lib/utils/logging.dart b/lib/utils/logging.dart index 7b5be90..78227ba 100644 --- a/lib/utils/logging.dart +++ b/lib/utils/logging.dart @@ -1,6 +1,7 @@ import 'dart:async'; -import 'package:fl_lib/fl_lib.dart'; +import '../kit/provider/debug.dart'; +import '../kit/core/logger.dart'; import 'package:logging/logging.dart'; Level get defaultLogLevel => Level.INFO; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 5d4c33c..391c94e 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,7 +7,6 @@ #include "generated_plugin_registrant.h" #include -#include #include #include #include @@ -18,9 +17,6 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) desktop_drop_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); - g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); - flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); g_autoptr(FlPluginRegistrar) local_notifier_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "LocalNotifierPlugin"); local_notifier_plugin_register_with_registrar(local_notifier_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 1ce4d07..aa6c779 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,7 +4,6 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_drop - flutter_secure_storage_linux local_notifier screen_retriever_linux tray_manager diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 91851ba..933bf20 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,13 +7,9 @@ import Foundation import desktop_drop import file_picker -import flutter_secure_storage_darwin -import icloud_storage -import local_auth_darwin import local_notifier import package_info_plus import screen_retriever_macos -import share_plus import shared_preferences_foundation import tray_manager import url_launcher_macos @@ -22,13 +18,9 @@ import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) - FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) - IcloudStoragePlugin.register(with: registry.registrar(forPlugin: "IcloudStoragePlugin")) - LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) - SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/packages/fl_lib b/packages/fl_lib deleted file mode 160000 index 654b1f1..0000000 --- a/packages/fl_lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 654b1f1eb5f06154c45905351dc092fb23f87082 diff --git a/pubspec.lock b/pubspec.lock index 030683e..8d60523 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,36 +1,12 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" - url: "https://pub.dev" - source: hosted - version: "93.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b - url: "https://pub.dev" - source: hosted - version: "10.0.1" - archive: - dependency: transitive - description: - name: archive - sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff - url: "https://pub.dev" - source: hosted - version: "4.0.9" args: dependency: transitive description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.7.0" async: @@ -38,7 +14,7 @@ packages: description: name: async sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.13.1" boolean_selector: @@ -46,136 +22,47 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" - camera: - dependency: transitive - description: - name: camera - sha256: "4142a19a38e388d3bab444227636610ba88982e36dff4552d5191a86f65dc437" - url: "https://pub.dev" - source: hosted - version: "0.11.4" - camera_android_camerax: - dependency: transitive - description: - name: camera_android_camerax - sha256: "8516fe308bc341a5067fb1a48edff0ddfa57c0d3cdcc9dbe7ceca3ba119e2577" - url: "https://pub.dev" - source: hosted - version: "0.6.30" - camera_avfoundation: - dependency: transitive - description: - name: camera_avfoundation - sha256: "11b4aee2f5e5e038982e152b4a342c749b414aa27857899d20f4323e94cb5f0b" - url: "https://pub.dev" - source: hosted - version: "0.9.23+2" - camera_platform_interface: - dependency: transitive - description: - name: camera_platform_interface - sha256: "7ac852d77699acee79f0d438b793feee26721841e50973576419ff5c6d95e9b7" - url: "https://pub.dev" - source: hosted - version: "2.13.0" - camera_web: - dependency: transitive - description: - name: camera_web - sha256: "57f49a635c8bf249d07fb95eb693d7e4dda6796dedb3777f9127fb54847beba7" - url: "https://pub.dev" - source: hosted - version: "0.3.5+3" characters: dependency: transitive description: name: characters sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" - charset: - dependency: transitive - description: - name: charset - sha256: "27802032a581e01ac565904ece8c8962564b1070690794f0072f6865958ce8b9" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - choice: - dependency: transitive - description: - name: choice - sha256: "52d07065e8056beba5b26cff7786134cbfa24927b1f5bf60a05d50058597b2d9" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" clock: dependency: transitive description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.2" code_assets: dependency: transitive description: name: code_assets - sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.dev" + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.2.1" collection: dependency: transitive description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.19.1" - computer: - dependency: transitive - description: - path: "." - ref: "v1.0.88" - resolved-ref: b0819c8a939e1fa6858f1a0e12ee8122db0df390 - url: "https://github.com/lollipopkit/dart_computer" - source: git - version: "3.2.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" - url: "https://pub.dev" - source: hosted - version: "1.15.0" cross_file: dependency: transitive description: name: cross_file sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.5+2" crypto: @@ -183,7 +70,7 @@ packages: description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.7" dbus: @@ -191,7 +78,7 @@ packages: description: name: dbus sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.12" desktop_drop: @@ -199,55 +86,15 @@ packages: description: name: desktop_drop sha256: "927511f590ce01ee90d0d80f79bc71b9c919d8522d01e495e89a00c6f4a4fb5b" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.6.1" - dio: - dependency: transitive - description: - name: dio - sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c - url: "https://pub.dev" - source: hosted - version: "5.9.2" - dio_web_adapter: - dependency: transitive - description: - name: dio_web_adapter - sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - equatable: - dependency: transitive - description: - name: equatable - sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" - url: "https://pub.dev" - source: hosted - version: "2.0.8" - extended_image: - dependency: transitive - description: - name: extended_image - sha256: f6cbb1d798f51262ed1a3d93b4f1f2aa0d76128df39af18ecb77fa740f88b2e0 - url: "https://pub.dev" - source: hosted - version: "10.0.1" - extended_image_library: - dependency: transitive - description: - name: extended_image_library - sha256: "1f9a24d3a00c2633891c6a7b5cab2807999eb2d5b597e5133b63f49d113811fe" - url: "https://pub.dev" - source: hosted - version: "5.0.1" fake_async: dependency: transitive description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.3" ffi: @@ -255,7 +102,7 @@ packages: description: name: ffi sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" file: @@ -263,7 +110,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" file_picker: @@ -271,7 +118,7 @@ packages: description: name: file_picker sha256: "57d9a1dd5063f85fa3107fb42d1faffda52fdc948cefd5fe5ea85267a5fc7343" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "10.3.10" fixnum: @@ -279,35 +126,20 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" - fl_lib: - dependency: "direct main" - description: - path: "packages/fl_lib" - relative: true - source: path - version: "0.0.1" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" - flutter_highlight: - dependency: transitive - description: - name: flutter_highlight - sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" - url: "https://pub.dev" - source: hosted - version: "0.7.0" flutter_lints: dependency: "direct dev" description: name: flutter_lints sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.0.0" flutter_localizations: @@ -315,102 +147,14 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_markdown_plus: - dependency: transitive - description: - name: flutter_markdown_plus - sha256: "039177906850278e8fb1cd364115ee0a46281135932fa8ecea8455522166d2de" - url: "https://pub.dev" - source: hosted - version: "1.0.7" - flutter_markdown_plus_latex: - dependency: transitive - description: - name: flutter_markdown_plus_latex - sha256: "2e7698b291f0657ca445efab730bb25a8c5851037e882cb7bf47d16a5c218de7" - url: "https://pub.dev" - source: hosted - version: "1.0.5" - flutter_math_fork: - dependency: transitive - description: - name: flutter_math_fork - sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407" - url: "https://pub.dev" - source: hosted - version: "0.7.4" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.34" - flutter_riverpod: - dependency: transitive - description: - name: flutter_riverpod - sha256: "4e166be88e1dbbaa34a280bdb744aeae73b7ef25fdf8db7a3bb776760a3648e2" - url: "https://pub.dev" - source: hosted - version: "3.3.1" - flutter_secure_storage: - dependency: transitive - description: - name: flutter_secure_storage - sha256: da922f2aab2d733db7e011a6bcc4a825b844892d4edd6df83ff156b09a9b2e40 - url: "https://pub.dev" - source: hosted - version: "10.0.0" - flutter_secure_storage_darwin: - dependency: transitive - description: - name: flutter_secure_storage_darwin - sha256: "8878c25136a79def1668c75985e8e193d9d7d095453ec28730da0315dc69aee3" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - flutter_secure_storage_linux: - dependency: transitive - description: - name: flutter_secure_storage_linux - sha256: "2b5c76dce569ab752d55a1cee6a2242bcc11fdba927078fb88c503f150767cda" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - flutter_secure_storage_platform_interface: - dependency: transitive - description: - name: flutter_secure_storage_platform_interface - sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - flutter_secure_storage_web: - dependency: transitive - description: - name: flutter_secure_storage_web - sha256: "6a1137df62b84b54261dca582c1c09ea72f4f9a4b2fcee21b025964132d5d0c3" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - flutter_secure_storage_windows: - dependency: transitive - description: - name: flutter_secure_storage_windows - sha256: "3b7c8e068875dfd46719ff57c90d8c459c87f2302ed6b00ff006b3c9fcad1613" - url: "https://pub.dev" - source: hosted - version: "4.1.0" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - sha256: "1ded017b39c8e15c8948ea855070a5ff8ff8b3d5e83f3446e02d6bb12add7ad9" - url: "https://pub.dev" - source: hosted - version: "2.2.4" flutter_test: dependency: "direct dev" description: flutter @@ -421,165 +165,44 @@ packages: description: flutter source: sdk version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - highlight: - dependency: transitive - description: - name: highlight - sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - hive_ce: - dependency: transitive - description: - name: hive_ce - sha256: "8e9980e68643afb1e765d3af32b47996552a64e190d03faf622cea07c1294418" - url: "https://pub.dev" - source: hosted - version: "2.19.3" - hive_ce_flutter: - dependency: transitive - description: - name: hive_ce_flutter - sha256: "2677e95a333ff15af43ccd06af7eb7abbf1a4f154ea071997f3de4346cae913a" - url: "https://pub.dev" - source: hosted - version: "2.3.4" hooks: dependency: transitive description: name: hooks - sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 - url: "https://pub.dev" + sha256: "62ae9bb76d02526c7c2110a19b6e6ad788fe28d35e553e35efb02a41a46ab43a" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.2" + version: "2.0.1" http: dependency: "direct main" description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.6.0" - http_client_helper: - dependency: transitive - description: - name: http_client_helper - sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" http_parser: dependency: transitive description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.2" - icloud_storage: - dependency: transitive - description: - name: icloud_storage - sha256: fa91d9c3b4264651f01a4f5b99cffa354ffe455623b13ecf92be86d88b1e26ea - url: "https://pub.dev" - source: hosted - version: "2.2.0" - icons_plus: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: "42670d29c8c1cffb7203dd110e0009ba98709667" - url: "https://github.com/lollipopkit/icons_plus" - source: git - version: "5.0.0" - image: - dependency: transitive - description: - name: image - sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce - url: "https://pub.dev" - source: hosted - version: "4.8.0" intl: dependency: "direct main" description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - isolate_channel: - dependency: transitive - description: - name: isolate_channel - sha256: a9d3d620695bc984244dafae00b95e4319d6974b2d77f4b9e1eb4f2efe099094 - url: "https://pub.dev" - source: hosted - version: "0.6.1" - isolate_contactor: - dependency: transitive - description: - name: isolate_contactor - sha256: "6ba8434ceb58238a1389d6365111a3efe7baa1c68a66f4db6d63d351cf6c3a0f" - url: "https://pub.dev" - source: hosted - version: "4.1.0" - isolate_manager: - dependency: transitive - description: - name: isolate_manager - sha256: "22ed0c25f80ec3b5f21e3a55d060f4650afff33f27c2dff34c0f9409d5759ae5" - url: "https://pub.dev" - source: hosted - version: "4.1.5+1" jni: dependency: transitive description: name: jni sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" jni_flutter: @@ -587,31 +210,23 @@ packages: description: name: jni_flutter sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" json_annotation: dependency: transitive description: name: json_annotation - sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 - url: "https://pub.dev" + sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.11.0" + version: "4.12.0" launch_at_startup: dependency: "direct main" description: name: launch_at_startup sha256: "7db33398b76ec0ed9e27f9f4640553e239977437564046625e215be89c91f084" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.5.1" leak_tracker: @@ -619,7 +234,7 @@ packages: description: name: leak_tracker sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "11.0.2" leak_tracker_flutter_testing: @@ -627,7 +242,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.10" leak_tracker_testing: @@ -635,7 +250,7 @@ packages: description: name: leak_tracker_testing sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.2" lints: @@ -643,87 +258,31 @@ packages: description: name: lints sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.0" - local_auth: - dependency: transitive - description: - name: local_auth - sha256: ae6f382f638108c6becd134318d7c3f0a93875383a54010f61d7c97ac05d5137 - url: "https://pub.dev" - source: hosted - version: "3.0.1" - local_auth_android: - dependency: transitive - description: - name: local_auth_android - sha256: b201c006fa769c23386f89aa6837ec0eb8179fcfb212eadcf87b422b3f9a6a78 - url: "https://pub.dev" - source: hosted - version: "2.0.8" - local_auth_darwin: - dependency: transitive - description: - name: local_auth_darwin - sha256: a8c3d4e17454111f7fd31ff72a31222359f6059f7fe956c2dcfe0f88f49826d4 - url: "https://pub.dev" - source: hosted - version: "2.0.3" - local_auth_platform_interface: - dependency: transitive - description: - name: local_auth_platform_interface - sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 - url: "https://pub.dev" - source: hosted - version: "1.1.0" - local_auth_windows: - dependency: transitive - description: - name: local_auth_windows - sha256: be12c5b8ba5e64896983123655c5f67d2484ecfcc95e367952ad6e3bff94cb16 - url: "https://pub.dev" - source: hosted - version: "2.0.1" local_notifier: dependency: "direct main" description: name: local_notifier sha256: f6cfc933c6fbc961f4e52b5c880f68e41b2d3cd29aad557cc654fd211093a025 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.6" - locale_names: - dependency: transitive - description: - name: locale_names - sha256: "7a89ca54072f4f13d0f5df5a9ba69337554bf2fd057d1dd2a238898f3f159374" - url: "https://pub.dev" - source: hosted - version: "1.1.1" logging: dependency: "direct main" description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9 - url: "https://pub.dev" - source: hosted - version: "7.3.1" matcher: dependency: transitive description: name: matcher sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.19" material_color_utilities: @@ -731,7 +290,7 @@ packages: description: name: material_color_utilities sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.13.0" menu_base: @@ -739,7 +298,7 @@ packages: description: name: menu_base sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.1" meta: @@ -747,63 +306,31 @@ packages: description: name: meta sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.17.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - multi_split_view: - dependency: transitive - description: - name: multi_split_view - sha256: "06f5126a65d3010ce0a9d5c003e793041fe99377b23e3534bb05059f79a580e9" - url: "https://pub.dev" - source: hosted - version: "3.6.1" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.dev" - source: hosted - version: "0.17.6" nested: dependency: transitive description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" objective_c: dependency: transitive description: name: objective_c - sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.dev" + sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed" + url: "https://pub.flutter-io.cn" source: hosted - version: "9.3.0" + version: "9.4.1" package_config: dependency: transitive description: name: package_config sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" package_info_plus: @@ -811,7 +338,7 @@ packages: description: name: package_info_plus sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "9.0.1" package_info_plus_platform_interface: @@ -819,7 +346,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" path: @@ -827,23 +354,15 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" path_provider: - dependency: transitive + dependency: "direct main" description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.5" path_provider_android: @@ -851,7 +370,7 @@ packages: description: name: path_provider_android sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.1" path_provider_foundation: @@ -859,7 +378,7 @@ packages: description: name: path_provider_foundation sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.6.0" path_provider_linux: @@ -867,7 +386,7 @@ packages: description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -875,7 +394,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" path_provider_windows: @@ -883,7 +402,7 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.0" petitparser: @@ -891,7 +410,7 @@ packages: description: name: petitparser sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.2" platform: @@ -899,7 +418,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.6" plugin_platform_interface: @@ -907,55 +426,23 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.8" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" port_forwarder: dependency: "direct main" description: name: port_forwarder sha256: "80f762d6bba492aa6f458a4cb00ecdbac02007bfa6435907397212370962ca7d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" - posix: - dependency: transitive - description: - name: posix - sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" - url: "https://pub.dev" - source: hosted - version: "6.5.0" - pretty_qr_code: - dependency: transitive - description: - name: pretty_qr_code - sha256: "474f8a4512113fba06f14a6ec9bbf42353b4e651d7a520e3096f2a9b6bbe7a8a" - url: "https://pub.dev" - source: hosted - version: "3.6.0" provider: dependency: "direct main" description: name: provider sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.5+1" pub_semver: @@ -963,80 +450,23 @@ packages: description: name: pub_semver sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" - qr: - dependency: transitive - description: - name: qr - sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - qr_code_dart_decoder: - dependency: transitive - description: - name: qr_code_dart_decoder - sha256: "4044f13a071da6102f7e9bc44a6b1ce577604d7846bcbeb1be412a137b825017" - url: "https://pub.dev" - source: hosted - version: "0.1.2" - qr_code_dart_scan: - dependency: transitive - description: - name: qr_code_dart_scan - sha256: "81443d940f8f27baaa4b9aeaa8d3d2155ad2c0b9842a9bacb03dab85c111e2f6" - url: "https://pub.dev" - source: hosted - version: "0.11.5" - re_editor: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: d5d70020da74082d182301a49e2bb87d30f0ab66 - url: "https://github.com/lollipopkit/re-editor" - source: git - version: "0.8.0" - re_highlight: - dependency: transitive - description: - name: re_highlight - sha256: "6c4ac3f76f939fb7ca9df013df98526634e17d8f7460e028bd23a035870024f2" - url: "https://pub.dev" - source: hosted - version: "0.0.3" - responsive_framework: - dependency: transitive - description: - name: responsive_framework - sha256: a8e1c13d4ba980c60cbf6fa1e9907cd60662bf2585184d7c96ca46c43de91552 - url: "https://pub.dev" - source: hosted - version: "1.5.1" - riverpod: - dependency: transitive - description: - name: riverpod - sha256: "8c22216be8ad3ef2b44af3a329693558c98eca7b8bd4ef495c92db0bba279f83" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - riverpod_annotation: + record_use: dependency: transitive description: - name: riverpod_annotation - sha256: "16471a1260b94e939394d78f1c63a9350936ac4a68c9fbdab40be47268c0b04f" - url: "https://pub.dev" + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.2" + version: "0.6.0" screen_retriever: dependency: transitive description: name: screen_retriever sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_linux: @@ -1044,7 +474,7 @@ packages: description: name: screen_retriever_linux sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_macos: @@ -1052,7 +482,7 @@ packages: description: name: screen_retriever_macos sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_platform_interface: @@ -1060,7 +490,7 @@ packages: description: name: screen_retriever_platform_interface sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_windows: @@ -1068,31 +498,15 @@ packages: description: name: screen_retriever_windows sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" - share_plus: - dependency: transitive - description: - name: share_plus - sha256: "223873d106614442ea6f20db5a038685cc5b32a2fba81cdecaefbbae0523f7fa" - url: "https://pub.dev" - source: hosted - version: "12.0.2" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" - url: "https://pub.dev" - source: hosted - version: "6.1.0" shared_preferences: - dependency: transitive + dependency: "direct main" description: name: shared_preferences sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.5" shared_preferences_android: @@ -1100,7 +514,7 @@ packages: description: name: shared_preferences_android sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.23" shared_preferences_foundation: @@ -1108,7 +522,7 @@ packages: description: name: shared_preferences_foundation sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.6" shared_preferences_linux: @@ -1116,7 +530,7 @@ packages: description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" shared_preferences_platform_interface: @@ -1124,7 +538,7 @@ packages: description: name: shared_preferences_platform_interface sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.2" shared_preferences_web: @@ -1132,7 +546,7 @@ packages: description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.3" shared_preferences_windows: @@ -1140,47 +554,15 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" shortid: dependency: transitive description: name: shortid sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.2" sky_engine: @@ -1188,28 +570,12 @@ packages: description: flutter source: sdk version: "0.0.0" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" source_span: dependency: transitive description: name: source_span sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.2" stack_trace: @@ -1217,39 +583,23 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.12.1" - state_notifier: - dependency: transitive - description: - name: state_notifier - sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb - url: "https://pub.dev" - source: hosted - version: "1.0.0" stream_channel: dependency: transitive description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" - source: hosted - version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" term_glyph: @@ -1257,55 +607,31 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" - url: "https://pub.dev" - source: hosted - version: "1.30.0" test_api: dependency: transitive description: name: test_api sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.10" - test_core: - dependency: transitive - description: - name: test_core - sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" - url: "https://pub.dev" - source: hosted - version: "0.6.16" tray_manager: dependency: "direct main" description: name: tray_manager sha256: c5fd83b0ae4d80be6eaedfad87aaefab8787b333b8ebd064b0e442a81006035b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.5.2" - tuple: - dependency: transitive - description: - name: tuple - sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.dev" - source: hosted - version: "2.0.2" typed_data: dependency: transitive description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" universal_platform: @@ -1313,7 +639,7 @@ packages: description: name: universal_platform sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" url_launcher: @@ -1321,23 +647,23 @@ packages: description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572" - url: "https://pub.dev" + sha256: "17bc677f0b301615530dd1d67e0a9828cafa2d0b6b6eae4cd3679b7eac4a273c" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.3.29" + version: "6.3.30" url_launcher_ios: dependency: transitive description: name: url_launcher_ios sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.4.1" url_launcher_linux: @@ -1345,7 +671,7 @@ packages: description: name: url_launcher_linux sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.2" url_launcher_macos: @@ -1353,7 +679,7 @@ packages: description: name: url_launcher_macos sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.5" url_launcher_platform_interface: @@ -1361,23 +687,23 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f - url: "https://pub.dev" + sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.2" + version: "2.4.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.5" uuid: @@ -1385,103 +711,39 @@ packages: description: name: uuid sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.5.3" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: "81da85e9ca8885ade47f9685b953cb098970d11be4821ac765580a6607ea4373" - url: "https://pub.dev" - source: hosted - version: "1.1.21" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74" - url: "https://pub.dev" - source: hosted - version: "1.2.0" vector_math: dependency: transitive description: name: vector_math sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" vm_service: dependency: transitive description: name: vm_service - sha256: "046d3928e16fa4dc46e8350415661755ab759d9fc97fc21b5ab295f71e4f0499" - url: "https://pub.dev" - source: hosted - version: "15.1.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" - url: "https://pub.dev" + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "15.2.0" web: dependency: transitive description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webdav_client_plus: - dependency: transitive - description: - name: webdav_client_plus - sha256: "0f992fe05a46674a800d9fd8fdc5c54952ff739da155c558776a62ca0c2bed3a" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" win32: dependency: transitive description: name: win32 sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.15.0" win32_registry: @@ -1489,7 +751,7 @@ packages: description: name: win32_registry sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" window_manager: @@ -1497,7 +759,7 @@ packages: description: name: window_manager sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.5.1" xdg_directories: @@ -1505,7 +767,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" xml: @@ -1513,7 +775,7 @@ packages: description: name: xml sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.6.1" yaml: @@ -1521,17 +783,9 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.3" - zxing_lib: - dependency: transitive - description: - name: zxing_lib - sha256: f9170470b6bc947d21a6783486f88ef48aad66fc1380c8acd02b118418ec0ce0 - url: "https://pub.dev" - source: hosted - version: "1.1.4" sdks: dart: ">=3.10.4 <4.0.0" flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index 024a5ba..4e7df71 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,8 +54,8 @@ dependencies: intl: ^0.20.2 # Local packages - fl_lib: - path: packages/fl_lib + path_provider: ^2.1.4 + shared_preferences: ^2.2.3 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index a66e509..bab040c 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,11 +7,8 @@ #include "generated_plugin_registrant.h" #include -#include -#include #include #include -#include #include #include #include @@ -19,16 +16,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { DesktopDropPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("DesktopDropPlugin")); - FlutterSecureStorageWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); - LocalAuthPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("LocalAuthPlugin")); LocalNotifierPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalNotifierPlugin")); ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); - SharePlusWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); TrayManagerPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("TrayManagerPlugin")); UrlLauncherWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ca3e30b..8790822 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,11 +4,8 @@ list(APPEND FLUTTER_PLUGIN_LIST desktop_drop - flutter_secure_storage_windows - local_auth_windows local_notifier screen_retriever_windows - share_plus tray_manager url_launcher_windows window_manager From 0656bb198c04146d0abb840da1d1df6e14309e9a Mon Sep 17 00:00:00 2001 From: GT610 Date: Tue, 2 Jun 2026 12:00:20 +0800 Subject: [PATCH 2/4] Fix --- lib/app.dart | 53 ++++++---- lib/kit/core/build.dart | 3 +- lib/kit/core/ext/widget.dart | 19 ++-- lib/kit/core/func.dart | 2 +- lib/kit/core/platform.dart | 2 +- lib/kit/core/rnode.dart | 14 +-- lib/kit/pages/debug_page.dart | 5 +- lib/kit/provider/debug.dart | 45 +++++--- lib/kit/res/font.dart | 21 ++-- lib/kit/res/ui.dart | 14 +-- lib/kit/widgets/btn.dart | 114 +++++++++------------ lib/kit/widgets/card.dart | 4 +- lib/kit/widgets/input.dart | 25 +++-- lib/kit/widgets/loading.dart | 5 +- lib/kit/widgets/text.dart | 4 +- lib/kit/widgets/virtual_window_frame.dart | 12 +-- lib/pages/settings_page/settings_page.dart | 17 +-- lib/utils/logging.dart | 5 +- 18 files changed, 181 insertions(+), 183 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index b09072d..4a1ac6d 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,12 +1,13 @@ import 'dart:async'; -import 'kit/kit.dart' as kit; -import 'kit/kit.dart' show ChineseThemeData; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:window_manager/window_manager.dart'; + import 'constants/app_branding.dart'; import 'generated/l10n/l10n.dart'; +import 'kit/kit.dart' as kit; +import 'kit/kit.dart' show ChineseThemeData; import 'models/aria2_instance.dart'; import 'models/settings.dart'; import 'pages/download_page/download_page.dart'; @@ -53,7 +54,23 @@ class _ThemeProviderState extends State<_ThemeProvider> { @override Widget build(BuildContext context) { - final display = context.select((s) => (locale: s.locale, hideTitleBar: s.hideTitleBar, primaryColor: s.primaryColor, themeMode: s.themeMode)); + final display = context + .select< + Settings, + ({ + Locale? locale, + bool hideTitleBar, + Color primaryColor, + ThemeMode themeMode, + }) + >( + (s) => ( + locale: s.locale, + hideTitleBar: s.hideTitleBar, + primaryColor: s.primaryColor, + themeMode: s.themeMode, + ), + ); return MaterialApp( title: kAppName, @@ -552,8 +569,7 @@ class _MainWindowState extends State with WindowListener, Loggable { connectedCount == 0 ? l10n.notConnected : '${l10n.connected}: $connectedCount', - if (settings.showTraySpeed) - l10n.totalSpeed(formatSpeed(summary.speed)), + if (settings.showTraySpeed) l10n.totalSpeed(formatSpeed(summary.speed)), l10n.activeTasks(summary.active.toString()), l10n.waitingTasks(summary.waiting.toString()), ]; @@ -902,7 +918,7 @@ class _MainWindowState extends State with WindowListener, Loggable { } ({int active, int waiting, int resumable, int pausable, int speed}) - _computeTaskSummary(List tasks) { +_computeTaskSummary(List tasks) { var active = 0; var waiting = 0; var resumable = 0; @@ -940,9 +956,13 @@ class _StatusBar extends StatelessWidget { Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final colorScheme = Theme.of(context).colorScheme; - final summary = context.select((service) { - return _computeTaskSummary(service.tasks); - }); + final summary = context + .select< + DownloadDataService, + ({int active, int waiting, int resumable, int pausable, int speed}) + >((service) { + return _computeTaskSummary(service.tasks); + }); return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -967,28 +987,19 @@ class _StatusBar extends StatelessWidget { label: Text(l10n.totalSpeed(formatSpeed(summary.speed))), avatar: const Icon(Icons.speed, size: 16), backgroundColor: colorScheme.surfaceContainerHighest, - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 6, - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), ), Chip( label: Text(l10n.activeTasks(summary.active.toString())), avatar: const Icon(Icons.task_alt, size: 16), backgroundColor: colorScheme.surfaceContainerHighest, - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 6, - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), ), Chip( label: Text(l10n.waitingTasks(summary.waiting.toString())), avatar: const Icon(Icons.pending, size: 16), backgroundColor: colorScheme.surfaceContainerHighest, - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 6, - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), ), ], ), diff --git a/lib/kit/core/build.dart b/lib/kit/core/build.dart index ac9f426..ad051ec 100644 --- a/lib/kit/core/build.dart +++ b/lib/kit/core/build.dart @@ -1,8 +1,7 @@ enum BuildMode { release, debug, - profile, - ; + profile; static final isDebug = _buildMode == BuildMode.debug; static final isProfile = _buildMode == BuildMode.profile; diff --git a/lib/kit/core/ext/widget.dart b/lib/kit/core/ext/widget.dart index e8dd139..6105b79 100644 --- a/lib/kit/core/ext/widget.dart +++ b/lib/kit/core/ext/widget.dart @@ -9,14 +9,13 @@ extension WidgetX on Widget { double top = 0, double right = 0, double bottom = 0, - }) => - Padding( - padding: EdgeInsets.only( - left: left, - top: top, - right: right, - bottom: bottom, - ), - child: this, - ); + }) => Padding( + padding: EdgeInsets.only( + left: left, + top: top, + right: right, + bottom: bottom, + ), + child: this, + ); } diff --git a/lib/kit/core/func.dart b/lib/kit/core/func.dart index 0fdd7cc..5ffc3a1 100644 --- a/lib/kit/core/func.dart +++ b/lib/kit/core/func.dart @@ -9,7 +9,7 @@ abstract final class Fns { FutureOr Function() func, { String id = _defaultThrottleId, int duration = _defaultDurationTime, - Function? continueClick, + void Function()? continueClick, }) async { final currentTime = DateTime.now().millisecondsSinceEpoch; if (currentTime - (startTimeMap[id] ?? 0) > duration) { diff --git a/lib/kit/core/platform.dart b/lib/kit/core/platform.dart index 8b564fe..476f334 100644 --- a/lib/kit/core/platform.dart +++ b/lib/kit/core/platform.dart @@ -25,7 +25,7 @@ enum Pfs { }; }(); - static final String seperator = isWindows ? '\\' : '/'; + static final String separator = isWindows ? '\\' : '/'; static final String? homeDir = () { final envVars = Platform.environment; diff --git a/lib/kit/core/rnode.dart b/lib/kit/core/rnode.dart index c1d7dbc..dfe4f9f 100644 --- a/lib/kit/core/rnode.dart +++ b/lib/kit/core/rnode.dart @@ -21,10 +21,14 @@ class RNode implements ChangeNotifier { Future notify({bool delay = false}) async { if (delay) await Future.delayed(const Duration(milliseconds: 277)); - for (final listener in _listeners) { + for (final listener in List.of(_listeners)) { try { listener(); - } catch (_) {} + } catch (error, stack) { + FlutterError.reportError( + FlutterErrorDetails(exception: error, stack: stack), + ); + } } } @@ -58,6 +62,7 @@ class VNode extends RNode implements ValueNotifier { @override set value(T newVal) { + if (_value == newVal) return; _value = newVal; notify(); } @@ -79,10 +84,7 @@ final class ValBuilder extends ValueListenableBuilder { super.key, required this.listenable, required Widget Function(T) builder, - }) : super( - valueListenable: listenable, - builder: (_, val, _) => builder(val), - ); + }) : super(valueListenable: listenable, builder: (_, val, _) => builder(val)); } final class ListenBuilder extends ListenableBuilder { diff --git a/lib/kit/pages/debug_page.dart b/lib/kit/pages/debug_page.dart index 1f70f43..665fde7 100644 --- a/lib/kit/pages/debug_page.dart +++ b/lib/kit/pages/debug_page.dart @@ -24,10 +24,7 @@ class DebugPage extends StatelessWidget { onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.arrow_back), ), - title: Text( - args?.title ?? 'Log', - style: const TextStyle(fontSize: 17), - ), + title: Text(args?.title ?? 'Log', style: const TextStyle(fontSize: 17)), actions: [ const Btn.icon( icon: Icon(Icons.copy, size: 23), diff --git a/lib/kit/provider/debug.dart b/lib/kit/provider/debug.dart index 985359f..bfd6074 100644 --- a/lib/kit/provider/debug.dart +++ b/lib/kit/provider/debug.dart @@ -9,7 +9,7 @@ import '../res/ui.dart'; const _level2Color = { 'INFO': Colors.cyan, 'WARNING': Colors.yellow, - 'ERROR': Color(0xffbb2d6f), + 'SEVERE': Color(0xffbb2d6f), }; final class DebugProvider { @@ -25,24 +25,36 @@ final class DebugProvider { ? '\n${record.message}' : '\n${record.message}: ${record.error}'; lines.add('$title$level$message'); - widgets.value.add(Text.rich(TextSpan( - children: [ - TextSpan(text: title, style: TextStyle(color: color)), - TextSpan(text: level, style: TextStyle(color: color)), + widgets.value.add( + Text.rich( TextSpan( - text: message, - style: const TextStyle(color: Colors.white), + children: [ + TextSpan( + text: title, + style: TextStyle(color: color), + ), + TextSpan( + text: level, + style: TextStyle(color: color), + ), + TextSpan( + text: message, + style: const TextStyle(color: Colors.white), + ), + ], ), - ], - ))); + ), + ); if (record.stackTrace != null) { - widgets.value.add(SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Text( - '${record.stackTrace}', - style: const TextStyle(color: Colors.white), + widgets.value.add( + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Text( + '${record.stackTrace}', + style: const TextStyle(color: Colors.white), + ), ), - )); + ); } widgets.value.add(UIs.height13); if (widgets.value.length > maxLines) { @@ -61,5 +73,6 @@ final class DebugProvider { widgets.notify(); } - static void copy() => Clipboard.setData(ClipboardData(text: lines.join('\n'))); + static void copy() => + Clipboard.setData(ClipboardData(text: lines.join('\n'))); } diff --git a/lib/kit/res/font.dart b/lib/kit/res/font.dart index ad81acc..b3662bc 100644 --- a/lib/kit/res/font.dart +++ b/lib/kit/res/font.dart @@ -4,21 +4,19 @@ import 'package:flutter/material.dart'; import '../core/platform.dart'; -const _fontFamilyFallback = [ - 'system-font', - 'sans-serif', - 'Microsoft YaHei', -]; +const _fontFamilyFallback = ['system-font', 'sans-serif', 'Microsoft YaHei']; extension ChineseTextTheme on TextTheme { static final Typography _typography = Typography.material2021(); TextTheme _fixChinese(Brightness brightness) { final newTextTheme = switch (brightness) { - Brightness.dark => - _typography.white.apply(fontFamilyFallback: _fontFamilyFallback), - Brightness.light => - _typography.black.apply(fontFamilyFallback: _fontFamilyFallback), + Brightness.dark => _typography.white.apply( + fontFamilyFallback: _fontFamilyFallback, + ), + Brightness.light => _typography.black.apply( + fontFamilyFallback: _fontFamilyFallback, + ), }; return newTextTheme.merge(this); } @@ -29,8 +27,9 @@ extension ChineseThemeData on ThemeData { if (!isWindows) return this; return switch (Platform.localeName) { - final locale when locale.startsWith('zh') => - copyWith(textTheme: textTheme._fixChinese(brightness)), + final locale when locale.startsWith('zh') => copyWith( + textTheme: textTheme._fixChinese(brightness), + ), _ => this, }; } diff --git a/lib/kit/res/ui.dart b/lib/kit/res/ui.dart index fe449e0..5e87635 100644 --- a/lib/kit/res/ui.dart +++ b/lib/kit/res/ui.dart @@ -37,13 +37,13 @@ abstract final class UIs { static const width13 = SizedBox(width: 13); static Widget dot({Color? color, double? size}) => Container( - width: size ?? 7, - height: size ?? 7, - decoration: BoxDecoration( - color: color ?? primaryColor, - shape: BoxShape.circle, - ), - ); + width: size ?? 7, + height: size ?? 7, + decoration: BoxDecoration( + color: color ?? primaryColor, + shape: BoxShape.circle, + ), + ); static const centerLoading = Padding( padding: EdgeInsets.symmetric(vertical: 7), diff --git a/lib/kit/widgets/btn.dart b/lib/kit/widgets/btn.dart index 2ee0c07..529bf05 100644 --- a/lib/kit/widgets/btn.dart +++ b/lib/kit/widgets/btn.dart @@ -2,13 +2,7 @@ import 'package:flutter/material.dart'; import '../res/ui.dart'; -enum BtnType { - row, - text, - icon, - column, - elevated, -} +enum BtnType { row, text, icon, column, elevated } Null _defaultOnTap() => null; @@ -38,13 +32,13 @@ final class Btn extends StatelessWidget { this.textStyle, this.padding, this.onLongTap, - }) : type = BtnType.text, - gap = null, - mainAxisAlignment = null, - mainAxisSize = null, - borderRadius = null, - popVal = null, - icon = null; + }) : type = BtnType.text, + gap = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = null, + icon = null; const Btn.icon({ super.key, @@ -53,13 +47,13 @@ final class Btn extends StatelessWidget { this.onTap = _defaultOnTap, this.padding = _kPadding, this.onLongTap, - }) : type = BtnType.icon, - gap = null, - mainAxisAlignment = null, - mainAxisSize = null, - borderRadius = null, - popVal = null, - textStyle = null; + }) : type = BtnType.icon, + gap = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = null, + textStyle = null; const Btn.column({ super.key, @@ -73,8 +67,8 @@ final class Btn extends StatelessWidget { this.mainAxisSize, this.borderRadius = _kBorderRadius, this.onLongTap, - }) : type = BtnType.column, - popVal = null; + }) : type = BtnType.column, + popVal = null; const Btn.row({ super.key, @@ -88,8 +82,8 @@ final class Btn extends StatelessWidget { this.mainAxisSize, this.borderRadius = _kBorderRadius, this.onLongTap, - }) : type = BtnType.row, - popVal = null; + }) : type = BtnType.row, + popVal = null; const Btn.tile({ super.key, @@ -97,17 +91,14 @@ final class Btn extends StatelessWidget { required this.icon, this.onTap = _defaultOnTap, this.gap = 20, - this.textStyle = const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - ), + this.textStyle = const TextStyle(fontSize: 16, fontWeight: FontWeight.w400), this.padding = const EdgeInsets.symmetric(vertical: 13, horizontal: 20), this.mainAxisAlignment, this.mainAxisSize, this.borderRadius = const BorderRadius.all(Radius.circular(13)), this.onLongTap, - }) : type = BtnType.row, - popVal = null; + }) : type = BtnType.row, + popVal = null; const Btn.elevated({ super.key, @@ -121,8 +112,8 @@ final class Btn extends StatelessWidget { this.mainAxisSize, this.borderRadius = const BorderRadius.all(Radius.circular(13)), this.onLongTap, - }) : type = BtnType.elevated, - popVal = null; + }) : type = BtnType.elevated, + popVal = null; const Btn.ok({ super.key, @@ -130,41 +121,41 @@ final class Btn extends StatelessWidget { bool red = false, this.onLongTap, String? text, - }) : this.text = text ?? 'OK', - icon = null, - type = BtnType.text, - gap = null, - padding = null, - mainAxisAlignment = null, - mainAxisSize = null, - borderRadius = null, - popVal = true, - textStyle = red ? UIs.textRed : null; + }) : this.text = text ?? 'OK', + icon = null, + type = BtnType.text, + gap = null, + padding = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = true, + textStyle = red ? UIs.textRed : null; const Btn.cancel({ super.key, this.onTap = _defaultOnTap, this.onLongTap, String? text, - }) : this.text = text ?? 'Cancel', - icon = null, - type = BtnType.text, - gap = null, - padding = null, - mainAxisAlignment = null, - mainAxisSize = null, - borderRadius = null, - popVal = false, - textStyle = null; + }) : this.text = text ?? 'Cancel', + icon = null, + type = BtnType.text, + gap = null, + padding = null, + mainAxisAlignment = null, + mainAxisSize = null, + borderRadius = null, + popVal = false, + textStyle = null; @override Widget build(BuildContext context) => switch (type) { - BtnType.text => _text(context), - BtnType.icon => _icon(context), - BtnType.column => _column(context), - BtnType.row => _row(context), - BtnType.elevated => _elevated(context), - }; + BtnType.text => _text(context), + BtnType.icon => _icon(context), + BtnType.column => _column(context), + BtnType.row => _row(context), + BtnType.elevated => _elevated(context), + }; VoidCallback? _resolveOnTap(BuildContext c) { if (onTap == _defaultOnTap) { @@ -186,10 +177,7 @@ final class Btn extends StatelessWidget { } Widget _icon(BuildContext context) { - Widget child = Tooltip( - message: text, - child: icon ?? _kPlaceholderIcon, - ); + Widget child = Tooltip(message: text, child: icon ?? _kPlaceholderIcon); if (padding != null) child = Padding(padding: padding!, child: child); return InkWell( borderRadius: borderRadius ?? _kBorderRadius, diff --git a/lib/kit/widgets/card.dart b/lib/kit/widgets/card.dart index 57513c5..f330299 100644 --- a/lib/kit/widgets/card.dart +++ b/lib/kit/widgets/card.dart @@ -22,9 +22,7 @@ class CardX extends StatelessWidget { key: key, clipBehavior: clipBehavior, color: color, - shape: RoundedRectangleBorder( - borderRadius: radius ?? borderRadius, - ), + shape: RoundedRectangleBorder(borderRadius: radius ?? borderRadius), elevation: 0, child: child, ); diff --git a/lib/kit/widgets/input.dart b/lib/kit/widgets/input.dart index 5b63f56..e646fc6 100644 --- a/lib/kit/widgets/input.dart +++ b/lib/kit/widgets/input.dart @@ -58,9 +58,9 @@ class Input extends StatefulWidget { this.maxLength, this.enabled, }) : assert( - !(obscureText && suffix != null), - 'suffix != null && obscureText', - ); + !(obscureText && suffix != null), + 'suffix != null && obscureText', + ); @override State createState() => _InputState(); @@ -71,8 +71,9 @@ class _InputState extends State { @override Widget build(BuildContext context) { - final icon = - widget.icon != null ? Icon(widget.icon!).paddingOnly(left: 5) : null; + final icon = widget.icon != null + ? Icon(widget.icon!).paddingOnly(left: 5) + : null; final child = _buildField(icon); if (widget.noWrap) return child; @@ -112,11 +113,11 @@ class _InputState extends State { onTapOutside: widget.onTapOutside, maxLength: widget.maxLength, enabled: widget.enabled, - contextMenuBuilder: widget.contextMenuBuilder ?? - (context, state) => - AdaptiveTextSelectionToolbar.editableText( - editableTextState: state, - ), + contextMenuBuilder: + widget.contextMenuBuilder ?? + (context, state) => AdaptiveTextSelectionToolbar.editableText( + editableTextState: state, + ), ); } @@ -125,9 +126,7 @@ class _InputState extends State { if (!widget.obscureText) return null; return IconButton( - icon: Icon( - _obscureText ? Icons.visibility : Icons.visibility_off, - ), + icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off), onPressed: () { setState(() { _obscureText = !_obscureText; diff --git a/lib/kit/widgets/loading.dart b/lib/kit/widgets/loading.dart index 0f638d5..e728530 100644 --- a/lib/kit/widgets/loading.dart +++ b/lib/kit/widgets/loading.dart @@ -7,7 +7,7 @@ final class SizedLoading extends StatelessWidget { final double padding; final Animation? valueColor; final Widget Function(BuildContext context, Animation? valueColor) - builder; + builder; const SizedLoading( this.size, { @@ -22,7 +22,8 @@ final class SizedLoading extends StatelessWidget { Animation? valueColor, ) { return LinearProgressIndicator( - valueColor: valueColor ?? + valueColor: + valueColor ?? AlwaysStoppedAnimation(Theme.of(context).colorScheme.primary), ); } diff --git a/lib/kit/widgets/text.dart b/lib/kit/widgets/text.dart index 4e400f3..070d07b 100644 --- a/lib/kit/widgets/text.dart +++ b/lib/kit/widgets/text.dart @@ -11,9 +11,7 @@ final class CenterGreyTitle extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: 23, bottom: 17), - child: Center( - child: Text(text, style: UIs.textGrey), - ), + child: Center(child: Text(text, style: UIs.textGrey)), ); } } diff --git a/lib/kit/widgets/virtual_window_frame.dart b/lib/kit/widgets/virtual_window_frame.dart index 384cce6..581422f 100644 --- a/lib/kit/widgets/virtual_window_frame.dart +++ b/lib/kit/widgets/virtual_window_frame.dart @@ -31,11 +31,11 @@ class VirtualWindowFrame extends StatelessWidget { final content = switch (CustomAppBar.sysStatusBarHeight) { 0.0 => child, _ when showCaption && WindowFrameConfig.showCaption => Column( - children: [ - _WindowCaption(title: title), - Expanded(child: child), - ], - ), + children: [ + _WindowCaption(title: title), + Expanded(child: child), + ], + ), _ => child, }; return wm.VirtualWindowFrame(child: content); @@ -73,7 +73,7 @@ class _WindowCaption extends StatelessWidget { wm.WindowCaption( backgroundColor: Colors.transparent, brightness: theme.brightness, - ) + ), ], ), ); diff --git a/lib/pages/settings_page/settings_page.dart b/lib/pages/settings_page/settings_page.dart index 9464599..1cb6a71 100644 --- a/lib/pages/settings_page/settings_page.dart +++ b/lib/pages/settings_page/settings_page.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import '../../kit/kit.dart' as kit; import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:provider/provider.dart'; @@ -9,6 +8,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../../constants/app_branding.dart'; import '../../constants/github_id.dart'; import '../../generated/l10n/l10n.dart'; +import '../../kit/kit.dart' as kit; import '../../models/settings.dart'; import '../../services/protocol_integration_service.dart'; import '../../services/startup_integration_service.dart'; @@ -537,11 +537,8 @@ class _SettingsPageState extends State Widget linkText(String text, String url) { return GestureDetector( - onTap: () => launchUrl(Uri.parse(url)), - child: Text( - text, - style: TextStyle(color: linkColor, fontSize: 14), - ), + onTap: () => _launchExternalUri(Uri.parse(url)), + child: Text(text, style: TextStyle(color: linkColor, fontSize: 14)), ); } @@ -572,16 +569,12 @@ class _SettingsPageState extends State if (GithubIds.contributors.isNotEmpty) section( l10n.contributors, - GithubIds.contributors - .map((id) => linkText(id, id.url)) - .toList(), + GithubIds.contributors.map((id) => linkText(id, id.url)).toList(), ), if (GithubIds.participants.isNotEmpty) section( l10n.participants, - GithubIds.participants - .map((id) => linkText(id, id.url)) - .toList(), + GithubIds.participants.map((id) => linkText(id, id.url)).toList(), ), ], ); diff --git a/lib/utils/logging.dart b/lib/utils/logging.dart index 78227ba..4d4fd6a 100644 --- a/lib/utils/logging.dart +++ b/lib/utils/logging.dart @@ -1,9 +1,10 @@ import 'dart:async'; -import '../kit/provider/debug.dart'; -import '../kit/core/logger.dart'; import 'package:logging/logging.dart'; +import '../kit/core/logger.dart'; +import '../kit/provider/debug.dart'; + Level get defaultLogLevel => Level.INFO; StreamSubscription? _rootLogSubscription; From 3b99ce4f42b0ec567fb57b340833e75cbb4a6b29 Mon Sep 17 00:00:00 2001 From: GT610 Date: Tue, 2 Jun 2026 12:01:02 +0800 Subject: [PATCH 3/4] Format --- lib/pages/components/settings_helpers.dart | 17 +++++++---------- lib/pages/download_page/download_page.dart | 15 +++++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/pages/components/settings_helpers.dart b/lib/pages/components/settings_helpers.dart index 8a21258..1b21760 100644 --- a/lib/pages/components/settings_helpers.dart +++ b/lib/pages/components/settings_helpers.dart @@ -51,23 +51,20 @@ mixin SettingsPageHelpers on State { ); } - Widget buildSettingsTabView( - List sections, - ) { + Widget buildSettingsTabView(List sections) { return LayoutBuilder( builder: (context, constraints) { final width = constraints.maxWidth; final maxColumns = width >= 1440 ? 3 : width >= 900 - ? 2 - : 1; - final columns = sections.isEmpty ? 1 : maxColumns.clamp(1, sections.length); + ? 2 + : 1; + final columns = sections.isEmpty + ? 1 + : maxColumns.clamp(1, sections.length); const gap = 16.0; - final distributedSections = List.generate( - columns, - (_) => [], - ); + final distributedSections = List.generate(columns, (_) => []); for (var index = 0; index < sections.length; index++) { distributedSections[index % columns].add(sections[index]); diff --git a/lib/pages/download_page/download_page.dart b/lib/pages/download_page/download_page.dart index 65b5d4f..ce122cc 100644 --- a/lib/pages/download_page/download_page.dart +++ b/lib/pages/download_page/download_page.dart @@ -291,9 +291,7 @@ class DownloadPageState extends State .toList(); } - Map _countAllActionableTasks( - List tasks, - ) { + Map _countAllActionableTasks(List tasks) { var pauseable = 0; var resumable = 0; var deletable = 0; @@ -399,7 +397,8 @@ class DownloadPageState extends State final key = '${task.instanceId}::${task.id}'; sortKeys[key] = _sortOption == TaskSortOption.name ? task.name.toLowerCase() - : (_instanceNames[task.instanceId] ?? task.instanceId).toLowerCase(); + : (_instanceNames[task.instanceId] ?? task.instanceId) + .toLowerCase(); } tasks.sort((left, right) { final leftKey = sortKeys['${left.instanceId}::${left.id}'] ?? ''; @@ -413,8 +412,12 @@ class DownloadPageState extends State tasks.sort((left, right) { final result = switch (_sortOption) { TaskSortOption.progress => left.progress.compareTo(right.progress), - TaskSortOption.size => left.totalLengthBytes.compareTo(right.totalLengthBytes), - TaskSortOption.speed => left.downloadSpeedBytes.compareTo(right.downloadSpeedBytes), + TaskSortOption.size => left.totalLengthBytes.compareTo( + right.totalLengthBytes, + ), + TaskSortOption.speed => left.downloadSpeedBytes.compareTo( + right.downloadSpeedBytes, + ), _ => 0, }; if (result != 0) return _sortDescending ? -result : result; From bff98d325dea78e259539f9d20778908671fcd1b Mon Sep 17 00:00:00 2001 From: GT610 Date: Tue, 2 Jun 2026 12:10:30 +0800 Subject: [PATCH 4/4] Fix bugs --- lib/kit/core/rnode.dart | 10 +++++++--- lib/kit/provider/debug.dart | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/kit/core/rnode.dart b/lib/kit/core/rnode.dart index dfe4f9f..1117271 100644 --- a/lib/kit/core/rnode.dart +++ b/lib/kit/core/rnode.dart @@ -19,8 +19,7 @@ class RNode implements ChangeNotifier { _listeners.remove(listener); } - Future notify({bool delay = false}) async { - if (delay) await Future.delayed(const Duration(milliseconds: 277)); + void _notifySync() { for (final listener in List.of(_listeners)) { try { listener(); @@ -32,6 +31,11 @@ class RNode implements ChangeNotifier { } } + Future notify({bool delay = false}) async { + if (delay) await Future.delayed(const Duration(milliseconds: 277)); + _notifySync(); + } + @override void dispose() { _listeners.clear(); @@ -42,7 +46,7 @@ class RNode implements ChangeNotifier { @override void notifyListeners() { - notify(); + _notifySync(); } } diff --git a/lib/kit/provider/debug.dart b/lib/kit/provider/debug.dart index bfd6074..9ec96b9 100644 --- a/lib/kit/provider/debug.dart +++ b/lib/kit/provider/debug.dart @@ -16,6 +16,7 @@ final class DebugProvider { static const int maxLines = 100; static final widgets = [].vn; static final lines = []; + static final _widgetCounts = []; static void addLog(LogRecord record) { final color = _level2Color[record.level.name] ?? Colors.blue; @@ -25,6 +26,8 @@ final class DebugProvider { ? '\n${record.message}' : '\n${record.message}: ${record.error}'; lines.add('$title$level$message'); + + var widgetCount = 1; widgets.value.add( Text.rich( TextSpan( @@ -46,6 +49,7 @@ final class DebugProvider { ), ); if (record.stackTrace != null) { + widgetCount++; widgets.value.add( SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -56,20 +60,24 @@ final class DebugProvider { ), ); } + widgetCount++; widgets.value.add(UIs.height13); - if (widgets.value.length > maxLines) { - widgets.value.removeRange(0, widgets.value.length - maxLines); - } - widgets.notify(); + _widgetCounts.add(widgetCount); - if (lines.length > maxLines) { - lines.removeRange(0, lines.length - maxLines); + while (lines.length > maxLines) { + final removed = _widgetCounts.removeAt(0); + lines.removeAt(0); + if (widgets.value.length >= removed) { + widgets.value.removeRange(0, removed); + } } + widgets.notify(); } static void clear() { widgets.value.clear(); lines.clear(); + _widgetCounts.clear(); widgets.notify(); }