mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
d742fc5f304a430e94e89b0d4a427d17adc1a47f
20 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d742fc5f30 | Use Silo for bundled object storage (#8023) | ||
|
|
83aab8cb5c |
feat(desktop): remove communities locally and stop their agent pairs (#7997)
🤖 Leave contacts the relay before it removes anything locally: it checks the relay's `/info` for NIP-43 membership support, then waits for the relay to accept a signed leave request. When a relay has been torn down, that check fails, Leave throws, and the community stays in the rail. Removing a community also left its relay's managed agent pairs running, and they kept reconnecting to it until the app was quit. **Remove from this device** - A new community action, **Remove from this device**, sits under **Leave community** in the profile menu's community actions. It never contacts the relay. A confirm dialog explains that relay membership isn't revoked. - `useCommunityNavigationTransitions` splits the old `removeCommunity` into `removeCommunityFromDevice` (local-only cleanup and navigation to a fallback community or the discovery screen) and `leaveAndRemoveCommunity` (calls `leaveCommunity`, then runs the same cleanup). Leave's flow hasn't changed. - When Leave fails, the error now adds: "If the community no longer exists, use Remove from this device." The error shown when community discovery state can't be saved no longer says "Membership was removed", so its wording fits both actions. **Agent pairs on a removed relay** - Once the local removal completes, the shared cleanup stops every live agent pair on that relay, including manually started ones. It matches relays with `canonicalRelayUrl`. Stopping is best-effort: failures are logged and the removal still completes. Pairs on other relays aren't touched, and nothing is stopped if another community still uses the same relay. - Both reconcile call sites (`useManagedAgentRuntimeReconciliation` and `bootstrapManagedAgentRuntimePairs`) now go through `reconcileConfiguredManagedAgentRuntimes`. A reconcile that is already running in Rust can't be cancelled, so after it resolves, this helper stops any pair it started whose relay is no longer in the saved community list. - Launch restore runs in the background after `apply_workspace` and can finish after its community is removed. `apply_workspace` takes a restore ticket (the current `launch_restore_generation` in `AppState`) before handing its lock to the restore task. Removing the active community calls the new `invalidate_launch_restore` command, which bumps that generation while holding the runtime transition lock. `restore_managed_agents_on_launch` re-checks its ticket under the same lock and spawns nothing if it changed. If restore takes the lock first, its pairs are registered before invalidation returns, and the removal stop then finds them. Removal never changes `relay_url_override`: the outgoing relay stays applied until the next `apply_workspace`, exactly as on `main`, so in-flight work never falls back to the default relay. Invalidation never takes `workspace_apply_lock`, which restore holds while waiting on the transition lock, so lock order is unchanged. - With no relay applied, backend readers fall back to the default relay, the same state as launch before the first `apply_workspace`. A normal quit and relaunch doesn't bring a pair back on a removed relay: restore targets the applied workspace, and the legacy per-record relay pin is ignored. **Tests** - A `community-rail` e2e case makes the mocked relay's membership check fail, the way an unreachable relay does. It checks that Leave shows the error and keeps the community, and that Remove from this device then removes it, switches to the fallback, stops the agent pair on the removed relay, and leaves the pair on the other relay running. - Unit tests in `managedAgentRelayCleanup.test.mjs` cover relay matching, a stop or listing failure not throwing, and the reconcile fence stopping a pair that started on a relay removed mid-flight. --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> |
||
|
|
d7e8fdb10c |
fix(shared-ui): delay hover disclosures by default (#5821)
**Category:** fix **User Impact:** Hover tooltips and informational popovers now wait for deliberate pointer dwell instead of appearing while users move around the app. **Problem:** Tooltips and hover-controlled popovers appeared after inconsistent, often very short delays, so moving across composer and navigation controls could obstruct the next interaction. **Solution:** Establish a 500 ms shared dwell default with no tooltip skip-delay cascade, apply it to informational hover-controlled Popovers, and preserve immediate click and keyboard behavior. The responsive Community actions navigation submenu retains its documented 80 ms open / 160 ms close timing. ## Before / after | Before | After | |---|---| |  |  | <details> <summary>File changes</summary> **desktop/src/shared/ui/tooltip.tsx** Wraps the Radix provider with documented 500 ms and zero skip-delay defaults. The provider API still permits a future proven exception, but no current `desktop/src` caller overrides either timing. **desktop/src/shared/ui/popover.tsx** Exports the documented shared hover-open timing for controlled popovers; ordinary click/focus Popovers remain immediate. **desktop/src/main.tsx** Uses the shared Tooltip provider defaults at the application root. **desktop/src/shared/ui/sidebar.tsx** Removes the sidebar's instant Tooltip timing override. **desktop/src/features/channels/ui/AddChannelBotTeamsSection.tsx** Removes the local short Tooltip timing override. **desktop/src/features/home/ui/InboxDetailPane.tsx** Removes the local short Tooltip timing override. **desktop/src/features/messages/ui/MessageTimeline.tsx** Removes the timeline's local short Tooltip timing override. **desktop/src/features/messages/ui/MessageTimestamp.tsx** Drops the timestamp-only provider now that its 500 ms, zero-skip behavior is shared globally. **desktop/src/features/channels/ui/BotActivityBar.tsx** Raises composer agent-activity hover dwell from 150 ms to the shared default while preserving immediate click/focus opening. **desktop/src/features/sidebar/ui/ChannelActivityPopover.tsx** Raises channel activity hover dwell from 250 ms to the shared default while preserving immediate focus opening. **desktop/src/features/profile/ui/UserProfilePopover.tsx** Reuses the shared hover timing in place of its equivalent local constant. **desktop/src/shared/ui/PubKey.tsx** Reuses the shared hover timing in place of its equivalent local constant. **desktop/src/shared/ui/markdown/InlineEmojiPopover.tsx** Raises emoji inspection hover dwell from 200 ms to the shared default while preserving immediate focus opening. **desktop/src/features/messages/ui/MessageReactions.tsx** Raises reaction inspection hover dwell from 200 ms to the shared default while preserving immediate focus and reaction clicks. **desktop/src/features/communities/ui/CommunitySwitcher.tsx** Documents the Community actions navigation submenu as an intentional timing exception: 80 ms to open responsively and 160 ms to preserve the pointer bridge into its portalled panel. </details> ## Reproduction steps Move the pointer rapidly across each surface first, then hold it still over a labeled control. Hover-only disclosures should stay closed during transit and open after about **500 ms** of deliberate dwell. Moving directly between adjacent Tooltip triggers should start a fresh 500 ms dwell rather than cascading the next Tooltip open immediately. | Surface | Where to test | What to expect | |---|---|---| | Composer controls | Attachment, emoji, image editor, formatting, and composer toolbar buttons | No Tooltip while sweeping across controls; the hovered control's Tooltip opens after ~500 ms. Clicking remains immediate. | | Message actions | Hover a message, then test reply, react, more-actions, edit, and related action-bar controls | Each Tooltip waits ~500 ms, including when moving between adjacent actions. The action itself still runs immediately on click or keyboard activation. | | Message metadata and content tools | Message timestamps, code-block copy controls, diff controls, system-message controls, and video-player controls | Tooltip appears after ~500 ms. Timestamp behavior should look unchanged; it was already 500 ms with no skip cascade. | | Reaction pills | Hover a reaction with one or more reactors; also click the pill | Reactor Popover waits ~500 ms instead of 200 ms. Clicking still toggles the reaction immediately. | | Inline custom emoji | Hover a rendered custom emoji in message Markdown, then focus it with the keyboard | Emoji inspector waits ~500 ms on hover instead of 200 ms. Keyboard focus opens it immediately. | | Masked links | Hover a masked Markdown link, including one revealed inside a spoiler | Destination Tooltip waits ~500 ms instead of the former app-level 300 ms. Hidden spoilers still reveal no destination; keyboard focus remains immediate. | | Main and collapsed sidebar controls | Collapse the sidebar and hover icon-only navigation/menu buttons; also test community-rail controls | Sidebar Tooltips wait ~500 ms instead of opening instantly. Rapid movement across icons should not produce a tooltip cascade. | | Channel header and management controls | Channel members, huddle, settings, thread-view mode, management rows, and quick-agent controls | Each Tooltip waits ~500 ms; click/keyboard behavior remains immediate. | | Add-channel team chips | Open Add channel where saved teams are available and hover a team chip | Team details Tooltip waits ~500 ms instead of 150 ms; clicking the chip still toggles the team immediately. | | Channel activity preview | Hover a sidebar channel that has activity, then keyboard-focus its trigger | Activity Popover waits ~500 ms instead of 250 ms. Focus opens it immediately, and quickly crossing channel rows should not leave previews in the way. | | Composer agent activity | Run an agent so the composer activity control is present; hover, click, and focus it | Hover Popover waits ~500 ms instead of 150 ms. Click and keyboard focus still open it immediately. | | Inbox and draft controls | Home inbox open-context/more-actions controls, inbox-list controls, draft detail, and drafts panel | Tooltips wait ~500 ms instead of the inbox detail's former 200 ms/local defaults. Clicks remain immediate. | | Profile and public-key previews | Hover avatars, names/mentions, project author identities, and displayed public keys | Profile/pubkey Popovers open after ~500 ms, matching their prior behavior; the change centralizes that timing. Click actions and focus behavior remain immediate. | | Agent, team, memory, and update controls | Managed-agent rows, team identity cards, restart-diff badges, memory actions, setup steps, and update indicator | Tooltips wait ~500 ms and do not cascade when traversing adjacent controls. Actions remain immediate. | | Huddle controls | Huddle bar/indicator, mic controls, and participant-list actions | Tooltips wait ~500 ms; mute, join, participant, and keyboard actions remain immediate. | | Projects and activity surfaces | Project/repository cards, overview rail, contribution graph, activity feed, reviewers, and Pulse note controls | Tooltips wait ~500 ms with a fresh dwell between adjacent targets. Clicking/focusing interactive controls remains immediate. | | Intentional interaction-mode exceptions | Focus a Tooltip trigger; click/focus an ordinary Popover; move the pointer from an open hover Popover into its panel | Tooltip focus and Popover click/focus open immediately because they are explicit user intent, not incidental hover. Hover Popovers retain their 180–200 ms close grace so the pointer can cross into the panel. The Community actions navigation submenu is the intentional exception: it opens after 80 ms and keeps its 160 ms pointer bridge; informational hover Popovers use the shared 500 ms delay. | ## Verification - `pnpm typecheck` - `pnpm check` (passes with three existing diagnostics outside this diff) - `pnpm test` — 4,775 passed - `pnpm build` --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> |
||
|
|
c442a90a17 |
fix(desktop-chrome): preserve balanced layout when sidebar collapses (#6000)
**Category:** fix **User Impact:** The desktop content surface now keeps balanced chrome spacing when the sidebar is collapsed or multiple communities are visible, with a cleaner sidebar transition. **Problem:** Collapsing the left sidebar removed the content surface's left inset, while multi-community layouts also exposed uneven visible gutters and sidebar content during the exit transition. **Solution:** Preserve an 8px visible gutter around the content surface, clip and fade only the sidebar's inner content while it trails off canvas, and leave the opaque shell in place until the existing visibility transition completes. <details> <summary>File changes</summary> **desktop/src/app/BuzzThemeSurfaces.tsx** Preserves a balanced visible left gutter after accounting for the content-edge shadow. **desktop/src/shared/ui/sidebar.tsx** Clips the collapsing sidebar, disables interaction off canvas, and fades/translates its inner content without exposing a different background. **desktop/tests/e2e/community-rail.spec.ts** Adds gutter assertions for single-community collapsed-sidebar and multi-community layouts. **desktop/tests/e2e/sidebar.spec.ts** Covers the collapse opacity, translation, clipping, pointer-event behavior, and restoration on reopen. </details> ## Reproduction steps 1. Launch the desktop app with the Buzz theme and at least two communities. 2. Collapse the channel sidebar. 3. Confirm the main content surface keeps equal visible left and right gutters and does not overlap the community rail. 4. Reopen and collapse the sidebar again; confirm its contents fade and trail right while the chrome background stays opaque, then restore fully when reopened. ## Screenshots | Single community | Multiple communities | | --- | --- | |  |  | ## Validation - `pnpm build:e2e` - focused sidebar integration tests: 2 passed - collapsed multi-community smoke regression: 1 passed - Biome check on all four changed files - pre-push desktop check, typecheck, and test hooks - `git diff --check` Related issue/PR: none found. --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> |
||
|
|
f086eb6544 |
fix(link-previews): send while previews finish in background (#5697)
**Category:** fix **User Impact:** Messages send immediately after submission while link previews finish in the background, with an option to skip delayed preview preparation. **Problem:** Waiting for link-preview metadata or snapshot uploads kept the composer occupied after users pressed Send, while races between completion, timeout, and cancellation risked inconsistent payloads. **Solution:** Freeze and promote speculative preview work into a bounded background send task, clear the composer immediately, and publish exactly once with prepared previews or gracefully without them when skipped, failed, or timed out. https://github.com/user-attachments/assets/987d2f2c-679f-473a-965f-dfb279951e52 <details> <summary>File changes</summary> **desktop/src/features/communities/useCommunityInit.ts** Resets pending link-preview preparation when community context changes so work cannot cross community boundaries. **desktop/src/features/messages/lib/linkPreviewPreparationStore.ts** Adds the coordinator-owned preparation state machine, bounded fallback, Skip behavior, and exactly-once terminal publication handling. **desktop/src/features/messages/ui/ComposerUploadProgressOverlay.tsx** Extends floating background progress UI to include link-preview preparation. **desktop/src/features/messages/ui/ComposerUploadProgressPill.tsx** Adds the preparing-link-preview label and Skip action to the progress pill. **desktop/src/features/messages/ui/MessageComposer.tsx** Hands submitted preview work to the background coordinator and clears the composer immediately. **desktop/src/features/messages/ui/messageComposerAutoSubmit.test.mjs** Updates auto-submit unit coverage for coordinator-owned preview preparation. **desktop/src/features/messages/ui/messageComposerAutoSubmit.ts** Allows submit to promote unfinished preview work instead of blocking composer submission. **desktop/src/features/messages/ui/useComposerLinkPreviews.tsx** Starts preview work speculatively and exposes frozen preparation jobs for adoption by the send flow. **desktop/src/features/messages/ui/useMentionSendFlow.helpers.ts** Carries prepared preview tags through the mention and media payload helpers. **desktop/src/features/messages/ui/useMentionSendFlow.ts** Integrates prepared preview tags into final message publication. **desktop/src/shared/lib/useResolvedLinkPreviews.ts** Exposes the in-flight metadata promise so promoted work can be adopted rather than restarted. **desktop/tests/e2e/messaging.spec.ts** Covers immediate submit, upload handoff, Skip/completion races, failure fallback, auto-send, and exactly-once publication. </details> ## Reproduction steps 1. Enter a supported link and press Send while preview metadata or snapshot upload is still pending. 2. Confirm the composer clears immediately and the floating progress UI shows **Preparing link preview · Skip**. 3. Let preparation finish and confirm one message is published with its preview. 4. Repeat and choose **Skip**; confirm one message is published without waiting for the preview. 5. Simulate preview failure or timeout and confirm the message still publishes once without preview tags. ## Validation - TypeScript, Biome/format, file-size, px-text, and pubkey checks - Full desktop unit suite: 4,734 passed - Focused Playwright messaging suite: 5 passed - Push hooks at `86c0aa7de2ff81b79286c99bf23db12345adc6ca`: desktop check, typecheck, and tests passed --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> |
||
|
|
5acb930821 |
feat(desktop-messages): render compact Buzz permalink chips (#5638)
**Category:** improvement **User Impact:** Buzz channel, message, repository, pull request, and issue links now open reliably and display recognizable context in the desktop app. **Problem:** Buzz links could appear as raw or ambiguous URLs, and navigation links received during startup or community transitions could be dropped before the UI was ready. Repository and issue shares in particular required hover context to understand at a glance. **Solution:** Queue desktop channel/message navigation until the UI is ready, then render bare Buzz permalinks as icon-prefixed chips with concise entity context while preserving user-authored Markdown labels as ordinary links. <details> <summary>File changes</summary> **desktop/src-tauri/src/deep_link.rs** Adds validated channel-link parsing and a deduplicated, acknowledged queue so navigation survives frontend startup. **desktop/src-tauri/src/lib.rs** Registers the pending-navigation state and commands with the desktop application. **desktop/src/features/communities/useCommunityInit.ts** Resets queued navigation safely across community boundaries without leaking stale destinations. **desktop/src/features/messages/lib/channelLink.test.mjs** Covers valid, malformed, and canonical channel permalink forms. **desktop/src/features/messages/lib/channelLink.ts** Defines strict parsing and detection for `buzz://channel/<uuid>` links. **desktop/src/features/messages/lib/composerMessageLinkNode.test.mjs** Extends composer-node coverage for normalized Buzz link content. **desktop/src/features/messages/lib/composerMessageLinkNode.ts** Keeps composer link-node handling aligned with the expanded Buzz link surface. **desktop/src/features/messages/lib/remarkChannelDeepLinks.test.mjs** Verifies bare channel URLs become renderable deep-link nodes without touching code. **desktop/src/features/messages/lib/remarkChannelDeepLinks.ts** Transforms eligible bare channel links into dedicated Markdown nodes. **desktop/src/features/messages/lib/remarkEntityLinks.test.mjs** Covers bare repository, pull-request, and issue detection and code-span exclusions. **desktop/src/features/messages/lib/remarkEntityLinks.ts** Adds dedicated Markdown nodes for bare Buzz project entities. **desktop/src/shared/deep-link.test.mjs** Exercises queued navigation, acknowledgement, serialization, and community-switch behavior. **desktop/src/shared/deep-link.ts** Serializes pending deep-link drains and acknowledges destinations only after successful navigation. **desktop/src/shared/styles/globals/markdown.css** Aligns permalink icon geometry and spacing with agent mention chips. **desktop/src/shared/ui/markdown.test.mjs** Adds integration coverage for every permalink chip, authored labels, fallbacks, icons, and static rendering. **desktop/src/shared/ui/markdown.tsx** Routes channel and entity nodes through the shared presentation path while preserving authored link text. **desktop/src/shared/ui/markdown/BuzzLinkChip.tsx** Introduces the shared interactive/static permalink chip and authored-label inline-link components. **desktop/src/shared/ui/markdown/ChannelDeepLink.tsx** Renders channel shares and references with Hash icons, names, and shortened-ID fallbacks. **desktop/src/shared/ui/markdown/MessageLinkPill.tsx** Renders ordinary message shares with message icons and channel/message context while retaining sent-from-thread behavior. **desktop/src/shared/ui/markdown/entityLinks.tsx** Maps repositories, pull requests, and issues to Projects-aligned icons and contextual labels. **desktop/src/shared/ui/markdown/nodeCache.ts** Includes entity-link rendering in cached Markdown node handling. **desktop/src/shared/ui/markdown/utils.ts** Allows validated channel links through the Buzz URL transform. **desktop/src/shared/useMessageDeepLinks.ts** Drains queued navigation links safely and clears them during teardown. **desktop/src/testing/e2eBridge.ts** Extends the mock bridge with pending-navigation command behavior. **desktop/tests/e2e/community-rail.spec.ts** Verifies queued links do not cross community boundaries. **desktop/tests/e2e/navigation.spec.ts** Covers channel/message deep-link navigation during startup and active sessions. **desktop/tests/helpers/bridge.ts** Adds reusable deep-link mock state and acknowledgement helpers. </details> ## Reproduction steps 1. Run the desktop app and open a channel containing bare `buzz://channel`, `buzz://message`, `buzz://repo`, `buzz://pr`, and `buzz://issue` URLs. 2. Confirm each bare URL renders as one cohesive chip with a type icon, a useful name or shortened identifier, and no duplicated channel `#` character. 3. Add an authored Markdown link such as `[design discussion](buzz://issue?...)` and confirm the supplied label remains an ordinary link rather than becoming a chip. 4. Select channel and message links and confirm they navigate correctly in warm and cold-start states. ## Screenshots / demos Houston dark theme with custom purple accent (`#a855f7`), captured from rebased visual implementation `ad411cc06`; current head `0aafa144f` only adjusts E2E expectations for the visible mention-label behavior shown here. **Composer — channel, message, repository, pull request, and issue pills**  **Message list — channel, message, repository, pull request, and issue pills**  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> |
||
|
|
c86443c599 |
perf(desktop): persist channel snapshot hash (#5684)
## Summary - persist each relay/identity's complete channel list and server hash as one integrity-checked snapshot - paint the snapshot immediately on cold boot, then revalidate with `knownHash` - fail slow-never-wrong: malformed/legacy/partial snapshots and mismatched not-modified responses force an unhashed full fetch - add sidebar boot diagnostics and deterministic unit/E2E coverage for boot, identity/relay isolation, partial writes, mismatch fallback, and community switches ## Safety invariants - channel list and hash are serialized in one localStorage document and replaced together - snapshot ownership is scoped to normalized relay URL plus identity pubkey - a not-modified response is accepted only when its hash exactly matches the hash describing the available list - any missing or impossible hash/list pairing retries `getChannels(null)` before replacing persistence ## Validation At exact commit `19ca25d23c434cc0b8893a93691aaf4c77794f60` with a clean working tree: - `cd desktop && pnpm check && pnpm typecheck` — passed (existing informational Biome findings only) - `cd desktop && pnpm test` — 4,723 passed - `cd desktop && node --import ./test-loader.mjs --experimental-strip-types --test src/features/channels/channelSnapshot.test.mjs` — 13 passed - `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts --grep "cold boot paints" --repeat-each=5` — 5 passed - `cd desktop && pnpm exec playwright test e2e/sidebar-snapshot.spec.ts` — 8 passed - push hooks repeated desktop check/typecheck and all 4,723 unit tests successfully The Playwright suite uses injected bridge delays. Its roughly 0.5–0.6 s snapshot paint and 3.0 s snapshot-to-live readings are synthetic invariant evidence, not production desktop performance measurements. ## Measurement context The controlled current-main investigation is documented separately in `RESEARCH/DESKTOP_PERF_DEEP_DIVE_2026_08_12.md`; its raw local artifacts are `.scratch/summer-perf-deepdive-results-v2.json`, `.scratch/summer-perf-deepdive-run.log`, `.scratch/summer-perf-deepdive-run-2.log`, and `.scratch/summer-perf-deepdive-build-2.log`. Those original timings are also synthetic Chromium/mock-bridge measurements and are not presented as shipped Tauri/WKWebView or production-relay numbers. ## Latest review delta At exact tip `e8e2b1d617aac7ea008258ad9974bbf8da9cd2eb`, storage-denial reads fail open to the live fetch, hashless retries reject `channels: null` before pair/persistence updates, identity-read failure enables a hashless live fetch, and repeated consumers reuse snapshot parsing/integrity validation by storage key + raw document. The four remaining review nits are deferred as non-blocking follow-ups. Validation at this tip: sidebar snapshot E2E 30/30 serial; desktop unit suite 4,725/4,725; full push gate green (desktop check/typecheck/unit, Rust, Tauri). --------- Signed-off-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz> Co-authored-by: Summer <1fdd3cc104e2911eb3b2da6f97d1b25f4a7f3550ded4492b24ff1d95acd66766@buzz.block.builderlab.xyz> |
||
|
|
5babb97ca3 |
feat(desktop): show selected community in rail (#5000)
## Summary - add a persistent vertical pill beside the active community - keep the selected state visually distinct from unread dots and mention badges - preserve the existing `aria-current` selection semantics ## Screenshot  ## Test plan - `pnpm exec biome check src/features/sidebar/ui/CommunityRail.tsx tests/e2e/community-rail.spec.ts` - `pnpm test` (4,387 passed) - `pnpm build:e2e && pnpm exec playwright test tests/e2e/community-rail.spec.ts --project=smoke` (20 passed) - pre-push hooks: desktop check and 4,387 desktop tests passed on `c1e80c66d12f73c4eb5c03a19e932439b14caf2d` Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> |
||
|
|
005fe54d02 |
fix(desktop): outline the selected community (#4969)
**Category:** improvement **User Impact:** Selected communities now use a clear offset outline without tinting or covering their icon. **Problem:** The selected community state replaced the icon surface with an accent fill, obscuring image icons and changing the tile's content treatment. Hover also changed the fill, text color, shape, and opacity, making navigation states visually jumpy. **Solution:** Preserve each community tile's neutral surface and content while using a primary CSS outline for selection and a lighter outline for hover. The transparent outline offset leaves the space around image edges unpainted, and adjusted spacing prevents neighboring outlines from colliding. <img width="200" height="152" alt="Screen Recording 2026-08-05 at 3 23 32 PM" src="https://github.com/user-attachments/assets/5c25b1c0-4be8-41c4-8f1d-ad0010310c92" /> <details> <summary>File changes</summary> **desktop/src/features/sidebar/ui/CommunityRail.tsx** Replaces selected and hover fills with offset outlines, keeps icon presentation stable across states, and adjusts rail and tooltip spacing for the new outline geometry. **desktop/tests/e2e/community-rail.spec.ts** Covers the shared active/inactive surface, radius, text color, opacity, and outline behavior, including hover invariants. </details> ## Reproduction steps 1. Run the desktop app with two or more communities. 2. Give the active community an image icon. 3. Confirm the active icon keeps its original image and receives a 2px primary outline with a transparent 2px gap. 4. Hover another community and confirm only a lighter outline appears; its fill, text color, opacity, and corner radius remain unchanged. 5. Switch communities and confirm the outline follows the active community. ## Screenshots **Full desktop context**  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> |
||
|
|
719f9730d4 |
feat(desktop): allow leaving your final community (#3621)
**Category:** improvement **User Impact:** People can leave their final Buzz community and return to **Join or create a community** without losing their signed-in identity. **Problem:** Buzz Desktop blocked people from leaving when only one community remained. Its existing remove action also changed local configuration without ending relay membership. **Solution:** Allow the final community to be left. Buzz now asks the relay to end membership, removes the community locally only after acceptance, and returns the person to the community selector while keeping their identity signed in. If other communities remain, Buzz switches to one of them. Relay rejection or timeout keeps the community in place and shows an actionable retry error. <details> <summary>File changes</summary> **desktop/src/features/communities/leaveCommunity.ts** Adds signed kind 28936 publishing for active and inactive community relays with actionable timeout handling. **desktop/src/features/communities/leaveCommunity.test.mjs** Covers event shape, relay selection, acceptance gating, rejection, timeout messaging, and cleanup. **desktop/src/features/communities/useCommunities.tsx** Allows final-community removal and clears community-specific storage without touching identity. **desktop/src/features/communities/resolveCommunityRemoval.test.mjs** Covers final, active, and inactive community removal state transitions. **desktop/src/app/useCommunityNavigationTransitions.ts** Gates local removal on relay acceptance and routes to a fallback community or setup selector. **desktop/src/app/AppShell.tsx** Passes the asynchronous leave operation through shell entry points. **desktop/src/features/communities/ui/EditCommunityDialog.tsx** Replaces the local-only remove action with a pending-aware Leave Community action that retains actionable errors. **desktop/src/features/communities/ui/CommunitySwitcher.tsx** Enables leaving the final community and carries the asynchronous callback. **desktop/src/features/sidebar/ui/AppSidebar.tsx** Carries the asynchronous leave callback through sidebar props. **desktop/src/features/sidebar/ui/CommunityRail.tsx** Enables leaving the final community from rail settings. **desktop/src/features/sidebar/ui/SidebarProfileCard.tsx** Carries the asynchronous leave callback through profile community settings. **desktop/src/testing/e2eBridge.ts** Teaches the mock relay to accept NIP-43 leave events. **desktop/tests/e2e/community-rail.spec.ts** Updates leave interactions and verifies final-community setup navigation, storage cleanup, and identity preservation. </details> ### Reproduction steps 1. Run Buzz Desktop with a signed-in identity and one joined community. 2. Open Community settings and choose **Leave Community**. 3. Confirm the app shows **Join or create a community** and the existing identity remains signed in. 4. Repeat with two communities and confirm leaving the active one switches cleanly to the remaining community. 5. Reject or withhold the relay `OK` response and confirm the community remains configured with an actionable error in the dialog. ### Test plan - `pnpm check` - `pnpm build` - `pnpm test` (3,913 passing) - `pnpm build:e2e && pnpm exec playwright test tests/e2e/community-rail.spec.ts --grep "final community"` <img width="557" height="316" alt="image" src="https://github.com/user-attachments/assets/b628182f-cba5-451d-ae4b-bee8d8dd19aa" /> --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> Co-authored-by: npub14ndfusear8wdpe4kss8h7juc7wjk78atnqzf63zvppcpneknv4sq6x9370 <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> |
||
|
|
631b05c883 |
feat: ship Buzz Term (#4347)
## Summary - ship **Buzz Term** end to end: the terminal engine/runtime, mounted desktop substrate, and user-visible naming - add Quinn's tape-deck-inspired banner: a beveled chassis filled by the `buzz term` wordmark, surrounded by a complete-hex field - derive the wordmark's three-stop sweep from each theme's terminal palette so primary, secondary, and accent roles remain visibly distinct across all 62 shipped themes, including light themes - paint the banner once on its own pointer-transparent canvas; PTY rendering beneath it remains unchanged ## Banner behavior - uses the renderer's shared `8.4 × 17` cell metrics and production aspect ratio `2.0238` - regenerates only for viewport/theme changes; palette switches repaint correctly while the banner is visible - dismisses on non-empty output from the active terminal session; empty output and inactive sessions do not dismiss it - fails closed below **70 columns** rather than squeezing or clipping the wordmark - adds **8 lines** to `terminalRenderer.ts` for shared cell metrics and **zero lines inside `paint()`** ## Screenshots | Buzz (light) | Buzz Dark | |---|---| |  |  | | Kanagawa Lotus (light) | Red | |---|---| |  |  | Additional production-aspect finals: [Vesper](https://buzz.block.builderlab.xyz/media/9ca6514b63f8cfb2107a85ca46f16a940c0883848e6fbc718e411af94aa13100.png), [Min Dark](https://buzz.block.builderlab.xyz/media/f67bd2970e5d64ffb07b1ae78ab58c847e6ebc23e7e7a48e067eb024dba64ec8.png), and [Dark Plus](https://buzz.block.builderlab.xyz/media/290fee08924f37d064abc687ecf3e9526ab05b87e8e56d610f23048949793dbe.png). The screenshot harness was checked against the shipped painter at this exact head: all **2,541 draw calls** matched on color, glyph, x, and y; four deliberate divergence controls fired. ## Verification at `98ebc8f9048bd5f0ceb7e843b67874d642f0b7fd` - desktop tests: **3,946 / 3,946** - TypeScript: clean - checks: pass (two pre-existing informational `useTemplate` notices only) - integration/e2e: PASS (independent exact-SHA lane; artifacts recorded in the originating Buzz thread) - artifact/dead-path sweep: clean - redteam G1–G7: PASS - all six named banner emitter-deletion mutants die - independent handwritten five-row full-wordmark fixture kills Quinn's seven-mutant battery, including a one-pixel glyph change - real `112 × 46` canvas-rect dismissal tests separately cover active non-empty, active empty, and inactive non-empty output - layer-drop and zero-draw painter mutants die; z-order and pointer-events verified - CI's `tsc && vite build` includes all three banner modules - performance at DPR 2 (worst-case measured envelope): - one-time content paint: **~0.7–0.8 ms**, paid only when the banner is built or its palette changes - busy compositor, CSS `1277 × 697`, backing `2554 × 1394`: **470–497 µs/frame** for the full banner (**2.82–2.98%** of a 60 Hz frame) - busy compositor, CSS `1920 × 1080`, backing `3840 × 2160`: **1,139–1,212 µs/frame** (**6.83–7.27%**) - empty, one-glyph, and full-banner controls converge: compositor cost follows backing-layer area and DPR rather than painted-cell count - in the actual idle welcome state, cost is below both vsync-clamped rigs' resolution; it is not claimed as zero - **Pane cross-rig spread: resolved at matched loop rate.** Two independent rigs initially differed 2.3× (58–68 vs 136 µs/Mpx of backing store; pane, CSS 1277×697 / backing 2554×1394, DPR 2). The cause of *that* spread is rAF loop rate: the higher figure came from a free-running loop at ~1600fps. Throttled to ~200–236fps, both rigs read 58–68 µs/Mpx (1.25–1.44% of a 60Hz frame). The busy-composite figures quoted above remain the **unthrottled worst case** and are conservative by ~2.3× at the pane. Not established: the mechanism and sign of free-running distortion (one rig under-charges ~15%, the other over-charges 2.3×), and the 1080p figure has not been re-measured throttled. - the layer paints only on generation/theme/resize and dismisses on first non-empty active-session output, so the measurable busy cost is a short-lived worst case rather than a persistent PTY paint-path tax ## Follow-ups in this PR These are intentionally subsequent commits after the certified static-banner head, not claims about `98ebc8f90`: 1. close the compositor metrology: remeasure the 1080p point throttled and characterize the opposite-sign free-running rAF distortion, with each measurement regime stated 2. add Tyler's animated honeycomb color waves, gated by `prefers-reduced-motion`, a full 62-theme phase-sweep contrast check, and DPR-2 per-tick performance certification 3. land the already-proven mounted theme-switch regression probe from `RESEARCH/BUZZ_TERM_G3A_PROBE/` 4. bound the slow/hang-shaped G1-c mutant `waitFor` 5. optionally trim the generator to its ink bounding box, reducing the minimum viewport from 70 to 62 columns --------- Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz> Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz> Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz> Signed-off-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@buzz.block.builderlab.xyz> Co-authored-by: npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6 <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz> Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz> Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@buzz.block.builderlab.xyz> Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz> Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> |
||
|
|
b29c8cdaa4 |
feat(desktop): redesign the Huddle experience (#4281)
## Summary - open Huddles in a focused companion window with a clean handoff back to the in-app drawer and backing channel - redesign the participant film strip, sidebar control, transcript surface, and themed shell treatment - preserve microphone and device control across windows, start agent voice on the first reply, and show agent speaking activity in the film strip - give each agent a distinct session voice, beginning with the configured default, plus compact per-agent text-to-speech and voice controls - enroll only agents explicitly mentioned or deliberately added through an agent panel into the live Huddle roster - keep temporary Huddle channels out of the sidebar unless the user explicitly brings one into the main app - remove Huddle-only avatar policy badges and filter short silence or noise segments before speech-to-text posts ## Why The previous flow exposed the temporary channel as product UI, obscured who was present or speaking, and split transcript and audio state between the main and companion windows. This keeps backing channels as implementation details unless a user explicitly brings a Huddle into the app, while sharing the live conversation and audio lifecycle across both surfaces. Agent participants now join only after an explicit invitation, distinct voices make multi-agent Huddles easier to follow, and short microphone noise no longer becomes stray transcript messages. ## Validation - `pnpm check` - `pnpm build:e2e` - `pnpm exec playwright test tests/e2e/huddle-transcription.spec.ts --project=smoke` (13 passed) - Huddle sidebar visibility unit coverage (4 passed) - focused managed-agent and persona-mention E2E coverage (2 passed) - `pnpm test` (3,910 passed) - `cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warnings` - `cargo test --manifest-path desktop/src-tauri/Cargo.toml` (2,093 passed, 14 ignored; 3 diagnostics passed) --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> |
||
|
|
310df2ec33 |
desktop: restore direct community member adds (#3634)
## Summary - restore direct community member adds in **Settings → Invites** - keep one consolidated entry point: the dialog now supports both adding someone directly and sharing an invite link - accept npub or 64-character hex keys while preserving role hierarchy (owners: Member/Admin; admins: Member only) - verify an npub direct-add publishes the decoded hex key in a kind `9030` NIP-IA event ## Why The Invites consolidation left `AddMemberDialog` without a live mount point, so the existing direct-add capability disappeared even though its mutation path still existed. This reuses that implementation rather than introducing a second one. ## Before and after | Before | After | | --- | --- | | The consolidated dialog only offered a share link; there was no direct-add path. | The same dialog now presents direct add and share-link controls as one invitation flow. | |  |  | <details> <summary>Before: Invites page entry point</summary>  </details> ## Verification - `pnpm --dir desktop build:e2e` - `pnpm exec playwright test tests/e2e/invites-settings-screenshots.spec.ts --project=smoke` — 4 passed - targeted Biome check on modified files - push hook: Desktop check and 3,783 Desktop tests passed - GitHub CI green except Desktop E2E Relay still running at last status snapshot --------- Signed-off-by: Joah Gerstenberg <joah@squareup.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Signed-off-by: kenny lopez <klopez4212@gmail.com> Co-authored-by: Joah Gerstenberg <joah@squareup.com> Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Co-authored-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
1d3b810ad7 |
fix(desktop): paint community rail full height (#3382)
## Summary - paint the community rail across the full app height instead of exposing the parent background through external margins - preserve the existing community-button alignment and balanced horizontal gutters by moving vertical spacing inside the rail - update the rail geometry coverage to require full-height paint ownership ## Root cause PR #2972 aligned the rail box with the inset content by adding top and bottom margins to the `bg-sidebar` element. Margins are outside the painted box, so flat light and dark themes exposed a differently colored app background above and below the rail. ## Validation - pre-push `desktop-check` - pre-push desktop unit suite: 3,751 passed - `git diff --check` Local Playwright/E2E was not run; CI owns the full browser matrix. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> |
||
|
|
e6c90bb7c4 |
Polish community rail and mobile pairing (#2972)
## Summary - align the multi-community rail with the content surface and balance its visible 10px side gutters - center Mobile pairing, start sessions on demand, and keep retry states inside the QR area - reveal the QR code and copy action with 250ms motion and use the standard loading spinner The rail was centered within its own box, but the adjacent sidebar added another 11px to the visible right gap. Mobile pairing also started before user intent, which could leave an idle session waiting for EOSE. ## Validation - `pnpm -C desktop build:e2e` - `pnpm -C desktop test` — 3,516 passed - `pnpm -C desktop exec playwright test tests/e2e/community-rail.spec.ts --project=smoke` — 19 passed - `pnpm -C desktop exec playwright test tests/e2e/mobile-pairing-qr.spec.ts --project=smoke` — 1 passed `pnpm -C desktop check` is currently blocked by the existing `src-tauri/src/managed_agents/runtime.rs` file-size baseline (2,220 lines; limit 2,216). |
||
|
|
384c72dee6 |
Refine community management flows (#2738)
## Summary - simplify Add community into clear create and join paths - align community actions and icon editing across the rail, profile menu, and settings - consolidate invites around the member list and a reusable link dialog ## Testing - `pnpm check` - `pnpm test` (3,483 passed) - `pnpm run build:e2e` - focused Playwright coverage (34 passed) ## Snapshots | Add a community | Join an existing community | | --- | --- | |  |  | | Create a new community | Hosted community icon | | --- | --- | |  |  | | Invites | Invite link | | --- | --- | |  |  | --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> |
||
|
|
95478919fc |
feat: remember per-community navigation location (#2629)
Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz> Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz> |
||
|
|
1e68c6c050 |
feat(desktop): add drag-to-reorder for community rail (#2549)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> |
||
|
|
f06b59ff13 |
feat(desktop): graduate community rail (#1995)
Signed-off-by: npub1k766u8wq088nkr9vy94uqlh9kmw5956g593a7xk7cks7frhgctmsr00p27 <b7b5ae1dc079cf3b0cac216bc07ee5b6dd42d348a163df1adec5a1e48ee8c2f7@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1k766u8wq088nkr9vy94uqlh9kmw5956g593a7xk7cks7frhgctmsr00p27 <b7b5ae1dc079cf3b0cac216bc07ee5b6dd42d348a163df1adec5a1e48ee8c2f7@sprout-oss.stage.blox.sqprod.co> |
||
|
|
3e76481a14 |
refactor(clients): standardize product naming on community (#1858)
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> |