Skip to content

Commit 69e88ef

Browse files
Tyristomgquestalextran1502
authored
fix(mobile): #15182 Video memories no longer play (#15210)
* Update current asset to play video. * Updated location of currentAssetProvider update per feedback. * Added a playbackDelayFactor to the video viewer to resolve an issue in memories. Also adjusted the scale of the memory preview image to match the ratio of the video. This still appears to jump because the video preview doesn't seem to be the first frame for some reason :\ * add video indicator --------- Co-authored-by: Tom graham <[email protected]> Co-authored-by: Alex <[email protected]>
1 parent 9358b4d commit 69e88ef

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

mobile/lib/pages/common/native_video_viewer.page.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ import 'package:wakelock_plus/wakelock_plus.dart';
2626
class NativeVideoViewerPage extends HookConsumerWidget {
2727
final Asset asset;
2828
final bool showControls;
29+
final int playbackDelayFactor;
2930
final Widget image;
3031

3132
const NativeVideoViewerPage({
3233
super.key,
3334
required this.asset,
3435
required this.image,
3536
this.showControls = true,
37+
this.playbackDelayFactor = 1,
3638
});
3739

3840
@override
@@ -317,12 +319,16 @@ class NativeVideoViewerPage extends HookConsumerWidget {
317319
}
318320

319321
// Delay the video playback to avoid a stutter in the swipe animation
322+
// Note, in some circumstances a longer delay is needed (eg: memories),
323+
// the playbackDelayFactor can be used for this
324+
// This delay seems like a hacky way to resolve underlying bugs in video
325+
// playback, but other resolutions failed thus far
320326
Timer(
321327
Platform.isIOS
322-
? const Duration(milliseconds: 300)
328+
? Duration(milliseconds: 300 * playbackDelayFactor)
323329
: imageToVideo
324-
? const Duration(milliseconds: 200)
325-
: const Duration(milliseconds: 400), () {
330+
? Duration(milliseconds: 200 * playbackDelayFactor)
331+
: Duration(milliseconds: 400 * playbackDelayFactor), () {
326332
if (!context.mounted) {
327333
return;
328334
}

mobile/lib/pages/photos/memory.page.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import 'package:flutter_hooks/flutter_hooks.dart';
55
import 'package:hooks_riverpod/hooks_riverpod.dart';
66
import 'package:immich_mobile/entities/asset.entity.dart';
77
import 'package:immich_mobile/models/memories/memory.model.dart';
8+
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
9+
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
810
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
911
import 'package:immich_mobile/widgets/common/immich_image.dart';
1012
import 'package:immich_mobile/widgets/memories/memory_bottom_info.dart';
@@ -13,6 +15,8 @@ import 'package:immich_mobile/widgets/memories/memory_epilogue.dart';
1315
import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart';
1416

1517
@RoutePage()
18+
19+
/// Expects [currentAssetProvider] to be set before navigating to this page
1620
class MemoryPage extends HookConsumerWidget {
1721
final List<Memory> memories;
1822
final int memoryIndex;
@@ -32,6 +36,7 @@ class MemoryPage extends HookConsumerWidget {
3236
"${currentAssetPage.value + 1}|${currentMemory.value.assets.length}",
3337
);
3438
const bgColor = Colors.black;
39+
final currentAsset = useState<Asset?>(null);
3540

3641
/// The list of all of the asset page controllers
3742
final memoryAssetPageControllers =
@@ -135,6 +140,14 @@ class MemoryPage extends HookConsumerWidget {
135140
ref.read(hapticFeedbackProvider.notifier).selectionClick();
136141
currentAssetPage.value = otherIndex;
137142
updateProgressText();
143+
144+
final asset = currentMemory.value.assets[otherIndex];
145+
currentAsset.value = asset;
146+
ref.read(currentAssetProvider.notifier).set(asset);
147+
if (asset.isVideo || asset.isMotionPhoto) {
148+
ref.read(videoPlaybackValueProvider.notifier).reset();
149+
}
150+
138151
// Wait for page change animation to finish
139152
await Future.delayed(const Duration(milliseconds: 400));
140153
// And then precache the next asset
@@ -274,6 +287,16 @@ class MemoryPage extends HookConsumerWidget {
274287
),
275288
),
276289
),
290+
if (currentAsset.value != null &&
291+
currentAsset.value!.isVideo)
292+
Positioned(
293+
bottom: 24,
294+
right: 32,
295+
child: Icon(
296+
Icons.videocam_outlined,
297+
color: Colors.grey[200],
298+
),
299+
),
277300
],
278301
),
279302
),

mobile/lib/widgets/memories/memory_card.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,12 @@ class MemoryCard extends StatelessWidget {
7575
key: ValueKey(asset.id),
7676
asset: asset,
7777
showControls: false,
78+
playbackDelayFactor: 2,
7879
image: ImmichImage(
7980
asset,
8081
width: context.width,
8182
height: context.height,
82-
fit: fit,
83+
fit: BoxFit.contain,
8384
),
8485
),
8586
),

mobile/lib/widgets/memories/memory_lane.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
44
import 'package:hooks_riverpod/hooks_riverpod.dart';
55
import 'package:immich_mobile/models/memories/memory.model.dart';
66
import 'package:immich_mobile/widgets/asset_grid/thumbnail_placeholder.dart';
7+
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
8+
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
79
import 'package:immich_mobile/providers/memory.provider.dart';
810
import 'package:immich_mobile/routing/router.dart';
911
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
@@ -33,6 +35,13 @@ class MemoryLane extends HookConsumerWidget {
3335
),
3436
onTap: (memoryIndex) {
3537
ref.read(hapticFeedbackProvider.notifier).heavyImpact();
38+
if (memories[memoryIndex].assets.isNotEmpty) {
39+
final asset = memories[memoryIndex].assets[0];
40+
ref.read(currentAssetProvider.notifier).set(asset);
41+
if (asset.isVideo || asset.isMotionPhoto) {
42+
ref.read(videoPlaybackValueProvider.notifier).reset();
43+
}
44+
}
3645
context.pushRoute(
3746
MemoryRoute(
3847
memories: memories,

0 commit comments

Comments
 (0)