feat(desktop): pulse thread ingress rows while an agent works in the thread#1569
Closed
tellaho wants to merge 4 commits into
Closed
feat(desktop): pulse thread ingress rows while an agent works in the thread#1569tellaho wants to merge 4 commits into
tellaho wants to merge 4 commits into
Conversation
…thread Derive a stable, sorted set of working thread head ids from thread-scoped bot typing entries in ChannelPane and pass it down the timeline as a ReadonlySet, so each thread summary row gets a plain boolean instead of scanning raw typing entries. The set identity only changes when the set of working threads changes — not on each 1s typing prune tick — preserving the existing timeline memo boundaries. Channel-level working surfaces are untouched; thread-only typing still stays out of agentWorkingSignal. The badge is a small motion-safe pulsing dot on the matching MessageThreadSummaryRow, with an aria-label suffix for screen readers. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
getTypingScopeId keyed typing entries on the reply parent tag, so an agent working deep in a thread produced a threadHeadId that matched no ingress row (and missed the open-thread composer filter). Typing and completion events already carry a root tag for nested replies — prefer it, falling back to the parent for direct replies where root === parent and no root tag is emitted. Both the registration and post-message suppression paths flow through the same helper, so suppression keys stay consistent. Exported for tests. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…moothly Closed thread ingress rows render inside .timeline-row-cv, which applies content-visibility: auto. The browser may skip or throttle rendering work for contained rows, so the badge's opacity pulse stuttered on the closed timeline while the same activity animated smoothly in the open thread panel (which has no containment) — exactly the reported repro signal. Opt only rows with an active working badge out of containment via a data-agent-working attribute on the row wrapper, mirroring the existing :hover/:focus-within un-pause rule. Scope stays tight: at most the one or two rows with live agent activity lose containment, and only while the badge is showing. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Collaborator
Author
|
Parking this draft direction in favor of a new header-level threads activity indicator exploration. Context preserved in the PR/thread; closing so it does not move forward accidentally. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a subtle pulsing badge to thread ingress rows (
MessageThreadSummaryRow) when an agent is actively working (bot typing) in that thread.Approach
threadScopedBotTypingHeadIdKeyhelper inuseChannelActivityTyping.ts— deduped, sorted key of thread head ids with active bot typing (channel-scoped entries excluded).ChannelPanederives one memoizedReadonlySet<string>from that key. Identity only changes when the set of working threads changes — not on each 1s typing prune tick.MessageTimeline→TimelineMessageList→MessageRowItem; eachMessageThreadSummaryRowreceives onlyisAgentWorking: boolean. No row ever sees raw typing entries.h-1.5 w-1.5 rounded-full bg-primary motion-safe:animate-pulsedot next to participant avatars, with anaria-labelsuffix for screen readers.agentWorkingSignal.Performance
TimelineMessageListre-renders its callback path —MessageRowis memoized and its props don't include the set, so heavy markdown rows stay put.Testing
Files changed
desktop/src/features/channels/ui/useChannelActivityTyping.tsdesktop/src/features/channels/ui/useChannelActivityTyping.test.mjsdesktop/src/features/channels/ui/ChannelPane.tsxdesktop/src/features/messages/ui/MessageTimeline.tsxdesktop/src/features/messages/ui/TimelineMessageList.tsxdesktop/src/features/messages/ui/MessageThreadSummaryRow.tsx