Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions lib/bloc/podcast/podcast_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum PodcastEvent {
episodeFilterStarted,
episodeFilterNotFinished,
episodeFilterFinished,
episodeFilterDownloaded,
// Sort
episodeSortDefault,
episodeSortLatest,
Expand Down Expand Up @@ -320,6 +321,13 @@ class PodcastBloc extends Bloc {
void _listenPodcastStateEvents() async {
_podcastEvent.listen((event) async {
switch (event) {
case PodcastEvent.episodeFilterDownloaded:
if (_podcast != null) {
_podcast!.filter = PodcastEpisodeFilter.downloaded;
_podcast = await podcastService.save(_podcast!, withEpisodes: false);
await _loadFilteredEpisodes();
}
break;
case PodcastEvent.subscribe:
if (_podcast != null) {
_podcast = await podcastService.subscribe(_podcast!);
Expand Down Expand Up @@ -435,6 +443,30 @@ class PodcastBloc extends Bloc {
});
}

List<Episode> applyEpisodeFilter(List<Episode> episodes) {
List<Episode> filtered = episodes;

switch (_podcast?.filter) {
case PodcastEpisodeFilter.started:
filtered = filtered.where((e) => e.position > 0 && !e.played).toList();
break;
case PodcastEpisodeFilter.played:
filtered = filtered.where((e) => e.played).toList();
break;
case PodcastEpisodeFilter.notPlayed:
filtered = filtered.where((e) => !e.played).toList();
break;
case PodcastEpisodeFilter.downloaded:
filtered = filtered.where((e) => e.downloadState == DownloadState.downloaded).toList();
break;
case PodcastEpisodeFilter.none:
default:
break;
}

return filtered;
}

void applySearchFilter() {
if (_searchTerm.isEmpty) {
_episodesStream.add(_episodes);
Expand Down
4 changes: 3 additions & 1 deletion lib/entities/podcast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ enum PodcastEpisodeFilter {
none(id: 0),
started(id: 1),
played(id: 2),
notPlayed(id: 3);
notPlayed(id: 3),
downloaded(id: 4);

const PodcastEpisodeFilter({required this.id});

Expand Down Expand Up @@ -210,6 +211,7 @@ class Podcast {
1 => PodcastEpisodeFilter.started,
2 => PodcastEpisodeFilter.played,
3 => PodcastEpisodeFilter.notPlayed,
4 => PodcastEpisodeFilter.downloaded,
_ => PodcastEpisodeFilter.none,
};
}
Expand Down
10 changes: 10 additions & 0 deletions lib/l10n/L.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,16 @@ class L {
);
}

String get episode_filter_downloaded_label {
return message('episode_filter_downloaded_label') ??
Intl.message(
'Downloaded',
name: 'episode_filter_downloaded_label',
desc: 'Only show episodes that have been downloaded',
locale: localeName,
);
}

String get episode_filter_no_episodes_title_label {
return message('episode_filter_no_episodes_title_label') ??
Intl.message(
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Heruntergeladen",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Sind Sie sicher, dass Sie diese Episode löschen möchten?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Downloaded",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Are you sure you wish to delete this episode?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Descargado",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "¿Estás seguro de que deseas eliminar este episodio?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_gl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Descargado",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Tes certeza de querer eliminar este episodio?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_it.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Scaricato",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Sicura/o di voler eliminare questo episodio?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
8 changes: 7 additions & 1 deletion lib/l10n/intl_messages.arb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"@@last_modified": "2025-07-04T06:40:38.603197",
"@@last_modified": "2025-08-05T01:00:20.230759",
"app_title": "Anytime Podcast Player",
"@app_title": {
"description": "Full title for the application",
Expand Down Expand Up @@ -878,6 +878,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Downloaded",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"episode_filter_no_episodes_title_label": "No Episodes Found",
"@episode_filter_no_episodes_title_label": {
"description": "No Episodes title",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_nl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Gedownload",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Weet je zeker dat je deze aflevering wilt verwijderen?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_ru.arb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Скачано",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Вы уверены, что хотите удалить этот выпуск?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
6 changes: 6 additions & 0 deletions lib/l10n/intl_vi.arb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@
"type": "text",
"placeholders": {}
},
"episode_filter_downloaded_label": "Đã tải xuống",
"@episode_filter_downloaded_label": {
"description": "Only show episodes that have been downloaded",
"type": "text",
"placeholders": {}
},
"delete_episode_confirmation": "Bạn có chắc chắn muốn xóa tập này không?",
"@delete_episode_confirmation": {
"description": "User is asked to confirm when they attempt to delete an episode",
Expand Down
43 changes: 21 additions & 22 deletions lib/l10n/messages_all_locales.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,50 @@
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
import 'package:intl/src/intl_helpers.dart';

import 'messages_de.dart' as messages_de;
import 'messages_en.dart' as messages_en;
import 'messages_es.dart' as messages_es;
import 'messages_gl.dart' as messages_gl;
import 'messages_it.dart' as messages_it;
import 'messages_messages.dart' as messages_messages;

import 'messages_en.dart' as messages_en;
import 'messages_de.dart' as messages_de;
import 'messages_gl.dart' as messages_gl;
import 'messages_nl.dart' as messages_nl;
import 'messages_ru.dart' as messages_ru;
import 'messages_vi.dart' as messages_vi;
import 'messages_ru.dart' as messages_ru;

typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'de': () => Future.value(null),
'en': () => Future.value(null),
'de': () => Future.value(null),
'es': () => Future.value(null),
'gl': () => Future.value(null),
'it': () => Future.value(null),
'messages': () => Future.value(null),
'it': () => Future.value(null),
'messages': () => Future.value(null),
'nl': () => Future.value(null),
'ru': () => Future.value(null),
'vi': () => Future.value(null),
'ru': () => Future.value(null),
};

MessageLookupByLibrary? _findExact(String localeName) {
switch (localeName) {
case 'de':
return messages_de.messages;
case 'en':
return messages_en.messages;
case 'de':
return messages_de.messages;
case 'es':
return messages_es.messages;
return messages_es.messages;
case 'gl':
return messages_gl.messages;
case 'it':
return messages_it.messages;
case 'messages':
return messages_messages.messages;
return messages_it.messages;
case 'messages':
return messages_messages.messages;
case 'nl':
return messages_nl.messages;
case 'ru':
return messages_ru.messages;
case 'vi':
return messages_vi.messages;
case 'ru':
return messages_ru.messages;
default:
return null;
}
Expand All @@ -64,9 +64,8 @@ MessageLookupByLibrary? _findExact(String localeName) {
/// User programs should call this before using [localeName] for messages.
Future<bool> initializeMessages(String? localeName) async {
var availableLocale = Intl.verifiedLocale(
localeName,
(locale) => _deferredLibraries[locale] != null,
onFailure: (_) => null);
localeName, (locale) => _deferredLibraries[locale] != null,
onFailure: (_) => null);
if (availableLocale == null) {
return Future.value(false);
}
Expand All @@ -86,8 +85,8 @@ bool _messagesExistFor(String locale) {
}

MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
onFailure: (_) => null);
var actualLocale =
Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
if (actualLocale == null) return null;
return _findExact(actualLocale);
}
1 change: 1 addition & 0 deletions lib/l10n/messages_de.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Ihre Warteschlange ist leer'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Episodeninformationen anzeigen'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Filter zurücksetzen'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Heruntergeladen'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Dieser Podcast hat keine Episoden, die Ihren Suchkriterien und Filtern entsprechen'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Keine Episoden Gefunden'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Keiner'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Your queue is empty'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Show episode information'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Clear Filters'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Downloaded'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('This podcast has no episodes matching your search criteria and filter'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('No Episodes Found'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('None'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_es.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Tu lista de reproducción está vacia'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Mostrar información del episodio'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Limpiar filtros'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Downloaded'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Este podcast no tiene episodios que coincidan con tus criterios de búsqueda y filtro'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Episodios no encontrados'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Sin filtro'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_gl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('A lista está baleira'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Mostrar información do episodio'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Limpar filtros'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Descargado'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Este podcast non ten episodios que sigan os criterios do teu filtro'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Non hai episodios'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Ningún'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_it.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('La tua coda è vuota'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Mostra le informazioni sull\'episodio'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Pulisci i Filtri'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Downloaded'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Questo podcast non ha episodi che corrispondono ai tuoi criteri di ricerca e filtro'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Nessun episodio trovato'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Nessuno'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Your queue is empty'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Show episode information'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Clear Filters'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Downloaded'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('No Episodes Found'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('No Episodes Found'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('None'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_nl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Je wachtrij is leeg'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Toon afleveringinformatie'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Filters wissen'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Gedownload'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Er zijn geen afleveringen van deze podcast die voldoen aan uw zoekcriteria en filter.'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Geen Afleveringen Gevonden'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Geen'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_ru.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Ваша очередь пуста'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Показать информацию выпуска'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Очистить фильтры'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Скачано'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('В этом подкасте нет выпусков по вашим критериям поиска и фильтру'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Не найдено выпусков'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Никаких'),
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/messages_vi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class MessageLookup extends MessageLookupByLibrary {
'empty_queue_message': MessageLookupByLibrary.simpleMessage('Hàng chờ của bạn đang trống'),
'episode_details_button_label': MessageLookupByLibrary.simpleMessage('Hiển thị thông tin tập'),
'episode_filter_clear_filters_button_label': MessageLookupByLibrary.simpleMessage('Xóa bộ lọc'),
'episode_filter_downloaded_label': MessageLookupByLibrary.simpleMessage('Đã tải xuống'),
'episode_filter_no_episodes_title_description': MessageLookupByLibrary.simpleMessage('Podcast này không có tập nào khớp với tiêu chí tìm kiếm và bộ lọc của bạn'),
'episode_filter_no_episodes_title_label': MessageLookupByLibrary.simpleMessage('Không tìm thấy tập nào'),
'episode_filter_none_label': MessageLookupByLibrary.simpleMessage('Không'),
Expand Down
3 changes: 3 additions & 0 deletions lib/repository/sembast/sembast_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@ class SembastRepository extends Repository {
case PodcastEpisodeFilter.notPlayed:
episodeFilter = Filter.and([Filter.equals('pguid', pguid), Filter.equals('played', 'false')]);
break;
case PodcastEpisodeFilter.downloaded:
episodeFilter = Filter.and([Filter.equals('pguid', pguid), Filter.equals('downloaded', '100')]);
break;
}
return episodeFilter;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/services/podcast/mobile_podcast_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,8 @@ class MobilePodcastService extends PodcastService {
case PodcastEpisodeFilter.notPlayed:
filteredEpisodes = podcast.episodes.where((e) => e.highlight || !e.played).toList();
break;
case PodcastEpisodeFilter.downloaded:
filteredEpisodes = podcast.episodes.where((e) => e.highlight || e.downloaded).toList();
}

switch (podcast.sort) {
Expand Down
Loading