@@ -4,15 +4,17 @@ Browser-style back/forward history, path resolution, paged keyboard shortcuts, a
44
55## Key files
66
7- | File | Purpose |
8- | ---------------------------- | ------------------------------------------------ |
9- | ` navigation-history.ts ` | Purely functional immutable history stack |
10- | ` path-navigation.ts ` | Async path resolution with fallback chain |
11- | ` keyboard-shortcuts.ts ` | Home/End/PageUp/PageDown handling for file lists |
12- | ` VolumeBreadcrumb.svelte ` | Clickable volume label + grouped dropdown |
13- | ` navigation-history.test.ts ` | Full unit test coverage of history functions |
14- | ` path-navigation.test.ts ` | Unit tests for path resolution and timeouts |
15- | ` keyboard-shortcuts.test.ts ` | Unit tests for shortcut calculations |
7+ | File | Purpose |
8+ | -------------------------------- | --------------------------------------------------------- |
9+ | ` navigation-history.ts ` | Purely functional immutable history stack |
10+ | ` path-navigation.ts ` | Async path resolution with fallback chain |
11+ | ` keyboard-shortcuts.ts ` | Home/End/PageUp/PageDown handling for file lists |
12+ | ` VolumeBreadcrumb.svelte ` | Clickable volume label + grouped dropdown |
13+ | ` volume-grouping.ts ` | Pure logic: group volumes by category, get volume icons |
14+ | ` volume-space-manager.svelte.ts ` | Reactive state machine for disk space fetch/retry/timeout |
15+ | ` navigation-history.test.ts ` | Full unit test coverage of history functions |
16+ | ` path-navigation.test.ts ` | Unit tests for path resolution and timeouts |
17+ | ` keyboard-shortcuts.test.ts ` | Unit tests for shortcut calculations |
1618
1719## ` navigation-history.ts `
1820
@@ -90,15 +92,8 @@ Brief PageUp/PageDown lands on the **bottom row** of the target column (TUI conv
9092
9193## ` VolumeBreadcrumb.svelte `
9294
93- Clickable label that opens a grouped dropdown of all available volumes.
94-
95- Volume groups (in display order):
96-
97- 1 . Favorites — no checkmark shown even if current path is a favorite
98- 2 . main_volume + attached_volume — merged into one group
99- 3 . Cloud drives
100- 4 . Mobile (MTP) devices
101- 5 . Network — always includes a synthetic ` 'network' ` entry (` smb:// ` ) plus any mounted SMB shares
95+ Clickable label that opens a grouped dropdown of all available volumes. Volume grouping logic and disk-space retry state
96+ are extracted into ` volume-grouping.ts ` and ` volume-space-manager.svelte.ts ` respectively.
10297
10398Props: ` volumeId ` , ` currentPath ` , ` onVolumeChange? ` .
10499
@@ -111,14 +106,30 @@ movement > 5px threshold exits keyboard mode.
111106MTP volumes are refreshed with a 100ms delay after hotplug events (` mtp-device-detected ` , ` mtp-device-connected ` ,
112107` mtp-device-removed ` ) to let ` mtp-store ` 's own event handler finish first.
113108
114- ### Timeout-aware UI
109+ Exported methods for parent components: ` toggle() ` , ` open() ` , ` close() ` , ` getIsOpen() ` , ` handleKeyDown(e) ` .
110+
111+ ## ` volume-grouping.ts `
112+
113+ Pure logic for organizing volumes into display groups. No reactive state.
114+
115+ ` groupByCategory(vols, mtpVols) ` — groups volumes by category in display order:
115116
116- Both ` listVolumes() ` and ` getVolumeSpace() ` return ` TimedOut<T> ` wrappers. The component tracks timeout state and
117- renders inline indicators (no toasts):
117+ 1 . Favorites — no checkmark shown even if current path is a favorite
118+ 2 . main_volume + attached_volume — merged into one group
119+ 3 . Cloud drives
120+ 4 . Mobile (MTP) devices — mapped from ` MtpVolume[] `
121+ 5 . Network — always includes a synthetic ` 'network' ` entry (` smb:// ` ) plus any mounted SMB shares
122+
123+ ` getIconForVolume(volume) ` — returns the appropriate icon path for a volume based on its category.
124+
125+ ## ` volume-space-manager.svelte.ts `
126+
127+ Reactive state machine for fetching, retrying, and caching disk space info per volume. Created via
128+ ` createVolumeSpaceManager() ` (functional factory, no classes).
129+
130+ Both ` listVolumes() ` and ` getVolumeSpace() ` return ` TimedOut<T> ` wrappers. The manager tracks timeout state and exposes
131+ reactive sets for the component to render inline indicators (no toasts):
118132
119- - ** Volume list timeout** (` volumesTimedOut ` ): Shows a warning row at the bottom of the dropdown ("Some volumes may be
120- missing") with a retry button that re-calls ` listVolumes() ` . The warning auto-clears on successful retry. The dropdown
121- still opens with whatever partial data was returned.
122133- ** Volume space timeout** (` spaceTimedOutSet ` ): Three-state cycle with per-volume tracking:
123134 - ** Idle** : Dashed-outline placeholder bar with "?" icon, "Unavailable" text, tooltip "Couldn't fetch disk space --
124135 click to retry". After a retry has been attempted, tooltip changes to "Still unavailable -- click to retry".
@@ -127,10 +138,11 @@ renders inline indicators (no toasts):
127138 - ** Failed** : Brief shake animation (300ms), then returns to idle with "Still unavailable" tooltip.
128139 - ** Auto-retry** : 5s after initial timeout, an automatic retry fires with full visual feedback (spinner + shake on
129140 failure). Tracked via ` spaceAutoRetryingSet ` for tooltip distinction.
130- - All retry sets are cleared on volume mount/unmount events. Auto-retry timers are cleaned up on destroy.
141+ - All retry sets are cleared via ` clearAll() ` on volume mount/unmount events. Auto-retry timers are cleaned up via
142+ ` destroy() ` .
131143 - Reduced motion: spinner degrades to pulsing opacity, shake degrades to opacity flash.
132-
133- Exported methods for parent components: ` toggle() ` , ` open() ` , ` close() ` , ` getIsOpen() ` , ` handleKeyDown(e) ` .
144+ - ** Volume list timeout ** ( ` volumesTimedOut ` ): Tracked in the component itself (not in the manager) since it controls
145+ the warning row at the bottom of the dropdown .
134146
135147## Dependencies
136148
0 commit comments