Files
buzz/mobile/lib/features
Logan Johnson aa5f3e7bde feat(mobile): show conversation activity by the composer, as buzz-app does (#8765)
## Summary

Stacked on #8754. This brings the rest of buzz-app's conversation
activity to mobile.

buzz-app shows who is active in a conversation in one place, just above
the composer (`src/features/messages/TypingIndicator.tsx`). Mobile had
its own design: a typing bubble at the end of the timeline that turned
into the agent's reply (the "handoff"). This change replaces that design
with buzz-app's indicator in channels, DMs, Me and threads.

What the indicator shows, as in buzz-app:

- **On the right: your agents working here.** Up to four agent avatars,
then "+N". "Your agents" are your agent inventory (kind 30177), as in
#8754. Tapping the avatars opens the "Working now" list.
- **On the left: everyone else typing here.** Typing dots and buzz-app's
text: "Alice is typing", "Alice, Bob are typing", "Alice, Bob and 1
others are typing".
- **"Working now" list.** Each row shows the agent, "Working" and, in a
channel view, where it works: "Channel conversation", or "Thread ·
<first 60 characters of the root>", with "+N more" after two places.
- If the agent works in exactly one thread, the row opens that thread. A
thread whose root is not loaded opens by its ID, as buzz-app's link
does. A button at the end of the row opens the agent's activity.
- Otherwise (in a thread view, in Me, in the channel only, or in several
threads), the row opens the agent's activity. As in buzz-app, work in
the channel does not count as a thread: an agent in the channel and one
thread opens that thread.
  - "Activity" is mobile's existing `AgentActivitySheet`.
  - The list closes when the last agent stops.
- **Scope** (`current-activity.ts`: "Channel views include threads;
thread views do not"):

  | View | Your agents | Everyone else |
  |---|---|---|
  | Channel or DM | Here and in any thread | Here only |
  | Thread | This thread only | This thread only |
  | Me | Anywhere | Anywhere |

- **Me** works like buzz-app's Solo chat: with one agent working,
tapping the avatars opens its activity directly.
- **Spoken status:** buzz-app's live status, for example "Jerry, Morty,
Summer are working. Alice is typing". The button says "Activity: Morty
working" or "Activity: 3 agents working".

Changes you will notice compared with #8754 and main:

- The typing bubble at the end of the timeline and the bubble-to-reply
handoff are removed. #8754's channel typing row goes with them. The root
message's reply row from #8754 stays.
- In DMs, other people's agents typing in a thread no longer show at the
DM level. Only your agents do, as in buzz-app. This reverses part of
#8731.
- With no composer, there is no indicator. This applies when you are not
a member or the channel is archived, as in buzz-app (`ChannelsPage`, and
`ThreadPanel`'s `composerRoot`). Before, mobile showed typing in those
threads.

Less than buzz-app, not in this PR:

- Status is always "Working". buzz-app also uses lifecycle evidence
(local agent state, kind 24200) and tool labels. Mobile uses typing
only, as in #8754.
- No hover preview and no keyboard path (Down arrow) into the list.
- The indicator sits in the composer dock, so it moves the timeline up a
little. In buzz-app it floats over the history.

Code:

- `conversation_activity_state.dart` holds the scope rules, read from
typing and the inventory.
- `conversation_activity.dart` is the indicator.
`working_now_sheet.dart` is the list.
- `channel_detail_page/composer_activity.dart` puts it in the channel
composer dock and opens threads. The thread page puts it above its
composer.
- Removed: `inline_agent_typing.dart`, `agent_reply_handoff.dart`,
`agent_typing_bubble.dart`, `typing_avatar_cluster.dart`,
`typing_motion_preview.dart`, `channel_typing_indicator.dart`, and their
tests.

### Related issue

N/A. Reported in Buzz #buzz-bugs (on iOS you cannot tell whether an
agent is down or typing). Searched issues and PRs for duplicates: none
found.

### Testing

Android emulator, local relay, debug build of `8362d46af`.

**Channel and thread.** Demo User mentions Morty. Morty, Summer and
Jerry (in Demo User's agent inventory) type in the mention's thread.
Rick (not in the inventory) types in the thread and in the channel
itself. In the video:

1. The channel shows three agent avatars on the right and "Rick is
typing" on the left. Rick's thread typing does not show.
2. Tapping the avatars opens "Working now". Each row reads "Working" and
"Thread · …". Tapping Morty's row opens the thread.
3. In the thread, the same three agents show, with "Rick is typing" (his
thread typing). Rows there open activity: tapping Morty's opens his
activity sheet.
4. Back in the channel, Summer, Jerry and Rick stop. Only Morty's avatar
is left. Then Morty replies and the indicator goes away. No typing
bubble shows at any point.


https://github.com/user-attachments/assets/b300e16e-8bec-4489-9ee4-a68c5c2dc30d

**DM.** A DM with Morty (in the inventory) and Rick (not). Demo User
posts. Both type in its thread, and only Morty's avatar shows. Then Rick
also types in the DM itself, and "Rick is typing" shows. Morty replies,
and his avatar goes away.


https://github.com/user-attachments/assets/3614be5f-3a69-4a1a-9290-d1fad16a5445

The UI tree confirmed each state, for example "Summer, Jerry, Morty are
working. Rick is typing", "Activity: 3 agents working", "Morty is
working" (agents only), and "Morty is working. Rick is typing" (DM).

- Widget tests in `channel_detail_page_test.dart` (Typing indicator
group):
- Scope table: Me, channel and DM, for a person and for your agent.
While the inventory loads, an agent never shows as a person.
- The journey from #8754, extended: the composer status and button, the
list's places, opening the thread, thread-view rows opening activity,
and the list closing when work stops.
- Six agents in several places: four avatars and "+2", "+1 more",
scrolling to the last row, opening a thread that is not loaded, and
opening activity.
- Me opens a lone agent's activity directly. People typing: 1, 2 and 3.
- Each new check was made to fail on purpose by removing the code it
guards.
- `just mobile-check` and the full `just mobile-test` passed on
`3480ad238` (3983 passed, 28 skipped).
- Typing names use the full foreground, so they stay readable in dark
themes (review feedback). A test checks the color.
- Auto and Cerveau reviewed it adversarially against buzz-app
origin/main. Their findings are fixed: the list did not scroll, unloaded
threads did not open, the Me behaviour, the non-member indicator, and a
double-tap pop. Their last pass on `2c45f3ec0` found nothing. The device
run then showed that, with only agents working, the spoken status had no
size and Android dropped it. `8362d46af` fixes this, and their review of
that fix found nothing.
- Not yet tested on iOS or by a human.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 17:17:34 -04:00
..