feat(file-browser): Modularize navigation history management - #2793
Open
AuDevTist1C wants to merge 1 commit into
Open
feat(file-browser): Modularize navigation history management#2793AuDevTist1C wants to merge 1 commit into
AuDevTist1C wants to merge 1 commit into
Conversation
2 tasks
Contributor
Greptile SummaryCommit
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope. No blocking failure remains. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Navigation request] --> B[getDir]
B -->|Success| C[NavStack mutation]
C --> D[Render directory]
C --> E[Microtask update event]
E --> F[Persist history]
E --> G[Update breadcrumbs]
E --> H[Synchronize back actions]
Reviews (5): Last reviewed commit: "feat(file-browser): Implement `NavStack`..." | Re-trigger Greptile |
AuDevTist1C
marked this pull request as ready for review
August 22, 2026 12:10
AuDevTist1C
force-pushed
the
refactor/fb-nav
branch
4 times, most recently
from
August 22, 2026 14:27
f338380 to
1e95b19
Compare
… management Abstract navigation tracking, history state management, and navbar UI syncing into a dedicated `EventTarget` class. Create `NavStack` class (`src/pages/fileBrowser/NavStack.js`): - Implement `NavStack` extending `EventTarget` with a custom `Symbol.toStringTag` property - Add `push`, `pop`, `popUntil`, `get` (supporting negative indexing), `has`, `on`, `off`, and `toJSON` methods with parameter validation - Maintain an internal `#urlSet` to prevent duplicate stack entries - Queue microtasks for `update` event dispatching, providing read-only `added` and `removed` location diffs in event details Integrate `NavStack` into file browser (`src/pages/fileBrowser/fileBrowser.js`): - Replace manual `state` array and direct `localStorage` persistence with a `NavStack` instance - Listen to `update` events on `NavStack` to persist state to `localStorage`, clean up removed navbar elements and `actionStack` entries, and register new back-navigation actions - Cache navbar DOM elements using a `navBarEls` Map with `getOrInsertComputed` - Refactor `navigate` to accept location objects or strings and manage stack state using `navStack.has`, `navStack.popUntil`, and `navStack.push` - Refactor `loadStates` to push history entries into `navStack` and navigate directly to the top item (`navStack.get(-1)`) - Update folder selection button state (`$openFolder.disabled`) in `render()` and remove obsolete `pushState()` helper function (AI generated commit message)
AuDevTist1C
force-pushed
the
refactor/fb-nav
branch
from
August 22, 2026 14:51
1e95b19 to
a478f90
Compare
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This pull request refactors and modernizes navigation history management within the Acode file browser module (
src/pages/fileBrowser/). Previously, navigation state tracking, local storage persistence, navbar breadcrumb DOM updates, and back-action stack synchronization were directly coupled and scattered across procedural helper functions infileBrowser.js.To improve maintainability, reactivity, and performance, this change introduces a dedicated$O(1)$ set lookups, microtask-batched reactivity for dynamic DOM diffing, and cleaner lifecycle tracking.
NavStackclass (src/pages/fileBrowser/NavStack.js) extending the standard Web APIEventTarget. The internal state management now utilizesArchitectural Motivation & Design Overview
1. Separation of Concerns & Class Encapsulation
In the original implementation, history state was stored in a mutable array (
state) that required manual filtering, array slicing, continuouslocalStorageserialization calls, and DOM query cleanups across functions likeMaps(),pushState(),loadStates(), and button action listeners.By abstracting state into an isolated$O(1)$ duplicate checking), preventing illegal external mutations and guaranteeing data integrity.
NavStackclass, navigation operations (push,pop,popUntil,get,has) are encapsulated behind a clear API contract. Internal tracking uses private class fields (#arrfor chronological stack ordering and#urlSetfor2. Batched Reactivity via Microtask Scheduling
Rather than triggering synchronous UI redraws or immediate
localStoragewrites on every individual stack mutation,NavStackleveragesqueueMicrotask()to batch pending updates. When history changes occur, additions and removals are recorded in a transient#updatedURLsstructure containing anaddedmap and aremovedset.At the end of the current task execution tick, an
updateCustomEventis dispatched. UI listeners (such as the main handler infileBrowser.js) receive read-only iterators overevent.detail.addedandevent.detail.removed, enabling unified, single-pass DOM breadcrumb synchronization, back-action stack pruning, and state persistence.Technical Implementation Details
1.
NavStackClass (src/pages/fileBrowser/NavStack.js)EventTargetand definesSymbol.toStringTagas"NavStack"on its prototype for proper introspection.#arr: InternalArray<Location>preserving historical stack ordering.#urlSet: InternalSet<string>used for instant URL membership checks and duplicate prevention.#updatedURLs: Internal state object capturing differential additions (Map<string, {name, index}>) and removals (Set<string>) between task ticks.#queueUpdateEvent): Ensures event emission is deferred to microtask timing, coalescing multiple sequential stack operations into a singleupdatedispatch.push(url, name): Accepts location objects or raw URL strings, validates inputs, checks#urlSet, appends state, and updates batch diffs.popUntil(url): Truncates history backwards to a target URL while collecting removed URLs for event notification.pop(): Convenience wrapper over#popUntil()to pop the top location entry.get(i): Provides standard and negative-indexed array lookup (e.g.,get(-1)yields the current top location) returning a cloned location object to preserve immutability.has(url): InstanttoJSON(): Returns a deep copy array of location objects for seamless compatibility withJSON.stringify().2. File Browser Refactoring (
src/pages/fileBrowser/fileBrowser.js)statearray and explicitpushState()helper function with aNavStackinstance (navStack).navBarElsMapto cacheHTMLSpanElementDOM nodes and avoid redundant DOM element recreations.navStacktolocalStorage.fileBrowserStateuponupdateevents.actionStackentries and corresponding navbar DOM nodes for all items inev.detail.removed.actionStackand callspushToNavbarfor newly added locations inev.detail.added.Maps(url, name): Polymorphic parameters (supports location objects or string pairs). UsesnavStack.has()andnavStack.popUntil()for back-navigation truncation, followed by directory fetching andnavStack.push().loadStates(states): Sequentially pushes stored location history intonavStackwithin an error-guarded loop and immediately navigates to the top element usingnavStack.get(-1).render(dir): Centralized folder-mode selection button state evaluation ($openFolder.disabled = (url || "/") === "/").Performance & Benchmark Comparison
Array.prototype.findSet.prototype.has$navigation.lastChilduntil targetremovedSet iteration via event detailspanelements on each navigationMaplocalStoragewrite on everypushStatestate[state.length - 1])navStack.get(-1))Synchronous Rendering & Microtask Decoupling
It is important to emphasize that while internal history diffing, event notification, navbar DOM updates, and
localStoragewrites are queued asynchronously via microtasks inNavStack, directory listing fetching and UI component rendering (render()) continue to be executed synchronously outside microtasks insideMaps().Architectural Rationale:
getDir()andrender()directly within the main call stack ensures that directory content renders without frame delays or visual flicker during user interaction.NavStackmicrotask pipeline is strictly responsible for updating background infrastructure (breadcrumb navigation elements, back-button action stacks, and local storage state). Separating view rendering from state event batching guarantees that layout painting remains responsive while background synchronization happens cleanly before the next paint frame.(PR name and description are AI generated (Gemini 3.6 Flash))