Control PC playback through interactive Live Activity intents

This commit is contained in:
2026-09-13 11:40:23 +03:00
parent fcc66aa328
commit 1e02247cbe
14 changed files with 266 additions and 32 deletions
+28 -4
View File
@@ -1,8 +1,10 @@
import SwiftUI
import AppIntents
struct MusicActivityCard: View {
let state: MusicActivityAttributes.ContentState
let stale: Bool
var activityID: String = ""
var body: some View {
VStack(alignment: .leading, spacing: 10) {
HStack(spacing: 12) {
@@ -14,7 +16,7 @@ struct MusicActivityCard: View {
}
ProgressView(value: state.progress).tint(.indigo)
ActivityStatus(state: state, stale: stale)
Label("Открыть плеер", systemImage: "arrow.up.forward.app").font(.caption.weight(.semibold))
MusicActivityControls(activityID: activityID)
}.padding(16)
}
}
@@ -34,13 +36,35 @@ struct ActivityStatus: View {
let state: MusicActivityAttributes.ContentState
let stale: Bool
var body: some View {
if stale || !state.connected {
Text("Данные устарели · откройте плеер").font(.caption).foregroundStyle(.secondary)
if let message = state.message {
Text(message).font(.caption).lineLimit(2)
} else if !state.connected {
Text("Нет связи с ПК · нажмите обновление").font(.caption).foregroundStyle(.secondary)
} else {
HStack(spacing: 4) {
Text("Снимок с ПК в")
Text("Обновлено в")
Text(state.updatedAt, style: .time)
}.font(.caption).foregroundStyle(.secondary)
}
}
}
struct MusicActivityControls: View {
let activityID: String
var body: some View {
HStack {
control(.previous, icon: "backward.end.fill", label: "Предыдущий трек")
Spacer(minLength: 4)
control(.toggle, icon: "playpause.fill", label: "Воспроизведение или пауза")
Spacer(minLength: 4)
control(.next, icon: "forward.end.fill", label: "Следующий трек")
Spacer(minLength: 4)
control(.refresh, icon: "arrow.clockwise", label: "Обновить трек")
}
}
private func control(_ action: MusicRemoteAction, icon: String, label: String) -> some View {
Button(intent: MusicControlIntent(action, activityID: activityID)) {
Image(systemName: icon).font(.title3).frame(minWidth: 44, minHeight: 44)
}.buttonStyle(.plain).accessibilityLabel(label).disabled(activityID.isEmpty)
}
}