18136 Commits
Author SHA1 Message Date
Claude 16030599d9 fix(concord): align top-bar height and simplify channel rows
Route the Concord community screen and hub through ShorterTopAppBar (50dp)
instead of the raw Material3 TopAppBar (64dp default), so the top bar — and
its 3-dot overflow menu — sits at the same height as the Buzz/relay-group
community screen, which already uses the shorter bar.

Also drop the recent-posters facepile from the Concord and Buzz channel
rows, and move the last-message time up to the first line (next to the
channel name), leaving the unread-message badge on the second line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017x22okBh6HbiCrJN3zf5xn
2026-07-29 17:18:29 +00:00
Claude ee8623bd20 refactor: dispatch all NIP-71 video kinds via the VideoEvent interface in NoteCompose
RenderNoteRow matched the four concrete video subtypes (VideoNormalEvent 21,
VideoShortEvent 22, VideoHorizontalEvent 34235, VideoVerticalEvent 34236) with
four identical branches. Collapse them into a single `is VideoEvent` branch,
matching how ThreadFeedView's NoteMaster already dispatches, so any future
VideoEvent subtype renders through VideoDisplay automatically instead of
falling through to the text fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QCKP4tD2seoDpr3ZcdPJNx
2026-07-29 17:01:53 +00:00
David KasparandGitHub 7e6170390d Merge pull request #3808 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-07-29 18:52:04 +02:00
Claude de1c4905cc Revert "fix: make mention connector a solid tapering wedge"
Back to the curved thin connecting stroke.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:44:17 +00:00
vitorpamplonaandgithub-actions[bot] 0279938e05 chore: sync Crowdin translations and seed translator npub placeholders 2026-07-29 16:41:58 +00:00
Claude 536d3cf1a5 fix: make mention connector a solid tapering wedge
Fill the connector as a solid region: thick at the gem's right side,
tapering to the gem's bottom tip and merging into the ring's upper opening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:38:52 +00:00
Vitor PamplonaandGitHub 979ce7a96f Merge pull request #3812 from vitorpamplona/claude/buzz-channel-delete-persist-e3lex3
NIP-29: Channel deletion, archival, and Buzz community UI
2026-07-29 12:38:42 -04:00
Vitor PamplonaandGitHub 7cda707380 Merge pull request #3811 from vitorpamplona/claude/draft-note-expansion-threadview-u2u32l
Make draft posts in thread view open edit screen on tap
2026-07-29 12:36:44 -04:00
Claude b58543fb2d fix: curve the mention connecting stroke
Replace the flat bar with a curved stroke that sweeps down from the gem and
up into the ring's upper opening, reading as a natural @.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:33:30 +00:00
Claude 707cffec6d fix: connect mention tail to the upper end of the ring opening
The bridge now joins the gem to the ring's upper-right end (~3 o'clock),
leaving the lower-right as the ring's free opening — the correct @ side.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:29:15 +00:00
Claude d44264a1ac feat(buzz): fix channel/forum type on the create screen from the caller
The create screen no longer shows a "Forum channel" toggle — the type is decided
by the community's per-section "+" (Channels vs Forums) and a Buzz channel's
channel_type isn't editable anyway (the relay's 9002 has no such key). The screen
loads with the fixed isForum parameter and creates the right type; its top-bar
title reads "New forum" when isForum, "New channel" otherwise (on Buzz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 16:22:34 +00:00
Claude 04243d8dfa fix: open edit-draft screen when tapping a draft in ThreadView
Tapping a note in the thread view toggles the collapse/expand state of
its children. For the user's own drafts, tap now opens the edit-draft
screen (via routeEditDraftTo) so the post can be resumed, matching the
behavior everywhere else a draft is tapped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQCNuxdYkfouNN3ujxm3mR
2026-07-29 16:19:17 +00:00
Claude 60161e3fae fix: mention tail connects the gem to the ring
Bridge the tail from the gem's bottom down into the ring's lower opening,
like the inner "a" stem joining the circle in an @.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:14:33 +00:00
Claude ca61eb107d fix(buzz): drop deleted channels that leaked as bare UUID rows
A channel deleted elsewhere (or before this device saw its metadata) keeps its
kind-44100 membership — the relay never retracts it — but the relay soft-deletes
its 39000, and it does NOT serve a channel_deleted 40099 for an already-deleted
channel, so the discovery fetch can't catch it. Such a channel arrived with no
metadata and was shown optimistically: a bare UUID row with "No messages yet".

The reliable signal is that very metadata absence. BuzzRelayImportViewModel.discover
now drops channels the relay serves no 39000 for — but only when the fetch clearly
worked (some channel returned a 39000); if none did, the read failed (auth/
connectivity) and the whole set is kept rather than blanking the community. A
genuinely new channel whose 39000 is merely slow returns on the next bind once its
metadata is cached, so the prune is live (not persisted) and self-correcting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 16:09:11 +00:00
Claude 9d2c5e0cee fix(buzz): show the channel/forum "+" on any community, not gated on an unloaded roster
The "+" was gated on BuzzCommunityMembership (kind-13534), but that roster is only
fetched by the Members screen — nothing on the channel-list screen subscribes to
it, so isMember read false and the "+" hid even from admins. Match the workspace
overflow menu's approach instead: offer create on any Buzz community and let the
relay reject a non-member's kind-9007 (its own doc: "any member sees them, the
relay only serves the owner/admin ones").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 16:07:07 +00:00
Claude e6bce31249 feat: add connected @ tail to the mention ring
The tail now flows out of the ring's upper opening end and hooks to the
right, connected to the ring rather than floating beside it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 16:05:44 +00:00
Claude 38e5c848a4 feat: add @ opening to the mention ring
Cut a clean gap in the lower-right of the circle for the @ opening, with no
separate tail curve.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:54:25 +00:00
The Daniel ac426531f3 feat(nip73): show rich previews for external-content comments
Kind 1111 comments scoped to a NIP-73 external identifier (e.g. a web
article) rendered as a bare URL with no context. Reuse the existing
OpenGraph preview pipeline so feed rows, expanded threads, the
reply-compose banner, and the URL thread screen all show a rich
image/title/description card instead, and give the URL thread screen
a proper scrolling header instead of a bare title.
2026-07-29 11:50:17 -04:00
Claude 967d51b6f9 fix: mention is a gem inside a clean complete circle
Drop the @ tail attempts, which read as a drooping curve. The mention is
now just the centered Amethyst gem with a clean full circle around it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:46:21 +00:00
Claude 21329b6dab fix: reshape mention @ tail to flick out to the right
The tail read as a downward-drooping comma; reshape it to flick outward to
the right like a proper @ tail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:44:31 +00:00
Claude 240f4e67a6 fix: thicken the mention circle stroke
Widens the @ ring stroke (1.4 -> 2.1) for a bolder circle around the gem.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:38:25 +00:00
Claude a41db22030 feat: redo mention as a clean @, bump chess gem 2%
- Mention: gem centered like the "a" with a near-complete circle around it,
  opened at the lower-right with a small tail — a proper @ shape, ring no
  longer touching the gem.
- Chess: enlarge the gem 2%.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:36:19 +00:00
Claude 417147cfe7 fix: move chess gem to the right side of the box
Positions the Amethyst gem on the right, blending into the knight's base
where they meet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:33:28 +00:00
Claude afaf5f582b feat: balance code icon; blend chess gem into the knight
- Code: widen the < > chevrons (0.62 -> 0.85) and shrink the gem (12 -> 10)
  for a more even balance.
- Chess: enlarge the Amethyst gem so it rides over and blends into the
  bottom of the knight.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:27:38 +00:00
Claude c13d2840b9 fix: match code gem height to the < > height
Grows the centered Amethyst gem so its height equals the bracket height
(y6..18); the slimmed chevrons leave room for it to sit between them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:21:57 +00:00
Claude bdc21fee1e fix: slimmer code brackets, bigger gem
Thins the < and > chevrons horizontally about their own tips (height kept,
still at the far edges) and enlarges the centered Amethyst gem (7.6 -> 8.8).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:20:26 +00:00
Claude 22383e7a1c fix: spread code < > to the far left/right edges
Splits the brackets and pushes < to the left edge and > to the right edge,
opening a clean centered gap for the Amethyst gem.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:17:19 +00:00
Claude 6ba53918c4 feat: @-style mention, rebalance zap, narrow code brackets
- Mention: thinner ring whose open lower-left end flows into the gem's
  bottom-left facet via a tapered stroke, echoing how an @ is drawn.
- Zap: enlarge the bolt and shrink the top-right gem.
- Code: squeeze the < > brackets narrower (width only, height kept) so they
  hug the centered gem.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:15:36 +00:00
Vitor PamplonaandGitHub 2496a7fb3d Merge pull request #3809 from vitorpamplona/claude/flaky-quic-stream-drain-oge3ze
Fix flaky PeerUniStreamDrainTest by confining drainer to producer's event loop
2026-07-29 11:09:18 -04:00
Claude c422a9d022 feat: rework zap layout — bolt left, gem in the top-right corner
Replaces the centered gem-knockout bolt with the bolt moved to the left
and the Amethyst gem as a separate mark in the top-right corner, mirroring
the reply layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:09:14 +00:00
Claude 3510296673 fix: make the reply arrow and gem larger still
Grows the reply arrow (0.78 -> 0.9) and the top-right gem (0.045 -> 0.052)
to fill more of the canvas, keeping the diagonal layout without collision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:06:49 +00:00
Claude f723310dc7 feat(buzz): archive/unarchive channels + fix visibility edits on Buzz
Two channel-management gaps vs the Buzz interface (both ride kind-9002 tags; no
new protocol), verified against block/buzz:

Archive/Unarchive — the reversible hide-from-the-sidebar the Buzz client has,
distinct from delete. EditMetadataEvent gains an `archived` tag; Account/
AccountViewModel expose archiveRelayGroup; the channel and forum top bars offer
Archive/Unarchive to admins (no confirm — it's reversible). The relay stamps
`["archived","true"]` on the 39000, so GroupMetadataEvent.isArchived() /
RelayGroupChannel.isArchived() read it directly; the community list drops archived
channels out of Channels/Forums into a collapsed "Archived" tail from which they
can be reopened and unarchived.

Visibility-on-edit — a Buzz relay reads its own `visibility` (open/private) tag,
not the NIP-29 `private` status flag, so the edit screen's private toggle was a
silent no-op on Buzz. editRelayGroupMetadata now sends the `visibility` tag on
Buzz relays (status flag still sent for vanilla NIP-29).

Not gaps (checked): topic/purpose/TTL are in the relay's system-message
vocabulary but not extracted on 9002/9007, so there's nothing to mirror.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 15:05:59 +00:00
Vitor PamplonaandGitHub 662bd87495 Merge pull request #3807 from vitorpamplona/claude/swipe-reply-sensitivity-y0y0v1
Refactor chat bubble swipe gesture to use lower-level pointer APIs
2026-07-29 11:05:32 -04:00
Claude 6e2a8f00f4 fix: enlarge reply arrow and gem
Bumps the reply arrow (0.62 -> 0.78) and the top-right Amethyst gem
(0.035 -> 0.045) so both read larger while keeping the bottom-left /
top-right diagonal layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 15:02:42 +00:00
Claude 21c44cfc36 test(quic): de-flake PeerUniStreamDrainTest slow-consumer overflow
drainPeerInitiatedUniStreamsIntoBlackHole_keeps_connection_alive passed
in isolation but flaked under parallel load with the audit-4 #3
"slow consumer overflowed incoming channel" teardown.

Root cause: the test ran the black-hole drainer on the shared
Dispatchers.Default pool. The drainer only has to keep the 64-deep
per-stream incomingChannel drained, but when the rest of the JVM test
suite saturates every Default worker thread the drainer coroutine can be
denied a scheduling slot long enough for the synchronous feed loop to
push more than 64 chunks ahead of it, tripping the slow-consumer
teardown. The fixed-delay yields (delay(1) every 16 chunks) do not help
when all pool threads are pinned.

Fix: run the drainer on the runBlocking coroutine's own single-threaded
event loop (CoroutineScope(coroutineContext + SupervisorJob())) and pace
the feed loop with cooperative yield() instead of wall-clock delays. Each
yield deterministically runs the drainer's queued channel-receive
continuation before the producer resumes, so the buffer never approaches
its bound regardless of machine load. The drain contract under test
(parser trySend -> incomingChannel -> collect -> discard) is exercised
identically; only the scheduling is pinned.

Verified with a temporary reproduction that pins every Default worker
thread: the old Default-scheduled drainer overflows to CLOSED while the
confined drainer stays CONNECTED under the same saturation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGZt6D298kGv2XgAi3Uuaj
2026-07-29 15:02:16 +00:00
David KasparandGitHub cb648011d3 Merge pull request #3806 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-07-29 16:59:01 +02:00
Claude 22503b8fe3 fix: tidy article icon lines and drop-cap alignment
Four evenly-spaced text lines (two short up top beside the gem drop-cap,
two full-width at the bottom) with equal spacing, and the drop-cap gem's
top aligned to the top line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 14:58:44 +00:00
Claude 0284c8c86a fix: keep swipe-to-reply from stranding the chat bubble off-screen
Two ways the bubble could get stuck shifted sideways (dragOffset frozen at a
non-zero value, reply icon left visible), both fixed:

1. Cancelling the settle-back animation on awaitFirstDown — which fires for
   every touch, including one that turns out to be a vertical scroll — while
   settleBack() only ran on the horizontal-drag path. A scroll started during
   an in-flight settle froze dragOffset. Now the settle is cancelled only once
   a horizontal drag is actually committed, so every cancel is paired with a
   settleBack().

2. Keying pointerInput on the onSwipeReply lambda. The caller allocates a fresh
   lambda every recomposition (it captures the note), so the detector was torn
   down and restarted on every row update. A restart mid-drag cancelled
   horizontalDrag before settleBack() ran, stranding the bubble; idle restarts
   also churned the gesture coroutine across all visible bubbles. Now keyed on
   the stable isLoggedInUser, with the callback read through rememberUpdatedState
   and the drag wrapped in try/finally so an interrupted drag always settles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016f7dTu8RoJRXjnHM7FKAE2
2026-07-29 14:58:08 +00:00
davotoulaandgithub-actions[bot] d504e43924 chore: sync Crowdin translations and seed translator npub placeholders 2026-07-29 14:58:05 +00:00
Claude 422bf10337 feat: rework reply, zap layout and grow reaction gem
- Reply: keep the arrow at its size but move it to the bottom-left and put
  the Amethyst gem in the top-right corner.
- Zap: scale the bolt up to fill the canvas and knock the gem out of its
  center (inverted), so the logo reads in front of the bolt.
- Reaction: grow the heart's knocked-out gem ~10% and nudge it toward the
  bottom of the heart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 14:57:05 +00:00
davotoula f353389892 update cs,sv,de,pt 2026-07-29 16:54:25 +02:00
Claude 97ff971542 feat(buzz): move per-row channel actions into the opened screen's top bar
The community list rows (channels, forums, DMs) each carried a 3-dot overflow —
Pin/Unpin and Add/Remove-from-Messages. Those are gone; each row is now a clean
tap-to-open target and its actions live in the top-bar overflow of the screen it
opens:

- Channels & DMs open RelayGroupChatScreen (RelayGroupTopBar): add Pin/Unpin
  (Buzz, non-DM) alongside the existing Messages toggle. A DM has no kind-10009
  entry, so its Messages toggle drives the DM-specific hide/unhide (kind-41012 /
  re-open) read from the per-viewer 30622 snapshot; the DM overflow is always
  shown so that action stays reachable.
- Forums open RelayGroupThreadsScreen: give its top bar an overflow with Pin/Unpin
  and Add/Remove-from-Messages.

Shared BuzzPinDropdownItem / RelayGroupMessagesDropdownItem keep the two bars
consistent. AccountViewModel gains hideBuzzDm/unhideBuzzDm wrappers. The
community-list top-bar overflow (Add people, Invite, Agent Console, Add all) is
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 14:36:42 +00:00
Claude ce25273898 perf: animate swipe-to-reply icon in the layer phase, not composition
The reply icon's fade/scale read dragOffset in composition, and because Box is
an inline composable that read invalidated the whole ChatBubbleLayout on every
drag and settle frame. Gate the icon on a derivedStateOf boolean that flips only
at the 0<->non-0 edges (icon added/removed twice per gesture) and move the
progress math into the icon's graphicsLayer block so it's read in the layer
phase. The bubble translation was already deferred; now the entire swipe and
settle animate with zero recomposition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016f7dTu8RoJRXjnHM7FKAE2
2026-07-29 14:33:47 +00:00
Vitor PamplonaandGitHub 3cfa2e0efb Merge pull request #3805 from vitorpamplona/chore/bump-winget-manifest-v1.13.1
chore: sync winget manifests to v1.13.1
2026-07-29 10:33:20 -04:00
vitorpamplonaandgithub-actions[bot] bf73e0934a chore: sync winget manifests to v1.13.1 2026-07-29 14:31:13 +00:00
Vitor Pamplona 8a183d1cbd refactor(ci): move the Winget bump out of CI onto a maintainer machine
Mirrors the Homebrew cask change. The old design stored a classic `public_repo`
PAT as WINGET_TOKEN and handed it to the third-party
vedantmgoyal9/winget-releaser action: a token with write access to every public
repo the owning account can reach, given to code we do not control, in a place
any push-access collaborator could read it from (a pushed branch containing a
workflow runs with repo secrets).

- CI (bump-winget.yml, now "Sync Winget Manifest Reference") uses GITHUB_TOKEN
  only: downloads the MSI, computes the sha256, reads the ProductCode from the
  MSI Property table via msitools, and opens an in-repo PR syncing
  desktopApp/packaging/winget/. Runs on ubuntu (1x billing) rather than Windows
  since msitools reads the Property table fine.
- scripts/bump-winget.sh does the upstream PR. It needs NO new token: it drives
  `gh`, which a maintainer already has authenticated, and it does not need
  wingetcreate (Windows-only) because the manifests are plain YAML — so it runs
  from macOS or Linux.

Add the three reference manifests under desktopApp/packaging/winget/, matching
the schema 1.12.0 shape used upstream. All three validate against Microsoft's
published JSON schemas.

Validation caught one real bug worth noting: an all-digit 64-char InstallerSha256
parses as a YAML *integer* and fails the schema's `string` type, so it is written
quoted. ProductCode is re-read every release because jpackage regenerates it per
build; it is the ARP key `winget upgrade` matches on.

Drops the last package-manager PAT from the secret inventory.
2026-07-29 10:30:21 -04:00
Claude 34fa103dbd feat(buzz): gate the channel/forum "+" to community members
Only a Buzz community member may create a channel (the relay makes the creator
its owner; a non-member's kind-9007 is rejected), so the section-label "+" now
shows only when the viewer is in the community's NIP-43 roster. Reactive: the
relay-signed roster snapshot (kind 13534, republished on every membership change)
can arrive after first composition, so BuzzCommunityMembership is re-read whenever
one lands. The section labels themselves still render for everyone; only the "+"
is gated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016MNVEKhaAu4vQRZnXv3rfG
2026-07-29 14:26:23 +00:00
Claude b4798331e8 fix: shrink badge gem ~20%, grow heart gem ~10%
Rebalances the two knockout icons: the badge gem drops from 11.6 to 9.3
(more disc margin around the mark) and the reaction heart gem grows from
8.2 to 9.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 14:23:12 +00:00
Claude 0703797bdb feat: bigger repost arrows; invert + maximize gem in badge
- Repost: scale the repeat-arrow glyph up ~15% so it fills the canvas like
  the original, with the centered gem enlarged to match.
- Badge: replace the medal ring + inner-circle-with-logo with a solid disc
  that has the Amethyst gem knocked straight out of it (inverted), sized to
  fill the disc. Ribbon tails kept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GXfHYcViokBQRtqCW9vLQi
2026-07-29 14:20:16 +00:00
Vitor Pamplona db529444c4 refactor(ci): move the Homebrew cask bump out of CI onto a maintainer machine
`brew bump-cask-pr` forks homebrew-cask into the token owner's account, which
requires a CLASSIC PAT with the `repo` scope. That scope cannot be narrowed: it
grants write to every repository the owning account can reach, including this
one. As an Actions secret it would be usable by anyone with push access here,
because a pushed branch containing a workflow runs with repo secrets — a strict
escalation for a channel that ships one DMG a month.

Split the work so the token never becomes a CI secret:

- CI (bump-homebrew.yml, now "Sync Homebrew Cask Reference") does the
  error-prone bookkeeping with GITHUB_TOKEN only: downloads the DMG, asserts it
  is notarized + stapled, computes the sha256, and opens an in-repo PR syncing
  desktopApp/packaging/homebrew/amethyst-nostr.rb. This makes it a third sibling
  of the amy/geode formula-sync workflows rather than a special case.
- scripts/bump-homebrew-cask.sh does the upstream PR from a maintainer's shell,
  re-verifying sha256 and the notarization ticket against the live asset first,
  and refusing to submit if either fails. Verified against v1.13.1: the sha256
  matches and it correctly refuses on the missing notarization ticket.

Drop HOMEBREW_TOKEN from the secret inventory, and rewrite the two formula
TODO(bootstrap) notes that proposed reintroducing it so a future homebrew-core
submission follows the same local pattern.
2026-07-29 10:19:57 -04:00