Skip to content

fix(macapp): show failed collection loads with inline retry instead of endless skeletons #993

Description

@dennisonbertram

Parent: #991

Summary

The app has a typed .failed collection state, but multiple views treat every non-loaded empty collection as “still loading.” A failed request can leave an endless skeleton with no explanation or retry even though ProjectSession.statusMessage recorded an error elsewhere.

Evidence

  • macapp/Sources/GoCodeUI/ActivityView.swift:33-37 — failed empty tasks render LoadingPlaceholder.
  • ActivityView.swift:45-47 — failed runs with runs == nil render LoadingPlaceholder.
  • macapp/Sources/GoCodeUI/SessionsView.swift:24-39 — failed empty conversations render loading rows.
  • SessionsView.swift:156-169 — failed rewind-point loads render loading rows.
  • macapp/Sources/GoCodeUI/ModelSettingsView.swift:181-186,235-247 — failed provider loads render loading placeholders.
  • CollectionLoadState.failed has no failure-presentation contract.

Impact

Network/server failures masquerade as indefinite work. Users cannot tell whether to wait, retry, or fix connectivity, and several affected screens do not render statusMessage at all.

Scope

  • Add one shared inline failure state with a concise reason and Retry action.
  • Render it for failed empty conversations, tasks, runs, rewind points, providers, profiles, and models.
  • When stale data exists, retain it and show a non-blocking refresh-error notice instead of replacing it.
  • Keep .idle, .loading, .loaded(empty), and .failed visually and semantically distinct.

Tests first

  • Table-driven tests for presentation derived from state + item count + stale-data presence.
  • Regression coverage for Activity, Sessions, Checkpoints, and Model Settings production call sites.
  • Stub-client tests: 500/transport failure exposes Retry; retry success transitions to loaded content/empty state.

Acceptance criteria

  • No .failed collection state renders an indefinite skeleton.
  • Every failed collection exposes a visible Retry action and useful next step.
  • Stale successful data remains visible during a failed refresh.
  • Empty messaging appears only after a successful loaded response.
  • Failure text is announced to assistive technology without stealing focus.
  • swift test, Swift build, formatting, and strict format lint pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmacappNative macOS app (macapp/)mediumMedium effort: 1-3 daysreliabilityReliability and resilience concernsuxUser experience improvementswell-specifiedIssue is clear, scoped, and ready to implement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions