Skip to content

Commit 247a918

Browse files
authored
fix: podcast updates not working after fully ID based podcast page (#1377)
refactoring
1 parent 2b67700 commit 247a918

23 files changed

+236
-149
lines changed

lib/app/view/create_master_items.dart

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ import '../../settings/view/settings_page.dart';
2828
import 'main_page_icon.dart';
2929
import 'master_item.dart';
3030

31-
Iterable<MasterItem> getAllMasterItems(LibraryModel libraryModel) => [
31+
Iterable<MasterItem> getAllMasterItems(
32+
BuildContext context,
33+
LibraryModel libraryModel,
34+
) => [
3235
...permanentMasterItems,
3336
...createPlaylistMasterItems(libraryModel),
34-
...createPodcastMasterItems(libraryModel),
37+
...createPodcastMasterItems(context, libraryModel),
3538
...createFavoriteAlbumsMasterItems(libraryModel),
3639
...createStarredStationsMasterItems(libraryModel),
3740
];
@@ -131,13 +134,20 @@ Iterable<MasterItem> createFavoriteAlbumsMasterItems(
131134
),
132135
);
133136

134-
Iterable<MasterItem> createPodcastMasterItems(LibraryModel libraryModel) =>
135-
libraryModel.podcastFeedUrls.map(
136-
(feedUrl) => MasterItem(
137-
titleBuilder: (_) => PodcastPageTitle(feedUrl: feedUrl),
138-
subtitleBuilder: (_) => PodcastPageSubTitle(feedUrl: feedUrl),
139-
pageId: feedUrl,
140-
pageBuilder: (_) => LazyPodcastPage(feedUrl: feedUrl),
141-
iconBuilder: (selected) => PodcastPageSideBarIcon(feedUrl: feedUrl),
142-
),
143-
);
137+
Iterable<MasterItem> createPodcastMasterItems(
138+
BuildContext context,
139+
LibraryModel libraryModel,
140+
) => libraryModel.podcastFeedUrls.map(
141+
(feedUrl) => MasterItem(
142+
titleBuilder: (_) => PodcastPageTitle(feedUrl: feedUrl),
143+
subtitleBuilder: (_) => PodcastPageSubTitle(feedUrl: feedUrl),
144+
pageId: feedUrl,
145+
pageBuilder: (_) => LazyPodcastPage(
146+
feedUrl: feedUrl,
147+
updateMessage: context.l10n.newEpisodeAvailable,
148+
multiUpdateMessage: (length) =>
149+
context.l10n.newEpisodesAvailableFor(length),
150+
),
151+
iconBuilder: (selected) => PodcastPageSideBarIcon(feedUrl: feedUrl),
152+
),
153+
);

lib/app/view/master_detail_page.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ class MasterDetailPage extends StatelessWidget {
5656
key: routingManager.masterNavigatorKey,
5757
observers: [routingManager],
5858
onGenerateRoute: (settings) {
59-
final masterItems = getAllMasterItems(di<LibraryModel>());
59+
final masterItems = getAllMasterItems(
60+
context,
61+
di<LibraryModel>(),
62+
);
6063
final page =
6164
(masterItems.firstWhereOrNull(
6265
(e) => e.pageId == settings.name,

lib/app/view/master_panel.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class PodcastList extends StatelessWidget with WatchItMixin {
9898
@override
9999
Widget build(BuildContext context) {
100100
watchPropertyValue((LibraryModel m) => m.podcastsLength);
101-
final masterItems = createPodcastMasterItems(di<LibraryModel>());
101+
final masterItems = createPodcastMasterItems(context, di<LibraryModel>());
102102
final selectedPageId = watchPropertyValue(
103103
(RoutingManager m) => m.selectedPageId,
104104
);

lib/app/view/mobile_musicpod_app.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class MobileMusicPodApp extends StatelessWidget with WatchItMixin {
3838
navigatorObservers: [routingManager],
3939
initialRoute: routingManager.selectedPageId ?? PageIDs.homePage,
4040
onGenerateRoute: (settings) {
41-
final masterItems = getAllMasterItems(di<LibraryModel>());
41+
final masterItems = getAllMasterItems(context, di<LibraryModel>());
4242
final page =
4343
(masterItems.firstWhereOrNull((e) => e.pageId == settings.name) ??
4444
masterItems.elementAt(0))

lib/common/view/audio_tile_option_button.dart

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:collection/collection.dart';
22
import 'package:flutter/material.dart';
3+
import 'package:future_loading_dialog/future_loading_dialog.dart';
34
import 'package:watch_it/watch_it.dart';
45
import 'package:yaru/yaru.dart';
56

@@ -13,6 +14,7 @@ import '../../local_audio/view/album_page.dart';
1314
import '../../local_audio/view/artist_page.dart';
1415
import '../../player/player_model.dart';
1516
import '../../playlists/view/add_to_playlist_dialog.dart';
17+
import '../../podcasts/podcast_model.dart';
1618
import '../../settings/settings_model.dart';
1719
import '../data/audio.dart';
1820
import '../data/audio_type.dart';
@@ -202,7 +204,7 @@ class AudioTileOptionButton extends StatelessWidget {
202204
),
203205
),
204206
),
205-
if (audios.every((e) => e.isPodcast))
207+
if (audios.every((e) => e.isPodcast)) ...[
206208
PopupMenuItem(
207209
onTap: () => di<SettingsModel>().setHideCompletedEpisodes(
208210
!hideCompletedEpisodes,
@@ -217,6 +219,25 @@ class AudioTileOptionButton extends StatelessWidget {
217219
),
218220
),
219221
),
222+
if (audios.firstOrNull?.website != null)
223+
PopupMenuItem(
224+
onTap: () => showFutureLoadingDialog(
225+
context: context,
226+
title: context.l10n.loadingPodcastFeed,
227+
future: () => di<PodcastModel>().checkForUpdates(
228+
feedUrls: {audios.first.website!},
229+
updateMessage: context.l10n.newEpisodeAvailable,
230+
multiUpdateMessage: (length) =>
231+
context.l10n.newEpisodesAvailableFor(length),
232+
),
233+
),
234+
child: ListTile(
235+
contentPadding: const EdgeInsets.symmetric(horizontal: 10),
236+
title: Text(context.l10n.checkForUpdates),
237+
leading: Icon(Iconz.refresh),
238+
),
239+
),
240+
],
220241
];
221242
},
222243
icon: icon ?? Icon(Iconz.viewMore),

lib/custom_content/view/custom_podcast_section.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class _CustomPodcastSectionState extends State<CustomPodcastSection> {
6868
di<RoutingManager>().push(
6969
pageId: _urlController.text,
7070
builder: (context) => LazyPodcastPage(
71+
updateMessage:
72+
context.l10n.newEpisodeAvailable,
73+
multiUpdateMessage: (length) => context
74+
.l10n
75+
.newEpisodesAvailableFor(length),
7176
imageUrl: v.firstOrNull?.imageUrl,
7277
feedUrl: _urlController.text,
7378
),

lib/extensions/string_x.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,35 @@ extension StringExtension on String {
4646
.replaceAll(Audio.albumIdReplacer, Audio.albumIdReplacement);
4747
String get artistOfId => (split(Audio.albumIdSplitter).firstOrNull ?? '')
4848
.replaceAll(Audio.albumIdReplacer, Audio.albumIdReplacement);
49+
50+
DateTime? get _parsedDateTimeFromPodcastTimeStamp {
51+
final list = this.split('_');
52+
53+
final year = int.tryParse(list.first);
54+
final month = int.tryParse(list[1]);
55+
final day = int.tryParse(list[2]);
56+
final hour = int.tryParse(list[3]);
57+
final minute = int.tryParse(list[4]);
58+
59+
if (year != null &&
60+
month != null &&
61+
day != null &&
62+
minute != null &&
63+
hour != null) {
64+
return DateTime(year, month, day, hour, minute);
65+
}
66+
67+
return null;
68+
}
69+
70+
bool isSamePodcastTimeStamp(DateTime other) {
71+
final ts = this._parsedDateTimeFromPodcastTimeStamp;
72+
if (ts == null) return false;
73+
return other.year == ts.year &&
74+
other.month == ts.month &&
75+
other.day == ts.day &&
76+
other.minute == ts.minute;
77+
}
4978
}
5079

5180
extension NullableStringX on String? {

lib/library/library_service.dart

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -549,18 +549,18 @@ class LibraryService {
549549
}
550550
addSubscribedPodcastName(feedUrl: feedUrl, name: name);
551551
addSubscribedPodcastArtist(feedUrl: feedUrl, artist: artist);
552-
await _addPodcastLastUpdatedWithTimestamp(feedUrl);
552+
await _checkAndAddPodcastLastUpdated(feedUrl);
553553
}
554554

555-
Future<void> _addPodcastLastUpdatedWithTimestamp(String feedUrl) async {
555+
Future<void> _checkAndAddPodcastLastUpdated(String feedUrl) async {
556556
DateTime? lastUpdated;
557557
try {
558558
lastUpdated = await Feed.feedLastUpdated(url: feedUrl);
559559
} on Exception catch (e) {
560560
printMessageInDebugMode(e);
561561
}
562562
if (lastUpdated != null) {
563-
_addPodcastLastUpdated(
563+
addPodcastLastUpdated(
564564
feedUrl: feedUrl,
565565
timestamp: lastUpdated.podcastTimeStamp,
566566
);
@@ -581,7 +581,7 @@ class LibraryService {
581581
}
582582
addSubscribedPodcastName(feedUrl: p.feedUrl, name: p.name);
583583
addSubscribedPodcastArtist(feedUrl: p.feedUrl, artist: p.artist);
584-
await _addPodcastLastUpdatedWithTimestamp(p.feedUrl);
584+
await _checkAndAddPodcastLastUpdated(p.feedUrl);
585585
}
586586
}
587587
_sharedPreferences
@@ -617,14 +617,12 @@ class LibraryService {
617617
Set<String>? _podcastUpdates;
618618
int? get podcastUpdatesLength => _podcastUpdates?.length;
619619

620-
void _addPodcastLastUpdated({
620+
Future<void> addPodcastLastUpdated({
621621
required String feedUrl,
622622
required String timestamp,
623-
}) {
624-
_sharedPreferences
625-
.setString(feedUrl + SPKeys.podcastLastUpdatedSuffix, timestamp)
626-
.then(notify);
627-
}
623+
}) async => _sharedPreferences
624+
.setString(feedUrl + SPKeys.podcastLastUpdatedSuffix, timestamp)
625+
.then(notify);
628626

629627
void _removePodcastLastUpdated(String feedUrl) => _sharedPreferences
630628
.remove(feedUrl + SPKeys.podcastLastUpdatedSuffix)
@@ -636,19 +634,16 @@ class LibraryService {
636634
bool podcastUpdateAvailable(String feedUrl) =>
637635
_podcastUpdates?.contains(feedUrl) == true;
638636

639-
void addPodcastUpdate(String feedUrl, DateTime? lastUpdated) {
640-
if (_podcastUpdates?.contains(feedUrl) == true || lastUpdated == null)
641-
return;
637+
Future<void> addPodcastUpdate(String feedUrl, DateTime lastUpdated) async {
638+
if (_podcastUpdates?.contains(feedUrl) == true) return;
642639

643-
_addPodcastLastUpdated(
644-
feedUrl: feedUrl,
645-
timestamp: lastUpdated.podcastTimeStamp,
646-
);
647-
_podcastUpdates?.add(feedUrl);
648-
writeStringIterable(
640+
await writeStringIterable(
649641
iterable: _podcastUpdates!,
650642
filename: FileNames.podcastUpdates,
651-
).then((_) => _propertiesChangedController.add(true));
643+
).then((_) {
644+
_podcastUpdates?.add(feedUrl);
645+
_propertiesChangedController.add(true);
646+
});
652647
}
653648

654649
Future<void> removePodcastUpdate(String feedUrl) async {

lib/player/view/player_title_and_artist.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin {
114114
onTap: audio == null
115115
? null
116116
: () => _onArtistTap(
117+
context: context,
117118
audio: audio,
118119
routingManager: routingManager,
119120
localAudioModel: localAudioModel,
@@ -260,6 +261,7 @@ class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin {
260261
}
261262

262263
void _onArtistTap({
264+
required BuildContext context,
263265
required Audio audio,
264266
required PodcastModel podcastModel,
265267
required LocalAudioModel localAudioModel,
@@ -288,6 +290,9 @@ class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin {
288290
builder: (_) => LazyPodcastPage(
289291
feedUrl: feedUrl,
290292
imageUrl: audio.imageUrl ?? audio.albumArtUrl,
293+
updateMessage: context.l10n.newEpisodeAvailable,
294+
multiUpdateMessage: (length) =>
295+
context.l10n.newEpisodesAvailableFor(length),
291296
),
292297
);
293298
}

lib/podcasts/podcast_model.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ class PodcastModel extends SafeChangeNotifier {
2222
notifyListeners();
2323
}
2424

25-
Future<void> update({
25+
Future<void> checkForUpdates({
2626
required String updateMessage,
2727
required String Function(int length) multiUpdateMessage,
2828
// Note: because the podcasts can be modified to include downloads
2929
// this needs a map and not only the feedurl
3030
Set<String>? feedUrls,
31-
}) async => _podcastService.updatePodcasts(
31+
}) async => _podcastService.checkForUpdates(
3232
updateMessage: updateMessage,
3333
multiUpdateMessage: multiUpdateMessage,
3434
feedUrls: feedUrls,
@@ -91,11 +91,11 @@ class PodcastModel extends SafeChangeNotifier {
9191
Future<List<Audio>> findEpisodes({
9292
Item? item,
9393
String? feedUrl,
94-
bool addUpdates = false,
94+
bool loadFromCache = true,
9595
}) => _podcastService.findEpisodes(
9696
item: item,
9797
feedUrl: feedUrl,
98-
addUpdates: addUpdates,
98+
loadFromCache: loadFromCache,
9999
);
100100

101101
List<Audio>? getPodcastEpisodesFromCache(String? feedUrl) =>

0 commit comments

Comments
 (0)