Files
openless/Sources/OpenLessApp/Capsule/CapsuleWindowController.swift
T

69 lines
2.2 KiB
Swift

import AppKit
import SwiftUI
import OpenLessUI
@MainActor
final class CapsuleWindowController {
private let window: NSPanel
private let hostingView: NSHostingView<CapsuleView>
private var currentState: CapsuleState = .hidden
private var currentLevel: Float = 0
private let panelSize = NSSize(width: 172, height: 44)
var onCancel: () -> Void = {}
var onConfirm: () -> Void = {}
init() {
let initialView = CapsuleView(state: .hidden, level: 0)
hostingView = NSHostingView(rootView: initialView)
hostingView.frame = NSRect(origin: .zero, size: panelSize)
let panel = NSPanel(
contentRect: NSRect(origin: .zero, size: panelSize),
styleMask: [.borderless, .nonactivatingPanel],
backing: .buffered,
defer: false
)
panel.isOpaque = false
panel.backgroundColor = .clear
panel.hasShadow = true
panel.level = .statusBar
panel.collectionBehavior = [.canJoinAllSpaces, .stationary, .ignoresCycle, .fullScreenAuxiliary]
// 必须接受鼠标点击,否则胶囊上的叉/勾按钮无法响应。
// .nonactivatingPanel 保证点击不会抢走前台 app 的焦点。
panel.ignoresMouseEvents = false
panel.contentView = hostingView
self.window = panel
repositionToBottomCenter()
}
func update(state: CapsuleState, level: Float = 0) {
currentState = state
currentLevel = level
hostingView.rootView = CapsuleView(
state: state,
level: level,
onCancel: { [weak self] in self?.onCancel() },
onConfirm: { [weak self] in self?.onConfirm() }
)
if state == .hidden {
window.orderOut(nil)
} else {
if !window.isVisible {
repositionToBottomCenter()
window.orderFrontRegardless()
}
}
}
private func repositionToBottomCenter() {
guard let screen = NSScreen.main else { return }
let screenFrame = screen.visibleFrame
let size = window.frame.size
let x = screenFrame.midX - size.width / 2
let y = screenFrame.minY + 24
window.setFrameOrigin(NSPoint(x: x, y: y))
}
}