From 12be81d93b226f7cfe8f83b761e823b2532030ed Mon Sep 17 00:00:00 2001 From: Anton Stubenbord Date: Thu, 16 Nov 2023 23:44:02 +0100 Subject: [PATCH] feat: add accessibility setting and conditionally disable animations --- .../metadata/android/de-DE/changelogs/58.txt | 1 + .../metadata/android/en-US/changelogs/58.txt | 1 + lib/accessibility/accessibility_utils.dart | 89 +++++++++++++++++++ lib/accessibility/accessible_page.dart | 58 ++++++++++++ lib/core/database/tables/global_settings.dart | 4 + .../notifier/go_router_refresh_stream.dart | 20 +++++ lib/core/widgets/hint_card.dart | 4 +- lib/features/app_drawer/view/app_drawer.dart | 5 +- .../changelogs/view/changelog_dialog.dart | 1 + .../view/pages/document_details_page.dart | 5 +- .../view/document_edit_page.dart | 4 +- .../view/document_search_page.dart | 3 +- .../view/widgets/document_preview.dart | 3 +- .../widgets/saved_views/saved_view_chip.dart | 4 +- .../saved_views/saved_views_widget.dart | 5 +- lib/features/settings/view/settings_page.dart | 3 + .../widgets/disable_animations_setting.dart | 23 +++++ lib/main.dart | 89 ++++++++++--------- .../routes/shells/authenticated_route.dart | 52 ++++++----- .../animated_touch_bubble_part.dart | 5 +- pubspec.yaml | 2 +- 21 files changed, 304 insertions(+), 77 deletions(-) create mode 100644 android/fastlane/metadata/android/de-DE/changelogs/58.txt create mode 100644 android/fastlane/metadata/android/en-US/changelogs/58.txt create mode 100644 lib/accessibility/accessibility_utils.dart create mode 100644 lib/accessibility/accessible_page.dart create mode 100644 lib/core/notifier/go_router_refresh_stream.dart create mode 100644 lib/features/settings/view/widgets/disable_animations_setting.dart diff --git a/android/fastlane/metadata/android/de-DE/changelogs/58.txt b/android/fastlane/metadata/android/de-DE/changelogs/58.txt new file mode 100644 index 0000000..da37e28 --- /dev/null +++ b/android/fastlane/metadata/android/de-DE/changelogs/58.txt @@ -0,0 +1 @@ +* Neue Einstellung um Animationen zu deaktivieren \ No newline at end of file diff --git a/android/fastlane/metadata/android/en-US/changelogs/58.txt b/android/fastlane/metadata/android/en-US/changelogs/58.txt new file mode 100644 index 0000000..5a8e3fa --- /dev/null +++ b/android/fastlane/metadata/android/en-US/changelogs/58.txt @@ -0,0 +1 @@ +* Add setting to disable animations \ No newline at end of file diff --git a/lib/accessibility/accessibility_utils.dart b/lib/accessibility/accessibility_utils.dart new file mode 100644 index 0000000..955a89c --- /dev/null +++ b/lib/accessibility/accessibility_utils.dart @@ -0,0 +1,89 @@ +import 'dart:ui'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:hive/hive.dart'; +import 'package:paperless_mobile/core/database/hive/hive_config.dart'; +import 'package:paperless_mobile/core/database/hive/hive_extensions.dart'; +import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart'; +import 'package:paperless_mobile/routing/navigation_keys.dart'; + +extension AccessibilityAwareAnimationDurationExtension on Duration { + Duration accessible() { + bool shouldDisableAnimations = WidgetsBinding.instance.disableAnimations || + Hive.globalSettingsBox.getValue()!.disableAnimations; + // print(shouldDisableAnimations); + if (shouldDisableAnimations) { + return 0.seconds; + } + return this; + } +} + +extension AccessibleHero on Hero { + Widget accessible() { + return GlobalSettingsBuilder( + builder: (context, settings) { + return HeroMode( + enabled: WidgetsBinding.instance.disableAnimations || + !settings.disableAnimations, + child: this, + ); + }, + ); + // bool shouldDisableAnimations = WidgetsBinding.instance.disableAnimations || + // Hive.globalSettingsBox.getValue()!.disableAnimations; + // return _AccessibilityAwareObserverWidget( + // accessibilityAwareBuilder: (context, accessibilityFeatures) { + // return HeroMode( + // enabled: !accessibilityFeatures.disableAnimations, + // child: this, + // ); + // }, + // ); + } +} + +class _AccessibilityAwareObserverWidget extends StatefulWidget { + final Widget Function( + BuildContext context, + AccessibilityFeatures accessibilityFeatures, + ) accessibilityAwareBuilder; + const _AccessibilityAwareObserverWidget({ + super.key, + required this.accessibilityAwareBuilder, + }); + + @override + State<_AccessibilityAwareObserverWidget> createState() => + _AccessibilityAwareObserverWidgetState(); +} + +class _AccessibilityAwareObserverWidgetState + extends State<_AccessibilityAwareObserverWidget> + with WidgetsBindingObserver { + late final AccessibilityFeatures _accessibilityFeatures; + + @override + void initState() { + super.initState(); + _accessibilityFeatures = WidgetsBinding.instance.accessibilityFeatures; + } + + @override + void didChangeAccessibilityFeatures() { + super.didChangeAccessibilityFeatures(); + setState(() { + _accessibilityFeatures = WidgetsBinding.instance.accessibilityFeatures; + }); + print("Accessibility features changed"); + } + + @override + Widget build(BuildContext context) { + return widget.accessibilityAwareBuilder( + context, + _accessibilityFeatures, + ); + } +} diff --git a/lib/accessibility/accessible_page.dart b/lib/accessibility/accessible_page.dart new file mode 100644 index 0000000..dca8ea2 --- /dev/null +++ b/lib/accessibility/accessible_page.dart @@ -0,0 +1,58 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:go_router/go_router.dart'; +import 'package:hive/hive.dart'; +import 'package:paperless_mobile/core/database/hive/hive_config.dart'; +import 'package:paperless_mobile/core/database/hive/hive_extensions.dart'; + +Page accessiblePlatformPage({ + required Widget child, + String? name, + Object? arguments, + String? restorationId, + LocalKey? key, + bool allowSnapshotting = true, + bool fullscreenDialog = false, + bool maintainState = true, + String? title, +}) { + final shouldDisableAnimations = WidgetsBinding.instance.disableAnimations || + Hive.globalSettingsBox.getValue()!.disableAnimations; + if (shouldDisableAnimations) { + return NoTransitionPage( + key: key, + name: name, + arguments: arguments, + restorationId: restorationId, + child: child, + ); + } + if (Platform.isAndroid) { + return MaterialPage( + child: child, + name: name, + restorationId: restorationId, + arguments: arguments, + allowSnapshotting: allowSnapshotting, + fullscreenDialog: fullscreenDialog, + key: key, + maintainState: maintainState, + ); + } else if (Platform.isIOS) { + return CupertinoPage( + child: child, + allowSnapshotting: allowSnapshotting, + arguments: arguments, + fullscreenDialog: fullscreenDialog, + key: key, + maintainState: maintainState, + name: name, + restorationId: restorationId, + title: title, + ); + } + throw UnsupportedError("The current platform is not supported."); +} diff --git a/lib/core/database/tables/global_settings.dart b/lib/core/database/tables/global_settings.dart index fbaf73b..094406a 100644 --- a/lib/core/database/tables/global_settings.dart +++ b/lib/core/database/tables/global_settings.dart @@ -35,6 +35,9 @@ class GlobalSettings with HiveObjectMixin { @HiveField(8, defaultValue: false) bool skipDocumentPreprarationOnUpload; + @HiveField(9, defaultValue: false) + bool disableAnimations; + GlobalSettings({ required this.preferredLocaleSubtag, this.preferredThemeMode = ThemeMode.system, @@ -45,5 +48,6 @@ class GlobalSettings with HiveObjectMixin { this.defaultShareType = FileDownloadType.alwaysAsk, this.enforceSinglePagePdfUpload = false, this.skipDocumentPreprarationOnUpload = false, + this.disableAnimations = false, }); } diff --git a/lib/core/notifier/go_router_refresh_stream.dart b/lib/core/notifier/go_router_refresh_stream.dart new file mode 100644 index 0000000..6793c13 --- /dev/null +++ b/lib/core/notifier/go_router_refresh_stream.dart @@ -0,0 +1,20 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +class GoRouterRefreshStream extends ChangeNotifier { + GoRouterRefreshStream(Stream stream) { + notifyListeners(); + _subscription = stream.asBroadcastStream().listen( + (dynamic _) => notifyListeners(), + ); + } + + late final StreamSubscription _subscription; + + @override + void dispose() { + _subscription.cancel(); + super.dispose(); + } +} diff --git a/lib/core/widgets/hint_card.dart b/lib/core/widgets/hint_card.dart index 3f3583e..195473f 100644 --- a/lib/core/widgets/hint_card.dart +++ b/lib/core/widgets/hint_card.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_animate/flutter_animate.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; @@ -24,7 +26,7 @@ class HintCard extends StatelessWidget { crossFadeState: show ? CrossFadeState.showFirst : CrossFadeState.showSecond, secondChild: const SizedBox.shrink(), - duration: const Duration(milliseconds: 500), + duration: 500.milliseconds.accessible(), firstChild: Card( elevation: elevation, child: Column( diff --git a/lib/features/app_drawer/view/app_drawer.dart b/lib/features/app_drawer/view/app_drawer.dart index 9f5e047..7439b35 100644 --- a/lib/features/app_drawer/view/app_drawer.dart +++ b/lib/features/app_drawer/view/app_drawer.dart @@ -164,7 +164,10 @@ class AppDrawer extends StatelessWidget { return child; } return child - .animate(onPlay: (c) => c.repeat(reverse: true)) + .animate( + onPlay: (c) => c.repeat(reverse: true), + autoPlay: !MediaQuery.disableAnimationsOf(context), + ) .fade(duration: 1.seconds, begin: 1, end: 0.3); }, ), diff --git a/lib/features/changelogs/view/changelog_dialog.dart b/lib/features/changelogs/view/changelog_dialog.dart index 7eee480..9e1da1f 100644 --- a/lib/features/changelogs/view/changelog_dialog.dart +++ b/lib/features/changelogs/view/changelog_dialog.dart @@ -63,6 +63,7 @@ class ChangelogDialog extends StatelessWidget { } const _versionNumbers = { + "58": "3.1.4", "57": "3.1.3", "56": "3.1.2", "55": "3.1.1", diff --git a/lib/features/document_details/view/pages/document_details_page.dart b/lib/features/document_details/view/pages/document_details_page.dart index fa483d1..0d0d92b 100644 --- a/lib/features/document_details/view/pages/document_details_page.dart +++ b/lib/features/document_details/view/pages/document_details_page.dart @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:open_filex/open_filex.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; @@ -60,6 +61,8 @@ class _DocumentDetailsPageState extends State { @override Widget build(BuildContext context) { + final disableAnimations = MediaQuery.disableAnimationsOf(context); + debugPrint(disableAnimations.toString()); final hasMultiUserSupport = context.watch().hasMultiUserSupport; final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0); @@ -150,7 +153,7 @@ class _DocumentDetailsPageState extends State { ], ), ), - ); + ).accessible(); }, ), ), diff --git a/lib/features/document_edit/view/document_edit_page.dart b/lib/features/document_edit/view/document_edit_page.dart index 3821cd9..a3d0d10 100644 --- a/lib/features/document_edit/view/document_edit_page.dart +++ b/lib/features/document_edit/view/document_edit_page.dart @@ -50,8 +50,8 @@ class _DocumentEditPageState extends State late final Animation _animation; @override - void initState() { - super.initState(); + void didChangeDependencies() { + super.didChangeDependencies(); _animationController = AnimationController( duration: const Duration(milliseconds: 150), vsync: this, diff --git a/lib/features/document_search/view/document_search_page.dart b/lib/features/document_search/view/document_search_page.dart index d555189..8cfe04c 100644 --- a/lib/features/document_search/view/document_search_page.dart +++ b/lib/features/document_search/view/document_search_page.dart @@ -4,6 +4,7 @@ import 'dart:math' as math; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/core/extensions/document_extensions.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart'; @@ -67,7 +68,7 @@ class _DocumentSearchPageState extends State { context.read().search(query); }, ), - ), + ).accessible(), actions: [ IconButton( color: theme.colorScheme.onSurfaceVariant, diff --git a/lib/features/documents/view/widgets/document_preview.dart b/lib/features/documents/view/widgets/document_preview.dart index da9f542..6884dae 100644 --- a/lib/features/documents/view/widgets/document_preview.dart +++ b/lib/features/documents/view/widgets/document_preview.dart @@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/helpers/connectivity_aware_action_wrapper.dart'; import 'package:paperless_mobile/routing/routes/documents_route.dart'; import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart'; @@ -46,7 +47,7 @@ class DocumentPreview extends StatelessWidget { return Hero( tag: "thumb_$documentId", child: _buildPreview(context), - ); + ).accessible(); } return _buildPreview(context); }), diff --git a/lib/features/documents/view/widgets/saved_views/saved_view_chip.dart b/lib/features/documents/view/widgets/saved_views/saved_view_chip.dart index 08103b6..aea8c96 100644 --- a/lib/features/documents/view/widgets/saved_views/saved_view_chip.dart +++ b/lib/features/documents/view/widgets/saved_views/saved_view_chip.dart @@ -1,7 +1,9 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/routing/routes/saved_views_route.dart'; import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart'; @@ -38,7 +40,7 @@ class _SavedViewChipState extends State super.initState(); _animationController = AnimationController( vsync: this, - duration: const Duration(milliseconds: 200), + duration: const Duration(milliseconds: 200).accessible(), ); _animation = _animationController.drive(Tween(begin: 0, end: 1)); } diff --git a/lib/features/documents/view/widgets/saved_views/saved_views_widget.dart b/lib/features/documents/view/widgets/saved_views/saved_views_widget.dart index aae2c33..c7d3bb2 100644 --- a/lib/features/documents/view/widgets/saved_views/saved_views_widget.dart +++ b/lib/features/documents/view/widgets/saved_views/saved_views_widget.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:paperless_api/paperless_api.dart'; -import 'package:paperless_mobile/core/widgets/shimmer_placeholder.dart'; +import 'package:paperless_mobile/accessibility/accessibility_utils.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; +import 'package:paperless_mobile/core/widgets/shimmer_placeholder.dart'; import 'package:paperless_mobile/features/documents/view/widgets/saved_views/saved_view_chip.dart'; import 'package:paperless_mobile/features/saved_view/cubit/saved_view_cubit.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; @@ -41,7 +42,7 @@ class _SavedViewsWidgetState extends State super.initState(); _animationController = AnimationController( vsync: this, - duration: const Duration(milliseconds: 200), + duration: const Duration(milliseconds: 200).accessible(), ); _animation = _animationController.drive(Tween(begin: 0, end: 0.5)); } diff --git a/lib/features/settings/view/settings_page.dart b/lib/features/settings/view/settings_page.dart index 9f01e07..2b43ca8 100644 --- a/lib/features/settings/view/settings_page.dart +++ b/lib/features/settings/view/settings_page.dart @@ -7,6 +7,7 @@ import 'package:paperless_mobile/features/settings/view/widgets/clear_storage_se import 'package:paperless_mobile/features/settings/view/widgets/color_scheme_option_setting.dart'; import 'package:paperless_mobile/features/settings/view/widgets/default_download_file_type_setting.dart'; import 'package:paperless_mobile/features/settings/view/widgets/default_share_file_type_setting.dart'; +import 'package:paperless_mobile/features/settings/view/widgets/disable_animations_setting.dart'; import 'package:paperless_mobile/features/settings/view/widgets/enforce_pdf_upload_setting.dart'; import 'package:paperless_mobile/features/settings/view/widgets/language_selection_setting.dart'; import 'package:paperless_mobile/features/settings/view/widgets/skip_document_prepraration_on_share_setting.dart'; @@ -39,6 +40,8 @@ class SettingsPage extends StatelessWidget { const SkipDocumentPreprationOnShareSetting(), _buildSectionHeader(context, S.of(context)!.storage), const ClearCacheSetting(), + _buildSectionHeader(context, 'Accessibility'), + const DisableAnimationsSetting(), _buildSectionHeader(context, S.of(context)!.misc), const AppLogsTile(), const ChangelogsTile(), diff --git a/lib/features/settings/view/widgets/disable_animations_setting.dart b/lib/features/settings/view/widgets/disable_animations_setting.dart new file mode 100644 index 0000000..c638995 --- /dev/null +++ b/lib/features/settings/view/widgets/disable_animations_setting.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart'; +import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; + +class DisableAnimationsSetting extends StatelessWidget { + const DisableAnimationsSetting({super.key}); + + @override + Widget build(BuildContext context) { + return GlobalSettingsBuilder(builder: (context, settings) { + return SwitchListTile( + value: settings.disableAnimations, + title: Text('Disable animations'), + subtitle: Text('Disables page transitions and most animations.' + ' Temporary workaround until system accessibility settings can be used.'), + onChanged: (val) async { + settings.disableAnimations = val; + settings.save(); + }, + ); + }); + } +} diff --git a/lib/main.dart b/lib/main.dart index e657389..6e91739 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,6 +19,7 @@ import 'package:local_auth/local_auth.dart'; import 'package:logger/logger.dart' as l; import 'package:package_info_plus/package_info_plus.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/accessibility/accessible_page.dart'; import 'package:paperless_mobile/constants.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; import 'package:paperless_mobile/core/database/hive/hive_config.dart'; @@ -29,6 +30,7 @@ import 'package:paperless_mobile/core/exception/server_message_exception.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory.dart'; import 'package:paperless_mobile/core/factory/paperless_api_factory_impl.dart'; import 'package:paperless_mobile/core/interceptor/language_header.interceptor.dart'; +import 'package:paperless_mobile/core/notifier/go_router_refresh_stream.dart'; import 'package:paperless_mobile/features/logging/data/formatted_printer.dart'; import 'package:paperless_mobile/features/logging/data/logger.dart'; import 'package:paperless_mobile/features/logging/data/mirrored_file_output.dart'; @@ -249,7 +251,7 @@ void main() async { _ => null }; logger.fe( - "An unexpected error occurred${message != null ? "- $message" : ""}", + "An unexpected error occurred ${message != null ? "- $message" : ""}", error: message == null ? error : null, methodName: "main", stackTrace: stackTrace, @@ -301,47 +303,50 @@ class _GoRouterShellState extends State { initialLocation: "/login", routes: [ ShellRoute( - builder: (context, state, child) { - return Provider.value( - value: widget.apiFactory, - child: BlocListener( - listener: (context, state) { - switch (state) { - case UnauthenticatedState( - redirectToAccountSelection: var shouldRedirect - ): - if (shouldRedirect) { - const LoginToExistingAccountRoute().go(context); - } else { - const LoginRoute().go(context); - } - break; - case RestoringSessionState(): - const RestoringSessionRoute().go(context); - break; - case VerifyIdentityState(userId: var userId): - VerifyIdentityRoute(userId: userId).go(context); - break; - case SwitchingAccountsState(): - const SwitchingAccountsRoute().push(context); - break; - case AuthenticatedState(): - const LandingRoute().go(context); - break; - case AuthenticatingState state: - AuthenticatingRoute(state.currentStage.name).push(context); - break; - case LoggingOutState(): - const LoggingOutRoute().go(context); - break; - case AuthenticationErrorState(): - if (context.canPop()) { - context.pop(); - } - break; - } - }, - child: child, + pageBuilder: (context, state, child) { + return accessiblePlatformPage( + child: Provider.value( + value: widget.apiFactory, + child: BlocListener( + listener: (context, state) { + switch (state) { + case UnauthenticatedState( + redirectToAccountSelection: var shouldRedirect + ): + if (shouldRedirect) { + const LoginToExistingAccountRoute().go(context); + } else { + const LoginRoute().go(context); + } + break; + case RestoringSessionState(): + const RestoringSessionRoute().go(context); + break; + case VerifyIdentityState(userId: var userId): + VerifyIdentityRoute(userId: userId).go(context); + break; + case SwitchingAccountsState(): + const SwitchingAccountsRoute().push(context); + break; + case AuthenticatedState(): + const LandingRoute().go(context); + break; + case AuthenticatingState state: + AuthenticatingRoute(state.currentStage.name) + .push(context); + break; + case LoggingOutState(): + const LoggingOutRoute().go(context); + break; + case AuthenticationErrorState(): + if (context.canPop()) { + context.pop(); + } + break; + } + }, + child: child, + ), ), ); }, diff --git a/lib/routing/routes/shells/authenticated_route.dart b/lib/routing/routes/shells/authenticated_route.dart index 136932f..feed381 100644 --- a/lib/routing/routes/shells/authenticated_route.dart +++ b/lib/routing/routes/shells/authenticated_route.dart @@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart'; import 'package:go_router/go_router.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:paperless_api/paperless_api.dart'; +import 'package:paperless_mobile/accessibility/accessible_page.dart'; import 'package:paperless_mobile/core/database/hive/hive_config.dart'; import 'package:paperless_mobile/core/database/tables/global_settings.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; @@ -141,32 +142,39 @@ class AuthenticatedRoute extends ShellRouteData { const AuthenticatedRoute(); @override - Widget builder( + Page pageBuilder( BuildContext context, GoRouterState state, Widget navigator, ) { - final currentUserId = Hive.box(HiveBoxes.globalSettings) - .getValue()! - .loggedInUserId; - if (currentUserId == null) { - return const SizedBox.shrink(); - } - final authenticatedUser = - Hive.box(HiveBoxes.localUserAccount).get( - currentUserId, - )!; - final apiFactory = context.read(); - return HomeShellWidget( - localUserId: authenticatedUser.id, - paperlessApiVersion: authenticatedUser.apiVersion, - paperlessProviderFactory: apiFactory, - child: ChangeNotifierProvider( - create: (context) => ConsumptionChangeNotifier() - ..loadFromConsumptionDirectory(userId: currentUserId), - child: EventListenerShell( - child: navigator, - ), + return accessiblePlatformPage( + child: Builder( + builder: (context) { + final currentUserId = + Hive.box(HiveBoxes.globalSettings) + .getValue()! + .loggedInUserId; + if (currentUserId == null) { + return const SizedBox.shrink(); + } + final authenticatedUser = + Hive.box(HiveBoxes.localUserAccount).get( + currentUserId, + )!; + final apiFactory = context.read(); + return HomeShellWidget( + localUserId: authenticatedUser.id, + paperlessApiVersion: authenticatedUser.apiVersion, + paperlessProviderFactory: apiFactory, + child: ChangeNotifierProvider( + create: (context) => ConsumptionChangeNotifier() + ..loadFromConsumptionDirectory(userId: currentUserId), + child: EventListenerShell( + child: navigator, + ), + ), + ); + }, ), ); } diff --git a/packages/paperless_document_scanner/example/lib/edge_detection_shape/animated_touch_bubble_part.dart b/packages/paperless_document_scanner/example/lib/edge_detection_shape/animated_touch_bubble_part.dart index d80aabc..778f515 100644 --- a/packages/paperless_document_scanner/example/lib/edge_detection_shape/animated_touch_bubble_part.dart +++ b/packages/paperless_document_scanner/example/lib/edge_detection_shape/animated_touch_bubble_part.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; class AnimatedTouchBubblePart extends StatefulWidget { - const AnimatedTouchBubblePart({super.key, + const AnimatedTouchBubblePart({ + super.key, required this.dragging, required this.size, }); @@ -22,6 +23,7 @@ class _AnimatedTouchBubblePartState extends State @override void didChangeDependencies() { + super.didChangeDependencies(); _controller = AnimationController( duration: const Duration(milliseconds: 1000), vsync: this, @@ -40,7 +42,6 @@ class _AnimatedTouchBubblePartState extends State ); _controller.repeat(); - super.didChangeDependencies(); } @override diff --git a/pubspec.yaml b/pubspec.yaml index b67b3eb..a5a113f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.1.3+57 +version: 3.1.4+58 environment: sdk: ">=3.0.0 <4.0.0"