mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
HotFix: DND persistance
This commit is contained in:
parent
2db3fc9aaf
commit
c7da3f025c
2 changed files with 41 additions and 4 deletions
|
|
@ -75,7 +75,6 @@ struct ContentView: View {
|
|||
@Default(.capsLockIndicatorTintMode) var capsLockTintMode
|
||||
@Default(.enableDoNotDisturbDetection) var enableDoNotDisturbDetection
|
||||
@Default(.showDoNotDisturbIndicator) var showDoNotDisturbIndicator
|
||||
@Default(.focusIndicatorNonPersistent) var focusIndicatorNonPersistent
|
||||
@Default(.enableScreenRecordingDetection) var enableScreenRecordingDetection
|
||||
@Default(.enableCapsLockIndicator) var enableCapsLockIndicator
|
||||
@Default(.enableExtensionLiveActivities) var enableExtensionLiveActivities
|
||||
|
|
@ -713,7 +712,7 @@ struct ContentView: View {
|
|||
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .download) && vm.notchState == .closed && downloadManager.isDownloading && Defaults[.enableDownloadListener] && !vm.hideOnClosed {
|
||||
DownloadLiveActivity()
|
||||
.transition(.blurReplace.animation(.interactiveSpring(dampingFraction: 1.2)))
|
||||
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .doNotDisturb) && vm.notchState == .closed && Defaults[.enableDoNotDisturbDetection] && Defaults[.showDoNotDisturbIndicator] && (doNotDisturbManager.isDoNotDisturbActive || Defaults[.focusIndicatorNonPersistent]) && !vm.hideOnClosed && !lockScreenManager.isLocked {
|
||||
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .doNotDisturb) && vm.notchState == .closed && Defaults[.enableDoNotDisturbDetection] && Defaults[.showDoNotDisturbIndicator] && (doNotDisturbManager.isDoNotDisturbActive || doNotDisturbManager.isFocusToastDismissing) && !vm.hideOnClosed && !lockScreenManager.isLocked {
|
||||
DoNotDisturbLiveActivity()
|
||||
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .lockScreen) && vm.notchState == .closed && (lockScreenManager.isLocked || !lockScreenManager.isLockIdle) && Defaults[.enableLockScreenLiveActivity] && !vm.hideOnClosed {
|
||||
LockScreenLiveActivity()
|
||||
|
|
@ -1044,7 +1043,7 @@ struct ContentView: View {
|
|||
return .recording
|
||||
}
|
||||
|
||||
if enableDoNotDisturbDetection && showDoNotDisturbIndicator && (doNotDisturbManager.isDoNotDisturbActive || focusIndicatorNonPersistent) {
|
||||
if enableDoNotDisturbDetection && showDoNotDisturbIndicator && doNotDisturbManager.isDoNotDisturbActive {
|
||||
let mode = FocusModeType.resolve(identifier: doNotDisturbManager.currentFocusModeIdentifier, name: doNotDisturbManager.currentFocusModeName)
|
||||
return .focus(mode)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
// Used by the brief-toast UI to show an ON toast when the active mode switches while Focus stays enabled.
|
||||
@Published var focusToastTrigger: UUID = UUID()
|
||||
|
||||
/// Briefly `true` after focus turns OFF while toast mode is enabled,
|
||||
/// keeping the standalone DoNotDisturbLiveActivity mounted long enough
|
||||
/// for the "Off" dismissal animation to play out.
|
||||
@Published private(set) var isFocusToastDismissing: Bool = false
|
||||
|
||||
private let notificationCenter = DistributedNotificationCenter.default()
|
||||
private let metadataExtractionQueue = DispatchQueue(label: "com.dynamicisland.focus.metadata", qos: .userInitiated)
|
||||
private let pollingQueue = DispatchQueue(label: "com.dynamicisland.focus.polling", qos: .utility)
|
||||
|
|
@ -56,6 +61,9 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
/// Delayed task that clears retained metadata after the OFF animation completes.
|
||||
private var metadataClearTask: Task<Void, Never>?
|
||||
|
||||
/// Task that resets `isFocusToastDismissing` after the OFF toast animation.
|
||||
private var toastDismissTask: Task<Void, Never>?
|
||||
|
||||
private init() {
|
||||
focusLogStream.onMetadataUpdate = { [weak self] identifier, name in
|
||||
self?.handleLogMetadataUpdate(identifier: identifier, name: name)
|
||||
|
|
@ -112,6 +120,7 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
stateVerificationTask = nil
|
||||
metadataClearTask?.cancel()
|
||||
metadataClearTask = nil
|
||||
cancelFocusToastDismiss()
|
||||
isMonitoring = false
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
|
@ -243,10 +252,12 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
self.currentFocusModeIdentifier = previousIdentifier
|
||||
self.currentFocusModeName = previousName
|
||||
self.scheduleMetadataClear()
|
||||
self.beginFocusToastDismissIfNeeded()
|
||||
} else {
|
||||
// Focus turned ON — cancel any pending metadata clear.
|
||||
// Focus turned ON — cancel any pending metadata clear and toast dismiss.
|
||||
self.metadataClearTask?.cancel()
|
||||
self.metadataClearTask = nil
|
||||
self.cancelFocusToastDismiss()
|
||||
}
|
||||
|
||||
// Start or stop periodic verification based on new state.
|
||||
|
|
@ -279,6 +290,7 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
self.isDoNotDisturbActive = false
|
||||
}
|
||||
self.scheduleMetadataClear()
|
||||
self.beginFocusToastDismissIfNeeded()
|
||||
debugPrint("[DoNotDisturbManager] State verification: focus no longer active, resetting.")
|
||||
break
|
||||
}
|
||||
|
|
@ -321,6 +333,32 @@ final class DoNotDisturbManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets `isFocusToastDismissing` to `true` for ~2.5 seconds when focus turns
|
||||
/// OFF while toast mode is enabled. This keeps the standalone DND live activity
|
||||
/// mounted long enough for the "Off" toast animation, without permanently
|
||||
/// occupying the live-activity slot.
|
||||
private func beginFocusToastDismissIfNeeded() {
|
||||
guard Defaults[.focusIndicatorNonPersistent] else { return }
|
||||
|
||||
toastDismissTask?.cancel()
|
||||
isFocusToastDismissing = true
|
||||
|
||||
toastDismissTask = Task { @MainActor [weak self] in
|
||||
try? await Task.sleep(for: .milliseconds(2500))
|
||||
guard !Task.isCancelled, let self else { return }
|
||||
withAnimation(.smooth(duration: 0.25)) {
|
||||
self.isFocusToastDismissing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancels any in-progress toast dismiss countdown (e.g. when focus turns back ON).
|
||||
private func cancelFocusToastDismiss() {
|
||||
toastDismissTask?.cancel()
|
||||
toastDismissTask = nil
|
||||
isFocusToastDismissing = false
|
||||
}
|
||||
|
||||
private func handleLogMetadataUpdate(identifier: String?, name: String?) {
|
||||
metadataExtractionQueue.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue