Commit Graph

12380 Commits

Author SHA1 Message Date
Vitor Pamplona 833dcf1048 Fixes size of Send icons 2026-04-27 21:49:07 -04:00
Vitor Pamplona 68e405c684 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-27 21:06:24 -04:00
Vitor Pamplona 9fcf7bc1e5 Merge pull request #2614 from vitorpamplona/claude/fix-nest-activity-layout-zziPP
Refactor NestFullScreen layout: tabs, action bar, and stage grid
2026-04-27 21:04:35 -04:00
Claude 4f391ed74f Merge branch 'main' into claude/fix-nest-activity-layout-zziPP
Resolves NestFullScreen.kt by keeping the redesigned layout (header
strip, stage grid, tabs, sticky NestActionBar) while dropping the
NestThemedScope wrapper that main removed in ff00dcf3 ("screens get
too dark"). The RoomTheme import goes with it; the stale doc-comment
reference to NestThemedScope is updated accordingly.
2026-04-28 01:01:08 +00:00
Vitor Pamplona 6f38c5ec82 Merge pull request #2613 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-27 20:55:25 -04:00
Vitor Pamplona 637174ef12 Add relays to the broadcast for Nests 2026-04-27 20:54:58 -04:00
Vitor Pamplona 6c284a31bf Removes the rest of the theming 2026-04-27 20:50:13 -04:00
Crowdin Bot d7c6e9b169 New Crowdin translations by GitHub Action 2026-04-28 00:40:23 +00:00
Vitor Pamplona ff00dcf3c6 Removes the implementation of custom designs because our screens get too dark 2026-04-27 20:38:18 -04:00
Claude 9381a7731d feat(nests): redesign room layout with stage grid, tabs, sticky action bar
Replaces the single scrolling Column (title → speakers row → audience
row → host queue → connection chip → talk row → buttons → chat) with
a Scaffold-bounded layout that scales to large rooms:

  - Header strip with LIVE chip + listener count (uses the existing
    nest_listener_count plural for the first time) and a 1-line
    ellipsised summary. Topbar stays slim.
  - StageGrid: vertical adaptive LazyVerticalGrid capped at 220dp,
    so a 30-speaker room scrolls inside the strip without pushing
    the chat below the fold.
  - Tab bar (Chat / Audience · N / Hands · N) with badge counts.
    Hands tab is host-only and only shown while the queue is non-empty.
  - AudienceGrid: vertical adaptive LazyVerticalGrid that fills the
    selected tab — handles 1,000+ listeners without performance issues
    (the old single-row LazyHorizontalGrid only let you see ~5 at a time).
  - NestActionBar: sticky bottom bar consolidating the old ConnectionRow,
    TalkRow, and hand/react/leave row. Layout adapts to connection /
    broadcast / on-stage state; failure messages get a thin status
    strip above the bar instead of stealing button slots.
  - Hand-raise control hides when the user is on stage (the action it
    represents — "I want to speak" — no longer applies).

The PIP screen and chat panel internals are untouched.
2026-04-28 00:37:32 +00:00
Vitor Pamplona 9d0c224c9e New Private FLAG for Nests 2026-04-27 20:36:45 -04:00
Vitor Pamplona 89176048f1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-27 20:36:26 -04:00
Vitor Pamplona 078c5f04a8 Solving the issue of a BackArrow on the Home Screen after a back press 2026-04-27 20:35:40 -04:00
Vitor Pamplona eb305a61f2 Merge pull request #2610 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-27 19:26:35 -04:00
Vitor Pamplona 96f976449e Merge pull request #2611 from vitorpamplona/claude/add-topbar-profile-screen-yw8IQ
Extract profile top bar into separate composable component
2026-04-27 19:26:25 -04:00
Vitor Pamplona a9f428526b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-27 19:25:21 -04:00
Vitor Pamplona a50a360964 Correctly downloads Nest events 2026-04-27 19:23:52 -04:00
Claude 152900688d Move profile back/more buttons into Scaffold topBar
The back button and the more-options menu used to float as
absolute-positioned overlays inside ProfileHeader. They are now
hosted in a transparent ShorterTopAppBar wired into the Scaffold's
topBar slot, so the banner can still render edge-to-edge as the
background by setting contentWindowInsets to zero and only applying
the bottom padding from Scaffold to the body.
2026-04-27 23:09:57 +00:00
Crowdin Bot afde1c8499 New Crowdin translations by GitHub Action 2026-04-27 22:58:19 +00:00
Vitor Pamplona b786b056bb Merge pull request #2609 from vitorpamplona/claude/add-chat-options-nest-PIyCp
Add full-featured composer to nest room chat
2026-04-27 18:56:50 -04:00
Claude 995f8384df feat(nests): wire nest chat composer to NestNewMessageViewModel
Completes the copy approach started in 57ebded6:

  - NestEditFieldRow.kt: copy of EditFieldRow, drops the BackHandler
    (the activity owns back; draft auto-save runs on every keystroke
    so there is nothing to flush) and points every callback at
    NestNewMessageViewModel.
  - NestFileUploadDialog.kt: copy of ChannelFileUploadDialog, header
    shows the room host's avatar + room name from the loaded
    MeetingSpaceEvent.
  - NestChatPanel.kt: replaces the slim inline composer with
    NestEditFieldRow + NestNewMessageViewModel. Chat message list is
    still rendered from NestViewModel.chat — the new VM is scoped to
    *editing and sending* messages only, per the brief.
  - NestNewMessageViewModel.sendPostSync: switched from
    signAndSendPrivately(template, emptySet()) to
    signAndComputeBroadcast(template) so messages actually reach the
    user's default relays (matches the original slim composer's
    behaviour).
2026-04-27 22:37:18 +00:00
Claude 57ebded68b wip(nests): start copying ChannelNewMessageViewModel into nest package
Pivot from sharing ChannelNewMessageViewModel (previous commit) to a
literal per-nest copy as requested.

State of this commit (incomplete — DO NOT MERGE):
  - EditFieldRow.kt: reverted to original (no interceptBackPress flag)
  - NestNewMessageViewModel.kt: new file, copy of ChannelNewMessageViewModel
    narrowed to MeetingSpaceEvent + LiveActivitiesChatMessageEvent only

Still TODO before this branch is usable:
  - Copy EditFieldRow into nests/room/send/NestEditFieldRow.kt
  - Copy ChannelFileUploadDialog into nests/room/send/NestFileUploadDialog.kt
  - Rewire NestChatPanel to use these copies (it currently still calls
    ChannelNewMessageViewModel + EditFieldRow from the previous commit's
    approach, which won't compile against the reverted EditFieldRow
    signature once NestChatPanel is also reverted)

User asked to stop mid-work — committing as WIP so the tree is clean.
2026-04-27 22:31:46 +00:00
Claude 46cfab4fa1 feat(nests): use shared EditFieldRow for nest chat composer
Wire the in-room chat composer to ChannelNewMessageViewModel +
EditFieldRow so nest chat picks up @-mention picker, file/image/
video upload, reply preview, NIP-37 draft auto-save, emoji
suggestions, content warnings, expiration, geohash, and zap-
split forwarding — the same affordances every other public chat
surface has.

The composer is backed by a LiveActivitiesChannel keyed by the
meeting space's address. ChannelNewMessageViewModel.createTemplate()
already handles the LiveActivitiesChannel branch: when channel.info
is null (which it always is for kind-30312, since info is typed to
the kind-30311 LiveActivitiesEvent), it falls through to
LiveActivitiesChatMessageEvent.message(post, channel.toATag()) —
the exact event shape the previous slim composer was emitting.

EditFieldRow gains an interceptBackPress flag so nest can opt out
of the channel-screen back-handler that would clear the field and
call nav.popBack() (a no-op on BouncingIntentNav).
2026-04-27 22:09:45 +00:00
Vitor Pamplona 3c3e327bcb Fixes test cases 2026-04-27 18:01:44 -04:00
Vitor Pamplona 40fa069a98 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-27 17:55:15 -04:00
Vitor Pamplona 1e86e15291 Adjustments to the loading and updating of the nest event in a PiPActivity 2026-04-27 17:54:16 -04:00
Vitor Pamplona 81b82198e2 Corrects the name of the room in Nests feed 2026-04-27 17:27:11 -04:00
Vitor Pamplona f37f1907a4 Merge pull request #2608 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-27 16:59:06 -04:00
Crowdin Bot 950f226375 New Crowdin translations by GitHub Action 2026-04-27 20:53:31 +00:00
Vitor Pamplona 414707c3cb Merge pull request #2607 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-27 16:51:52 -04:00
Vitor Pamplona f403ae9615 Merge pull request #2585 from vitorpamplona/claude/audio-rooms-android-ui-PIpFN
Add NIP-53 audio room speaker/broadcaster support
2026-04-27 16:51:31 -04:00
Claude 6da4483fa3 Merge remote-tracking branch 'origin/main' into claude/audio-rooms-android-ui-PIpFN
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/AudioRoomsScreen.kt
2026-04-27 20:45:04 +00:00
Crowdin Bot f1fc9d43fb New Crowdin translations by GitHub Action 2026-04-27 20:43:16 +00:00
Vitor Pamplona a0f45b49e8 Merge pull request #2606 from vitorpamplona/claude/fix-nav-back-arrow-99NGn
Adds a BottomNavBar for screens that didn't have before
2026-04-27 16:41:37 -04:00
Claude 8c5804063e feat(nests): wrap room screen in Scaffold; title + overflow → TopAppBar
The room name and the MoreVert overflow lived inline at the top of
the metadata Column, so they scrolled with the rest. Hoist them into
a Material 3 TopAppBar inside a Scaffold, matching every other major
screen in the app.

NestTopAppBar — new private composable:
  - Title is `event.room()`, single-line ellipsis.
  - Actions: Box wrapping the MoreVert IconButton + DropdownMenu
    (Share for everyone, Edit gated on `isHost`).
  - containerColor = Transparent so the themed background painted by
    NestThemedScope's Surface (and any optional `bg` image) shows
    through cleanly without a double-paint.

NestFullScreen body now:
  Scaffold(
    containerColor = Color.Transparent,
    topBar = { NestTopAppBar(...) },
  ) { padding ->
    Column(fillMaxSize.padding(padding)) {
      Column(weight(1, false), verticalScroll, hpad+top pad) {
        // summary, listener count, participants grid, host actions
        // sheet, hand-raise queue, connection row, talk row, action
        // row, reaction picker, host-leave confirm dialog
      }
      NestChatPanel(weight(1, true), hpad+bottom pad)
    }
  }

Side effects:
  - Drops the manual windowInsetsPadding(safeDrawing) — Scaffold's
    contentWindowInsets handles that and the TopAppBar's own
    windowInsets handles the top edge.
  - The EditNestSheet conditional moves to NestThemedScope's body
    (after the Scaffold). It's a ModalBottomSheet, so position in
    the tree doesn't change layout, but adjacency to the Scaffold
    keeps the sheet/dialog boundary obvious.

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 20:36:28 +00:00
Claude baaee94555 feat(nav): add bottom bar to remaining tab-eligible screens
The bottom-nav settings let users place any of these routes in the bar,
but the screens themselves never rendered AppBottomBar — so even when
configured as a tab, the bar was missing on Profile, Wallet, Lists,
BookmarkGroups, WebBookmarks, Drafts, InterestSets, EmojiPacks,
BrowseEmojiSets, and AllSettings.

AppBottomBar self-hides via nav.canPop(), so adding the bar is safe on
every entry: it appears only when the screen is the tab root, hidden
otherwise (drawer / deep link).

Same-tab tap scrolls the screen's main list to the top, mirroring the
existing tab behavior. State is hoisted as needed:
- WebBookmarks, Drafts, BrowseEmojiSets: feedState.sendToTop()
- Lists, BookmarkGroups, EmojiPacks: hoisted LazyListState/LazyGridState
  through the feed-view helper, animateScrollTo(0)
- Wallet, InterestSets: hoisted LazyListState locally
- AllSettings: hoisted ScrollState (verticalScroll column)
- Profile: wrapped in Scaffold, hoisted ScrollState from RenderSurface

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
2026-04-27 20:35:56 +00:00
Claude 84712f48f1 fix(nests): NestChatPanel takes weight(1) so chat fills the screen
Previously the room screen wrapped EVERYTHING — title, summary,
participants, talk row, action row, AND chat — in a single
verticalScroll Column. The chat panel sat at the bottom with a fixed
NEST_CHAT_PANEL_HEIGHT (420dp), which meant on tall phones the chat
left blank space below it and on small phones the chat was cramped.

Restructure NestFullScreen's body:
  - Outer Column.fillMaxSize, no scroll, owns safeDrawing inset.
  - Top metadata: Column with weight(1f, fill=false), internal
    verticalScroll, horizontal+top padding. Caps at half the screen
    so an over-tall participants list scrolls internally instead of
    pushing the chat off-screen.
  - NestChatPanel: Column-scoped weight(1f, fill=true), horizontal
    padding + bottom inset. Always takes its full allocation —
    chat dominates the screen, fixed-height fallback gone.

NestChatPanel is now a `ColumnScope.NestChatPanel` extension so its
modifier can use `weight()` from the caller. Inside the panel, the
message list Box also uses weight(1f, fill=true) of the panel's own
Column, so the LazyColumn fills everything except the composer.

NEST_CHAT_PANEL_HEIGHT constant removed — it was the source of the
fixed-height behavior the user explicitly didn't want.

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 20:31:08 +00:00
Claude 759fd67ef5 fix(nav): hide bottom bar on screens reached via non-tab-root entries
Bottom-nav screens (Notifications, Discover, etc.) used to render the
bottom bar unconditionally. When reached as a non-tab-root entry —
drawer, deep link, in-app navigation that pushed a fresh copy with
different args — the bar should disappear, matching the back-arrow and
slide-animation rules.

AppBottomBar now takes an INav and returns early when nav.canPop() is
true. The check covers two valid cases for showing the bar:
  - Tab-root entry (carries BOTTOM_NAV_ROOT_KEY, canPop is false).
  - Graph start destination Home (no previous entry, canPop is false).

All 19 callers updated to pass nav; the existing click callback param
is renamed onClick to free up the nav name.

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
2026-04-27 20:00:28 +00:00
Claude 7f48b18319 fix(nests): wrap NestThemedScope in Surface so LocalContentColor flips
NestThemedScope painted `themed.background` on a plain Box. Compose's
`LocalContentColor` was never updated, so it stayed at its
CompositionLocal default — `Color.Black` — for every Text inside.
On the user's dark theme that meant black-on-black for the room
title and the chat panel: unreadable.

AmethystTheme installs `MaterialTheme(colorScheme = ...)` but does
NOT wrap content in a Surface; screens that use Scaffold inherit
LocalContentColor via Scaffold's internal Surface. NestFullScreen
goes Column → verticalScroll, no Scaffold, no Surface, so the
black-default fell through.

Replace the bare `Box.background(themed.background)` with a Material
Surface that paints `color = themed.background` AND provides
`contentColor = themed.onBackground` to LocalContentColor for the
inner subtree. The `bg` image still overlays the Surface inside the
Box, exactly as before.

This was the actual cause of the user's "title impossible to read /
chat super dark" report — the event in question shipped no `c` tags
(only the unparseable `["color", "gradient-7"]`), so RoomTheme was
already Empty. The previous "all-or-nothing palette" gate (commit
15169de7) is still right for half-applied palettes; this Surface
fix is what makes empty / un-themed rooms read correctly on dark.

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 19:54:45 +00:00
Claude 15169de7e5 fix(nests): drop themed colors when palette is incomplete
EGG-10 lets each `["c", hex, role]` tag stand alone, but a half-
applied palette (themed background + platform text, or themed text
+ platform background) collides with whichever system theme — light
or dark — the user is on. A room that ships ONLY `background=#FFE4B5`
ends up with platform-default white text on dark theme; unreadable.

Gate all three color overrides on having a complete bg + text pair
inside `RoomTheme.from(event)`. When either is missing the whole
palette drops to null and renderers fall through to the platform
theme. Background image (`bg`) and font tags still flow through —
they don't break contrast on their own.

Both consumers — NestThemedScope (room screen) and NestJoinCard
(lobby) — pick up the change without code edits because they read
through the same `RoomTheme` projection.

The nostrnests-style `["color", "gradient-7"]` tag was never parsed
(our `c`-tag parser ignores it), so events shipping only that don't
override anything either way; this fix targets the genuine half-
applied case (rooms that emit one EGG-10 c-tag without the matching
companion).

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 19:46:18 +00:00
Claude 1a6b9a4cee Merge remote-tracking branch 'origin/main' into claude/audio-rooms-android-ui-PIpFN 2026-04-27 19:30:18 +00:00
Vitor Pamplona cf706abb99 Merge pull request #2605 from vitorpamplona/claude/fix-nav-back-arrow-99NGn
Claude/fix nav back arrow 99 n gn
2026-04-27 15:27:32 -04:00
Claude 41aa908fbe refactor(nav): collapse SKIP_SLIDE_ANIMATION_KEY into BOTTOM_NAV_ROOT_KEY
Both flags were stamped at the same call site (navBottomBar) and meant
the same thing — "this entry is a bottom-nav tab root". Collapse them
into a single key and use isBottomNavRoot() in composableFromEnd's
transition lambdas.

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
2026-04-27 19:19:10 +00:00
Claude 32157ff82f fix(nav): keep Home below tab roots, hide back arrow via per-entry flag
Previous attempt cleared Home from the back stack on every bottom-nav
tap, which broke back-swipe: the user expects swipe-back from any tab
to return to Home, and swipe-back from Home to leave the app.

Restore that contract while still hiding the back arrow on tab roots:
- navBottomBar pops up to (but not including) Route.Home, so sibling
  tabs are cleared while Home stays at the bottom of the stack.
- The new entry is stamped with BOTTOM_NAV_ROOT_KEY on its
  savedStateHandle.
- Nav.canPop returns false when the current entry carries that flag,
  even though previousBackStackEntry (Home) is non-null.

Home itself is the graph's start destination and has no previous entry,
so canPop returns false there without needing the flag.

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
2026-04-27 19:16:37 +00:00
Claude 8d53c9025d feat(meetingrooms): show parent MeetingSpace link on kind:30313
A NIP-53 kind-30313 [MeetingRoomEvent] references its parent kind-30312
[MeetingSpaceEvent] via the standard `["a", "30312:<host>:<d>"]` tag.
Without surfacing it, a meeting card in a feed lost the context of
which Nest the meeting belonged to — users couldn't tell if "Office
Hours Q3" lived inside their company nest or someone else's.

Render a small "In <Space Name>" label above the meeting's title
inside [RenderMeetingRoomEventInner]:

  - Resolves the parent address via `MeetingRoomEvent.interactiveRoom()`
    → `MeetingSpaceTag.address`. Bails when the address points at
    something other than kind:30312 (no broken links).
  - Loads the parent through the existing `LoadAddressableNote`
    helper. When the kind:30312 hasn't propagated to LocalCache yet,
    the row falls back to a generic "In a Nest" label and tapping
    routes through the standard `routeFor` thread path which
    auto-fetches.
  - Tap navigates to the parent space's thread view via `routeFor`
    + `nav.nav` — the same path Discovery / NoteCompose use for
    quote-into-thread navigation.

Two new strings:
  - meeting_room_in_space ("In %1$s")
  - meeting_room_in_space_unknown ("a Nest" — fallback when the
    parent space isn't yet resolvable)

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 19:10:12 +00:00
Claude 0ceeafe90c revert(meetingrooms): drop the kind:30313 drawer split
User changed direction — the Nests / Meeting Rooms separation was
the wrong call. Kind 30313 stays out of the Nests list, but doesn't
get its own drawer entry either; it surfaces through the standard
NoteCompose / thread paths instead.

Reverted:
  - Deleted: meetingrooms/MeetingRoomsScreen, MeetingRoomsTopBar,
    MeetingRoomsFeedLoaded, dal/MeetingRoomsFeedFilter.
  - Removed Route.MeetingRooms, NavBarItem.MEETING_ROOMS, the
    catalog entry, the drawer entry.
  - Removed meetingRoomsFeed from AccountFeedContentStates and
    ScrollStateKeys.MEETING_ROOMS_SCREEN.
  - Removed `meeting_rooms` string.
  - Updated AppNavigation imports.

Kept:
  - NestsFeedFilter narrowed to kind:30312 only (per user: "only
    show kind 30312 in the items of the NestScreen"). The dual-kind
    branches stay gone.
  - Doc comment updated to note that kind:30313 renders on the
    standard NoteCompose / thread paths outside the Nests drawer.

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 19:07:44 +00:00
Claude befa13d797 Merge remote-tracking branch 'origin/main' into claude/audio-rooms-android-ui-PIpFN 2026-04-27 19:00:48 +00:00
Claude 3e19651d22 feat(nests): show like + zap row on Nest / MeetingRoom cards
Discovery's RenderLiveActivityThumb cards already render a creator
+ name + like + zap row at the bottom — but only when the channel
holds a kind:30311 LiveActivitiesEvent. Nests (kind:30312) and
Meeting Rooms (kind:30313) populate channels with the same address
shape but `LiveActivitiesChannel.info` is null for them, so the
reactions row was hidden.

ShortLiveActivityChannelHeader:
  - Add an `addressableNote: Note?` parameter to the inner overload.
    The outer (LiveActivitiesChannel) overload fills it from
    `LocalCache.getAddressableNoteIfExists(channel.address)`, which
    works for any kind that registers an addressable note.
  - Move the like/zap row OUT of the `liveActivitiesEvent?.let { }`
    gate so it renders for any addressable note — kind:30311,
    30312, 30313 all share it now.
  - Keep the LIVE / OFFLINE flag inside the LiveActivitiesEvent gate
    (it pings the streaming URL — stream-specific). Extracted into
    a small `LiveChannelLiveFlag` helper so the reaction row can
    render independently.

MeetingRoomsFeedLoaded:
  - Swap from RenderMeetingRoomEvent to RenderLiveActivityThumb so
    the Meeting Rooms list visually matches the Nests list and
    Discovery — same cover-image card with status flag, participant
    gallery, and bottom header (creator + name + reactions).

Other call sites (LiveActivityTopBar, LiveActivitiesChannelHeader)
use the outer `baseChannel` overload and pick up the new behavior
automatically.

https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
2026-04-27 18:51:33 +00:00
Vitor Pamplona 09f653950e Merge pull request #2604 from vitorpamplona/claude/fix-nav-back-arrow-99NGn
Fix back stack management in bottom navigation
2026-04-27 14:49:03 -04:00
Claude 0e4379c5bf fix(nav): clear back stack on bottom-nav taps so no back arrow shows
popUpTo(route) { inclusive = true } only pops if `route` is already in
the stack. From Home, tapping any other bottom-nav tab left Home in the
back stack, so canPop() returned true and the back arrow appeared on a
root tab.

Pop up to the graph's start destination instead (also inclusive). This
clears Home — and any drawer/deep-push entries above it — before
navigating to the new bottom-nav root, so each bottom-nav tap leaves
exactly one entry in the stack.

https://claude.ai/code/session_01PrirRcL7g8iX7vTqqLTkBS
2026-04-27 18:39:23 +00:00