Skip to content

perf(desktop): compute the turn's elapsed time in its own component - #165

Merged
GoDiao merged 5 commits into
GoDiao:mainfrom
princecherry9905:fix/156-elapsed-time-component
Oct 23, 2026
Merged

GoDiao merged 5 commits into
GoDiao:mainfrom
princecherry9905:fix/156-elapsed-time-component

Conversation

@princecherry9905

Copy link
Copy Markdown
Contributor

Closes #156. Part of #153.

Why

While a reply ran, a 1s interval in chatStore wrote elapsedSeconds into the session, so the page, the message list, the composer and the streaming indicator all re-rendered once a second for the whole turn.

What changed

  • Both intervals are gone: the one started in sendMessage and the one applyMirror started when a turn began running. The elapsedSeconds and elapsedTimer session fields go with them, along with every clearInterval that only existed to stop those timers (stop, message complete, error, history reload, /clear, disconnect).
  • As you suggested, the start time comes from the server's turn.startedAt in the mirrored session state, not from a value recorded on the client.
  • ElapsedTime (new, components/chat/ElapsedTime.tsx) keeps its own 1s timer and computes the value from startedAt, so only that span re-renders each second. StreamingIndicator renders it while the mirrored turn isn't idle. The format (42s, 1m 5s) and the "hidden at 0s" rule are unchanged.
  • Test fixtures drop the two removed fields. teamStore's member session default drops them too.

Behaviour difference: the time now starts when the server marks the turn as running, not at the moment you press send. Before that the indicator shows the verb with no time, which is what the old code showed during the first second anyway.

Tests

  • chatStore.test.ts: "leaves the store unchanged while a turn runs" sends a message, starts a running turn and advances fake timers 5s, then checks the sessions object is the same reference.
  • StreamingIndicator.test.tsx (new): counts from the server's start and ticks each second (1m 5s then 1m 6s), shows the right time after switching sessions, keeps counting from the same start after a reconnect snapshot, and shows no time when no turn has started.
  • 4 of the 5 new tests fail on main (the 5th checks the idle case, which already passed) and all pass with this change.

Checks run locally (bun 1.4.2):

  • cd desktop && bun run lint: pass
  • cd desktop && bun run test -- --run: 115 files, 1195 passed, 4 skipped
  • cd desktop && bun run build: pass
  • bun test (server): 1343 pass, 2 fail. The failures are h5-access-service.test.ts (getDiagnostics) and e2e/business-flow.test.ts (echo message), and both fail the same way on unchanged main in my environment. This PR doesn't touch server code.

I couldn't run bun run tauri dev in my environment, so I haven't watched it in the app.

A 1s interval in chatStore wrote elapsedSeconds into the session while
a turn ran, so every subscriber of the session re-rendered once a
second. Both intervals (the one started on send and the one started
when a mirror turn begins running) are gone, together with the
elapsedSeconds and elapsedTimer fields and the clearInterval calls
that went with them. The elapsed time now comes from turn.startedAt in
the server's session state.
ElapsedTime keeps its own 1s timer and computes the value from the
turn start the server reports, so only it re-renders each second, and
the time stays right after switching sessions, a reconnect or a
refresh. Test fixtures drop the removed session fields.

@GoDiao GoDiao left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks good to merge.

@GoDiao
GoDiao merged commit 47f24a7 into GoDiao:main Oct 23, 2026
4 checks passed
GoDiao added a commit that referenced this pull request Oct 23, 2026
@GoDiao

GoDiao commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Merged, thanks @princecherry9905! This was a clean first PR. Reading the start time from the server's turn.startedAt was the right call, the timer cleanup covers every path the old interval touched, and the store test that checks the sessions reference stays the same is a nice way to pin the fix. The PR description made it easy to review too.

We added the CHANGELOG entry. If DreamCoder is useful to you, a ⭐ on the repo would mean a lot. Hope to see you around for more!

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.

Compute the turn's elapsed time in its own component instead of the store

2 participants