import AppKit import VoiceCatCore final class MoveUserSheet: NSViewController { var onComplete: ((UInt32?) -> Void)? private let channels: [Channel] private let currentChannelId: UInt32 private let picker = NSPopUpButton() init(channels: [Channel], currentChannelId: UInt32) { self.channels = channels.sorted(by: { $0.name < $1.name }) self.currentChannelId = currentChannelId super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError() } override func loadView() { view = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 100)) } override func viewDidLoad() { super.viewDidLoad() buildUI() } private func buildUI() { let label = NSTextField(labelWithString: "Move user to channel:") label.setAccessibilityLabel("Select destination channel") for ch in channels where ch.id != currentChannelId { let item = NSMenuItem(title: ch.name, action: nil, keyEquivalent: "") item.representedObject = ch.id picker.menu?.addItem(item) } picker.setAccessibilityLabel("Destination channel") let cancelButton = NSButton(title: "Cancel", target: self, action: #selector(cancelClicked)) cancelButton.bezelStyle = .rounded let moveButton = NSButton(title: "Move", target: self, action: #selector(moveClicked)) moveButton.bezelStyle = .rounded; moveButton.keyEquivalent = "\r" moveButton.setAccessibilityLabel("Move user to selected channel") let buttonRow = NSStackView(views: [NSView(), cancelButton, moveButton]) buttonRow.orientation = .horizontal; buttonRow.spacing = 8 let stack = NSStackView(views: [label, picker, buttonRow]) stack.orientation = .vertical; stack.spacing = 10 stack.edgeInsets = NSEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) stack.translatesAutoresizingMaskIntoConstraints = false view.addSubview(stack) NSLayoutConstraint.activate([ stack.topAnchor.constraint(equalTo: view.topAnchor), stack.leadingAnchor.constraint(equalTo: view.leadingAnchor), stack.trailingAnchor.constraint(equalTo: view.trailingAnchor), stack.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } @objc private func moveClicked() { let channelId = picker.selectedItem?.representedObject as? UInt32 dismiss(nil) onComplete?(channelId) } @objc private func cancelClicked() { dismiss(nil) onComplete?(nil) } }