130 lines
4.3 KiB
Swift
130 lines
4.3 KiB
Swift
import Domain
|
|
import Store
|
|
import SwiftUI
|
|
|
|
struct AlbumsView: View {
|
|
@Environment(AppModel.self) private var app
|
|
@State private var albums: [Album] = []
|
|
@State private var sort: AlbumSort = .artist
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
AlbumGrid(albums: albums).padding(.vertical, 12)
|
|
}
|
|
.pageTitle("Albums")
|
|
.toolbar {
|
|
ToolbarItem(placement: .primaryAction) {
|
|
Menu("Sort", systemImage: "arrow.up.arrow.down") {
|
|
Picker("Sort", selection: $sort) {
|
|
Text("Artist").tag(AlbumSort.artist)
|
|
Text("Title").tag(AlbumSort.title)
|
|
Text("Year").tag(AlbumSort.year)
|
|
Text("Recently Added").tag(AlbumSort.recentlyAdded)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.task(id: [app.revision, sort.hashValue]) { albums = await app.library.albums(sortedBy: sort) }
|
|
}
|
|
}
|
|
|
|
struct ArtistsView: View {
|
|
@Environment(AppModel.self) private var app
|
|
@State private var artists: [Artist] = []
|
|
|
|
var body: some View {
|
|
List(artists) { artist in
|
|
NavigationLink(value: Route.artist(artist.id)) {
|
|
HStack(spacing: 14) {
|
|
ArtworkView(artwork: artist.artwork, shape: .circle).frame(width: 52, height: 52)
|
|
Text(artist.name).font(.title3)
|
|
}
|
|
}
|
|
.alignmentGuide(.listRowSeparatorLeading) { $0[.leading] + 66 }
|
|
}
|
|
.listStyle(.plain)
|
|
.pageTitle("Artists")
|
|
.task(id: app.revision) { artists = await app.library.artists() }
|
|
}
|
|
}
|
|
|
|
struct SongsView: View {
|
|
@Environment(AppModel.self) private var app
|
|
@Environment(PlayerModel.self) private var player
|
|
@State private var tracks: [Track] = []
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
PlayShuffleButtons { player.play(tracks) } onShuffle: { player.shuffle(tracks) }
|
|
.padding(.horizontal, Metrics.margin)
|
|
.padding(.vertical, 12)
|
|
TrackList(tracks: tracks)
|
|
}
|
|
.pageTitle("Songs")
|
|
.task(id: app.revision) { tracks = await app.library.tracks() }
|
|
}
|
|
}
|
|
|
|
struct PlaylistsView: View {
|
|
@Environment(AppModel.self) private var app
|
|
@State private var playlists: [Playlist] = []
|
|
|
|
var body: some View {
|
|
List {
|
|
NavigationLink(value: Route.favorites) {
|
|
row(Text("Favorite Songs")) {
|
|
RoundedRectangle(cornerRadius: 6, style: .continuous)
|
|
.fill(Color.accentColor.gradient)
|
|
.overlay { Image(systemName: "star.fill").font(.title).foregroundStyle(.white) }
|
|
}
|
|
}
|
|
.listRowSeparator(.hidden, edges: .top)
|
|
.alignmentGuide(.listRowSeparatorLeading) { $0[.leading] + 86 }
|
|
ForEach(playlists) { playlist in
|
|
NavigationLink(value: Route.playlist(playlist.id)) {
|
|
row(Text(playlist.name)) { ArtworkView(artwork: playlist.artwork, shape: .rounded(6)) }
|
|
}
|
|
}
|
|
.alignmentGuide(.listRowSeparatorLeading) { $0[.leading] + 86 }
|
|
}
|
|
.listStyle(.plain)
|
|
.pageTitle("Playlists")
|
|
.task(id: app.revision) { playlists = await app.library.playlists() }
|
|
}
|
|
|
|
private func row(_ name: Text, @ViewBuilder artwork: () -> some View) -> some View {
|
|
HStack(spacing: 14) {
|
|
artwork().frame(width: 72, height: 72)
|
|
name.lineLimit(2)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct GenresView: View {
|
|
@Environment(AppModel.self) private var app
|
|
@State private var genres: [Genre] = []
|
|
|
|
var body: some View {
|
|
List(genres) { genre in
|
|
NavigationLink(value: Route.genre(genre.name)) { Text(genre.name).font(.title3) }
|
|
}
|
|
.listStyle(.plain)
|
|
.pageTitle("Genres")
|
|
.task(id: app.revision) { genres = await app.library.genres() }
|
|
}
|
|
}
|
|
|
|
struct GenreDetailView: View {
|
|
let genre: String
|
|
@Environment(AppModel.self) private var app
|
|
@State private var albums: [Album] = []
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
AlbumGrid(albums: albums).padding(.vertical, 12)
|
|
}
|
|
.pageTitle(verbatim: genre)
|
|
.task(id: app.revision) { albums = await app.library.albums(inGenre: genre) }
|
|
}
|
|
}
|