mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
fix controls when swiping between image and video
This commit is contained in:
parent
190dbb0042
commit
0010eda67f
6 changed files with 51 additions and 45 deletions
|
@ -168,6 +168,9 @@ class Asset {
|
|||
@ignore
|
||||
bool get isImage => type == AssetType.image;
|
||||
|
||||
@ignore
|
||||
bool get isVideo => type == AssetType.video;
|
||||
|
||||
@ignore
|
||||
bool get isMotionPhoto => livePhotoVideoId != null;
|
||||
|
||||
|
|
|
@ -79,10 +79,8 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
ref.listen(
|
||||
videoPlaybackValueProvider.select(
|
||||
(playback) => playback.state == VideoPlaybackState.playing,
|
||||
), (wasPlaying, isPlaying) {
|
||||
if (wasPlaying != null && wasPlaying && !isPlaying) {
|
||||
isPlayingMotionVideo.value = false;
|
||||
}
|
||||
), (_, isPlaying) {
|
||||
isPlayingMotionVideo.value = isPlaying;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -271,11 +269,13 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
onTapDown: (_, __, ___) {
|
||||
ref.read(showControlsProvider.notifier).toggle();
|
||||
},
|
||||
onLongPressStart: (_, __, ___) {
|
||||
if (asset.livePhotoVideoId != null) {
|
||||
isPlayingMotionVideo.value = true;
|
||||
}
|
||||
},
|
||||
onLongPressStart: asset.isMotionPhoto
|
||||
? (_, __, ___) {
|
||||
if (asset.isMotionPhoto) {
|
||||
isPlayingMotionVideo.value = true;
|
||||
}
|
||||
}
|
||||
: null,
|
||||
imageProvider: ImmichImage.imageProvider(asset: asset),
|
||||
heroAttributes: PhotoViewHeroAttributes(
|
||||
tag: getHeroTag(asset),
|
||||
|
@ -336,10 +336,6 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
PhotoViewGalleryPageOptions buildAsset(BuildContext context, int index) {
|
||||
final newAsset = index == currentIndex.value ? asset : loadAsset(index);
|
||||
|
||||
if (newAsset.isImage) {
|
||||
ref.read(showControlsProvider.notifier).show = false;
|
||||
}
|
||||
|
||||
if (newAsset.isImage && !isPlayingMotionVideo.value) {
|
||||
return buildImage(context, newAsset);
|
||||
}
|
||||
|
@ -357,8 +353,11 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
PhotoViewGallery.builder(
|
||||
key: ValueKey(asset),
|
||||
scaleStateChangedCallback: (state) {
|
||||
isZoomed.value = state != PhotoViewScaleState.initial;
|
||||
ref.read(showControlsProvider.notifier).show = !isZoomed.value;
|
||||
if (asset.isImage && !isPlayingMotionVideo.value) {
|
||||
isZoomed.value = state != PhotoViewScaleState.initial;
|
||||
ref.read(showControlsProvider.notifier).show =
|
||||
!isZoomed.value;
|
||||
}
|
||||
},
|
||||
// wantKeepAlive: true,
|
||||
gaplessPlayback: true,
|
||||
|
@ -396,15 +395,15 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
|
||||
final newAsset =
|
||||
value == currentIndex.value ? asset : loadAsset(value);
|
||||
if (!newAsset.isImage || newAsset.isMotionPhoto) {
|
||||
ref.read(videoPlaybackValueProvider.notifier).reset();
|
||||
}
|
||||
|
||||
currentIndex.value = value;
|
||||
stackIndex.value = -1;
|
||||
isPlayingMotionVideo.value = false;
|
||||
|
||||
ref.read(currentAssetProvider.notifier).set(newAsset);
|
||||
if (newAsset.isVideo || newAsset.isMotionPhoto) {
|
||||
ref.read(videoPlaybackValueProvider.notifier).reset();
|
||||
}
|
||||
|
||||
// Wait for page change animation to finish, then precache the next image
|
||||
Timer(const Duration(milliseconds: 400), () {
|
||||
|
@ -418,11 +417,8 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
left: 0,
|
||||
right: 0,
|
||||
child: GalleryAppBar(
|
||||
asset: asset,
|
||||
showInfo: showInfo,
|
||||
isPlayingVideo: isPlayingMotionVideo.value,
|
||||
onToggleMotionVideo: () =>
|
||||
isPlayingMotionVideo.value = !isPlayingMotionVideo.value,
|
||||
isPlayingMotionVideo: isPlayingMotionVideo,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
|
@ -444,10 +440,7 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||
controller: controller,
|
||||
showStack: showStack,
|
||||
stackIndex: stackIndex.value,
|
||||
asset: asset,
|
||||
assetIndex: currentIndex,
|
||||
showVideoPlayerControls:
|
||||
!asset.isImage && !asset.isMotionPhoto,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -184,8 +184,8 @@ class NativeVideoViewerPage extends HookConsumerWidget {
|
|||
try {
|
||||
if (mute && playbackInfo.volume != 0.0) {
|
||||
await playerController.setVolume(0.0);
|
||||
} else if (!mute && playbackInfo.volume != 0.7) {
|
||||
await playerController.setVolume(0.7);
|
||||
} else if (!mute && playbackInfo.volume != 0.9) {
|
||||
await playerController.setVolume(0.9);
|
||||
}
|
||||
} catch (error) {
|
||||
log.severe('Error setting volume: $error');
|
||||
|
|
|
@ -10,6 +10,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
|||
import 'package:immich_mobile/providers/album/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/asset_stack.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/download.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
||||
import 'package:immich_mobile/services/stack.service.dart';
|
||||
|
@ -26,12 +27,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
|||
import 'package:immich_mobile/pages/editing/edit.page.dart';
|
||||
|
||||
class BottomGalleryBar extends ConsumerWidget {
|
||||
final Asset asset;
|
||||
final ValueNotifier<int> assetIndex;
|
||||
final bool showStack;
|
||||
final int stackIndex;
|
||||
final ValueNotifier<int> totalAssets;
|
||||
final bool showVideoPlayerControls;
|
||||
final PageController controller;
|
||||
final RenderList renderList;
|
||||
|
||||
|
@ -39,17 +38,20 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||
super.key,
|
||||
required this.showStack,
|
||||
required this.stackIndex,
|
||||
required this.asset,
|
||||
required this.assetIndex,
|
||||
required this.controller,
|
||||
required this.totalAssets,
|
||||
required this.showVideoPlayerControls,
|
||||
required this.renderList,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final asset = ref.watch(currentAssetProvider);
|
||||
if (asset == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
final isOwner = asset.ownerId == ref.watch(currentUserProvider)?.isarId;
|
||||
final showControls = ref.watch(showControlsProvider);
|
||||
|
||||
final stackItems = showStack && asset.stackCount > 0
|
||||
? ref.watch(assetStackStateProvider(asset))
|
||||
|
@ -324,7 +326,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||
},
|
||||
];
|
||||
return IgnorePointer(
|
||||
ignoring: !ref.watch(showControlsProvider),
|
||||
ignoring: !showControls,
|
||||
child: AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
opacity: ref.watch(showControlsProvider) ? 1.0 : 0.0,
|
||||
|
@ -341,7 +343,7 @@ class BottomGalleryBar extends ConsumerWidget {
|
|||
padding: EdgeInsets.only(top: 40.0),
|
||||
child: Column(
|
||||
children: [
|
||||
if (showVideoPlayerControls) const VideoControls(),
|
||||
if (asset.isVideo) const VideoControls(),
|
||||
BottomNavigationBar(
|
||||
elevation: 0.0,
|
||||
backgroundColor: Colors.transparent,
|
||||
|
|
|
@ -17,10 +17,15 @@ class CustomVideoPlayerControls extends HookConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final showControls = ref.watch(showControlsProvider);
|
||||
// A timer to hide the controls
|
||||
final hideTimer = useTimer(
|
||||
hideTimerDuration,
|
||||
() {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final state = ref.read(videoPlaybackValueProvider).state;
|
||||
// Do not hide on paused
|
||||
if (state != VideoPlaybackState.paused) {
|
||||
|
@ -66,7 +71,7 @@ class CustomVideoPlayerControls extends HookConsumerWidget {
|
|||
behavior: HitTestBehavior.opaque,
|
||||
onTap: showControlsAndStartHideTimer,
|
||||
child: AbsorbPointer(
|
||||
absorbing: !ref.watch(showControlsProvider),
|
||||
absorbing: !showControls,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (showBuffering)
|
||||
|
@ -84,7 +89,7 @@ class CustomVideoPlayerControls extends HookConsumerWidget {
|
|||
iconColor: Colors.white,
|
||||
isFinished: state == VideoPlaybackState.completed,
|
||||
isPlaying: state == VideoPlaybackState.playing,
|
||||
show: ref.watch(showControlsProvider),
|
||||
show: showControls,
|
||||
onPressed: togglePlay,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/providers/album/current_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
||||
import 'package:immich_mobile/widgets/album/add_to_album_bottom_sheet.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/download.provider.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
||||
|
@ -19,23 +20,24 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
|||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||
|
||||
class GalleryAppBar extends ConsumerWidget {
|
||||
final Asset asset;
|
||||
final void Function() showInfo;
|
||||
final void Function() onToggleMotionVideo;
|
||||
final bool isPlayingVideo;
|
||||
final ValueNotifier<bool> isPlayingMotionVideo;
|
||||
|
||||
const GalleryAppBar({
|
||||
super.key,
|
||||
required this.asset,
|
||||
required this.showInfo,
|
||||
required this.onToggleMotionVideo,
|
||||
required this.isPlayingVideo,
|
||||
required this.isPlayingMotionVideo,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final asset = ref.watch(currentAssetProvider);
|
||||
if (asset == null) {
|
||||
return const SizedBox();
|
||||
}
|
||||
final album = ref.watch(currentAlbumProvider);
|
||||
final isOwner = asset.ownerId == ref.watch(currentUserProvider)?.isarId;
|
||||
final showControls = ref.watch(showControlsProvider);
|
||||
|
||||
final isPartner = ref
|
||||
.watch(partnerSharedWithProvider)
|
||||
|
@ -98,23 +100,24 @@ class GalleryAppBar extends ConsumerWidget {
|
|||
}
|
||||
|
||||
return IgnorePointer(
|
||||
ignoring: !ref.watch(showControlsProvider),
|
||||
ignoring: !showControls,
|
||||
child: AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
opacity: ref.watch(showControlsProvider) ? 1.0 : 0.0,
|
||||
opacity: showControls ? 1.0 : 0.0,
|
||||
child: Container(
|
||||
color: Colors.black.withOpacity(0.4),
|
||||
child: TopControlAppBar(
|
||||
isOwner: isOwner,
|
||||
isPartner: isPartner,
|
||||
isPlayingMotionVideo: isPlayingVideo,
|
||||
isPlayingMotionVideo: isPlayingMotionVideo.value,
|
||||
asset: asset,
|
||||
onMoreInfoPressed: showInfo,
|
||||
onFavorite: toggleFavorite,
|
||||
onRestorePressed: () => handleRestore(asset),
|
||||
onUploadPressed: asset.isLocal ? () => handleUpload(asset) : null,
|
||||
onDownloadPressed: asset.isLocal ? null : handleDownloadAsset,
|
||||
onToggleMotionVideo: onToggleMotionVideo,
|
||||
onToggleMotionVideo: () =>
|
||||
isPlayingMotionVideo.value = !isPlayingMotionVideo.value,
|
||||
onAddToAlbumPressed: () => addToAlbum(asset),
|
||||
onActivitiesPressed: handleActivities,
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue