Skip to content

Commit

Permalink
feat: display online art errors in the player images, improved radio …
Browse files Browse the repository at this point in the history
…search (#943)
  • Loading branch information
Feichtmeier authored Oct 11, 2024
1 parent cdce7cf commit 42d61ee
Show file tree
Hide file tree
Showing 86 changed files with 640 additions and 453 deletions.
8 changes: 4 additions & 4 deletions lib/app/view/master_detail_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin {
? masterScaffoldKey.currentState?.closeEndDrawer
: masterScaffoldKey.currentState?.closeDrawer,
icon: Icon(
Iconz().close,
Iconz.close,
),
),
),
Expand Down Expand Up @@ -198,7 +198,7 @@ List<MasterItem> createMasterItems({required LibraryModel libraryModel}) {
MasterItem(
titleBuilder: (context) => Text(context.l10n.search),
pageBuilder: (_) => const SearchPage(),
iconBuilder: (_) => Icon(Iconz().search),
iconBuilder: (_) => Icon(Iconz.search),
pageId: kSearchPageId,
),
MasterItem(
Expand Down Expand Up @@ -226,7 +226,7 @@ List<MasterItem> createMasterItems({required LibraryModel libraryModel}) {
pageId: kPodcastsPageId,
),
MasterItem(
iconBuilder: (selected) => Icon(Iconz().plus),
iconBuilder: (selected) => Icon(Iconz.plus),
titleBuilder: (context) => Text(context.l10n.add),
pageBuilder: (_) => const SizedBox.shrink(),
pageId: kNewPlaylistPageId,
Expand All @@ -247,7 +247,7 @@ List<MasterItem> createMasterItems({required LibraryModel libraryModel}) {
iconBuilder: (selected) => SideBarFallBackImage(
color: getAlphabetColor(playlist.key),
child: Icon(
Iconz().playlist,
Iconz.playlist,
),
),
),
Expand Down
4 changes: 1 addition & 3 deletions lib/app/view/master_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ class __PlayAbleMasterTileState extends State<_PlayAbleMasterTile> {
child: IconButton(
onPressed: onPlay,
icon: Icon(
isPlaying && isEnQueued
? Iconz().pause
: Iconz().playFilled,
isPlaying && isEnQueued ? Iconz.pause : Iconz.playFilled,
size: kTinyButtonIconSize,
color: context.t.colorScheme.primary,
),
Expand Down
2 changes: 1 addition & 1 deletion lib/app/view/splash_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class SplashScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Iconz().musicNote,
Iconz.musicNote,
size: 150,
color: Colors.white,
),
Expand Down
24 changes: 13 additions & 11 deletions lib/common/data/audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Audio {
/// The artist(s) of the audio file or stream, for radio stations this is the language.
final String? artist;

/// The album of the audio file or stream.
/// The album of the audio file or stream, for radio stations these are the tags.
final String? album;

/// The album artist(s) of the audio file or stream, for radio stations this is the codec.
Expand Down Expand Up @@ -264,7 +264,7 @@ class Audio {
if (other.audioType != null &&
other.audioType == AudioType.radio &&
audioType == AudioType.radio) {
return other.description == description;
return other.uuid == uuid;
}

return (other.url != null && other.url == url) ||
Expand All @@ -275,7 +275,7 @@ class Audio {
}

@override
int get hashCode => path.hashCode ^ url.hashCode ^ description.hashCode;
int get hashCode => path.hashCode ^ url.hashCode ^ uuid.hashCode;

factory Audio.fromMetadata({
required String path,
Expand Down Expand Up @@ -311,12 +311,19 @@ class Audio {
}

String? get uuid => description;
String? get language => artist;
String get language => artist ?? '';
int get clicks => discTotal ?? 0;
int get bitRate => fileSize ?? 0;
List<String>? get tags => album?.isNotEmpty == false
? null
: <String>[
for (final tag in album?.split(',') ?? <String>[]) tag,
];

factory Audio.fromStation(Station station) {
return Audio(
url: station.urlResolved,
title: station.name,
title: station.name.trim(),
artist: station.language,
album: station.tags ?? '',
audioType: AudioType.radio,
Expand All @@ -325,6 +332,7 @@ class Audio {
description: station.stationUUID,
fileSize: station.bitrate,
albumArtist: station.codec,
discTotal: station.clickCount,
);
}

Expand Down Expand Up @@ -360,12 +368,6 @@ class Audio {
return id;
}

List<String>? get tags => album?.isNotEmpty == false
? null
: <String>[
for (final tag in album?.split(',') ?? <String>[]) tag,
];

bool get hasPathAndId =>
albumId?.isNotEmpty == true &&
path != null &&
Expand Down
67 changes: 67 additions & 0 deletions lib/common/view/animated_like_icon.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'icons.dart';
import 'package:flutter/material.dart';
import 'package:yaru/yaru.dart';
import 'theme.dart';

class AnimatedStar extends StatelessWidget {
const AnimatedStar({
super.key,
required this.isStarred,
this.color,
});

final bool isStarred;
final Color? color;

@override
Widget build(BuildContext context) {
if (yaruStyled) {
return YaruAnimatedVectorIcon(
isStarred ? YaruAnimatedIcons.star_filled : YaruAnimatedIcons.star,
initialProgress: 1.0,
color: color,
size: iconSize,
);
} else {
return isStarred
? Icon(
Iconz.starFilled,
size: iconSize,
color: isStarred ? color : null,
)
: Icon(
Iconz.star,
size: iconSize,
color: isStarred ? color : null,
);
}
}
}

class AnimatedHeart extends StatelessWidget {
const AnimatedHeart({
super.key,
required this.liked,
this.color,
});

final bool liked;
final Color? color;

@override
Widget build(BuildContext context) {
if (yaruStyled) {
return YaruAnimatedVectorIcon(
liked ? YaruAnimatedIcons.heart_filled : YaruAnimatedIcons.heart,
initialProgress: 1.0,
color: color,
size: iconSize,
);
} else {
return Icon(
liked ? Icons.favorite : Icons.favorite_outline,
color: color,
);
}
}
}
2 changes: 1 addition & 1 deletion lib/common/view/audio_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class _AudioCardState extends State<AudioCard> {
? const EdgeInsets.only(left: 3)
: EdgeInsets.zero,
child: Icon(
Iconz().playFilled,
Iconz.playFilled,
color: contrastColor(theme.colorScheme.primary),
),
),
Expand Down
16 changes: 11 additions & 5 deletions lib/common/view/audio_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ class _AudioTileState extends State<AudioTile> {
@override
Widget build(BuildContext context) {
final theme = context.t;
final l10n = context.l10n;
final playerModel = di<PlayerModel>();
final liked = watchPropertyValue((LibraryModel m) => m.liked(widget.audio));
final starred = watchPropertyValue(
(LibraryModel m) => m.isStarredStation(widget.audio.uuid),
);
final selectedColor = widget.selectedColor ?? theme.contrastyPrimary;
final subTitle = switch (widget.audioPageType) {
AudioPageType.artist => widget.audio.album ?? context.l10n.unknown,
AudioPageType.radioSearch =>
'${widget.audio.artist ?? context.l10n.unknown}, ${widget.audio.albumArtist ?? ''}, ${widget.audio.fileSize ?? ''} kbps',
_ => widget.audio.artist ?? context.l10n.unknown,
AudioPageType.artist => widget.audio.album ?? l10n.unknown,
AudioPageType.radioSearch => _buildRadioSubTitle(widget.audio, l10n),
_ => widget.audio.artist ?? l10n.unknown,
};

var leading = !widget.showLeading
Expand Down Expand Up @@ -112,7 +112,7 @@ class _AudioTileState extends State<AudioTile> {
title: Padding(
padding: const EdgeInsets.only(right: kYaruPagePadding),
child: Text(
widget.audio.title ?? context.l10n.unknown,
widget.audio.title ?? l10n.unknown,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Expand All @@ -137,6 +137,12 @@ class _AudioTileState extends State<AudioTile> {
),
);
}

String _buildRadioSubTitle(
Audio audio,
AppLocalizations l10n,
) =>
'${audio.albumArtist?.isNotEmpty == true ? '${audio.albumArtist}' : ''}${audio.bitRate > 0 ? ' • ${audio.fileSize} kbps' : ''}${audio.clicks > 0 ? ' • ${audio.clicks} ${l10n.clicks}' : ''}${audio.language.trim().isNotEmpty ? ' • ${audio.language}' : ''}';
}

class _AudioTileTrail extends StatelessWidget with WatchItMixin {
Expand Down
6 changes: 3 additions & 3 deletions lib/common/view/audio_tile_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ class AudioTileImage extends StatelessWidget {
Widget build(BuildContext context) {
final icon = Icon(
switch (audio?.audioType) {
AudioType.radio => Iconz().radio,
AudioType.podcast => Iconz().podcast,
_ => Iconz().musicNote,
AudioType.radio => Iconz.radio,
AudioType.podcast => Iconz.podcast,
_ => Iconz.musicNote,
},
size: size / (1.65),
);
Expand Down
55 changes: 30 additions & 25 deletions lib/common/view/audio_tile_option_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class AudioTileOptionButton extends StatelessWidget {
);
},
child: YaruTile(
leading: Icon(Iconz().insertIntoQueue),
leading: Icon(Iconz.insertIntoQueue),
title: Text(context.l10n.playNext),
),
),
Expand All @@ -61,7 +61,7 @@ class AudioTileOptionButton extends StatelessWidget {
onTap: () =>
libraryModel.removeAudioFromPlaylist(playlistId, audio),
child: YaruTile(
leading: Icon(Iconz().remove),
leading: Icon(Iconz.remove),
title: Text('${context.l10n.removeFrom} $playlistId'),
),
),
Expand All @@ -77,7 +77,7 @@ class AudioTileOptionButton extends StatelessWidget {
},
),
child: YaruTile(
leading: Icon(Iconz().plus),
leading: Icon(Iconz.plus),
title: Text(
'${context.l10n.addToPlaylist} ...',
),
Expand All @@ -91,7 +91,7 @@ class AudioTileOptionButton extends StatelessWidget {
},
),
child: YaruTile(
leading: Icon(Iconz().info),
leading: Icon(Iconz.info),
title: Text(
'${context.l10n.showMetaData} ...',
),
Expand All @@ -117,7 +117,7 @@ class AudioTileOptionButton extends StatelessWidget {
),
];
},
icon: Icon(Iconz().viewMore),
icon: Icon(Iconz.viewMore),
);
}
}
Expand All @@ -129,39 +129,44 @@ class MetaDataDialog extends StatelessWidget {

@override
Widget build(BuildContext context) {
final radio = audio.audioType == AudioType.radio;

final items = <(String, String)>{
(
context.l10n.title,
radio ? context.l10n.stationName : context.l10n.title,
'${audio.title}',
),
(
context.l10n.album,
'${audio.album}',
radio ? context.l10n.tags : context.l10n.album,
'${radio ? audio.album?.replaceAll(',', ', ') : audio.album}',
),
(
context.l10n.artist,
'${audio.artist}',
radio ? context.l10n.language : context.l10n.artist,
'${radio ? audio.language : audio.artist}',
),
(
context.l10n.albumArtists,
radio ? context.l10n.quality : context.l10n.albumArtists,
'${audio.albumArtist}',
),
if (!radio)
(
context.l10n.trackNumber,
'${audio.trackNumber}',
),
if (!radio)
(
context.l10n.diskNumber,
'${audio.discNumber}',
),
(
context.l10n.trackNumber,
'${audio.trackNumber}',
),
(
context.l10n.diskNumber,
'${audio.discNumber}',
),
(
context.l10n.totalDisks,
'${audio.discTotal}',
),
(
context.l10n.genre,
'${audio.genre}',
radio ? context.l10n.clicks : context.l10n.totalDisks,
'${radio ? audio.clicks : audio.discTotal}',
),
if (!radio)
(
context.l10n.genre,
'${audio.genre}',
),
(
context.l10n.url,
(audio.url ?? ''),
Expand Down
2 changes: 1 addition & 1 deletion lib/common/view/avatar_play_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class AvatarPlayButton extends StatelessWidget with WatchItMixin {
(PlayerModel m) => m.queueName != null && m.queueName == pageId,
);
final iconData =
isPlayerPlaying && pageIsQueue ? Iconz().pause : Iconz().playFilled;
isPlayerPlaying && pageIsQueue ? Iconz.pause : Iconz.playFilled;

return Padding(
padding: bigPlayButtonPadding,
Expand Down
2 changes: 1 addition & 1 deletion lib/common/view/back_gesture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class _BackGestureState extends State<BackGesture>
BorderRadius.circular(_kButtonSize),
),
),
child: Icon(Iconz().goBack),
child: Icon(Iconz.goBack),
),
),
),
Expand Down
2 changes: 1 addition & 1 deletion lib/common/view/country_auto_complete.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class _CountryTile extends StatelessWidget {
favs?.contains(t.code) == false ? addFav(t) : removeFav(t);
},
icon: Icon(
favs?.contains(t.code) == true ? Iconz().starFilled : Iconz().star,
favs?.contains(t.code) == true ? Iconz.starFilled : Iconz.star,
),
),
);
Expand Down
Loading

0 comments on commit 42d61ee

Please sign in to comment.