mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 15:11:58 +00:00
remove video_player
This commit is contained in:
parent
2ece3d3822
commit
fa3156e6ee
8 changed files with 7 additions and 452 deletions
|
@ -93,6 +93,7 @@ class Asset {
|
||||||
@ignore
|
@ignore
|
||||||
bool _didUpdateLocal = false;
|
bool _didUpdateLocal = false;
|
||||||
|
|
||||||
|
@ignore
|
||||||
Future<AssetEntity> get localAsync async {
|
Future<AssetEntity> get localAsync async {
|
||||||
final local = this.local;
|
final local = this.local;
|
||||||
if (local == null) {
|
if (local == null) {
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_controller_provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider.dart';
|
|
||||||
import 'package:immich_mobile/widgets/asset_viewer/video_player.dart';
|
|
||||||
import 'package:immich_mobile/widgets/common/delayed_loading_indicator.dart';
|
|
||||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
|
||||||
|
|
||||||
class VideoViewerPage extends HookConsumerWidget {
|
|
||||||
final Asset asset;
|
|
||||||
final bool isMotionVideo;
|
|
||||||
final Widget? placeholder;
|
|
||||||
final Duration hideControlsTimer;
|
|
||||||
final bool showControls;
|
|
||||||
final bool showDownloadingIndicator;
|
|
||||||
final bool loopVideo;
|
|
||||||
|
|
||||||
const VideoViewerPage({
|
|
||||||
super.key,
|
|
||||||
required this.asset,
|
|
||||||
this.isMotionVideo = false,
|
|
||||||
this.placeholder,
|
|
||||||
this.showControls = true,
|
|
||||||
this.hideControlsTimer = const Duration(seconds: 5),
|
|
||||||
this.showDownloadingIndicator = true,
|
|
||||||
this.loopVideo = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
build(BuildContext context, WidgetRef ref) {
|
|
||||||
final controller =
|
|
||||||
ref.watch(videoPlayerControllerProvider(asset: asset)).value;
|
|
||||||
// The last volume of the video used when mute is toggled
|
|
||||||
final lastVolume = useState(0.5);
|
|
||||||
|
|
||||||
// When the volume changes, set the volume
|
|
||||||
ref.listen(videoPlayerControlsProvider.select((value) => value.mute),
|
|
||||||
(_, mute) {
|
|
||||||
if (mute) {
|
|
||||||
controller?.setVolume(0.0);
|
|
||||||
} else {
|
|
||||||
controller?.setVolume(lastVolume.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the position changes, seek to the position
|
|
||||||
ref.listen(videoPlayerControlsProvider.select((value) => value.position),
|
|
||||||
(_, position) {
|
|
||||||
if (controller == null) {
|
|
||||||
// No seeeking if there is no video
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the position to seek to
|
|
||||||
final Duration seek = controller.value.duration * (position / 100.0);
|
|
||||||
controller.seekTo(seek);
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the custom video controls paus or plays
|
|
||||||
ref.listen(videoPlayerControlsProvider.select((value) => value.pause),
|
|
||||||
(lastPause, pause) {
|
|
||||||
if (pause) {
|
|
||||||
controller?.pause();
|
|
||||||
} else {
|
|
||||||
controller?.play();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Updates the [videoPlaybackValueProvider] with the current
|
|
||||||
// position and duration of the video from the Chewie [controller]
|
|
||||||
// Also sets the error if there is an error in the playback
|
|
||||||
void updateVideoPlayback() {
|
|
||||||
final videoPlayback = VideoPlaybackValue.fromController(controller);
|
|
||||||
ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback;
|
|
||||||
final state = videoPlayback.state;
|
|
||||||
|
|
||||||
// Enable the WakeLock while the video is playing
|
|
||||||
if (state == VideoPlaybackState.playing) {
|
|
||||||
// Sync with the controls playing
|
|
||||||
WakelockPlus.enable();
|
|
||||||
} else {
|
|
||||||
// Sync with the controls pause
|
|
||||||
WakelockPlus.disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds and removes the listener to the video player
|
|
||||||
useEffect(
|
|
||||||
() {
|
|
||||||
Future.microtask(
|
|
||||||
() => ref.read(videoPlayerControlsProvider.notifier).reset(),
|
|
||||||
);
|
|
||||||
// Guard no controller
|
|
||||||
if (controller == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide the controls
|
|
||||||
// Done in a microtask to avoid setting the state while the is building
|
|
||||||
if (!isMotionVideo) {
|
|
||||||
Future.microtask(() {
|
|
||||||
ref.read(showControlsProvider.notifier).show = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribes to listener
|
|
||||||
Future.microtask(() {
|
|
||||||
controller.addListener(updateVideoPlayback);
|
|
||||||
});
|
|
||||||
return () {
|
|
||||||
// Removes listener when we dispose
|
|
||||||
controller.removeListener(updateVideoPlayback);
|
|
||||||
controller.pause();
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[controller],
|
|
||||||
);
|
|
||||||
|
|
||||||
final size = MediaQuery.sizeOf(context);
|
|
||||||
|
|
||||||
return PopScope(
|
|
||||||
onPopInvokedWithResult: (didPop, _) {
|
|
||||||
ref.read(videoPlaybackValueProvider.notifier).reset();
|
|
||||||
},
|
|
||||||
child: AnimatedSwitcher(
|
|
||||||
duration: const Duration(milliseconds: 400),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Visibility(
|
|
||||||
visible: controller == null,
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
if (placeholder != null) placeholder!,
|
|
||||||
const Positioned.fill(
|
|
||||||
child: Center(
|
|
||||||
child: DelayedLoadingIndicator(
|
|
||||||
fadeInDuration: Duration(milliseconds: 500),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (controller != null)
|
|
||||||
SizedBox(
|
|
||||||
height: size.height,
|
|
||||||
width: size.width,
|
|
||||||
child: VideoPlayerViewer(
|
|
||||||
controller: controller,
|
|
||||||
isMotionVideo: isMotionVideo,
|
|
||||||
placeholder: placeholder,
|
|
||||||
hideControlsTimer: hideControlsTimer,
|
|
||||||
showControls: showControls,
|
|
||||||
showDownloadingIndicator: showDownloadingIndicator,
|
|
||||||
loopVideo: loopVideo,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
||||||
import 'package:video_player/video_player.dart';
|
|
||||||
|
|
||||||
part 'video_player_controller_provider.g.dart';
|
|
||||||
|
|
||||||
@riverpod
|
|
||||||
Future<VideoPlayerController> videoPlayerController(
|
|
||||||
VideoPlayerControllerRef ref, {
|
|
||||||
required Asset asset,
|
|
||||||
}) async {
|
|
||||||
late VideoPlayerController controller;
|
|
||||||
if (asset.isLocal && asset.livePhotoVideoId == null) {
|
|
||||||
// Use a local file for the video player controller
|
|
||||||
final file = await asset.local!.file;
|
|
||||||
if (file == null) {
|
|
||||||
throw Exception('No file found for the video');
|
|
||||||
}
|
|
||||||
controller = VideoPlayerController.file(file);
|
|
||||||
} else {
|
|
||||||
// Use a network URL for the video player controller
|
|
||||||
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
|
||||||
final String videoUrl = asset.livePhotoVideoId != null
|
|
||||||
? '$serverEndpoint/assets/${asset.livePhotoVideoId}/video/playback'
|
|
||||||
: '$serverEndpoint/assets/${asset.remoteId}/video/playback';
|
|
||||||
|
|
||||||
final url = Uri.parse(videoUrl);
|
|
||||||
controller = VideoPlayerController.networkUrl(
|
|
||||||
url,
|
|
||||||
httpHeaders: ApiService.getRequestHeaders(),
|
|
||||||
videoPlayerOptions: asset.livePhotoVideoId != null
|
|
||||||
? VideoPlayerOptions(mixWithOthers: true)
|
|
||||||
: VideoPlayerOptions(mixWithOthers: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await controller.initialize();
|
|
||||||
|
|
||||||
ref.onDispose(() {
|
|
||||||
controller.dispose();
|
|
||||||
});
|
|
||||||
|
|
||||||
return controller;
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:native_video_player/native_video_player.dart';
|
import 'package:native_video_player/native_video_player.dart';
|
||||||
import 'package:video_player/video_player.dart';
|
|
||||||
|
|
||||||
enum VideoPlaybackState {
|
enum VideoPlaybackState {
|
||||||
initializing,
|
initializing,
|
||||||
|
@ -54,29 +53,6 @@ class VideoPlaybackValue {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory VideoPlaybackValue.fromController(VideoPlayerController? controller) {
|
|
||||||
final video = controller?.value;
|
|
||||||
late VideoPlaybackState s;
|
|
||||||
if (video == null) {
|
|
||||||
s = VideoPlaybackState.initializing;
|
|
||||||
} else if (video.isCompleted) {
|
|
||||||
s = VideoPlaybackState.completed;
|
|
||||||
} else if (video.isPlaying) {
|
|
||||||
s = VideoPlaybackState.playing;
|
|
||||||
} else if (video.isBuffering) {
|
|
||||||
s = VideoPlaybackState.buffering;
|
|
||||||
} else {
|
|
||||||
s = VideoPlaybackState.paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
return VideoPlaybackValue(
|
|
||||||
position: video?.position ?? Duration.zero,
|
|
||||||
duration: video?.duration ?? Duration.zero,
|
|
||||||
state: s,
|
|
||||||
volume: video?.volume ?? 0.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoPlaybackValue copyWith({
|
VideoPlaybackValue copyWith({
|
||||||
Duration? position,
|
Duration? position,
|
||||||
Duration? duration,
|
Duration? duration,
|
||||||
|
|
|
@ -1085,7 +1085,7 @@ class NativeVideoViewerRoute extends PageRouteInfo<NativeVideoViewerRouteArgs> {
|
||||||
NativeVideoViewerRoute({
|
NativeVideoViewerRoute({
|
||||||
Key? key,
|
Key? key,
|
||||||
required Asset asset,
|
required Asset asset,
|
||||||
required Widget placeholder,
|
required Widget image,
|
||||||
bool showControls = true,
|
bool showControls = true,
|
||||||
List<PageRouteInfo>? children,
|
List<PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
|
@ -1093,7 +1093,7 @@ class NativeVideoViewerRoute extends PageRouteInfo<NativeVideoViewerRouteArgs> {
|
||||||
args: NativeVideoViewerRouteArgs(
|
args: NativeVideoViewerRouteArgs(
|
||||||
key: key,
|
key: key,
|
||||||
asset: asset,
|
asset: asset,
|
||||||
placeholder: placeholder,
|
image: image,
|
||||||
showControls: showControls,
|
showControls: showControls,
|
||||||
),
|
),
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
|
@ -1108,7 +1108,7 @@ class NativeVideoViewerRoute extends PageRouteInfo<NativeVideoViewerRouteArgs> {
|
||||||
return NativeVideoViewerPage(
|
return NativeVideoViewerPage(
|
||||||
key: args.key,
|
key: args.key,
|
||||||
asset: args.asset,
|
asset: args.asset,
|
||||||
image: args.placeholder,
|
image: args.image,
|
||||||
showControls: args.showControls,
|
showControls: args.showControls,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1119,7 +1119,7 @@ class NativeVideoViewerRouteArgs {
|
||||||
const NativeVideoViewerRouteArgs({
|
const NativeVideoViewerRouteArgs({
|
||||||
this.key,
|
this.key,
|
||||||
required this.asset,
|
required this.asset,
|
||||||
required this.placeholder,
|
required this.image,
|
||||||
this.showControls = true,
|
this.showControls = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1127,13 +1127,13 @@ class NativeVideoViewerRouteArgs {
|
||||||
|
|
||||||
final Asset asset;
|
final Asset asset;
|
||||||
|
|
||||||
final Widget placeholder;
|
final Widget image;
|
||||||
|
|
||||||
final bool showControls;
|
final bool showControls;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'NativeVideoViewerRouteArgs{key: $key, asset: $asset, placeholder: $placeholder, showControls: $showControls}';
|
return 'NativeVideoViewerRouteArgs{key: $key, asset: $asset, image: $image, showControls: $showControls}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
import 'package:chewie/chewie.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:video_player/video_player.dart';
|
|
||||||
|
|
||||||
/// Provides the initialized video player controller
|
|
||||||
/// If the asset is local, use the local file
|
|
||||||
/// Otherwise, use a video player with a URL
|
|
||||||
ChewieController useChewieController({
|
|
||||||
required VideoPlayerController controller,
|
|
||||||
EdgeInsets controlsSafeAreaMinimum = const EdgeInsets.only(
|
|
||||||
bottom: 100,
|
|
||||||
),
|
|
||||||
bool showOptions = true,
|
|
||||||
bool showControlsOnInitialize = false,
|
|
||||||
bool autoPlay = true,
|
|
||||||
bool allowFullScreen = false,
|
|
||||||
bool allowedScreenSleep = false,
|
|
||||||
bool showControls = true,
|
|
||||||
bool loopVideo = false,
|
|
||||||
Widget? customControls,
|
|
||||||
Widget? placeholder,
|
|
||||||
Duration hideControlsTimer = const Duration(seconds: 1),
|
|
||||||
VoidCallback? onPlaying,
|
|
||||||
VoidCallback? onPaused,
|
|
||||||
VoidCallback? onVideoEnded,
|
|
||||||
}) {
|
|
||||||
return use(
|
|
||||||
_ChewieControllerHook(
|
|
||||||
controller: controller,
|
|
||||||
placeholder: placeholder,
|
|
||||||
showOptions: showOptions,
|
|
||||||
controlsSafeAreaMinimum: controlsSafeAreaMinimum,
|
|
||||||
autoPlay: autoPlay,
|
|
||||||
allowFullScreen: allowFullScreen,
|
|
||||||
customControls: customControls,
|
|
||||||
hideControlsTimer: hideControlsTimer,
|
|
||||||
showControlsOnInitialize: showControlsOnInitialize,
|
|
||||||
showControls: showControls,
|
|
||||||
loopVideo: loopVideo,
|
|
||||||
allowedScreenSleep: allowedScreenSleep,
|
|
||||||
onPlaying: onPlaying,
|
|
||||||
onPaused: onPaused,
|
|
||||||
onVideoEnded: onVideoEnded,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ChewieControllerHook extends Hook<ChewieController> {
|
|
||||||
final VideoPlayerController controller;
|
|
||||||
final EdgeInsets controlsSafeAreaMinimum;
|
|
||||||
final bool showOptions;
|
|
||||||
final bool showControlsOnInitialize;
|
|
||||||
final bool autoPlay;
|
|
||||||
final bool allowFullScreen;
|
|
||||||
final bool allowedScreenSleep;
|
|
||||||
final bool showControls;
|
|
||||||
final bool loopVideo;
|
|
||||||
final Widget? customControls;
|
|
||||||
final Widget? placeholder;
|
|
||||||
final Duration hideControlsTimer;
|
|
||||||
final VoidCallback? onPlaying;
|
|
||||||
final VoidCallback? onPaused;
|
|
||||||
final VoidCallback? onVideoEnded;
|
|
||||||
|
|
||||||
const _ChewieControllerHook({
|
|
||||||
required this.controller,
|
|
||||||
this.controlsSafeAreaMinimum = const EdgeInsets.only(
|
|
||||||
bottom: 100,
|
|
||||||
),
|
|
||||||
this.showOptions = true,
|
|
||||||
this.showControlsOnInitialize = false,
|
|
||||||
this.autoPlay = true,
|
|
||||||
this.allowFullScreen = false,
|
|
||||||
this.allowedScreenSleep = false,
|
|
||||||
this.showControls = true,
|
|
||||||
this.loopVideo = false,
|
|
||||||
this.customControls,
|
|
||||||
this.placeholder,
|
|
||||||
this.hideControlsTimer = const Duration(seconds: 3),
|
|
||||||
this.onPlaying,
|
|
||||||
this.onPaused,
|
|
||||||
this.onVideoEnded,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
createState() => _ChewieControllerHookState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ChewieControllerHookState
|
|
||||||
extends HookState<ChewieController, _ChewieControllerHook> {
|
|
||||||
late ChewieController chewieController = ChewieController(
|
|
||||||
videoPlayerController: hook.controller,
|
|
||||||
controlsSafeAreaMinimum: hook.controlsSafeAreaMinimum,
|
|
||||||
showOptions: hook.showOptions,
|
|
||||||
showControlsOnInitialize: hook.showControlsOnInitialize,
|
|
||||||
autoPlay: hook.autoPlay,
|
|
||||||
allowFullScreen: hook.allowFullScreen,
|
|
||||||
allowedScreenSleep: hook.allowedScreenSleep,
|
|
||||||
showControls: hook.showControls,
|
|
||||||
looping: hook.loopVideo,
|
|
||||||
customControls: hook.customControls,
|
|
||||||
placeholder: hook.placeholder,
|
|
||||||
hideControlsTimer: hook.hideControlsTimer,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
chewieController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
ChewieController build(BuildContext context) {
|
|
||||||
return chewieController;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
/// Initializes the chewie controller and video player controller
|
|
||||||
Future<void> _initialize() async {
|
|
||||||
if (hook.asset.isLocal && hook.asset.livePhotoVideoId == null) {
|
|
||||||
// Use a local file for the video player controller
|
|
||||||
final file = await hook.asset.local!.file;
|
|
||||||
if (file == null) {
|
|
||||||
throw Exception('No file found for the video');
|
|
||||||
}
|
|
||||||
videoPlayerController = VideoPlayerController.file(file);
|
|
||||||
} else {
|
|
||||||
// Use a network URL for the video player controller
|
|
||||||
final serverEndpoint = store.Store.get(store.StoreKey.serverEndpoint);
|
|
||||||
final String videoUrl = hook.asset.livePhotoVideoId != null
|
|
||||||
? '$serverEndpoint/assets/${hook.asset.livePhotoVideoId}/video/playback'
|
|
||||||
: '$serverEndpoint/assets/${hook.asset.remoteId}/video/playback';
|
|
||||||
|
|
||||||
final url = Uri.parse(videoUrl);
|
|
||||||
final accessToken = store.Store.get(StoreKey.accessToken);
|
|
||||||
|
|
||||||
videoPlayerController = VideoPlayerController.networkUrl(
|
|
||||||
url,
|
|
||||||
httpHeaders: {"x-immich-user-token": accessToken},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await videoPlayerController!.initialize();
|
|
||||||
|
|
||||||
chewieController = ChewieController(
|
|
||||||
videoPlayerController: videoPlayerController!,
|
|
||||||
controlsSafeAreaMinimum: hook.controlsSafeAreaMinimum,
|
|
||||||
showOptions: hook.showOptions,
|
|
||||||
showControlsOnInitialize: hook.showControlsOnInitialize,
|
|
||||||
autoPlay: hook.autoPlay,
|
|
||||||
allowFullScreen: hook.allowFullScreen,
|
|
||||||
allowedScreenSleep: hook.allowedScreenSleep,
|
|
||||||
showControls: hook.showControls,
|
|
||||||
customControls: hook.customControls,
|
|
||||||
placeholder: hook.placeholder,
|
|
||||||
hideControlsTimer: hook.hideControlsTimer,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
import 'package:chewie/chewie.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:immich_mobile/utils/hooks/chewiew_controller_hook.dart';
|
|
||||||
import 'package:immich_mobile/widgets/asset_viewer/custom_video_player_controls.dart';
|
|
||||||
import 'package:video_player/video_player.dart';
|
|
||||||
|
|
||||||
class VideoPlayerViewer extends HookConsumerWidget {
|
|
||||||
final VideoPlayerController controller;
|
|
||||||
final bool isMotionVideo;
|
|
||||||
final Widget? placeholder;
|
|
||||||
final Duration hideControlsTimer;
|
|
||||||
final bool showControls;
|
|
||||||
final bool showDownloadingIndicator;
|
|
||||||
final bool loopVideo;
|
|
||||||
|
|
||||||
const VideoPlayerViewer({
|
|
||||||
super.key,
|
|
||||||
required this.controller,
|
|
||||||
required this.isMotionVideo,
|
|
||||||
this.placeholder,
|
|
||||||
required this.hideControlsTimer,
|
|
||||||
required this.showControls,
|
|
||||||
required this.showDownloadingIndicator,
|
|
||||||
required this.loopVideo,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final chewie = useChewieController(
|
|
||||||
controller: controller,
|
|
||||||
controlsSafeAreaMinimum: const EdgeInsets.only(
|
|
||||||
bottom: 100,
|
|
||||||
),
|
|
||||||
placeholder: SizedBox.expand(child: placeholder),
|
|
||||||
customControls: CustomVideoPlayerControls(
|
|
||||||
hideTimerDuration: hideControlsTimer,
|
|
||||||
),
|
|
||||||
showControls: showControls && !isMotionVideo,
|
|
||||||
hideControlsTimer: hideControlsTimer,
|
|
||||||
loopVideo: loopVideo,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Chewie(
|
|
||||||
controller: chewie,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue