From 1fdff50bcd9707ff6b3167d2ef4a5ab8d01eddeb Mon Sep 17 00:00:00 2001 From: Shane Becker Date: Thu, 25 Jun 2026 17:55:04 -0700 Subject: [PATCH 1/2] Renaming --- Sources/FileTree/FileTree.swift | 24 ++++++++++++++++++++---- Sources/FileTree/FileTreeStore.swift | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Sources/FileTree/FileTree.swift b/Sources/FileTree/FileTree.swift index 980f44c..9af2eb0 100644 --- a/Sources/FileTree/FileTree.swift +++ b/Sources/FileTree/FileTree.swift @@ -37,6 +37,14 @@ public struct FileTree: View { initiallyExpanded: true ) } + .focusable() + .onKeyPress(.return) { + guard store.renamingNode == nil else { return .ignored } + guard let selected = store.selectedNode else { return .ignored } + guard config.clickBehavior.enterKey == .rename else { return .ignored } + store.renamingNode = selected + return .handled + } } else { ProgressView() .frame(maxWidth: .infinity, maxHeight: .infinity) @@ -69,7 +77,6 @@ struct FileTreeDisclosureNode: View { let store: FileTreeStore let config: FileTreeConfiguration var initiallyExpanded: Bool = false - @State private var isRenaming = false init( node: FileTreeNode, @@ -86,6 +93,15 @@ struct FileTreeDisclosureNode: View { } } + private var isRenaming: Binding { + Binding( + get: { store.renamingNode === node }, + set: { newValue in + store.renamingNode = newValue ? node : nil + } + ) + } + var body: some View { if node.isFolder { DisclosureGroup(isExpanded: $node.isExpanded) { @@ -114,7 +130,7 @@ struct FileTreeDisclosureNode: View { isFocused: store.isFocused(node), isOpen: store.isOpen(node), isModified: store.isModified(node), - isRenaming: $isRenaming, + isRenaming: isRenaming, onRename: { newName in Task { try? await store.renameNode(node, to: newName) } } @@ -134,7 +150,7 @@ struct FileTreeDisclosureNode: View { .onTapGesture(count: 1) { if store.selectedNode === node { if config.clickBehavior.selectedLabelClick == .rename { - isRenaming = true + isRenaming.wrappedValue = true } } else { store.select(node) @@ -146,7 +162,7 @@ struct FileTreeDisclosureNode: View { node: node, store: store, menuConfiguration: config.contextMenu, - onRenameRequest: { isRenaming = true } + onRenameRequest: { store.renamingNode = node } ) } } diff --git a/Sources/FileTree/FileTreeStore.swift b/Sources/FileTree/FileTreeStore.swift index e6ca542..86f665f 100644 --- a/Sources/FileTree/FileTreeStore.swift +++ b/Sources/FileTree/FileTreeStore.swift @@ -6,6 +6,7 @@ import Observation public final class FileTreeStore { public let rootNode: FileTreeNode public var selectedNode: FileTreeNode? + public var renamingNode: FileTreeNode? public var interactionMode: InteractionMode = .normal public var filterQuery: String = "" public var filterHeuristic: FilterHeuristic = .fuzzy From 95818e0bda11102c2e60fcbb5b5f95c792b31207 Mon Sep 17 00:00:00 2001 From: Shane Becker Date: Thu, 25 Jun 2026 17:56:05 -0700 Subject: [PATCH 2/2] TEMP README, to make a test PR --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 76d7b3f..d0bc144 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +temptestpr + # FileTree A convention-over-configuration SwiftUI component for adding a file/folder tree sidebar to macOS apps.