diff --git a/DynamicIsland/Localizable.xcstrings b/DynamicIsland/Localizable.xcstrings index d30c6da..0da0743 100644 --- a/DynamicIsland/Localizable.xcstrings +++ b/DynamicIsland/Localizable.xcstrings @@ -26248,6 +26248,9 @@ } } } + }, + "When disabled, the notch music player stays visible with placeholder metadata even when playback is inactive." : { + }, "When enabled, Atoll connects to Lunar's TCP socket and displays DDC brightness, contrast, and volume events using your selected HUD style above." : { diff --git a/DynamicIsland/components/Notch/NotchHomeView.swift b/DynamicIsland/components/Notch/NotchHomeView.swift index 7b3d0fa..fff6be9 100644 --- a/DynamicIsland/components/Notch/NotchHomeView.swift +++ b/DynamicIsland/components/Notch/NotchHomeView.swift @@ -36,8 +36,6 @@ struct MusicPlayerView: View { .padding(.all, 5) MusicControlsView() .frame(maxWidth: .infinity, alignment: .leading) - .drawingGroup() - .compositingGroup() } .frame(maxWidth: .infinity, alignment: .leading) } @@ -529,11 +527,12 @@ struct NotchHomeView: View { @ObservedObject private var extensionNotchExperienceManager = ExtensionNotchExperienceManager.shared @ObservedObject private var musicManager = MusicManager.shared @Default(.showStandardMediaControls) private var showStandardMediaControls + @Default(.autoHideInactiveNotchMediaPlayer) private var autoHideInactiveNotchMediaPlayer let albumArtNamespace: Namespace.ID /// Whether the music player should actively display (enabled AND has real content). private var shouldShowMusicPlayer: Bool { - showStandardMediaControls && musicManager.hasActiveSession + showStandardMediaControls && (!autoHideInactiveNotchMediaPlayer || musicManager.hasActiveSession) } var body: some View { diff --git a/DynamicIsland/components/Settings/SettingsView.swift b/DynamicIsland/components/Settings/SettingsView.swift index f974daf..8bd68cd 100644 --- a/DynamicIsland/components/Settings/SettingsView.swift +++ b/DynamicIsland/components/Settings/SettingsView.swift @@ -747,6 +747,7 @@ struct SettingsView: View { SettingsSearchEntry(tab: .media, title: "Skip buttons", keywords: ["skip", "controls", "±10"], highlightID: SettingsTab.media.highlightID(for: "Skip buttons")), SettingsSearchEntry(tab: .media, title: "Sneak Peek Style", keywords: ["sneak peek", "preview"], highlightID: SettingsTab.media.highlightID(for: "Sneak Peek Style")), SettingsSearchEntry(tab: .media, title: "Enable lyrics", keywords: ["lyrics", "song text"], highlightID: SettingsTab.media.highlightID(for: "Enable lyrics")), + SettingsSearchEntry(tab: .media, title: "Auto-hide inactive notch media player", keywords: ["auto hide", "inactive", "placeholder", "notch media"], highlightID: SettingsTab.media.highlightID(for: "Auto-hide inactive notch media player")), SettingsSearchEntry(tab: .media, title: "Show Change Media Output control", keywords: ["airplay", "route picker", "media output"], highlightID: SettingsTab.media.highlightID(for: "Show Change Media Output control")), SettingsSearchEntry(tab: .media, title: "Enable album art parallax", keywords: ["parallax", "lock screen", "album art"], highlightID: SettingsTab.media.highlightID(for: "Enable album art parallax")), SettingsSearchEntry(tab: .media, title: "Enable album art parallax effect", keywords: ["parallax", "parallax effect", "album art"], highlightID: SettingsTab.media.highlightID(for: "Enable album art parallax effect")), @@ -2397,6 +2398,7 @@ struct Media: View { @Default(.lockScreenGlassCustomizationMode) private var lockScreenGlassCustomizationMode @Default(.lockScreenMusicAlbumParallaxEnabled) private var lockScreenMusicAlbumParallaxEnabled @Default(.showStandardMediaControls) private var showStandardMediaControls + @Default(.autoHideInactiveNotchMediaPlayer) private var autoHideInactiveNotchMediaPlayer private func highlightID(_ title: String) -> String { SettingsTab.media.highlightID(for: title) @@ -2444,6 +2446,10 @@ struct Media: View { .disabled(enableMinimalisticUI) .settingsHighlight(id: highlightID("Show media controls in Dynamic Island")) + Defaults.Toggle("Auto-hide inactive notch media player", key: .autoHideInactiveNotchMediaPlayer) + .disabled(enableMinimalisticUI || !showStandardMediaControls) + .settingsHighlight(id: highlightID("Auto-hide inactive notch media player")) + if enableMinimalisticUI { Text("Disable Minimalistic UI to configure the standard notch media controls.") .font(.caption) @@ -2452,6 +2458,10 @@ struct Media: View { Text("Standard notch media controls are hidden. Re-enable the toggle above to restore them.") .font(.caption) .foregroundStyle(.secondary) + } else if !autoHideInactiveNotchMediaPlayer { + Text("When disabled, the notch music player stays visible with placeholder metadata even when playback is inactive.") + .font(.caption) + .foregroundStyle(.secondary) } } header: { Text("Dynamic Island Visibility") diff --git a/DynamicIsland/managers/MusicManager.swift b/DynamicIsland/managers/MusicManager.swift index c5edc0f..e1bfd36 100644 --- a/DynamicIsland/managers/MusicManager.swift +++ b/DynamicIsland/managers/MusicManager.swift @@ -630,15 +630,19 @@ class MusicManager: ObservableObject { func togglePlay() { guard let controller = activeController else { return } + let targetState = !isPlaying Task { await MainActor.run { - let newState = !isPlaying - pendingOptimisticPlayState = newState - applyPlayState(newState, animation: .smooth(duration: 0.18)) + pendingOptimisticPlayState = targetState + applyPlayState(targetState, animation: .smooth(duration: 0.18)) } - await controller.togglePlay() + if targetState { + await controller.play() + } else { + await controller.pause() + } } } diff --git a/DynamicIsland/models/Constants.swift b/DynamicIsland/models/Constants.swift index cef66c7..459e537 100644 --- a/DynamicIsland/models/Constants.swift +++ b/DynamicIsland/models/Constants.swift @@ -774,6 +774,7 @@ extension Defaults.Keys { static let musicSkipBehavior = Key("musicSkipBehavior", default: .track) static let musicControlWindowEnabled = Key("musicControlWindowEnabled", default: false) static let showStandardMediaControls = Key("showStandardMediaControls", default: true) + static let autoHideInactiveNotchMediaPlayer = Key("autoHideInactiveNotchMediaPlayer", default: true) static let cachedMusicLiveActivityPreference = Key("cachedMusicLiveActivityPreference", default: nil) static let cachedLockScreenMediaWidgetPreference = Key("cachedLockScreenMediaWidgetPreference", default: nil) static let cachedMusicControlWindowPreference = Key("cachedMusicControlWindowPreference", default: nil)