mirror of
https://github.com/immich-app/immich.git
synced 2026-03-22 14:39:25 +03:00
fix(mobile): asset viewer hero animation (#26545)
The image in the photo view has no height, and is therefore entirely unconstrained. This causes the image to take up the full height of the viewport during the hero animation, which can make look out of sync. In some other cases, it can stretch or resize the image to fill the entire viewport.
This commit is contained in:
@@ -14,7 +14,6 @@ import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_details.wi
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||
@@ -329,10 +328,19 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||
);
|
||||
}
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
PhotoView.customChild(
|
||||
final Size childSize;
|
||||
if (displayAsset.width != null && displayAsset.height != null) {
|
||||
final r = displayAsset.width! / displayAsset.height!;
|
||||
final w = math.min(context.width, context.height * r);
|
||||
childSize = Size(w, w / r);
|
||||
} else {
|
||||
childSize = Size(context.height, context.height);
|
||||
}
|
||||
|
||||
return PhotoView.customChild(
|
||||
key: Key(displayAsset.heroTag),
|
||||
childSize: childSize,
|
||||
filterQuality: FilterQuality.low,
|
||||
onDragStart: _onDragStart,
|
||||
onDragUpdate: _onDragUpdate,
|
||||
onDragEnd: _onDragEnd,
|
||||
@@ -345,24 +353,15 @@ class _AssetPageState extends ConsumerState<AssetPage> {
|
||||
onPageBuild: _onPageBuild,
|
||||
enablePanAlways: true,
|
||||
backgroundDecoration: backgroundDecoration,
|
||||
child: SizedBox(
|
||||
width: context.width,
|
||||
height: context.height,
|
||||
child: NativeVideoViewer(
|
||||
key: _NativeVideoViewerKey(displayAsset.heroTag),
|
||||
asset: displayAsset,
|
||||
image: Image(
|
||||
image: getFullImageProvider(displayAsset, size: context.sizeData),
|
||||
image: getFullImageProvider(displayAsset, size: childSize),
|
||||
fit: BoxFit.contain,
|
||||
height: context.height,
|
||||
width: context.width,
|
||||
alignment: Alignment.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Center(child: VideoViewerControls()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:immich_mobile/domain/services/setting.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
||||
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
||||
@@ -393,13 +394,9 @@ class NativeVideoViewer extends HookConsumerWidget {
|
||||
if (aspectRatio.value != null && !isCasting)
|
||||
Visibility.maintain(
|
||||
visible: isVisible.value,
|
||||
child: Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatio.value!,
|
||||
child: isCurrent ? NativeVideoPlayerView(onViewReady: initController) : null,
|
||||
),
|
||||
),
|
||||
child: NativeVideoPlayerView(onViewReady: initController),
|
||||
),
|
||||
const Center(child: VideoViewerControls()),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -420,7 +420,11 @@ class PhotoViewCoreState extends State<PhotoViewCore>
|
||||
|
||||
Widget _buildChild() {
|
||||
return widget.hasCustomChild
|
||||
? widget.customChild!
|
||||
? SizedBox(
|
||||
width: scaleBoundaries.childSize.width * scale,
|
||||
height: scaleBoundaries.childSize.height * scale,
|
||||
child: widget.customChild!,
|
||||
)
|
||||
: Image(
|
||||
key: widget.heroAttributes?.tag != null ? ObjectKey(widget.heroAttributes!.tag) : null,
|
||||
image: widget.imageProvider!,
|
||||
@@ -428,7 +432,7 @@ class PhotoViewCoreState extends State<PhotoViewCore>
|
||||
gaplessPlayback: widget.gaplessPlayback ?? false,
|
||||
filterQuality: widget.filterQuality,
|
||||
width: scaleBoundaries.childSize.width * scale,
|
||||
fit: BoxFit.cover,
|
||||
fit: BoxFit.contain,
|
||||
isAntiAlias: widget.filterQuality == FilterQuality.high,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user