Skip to content

Commit

Permalink
fix(mobile): not being able to zoom into live photos (#14608)
Browse files Browse the repository at this point in the history
fix live photo zoom
  • Loading branch information
mertalev authored Dec 11, 2024
1 parent e40c7c5 commit 3053d84
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 33 deletions.
6 changes: 3 additions & 3 deletions mobile/lib/pages/common/gallery_viewer.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class GalleryViewerPage extends HookConsumerWidget {
final localPosition = useRef<Offset?>(null);
final currentIndex = useValueNotifier(initialIndex);
final loadAsset = renderList.loadAsset;
final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider);

Future<void> precacheNextImage(int index) async {
if (!context.mounted) {
Expand Down Expand Up @@ -249,7 +250,6 @@ class GalleryViewerPage extends HookConsumerWidget {
}

PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
ref.read(isPlayingMotionVideoProvider.notifier).playing = false;
var newAsset = loadAsset(index);
final stackId = newAsset.stackId;
if (stackId != null && currentIndex.value == index) {
Expand All @@ -260,7 +260,7 @@ class GalleryViewerPage extends HookConsumerWidget {
}
}

if (newAsset.isImage && !newAsset.isMotionPhoto) {
if (newAsset.isImage && !isPlayingMotionVideo) {
return buildImage(context, newAsset);
}
return buildVideo(context, newAsset);
Expand All @@ -275,7 +275,7 @@ class GalleryViewerPage extends HookConsumerWidget {
body: Stack(
children: [
PhotoViewGallery.builder(
key: const ValueKey('gallery'),
key: ValueKey(isPlayingMotionVideo),
scaleStateChangedCallback: (state) {
final asset = ref.read(currentAssetProvider);
if (asset == null) {
Expand Down
35 changes: 5 additions & 30 deletions mobile/lib/pages/common/native_video_viewer.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class NativeVideoViewerPage extends HookConsumerWidget {
final controller = useState<NativeVideoPlayerController?>(null);
final lastVideoPosition = useRef(-1);
final isBuffering = useRef(false);
final showMotionVideo = useState(false);

// When a video is opened through the timeline, `isCurrent` will immediately be true.
// When swiping from video A to video B, `isCurrent` will initially be true for video A and false for video B.
Expand All @@ -50,38 +49,18 @@ class NativeVideoViewerPage extends HookConsumerWidget {
final isCurrent = currentAsset.value == asset;

// Used to show the placeholder during hero animations for remote videos to avoid a stutter
final isVisible =
useState((Platform.isIOS && asset.isLocal) || asset.isMotionPhoto);
final isVisible = useState(Platform.isIOS && asset.isLocal);

final log = Logger('NativeVideoViewerPage');

ref.listen(isPlayingMotionVideoProvider, (_, value) async {
final videoController = controller.value;
if (!asset.isMotionPhoto || videoController == null || !context.mounted) {
return;
}

showMotionVideo.value = value;
try {
if (value) {
await videoController.seekTo(0);
await videoController.play();
} else {
await videoController.pause();
}
} catch (error) {
log.severe('Error toggling motion video: $error');
}
});

Future<VideoSource?> createSource() async {
if (!context.mounted) {
return null;
}

try {
final local = asset.local;
if (local != null && !asset.isMotionPhoto) {
if (local != null) {
final file = await local.file;
if (file == null) {
throw Exception('No file found for the video');
Expand Down Expand Up @@ -204,9 +183,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;

try {
if (asset.isVideo || showMotionVideo.value) {
await videoController.play();
}
await videoController.play();
await videoController.setVolume(0.9);
} catch (error) {
log.severe('Error playing video: $error');
Expand Down Expand Up @@ -268,8 +245,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
return;
}

if (showMotionVideo.value &&
videoController.playbackInfo?.status == PlaybackStatus.stopped &&
if (videoController.playbackInfo?.status == PlaybackStatus.stopped &&
!ref
.read(appSettingsServiceProvider)
.getSetting<bool>(AppSettingsEnum.loopVideo)) {
Expand Down Expand Up @@ -388,8 +364,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
if (aspectRatio.value != null)
Visibility.maintain(
key: ValueKey(asset),
visible:
(asset.isVideo || showMotionVideo.value) && isVisible.value,
visible: isVisible.value,
child: Center(
key: ValueKey(asset),
child: AspectRatio(
Expand Down
2 changes: 2 additions & 0 deletions mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/collection_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/scroll_notifier.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
import 'package:immich_mobile/widgets/asset_grid/asset_drag_region.dart';
Expand Down Expand Up @@ -206,6 +207,7 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
heroOffset: widget.heroOffset,
onAssetTap: (asset) {
ref.read(currentAssetProvider.notifier).set(asset);
ref.read(isPlayingMotionVideoProvider.notifier).playing = false;
if (asset.isVideo) {
ref.read(showControlsProvider.notifier).show = false;
}
Expand Down

0 comments on commit 3053d84

Please sign in to comment.