import AppKit extension AppDelegate { func setupWindows() { for screen in NSScreen.screens { let window = NSWindow( contentRect: screen.frame, styleMask: .borderless, backing: .buffered, defer: false ) window.level = .screenSaver window.backgroundColor = .clear window.isOpaque = false window.hasShadow = false window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] window.ignoresMouseEvents = true window.isReleasedWhenClosed = false let gradientView = EdgeGradientView(frame: NSRect(origin: .zero, size: screen.frame.size)) gradientView.autoresizingMask = [.width, .height] window.contentView = gradientView window.alphaValue = 0.0 window.orderFrontRegardless() overlayWindows.append(window) let pillW: CGFloat = 200 let pillH: CGFloat = 80 let pillX = screen.frame.origin.x + (screen.frame.width - pillW) / 2 let pillY = screen.frame.origin.y + 40 let pillWindow = NSWindow( contentRect: NSRect(x: pillX, y: pillY, width: pillW, height: pillH), styleMask: .borderless, backing: .buffered, defer: false ) pillWindow.level = .screenSaver pillWindow.backgroundColor = .clear pillWindow.isOpaque = false pillWindow.hasShadow = false pillWindow.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] pillWindow.ignoresMouseEvents = true pillWindow.isReleasedWhenClosed = false let pillView = NSView(frame: NSRect(x: 0, y: 0, width: pillW, height: pillH)) pillView.wantsLayer = true pillView.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.6).cgColor pillView.layer?.cornerRadius = pillH / 2 let label = NSTextField(labelWithString: "00:10") label.font = NSFont.monospacedSystemFont(ofSize: 36, weight: .bold) label.textColor = Settings.shared.gradientColor label.alignment = .center label.frame = NSRect(x: 0, y: 14, width: pillW, height: 50) pillView.addSubview(label) pillWindow.contentView = pillView pillWindow.alphaValue = 0.0 pillWindow.orderFrontRegardless() countdownWindows.append(pillWindow) countdownLabels.append(label) } } func showCountdownPills() { for window in countdownWindows { if window.alphaValue < 1.0 { NSAnimationContext.runAnimationGroup { ctx in ctx.duration = 0.2 window.animator().alphaValue = 1.0 } } } } func hideCountdownPills() { for window in countdownWindows { window.alphaValue = 0.0 } } func updateCountdownLabels() { let seconds = max(remainingSeconds, 0) let text = String(format: "00:%02d", seconds) for label in countdownLabels { label.stringValue = text } } func triggerBlink() { let settings = Settings.shared let scale = CGFloat(settings.intensityScale) let durationScale = settings.blinkDurationScale // Intensity scales across the effective countdown window (capped to work timer) let effectiveCountdown = min(countdownDuration, workTimerDuration) let countdownElapsed = Double(effectiveCountdown - remainingSeconds) let countdownTotal = Double(effectiveCountdown) let progress = min(max(countdownElapsed / countdownTotal, 0.0), 1.0) let baseIntensity = 0.15 + (0.60 * progress) // 0.15 at start, up to 0.75 at 0:00 let intensity = min(baseIntensity * Double(scale), 1.0) let fadeIn: Double let hold: Double let fadeOut: Double if remainingSeconds > 60 { fadeIn = 1.0 * durationScale; hold = 0.8 * durationScale; fadeOut = 1.0 * durationScale } else if remainingSeconds > 30 { fadeIn = 0.8 * durationScale; hold = 0.6 * durationScale; fadeOut = 0.8 * durationScale } else if remainingSeconds > 10 { fadeIn = 0.5 * durationScale; hold = 0.4 * durationScale; fadeOut = 0.6 * durationScale } else { fadeIn = 0.3 * durationScale; hold = 0.3 * durationScale; fadeOut = 0.4 * durationScale } let color = settings.gradientColor for window in overlayWindows { guard let view = window.contentView as? EdgeGradientView else { continue } view.intensity = CGFloat(intensity) view.color = color view.needsDisplay = true NSAnimationContext.runAnimationGroup { ctx in ctx.duration = fadeIn window.animator().alphaValue = 1.0 } completionHandler: { DispatchQueue.main.asyncAfter(deadline: .now() + hold) { NSAnimationContext.runAnimationGroup({ ctx in ctx.duration = fadeOut window.animator().alphaValue = 0.0 }) } } } } func makeSolid() { isSolid = true let settings = Settings.shared let maxIntensity = min(0.75 * CGFloat(settings.intensityScale), 1.0) let color = settings.gradientColor for window in overlayWindows { guard let view = window.contentView as? EdgeGradientView else { continue } view.intensity = maxIntensity view.color = color view.needsDisplay = true NSAnimationContext.runAnimationGroup { ctx in ctx.duration = 0.3 window.animator().alphaValue = 1.0 } } } func resetOverlayToGradient() { for window in overlayWindows { window.ignoresMouseEvents = true let size = window.frame.size let gradientView = EdgeGradientView(frame: NSRect(origin: .zero, size: size)) gradientView.autoresizingMask = [.width, .height] window.contentView = gradientView window.alphaValue = 0.0 } } }