Fit player artwork to the available screen height
This commit is contained in:
@@ -6,6 +6,7 @@ struct ContentView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
GeometryReader { viewport in
|
||||||
ScrollView {
|
ScrollView {
|
||||||
VStack(spacing: 20) {
|
VStack(spacing: 20) {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
@@ -16,7 +17,7 @@ struct ContentView: View {
|
|||||||
if store.connection == nil {
|
if store.connection == nil {
|
||||||
PairingView(store: store, discovery: store.discovery)
|
PairingView(store: store, discovery: store.discovery)
|
||||||
} else {
|
} else {
|
||||||
PlayerView(store: store)
|
PlayerView(store: store, coverSize: min(280, max(120, min(viewport.size.width - 40, viewport.size.height * 0.30))))
|
||||||
|
|
||||||
if !store.connected && !store.needsPairing {
|
if !store.connected && !store.needsPairing {
|
||||||
Button("Подключиться снова") { store.resume() }
|
Button("Подключиться снова") { store.resume() }
|
||||||
@@ -33,6 +34,7 @@ struct ContentView: View {
|
|||||||
}.padding(20)
|
}.padding(20)
|
||||||
}
|
}
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboard(.interactively)
|
||||||
|
}
|
||||||
.background(Color(.systemGroupedBackground))
|
.background(Color(.systemGroupedBackground))
|
||||||
.navigationTitle("MusicBridge")
|
.navigationTitle("MusicBridge")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
@@ -188,6 +190,7 @@ private struct PairingView: View {
|
|||||||
|
|
||||||
private struct PlayerView: View {
|
private struct PlayerView: View {
|
||||||
@ObservedObject var store: PlayerStore
|
@ObservedObject var store: PlayerStore
|
||||||
|
let coverSize: CGFloat
|
||||||
@Environment(\.dynamicTypeSize) private var textSize
|
@Environment(\.dynamicTypeSize) private var textSize
|
||||||
@State private var seekValue = 0.0
|
@State private var seekValue = 0.0
|
||||||
@State private var seeking = false
|
@State private var seeking = false
|
||||||
@@ -204,7 +207,9 @@ private struct PlayerView: View {
|
|||||||
.fill(LinearGradient(colors: [.indigo.opacity(0.85), .teal.opacity(0.75)], startPoint: .topLeading, endPoint: .bottomTrailing))
|
.fill(LinearGradient(colors: [.indigo.opacity(0.85), .teal.opacity(0.75)], startPoint: .topLeading, endPoint: .bottomTrailing))
|
||||||
.overlay { Image(systemName: "waveform.path").font(.system(size: 72, weight: .light)).foregroundStyle(.white.opacity(0.9)) }
|
.overlay { Image(systemName: "waveform.path").font(.system(size: 72, weight: .light)).foregroundStyle(.white.opacity(0.9)) }
|
||||||
}
|
}
|
||||||
}.frame(maxWidth: textSize.isAccessibilitySize ? 210 : 300).aspectRatio(1, contentMode: .fit).clipShape(RoundedRectangle(cornerRadius: 28))
|
}.frame(width: textSize.isAccessibilitySize ? min(180, coverSize) : coverSize,
|
||||||
|
height: textSize.isAccessibilitySize ? min(180, coverSize) : coverSize)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 28))
|
||||||
.accessibilityLabel("Обложка трека")
|
.accessibilityLabel("Обложка трека")
|
||||||
if let error = store.artworkError {
|
if let error = store.artworkError {
|
||||||
Text(error).font(.footnote).foregroundStyle(.secondary)
|
Text(error).font(.footnote).foregroundStyle(.secondary)
|
||||||
@@ -213,7 +218,7 @@ private struct PlayerView: View {
|
|||||||
if let state = store.state {
|
if let state = store.state {
|
||||||
Text(state.hasSession ? (state.title.isEmpty ? "Без названия" : state.title) : "Откройте плеер на ПК")
|
Text(state.hasSession ? (state.title.isEmpty ? "Без названия" : state.title) : "Откройте плеер на ПК")
|
||||||
.font(.title2.bold()).multilineTextAlignment(.center)
|
.font(.title2.bold()).multilineTextAlignment(.center)
|
||||||
Text(state.artist).foregroundStyle(.secondary)
|
Text(state.artist).foregroundStyle(.secondary).multilineTextAlignment(.center)
|
||||||
TimelineView(.periodic(from: .now, by: 0.25)) { timeline in
|
TimelineView(.periodic(from: .now, by: 0.25)) { timeline in
|
||||||
let position = state.position(elapsed: timeline.date.timeIntervalSince(store.receivedAt))
|
let position = state.position(elapsed: timeline.date.timeIntervalSince(store.receivedAt))
|
||||||
VStack {
|
VStack {
|
||||||
|
|||||||
Reference in New Issue
Block a user