Skip to content

fix: retention starvation + duplicate threshold, perf and UI polish (v0.6.1) - #112

Merged
RasputinKaiser merged 1 commit into
mainfrom
feat/ui-perf-improvements
Jul 1, 2026
Merged

fix: retention starvation + duplicate threshold, perf and UI polish (v0.6.1)#112
RasputinKaiser merged 1 commit into
mainfrom
feat/ui-perf-improvements

Conversation

@RasputinKaiser

Copy link
Copy Markdown
Owner

Summary

  • Fix Tree/Storage Map rendering empty on large scans. scanItem recurses depth-first/post-order, so nested directories spend the shared retention budget before the root's own retainedChildren() call — the last one to run — finds it exhausted and returns []. The root's direct children are now always retained regardless of remaining budget (bounded by maxChildrenPerDirectory, not exponential). Added a regression test verified to actually catch the bug (fails without the fix, passes with it).
  • Duplicate detection found almost nothing in typical folders. Lowered the default duplicateCandidateThreshold 100MB → 10MB, added a Settings stepper to make it user-tunable, and made empty states name the active threshold instead of misdirecting to "scan a broader folder." Also fixed "Clear Filters" rendering as a no-op button when no filters were active.
  • Performance: autoreleasepool around the parallel directory-enumeration hot loop, lookup-table SHA-256 hex encoding (replacing per-byte String(format:)), LazyVStack for Type Breakdown's up-to-4000-row lists, cached mountedVolumes instead of FileManager I/O on every sidebar render.
  • UI polish: shared scale-on-press button style for row buttons, subtle default card shadow, accessibilityHidden on decorative size bars (plus full accessibility semantics added to StorageMapRow, which had none), a collapsed-by-default "Scan limits" disclosure on Overview, larger Tree Explorer hit target, missing .help() tooltips, tabular-number fixes.

Reconciliation note

This branch forked before PR #107 (perf(ui): eliminate per-row store subscriptions) merged into main. That PR did an independent, more thorough version of the same row-observation fix I was working on. I rebuilt this branch off current main, kept #107's closure-based row architecture as-is, and re-applied only the additive parts of my work (press feedback, accessibility, tooltips, scan-limits disclosure, empty-state copy) on top — no regression of #107's fix. Verified via codesign --verify + full build + full test suite after reconciliation.

Test plan

  • swift build (debug + release) — clean
  • swift test — 173/173 pass, including the new P-1 regression test (independently verified to fail without the fix via git stash)
  • Manually launched the built app and confirmed it runs

🤖 Generated with Claude Code

…v0.6.1)

Correctness (confirmed via live audit + regression test):
- Fix Tree/Storage Map rendering empty on large scans. scanItem recurses
  depth-first/post-order, so nested directories spend the shared retention
  budget before the root's own retainedChildren() call — the last one to
  run — finds it exhausted and returns []. Now the root's direct children
  are always retained regardless of remaining budget (bounded by
  maxChildrenPerDirectory, not exponential). Regression test verifies the
  fix actually catches the bug (fails without it, passes with it).
- Lower default duplicateCandidateThreshold 100MB -> 10MB; the old default
  meant Duplicate Review found almost nothing in typical folders. Added a
  Settings stepper so it's user-tunable, wired into scan-options staleness
  tracking. Empty states now name the active threshold instead of
  misdirecting to "scan a broader folder"; "Clear Filters" no longer
  renders as a no-op when no filters are active.

Performance:
- autoreleasepool around each parallel directory-enumeration iteration in
  FileSystemScanner (bounds peak RSS instead of accumulating Foundation
  objects for the whole enumeration).
- Lookup-table SHA-256 hex encoding, replacing per-byte String(format:).
- LazyVStack for Type Breakdown's category/file-type lists (previously
  eager VStack over up to 4000+ rows).
- Cache ScanStore.mountedVolumes instead of doing FileManager I/O on every
  SidebarView render; dedupe a duplicate items(for: .overview) call.

UI polish:
- Shared PressableRowButtonStyle (scale 0.96 on press) across row buttons.
- Subtle default shadow on cardBackground() instead of a flat fill;
  hardcoded .black shadow in WelcomeView replaced with NSColor.shadowColor.
- accessibilityHidden on decorative size-bar shapes so VoiceOver doesn't
  land on unlabeled rectangles; StorageMapRow gained full accessibility
  semantics it was missing entirely.
- Scan-limits disclosure on Overview stating the active ranked-list cap,
  duplicate threshold, and tree retention cap.
- Larger Tree Explorer disclosure-triangle hit target, missing .help()
  tooltips on truncated paths, monospacedDigit on two jittering columns.

Reconciled against main's PR #107 (independent per-row store-decoupling
refactor merged after this branch's fork point): kept #107's closure-based
row architecture, re-applied only the additive changes above on top.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@RasputinKaiser
RasputinKaiser merged commit 4b6ab68 into main Jul 1, 2026
6 checks passed
@RasputinKaiser
RasputinKaiser deleted the feat/ui-perf-improvements branch July 1, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant