Files
Amphlify/Amphlify/UI/Detail/ArtistDetailView.swift
T

97 lines
3.7 KiB
Swift

import Domain
import SwiftUI
struct ArtistDetailView: View {
let id: EntityID
@Environment(AppModel.self) private var app
@Environment(PlayerModel.self) private var player
@State private var artist: Artist?
@State private var albums: [Album] = []
@State private var topTracks: [Track] = []
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 24) {
hero
if !topTracks.isEmpty {
VStack(alignment: .leading, spacing: 8) {
SectionHeader(title: "Top Songs")
TrackList(tracks: topTracks, subtitle: .album)
}
}
if !albums.isEmpty {
VStack(alignment: .leading, spacing: 12) {
SectionHeader(title: "Albums")
AlbumGrid(albums: albums, showsArtist: false)
}
}
}
.padding(.bottom, 24)
}
.ignoresSafeArea(edges: .top)
.modifier(ScrollRevealedTitle(title: artist?.name ?? "", threshold: 270))
.scrollEdgeEffectHidden(true, for: .top)
.toolbar {
if app.canFavorite(id) {
ToolbarItem(placement: .topBarTrailing) {
let isFavorite = app.favorites.contains(id)
Button(
isFavorite ? "Undo Favorite" as LocalizedStringKey : "Favorite",
systemImage: isFavorite ? "star.fill" : "star"
) {
app.toggleFavorite(id, kind: .artist)
}
}
}
}
.task(id: app.revision) {
artist = await app.library.artist(id)
albums = await app.library.albums(byArtist: id)
topTracks = await Array(app.library.tracks(byArtist: id).prefix(5))
}
}
private var hero: some View {
ArtworkView(artwork: artist?.artwork, shape: .rounded(0), pixelSize: 1024)
.containerRelativeFrame(.horizontal)
.visualEffect { content, proxy in
let pull = max(proxy.frame(in: .scrollView).minY, 0)
return content.scaleEffect(1 + pull / max(proxy.size.height, 1), anchor: .bottom)
}
.overlay(alignment: .bottom) {
LinearGradient(
stops: [
.init(color: .clear, location: 0),
.init(color: Color(.systemBackground).opacity(0.55), location: 0.55),
.init(color: Color(.systemBackground), location: 1),
],
startPoint: .top,
endPoint: .bottom
)
.frame(height: 200)
}
.overlay(alignment: .bottom) {
HStack(alignment: .bottom) {
Text(artist?.name ?? "")
.font(.largeTitle.bold())
.lineLimit(2)
.minimumScaleFactor(0.7)
Spacer()
Button {
Task { await player.shuffle(app.library.tracks(byArtist: id)) }
} label: {
Image(systemName: "play.fill")
.font(.title3)
.foregroundStyle(.white)
.frame(width: 48, height: 48)
.background(.tint, in: .circle)
}
.accessibilityLabel("Play")
}
.padding(.horizontal, Metrics.margin)
.padding(.bottom, 12)
}
}
}