Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
Swift
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188import AppKit
/// Small "Jam" window — the social / come-hang-out surface that used to/// live at the bottom of the About panel: the Aesthetic.Computer badge/// and the computer-club invites. Opened from the popover's Jam button/// (the peer to About), so About stays a tight identity/settings panel.final class JamWindowController: NSWindowController, NSWindowDelegate { /// Self-retain so a popoverVC rebuild (language switch) can't drop /// the window mid-interaction. Cleared in `windowWillClose`. private static var active: JamWindowController?
init() { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 256, height: 210), styleMask: [.titled, .closable, .fullSizeContentView], backing: .buffered, defer: false ) window.titlebarAppearsTransparent = true window.titleVisibility = .hidden window.isMovableByWindowBackground = true window.isReleasedWhenClosed = false // Ordinary window level. These secondary windows used to sit at // popUpMenu + 1 so the status-bar popover couldn't bury them — but that // floated them above every other app on the Mac for as long as they // stayed open. Each one activates the app and orders front when shown, // which lifts it over the popover at the only moment that matters. window.level = .normal super.init(window: window) window.delegate = self buildContent() }
required init?(coder: NSCoder) { fatalError("init(coder:) is not used") }
@discardableResult static func show() -> JamWindowController { active?.close() let ctrl = JamWindowController() ctrl.present() return ctrl }
func present() { guard let window = window else { return } JamWindowController.active = self window.center() window.level = .normal NSApp.activate(ignoringOtherApps: true) window.makeKeyAndOrderFront(nil) }
func windowWillClose(_ notification: Notification) { if JamWindowController.active === self { JamWindowController.active = nil } }
private func buildContent() { guard let window = window else { return } let content = NSView() content.translatesAutoresizingMaskIntoConstraints = false window.contentView = content
let stack = NSStackView() stack.orientation = .vertical stack.alignment = .centerX stack.spacing = 12 stack.edgeInsets = NSEdgeInsets(top: 40, left: 28, bottom: 26, right: 28) stack.translatesAutoresizingMaskIntoConstraints = false content.addSubview(stack) NSLayoutConstraint.activate([ stack.leadingAnchor.constraint(equalTo: content.leadingAnchor), stack.trailingAnchor.constraint(equalTo: content.trailingAnchor), stack.topAnchor.constraint(equalTo: content.topAnchor), stack.bottomAnchor.constraint(equalTo: content.bottomAnchor), ])
// Colored-pencil banner — a communal notepat jam (generated in the // marketing stack, house style). Sets the come-hang-out tone above // the heading + links. if let url = Bundle.appResources.url(forResource: "looking-for-players", withExtension: "png"), let banner = NSImage(contentsOf: url) { let bannerView = NSImageView() bannerView.image = banner bannerView.imageScaling = .scaleProportionallyUpOrDown bannerView.translatesAutoresizingMaskIntoConstraints = false bannerView.wantsLayer = true bannerView.layer?.cornerRadius = 8 bannerView.layer?.masksToBounds = true if #available(macOS 10.15, *) { bannerView.layer?.cornerCurve = .continuous } stack.addArrangedSubview(bannerView) NSLayoutConstraint.activate([ bannerView.widthAnchor.constraint(equalToConstant: 200), // 3:2 source → keep the aspect for the banner crop. bannerView.heightAnchor.constraint(equalToConstant: 133), ]) stack.setCustomSpacing(14, after: bannerView) }
let heading = NSTextField(labelWithString: L("popover.about.lookingForPlayers")) heading.font = NSFont.systemFont(ofSize: 18, weight: .bold) heading.alignment = .center stack.addArrangedSubview(heading) stack.setCustomSpacing(14, after: heading)
// Aesthetic.Computer badge — purple words flanking a pink dot. let acPurple = NSColor(red: 167/255, green: 139/255, blue: 250/255, alpha: 1) let acLink = MenuBandPopoverViewController.makeLinkButton( attr: MenuBandPopoverViewController.aestheticComputerTitle(), target: self, action: #selector(openAesthetic), background: acPurple.withAlphaComponent(0.14), border: acPurple.withAlphaComponent(0.55) ) stack.addArrangedSubview(acLink) stack.setCustomSpacing(12, after: acLink)
// NELA invite + "start your own" — the come-hang-out pair. let para = NSMutableParagraphStyle() para.alignment = .center para.lineBreakMode = .byWordWrapping let nela = clubLink(L("popover.about.nela"), action: #selector(openNELA), tooltip: "https://nelacomputer.club", para: para, color: NSColor(red: 0.36, green: 0.80, blue: 0.92, alpha: 1)) // cyan stack.addArrangedSubview(nela) stack.setCustomSpacing(12, after: nela) stack.addArrangedSubview(clubLink(L("popover.about.startaclub"), action: #selector(openStartAClub), tooltip: "https://startacomputer.club", para: para, color: NSColor(red: 1.0, green: 0.56, blue: 0.42, alpha: 1))) // coral }
private func clubLink(_ text: String, action: Selector, tooltip: String, para: NSParagraphStyle, color: NSColor) -> NSButton { // HoverFeedbackButton, not NSButton: these read as links (colored, // underlined) but had no pointing-hand cursor and no hover state, so // they looked like decorated text. let button = HoverFeedbackButton(title: "", target: self, action: action) button.attributedTitle = NSAttributedString( string: text, attributes: [ .font: NSFont.monospacedSystemFont(ofSize: 10, weight: .regular), .foregroundColor: color, .underlineStyle: NSUnderlineStyle.single.rawValue, .underlineColor: color.withAlphaComponent(0.6), .paragraphStyle: para, ]) button.bezelStyle = .regularSquare button.isBordered = false // Single line, sized to the text — a fixed 200pt width was wrapping // longer links onto two lines (looked broken). button.cell?.wraps = false button.cell?.lineBreakMode = .byClipping if let cell = button.cell as? NSButtonCell { cell.imageScaling = .scaleNone } button.translatesAutoresizingMaskIntoConstraints = false button.toolTip = tooltip button.titleBrightensOnHover(hoverColor: .white) return button }
@objc private func openAesthetic() { // The real browser, like its two row-mates below (NELA, start-a-club). // This badge used to open the in-app AestheticWebWindow — the only one // of the three that didn't leave the app, and it floats at .statusBar // on top of everything besides. if let url = URL(string: "https://aesthetic.computer") { NSWorkspace.shared.open(url) } } @objc private func openNELA() { if let url = URL(string: "https://nelacomputer.club") { NSWorkspace.shared.open(url) } } @objc private func openStartAClub() { if let url = URL(string: "https://startacomputer.club") { NSWorkspace.shared.open(url) } }}