mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Fully fixed: Timer Lock Screen Widget
This commit is contained in:
parent
f9a8887879
commit
a08540c589
3 changed files with 36 additions and 14 deletions
|
|
@ -201,22 +201,22 @@ struct LockScreenTimerWidget: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func stopTimer() {
|
private func stopTimer() {
|
||||||
let stopAction: @MainActor () -> Void = {
|
let allowsManualInteraction = timerManager.allowsManualInteraction
|
||||||
if timerManager.allowsManualInteraction {
|
|
||||||
timerManager.stopTimer()
|
|
||||||
} else {
|
|
||||||
timerManager.endExternalTimer(triggerSmoothClose: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Task { @MainActor in
|
LockScreenTimerWidgetPanelManager.shared.hide()
|
||||||
// Trigger the scale-out animation first so the dismissal mirrors the unlock flow.
|
|
||||||
LockScreenTimerWidgetPanelManager.shared.hide()
|
|
||||||
|
|
||||||
|
Task.detached(priority: .userInitiated) { [allowsManualInteraction] in
|
||||||
try? await Task.sleep(nanoseconds: LockScreenTimerWidgetPanelManager.hideAnimationDurationNanoseconds)
|
try? await Task.sleep(nanoseconds: LockScreenTimerWidgetPanelManager.hideAnimationDurationNanoseconds)
|
||||||
|
|
||||||
guard !Task.isCancelled else { return }
|
guard !Task.isCancelled else { return }
|
||||||
stopAction()
|
|
||||||
|
await MainActor.run {
|
||||||
|
if allowsManualInteraction {
|
||||||
|
TimerManager.shared.stopTimer()
|
||||||
|
} else {
|
||||||
|
TimerManager.shared.endExternalTimer(triggerSmoothClose: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,7 @@ final class LockScreenTimerWidgetPanelManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func refreshPosition(animated: Bool) {
|
func refreshPosition(animated: Bool) {
|
||||||
guard let window, window.isVisible, let screen = NSScreen.main else { return }
|
guard let window, window.isVisible, let screen = NSScreen.main else { return }
|
||||||
let frame = targetFrame(on: screen)
|
let frame = targetFrame(on: screen)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import SwiftUI
|
||||||
import SkyLightWindow
|
import SkyLightWindow
|
||||||
import QuartzCore
|
import QuartzCore
|
||||||
|
|
||||||
struct TimerControlWindowMetrics {
|
struct TimerControlWindowMetrics: Equatable {
|
||||||
let notchHeight: CGFloat
|
let notchHeight: CGFloat
|
||||||
let notchWidth: CGFloat
|
let notchWidth: CGFloat
|
||||||
let rightWingWidth: CGFloat
|
let rightWingWidth: CGFloat
|
||||||
|
|
@ -90,15 +90,23 @@ final class TimerControlWindowManager {
|
||||||
guard window != nil else {
|
guard window != nil else {
|
||||||
return present(using: viewModel, metrics: metrics)
|
return present(using: viewModel, metrics: metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let lastMetrics, lastMetrics == metrics {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return present(using: viewModel, metrics: metrics)
|
return present(using: viewModel, metrics: metrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hide(animated: Bool = true) {
|
func hide(animated: Bool = true, tearDown: Bool = true) {
|
||||||
guard let window else { return }
|
guard let window else { return }
|
||||||
|
|
||||||
guard animated, window.alphaValue > 0.01 else {
|
guard animated, window.alphaValue > 0.01 else {
|
||||||
window.orderOut(nil)
|
window.orderOut(nil)
|
||||||
window.alphaValue = 0
|
window.alphaValue = 0
|
||||||
|
if tearDown {
|
||||||
|
tearDownWindowResources(using: window)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,13 +118,26 @@ final class TimerControlWindowManager {
|
||||||
context.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
context.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
||||||
window.animator().setFrame(retreatFrame, display: true)
|
window.animator().setFrame(retreatFrame, display: true)
|
||||||
window.animator().alphaValue = 0
|
window.animator().alphaValue = 0
|
||||||
} completionHandler: {
|
} completionHandler: { [weak self] in
|
||||||
window.setFrame(originalFrame, display: false)
|
window.setFrame(originalFrame, display: false)
|
||||||
window.orderOut(nil)
|
window.orderOut(nil)
|
||||||
window.alphaValue = 0
|
window.alphaValue = 0
|
||||||
|
if tearDown {
|
||||||
|
self?.tearDownWindowResources(using: window)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func tearDownWindowResources(using window: NSWindow? = nil) {
|
||||||
|
let targetWindow = window ?? self.window
|
||||||
|
targetWindow?.contentView = nil
|
||||||
|
targetWindow?.orderOut(nil)
|
||||||
|
hostingView = nil
|
||||||
|
lastMetrics = nil
|
||||||
|
self.window = nil
|
||||||
|
hasDelegated = false
|
||||||
|
}
|
||||||
|
|
||||||
private func ensureHostingView(with overlay: TimerControlOverlay) -> NSHostingView<TimerControlOverlay> {
|
private func ensureHostingView(with overlay: TimerControlOverlay) -> NSHostingView<TimerControlOverlay> {
|
||||||
if let hostingView {
|
if let hostingView {
|
||||||
hostingView.rootView = overlay
|
hostingView.rootView = overlay
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue