Sapling/Sources/SaplingUI/WorkspaceTreeView.swift

82 lines
2.4 KiB
Swift

import SwiftUI
import SaplingCore
public struct WorkspaceTreeView: View {
private let workspace: Workspace
private let onSelectFile: (WorkspaceFile) -> Void
private let onSelectProject: (Project) -> Void
public init(
workspace: Workspace,
onSelectFile: @escaping (WorkspaceFile) -> Void,
onSelectProject: @escaping (Project) -> Void
) {
self.workspace = workspace
self.onSelectFile = onSelectFile
self.onSelectProject = onSelectProject
}
public var body: some View {
List {
Section(workspace.name) {
ForEach(workspace.items) { item in
WorkspaceItemRow(
item: item,
onSelectFile: onSelectFile,
onSelectProject: onSelectProject
)
}
}
}
.listStyle(.sidebar)
.navigationTitle("Workspace")
}
}
private struct WorkspaceItemRow: View {
let item: WorkspaceItem
let onSelectFile: (WorkspaceFile) -> Void
let onSelectProject: (Project) -> Void
var body: some View {
switch item {
case .folder(let folder):
DisclosureGroup {
ForEach(folder.children) { child in
WorkspaceItemRow(
item: child,
onSelectFile: onSelectFile,
onSelectProject: onSelectProject
)
}
} label: {
Label(folder.name, systemImage: "folder")
}
case .file(let file):
Button {
onSelectFile(file)
} label: {
Label(file.name, systemImage: iconName(for: file.kind))
}
.buttonStyle(.plain)
case .project(let project):
Button {
onSelectProject(project)
} label: {
Label(project.name, systemImage: "point.3.connected.trianglepath.dotted")
}
.buttonStyle(.plain)
case .subproject(let subproject):
Label(subproject.name, systemImage: "rectangle.connected.to.line.below")
.foregroundStyle(.secondary)
}
}
private func iconName(for kind: WorkspaceFileKind) -> String {
switch kind {
case .markdown: "doc.plaintext"
case .attachment: "paperclip"
case .other: "doc"
}
}
}