diff --git a/Sources/SaplingUI/WorkspaceTreeView.swift b/Sources/SaplingUI/WorkspaceTreeView.swift index ae2e240..a95cc4d 100644 --- a/Sources/SaplingUI/WorkspaceTreeView.swift +++ b/Sources/SaplingUI/WorkspaceTreeView.swift @@ -34,7 +34,7 @@ public struct WorkspaceTreeView: View { if let workspace { List(selection: $selection) { Section(workspace.name) { - ForEach(workspace.items) { item in + ForEach(workspace.items, id: \.stableTreeID) { item in WorkspaceItemRow( item: item, selection: $selection, @@ -69,7 +69,7 @@ private struct WorkspaceItemRow: View { switch item { case .folder(let folder): DisclosureGroup { - ForEach(folder.children) { child in + ForEach(folder.children, id: \.stableTreeID) { child in WorkspaceItemRow( item: child, selection: $selection, @@ -86,17 +86,21 @@ private struct WorkspaceItemRow: View { } .tag(WorkspaceTreeSelection.folder(folder.url)) case .file(let file): - Label(file.name, systemImage: iconName(for: file.kind)) - .foregroundStyle(file.kind == .markdown ? .primary : .secondary) - .contentShape(Rectangle()) - .onTapGesture { + Button { + if file.kind == .markdown { selection = .file(file.url) onSelectFile(file) } - .tag(WorkspaceTreeSelection.file(file.url)) + } label: { + Label(file.name, systemImage: iconName(for: file.kind)) + .foregroundStyle(file.kind == .markdown ? .primary : .secondary) + } + .buttonStyle(.plain) + .disabled(file.kind != .markdown) + .tag(WorkspaceTreeSelection.file(file.url)) case .project(let project): DisclosureGroup { - ForEach(project.children) { child in + ForEach(project.children, id: \.stableTreeID) { child in WorkspaceItemRow( item: child, selection: $selection, @@ -130,3 +134,18 @@ private struct WorkspaceItemRow: View { } } } + +private extension WorkspaceItem { + var stableTreeID: URL { + switch self { + case .folder(let folder): + return folder.url.standardizedFileURL + case .file(let file): + return file.url.standardizedFileURL + case .project(let project): + return project.repositoryURL.standardizedFileURL + case .subproject(let subproject): + return subproject.repositoryURL.standardizedFileURL + } + } +}