Commit Graph

11573 Commits

Author SHA1 Message Date
Vitor Pamplona a01cbbf2e1 Merge pull request #2461 from davotoula/claude/hls-resolution-selection-jzBTG
HLS video: Lowest resolution in feed/PiP, auto resolution in full screen
2026-04-20 15:19:30 -04:00
davotoula cb4a987498 refactor(video): apply code review fixes 2026-04-20 20:51:40 +02:00
davotoula 830e410a79 feat(video): default feed/PiP to lowest HLS resolution, fullscreen to auto 2026-04-20 20:51:14 +02:00
Vitor Pamplona c7b8d178f5 Merge pull request #2460 from vitorpamplona/claude/fix-empty-groups-display-MO6E9
Show placeholder notes for empty Marmot groups in chat list
2026-04-20 13:15:26 -04:00
Claude aea1dc53c3 fix: show empty Marmot groups in Messages screen
Previously ChatroomListKnownFeedFilter dropped any group whose
newestMessage was null, so groups the user just created and groups
received via Welcome events without any activity yet never appeared
in the Messages list.

Emit a stable placeholder Note (carrying the chatroom as a gatherer)
per empty group, route it through the existing Marmot row path, and
invalidate dmKnown on MarmotGroupList.groupListChanges so newly added
or promoted groups rebuild the feed.
2026-04-20 17:08:59 +00:00
Vitor Pamplona d7eb11bb08 Merge pull request #2459 from vitorpamplona/claude/relay-icons-group-info-23CZ8
Track relay activity for Marmot group chats
2026-04-20 13:03:47 -04:00
Claude 42e226bf8d feat: show Marmot group relays as clickable icons with activity status
Replaces the comma-separated relay text on the Marmot Group Info
screen with a FlowRow of 55dp relay avatars that open RelayInfo on
tap and copy the URL on long-press, matching the relay-icon pattern
used elsewhere in the app.

To surface whether each configured relay is actually carrying traffic
for the group, MarmotGroupChatroom now tracks the most recent
kind:445 event timestamp observed from each delivering relay and the
info screen renders a green dot when a relay has delivered a group
event within the last 7 days (gray otherwise).
2026-04-20 16:59:19 +00:00
Vitor Pamplona f76e4f4c49 Merge pull request #2458 from vitorpamplona/claude/investigate-github-issue-k17Fx
Add emoji set support and shortcode validation to NIP-30
2026-04-20 12:36:18 -04:00
Claude 254f5bdcc2 NIP-30: use Address type for emoji-set reference instead of raw string
Makes the API safer: callers can't accidentally pass an unparsed or
malformed identifier. EmojiUrlTag.emojiSet is now Address?, serialized
via toValue() and parsed via Address.parse() (which rejects anything
that isn't a well-formed kind:pubkey:dTag).
2026-04-20 16:35:29 +00:00
Vitor Pamplona 99ce01af4e Merge pull request #2457 from vitorpamplona/claude/fix-members-tag-update-OKFvB
Refactor Marmot group members to use reactive state flow
2026-04-20 12:33:34 -04:00
Vitor Pamplona e0094f163b ⏺ fix: derive nostrGroupId from MLS GroupContext in Welcome processing
The "h" tag is optional in MIP-02 Welcome events — senders like
  whitenoise-rs omit it. Instead of failing when the h-tag is absent,
  derive nostrGroupId from the NostrGroupData extension embedded in the
  Welcome's GroupContext (the authoritative MLS source). An h-tag hint,
  if present, is still validated against the MLS-derived value.
2026-04-20 12:32:42 -04:00
Claude b6e31b21c8 refactor: make Marmot group members list reactive
Expose the member list as MutableStateFlow<List<GroupMemberInfo>> on
MarmotGroupChatroom, populated by MarmotManager.syncMetadataTo alongside
the existing memberCount. MarmotGroupInfoScreen and RemoveMemberScreen
now observe it via collectAsStateWithLifecycle, so both remote commits
(already routed through syncMetadataTo in DecryptAndIndexProcessor) and
local mutations refresh the UI without manual re-queries.

Account.addMarmotGroupMember and removeMarmotGroupMember now call
syncMetadataTo right after the MLS state is mutated, mirroring the
pattern already used by updateMarmotGroupMetadata, so the local change
is visible immediately without waiting for the relay round-trip.
2026-04-20 16:27:31 +00:00
Vitor Pamplona 9766cc5901 Fixes the group id parsing 2026-04-20 12:23:46 -04:00
Claude 93c2041f0f NIP-30: add optional emoji-set address and shortcode validation
Per NIP-30 the emoji tag is ["emoji", <shortcode>, <url>, <emoji-set-address>]
with the fourth field optional. EmojiUrlTag only exposed the first three.
Adds emojiSet as an optional field, preserves existing positional callers
via default null, and introduces isValidShortcode() so callers can validate
user input against the spec (alphanumeric, hyphens, underscores).
2026-04-20 16:21:30 +00:00
Vitor Pamplona 4ccabb01e6 Adding capabilities to Amethyst's groups 2026-04-20 12:14:35 -04:00
Vitor Pamplona 4f2f8e180e Generates keypackages with 64 chars 2026-04-20 12:00:31 -04:00
Claude 7e45042c27 fix: refresh Marmot group members list when returning to info screen
Replace LaunchedEffect with LifecycleResumeEffect so the members list
(and chatroom.memberCount) is re-queried every time MarmotGroupInfoScreen
resumes, not just when nostrGroupId changes. Previously, after adding a
member via the AddMemberScreen and popping back, the members count
displayed in the header and chat top bar stayed stale until the screen
was fully recreated.
2026-04-20 15:58:00 +00:00
Vitor Pamplona f71d8eebb8 fixes the script for keypackages not showing up in wn 2026-04-20 11:42:29 -04:00
Vitor Pamplona e41ad84096 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-20 11:22:50 -04:00
Vitor Pamplona 1c797107bc fixes script on macos 2026-04-20 11:20:38 -04:00
Vitor Pamplona ad624031bf Improves the FetchFirst to not fail in the first eose from the first relay. 2026-04-20 11:15:09 -04:00
Vitor Pamplona d7cc99b196 update dependencies 2026-04-20 10:51:40 -04:00
Vitor Pamplona 37af8b0c45 fixes deprecation on vico charts 2026-04-20 10:51:18 -04:00
Vitor Pamplona 036323fa53 This was added by the secp rewrite, but we moved them out to another repo, so now it can be removed. 2026-04-20 10:43:54 -04:00
Vitor Pamplona 57af16302e Merge pull request #2455 from vitorpamplona/claude/fix-scaffold-scrolling-NHdRa
Refactor DisappearingScaffold to use unified bar state management
2026-04-20 10:42:01 -04:00
Vitor Pamplona 3e488623d4 Merge pull request #2453 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-20 10:24:23 -04:00
Crowdin Bot e808d40834 New Crowdin translations by GitHub Action 2026-04-20 14:19:21 +00:00
Claude 7637596835 Merge remote-tracking branch 'origin/main' into claude/fix-scaffold-scrolling-NHdRa 2026-04-20 14:19:18 +00:00
Vitor Pamplona 5551f2f7d2 Merge pull request #2456 from vitorpamplona/claude/nip51-interest-sets-p0f6r
Add Interest Sets feature for organizing hashtags
2026-04-20 10:17:31 -04:00
Claude 4c82011a25 fix(interest-sets): consume kind 30015 locally + empty-state polish
- LocalCache.consume dispatcher now handles InterestSetEvent via
  consumeBaseReplaceable, so the event created by the user is stored
  and flows through newEventBundles → interestSets.newNotes → listFeedFlow
  refresh. Without this, the just-signed event sat in the sendMyPublicAndPrivateOutbox
  call but the UI never saw the update.
- List screen: icon + centered text for the empty state and dividers
  between rows.
2026-04-20 14:11:06 +00:00
Vitor Pamplona 282b3a436b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-20 09:53:18 -04:00
Vitor Pamplona 0e077c02d0 linting 2026-04-20 09:41:58 -04:00
Vitor Pamplona 83837ad090 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-20 09:38:12 -04:00
davotoula 5eb91145df style: strip trailing whitespace and fix indent flagged by spotless
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 15:37:56 +02:00
Vitor Pamplona 2f3d035d3c Fixes failing tests due to dispatcher misconfiguration 2026-04-20 09:34:48 -04:00
Claude 198e950f37 feat(interest-sets): NIP-51 Interest Sets (kind 30015) UI + TopNav chips
Add Android UI for managing NIP-51 Interest Sets and surface them as chips
in the TopNav feed filter alongside followed hashtags. InterestSetEvent was
already implemented in Quartz; this wires it into the app.

- InterestSetsState mirrors LabeledBookmarkListsState: listFeedFlow with
  versioned refresh, decrypted hashtag cache keyed by dTag for the feed
  filter pipeline, and suspend helpers for create/rename/delete/clone/add
  hashtag/remove hashtag/move (public<->private).
- New screens under ui/screen/loggedIn/interestSets/: list, metadata edit
  (create/rename, title-only since InterestSetEvent has no image field),
  and display screen with add/remove + public/private toggle per hashtag.
- TopFilter.InterestSet(address) feeds into a new MultiHashtagFeedFlow
  that reuses HashtagTopNavFilter with Set<String>.
- TopNavFilterState.mergeInterests emits interest-set chips; FeedFilterSpinner
  groups them under a new "Interest Sets" category.
- Drawer entry + HomeScreen FAB branch.
2026-04-20 13:28:51 +00:00
Vitor Pamplona 516115cc1c Fixes test cases for the CallManagerTest 2026-04-20 09:21:01 -04:00
Vitor Pamplona fab435509b Merge pull request #2454 from vitorpamplona/claude/add-thumbhash-support-ZfNS1
Add ThumbHash support for image placeholders
2026-04-20 08:51:36 -04:00
Claude 63da850e3b perf(thumbhash): cache cosine tables and flatten hot loop in decoder
The reference port recomputed the inverse DCT cosine tables once per output
pixel — for a 32x24 decode that's ~43k redundant cos() calls. This change
lifts the tables out of the inner loop and caches them across decodes
keyed by (size, componentCount) so subsequent placeholders at the same
target size skip cosine evaluation entirely.

Additional wins:
- AC coefficients unpack into pre-sized DoubleArrays (no ArrayList<Double>
  boxing, no post-hoc copy)
- truncated hashes are rejected up-front via a single length check instead
  of mid-stream
- LPQA -> sRGB uses an inline branch clamp instead of a
  min/max/round/coerceIn chain

Tests: 12 unit tests cover determinism across repeated decodes, cache
clearing, alpha preservation, aspect-ratio preservation both directions,
average-color drift bounds, truncated input rejection, and round-tripping
base64 vs. raw bytes. All green.

Bench: new ThumbHashBenchmark exercises opaque decode, alpha decode,
warm- and cold-cache decode, aspect-ratio probe, and the full
decodeKeepAspectRatio pipeline so the perf delta is visible on device.
2026-04-20 00:33:26 +00:00
Claude b2f297b3bb feat: add ThumbHash support alongside BlurHash across events, uploads, and UI
Adds a parallel ThumbHash placeholder everywhere BlurHash is already used.
Remote events now carry both hashes; renderers prefer thumbhash when
available and fall back to blurhash. The MIP-04 `thumbhash` imeta field
that was previously reserved-but-unused is now wired end-to-end.

- New ThumbHash encoder/decoder in commons/commonMain (no new Gradle dep)
- New ThumbhashTag and thumbhash accessors/builders across NIP-17, 68,
  71, 94, 95, 99, the experimental profile gallery, and MIP-04
- RichTextParser + MediaContentModels carry a thumbhash field alongside
  blurhash so every downstream composable can pick its preferred placeholder
- New ThumbHashFetcher (Android + Desktop) registered with Coil, plus a
  small placeholderModel(thumbhash, blurhash) helper centralising the
  "prefer thumbhash, fall back to blurhash" rule
- Rename BlurhashMetadataCalculator -> PreviewMetadataCalculator; the
  calculator decodes the bitmap / video thumbnail once and runs both
  encoders on the same pixels to keep upload cost flat
- DesktopMediaMetadata, MediaUploadResult, and FileHeader now surface
  both hashes through the NIP-96, Blossom, NIP-95, MIP-04, NIP-17 DM,
  Classifieds, picture, video, and long-form upload paths
- Round-trip unit test for the ThumbHash port
2026-04-20 00:12:28 +00:00
Claude 5b8bbbaa42 merge: origin/main (BadgesScreen + banner features)
Resolves conflicts between our CompositionLocal-based scaffold padding
and main's new features:

Conflicts resolved:
- HomeScreen: main added `HomeAlgoFeedStatusBanner` floated on top of
  the feed with a Box wrapper. Kept main's Box + banner, but dropped
  the `Modifier.padding(paddingValues)` + `HorizontalPager
  (contentPadding = PaddingValues(0.dp))` — inner LazyColumns now pull
  scaffold padding via LocalDisappearingScaffoldPadding, and the banner
  aligns TopCenter with `padding(top = paddingValues.calculateTopPadding())`
  so it sits below the top bar even when the feed scrolls behind it.
- PinnedNotesScreen / BookmarkListScreen / OldBookmarkListScreen: main
  added `DeletedItemsBanner` that was stacked above the feed inside a
  padded Column. Same pattern as Home — feed fills the Box, banner
  overlays at TopCenter with the scaffold's top padding so items scroll
  under the bar while the banner stays pinned.
- `DeletedItemsBanner` gained a `modifier: Modifier = Modifier` param
  so callers can position it.

New-on-main screens audited and migrated:
- BadgesScreen: dropped `Column(Modifier.padding(paddingValues))`
  wrapper; LazyColumn now extends behind the bars via the
  CompositionLocal.
- BookmarkGroupScreen: SecondaryTabRow `containerColor =
  Color.Transparent` changed to `MaterialTheme.colorScheme.background`
  to match the other opaque tab rows (items scrolling underneath
  would otherwise bleed through).
- AwardBadgeScreen, NewBadgeScreen, ProfileBadgesScreen,
  AllSettingsScreen, FavoriteAlgoFeedsListScreen: none use
  DisappearingScaffold (stock `Scaffold`) — no migration needed.

Unit tests still green (10/10). Full amethyst module compiles.

https://claude.ai/code/session_01M3Bj24jLc9aVhMuvn55jXa
2026-04-19 23:46:54 +00:00
Vitor Pamplona 3bfeac885a Merge pull request #2452 from vitorpamplona/claude/badge-system-amethyst-J07UM
Add comprehensive badge system with creation, awarding, and profile management
2026-04-19 17:41:10 -04:00
Vitor Pamplona f43b334d93 Merge branch 'main' into claude/badge-system-amethyst-J07UM 2026-04-19 17:41:02 -04:00
Claude 35cab28543 feat(badges): add accept controls to notification card
The notification card BadgeCompose rendered the awarded badge via
BadgeDisplay (definition-only) and stopped there, so a recipient
viewing a fresh badge in their inbox had no way to add it to their
profile without navigating to the award's thread first.

Expose AcceptBadgeControls (was private inside Badge.kt) and call it
from BadgeCompose under the BadgeDisplay row when the underlying note
is a BadgeAwardEvent.

Other surfaces are unchanged:
- RenderBadgeAward (Badge feed / threads) keeps its own call to the
  same composable; behaviour is identical because the controls were
  already package-private.
- BadgeCompose has only one caller (CardFeedView, the notifications
  feed), so the new row only appears there.
2026-04-19 21:35:04 +00:00
Claude 8eeeae9601 refactor(badges/new): show form first with an upload placeholder
The FAB now opens the new-badge dialog directly. The dialog renders a
big bordered "Upload an image" placeholder where the picture will go;
tapping it opens the gallery. Once the user picks an image, the
placeholder is replaced by the existing ShowImageUploadGallery preview
and tapping the preview lets them pick a different image.

Lets the user see the whole form (name, description, server, quality,
strip-metadata) immediately instead of being thrown into the picker
the moment they hit the FAB.
2026-04-19 21:20:38 +00:00
Claude 29518dbf19 feat(badges/new): image-first creation flow with upload + auto UUID
Replace the form-first create screen with a picker-first media pipeline
that matches the other upload screens in the app.

- NewBadgeButton (FAB, AddPhotoAlternate icon) opens GallerySelect
  directly.
- After the image is picked, NewBadgeDialog mirrors the NewMediaView /
  ImageVideoPost pattern: a thumbnail strip, name + description fields,
  server picker, compression-quality slider, and strip-metadata switch.
- NewBadgeModel drives the upload through the shared MultiOrchestrator.
  Only on a successful upload does it reach into Account.sendBadgeDefinition
  with an auto-generated UUID d-tag, the uploaded URL + dimensions, and
  the uploaded URL reused as the NIP-58 thumb (a separate thumbnail
  upload can land as a follow-up).

The Cancel / Post buttons use the CreatingTopBar so "Create" reads
right on the primary action. Submit is disabled until the name is
non-empty, an image is staged, and a server is selected.

Drops the old route-based NewBadgeScreen / NewBadgeViewModel and the
Route.NewBadge entry.
2026-04-19 20:53:24 +00:00
Claude a346ae86de refactor(badges): default Badges feed filter to Mine 2026-04-19 20:20:55 +00:00
Vitor Pamplona 2d5097e8b0 Merge pull request #2451 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-19 16:13:40 -04:00
Crowdin Bot af27ad4673 New Crowdin translations by GitHub Action 2026-04-19 19:37:16 +00:00
davotoula f15e280862 updated cz,sv,pt,de 2026-04-19 21:31:56 +02:00