From 5ab05e57fae2e3b8ae111c9fa60163ced0bb69f3 Mon Sep 17 00:00:00 2001 From: Thomas <9749173+uhthomas@users.noreply.github.com> Date: Thu, 5 Mar 2026 17:45:21 +0000 Subject: [PATCH] fix(mobile): inconsistent asset details background (#26634) The background of the photo view does not extend below the height of the viewport, and so the asset details fade in over black with the photo view, and the standard surface colour scheme of the scaffold for the rest. This leads to a janky animation. We can't change the background of the scaffold to black, as it in turn makes the iOS bouncing scroll physics cut off incorrectly. The best fix is to remove background decoration from the photo view, and defer to the parent to colour the background. Co-authored-by: Alex --- .../asset_viewer/asset_page.widget.dart | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart index ea7ff51fa6..abb7b779fe 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_page.widget.dart @@ -292,7 +292,6 @@ class _AssetPageState extends ConsumerState { required PhotoViewHeroAttributes? heroAttributes, required bool isCurrent, required bool isPlayingMotionVideo, - required BoxDecoration backgroundDecoration, }) { final size = context.sizeData; @@ -303,7 +302,6 @@ class _AssetPageState extends ConsumerState { imageProvider: getFullImageProvider(asset, size: size), heroAttributes: heroAttributes, loadingBuilder: (context, progress, index) => const Center(child: ImmichLoadingIndicator()), - backgroundDecoration: backgroundDecoration, gaplessPlayback: true, filterQuality: FilterQuality.high, tightMode: true, @@ -345,7 +343,6 @@ class _AssetPageState extends ConsumerState { tightMode: true, onPageBuild: _onPageBuild, enablePanAlways: true, - backgroundDecoration: backgroundDecoration, child: NativeVideoViewer( key: _NativeVideoViewerKey(asset.heroTag), asset: asset, @@ -397,41 +394,43 @@ class _AssetPageState extends ConsumerState { SingleChildScrollView( controller: _scrollController, physics: const SnapScrollPhysics(), - child: Stack( - children: [ - SizedBox( - width: viewportWidth, - height: viewportHeight, - child: _buildPhotoView( - asset: displayAsset, - heroAttributes: isCurrent - ? PhotoViewHeroAttributes(tag: '${asset.heroTag}_${widget.heroOffset}') - : null, - isCurrent: isCurrent, - isPlayingMotionVideo: isPlayingMotionVideo, - backgroundDecoration: BoxDecoration(color: _showingDetails ? Colors.black : Colors.transparent), + child: ColoredBox( + color: _showingDetails ? Colors.black : Colors.transparent, + child: Stack( + children: [ + SizedBox( + width: viewportWidth, + height: viewportHeight, + child: _buildPhotoView( + asset: displayAsset, + heroAttributes: isCurrent + ? PhotoViewHeroAttributes(tag: '${asset.heroTag}_${widget.heroOffset}') + : null, + isCurrent: isCurrent, + isPlayingMotionVideo: isPlayingMotionVideo, + ), ), - ), - IgnorePointer( - ignoring: !_showingDetails, - child: Column( - children: [ - SizedBox(height: detailsOffset), - GestureDetector( - onVerticalDragStart: _beginDrag, - onVerticalDragUpdate: _updateDrag, - onVerticalDragEnd: _endDrag, - onVerticalDragCancel: _onDragCancel, - child: AnimatedOpacity( - opacity: _showingDetails ? 1.0 : 0.0, - duration: Durations.short2, - child: AssetDetails(asset: displayAsset, minHeight: viewportHeight - snapTarget), + IgnorePointer( + ignoring: !_showingDetails, + child: Column( + children: [ + SizedBox(height: detailsOffset), + GestureDetector( + onVerticalDragStart: _beginDrag, + onVerticalDragUpdate: _updateDrag, + onVerticalDragEnd: _endDrag, + onVerticalDragCancel: _onDragCancel, + child: AnimatedOpacity( + opacity: _showingDetails ? 1.0 : 0.0, + duration: Durations.short2, + child: AssetDetails(asset: displayAsset, minHeight: viewportHeight - snapTarget), + ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), if (stackChildren != null && stackChildren.isNotEmpty)