refinements and fixes

fix orientation for remote assets

wip separate widget

separate video loader widget

fixed memory leak

optimized seeking, cleanup

debug context pop

use global key

back to one widget

fixed rebuild

wait for swipe animation to finish

smooth hero animation for remote videos

faster scroll animation
This commit is contained in:
mertalev
2024-11-07 17:14:35 -05:00
parent 3272ad4a7b
commit 49c4d7cff9
12 changed files with 624 additions and 436 deletions
@@ -1,7 +1,7 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
class VideoPlaybackControls {
VideoPlaybackControls({
const VideoPlaybackControls({
required this.position,
required this.mute,
required this.pause,
@@ -17,15 +17,14 @@ final videoPlayerControlsProvider =
return VideoPlayerControls(ref);
});
const videoPlayerControlsDefault = VideoPlaybackControls(
position: 0,
pause: false,
mute: false,
);
class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
VideoPlayerControls(this.ref)
: super(
VideoPlaybackControls(
position: 0,
pause: false,
mute: false,
),
);
VideoPlayerControls(this.ref) : super(videoPlayerControlsDefault);
final Ref ref;
@@ -36,17 +35,17 @@ class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
}
void reset() {
state = VideoPlaybackControls(
position: 0,
pause: false,
mute: false,
);
state = videoPlayerControlsDefault;
}
double get position => state.position;
bool get mute => state.mute;
set position(double value) {
if (state.position == value) {
return;
}
state = VideoPlaybackControls(
position: value,
mute: state.mute,
@@ -55,6 +54,10 @@ class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
}
set mute(bool value) {
if (state.mute == value) {
return;
}
state = VideoPlaybackControls(
position: state.position,
mute: value,
@@ -71,6 +74,10 @@ class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
}
void pause() {
if (state.pause) {
return;
}
state = VideoPlaybackControls(
position: state.position,
mute: state.mute,
@@ -79,6 +86,10 @@ class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
}
void play() {
if (!state.pause) {
return;
}
state = VideoPlaybackControls(
position: state.position,
mute: state.mute,
@@ -95,12 +106,6 @@ class VideoPlayerControls extends StateNotifier<VideoPlaybackControls> {
}
void restart() {
state = VideoPlaybackControls(
position: 0,
mute: state.mute,
pause: true,
);
state = VideoPlaybackControls(
position: 0,
mute: state.mute,
@@ -23,7 +23,7 @@ class VideoPlaybackValue {
/// The volume of the video
final double volume;
VideoPlaybackValue({
const VideoPlaybackValue({
required this.position,
required this.duration,
required this.state,
@@ -33,32 +33,24 @@ class VideoPlaybackValue {
factory VideoPlaybackValue.fromNativeController(
NativeVideoPlayerController controller,
) {
PlaybackInfo? playbackInfo;
VideoInfo? videoInfo;
try {
playbackInfo = controller.playbackInfo;
videoInfo = controller.videoInfo;
} catch (_) {
// Consume error from the controller
}
late VideoPlaybackState s;
if (playbackInfo?.status == null) {
s = VideoPlaybackState.initializing;
} else if (playbackInfo?.status == PlaybackStatus.stopped &&
(playbackInfo?.positionFraction == 1 ||
playbackInfo?.positionFraction == 0)) {
s = VideoPlaybackState.completed;
} else if (playbackInfo?.status == PlaybackStatus.playing) {
s = VideoPlaybackState.playing;
} else {
s = VideoPlaybackState.paused;
final playbackInfo = controller.playbackInfo;
final videoInfo = controller.videoInfo;
if (playbackInfo == null || videoInfo == null) {
return videoPlaybackValueDefault;
}
final VideoPlaybackState status = switch (playbackInfo.status) {
PlaybackStatus.playing => VideoPlaybackState.playing,
PlaybackStatus.paused => VideoPlaybackState.paused,
PlaybackStatus.stopped => VideoPlaybackState.completed,
};
return VideoPlaybackValue(
position: Duration(seconds: playbackInfo?.position ?? 0),
duration: Duration(seconds: videoInfo?.duration ?? 0),
state: s,
volume: playbackInfo?.volume ?? 0.0,
position: Duration(seconds: playbackInfo.position),
duration: Duration(seconds: videoInfo.duration),
state: status,
volume: playbackInfo.volume,
);
}
@@ -85,15 +77,6 @@ class VideoPlaybackValue {
);
}
factory VideoPlaybackValue.uninitialized() {
return VideoPlaybackValue(
position: Duration.zero,
duration: Duration.zero,
state: VideoPlaybackState.initializing,
volume: 0.0,
);
}
VideoPlaybackValue copyWith({
Duration? position,
Duration? duration,
@@ -109,16 +92,20 @@ class VideoPlaybackValue {
}
}
const VideoPlaybackValue videoPlaybackValueDefault = VideoPlaybackValue(
position: Duration.zero,
duration: Duration.zero,
state: VideoPlaybackState.initializing,
volume: 0.0,
);
final videoPlaybackValueProvider =
StateNotifierProvider<VideoPlaybackValueState, VideoPlaybackValue>((ref) {
return VideoPlaybackValueState(ref);
});
class VideoPlaybackValueState extends StateNotifier<VideoPlaybackValue> {
VideoPlaybackValueState(this.ref)
: super(
VideoPlaybackValue.uninitialized(),
);
VideoPlaybackValueState(this.ref) : super(videoPlaybackValueDefault);
final Ref ref;
@@ -129,6 +116,7 @@ class VideoPlaybackValueState extends StateNotifier<VideoPlaybackValue> {
}
set position(Duration value) {
if (state.position == value) return;
state = VideoPlaybackValue(
position: value,
duration: state.duration,
@@ -136,4 +124,8 @@ class VideoPlaybackValueState extends StateNotifier<VideoPlaybackValue> {
volume: state.volume,
);
}
void reset() {
state = videoPlaybackValueDefault;
}
}