ExpandedControls: integrate stream progress
This commit is contained in:
parent
a5530e7441
commit
d8d815710f
2 changed files with 106 additions and 9 deletions
|
|
@ -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<ExpandedControls> createState() => _ExpandedControlsState();
|
||||
}
|
||||
|
||||
class _ExpandedControlsState extends State<ExpandedControls> {
|
||||
@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),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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<ExpandedControlsProgress> createState() =>
|
||||
_ExpandedControlsProgressState();
|
||||
}
|
||||
|
||||
class _ExpandedControlsProgressState extends State<ExpandedControlsProgress> {
|
||||
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))}";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue