Commit eccd1b36 authored by Kourser's avatar Kourser
Browse files

Fix episodes vanishing on re-entry (cancelled DB read clobbering)



Root cause (reproduced deterministically): GRDB's async reads honour task
cancellation. Returning to a podcast quickly cancels the detail's `.task`, so the
episode query threw CancellationError, which was turned into an empty list and
written over the displayed episodes — hence "Aucun épisode" until a manual
refresh.

Fix: in PodcastDetailView, never overwrite the list when the load was cancelled
(guard `Task.isCancelled` after each await; only treat a non-cancelled empty
result as "no episodes"). reloadFromStore likewise bails on cancellation.

51 package tests green; iOS + macOS build; verified with a scripted
open → back → re-open flow (episodes now persist on screen).

Co-Authored-By: default avatarClaude <claude@anthropic.com>
parent 9a4ad624
Loading
Loading
Loading
Loading
Loading
+23 −14
Original line number Diff line number Diff line
@@ -40,27 +40,36 @@ struct PodcastDetailView: View {
    }

    private func loadEpisodes() async {
        loaded = false
        var result = await model.episodes(for: podcast)
        if result.isEmpty {
            // Nothing stored yet for this feed — fetch it so episodes show
            // without a manual pull-to-refresh.
            await model.refresh(podcast)
            result = await model.episodes(for: podcast)
        }
        let result = await model.episodes(for: podcast)
        // A cancelled DB read (view disappeared/reappeared quickly) returns an
        // empty list — never let that clobber the displayed episodes.
        guard !Task.isCancelled else { return }

        if !result.isEmpty {
            episodes = result
            loaded = true
            await model.loadPlayStates(for: episodes)
            return
        }

        // Genuinely empty for this feed — fetch it once so episodes appear
        // without a manual pull-to-refresh.
        await model.refresh(podcast)
        guard !Task.isCancelled else { return }
        let refetched = await model.episodes(for: podcast)
        guard !Task.isCancelled else { return }
        episodes = refetched
        loaded = true
        await model.loadPlayStates(for: episodes)
    }

    private func reloadFromStore() {
        Task {
            let result = await model.episodes(for: podcast)
            if !result.isEmpty {
            guard !Task.isCancelled, !result.isEmpty else { return }
            episodes = result
                await model.loadPlayStates(for: result)
            loaded = true
            }
            await model.loadPlayStates(for: result)
        }
    }
}