diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 4a5504249..35a2d3fe9 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -125,6 +125,7 @@ class AIcons { static const IconData setCover = MdiIcons.imageEditOutline; static const IconData share = Icons.share_outlined; static const IconData show = Icons.visibility_outlined; + static const IconData showFullscreen = MdiIcons.arrowExpand; static const IconData slideshow = Icons.slideshow_outlined; static const IconData speed = Icons.speed_outlined; static const IconData stats = Icons.donut_small_outlined; diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 85435a667..ab7d37a03 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -5,6 +5,7 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/favourites.dart'; import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/mime.dart'; +import 'package:aves/model/selection.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; @@ -21,6 +22,7 @@ import 'package:aves/widgets/collection/grid/section_layout.dart'; import 'package:aves/widgets/collection/grid/tile.dart'; import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart'; import 'package:aves/widgets/common/basic/insets.dart'; +import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; @@ -39,8 +41,10 @@ import 'package:aves/widgets/common/identity/scroll_thumb.dart'; import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; import 'package:aves/widgets/common/thumbnail/image.dart'; +import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:aves/widgets/common/tile_extent_controller.dart'; import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart'; +import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; @@ -152,58 +156,64 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { tileAnimationDelay = Duration.zero; } - return StreamBuilder( - stream: source.eventBus.on(), - builder: (context, snapshot) => SectionedEntryListLayoutProvider( - collection: collection, - selectable: selectable, - scrollableWidth: scrollableWidth, - tileLayout: tileLayout, - columnCount: columnCount, - spacing: tileSpacing, - horizontalPadding: horizontalPadding, - tileExtent: thumbnailExtent, - tileBuilder: (entry, tileSize) { - final extent = tileSize.shortestSide; - return AnimatedBuilder( - animation: favourites, - builder: (context, child) { - Widget tile = InteractiveTile( - key: ValueKey(entry.id), - collection: collection, - entry: entry, - thumbnailExtent: extent, - tileLayout: tileLayout, - isScrollingNotifier: _isScrollingNotifier, - ); - if (!settings.useTvLayout) return tile; + return NotificationListener( + onNotification: (notification) { + _goToViewer(collection, notification.entry); + return true; + }, + child: StreamBuilder( + stream: source.eventBus.on(), + builder: (context, snapshot) => SectionedEntryListLayoutProvider( + collection: collection, + selectable: selectable, + scrollableWidth: scrollableWidth, + tileLayout: tileLayout, + columnCount: columnCount, + spacing: tileSpacing, + horizontalPadding: horizontalPadding, + tileExtent: thumbnailExtent, + tileBuilder: (entry, tileSize) { + final extent = tileSize.shortestSide; + return AnimatedBuilder( + animation: favourites, + builder: (context, child) { + Widget tile = InteractiveTile( + key: ValueKey(entry.id), + collection: collection, + entry: entry, + thumbnailExtent: extent, + tileLayout: tileLayout, + isScrollingNotifier: _isScrollingNotifier, + ); + if (!settings.useTvLayout) return tile; - return Focus( - onFocusChange: (focused) { - if (focused) { - _focusedItemNotifier.value = entry; - } else if (_focusedItemNotifier.value == entry) { - _focusedItemNotifier.value = null; - } - }, - child: ValueListenableBuilder( - valueListenable: _focusedItemNotifier, - builder: (context, focusedItem, child) { - return AnimatedScale( - scale: focusedItem == entry ? 1 : .9, - curve: Curves.fastOutSlowIn, - duration: context.select((v) => v.tvImageFocusAnimation), - child: child!, - ); + return Focus( + onFocusChange: (focused) { + if (focused) { + _focusedItemNotifier.value = entry; + } else if (_focusedItemNotifier.value == entry) { + _focusedItemNotifier.value = null; + } }, - child: tile, - ), - ); - }, - ); - }, - tileAnimationDelay: tileAnimationDelay, - child: child!, + child: ValueListenableBuilder( + valueListenable: _focusedItemNotifier, + builder: (context, focusedItem, child) { + return AnimatedScale( + scale: focusedItem == entry ? 1 : .9, + curve: Curves.fastOutSlowIn, + duration: context.select((v) => v.tvImageFocusAnimation), + child: child!, + ); + }, + child: tile, + ), + ); + }, + ); + }, + tileAnimationDelay: tileAnimationDelay, + child: child!, + ), ), ); }, @@ -227,6 +237,34 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { }, ); } + + void _goToViewer(CollectionLens collection, AvesEntry entry) { + final selection = context.read>(); + Navigator.maybeOf(context)?.push( + TransparentMaterialPageRoute( + settings: const RouteSettings(name: EntryViewerPage.routeName), + pageBuilder: (context, a, sa) { + final viewerCollection = collection.copyWith( + listenToSource: false, + ); + assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id)); + Widget child = EntryViewerPage( + collection: viewerCollection, + initialEntry: entry, + ); + + if (selection.isSelecting) { + child = ChangeNotifierProvider>.value( + value: selection, + child: child, + ); + } + + return child; + }, + ), + ); + } } class _CollectionSectionedContent extends StatefulWidget { diff --git a/lib/widgets/collection/grid/tile.dart b/lib/widgets/collection/grid/tile.dart index 9f18792cb..64eddc2c0 100644 --- a/lib/widgets/collection/grid/tile.dart +++ b/lib/widgets/collection/grid/tile.dart @@ -6,10 +6,9 @@ import 'package:aves/model/source/enums/enums.dart'; import 'package:aves/services/intent_service.dart'; import 'package:aves/widgets/collection/grid/list_details.dart'; import 'package:aves/widgets/collection/grid/list_details_theme.dart'; -import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/grid/scaling.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; +import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -40,7 +39,7 @@ class InteractiveTile extends StatelessWidget { if (selection.isSelecting) { selection.toggleSelection(entry); } else { - _goToViewer(context); + OpenViewerNotification(entry).dispatch(context); } break; case AppMode.pickSingleMediaExternal: @@ -79,24 +78,6 @@ class InteractiveTile extends StatelessWidget { ), ); } - - void _goToViewer(BuildContext context) { - Navigator.maybeOf(context)?.push( - TransparentMaterialPageRoute( - settings: const RouteSettings(name: EntryViewerPage.routeName), - pageBuilder: (context, a, sa) { - final viewerCollection = collection.copyWith( - listenToSource: false, - ); - assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id)); - return EntryViewerPage( - collection: viewerCollection, - initialEntry: entry, - ); - }, - ), - ); - } } class Tile extends StatelessWidget { diff --git a/lib/widgets/common/basic/color_list_tile.dart b/lib/widgets/common/basic/list_tiles/color.dart similarity index 100% rename from lib/widgets/common/basic/color_list_tile.dart rename to lib/widgets/common/basic/list_tiles/color.dart diff --git a/lib/widgets/common/basic/reselectable_radio_list_tile.dart b/lib/widgets/common/basic/list_tiles/reselectable_radio.dart similarity index 100% rename from lib/widgets/common/basic/reselectable_radio_list_tile.dart rename to lib/widgets/common/basic/list_tiles/reselectable_radio.dart diff --git a/lib/widgets/common/basic/slider_list_tile.dart b/lib/widgets/common/basic/list_tiles/slider.dart similarity index 100% rename from lib/widgets/common/basic/slider_list_tile.dart rename to lib/widgets/common/basic/list_tiles/slider.dart diff --git a/lib/widgets/common/grid/overlay.dart b/lib/widgets/common/grid/overlay.dart index a1ba82ad8..28501f925 100644 --- a/lib/widgets/common/grid/overlay.dart +++ b/lib/widgets/common/grid/overlay.dart @@ -22,44 +22,38 @@ class GridItemSelectionOverlay extends StatelessWidget { @override Widget build(BuildContext context) { final isSelecting = context.select, bool>((selection) => selection.isSelecting); - final child = isSelecting - ? Selector, bool>( - selector: (context, selection) => selection.isSelected([item]), - builder: (context, isSelected, child) { - var child = isSelecting - ? OverlayIcon( + return AnimatedSwitcher( + duration: duration, + child: isSelecting + ? Selector, bool>( + selector: (context, selection) => selection.isSelected([item]), + builder: (context, isSelected, child) { + return AnimatedContainer( + alignment: AlignmentDirectional.topEnd, + padding: padding, + decoration: BoxDecoration( + color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(.6) : Colors.transparent, + borderRadius: borderRadius, + ), + duration: duration, + child: AnimatedSwitcher( + duration: duration, + switchInCurve: Curves.easeOutBack, + switchOutCurve: Curves.easeOutBack, + transitionBuilder: (child, animation) => ScaleTransition( + scale: animation, + child: child, + ), + child: OverlayIcon( key: ValueKey(isSelected), icon: isSelected ? AIcons.selected : AIcons.unselected, margin: EdgeInsets.zero, - ) - : const SizedBox(); - child = AnimatedSwitcher( - duration: duration, - switchInCurve: Curves.easeOutBack, - switchOutCurve: Curves.easeOutBack, - transitionBuilder: (child, animation) => ScaleTransition( - scale: animation, - child: child, - ), - child: child, - ); - child = AnimatedContainer( - alignment: AlignmentDirectional.topEnd, - padding: padding, - decoration: BoxDecoration( - color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(.6) : Colors.transparent, - borderRadius: borderRadius, - ), - duration: duration, - child: child, - ); - return child; - }, - ) - : const SizedBox(); - return AnimatedSwitcher( - duration: duration, - child: child, + ), + ), + ); + }, + ) + : const SizedBox(), ); } } diff --git a/lib/widgets/common/grid/theme.dart b/lib/widgets/common/grid/theme.dart index 4076bd32e..2e7bdd1ef 100644 --- a/lib/widgets/common/grid/theme.dart +++ b/lib/widgets/common/grid/theme.dart @@ -30,10 +30,12 @@ class GridTheme extends StatelessWidget { final fontSize = (iconSize * .7).floorToDouble(); iconSize *= mq.textScaleFactor; final highlightBorderWidth = extent * .1; + final interactiveDimension = min(iconSize * 2, kMinInteractiveDimension); return GridThemeData( iconSize: iconSize, fontSize: fontSize, highlightBorderWidth: highlightBorderWidth, + interactiveDimension: interactiveDimension, showFavourite: settings.showThumbnailFavourite, locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none, tagIcon: settings.thumbnailTagIcon, @@ -52,7 +54,7 @@ class GridTheme extends StatelessWidget { typedef GridThemeIconBuilder = List Function(BuildContext context, AvesEntry entry); class GridThemeData { - final double iconSize, fontSize, highlightBorderWidth; + final double iconSize, fontSize, highlightBorderWidth, interactiveDimension; final bool showFavourite, showMotionPhoto, showRating, showRaw, showTrash, showVideoDuration; final bool showLocated, showUnlocated, showTagged, showUntagged; late final GridThemeIconBuilder iconBuilder; @@ -61,6 +63,7 @@ class GridThemeData { required this.iconSize, required this.fontSize, required this.highlightBorderWidth, + required this.interactiveDimension, required this.showFavourite, required ThumbnailOverlayLocationIcon locationIcon, required ThumbnailOverlayTagIcon tagIcon, diff --git a/lib/widgets/common/thumbnail/notifications.dart b/lib/widgets/common/thumbnail/notifications.dart new file mode 100644 index 000000000..b52226070 --- /dev/null +++ b/lib/widgets/common/thumbnail/notifications.dart @@ -0,0 +1,9 @@ +import 'package:aves/model/entry.dart'; +import 'package:flutter/widgets.dart'; + +@immutable +class OpenViewerNotification extends Notification { + final AvesEntry entry; + + const OpenViewerNotification(this.entry); +} diff --git a/lib/widgets/common/thumbnail/overlay.dart b/lib/widgets/common/thumbnail/overlay.dart index aa3b639d6..ed64484d5 100644 --- a/lib/widgets/common/thumbnail/overlay.dart +++ b/lib/widgets/common/thumbnail/overlay.dart @@ -2,6 +2,9 @@ import 'dart:math'; import 'package:aves/model/entry.dart'; import 'package:aves/model/highlight.dart'; +import 'package:aves/model/selection.dart'; +import 'package:aves/theme/durations.dart'; +import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/common/fx/sweeper.dart'; import 'package:aves/widgets/common/grid/theme.dart'; import 'package:flutter/material.dart'; @@ -70,3 +73,43 @@ class _ThumbnailHighlightOverlayState extends State { ); } } + +class ThumbnailZoomOverlay extends StatelessWidget { + final VoidCallback? onZoom; + + const ThumbnailZoomOverlay({ + super.key, + this.onZoom, + }); + + static const alignment = AlignmentDirectional.bottomEnd; + static const duration = Durations.thumbnailOverlayAnimation; + + @override + Widget build(BuildContext context) { + final isSelecting = context.select, bool>((selection) => selection.isSelecting); + final interactiveDimension = context.select((t) => t.interactiveDimension); + return AnimatedSwitcher( + duration: duration, + child: isSelecting + ? Align( + alignment: alignment, + child: GestureDetector( + onTap: onZoom, + child: Container( + alignment: alignment, + padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 2), + width: interactiveDimension, + height: interactiveDimension, + child: Icon( + AIcons.showFullscreen, + size: context.select((t) => t.iconSize), + color: Colors.white70, + ), + ), + ), + ) + : const SizedBox(), + ); + } +} diff --git a/lib/widgets/dialogs/aves_selection_dialog.dart b/lib/widgets/dialogs/aves_selection_dialog.dart index bede0ca1c..068ef5dd6 100644 --- a/lib/widgets/dialogs/aves_selection_dialog.dart +++ b/lib/widgets/dialogs/aves_selection_dialog.dart @@ -1,5 +1,5 @@ import 'package:aves/theme/durations.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; diff --git a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart index 3dde93755..afbeb28f2 100644 --- a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart @@ -10,7 +10,7 @@ import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/constants.dart'; -import 'package:aves/widgets/common/basic/color_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/color.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/borders.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart'; diff --git a/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart index e49e7334b..2b9799064 100644 --- a/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart @@ -2,8 +2,8 @@ import 'package:aves/image_providers/app_icon_image_provider.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/utils/android_file_utils.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:aves/widgets/common/basic/query_bar.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:collection/collection.dart'; diff --git a/lib/widgets/settings/language/locale_selection_page.dart b/lib/widgets/settings/language/locale_selection_page.dart index 8c95015f5..b1d02fe13 100644 --- a/lib/widgets/settings/language/locale_selection_page.dart +++ b/lib/widgets/settings/language/locale_selection_page.dart @@ -2,8 +2,8 @@ import 'dart:collection'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/widgets/aves_app.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:aves/widgets/common/basic/query_bar.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/language/locale_tile.dart'; diff --git a/lib/widgets/settings/video/subtitle_theme.dart b/lib/widgets/settings/video/subtitle_theme.dart index 220edce07..5121d0377 100644 --- a/lib/widgets/settings/video/subtitle_theme.dart +++ b/lib/widgets/settings/video/subtitle_theme.dart @@ -1,9 +1,9 @@ import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/enums/subtitle_position.dart'; import 'package:aves/model/settings/settings.dart'; -import 'package:aves/widgets/common/basic/color_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/color.dart'; +import 'package:aves/widgets/common/basic/list_tiles/slider.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; -import 'package:aves/widgets/common/basic/slider_list_tile.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/common/tiles.dart'; import 'package:aves/widgets/settings/video/subtitle_sample.dart'; diff --git a/lib/widgets/viewer/entry_viewer_page.dart b/lib/widgets/viewer/entry_viewer_page.dart index 89fc4dc6e..1efca6ae1 100644 --- a/lib/widgets/viewer/entry_viewer_page.dart +++ b/lib/widgets/viewer/entry_viewer_page.dart @@ -3,10 +3,8 @@ import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; -import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/overlay/bottom.dart'; -import 'package:aves/widgets/viewer/video/conductor.dart'; -import 'package:aves/widgets/viewer/visual/conductor.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -43,16 +41,16 @@ class _EntryViewerPageState extends State { Widget build(BuildContext context) { final collection = widget.collection; return AvesScaffold( - body: ViewStateConductorProvider( - child: VideoConductorProvider( + body: MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(collection: collection), + MultiPageConductorProvider(), + ], + child: EntryViewerStack( collection: collection, - child: MultiPageConductorProvider( - child: EntryViewerStack( - collection: collection, - initialEntry: widget.initialEntry, - viewerController: _viewerController, - ), - ), + initialEntry: widget.initialEntry, + viewerController: _viewerController, ), ), backgroundColor: Navigator.canPop(context) @@ -64,63 +62,3 @@ class _EntryViewerPageState extends State { ); } } - -class ViewStateConductorProvider extends StatelessWidget { - final Widget? child; - - const ViewStateConductorProvider({ - super.key, - this.child, - }); - - @override - Widget build(BuildContext context) { - return ProxyProvider( - create: (context) => ViewStateConductor(), - update: (context, mq, value) { - value!.viewportSize = mq.size; - return value; - }, - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} - -class VideoConductorProvider extends StatelessWidget { - final CollectionLens? collection; - final Widget? child; - - const VideoConductorProvider({ - super.key, - this.collection, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return Provider( - create: (context) => VideoConductor(collection: collection), - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} - -class MultiPageConductorProvider extends StatelessWidget { - final Widget? child; - - const MultiPageConductorProvider({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return Provider( - create: (context) => MultiPageConductor(), - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} diff --git a/lib/widgets/viewer/providers.dart b/lib/widgets/viewer/providers.dart new file mode 100644 index 000000000..1a76a0a35 --- /dev/null +++ b/lib/widgets/viewer/providers.dart @@ -0,0 +1,41 @@ +import 'package:aves/model/source/collection_lens.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; +import 'package:aves/widgets/viewer/video/conductor.dart'; +import 'package:aves/widgets/viewer/visual/conductor.dart'; +import 'package:flutter/widgets.dart'; +import 'package:provider/provider.dart'; + +class ViewStateConductorProvider extends ProxyProvider { + ViewStateConductorProvider({ + super.key, + super.child, + }) : super( + create: (context) => ViewStateConductor(), + update: (context, mq, value) { + value!.viewportSize = mq.size; + return value; + }, + dispose: (context, value) => value.dispose(), + ); +} + +class VideoConductorProvider extends Provider { + VideoConductorProvider({ + super.key, + CollectionLens? collection, + super.child, + }) : super( + create: (context) => VideoConductor(collection: collection), + dispose: (context, value) => value.dispose(), + ); +} + +class MultiPageConductorProvider extends Provider { + MultiPageConductorProvider({ + super.key, + super.child, + }) : super( + create: (context) => MultiPageConductor(), + dispose: (context, value) => value.dispose(), + ); +} diff --git a/lib/widgets/viewer/screen_saver_page.dart b/lib/widgets/viewer/screen_saver_page.dart index 61ec663e4..bad726db5 100644 --- a/lib/widgets/viewer/screen_saver_page.dart +++ b/lib/widgets/viewer/screen_saver_page.dart @@ -8,10 +8,11 @@ import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/empty.dart'; import 'package:aves/widgets/viewer/controller.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves_magnifier/aves_magnifier.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class ScreenSaverPage extends StatefulWidget { static const routeName = '/screen_saver'; @@ -80,15 +81,16 @@ class _ScreenSaverPageState extends State with WidgetsBindingOb alignment: Alignment.center, ); } else { - child = ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: EntryViewerStack( - collection: collection, - initialEntry: entries.first, - viewerController: _viewerController, - ), - ), + child = MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: EntryViewerStack( + collection: collection, + initialEntry: entries.first, + viewerController: _viewerController, ), ); } diff --git a/lib/widgets/viewer/slideshow_page.dart b/lib/widgets/viewer/slideshow_page.dart index e070459f5..eccf250bf 100644 --- a/lib/widgets/viewer/slideshow_page.dart +++ b/lib/widgets/viewer/slideshow_page.dart @@ -14,8 +14,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/empty.dart'; import 'package:aves/widgets/settings/viewer/slideshow.dart'; import 'package:aves/widgets/viewer/controller.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves_magnifier/aves_magnifier.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; @@ -69,21 +69,22 @@ class _SlideshowPageState extends State { text: context.l10n.collectionEmptyImages, alignment: Alignment.center, ) - : ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: NotificationListener( - onNotification: (notification) { - _onActionSelected(notification.action); - return true; - }, - child: EntryViewerStack( - key: ValueKey(_viewerController), - collection: _slideshowCollection, - initialEntry: initialEntry, - viewerController: _viewerController, - ), - ), + : MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: NotificationListener( + onNotification: (notification) { + _onActionSelected(notification.action); + return true; + }, + child: EntryViewerStack( + key: ValueKey(_viewerController), + collection: _slideshowCollection, + initialEntry: initialEntry, + viewerController: _viewerController, ), ), ), diff --git a/lib/widgets/wallpaper_page.dart b/lib/widgets/wallpaper_page.dart index 59371a258..e052b4e8e 100644 --- a/lib/widgets/wallpaper_page.dart +++ b/lib/widgets/wallpaper_page.dart @@ -8,12 +8,12 @@ import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/entry_horizontal_pager.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/notifications.dart'; import 'package:aves/widgets/viewer/overlay/bottom.dart'; import 'package:aves/widgets/viewer/overlay/video/video.dart'; import 'package:aves/widgets/viewer/page_entry_builder.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves/widgets/viewer/video/conductor.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:aves/widgets/viewer/video_action_delegate.dart'; @@ -37,13 +37,14 @@ class WallpaperPage extends StatelessWidget { Widget build(BuildContext context) { return AvesScaffold( body: entry != null - ? ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: EntryEditor( - entry: entry!, - ), - ), + ? MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: EntryEditor( + entry: entry!, ), ) : const SizedBox(),