fix: properly dispose VideoPlayerController
This ensures that a playing video stops playing when we navigate away from the chat. I also reorganized the code a little.
This commit is contained in:
parent
7c1c1ad25c
commit
d9ee3fbec6
1 changed files with 35 additions and 28 deletions
|
|
@ -37,22 +37,30 @@ class EventVideoPlayer extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventVideoPlayerState extends State<EventVideoPlayer> {
|
class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
ChewieController? _chewieManager;
|
ChewieController? _chewieController;
|
||||||
|
VideoPlayerController? _videoPlayerController;
|
||||||
bool _isDownloading = false;
|
bool _isDownloading = false;
|
||||||
String? _networkUri;
|
|
||||||
File? _tmpFile;
|
|
||||||
|
|
||||||
void _downloadAction() async {
|
void _downloadAction() async {
|
||||||
if (PlatformInfos.isDesktop) {
|
if (PlatformInfos.isDesktop) {
|
||||||
widget.event.saveFile(context);
|
widget.event.saveFile(context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() => _isDownloading = true);
|
setState(() => _isDownloading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final videoFile = await widget.event.downloadAndDecryptAttachment();
|
final videoFile = await widget.event.downloadAndDecryptAttachment();
|
||||||
|
|
||||||
|
// Dispose the controllers if we already have them.
|
||||||
|
_disposeControllers();
|
||||||
|
late VideoPlayerController videoPlayerController;
|
||||||
|
|
||||||
|
// Create the VideoPlayerController from the contents of videoFile.
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
final blob = html.Blob([videoFile.bytes]);
|
final blob = html.Blob([videoFile.bytes]);
|
||||||
_networkUri = html.Url.createObjectUrlFromBlob(blob);
|
final networkUri = Uri.parse(html.Url.createObjectUrlFromBlob(blob));
|
||||||
|
videoPlayerController = VideoPlayerController.networkUrl(networkUri);
|
||||||
} else {
|
} else {
|
||||||
final tempDir = await getTemporaryDirectory();
|
final tempDir = await getTemporaryDirectory();
|
||||||
final fileName = Uri.encodeComponent(
|
final fileName = Uri.encodeComponent(
|
||||||
|
|
@ -62,25 +70,19 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
if (await file.exists() == false) {
|
if (await file.exists() == false) {
|
||||||
await file.writeAsBytes(videoFile.bytes);
|
await file.writeAsBytes(videoFile.bytes);
|
||||||
}
|
}
|
||||||
_tmpFile = file;
|
videoPlayerController = VideoPlayerController.file(file);
|
||||||
}
|
|
||||||
final tmpFile = _tmpFile;
|
|
||||||
final networkUri = _networkUri;
|
|
||||||
if (kIsWeb && networkUri != null && _chewieManager == null) {
|
|
||||||
_chewieManager ??= ChewieController(
|
|
||||||
videoPlayerController:
|
|
||||||
VideoPlayerController.networkUrl(Uri.parse(networkUri)),
|
|
||||||
autoPlay: true,
|
|
||||||
autoInitialize: true,
|
|
||||||
);
|
|
||||||
} else if (!kIsWeb && tmpFile != null && _chewieManager == null) {
|
|
||||||
_chewieManager ??= ChewieController(
|
|
||||||
useRootNavigator: false,
|
|
||||||
videoPlayerController: VideoPlayerController.file(tmpFile),
|
|
||||||
autoPlay: true,
|
|
||||||
autoInitialize: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
_videoPlayerController = videoPlayerController;
|
||||||
|
|
||||||
|
await videoPlayerController.initialize();
|
||||||
|
|
||||||
|
// Create a ChewieController on top.
|
||||||
|
_chewieController = ChewieController(
|
||||||
|
videoPlayerController: videoPlayerController,
|
||||||
|
useRootNavigator: !kIsWeb,
|
||||||
|
autoPlay: true,
|
||||||
|
autoInitialize: true,
|
||||||
|
);
|
||||||
} on IOException catch (e) {
|
} on IOException catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
|
|
@ -90,15 +92,20 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
ErrorReporter(context, 'Unable to play video').onErrorCallback(e, s);
|
ErrorReporter(context, 'Unable to play video').onErrorCallback(e, s);
|
||||||
} finally {
|
} finally {
|
||||||
// Workaround for Chewie needs time to get the aspectRatio
|
|
||||||
await Future.delayed(const Duration(milliseconds: 100));
|
|
||||||
setState(() => _isDownloading = false);
|
setState(() => _isDownloading = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _disposeControllers() {
|
||||||
|
_chewieController?.dispose();
|
||||||
|
_videoPlayerController?.dispose();
|
||||||
|
_chewieController = null;
|
||||||
|
_videoPlayerController = null;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_chewieManager?.dispose();
|
_disposeControllers();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +125,7 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
|
|
||||||
const width = 300.0;
|
const width = 300.0;
|
||||||
|
|
||||||
final chewieManager = _chewieManager;
|
final chewieController = _chewieController;
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
|
|
@ -128,8 +135,8 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: width,
|
height: width,
|
||||||
child: chewieManager != null
|
child: chewieController != null
|
||||||
? Center(child: Chewie(controller: chewieManager))
|
? Center(child: Chewie(controller: chewieController))
|
||||||
: Stack(
|
: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (hasThumbnail)
|
if (hasThumbnail)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue