Skip to content

fix: Apps settings connection badge never updates after connect/disconnect - #404

Merged
gdoumen merged 3 commits into
mainfrom
feat/fix-apps-badge-stale
Aug 19, 2026
Merged

fix: Apps settings connection badge never updates after connect/disconnect#404
gdoumen merged 3 commits into
mainfrom
feat/fix-apps-badge-stale

Conversation

@gdoumen

@gdoumen gdoumen commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • NavigationBar fetched the apps array once on mount (refInitialized guard) and passed it to AppsDialog, which derives its connection badge purely from that array. Nothing propagated connect/disconnect changes back up to NavigationBar, so the badge stayed stale until the screen remounted (navigation or restart).
  • NavigationBar now subscribes to AppsService's existing 'connected'/'disconnected' events (services/src/apps/service.ts:59,76) and refetches apps on each, so the badge updates live within the same dialog session — no remount required.
  • Removed the dead-code AppsSettings/AppsSettingsView components (confirmed unreferenced by any live navigation screen via grep — only their AppDisplayProps/AppsSettingsViewProps/AppsSettingsProps types were referenced elsewhere). They carried the identical staleness bug in their own onBack path. Kept AppsSettings/types.ts, trimmed to just AppDisplayProps, since AppsDialog and NavigationBar still depend on that type.
  • Added NavigationBar.test.tsx (didn't exist before) covering: fetch + subscribe on mount, apps state updates on 'connected', apps state updates on 'disconnected', and unsubscribe on unmount.

Refs FIXES_BACKLOG.md item #60.

Test plan

  • npx jest — full suite: 110 suites / 791 tests passing
  • npx eslint src/ — 0 errors (pre-existing warnings only, none in touched files)
  • npx tsc --noEmit — clean
  • Manual device verification (connect/disconnect Strava and Intervals.icu, badge should flip live without navigating away)

NavigationBar fetched the apps list once on mount and never again, so
AppsDialog's connection badge stayed stale for the lifetime of the
mount even though OAuthAppSettings connected/disconnected correctly
underneath. Subscribe to AppsService's 'connected'/'disconnected'
events and refetch on each, so the badge updates live without a
remount.

Also removed the dead-code AppsSettings/AppsSettingsView components
(unreferenced by any live screen, confirmed via grep) which carried
the same staleness bug in their own onBack path. Kept AppsSettings/types.ts
since AppDisplayProps is still consumed by AppsDialog and NavigationBar.

Fixes FIXES_BACKLOG item #60.
Repo-owner review on PR #404: having NavigationBar subscribe to
AppsService and pass a refreshed `apps` array down to AppsDialog created
an unwanted dependency between NavigationBar and the Apps-settings
feature. AppsDialog should own its own service subscription instead.

Splits AppsDialog into a thin smart AppsDialog.tsx (fetches apps via
appsService.openSettings(), subscribes to 'connected'/'disconnected',
no incyclist-services import in the view) and a pure AppsDialogView.tsx
carrying the original presentational logic, mirroring the live
WorkoutDetailsDialog/WorkoutDetailsView and NavigationBar/NavigationBarView
split already used in this codebase. Storybook (AppsDialog.stories.tsx)
now targets AppsDialogView directly with plain mock apps, same pattern
as NavigationBar.stories.tsx targeting NavigationBarView - no service
mocking needed.

NavigationBar.tsx reverts to rendering <AppsDialog /> without owning any
apps state or AppsService subscription itself. The subscription-behavior
test moves from NavigationBar.test.tsx to AppsDialog.test.tsx; the
former now only asserts NavigationBar renders AppsDialog without an
`apps` prop.
…ipt:S6481)

AppsDialogView.tsx:81 created a fresh { standalone: false } object literal
on every render inside a .map() loop, where useMemo can't be used without
violating Rules of Hooks. Hoisted to a module-level constant instead.
@sonarqubecloud

Copy link
Copy Markdown

@gdoumen
gdoumen marked this pull request as ready for review August 19, 2026 11:48
@gdoumen
gdoumen merged commit 1b7a09d into main Aug 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant