File ▸ Share… stages a board as a zip and hands it to the system share sheet
Duplicate's own posture — a faithful copy, `.git` the sole exclusion, attachments/comments/trash carried verbatim — staged to a temp directory (BoardShareStager, ditto-zipped via DittoZipArchiver) and presented through NSSharingServicePicker (BoardSharePresentation), anchored to the board window's toolbar or its center. Follows Duplicate/Save as Template's flush-then- cancellable-copy sequence under the banner's in-progress row (ShareBoardCommand, AppCommands.swift), menu-validated on focus alone rather than the read-only lock (a share is a read, Print's own posture) with the one carve-out an open inline title editor still needs. WriteOperation gains .shareBoard for the banner vocabulary; 11-command-nexus.md's File menu table gains the row. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -3010,6 +3010,14 @@ public enum WriteOperation: Sendable, Equatable, CustomStringConvertible {
|
||||
/// `title` is the board's display name.
|
||||
case saveAsTemplate(title: String?)
|
||||
|
||||
/// File ▸ Share… — the whole board staged into a `.zip` for `NSSharingServicePicker`
|
||||
/// (design ruling 2026-08-09, card 72691b11; `BoardShareStager`). Its own case beside
|
||||
/// `.duplicateBoard` and `.saveAsTemplate`, on both their reasoning: a third command copies a
|
||||
/// board wholesale for a third reason, and a banner saying the app could not "duplicate" or
|
||||
/// "save as template" a board nobody asked to duplicate or template would name gestures that
|
||||
/// never happened. `title` is the board's display name.
|
||||
case shareBoard(title: String?)
|
||||
|
||||
case importAttachment(filename: String)
|
||||
case listAttachments
|
||||
|
||||
@@ -3246,6 +3254,7 @@ public enum WriteOperation: Sendable, Equatable, CustomStringConvertible {
|
||||
case .rename: .rename(title: title)
|
||||
case .duplicateBoard: .duplicateBoard(title: title)
|
||||
case .saveAsTemplate: .saveAsTemplate(title: title)
|
||||
case .shareBoard: .shareBoard(title: title)
|
||||
case .toggleTask: .toggleTask(title: title)
|
||||
case .editBody: .editBody(title: title)
|
||||
case .rawSource: .rawSource(title: title)
|
||||
@@ -3289,7 +3298,7 @@ public enum WriteOperation: Sendable, Equatable, CustomStringConvertible {
|
||||
// reading to be about — and `.deleteComment`'s move into `comments/.trash/` stamps for the
|
||||
// plain container reason its board-level twin does.
|
||||
case .createBoard, .createLane, .createCard, .move, .copy, .delete, .purge, .migrateTombstone,
|
||||
.style, .resize, .collapse, .expand, .rename, .duplicateBoard, .saveAsTemplate, .paste,
|
||||
.style, .resize, .collapse, .expand, .rename, .duplicateBoard, .saveAsTemplate, .shareBoard, .paste,
|
||||
.importAttachment,
|
||||
.listAttachments, .removeAttachment, .relocateLooseFile, .agentGuide, .seedGitignore,
|
||||
.mintBoardIndex, .stampSchema, .setBoardBackground,
|
||||
@@ -3326,6 +3335,7 @@ public enum WriteOperation: Sendable, Equatable, CustomStringConvertible {
|
||||
case let .rename(title): Self.phrase("rename", title)
|
||||
case let .duplicateBoard(title): Self.phrase("duplicate board", title)
|
||||
case let .saveAsTemplate(title): Self.phrase("save as template", title)
|
||||
case let .shareBoard(title): Self.phrase("share board", title)
|
||||
case let .importAttachment(filename): "import attachment '\(filename)'"
|
||||
case .listAttachments: "list attachments"
|
||||
case let .removeAttachment(filename): "move attachment '\(filename)' to the Trash"
|
||||
|
||||
Reference in New Issue
Block a user