From 1533707aa6af3c55f9754ac12d86c070cca4add8 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 22 Apr 2021 11:53:46 +0900 Subject: [PATCH] viewer: play videos in multitrack HEIC --- lib/model/multipage.dart | 3 + lib/model/video/metadata.dart | 2 +- .../viewer/entry_horizontal_pager.dart | 19 +--- lib/widgets/viewer/entry_vertical_pager.dart | 6 - lib/widgets/viewer/entry_viewer_page.dart | 13 ++- lib/widgets/viewer/entry_viewer_stack.dart | 107 +++++++++++------- lib/widgets/viewer/multipage/conductor.dart | 31 +++++ .../controller.dart} | 3 +- .../{bottom.dart => bottom/common.dart} | 4 +- .../overlay/{ => bottom}/multipage.dart | 2 +- .../viewer/overlay/{ => bottom}/panorama.dart | 0 .../viewer/overlay/{ => bottom}/video.dart | 2 +- lib/widgets/viewer/overlay/minimap.dart | 2 +- lib/widgets/viewer/overlay/top.dart | 6 +- .../{common => viewer}/video/conductor.dart | 8 +- .../{common => viewer}/video/controller.dart | 6 +- .../{common => viewer}/video/fijkplayer.dart | 2 +- .../video/flutter_vlc_player.dart | 2 +- .../video/video_player.dart | 2 +- .../viewer/visual/entry_page_view.dart | 4 +- lib/widgets/viewer/visual/video.dart | 2 +- 21 files changed, 136 insertions(+), 90 deletions(-) create mode 100644 lib/widgets/viewer/multipage/conductor.dart rename lib/widgets/viewer/{multipage.dart => multipage/controller.dart} (92%) rename lib/widgets/viewer/overlay/{bottom.dart => bottom/common.dart} (99%) rename lib/widgets/viewer/overlay/{ => bottom}/multipage.dart (98%) rename lib/widgets/viewer/overlay/{ => bottom}/panorama.dart (100%) rename lib/widgets/viewer/overlay/{ => bottom}/video.dart (99%) rename lib/widgets/{common => viewer}/video/conductor.dart (75%) rename lib/widgets/{common => viewer}/video/controller.dart (91%) rename lib/widgets/{common => viewer}/video/fijkplayer.dart (99%) rename lib/widgets/{common => viewer}/video/flutter_vlc_player.dart (98%) rename lib/widgets/{common => viewer}/video/video_player.dart (97%) diff --git a/lib/model/multipage.dart b/lib/model/multipage.dart index 2006b24ee..b19d2a100 100644 --- a/lib/model/multipage.dart +++ b/lib/model/multipage.dart @@ -1,3 +1,4 @@ +import 'package:aves/ref/mime_types.dart'; import 'package:flutter/foundation.dart'; class MultiPageInfo { @@ -80,6 +81,8 @@ class SinglePageInfo implements Comparable { ); } + bool get isVideo => MimeTypes.isVideo(mimeType); + @override String toString() => '$runtimeType#${shortHash(this)}{index=$index, pageId=$pageId, mimeType=$mimeType, isDefault=$isDefault, width=$width, height=$height, durationMillis=$durationMillis}'; diff --git a/lib/model/video/metadata.dart b/lib/model/video/metadata.dart index c03dc3cfb..ec31d08af 100644 --- a/lib/model/video/metadata.dart +++ b/lib/model/video/metadata.dart @@ -10,7 +10,7 @@ import 'package:aves/utils/file_utils.dart'; import 'package:aves/utils/math_utils.dart'; import 'package:aves/utils/string_utils.dart'; import 'package:aves/utils/time_utils.dart'; -import 'package:aves/widgets/common/video/fijkplayer.dart'; +import 'package:aves/widgets/viewer/video/fijkplayer.dart'; import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/foundation.dart'; diff --git a/lib/widgets/viewer/entry_horizontal_pager.dart b/lib/widgets/viewer/entry_horizontal_pager.dart index f338b8222..1dfe4bc35 100644 --- a/lib/widgets/viewer/entry_horizontal_pager.dart +++ b/lib/widgets/viewer/entry_horizontal_pager.dart @@ -3,24 +3,21 @@ import 'package:aves/model/multipage.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/magnifier/pan/gesture_detector_scope.dart'; import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/visual/entry_page_view.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:tuple/tuple.dart'; class MultiEntryScroller extends StatefulWidget { final CollectionLens collection; final PageController pageController; final ValueChanged onPageChanged; - final List> multiPageControllers; final void Function(String uri) onViewDisposed; const MultiEntryScroller({ this.collection, this.pageController, this.onPageChanged, - this.multiPageControllers, this.onViewDisposed, }); @@ -48,7 +45,7 @@ class _MultiEntryScrollerState extends State with AutomaticK Widget child; if (entry.isMultipage) { - final multiPageController = _getMultiPageController(entry); + final multiPageController = context.read().getController(entry); if (multiPageController != null) { child = FutureBuilder( future: multiPageController.info, @@ -90,21 +87,15 @@ class _MultiEntryScrollerState extends State with AutomaticK ); } - MultiPageController _getMultiPageController(AvesEntry entry) { - return widget.multiPageControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2; - } - @override bool get wantKeepAlive => true; } class SingleEntryScroller extends StatefulWidget { final AvesEntry entry; - final List> multiPageControllers; const SingleEntryScroller({ this.entry, - this.multiPageControllers, }); @override @@ -120,7 +111,7 @@ class _SingleEntryScrollerState extends State with Automati Widget child; if (entry.isMultipage) { - final multiPageController = _getMultiPageController(entry); + final multiPageController = context.read().getController(entry); if (multiPageController != null) { child = FutureBuilder( future: multiPageController.info, @@ -157,10 +148,6 @@ class _SingleEntryScrollerState extends State with Automati ); } - MultiPageController _getMultiPageController(AvesEntry entry) { - return widget.multiPageControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2; - } - @override bool get wantKeepAlive => true; } diff --git a/lib/widgets/viewer/entry_vertical_pager.dart b/lib/widgets/viewer/entry_vertical_pager.dart index 5601e18f9..a054b7008 100644 --- a/lib/widgets/viewer/entry_vertical_pager.dart +++ b/lib/widgets/viewer/entry_vertical_pager.dart @@ -6,16 +6,13 @@ import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart'; import 'package:aves/widgets/viewer/entry_horizontal_pager.dart'; import 'package:aves/widgets/viewer/info/info_page.dart'; import 'package:aves/widgets/viewer/info/notifications.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; -import 'package:tuple/tuple.dart'; class ViewerVerticalPageView extends StatefulWidget { final CollectionLens collection; final ValueNotifier entryNotifier; - final List> multiPageControllers; final PageController horizontalPager, verticalPager; final void Function(int page) onVerticalPageChanged, onHorizontalPageChanged; final VoidCallback onImagePageRequested; @@ -24,7 +21,6 @@ class ViewerVerticalPageView extends StatefulWidget { const ViewerVerticalPageView({ @required this.collection, @required this.entryNotifier, - @required this.multiPageControllers, @required this.verticalPager, @required this.horizontalPager, @required this.onVerticalPageChanged, @@ -89,12 +85,10 @@ class _ViewerVerticalPageViewState extends State { collection: collection, pageController: widget.horizontalPager, onPageChanged: widget.onHorizontalPageChanged, - multiPageControllers: widget.multiPageControllers, onViewDisposed: widget.onViewDisposed, ) : SingleEntryScroller( entry: entry, - multiPageControllers: widget.multiPageControllers, ), NotificationListener( onNotification: (notification) { diff --git a/lib/widgets/viewer/entry_viewer_page.dart b/lib/widgets/viewer/entry_viewer_page.dart index 0cefd2007..8fd6512aa 100644 --- a/lib/widgets/viewer/entry_viewer_page.dart +++ b/lib/widgets/viewer/entry_viewer_page.dart @@ -1,8 +1,9 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; -import 'package:aves/widgets/common/video/conductor.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; +import 'package:aves/widgets/viewer/video/conductor.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -25,9 +26,13 @@ class EntryViewerPage extends StatelessWidget { body: Provider( create: (context) => VideoConductor(), dispose: (context, value) => value.dispose(), - child: EntryViewerStack( - collection: collection, - initialEntry: initialEntry, + child: Provider( + create: (context) => MultiPageConductor(), + dispose: (context, value) => value.dispose(), + child: EntryViewerStack( + collection: collection, + initialEntry: initialEntry, + ), ), ), backgroundColor: Navigator.canPop(context) ? Colors.transparent : Colors.black, diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index 55ed963a3..0b873ded9 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/multipage.dart'; import 'package:aves/model/settings/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; @@ -11,18 +12,18 @@ import 'package:aves/theme/durations.dart'; import 'package:aves/utils/change_notifier.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/common/basic/insets.dart'; -import 'package:aves/widgets/common/video/conductor.dart'; -import 'package:aves/widgets/common/video/controller.dart'; import 'package:aves/widgets/viewer/entry_action_delegate.dart'; import 'package:aves/widgets/viewer/entry_vertical_pager.dart'; import 'package:aves/widgets/viewer/hero.dart'; import 'package:aves/widgets/viewer/info/notifications.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; -import 'package:aves/widgets/viewer/overlay/bottom.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; +import 'package:aves/widgets/viewer/overlay/bottom/common.dart'; +import 'package:aves/widgets/viewer/overlay/bottom/panorama.dart'; +import 'package:aves/widgets/viewer/overlay/bottom/video.dart'; import 'package:aves/widgets/viewer/overlay/notifications.dart'; -import 'package:aves/widgets/viewer/overlay/panorama.dart'; import 'package:aves/widgets/viewer/overlay/top.dart'; -import 'package:aves/widgets/viewer/overlay/video.dart'; +import 'package:aves/widgets/viewer/video/conductor.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:aves/widgets/viewer/visual/state.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -57,7 +58,6 @@ class _EntryViewerStackState extends State with SingleTickerPr Animation _bottomOverlayOffset; EdgeInsets _frozenViewInsets, _frozenViewPadding; EntryActionDelegate _actionDelegate; - final List> _multiPageControllers = []; final List>> _viewStateNotifiers = []; final ValueNotifier _heroInfoNotifier = ValueNotifier(null); @@ -127,8 +127,6 @@ class _EntryViewerStackState extends State with SingleTickerPr void dispose() { _overlayAnimationController.dispose(); _overlayVisible.removeListener(_onOverlayVisibleChange); - _multiPageControllers.forEach((kv) => kv.item2.dispose()); - _multiPageControllers.clear(); _verticalPager.removeListener(_onVerticalPageControllerChange); WidgetsBinding.instance.removeObserver(this); _unregisterWidget(widget); @@ -195,7 +193,6 @@ class _EntryViewerStackState extends State with SingleTickerPr ViewerVerticalPageView( collection: collection, entryNotifier: _entryNotifier, - multiPageControllers: _multiPageControllers, verticalPager: _verticalPager, horizontalPager: _horizontalPager, onVerticalPageChanged: _onVerticalPageChanged, @@ -225,8 +222,6 @@ class _EntryViewerStackState extends State with SingleTickerPr builder: (context, entry, child) { if (entry == null) return SizedBox.shrink(); - final multiPageController = _getMultiPageController(entry); - final viewStateNotifier = _viewStateNotifiers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2; return ViewerTopOverlay( entry: entry, @@ -236,7 +231,6 @@ class _EntryViewerStackState extends State with SingleTickerPr viewPadding: _frozenViewPadding, onActionSelected: (action) => _actionDelegate.onActionSelected(context, entry, action), viewStateNotifier: viewStateNotifier, - multiPageController: multiPageController, ); }, ); @@ -258,25 +252,43 @@ class _EntryViewerStackState extends State with SingleTickerPr builder: (context, entry, child) { if (entry == null) return SizedBox.shrink(); - final multiPageController = _getMultiPageController(entry); - - Widget extraBottomOverlay; - if (entry.isVideo) { - final videoController = context.read().getController(entry); - if (videoController != null) { - extraBottomOverlay = VideoControlOverlay( - entry: entry, - controller: videoController, + Widget _buildExtraBottomOverlay(AvesEntry pageEntry) { + // a 360 video is both a video and a panorama but only the video controls are displayed + if (pageEntry.isVideo) { + final videoController = context.read().getController(pageEntry); + if (videoController != null) { + return VideoControlOverlay( + entry: pageEntry, + controller: videoController, + scale: _bottomOverlayScale, + ); + } + } else if (pageEntry.is360) { + return PanoramaOverlay( + entry: pageEntry, scale: _bottomOverlayScale, ); } - } else if (entry.is360) { - extraBottomOverlay = PanoramaOverlay( - entry: entry, - scale: _bottomOverlayScale, - ); + return null; } + final multiPageController = entry.isMultipage ? context.read().getController(entry) : null; + final extraBottomOverlay = multiPageController != null + ? FutureBuilder( + future: multiPageController.info, + builder: (context, snapshot) { + final multiPageInfo = snapshot.data; + if (multiPageInfo == null) return SizedBox.shrink(); + return ValueListenableBuilder( + valueListenable: multiPageController.pageNotifier, + builder: (context, page, child) { + final pageEntry = entry.getPageEntry(multiPageInfo?.getByIndex(page)); + return _buildExtraBottomOverlay(pageEntry) ?? SizedBox(); + }, + ); + }) + : _buildExtraBottomOverlay(entry); + final child = Column( children: [ if (extraBottomOverlay != null) @@ -331,10 +343,6 @@ class _EntryViewerStackState extends State with SingleTickerPr return bottomOverlay; } - MultiPageController _getMultiPageController(AvesEntry entry) { - return entry.isMultipage ? _multiPageControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2 : null; - } - void _onVerticalPageControllerChange() { _verticalScrollNotifier.notifyListeners(); } @@ -504,22 +512,41 @@ class _EntryViewerStackState extends State with SingleTickerPr if (entry.isVideo) { final controller = context.read().getOrCreateController(entry); if (settings.enableVideoAutoPlay) { - _playVideo(controller); + _playVideo(controller, () => entry == _entryNotifier.value); } } if (entry.isMultipage) { - _initViewSpecificController( - uri, - _multiPageControllers, - () => MultiPageController(entry), - (_) => _.dispose(), - ); + final multiPageController = context.read().getOrCreateController(entry); + multiPageController.info.then((info) { + final videoPageEntries = info.pages.where((page) => page.isVideo).map(entry.getPageEntry).toSet(); + if (videoPageEntries.isNotEmpty) { + // init video controllers for all pages that could need it + final videoConductor = context.read(); + videoPageEntries.forEach(videoConductor.getOrCreateController); + + // auto play/pause when changing page + void _onPageChange() { + _pauseVideoControllers(); + if (settings.enableVideoAutoPlay) { + final page = multiPageController.page; + final pageInfo = info.getByIndex(page); + if (pageInfo.isVideo) { + final pageVideoController = videoConductor.getController(entry.getPageEntry(pageInfo)); + _playVideo(pageVideoController, () => entry == _entryNotifier.value && page == multiPageController.page); + } + } + } + + multiPageController.pageNotifier.addListener(_onPageChange); + _onPageChange(); + } + }); } setState(() {}); } - Future _playVideo(AvesVideoController videoController) async { + Future _playVideo(AvesVideoController videoController, bool Function() isCurrent) async { // video decoding may fail or have initial artifacts when the player initializes // during this widget initialization (because of the page transition and hero animation?) // so we play after a delay for increased stability @@ -530,7 +557,7 @@ class _EntryViewerStackState extends State with SingleTickerPr // playing controllers are paused when the entry changes, // but the controller may still be preparing (not yet playing) when this happens // so we make sure the current entry is still the same to keep playing - if (videoController.entry != _entryNotifier.value) { + if (!isCurrent()) { await videoController.pause(); } } diff --git a/lib/widgets/viewer/multipage/conductor.dart b/lib/widgets/viewer/multipage/conductor.dart new file mode 100644 index 000000000..709c3a711 --- /dev/null +++ b/lib/widgets/viewer/multipage/conductor.dart @@ -0,0 +1,31 @@ +import 'package:aves/model/entry.dart'; +import 'package:aves/widgets/viewer/multipage/controller.dart'; + +class MultiPageConductor { + final List _controllers = []; + + static const maxControllerCount = 3; + + Future dispose() async { + await Future.forEach(_controllers, (controller) => controller.dispose()); + _controllers.clear(); + } + + MultiPageController getOrCreateController(AvesEntry entry) { + var controller = getController(entry); + if (controller != null) { + _controllers.remove(controller); + } else { + controller = MultiPageController(entry); + } + _controllers.insert(0, controller); + while (_controllers.length > maxControllerCount) { + _controllers.removeLast().dispose(); + } + return controller; + } + + MultiPageController getController(AvesEntry entry) { + return _controllers.firstWhere((c) => c.entry.uri == entry.uri && c.entry.pageId == entry.pageId, orElse: () => null); + } +} diff --git a/lib/widgets/viewer/multipage.dart b/lib/widgets/viewer/multipage/controller.dart similarity index 92% rename from lib/widgets/viewer/multipage.dart rename to lib/widgets/viewer/multipage/controller.dart index c599f09de..d3a81154c 100644 --- a/lib/widgets/viewer/multipage.dart +++ b/lib/widgets/viewer/multipage/controller.dart @@ -7,10 +7,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class MultiPageController extends ChangeNotifier { + final AvesEntry entry; Future info; final ValueNotifier pageNotifier = ValueNotifier(null); - MultiPageController(AvesEntry entry) { + MultiPageController(this.entry) { info = metadataService.getMultiPageInfo(entry).then((value) { pageNotifier.value = value.defaultPage.index; return value; diff --git a/lib/widgets/viewer/overlay/bottom.dart b/lib/widgets/viewer/overlay/bottom/common.dart similarity index 99% rename from lib/widgets/viewer/overlay/bottom.dart rename to lib/widgets/viewer/overlay/bottom/common.dart index a36837652..034b0631f 100644 --- a/lib/widgets/viewer/overlay/bottom.dart +++ b/lib/widgets/viewer/overlay/bottom/common.dart @@ -11,9 +11,9 @@ import 'package:aves/theme/icons.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/blurred.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; +import 'package:aves/widgets/viewer/multipage/controller.dart'; +import 'package:aves/widgets/viewer/overlay/bottom/multipage.dart'; import 'package:aves/widgets/viewer/overlay/common.dart'; -import 'package:aves/widgets/viewer/overlay/multipage.dart'; import 'package:decorated_icon/decorated_icon.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; diff --git a/lib/widgets/viewer/overlay/multipage.dart b/lib/widgets/viewer/overlay/bottom/multipage.dart similarity index 98% rename from lib/widgets/viewer/overlay/multipage.dart rename to lib/widgets/viewer/overlay/bottom/multipage.dart index b40adda34..97ac36d5f 100644 --- a/lib/widgets/viewer/overlay/multipage.dart +++ b/lib/widgets/viewer/overlay/bottom/multipage.dart @@ -5,7 +5,7 @@ import 'package:aves/model/multipage.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/collection/thumbnail/decorated.dart'; import 'package:aves/widgets/collection/thumbnail/theme.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; +import 'package:aves/widgets/viewer/multipage/controller.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/viewer/overlay/panorama.dart b/lib/widgets/viewer/overlay/bottom/panorama.dart similarity index 100% rename from lib/widgets/viewer/overlay/panorama.dart rename to lib/widgets/viewer/overlay/bottom/panorama.dart diff --git a/lib/widgets/viewer/overlay/video.dart b/lib/widgets/viewer/overlay/bottom/video.dart similarity index 99% rename from lib/widgets/viewer/overlay/video.dart rename to lib/widgets/viewer/overlay/bottom/video.dart index e44d316d6..9dff72c5a 100644 --- a/lib/widgets/viewer/overlay/video.dart +++ b/lib/widgets/viewer/overlay/bottom/video.dart @@ -8,9 +8,9 @@ import 'package:aves/utils/time_utils.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/blurred.dart'; import 'package:aves/widgets/common/fx/borders.dart'; -import 'package:aves/widgets/common/video/controller.dart'; import 'package:aves/widgets/viewer/overlay/common.dart'; import 'package:aves/widgets/viewer/overlay/notifications.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:flutter/material.dart'; class VideoControlOverlay extends StatefulWidget { diff --git a/lib/widgets/viewer/overlay/minimap.dart b/lib/widgets/viewer/overlay/minimap.dart index 3aea62b92..27fafb0f2 100644 --- a/lib/widgets/viewer/overlay/minimap.dart +++ b/lib/widgets/viewer/overlay/minimap.dart @@ -2,7 +2,7 @@ import 'dart:math'; import 'package:aves/model/entry.dart'; import 'package:aves/model/multipage.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; +import 'package:aves/widgets/viewer/multipage/controller.dart'; import 'package:aves/widgets/viewer/visual/state.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/viewer/overlay/top.dart b/lib/widgets/viewer/overlay/top.dart index 08f4631c0..8473cca6a 100644 --- a/lib/widgets/viewer/overlay/top.dart +++ b/lib/widgets/viewer/overlay/top.dart @@ -7,7 +7,7 @@ import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/common/basic/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/sweeper.dart'; -import 'package:aves/widgets/viewer/multipage.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/overlay/common.dart'; import 'package:aves/widgets/viewer/overlay/minimap.dart'; import 'package:aves/widgets/viewer/visual/state.dart'; @@ -23,7 +23,6 @@ class ViewerTopOverlay extends StatelessWidget { final Function(EntryAction value) onActionSelected; final bool canToggleFavourite; final ValueNotifier viewStateNotifier; - final MultiPageController multiPageController; static const double padding = 8; @@ -36,7 +35,6 @@ class ViewerTopOverlay extends StatelessWidget { @required this.viewPadding, @required this.onActionSelected, @required this.viewStateNotifier, - @required this.multiPageController, }) : super(key: key); @override @@ -72,7 +70,7 @@ class ViewerTopOverlay extends StatelessWidget { child: Minimap( mainEntry: entry, viewStateNotifier: viewStateNotifier, - multiPageController: multiPageController, + multiPageController: entry.isMultipage ? context.read().getController(entry) : null, ), ) ], diff --git a/lib/widgets/common/video/conductor.dart b/lib/widgets/viewer/video/conductor.dart similarity index 75% rename from lib/widgets/common/video/conductor.dart rename to lib/widgets/viewer/video/conductor.dart index f4a4d7485..ed1e0e718 100644 --- a/lib/widgets/common/video/conductor.dart +++ b/lib/widgets/viewer/video/conductor.dart @@ -1,6 +1,6 @@ import 'package:aves/model/entry.dart'; -import 'package:aves/widgets/common/video/controller.dart'; -import 'package:aves/widgets/common/video/fijkplayer.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; +import 'package:aves/widgets/viewer/video/fijkplayer.dart'; import 'package:fijkplayer/fijkplayer.dart'; class VideoConductor { @@ -31,7 +31,9 @@ class VideoConductor { return controller; } - AvesVideoController getController(AvesEntry entry) => _controllers.firstWhere((controller) => controller.entry == entry, orElse: () => null); + AvesVideoController getController(AvesEntry entry) { + return _controllers.firstWhere((c) => c.entry.uri == entry.uri && c.entry.pageId == entry.pageId, orElse: () => null); + } void pauseAll() => _controllers.forEach((controller) => controller.pause()); } diff --git a/lib/widgets/common/video/controller.dart b/lib/widgets/viewer/video/controller.dart similarity index 91% rename from lib/widgets/common/video/controller.dart rename to lib/widgets/viewer/video/controller.dart index 322ccf282..3b586908b 100644 --- a/lib/widgets/common/video/controller.dart +++ b/lib/widgets/viewer/video/controller.dart @@ -3,13 +3,11 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; abstract class AvesVideoController { - AvesEntry _entry; + final AvesEntry _entry; AvesEntry get entry => _entry; - AvesVideoController(AvesEntry entry) { - _entry = entry; - } + AvesVideoController(AvesEntry entry) : _entry = entry; Future dispose(); diff --git a/lib/widgets/common/video/fijkplayer.dart b/lib/widgets/viewer/video/fijkplayer.dart similarity index 99% rename from lib/widgets/common/video/fijkplayer.dart rename to lib/widgets/viewer/video/fijkplayer.dart index 4f49f1441..11fc20ba6 100644 --- a/lib/widgets/common/video/fijkplayer.dart +++ b/lib/widgets/viewer/video/fijkplayer.dart @@ -7,7 +7,7 @@ import 'package:aves/model/settings/video_loop_mode.dart'; import 'package:aves/model/video/keys.dart'; import 'package:aves/model/video/metadata.dart'; import 'package:aves/utils/change_notifier.dart'; -import 'package:aves/widgets/common/video/controller.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/common/video/flutter_vlc_player.dart b/lib/widgets/viewer/video/flutter_vlc_player.dart similarity index 98% rename from lib/widgets/common/video/flutter_vlc_player.dart rename to lib/widgets/viewer/video/flutter_vlc_player.dart index 6dfdfcefa..d8f4dcaf4 100644 --- a/lib/widgets/common/video/flutter_vlc_player.dart +++ b/lib/widgets/viewer/video/flutter_vlc_player.dart @@ -3,7 +3,7 @@ // // import 'package:aves/model/entry.dart'; // import 'package:aves/utils/change_notifier.dart'; -// import 'package:aves/widgets/common/video/controller.dart'; +// import 'package:aves/widgets/viewer/video/controller.dart'; // import 'package:flutter/material.dart'; // import 'package:flutter/src/foundation/change_notifier.dart'; // import 'package:flutter/src/widgets/framework.dart'; diff --git a/lib/widgets/common/video/video_player.dart b/lib/widgets/viewer/video/video_player.dart similarity index 97% rename from lib/widgets/common/video/video_player.dart rename to lib/widgets/viewer/video/video_player.dart index 6e0fb35af..ee6d438c7 100644 --- a/lib/widgets/common/video/video_player.dart +++ b/lib/widgets/viewer/video/video_player.dart @@ -2,7 +2,7 @@ // // import 'package:aves/model/entry.dart'; // import 'package:aves/utils/change_notifier.dart'; -// import 'package:aves/widgets/common/video/controller.dart'; +// import 'package:aves/widgets/viewer/video/controller.dart'; // import 'package:flutter/src/foundation/change_notifier.dart'; // import 'package:flutter/src/widgets/framework.dart'; // import 'package:video_player/video_player.dart'; diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index d16438158..2c33fe868 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -15,10 +15,10 @@ import 'package:aves/widgets/common/magnifier/magnifier.dart'; import 'package:aves/widgets/common/magnifier/scale/scale_boundaries.dart'; import 'package:aves/widgets/common/magnifier/scale/scale_level.dart'; import 'package:aves/widgets/common/magnifier/scale/state.dart'; -import 'package:aves/widgets/common/video/conductor.dart'; -import 'package:aves/widgets/common/video/controller.dart'; import 'package:aves/widgets/viewer/hero.dart'; import 'package:aves/widgets/viewer/overlay/notifications.dart'; +import 'package:aves/widgets/viewer/video/conductor.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:aves/widgets/viewer/visual/error.dart'; import 'package:aves/widgets/viewer/visual/raster.dart'; import 'package:aves/widgets/viewer/visual/state.dart'; diff --git a/lib/widgets/viewer/visual/video.dart b/lib/widgets/viewer/visual/video.dart index 121c44b08..eda8c6d2a 100644 --- a/lib/widgets/viewer/visual/video.dart +++ b/lib/widgets/viewer/visual/video.dart @@ -1,5 +1,5 @@ import 'package:aves/model/entry.dart'; -import 'package:aves/widgets/common/video/controller.dart'; +import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:flutter/material.dart'; class VideoView extends StatefulWidget {