refactor(opensidian): consolidate state, eliminate duplication, and reorganize by concern#1541
Merged
refactor(opensidian): consolidate state, eliminate duplication, and reorganize by concern#1541
Conversation
… O(1) path lookups - Consolidate dialog open/close state into fsState factory (zone 2) - Add openCreate/closeCreate/openRename/closeRename/openDelete/closeDelete actions - Extract withErrorToast helper to eliminate 5 duplicate try/catch/toast patterns - Add walkTree<T> generic tree traversal method for reuse by components - Add idToPath reverse map to FileSystemIndex for O(1) getPathById lookups - Replace O(n) allPaths() iteration in selectedPath and getPathForId with O(1) lookups
…tree and toolbar - Dialogs now read open/mode state from fsState singleton (no props) - AppShell renders CreateDialog, RenameDialog, DeleteConfirmation once - FileTreeItem: stripped 4 dialog state vars, 3 helper fns, 3 dialog instances - Toolbar: stripped 4 dialog state vars, 4 open fns, 3 dialog instances - Context menu handlers inline fsState.actions.selectFile + openCreate/Rename/Delete
… CommandPalette - FileTree.visibleIds: replaced 15-line recursive walk with 4-line walkTree call - CommandPalette.allFiles: replaced 20-line recursive collect with 8-line walkTree call - Both now delegate the getChildIds/getRow/null-check loop to fsState.walkTree
- /fs/fs-state.svelte -> /state/fs-state.svelte - /fs/file-icons -> /utils/file-icons - Relative component imports updated for tree/, editor/, dialogs/ subdirectories
…pace.ts Split createFsState() into two modules so workspace infrastructure (Yjs workspace, filesystem, extensions) lives in pure TypeScript separate from Svelte reactive UI state. Consumers that only need infra (Toolbar, ContentEditor) now import directly from workspace.ts.
…posures Match monorepo convention (tab-manager, whispering) by placing workspace infrastructure at lib/ root instead of state/. Remove window.workspace and window.fsState debug exposures—can be re-added when needed.
Remove documents, filesDb, and sqliteIndex aliases from workspace.ts. Export ws directly so consumers access ws.tables.files and ws.documents.files.content without intermediate variables.
Resolve 9 conflicts between the PR's architectural improvements and main's inline-editing UI evolution: - Keep workspace.ts extraction, walkTree, O(1) path lookups, withErrorToast - Adopt main's InlineNameInput for create/rename (delete Create/RenameDialog) - Adopt main's flattened API surface (no actions namespace) - Adopt main's command-palette upgrade and @lucide/svelte imports - Centralize DeleteConfirmation state in fsState, render once in AppShell - Move InlineNameInput into tree/ subdirectory to match file reorganization
…criminated union Replace renamingId/inlineCreate/deleteDialogOpen with a single InteractionMode union so impossible state combinations are unrepresentable. Add contextMenuTargetId for hover persistence while a context menu is open, and fix the InlineNameInput blur race that caused 'New File' from context menu to silently cancel.
Reword derived-getters comment to indicate permanent API (not migration scaffolding). Rename blurConfirmed → confirmed and document why the rAF blur deferral exists.
Contributor
|
Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement. This is a one-time requirement—it lets us offer commercial licenses for the sync server while you retain full copyright on your code. To sign, please comment on this PR with:
I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
…ring skill Positive framing for when keeping 1-3 line duplications inline is more readable than extracting a helper. Includes readability test, concrete examples, and threshold for when extraction IS worth it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Opensidian's single
createFsState()factory was doing too much—creating the workspace infrastructure, managing UI reactive state, and proxying infra internals through its return object. Meanwhile, dialog components were instantiated per tree node (300+ instances for 100 files), tree traversal logic was duplicated across components, and path lookups were O(n) scans.This PR splits the architecture into two clean layers, eliminates the duplication, and reorganizes files by concern.
Workspace vs. UI state separation
createFsState()previously owned both workspace creation (Yjs, extensions, filesystem) and Svelte reactive state (active file, open tabs, dialogs, focus). Now they're separate modules:Components that need raw infra (Toolbar for sample data, ContentEditor for document handles) import
workspace.tsdirectly instead of reaching throughfsState.fsorfsState.documents.Dialog consolidation
Before: 3 dialogs (Create, Rename, Delete) instantiated in both FileTreeItem and Toolbar—7 duplicate
$state(false)declarations, 7 duplicate helper functions, and N×3 dialog instances (one set per tree node).After: Dialog state lives in
fsState, dialogs render once in AppShell, and context menu handlers are one-liners:withErrorToasthelperFive actions had identical try/catch/toast.error/console.error blocks. Now they use a shared zone-3 helper:
walkTree<T>generic traversalFileTree and CommandPalette both had 15-20 line recursive tree walks with the same getChildIds→getRow→null-check→recurse pattern. Now they use a shared method:
O(1) path lookups
getPathForId(id)andselectedPathwere iterating all paths linearly. Added a reverseidToPathmap tocreateFileSystemIndexin@epicenter/filesystem:File reorganization