diff --git a/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift b/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift index 2ecdb29..0a505cd 100644 --- a/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift +++ b/DynamicIsland/components/Notch/MinimalisticMusicPlayerView.swift @@ -670,7 +670,7 @@ private struct MinimalisticReminderDetailsView: View { Task { await musicManager.toggleShuffle() } } case .repeatMode: - controlButton(icon: repeatIcon, isActive: musicManager.repeatMode != .off) { + controlButton(icon: repeatIcon, isActive: musicManager.repeatMode != .off, symbolEffect: .replace) { Task { await musicManager.toggleRepeat() } } case .mediaOutput: @@ -706,7 +706,8 @@ private struct MinimalisticReminderDetailsView: View { fontWeight: .medium, frameSize: CGSize(width: 40, height: 40), cornerRadius: 16, - foregroundColor: .white.opacity(0.85) + foregroundColor: .white.opacity(0.85), + symbolEffectStyle: .replace ) { isPopoverPresented.toggle() if isPopoverPresented { diff --git a/DynamicIsland/components/Settings/SettingsView.swift b/DynamicIsland/components/Settings/SettingsView.swift index ea4cf75..d7aa82f 100644 --- a/DynamicIsland/components/Settings/SettingsView.swift +++ b/DynamicIsland/components/Settings/SettingsView.swift @@ -857,6 +857,8 @@ struct Media: View { @Default(.showShuffleAndRepeat) private var showShuffleAndRepeat @Default(.musicAuxLeftControl) private var musicAuxLeftControl @Default(.musicAuxRightControl) private var musicAuxRightControl + @State private var previousLeftAuxControl: MusicAuxiliaryControl = Defaults[.musicAuxLeftControl] + @State private var previousRightAuxControl: MusicAuxiliaryControl = Defaults[.musicAuxRightControl] var body: some View { Form { @@ -969,6 +971,42 @@ struct Media: View { Defaults[.enableFullscreenMediaDetection] = hideNotchOption != .never } } + .onAppear { + ensureAuxControlsUnique() + previousLeftAuxControl = musicAuxLeftControl + previousRightAuxControl = musicAuxRightControl + } + .onChange(of: musicAuxLeftControl) { newValue in + if newValue == musicAuxRightControl { + let fallback = MusicAuxiliaryControl.alternative( + excluding: newValue, + preferring: previousLeftAuxControl + ) + if fallback != musicAuxRightControl { + musicAuxRightControl = fallback + } + } + + previousLeftAuxControl = newValue + } + .onChange(of: musicAuxRightControl) { newValue in + if newValue == musicAuxLeftControl { + let fallback = MusicAuxiliaryControl.alternative( + excluding: newValue, + preferring: previousRightAuxControl + ) + if fallback != musicAuxLeftControl { + musicAuxLeftControl = fallback + } + } + + previousRightAuxControl = newValue + } + .onChange(of: showShuffleAndRepeat) { isEnabled in + if isEnabled { + ensureAuxControlsUnique() + } + } .navigationTitle("Media") } @@ -980,6 +1018,15 @@ struct Media: View { return MediaControllerType.allCases } } + + private func ensureAuxControlsUnique() { + guard showShuffleAndRepeat, musicAuxLeftControl == musicAuxRightControl else { return } + + let fallback = MusicAuxiliaryControl.alternative(excluding: musicAuxLeftControl) + if fallback != musicAuxRightControl { + musicAuxRightControl = fallback + } + } } struct CalendarSettings: View { diff --git a/DynamicIsland/models/Constants.swift b/DynamicIsland/models/Constants.swift index 33d96fd..55cf754 100644 --- a/DynamicIsland/models/Constants.swift +++ b/DynamicIsland/models/Constants.swift @@ -230,8 +230,15 @@ enum MusicAuxiliaryControl: String, CaseIterable, Identifiable, Defaults.Seriali } } - static func alternative(excluding control: MusicAuxiliaryControl) -> MusicAuxiliaryControl { - allCases.first { $0 != control } ?? .shuffle + static func alternative( + excluding control: MusicAuxiliaryControl, + preferring candidate: MusicAuxiliaryControl? = nil + ) -> MusicAuxiliaryControl { + if let candidate, candidate != control { + return candidate + } + + return allCases.first { $0 != control } ?? .shuffle } } @@ -596,12 +603,22 @@ extension Defaults.Keys { } static func migrateMusicAuxControls() { - guard Defaults[.didMigrateMusicAuxControls] == false else { return } + if Defaults[.didMigrateMusicAuxControls] == false { + if Defaults[.showMediaOutputControl] { + Defaults[.musicAuxRightControl] = .mediaOutput + } - if Defaults[.showMediaOutputControl] { - Defaults[.musicAuxRightControl] = .mediaOutput + Defaults[.didMigrateMusicAuxControls] = true } - Defaults[.didMigrateMusicAuxControls] = true + normalizeMusicAuxControls() + } + + private static func normalizeMusicAuxControls() { + guard Defaults[.musicAuxLeftControl] == Defaults[.musicAuxRightControl] else { return } + + let current = Defaults[.musicAuxLeftControl] + let fallback = MusicAuxiliaryControl.alternative(excluding: current) + Defaults[.musicAuxRightControl] = fallback } }