mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 02:46:16 -08:00
`PlaylistRefreshActionService.refreshXtream()` and `RecentPlaylistsComponent.refreshXtreamPlaylist()` were two independent ~60-line implementations of the same sequence: confirm, reset the connectivity guard, delete the cached catalog while collecting playback positions and stamping the update date, park the restore state, dispatch the meta update, navigate to re-import. That duplication is what let the guard reset land in one of them and look landed in both, which the previous commit had to fix separately. `XtreamRefreshFlowService` now owns the sequence once. The two entry points differ only in how they report progress — the header action drives one global preparation signal, the sources page drives per-row busy indicators shared with deletion — so that part is injected as an `XtreamRefreshProgressReporter`. Its optional `waitForVisibleProgress` hook keeps the action's paint delay without imposing it on the sources page, which never had one. A reporter cannot reach the guard reset, so a third entry point gets it for free. The sources page now awaits `router.navigate` before clearing its busy row, matching the action service; it previously cleared the row while navigation was still in flight. Both guard-reset regression tests still fail on their own when the reset is removed from the shared flow. The new spec pins the reporter contract: re-entry after confirmation, busy-before-reset ordering, progress forwarding under one run, abort vs error, and a reporter without the optional paint hook. The sources spec's abort test counted a fixed number of microtasks to reach the delete; the shared flow adds one await to that path, so it now waits on a deterministic signal instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>