Skip to content

refactor(frontend): extract useSessionListStreams from App.vue - #318

Merged
attson merged 1 commit into
mainfrom
refactor/extract-session-list-conns
Aug 4, 2026
Merged

refactor(frontend): extract useSessionListStreams from App.vue#318
attson merged 1 commit into
mainfrom
refactor/extract-session-list-conns

Conversation

@attson

@attson attson commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

Seventh slice of milestone 5-a. App.vue carried three module-scope transport handles for the session lists:

```ts
let localSessionListConn: SessionListConnection | null = null;
let remoteSessionListConn: SessionListConnection | null = null;
let remotePollHandle: number | null = null;
```

Every attach/replace had to detach the old handle first, and the remote side had two competing transports (WS + HTTP poll) that had to be mutually exclusive. That policy was open-coded across six sites (`connectLocalSessionList`, `connectRemoteSessionListWS`, `stopRemotePoll`, `startPlatformRemotePoll`, `connectRemoteSessionList`, and the web-boot catch block that fell back to polling on error) — each one manually calling `?.detach()` + `clearInterval` + reassigning the module handle.

Pull the three handles + the transport policy into `composables/useSessionListStreams.ts`, exposing:

```ts
attachLocal(endpoint, callbacks)
attachRemoteWS(endpoint, callbacks) // stops any active poll first
startRemotePoll(fn, intervalMs) // stops any active WS first
stopRemote() // detach WS + clear poll
isRemoteWSAttached() // for startPlatformRemotePoll gate
detachAll() // onUnmounted cleanup
```

The composable is purely the transport layer — all app-level state (list refs, endpoint refs, `missingSince` map, config dedup key, apply / prune functions) stays with the caller. The WS ↔ poll mutex is now enforced by construction: `startRemotePoll` always calls `stopRemote` first, `attachRemoteWS` too.

App.vue side:

  • Drop the three module-scope handles.
  • Drop the standalone `stopRemotePoll()` helper (was 8 lines).
  • Drop the `SessionListConnection` import.
  • Every attach/detach site collapses to one composable method call.
  • `startPlatformRemotePoll`'s "is WS already up?" check moves from a `remoteSessionListConn` module-var peek to `sessionListStreams.isRemoteWSAttached()`.

Net: App.vue -32 / +15; new composable +108. App.vue now 1749 lines (was 1766).

Test plan

  • `npm test` 1631 pass
  • `npm run build` (vue-tsc + vite) green
  • Manual (desktop): boot with relay configured → `/client-sessions` WS attaches; kill the WS → HTTP poll takes over at 2s; toggle relay off → both stop; toggle back on → WS reattaches
  • Manual (web): boot → `refreshPlatformRelayState()` uses WS when the relay's proxy is reachable; else the 3s poll runs; reload with no relay config → no polling, no WS

Seventh slice of milestone 5-a. App.vue carried three module-scope
transport handles for the session lists:

  let localSessionListConn: SessionListConnection | null = null;
  let remoteSessionListConn: SessionListConnection | null = null;
  let remotePollHandle: number | null = null;

Every attach/replace had to detach the old handle first, and the remote
side had two competing transports (WS + HTTP poll) that had to be
mutually exclusive. That policy was open-coded across six sites
(connectLocalSessionList, connectRemoteSessionListWS, stopRemotePoll,
startPlatformRemotePoll, connectRemoteSessionList, and the web-boot
catch block that fell back to polling on error) — each one manually
calling `?.detach()` + `clearInterval` + reassigning the module handle.

Pull the three handles + the transport policy into
composables/useSessionListStreams.ts, exposing:

  attachLocal(endpoint, callbacks)
  attachRemoteWS(endpoint, callbacks)   // stops any active poll first
  startRemotePoll(fn, intervalMs)       // stops any active WS first
  stopRemote()                          // detach WS + clear poll
  isRemoteWSAttached()                  // for startPlatformRemotePoll gate
  detachAll()                           // onUnmounted cleanup

The composable is purely the transport layer — all app-level state
(list refs, endpoint refs, missingSince map, config dedup key,
apply / prune functions) stays with the caller. The WS <-> poll mutex
is now enforced by construction: startRemotePoll always calls
stopRemote first, attachRemoteWS too.

App.vue side:
- Drop the three module-scope handles.
- Drop the standalone stopRemotePoll() helper (was 8 lines).
- Drop the SessionListConnection import.
- Every attach/detach site collapses to one composable method call.
- startPlatformRemotePoll's "is WS already up?" check moves from a
  `remoteSessionListConn` module-var peek to
  `sessionListStreams.isRemoteWSAttached()`.

Net: App.vue -32 / +15; new composable +108. `npm test` 1631 pass;
`npm run build` green.
@attson
attson merged commit 178d0da into main Aug 4, 2026
7 checks passed
@attson
attson deleted the refactor/extract-session-list-conns branch August 4, 2026 10:38
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