Open on startup by default and block duplicate workspace names

- LoginItem registers on the first bundled launch, so the app opens on
  startup without the user finding the toggle; a user who turns it off is
  never overridden. A never-registered bundle reports SMAppService .notFound
  rather than .notRegistered, so the guard only treats enabled/approval as
  done. --diag now prints the raw status.
- New Workspace refuses a name that already exists (case-insensitive) and
  says so inline; Return cannot bypass it. The composer's '# Name' still
  switches to the existing workspace, which is the quick-capture gesture.
This commit is contained in:
2026-10-26 20:46:02 +08:00
parent e0c47ad010
commit 15a2aa92f7
3 changed files with 57 additions and 5 deletions
+21 -3
View File
@@ -616,6 +616,19 @@ struct PanelView: View {
// MARK: - New workspace
private var trimmedWorkspaceName: String {
newWorkspaceName.trimmingCharacters(in: .whitespacesAndNewlines)
}
/// Case-insensitive, like the store's dedupe. The modal blocks creation
/// with a hint instead of silently switching to the existing workspace.
private var workspaceNameExists: Bool {
let name = trimmedWorkspaceName
return !name.isEmpty && store.sections.contains {
$0.name.caseInsensitiveCompare(name) == .orderedSame
}
}
@ViewBuilder
private var newWorkspaceModal: some View {
if showNewWorkspace {
@@ -630,12 +643,17 @@ struct PanelView: View {
.focused($focusedField, equals: .newWorkspace)
.onSubmit(createWorkspace)
.onExitCommand { dismissNewWorkspace() }
if workspaceNameExists {
Text("A workspace named “\(trimmedWorkspaceName)” already exists.")
.font(.caption)
.foregroundStyle(.red)
}
HStack {
Spacer()
Button("Cancel") { dismissNewWorkspace() }
Button("Create") { createWorkspace() }
.keyboardShortcut(.defaultAction)
.disabled(newWorkspaceName.trimmingCharacters(in: .whitespaces).isEmpty)
.disabled(trimmedWorkspaceName.isEmpty || workspaceNameExists)
}
}
.padding(16)
@@ -649,8 +667,8 @@ struct PanelView: View {
}
private func createWorkspace() {
let name = newWorkspaceName.trimmingCharacters(in: .whitespacesAndNewlines)
guard !name.isEmpty else { return }
let name = trimmedWorkspaceName
guard !name.isEmpty, !workspaceNameExists else { return }
store.createSection(named: name)
dismissNewWorkspace()
}