mirror of
https://github.com/immich-app/immich.git
synced 2025-05-31 04:05:39 -04:00
Adds photo thumbnail to videos (#2880)
* Motion photos use placeholder image for more seamless loading * Fixes merge conflicts
This commit is contained in:
parent
48e4ea5231
commit
1b15b5414c
@ -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(
|
return Scaffold(
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: WillPopScope(
|
body: WillPopScope(
|
||||||
@ -460,26 +480,9 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
: null,
|
: null,
|
||||||
builder: (context, index) {
|
builder: (context, index) {
|
||||||
final asset = loadAsset(index);
|
final asset = loadAsset(index);
|
||||||
|
final ImageProvider provider = imageProvider(asset);
|
||||||
|
|
||||||
if (asset.isImage && !isPlayingMotionVideo.value) {
|
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(
|
return PhotoViewGalleryPageOptions(
|
||||||
onDragStart: (_, details, __) =>
|
onDragStart: (_, details, __) =>
|
||||||
localPosition = details.localPosition,
|
localPosition = details.localPosition,
|
||||||
@ -512,18 +515,23 @@ class GalleryViewerPage extends HookConsumerWidget {
|
|||||||
maxScale: 1.0,
|
maxScale: 1.0,
|
||||||
minScale: 1.0,
|
minScale: 1.0,
|
||||||
basePosition: Alignment.bottomCenter,
|
basePosition: Alignment.bottomCenter,
|
||||||
child: SafeArea(
|
child: VideoViewerPage(
|
||||||
child: VideoViewerPage(
|
onPlaying: () => isPlayingVideo.value = true,
|
||||||
onPlaying: () => isPlayingVideo.value = true,
|
onPaused: () => isPlayingVideo.value = false,
|
||||||
onPaused: () => isPlayingVideo.value = false,
|
asset: asset,
|
||||||
asset: asset,
|
isMotionVideo: isPlayingMotionVideo.value,
|
||||||
isMotionVideo: isPlayingMotionVideo.value,
|
placeholder: Image(
|
||||||
onVideoEnded: () {
|
image: provider,
|
||||||
if (isPlayingMotionVideo.value) {
|
fit: BoxFit.fitWidth,
|
||||||
isPlayingMotionVideo.value = false;
|
height: MediaQuery.of(context).size.height,
|
||||||
}
|
width: MediaQuery.of(context).size.width,
|
||||||
},
|
alignment: Alignment.center,
|
||||||
),
|
),
|
||||||
|
onVideoEnded: () {
|
||||||
|
if (isPlayingMotionVideo.value) {
|
||||||
|
isPlayingMotionVideo.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import 'package:video_player/video_player.dart';
|
|||||||
class VideoViewerPage extends HookConsumerWidget {
|
class VideoViewerPage extends HookConsumerWidget {
|
||||||
final Asset asset;
|
final Asset asset;
|
||||||
final bool isMotionVideo;
|
final bool isMotionVideo;
|
||||||
|
final Widget? placeholder;
|
||||||
final VoidCallback onVideoEnded;
|
final VoidCallback onVideoEnded;
|
||||||
final VoidCallback? onPlaying;
|
final VoidCallback? onPlaying;
|
||||||
final VoidCallback? onPaused;
|
final VoidCallback? onPaused;
|
||||||
@ -26,6 +27,7 @@ class VideoViewerPage extends HookConsumerWidget {
|
|||||||
required this.onVideoEnded,
|
required this.onVideoEnded,
|
||||||
this.onPlaying,
|
this.onPlaying,
|
||||||
this.onPaused,
|
this.onPaused,
|
||||||
|
this.placeholder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -66,6 +68,7 @@ class VideoViewerPage extends HookConsumerWidget {
|
|||||||
onVideoEnded: onVideoEnded,
|
onVideoEnded: onVideoEnded,
|
||||||
onPaused: onPaused,
|
onPaused: onPaused,
|
||||||
onPlaying: onPlaying,
|
onPlaying: onPlaying,
|
||||||
|
placeholder: placeholder,
|
||||||
),
|
),
|
||||||
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
if (downloadAssetStatus == DownloadAssetStatus.loading)
|
||||||
const Center(
|
const Center(
|
||||||
@ -95,6 +98,10 @@ class VideoPlayer extends StatefulWidget {
|
|||||||
final Function()? onPlaying;
|
final Function()? onPlaying;
|
||||||
final Function()? onPaused;
|
final Function()? onPaused;
|
||||||
|
|
||||||
|
/// The placeholder to show while the video is loading
|
||||||
|
/// usually, a thumbnail of the video
|
||||||
|
final Widget? placeholder;
|
||||||
|
|
||||||
const VideoPlayer({
|
const VideoPlayer({
|
||||||
Key? key,
|
Key? key,
|
||||||
this.url,
|
this.url,
|
||||||
@ -104,6 +111,7 @@ class VideoPlayer extends StatefulWidget {
|
|||||||
required this.isMotionVideo,
|
required this.isMotionVideo,
|
||||||
this.onPlaying,
|
this.onPlaying,
|
||||||
this.onPaused,
|
this.onPaused,
|
||||||
|
this.placeholder,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -186,12 +194,18 @@ class _VideoPlayerState extends State<VideoPlayer> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const Center(
|
return SizedBox(
|
||||||
child: SizedBox(
|
height: MediaQuery.of(context).size.height,
|
||||||
width: 75,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: 75,
|
child: Center(
|
||||||
child: CircularProgressIndicator.adaptive(
|
child: Stack(
|
||||||
strokeWidth: 2,
|
children: [
|
||||||
|
if (widget.placeholder != null)
|
||||||
|
widget.placeholder!,
|
||||||
|
const Center(
|
||||||
|
child: ImmichLoadingIndicator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user