From e0b3f92b651ea768514e03ee83da3e6c321b5e34 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 30 Oct 2024 11:40:07 +0100 Subject: [PATCH] video: custom playback buttons --- lib/l10n/app_en.arb | 3 - lib/model/settings/settings.dart | 4 +- lib/view/src/actions/entry.dart | 3 +- lib/view/src/settings/enums.dart | 12 ---- .../settings/video/control_actions.dart | 58 +++++++++++++++++++ lib/widgets/settings/video/controls.dart | 13 ++--- .../viewer/overlay/video/controls.dart | 25 +------- plugins/aves_model/lib/src/actions/entry.dart | 4 +- .../aves_model/lib/src/settings/enums.dart | 2 - plugins/aves_model/lib/src/settings/keys.dart | 2 +- .../aves_video/lib/src/settings/defaults.dart | 2 +- .../aves_video/lib/src/settings/video.dart | 4 +- 12 files changed, 76 insertions(+), 56 deletions(-) create mode 100644 lib/widgets/settings/video/control_actions.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 8d2b93dd5..95df01843 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -272,10 +272,7 @@ "settingsVideoEnablePip": "Picture-in-picture", - "videoControlsPlay": "Play", - "videoControlsPlaySeek": "Play & seek backward/forward", "videoControlsPlayOutside": "Open with other player", - "videoControlsNone": "None", "videoLoopModeNever": "Never", "videoLoopModeShortOnly": "Short videos only", diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 57eb786c1..40804ec4f 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -133,7 +133,7 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings viewerGestureSideTapNext = false; viewerUseCutout = true; videoBackgroundMode = VideoBackgroundMode.disabled; - videoControls = VideoControls.none; + videoControlActions = []; videoGestureDoubleTapTogglePlay = false; videoGestureSideDoubleTapSeek = false; enableBin = false; @@ -459,7 +459,6 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings case SettingKeys.videoBackgroundModeKey: case SettingKeys.videoLoopModeKey: case SettingKeys.videoResumptionModeKey: - case SettingKeys.videoControlsKey: case SettingKeys.subtitleTextAlignmentKey: case SettingKeys.subtitleTextPositionKey: case SettingKeys.tagEditorExpandedSectionKey: @@ -490,6 +489,7 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings case SettingKeys.collectionBrowsingQuickActionsKey: case SettingKeys.collectionSelectionQuickActionsKey: case SettingKeys.viewerQuickActionsKey: + case SettingKeys.videoControlActionsKey: case SettingKeys.screenSaverCollectionFiltersKey: if (newValue is List) { store.setStringList(key, newValue.cast()); diff --git a/lib/view/src/actions/entry.dart b/lib/view/src/actions/entry.dart index dae941f3f..943b7bf60 100644 --- a/lib/view/src/actions/entry.dart +++ b/lib/view/src/actions/entry.dart @@ -47,7 +47,8 @@ extension ExtraEntryActionView on EntryAction { EntryAction.videoShowNextFrame => l10n.videoActionShowNextFrame, // external EntryAction.edit => l10n.entryActionEdit, - EntryAction.open || EntryAction.openVideo => l10n.entryActionOpen, + EntryAction.open => l10n.entryActionOpen, + EntryAction.openVideo => l10n.videoControlsPlayOutside, EntryAction.openMap => l10n.entryActionOpenMap, EntryAction.setAs => l10n.entryActionSetAs, EntryAction.cast => l10n.entryActionCast, diff --git a/lib/view/src/settings/enums.dart b/lib/view/src/settings/enums.dart index 64c41c1d5..10854be4c 100644 --- a/lib/view/src/settings/enums.dart +++ b/lib/view/src/settings/enums.dart @@ -174,18 +174,6 @@ extension ExtraVideoBackgroundModeView on VideoBackgroundMode { } } -extension ExtraVideoControlsView on VideoControls { - String getName(BuildContext context) { - final l10n = context.l10n; - return switch (this) { - VideoControls.play => l10n.videoControlsPlay, - VideoControls.playSeek => l10n.videoControlsPlaySeek, - VideoControls.playOutside => l10n.videoControlsPlayOutside, - VideoControls.none => l10n.videoControlsNone, - }; - } -} - extension ExtraVideoLoopModeView on VideoLoopMode { String getName(BuildContext context) { final l10n = context.l10n; diff --git a/lib/widgets/settings/video/control_actions.dart b/lib/widgets/settings/video/control_actions.dart new file mode 100644 index 000000000..1783bf377 --- /dev/null +++ b/lib/widgets/settings/video/control_actions.dart @@ -0,0 +1,58 @@ +import 'package:aves/model/settings/settings.dart'; +import 'package:aves/view/view.dart'; +import 'package:aves/widgets/common/basic/scaffold.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves_model/aves_model.dart'; +import 'package:flutter/material.dart'; + +class VideoControlButtonsPage extends StatefulWidget { + static const routeName = '/settings/video/control_buttons'; + + const VideoControlButtonsPage({super.key}); + + @override + State createState() => _VideoControlButtonsPageState(); +} + +class _VideoControlButtonsPageState extends State { + late final Set _selectedActions; + + static const _availableActions = [...EntryActions.videoPlayback, EntryAction.openVideo]; + + @override + void initState() { + super.initState(); + _selectedActions = settings.videoControlActions.toSet(); + } + + @override + Widget build(BuildContext context) { + return AvesScaffold( + appBar: AppBar( + automaticallyImplyLeading: !settings.useTvLayout, + title: Text(context.l10n.settingsViewerOverlayPageTitle), + ), + body: SafeArea( + child: PopScope( + canPop: true, + onPopInvokedWithResult: (didPop, result) => settings.videoControlActions = _availableActions.where(_selectedActions.contains).toList(), + child: ListView( + children: _availableActions.map((action) { + return SwitchListTile( + value: _selectedActions.contains(action), + onChanged: (v) => setState(() { + if (v) { + _selectedActions.add(action); + } else { + _selectedActions.remove(action); + } + }), + title: Text(action.getText(context)), + ); + }).toList(), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/settings/video/controls.dart b/lib/widgets/settings/video/controls.dart index 509284435..da1ceeecd 100644 --- a/lib/widgets/settings/video/controls.dart +++ b/lib/widgets/settings/video/controls.dart @@ -1,9 +1,8 @@ import 'package:aves/model/settings/settings.dart'; -import 'package:aves/view/view.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/common/tiles.dart'; -import 'package:aves_model/aves_model.dart'; +import 'package:aves/widgets/settings/video/control_actions.dart'; import 'package:flutter/material.dart'; class VideoControlsPage extends StatelessWidget { @@ -20,12 +19,10 @@ class VideoControlsPage extends StatelessWidget { body: SafeArea( child: ListView( children: [ - SettingsSelectionListTile( - values: VideoControls.values, - getName: (context, v) => v.getName(context), - selector: (context, s) => s.videoControls, - onSelection: (v) => settings.videoControls = v, - tileTitle: context.l10n.settingsVideoButtonsTile, + SettingsSubPageTile( + title: context.l10n.settingsVideoButtonsTile, + routeName: VideoControlButtonsPage.routeName, + builder: (context) => const VideoControlButtonsPage(), ), SettingsSwitchListTile( selector: (context, s) => s.videoGestureDoubleTapTogglePlay, diff --git a/lib/widgets/viewer/overlay/video/controls.dart b/lib/widgets/viewer/overlay/video/controls.dart index ee88fb3bc..b538ca0c0 100644 --- a/lib/widgets/viewer/overlay/video/controls.dart +++ b/lib/widgets/viewer/overlay/video/controls.dart @@ -28,11 +28,9 @@ class VideoControlRow extends StatelessWidget { @override Widget build(BuildContext context) { - return Selector( - selector: (context, s) => s.videoControls, - builder: (context, videoControls, child) { - final actions = _toActions(videoControls); - + return Selector>( + selector: (context, s) => s.videoControlActions, + builder: (context, actions, child) { if (actions.isEmpty) { return const SizedBox(); } @@ -65,23 +63,6 @@ class VideoControlRow extends StatelessWidget { ); } - List _toActions(VideoControls videoControls) { - switch (videoControls) { - case VideoControls.play: - return [EntryAction.videoTogglePlay]; - case VideoControls.playSeek: - return [ - EntryAction.videoReplay10, - EntryAction.videoTogglePlay, - EntryAction.videoSkip10, - ]; - case VideoControls.playOutside: - return [EntryAction.openVideo]; - case VideoControls.none: - return []; - } - } - Widget _buildOverlayButton( BuildContext context, EntryAction action, { diff --git a/plugins/aves_model/lib/src/actions/entry.dart b/plugins/aves_model/lib/src/actions/entry.dart index fc1981a55..eef9c19a9 100644 --- a/plugins/aves_model/lib/src/actions/entry.dart +++ b/plugins/aves_model/lib/src/actions/entry.dart @@ -117,8 +117,6 @@ class EntryActions { EntryAction.videoToggleMute, EntryAction.videoSetSpeed, EntryAction.videoABRepeat, - EntryAction.videoShowPreviousFrame, - EntryAction.videoShowNextFrame, EntryAction.videoSelectStreams, EntryAction.videoSettings, EntryAction.lockViewer, @@ -126,7 +124,9 @@ class EntryActions { static const videoPlayback = [ EntryAction.videoReplay10, + EntryAction.videoShowPreviousFrame, EntryAction.videoTogglePlay, + EntryAction.videoShowNextFrame, EntryAction.videoSkip10, ]; diff --git a/plugins/aves_model/lib/src/settings/enums.dart b/plugins/aves_model/lib/src/settings/enums.dart index fce0ea57e..196d57774 100644 --- a/plugins/aves_model/lib/src/settings/enums.dart +++ b/plugins/aves_model/lib/src/settings/enums.dart @@ -36,8 +36,6 @@ enum VideoAutoPlayMode { disabled, playMuted, playWithSound } enum VideoBackgroundMode { disabled, pip } -enum VideoControls { play, playSeek, playOutside, none } - enum VideoLoopMode { never, shortOnly, always } enum VideoResumptionMode { never, ask, always } diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart index a0ca10939..19be577ed 100644 --- a/plugins/aves_model/lib/src/settings/keys.dart +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -109,7 +109,7 @@ class SettingKeys { static const videoAutoPlayModeKey = 'video_auto_play_mode'; static const videoLoopModeKey = 'video_loop'; static const videoResumptionModeKey = 'video_resumption_mode'; - static const videoControlsKey = 'video_controls'; + static const videoControlActionsKey = 'video_control_actions'; static const videoGestureDoubleTapTogglePlayKey = 'video_gesture_double_tap_toggle_play'; static const videoGestureSideDoubleTapSeekKey = 'video_gesture_side_double_tap_skip'; static const videoGestureVerticalDragBrightnessVolumeKey = 'video_gesture_vertical_drag_brightness_volume'; diff --git a/plugins/aves_video/lib/src/settings/defaults.dart b/plugins/aves_video/lib/src/settings/defaults.dart index fcdc9b0df..dd457cccc 100644 --- a/plugins/aves_video/lib/src/settings/defaults.dart +++ b/plugins/aves_video/lib/src/settings/defaults.dart @@ -11,7 +11,7 @@ class SettingsDefaults { static const videoLoopMode = VideoLoopMode.shortOnly; static const videoResumptionMode = VideoResumptionMode.ask; static const videoShowRawTimedText = false; - static const videoControls = VideoControls.play; + static const videoControlActions = [EntryAction.videoTogglePlay]; static const videoGestureDoubleTapTogglePlay = false; static const videoGestureSideDoubleTapSeek = true; static const videoGestureVerticalDragBrightnessVolume = false; diff --git a/plugins/aves_video/lib/src/settings/video.dart b/plugins/aves_video/lib/src/settings/video.dart index 11aa335ff..80be2351f 100644 --- a/plugins/aves_video/lib/src/settings/video.dart +++ b/plugins/aves_video/lib/src/settings/video.dart @@ -22,9 +22,9 @@ mixin VideoSettings on SettingsAccess { set videoResumptionMode(VideoResumptionMode newValue) => set(SettingKeys.videoResumptionModeKey, newValue.toString()); - VideoControls get videoControls => getEnumOrDefault(SettingKeys.videoControlsKey, SettingsDefaults.videoControls, VideoControls.values); + List get videoControlActions => getEnumListOrDefault(SettingKeys.videoControlActionsKey, SettingsDefaults.videoControlActions, EntryAction.values); - set videoControls(VideoControls newValue) => set(SettingKeys.videoControlsKey, newValue.toString()); + set videoControlActions(List newValue) => set(SettingKeys.videoControlActionsKey, newValue.map((v) => v.toString()).toList()); bool get videoGestureDoubleTapTogglePlay => getBool(SettingKeys.videoGestureDoubleTapTogglePlayKey) ?? SettingsDefaults.videoGestureDoubleTapTogglePlay;