fix(workspace): refresh expanded folder contents
This commit is contained in:
parent
3b9b165464
commit
bfedd11186
2 changed files with 38 additions and 14 deletions
|
|
@ -62,6 +62,7 @@ private final class SaplingAppModel: ObservableObject {
|
|||
@Published var workspace: Workspace?
|
||||
@Published var workspaceChildren: [URL: [WorkspaceItem]] = [:]
|
||||
@Published var loadingTreeItemURLs: Set<URL> = []
|
||||
@Published var workspaceTreeRevision = 0
|
||||
@Published var workspaceSelection: WorkspaceTreeSelection?
|
||||
@Published var selectedProject: Project?
|
||||
@Published var selectedDocument: MarkdownDocument?
|
||||
|
|
@ -133,6 +134,7 @@ private final class SaplingAppModel: ObservableObject {
|
|||
self.workspace = workspace
|
||||
workspaceChildren = [:]
|
||||
loadingTreeItemURLs = []
|
||||
invalidateWorkspaceTree()
|
||||
workspaceSelection = nil
|
||||
selectedProject = nil
|
||||
selectedDocument = nil
|
||||
|
|
@ -167,6 +169,7 @@ private final class SaplingAppModel: ObservableObject {
|
|||
var loadingURLs = loadingTreeItemURLs
|
||||
loadingURLs.insert(url)
|
||||
loadingTreeItemURLs = loadingURLs
|
||||
invalidateWorkspaceTree()
|
||||
let workspaceManager = self.workspaceManager
|
||||
Task {
|
||||
do {
|
||||
|
|
@ -176,6 +179,7 @@ private final class SaplingAppModel: ObservableObject {
|
|||
var loadedChildren = workspaceChildren
|
||||
loadedChildren[url] = children
|
||||
workspaceChildren = loadedChildren
|
||||
invalidateWorkspaceTree()
|
||||
} catch {
|
||||
editorErrorMessage = "Unable to load \(item.displayName): \(error.localizedDescription)"
|
||||
logger.error("Failed to load workspace tree item: \(error)", category: .workspace)
|
||||
|
|
@ -183,6 +187,7 @@ private final class SaplingAppModel: ObservableObject {
|
|||
var loadingURLs = loadingTreeItemURLs
|
||||
loadingURLs.remove(url)
|
||||
loadingTreeItemURLs = loadingURLs
|
||||
invalidateWorkspaceTree()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,6 +258,10 @@ private final class SaplingAppModel: ObservableObject {
|
|||
configuration.recentWorkspaceURLs = Array(configuration.recentWorkspaceURLs.prefix(10))
|
||||
save(configuration: configuration)
|
||||
}
|
||||
|
||||
private func invalidateWorkspaceTree() {
|
||||
workspaceTreeRevision &+= 1
|
||||
}
|
||||
}
|
||||
|
||||
private struct MainWindow: View {
|
||||
|
|
@ -265,6 +274,7 @@ private struct MainWindow: View {
|
|||
WorkspaceTreeView(
|
||||
workspace: model.workspace,
|
||||
isLoadingWorkspace: model.isLoadingWorkspace,
|
||||
treeContentRevision: model.workspaceTreeRevision,
|
||||
selection: $model.workspaceSelection,
|
||||
childrenFor: model.children(for:),
|
||||
isLoadingChildren: model.isLoadingChildren(for:),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ public enum WorkspaceTreeSelection: Hashable, Sendable {
|
|||
public struct WorkspaceTreeView: View {
|
||||
private let workspace: Workspace?
|
||||
private let isLoadingWorkspace: Bool
|
||||
private let treeContentRevision: Int
|
||||
@Binding private var selection: WorkspaceTreeSelection?
|
||||
private let childrenFor: (WorkspaceItem) -> [WorkspaceItem]
|
||||
private let isLoadingChildren: (WorkspaceItem) -> Bool
|
||||
|
|
@ -22,6 +23,7 @@ public struct WorkspaceTreeView: View {
|
|||
public init(
|
||||
workspace: Workspace?,
|
||||
isLoadingWorkspace: Bool = false,
|
||||
treeContentRevision: Int = 0,
|
||||
selection: Binding<WorkspaceTreeSelection?>,
|
||||
childrenFor: @escaping (WorkspaceItem) -> [WorkspaceItem] = { $0.children ?? [] },
|
||||
isLoadingChildren: @escaping (WorkspaceItem) -> Bool = { _ in false },
|
||||
|
|
@ -32,6 +34,7 @@ public struct WorkspaceTreeView: View {
|
|||
) {
|
||||
self.workspace = workspace
|
||||
self.isLoadingWorkspace = isLoadingWorkspace
|
||||
self.treeContentRevision = treeContentRevision
|
||||
self._selection = selection
|
||||
self.childrenFor = childrenFor
|
||||
self.isLoadingChildren = isLoadingChildren
|
||||
|
|
@ -53,6 +56,7 @@ public struct WorkspaceTreeView: View {
|
|||
ForEach(workspace.items, id: \.stableTreeID) { item in
|
||||
WorkspaceItemRow(
|
||||
item: item,
|
||||
treeContentRevision: treeContentRevision,
|
||||
selection: $selection,
|
||||
childrenFor: childrenFor,
|
||||
isLoadingChildren: isLoadingChildren,
|
||||
|
|
@ -87,6 +91,7 @@ public struct WorkspaceTreeView: View {
|
|||
|
||||
private struct WorkspaceItemRow: View {
|
||||
let item: WorkspaceItem
|
||||
let treeContentRevision: Int
|
||||
@Binding var selection: WorkspaceTreeSelection?
|
||||
let childrenFor: (WorkspaceItem) -> [WorkspaceItem]
|
||||
let isLoadingChildren: (WorkspaceItem) -> Bool
|
||||
|
|
@ -159,22 +164,26 @@ private struct WorkspaceItemRow: View {
|
|||
|
||||
@ViewBuilder
|
||||
private var children: some View {
|
||||
if isLoadingChildren(item) {
|
||||
Label("Loading...", systemImage: "progress.indicator")
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
ForEach(childrenFor(item), id: \.stableTreeID) { child in
|
||||
WorkspaceItemRow(
|
||||
item: child,
|
||||
selection: $selection,
|
||||
childrenFor: childrenFor,
|
||||
isLoadingChildren: isLoadingChildren,
|
||||
onExpandItem: onExpandItem,
|
||||
onSelectFile: onSelectFile,
|
||||
onSelectProject: onSelectProject
|
||||
)
|
||||
Group {
|
||||
if isLoadingChildren(item) {
|
||||
Label("Loading...", systemImage: "progress.indicator")
|
||||
.foregroundStyle(.secondary)
|
||||
} else {
|
||||
ForEach(childrenFor(item), id: \.stableTreeID) { child in
|
||||
WorkspaceItemRow(
|
||||
item: child,
|
||||
treeContentRevision: treeContentRevision,
|
||||
selection: $selection,
|
||||
childrenFor: childrenFor,
|
||||
isLoadingChildren: isLoadingChildren,
|
||||
onExpandItem: onExpandItem,
|
||||
onSelectFile: onSelectFile,
|
||||
onSelectProject: onSelectProject
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.id(WorkspaceChildrenContentID(itemURL: item.stableTreeID, revision: treeContentRevision))
|
||||
}
|
||||
|
||||
private func iconName(for kind: WorkspaceFileKind) -> String {
|
||||
|
|
@ -186,6 +195,11 @@ private struct WorkspaceItemRow: View {
|
|||
}
|
||||
}
|
||||
|
||||
private struct WorkspaceChildrenContentID: Hashable {
|
||||
var itemURL: URL
|
||||
var revision: Int
|
||||
}
|
||||
|
||||
private extension WorkspaceItem {
|
||||
var stableTreeID: URL {
|
||||
switch self {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue