diff --git a/lib/app.dart b/lib/app.dart index 2f48877..4a1ac6d 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,12 +1,13 @@ import 'dart:async'; -import 'package:fl_lib/fl_lib.dart' as fl; -import 'package:fl_lib/fl_lib.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,14 +54,30 @@ 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, 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 +220,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(); } @@ -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 new file mode 100644 index 0000000..ad051ec --- /dev/null +++ b/lib/kit/core/build.dart @@ -0,0 +1,21 @@ +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..6105b79 --- /dev/null +++ b/lib/kit/core/ext/widget.dart @@ -0,0 +1,21 @@ +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..5ffc3a1 --- /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, + void 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..476f334 --- /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 separator = 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..1117271 --- /dev/null +++ b/lib/kit/core/rnode.dart @@ -0,0 +1,118 @@ +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); + } + + void _notifySync() { + for (final listener in List.of(_listeners)) { + try { + listener(); + } catch (error, stack) { + FlutterError.reportError( + FlutterErrorDetails(exception: error, stack: stack), + ); + } + } + } + + Future notify({bool delay = false}) async { + if (delay) await Future.delayed(const Duration(milliseconds: 277)); + _notifySync(); + } + + @override + void dispose() { + _listeners.clear(); + } + + @override + bool get hasListeners => _listeners.isNotEmpty; + + @override + void notifyListeners() { + _notifySync(); + } +} + +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) { + if (_value == newVal) return; + _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..665fde7 --- /dev/null +++ b/lib/kit/pages/debug_page.dart @@ -0,0 +1,74 @@ +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..9ec96b9 --- /dev/null +++ b/lib/kit/provider/debug.dart @@ -0,0 +1,86 @@ +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, + 'SEVERE': Color(0xffbb2d6f), +}; + +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; + 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'); + + var widgetCount = 1; + 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) { + widgetCount++; + widgets.value.add( + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Text( + '${record.stackTrace}', + style: const TextStyle(color: Colors.white), + ), + ), + ); + } + widgetCount++; + widgets.value.add(UIs.height13); + _widgetCounts.add(widgetCount); + + 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(); + } + + 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..b3662bc --- /dev/null +++ b/lib/kit/res/font.dart @@ -0,0 +1,36 @@ +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..5e87635 --- /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..529bf05 --- /dev/null +++ b/lib/kit/widgets/btn.dart @@ -0,0 +1,265 @@ +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..f330299 --- /dev/null +++ b/lib/kit/widgets/card.dart @@ -0,0 +1,30 @@ +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..e646fc6 --- /dev/null +++ b/lib/kit/widgets/input.dart @@ -0,0 +1,138 @@ +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..e728530 --- /dev/null +++ b/lib/kit/widgets/loading.dart @@ -0,0 +1,43 @@ +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..070d07b --- /dev/null +++ b/lib/kit/widgets/text.dart @@ -0,0 +1,17 @@ +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..581422f --- /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..1b21760 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,30 +44,27 @@ mixin SettingsPageHelpers on State { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - fl.CenterGreyTitle(section.title), + kit.CenterGreyTitle(section.title), const SizedBox(height: 4), section.child, ], ); } - 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/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/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; 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..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 'package:fl_lib/fl_lib.dart' as fl; 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'; @@ -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,52 @@ 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: () => _launchExternalUri(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 +606,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 +614,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 +642,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 +816,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..4d4fd6a 100644 --- a/lib/utils/logging.dart +++ b/lib/utils/logging.dart @@ -1,8 +1,10 @@ import 'dart:async'; -import 'package:fl_lib/fl_lib.dart'; import 'package:logging/logging.dart'; +import '../kit/core/logger.dart'; +import '../kit/provider/debug.dart'; + Level get defaultLogLevel => Level.INFO; StreamSubscription? _rootLogSubscription; 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