feat: add accessibility setting and conditionally disable animations

This commit is contained in:
Anton Stubenbord
2023-11-16 23:44:02 +01:00
parent a17f658df5
commit 12be81d93b
21 changed files with 304 additions and 77 deletions

View File

@@ -0,0 +1 @@
* Neue Einstellung um Animationen zu deaktivieren

View File

@@ -0,0 +1 @@
* Add setting to disable animations

View File

@@ -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,
);
}
}

View File

@@ -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<T> accessiblePlatformPage<T>({
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.");
}

View File

@@ -35,6 +35,9 @@ class GlobalSettings with HiveObjectMixin {
@HiveField(8, defaultValue: false) @HiveField(8, defaultValue: false)
bool skipDocumentPreprarationOnUpload; bool skipDocumentPreprarationOnUpload;
@HiveField(9, defaultValue: false)
bool disableAnimations;
GlobalSettings({ GlobalSettings({
required this.preferredLocaleSubtag, required this.preferredLocaleSubtag,
this.preferredThemeMode = ThemeMode.system, this.preferredThemeMode = ThemeMode.system,
@@ -45,5 +48,6 @@ class GlobalSettings with HiveObjectMixin {
this.defaultShareType = FileDownloadType.alwaysAsk, this.defaultShareType = FileDownloadType.alwaysAsk,
this.enforceSinglePagePdfUpload = false, this.enforceSinglePagePdfUpload = false,
this.skipDocumentPreprarationOnUpload = false, this.skipDocumentPreprarationOnUpload = false,
this.disableAnimations = false,
}); });
} }

View File

@@ -0,0 +1,20 @@
import 'dart:async';
import 'package:flutter/widgets.dart';
class GoRouterRefreshStream extends ChangeNotifier {
GoRouterRefreshStream(Stream<dynamic> stream) {
notifyListeners();
_subscription = stream.asBroadcastStream().listen(
(dynamic _) => notifyListeners(),
);
}
late final StreamSubscription<dynamic> _subscription;
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}

View File

@@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; 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/core/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
@@ -24,7 +26,7 @@ class HintCard extends StatelessWidget {
crossFadeState: crossFadeState:
show ? CrossFadeState.showFirst : CrossFadeState.showSecond, show ? CrossFadeState.showFirst : CrossFadeState.showSecond,
secondChild: const SizedBox.shrink(), secondChild: const SizedBox.shrink(),
duration: const Duration(milliseconds: 500), duration: 500.milliseconds.accessible(),
firstChild: Card( firstChild: Card(
elevation: elevation, elevation: elevation,
child: Column( child: Column(

View File

@@ -164,7 +164,10 @@ class AppDrawer extends StatelessWidget {
return child; return child;
} }
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); .fade(duration: 1.seconds, begin: 1, end: 0.3);
}, },
), ),

View File

@@ -63,6 +63,7 @@ class ChangelogDialog extends StatelessWidget {
} }
const _versionNumbers = { const _versionNumbers = {
"58": "3.1.4",
"57": "3.1.3", "57": "3.1.3",
"56": "3.1.2", "56": "3.1.2",
"55": "3.1.1", "55": "3.1.1",

View File

@@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/date_symbol_data_local.dart';
import 'package:open_filex/open_filex.dart'; import 'package:open_filex/open_filex.dart';
import 'package:paperless_api/paperless_api.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/bloc/connectivity_cubit.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
@@ -60,6 +61,8 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final disableAnimations = MediaQuery.disableAnimationsOf(context);
debugPrint(disableAnimations.toString());
final hasMultiUserSupport = final hasMultiUserSupport =
context.watch<LocalUserAccount>().hasMultiUserSupport; context.watch<LocalUserAccount>().hasMultiUserSupport;
final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0); final tabLength = 4 + (hasMultiUserSupport && false ? 1 : 0);
@@ -150,7 +153,7 @@ class _DocumentDetailsPageState extends State<DocumentDetailsPage> {
], ],
), ),
), ),
); ).accessible();
}, },
), ),
), ),

View File

@@ -50,8 +50,8 @@ class _DocumentEditPageState extends State<DocumentEditPage>
late final Animation<double> _animation; late final Animation<double> _animation;
@override @override
void initState() { void didChangeDependencies() {
super.initState(); super.didChangeDependencies();
_animationController = AnimationController( _animationController = AnimationController(
duration: const Duration(milliseconds: 150), duration: const Duration(milliseconds: 150),
vsync: this, vsync: this,

View File

@@ -4,6 +4,7 @@ import 'dart:math' as math;
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/document_extensions.dart';
import 'package:paperless_mobile/core/extensions/flutter_extensions.dart'; import 'package:paperless_mobile/core/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart'; import 'package:paperless_mobile/features/document_search/cubit/document_search_cubit.dart';
@@ -67,7 +68,7 @@ class _DocumentSearchPageState extends State<DocumentSearchPage> {
context.read<DocumentSearchCubit>().search(query); context.read<DocumentSearchCubit>().search(query);
}, },
), ),
), ).accessible(),
actions: [ actions: [
IconButton( IconButton(
color: theme.colorScheme.onSurfaceVariant, color: theme.colorScheme.onSurfaceVariant,

View File

@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:paperless_api/paperless_api.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/helpers/connectivity_aware_action_wrapper.dart';
import 'package:paperless_mobile/routing/routes/documents_route.dart'; import 'package:paperless_mobile/routing/routes/documents_route.dart';
import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart'; import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart';
@@ -46,7 +47,7 @@ class DocumentPreview extends StatelessWidget {
return Hero( return Hero(
tag: "thumb_$documentId", tag: "thumb_$documentId",
child: _buildPreview(context), child: _buildPreview(context),
); ).accessible();
} }
return _buildPreview(context); return _buildPreview(context);
}), }),

View File

@@ -1,7 +1,9 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:paperless_api/paperless_api.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/core/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/routing/routes/saved_views_route.dart'; import 'package:paperless_mobile/routing/routes/saved_views_route.dart';
import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart'; import 'package:paperless_mobile/routing/routes/shells/authenticated_route.dart';
@@ -38,7 +40,7 @@ class _SavedViewChipState extends State<SavedViewChip>
super.initState(); super.initState();
_animationController = AnimationController( _animationController = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200).accessible(),
); );
_animation = _animationController.drive(Tween(begin: 0, end: 1)); _animation = _animationController.drive(Tween(begin: 0, end: 1));
} }

View File

@@ -1,8 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:paperless_api/paperless_api.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/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/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/features/saved_view/cubit/saved_view_cubit.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart'; import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
@@ -41,7 +42,7 @@ class _SavedViewsWidgetState extends State<SavedViewsWidget>
super.initState(); super.initState();
_animationController = AnimationController( _animationController = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200).accessible(),
); );
_animation = _animationController.drive(Tween(begin: 0, end: 0.5)); _animation = _animationController.drive(Tween(begin: 0, end: 0.5));
} }

View File

@@ -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/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_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/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/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/language_selection_setting.dart';
import 'package:paperless_mobile/features/settings/view/widgets/skip_document_prepraration_on_share_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(), const SkipDocumentPreprationOnShareSetting(),
_buildSectionHeader(context, S.of(context)!.storage), _buildSectionHeader(context, S.of(context)!.storage),
const ClearCacheSetting(), const ClearCacheSetting(),
_buildSectionHeader(context, 'Accessibility'),
const DisableAnimationsSetting(),
_buildSectionHeader(context, S.of(context)!.misc), _buildSectionHeader(context, S.of(context)!.misc),
const AppLogsTile(), const AppLogsTile(),
const ChangelogsTile(), const ChangelogsTile(),

View File

@@ -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();
},
);
});
}
}

View File

@@ -19,6 +19,7 @@ import 'package:local_auth/local_auth.dart';
import 'package:logger/logger.dart' as l; import 'package:logger/logger.dart' as l;
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:paperless_api/paperless_api.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/constants.dart';
import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart'; import 'package:paperless_mobile/core/bloc/connectivity_cubit.dart';
import 'package:paperless_mobile/core/database/hive/hive_config.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.dart';
import 'package:paperless_mobile/core/factory/paperless_api_factory_impl.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/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/formatted_printer.dart';
import 'package:paperless_mobile/features/logging/data/logger.dart'; import 'package:paperless_mobile/features/logging/data/logger.dart';
import 'package:paperless_mobile/features/logging/data/mirrored_file_output.dart'; import 'package:paperless_mobile/features/logging/data/mirrored_file_output.dart';
@@ -249,7 +251,7 @@ void main() async {
_ => null _ => null
}; };
logger.fe( logger.fe(
"An unexpected error occurred${message != null ? "- $message" : ""}", "An unexpected error occurred ${message != null ? "- $message" : ""}",
error: message == null ? error : null, error: message == null ? error : null,
methodName: "main", methodName: "main",
stackTrace: stackTrace, stackTrace: stackTrace,
@@ -301,47 +303,50 @@ class _GoRouterShellState extends State<GoRouterShell> {
initialLocation: "/login", initialLocation: "/login",
routes: [ routes: [
ShellRoute( ShellRoute(
builder: (context, state, child) { pageBuilder: (context, state, child) {
return Provider.value( return accessiblePlatformPage(
value: widget.apiFactory, child: Provider.value(
child: BlocListener<AuthenticationCubit, AuthenticationState>( value: widget.apiFactory,
listener: (context, state) { child: BlocListener<AuthenticationCubit, AuthenticationState>(
switch (state) { listener: (context, state) {
case UnauthenticatedState( switch (state) {
redirectToAccountSelection: var shouldRedirect case UnauthenticatedState(
): redirectToAccountSelection: var shouldRedirect
if (shouldRedirect) { ):
const LoginToExistingAccountRoute().go(context); if (shouldRedirect) {
} else { const LoginToExistingAccountRoute().go(context);
const LoginRoute().go(context); } else {
} const LoginRoute().go(context);
break; }
case RestoringSessionState(): break;
const RestoringSessionRoute().go(context); case RestoringSessionState():
break; const RestoringSessionRoute().go(context);
case VerifyIdentityState(userId: var userId): break;
VerifyIdentityRoute(userId: userId).go(context); case VerifyIdentityState(userId: var userId):
break; VerifyIdentityRoute(userId: userId).go(context);
case SwitchingAccountsState(): break;
const SwitchingAccountsRoute().push(context); case SwitchingAccountsState():
break; const SwitchingAccountsRoute().push(context);
case AuthenticatedState(): break;
const LandingRoute().go(context); case AuthenticatedState():
break; const LandingRoute().go(context);
case AuthenticatingState state: break;
AuthenticatingRoute(state.currentStage.name).push(context); case AuthenticatingState state:
break; AuthenticatingRoute(state.currentStage.name)
case LoggingOutState(): .push(context);
const LoggingOutRoute().go(context); break;
break; case LoggingOutState():
case AuthenticationErrorState(): const LoggingOutRoute().go(context);
if (context.canPop()) { break;
context.pop(); case AuthenticationErrorState():
} if (context.canPop()) {
break; context.pop();
} }
}, break;
child: child, }
},
child: child,
),
), ),
); );
}, },

View File

@@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hive_flutter/adapters.dart'; import 'package:hive_flutter/adapters.dart';
import 'package:paperless_api/paperless_api.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/hive/hive_config.dart';
import 'package:paperless_mobile/core/database/tables/global_settings.dart'; import 'package:paperless_mobile/core/database/tables/global_settings.dart';
import 'package:paperless_mobile/core/database/tables/local_user_account.dart'; import 'package:paperless_mobile/core/database/tables/local_user_account.dart';
@@ -141,32 +142,39 @@ class AuthenticatedRoute extends ShellRouteData {
const AuthenticatedRoute(); const AuthenticatedRoute();
@override @override
Widget builder( Page<void> pageBuilder(
BuildContext context, BuildContext context,
GoRouterState state, GoRouterState state,
Widget navigator, Widget navigator,
) { ) {
final currentUserId = Hive.box<GlobalSettings>(HiveBoxes.globalSettings) return accessiblePlatformPage(
.getValue()! child: Builder(
.loggedInUserId; builder: (context) {
if (currentUserId == null) { final currentUserId =
return const SizedBox.shrink(); Hive.box<GlobalSettings>(HiveBoxes.globalSettings)
} .getValue()!
final authenticatedUser = .loggedInUserId;
Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get( if (currentUserId == null) {
currentUserId, return const SizedBox.shrink();
)!; }
final apiFactory = context.read<PaperlessApiFactory>(); final authenticatedUser =
return HomeShellWidget( Hive.box<LocalUserAccount>(HiveBoxes.localUserAccount).get(
localUserId: authenticatedUser.id, currentUserId,
paperlessApiVersion: authenticatedUser.apiVersion, )!;
paperlessProviderFactory: apiFactory, final apiFactory = context.read<PaperlessApiFactory>();
child: ChangeNotifierProvider( return HomeShellWidget(
create: (context) => ConsumptionChangeNotifier() localUserId: authenticatedUser.id,
..loadFromConsumptionDirectory(userId: currentUserId), paperlessApiVersion: authenticatedUser.apiVersion,
child: EventListenerShell( paperlessProviderFactory: apiFactory,
child: navigator, child: ChangeNotifierProvider(
), create: (context) => ConsumptionChangeNotifier()
..loadFromConsumptionDirectory(userId: currentUserId),
child: EventListenerShell(
child: navigator,
),
),
);
},
), ),
); );
} }

View File

@@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AnimatedTouchBubblePart extends StatefulWidget { class AnimatedTouchBubblePart extends StatefulWidget {
const AnimatedTouchBubblePart({super.key, const AnimatedTouchBubblePart({
super.key,
required this.dragging, required this.dragging,
required this.size, required this.size,
}); });
@@ -22,6 +23,7 @@ class _AnimatedTouchBubblePartState extends State<AnimatedTouchBubblePart>
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies();
_controller = AnimationController( _controller = AnimationController(
duration: const Duration(milliseconds: 1000), duration: const Duration(milliseconds: 1000),
vsync: this, vsync: this,
@@ -40,7 +42,6 @@ class _AnimatedTouchBubblePartState extends State<AnimatedTouchBubblePart>
); );
_controller.repeat(); _controller.repeat();
super.didChangeDependencies();
} }
@override @override

View File

@@ -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. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 3.1.3+57 version: 3.1.4+58
environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"