From 995eba0e3e6409185c148f40ea0e9589b2a29860 Mon Sep 17 00:00:00 2001 From: MSOB7YY Date: Tue, 23 Jul 2024 00:50:59 +0300 Subject: [PATCH] feat: add "mark_video_watched" as a flag in youtube settings --- lib/base/audio_handler.dart | 4 +- lib/controller/settings.youtube.dart | 15 ++++-- lib/ui/widgets/settings/youtube_settings.dart | 52 +++++++++++++++++++ .../info_controllers/yt_history_linker.dart | 6 ++- pubspec.yaml | 2 +- 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/lib/base/audio_handler.dart b/lib/base/audio_handler.dart index be5cabbe..2901cd9b 100644 --- a/lib/base/audio_handler.dart +++ b/lib/base/audio_handler.dart @@ -852,7 +852,7 @@ class NamidaAudioVideoHandler extends BasicAudioHandler { /// Shows error if [marked] is not true. void _onVideoMarkWatchResultError(YTMarkVideoWatchedResult marked) { if (marked == YTMarkVideoWatchedResult.addedAsPending) { - snackyy(message: 'Failed to mark video as watched.', top: false, isError: true); + snackyy(message: 'Failed to mark video as watched, saved as pending.', top: false, isError: true); } } @@ -1060,7 +1060,7 @@ class NamidaAudioVideoHandler extends BasicAudioHandler { // -- older request was initiated, wait to see the value. markedAsWatched.future.then( (marked) { - if (marked == YTMarkVideoWatchedResult.noAccount && streamsResult != null) { + if ((marked == YTMarkVideoWatchedResult.noAccount || marked == YTMarkVideoWatchedResult.userDenied) && streamsResult != null) { YoutubeInfoController.history.markVideoWatched(videoId: item.id, streamResult: streamsResult).then(_onVideoMarkWatchResultError); } }, diff --git a/lib/controller/settings.youtube.dart b/lib/controller/settings.youtube.dart index 319de9b2..0143fc9a 100644 --- a/lib/controller/settings.youtube.dart +++ b/lib/controller/settings.youtube.dart @@ -6,10 +6,15 @@ class _YoutubeSettings with SettingsFileWriter { final ytVisibleShorts = {}.obs; final ytVisibleMixes = {}.obs; + bool markVideoWatched = true; int addToPlaylistsTabIndex = 0; - void save({int? addToPlaylistsTabIndex}) { + void save({ + int? addToPlaylistsTabIndex, + bool? markVideoWatched, + }) { if (addToPlaylistsTabIndex != null) this.addToPlaylistsTabIndex = addToPlaylistsTabIndex; + if (markVideoWatched != null) this.markVideoWatched = markVideoWatched; _writeToStorage(); } @@ -27,9 +32,10 @@ class _YoutubeSettings with SettingsFileWriter { final json = await prepareSettingsFile_(); if (json == null) return; try { - ytVisibleShorts.value = (json['ytVisibleShorts'] as Map?)?.map((key, value) => MapEntry(YTVisibleShortPlaces.values.getEnum(key)!, value)) ?? {}; - ytVisibleMixes.value = (json['ytVisibleMixes'] as Map?)?.map((key, value) => MapEntry(YTVisibleMixesPlaces.values.getEnum(key)!, value)) ?? {}; - addToPlaylistsTabIndex = json['addToPlaylistsTabIndex'] ?? 0; + ytVisibleShorts.value = (json['ytVisibleShorts'] as Map?)?.map((key, value) => MapEntry(YTVisibleShortPlaces.values.getEnum(key)!, value)) ?? ytVisibleShorts.value; + ytVisibleMixes.value = (json['ytVisibleMixes'] as Map?)?.map((key, value) => MapEntry(YTVisibleMixesPlaces.values.getEnum(key)!, value)) ?? ytVisibleMixes.value; + addToPlaylistsTabIndex = json['addToPlaylistsTabIndex'] ?? addToPlaylistsTabIndex; + markVideoWatched = json['markVideoWatched'] ?? markVideoWatched; } catch (e) { printy(e, isError: true); } @@ -40,6 +46,7 @@ class _YoutubeSettings with SettingsFileWriter { 'ytVisibleShorts': ytVisibleShorts.map((key, value) => MapEntry(key.convertToString, value)), 'ytVisibleMixes': ytVisibleMixes.map((key, value) => MapEntry(key.convertToString, value)), 'addToPlaylistsTabIndex ': addToPlaylistsTabIndex, + 'markVideoWatched ': markVideoWatched, }; Future _writeToStorage() async => await writeToStorage(); diff --git a/lib/ui/widgets/settings/youtube_settings.dart b/lib/ui/widgets/settings/youtube_settings.dart index c72d5ed9..65ad7809 100644 --- a/lib/ui/widgets/settings/youtube_settings.dart +++ b/lib/ui/widgets/settings/youtube_settings.dart @@ -55,12 +55,34 @@ class YoutubeSettings extends SettingSubpageProvider { _YoutubeSettingKeys.onOpeningYTLink: [lang.ON_OPENING_YOUTUBE_LINK], }; + void _showYTFlagsDialog() { + NamidaNavigator.inst.navigateDialog( + dialog: CustomBlurryDialog( + icon: Broken.flag, + title: lang.CONFIGURE, + normalTitleStyle: true, + actions: [ + NamidaButton( + text: lang.DONE, + onPressed: NamidaNavigator.inst.closeDialog, + ), + ], + child: const _YTFlagsOptions(), + ), + ); + } + @override Widget build(BuildContext context) { return SettingsCard( title: lang.YOUTUBE, subtitle: lang.YOUTUBE_SETTINGS_SUBTITLE, icon: Broken.video, + trailing: NamidaIconButton( + icon: Broken.flag, + tooltip: () => lang.REFRESH_LIBRARY, + onPressed: _showYTFlagsDialog, + ), child: Column( children: [ getItemWrapper( @@ -492,3 +514,33 @@ class _ShowItemInListTile extends StatelessWidget { ); } } + +class _YTFlagsOptions extends StatefulWidget { + const _YTFlagsOptions(); + + @override + State<_YTFlagsOptions> createState() => __YTFlagsOptionsState(); +} + +class __YTFlagsOptionsState extends State<_YTFlagsOptions> { + @override + Widget build(BuildContext context) { + return SizedBox( + width: context.width, + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: context.height * 0.6), + child: ListView( + padding: EdgeInsets.zero, + shrinkWrap: true, + children: [ + CustomSwitchListTile( + value: settings.youtube.markVideoWatched, + onChanged: (isTrue) => settings.youtube.save(markVideoWatched: !isTrue), + title: 'mark_video_watched'.toUpperCase(), + ), + ], + ), + ), + ); + } +} diff --git a/lib/youtube/controller/info_controllers/yt_history_linker.dart b/lib/youtube/controller/info_controllers/yt_history_linker.dart index 44c560ea..e16307d9 100644 --- a/lib/youtube/controller/info_controllers/yt_history_linker.dart +++ b/lib/youtube/controller/info_controllers/yt_history_linker.dart @@ -22,6 +22,7 @@ class _YoutubeHistoryLinker { _dbOpenedAccId = accId; _pendingRequestsDBIdle?.close(); + if (accId == null) return; _pendingRequestsDBIdle = DBWrapper.open(_dbDirectory, 'pending_history_$accId'); _pendingRequestsCompleter?.completeIfWasnt(); _pendingRequestsCompleter = null; @@ -66,7 +67,8 @@ class _YoutubeHistoryLinker { } void executePendingRequests() async { - if (!_hasConnection) return null; + if (!_hasConnection) return; + if (!settings.youtube.markVideoWatched) return; if (_pendingRequestsCompleter != null) { // -- already executing @@ -141,6 +143,7 @@ class _YoutubeHistoryLinker { Future markVideoWatched({required String videoId, required VideoStreamsResult? streamResult, bool errorOnMissingParam = true}) async { if (_dbOpenedAccId == null) return YTMarkVideoWatchedResult.noAccount; // no acc signed in + if (!settings.youtube.markVideoWatched) return YTMarkVideoWatchedResult.userDenied; if (_hasPendingRequests) { executePendingRequests(); @@ -191,6 +194,7 @@ class _YoutubeHistoryLinker { enum YTMarkVideoWatchedResult { noAccount, + userDenied, marked, addedAsPending, } diff --git a/pubspec.yaml b/pubspec.yaml index 0fac68df..a3d11f4f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: namida description: A Beautiful and Feature-rich Music Player, With YouTube & Video Support Built in Flutter publish_to: "none" -version: 3.5.3-beta+240722157 +version: 3.5.4-beta+240722218 environment: sdk: ">=3.4.0 <4.0.0"