Repository navigation
feat(mobile): move Inbox to Home bell and align spacing - #9193
klopez4212 wants to merge 22 commits into
Conversation
Include Home spacing refinements, separate native glass bell, unread indicator, and matching filter heights. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Constrain label content with standard density so Android capsule paint matches the 48dp controls. Assert the Material surface height as well as the tap target. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
🔐 Codex Security Review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e68ab12de
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| right: _kChannelSectionInset, | ||
| top: _kChannelRowVerticalPadding, | ||
| bottom: _kChannelRowVerticalPadding, | ||
| bottom: Grid.xxs, |
There was a problem hiding this comment.
Restore the minimum tap height for conversation rows
At the default text scale, replacing the 11-point bottom inset with Grid.xxs makes a standard channel row only 41 points high (22-point label + 11 top + 8 bottom), below the existing 44-point inventory-row contract and smaller than its previous hit target. The same asymmetric inset was introduced for Solo chat rows in me_page_helpers.dart, so both frequently used navigation targets become harder to tap; retain the original bottom inset or enforce a minimum row height.
Useful? React with 👍 / 👎.
Restore the original 6pt icon badge placement and fade unread transitions with reduced-motion support. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9beaf90ae0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Badge( | ||
| key: const Key('home-inbox-badge'), | ||
| isLabelVisible: hasUnreadInbox, |
There was a problem hiding this comment.
Reserve the full action width when collapsing filters
When the header is fully collapsed, channels_page.dart still reserves only 60 px on the right for its filters, but this new bell makes the trailing action cluster 96 px wide on iOS and 104 px on Android. With accessibility text scaling or a horizontally scrolled filter bar, the final chip can therefore render and receive taps underneath the bell or community control; base the collapsed right inset on the complete action-cluster width rather than the previous single-action allowance.
AGENTS.md reference: AGENTS.md:L13-L24
Useful? React with 👍 / 👎.
#9168) Fixes five defects in the `buzz` CLI. - **`dms list` returned `[]`.** It queried kind 41001, which the relay no longer publishes. It now reads the viewer's DM group metadata (kind 39000, `t=dm`, `p=viewer`) and drops every DM listed in the viewer's newest relay-signed visibility snapshot (kind 30622), the same hidden set the desktop uses. It keeps paging until it has the requested number of visible DMs or the history runs out, so hidden DMs never crowd out visible ones. Hidden DMs stay hidden; reopening one brings it back. - **Uploads accepted only images and MP4.** The CLI now leaves type acceptance to the relay, as the desktop does: unsniffable files go up as `application/octet-stream`, and the relay's own allow and deny rules apply. Local size caps match the relay's defaults (50 MB images, 500 MB MP4, 100 MB other files). `messages send --file` adds an imeta `filename` (the basename, with control characters and both path separators replaced by spaces) and writes non-media files as a plain link (`[name](<url>)`) instead of ``; inline media still embeds. - **`messages get --kinds` silently ignored bad values.** Any non-numeric or out-of-range (above 65535) kind now fails with a bad-input error, exit 1. - **Upload errors lost their category.** A missing or unreadable file is bad input (exit 1), and `messages send --file` returns the upload's own error instead of wrapping every failure as `Other` (exit 4). The "auth tag may be stale" hint on every 403 is gone: the relay answers 403 for ordinary permission denials, such as a non-moderator reading moderation data, so the hint misled. - **Agents had to pass the relay by hand.** On macOS and Linux, with no `--relay` and no `BUZZ_RELAY_URL`, the CLI uses the relay an agent's inherited `BUZZ_CREDENTIAL_PROVIDER` token acts on, from its `describe` answer. If that lists several relays, it fails with exit 1 and asks for `--relay`. An explicit flag or env var still wins and is still checked against the credential. Paired tokens never choose a relay, `auth desktop unpair` never asks the desktop, and otherwise the default stays `http://localhost:3000`. Help text says so. --------- Signed-off-by: Will Pfleger <[email protected]> Signed-off-by: wpfleger <[email protected]> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
## Why The loadgen agent polled HTTP `/query` every few seconds. A real agent harness (`buzz-acp`) never polls when idle. It works in bursts around each prompt, and those bursts are the load a fleet of active agents puts on the relay. To answer "how well does the relay handle N active users plus their agents over a sustained period", the loadgen needs to model those bursts and hold them for an hour or more. ## What - **`[agent.turn]`**: an idle agent starts a turn on a Poisson schedule and runs one turn at a time. A turn lasts 0.5–1.5 × `mean_secs`. The steps follow `buzz-acp`: - **Start**: a `limit:1` `/query` finds the message to answer (`http_query`), which stands in for the harness's subscription. Then the harness's own reads (`turn_context` op): for a threaded message, its thread context in one `/query` (root by id, newest 13 replies, the agent's own newest reply) plus a `/count` when the window is full. Then kind:39000 metadata, project home (kind:30621, kind:30617) and the author's profile. Then two kind:7 reactions on the message. - **Work**: typing every `typing_secs` and observer frames of `frame_bytes` every `frame_secs` over the socket, plus `reads` tool reads (`/query`, limit 50). - **End**: a threaded reply, under the root that NIP-10 `resolve()` gives. Then reaction removal: query own reactions, then a kind:5 deletion for each. - One HTTP action at a time runs next to the socket. Socket publishes (presence, typing, frames) don't wait for their OK: each OK is matched as it arrives, one missing after 30 s is an error, and at most 128 wait at once. So the socket and HTTP sides stay on schedule while either is slow, as in the harness. A 2xx response that doesn't decode counts as an error. No agent request starts after the stop. - The request mix approximates sustained turns: every turn reads like a first prompt. A harness already holding a thread reads 25 replies (not 13), batches profile lookups and caches project-home lookups for 30 s, so this reads profiles and project homes more often than a busy harness. - `agent.channel_subscriptions`: one live mentions REQ per channel, like the harness. `agent.presence_interval_secs`: presence heartbeats. - `agent.query_interval_secs = 0` turns polling off. - **Sustained holds**: ramp steps may now repeat a level. A 60-minute hold can be six 600 s steps, each one reported and judged, so drift shows up as a trend. - New op `turn_context`. New scenario `perf/scenarios/local-agent-turns.toml`. `perf/LOADGEN.md` documents the model. All new fields are off by default (`turn.per_hour = 0`, presence 0, no channel subscriptions), so existing scenarios run unchanged. ## What got simpler - The agent loop's per-action branches now go through one `sent` result. The observer frame build, the HTTP submit and the `/query` body read are shared helpers. The old inline frame code is gone. - "Hold for an hour, judge every 10 minutes" is now a ramp of repeated levels. No new abort-window concept was needed. - Identified debt, not touched here: abort is still judged only at step end, so a collapsed relay is not detected until the step closes. Repeated short steps reduce that gap. ## Testing - On a Blox workstation at 6bb151d: `cargo fmt --check`, `cargo clippy -p buzz-test-client --all-targets -D warnings`, and `cargo test -p buzz-test-client --lib` (103 passed). The five turn tests passed 10/10 repeated runs. Three mutants (awaiting the OK again, dropping the stop guard in `submit`, dropping it in `query`) each fail a test. - `local-agent-turns` against a local relay at 6bb151d: both steps 0 errors, 0 clients cancelled. - `agent_turns_read_react_stream_reply_and_remove_their_reactions` runs an agent against a fake socket and a fake HTTP relay. It asserts the exact thread-context filters and count, the metadata, project and profile reads, the reactions, typing, frames and presence, and that typing or frames arrive while a tool read is held. It also asserts the threaded reply under the right root and the deletion of exactly the reactions the agent added. - `agent_turns_keep_moving_while_socket_oks_lag`: the same journey with every socket OK 1.5 s late, past the 1 s heartbeat. - `a_turn_stopped_while_adding_a_reaction_sends_nothing_more` and `a_turn_stopped_while_reading_its_reactions_deletes_none`: the stop lands while a reaction POST or removal query is held, and no request follows it. - `agent_turn_reads_that_do_not_decode_are_errors`: 200 responses that are not events count as errors, and no turn reacts. - `a_timed_out_route_is_recovered_again_after_a_renewal` (desktop) fails 2 times in 10 on unmodified main as well. That flake is pre-existing and unrelated to this change. - Live: a single-relay run with 10k humans and 20k turn-taking agents (held at 1x for 60 min, then 1.5x and 2x). Results will be added here. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Luke Tornquist <[email protected]> Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
… into terp-home-split-20261106 Signed-off-by: kenny lopez <[email protected]>
Move the six-point dot two points down and left, adding a one-point contrasting outline while preserving unread animation and semantics. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]> (cherry picked from commit 9093527) Signed-off-by: kenny lopez <[email protected]>
Move the outlined dot one further point down and two left. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]> (cherry picked from commit d7f5f48) Signed-off-by: kenny lopez <[email protected]>
…0261106 Signed-off-by: kenny lopez <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Optically center Android Home labels within their capsules. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd1310c99b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…eshes Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc940d87fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| void _applyLiveEvent(NostrEvent event, int generation) { | ||
| if (generation != _subscriptionGeneration || | ||
| isQuietAgentMessage(event.tags)) { | ||
| return; |
There was a problem hiding this comment.
Page past quiet events during reconnect replay
When a reconnect replays this addressed subscription, its 100-event limit can be filled entirely by newer audience: agents events; this early return discards those events without invoking _refillPastQuiet, so an older user-visible mention from the disconnect window is never merged into Activity or reflected by the unread bell. The initial history path explicitly pages past quiet events, but reconnect replay now needs equivalent paging or a separate filter rather than silently leaving a gap.
AGENTS.md reference: AGENTS.md:L238-L241
Useful? React with 👍 / 👎.
| unawaited(_subscribeLive(generation)); | ||
| if (generation == _subscriptionGeneration) { | ||
| // Overlap the history read, including events arriving during the fetch. | ||
| unawaited(_subscribeLive(generation, since)); |
There was a problem hiding this comment.
🤖 P2 · Successful Retry leaves Activity without live subscriptions
If the initial HTTP query and WebSocket fallback fail, build() exits before _subscribeLive. Retry runs the refresh queue, which can publish a successful snapshot without installing those skipped subscriptions. Because this change also removes the session-state dependency, reconnect no longer rebuilds the provider to recover them.
User/system effect: The feed can look recovered while new mentions, DM updates and hidden-DM resurfacing remain disconnected.
| if (old == null || | ||
| categoryPriority(item.category) <= categoryPriority(old.category)) { | ||
| byId[item.id] = item; | ||
| } |
There was a problem hiding this comment.
🤖 P2 · Deleted Activity items survive reconnect
The retained merge only adds or replaces IDs, and the live filters exclude deletion kinds. If an unread item is deleted while the client is disconnected, reconnect now replays the remaining source events without an authoritative refresh that removes the deleted ID. The old snapshot refresh excluded deleted events; the retained item can now survive until manual refresh or eviction.
User/system effect: Deleted content remains visible in Activity and can keep the unread bell lit.
| final sessionState = ref.watch(relaySessionProvider); | ||
| // The session owns cursor-based replay and jittered reconnect backoff. | ||
| // Watching its status would discard those cursors and reload all history. | ||
| ref.watch(myPubkeyProvider); |
There was a problem hiding this comment.
🤖 P2 · Reconnect replay misses messages with accepted clock skew
After an observed event at timestamp 1000, the replay cursor advances to at least 995. A message arriving during the disconnect at server time 1010 with created_at=980 is valid under the relay’s ±900-second drift allowance but falls behind that cursor. Removing the reconnect history fetch makes replay the only automatic recovery path.
User/system effect: A valid mention or DM from a sender with a modestly slow clock never reaches Activity or its unread indicator after reconnect, even when the replay is below its limit.
) The UI-only part of #9193 by @klopez4212, split out so it can land without the Activity sync changes. - Activity moves from a row in the Home list to a bell button in the Home header, with an unread dot driven by the existing Activity feed and read state. - Home filter capsules match native iOS and Android widths, with a subtle outline on Android when the header collapses. - Home section spacing is tighter. Left out: the reconnect rewrite in #9193's last commit (live events applied in place, no rebuild on reconnect, fatal fallback reads). The Activity provider is unchanged from main. Channel and Solo rows keep their bottom padding so they stay at the 44 pt minimum tap height. ### Validation - Kenny's added tests: `inbox_unread_provider_test` (unread dot) and the Home page bell and filter width tests. - Full mobile suite: all pass except 11 push and notification-toggle tests that fail identically on an unchanged checkout in this environment. - Automated simulator run (iPhone 17 Pro, iOS 27) of a build combining this PR with its sibling split: Home rows measure 44 pt, the bell opens Activity and shows its dot after a row is marked unread, type/sender/Unread filters each narrow the feed, a row opens its conversation, Search results scroll under the fade, and filter labels fit at the largest text size. Screenshots are in Buzz rather than here because they show internal test data. Android was covered only by widget tests. ### Before merge - [x] Automated simulator run of Home, the bell, Activity and channel navigation, with screenshots. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Tom Brow <[email protected]> Co-authored-by: Tom Brow <[email protected]> Co-authored-by: kenny lopez <[email protected]> Co-authored-by: studio <dc2fc481343672df31a689840c09299972e704dac592e0da6f18486646a7ee3e@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
Moves Activity access to a separate Home header bell, with native Liquid Glass on iOS and an unread dot over the glyph (6-point fill, 2-point outline, reduced-motion-aware fade). Matches filter heights to header controls and preserves production iOS Liquid Glass label-sized widths for All / Solo / Team and matches those individual widths on Android. Android filters gain a 1 dp outline at 2% of the active color only when fully collapsed into the navigation bar. The labels include the requested leftward adjustment; bell and community backgrounds match the unselected filters. Includes spacing from #9187; The Activity screen redesign remains separate in #9186.
The bell’s Activity source keeps its live subscriptions across reconnects, using the relay’s cursor replay and jittered backoff instead of reloading history. Incoming events update the bounded feed directly. Failed HTTP and WebSocket fallback reads retain the last successful feed, preserving the unread indicator.
Visual changes validated on Pixel and iPhone with saved sessions. The width refinement preserves the accepted control heights and bell-dot position.
Android expanded and fully scrolled states: