Skip to content

Latest commit

 

History

History
156 lines (123 loc) · 4.9 KB

File metadata and controls

156 lines (123 loc) · 4.9 KB

Provider Refactoring Summary

Problem Solved

The original FileProvider was a massive "god component" that violated the Single Responsibility Principle by handling:

  • File operations and file tree management
  • Editor state and content management
  • Navigation history and file selection
  • UI settings (spell check, suggestions, highlighting)
  • Auto-saving logic
  • File renaming logic
  • 15+ individual useState hooks
  • Complex interdependencies between states
  • Side effects scattered throughout with numerous useEffects

New Architecture

We've broken down the monolithic FileProvider into 4 focused providers:

1. FileSystemProvider (src/contexts/FileSystemProvider.tsx)

Responsibility: File operations and file tree management

State:

  • vaultFilesTree: File tree structure
  • vaultFilesFlattened: Flattened file list
  • expandedDirectories: Directory expansion state

Operations:

  • createFileIfNotExists(): Create files
  • renameFile(): Rename files
  • deleteFile(): Delete files
  • readFileContent(): Read file content
  • writeFileAndCacheContent(): Write file content
  • prefetchFile(): Preload file content
  • handleNewFileRenaming(): Auto-rename logic
  • handleDirectoryToggle(): Directory expansion
  • refreshFileTree(): Refresh file tree

2. EditorProvider (src/contexts/EditorProvider.tsx)

Responsibility: Editor state and content management

State:

  • currentlyOpenFilePath: Currently open file
  • currentlyChangingFilePath: File switching state
  • needToWriteEditorContentToDisk: Auto-save flag
  • needToIndexEditorContent: Indexing flag

Operations:

  • loadFileIntoEditor(): Load file into editor
  • saveCurrentlyOpenedFile(): Save current file
  • openOrCreateFile(): Open or create file
  • writeEditorContentToDisk(): Write content to disk
  • triggerIndexing(): Trigger file indexing

Auto-save Logic:

  • Debounced auto-save on content changes
  • Auto-save on window close
  • Welcome note for first-time users

3. NavigationProvider (src/contexts/NavigationProvider.tsx)

Responsibility: Navigation history and file selection

State:

  • navigationHistory: File navigation history
  • selectedDirectory: Currently selected directory
  • noteToBeRenamed: File rename state
  • fileDirToBeRenamed: Directory rename state

Operations:

  • addToNavigationHistory(): Add to history
  • removeFromNavigationHistory(): Remove from history
  • Directory and file selection management

4. UISettingsProvider (src/contexts/UISettingsProvider.tsx)

Responsibility: UI-specific state management

State:

  • spellCheckEnabled: Spell check setting
  • suggestionsState: Editor suggestions
  • highlightData: Text highlighting data

Operations:

  • Load spell check setting from storage
  • Manage editor suggestions and highlighting

Provider Hierarchy

QueryClientProvider
└── FileCacheProvider
    └── FileSystemProvider
        └── EditorProvider
            └── NavigationProvider
                └── UISettingsProvider
                    └── FileProvider (Facade)
                        └── ChatProvider
                            └── ContentProvider
                                └── ModalProvider

Benefits

Single Responsibility

Each provider has a clear, focused responsibility

Reduced Complexity

  • Smaller, manageable components
  • Clear separation of concerns
  • Easier to test and debug

Better State Management

  • Logical grouping of related state
  • Reduced interdependencies
  • Cleaner state flow

Improved Maintainability

  • Easier to modify individual features
  • Better code organization
  • Clearer dependencies

Enhanced Reusability

  • Providers can be used independently
  • Easier to compose functionality
  • Better for testing

Migration Strategy

The FileProvider now acts as a facade that combines all the functionality from the focused providers, ensuring backward compatibility with existing components.

Components can still use:

const { 
  vaultFilesTree, 
  currentlyOpenFilePath, 
  openOrCreateFile,
  // ... all existing properties
} = useFileContext()

Or use specific providers directly:

const { vaultFilesTree, createFileIfNotExists } = useFileSystem()
const { editor, loadFileIntoEditor } = useEditor()
const { navigationHistory, addToNavigationHistory } = useNavigation()
const { spellCheckEnabled, setSpellCheckEnabled } = useUISettings()

Next Steps

  1. Gradual Migration: Components can gradually migrate to use specific providers
  2. Testing: Each provider can be tested independently
  3. Documentation: Add JSDoc comments to all provider methods
  4. Performance: Monitor for any performance impacts and optimize if needed

This refactoring transforms a monolithic, hard-to-maintain provider into a clean, modular architecture that follows React best practices and the Single Responsibility Principle.