Atoll/DynamicIsland/managers/LockScreenPanelManager.swift
Hariharan Mudaliar b77de94b62 Working widget
2025-10-27 01:15:27 +05:30

124 lines
4 KiB
Swift

//
// LockScreenPanelManager.swift
// DynamicIsland
//
// Manages the lock screen music panel window.
//
import SwiftUI
import AppKit
import SkyLightWindow
import Defaults
@MainActor
class LockScreenPanelManager {
static let shared = LockScreenPanelManager()
private var panelWindow: NSWindow?
private var hasDelegated = false
private var collapsedFrame: NSRect?
private init() {
print("[\(timestamp())] LockScreenPanelManager: initialized")
}
private func timestamp() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss.SSS"
return formatter.string(from: Date())
}
func showPanel() {
print("[\(timestamp())] LockScreenPanelManager: showPanel")
guard Defaults[.enableLockScreenMediaWidget] else {
print("[\(timestamp())] LockScreenPanelManager: widget disabled")
hidePanel()
return
}
guard let screen = NSScreen.main else {
print("[\(timestamp())] LockScreenPanelManager: no main screen available")
return
}
let collapsedSize = LockScreenMusicPanel.collapsedSize
let screenFrame = screen.frame
let centerX = screenFrame.origin.x + (screenFrame.width / 2)
let originX = centerX - (collapsedSize.width / 2)
let originY = screenFrame.origin.y + (screenFrame.height / 2) - collapsedSize.height - 32
let targetFrame = NSRect(x: originX, y: originY, width: collapsedSize.width, height: collapsedSize.height)
collapsedFrame = targetFrame
let window: NSWindow
if let existingWindow = panelWindow {
window = existingWindow
} else {
let newWindow = NSWindow(
contentRect: targetFrame,
styleMask: [.borderless, .nonactivatingPanel],
backing: .buffered,
defer: false
)
newWindow.isReleasedWhenClosed = false
newWindow.isOpaque = false
newWindow.backgroundColor = .clear
newWindow.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel()))
newWindow.collectionBehavior = [.canJoinAllSpaces, .stationary, .fullScreenAuxiliary]
newWindow.isMovable = false
newWindow.hasShadow = false
panelWindow = newWindow
window = newWindow
hasDelegated = false
}
window.setFrame(targetFrame, display: true)
window.contentView = NSHostingView(rootView: LockScreenMusicPanel())
if !hasDelegated {
SkyLightOperator.shared.delegateWindow(window)
hasDelegated = true
}
// Keep the window alive and simply order it out on unlock to avoid SkyLight crashes.
window.orderFrontRegardless()
print("[\(timestamp())] LockScreenPanelManager: panel visible")
}
func updatePanelSize(expanded: Bool, additionalHeight: CGFloat = 0, animated: Bool = true) {
guard let window = panelWindow, let baseFrame = collapsedFrame else {
return
}
let baseSize = expanded ? LockScreenMusicPanel.expandedSize : LockScreenMusicPanel.collapsedSize
let targetWidth = baseSize.width
let targetHeight = baseSize.height + additionalHeight
let originX = baseFrame.midX - (targetWidth / 2)
let originY = baseFrame.origin.y
let targetFrame = NSRect(x: originX, y: originY, width: targetWidth, height: targetHeight)
if animated {
window.animator().setFrame(targetFrame, display: true)
} else {
window.setFrame(targetFrame, display: true)
}
}
func hidePanel() {
print("[\(timestamp())] LockScreenPanelManager: hidePanel")
guard let window = panelWindow else {
print("LockScreenPanelManager: no panel to hide")
return
}
window.orderOut(nil)
window.contentView = nil
print("[\(timestamp())] LockScreenPanelManager: panel hidden")
}
}