Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add favs to playlistsview + friends #981

Merged
merged 1 commit into from
Oct 26, 2024
Merged
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
5 changes: 4 additions & 1 deletion lib/common/view/copy_clipboard_content.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:yaru/yaru.dart';

import '../../extensions/build_context_x.dart';
import '../../l10n/l10n.dart';
Expand Down Expand Up @@ -58,7 +59,9 @@ class _CopyClipboardContentState extends State<CopyClipboardContent> {
),
if (widget.showActions)
StreamProviderRow(
iconColor: theme.snackBarTheme.actionTextColor,
iconColor: theme.snackBarTheme.backgroundColor != null
? contrastColor(theme.snackBarTheme.backgroundColor!)
: theme.colorScheme.primary,
onSearch: widget.onSearch,
text: widget.text,
),
Expand Down
26 changes: 20 additions & 6 deletions lib/local_audio/view/playlists_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PlaylistsView extends StatelessWidget {
Widget build(BuildContext context) {
final lists = [
kNewPlaylistPageId,
kLikedAudiosPageId,
...(playlists ?? []),
];

Expand All @@ -38,7 +39,8 @@ class PlaylistsView extends StatelessWidget {
onTap: () => id == kNewPlaylistPageId
? showDialog(
context: context,
builder: (context) => const ManualAddDialog(),
builder: (context) =>
const ManualAddDialog(onlyPlaylists: true),
)
: di<LibraryModel>().push(
builder: (_) => PlaylistPage(
Expand All @@ -63,12 +65,24 @@ class PlaylistsView extends StatelessWidget {
),
child: Icon(Iconz.plus),
)
: RoundImageContainer(
images: const {},
fallBackText: id,
),
: id == kLikedAudiosPageId
? Container(
decoration: BoxDecoration(
color:
context.colorScheme.primary.withOpacity(0.3),
shape: BoxShape.circle,
),
child: Icon(Iconz.heart),
)
: RoundImageContainer(
images: const {},
fallBackText: id,
),
),
if (id != kNewPlaylistPageId) ArtistVignette(text: id),
if (id != kNewPlaylistPageId && id != kLikedAudiosPageId)
ArtistVignette(
text: id,
),
],
),
);
Expand Down
73 changes: 47 additions & 26 deletions lib/playlists/view/manual_add_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@ import '../../common/view/common_widgets.dart';
import '../../common/view/global_keys.dart';
import '../../common/view/icons.dart';
import '../../common/view/theme.dart';
import '../../constants.dart';
import '../../external_path/external_path_service.dart';
import '../../l10n/l10n.dart';
import '../../library/library_model.dart';
import '../../local_audio/local_audio_model.dart';
import '../../local_audio/view/local_audio_view.dart';
import '../../podcasts/podcast_model.dart';

class ManualAddDialog extends StatelessWidget {
const ManualAddDialog({super.key});
const ManualAddDialog({
super.key,
this.onlyPlaylists = false,
});

final bool onlyPlaylists;

@override
Widget build(BuildContext context) {
Expand All @@ -30,31 +38,40 @@ class ManualAddDialog extends StatelessWidget {
content: SizedBox(
height: 200,
width: 400,
child: Navigator(
// ignore: deprecated_member_use
onPopPage: (route, result) => route.didPop(result),
key: manualAddNavigatorKey,
initialRoute: '/chose',
onGenerateRoute: (settings) {
Widget page = switch (settings.name) {
'/addPlaylist' => PlaylistContent(
child: onlyPlaylists
? Padding(
padding: const EdgeInsets.only(top: 20),
child: PlaylistContent(
playlistName: context.l10n.createNewPlaylist,
libraryModel: di<LibraryModel>(),
allowCreate: true,
),
'/addPodcast' => const AddPodcastContent(),
'/addStation' => const AddStationContent(),
_ => const SelectAddContent()
};

return PageRouteBuilder(
barrierDismissible: true,
pageBuilder: (_, __, ___) => page,
reverseTransitionDuration: const Duration(seconds: 0),
transitionDuration: const Duration(milliseconds: 0),
);
},
),
)
: Navigator(
// ignore: deprecated_member_use
onPopPage: (route, result) => route.didPop(result),
key: manualAddNavigatorKey,
initialRoute: '/chose',
onGenerateRoute: (settings) {
Widget page = switch (settings.name) {
'/addPlaylist' => PlaylistContent(
playlistName: context.l10n.createNewPlaylist,
libraryModel: di<LibraryModel>(),
allowCreate: true,
),
'/addPodcast' => const AddPodcastContent(),
'/addStation' => const AddStationContent(),
_ => const SelectAddContent()
};

return PageRouteBuilder(
barrierDismissible: true,
pageBuilder: (_, __, ___) => page,
reverseTransitionDuration: const Duration(seconds: 0),
transitionDuration: const Duration(milliseconds: 0),
);
},
),
),
);
}
Expand Down Expand Up @@ -204,10 +221,14 @@ class _PlaylistContentState extends State<PlaylistContent> {
if (widget.allowRename && widget.playlistName != null)
ImportantButton(
onPressed: () {
widget.libraryModel.updatePlaylistName(
widget.playlistName!,
_controller.text,
);
di<LocalAudioModel>().localAudioindex =
LocalAudioView.playlists.index;
widget.libraryModel
..pushNamed(pageId: kLocalAudioPageId)
..updatePlaylistName(
widget.playlistName!,
_controller.text,
);
Navigator.of(context).pop();
},
child: Text(
Expand Down
17 changes: 11 additions & 6 deletions lib/radio/view/radio_history_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,17 @@ class RadioHistoryList extends StatelessWidget with WatchItMixin {
final e = di<PlayerModel>()
.filteredRadioHistory(filter: filter)
.elementAt(reversedIndex);
return RadioHistoryTile(
simpleTile: simpleList,
entry: e,
selected: current?.icyTitle != null &&
current?.icyTitle == e.value.icyTitle,
);
return simpleList
? RadioHistoryTile.simple(
entry: e,
selected: current?.icyTitle != null &&
current?.icyTitle == e.value.icyTitle,
)
: RadioHistoryTile(
entry: e,
selected: current?.icyTitle != null &&
current?.icyTitle == e.value.icyTitle,
);
},
);
},
Expand Down
154 changes: 100 additions & 54 deletions lib/radio/view/radio_history_tile.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:watch_it/watch_it.dart';
import 'package:yaru/constants.dart';
import 'package:yaru/yaru.dart';

import '../../common/data/audio.dart';
import '../../common/data/mpv_meta_data.dart';
Expand All @@ -19,58 +20,118 @@ import '../radio_model.dart';
import 'icy_image.dart';
import 'station_page.dart';

enum _RadioHistoryTileVariant { regular, simple }

class RadioHistoryTile extends StatelessWidget {
const RadioHistoryTile({
super.key,
required this.entry,
required this.selected,
this.simpleTile = false,
}) : _variant = _RadioHistoryTileVariant.regular;

const RadioHistoryTile.simple({
super.key,
required this.entry,
required this.selected,
}) : _variant = _RadioHistoryTileVariant.simple;

final _RadioHistoryTileVariant _variant;
final MapEntry<String, MpvMetaData> entry;
final bool selected;

@override
Widget build(BuildContext context) {
return switch (_variant) {
_RadioHistoryTileVariant.simple => _SimpleRadioHistoryTile(
key: ValueKey(entry.value.icyTitle),
entry: entry,
selected: selected,
),
_RadioHistoryTileVariant.regular => ListTile(
key: ValueKey(entry.value.icyTitle),
selected: selected,
selectedColor: context.theme.contrastyPrimary,
contentPadding:
const EdgeInsets.symmetric(horizontal: kYaruPagePadding),
leading: IcyImage(
key: ValueKey(entry.value.icyTitle),
height: yaruStyled ? 34 : 40,
width: yaruStyled ? 34 : 40,
mpvMetaData: entry.value,
),
trailing: IconButton(
tooltip: context.l10n.metadata,
onPressed: () => showDialog(
context: context,
builder: (context) {
final image = di<RadioModel>().getCover(entry.value.icyTitle);
return MpvMetadataDialog(
mpvMetaData: entry.value,
image: image,
);
},
),
icon: Icon(
Iconz.info,
),
),
title: TapAbleText(
overflow: TextOverflow.visible,
maxLines: 10,
text: entry.value.icyTitle,
onTap: () => showSnackBar(
context: context,
content: CopyClipboardContent(text: entry.value.icyTitle),
),
),
subtitle: TapAbleText(
text: entry.value.icyName,
onTap: () async {
final libraryModel = di<LibraryModel>();
if (libraryModel.selectedPageId == entry.value.icyUrl) return;

await di<RadioModel>().init();
di<SearchModel>().radioNameSearch(entry.value.icyName).then((v) {
if (v?.firstOrNull?.stationUUID != null) {
libraryModel.push(
builder: (_) =>
StationPage(station: Audio.fromStation(v.first)),
pageId: v!.first.stationUUID,
);
}
});
},
),
)
};
}
}

class _SimpleRadioHistoryTile extends StatelessWidget {
const _SimpleRadioHistoryTile({
super.key,
required this.entry,
required this.selected,
});

final MapEntry<String, MpvMetaData> entry;
final bool selected, simpleTile;
final bool selected;

@override
Widget build(BuildContext context) {
return ListTile(
key: ValueKey(entry.value.icyTitle),
selected: selected,
selectedColor: simpleTile
? context.theme.colorScheme.onSurface
: context.theme.contrastyPrimary,
selectedColor: context.theme.colorScheme.onSurface,
contentPadding: const EdgeInsets.symmetric(horizontal: kYaruPagePadding),
leading: simpleTile
? Visibility(
visible: selected,
child: const Text('>'),
)
: IcyImage(
key: ValueKey(entry.value.icyTitle),
height: yaruStyled ? 34 : 40,
width: yaruStyled ? 34 : 40,
mpvMetaData: entry.value,
),
trailing: simpleTile
? Visibility(
visible: selected,
child: const Text('<'),
)
: IconButton(
tooltip: context.l10n.metadata,
onPressed: () => showDialog(
context: context,
builder: (context) {
final image = di<RadioModel>().getCover(entry.value.icyTitle);
return MpvMetadataDialog(
mpvMetaData: entry.value,
image: image,
);
},
),
icon: Icon(
Iconz.info,
),
),
leading: Visibility(
visible: selected,
child: const Text('>'),
),
trailing: Visibility(
visible: selected,
child: const Text('<'),
),
title: TapAbleText(
overflow: TextOverflow.visible,
maxLines: 10,
Expand All @@ -80,23 +141,8 @@ class RadioHistoryTile extends StatelessWidget {
content: CopyClipboardContent(text: entry.value.icyTitle),
),
),
subtitle: TapAbleText(
text: entry.value.icyName,
onTap: () async {
final libraryModel = di<LibraryModel>();
if (libraryModel.selectedPageId == entry.value.icyUrl) return;

await di<RadioModel>().init();
di<SearchModel>().radioNameSearch(entry.value.icyName).then((v) {
if (v?.firstOrNull?.stationUUID != null) {
libraryModel.push(
builder: (_) =>
StationPage(station: Audio.fromStation(v.first)),
pageId: v!.first.stationUUID,
);
}
});
},
subtitle: Text(
entry.value.icyName,
),
);
}
Expand Down
6 changes: 3 additions & 3 deletions lib/search/search_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ class SearchModel extends SafeChangeNotifier {
genres: search?.genres,
artists: search?.artists,
playlists: (query != null && query.isNotEmpty)
? _libraryService.playlists.keys.toList()
: _libraryService.playlists.keys
? _libraryService.playlists.keys
.where(
(e) => e.toLowerCase().contains(query?.toLowerCase() ?? ''),
(e) => e.toLowerCase().contains(query.toLowerCase()),
)
.toList()
: null
);
}

Expand Down