0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-03-11 02:23:09 -05:00

fix: handle buffering

This commit is contained in:
shenlong-tanwen 2024-08-30 00:16:39 +05:30 committed by Mert Alev
parent 6553e4d0be
commit 7bf5a19971
2 changed files with 53 additions and 5 deletions

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -33,6 +35,28 @@ class NativeVideoViewerPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final controller = useState<NativeVideoPlayerController?>(null);
final lastVideoPosition = useRef(-1);
final isBuffering = useRef(false);
void checkIfBuffering([Timer? timer]) {
if (!context.mounted) {
timer?.cancel();
return;
}
final videoPlayback = ref.read(videoPlaybackValueProvider);
if ((isBuffering.value ||
videoPlayback.state == VideoPlaybackState.initializing) &&
videoPlayback.state != VideoPlaybackState.buffering) {
ref.read(videoPlaybackValueProvider.notifier).value =
videoPlayback.copyWith(state: VideoPlaybackState.buffering);
}
}
// timer to mark videos as buffering if the position does not change
final bufferingTimer = useRef<Timer>(
Timer.periodic(const Duration(seconds: 5), checkIfBuffering),
);
Future<VideoSource> createSource(Asset asset) async {
if (asset.isLocal && asset.livePhotoVideoId == null) {
@ -100,6 +124,15 @@ class NativeVideoViewerPage extends HookConsumerWidget {
final videoPlayback =
VideoPlaybackValue.fromNativeController(controller.value!);
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;
// Check if the video is buffering
if (videoPlayback.state == VideoPlaybackState.playing) {
isBuffering.value =
lastVideoPosition.value == videoPlayback.position.inSeconds;
lastVideoPosition.value = videoPlayback.position.inSeconds;
} else {
isBuffering.value = false;
lastVideoPosition.value = -1;
}
final state = videoPlayback.state;
// Enable the WakeLock while the video is playing
@ -142,6 +175,8 @@ class NativeVideoViewerPage extends HookConsumerWidget {
final videoSource = await createSource(asset);
controller.value?.loadVideoSource(videoSource);
Timer(const Duration(milliseconds: 200), checkIfBuffering);
}
useEffect(
@ -158,6 +193,7 @@ class NativeVideoViewerPage extends HookConsumerWidget {
}
return () {
bufferingTimer.value.cancel();
controller.value?.onPlaybackPositionChanged
.removeListener(onPlaybackPositionChanged);
controller.value?.onPlaybackStatusChanged
@ -169,9 +205,6 @@ class NativeVideoViewerPage extends HookConsumerWidget {
[],
);
void updatePlayback(VideoPlaybackValue value) =>
ref.read(videoPlaybackValueProvider.notifier).value = value;
final size = MediaQuery.sizeOf(context);
return SizedBox(
@ -180,8 +213,9 @@ class NativeVideoViewerPage extends HookConsumerWidget {
child: GestureDetector(
behavior: HitTestBehavior.deferToChild,
child: PopScope(
onPopInvokedWithResult: (didPop, _) =>
updatePlayback(VideoPlaybackValue.uninitialized()),
onPopInvokedWithResult: (didPop, _) => ref
.read(videoPlaybackValueProvider.notifier)
.value = VideoPlaybackValue.uninitialized(),
child: SizedBox(
height: size.height,
width: size.width,

View file

@ -87,6 +87,20 @@ class VideoPlaybackValue {
volume: 0.0,
);
}
VideoPlaybackValue copyWith({
Duration? position,
Duration? duration,
VideoPlaybackState? state,
double? volume,
}) {
return VideoPlaybackValue(
position: position ?? this.position,
duration: duration ?? this.duration,
state: state ?? this.state,
volume: volume ?? this.volume,
);
}
}
final videoPlaybackValueProvider =