Build the attachments sidebar section
The card's complete file inventory: compact QuickLook-thumbnail rows over Card.attachments — no reference tracking, subfolders tolerated and unsurfaced — with a quiet header add affordance and the drop hint empty state. The whole window is the file-drop surface, Edit mode included (the editor's drag types were already filtered; now tested), sharing the board's folder-refusal semantics literally: FinderDrop moved verbatim into its own file so both windows run the same partition and loss row. Dragged text still lands at the caret and is inert elsewhere — the window delegate accepts file payloads only. Rows open on double-click or Return, drag out their file URL, and Remove is a bracketed write through FileManager.trashItem — the system Trash, never a hard delete, returning the in-Trash URL so the promise is testable; the attachment listing is the guard, so traversal and subfolder names refuse in one line. Keyboard-native per 05: the section is one Tab stop, arrows walk rows by name, Space toggles the shared QuickLook panel, Backspace removes. File > Add Attachment (shift-cmd-A) comes alive through the same import path. Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -322,12 +322,15 @@ private final class DuplicateCancellation {
|
||||
/// will drop) disables rather than falling back to the root: revealing the wrong thing is worse
|
||||
/// than nothing, and only a genuinely empty selection means "the board".
|
||||
///
|
||||
// m6-card-window: the item's third scope — the card's folder, or the selected attachment's file
|
||||
// when the attachments section is focused — adds a focused value and a branch here; the two below
|
||||
// do not move.
|
||||
/// **The card-window scope is the third branch**, and it is the one the attachment row's context
|
||||
/// menu twins (11-command-nexus.md ▸ Context menus): "card window: the card's folder — the selected
|
||||
/// attachment's file instead when the attachments section is focused". The rule itself is
|
||||
/// `CardAttachments.revealURLs`, so the menu row and the row's own Reveal cannot disagree about what
|
||||
/// "the selected attachment" means.
|
||||
struct RevealInFinderCommand: View {
|
||||
|
||||
@FocusedValue(\.boardStore) private var store
|
||||
@FocusedValue(\.cardAttachments) private var attachments
|
||||
@FocusedValue(\.welcomeSelection) private var selection
|
||||
|
||||
var body: some View {
|
||||
@@ -338,7 +341,8 @@ struct RevealInFinderCommand: View {
|
||||
}
|
||||
|
||||
/// What the item would reveal, and therefore whether it is enabled — one answer for both, the
|
||||
/// codebase's usual shape. The board in front wins; the welcome branch stands when no board is.
|
||||
/// codebase's usual shape. The board in front wins; the card-window branch stands when a card
|
||||
/// window is; the welcome branch stands when neither is.
|
||||
private var urls: [URL] {
|
||||
if let store {
|
||||
let ids = store.selection.ids
|
||||
@@ -346,6 +350,13 @@ struct RevealInFinderCommand: View {
|
||||
return TrashModel.paths(of: ids, on: store.selection.liveness, in: store.snapshot)
|
||||
.map { $0.folder(under: store.rootURL) }
|
||||
}
|
||||
if let attachments {
|
||||
return CardAttachments.revealURLs(
|
||||
cardFolder: attachments.cardFolder,
|
||||
selectedURL: attachments.selectedURL,
|
||||
isSectionFocused: attachments.isFocused
|
||||
)
|
||||
}
|
||||
guard let selection, selection.canReveal, let url = selection.url else { return [] }
|
||||
return [url]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user