feat(media): decouple airplay and output, merged output for lock screen

This commit is contained in:
Amir Zarrinkafsh 2026-03-27 13:03:59 +11:00
commit 9d17e4aafb
No known key found for this signature in database
GPG key ID: ECDB8EF9E77E4EBF
7 changed files with 296 additions and 84 deletions

View file

@ -834,6 +834,7 @@ extension Defaults.Keys {
static let lockScreenShowAppIcon = Key<Bool>("lockScreenShowAppIcon", default: false)
static let lockScreenPanelShowsBorder = Key<Bool>("lockScreenPanelShowsBorder", default: false)
static let lockScreenPanelUsesBlur = Key<Bool>("lockScreenPanelUsesBlur", default: true)
static let lockScreenMusicMergedAirPlayOutput = Key<Bool>("lockScreenMusicMergedAirPlayOutput", default: true)
static let lockScreenTimerWidgetUsesBlur = Key<Bool>("lockScreenTimerWidgetUsesBlur", default: false)
static let lockScreenReminderChipStyle = Key<LockScreenReminderChipStyle>("lockScreenReminderChipStyle", default: .eventColor)
static let lockScreenReminderWidgetHorizontalAlignment = Key<String>("lockScreenReminderWidgetHorizontalAlignment", default: "center")

View file

@ -29,6 +29,7 @@ enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.S
case trackForward
case repeatMode
case mediaOutput
case airPlay
case lyrics
case seekBackward
case seekForward
@ -61,9 +62,15 @@ enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.S
.shuffle,
.repeatMode,
.lyrics,
.mediaOutput
.mediaOutput,
.airPlay
]
/// Controls that are only available when Apple Music is the active media source.
var isAppleMusicExclusive: Bool {
self == .airPlay
}
var id: String { rawValue }
var label: String {
@ -80,6 +87,8 @@ enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.S
return "Repeat"
case .mediaOutput:
return "Change Media Output"
case .airPlay:
return "AirPlay"
case .lyrics:
return "Lyrics"
case .seekBackward:
@ -105,6 +114,8 @@ enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.S
return "repeat"
case .mediaOutput:
return "speaker.wave.2"
case .airPlay:
return "airplayaudio"
case .lyrics:
return "quote.bubble"
case .seekBackward:
@ -122,11 +133,10 @@ enum MusicControlButton: String, CaseIterable, Identifiable, Codable, Defaults.S
}
extension Array where Element == MusicControlButton {
func normalized(allowingMediaOutput: Bool) -> [MusicControlButton] {
func normalized(allowingMediaOutput: Bool, isAppleMusicActive: Bool = true) -> [MusicControlButton] {
var sanitized = map { button -> MusicControlButton in
if button == .mediaOutput && !allowingMediaOutput {
return .none
}
if button == .mediaOutput && !allowingMediaOutput { return .none }
if button.isAppleMusicExclusive && !isAppleMusicActive { return .none }
return button
}