mirror of
https://github.com/immich-app/immich.git
synced 2025-06-22 23:11:06 -04:00
fix(mobile): not being able to zoom into live photos (#14608)
fix live photo zoom
This commit is contained in:
parent
e40c7c51ee
commit
3053d84e49
@ -61,6 +61,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
final localPosition = useRef<Offset?>(null);
|
final localPosition = useRef<Offset?>(null);
|
||||||
final currentIndex = useValueNotifier(initialIndex);
|
final currentIndex = useValueNotifier(initialIndex);
|
||||||
final loadAsset = renderList.loadAsset;
|
final loadAsset = renderList.loadAsset;
|
||||||
|
final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider);
|
||||||
|
|
||||||
Future<void> precacheNextImage(int index) async {
|
Future<void> precacheNextImage(int index) async {
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
@ -249,7 +250,6 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
|
PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
|
||||||
ref.read(isPlayingMotionVideoProvider.notifier).playing = false;
|
|
||||||
var newAsset = loadAsset(index);
|
var newAsset = loadAsset(index);
|
||||||
final stackId = newAsset.stackId;
|
final stackId = newAsset.stackId;
|
||||||
if (stackId != null && currentIndex.value == index) {
|
if (stackId != null && currentIndex.value == index) {
|
||||||
@ -260,7 +260,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAsset.isImage && !newAsset.isMotionPhoto) {
|
if (newAsset.isImage && !isPlayingMotionVideo) {
|
||||||
return buildImage(context, newAsset);
|
return buildImage(context, newAsset);
|
||||||
}
|
}
|
||||||
return buildVideo(context, newAsset);
|
return buildVideo(context, newAsset);
|
||||||
@ -275,7 +275,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
PhotoViewGallery.builder(
|
PhotoViewGallery.builder(
|
||||||
key: const ValueKey('gallery'),
|
key: ValueKey(isPlayingMotionVideo),
|
||||||
scaleStateChangedCallback: (state) {
|
scaleStateChangedCallback: (state) {
|
||||||
final asset = ref.read(currentAssetProvider);
|
final asset = ref.read(currentAssetProvider);
|
||||||
if (asset == null) {
|
if (asset == null) {
|
||||||
|
@ -40,7 +40,6 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
final controller = useState<NativeVideoPlayerController?>(null);
|
final controller = useState<NativeVideoPlayerController?>(null);
|
||||||
final lastVideoPosition = useRef(-1);
|
final lastVideoPosition = useRef(-1);
|
||||||
final isBuffering = useRef(false);
|
final isBuffering = useRef(false);
|
||||||
final showMotionVideo = useState(false);
|
|
||||||
|
|
||||||
// When a video is opened through the timeline, `isCurrent` will immediately be true.
|
// 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.
|
// When swiping from video A to video B, `isCurrent` will initially be true for video A and false for video B.
|
||||||
@ -50,30 +49,10 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
final isCurrent = currentAsset.value == asset;
|
final isCurrent = currentAsset.value == asset;
|
||||||
|
|
||||||
// Used to show the placeholder during hero animations for remote videos to avoid a stutter
|
// Used to show the placeholder during hero animations for remote videos to avoid a stutter
|
||||||
final isVisible =
|
final isVisible = useState(Platform.isIOS && asset.isLocal);
|
||||||
useState((Platform.isIOS && asset.isLocal) || asset.isMotionPhoto);
|
|
||||||
|
|
||||||
final log = Logger('NativeVideoViewerPage');
|
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 {
|
Future<VideoSource?> createSource() async {
|
||||||
if (!context.mounted) {
|
if (!context.mounted) {
|
||||||
return null;
|
return null;
|
||||||
@ -81,7 +60,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final local = asset.local;
|
final local = asset.local;
|
||||||
if (local != null && !asset.isMotionPhoto) {
|
if (local != null) {
|
||||||
final file = await local.file;
|
final file = await local.file;
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
throw Exception('No file found for the video');
|
throw Exception('No file found for the video');
|
||||||
@ -204,9 +183,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;
|
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (asset.isVideo || showMotionVideo.value) {
|
|
||||||
await videoController.play();
|
await videoController.play();
|
||||||
}
|
|
||||||
await videoController.setVolume(0.9);
|
await videoController.setVolume(0.9);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.severe('Error playing video: $error');
|
log.severe('Error playing video: $error');
|
||||||
@ -268,8 +245,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showMotionVideo.value &&
|
if (videoController.playbackInfo?.status == PlaybackStatus.stopped &&
|
||||||
videoController.playbackInfo?.status == PlaybackStatus.stopped &&
|
|
||||||
!ref
|
!ref
|
||||||
.read(appSettingsServiceProvider)
|
.read(appSettingsServiceProvider)
|
||||||
.getSetting<bool>(AppSettingsEnum.loopVideo)) {
|
.getSetting<bool>(AppSettingsEnum.loopVideo)) {
|
||||||
@ -388,8 +364,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||||||
if (aspectRatio.value != null)
|
if (aspectRatio.value != null)
|
||||||
Visibility.maintain(
|
Visibility.maintain(
|
||||||
key: ValueKey(asset),
|
key: ValueKey(asset),
|
||||||
visible:
|
visible: isVisible.value,
|
||||||
(asset.isVideo || showMotionVideo.value) && isVisible.value,
|
|
||||||
child: Center(
|
child: Center(
|
||||||
key: ValueKey(asset),
|
key: ValueKey(asset),
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
|
@ -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/collection_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/theme_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/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/scroll_notifier.provider.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_drag_region.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_drag_region.dart';
|
||||||
@ -206,6 +207,7 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
|
|||||||
heroOffset: widget.heroOffset,
|
heroOffset: widget.heroOffset,
|
||||||
onAssetTap: (asset) {
|
onAssetTap: (asset) {
|
||||||
ref.read(currentAssetProvider.notifier).set(asset);
|
ref.read(currentAssetProvider.notifier).set(asset);
|
||||||
|
ref.read(isPlayingMotionVideoProvider.notifier).playing = false;
|
||||||
if (asset.isVideo) {
|
if (asset.isVideo) {
|
||||||
ref.read(showControlsProvider.notifier).show = false;
|
ref.read(showControlsProvider.notifier).show = false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user