Commit Graph

13621 Commits

Author SHA1 Message Date
Crowdin Bot 674b4a85f5 New Crowdin translations by GitHub Action 2026-05-12 10:11:17 +00:00
Vitor Pamplona 54001267e3 Merge pull request #2855 from davotoula/feat/split-notifications-197
Split notifications: Following vs Everyone
2026-05-12 06:09:21 -04:00
davotoula 9b900b22f8 test(notifications): cover NotificationFeedFilter modeOverride wiring
Adds an instrumented test for the split-notifications feature
2026-05-12 09:56:11 +02:00
davotoula b91e84b416 Code review:
- Gate the new notificationsFollowing / notificationsEveryone fan-out in
  updateFeedsWith / deleteNotes on splitNotificationsEnabled.value so the
  default-off case stops doing two extra filter scans per event bundle.
- Lazy-init NotificationFeedFilter.overrideFollowLists so the
  SharingStarted.Eagerly topNavFilter pipeline only starts when the
  split UI actually opens the filter.
- Switch SplitNotificationsScaffold to rememberForeverPagerState so the
  active tab survives recomposition, matching HomeScreen/DiscoverScreen.
- Promote the duplicated "Notification" last-read key string to a
  NOTIFICATION_LAST_READ_KEY const.
- Move the opaque-background fix into SummaryBar itself so callers don't
  need a band-aid Modifier.background on their topBar Column.
- Trim narrating / WHAT comments; keep only the deep-link scroll WHY.
2026-05-12 09:16:46 +02:00
davotoula 972bce75c5 feat(notifications): opt-in Following / Everyone tab split (#197)
Adds an opt-in toggle under Settings → Notifications that splits the
notifications screen into two pinned-mode tabs — Following (kind:3
follow list only) and Everyone (global). The bottom-bar unread dot
glows only for Following so it behaves like the DM-style indicator
the bounty asks for. Default is off; existing single-feed behavior
and the FeedFilterSpinner are unchanged when the toggle is off.
2026-05-12 09:16:19 +02:00
Claude 24a87602a7 fix(nests): tighten participant context sheet bugs and UX gaps
Fixes ten issues found while reviewing the per-participant ModalBottomSheet
on the Nest full-screen UI:

  1. demoteToListener used to fall through to setRole(PARTICIPANT) when the
     target had no participant row, silently adding a pure-audience listener
     as PARTICIPANT to the kind-30312. Now returns null in that case and
     when the target is already PARTICIPANT.
  2. Kick and Force-mute now require an AlertDialog confirmation before
     firing, matching the host's own Leave-room flow.
  3. Sheet header switched from a raw hex stub to UsernameDisplay so the
     user knows who they're acting on.
  4. Local Hush is hidden when the target isn't currently broadcasting —
     the volume gate attaches to an active subscription, so a hush against
     a non-speaker was a silent no-op.
  5. Follow/Mute/Promote/Demote/Force-mute/Kick now emit success toasts
     (launchSigner already surfaces errors).
  6. isFollowing and isHidden moved to collectAsState so labels update
     live if the kind-3 / mute-list publish lands while the sheet is open.
  7. Force-mute row carries a "May be ignored by clients that don't honor
     the verb" subtitle (the verb is an Amethyst extension over nostrnests).
  8. Tap on a stage avatar now opens the same sheet as long-press — the
     audience grid already worked this way; the stage was long-press only.
  9. Hand-raise queue avatars are now click+long-press → sheet, so a host
     can profile / kick a raised-hand audience member without switching tabs.
 10. Promote-to-Speaker / Promote-to-Moderator / Demote-to-Listener rows
     are hidden when the target already has that role.

https://claude.ai/code/session_013Aj1h3epWkvucKFLdunjcv
2026-05-12 02:12:02 +00:00
Claude c92a9df6ea perf(observeEdits): filter modification updates at the flow level
`observeEdits` in NoteCompose previously listened to the raw
`note.flow().edits.stateFlow` and re-ran `findModificationEventsForNote`
(an IO scan) inside a `LaunchedEffect` on every emission — even when
the emission didn't change the actual list of modifications. That
mutated `editState` repeatedly with the same value during scroll on
any active TextNote.

Add `observeNoteModifications` in EventObservers.kt: it does the IO
resolution via `mapLatest { LocalCache.findLatestModificationForNote(note) }`
on Dispatchers.IO, then `distinctUntilChanged()` — so the State only
updates (and the consumer's LaunchedEffect only re-keys) when the
modification list truly changes. The State is `null` until the first
IO resolution completes; consumers treat that as "still loading" and
don't flip the UI to "no edits" prematurely.

Drop the now-unused `observeNoteEdits` and the
`AccountViewModel.findModificationEventsForNote` wrapper.
2026-05-12 02:11:53 +00:00
Claude 1f578eaff8 feat(TimeAgo): single shared ticker so on-screen ages stay fresh
`TimeAgo`, `NormalTimeAgo`, `ChatTimeAgo`, and the chatroom header's
private `TimeAgo` previously formatted the timestamp once inside
`remember(time)` and never refreshed — a note shown when it was 59 s
old would keep saying "59s" forever, even when it had been minutes.

Introduce a single app-wide ticker:

* `LocalNowSeconds` is a `CompositionLocal<State<Long>>` whose value
  is refreshed every 30 s by a single `produceState` coroutine inside
  `NowProvider` (mounted once at the app root in `MainActivity`).
* Each `TimeAgo` composable reads the ticker inside `derivedStateOf`,
  so it only triggers a Text recomposition when the formatted string
  actually crosses a threshold (e.g. 1m → 2m). Ticks that don't change
  the displayed string are filtered by `derivedStateOf` equality.

One coroutine total, no per-item timers, and recompositions are
proportional to "strings that actually need to update" rather than
"items on screen × ticks/second".
2026-05-12 01:53:14 +00:00
Claude 4d9479fa1b Revert "refactor(RichTextViewer): move isMarkdown onto RichTextViewerState"
This reverts commit 7e2e3304e1.
2026-05-12 01:09:05 +00:00
Vitor Pamplona 4364bc1023 Merge pull request #2852 from vitorpamplona/claude/fix-promote-speaker-menu-L9mT7
Fix coroutine scope for async broadcast operations in room actions
2026-05-11 18:55:32 -04:00
Vitor Pamplona f91ac72465 Merge pull request #2850 from greenart7c3/claude/fix-home-settings-loading-iKfkV
Add preferences for home feed tab visibility
2026-05-11 18:55:06 -04:00
David Kaspar 2ed6247b93 Merge pull request #2853 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-11 23:48:17 +02:00
Crowdin Bot c531c77516 New Crowdin translations by GitHub Action 2026-05-11 21:44:59 +00:00
davotoula 596fa93fed i18n: translate cast / report-warning-threshold strings into cs, de, pt-BR, sv
Also drop DLNA from the cast description (functionality removed) in English and Polish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:41:12 +02:00
Claude c0710b794f refactor(nests): route host actions through AccountViewModel.launchSigner
Replace the raw viewModelScope.launch + runCatching with launchSigner,
matching the rest of the codebase. Same survival-past-dismiss
guarantee, plus signer errors (read-only key, NIP-46 unauthorized /
timeout, signer not found) now surface as toasts instead of being
silently swallowed.
2026-05-11 21:02:57 +00:00
Vitor Pamplona e0335d4340 Merge pull request #2851 from vitorpamplona/claude/fix-nest-profile-shape-dRMiY
Fix avatar oval distortion in narrow grid cells
2026-05-11 16:59:27 -04:00
Claude 924e79b2c3 fix(home): persist home-tab visibility toggles across app restarts
The HomeTabsSettingsScreen toggles (New Threads / Conversations /
Everything) wrote to UiSettingsFlow but UiSharedPreferences had no
DataStore keys for them, so the debounced save was a no-op and startup
always reloaded the defaults. Add the missing keys, reads, and writes.
2026-05-11 20:49:42 +00:00
Claude c75349feb5 fix(nests): avatar circular on narrow grid cells
The stage/audience LazyVerticalGrid uses Adaptive(80dp) cells while
the avatar wants 75dp. Wrapping the avatar in an inner Box with
`Modifier.padding(ringPadding=12dp)` reserved room for the speaking
glow + outer ring, but it also reduced the avatar's max **width** to
56dp on a typical 82dp cell while leaving its height at the requested
75dp — Compose grid items are tight on width and free on height.
Result: a 56×75 ellipse instead of a circle.

Drop the inner padding and size the outer drawBehind Box explicitly
to `avatarSize + ringPadding * 2`. AvatarAndBadges still sizes tight
to the picture (so role/hand/mic/reaction badge corner alignment is
unchanged), but no longer inherits a width-only constraint from the
cell — the 75dp picture stays a circle.
2026-05-11 20:47:23 +00:00
Claude 5bda97db04 fix(nests): promote/demote/kick actions no longer cancelled by sheet dismiss
The per-participant host actions (Promote to Speaker, Promote to
Moderator, Demote, Force Mute, Kick) and the Hand-Raise queue's
Approve button all launched their sign+broadcast on a
rememberCoroutineScope() bound to the local composable. Because
every action row calls onDismiss() (and the hand-raise row may
disappear when canSpeak() flips true), the composable leaves the
tree synchronously after the click, cancelling the scope before
the launched coroutine ever runs sign(template). The user saw the
sheet close and nothing else — the kind-30312 republish / kind-4312
admin event was never actually emitted.

Launch on accountViewModel.viewModelScope instead so the
broadcast outlives the dismissing UI.
2026-05-11 20:43:56 +00:00
Vitor Pamplona bc00476915 Merge pull request #2848 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-11 16:36:22 -04:00
Crowdin Bot 83f6ccadf4 New Crowdin translations by GitHub Action 2026-05-11 19:49:27 +00:00
Vitor Pamplona e82cd0f6f8 Merge pull request #2845 from davotoula/docs/contributing-guide
Add CONTRIBUTING-WITH-AI.md companion guide
2026-05-11 15:47:35 -04:00
davotoula fd02b47d9a docs(contributing): add automated tests and code review sections
Two additional gates on top of the AI-companion guide:

  - Automated tests for new logic — quartz/ and commons/ get unit
    tests; bug fixes get a regression test; UI-only stays exempt
    from automated UI tests but keeps the manual on-device test
    plan + screenshots. Pointer into CONTRIBUTING.md § Interop tests.
  - Code review pass before opening the PR — run a second-agent
    review with a different model or skill (/simplify, /kotlin-review,
    /security-review, /code-review), then re-run tests and manual
    test plan to catch fix-introduced regressions.

CONTRIBUTING.md pointer paragraph updated to enumerate the two new
gates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:18:40 +02:00
davotoula 3ba2049566 docs(contributing): add CONTRIBUTING-WITH-AI.md companion guide
Companion to CONTRIBUTING.md targeting external PRs whose diff was
substantially authored by an AI coding assistant. Adds five gates the
existing doc does not cover:

  - Research before code (issue still valid, decentralisation fit)
  - Build and install both flavours (Play + F-Droid)
  - Performance and resource hygiene (main-thread, coroutines,
    LocalCache reuse, relay subscriptions, KMP source sets, lambda Log)
  - Regression test plan alongside feature test plan
  - Don't-touch list (signer/KeyStore, release pipeline, NIP direction)

Filename deliberately avoids AGENTS.md to keep internal dev-team
agents unaffected by auto-load conventions. CONTRIBUTING.md and the
PR template each gain a one-line pointer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 20:24:47 +02:00
Vitor Pamplona 4b195ad6df Merge pull request #2843 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-11 12:05:22 -04:00
Crowdin Bot ab9f660bf9 New Crowdin translations by GitHub Action 2026-05-11 16:02:03 +00:00
Vitor Pamplona 6f9f3d8ef3 Merge pull request #2844 from vitorpamplona/claude/add-contributing-guidelines-dgPV3
docs: add CONTRIBUTING.md and PR template
2026-05-11 11:59:51 -04:00
Claude fc29147c4a docs(contributing): tighten and fix consistency bugs
- Add missing `## Commits` header so the ToC anchor resolves.
- Drop "Modules touched" and "Risk / rollback" from the PR description
  checklist so CONTRIBUTING matches the PR template (PR template lost
  those sections in 8ea7d1e).
- Fold "Human and AI contributions" into "Proof of testing" — the two
  sections restated the same author-of-record rule.
- Remove duplicate "Sending issues over Nostr" subsection (already
  covered under "Ways to contribute").
- Compress "Project layout" ascii tree into a bullet list and merge
  with "Where code belongs".
- Tighten "Coding standards" (drop bullets that restated generic
  don't-over-engineer guidance) and "Bounties" (single paragraph
  instead of a quote block plus six bullets).
- Trim the interop "Running them" subsection to the non-obvious bits
  (opt-in flags, run-matrix.sh not concurrency-safe) instead of
  repeating paths from the table.

Net: 406 → 316 lines, no information lost.
2026-05-11 15:56:12 +00:00
Vitor Pamplona 6c6d1c4f47 Merge pull request #2842 from davotoula/add-video-casting-feature
Add LAN video casting via Chromecast (Google Play flavour only)
2026-05-11 11:52:35 -04:00
davotoula 9d2f106466 Lambda-convert eager Log.w + drop redundant ${t.message} 2026-05-11 16:35:47 +02:00
davotoula 91aa72ae1e Rip DLNA code paths, collapse to Chromecast-only
- chore(cast): drop protocol-toggle settings, strings, perms, deps
- gate cast on play flavor via BuildConfig.IS_CASTING_AVAILABLE
- fix(cast): keep local player paused across recompose; disable transport while casting
2026-05-11 16:35:47 +02:00
davotoula 725de43c0a Stop-from-phone button + pause local player while casting
fix(cast): explicit RemoteMediaClient.stop() and receiver-status diagnostics
fix(cast): keep SessionManagerListener for caster lifetime + await stop() ack
refactor(cast): kotlin-review fixes — cancellation, valueOf safety, recomp
refactor(cast): tighten types, fix HLS query-string mime, parallelize stop
2026-05-11 16:35:47 +02:00
Claude 5df0e2a37a Add LAN video casting (Chromecast on play, DLNA on both flavors) v1
fix(cast): handle every Chromecast session terminal state and HLS mime hint
fix(cast): repair DLNA Res ctor and add play-only protocol toggle
fix(cast): backfill Cast button for accounts with pre-existing video settings
fix(cast): include cast glyphs in symbol font subset and add diagnostic logs
fix(cast): wire jUPnP's required Jetty deps and survive dialog dismissal
fix(cast): add jetty-client so jUPnP can issue UPnP control requests
2026-05-11 16:35:47 +02:00
Claude 8056eb899f docs(contributing): scope proof-of-testing to non-regular contributors 2026-05-11 14:23:37 +00:00
Claude 8ea7d1ee81 docs(pr-template): drop modules-touched and risk/rollback sections 2026-05-11 14:11:59 +00:00
Claude cfa6899c65 docs: cross-link CONTRIBUTING.md from README and add PR template 2026-05-11 13:42:22 +00:00
Claude ee20ab6ca4 docs(contributing): document interop suites and issue-template practice 2026-05-11 13:25:13 +00:00
Claude 9c39af718b docs: add CONTRIBUTING.md with proof-of-testing rule for new contributors 2026-05-11 13:06:35 +00:00
Vitor Pamplona 89c711ca9f lint 2026-05-11 08:50:05 -04:00
Vitor Pamplona 1ff4f98fff docs(quic-interop): add quinn to the default peer set
quinn is now treated as a flawless-required interop target alongside
aioquic, picoquic, and quic-go. Most Rust-based Nostr/MoQ relays our
users run their servers on are built on quinn, so an interop regression
there is a user-visible regression.

Validated by a 3-round flakiness sweep (1 full matrix + 2 audio-critical
subsets) — zero result flakiness across 528 test executions across all
four peers, with two environmental docker-compose stall classes documented
separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 08:44:15 -04:00
Vitor Pamplona 2ddf59fc5f Merge pull request #2838 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-11 08:39:59 -04:00
Crowdin Bot a8aaf48c8b New Crowdin translations by GitHub Action 2026-05-11 12:32:31 +00:00
Vitor Pamplona 850345a1f2 Merge pull request #2831 from skotchdopolepet/codex/two-stage-zap-progress
Show two-stage zap progress
2026-05-11 08:30:21 -04:00
Vitor Pamplona 94125d6001 Merge pull request #2830 from skotchdopolepet/codex/report-warning-threshold
Configure report warning threshold
2026-05-11 08:27:13 -04:00
Vitor Pamplona 57807e393b Merge pull request #2828 from skotchdopolepet/codex/fix-hidden-dm-unread-dot
Fix hidden DM unread badge after blocking users
2026-05-11 08:23:07 -04:00
Vitor Pamplona f184f715b1 Merge pull request #2834 from coreymull/gif-keyboard-chat-upload
Add GIF keyboard uploads to chat composers
2026-05-11 08:19:54 -04:00
Vitor Pamplona d6b7cd456a Merge pull request #2841 from nrobi144/feat/desktop-embedded-local-relay
feat(desktop): embedded local relay with SQLite event persistence
2026-05-11 08:16:17 -04:00
nrobi144 2b96e83264 feat(desktop): add embedded local relay with SQLite event persistence
Add an in-process local relay to Amethyst Desktop that persists all
received events to a per-account SQLite database using quartz's existing
EventStore infrastructure. On startup, the local store hydrates
DesktopLocalCache for instant feed rendering before remote relays connect.

- LocalRelayStore: manages per-account EventStore lifecycle, batched
  write-through via BasicBundledInsert (250ms window), startup hydration
  (contact list -> metadata -> recent content events)
- LocalRelayMaintenance: periodic cleanup (NIP-40 expiration, 30-day
  prune, weekly VACUUM), disk space monitoring
- Settings UI: integrated into RelaySettingsScreen with statistics,
  storage management (prune/vacuum/clear), JSONL export/import, and
  error display
- OfflineBanner: animated banner in both SinglePaneLayout and
  DeckColumnContainer showing offline status with local cache indicator
- Thread-safe store access via @Volatile + synchronized lock
- Skips re-enqueue during hydration (checks LOCAL_RELAY_URL)
- DB stored at ~/.amethyst/accounts/<pubkey8>/events.db
- Corrupt DB auto-detected and recreated on open

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 11:35:39 +03:00
David Kaspar 17b6bba9fb Merge pull request #2824 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-11 08:10:02 +02:00
Corey Mull e38902fb66 Wire keyboard image input into chat uploads 2026-05-11 00:26:05 -04:00