From d8d815710f744d3b5ed5784851be1ea05e2c9c9d Mon Sep 17 00:00:00 2001 From: gianlucaparadise Date: Mon, 29 Nov 2021 20:09:25 +0100 Subject: [PATCH] ExpandedControls: integrate stream progress --- .../expanded_controls/ExpandedControls.dart | 43 +++++++++-- .../ExpandedControlsProgress.dart | 72 +++++++++++++++++-- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart index f5dbede..6b26f78 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControls.dart @@ -30,10 +30,11 @@ const _bottomUpBlackGradient = BoxDecoration( ), ); -class ExpandedControls extends StatelessWidget { +class ExpandedControls extends StatefulWidget { final FlutterCastFramework castFramework; final String castingToText; final VoidCallback? onBackTapped; + final controller = ExpandedControlsProgressController(); ExpandedControls({ required this.castFramework, @@ -41,6 +42,33 @@ class ExpandedControls extends StatelessWidget { this.onBackTapped, }); + @override + State createState() => _ExpandedControlsState(); +} + +class _ExpandedControlsState extends State { + @override + void initState() { + final sessionManager = widget.castFramework.castContext.sessionManager; + sessionManager.remoteMediaClient.onProgressUpdated = _onProgressUpdated; + + super.initState(); + } + + @override + void dispose() { + final sessionManager = widget.castFramework.castContext.sessionManager; + sessionManager.remoteMediaClient.onProgressUpdated = null; + + widget.controller.dispose(); + + super.dispose(); + } + + void _onProgressUpdated(int progress, int duration) { + widget.controller.updateProgress(progress, duration); + } + Widget _getDecoratedToolbar(MediaInfo? mediaInfo) { // Title and subtitle can't be retrieved at the moment // final title = mediaInfo?.mediaMetadata?.strings[MediaMetadataKey.title] @@ -51,13 +79,15 @@ class ExpandedControls extends StatelessWidget { return Container( decoration: _topDownBlackGradient, child: ExpandedControlsToolbar( + castFramework: widget.castFramework, title: title, subtitle: subtitle, + onBackTapped: widget.onBackTapped, ), ); } - Widget _getDecorateControls(BuildContext context) { + Widget _getDecoratedControls(BuildContext context, MediaInfo? mediaInfo) { final textStyle = Theme.of(context).textTheme.bodyText2?.copyWith(color: Colors.white); @@ -67,11 +97,14 @@ class ExpandedControls extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.all(8.0), - child: Text("$castingToText $castDevice", style: textStyle), + child: + Text("${widget.castingToText} $castDevice", style: textStyle), ), Padding( padding: const EdgeInsets.all(8.0), - child: ExpandedControlsProgress(), + child: ExpandedControlsProgress( + controller: widget.controller, + ), ), Padding( padding: const EdgeInsets.all(8.0), @@ -104,7 +137,7 @@ class ExpandedControls extends StatelessWidget { children: [ _getDecoratedToolbar(mediaInfo), Spacer(), - _getDecorateControls(context), + _getDecoratedControls(context, mediaInfo), ], ), ); diff --git a/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart b/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart index d759b5f..defa59e 100644 --- a/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart +++ b/lib/src/cast/widgets/expanded_controls/ExpandedControlsProgress.dart @@ -1,29 +1,83 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -class ExpandedControlsProgress extends StatelessWidget { +class ExpandedControlsProgressController extends ChangeNotifier { + int progress = 0; + int duration = 0; + + void updateProgress(int progress, int duration) { + this.progress = progress; + this.duration = duration; + notifyListeners(); + } +} + +class ExpandedControlsProgress extends StatefulWidget { + final ExpandedControlsProgressController controller; + + const ExpandedControlsProgress({ + Key? key, + required this.controller, + }) : super(key: key); + + @override + State createState() => + _ExpandedControlsProgressState(); +} + +class _ExpandedControlsProgressState extends State { + int progress = 0; + int duration = 0; + + @override + void initState() { + widget.controller.addListener(_onProgressUpdated); + super.initState(); + } + + @override + void dispose() { + widget.controller.removeListener(_onProgressUpdated); + super.dispose(); + } + + void _onProgressUpdated() { + setState(() { + if (!mounted) return; + this.progress = widget.controller.progress; + this.duration = widget.controller.duration; + }); + } + @override Widget build(BuildContext context) { final textStyle = Theme.of(context).textTheme.bodyText2?.copyWith(color: Colors.white); + // this is the denominator, can't be 0 + final durationFix = this.duration == 0 ? 1 : this.duration; + final progressPercent = this.progress / durationFix; + + final progressD = Duration(milliseconds: this.progress); + final durationD = Duration(milliseconds: this.duration); + return Column( children: [ LinearProgressIndicator( color: Colors.red, backgroundColor: Colors.grey, - value: 0.5, + value: progressPercent, ), Container(height: 8), // Spacer Row( children: [ Text( - "start", + _positionToString(progressD, durationD), style: textStyle, ), Spacer(), Text( - "end", + _positionToString(durationD, durationD), style: textStyle, ), ], @@ -32,3 +86,13 @@ class ExpandedControlsProgress extends StatelessWidget { ); } } + +String _positionToString(Duration d, Duration total) { + String twoDigits(int n) => n.toString().padLeft(2, "0"); + if (total.inMinutes <= 60) { + // This is less than a hour, I display only minutes and seconds + return "${twoDigits(d.inMinutes)}:${twoDigits(d.inSeconds.remainder(60))}"; + } + + return "${twoDigits(d.inHours)}:${twoDigits(d.inMinutes.remainder(60))}:${twoDigits(d.inSeconds.remainder(60))}"; +}