Repository navigation
Retain last folder on each tab for file functions - #4001
haslinghuis wants to merge 1 commit into
Conversation
✅ Deploy Preview for origin-betaflight-app ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
acefa48 to
03e1c9f
Compare
|
03e1c9f to
8e0a9f6
Compare
|
8e0a9f6 to
d6b986b
Compare
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
d6b986b to
9c22f04
Compare
|
|
🎉 Do you want to test this code? 🎉 |
|
Resolved in #5525 |




Some reference:
EDIT: New goal will be to create a single workspace and use board name to store all different files.
Now awaiting completion of Vue migration.
===
Workspace Directory — Implementation Plan
1. Concept
The user picks a root workspace folder once. The
FileSystemDirectoryHandleis stored in IndexedDB (the only storage API that can serialize directory handles). On subsequent visits, Chrome 122+ persistent permissions allow the app to re-acquirereadwriteaccess without a picker — only a one-time permission prompt on first use per session.When no workspace is configured, the original file-picker behavior is preserved unchanged.
Directory Structure
2. Platform Support
showDirectoryPickerDetection:
typeof window.showDirectoryPicker === "function"3. Chrome API Reference
Storing handles in IndexedDB
Per Chrome docs:
Persistent permissions (Chrome 122+)
Per Chrome blog:
4. Architecture
Why extend
FileSystem.js+ add a composableThe codebase has two consumption patterns:
CliTab.vue,useVtx.js,OptionsTab.vue, etc.AutoBackup.js(importsFileSystemdirectly)Solution: Add workspace methods to the
FileSystemsingleton (accessible everywhere), plus a thinuseWorkspace.jscomposable for Vue-reactive state inOptionsTab.vue.Category Constants
Storage
FileSystemDirectoryHandleBetaflightApp→ storehandles→ keyworkspace_rootworkspaceEnabledtoggleNo new npm dependencies — raw IndexedDB API (we store exactly one key).
5. File Changes
5a.
src/js/FileSystem.js— Core Workspace APIExtend the existing singleton. Zero breaking changes to existing
pickSaveFile/pickOpenFile.5b.
src/composables/useWorkspace.js— Vue Reactive WrapperThin composable for OptionsTab and any Vue component that needs reactive workspace state.
5c.
src/components/tabs/OptionsTab.vue— Workspace Setting UIAdd a new "File Storage" settings box. Follows the existing pattern (
gui_boxwithspacer).Template (add after "Main Options" box, ~line 99)
Script (additions to
setup())5d. App Startup —
src/js/main.jsAdd workspace initialization early in the startup sequence (after DOM ready, before tab loading):
This loads the stored handle from IndexedDB. No permission prompt — that happens on first user-gesture file operation.
5e. Consumer Changes — Save Operations
Every save site gets a try-workspace-or-fallback wrapper. The pattern is identical across all tabs:
Per-File Changes
saveFile()CLI_BACKUPloadFile()FIRMWAREself.selectedBoardas board overrideprepare_file()BLACKBOXopenWorkspaceFileForWriting)prepare_file()LOGSsave_lua(),save_json()VTXload_json()OSDFONT.openFontFile()onSaveConfigClick()CLI_BACKUPonLoadConfigClick()save()CLI_BACKUPopenImage()Open operations stay with picker
showOpenFilePickerdoesn't support setting an initial directory from a handle. Building a custom file browser UI is out of scope. Users may also want to open files from arbitrary locations. Save = workspace, Open = picker.5f. AutoBackup.js — Zero-Picker Backup (Key UX Win)
This is the biggest improvement. Currently AutoBackup shows a save dialog mid-flash. With workspace:
5g. Board Name for Firmware Flasher (Special Case)
The firmware flasher operates in two modes:
FC.CONFIG.boardName"MATEKF405""BETAFLIGHTF4"Pass the selected board as an override:
For AutoBackup (always runs while connected),
FC.CONFIG.boardNameis always available — no override needed.5h. i18n Strings
Add to
src/locales/en/messages.json:6. Error Handling
Every workspace operation is wrapped in try/catch with picker fallback. The app never breaks if workspace is misconfigured.
"unknown_board"subfolderinitWorkspace()catches error silently, workspace stays unconfiguredshowDirectoryPickerunsupportedisWorkspaceSupported()→ false, workspace UI hidden in OptionsgetDirectoryHandlethrows, caught → picker fallback7. Permission Flow
8. Implementation Phases
Phase 1 (this PR)
FileSystem.jsuseWorkspace.jscomposableOptionsTab.vueinitWorkspace()call in app startupPhase 2 (future)
Phase 3 (future)
@capacitor/filesystemusing app internal storage as workspace root9. File Impact Summary
src/js/FileSystem.js— workspace API + IndexedDB + categoriessrc/composables/useWorkspace.js— Vue reactive wrappersrc/components/tabs/OptionsTab.vue— "File Storage" settings boxsrc/js/main.js—initWorkspace()on startupsrc/composables/useCli.js— workspace-aware savesrc/composables/useVtx.js— workspace-aware savesrc/components/tabs/FirmwareFlasherTab.vue— workspace-aware save + board overridesrc/components/tabs/OnboardLoggingTab.vue— workspace-aware streaming savesrc/components/tabs/LoggingTab.vue— workspace-aware streaming savesrc/components/tabs/OsdTab.vue— workspace-aware savesrc/components/tabs/PresetsTab.vue— workspace-aware savesrc/js/utils/AutoBackup.js— workspace-aware save (zero picker)src/locales/en/messages.json— i18n stringssrc/js/LogoManager.js— open-only, keeps picker10. Testing Checklist