viewer: hide overlay when pressing play
This commit is contained in:
parent
a0f8b32440
commit
fee9386d3d
11 changed files with 80 additions and 71 deletions
|
@ -14,7 +14,6 @@ class MultiEntryScroller extends StatefulWidget {
|
||||||
final CollectionLens collection;
|
final CollectionLens collection;
|
||||||
final PageController pageController;
|
final PageController pageController;
|
||||||
final ValueChanged<int> onPageChanged;
|
final ValueChanged<int> onPageChanged;
|
||||||
final VoidCallback onTap;
|
|
||||||
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
||||||
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
||||||
final void Function(String uri) onViewDisposed;
|
final void Function(String uri) onViewDisposed;
|
||||||
|
@ -23,7 +22,6 @@ class MultiEntryScroller extends StatefulWidget {
|
||||||
this.collection,
|
this.collection,
|
||||||
this.pageController,
|
this.pageController,
|
||||||
this.onPageChanged,
|
this.onPageChanged,
|
||||||
this.onTap,
|
|
||||||
this.videoControllers,
|
this.videoControllers,
|
||||||
this.multiPageControllers,
|
this.multiPageControllers,
|
||||||
this.onViewDisposed,
|
this.onViewDisposed,
|
||||||
|
@ -89,7 +87,6 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
|
||||||
mainEntry: entry,
|
mainEntry: entry,
|
||||||
page: page,
|
page: page,
|
||||||
viewportSize: mqSize,
|
viewportSize: mqSize,
|
||||||
onTap: widget.onTap == null ? null : (_) => widget.onTap(),
|
|
||||||
videoControllers: widget.videoControllers,
|
videoControllers: widget.videoControllers,
|
||||||
onDisposed: () => widget.onViewDisposed?.call(entry.uri),
|
onDisposed: () => widget.onViewDisposed?.call(entry.uri),
|
||||||
);
|
);
|
||||||
|
@ -107,13 +104,11 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
|
||||||
|
|
||||||
class SingleEntryScroller extends StatefulWidget {
|
class SingleEntryScroller extends StatefulWidget {
|
||||||
final AvesEntry entry;
|
final AvesEntry entry;
|
||||||
final VoidCallback onTap;
|
|
||||||
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
||||||
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
||||||
|
|
||||||
const SingleEntryScroller({
|
const SingleEntryScroller({
|
||||||
this.entry,
|
this.entry,
|
||||||
this.onTap,
|
|
||||||
this.videoControllers,
|
this.videoControllers,
|
||||||
this.multiPageControllers,
|
this.multiPageControllers,
|
||||||
});
|
});
|
||||||
|
@ -163,7 +158,6 @@ class _SingleEntryScrollerState extends State<SingleEntryScroller> with Automati
|
||||||
mainEntry: entry,
|
mainEntry: entry,
|
||||||
page: page,
|
page: page,
|
||||||
viewportSize: mqSize,
|
viewportSize: mqSize,
|
||||||
onTap: widget.onTap == null ? null : (_) => widget.onTap(),
|
|
||||||
videoControllers: widget.videoControllers,
|
videoControllers: widget.videoControllers,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,7 +20,7 @@ class ViewerVerticalPageView extends StatefulWidget {
|
||||||
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
final List<Tuple2<String, MultiPageController>> multiPageControllers;
|
||||||
final PageController horizontalPager, verticalPager;
|
final PageController horizontalPager, verticalPager;
|
||||||
final void Function(int page) onVerticalPageChanged, onHorizontalPageChanged;
|
final void Function(int page) onVerticalPageChanged, onHorizontalPageChanged;
|
||||||
final VoidCallback onImageTap, onImagePageRequested;
|
final VoidCallback onImagePageRequested;
|
||||||
final void Function(String uri) onViewDisposed;
|
final void Function(String uri) onViewDisposed;
|
||||||
|
|
||||||
const ViewerVerticalPageView({
|
const ViewerVerticalPageView({
|
||||||
|
@ -32,7 +32,6 @@ class ViewerVerticalPageView extends StatefulWidget {
|
||||||
@required this.horizontalPager,
|
@required this.horizontalPager,
|
||||||
@required this.onVerticalPageChanged,
|
@required this.onVerticalPageChanged,
|
||||||
@required this.onHorizontalPageChanged,
|
@required this.onHorizontalPageChanged,
|
||||||
this.onImageTap,
|
|
||||||
@required this.onImagePageRequested,
|
@required this.onImagePageRequested,
|
||||||
@required this.onViewDisposed,
|
@required this.onViewDisposed,
|
||||||
});
|
});
|
||||||
|
@ -92,7 +91,6 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
|
||||||
? MultiEntryScroller(
|
? MultiEntryScroller(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
pageController: widget.horizontalPager,
|
pageController: widget.horizontalPager,
|
||||||
onTap: widget.onImageTap,
|
|
||||||
onPageChanged: widget.onHorizontalPageChanged,
|
onPageChanged: widget.onHorizontalPageChanged,
|
||||||
videoControllers: widget.videoControllers,
|
videoControllers: widget.videoControllers,
|
||||||
multiPageControllers: widget.multiPageControllers,
|
multiPageControllers: widget.multiPageControllers,
|
||||||
|
@ -100,7 +98,6 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
|
||||||
)
|
)
|
||||||
: SingleEntryScroller(
|
: SingleEntryScroller(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
onTap: widget.onImageTap,
|
|
||||||
videoControllers: widget.videoControllers,
|
videoControllers: widget.videoControllers,
|
||||||
multiPageControllers: widget.multiPageControllers,
|
multiPageControllers: widget.multiPageControllers,
|
||||||
),
|
),
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:aves/widgets/viewer/hero.dart';
|
||||||
import 'package:aves/widgets/viewer/info/notifications.dart';
|
import 'package:aves/widgets/viewer/info/notifications.dart';
|
||||||
import 'package:aves/widgets/viewer/multipage.dart';
|
import 'package:aves/widgets/viewer/multipage.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
||||||
|
import 'package:aves/widgets/viewer/overlay/notifications.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/panorama.dart';
|
import 'package:aves/widgets/viewer/overlay/panorama.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/top.dart';
|
import 'package:aves/widgets/viewer/overlay/top.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/video.dart';
|
import 'package:aves/widgets/viewer/overlay/video.dart';
|
||||||
|
@ -175,7 +176,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
|
||||||
value: _heroInfoNotifier,
|
value: _heroInfoNotifier,
|
||||||
child: NotificationListener(
|
child: NotificationListener(
|
||||||
onNotification: (notification) {
|
onNotification: (notification) {
|
||||||
if (notification is FilterNotification) {
|
if (notification is FilterSelectedNotification) {
|
||||||
_goToCollection(notification.filter);
|
_goToCollection(notification.filter);
|
||||||
} else if (notification is ViewStateNotification) {
|
} else if (notification is ViewStateNotification) {
|
||||||
_updateViewState(notification.uri, notification.viewState);
|
_updateViewState(notification.uri, notification.viewState);
|
||||||
|
@ -184,6 +185,14 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
child: NotificationListener(
|
||||||
|
onNotification: (notification) {
|
||||||
|
if (notification is ToggleOverlayNotification) {
|
||||||
|
_overlayVisible.value = !_overlayVisible.value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
ViewerVerticalPageView(
|
ViewerVerticalPageView(
|
||||||
|
@ -195,7 +204,6 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
|
||||||
horizontalPager: _horizontalPager,
|
horizontalPager: _horizontalPager,
|
||||||
onVerticalPageChanged: _onVerticalPageChanged,
|
onVerticalPageChanged: _onVerticalPageChanged,
|
||||||
onHorizontalPageChanged: _onHorizontalPageChanged,
|
onHorizontalPageChanged: _onHorizontalPageChanged,
|
||||||
onImageTap: () => _overlayVisible.value = !_overlayVisible.value,
|
|
||||||
onImagePageRequested: () => _goToVerticalPage(imagePage),
|
onImagePageRequested: () => _goToVerticalPage(imagePage),
|
||||||
onViewDisposed: (uri) => _updateViewState(uri, null),
|
onViewDisposed: (uri) => _updateViewState(uri, null),
|
||||||
),
|
),
|
||||||
|
@ -206,6 +214,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,6 +222,6 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
||||||
|
|
||||||
void _goToCollection(CollectionFilter filter) {
|
void _goToCollection(CollectionFilter filter) {
|
||||||
if (collection == null) return;
|
if (collection == null) return;
|
||||||
FilterNotification(filter).dispatch(context);
|
FilterSelectedNotification(filter).dispatch(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,34 +116,3 @@ class XmpProp {
|
||||||
@override
|
@override
|
||||||
String toString() => '$runtimeType#${shortHash(this)}{path=$path, value=$value}';
|
String toString() => '$runtimeType#${shortHash(this)}{path=$path, value=$value}';
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EmbeddedDataSource { videoCover, xmp }
|
|
||||||
|
|
||||||
class OpenEmbeddedDataNotification extends Notification {
|
|
||||||
final EmbeddedDataSource source;
|
|
||||||
final String propPath;
|
|
||||||
final String mimeType;
|
|
||||||
|
|
||||||
const OpenEmbeddedDataNotification._private({
|
|
||||||
@required this.source,
|
|
||||||
this.propPath,
|
|
||||||
this.mimeType,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory OpenEmbeddedDataNotification.videoCover() => OpenEmbeddedDataNotification._private(
|
|
||||||
source: EmbeddedDataSource.videoCover,
|
|
||||||
);
|
|
||||||
|
|
||||||
factory OpenEmbeddedDataNotification.xmp({
|
|
||||||
@required String propPath,
|
|
||||||
@required String mimeType,
|
|
||||||
}) =>
|
|
||||||
OpenEmbeddedDataNotification._private(
|
|
||||||
source: EmbeddedDataSource.xmp,
|
|
||||||
propPath: propPath,
|
|
||||||
mimeType: mimeType,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => '$runtimeType#${shortHash(this)}{source=$source, propPath=$propPath, mimeType=$mimeType}';
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/viewer/info/common.dart';
|
import 'package:aves/widgets/viewer/info/common.dart';
|
||||||
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
|
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
|
||||||
|
import 'package:aves/widgets/viewer/info/notifications.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
abstract class XmpGoogleNamespace extends XmpNamespace {
|
abstract class XmpGoogleNamespace extends XmpNamespace {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/viewer/info/common.dart';
|
import 'package:aves/widgets/viewer/info/common.dart';
|
||||||
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
|
import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart';
|
||||||
import 'package:aves/widgets/viewer/info/metadata/xmp_structs.dart';
|
import 'package:aves/widgets/viewer/info/metadata/xmp_structs.dart';
|
||||||
|
import 'package:aves/widgets/viewer/info/notifications.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class XmpBasicNamespace extends XmpNamespace {
|
class XmpBasicNamespace extends XmpNamespace {
|
||||||
|
|
|
@ -5,10 +5,10 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BackUpNotification extends Notification {}
|
class BackUpNotification extends Notification {}
|
||||||
|
|
||||||
class FilterNotification extends Notification {
|
class FilterSelectedNotification extends Notification {
|
||||||
final CollectionFilter filter;
|
final CollectionFilter filter;
|
||||||
|
|
||||||
const FilterNotification(this.filter);
|
const FilterSelectedNotification(this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
class EntryDeletedNotification extends Notification {
|
class EntryDeletedNotification extends Notification {
|
||||||
|
@ -27,3 +27,34 @@ class OpenTempEntryNotification extends Notification {
|
||||||
@override
|
@override
|
||||||
String toString() => '$runtimeType#${shortHash(this)}{entry=$entry}';
|
String toString() => '$runtimeType#${shortHash(this)}{entry=$entry}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EmbeddedDataSource { videoCover, xmp }
|
||||||
|
|
||||||
|
class OpenEmbeddedDataNotification extends Notification {
|
||||||
|
final EmbeddedDataSource source;
|
||||||
|
final String propPath;
|
||||||
|
final String mimeType;
|
||||||
|
|
||||||
|
const OpenEmbeddedDataNotification._private({
|
||||||
|
@required this.source,
|
||||||
|
this.propPath,
|
||||||
|
this.mimeType,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory OpenEmbeddedDataNotification.videoCover() => OpenEmbeddedDataNotification._private(
|
||||||
|
source: EmbeddedDataSource.videoCover,
|
||||||
|
);
|
||||||
|
|
||||||
|
factory OpenEmbeddedDataNotification.xmp({
|
||||||
|
@required String propPath,
|
||||||
|
@required String mimeType,
|
||||||
|
}) =>
|
||||||
|
OpenEmbeddedDataNotification._private(
|
||||||
|
source: EmbeddedDataSource.xmp,
|
||||||
|
propPath: propPath,
|
||||||
|
mimeType: mimeType,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => '$runtimeType#${shortHash(this)}{source=$source, propPath=$propPath, mimeType=$mimeType}';
|
||||||
|
}
|
||||||
|
|
3
lib/widgets/viewer/overlay/notifications.dart
Normal file
3
lib/widgets/viewer/overlay/notifications.dart
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ToggleOverlayNotification extends Notification {}
|
|
@ -10,6 +10,7 @@ import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
import 'package:aves/widgets/common/fx/borders.dart';
|
import 'package:aves/widgets/common/fx/borders.dart';
|
||||||
import 'package:aves/widgets/common/video/controller.dart';
|
import 'package:aves/widgets/common/video/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/viewer/overlay/common.dart';
|
||||||
|
import 'package:aves/widgets/viewer/overlay/notifications.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class VideoControlOverlay extends StatefulWidget {
|
class VideoControlOverlay extends StatefulWidget {
|
||||||
|
@ -209,6 +210,10 @@ class _VideoControlOverlayState extends State<VideoControlOverlay> with SingleTi
|
||||||
} else {
|
} else {
|
||||||
await controller.setDataSource(entry.uri);
|
await controller.setDataSource(entry.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hide overlay
|
||||||
|
await Future.delayed(Durations.iconAnimation);
|
||||||
|
ToggleOverlayNotification().dispatch(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updatePlayPauseIcon() {
|
void _updatePlayPauseIcon() {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'package:aves/widgets/common/magnifier/scale/scale_level.dart';
|
||||||
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
import 'package:aves/widgets/common/magnifier/scale/state.dart';
|
||||||
import 'package:aves/widgets/common/video/controller.dart';
|
import 'package:aves/widgets/common/video/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/hero.dart';
|
import 'package:aves/widgets/viewer/hero.dart';
|
||||||
|
import 'package:aves/widgets/viewer/overlay/notifications.dart';
|
||||||
import 'package:aves/widgets/viewer/visual/error.dart';
|
import 'package:aves/widgets/viewer/visual/error.dart';
|
||||||
import 'package:aves/widgets/viewer/visual/raster.dart';
|
import 'package:aves/widgets/viewer/visual/raster.dart';
|
||||||
import 'package:aves/widgets/viewer/visual/state.dart';
|
import 'package:aves/widgets/viewer/visual/state.dart';
|
||||||
|
@ -30,7 +31,6 @@ class EntryPageView extends StatefulWidget {
|
||||||
final AvesEntry entry;
|
final AvesEntry entry;
|
||||||
final SinglePageInfo page;
|
final SinglePageInfo page;
|
||||||
final Size viewportSize;
|
final Size viewportSize;
|
||||||
final MagnifierTapCallback onTap;
|
|
||||||
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
final List<Tuple2<String, AvesVideoController>> videoControllers;
|
||||||
final VoidCallback onDisposed;
|
final VoidCallback onDisposed;
|
||||||
|
|
||||||
|
@ -41,7 +41,6 @@ class EntryPageView extends StatefulWidget {
|
||||||
this.mainEntry,
|
this.mainEntry,
|
||||||
this.page,
|
this.page,
|
||||||
this.viewportSize,
|
this.viewportSize,
|
||||||
@required this.onTap,
|
|
||||||
@required this.videoControllers,
|
@required this.videoControllers,
|
||||||
this.onDisposed,
|
this.onDisposed,
|
||||||
}) : entry = mainEntry.getPageEntry(page) ?? mainEntry,
|
}) : entry = mainEntry.getPageEntry(page) ?? mainEntry,
|
||||||
|
@ -62,8 +61,6 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
|
|
||||||
Size get viewportSize => widget.viewportSize;
|
Size get viewportSize => widget.viewportSize;
|
||||||
|
|
||||||
MagnifierTapCallback get onTap => widget.onTap;
|
|
||||||
|
|
||||||
static const initialScale = ScaleLevel(ref: ScaleReference.contained);
|
static const initialScale = ScaleLevel(ref: ScaleReference.contained);
|
||||||
static const minScale = ScaleLevel(ref: ScaleReference.contained);
|
static const minScale = ScaleLevel(ref: ScaleReference.contained);
|
||||||
static const maxScale = ScaleLevel(factor: 2.0);
|
static const maxScale = ScaleLevel(factor: 2.0);
|
||||||
|
@ -138,7 +135,7 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
}
|
}
|
||||||
child ??= ErrorView(
|
child ??= ErrorView(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
onTap: onTap == null ? null : () => onTap(null),
|
onTap: _onTap,
|
||||||
);
|
);
|
||||||
return child;
|
return child;
|
||||||
},
|
},
|
||||||
|
@ -162,7 +159,7 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
viewStateNotifier: _viewStateNotifier,
|
viewStateNotifier: _viewStateNotifier,
|
||||||
errorBuilder: (context, error, stackTrace) => ErrorView(
|
errorBuilder: (context, error, stackTrace) => ErrorView(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
onTap: () => onTap?.call(null),
|
onTap: _onTap,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -221,11 +218,13 @@ class _EntryPageViewState extends State<EntryPageView> {
|
||||||
initialScale: initialScale,
|
initialScale: initialScale,
|
||||||
scaleStateCycle: scaleStateCycle,
|
scaleStateCycle: scaleStateCycle,
|
||||||
applyScale: applyScale,
|
applyScale: applyScale,
|
||||||
onTap: onTap == null ? null : (c, d, s, childPosition) => onTap(childPosition),
|
onTap: (c, d, s, o) => _onTap(),
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onTap() => ToggleOverlayNotification().dispatch(context);
|
||||||
|
|
||||||
void _onViewStateChanged(MagnifierState v) {
|
void _onViewStateChanged(MagnifierState v) {
|
||||||
final current = _viewStateNotifier.value;
|
final current = _viewStateNotifier.value;
|
||||||
final viewState = ViewState(v.position, v.scale, current.viewportSize);
|
final viewState = ViewState(v.position, v.scale, current.viewportSize);
|
||||||
|
|
Loading…
Reference in a new issue