mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 11:06:16 -08:00
The two refresh entry points cannot see each other: the header action tracks one global flag, the sources row tracks its own id set, and neither disables the other's button. Both can be confirmed for the same playlist inside the delete window, and the second run then collects an already-emptied catalog and parks it over the first run's snapshot — `XtreamPendingRestoreService.set()` overwrites unconditionally — so favorites, history, hidden categories and playback positions are lost on re-import. The race predates this PR: on master the two guards are already independent (`isRefreshing()` against the per-row pending sets), so neither entry point could ever have fixed it alone. Extracting the flow is what makes it fixable once. `XtreamRefreshFlowService` now holds the set of playlists with a run in flight and refuses a second one before it resets the guard, releasing it in the same finally that ends the reporter, so a finished run never strands a playlist. Found by Greptile on #1431. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>