fullscreen: fixed video init when deleting previous entry
This commit is contained in:
parent
7fe8dbe13c
commit
1400ff7ecc
1 changed files with 67 additions and 33 deletions
|
@ -33,6 +33,7 @@ class FullscreenBody extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProviderStateMixin {
|
class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProviderStateMixin {
|
||||||
|
ImageEntry _entry;
|
||||||
int _currentHorizontalPage;
|
int _currentHorizontalPage;
|
||||||
ValueNotifier<int> _currentVerticalPage;
|
ValueNotifier<int> _currentVerticalPage;
|
||||||
PageController _horizontalPager, _verticalPager;
|
PageController _horizontalPager, _verticalPager;
|
||||||
|
@ -61,7 +62,8 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_currentHorizontalPage = max(0, entries.indexOf(widget.initialEntry));
|
_entry = widget.initialEntry;
|
||||||
|
_currentHorizontalPage = max(0, entries.indexOf(_entry));
|
||||||
_currentVerticalPage = ValueNotifier(imagePage);
|
_currentVerticalPage = ValueNotifier(imagePage);
|
||||||
_horizontalPager = PageController(initialPage: _currentHorizontalPage);
|
_horizontalPager = PageController(initialPage: _currentHorizontalPage);
|
||||||
_verticalPager = PageController(initialPage: _currentVerticalPage.value);
|
_verticalPager = PageController(initialPage: _currentVerticalPage.value);
|
||||||
|
@ -90,13 +92,14 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
);
|
);
|
||||||
_initVideoController();
|
_initVideoController();
|
||||||
_initOverlay();
|
_initOverlay();
|
||||||
|
_registerWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initOverlay() async {
|
@override
|
||||||
// wait for MaterialPageRoute.transitionDuration
|
void didUpdateWidget(FullscreenBody oldWidget) {
|
||||||
// to show overlay after hero animation is complete
|
super.didUpdateWidget(oldWidget);
|
||||||
await Future.delayed(Duration(milliseconds: (300 * timeDilation).toInt()));
|
_unregisterWidget(oldWidget);
|
||||||
await _onOverlayVisibleChange();
|
_registerWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -104,12 +107,20 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
_overlayAnimationController.dispose();
|
_overlayAnimationController.dispose();
|
||||||
_overlayVisible.removeListener(_onOverlayVisibleChange);
|
_overlayVisible.removeListener(_onOverlayVisibleChange);
|
||||||
_videoControllers.forEach((kv) => kv.item2.dispose());
|
_videoControllers.forEach((kv) => kv.item2.dispose());
|
||||||
|
_unregisterWidget(widget);
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _registerWidget(FullscreenBody widget) {
|
||||||
|
widget.collection.addListener(_onCollectionChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _unregisterWidget(FullscreenBody widget) {
|
||||||
|
widget.collection.removeListener(_onCollectionChange);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final entry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null;
|
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () {
|
onWillPop: () {
|
||||||
if (_currentVerticalPage.value == infoPage) {
|
if (_currentVerticalPage.value == infoPage) {
|
||||||
|
@ -128,7 +139,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
children: [
|
children: [
|
||||||
FullscreenVerticalPageView(
|
FullscreenVerticalPageView(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
entry: entry,
|
entry: _entry,
|
||||||
videoControllers: _videoControllers,
|
videoControllers: _videoControllers,
|
||||||
verticalPager: _verticalPager,
|
verticalPager: _verticalPager,
|
||||||
horizontalPager: _horizontalPager,
|
horizontalPager: _horizontalPager,
|
||||||
|
@ -140,7 +151,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
ValueListenableBuilder<int>(
|
ValueListenableBuilder<int>(
|
||||||
valueListenable: _currentVerticalPage,
|
valueListenable: _currentVerticalPage,
|
||||||
builder: (context, page, child) {
|
builder: (context, page, child) {
|
||||||
final showOverlay = entry != null && page == imagePage;
|
final showOverlay = _entry != null && page == imagePage;
|
||||||
return showOverlay
|
return showOverlay
|
||||||
? FullscreenTopOverlay(
|
? FullscreenTopOverlay(
|
||||||
entries: entries,
|
entries: entries,
|
||||||
|
@ -148,7 +159,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
scale: _topOverlayScale,
|
scale: _topOverlayScale,
|
||||||
viewInsets: _frozenViewInsets,
|
viewInsets: _frozenViewInsets,
|
||||||
viewPadding: _frozenViewPadding,
|
viewPadding: _frozenViewPadding,
|
||||||
onActionSelected: (action) => _actionDelegate.onActionSelected(context, entry, action),
|
onActionSelected: (action) => _actionDelegate.onActionSelected(context, _entry, action),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: const SizedBox.shrink();
|
||||||
},
|
},
|
||||||
|
@ -156,8 +167,8 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
ValueListenableBuilder<int>(
|
ValueListenableBuilder<int>(
|
||||||
valueListenable: _currentVerticalPage,
|
valueListenable: _currentVerticalPage,
|
||||||
builder: (context, page, child) {
|
builder: (context, page, child) {
|
||||||
final showOverlay = entry != null && page == imagePage;
|
final showOverlay = _entry != null && page == imagePage;
|
||||||
final videoController = showOverlay && entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2 : null;
|
final videoController = showOverlay && _entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == _entry.uri, orElse: () => null)?.item2 : null;
|
||||||
return showOverlay
|
return showOverlay
|
||||||
? Positioned(
|
? Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
|
@ -165,7 +176,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
children: [
|
children: [
|
||||||
if (videoController != null)
|
if (videoController != null)
|
||||||
VideoControlOverlay(
|
VideoControlOverlay(
|
||||||
entry: entry,
|
entry: _entry,
|
||||||
controller: videoController,
|
controller: videoController,
|
||||||
scale: _bottomOverlayScale,
|
scale: _bottomOverlayScale,
|
||||||
viewInsets: _frozenViewInsets,
|
viewInsets: _frozenViewInsets,
|
||||||
|
@ -208,12 +219,41 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onHorizontalPageChanged(int page) {
|
||||||
|
_currentHorizontalPage = page;
|
||||||
|
_updateEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCollectionChange() {
|
||||||
|
_updateEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateEntry() {
|
||||||
|
final newEntry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null;
|
||||||
|
if (_entry == newEntry) return;
|
||||||
|
_entry = newEntry;
|
||||||
|
_pauseVideoControllers();
|
||||||
|
_initVideoController();
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// system UI
|
||||||
|
|
||||||
void _onLeave() => _showSystemUI();
|
void _onLeave() => _showSystemUI();
|
||||||
|
|
||||||
void _showSystemUI() => SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
void _showSystemUI() => SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
||||||
|
|
||||||
void _hideSystemUI() => SystemChrome.setEnabledSystemUIOverlays([]);
|
void _hideSystemUI() => SystemChrome.setEnabledSystemUIOverlays([]);
|
||||||
|
|
||||||
|
// overlay
|
||||||
|
|
||||||
|
Future<void> _initOverlay() async {
|
||||||
|
// wait for MaterialPageRoute.transitionDuration
|
||||||
|
// to show overlay after hero animation is complete
|
||||||
|
await Future.delayed(Duration(milliseconds: (300 * timeDilation).toInt()));
|
||||||
|
await _onOverlayVisibleChange();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _onOverlayVisibleChange() async {
|
Future<void> _onOverlayVisibleChange() async {
|
||||||
if (_overlayVisible.value) {
|
if (_overlayVisible.value) {
|
||||||
_showSystemUI();
|
_showSystemUI();
|
||||||
|
@ -231,20 +271,14 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onHorizontalPageChanged(int page) {
|
// video controller
|
||||||
_currentHorizontalPage = page;
|
|
||||||
_pauseVideoControllers();
|
|
||||||
_initVideoController();
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pauseVideoControllers() => _videoControllers.forEach((e) => e.item2.pause());
|
void _pauseVideoControllers() => _videoControllers.forEach((e) => e.item2.pause());
|
||||||
|
|
||||||
void _initVideoController() {
|
void _initVideoController() {
|
||||||
final entry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null;
|
if (_entry == null || !_entry.isVideo) return;
|
||||||
if (entry == null || !entry.isVideo) return;
|
|
||||||
|
|
||||||
final uri = entry.uri;
|
final uri = _entry.uri;
|
||||||
var controllerEntry = _videoControllers.firstWhere((kv) => kv.item1 == uri, orElse: () => null);
|
var controllerEntry = _videoControllers.firstWhere((kv) => kv.item1 == uri, orElse: () => null);
|
||||||
if (controllerEntry != null) {
|
if (controllerEntry != null) {
|
||||||
_videoControllers.remove(controllerEntry);
|
_videoControllers.remove(controllerEntry);
|
||||||
|
@ -323,17 +357,6 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
|
||||||
widget.entry.imageChangeNotifier.removeListener(_onImageChange);
|
widget.entry.imageChangeNotifier.removeListener(_onImageChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onVerticalPageControllerChange() {
|
|
||||||
_backgroundColorNotifier.value = _backgroundColorNotifier.value.withOpacity(min(1.0, widget.verticalPager.page));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onImageChange() async {
|
|
||||||
await UriImage(entry.uri).evict();
|
|
||||||
if (entry.path != null) await FileImage(File(entry.path)).evict();
|
|
||||||
// rebuild to refresh the Image inside ImagePage
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final onScaleChanged = (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial);
|
final onScaleChanged = (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial);
|
||||||
|
@ -386,4 +409,15 @@ class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onVerticalPageControllerChange() {
|
||||||
|
_backgroundColorNotifier.value = _backgroundColorNotifier.value.withOpacity(min(1.0, widget.verticalPager.page));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onImageChange() async {
|
||||||
|
await UriImage(entry.uri).evict();
|
||||||
|
if (entry.path != null) await FileImage(File(entry.path)).evict();
|
||||||
|
// rebuild to refresh the Image inside ImagePage
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue