0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-02-04 01:09:14 -05:00

feat(mobile): Tap to enter immersive mode on gallery viewer (#1546)

This commit is contained in:
martyfuhry 2023-02-05 07:57:07 -05:00 committed by GitHub
parent bb0b2a1f53
commit f38c7a4b7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 5 deletions

View file

@ -52,6 +52,7 @@ class GalleryViewerPage extends HookConsumerWidget {
final showAppBar = useState<bool>(true); final showAppBar = useState<bool>(true);
final indexOfAsset = useState(assetList.indexOf(asset)); final indexOfAsset = useState(assetList.indexOf(asset));
final isPlayingMotionVideo = useState(false); final isPlayingMotionVideo = useState(false);
final isPlayingVideo = useState(false);
late Offset localPosition; late Offset localPosition;
final authToken = 'Bearer ${box.get(accessTokenKey)}'; final authToken = 'Bearer ${box.get(accessTokenKey)}';
@ -233,9 +234,13 @@ class GalleryViewerPage extends HookConsumerWidget {
} }
buildAppBar() { buildAppBar() {
final show = (showAppBar.value || // onTap has the final say
(showAppBar.value && !isZoomed.value)) &&
!isPlayingVideo.value;
return AnimatedOpacity( return AnimatedOpacity(
duration: const Duration(milliseconds: 100), duration: const Duration(milliseconds: 100),
opacity: (showAppBar.value || !isZoomed.value) ? 1.0 : 0.0, opacity: show ? 1.0 : 0.0,
child: Container( child: Container(
color: Colors.black.withOpacity(0.4), color: Colors.black.withOpacity(0.4),
child: TopControlAppBar( child: TopControlAppBar(
@ -312,8 +317,14 @@ class GalleryViewerPage extends HookConsumerWidget {
// Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to acheive // Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to acheive
// Three-Stage Loading (WEBP -> JPEG -> Original) // Three-Stage Loading (WEBP -> JPEG -> Original)
final webPThumbnail = CachedNetworkImage( final webPThumbnail = CachedNetworkImage(
imageUrl: getThumbnailUrl(asset), imageUrl: getThumbnailUrl(
cacheKey: getThumbnailCacheKey(asset), asset,
type: api.ThumbnailFormat.WEBP,
),
cacheKey: getThumbnailCacheKey(
asset,
type: api.ThumbnailFormat.WEBP,
),
httpHeaders: {'Authorization': authToken}, httpHeaders: {'Authorization': authToken},
progressIndicatorBuilder: (_, __, ___) => const Center( progressIndicatorBuilder: (_, __, ___) => const Center(
child: ImmichLoadingIndicator(), child: ImmichLoadingIndicator(),
@ -377,14 +388,14 @@ class GalleryViewerPage extends HookConsumerWidget {
onDragStart: (_, details, __) => onDragStart: (_, details, __) =>
localPosition = details.localPosition, localPosition = details.localPosition,
onDragUpdate: (_, details, __) => handleSwipeUpDown(details), onDragUpdate: (_, details, __) => handleSwipeUpDown(details),
onTapDown: (_, __, ___) =>
showAppBar.value = !showAppBar.value,
heroAttributes: heroAttributes:
PhotoViewHeroAttributes(tag: assetList[index].id), PhotoViewHeroAttributes(tag: assetList[index].id),
maxScale: 1.0, maxScale: 1.0,
minScale: 1.0, minScale: 1.0,
child: SafeArea( child: SafeArea(
child: VideoViewerPage( child: VideoViewerPage(
onPlaying: () => isPlayingVideo.value = true,
onPaused: () => isPlayingVideo.value = false,
asset: assetList[index], asset: assetList[index],
isMotionVideo: isPlayingMotionVideo.value, isMotionVideo: isPlayingMotionVideo.value,
onVideoEnded: () { onVideoEnded: () {

View file

@ -17,12 +17,16 @@ class VideoViewerPage extends HookConsumerWidget {
final Asset asset; final Asset asset;
final bool isMotionVideo; final bool isMotionVideo;
final VoidCallback onVideoEnded; final VoidCallback onVideoEnded;
final VoidCallback? onPlaying;
final VoidCallback? onPaused;
const VideoViewerPage({ const VideoViewerPage({
Key? key, Key? key,
required this.asset, required this.asset,
required this.isMotionVideo, required this.isMotionVideo,
required this.onVideoEnded, required this.onVideoEnded,
this.onPlaying,
this.onPaused,
}) : super(key: key); }) : super(key: key);
@override @override
@ -63,6 +67,8 @@ class VideoViewerPage extends HookConsumerWidget {
jwtToken: jwtToken, jwtToken: jwtToken,
isMotionVideo: isMotionVideo, isMotionVideo: isMotionVideo,
onVideoEnded: onVideoEnded, onVideoEnded: onVideoEnded,
onPaused: onPaused,
onPlaying: onPlaying,
), ),
if (downloadAssetStatus == DownloadAssetStatus.loading) if (downloadAssetStatus == DownloadAssetStatus.loading)
const Center( const Center(
@ -89,6 +95,9 @@ class VideoThumbnailPlayer extends StatefulWidget {
final bool isMotionVideo; final bool isMotionVideo;
final VoidCallback onVideoEnded; final VoidCallback onVideoEnded;
final Function()? onPlaying;
final Function()? onPaused;
const VideoThumbnailPlayer({ const VideoThumbnailPlayer({
Key? key, Key? key,
this.url, this.url,
@ -96,6 +105,8 @@ class VideoThumbnailPlayer extends StatefulWidget {
this.file, this.file,
required this.onVideoEnded, required this.onVideoEnded,
required this.isMotionVideo, required this.isMotionVideo,
this.onPlaying,
this.onPaused,
}) : super(key: key); }) : super(key: key);
@override @override
@ -112,6 +123,11 @@ class _VideoThumbnailPlayerState extends State<VideoThumbnailPlayer> {
initializePlayer(); initializePlayer();
videoPlayerController.addListener(() { videoPlayerController.addListener(() {
if (videoPlayerController.value.isPlaying) {
widget.onPlaying?.call();
} else if (!videoPlayerController.value.isPlaying) {
widget.onPaused?.call();
}
if (videoPlayerController.value.position == if (videoPlayerController.value.position ==
videoPlayerController.value.duration) { videoPlayerController.value.duration) {
widget.onVideoEnded(); widget.onVideoEnded();