From 3ecd3d0a140691a80a1547b2a4980a89f8ecefda Mon Sep 17 00:00:00 2001 From: Schnitzel5 Date: Sat, 22 Feb 2025 21:00:32 +0100 Subject: [PATCH] added long press for 2x playback speed --- lib/modules/anime/anime_player_view.dart | 24 ++++++++++++++++++++++++ lib/modules/anime/widgets/desktop.dart | 20 +++++++++++++++++++- lib/modules/anime/widgets/mobile.dart | 20 +++++++++++++++++++- lib/services/aniskip.g.dart | 2 +- lib/services/trackers/anilist.g.dart | 2 +- 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/modules/anime/anime_player_view.dart b/lib/modules/anime/anime_player_view.dart index 97b55088..f33053fd 100644 --- a/lib/modules/anime/anime_player_view.dart +++ b/lib/modules/anime/anime_player_view.dart @@ -171,6 +171,7 @@ class _AnimeStreamPageState extends riv.ConsumerState headers: _firstVid.headers)); final ValueNotifier _playbackSpeed = ValueNotifier(1.0); final ValueNotifier _enterFullScreen = ValueNotifier(false); + final ValueNotifier _isDoubleSpeed = ValueNotifier(false); late final ValueNotifier _currentPosition = ValueNotifier(_streamController.geTCurrentPosition()); final ValueNotifier _currentTotalDuration = ValueNotifier(null); @@ -977,6 +978,23 @@ class _AnimeStreamPageState extends riv.ConsumerState ), ), ), + Flexible( + fit: FlexFit.tight, + child: ValueListenableBuilder( + valueListenable: _isDoubleSpeed, + builder: (context, snapshot, _) { + return Text.rich( + TextSpan( + children: snapshot + ? [ + WidgetSpan(child: Icon(Icons.fast_forward)), + TextSpan(text: " 2X"), + ] + : [], + ), + ); + }), + ), Row(children: [ btnToShowChapterListDialog( context, @@ -1080,6 +1098,9 @@ class _AnimeStreamPageState extends riv.ConsumerState tempDuration: (value) { _tempPosition.value = value; }, + doubleSpeed: (value) { + _isDoubleSpeed.value = value ?? false; + }, ) : MobileControllerWidget( videoController: _controller, @@ -1087,6 +1108,9 @@ class _AnimeStreamPageState extends riv.ConsumerState videoStatekey: _key, bottomButtonBarWidget: _mobileBottomButtonBar(context), streamController: _streamController, + doubleSpeed: (value) { + _isDoubleSpeed.value = value ?? false; + }, ), controller: _controller, width: context.width(1), diff --git a/lib/modules/anime/widgets/desktop.dart b/lib/modules/anime/widgets/desktop.dart index 04faf90d..9a38796b 100644 --- a/lib/modules/anime/widgets/desktop.dart +++ b/lib/modules/anime/widgets/desktop.dart @@ -15,6 +15,7 @@ import 'package:window_manager/window_manager.dart'; class DesktopControllerWidget extends StatefulWidget { final Function(Duration?) tempDuration; + final Function(bool?) doubleSpeed; final AnimeStreamController streamController; final VideoController videoController; final Widget topButtonBarWidget; @@ -29,7 +30,8 @@ class DesktopControllerWidget extends StatefulWidget { required this.streamController, required this.videoStatekey, required this.seekToWidget, - required this.tempDuration}); + required this.tempDuration, + required this.doubleSpeed}); @override State createState() => @@ -46,6 +48,7 @@ class _DesktopControllerWidgetState extends State { int swipeDuration = 0; // Duration to seek in video bool showSwipeDuration = false; // Whether to show the seek duration overlay + double previousPlaybackSpeed = -1; late bool buffering = widget.videoController.player.state.buffering; final controlsHoverDuration = const Duration(seconds: 3); @@ -230,6 +233,21 @@ class _DesktopControllerWidgetState extends State { } : null, child: GestureDetector( + onLongPressStart: (e) { + previousPlaybackSpeed = + widget.videoController.player.state.rate; + widget.videoController.player + .setRate(previousPlaybackSpeed * 2); + widget.doubleSpeed(true); + }, + onLongPressEnd: (e) { + if (previousPlaybackSpeed != -1) { + widget.videoController.player + .setRate(previousPlaybackSpeed); + previousPlaybackSpeed = -1; + widget.doubleSpeed(false); + } + }, onTapUp: !toggleFullscreenOnDoublePress ? null : (e) { diff --git a/lib/modules/anime/widgets/mobile.dart b/lib/modules/anime/widgets/mobile.dart index 95f276a0..6bd19abd 100644 --- a/lib/modules/anime/widgets/mobile.dart +++ b/lib/modules/anime/widgets/mobile.dart @@ -17,6 +17,7 @@ import 'package:media_kit_video/media_kit_video.dart'; import 'package:media_kit_video/media_kit_video_controls/src/controls/extensions/duration.dart'; class MobileControllerWidget extends ConsumerStatefulWidget { + final Function(bool?) doubleSpeed; final AnimeStreamController streamController; final VideoController videoController; final Widget topButtonBarWidget; @@ -28,7 +29,8 @@ class MobileControllerWidget extends ConsumerStatefulWidget { required this.topButtonBarWidget, required this.bottomButtonBarWidget, required this.streamController, - required this.videoStatekey}); + required this.videoStatekey, + required this.doubleSpeed}); @override ConsumerState createState() => @@ -58,6 +60,7 @@ class _MobileControllerWidgetState Offset.zero; // Initial position for horizontal drag int swipeDuration = 0; // Duration to seek in video bool showSwipeDuration = false; // Whether to show the seek duration overlay + double previousPlaybackSpeed = -1; late bool buffering = widget.videoController.player.state.buffering; final controlsHoverDuration = const Duration(seconds: 3); @@ -346,6 +349,21 @@ class _MobileControllerWidgetState onDoubleTapSeekBackward(); } }, + onLongPressStart: (e) { + previousPlaybackSpeed = + widget.videoController.player.state.rate; + widget.videoController.player + .setRate(previousPlaybackSpeed * 2); + widget.doubleSpeed(true); + }, + onLongPressEnd: (e) { + if (previousPlaybackSpeed != -1) { + widget.videoController.player + .setRate(previousPlaybackSpeed); + previousPlaybackSpeed = -1; + widget.doubleSpeed(false); + } + }, onHorizontalDragUpdate: (details) { onHorizontalDragUpdate(details); }, diff --git a/lib/services/aniskip.g.dart b/lib/services/aniskip.g.dart index b2e1defb..c05db920 100644 --- a/lib/services/aniskip.g.dart +++ b/lib/services/aniskip.g.dart @@ -6,7 +6,7 @@ part of 'aniskip.dart'; // RiverpodGenerator // ************************************************************************** -String _$aniSkipHash() => r'887869b54e2e151633efd46da83bde845e14f421'; +String _$aniSkipHash() => r'2e5d19b025a2207ff64da7bf7908450ea9e5ff8c'; /// See also [AniSkip]. @ProviderFor(AniSkip) diff --git a/lib/services/trackers/anilist.g.dart b/lib/services/trackers/anilist.g.dart index 558da2c4..834afd64 100644 --- a/lib/services/trackers/anilist.g.dart +++ b/lib/services/trackers/anilist.g.dart @@ -6,7 +6,7 @@ part of 'anilist.dart'; // RiverpodGenerator // ************************************************************************** -String _$anilistHash() => r'70e8cd537270a9054a1ef72de117fc7ad5545218'; +String _$anilistHash() => r'ddd07acc8d28d2aa95c942566109e9393ca9e5ed'; /// Copied from Dart SDK class _SystemHash {