Adds photo thumbnail to videos (#2880)

* Motion photos use placeholder image for more seamless loading

* Fixes merge conflicts
This commit is contained in:
martyfuhry 2023-06-20 17:17:43 -04:00 committed by GitHub
parent 48e4ea5231
commit 1b15b5414c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 36 deletions

View file

@ -367,6 +367,26 @@ class GalleryViewerPage extends HookConsumerWidget {
);
}
ImageProvider imageProvider(Asset asset) {
if (asset.isLocal) {
return localImageProvider(asset);
} else {
if (isLoadOriginal.value) {
return originalImageProvider(asset);
} else if (isLoadPreview.value) {
return remoteThumbnailImageProvider(
asset,
api.ThumbnailFormat.JPEG,
);
} else {
return remoteThumbnailImageProvider(
asset,
api.ThumbnailFormat.WEBP,
);
}
}
}
return Scaffold(
backgroundColor: Colors.black,
body: WillPopScope(
@ -460,26 +480,9 @@ class GalleryViewerPage extends HookConsumerWidget {
: null,
builder: (context, index) {
final asset = loadAsset(index);
final ImageProvider provider = imageProvider(asset);
if (asset.isImage && !isPlayingMotionVideo.value) {
// Show photo
final ImageProvider provider;
if (asset.isLocal) {
provider = localImageProvider(asset);
} else {
if (isLoadOriginal.value) {
provider = originalImageProvider(asset);
} else if (isLoadPreview.value) {
provider = remoteThumbnailImageProvider(
asset,
api.ThumbnailFormat.JPEG,
);
} else {
provider = remoteThumbnailImageProvider(
asset,
api.ThumbnailFormat.WEBP,
);
}
}
return PhotoViewGalleryPageOptions(
onDragStart: (_, details, __) =>
localPosition = details.localPosition,
@ -512,18 +515,23 @@ class GalleryViewerPage extends HookConsumerWidget {
maxScale: 1.0,
minScale: 1.0,
basePosition: Alignment.bottomCenter,
child: SafeArea(
child: VideoViewerPage(
onPlaying: () => isPlayingVideo.value = true,
onPaused: () => isPlayingVideo.value = false,
asset: asset,
isMotionVideo: isPlayingMotionVideo.value,
onVideoEnded: () {
if (isPlayingMotionVideo.value) {
isPlayingMotionVideo.value = false;
}
},
child: VideoViewerPage(
onPlaying: () => isPlayingVideo.value = true,
onPaused: () => isPlayingVideo.value = false,
asset: asset,
isMotionVideo: isPlayingMotionVideo.value,
placeholder: Image(
image: provider,
fit: BoxFit.fitWidth,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
alignment: Alignment.center,
),
onVideoEnded: () {
if (isPlayingMotionVideo.value) {
isPlayingMotionVideo.value = false;
}
},
),
);
}

View file

@ -15,6 +15,7 @@ import 'package:video_player/video_player.dart';
class VideoViewerPage extends HookConsumerWidget {
final Asset asset;
final bool isMotionVideo;
final Widget? placeholder;
final VoidCallback onVideoEnded;
final VoidCallback? onPlaying;
final VoidCallback? onPaused;
@ -26,6 +27,7 @@ class VideoViewerPage extends HookConsumerWidget {
required this.onVideoEnded,
this.onPlaying,
this.onPaused,
this.placeholder,
}) : super(key: key);
@override
@ -66,6 +68,7 @@ class VideoViewerPage extends HookConsumerWidget {
onVideoEnded: onVideoEnded,
onPaused: onPaused,
onPlaying: onPlaying,
placeholder: placeholder,
),
if (downloadAssetStatus == DownloadAssetStatus.loading)
const Center(
@ -95,6 +98,10 @@ class VideoPlayer extends StatefulWidget {
final Function()? onPlaying;
final Function()? onPaused;
/// The placeholder to show while the video is loading
/// usually, a thumbnail of the video
final Widget? placeholder;
const VideoPlayer({
Key? key,
this.url,
@ -104,6 +111,7 @@ class VideoPlayer extends StatefulWidget {
required this.isMotionVideo,
this.onPlaying,
this.onPaused,
this.placeholder,
}) : super(key: key);
@override
@ -186,12 +194,18 @@ class _VideoPlayerState extends State<VideoPlayer> {
),
);
} else {
return const Center(
child: SizedBox(
width: 75,
height: 75,
child: CircularProgressIndicator.adaptive(
strokeWidth: 2,
return SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Center(
child: Stack(
children: [
if (widget.placeholder != null)
widget.placeholder!,
const Center(
child: ImmichLoadingIndicator(),
),
],
),
),
);