Merge pull request #275 from Ebullioscopic/ui/fixes

Fixes and issue resolving
This commit is contained in:
Hariharan Mudaliar 2026-01-29 19:34:34 +05:30 • committed by GitHub
commit bb9b61192c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
274 changed files with 5691 additions and 1531 deletions

8
COPYRIGHT_ASSETS Normal file
View file

@ -0,0 +1,8 @@
Atoll (DynamicIsland) - Assets Copyright
Unless otherwise noted, the original assets created specifically for Atoll
(DynamicIsland) are Copyright (C) 2024-2026 Atoll Contributors.
This includes original media, artwork, animations, and other creative assets
unique to Atoll. Third-party assets retain their original licenses and
copyrights; see NOTICE and any THIRD_PARTY_LICENSES files for details.

View file

@ -1,11 +1,24 @@
// /*
// ContentView.swift * Atoll (DynamicIsland)
// DynamicIslandApp * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 02/08/24 * Originally from boring.notch project
// Modified by Richard Kunkli on 24/08/2024. * Modified and adapted for Atoll (DynamicIsland)
// Modified by A Akhil on 13/01/2026. * See NOTICE for details.
// *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AVFoundation import AVFoundation
import Combine import Combine
@ -66,6 +79,7 @@ struct ContentView: View {
@Default(.enableScreenRecordingDetection) var enableScreenRecordingDetection @Default(.enableScreenRecordingDetection) var enableScreenRecordingDetection
@Default(.enableCapsLockIndicator) var enableCapsLockIndicator @Default(.enableCapsLockIndicator) var enableCapsLockIndicator
@Default(.enableExtensionLiveActivities) var enableExtensionLiveActivities @Default(.enableExtensionLiveActivities) var enableExtensionLiveActivities
@Default(.showStandardMediaControls) var showStandardMediaControls
// Dynamic sizing based on view type and graph count with smooth transitions // Dynamic sizing based on view type and graph count with smooth transitions
var dynamicNotchSize: CGSize { var dynamicNotchSize: CGSize {
@ -161,16 +175,21 @@ struct ContentView: View {
enqueueMusicControlWindowSync(forceRefresh: forceRefresh, delay: delay) enqueueMusicControlWindowSync(forceRefresh: forceRefresh, delay: delay)
} }
private var dynamicNotchResizeAnimation: Animation? { private var dynamicNotchResizeAnimation: Animation? {
if enableMinimalisticUI && reminderManager.activeWindowReminders.isEmpty == false { nil
return nil
}
return .easeInOut(duration: 0.4)
} }
private let zeroHeightHoverPadding: CGFloat = 10 private let zeroHeightHoverPadding: CGFloat = 10
private let statsAdditionalRowHeight: CGFloat = 110 private let statsAdditionalRowHeight: CGFloat = 110
private let musicControlPauseGrace: TimeInterval = 5 private let musicControlPauseGrace: TimeInterval = 5
private let musicControlResumeDelay: TimeInterval = 0.24 private let musicControlResumeDelay: TimeInterval = 0.24
private var standardMediaControlsActive: Bool {
showStandardMediaControls && !enableMinimalisticUI
}
private var closedMusicContentEnabled: Bool {
enableMinimalisticUI || showStandardMediaControls
}
// Use minimalistic corner radius ONLY when opened, keep normal when closed // Use minimalistic corner radius ONLY when opened, keep normal when closed
private var activeCornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) { private var activeCornerRadiusInsets: (opened: (top: CGFloat, bottom: CGFloat), closed: (top: CGFloat, bottom: CGFloat)) {
@ -197,14 +216,27 @@ struct ContentView: View {
var body: some View { var body: some View {
let interactionsEnabled = !lockScreenManager.isLocked let interactionsEnabled = !lockScreenManager.isLocked
let notchHorizontalPadding: CGFloat = {
guard vm.notchState == .open else {
return activeCornerRadiusInsets.closed.bottom
}
if Defaults[.cornerRadiusScaling] {
return activeCornerRadiusInsets.opened.top - 5
}
return activeCornerRadiusInsets.opened.bottom - 5
}()
let hoverAreaPadding: CGFloat = {
if vm.notchState == .open && Defaults[.extendHoverArea] {
return 0
}
return vm.effectiveClosedNotchHeight == 0 ? zeroHeightHoverPadding : 0
}()
let notchBottomPadding = currentShadowPadding + hoverAreaPadding
ZStack(alignment: .top) { ZStack(alignment: .top) {
let mainLayout = NotchLayout() let mainLayout = NotchLayout()
.frame(alignment: .top) .frame(alignment: .top)
.padding(.horizontal, vm.notchState == .open .padding(.horizontal, notchHorizontalPadding)
? Defaults[.cornerRadiusScaling] ? (activeCornerRadiusInsets.opened.top - 5) : (activeCornerRadiusInsets.opened.bottom - 5)
: activeCornerRadiusInsets.closed.bottom
)
.padding([.horizontal, .bottom], vm.notchState == .open ? 12 : 0) .padding([.horizontal, .bottom], vm.notchState == .open ? 12 : 0)
.background(.black) .background(.black)
.clipShape(currentNotchShape) .clipShape(currentNotchShape)
@ -215,23 +247,15 @@ struct ContentView: View {
: .clear, : .clear,
radius: Defaults[.cornerRadiusScaling] ? 10 : 5 radius: Defaults[.cornerRadiusScaling] ? 10 : 5
) )
.padding(.bottom, .padding(.bottom, notchBottomPadding)
currentShadowPadding + (
vm.notchState == .open && Defaults[.extendHoverArea]
? 0
: (vm.effectiveClosedNotchHeight == 0 ? zeroHeightHoverPadding : 0)
)
)
mainLayout mainLayout
.conditionalModifier(!useModernCloseAnimation) { view in .conditionalModifier(!useModernCloseAnimation) { view in
let hoverAnimation = Animation.bouncy.speed(1.2) let hoverAnimation = Animation.bouncy.speed(1.2)
let notchStateAnimation = Animation.spring.speed(1.2) let notchStateAnimation = Animation.spring.speed(1.2)
let viewTransitionAnimation = Animation.easeInOut(duration: 0.4)
return view return view
.animation(hoverAnimation, value: isHovering) .animation(hoverAnimation, value: isHovering)
.animation(notchStateAnimation, value: vm.notchState) .animation(notchStateAnimation, value: vm.notchState)
.animation(viewTransitionAnimation, value: coordinator.currentView)
.animation(.smooth, value: gestureProgress) .animation(.smooth, value: gestureProgress)
.transition(.blurReplace.animation(.interactiveSpring(dampingFraction: 1.2))) .transition(.blurReplace.animation(.interactiveSpring(dampingFraction: 1.2)))
} }
@ -239,12 +263,10 @@ struct ContentView: View {
let hoverAnimation = Animation.bouncy.speed(1.2) let hoverAnimation = Animation.bouncy.speed(1.2)
let openAnimation = Animation.spring(response: 0.42, dampingFraction: 0.8, blendDuration: 0) let openAnimation = Animation.spring(response: 0.42, dampingFraction: 0.8, blendDuration: 0)
let closeAnimation = Animation.spring(response: 0.45, dampingFraction: 1.0, blendDuration: 0) let closeAnimation = Animation.spring(response: 0.45, dampingFraction: 1.0, blendDuration: 0)
let viewTransitionAnimation = Animation.easeInOut(duration: 0.4)
let notchAnimation = vm.notchState == .open ? openAnimation : closeAnimation let notchAnimation = vm.notchState == .open ? openAnimation : closeAnimation
return view return view
.animation(hoverAnimation, value: isHovering) .animation(hoverAnimation, value: isHovering)
.animation(notchAnimation, value: vm.notchState) .animation(notchAnimation, value: vm.notchState)
.animation(viewTransitionAnimation, value: coordinator.currentView)
.animation(.smooth, value: gestureProgress) .animation(.smooth, value: gestureProgress)
} }
.conditionalModifier(interactionsEnabled) { view in .conditionalModifier(interactionsEnabled) { view in
@ -373,13 +395,10 @@ struct ContentView: View {
maxHeight: dynamicNotchSize.height + currentShadowPadding, maxHeight: dynamicNotchSize.height + currentShadowPadding,
alignment: .top alignment: .top
) )
.animation(dynamicNotchResizeAnimation, value: dynamicNotchSize)
.animation(.easeInOut(duration: 0.4), value: coordinator.currentView)
.environmentObject(privacyManager) .environmentObject(privacyManager)
.onChange(of: dynamicNotchSize) { oldSize, newSize in .onChange(of: dynamicNotchSize) { oldSize, newSize in
guard oldSize != newSize else { return } guard oldSize != newSize else { return }
let delay: TimeInterval = dynamicNotchResizeAnimation == nil ? 0.25 : 1.0 runAfter(0.1) {
runAfter(delay) {
vm.shouldRecheckHover.toggle() vm.shouldRecheckHover.toggle()
} }
} }
@ -449,6 +468,12 @@ struct ContentView: View {
enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05) enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05)
} }
} }
.onChange(of: showStandardMediaControls) { _, _ in
handleStandardMediaControlsAvailabilityChange()
}
.onChange(of: enableMinimalisticUI) { _, _ in
handleStandardMediaControlsAvailabilityChange()
}
.onChange(of: gestureProgress) { _, _ in .onChange(of: gestureProgress) { _, _ in
if shouldShowMusicControlWindow() { if shouldShowMusicControlWindow() {
enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05) enqueueMusicControlWindowSync(forceRefresh: true, delay: 0.05)
@ -506,6 +531,7 @@ struct ContentView: View {
let musicPairingEligible = vm.notchState == .closed let musicPairingEligible = vm.notchState == .closed
&& hasActiveMusicSnapshot && hasActiveMusicSnapshot
&& coordinator.musicLiveActivityEnabled && coordinator.musicLiveActivityEnabled
&& closedMusicContentEnabled
&& !vm.hideOnClosed && !vm.hideOnClosed
&& !lockScreenManager.isLocked && !lockScreenManager.isLocked
let musicSecondary = resolveMusicSecondaryLiveActivity(isMusicPairingEligible: musicPairingEligible) let musicSecondary = resolveMusicSecondaryLiveActivity(isMusicPairingEligible: musicPairingEligible)
@ -722,14 +748,9 @@ struct ContentView: View {
} }
} }
} }
.transition(.asymmetric(
insertion: .scale(scale: 0.8).combined(with: .opacity).animation(.easeInOut(duration: 0.4)),
removal: .scale(scale: 0.8).combined(with: .opacity).animation(.easeInOut(duration: 0.4))
))
.id(coordinator.currentView) // Force SwiftUI to treat each view as unique .id(coordinator.currentView) // Force SwiftUI to treat each view as unique
} }
} }
.animation(.easeInOut(duration: 0.4), value: coordinator.currentView)
.zIndex(1) .zIndex(1)
.allowsHitTesting(vm.notchState == .open) .allowsHitTesting(vm.notchState == .open)
.blur(radius: abs(gestureProgress) > 0.3 ? min(abs(gestureProgress), 8) : 0) .blur(radius: abs(gestureProgress) > 0.3 ? min(abs(gestureProgress), 8) : 0)
@ -1035,16 +1056,11 @@ struct ContentView: View {
.font(.system(size: badgeSize * 0.5, weight: .semibold)) .font(.system(size: badgeSize * 0.5, weight: .semibold))
.foregroundStyle(capsLockTintMode.color) .foregroundStyle(capsLockTintMode.color)
case .extensionPayload(let payload): case .extensionPayload(let payload):
ExtensionCompositeIconView( ExtensionBadgeIconView(
leading: payload.descriptor.leadingIcon, descriptor: payload.descriptor.leadingIcon,
badge: payload.descriptor.badgeIcon,
accent: payload.descriptor.accentColor.swiftUIColor, accent: payload.descriptor.accentColor.swiftUIColor,
size: badgeSize size: badgeSize
) )
.background(
Circle()
.fill(Color.black.opacity(0.85))
)
} }
} }
.frame(width: badgeSize, height: badgeSize) .frame(width: badgeSize, height: badgeSize)
@ -1058,8 +1074,6 @@ struct ContentView: View {
private func badgeDisplaySize(for secondary: MusicSecondaryLiveActivity?, baseSize: CGFloat) -> CGFloat { private func badgeDisplaySize(for secondary: MusicSecondaryLiveActivity?, baseSize: CGFloat) -> CGFloat {
guard let secondary else { return baseSize } guard let secondary else { return baseSize }
switch secondary { switch secondary {
case .extensionPayload:
return max(11, baseSize * 0.86)
default: default:
return baseSize return baseSize
} }
@ -1068,8 +1082,6 @@ struct ContentView: View {
private func badgeOverlayOffset(for secondary: MusicSecondaryLiveActivity?, badgeSize: CGFloat) -> CGSize { private func badgeOverlayOffset(for secondary: MusicSecondaryLiveActivity?, badgeSize: CGFloat) -> CGSize {
guard let secondary else { return CGSize(width: badgeSize * 0.2, height: badgeSize * 0.25) } guard let secondary else { return CGSize(width: badgeSize * 0.2, height: badgeSize * 0.25) }
switch secondary { switch secondary {
case .extensionPayload:
return CGSize(width: badgeSize * 0.14, height: badgeSize * 0.12)
default: default:
return CGSize(width: badgeSize * 0.2, height: badgeSize * 0.25) return CGSize(width: badgeSize * 0.2, height: badgeSize * 0.25)
} }
@ -1181,6 +1193,15 @@ struct ContentView: View {
return nil return nil
} }
guard closedMusicContentEnabled else {
ExtensionRoutingDiagnostics.shared.logSuppression(
.music,
reason: "music content disabled",
pendingCount: candidates.count
)
return nil
}
guard vm.notchState == .closed else { guard vm.notchState == .closed else {
ExtensionRoutingDiagnostics.shared.logSuppression( ExtensionRoutingDiagnostics.shared.logSuppression(
.music, .music,
@ -1706,6 +1727,26 @@ struct ContentView: View {
} }
} }
private func handleStandardMediaControlsAvailabilityChange() {
guard musicControlWindowEnabled else {
hideMusicControlWindow()
return
}
if standardMediaControlsActive {
if musicManager.isPlaying || !musicManager.isPlayerIdle {
clearMusicControlVisibilityDeadline()
}
enqueueMusicControlWindowSync(forceRefresh: true)
} else {
cancelMusicControlWindowSync()
hideMusicControlWindow()
clearMusicControlVisibilityDeadline()
hasPendingMusicControlSync = false
pendingMusicControlForceRefresh = false
}
}
private func extendMusicControlVisibilityAfterPause() { private func extendMusicControlVisibilityAfterPause() {
let deadline = Date().addingTimeInterval(musicControlPauseGrace) let deadline = Date().addingTimeInterval(musicControlPauseGrace)
musicControlVisibilityDeadline = deadline musicControlVisibilityDeadline = deadline
@ -1817,6 +1858,7 @@ struct ContentView: View {
private func shouldShowMusicControlWindow() -> Bool { private func shouldShowMusicControlWindow() -> Bool {
guard musicControlWindowEnabled, guard musicControlWindowEnabled,
coordinator.musicLiveActivityEnabled, coordinator.musicLiveActivityEnabled,
standardMediaControlsActive,
vm.notchState == .closed, vm.notchState == .closed,
!vm.hideOnClosed, !vm.hideOnClosed,
!lockScreenManager.isLocked, !lockScreenManager.isLocked,

View file

@ -1,9 +1,20 @@
// /*
// DynamicIslandApp.swift * Atoll (DynamicIsland)
// DynamicIslandApp * Copyright (C) 2024-2026 Atoll Contributors
// *
// Modified by Hariharan Mudaliar on 20/09/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AVFoundation import AVFoundation
import Combine import Combine
@ -90,6 +101,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let idleAnimationManager = IdleAnimationManager.shared // NEW: Custom idle animations let idleAnimationManager = IdleAnimationManager.shared // NEW: Custom idle animations
let downloadManager = DownloadManager.shared // NEW: Chromium downloads detection let downloadManager = DownloadManager.shared // NEW: Chromium downloads detection
let lockScreenPanelManager = LockScreenPanelManager.shared // NEW: Lock screen music panel let lockScreenPanelManager = LockScreenPanelManager.shared // NEW: Lock screen music panel
let mediaControlsStateCoordinator = MediaControlsStateCoordinator.shared
let systemTimerBridge = SystemTimerBridge.shared let systemTimerBridge = SystemTimerBridge.shared
let extensionXPCServiceHost = ExtensionXPCServiceHost.shared let extensionXPCServiceHost = ExtensionXPCServiceHost.shared
var closeNotchWorkItem: DispatchWorkItem? var closeNotchWorkItem: DispatchWorkItem?
@ -208,6 +220,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
backing: .buffered, backing: .buffered,
defer: false defer: false
) )
window.animationBehavior = .none
window.contentView = NSHostingView( window.contentView = NSHostingView(
rootView: ContentView() rootView: ContentView()
@ -252,6 +266,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let animateResize = shouldAnimateResize(for: requiredSize) let animateResize = shouldAnimateResize(for: requiredSize)
resizeWindows(to: requiredSize, animated: animateResize, force: false) resizeWindows(to: requiredSize, animated: animateResize, force: false)
} }
private func updateWindowSizeForTabSwitch() {
let requiredSize = calculateRequiredNotchSize()
resizeWindows(to: requiredSize, animated: false, force: true)
}
private func calculateRequiredNotchSize() -> CGSize { private func calculateRequiredNotchSize() -> CGSize {
// Check if inline sneak peek is showing and notch is closed // Check if inline sneak peek is showing and notch is closed
@ -320,16 +339,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
let newY = screenFrame.origin.y + screenFrame.height - size.height let newY = screenFrame.origin.y + screenFrame.height - size.height
let targetFrame = NSRect(x: newX, y: newY, width: size.width, height: size.height) let targetFrame = NSRect(x: newX, y: newY, width: size.width, height: size.height)
if animated { window.setFrame(targetFrame, display: true)
NSAnimationContext.runAnimationGroup { context in
context.duration = 0.25
context.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
context.allowsImplicitAnimation = true
window.animator().setFrame(targetFrame, display: true)
}
} else {
window.setFrame(targetFrame, display: true)
}
} }
private func shouldAnimateResize(for newSize: CGSize) -> Bool { private func shouldAnimateResize(for newSize: CGSize) -> Bool {
@ -352,6 +362,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Initialize idle animations (load bundled + built-in face) // Initialize idle animations (load bundled + built-in face)
idleAnimationManager.initializeDefaultAnimations() idleAnimationManager.initializeDefaultAnimations()
applySelectedAppIcon()
// Setup SystemHUD Manager // Setup SystemHUD Manager
SystemHUDManager.shared.setup(coordinator: coordinator) SystemHUDManager.shared.setup(coordinator: coordinator)
@ -369,9 +381,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Setup Privacy Indicator Manager (camera and microphone monitoring) // Setup Privacy Indicator Manager (camera and microphone monitoring)
PrivacyIndicatorManager.shared.startMonitoring() PrivacyIndicatorManager.shared.startMonitoring()
// Observe tab changes - use immediate updates to prevent clipping // Observe tab changes - use immediate resize to keep the notch pinned
coordinator.$currentView.sink { [weak self] newView in coordinator.$currentView.sink { [weak self] _ in
self?.updateWindowSizeIfNeeded() self?.updateWindowSizeForTabSwitch()
}.store(in: &cancellables) }.store(in: &cancellables)
coordinator.$notesLayoutState coordinator.$notesLayoutState
@ -889,3 +901,98 @@ extension CGRect: @retroactive Hashable {
return lhs.origin == rhs.origin && lhs.size == rhs.size return lhs.origin == rhs.origin && lhs.size == rhs.size
} }
} }
@MainActor
final class MediaControlsStateCoordinator {
static let shared = MediaControlsStateCoordinator()
private var cancellables = Set<AnyCancellable>()
private init() {
let masterPublisher = Defaults.publisher(.showStandardMediaControls)
let minimalisticPublisher = Defaults.publisher(.enableMinimalisticUI)
Publishers.CombineLatest(masterPublisher, minimalisticPublisher)
.receive(on: RunLoop.main)
.sink { [weak self] masterChange, minimalisticChange in
self?.handleStateChange(
showStandard: masterChange.newValue,
minimalistic: minimalisticChange.newValue
)
}
.store(in: &cancellables)
}
private func handleStateChange(showStandard: Bool, minimalistic: Bool) {
if !showStandard && !minimalistic {
cacheAndDisableMusicLiveActivity()
} else {
restoreMusicLiveActivity(clearCache: showStandard)
}
if showStandard {
restoreLockScreenPanelIfNeeded()
restoreMusicControlWindowIfNeeded()
} else {
cacheAndDisableLockScreenPanel()
cacheAndDisableMusicControlWindow()
}
}
private func cacheAndDisableMusicLiveActivity() {
if Defaults[.cachedMusicLiveActivityPreference] == nil {
Defaults[.cachedMusicLiveActivityPreference] = DynamicIslandViewCoordinator.shared.musicLiveActivityEnabled
}
if DynamicIslandViewCoordinator.shared.musicLiveActivityEnabled {
DynamicIslandViewCoordinator.shared.musicLiveActivityEnabled = false
}
}
private func restoreMusicLiveActivity(clearCache: Bool) {
guard let cached = Defaults[.cachedMusicLiveActivityPreference] else { return }
if DynamicIslandViewCoordinator.shared.musicLiveActivityEnabled != cached {
DynamicIslandViewCoordinator.shared.musicLiveActivityEnabled = cached
}
if clearCache {
Defaults[.cachedMusicLiveActivityPreference] = nil
}
}
private func cacheAndDisableLockScreenPanel() {
if Defaults[.cachedLockScreenMediaWidgetPreference] == nil {
Defaults[.cachedLockScreenMediaWidgetPreference] = Defaults[.enableLockScreenMediaWidget]
}
if Defaults[.enableLockScreenMediaWidget] {
Defaults[.enableLockScreenMediaWidget] = false
LockScreenPanelManager.shared.hidePanel()
}
}
private func restoreLockScreenPanelIfNeeded() {
guard let cached = Defaults[.cachedLockScreenMediaWidgetPreference] else { return }
Defaults[.enableLockScreenMediaWidget] = cached
Defaults[.cachedLockScreenMediaWidgetPreference] = nil
}
private func cacheAndDisableMusicControlWindow() {
if Defaults[.cachedMusicControlWindowPreference] == nil {
Defaults[.cachedMusicControlWindowPreference] = Defaults[.musicControlWindowEnabled]
}
if Defaults[.musicControlWindowEnabled] {
Defaults[.musicControlWindowEnabled] = false
}
MusicControlWindowManager.shared.hide()
}
private func restoreMusicControlWindowIfNeeded() {
guard let cached = Defaults[.cachedMusicControlWindowPreference] else { return }
Defaults[.musicControlWindowEnabled] = cached
Defaults[.cachedMusicControlWindowPreference] = nil
}
}

View file

@ -1,9 +1,20 @@
// /*
// DynamicIslandViewCoordinator.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2024-11-20. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Combine import Combine
import Defaults import Defaults
@ -102,9 +113,6 @@ class DynamicIslandViewCoordinator: ObservableObject {
} }
@Published var statsSecondRowExpansion: CGFloat = 1 @Published var statsSecondRowExpansion: CGFloat = 1
private var statsSecondRowWorkItem: DispatchWorkItem?
private let statsSecondRowRevealDelay: TimeInterval = 0.5
private let statsSecondRowAnimationDuration: TimeInterval = 0.3
@Published var notesLayoutState: NotesLayoutState = .list @Published var notesLayoutState: NotesLayoutState = .list
@Published var selectedExtensionExperienceID: String? @Published var selectedExtensionExperienceID: String?
@ -206,22 +214,8 @@ class DynamicIslandViewCoordinator: ObservableObject {
private func handleStatsTabTransition(from oldValue: NotchViews, to newValue: NotchViews) { private func handleStatsTabTransition(from oldValue: NotchViews, to newValue: NotchViews) {
guard oldValue != newValue else { return } guard oldValue != newValue else { return }
statsSecondRowWorkItem?.cancel()
if newValue == .stats && Defaults[.enableStatsFeature] { if newValue == .stats && Defaults[.enableStatsFeature] {
statsSecondRowExpansion = 0 statsSecondRowExpansion = 1
let workItem = DispatchWorkItem { [weak self] in
guard let self else { return }
withAnimation(.easeInOut(duration: self.statsSecondRowAnimationDuration)) {
self.statsSecondRowExpansion = 1
}
self.statsSecondRowWorkItem = nil
}
statsSecondRowWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + statsSecondRowRevealDelay, execute: workItem)
} else {
withAnimation(.easeInOut(duration: 0.2)) {
statsSecondRowExpansion = 0
}
} }
} }

View file

@ -2061,6 +2061,9 @@
} }
} }
} }
},
"Add icon" : {
}, },
"Add manually" : { "Add manually" : {
"extractionState" : "stale", "extractionState" : "stale",
@ -7070,6 +7073,9 @@
} }
} }
} }
},
"Disable Minimalistic UI to configure the standard notch media controls." : {
}, },
"Disabled" : { "Disabled" : {
"localizations" : { "localizations" : {
@ -7500,6 +7506,9 @@
"Drag the previews to adjust vertical placement. Positive values lift the panel; negative values lower it. Use the width sliders below to narrow the media and timer widgets without exceeding their default size. Changes apply instantly while the widgets are visible." : { "Drag the previews to adjust vertical placement. Positive values lift the panel; negative values lower it. Use the width sliders below to narrow the media and timer widgets without exceeding their default size. Changes apply instantly while the widgets are visible." : {
"comment" : "A footer text describing the functionality of the lock screen positioning controls.", "comment" : "A footer text describing the functionality of the lock screen positioning controls.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
},
"Drop a PNG, JPEG, TIFF, or ICNS file to add it to your icon library." : {
}, },
"Drop files here" : { "Drop files here" : {
"localizations" : { "localizations" : {
@ -7604,6 +7613,9 @@
"Dynamic Island Progress Bars" : { "Dynamic Island Progress Bars" : {
"comment" : "A section header that lists the options for customizing the appearance of the progress bars displayed by Dynamic Island.", "comment" : "A section header that lists the options for customizing the appearance of the progress bars displayed by Dynamic Island.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
},
"Dynamic Island Visibility" : {
}, },
"dynamic.island" : { "dynamic.island" : {
"localizations" : { "localizations" : {
@ -7990,6 +8002,9 @@
"Enable customizable controls" : { "Enable customizable controls" : {
"comment" : "A toggle that allows users to enable or disable customizable controls for media playback.", "comment" : "A toggle that allows users to enable or disable customizable controls for media playback.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
},
"Enable Dynamic Island media controls to manage the lock screen panel." : {
}, },
"Enable extensions to allow third-party apps to display live activities and lock screen widgets in Atoll." : { "Enable extensions to allow third-party apps to display live activities and lock screen widgets in Atoll." : {
"comment" : "A footer text that explains the purpose of enabling extensions.", "comment" : "A footer text that explains the purpose of enabling extensions.",
@ -16030,6 +16045,9 @@
}, },
"Remove from shelf after dragging" : { "Remove from shelf after dragging" : {
},
"Remove selected" : {
}, },
"Request Access" : { "Request Access" : {
"localizations" : { "localizations" : {
@ -18463,6 +18481,12 @@
} }
} }
} }
},
"Standard notch media controls are hidden while this toggle is off." : {
},
"Standard notch media controls are hidden. Re-enable the toggle above to restore them." : {
}, },
"Start" : { "Start" : {
"localizations" : { "localizations" : {

View file

@ -1,9 +1,24 @@
// /*
// AppleMusicController.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-03-29. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import Combine import Combine

View file

@ -1,9 +1,24 @@
// /*
// MediaControllerProtocol.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander Greco on 2025-03-29. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import AppKit import AppKit

View file

@ -1,9 +1,24 @@
// /*
// NowPlayingController.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-03-29. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import Combine import Combine

View file

@ -1,9 +1,24 @@
// /*
// SpotifyController.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-03-29. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import Combine import Combine

View file

@ -1,9 +1,24 @@
// /*
// YouTubeMusicAuthentication.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-09-14. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation

View file

@ -1,10 +1,24 @@
// /*
// YouTubeMusicController.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created By Alexander on 2025-03-30. * Originally from boring.notch project
// Modified by Pranav on 2025-06-16. * Modified and adapted for Atoll (DynamicIsland)
// * See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import Combine import Combine

View file

@ -1,9 +1,24 @@
// /*
// YouTubeMusicModels.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-09-14. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation

View file

@ -1,9 +1,24 @@
// /*
// YouTubeMusicNetworking.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-09-14. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation

View file

@ -1,11 +1,24 @@
// /*
// CalendarServiceProvider.swift * Atoll (DynamicIsland)
// Calendr * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Paker on 31/12/20. * Originally from boring.notch project
// Original source: Original source: https://github.com/pakerwreah/Calendr * Modified and adapted for Atoll (DynamicIsland)
// Modified by Alexander on 08/06/25 * See NOTICE for details.
// *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import EventKit import EventKit

View file

@ -1,9 +1,24 @@
// /*
// Constants.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 16/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import KeyboardShortcuts import KeyboardShortcuts
import SwiftUI import SwiftUI

View file

@ -1,13 +1,24 @@
// /*
// HelloAnimation.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 04/08/24. * Originally from boring.notch project
// HelloAnimation.swift * Modified and adapted for Atoll (DynamicIsland)
// DynamicIsland * See NOTICE for details.
// *
// Created by Harsh Vardhan Goswami on 08/08/24. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// drop.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 04/08/24. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import SwiftUI import SwiftUI

View file

@ -1,8 +1,24 @@
// /*
// AnimatedFace.swift * Atoll (DynamicIsland)
// * Copyright (C) 2024-2026 Atoll Contributors
// Created by Harsh Vardhan Goswami on 04/08/24. *
// * Originally from boring.notch project
* Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,4 +1,24 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* Originally from boring.notch project
* Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// DynamicIslandCalendar.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 08/09/24. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// ReminderLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by GitHub Copilot on 2025-11-12. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// ClipboardPanel.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 12/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// ClipboardPopover.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 13/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// ClipboardShared.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 12/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// ClipboardWindow.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 12/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,20 @@
// /*
// ColorCodedProgressBar.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for color-coded battery and volume displays * This program is free software: you can redistribute it and/or modify
// Provides smooth gradient transitions from red to green (or reversed) * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// ColorPickedFeedbackView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 14/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// ColorPickerPanel.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 14/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Cocoa import Cocoa

View file

@ -1,9 +1,20 @@
// /*
// ColorPickerPopover.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 14/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,20 @@
// /*
// DownloadLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Shows a download indicator when Chromium-style downloads * This program is free software: you can redistribute it and/or modify
// are detected in the user's Downloads folder. * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
struct SpinningCircleDownloadView: View { struct SpinningCircleDownloadView: View {

View file

@ -1,13 +1,20 @@
// /*
// DynamicIslandSystemTiles.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 04/08/24. * This program is free software: you can redistribute it and/or modify
// DynamicIslandSystemTiles.swift * it under the terms of the GNU General Public License as published by
// DynamicIsland * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// Created by Harsh Vardhan Goswami on 16/08/24. *
// * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import SwiftUI import SwiftUI

View file

@ -1,8 +1,24 @@
// /*
// EmptyState.swift * Atoll (DynamicIsland)
// * Copyright (C) 2024-2026 Atoll Contributors
// Created by Harsh Vardhan Goswami on 04/08/24. *
// * Originally from boring.notch project
* Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults
import AtollExtensionKit import AtollExtensionKit

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults
import AtollExtensionKit import AtollExtensionKit

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import AppKit import AppKit
import AtollExtensionKit import AtollExtensionKit
@ -202,6 +220,63 @@ struct ExtensionCompositeIconView: View {
} }
} }
struct ExtensionBadgeIconView: View {
let descriptor: AtollIconDescriptor
let accent: Color
let size: CGFloat
private var symbolSize: CGFloat { size * 0.5 }
private var imageSize: CGFloat { size * 0.62 }
private var imageCornerRadius: CGFloat { size * 0.18 }
var body: some View {
Group {
switch descriptor {
case let .symbol(name, _, weight):
Image(systemName: name)
.font(.system(size: symbolSize, weight: weight.swiftUI))
.foregroundStyle(accent)
case let .image(data, _, _):
if let image = NSImage(data: data) {
Image(nsImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: imageSize, height: imageSize)
.clipShape(RoundedRectangle(cornerRadius: imageCornerRadius, style: .continuous))
} else {
fallbackSymbol
}
case let .appIcon(bundleIdentifier, _, _):
if let icon = AppIconAsNSImage(for: bundleIdentifier) {
Image(nsImage: icon)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: imageSize, height: imageSize)
.clipShape(RoundedRectangle(cornerRadius: imageCornerRadius, style: .continuous))
} else {
fallbackSymbol
}
case let .lottie(animationData, _):
ExtensionLottieView(data: animationData, size: CGSize(width: imageSize, height: imageSize))
case .none:
fallbackSymbol
}
}
.frame(width: size, height: size)
}
private var fallbackSymbol: some View {
Image(systemName: "app.dashed")
.font(.system(size: symbolSize, weight: .medium))
.foregroundStyle(accent)
.frame(width: imageSize, height: imageSize)
.background(
RoundedRectangle(cornerRadius: imageCornerRadius, style: .continuous)
.fill(accent.opacity(0.15))
)
}
}
// MARK: - Lottie Rendering // MARK: - Lottie Rendering
struct ExtensionLottieView: View { struct ExtensionLottieView: View {

View file

@ -1,10 +1,20 @@
// /*
// DoNotDisturbLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Renders the closed-notch Focus indicator with per-mode colours and * This program is free software: you can redistribute it and/or modify
// an icon-first layout that collapses gracefully when Focus ends. * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// HoverButton.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Kraigo on 04.09.2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,10 +1,20 @@
// /*
// IdleAnimationView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by AI Assistant on 11/10/2025. * This program is free software: you can redistribute it and/or modify
// Unified view for displaying idle animations (Lottie or built-in face) * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Lottie import Lottie

View file

@ -1,9 +1,24 @@
// /*
// DownloadView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 17/08/24. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import SwiftUI import SwiftUI

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// InlineHUDs.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 14/09/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// LiveActivityModifier.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 12/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// MarqueeTextView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 08/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// SystemEventIndicatorModifier.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 12/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// LockIconAnimationView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Shared animator and SwiftUI Lottie rendering for the lock/unlock sequence. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Lottie import Lottie

View file

@ -1 +1,18 @@
// Legacy placeholder file superseded by LockScreenLiveActivityOverlay.swift. /*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

View file

@ -1,9 +1,20 @@
// /*
// LockScreenLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for lock screen live activity * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
final class LockScreenLiveActivityOverlayModel: ObservableObject { final class LockScreenLiveActivityOverlayModel: ObservableObject {

View file

@ -1,9 +1,20 @@
// /*
// LockScreenMusicPanel.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for lock screen music panel with liquid glass effect * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
struct LockScreenReminderWidget: View { struct LockScreenReminderWidget: View {

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,20 @@
// /*
// MinimalisticMusicView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for minimalistic UI mode * This program is free software: you can redistribute it and/or modify
// A clean, focused music player for closed notch state * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// LiveStreamProgressIndicator.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Shared indicator used for live stream playback timelines. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// LottieAnimationView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 2024. 10. 29.. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Lottie import Lottie

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,25 @@
// /*
// MusicVisualizer.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 02/08/24. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import Cocoa import Cocoa
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// ClipboardHistoryPopover.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 17/07/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// DynamicIslandExtrasMenu.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 04/08/24. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// DynamicIslandHeader.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 04/08/24. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Defaults import Defaults
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// DynamicIslandWindow.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 06/08/24. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Cocoa import Cocoa

View file

@ -1,9 +1,20 @@
// /*
// MinimalisticMusicPlayerView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for minimalistic UI mode - Open state music player * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,20 @@
// /*
// NotchColorPickerView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Ebullioscopic on 14/08/25. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,24 @@
// /*
// NotchHomeView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Hugo Persson on 2024-08-18. * Originally from boring.notch project
// Modified by Harsh Vardhan Goswami & Richard Kunkli & Mustafa Ramadan * Modified and adapted for Atoll (DynamicIsland)
// * See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Combine import Combine
import Defaults import Defaults
@ -383,6 +397,7 @@ struct NotchHomeView: View {
@ObservedObject var batteryModel = BatteryStatusViewModel.shared @ObservedObject var batteryModel = BatteryStatusViewModel.shared
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared @ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@ObservedObject private var extensionNotchExperienceManager = ExtensionNotchExperienceManager.shared @ObservedObject private var extensionNotchExperienceManager = ExtensionNotchExperienceManager.shared
@Default(.showStandardMediaControls) private var showStandardMediaControls
let albumArtNamespace: Namespace.ID let albumArtNamespace: Namespace.ID
var body: some View { var body: some View {
@ -407,8 +422,10 @@ struct NotchHomeView: View {
} }
} else { } else {
// Normal mode: Show full music player with optional calendar and webcam // Normal mode: Show full music player with optional calendar and webcam
MusicPlayerView(albumArtNamespace: albumArtNamespace) if showStandardMediaControls {
.frame(maxWidth: .infinity, alignment: .leading) MusicPlayerView(albumArtNamespace: albumArtNamespace)
.frame(maxWidth: .infinity, alignment: .leading)
}
if Defaults[.showCalendar] { if Defaults[.showCalendar] {
CalendarView() CalendarView()

View file

@ -1,9 +1,20 @@
// /*
// NotchNotesView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Assistant * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,24 @@
// /*
// NotchShape.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Kai Azim on 2023-08-24. * Originally from boring.notch project
// Original source: https://github.com/MrKai77/DynamicNotchKit * Modified and adapted for Atoll (DynamicIsland)
// Modified by Alexander on 2025-05-18. * See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,3 +1,20 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// NotchStatsView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Adapted from boring.notch StatsView * This program is free software: you can redistribute it and/or modify
// Stats tab view for system performance monitoring with clickable process popovers * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults
@ -63,9 +74,6 @@ struct NotchStatsView: View {
@State private var isHoveringGPUPopover = false @State private var isHoveringGPUPopover = false
@State private var isHoveringNetworkPopover = false @State private var isHoveringNetworkPopover = false
@State private var isHoveringDiskPopover = false @State private var isHoveringDiskPopover = false
@State private var isResizingForStats = false
@State private var statsHoverGraceActive = false
@State private var statsHoverGraceWorkItem: DispatchWorkItem?
@EnvironmentObject var vm: DynamicIslandViewModel @EnvironmentObject var vm: DynamicIslandViewModel
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared @ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@ -149,8 +157,8 @@ struct NotchStatsView: View {
} }
} }
} else if graphCount == 4 { } else if graphCount == 4 {
// 4 graphs: second row scales from zero height on tab open // 4 graphs: two rows (2x2) without a collapsible expansion
VStack(spacing: 0) { VStack(spacing: statsGridSpacingHeight) {
LazyVGrid( LazyVGrid(
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2), columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2),
spacing: 12 spacing: 12
@ -159,26 +167,18 @@ struct NotchStatsView: View {
graphViewForIndex(index) graphViewForIndex(index)
} }
} }
LazyVGrid(
StatsCollapsibleRow( columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2),
expansion: coordinator.statsSecondRowExpansion, spacing: 12
height: statsSecondRowContentHeight + statsGridSpacingHeight
) { ) {
LazyVGrid( ForEach(2..<graphCount, id: \.self) { index in
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2), graphViewForIndex(index)
spacing: 12
) {
ForEach(2..<graphCount, id: \.self) { index in
graphViewForIndex(index)
}
} }
.padding(.top, statsGridSpacingHeight)
} }
} }
} else { } else {
// 5 graphs: First row 3 graphs, second row 2 graphs (half-width each) // 5 graphs: First row 3 graphs, second row 2 graphs (half-width each)
VStack(spacing: 0) { VStack(spacing: statsGridSpacingHeight) {
// First row: 3 graphs
LazyVGrid( LazyVGrid(
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 3), columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 3),
spacing: 8 spacing: 8
@ -187,20 +187,13 @@ struct NotchStatsView: View {
graphViewForIndex(index) graphViewForIndex(index)
} }
} }
// Second row: 2 graphs (half-width each) LazyVGrid(
StatsCollapsibleRow( columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2),
expansion: coordinator.statsSecondRowExpansion, spacing: 8
height: statsSecondRowContentHeight + statsGridSpacingHeight
) { ) {
LazyVGrid( ForEach(3..<graphCount, id: \.self) { index in
columns: Array(repeating: GridItem(.flexible(), spacing: 8), count: 2), graphViewForIndex(index)
spacing: 8
) {
ForEach(3..<graphCount, id: \.self) { index in
graphViewForIndex(index)
}
} }
.padding(.top, statsGridSpacingHeight)
} }
} }
} }
@ -382,68 +375,26 @@ struct NotchStatsView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear { .onAppear {
// Note: Smart monitoring will handle starting/stopping based on notch state and current view // Note: Smart monitoring will handle starting/stopping based on notch state and current view
// Protect against hover interference during view transition
isResizingForStats = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
isResizingForStats = false
}
} }
.onDisappear { .onDisappear {
statsHoverGraceWorkItem?.cancel()
statsHoverGraceWorkItem = nil
if statsHoverGraceActive {
statsHoverGraceActive = false
}
// Keep monitoring running when tab is not visible // Keep monitoring running when tab is not visible
updateStatsPopoverState() updateStatsPopoverState()
} }
.animation(.easeInOut(duration: 0.4), value: enableStatsFeature) .animation(.easeInOut(duration: 0.4), value: enableStatsFeature)
.animation(.easeInOut(duration: 0.4), value: availableGraphs.count) .animation(.easeInOut(duration: 0.4), value: availableGraphs.count)
.onChange(of: availableGraphs.count) { _, _ in
// Protect against hover interference during dynamic sizing
isResizingForStats = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
isResizingForStats = false
}
}
.onChange(of: showingCPUPopover) { _, newValue in .onChange(of: showingCPUPopover) { _, newValue in
if newValue {
activateStatsHoverGrace()
} else {
deactivateStatsHoverGrace()
}
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: showingMemoryPopover) { _, newValue in .onChange(of: showingMemoryPopover) { _, newValue in
if newValue {
activateStatsHoverGrace()
} else {
deactivateStatsHoverGrace()
}
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: showingGPUPopover) { _, newValue in .onChange(of: showingGPUPopover) { _, newValue in
if newValue {
activateStatsHoverGrace()
} else {
deactivateStatsHoverGrace()
}
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: showingNetworkPopover) { _, newValue in .onChange(of: showingNetworkPopover) { _, newValue in
if newValue {
activateStatsHoverGrace()
} else {
deactivateStatsHoverGrace()
}
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: showingDiskPopover) { _, newValue in .onChange(of: showingDiskPopover) { _, newValue in
if newValue {
activateStatsHoverGrace()
} else {
deactivateStatsHoverGrace()
}
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: isHoveringCPUPopover) { _, _ in .onChange(of: isHoveringCPUPopover) { _, _ in
@ -461,76 +412,10 @@ struct NotchStatsView: View {
.onChange(of: isHoveringDiskPopover) { _, _ in .onChange(of: isHoveringDiskPopover) { _, _ in
updateStatsPopoverState() updateStatsPopoverState()
} }
.onChange(of: coordinator.statsSecondRowExpansion) { _, newValue in
let shouldHold = availableGraphs.count >= 4 && newValue < 0.999
if shouldHold {
isResizingForStats = true
} else {
DispatchQueue.main.async {
isResizingForStats = false
}
}
}
} }
private struct StatsCollapsibleRow<Content: View>: View {
let expansion: CGFloat
let height: CGFloat
let content: () -> Content
private let minVisibleHeight: CGFloat = 0.5
init(expansion: CGFloat, height: CGFloat, @ViewBuilder content: @escaping () -> Content) {
self.expansion = expansion
self.height = height
self.content = content
}
var body: some View {
let clamped = max(0, min(expansion, 1))
let targetHeight = clamped == 0 ? 0 : max(height * clamped, minVisibleHeight)
return Group {
if targetHeight == 0 {
Color.clear.frame(height: 0)
} else {
content()
.frame(height: height, alignment: .top)
.clipped()
.mask(
Rectangle()
.frame(height: targetHeight)
.frame(maxWidth: .infinity, alignment: .top)
)
.frame(height: targetHeight, alignment: .top)
}
}
.animation(.easeInOut(duration: 0.3), value: clamped)
}
}
private func activateStatsHoverGrace(duration: TimeInterval = 0.45) {
statsHoverGraceWorkItem?.cancel()
statsHoverGraceActive = true
let workItem = DispatchWorkItem {
statsHoverGraceActive = false
statsHoverGraceWorkItem = nil
updateStatsPopoverState()
}
statsHoverGraceWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: workItem)
}
private func deactivateStatsHoverGrace() {
statsHoverGraceWorkItem?.cancel()
statsHoverGraceWorkItem = nil
if statsHoverGraceActive {
statsHoverGraceActive = false
}
}
private func updateStatsPopoverState() { private func updateStatsPopoverState() {
let anyPopoverOpen = showingCPUPopover || showingMemoryPopover || showingGPUPopover || showingNetworkPopover || showingDiskPopover let anyPopoverOpen = showingCPUPopover || showingMemoryPopover || showingGPUPopover || showingNetworkPopover || showingDiskPopover
let newState = anyPopoverOpen || isResizingForStats || statsHoverGraceActive let newState = anyPopoverOpen
if vm.isStatsPopoverActive != newState { if vm.isStatsPopoverActive != newState {
vm.isStatsPopoverActive = newState vm.isStatsPopoverActive = newState
#if DEBUG #if DEBUG
@ -540,8 +425,6 @@ private struct StatsCollapsibleRow<Content: View>: View {
print(" GPU open=\(showingGPUPopover)") print(" GPU open=\(showingGPUPopover)")
print(" Network open=\(showingNetworkPopover)") print(" Network open=\(showingNetworkPopover)")
print(" Disk open=\(showingDiskPopover)") print(" Disk open=\(showingDiskPopover)")
print(" Resizing: \(isResizingForStats)")
print(" Hover grace: \(statsHoverGraceActive)")
#endif #endif
} }
} }

View file

@ -1,9 +1,20 @@
// /*
// NotchTimerView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Timer tab interface for the Atoll * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if os(macOS) #if os(macOS)
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if os(macOS) #if os(macOS)
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if os(macOS) #if os(macOS)
import SwiftUI import SwiftUI

View file

@ -1,3 +1,21 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if os(macOS) #if os(macOS)
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// MusicControllerSelectionView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-06-23. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,24 @@
// /*
// OnboardingFinishView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-06-23. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// OnboardingView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-06-23. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import AVFoundation import AVFoundation

View file

@ -1,9 +1,24 @@
// /*
// PermissionsRequestView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-06-23. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// ProOnboarding.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 2024. 09. 26.. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import SwiftUIIntrospect import SwiftUIIntrospect

View file

@ -1,9 +1,20 @@
// /*
// ProfileSelectionView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created on 2025-10-05. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// SparkleView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 2024. 09. 26.. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import AppKit import AppKit

View file

@ -1,9 +1,24 @@
// /*
// WelcomeView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 2024. 09. 26.. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import SwiftUIIntrospect import SwiftUIIntrospect

View file

@ -1,9 +1,20 @@
// /*
// PrivacyLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for camera and microphone privacy indicators * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,20 @@
// /*
// PrivacyIndicatorIcon.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for privacy indicator feature * This program is free software: you can redistribute it and/or modify
// Visual component for camera and microphone privacy indicators * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// ProgressIndicator.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Harsh Vardhan Goswami on 11/08/24. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Foundation import Foundation
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// RecordingLiveActivity.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created for screen recording live activity * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,8 +1,20 @@
// /*
// ChatPanels.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Hariharan Mudaliar * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,8 +1,20 @@
// /*
// ModelSelectionPanel.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Hariharan Mudaliar * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,8 +1,20 @@
// /*
// ScreenAssistantPanel.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Hariharan Mudaliar * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,8 +1,20 @@
// /*
// ScreenshotSnippingTool.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Assistant based on ScreenshotApp-main research * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,10 +1,20 @@
// /*
// AnimationEditorView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by AI Assistant on 11/10/2025. * This program is free software: you can redistribute it and/or modify
// Editor for resizing, repositioning, and cropping Lottie animations * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import LottieUI import LottieUI

View file

@ -1,9 +1,24 @@
// /*
// EditPanelView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 12/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,9 +1,20 @@
// /*
// ExtensionsSettings.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created on 13/01/2026. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,10 +1,20 @@
// /*
// IdleAnimationsSettingsSection.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by AI Assistant on 11/10/2025. * This program is free software: you can redistribute it and/or modify
// Settings section for custom idle animations * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Defaults import Defaults

View file

@ -1,9 +1,24 @@
// /*
// ListItemPopover.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 15/09/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI

View file

@ -1,3 +1,25 @@
/*
* Atoll (DynamicIsland)
* Copyright (C) 2024-2026 Atoll Contributors
*
* Originally from boring.notch project
* Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Defaults import Defaults
import SwiftUI import SwiftUI
import UniformTypeIdentifiers import UniformTypeIdentifiers

View file

@ -1,9 +1,25 @@
// /*
// SettingsView.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 07/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import AVFoundation import AVFoundation
import Combine import Combine
@ -677,6 +693,7 @@ struct SettingsView: View {
SettingsSearchEntry(tab: .appearance, title: "Enable Dynamic mirror", keywords: ["mirror", "reflection"], highlightID: SettingsTab.appearance.highlightID(for: "Enable Dynamic mirror")), SettingsSearchEntry(tab: .appearance, title: "Enable Dynamic mirror", keywords: ["mirror", "reflection"], highlightID: SettingsTab.appearance.highlightID(for: "Enable Dynamic mirror")),
SettingsSearchEntry(tab: .appearance, title: "Mirror shape", keywords: ["mirror shape", "circle", "rectangle"], highlightID: SettingsTab.appearance.highlightID(for: "Mirror shape")), SettingsSearchEntry(tab: .appearance, title: "Mirror shape", keywords: ["mirror shape", "circle", "rectangle"], highlightID: SettingsTab.appearance.highlightID(for: "Mirror shape")),
SettingsSearchEntry(tab: .appearance, title: "Show cool face animation while inactivity", keywords: ["face animation", "idle"], highlightID: SettingsTab.appearance.highlightID(for: "Show cool face animation while inactivity")), SettingsSearchEntry(tab: .appearance, title: "Show cool face animation while inactivity", keywords: ["face animation", "idle"], highlightID: SettingsTab.appearance.highlightID(for: "Show cool face animation while inactivity")),
SettingsSearchEntry(tab: .appearance, title: "App icon", keywords: ["app icon", "custom icon"], highlightID: SettingsTab.appearance.highlightID(for: "App icon")),
// Lock Screen // Lock Screen
SettingsSearchEntry(tab: .lockScreen, title: "Enable lock screen live activity", keywords: ["lock screen", "live activity"], highlightID: SettingsTab.lockScreen.highlightID(for: "Enable lock screen live activity")), SettingsSearchEntry(tab: .lockScreen, title: "Enable lock screen live activity", keywords: ["lock screen", "live activity"], highlightID: SettingsTab.lockScreen.highlightID(for: "Enable lock screen live activity")),
@ -1964,11 +1981,16 @@ struct Media: View {
@Default(.lockScreenGlassStyle) private var lockScreenGlassStyle @Default(.lockScreenGlassStyle) private var lockScreenGlassStyle
@Default(.lockScreenGlassCustomizationMode) private var lockScreenGlassCustomizationMode @Default(.lockScreenGlassCustomizationMode) private var lockScreenGlassCustomizationMode
@Default(.lockScreenMusicAlbumParallaxEnabled) private var lockScreenMusicAlbumParallaxEnabled @Default(.lockScreenMusicAlbumParallaxEnabled) private var lockScreenMusicAlbumParallaxEnabled
@Default(.showStandardMediaControls) private var showStandardMediaControls
private func highlightID(_ title: String) -> String { private func highlightID(_ title: String) -> String {
SettingsTab.media.highlightID(for: title) SettingsTab.media.highlightID(for: title)
} }
private var standardControlsSuppressed: Bool {
!showStandardMediaControls && !enableMinimalisticUI
}
var body: some View { var body: some View {
Form { Form {
Section { Section {
@ -2002,6 +2024,23 @@ struct Media: View {
.font(.caption) .font(.caption)
} }
} }
Section {
Defaults.Toggle("Show media controls in Dynamic Island", key: .showStandardMediaControls)
.disabled(enableMinimalisticUI)
.settingsHighlight(id: highlightID("Show media controls in Dynamic Island"))
if enableMinimalisticUI {
Text("Disable Minimalistic UI to configure the standard notch media controls.")
.font(.caption)
.foregroundStyle(.secondary)
} else if standardControlsSuppressed {
Text("Standard notch media controls are hidden. Re-enable the toggle above to restore them.")
.font(.caption)
.foregroundStyle(.secondary)
}
} header: {
Text("Dynamic Island Visibility")
}
Section { Section {
Defaults.Toggle(key: .showShuffleAndRepeat) { Defaults.Toggle(key: .showShuffleAndRepeat) {
HStack { HStack {
@ -2053,11 +2092,13 @@ struct Media: View {
"Enable music live activity", "Enable music live activity",
isOn: $coordinator.musicLiveActivityEnabled.animation() isOn: $coordinator.musicLiveActivityEnabled.animation()
) )
.disabled(standardControlsSuppressed)
.help(standardControlsSuppressed ? "Standard notch media controls are hidden while this toggle is off." : "")
Defaults.Toggle( Defaults.Toggle(
"Show floating media controls", "Show floating media controls",
key: .musicControlWindowEnabled key: .musicControlWindowEnabled
) )
.disabled(!coordinator.musicLiveActivityEnabled) .disabled(!coordinator.musicLiveActivityEnabled || standardControlsSuppressed)
.help("Displays play/pause and skip buttons beside the notch while music is active. Disabled by default.") .help("Displays play/pause and skip buttons beside the notch while music is active. Disabled by default.")
Toggle("Enable sneak peek", isOn: $enableSneakPeek) Toggle("Enable sneak peek", isOn: $enableSneakPeek)
Toggle("Show sneak peek on playback changes", isOn: $showSneakPeekOnTrackChange) Toggle("Show sneak peek on playback changes", isOn: $showSneakPeekOnTrackChange)
@ -2124,6 +2165,8 @@ struct Media: View {
} footer: { } footer: {
Text("These controls mirror the Lock Screen tab so you can tune the media overlay while focusing on playback settings.") Text("These controls mirror the Lock Screen tab so you can tune the media overlay while focusing on playback settings.")
} }
.disabled(!showStandardMediaControls)
.opacity(showStandardMediaControls ? 1 : 0.5)
Picker(selection: $hideNotchOption, label: Picker(selection: $hideNotchOption, label:
HStack { HStack {
@ -2801,6 +2844,8 @@ struct Appearance: View {
@Default(.useMusicVisualizer) var useMusicVisualizer @Default(.useMusicVisualizer) var useMusicVisualizer
@Default(.customVisualizers) var customVisualizers @Default(.customVisualizers) var customVisualizers
@Default(.selectedVisualizer) var selectedVisualizer @Default(.selectedVisualizer) var selectedVisualizer
@Default(.customAppIcons) private var customAppIcons
@Default(.selectedAppIconID) private var selectedAppIconID
@Default(.openNotchWidth) var openNotchWidth @Default(.openNotchWidth) var openNotchWidth
@Default(.enableMinimalisticUI) var enableMinimalisticUI @Default(.enableMinimalisticUI) var enableMinimalisticUI
@Default(.lockScreenGlassCustomizationMode) private var lockScreenGlassCustomizationMode @Default(.lockScreenGlassCustomizationMode) private var lockScreenGlassCustomizationMode
@ -2812,10 +2857,12 @@ struct Appearance: View {
@Default(.lockScreenTimerWidgetUsesBlur) private var timerGlassModeIsGlass @Default(.lockScreenTimerWidgetUsesBlur) private var timerGlassModeIsGlass
@Default(.enableLockScreenMediaWidget) private var enableLockScreenMediaWidget @Default(.enableLockScreenMediaWidget) private var enableLockScreenMediaWidget
@Default(.enableLockScreenTimerWidget) private var enableLockScreenTimerWidget @Default(.enableLockScreenTimerWidget) private var enableLockScreenTimerWidget
let icons: [String] = ["logo2"]
@State private var selectedIcon: String = "logo2"
@State private var selectedListVisualizer: CustomVisualizer? = nil @State private var selectedListVisualizer: CustomVisualizer? = nil
@State private var isIconImporterPresented = false
@State private var isIconDropTarget = false
@State private var iconImportError: String?
@State private var isPresented: Bool = false @State private var isPresented: Bool = false
@State private var name: String = "" @State private var name: String = ""
@State private var url: String = "" @State private var url: String = ""
@ -3159,55 +3206,205 @@ struct Appearance: View {
IdleAnimationsSettingsSection() IdleAnimationsSettingsSection()
Section { Section {
HStack { VStack(alignment: .leading, spacing: 12) {
ForEach(icons, id: \.self) { icon in let columns = [GridItem(.adaptive(minimum: 90), spacing: 12)]
Spacer() LazyVGrid(columns: columns, spacing: 12) {
VStack { appIconCard(
Image(icon) title: "Default",
.resizable() image: defaultAppIconImage(),
.frame(width: 80, height: 80) isSelected: selectedAppIconID == nil
.background( ) {
RoundedRectangle(cornerRadius: 20, style: .circular) selectedAppIconID = nil
.strokeBorder( applySelectedAppIcon()
icon == selectedIcon ? Color.accentColor : .clear, }
lineWidth: 2.5
)
)
Text("Default") ForEach(customAppIcons) { icon in
.fontWeight(.medium) appIconCard(
.font(.caption) title: icon.name,
.foregroundStyle(icon == selectedIcon ? .white : .secondary) image: customIconImage(for: icon),
.padding(.horizontal, 10) isSelected: selectedAppIconID == icon.id.uuidString
.padding(.vertical, 3) ) {
.background( selectedAppIconID = icon.id.uuidString
Capsule() applySelectedAppIcon()
.fill(icon == selectedIcon ? Color.accentColor : .clear) }
) .contextMenu {
} Button("Remove") {
.onTapGesture { removeCustomIcon(icon)
withAnimation { }
selectedIcon = icon
} }
NSApp.applicationIconImage = NSImage(named: icon)
} }
Spacer() }
.padding(8)
.background(
RoundedRectangle(cornerRadius: 14, style: .continuous)
.fill(Color.secondary.opacity(isIconDropTarget ? 0.18 : 0.1))
)
.overlay(
RoundedRectangle(cornerRadius: 14, style: .continuous)
.strokeBorder(Color.accentColor.opacity(isIconDropTarget ? 0.8 : 0), lineWidth: 2)
)
.onDrop(of: [UTType.fileURL], isTargeted: $isIconDropTarget) { providers in
handleIconDrop(providers)
}
HStack(spacing: 8) {
Button("Add icon") {
iconImportError = nil
isIconImporterPresented = true
}
.buttonStyle(.borderedProminent)
Button("Remove selected") {
if let id = selectedAppIconID,
let icon = customAppIcons.first(where: { $0.id.uuidString == id }) {
removeCustomIcon(icon)
}
}
.buttonStyle(.bordered)
.disabled(selectedAppIconID == nil)
}
if let iconImportError {
Text(iconImportError)
.font(.caption)
.foregroundStyle(.secondary)
} else {
Text("Drop a PNG, JPEG, TIFF, or ICNS file to add it to your icon library.")
.font(.caption)
.foregroundStyle(.secondary)
} }
} }
.disabled(true) .settingsHighlight(id: highlightID("App icon"))
} header: { } header: {
HStack { HStack {
Text("App icon") Text("App icon")
customBadge(text: "Coming soon")
} }
} }
} }
.onAppear(perform: enforceLockScreenGlassConsistency) .onAppear(perform: enforceLockScreenGlassConsistency)
.onChange(of: lockScreenGlassStyle) { _, _ in enforceLockScreenGlassConsistency() } .onChange(of: lockScreenGlassStyle) { _, _ in enforceLockScreenGlassConsistency() }
.onChange(of: lockScreenGlassCustomizationMode) { _, _ in enforceLockScreenGlassConsistency() } .onChange(of: lockScreenGlassCustomizationMode) { _, _ in enforceLockScreenGlassConsistency() }
.fileImporter(
isPresented: $isIconImporterPresented,
allowedContentTypes: [.png, .jpeg, .tiff, .icns, .image]
) { result in
switch result {
case .success(let url):
importCustomIcon(from: url)
case .failure:
iconImportError = "Icon import was canceled or failed."
}
}
.navigationTitle("Appearance") .navigationTitle("Appearance")
} }
private func defaultAppIconImage() -> NSImage? {
let fallbackName = Bundle.main.iconFileName ?? "AppIcon"
return NSImage(named: fallbackName)
}
private func customIconImage(for icon: CustomAppIcon) -> NSImage? {
NSImage(contentsOf: icon.fileURL)
}
private func appIconCard(title: String, image: NSImage?, isSelected: Bool, action: @escaping () -> Void) -> some View {
Button(action: action) {
VStack(spacing: 6) {
Group {
if let image {
Image(nsImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
} else {
Image(systemName: "app.dashed")
.font(.system(size: 28, weight: .medium))
.foregroundStyle(.secondary)
}
}
.frame(width: 64, height: 64)
.background(
RoundedRectangle(cornerRadius: 16, style: .continuous)
.fill(Color.black.opacity(0.08))
)
.overlay(
RoundedRectangle(cornerRadius: 16, style: .continuous)
.strokeBorder(isSelected ? Color.accentColor : .clear, lineWidth: 2)
)
Text(title)
.font(.caption)
.lineLimit(1)
.foregroundStyle(isSelected ? .white : .secondary)
.padding(.horizontal, 8)
.padding(.vertical, 3)
.background(
Capsule().fill(isSelected ? Color.accentColor : .clear)
)
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.plain)
}
private func handleIconDrop(_ providers: [NSItemProvider]) -> Bool {
let matching = providers.first { $0.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) }
guard let provider = matching else { return false }
provider.loadItem(forTypeIdentifier: UTType.fileURL.identifier, options: nil) { item, _ in
let url: URL?
if let directURL = item as? URL {
url = directURL
} else if let data = item as? Data {
url = URL(dataRepresentation: data, relativeTo: nil)
} else {
url = nil
}
guard let url else { return }
Task { @MainActor in importCustomIcon(from: url) }
}
return true
}
private func importCustomIcon(from url: URL) {
guard let image = NSImage(contentsOf: url) else {
iconImportError = "That file could not be loaded as an image."
return
}
let name = url.deletingPathExtension().lastPathComponent
let ext = url.pathExtension.isEmpty ? "png" : url.pathExtension
let id = UUID()
let fileName = "custom-icon-\(id.uuidString).\(ext)"
let destination = CustomAppIcon.iconDirectory.appendingPathComponent(fileName)
do {
let data = try Data(contentsOf: url)
try data.write(to: destination, options: [.atomic])
} catch {
iconImportError = "Unable to save the icon file."
return
}
let newIcon = CustomAppIcon(id: id, name: name.isEmpty ? "Custom Icon" : name, fileName: fileName)
if !customAppIcons.contains(newIcon) {
customAppIcons.append(newIcon)
}
selectedAppIconID = newIcon.id.uuidString
NSApp.applicationIconImage = image
iconImportError = nil
}
private func removeCustomIcon(_ icon: CustomAppIcon) {
if let index = customAppIcons.firstIndex(of: icon) {
customAppIcons.remove(at: index)
}
if FileManager.default.fileExists(atPath: icon.fileURL.path) {
try? FileManager.default.removeItem(at: icon.fileURL)
}
if selectedAppIconID == icon.id.uuidString {
selectedAppIconID = nil
applySelectedAppIcon()
}
}
func checkVideoInput() -> Bool { func checkVideoInput() -> Bool {
if let _ = AVCaptureDevice.default(for: .video) { if let _ = AVCaptureDevice.default(for: .video) {
return true return true
@ -3301,6 +3498,7 @@ struct LockScreenSettings: View {
@Default(.lockScreenWeatherShowsAQI) private var lockScreenWeatherShowsAQI @Default(.lockScreenWeatherShowsAQI) private var lockScreenWeatherShowsAQI
@Default(.lockScreenWeatherShowsSunrise) private var lockScreenWeatherShowsSunrise @Default(.lockScreenWeatherShowsSunrise) private var lockScreenWeatherShowsSunrise
@Default(.lockScreenWeatherAQIScale) private var lockScreenWeatherAQIScale @Default(.lockScreenWeatherAQIScale) private var lockScreenWeatherAQIScale
@Default(.showStandardMediaControls) private var showStandardMediaControls
private func highlightID(_ title: String) -> String { private func highlightID(_ title: String) -> String {
SettingsTab.lockScreen.highlightID(for: title) SettingsTab.lockScreen.highlightID(for: title)
@ -3422,11 +3620,20 @@ struct LockScreenSettings: View {
.opacity(enableLockScreenMediaWidget ? 1 : 0.5) .opacity(enableLockScreenMediaWidget ? 1 : 0.5)
.settingsHighlight(id: highlightID("Enable media panel blur")) .settingsHighlight(id: highlightID("Enable media panel blur"))
} }
if !showStandardMediaControls {
Text("Enable Dynamic Island media controls to manage the lock screen panel.")
.font(.caption)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
} header: { } header: {
Text("Media Panel") Text("Media Panel")
} footer: { } footer: {
Text("Enable and style the media controls that appear above the system clock when the screen is locked.") Text("Enable and style the media controls that appear above the system clock when the screen is locked.")
} }
.disabled(!showStandardMediaControls)
.opacity(showStandardMediaControls ? 1 : 0.5)
Section { Section {
Defaults.Toggle("Show lock screen timer", key: .enableLockScreenTimerWidget) Defaults.Toggle("Show lock screen timer", key: .enableLockScreenTimerWidget)

View file

@ -1,9 +1,24 @@
// /*
// SettingsWindowController.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Alexander on 2025-06-14. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import AppKit import AppKit
import SwiftUI import SwiftUI

View file

@ -1,9 +1,24 @@
// /*
// SoftwareUpdater.swift * Atoll (DynamicIsland)
// DynamicIsland * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by Richard Kunkli on 09/08/2024. * Originally from boring.notch project
// * Modified and adapted for Atoll (DynamicIsland)
* See NOTICE for details.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import SwiftUI import SwiftUI
import Sparkle import Sparkle

View file

@ -1,9 +1,20 @@
// /*
// AirDrop.swift * Atoll (DynamicIsland)
// NotchDrop * Copyright (C) 2024-2026 Atoll Contributors
// *
// Created by 秋星桥 on 2024/7/7. * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Cocoa import Cocoa

Some files were not shown because too many files have changed in this diff Show more