Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions apps/desktop/src/components/collection-view/collection-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { type MouseEvent, useCallback, useMemo, useRef } from "react"
import { useShallow } from "zustand/shallow"
import { useRenameNoteWithAI } from "@/components/common/explorer-agent/hooks/use-rename-note-with-ai"
import { useResizablePanel } from "@/hooks/use-resizable-panel"
import { useStore } from "@/store"
import { computeCollectionEntries, useStore } from "@/store"
import { isMac } from "@/utils/platform"
import { useCollectionContextMenu } from "./hooks/use-collection-context-menu"
import { useCollectionRename } from "./hooks/use-collection-rename"
Expand All @@ -28,7 +28,7 @@ export function CollectionView() {
isFileExplorerOpen,
currentCollectionPath,
setCurrentCollectionPath,
collectionEntries,
entries,
tab,
openTab,
activeTabSaved,
Expand All @@ -41,7 +41,7 @@ export function CollectionView() {
isFileExplorerOpen: state.isFileExplorerOpen,
currentCollectionPath: state.currentCollectionPath,
setCurrentCollectionPath: state.setCurrentCollectionPath,
collectionEntries: state.collectionEntries,
entries: state.entries,
tab: state.getActiveTab(),
openTab: state.openTab,
activeTabSaved: state.getIsSaved(),
Expand All @@ -66,6 +66,10 @@ export function CollectionView() {
const displayName = currentCollectionPath
? getFolderNameFromPath(currentCollectionPath)
: undefined
const collectionEntries = useMemo(
() => computeCollectionEntries(currentCollectionPath, entries),
[currentCollectionPath, entries],
)

const {
sortedEntries,
Expand Down
1 change: 1 addition & 0 deletions packages/store/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type {
} from "./ai-settings/credentials"
export type { OllamaModels } from "./ai-settings/ollama-types"
export type { BrowserStorageLike } from "./browser-storage"
export { computeCollectionEntries } from "./collection/helpers/collection-entries"
export type { EditorSlice } from "./editor/editor-slice"
export { prepareEditorSlice } from "./editor/editor-slice"
export type {
Expand Down
14 changes: 5 additions & 9 deletions packages/store/src/workspace/collection/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ describe("workspace collection event handlers", () => {

expect(store.getState().currentCollectionPath).toBeNull()
expect(store.getState().lastCollectionPath).toBeNull()
expect(store.getState().collectionEntries).toEqual([])
})

it("onEntryRenamed rewrites descendant current and last paths", () => {
Expand All @@ -55,10 +54,9 @@ describe("workspace collection event handlers", () => {
})

store.getState().onEntryRenamed({
oldPath: "/ws/old",
newPath: "/ws/new",
sourcePath: "/ws/old",
targetPath: "/ws/new",
isDirectory: true,
newName: "new",
})

expect(store.getState().currentCollectionPath).toBe("/ws/new/child")
Expand All @@ -75,8 +73,7 @@ describe("workspace collection event handlers", () => {

store.getState().onEntryMoved({
sourcePath: "/ws/src",
destinationDirPath: "/ws",
newPath: "/ws/dest",
targetPath: "/ws/dest",
isDirectory: true,
})

Expand All @@ -93,10 +90,9 @@ describe("workspace collection event handlers", () => {
})

store.getState().onEntryRenamed({
oldPath: "/ws/other",
newPath: "/ws/new-other",
sourcePath: "/ws/other",
targetPath: "/ws/new-other",
isDirectory: true,
newName: "new-other",
})

expect(store.getState().currentCollectionPath).toBe("/ws/keep/current")
Expand Down
161 changes: 52 additions & 109 deletions packages/store/src/workspace/collection/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
import { isPathEqualOrDescendant } from "@mdit/utils/path-utils"
import type { StoreApi } from "zustand"
import { computeCollectionEntries } from "../../collection/helpers/collection-entries"
import type { WorkspaceEntry } from "../workspace-state"

type EntryCreatedInput = {
parentPath: string
entry: WorkspaceEntry
expandParent?: boolean
expandNewDirectory?: boolean
}

type EntriesDeletedInput = {
paths: string[]
}

type EntryRenamedInput = {
oldPath: string
newPath: string
sourcePath: string
targetPath: string
isDirectory: boolean
newName: string
clearSyncedName?: boolean
}

type EntryMovedInput = {
sourcePath: string
destinationDirPath: string
newPath: string
targetPath: string
isDirectory: boolean
refreshContent?: boolean
}

export type WorkspaceCollectionState = {
currentCollectionPath: string | null
lastCollectionPath: string | null
collectionEntries: WorkspaceEntry[]
}

export type WorkspaceCollectionActions = {
Expand All @@ -42,8 +28,6 @@ export type WorkspaceCollectionActions = {
) => void
resetCollectionPath: () => void
toggleCollectionView: () => void
refreshCollectionEntries: () => void
onEntryCreated: (input: EntryCreatedInput) => void
onEntriesDeleted: (input: EntriesDeletedInput) => void
onEntryRenamed: (input: EntryRenamedInput) => void
onEntryMoved: (input: EntryMovedInput) => void
Expand All @@ -52,32 +36,63 @@ export type WorkspaceCollectionActions = {
export type WorkspaceCollectionSlice = WorkspaceCollectionState &
WorkspaceCollectionActions

type CollectionStoreState = WorkspaceCollectionState & {
entries: WorkspaceEntry[]
}
type CollectionStoreState = WorkspaceCollectionState

const replacePathPrefixIfDescendant = (
path: string | null,
oldPath: string,
newPath: string,
sourcePath: string,
targetPath: string,
): string | null => {
if (!path || !isPathEqualOrDescendant(path, oldPath)) {
if (!path || !isPathEqualOrDescendant(path, sourcePath)) {
return path
}

if (path === oldPath) {
return newPath
if (path === sourcePath) {
return targetPath
}

return `${newPath}${path.slice(oldPath.length)}`
return `${targetPath}${path.slice(sourcePath.length)}`
}

const rebaseCollectionPaths = (
state: WorkspaceCollectionState,
sourcePath: string,
targetPath: string,
isDirectory: boolean,
): WorkspaceCollectionState => {
if (!isDirectory) {
return state
}

const nextCurrentCollectionPath = replacePathPrefixIfDescendant(
state.currentCollectionPath,
sourcePath,
targetPath,
)
const nextLastCollectionPath = replacePathPrefixIfDescendant(
state.lastCollectionPath,
sourcePath,
targetPath,
)

if (
nextCurrentCollectionPath === state.currentCollectionPath &&
nextLastCollectionPath === state.lastCollectionPath
) {
return state
}

return {
currentCollectionPath: nextCurrentCollectionPath,
lastCollectionPath: nextLastCollectionPath,
}
}
Comment thread
hhhjin marked this conversation as resolved.

export const buildWorkspaceCollectionState = (
overrides?: Partial<WorkspaceCollectionState>,
): WorkspaceCollectionState => ({
currentCollectionPath: null,
lastCollectionPath: null,
collectionEntries: [],
...overrides,
})

Expand Down Expand Up @@ -108,7 +123,6 @@ export const createWorkspaceCollectionActions = <
currentCollectionPath: nextPath,
lastCollectionPath:
nextPath !== null ? nextPath : state.lastCollectionPath,
collectionEntries: computeCollectionEntries(nextPath, get().entries),
}
})
},
Expand All @@ -122,37 +136,14 @@ export const createWorkspaceCollectionActions = <
if (currentCollectionPath !== null) {
setCollectionState({
currentCollectionPath: null,
collectionEntries: [],
})
} else if (lastCollectionPath !== null) {
setCollectionState({
currentCollectionPath: lastCollectionPath,
collectionEntries: computeCollectionEntries(
lastCollectionPath,
get().entries,
),
})
}
},

refreshCollectionEntries: () => {
setCollectionState((state) => ({
collectionEntries: computeCollectionEntries(
state.currentCollectionPath,
get().entries,
),
}))
},

onEntryCreated: (_input) => {
setCollectionState((state) => ({
collectionEntries: computeCollectionEntries(
state.currentCollectionPath,
get().entries,
),
}))
},

onEntriesDeleted: ({ paths }) => {
setCollectionState((state) => {
const { currentCollectionPath, lastCollectionPath } = state
Expand All @@ -177,68 +168,20 @@ export const createWorkspaceCollectionActions = <
return {
currentCollectionPath: nextCurrentCollectionPath,
lastCollectionPath: nextLastCollectionPath,
collectionEntries: computeCollectionEntries(
nextCurrentCollectionPath,
get().entries,
),
}
})
},

onEntryRenamed: ({ oldPath, newPath, isDirectory }) => {
setCollectionState((state) => {
const nextCurrentCollectionPath = isDirectory
? replacePathPrefixIfDescendant(
state.currentCollectionPath,
oldPath,
newPath,
)
: state.currentCollectionPath
const nextLastCollectionPath = isDirectory
? replacePathPrefixIfDescendant(
state.lastCollectionPath,
oldPath,
newPath,
)
: state.lastCollectionPath

return {
currentCollectionPath: nextCurrentCollectionPath,
lastCollectionPath: nextLastCollectionPath,
collectionEntries: computeCollectionEntries(
nextCurrentCollectionPath,
get().entries,
),
}
})
onEntryRenamed: ({ sourcePath, targetPath, isDirectory }) => {
setCollectionState((state) =>
rebaseCollectionPaths(state, sourcePath, targetPath, isDirectory),
)
},

onEntryMoved: ({ sourcePath, newPath, isDirectory }) => {
setCollectionState((state) => {
const nextCurrentCollectionPath = isDirectory
? replacePathPrefixIfDescendant(
state.currentCollectionPath,
sourcePath,
newPath,
)
: state.currentCollectionPath
const nextLastCollectionPath = isDirectory
? replacePathPrefixIfDescendant(
state.lastCollectionPath,
sourcePath,
newPath,
)
: state.lastCollectionPath

return {
currentCollectionPath: nextCurrentCollectionPath,
lastCollectionPath: nextLastCollectionPath,
collectionEntries: computeCollectionEntries(
nextCurrentCollectionPath,
get().entries,
),
}
})
onEntryMoved: ({ sourcePath, targetPath, isDirectory }) => {
setCollectionState((state) =>
rebaseCollectionPaths(state, sourcePath, targetPath, isDirectory),
)
},
}
}
12 changes: 0 additions & 12 deletions packages/store/src/workspace/lifecycle/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ describe("lifecycle-actions", () => {
unwatchFn: unwatch,
currentCollectionPath: "/old/folder",
lastCollectionPath: "/old/folder",
collectionEntries: [
{ path: "/old/folder/note.md", name: "note.md", isDirectory: false },
],
})
deps.historyRepository.listWorkspacePaths.mockResolvedValue([
"/new",
Expand All @@ -53,7 +50,6 @@ describe("lifecycle-actions", () => {
expect(getState().getIndexingConfig).toHaveBeenCalledWith("/new")
expect(getState().currentCollectionPath).toBeNull()
expect(getState().lastCollectionPath).toBeNull()
expect(getState().collectionEntries).toEqual([])
expect(getState().workspacePath).toBe("/new")
expect(getState().unwatchFn).toBeNull()
})
Expand Down Expand Up @@ -127,9 +123,6 @@ describe("lifecycle-actions", () => {
unwatchFn: unwatch,
currentCollectionPath: "/old/folder",
lastCollectionPath: "/old/folder",
collectionEntries: [
{ path: "/old/folder/note.md", name: "note.md", isDirectory: false },
],
})
deps.historyRepository.listWorkspacePaths.mockResolvedValue(["/other"])

Expand All @@ -140,7 +133,6 @@ describe("lifecycle-actions", () => {
expect(getState().resetIndexingState).toHaveBeenCalled()
expect(getState().currentCollectionPath).toBeNull()
expect(getState().lastCollectionPath).toBeNull()
expect(getState().collectionEntries).toEqual([])
expect(getState().workspacePath).toBeNull()
expect(getState().unwatchFn).toBeNull()
})
Expand Down Expand Up @@ -197,9 +189,6 @@ describe("lifecycle-actions", () => {
unwatchFn: unwatch,
currentCollectionPath: "/old/folder",
lastCollectionPath: "/old/folder",
collectionEntries: [
{ path: "/old/folder/note.md", name: "note.md", isDirectory: false },
],
})
deps.historyRepository.listWorkspacePaths.mockResolvedValue(["/new"])
deps.fileSystemRepository.isExistingDirectory.mockResolvedValue(true)
Expand All @@ -211,7 +200,6 @@ describe("lifecycle-actions", () => {
expect(getState().getIndexingConfig).toHaveBeenCalledWith("/new")
expect(getState().currentCollectionPath).toBeNull()
expect(getState().lastCollectionPath).toBeNull()
expect(getState().collectionEntries).toEqual([])
expect(getState().workspacePath).toBe("/new")
expect(getState().unwatchFn).toBeNull()
})
Expand Down
Loading
Loading