Skip to content

[Enhancement]: SectorChanged triggers a full folder rescan instead of a targeted Riverpod invalidation #207

Description

@G00dS0ul

What happens now

When the Live Radar reports a change, the app re-scans the entire open directory and
re-fetches the whole drive list, no matter how small the change was. Creating one file in a
deeply nested subfolder costs the same as if every file in the folder had changed.

With the #170 fix in place the radar now reports changes from anywhere in the visible tree
rather than only the top level, so this fires considerably more often than it used to. The
work per event has not changed; only the number of events has.


Why it is currently written that way

The refresh is gated on an exact string comparison between the reported path and the open
folder:

core/frontend/gs_analyzer_ui/lib/providers/telemetry_provider.dart:158-176

_telemetryService?.onSectorChanged = (changedFolder) {
  final currentProgress = ref.read(nukeProgressProvider);
  if (currentProgress > 0.0 && currentProgress < 100.0) return;

  final currentPath = ref.read(directoryProvider).currentPath;
  final normalizedCurrent = currentPath
      .replaceAll('\\\\', '/')
      .toLowerCase();
  final normalizedChanged = changedFolder
      .replaceAll('\\\\', '/')
      .toLowerCase();

  if (normalizedCurrent == normalizedChanged) {
    appLogger.i('LIVE UPDATE: REFRESHING UI FOR $currentPath');
    ref.read(directoryProvider.notifier).scanDirectory(currentPath);
  }

  ref.read(drivesProvider.notifier).refresh();
};

Because that comparison is exact, a payload naming a nested folder matches nothing and
refreshes nothing. The backend therefore has to send the watched root — which is always
the folder the user has open — for any refresh to happen at all. That keeps the feature
working, but it means the payload can no longer say which part of the tree changed, so the
client falls back to rescanning all of it.

This is the trade-off worth revisiting, not a defect in the backend fix.


What is being asked for

Two requirements in the product spec are only partly met today:

FR-R2: On create/modify/delete, the backend must push a targeted update rather than
forcing a full refresh.

FR-R3: Updates must trigger a targeted Riverpod invalidation that redraws only the
affected UI.

A design that satisfies both would need the payload to carry enough information to identify
the affected node — for example the changed path alongside the watched root — and the client
to match by prefix rather than by equality, updating just that node's entry in the tree.

That is a contract change on both sides, which is why it is a separate piece of work rather
than part of the #170 fix.


Two things worth fixing while in this code

1. A normalisation bug that is currently harmless.
telemetry_provider.dart:164 and :167 use replaceAll('\\\\', '/'), which in Dart matches
two consecutive backslashes. Everywhere else in the app uses replaceAll('\\', '/') —
one backslash — for example core/frontend/gs_analyzer_ui/lib/providers/directory_provider.dart
at lines 183, 242, 269, 304 and 358. It causes no visible problem today only because both
sides of the comparison already use forward slashes by the time they meet. Any future change
that lets a Windows-style path reach this comparison would silently stop matching, and the
symptom would be "the tree just stops refreshing", with nothing in the logs.

2. The drive list refreshes on every event.
ref.read(drivesProvider.notifier).refresh() at :175 runs outside the equality check, so it
fires for every radar event regardless of whether it concerns the open folder. Drive totals
move far more slowly than file events do.


Suggested acceptance criteria

  • Creating or deleting a single file in a nested subfolder updates only that part of the tree;
    sibling nodes are not refetched.
  • A burst of changes produces one coalesced UI update, matching the backend's existing
    coalescing behaviour.
  • Path comparison is exercised by a test covering both separator styles and mixed casing.
  • The drive list no longer refreshes on every file event.
  • Deleting the open folder itself still navigates or errors as it does today.

Out of scope

The backend coalescing, subdirectory watching and overflow handling are all handled by #170
and should not be revisited here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    PerformanceOptimize current featuresenhancementNew feature or requestfrontendFlutter/DartscannerStorage scanner

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions