Live Activities fix
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// MobileMALiveActivityLiveActivity.swift
|
||||
// MobileMALiveActivity
|
||||
//
|
||||
|
||||
import ActivityKit
|
||||
import MobileMAShared
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
import WidgetKit
|
||||
|
||||
private let activityTeal = Color(red: 0.0, green: 0.82, blue: 0.75)
|
||||
|
||||
// MARK: - Artwork View
|
||||
|
||||
private struct ArtworkView: View {
|
||||
let artworkData: Data?
|
||||
let size: CGFloat
|
||||
let cornerRadius: CGFloat
|
||||
let isPlaying: Bool
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let artworkData, let uiImage = UIImage(data: artworkData) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
} else {
|
||||
fallbackIcon
|
||||
}
|
||||
}
|
||||
.frame(width: size, height: size)
|
||||
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
||||
}
|
||||
|
||||
private var fallbackIcon: some View {
|
||||
ZStack {
|
||||
activityTeal.opacity(0.2)
|
||||
Image(systemName: "speaker.wave.3.fill")
|
||||
.symbolEffect(
|
||||
.variableColor.iterative.dimInactiveLayers.reversing,
|
||||
isActive: isPlaying
|
||||
)
|
||||
.font(.system(size: size * 0.4, weight: .semibold))
|
||||
.foregroundStyle(activityTeal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Widget
|
||||
|
||||
struct MobileMALiveActivityLiveActivity: Widget {
|
||||
var body: some WidgetConfiguration {
|
||||
ActivityConfiguration(for: MusicActivityAttributes.self) { context in
|
||||
LockScreenView(state: context.state)
|
||||
.activityBackgroundTint(activityTeal.opacity(0.2))
|
||||
} dynamicIsland: { context in
|
||||
DynamicIsland {
|
||||
DynamicIslandExpandedRegion(.leading) {
|
||||
ArtworkView(
|
||||
artworkData: context.state.artworkData,
|
||||
size: 50,
|
||||
cornerRadius: 10,
|
||||
isPlaying: context.state.isPlaying
|
||||
)
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
DynamicIslandExpandedRegion(.trailing) {
|
||||
Image(systemName: context.state.isPlaying ? "pause.circle.fill" : "play.circle.fill")
|
||||
.font(.title)
|
||||
.foregroundStyle(activityTeal)
|
||||
.padding(.trailing, 4)
|
||||
}
|
||||
DynamicIslandExpandedRegion(.center) {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(context.state.trackTitle)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
Text(context.state.artistName)
|
||||
.font(.subheadline)
|
||||
.lineLimit(1)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
DynamicIslandExpandedRegion(.bottom) {
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "hifispeaker.fill")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(activityTeal)
|
||||
Text(context.state.playerName)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
}
|
||||
} compactLeading: {
|
||||
ArtworkView(
|
||||
artworkData: context.state.artworkData,
|
||||
size: 28,
|
||||
cornerRadius: 6,
|
||||
isPlaying: context.state.isPlaying
|
||||
)
|
||||
.padding(.leading, 2)
|
||||
} compactTrailing: {
|
||||
Image(systemName: context.state.isPlaying ? "pause.circle.fill" : "play.circle.fill")
|
||||
.font(.body)
|
||||
.foregroundStyle(activityTeal)
|
||||
.padding(.trailing, 2)
|
||||
} minimal: {
|
||||
ArtworkView(
|
||||
artworkData: context.state.artworkData,
|
||||
size: 24,
|
||||
cornerRadius: 12,
|
||||
isPlaying: context.state.isPlaying
|
||||
)
|
||||
}
|
||||
.keylineTint(activityTeal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Lock Screen View
|
||||
|
||||
private struct LockScreenView: View {
|
||||
let state: MusicActivityAttributes.ContentState
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
ArtworkView(artworkData: state.artworkData, size: 54, cornerRadius: 10, isPlaying: state.isPlaying)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(state.trackTitle.isEmpty ? "Now Playing" : state.trackTitle)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
if !state.artistName.isEmpty {
|
||||
Text(state.artistName)
|
||||
.font(.subheadline)
|
||||
.lineLimit(1)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "hifispeaker.fill")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(activityTeal)
|
||||
Text(state.playerName)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(systemName: state.isPlaying ? "pause.circle.fill" : "play.circle.fill")
|
||||
.font(.system(size: 32))
|
||||
.foregroundStyle(activityTeal)
|
||||
}
|
||||
.padding(16)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
|
||||
#Preview("Notification", as: .content, using: MusicActivityAttributes()) {
|
||||
MobileMALiveActivityLiveActivity()
|
||||
} contentStates: {
|
||||
MusicActivityAttributes.ContentState(
|
||||
trackTitle: "Bohemian Rhapsody", artistName: "Queen",
|
||||
artworkData: nil, isPlaying: true, playerName: "Living Room")
|
||||
MusicActivityAttributes.ContentState(
|
||||
trackTitle: "Bohemian Rhapsody", artistName: "Queen",
|
||||
artworkData: nil, isPlaying: false, playerName: "Living Room")
|
||||
}
|
||||
Reference in New Issue
Block a user