174 lines
6.0 KiB
Swift
174 lines
6.0 KiB
Swift
//
|
|
// 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")
|
|
}
|