Skip to content
Closed
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
14 changes: 10 additions & 4 deletions lib/app/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import '../extensions/build_context_x.dart';
import '../player/player_manager.dart';
import '../player/view/player_full_view.dart';
import '../player/view/player_view.dart';
import '../podcasts/download_manager.dart';
import '../podcasts/view/recent_downloads_button.dart';
import '../search/view/search_view.dart';
import '../settings/view/settings_dialog.dart';
Expand All @@ -18,9 +17,16 @@ class Home extends StatelessWidget with WatchItMixin {

@override
Widget build(BuildContext context) {
registerStreamHandler(
select: (DownloadManager m) => m.messageStream,
handler: downloadMessageStreamHandler,
registerStreamHandler<Stream<CommandError>, CommandError>(
target: Command.globalErrors,
handler: (context, snapshot, cancel) {
if (snapshot.hasData) {
final error = snapshot.data!;
ScaffoldMessenger.maybeOf(context)?.showSnackBar(
SnackBar(content: Text('Download error: ${error.error}')),
);
}
},
);

final playerFullWindowMode = watchValue(
Expand Down
32 changes: 32 additions & 0 deletions lib/extensions/podcast_item_x.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:podcast_search/podcast_search.dart';

extension PodcastItemX on Item {
Map<String, dynamic> toJson() => {
'artistId': artistId,
'collectionId': collectionId,
'trackId': trackId,
'guid': guid,
'artistName': artistName,
'collectionName': collectionName,
'collectionExplicitness': collectionExplicitness,
'trackExplicitness': trackExplicitness,
'trackName': trackName,
'trackCount': trackCount,
'collectionCensoredName': collectionCensoredName,
'trackCensoredName': trackCensoredName,
'artistViewUrl': artistViewUrl,
'collectionViewUrl': collectionViewUrl,
'feedUrl': feedUrl,
'trackViewUrl': trackViewUrl,
'artworkUrl30': artworkUrl30,
'artworkUrl60': artworkUrl60,
'artworkUrl100': artworkUrl100,
'artworkUrl600': artworkUrl600,
'releaseDate': releaseDate?.toIso8601String(),
'country': country,
'primaryGenreName': primaryGenreName,
'contentAdvisoryRating': contentAdvisoryRating,
'genreIds': genre?.map((g) => g.id.toString()).toList(),
'genres': genre?.map((g) => g.name).toList(),
};
}
5 changes: 1 addition & 4 deletions lib/extensions/shared_preferences_x.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ extension SPKeys on SharedPreferences {
static const usePlayerColor = 'usePlayerColor';
static const saveWindowSize = 'saveWindowSize';
static const podcastFeedUrls = 'podcastFeedUrls';
static const podcastImageUrlSuffix = '_imageUrl';
static const podcastNameSuffix = '_name';
static const podcastArtistSuffix = '_artist';
static const podcastGenreListSuffix = '_genreList';
static const podcastDataSuffix = '_podcastData';
static const podcastEpisodeDownloadedSuffix = '_episodeDownloaded';
static const podcastsWithDownloads = 'podcastsWithDownloads';
static const podcastsWithUpdates = 'podcastsWithUpdates';
Expand Down
26 changes: 23 additions & 3 deletions lib/player/player_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ import 'package:media_kit_video/media_kit_video.dart';

import '../common/logging.dart';
import '../extensions/color_x.dart';
import '../podcasts/podcast_library_service.dart';
import 'data/episode_media.dart';
import 'data/unique_media.dart';
import 'view/player_view_state.dart';

class PlayerManager extends BaseAudioHandler with SeekHandler {
PlayerManager({required VideoController controller})
: _controller = controller {
PlayerManager({
required VideoController controller,
required PodcastLibraryService podcastLibraryService,
}) : _controller = controller,
_podcastLibraryService = podcastLibraryService {
playbackState.add(
PlaybackState(
playing: false,
Expand Down Expand Up @@ -40,6 +45,7 @@ class PlayerManager extends BaseAudioHandler with SeekHandler {
}

final VideoController _controller;
final PodcastLibraryService _podcastLibraryService;
VideoController get videoController => _controller;

final playerViewState = ValueNotifier<PlayerViewState>(
Expand Down Expand Up @@ -234,7 +240,21 @@ class PlayerManager extends BaseAudioHandler with SeekHandler {
}) async {
if (mediaList.isEmpty) return;
updateState(resetRemoteSource: true);
await _player.open(Playlist(mediaList, index: index), play: play);
await _player.open(
Playlist(
mediaList.map((e) {
if (e is EpisodeMedia &&
_podcastLibraryService.getDownload(e.url) != null) {
return e.copyWithX(
resource: _podcastLibraryService.getDownload(e.url)!,
);
}
return e;
}).toList(),
index: index,
),
play: play,
);
}

Future<void> addToPlaylist(UniqueMedia media) async => _player.add(media);
Expand Down
50 changes: 50 additions & 0 deletions lib/player/view/player_podcast_favorite_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:flutter_it/flutter_it.dart';
import 'package:podcast_search/podcast_search.dart';

import '../../podcasts/podcast_manager.dart';
import '../data/episode_media.dart';

class PlayerPodcastFavoriteButton extends StatelessWidget with WatchItMixin {
const PlayerPodcastFavoriteButton({super.key, required this.episodeMedia})
: _floating = false;
const PlayerPodcastFavoriteButton.floating({
super.key,
required this.episodeMedia,
}) : _floating = true;

final EpisodeMedia episodeMedia;
final bool _floating;

@override
Widget build(BuildContext context) {
final isSubscribed = watchValue(
(PodcastManager m) => m.getSubscribedPodcastsCommand.select(
(podcasts) => podcasts.any((p) => p.feedUrl == episodeMedia.feedUrl),
),
);

void onPressed() => isSubscribed
? di<PodcastManager>().removePodcast(feedUrl: episodeMedia.feedUrl)
: di<PodcastManager>().addPodcast(
Item(
feedUrl: episodeMedia.feedUrl,
artworkUrl: episodeMedia.albumArtUrl,
artworkUrl600: episodeMedia.albumArtUrl,
collectionName: episodeMedia.collectionName,
artistName: episodeMedia.artist,
),
);
final icon = Icon(isSubscribed ? Icons.favorite : Icons.favorite_border);

if (_floating) {
return FloatingActionButton.small(
heroTag: 'favtag',
onPressed: onPressed,
child: icon,
);
}

return IconButton(onPressed: onPressed, icon: icon);
}
}
8 changes: 7 additions & 1 deletion lib/player/view/player_track_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import '../../extensions/build_context_x.dart';
import '../../extensions/duration_x.dart';
import '../../radio/view/radio_browser_station_star_button.dart';
import '../../search/copy_to_clipboard_content.dart';
import '../data/episode_media.dart';
import '../data/station_media.dart';
import '../player_manager.dart';
import 'player_podcast_favorite_button.dart';

class PlayerTrackInfo extends StatelessWidget with WatchItMixin {
const PlayerTrackInfo({
Expand All @@ -30,6 +32,7 @@ class PlayerTrackInfo extends StatelessWidget with WatchItMixin {
final media = watchStream(
(PlayerManager p) => p.currentMediaStream,
initialValue: di<PlayerManager>().currentMedia,
allowStreamChange: true,
preserveState: false,
).data;

Expand Down Expand Up @@ -90,7 +93,10 @@ class PlayerTrackInfo extends StatelessWidget with WatchItMixin {
],
),
),
if (media is StationMedia) const RadioStationStarButton(),
if (media is StationMedia)
RadioStationStarButton(currentMedia: media)
else if (media is EpisodeMedia)
PlayerPodcastFavoriteButton(episodeMedia: media),
],
),
);
Expand Down
15 changes: 0 additions & 15 deletions lib/podcasts/data/podcast_metadata.dart

This file was deleted.

Loading