From ddc10bcf8a9ce4da9785dd59fe063c2afd08338e Mon Sep 17 00:00:00 2001 From: Feichtmeier Date: Mon, 20 Jan 2025 21:00:26 +0100 Subject: [PATCH] feat: mark podcast episodes as played Fixes #1117 --- lib/common/view/icons.dart | 5 ++ lib/l10n/app_en.arb | 1 + lib/persistence_utils.dart | 67 ++++++++++++++++++- lib/player/player_model.dart | 4 ++ lib/player/player_service.dart | 43 +++++++++--- lib/player/view/bottom_player.dart | 2 + .../view/full_height_player_top_controls.dart | 4 ++ lib/player/view/player_main_controls.dart | 8 ++- lib/podcasts/view/podcast_page.dart | 12 +++- needs_translation.json | 44 ++++++++++++ 10 files changed, 172 insertions(+), 18 deletions(-) diff --git a/lib/common/view/icons.dart b/lib/common/view/icons.dart index d4749d031..0c03ea6e2 100644 --- a/lib/common/view/icons.dart +++ b/lib/common/view/icons.dart @@ -462,4 +462,9 @@ class Iconz { : appleStyled ? CupertinoIcons.moon : Icons.mode_night_rounded; + static IconData get markAllRead => yaruStyled + ? YaruIcons.ok_filled + : appleStyled + ? CupertinoIcons.check_mark_circled_solid + : Icons.check_circle; } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 29d7f4b9b..6f7b7557e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -179,6 +179,7 @@ } } }, + "markAllEpisodesAsDone": "Mark all episodes as done", "downloadsOnly": "Downloads only", "downloadsDirectory": "Location of your downloads", "downloadsDirectoryDescription": "Make sure MusicPod can access this directory!", diff --git a/lib/persistence_utils.dart b/lib/persistence_utils.dart index 5ab5c00b6..bffaab040 100644 --- a/lib/persistence_utils.dart +++ b/lib/persistence_utils.dart @@ -83,7 +83,33 @@ Future writeCustomSetting( final file = File(p.join(workingDir, filename)); if (!file.existsSync()) { - file.create(); + file.createSync(); + } + + await file.writeAsString(jsonStr); +} + +Future writeCustomSettings({ + required List> entries, + required String filename, +}) async { + if (entries.isEmpty) return; + final oldSettings = await getCustomSettings(filename); + + for (var entry in entries) { + if (oldSettings.containsKey(entry.key)) { + oldSettings.update(entry.key, (v) => entry.value); + } else { + oldSettings.putIfAbsent(entry.key, () => entry.value); + } + } + + final jsonStr = jsonEncode(oldSettings); + final workingDir = await getWorkingDir(); + final file = File(p.join(workingDir, filename)); + + if (!file.existsSync()) { + await file.create(); } await file.writeAsString(jsonStr); @@ -103,12 +129,33 @@ Future removeCustomSetting( final file = File(p.join(workingDir, filename)); if (!file.existsSync()) { - file.create(); + await file.create(); } await file.writeAsString(jsonStr); } } +Future removeCustomSettings( + List keys, [ + String filename = kSettingsFileName, +]) async { + final oldSettings = await getCustomSettings(filename); + for (var key in keys) { + if (oldSettings.containsKey(key)) { + oldSettings.remove(key); + } + } + + final jsonStr = jsonEncode(oldSettings); + final workingDir = await getWorkingDir(); + final file = File(p.join(workingDir, filename)); + + if (!file.existsSync()) { + await file.create(); + } + await file.writeAsString(jsonStr); +} + Future readCustomSetting( dynamic key, [ String filename = kSettingsFileName, @@ -143,6 +190,20 @@ Future> getCustomSettings([ } } +Future wipeCustomSettings([ + String filename = kSettingsFileName, +]) async { + final workingDir = await getWorkingDir(); + + final file = File(p.join(workingDir, filename)); + + if (!file.existsSync()) { + file.createSync(); + } + + await file.writeAsString('{}'); +} + Future writeStringIterable({ required Iterable iterable, required String filename, @@ -150,7 +211,7 @@ Future writeStringIterable({ final workingDir = await getWorkingDir(); final file = File('$workingDir/$filename'); if (!file.existsSync()) { - file.create(); + await file.create(); } await file.writeAsString(iterable.join('\n')); } diff --git a/lib/player/player_model.dart b/lib/player/player_model.dart index e85f989b6..3af1ddc31 100644 --- a/lib/player/player_model.dart +++ b/lib/player/player_model.dart @@ -117,6 +117,10 @@ class PlayerModel extends SafeChangeNotifier { Map? get lastPositions => _playerService.lastPositions; Duration? getLastPosition(String? url) => _playerService.getLastPosition(url); Future safeLastPosition() => _playerService.safeLastPosition(); + + Future safeAllLastPositions(List