mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-28 15:44:32 +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(.capsLockIndicatorTintMode) var capsLockTintMode
|
||||||
@Default(.enableDoNotDisturbDetection) var enableDoNotDisturbDetection
|
@Default(.enableDoNotDisturbDetection) var enableDoNotDisturbDetection
|
||||||
@Default(.showDoNotDisturbIndicator) var showDoNotDisturbIndicator
|
@Default(.showDoNotDisturbIndicator) var showDoNotDisturbIndicator
|
||||||
@Default(.focusIndicatorNonPersistent) var focusIndicatorNonPersistent
|
|
||||||
@Default(.enableScreenRecordingDetection) var enableScreenRecordingDetection
|
@Default(.enableScreenRecordingDetection) var enableScreenRecordingDetection
|
||||||
@Default(.enableCapsLockIndicator) var enableCapsLockIndicator
|
@Default(.enableCapsLockIndicator) var enableCapsLockIndicator
|
||||||
@Default(.enableExtensionLiveActivities) var enableExtensionLiveActivities
|
@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 {
|
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .download) && vm.notchState == .closed && downloadManager.isDownloading && Defaults[.enableDownloadListener] && !vm.hideOnClosed {
|
||||||
DownloadLiveActivity()
|
DownloadLiveActivity()
|
||||||
.transition(.blurReplace.animation(.interactiveSpring(dampingFraction: 1.2)))
|
.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()
|
DoNotDisturbLiveActivity()
|
||||||
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .lockScreen) && vm.notchState == .closed && (lockScreenManager.isLocked || !lockScreenManager.isLockIdle) && Defaults[.enableLockScreenLiveActivity] && !vm.hideOnClosed {
|
} else if (!coordinator.expandingView.show || coordinator.expandingView.type == .lockScreen) && vm.notchState == .closed && (lockScreenManager.isLocked || !lockScreenManager.isLockIdle) && Defaults[.enableLockScreenLiveActivity] && !vm.hideOnClosed {
|
||||||
LockScreenLiveActivity()
|
LockScreenLiveActivity()
|
||||||
|
|
@ -1044,7 +1043,7 @@ struct ContentView: View {
|
||||||
return .recording
|
return .recording
|
||||||
}
|
}
|
||||||
|
|
||||||
if enableDoNotDisturbDetection && showDoNotDisturbIndicator && (doNotDisturbManager.isDoNotDisturbActive || focusIndicatorNonPersistent) {
|
if enableDoNotDisturbDetection && showDoNotDisturbIndicator && doNotDisturbManager.isDoNotDisturbActive {
|
||||||
let mode = FocusModeType.resolve(identifier: doNotDisturbManager.currentFocusModeIdentifier, name: doNotDisturbManager.currentFocusModeName)
|
let mode = FocusModeType.resolve(identifier: doNotDisturbManager.currentFocusModeIdentifier, name: doNotDisturbManager.currentFocusModeName)
|
||||||
return .focus(mode)
|
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.
|
// 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()
|
@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 notificationCenter = DistributedNotificationCenter.default()
|
||||||
private let metadataExtractionQueue = DispatchQueue(label: "com.dynamicisland.focus.metadata", qos: .userInitiated)
|
private let metadataExtractionQueue = DispatchQueue(label: "com.dynamicisland.focus.metadata", qos: .userInitiated)
|
||||||
private let pollingQueue = DispatchQueue(label: "com.dynamicisland.focus.polling", qos: .utility)
|
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.
|
/// Delayed task that clears retained metadata after the OFF animation completes.
|
||||||
private var metadataClearTask: Task<Void, Never>?
|
private var metadataClearTask: Task<Void, Never>?
|
||||||
|
|
||||||
|
/// Task that resets `isFocusToastDismissing` after the OFF toast animation.
|
||||||
|
private var toastDismissTask: Task<Void, Never>?
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
focusLogStream.onMetadataUpdate = { [weak self] identifier, name in
|
focusLogStream.onMetadataUpdate = { [weak self] identifier, name in
|
||||||
self?.handleLogMetadataUpdate(identifier: identifier, name: name)
|
self?.handleLogMetadataUpdate(identifier: identifier, name: name)
|
||||||
|
|
@ -112,6 +120,7 @@ final class DoNotDisturbManager: ObservableObject {
|
||||||
stateVerificationTask = nil
|
stateVerificationTask = nil
|
||||||
metadataClearTask?.cancel()
|
metadataClearTask?.cancel()
|
||||||
metadataClearTask = nil
|
metadataClearTask = nil
|
||||||
|
cancelFocusToastDismiss()
|
||||||
isMonitoring = false
|
isMonitoring = false
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
@ -243,10 +252,12 @@ final class DoNotDisturbManager: ObservableObject {
|
||||||
self.currentFocusModeIdentifier = previousIdentifier
|
self.currentFocusModeIdentifier = previousIdentifier
|
||||||
self.currentFocusModeName = previousName
|
self.currentFocusModeName = previousName
|
||||||
self.scheduleMetadataClear()
|
self.scheduleMetadataClear()
|
||||||
|
self.beginFocusToastDismissIfNeeded()
|
||||||
} else {
|
} 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?.cancel()
|
||||||
self.metadataClearTask = nil
|
self.metadataClearTask = nil
|
||||||
|
self.cancelFocusToastDismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start or stop periodic verification based on new state.
|
// Start or stop periodic verification based on new state.
|
||||||
|
|
@ -279,6 +290,7 @@ final class DoNotDisturbManager: ObservableObject {
|
||||||
self.isDoNotDisturbActive = false
|
self.isDoNotDisturbActive = false
|
||||||
}
|
}
|
||||||
self.scheduleMetadataClear()
|
self.scheduleMetadataClear()
|
||||||
|
self.beginFocusToastDismissIfNeeded()
|
||||||
debugPrint("[DoNotDisturbManager] State verification: focus no longer active, resetting.")
|
debugPrint("[DoNotDisturbManager] State verification: focus no longer active, resetting.")
|
||||||
break
|
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?) {
|
private func handleLogMetadataUpdate(identifier: String?, name: String?) {
|
||||||
metadataExtractionQueue.async { [weak self] in
|
metadataExtractionQueue.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue