System Storage: show available space per root folder, app data and system disk (#508)#656
Conversation
therobbiedavis
left a comment
There was a problem hiding this comment.
Thanks for the fix here. I left a couple of small review notes around edge cases/UX polish; nothing huge, but worth tightening before merge.
therobbiedavis
left a comment
There was a problem hiding this comment.
LGTM, but there is one non-blocking request: Could we pull the Windows path/native-call handling behind a tiny testable seam and add coverage for UNC inputs? I’m not asking because I reproduced a failure: I tested GetDiskFreeSpaceExW against a temporary elevated local SMB share and it succeeded with and without a trailing slash. This is more about keeping the NAS-support behavior from regressing later.
|
Done in Same commit also tightens a few small things: clamp used bytes/percentage so filesystems reporting free > total (over-provisioning, ZFS/Btrfs, network shares) can't go negative; XML-doc the legacy top-level |
|
@s3ntin3l8 LGTM. Can you update the PR description to match the template? We should be good to merge after that. |
@therobbiedavis: Done and ready to merge |
GET /api/v1/system/storage now returns a disks array alongside the existing fields: the System disk (container root, e.g. docker.img on Unraid), the App Data disk (config volume holding database/logs/cache), and one entry per configured root folder. Each disk is measured with DriveInfo on the path itself so Docker volume mounts report their own filesystem instead of the container root's. Missing or inaccessible paths yield an 'unavailable' entry instead of failing the request. The legacy top-level fields now describe the App Data disk (config volume) rather than the install-path root, and DriveName carries that path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Storage card now renders one entry per disk from the new disks array — label and mount point, a full-width usage bar, and the percentage / used-of-total line — via a new StorageDisksList component. ProgressBar's size formatter gains a TB unit so multi-terabyte mounts no longer display as thousands of GB. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Listenarrs#508) DriveInfo throws on UNC/NAS roots (\\server\share), so those reported as unavailable. On Windows, measure any directory — drive paths, mounted-folder junctions, and UNC shares — via GetDiskFreeSpaceExW. Unix keeps DriveInfo (statvfs). Disk-info construction is now shared through a BuildDiskInfo helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address PR review: - Composite v-for key (label:path:index) so a configured root folder sharing a path with the System/App Data entry no longer triggers a duplicate-key warning. - Each row shows free-of-total capacity (Listenarrs#508 is about available space), replacing the bar's used/total readout; the percentage stays. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Extract disk-space measurement behind an IDiskSpaceProbe seam so the Windows GetDiskFreeSpaceEx path is unit-testable; cover UNC inputs. - Clamp used bytes/percentage so filesystems reporting free > total (reserved blocks, over-provisioning, ZFS/Btrfs, network shares) cannot go negative; add an over-provisioned test. - Document the legacy top-level StorageInfo fields as describing the App Data disk, with per-disk detail in Disks; fix the disk-order comment. - Drop the Storage card summary badge (it headlined the least useful disk); the per-disk list already shows each disk's free/total. - Add ProgressBar TB-formatting tests. - Remove the CHANGELOG entry per repo policy (no changelog on upstream PRs). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1bbdc32 to
04a2cd6
Compare
Fixes #508
Summary
The System page's Storage card previously reported only the disk hosting the application — in Docker/NAS setups that's a small boot/app device (e.g. a 4 GB USB DOM), while the audiobook library lives on a separate mount that was never shown. This adds per-disk reporting so the System page shows available space for the System disk, the App Data (config) volume, and every configured root folder.
Changes
Added
GET /api/v1/system/storagenow returns adisks[]array with an independently-measured entry for the System disk (container root, e.g.docker.imgon Unraid), the App Data disk (config volume holding the database/logs/cache), and each configured root folder (one row per folder, no dedupe). Missing or inaccessible paths yield anunavailableentry instead of failing the request.IDiskSpaceProbeseam abstracting disk measurement — WindowsGetDiskFreeSpaceEx(handles drive paths, mounted-folder junctions, and UNC/NAS shares) with aDriveInfo/statvfs fallback on Unix — so NAS roots are measured and the logic is unit-testable.Changed
StorageInfofields are retained for compatibility but now describe the App Data disk (config volume);driveNamecarries that path (wasDriveInfo.Name, e.g./). Per-disk detail is indisks[]. API consumers relying on these fields should note the changed meaning.ProgressBar's size formatter gains aTBunit (multi-terabyte mounts previously displayed as thousands of GB).Fixed
Removed
Screenshots
Testing
SystemServiceStorageTests, hermetic via temp dirs): no root folders, config-root measurement and content-root fallback, multiple folders on one filesystem, missing path →unavailable, UNC path measured via a fake probe (available + unavailable), and an over-provisioned disk → usage clamped to zero.DiskSpaceProbeTests): the realDriveInfobranch on an existing temp dir and a missing path. The WindowsGetDiskFreeSpaceExcall can't run on Linux CI, so that path is review-covered.StorageDisksList.spec.ts(per-disk rows, free-of-total, unique keys, unavailable) andProgressBar.spec.ts(TB / sub-TB formatting).dotnet format,vue-tsc, ESLint, Prettier.Notes
Validate PR version labelcheck — I don't have triage rights to add it.CHANGELOG.mdentry, per the no-changelog-on-upstream-PRs policy.🤖 Generated with Claude Code