diff --git a/lib/widgets/viewer/overlay/video/progress_bar.dart b/lib/widgets/viewer/overlay/video/progress_bar.dart index aa9a1774c..185b7e691 100644 --- a/lib/widgets/viewer/overlay/video/progress_bar.dart +++ b/lib/widgets/viewer/overlay/video/progress_bar.dart @@ -2,12 +2,14 @@ import 'dart:async'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/format.dart'; +import 'package:aves/theme/icons.dart'; import 'package:aves/theme/themes.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/common/fx/blurred.dart'; import 'package:aves/widgets/common/fx/borders.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class VideoProgressBar extends StatefulWidget { final AvesVideoController? controller; @@ -114,10 +116,16 @@ class _VideoProgressBarState extends State { }), ), ), - Text( - // fake text below to match the height of the text above and center the whole thing - '', - style: textStyle, + Row( + children: [ + _buildSpeedIndicator(), + _buildMuteIndicator(), + Text( + // fake text below to match the height of the text above and center the whole thing + '', + style: textStyle, + ), + ], ), ], ), @@ -128,6 +136,38 @@ class _VideoProgressBarState extends State { ); } + Widget _buildSpeedIndicator() => StreamBuilder( + stream: controller?.speedStream ?? Stream.value(1.0), + builder: (context, snapshot) { + final speed = controller?.speed ?? 1.0; + return speed != 1 + ? Padding( + padding: const EdgeInsetsDirectional.only(end: 8), + child: Text('x$speed'), + ) + : const SizedBox(); + }, + ); + + Widget _buildMuteIndicator() => StreamBuilder( + stream: controller?.volumeStream ?? Stream.value(1.0), + builder: (context, snapshot) { + final isMuted = controller?.isMuted ?? false; + return isMuted + ? Padding( + padding: const EdgeInsetsDirectional.only(end: 8), + child: Selector( + selector: (context, mq) => mq.textScaleFactor, + builder: (context, textScaleFactor, child) => Icon( + AIcons.mute, + size: 16 * textScaleFactor, + ), + ), + ) + : const SizedBox(); + }, + ); + void _seekFromTap(Offset globalPosition) async { if (controller == null) return; final keyContext = _progressBarKey.currentContext!; diff --git a/lib/widgets/viewer/video/controller.dart b/lib/widgets/viewer/video/controller.dart index 6507d5e58..cb07d6e4a 100644 --- a/lib/widgets/viewer/video/controller.dart +++ b/lib/widgets/viewer/video/controller.dart @@ -94,6 +94,8 @@ abstract class AvesVideoController { Stream get volumeStream; + Stream get speedStream; + bool get isReady; bool get isPlaying => status == VideoStatus.playing; diff --git a/lib/widgets/viewer/video/fijkplayer.dart b/lib/widgets/viewer/video/fijkplayer.dart index 253a946b8..2954be504 100644 --- a/lib/widgets/viewer/video/fijkplayer.dart +++ b/lib/widgets/viewer/video/fijkplayer.dart @@ -18,6 +18,7 @@ class IjkPlayerAvesVideoController extends AvesVideoController { final StreamController _valueStreamController = StreamController.broadcast(); final StreamController _timedTextStreamController = StreamController.broadcast(); final StreamController _volumeStreamController = StreamController.broadcast(); + final StreamController _speedStreamController = StreamController.broadcast(); final AChangeNotifier _completedNotifier = AChangeNotifier(); Offset _macroBlockCrop = Offset.zero; final List _streams = []; @@ -333,6 +334,9 @@ class IjkPlayerAvesVideoController extends AvesVideoController { @override Stream get volumeStream => _volumeStreamController.stream; + @override + Stream get speedStream => _speedStreamController.stream; + @override bool get isReady => _instance.isPlayable(); @@ -372,6 +376,7 @@ class IjkPlayerAvesVideoController extends AvesVideoController { if (speed <= 0 || _speed == speed) return; final optionChange = _needSoundTouch(speed) != _needSoundTouch(_speed); _speed = speed; + _speedStreamController.add(_speed); if (optionChange) { _init(startMillis: currentPosition);