diff --git a/lib/common/widgets/flutter/refresh_indicator.dart b/lib/common/widgets/flutter/refresh_indicator.dart index 1056034a0..68b226ad4 100644 --- a/lib/common/widgets/flutter/refresh_indicator.dart +++ b/lib/common/widgets/flutter/refresh_indicator.dart @@ -12,6 +12,13 @@ import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart' import 'package:flutter/foundation.dart' show clampDouble; import 'package:flutter/material.dart' hide RefreshIndicator; +/// The distance from the child's top or bottom [edgeOffset] where +/// the refresh indicator will settle. During the drag that exposes the refresh +/// indicator, its actual displacement may significantly exceed this value. +/// +/// In most cases, [displacement] distance starts counting from the parent's +/// edges. However, if [edgeOffset] is larger than zero then the [displacement] +/// value is calculated from that offset instead of the parent's edge. double displacement = Pref.refreshDisplacement; // The over-scroll distance that moves the indicator to its maximum @@ -125,7 +132,6 @@ class RefreshIndicator extends StatefulWidget { /// The [semanticsValue] may be used to specify progress on the widget. const RefreshIndicator({ super.key, - this.displacement = 40.0, this.edgeOffset = 0.0, required this.onRefresh, this.color, @@ -145,15 +151,6 @@ class RefreshIndicator extends StatefulWidget { /// Typically a [ListView] or [CustomScrollView]. final Widget child; - /// The distance from the child's top or bottom [edgeOffset] where - /// the refresh indicator will settle. During the drag that exposes the refresh - /// indicator, its actual displacement may significantly exceed this value. - /// - /// In most cases, [displacement] distance starts counting from the parent's - /// edges. However, if [edgeOffset] is larger than zero then the [displacement] - /// value is calculated from that offset instead of the parent's edge. - final double displacement; - /// The offset where [RefreshProgressIndicator] starts to appear on drag start. /// /// Depending whether the indicator is showing on the top or bottom, the value @@ -522,7 +519,7 @@ class RefreshIndicatorState extends State axisAlignment: 1.0, sizeFactor: _positionFactor, // This is what brings it down. child: Padding( - padding: EdgeInsets.only(top: widget.displacement), + padding: EdgeInsets.only(top: displacement), child: Align( alignment: Alignment.topCenter, child: ScaleTransition( @@ -571,18 +568,8 @@ class RefreshIndicatorState extends State } } -Widget refreshIndicator({ - required RefreshCallback onRefresh, - required Widget child, - bool isClampingScrollPhysics = false, -}) { - return RefreshIndicator( - displacement: displacement, - onRefresh: onRefresh, - isClampingScrollPhysics: isClampingScrollPhysics, - child: child, - ); -} +// ignore: camel_case_types +typedef refreshIndicator = RefreshIndicator; class RefreshScrollBehavior extends CustomScrollBehavior { const RefreshScrollBehavior( diff --git a/lib/main.dart b/lib/main.dart index b6b9ebdd0..d05282603 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -250,26 +250,34 @@ class MyApp extends StatelessWidget { } } - @override - Widget build(BuildContext context) { - final dynamicColor = Pref.dynamicColor && _light != null && _dark != null; + static (ThemeData, ThemeData) getAllTheme() { + final dynamicColor = _light != null && _dark != null && Pref.dynamicColor; late final brandColor = colorThemeTypes[Pref.customColor].color; late final variant = Pref.schemeVariant; - return GetMaterialApp( - title: Constants.appName, - theme: ThemeUtils.getThemeData( + return ( + ThemeUtils.getThemeData( colorScheme: dynamicColor ? _light! : brandColor.asColorSchemeSeed(variant, .light), isDynamic: dynamicColor, ), - darkTheme: ThemeUtils.getThemeData( + ThemeUtils.getThemeData( isDark: true, colorScheme: dynamicColor ? _dark! : brandColor.asColorSchemeSeed(variant, .dark), isDynamic: dynamicColor, ), + ); + } + + @override + Widget build(BuildContext context) { + final (light, dark) = getAllTheme(); + return GetMaterialApp( + title: Constants.appName, + theme: light, + darkTheme: dark, themeMode: Pref.themeMode, localizationsDelegates: const [ GlobalCupertinoLocalizations.delegate, diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 826a19847..a241825bc 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -42,7 +42,7 @@ import 'package:PiliPlus/utils/update.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/foundation.dart' show kDebugMode; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide RefreshIndicator; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -972,7 +972,7 @@ Future _showRefreshDragDialog( if (res != null) { kDragContainerExtentPercentage = res; await GStorage.setting.put(SettingBoxKey.refreshDragPercentage, res); - Get.forceAppUpdate(); + setState(); } } @@ -993,7 +993,19 @@ Future _showRefreshDialog( if (res != null) { displacement = res; await GStorage.setting.put(SettingBoxKey.refreshDisplacement, res); - Get.forceAppUpdate(); + if (WidgetsBinding.instance.rootElement case final context?) { + context.visitChildElements(_visitor); + } + setState(); + } +} + +void _visitor(Element context) { + if (!context.mounted) return; + if (context.widget is RefreshIndicator) { + context.markNeedsBuild(); + } else { + context.visitChildren(_visitor); } } diff --git a/lib/pages/setting/models/style_settings.dart b/lib/pages/setting/models/style_settings.dart index 834f82c65..92e450944 100644 --- a/lib/pages/setting/models/style_settings.dart +++ b/lib/pages/setting/models/style_settings.dart @@ -26,6 +26,7 @@ import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; import 'package:PiliPlus/pages/setting/widgets/slider_dialog.dart'; import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/utils/extension/file_ext.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/extension/num_ext.dart'; import 'package:PiliPlus/utils/extension/theme_ext.dart'; import 'package:PiliPlus/utils/global_data.dart'; @@ -88,7 +89,7 @@ List get styleSettings => [ setKey: SettingBoxKey.appFontWeight, defaultVal: false, leading: const Icon(Icons.text_fields), - onChanged: (value) => Get.forceAppUpdate(), + onChanged: (_) => Get.updateMyAppTheme(), onTap: _showFontWeightDialog, ), NormalModel( @@ -132,7 +133,7 @@ List get styleSettings => [ defaultVal: false, onChanged: (value) { if (value && MyApp.darkThemeData == null) { - Get.forceAppUpdate(); + Get.updateMyAppTheme(); } }, ), @@ -279,7 +280,7 @@ List get styleSettings => [ defaultVal: false, onChanged: (value) { if (Get.isDarkMode || Pref.darkVideoPage) { - Get.forceAppUpdate(); + Get.updateMyAppTheme(); } }, ), @@ -634,7 +635,7 @@ Future _showFontWeightDialog(BuildContext context) async { ); if (res != null) { await GStorage.setting.put(SettingBoxKey.appFontWeight, res.toInt() - 1); - Get.forceAppUpdate(); + Get.updateMyAppTheme(); } } diff --git a/lib/pages/setting/pages/color_select.dart b/lib/pages/setting/pages/color_select.dart index c62396c09..3bb7476bf 100644 --- a/lib/pages/setting/pages/color_select.dart +++ b/lib/pages/setting/pages/color_select.dart @@ -9,6 +9,7 @@ import 'package:PiliPlus/pages/home/view.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/pages/setting/widgets/popup_item.dart'; import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/extension/theme_ext.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; @@ -17,7 +18,6 @@ import 'package:flex_seed_scheme/flex_seed_scheme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:hive/hive.dart'; class ColorSelectPage extends StatefulWidget { const ColorSelectPage({super.key}); @@ -44,19 +44,13 @@ class _ColorSelectPageState extends State { Future _onChanged([bool? val]) async { val ??= !ctr.dynamicColor.value; - if (val) { - if (await MyApp.initPlatformState()) { - Get.forceAppUpdate(); - } else { - SmartDialog.showToast('该设备可能不支持动态取色'); - return; - } - } else { - Get.forceAppUpdate(); + if (val && !await MyApp.initPlatformState()) { + SmartDialog.showToast('设备可能不支持动态取色'); + return; } - ctr - ..dynamicColor.value = val - ..setting.put(SettingBoxKey.dynamicColor, val); + ctr.dynamicColor.value = val; + await GStorage.setting.put(SettingBoxKey.dynamicColor, val); + Get.updateMyAppTheme(); } @override @@ -117,8 +111,9 @@ class _ColorSelectPageState extends State { .toList(), onSelected: (value, setState) { _dynamicSchemeVariant = value; - GStorage.setting.put(SettingBoxKey.schemeVariant, value.index); - Get.forceAppUpdate(); + GStorage.setting + .put(SettingBoxKey.schemeVariant, value.index) + .whenComplete(Get.updateMyAppTheme); }, ), ), @@ -131,10 +126,7 @@ class _ColorSelectPageState extends State { value: ctr.dynamicColor.value, onChanged: _onChanged, materialTapTargetSize: .shrinkWrap, - visualDensity: const VisualDensity( - horizontal: -4, - vertical: -4, - ), + visualDensity: const .new(horizontal: -4, vertical: -4), ), ), onTap: _onChanged, @@ -162,13 +154,10 @@ class _ColorSelectPageState extends State { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - ctr - ..currentColor.value = index - ..setting.put( - SettingBoxKey.customColor, - index, - ); - Get.forceAppUpdate(); + ctr.currentColor.value = index; + GStorage.setting + .put(SettingBoxKey.customColor, index) + .whenComplete(Get.updateMyAppTheme); }, child: Column( spacing: 3, @@ -236,6 +225,4 @@ class _ColorSelectController extends GetxController { final RxBool dynamicColor = Pref.dynamicColor.obs; final RxInt currentColor = Pref.customColor.obs; final Rx themeType = Pref.themeType.obs; - - Box get setting => GStorage.setting; } diff --git a/lib/utils/extension/get_ext.dart b/lib/utils/extension/get_ext.dart index b2a94aeb6..01639b3cb 100644 --- a/lib/utils/extension/get_ext.dart +++ b/lib/utils/extension/get_ext.dart @@ -1,6 +1,15 @@ +import 'package:PiliPlus/main.dart'; import 'package:get/get.dart'; extension GetExt on GetInterface { S putOrFind(InstanceBuilderCallback dep, {String? tag}) => GetInstance().putOrFind(dep, tag: tag); + + void updateMyAppTheme() { + final (l, d) = MyApp.getAllTheme(); + rootController + ..theme = l + ..darkTheme = d + ..update(); + } }