fix(mobile): prevent live photo from getting stuck during dismiss animation

This commit is contained in:
LeLunZ
2026-04-25 16:36:50 +02:00
parent 6b3e07dc52
commit 5271863291
@@ -48,6 +48,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
bool _showingDetails = false; bool _showingDetails = false;
bool _isZoomed = false; bool _isZoomed = false;
// Frozen during dismiss drag + settle to prevent widget tree swap mid-animation.
bool _frozenMotionPlaying = false;
bool _dismissSettling = false;
final _scrollController = SnapScrollController(); final _scrollController = SnapScrollController();
double _snapOffset = 0.0; double _snapOffset = 0.0;
@@ -135,6 +138,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
> 0 => _DragIntent.dismiss, > 0 => _DragIntent.dismiss,
_ => _DragIntent.none, _ => _DragIntent.none,
}; };
if (_dragIntent == _DragIntent.dismiss) {
_frozenMotionPlaying = ref.read(isPlayingMotionVideoProvider);
}
} }
switch (_dragIntent) { switch (_dragIntent) {
@@ -172,12 +178,18 @@ class _AssetPageState extends ConsumerState<AssetPage> {
context.maybePop(); context.maybePop();
return; return;
} }
_viewController?.animateMultiple(
position: _initialPhotoViewState.position,
scale: _viewController?.initialScale ?? _initialPhotoViewState.scale,
rotation: _initialPhotoViewState.rotation,
);
_viewer.setOpacity(1.0); _viewer.setOpacity(1.0);
_dismissSettling = true;
_viewController
?.animateMultiple(
position: _initialPhotoViewState.position,
scale: _viewController?.initialScale ?? _initialPhotoViewState.scale,
rotation: _initialPhotoViewState.rotation,
)
.whenComplete(() {
if (!mounted) return;
setState(() => _dismissSettling = false);
});
} }
} }
@@ -355,7 +367,10 @@ class _AssetPageState extends ConsumerState<AssetPage> {
final currentHeroTag = ref.watch(assetViewerProvider.select((s) => s.currentAsset?.heroTag)); final currentHeroTag = ref.watch(assetViewerProvider.select((s) => s.currentAsset?.heroTag));
_showingDetails = ref.watch(assetViewerProvider.select((s) => s.showingDetails)); _showingDetails = ref.watch(assetViewerProvider.select((s) => s.showingDetails));
final stackIndex = ref.watch(assetViewerProvider.select((s) => s.stackIndex)); final stackIndex = ref.watch(assetViewerProvider.select((s) => s.stackIndex));
final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider); final liveMotionPlaying = ref.watch(isPlayingMotionVideoProvider);
final isPlayingMotionVideo = (_dragIntent == _DragIntent.dismiss || _dismissSettling)
? _frozenMotionPlaying
: liveMotionPlaying;
final asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index); final asset = ref.read(timelineServiceProvider).getAssetSafe(widget.index);
if (asset == null) { if (asset == null) {