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 <alex.tran1502@gmail.com>
This commit is contained in:
Thomas
2026-03-05 17:45:21 +00:00
committed by GitHub
parent ba3f114625
commit 5ab05e57fa

View File

@@ -292,7 +292,6 @@ class _AssetPageState extends ConsumerState<AssetPage> {
required PhotoViewHeroAttributes? heroAttributes, required PhotoViewHeroAttributes? heroAttributes,
required bool isCurrent, required bool isCurrent,
required bool isPlayingMotionVideo, required bool isPlayingMotionVideo,
required BoxDecoration backgroundDecoration,
}) { }) {
final size = context.sizeData; final size = context.sizeData;
@@ -303,7 +302,6 @@ class _AssetPageState extends ConsumerState<AssetPage> {
imageProvider: getFullImageProvider(asset, size: size), imageProvider: getFullImageProvider(asset, size: size),
heroAttributes: heroAttributes, heroAttributes: heroAttributes,
loadingBuilder: (context, progress, index) => const Center(child: ImmichLoadingIndicator()), loadingBuilder: (context, progress, index) => const Center(child: ImmichLoadingIndicator()),
backgroundDecoration: backgroundDecoration,
gaplessPlayback: true, gaplessPlayback: true,
filterQuality: FilterQuality.high, filterQuality: FilterQuality.high,
tightMode: true, tightMode: true,
@@ -345,7 +343,6 @@ class _AssetPageState extends ConsumerState<AssetPage> {
tightMode: true, tightMode: true,
onPageBuild: _onPageBuild, onPageBuild: _onPageBuild,
enablePanAlways: true, enablePanAlways: true,
backgroundDecoration: backgroundDecoration,
child: NativeVideoViewer( child: NativeVideoViewer(
key: _NativeVideoViewerKey(asset.heroTag), key: _NativeVideoViewerKey(asset.heroTag),
asset: asset, asset: asset,
@@ -397,41 +394,43 @@ class _AssetPageState extends ConsumerState<AssetPage> {
SingleChildScrollView( SingleChildScrollView(
controller: _scrollController, controller: _scrollController,
physics: const SnapScrollPhysics(), physics: const SnapScrollPhysics(),
child: Stack( child: ColoredBox(
children: [ color: _showingDetails ? Colors.black : Colors.transparent,
SizedBox( child: Stack(
width: viewportWidth, children: [
height: viewportHeight, SizedBox(
child: _buildPhotoView( width: viewportWidth,
asset: displayAsset, height: viewportHeight,
heroAttributes: isCurrent child: _buildPhotoView(
? PhotoViewHeroAttributes(tag: '${asset.heroTag}_${widget.heroOffset}') asset: displayAsset,
: null, heroAttributes: isCurrent
isCurrent: isCurrent, ? PhotoViewHeroAttributes(tag: '${asset.heroTag}_${widget.heroOffset}')
isPlayingMotionVideo: isPlayingMotionVideo, : null,
backgroundDecoration: BoxDecoration(color: _showingDetails ? Colors.black : Colors.transparent), isCurrent: isCurrent,
isPlayingMotionVideo: isPlayingMotionVideo,
),
), ),
), IgnorePointer(
IgnorePointer( ignoring: !_showingDetails,
ignoring: !_showingDetails, child: Column(
child: Column( children: [
children: [ SizedBox(height: detailsOffset),
SizedBox(height: detailsOffset), GestureDetector(
GestureDetector( onVerticalDragStart: _beginDrag,
onVerticalDragStart: _beginDrag, onVerticalDragUpdate: _updateDrag,
onVerticalDragUpdate: _updateDrag, onVerticalDragEnd: _endDrag,
onVerticalDragEnd: _endDrag, onVerticalDragCancel: _onDragCancel,
onVerticalDragCancel: _onDragCancel, child: AnimatedOpacity(
child: AnimatedOpacity( opacity: _showingDetails ? 1.0 : 0.0,
opacity: _showingDetails ? 1.0 : 0.0, duration: Durations.short2,
duration: Durations.short2, child: AssetDetails(asset: displayAsset, minHeight: viewportHeight - snapTarget),
child: AssetDetails(asset: displayAsset, minHeight: viewportHeight - snapTarget), ),
), ),
), ],
], ),
), ),
), ],
], ),
), ),
), ),
if (stackChildren != null && stackChildren.isNotEmpty) if (stackChildren != null && stackChildren.isNotEmpty)