Yep. AI rewrote the whole thing.

This commit is contained in:
2026-03-13 03:24:24 +11:00
parent e4719cb9f4
commit fe6c7d8c12
47 changed files with 5348 additions and 1182 deletions

View File

@@ -0,0 +1,161 @@
import SwiftUI
struct WorkspaceSwitcherView: View {
@ObservedObject var screen: ScreenContext
let orchestrator: NotchOrchestrator
@ObservedObject private var screenRegistry = ScreenRegistry.shared
@ObservedObject private var workspaceRegistry = WorkspaceRegistry.shared
@State private var isRenameAlertPresented = false
@State private var isDeleteConfirmationPresented = false
@State private var renameDraft = ""
private var currentWorkspaceSummary: WorkspaceSummary {
workspaceRegistry.summary(for: screen.workspaceID)
?? workspaceRegistry.allWorkspaceSummaries().first
?? WorkspaceSummary(id: screen.workspaceID, name: "Workspace")
}
private var deletionFallbackSummary: WorkspaceSummary? {
guard let fallbackWorkspaceID = workspaceRegistry.deletionFallbackWorkspaceID(
forDeleting: screen.workspaceID,
preferredFallback: workspaceRegistry.defaultWorkspaceID
) else {
return nil
}
return workspaceRegistry.summary(for: fallbackWorkspaceID)
}
private var assignedScreenCount: Int {
screenRegistry.assignedScreenCount(to: screen.workspaceID)
}
var body: some View {
Menu {
ForEach(workspaceRegistry.workspaceSummaries) { summary in
Button {
selectWorkspace(summary.id)
} label: {
if summary.id == screen.workspaceID {
Label(summary.name, systemImage: "checkmark")
} else {
Text(summary.name)
}
}
}
Divider()
Button("New Workspace") {
let workspaceID = workspaceRegistry.createWorkspace()
selectWorkspace(workspaceID)
}
Button("Rename Current Workspace") {
renameDraft = currentWorkspaceSummary.name
syncFocusLossSuppression(renamePresented: true, deletePresented: isDeleteConfirmationPresented)
isRenameAlertPresented = true
}
Button("Delete Current Workspace", role: .destructive) {
syncFocusLossSuppression(renamePresented: isRenameAlertPresented, deletePresented: true)
isDeleteConfirmationPresented = true
}
.disabled(!workspaceRegistry.canDeleteWorkspace(id: screen.workspaceID))
} label: {
switcherLabel
}
.menuStyle(.borderlessButton)
.accessibilityIdentifier("notch.workspace-switcher")
.accessibilityLabel("Workspace Switcher")
.accessibilityValue(currentWorkspaceSummary.name)
.fixedSize(horizontal: false, vertical: true)
.help("Switch workspace for this screen")
.alert("Rename Workspace", isPresented: $isRenameAlertPresented) {
TextField("Workspace name", text: $renameDraft)
Button("Cancel", role: .cancel) {}
Button("Save") {
workspaceRegistry.renameWorkspace(id: screen.workspaceID, to: renameDraft)
}
} message: {
Text("This only renames the shared workspace. Screens assigned to it keep following the new name.")
}
.confirmationDialog("Delete Workspace", isPresented: $isDeleteConfirmationPresented, titleVisibility: .visible) {
Button("Delete Workspace", role: .destructive) {
deleteCurrentWorkspace()
}
} message: {
Text(deleteMessage)
}
.onChange(of: isRenameAlertPresented) { _, isPresented in
syncFocusLossSuppression(renamePresented: isPresented, deletePresented: isDeleteConfirmationPresented)
}
.onChange(of: isDeleteConfirmationPresented) { _, isPresented in
syncFocusLossSuppression(renamePresented: isRenameAlertPresented, deletePresented: isPresented)
}
.onDisappear {
screen.setCloseOnFocusLossSuppressed(false)
}
}
private var deleteMessage: String {
if let fallback = deletionFallbackSummary {
return "This reassigns \(assignedScreenCount) screen\(assignedScreenCount == 1 ? "" : "s") to \(fallback.name) and closes this workspace."
}
return "At least one workspace must remain."
}
private var switcherLabel: some View {
HStack(spacing: 6) {
Image(systemName: "rectangle.3.group")
.font(.system(size: 11, weight: .medium))
Text(currentWorkspaceSummary.name)
.font(.system(size: 11, weight: .medium))
.lineLimit(1)
Image(systemName: "chevron.down")
.font(.system(size: 9, weight: .semibold))
}
.foregroundStyle(.white.opacity(0.7))
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.white.opacity(0.08))
)
.contentShape(Rectangle())
.accessibilityElement(children: .ignore)
.accessibilityLabel("Workspace Switcher")
.accessibilityValue(currentWorkspaceSummary.name)
.accessibilityIdentifier("notch.workspace-switcher")
}
private func selectWorkspace(_ workspaceID: WorkspaceID) {
screenRegistry.assignWorkspace(workspaceID, to: screen.id)
if screen.notchState == .open {
orchestrator.open(screenID: screen.id)
}
}
private func deleteCurrentWorkspace() {
guard let fallback = screenRegistry.deleteWorkspace(
screen.workspaceID,
preferredFallback: workspaceRegistry.defaultWorkspaceID
) else {
return
}
screenRegistry.assignWorkspace(fallback, to: screen.id)
if screen.notchState == .open {
orchestrator.open(screenID: screen.id)
} else {
screen.requestTerminalFocus?()
}
}
private func syncFocusLossSuppression(renamePresented: Bool, deletePresented: Bool) {
screen.setCloseOnFocusLossSuppressed(renamePresented || deletePresented)
}
}