Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
2.7 kB · 72 lines
Swift
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273// BackdropView.swift — the JukeWizard living backdrop: a seamless looping// video of the wizard illy (generated by bin/gen-backdrop.mjs via Seedance),// drawn aspect-fill at low opacity behind the whole UI. If the video asset// isn't present it degrades to the faded static mascot image. Never// intercepts mouse events.import AppKitimport AVFoundation
final class BackdropView: NSView { private var player: AVQueuePlayer? private var looper: AVPlayerLooper? private let playerLayer = AVPlayerLayer() private let fallbackImage: NSImage?
override init(frame: NSRect) { // static fallback (same illy the dock icon comes from) fallbackImage = { if let u = JukeResources.url(forResource: "jukewizard-mascot", withExtension: "png"), let img = NSImage(contentsOf: u) { return img } return nil }() super.init(frame: frame) wantsLayer = true setupVideo() } required init?(coder: NSCoder) { fatalError() }
override func hitTest(_ point: NSPoint) -> NSView? { nil }
private func setupVideo() { guard let url = JukeResources.url(forResource: "jukewizard-backdrop", withExtension: "mp4") else { return } let item = AVPlayerItem(url: url) let queue = AVQueuePlayer() queue.isMuted = true queue.actionAtItemEnd = .advance looper = AVPlayerLooper(player: queue, templateItem: item) // seamless gapless loop player = queue playerLayer.player = queue playerLayer.videoGravity = .resizeAspectFill playerLayer.opacity = 0.16 layer?.addSublayer(playerLayer) queue.play() }
override func viewDidMoveToWindow() { super.viewDidMoveToWindow() if window != nil { player?.play() } }
override func layout() { super.layout() CATransaction.begin(); CATransaction.setDisableActions(true) playerLayer.frame = bounds CATransaction.commit() }
// fallback render when there's no video yet override func draw(_ dirtyRect: NSRect) { guard player == nil, let img = fallbackImage else { return } let imgAR = img.size.width / img.size.height let viewAR = bounds.width / max(1, bounds.height) var r = bounds if imgAR > viewAR { let w = bounds.height * imgAR r = NSRect(x: (bounds.width - w) * 0.5, y: 0, width: w, height: bounds.height) } else { let h = bounds.width / imgAR r = NSRect(x: 0, y: (bounds.height - h) * 0.5, width: bounds.width, height: h) } img.draw(in: r, from: .zero, operation: .sourceOver, fraction: 0.10) }}