import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:video_player/video_player.dart'; import '../controller/story_controller.dart'; import '../utils.dart'; class VideoLoader { String url; File? videoFile; Map? requestHeaders; LoadState state = LoadState.loading; VideoLoader(this.url, {this.requestHeaders}); void loadVideo(VoidCallback onComplete) { if (videoFile != null) { state = LoadState.success; onComplete(); } final fileStream = DefaultCacheManager().getFileStream(url, headers: requestHeaders as Map?); fileStream.listen((fileResponse) { if (fileResponse is FileInfo) { if (videoFile == null) { state = LoadState.success; videoFile = fileResponse.file; onComplete(); } } }); } } class StoryVideo extends StatefulWidget { final StoryController? storyController; final VideoLoader videoLoader; final Widget? loadingWidget; final Widget? errorWidget; StoryVideo( this.videoLoader, { Key? key, this.storyController, this.loadingWidget, this.errorWidget, }) : super(key: key ?? UniqueKey()); static StoryVideo url( String url, { StoryController? controller, Map? requestHeaders, Key? key, Widget? loadingWidget, Widget? errorWidget, }) { return StoryVideo( VideoLoader(url, requestHeaders: requestHeaders), storyController: controller, key: key, loadingWidget: loadingWidget, errorWidget: errorWidget, ); } @override State createState() { return StoryVideoState(); } } class StoryVideoState extends State { Future? playerLoader; StreamSubscription? _streamSubscription; VideoPlayerController? playerController; @override void initState() { super.initState(); widget.storyController!.pause(); widget.videoLoader.loadVideo(() { if (widget.videoLoader.state == LoadState.success) { playerController = VideoPlayerController.file(widget.videoLoader.videoFile!); playerController!.initialize().then((v) { setState(() {}); widget.storyController!.play(); }); if (widget.storyController != null) { _streamSubscription = widget.storyController!.playbackNotifier.listen((playbackState) { if (playbackState == PlaybackState.pause) { playerController!.pause(); } else { playerController!.play(); } }); } } else { setState(() {}); } }); } Widget getContentView() { if (widget.videoLoader.state == LoadState.success && playerController!.value.isInitialized) { return Center( child: AspectRatio( aspectRatio: playerController!.value.aspectRatio, child: VideoPlayer(playerController!), ), ); } return widget.videoLoader.state == LoadState.loading ? Center( child: widget.loadingWidget ?? const SizedBox( width: 70, height: 70, child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.white), strokeWidth: 3, ), ), ) : Center( child: widget.errorWidget ?? const Text( "Media failed to load.", style: TextStyle( color: Colors.white, ), )); } @override Widget build(BuildContext context) { return Container( color: Colors.black, height: double.infinity, width: double.infinity, child: getContentView(), ); } @override void dispose() { playerController?.dispose(); _streamSubscription?.cancel(); super.dispose(); } }