mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Make some changes: fixes and stuff
This commit is contained in:
parent
05d41f6bb7
commit
d0448ec2cb
10 changed files with 209 additions and 150 deletions
|
|
@ -18,7 +18,8 @@ class LockScreenLiveActivityWindowManager {
|
|||
private var hasDelegated = false
|
||||
private var hideTask: Task<Void, Never>?
|
||||
private var hostingView: NSHostingView<LockScreenLiveActivityOverlay>?
|
||||
private let overlayModel = LockScreenLiveActivityOverlayViewModel()
|
||||
private let overlayModel = LockScreenLiveActivityOverlayModel()
|
||||
private weak var viewModel: DynamicIslandViewModel?
|
||||
|
||||
private init() {}
|
||||
|
||||
|
|
@ -28,25 +29,30 @@ class LockScreenLiveActivityWindowManager {
|
|||
return formatter.string(from: Date())
|
||||
}
|
||||
|
||||
private func frame(for notchSize: CGSize, on screen: NSScreen) -> NSRect {
|
||||
let indicatorSize = max(0, notchSize.height - 12)
|
||||
private func windowSize(for notchSize: CGSize) -> CGSize {
|
||||
let indicatorWidth = max(0, notchSize.height - 12)
|
||||
let horizontalPadding = cornerRadiusInsets.closed.bottom
|
||||
let totalWidth = notchSize.width + (indicatorSize * 2) + (horizontalPadding * 2)
|
||||
|
||||
let screenFrame = screen.frame
|
||||
let originX = screenFrame.origin.x + (screenFrame.width / 2) - (totalWidth / 2)
|
||||
let originY = screenFrame.origin.y + screenFrame.height - notchSize.height
|
||||
let totalWidth = notchSize.width + (indicatorWidth * 2) + (horizontalPadding * 2)
|
||||
|
||||
return NSRect(x: originX, y: originY, width: totalWidth, height: notchSize.height)
|
||||
return CGSize(width: totalWidth, height: notchSize.height)
|
||||
}
|
||||
|
||||
private func ensureWindow(notchSize: CGSize, screen: NSScreen) -> NSWindow {
|
||||
private func frame(for windowSize: CGSize, on screen: NSScreen) -> NSRect {
|
||||
let screenFrame = screen.frame
|
||||
let originX = screenFrame.origin.x + (screenFrame.width / 2) - (windowSize.width / 2)
|
||||
let originY = screenFrame.origin.y + screenFrame.height - windowSize.height
|
||||
|
||||
return NSRect(x: originX, y: originY, width: windowSize.width, height: windowSize.height)
|
||||
}
|
||||
|
||||
private func ensureWindow(windowSize: CGSize, screen: NSScreen) -> NSWindow {
|
||||
if let window {
|
||||
return window
|
||||
}
|
||||
|
||||
let window = NSWindow(
|
||||
contentRect: frame(for: notchSize, on: screen),
|
||||
contentRect: frame(for: windowSize, on: screen),
|
||||
styleMask: [.borderless, .nonactivatingPanel],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
|
|
@ -67,29 +73,43 @@ class LockScreenLiveActivityWindowManager {
|
|||
return window
|
||||
}
|
||||
|
||||
private func present(state: LockLiveActivityState) {
|
||||
private func lockContext() -> (notchSize: CGSize, screen: NSScreen)? {
|
||||
guard let screen = NSScreen.main else {
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: no main screen available")
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let viewModel else {
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: no view model configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
var notchSize = viewModel.closedNotchSize
|
||||
if notchSize.width <= 0 || notchSize.height <= 0 {
|
||||
notchSize = getClosedNotchSize(screen: screen.localizedName)
|
||||
}
|
||||
|
||||
return (notchSize, screen)
|
||||
}
|
||||
|
||||
private func present(notchSize: CGSize, on screen: NSScreen) {
|
||||
guard Defaults[.enableLockScreenLiveActivity] else {
|
||||
hideImmediately()
|
||||
return
|
||||
}
|
||||
|
||||
guard let screen = NSScreen.main else {
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: no main screen available")
|
||||
return
|
||||
}
|
||||
|
||||
let notchSize = getClosedNotchSize(screen: screen.localizedName)
|
||||
let window = ensureWindow(notchSize: notchSize, screen: screen)
|
||||
let targetFrame = frame(for: notchSize, on: screen)
|
||||
let windowSize = windowSize(for: notchSize)
|
||||
let window = ensureWindow(windowSize: windowSize, screen: screen)
|
||||
let targetFrame = frame(for: windowSize, on: screen)
|
||||
window.setFrame(targetFrame, display: true)
|
||||
|
||||
let overlay = LockScreenLiveActivityOverlay(state: state, notchSize: notchSize, viewModel: overlayModel)
|
||||
let overlayView = LockScreenLiveActivityOverlay(model: overlayModel, notchSize: notchSize)
|
||||
|
||||
if let hostingView {
|
||||
hostingView.rootView = overlay
|
||||
hostingView.rootView = overlayView
|
||||
hostingView.frame = CGRect(origin: .zero, size: targetFrame.size)
|
||||
} else {
|
||||
let view = NSHostingView(rootView: overlay)
|
||||
let view = NSHostingView(rootView: overlayView)
|
||||
view.frame = CGRect(origin: .zero, size: targetFrame.size)
|
||||
hostingView = view
|
||||
window.contentView = view
|
||||
|
|
@ -107,40 +127,55 @@ class LockScreenLiveActivityWindowManager {
|
|||
}
|
||||
|
||||
window.orderFrontRegardless()
|
||||
|
||||
if state == .locked {
|
||||
overlayModel.expansion = 0.2
|
||||
withAnimation(.spring(response: 0.55, dampingFraction: 0.82)) {
|
||||
overlayModel.expansion = 1
|
||||
}
|
||||
} else {
|
||||
overlayModel.expansion = 1
|
||||
}
|
||||
|
||||
if window.alphaValue < 1 {
|
||||
NSAnimationContext.runAnimationGroup { context in
|
||||
context.duration = 0.12
|
||||
window.animator().alphaValue = 1
|
||||
}
|
||||
}
|
||||
window.alphaValue = 1
|
||||
}
|
||||
|
||||
func showLocked() {
|
||||
hideTask?.cancel()
|
||||
present(state: .locked)
|
||||
guard let context = lockContext() else { return }
|
||||
|
||||
overlayModel.iconName = "lock.fill"
|
||||
overlayModel.scale = 0.6
|
||||
overlayModel.opacity = 0
|
||||
|
||||
present(notchSize: context.notchSize, on: context.screen)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
withAnimation(.spring(response: 0.45, dampingFraction: 0.82)) {
|
||||
self.overlayModel.scale = 1
|
||||
}
|
||||
withAnimation(.easeOut(duration: 0.18)) {
|
||||
self.overlayModel.opacity = 1
|
||||
}
|
||||
}
|
||||
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: showing locked state")
|
||||
}
|
||||
|
||||
func showUnlockAndScheduleHide() {
|
||||
hideTask?.cancel()
|
||||
present(state: .unlocking)
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: showing unlock state")
|
||||
guard let context = lockContext() else { return }
|
||||
|
||||
overlayModel.iconName = "lock.open.fill"
|
||||
overlayModel.scale = 0.7
|
||||
overlayModel.opacity = 0
|
||||
|
||||
present(notchSize: context.notchSize, on: context.screen)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
withAnimation(.spring(response: 0.45, dampingFraction: 0.85)) {
|
||||
self.overlayModel.scale = 1
|
||||
}
|
||||
withAnimation(.easeOut(duration: 0.16)) {
|
||||
self.overlayModel.opacity = 1
|
||||
}
|
||||
}
|
||||
|
||||
hideTask = Task { [weak self] in
|
||||
try? await Task.sleep(for: .seconds(max(Defaults[.waitInterval], 1.0)))
|
||||
guard let self, !Task.isCancelled else { return }
|
||||
await MainActor.run {
|
||||
self.hideImmediately()
|
||||
self.hideWithAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,17 +184,30 @@ class LockScreenLiveActivityWindowManager {
|
|||
hideTask?.cancel()
|
||||
hideTask = nil
|
||||
|
||||
hideWithAnimation()
|
||||
}
|
||||
|
||||
private func hideWithAnimation() {
|
||||
guard let window else { return }
|
||||
|
||||
withAnimation(.easeOut(duration: 0.1)) {
|
||||
overlayModel.expansion = 0.2
|
||||
withAnimation(.easeInOut(duration: 0.18)) {
|
||||
overlayModel.opacity = 0
|
||||
overlayModel.scale = 0.7
|
||||
}
|
||||
|
||||
NSAnimationContext.runAnimationGroup { context in
|
||||
context.duration = 0.1
|
||||
context.duration = 0.2
|
||||
window.animator().alphaValue = 0
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.22) {
|
||||
window.orderOut(nil)
|
||||
}
|
||||
|
||||
print("[\(timestamp())] LockScreenLiveActivityWindowManager: HUD hidden")
|
||||
}
|
||||
|
||||
func configure(viewModel: DynamicIslandViewModel) {
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue