Skip to content

Commit c075d9b

Browse files
authored
feat: rework library to be fully ID based and add local audio metadata writer UI (#1227)
1 parent be71b08 commit c075d9b

File tree

79 files changed

+2613
-1661
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2613
-1661
lines changed

lib/app/view/create_master_items.dart

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:watch_it/watch_it.dart';
3+
4+
import '../../app_config.dart';
5+
import '../../common/data/audio_type.dart';
6+
import '../../common/page_ids.dart';
7+
import '../../common/view/icons.dart';
8+
import '../../common/view/side_bar_fall_back_image.dart';
9+
import '../../common/view/theme.dart';
10+
import '../../custom_content/view/custom_content_page.dart';
11+
import '../../extensions/string_x.dart';
12+
import '../../home/home_page.dart';
13+
import '../../l10n/l10n.dart';
14+
import '../../library/library_model.dart';
15+
import '../../local_audio/view/album_page.dart';
16+
import '../../local_audio/view/local_audio_page.dart';
17+
import '../../playlists/view/liked_audio_page.dart';
18+
import '../../playlists/view/playlist_page.dart';
19+
import '../../podcasts/view/lazy_podcast_page.dart';
20+
import '../../podcasts/view/podcast_page_side_bar_icon.dart';
21+
import '../../podcasts/view/podcast_page_title.dart';
22+
import '../../podcasts/view/podcasts_page.dart';
23+
import '../../radio/view/radio_page.dart';
24+
import '../../radio/view/station_page.dart';
25+
import '../../radio/view/station_page_icon.dart';
26+
import '../../radio/view/station_title.dart';
27+
import '../../search/view/search_page.dart';
28+
import '../../settings/view/settings_page.dart';
29+
import 'main_page_icon.dart';
30+
import 'master_items.dart';
31+
32+
List<MasterItem> createMasterItems() {
33+
final libraryModel = di<LibraryModel>();
34+
return [
35+
MasterItem(
36+
titleBuilder: (context) => Text(context.l10n.search),
37+
pageBuilder: (_) => const SearchPage(),
38+
iconBuilder: (_) => Icon(Iconz.search),
39+
pageId: PageIDs.searchPage,
40+
),
41+
MasterItem(
42+
titleBuilder: (context) => Text(context.l10n.local),
43+
pageBuilder: (_) => const LocalAudioPage(),
44+
iconBuilder: (selected) => MainPageIcon(
45+
audioType: AudioType.local,
46+
selected: selected,
47+
),
48+
pageId: PageIDs.localAudio,
49+
),
50+
MasterItem(
51+
titleBuilder: (context) => Text(context.l10n.radio),
52+
pageBuilder: (_) => const RadioPage(),
53+
iconBuilder: (selected) => MainPageIcon(
54+
audioType: AudioType.radio,
55+
selected: selected,
56+
),
57+
pageId: PageIDs.radio,
58+
),
59+
MasterItem(
60+
titleBuilder: (context) => Text(context.l10n.podcasts),
61+
pageBuilder: (_) => const PodcastsPage(),
62+
iconBuilder: (selected) => MainPageIcon(
63+
audioType: AudioType.podcast,
64+
selected: selected,
65+
),
66+
pageId: PageIDs.podcasts,
67+
),
68+
if (AppConfig.isMobilePlatform)
69+
MasterItem(
70+
titleBuilder: (context) => Text(context.l10n.settings),
71+
iconBuilder: (selected) =>
72+
Icon(selected ? Iconz.settingsFilled : Iconz.settings),
73+
pageBuilder: (context) => const SettingsPage(),
74+
pageId: PageIDs.settings,
75+
),
76+
if (AppConfig.isMobilePlatform)
77+
MasterItem(
78+
titleBuilder: (context) => Text(context.l10n.home),
79+
iconBuilder: (selected) =>
80+
Icon(selected ? Iconz.homeFilled : Iconz.home),
81+
pageBuilder: (context) => const HomePage(),
82+
pageId: PageIDs.homePage,
83+
),
84+
MasterItem(
85+
iconBuilder: (selected) => Icon(Iconz.plus),
86+
titleBuilder: (context) => Text(context.l10n.add),
87+
pageBuilder: (_) => const CustomContentPage(),
88+
pageId: PageIDs.customContent,
89+
),
90+
MasterItem(
91+
titleBuilder: (context) => Text(context.l10n.likedSongs),
92+
pageId: PageIDs.likedAudios,
93+
pageBuilder: (_) => const LikedAudioPage(),
94+
subtitleBuilder: (context) => Text(context.l10n.playlist),
95+
iconBuilder: (selected) => LikedAudioPageIcon(selected: selected),
96+
),
97+
for (final id in libraryModel.playlistIDs)
98+
MasterItem(
99+
titleBuilder: (context) => Text(id),
100+
subtitleBuilder: (context) => Text(context.l10n.playlist),
101+
pageId: id,
102+
pageBuilder: (_) => PlaylistPage(pageId: id),
103+
iconBuilder: (selected) => SideBarFallBackImage(
104+
color: getAlphabetColor(id),
105+
child: Icon(Iconz.playlist),
106+
),
107+
),
108+
for (final feedUrl in libraryModel.podcastFeedUrls)
109+
MasterItem(
110+
titleBuilder: (_) => PodcastPageTitle(
111+
feedUrl: feedUrl,
112+
),
113+
subtitleBuilder: (context) => PodcastPageSubTitle(feedUrl: feedUrl),
114+
pageId: feedUrl,
115+
pageBuilder: (_) => LazyPodcastPage(feedUrl: feedUrl),
116+
iconBuilder: (selected) => PodcastPageSideBarIcon(feedUrl: feedUrl),
117+
),
118+
for (final id in libraryModel.favoriteAlbums)
119+
MasterItem(
120+
titleBuilder: (context) => Text(id.albumOfId),
121+
subtitleBuilder: (context) => Text(id.artistOfId),
122+
pageId: id,
123+
pageBuilder: (_) => AlbumPage(id: id),
124+
iconBuilder: (selected) => AlbumPageSideBarIcon(
125+
albumId: id,
126+
),
127+
),
128+
for (final uuid in libraryModel.starredStations.where((e) => e.isNotEmpty))
129+
MasterItem(
130+
titleBuilder: (context) => StationTitle(uuid: uuid),
131+
subtitleBuilder: (context) => Text(context.l10n.station),
132+
pageId: uuid,
133+
pageBuilder: (_) => StationPage(uuid: uuid),
134+
iconBuilder: (selected) => StationPageIcon(
135+
uuid: uuid,
136+
selected: selected,
137+
),
138+
),
139+
];
140+
}

lib/app/view/desktop_home_page.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class _DesktopHomePageState extends State<DesktopHomePage> {
3838
builder: (_) => PatchNotesDialog(
3939
onClose: () {
4040
if ((di<LocalAudioModel>().audios?.isNotEmpty ?? false) &&
41-
di<LibraryModel>().playlists.isNotEmpty &&
42-
di<LibraryModel>().pinnedAlbums.isNotEmpty &&
41+
di<LibraryModel>().playlistIDs.isNotEmpty &&
42+
di<LibraryModel>().favoriteAlbums.isNotEmpty &&
4343
di<AppModel>().isBackupScreenNeeded &&
4444
!di<AppModel>().wasBackupSaved &&
4545
mounted) {

lib/app/view/master_detail_page.dart

+7-77
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,30 @@ import 'dart:io';
33
import 'package:collection/collection.dart';
44
import 'package:flutter/material.dart';
55
import 'package:watch_it/watch_it.dart';
6-
import 'package:yaru/yaru.dart';
76

87
import '../../app_config.dart';
98
import '../../common/page_ids.dart';
109
import '../../common/view/back_gesture.dart';
1110
import '../../common/view/global_keys.dart';
12-
import '../../common/view/header_bar.dart';
1311
import '../../common/view/icons.dart';
1412
import '../../common/view/ui_constants.dart';
1513
import '../../extensions/build_context_x.dart';
1614
import '../../library/library_model.dart';
17-
import '../../settings/view/settings_action.dart';
18-
import 'master_items.dart';
19-
import 'master_tile.dart';
15+
import 'create_master_items.dart';
16+
import 'master_panel.dart';
2017

21-
class MasterDetailPage extends StatelessWidget with WatchItMixin {
18+
class MasterDetailPage extends StatelessWidget {
2219
const MasterDetailPage({super.key});
2320

2421
@override
2522
Widget build(BuildContext context) {
26-
final libraryModel = watchIt<LibraryModel>();
27-
final masterItems = createMasterItems(libraryModel: libraryModel);
23+
final libraryModel = di<LibraryModel>();
2824

2925
final drawer = Drawer(
3026
width: kMasterDetailSideBarWidth,
3127
child: Stack(
3228
children: [
33-
MasterPanel(masterItems: masterItems, libraryModel: libraryModel),
29+
const MasterPanel(),
3430
Positioned(
3531
left: Platform.isMacOS ? 5 : null,
3632
top: 5,
@@ -55,11 +51,7 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin {
5551
drawer: Platform.isMacOS ? null : drawer,
5652
body: Row(
5753
children: [
58-
if (context.showMasterPanel)
59-
MasterPanel(
60-
masterItems: masterItems,
61-
libraryModel: libraryModel,
62-
),
54+
if (context.showMasterPanel) const MasterPanel(),
6355
if (context.showMasterPanel) const VerticalDivider(),
6456
Expanded(
6557
child: Navigator(
@@ -68,6 +60,7 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin {
6860
key: libraryModel.masterNavigatorKey,
6961
observers: [libraryModel],
7062
onGenerateRoute: (settings) {
63+
final masterItems = createMasterItems();
7164
final page = (masterItems.firstWhereOrNull(
7265
(e) => e.pageId == settings.name,
7366
) ??
@@ -88,66 +81,3 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin {
8881
);
8982
}
9083
}
91-
92-
class MasterPanel extends StatelessWidget {
93-
const MasterPanel({
94-
super.key,
95-
required this.masterItems,
96-
required this.libraryModel,
97-
});
98-
99-
final List<MasterItem> masterItems;
100-
final LibraryModel libraryModel;
101-
102-
@override
103-
Widget build(BuildContext context) {
104-
return SizedBox(
105-
width: kMasterDetailSideBarWidth,
106-
child: Column(
107-
children: [
108-
const HeaderBar(
109-
includeBackButton: false,
110-
includeSidebarButton: false,
111-
backgroundColor: Colors.transparent,
112-
style: YaruTitleBarStyle.undecorated,
113-
adaptive: false,
114-
title: Text(AppConfig.appTitle),
115-
),
116-
Expanded(
117-
child: ListView.separated(
118-
itemCount: masterItems.length,
119-
itemBuilder: (context, index) {
120-
final item = masterItems.elementAt(index);
121-
return MasterTile(
122-
key: ValueKey(item.pageId),
123-
onTap: () {
124-
libraryModel.push(pageId: item.pageId);
125-
126-
if (!context.showMasterPanel) {
127-
if (Platform.isMacOS) {
128-
masterScaffoldKey.currentState?.closeEndDrawer();
129-
} else {
130-
masterScaffoldKey.currentState?.closeDrawer();
131-
}
132-
}
133-
},
134-
pageId: item.pageId,
135-
libraryModel: libraryModel,
136-
leading: item.iconBuilder
137-
?.call(libraryModel.selectedPageId == item.pageId),
138-
title: item.titleBuilder(context),
139-
subtitle: item.subtitleBuilder?.call(context),
140-
selected: libraryModel.selectedPageId == item.pageId,
141-
);
142-
},
143-
separatorBuilder: (_, __) => const SizedBox(
144-
height: 5,
145-
),
146-
),
147-
),
148-
const SettingsButton.tile(),
149-
],
150-
),
151-
);
152-
}
153-
}

0 commit comments

Comments
 (0)