Commit Graph
15873 Commits
Author SHA1 Message Date
Claude 2786c5b683 fix(relayauth): expand IF_IN_MY_LIST to all live relay lists minus blocked
Replace the localRelayServers-only check with account.trustedRelays
(nip65, private outbox, local, dm, search, indexer, proxy, trusted,
broadcast relay lists combined) minus account.blockedRelayList. Uses
normalizeRelayUrlOrNull for consistent URL comparison.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude 162ee51955 feat(ui): modernize napplet and relay auth permission screens
- ConnectedAppDetailScreen: replace emoji policy icons (❤👍🕶) with
  themed MaterialSymbols (Favorite/Shield/Lock); show domain instead of
  raw coordinate in AppIdentityHeader
- ConnectedAppsScreen: remove redundant Column wrapper around SuggestionChip
- NappletSignerConsentActivity: add centered FavoriteAppIcon header with
  title + description; promote "Allow once" to FilledTonalButton; collapse
  time-based/granular grants behind a "More options" toggle; resolve app
  icon from cache using coordinate
- RelayAuthSettingsScreen: replace plain radio buttons with styled PolicyCard
  composable (bordered card, icon, check mark); wrap per-relay overrides in
  surfaceVariant Surface with dividers; fix duplicate if/if → if/else;
  add TextOverflow.Ellipsis to URL text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude 9a117d6166 feat(napplets): show app icon in Connected Apps list and detail
Replace the static placeholder glyph with the napplet manifest's
icon() URL loaded via FavoriteAppIcon (Coil AsyncImage + glyph
fallback). Both ConnectedAppsScreen and ConnectedAppDetailScreen now
resolve iconUrl alongside title from the event cache and display the
real app icon when available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude d57c3f71db fix: update quartz auth tests to match new two-arg signWithAllLoggedInUsers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude 0e6e7901c2 fix: update KtorRelayTest to match new signWithAllLoggedInUsers signature
The lambda now receives (relay, template) after RelayAuthenticator was
updated to pass the relay URL for per-relay auth policy checks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude 328790ac9f feat: time-bound signer grants, last-used tracking, and relay AUTH settings (NIP-42)
- Add AllowForSession and AllowUntil(expiresAt) signer grant types so users
  can grant temporary access (session, 24h, 30d) from the consent dialog
- Track per-app lastUsed timestamp in NostrSignerPermissionStore and update
  it on every granted signing operation
- Auto-expire timed grants: decide() clears expired op decisions before
  returning, so no background sweep is needed
- Add NappletBroker.sessionAllows in-memory set for session grants (cleared
  on broker destroy, never persisted)
- Implement full NIP-42 relay auth policy system:
  - RelayAuthPolicy enum (ALWAYS / NEVER / IF_IN_MY_LIST) stored in
    AccountSettings and persisted in LocalPreferences
  - RelayAuthDecision (ALLOW / DENY) per-relay overrides in DataStore
  - RelayAuthPermissionLedger combining global policy + per-relay overrides
  - DataStoreRelayAuthPermissionStore writing to relay_auth.preferences_pb
- Wire relay auth into AuthCoordinator: subscribeLedger/unsubscribeLedger
  lets each logged-in account contribute its own policy; signWithAllLoggedInUsers
  now receives the relay URL so it can check the ledger before signing
- Update RelayAuthenticator (quartz) to pass relay URL in the signing lambda
- Add RelayAuthSubscription composable that subscribes both the account and
  its ledger when a screen is active
- Add RelayAuthSettingsScreen: global policy radio picker + per-relay
  override list with toggle and remove; reachable from Settings
- Add Route.RelayAuthSettings, AppNavigation wiring, and SettingsCatalog entry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude 77dacd9e68 feat: add Connected Apps settings screen with per-app permission detail
Adds a unified "Connected Apps" entry to Account Settings that surfaces
all web apps that have connected to the user's Nostr key (both capability
grants and signer trust levels) in one place.

- Route.ConnectedApps (list) + Route.ConnectedAppDetail(coordinate) (detail)
- ConnectedAppsScreen: merges NappletPermissionLedger + NostrSignerPermissionLedger,
  shows one card per app sorted alphabetically with trust-level chip
- ConnectedAppDetailScreen: identity header, editable trust-level picker
  (Full Trust / Reasonable / Paranoid), op override rows with revoke, capability
  switches, and a "Forget this app" button that clears all permissions
- Settings catalog entry under Account (Apps symbol, keyword-searchable)
- NappletsTopBar Tune icon now navigates to ConnectedApps instead of
  the old capability-only NappletPermissions screen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:51 +00:00
Claude e03fef36e4 refactor: replace hand-rolled JSON builder with org.json.JSONObject
buildEventJson was manually escaping quotes, newlines, and backslashes
which is fragile. org.json.JSONObject.toString(2) handles all escaping
correctly and produces the same pretty-printed output.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:50 +00:00
Claude e5763b947c fix: polish napplet signer permission UIs
- NappletSignerConsentActivity: replace AlertDialog (broken 5-button
  layout) with a custom Dialog + Surface using heightIn + verticalScroll;
  color-coded allow (primary) / deny (error) action rows; monospace
  "See more" toggle that reveals full raw event JSON with SelectionContainer
  so users can inspect and copy the data being signed/encrypted
- NappletConnectActivity: wrap column in verticalScroll so the trust-level
  options are not clipped on small screens or large font sizes
- NappletSignerPermissionsScreen: show localized op labels ("sign kind 1
  event") and decision labels ("Allow"/"Ask"/"Deny") instead of raw key
  strings and enum names; fix per-op delete touch target to 48dp (M3 min)
- NappletSignerConsentInfo: add rawData field carrying full event JSON for
  sign/encrypt or decrypted plaintext for future decrypt operations
- NostrSignerOpLabels: populate rawData; add buildEventJson helper
- strings: napplet_op_decrypt → "read your private messages" (the consent
  is to expose already-decrypted content, not to perform decryption);
  add napplet_consent_wants_to, see_more/see_less, decision labels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:50 +00:00
Claude b48cad67e5 feat: add Nostr signer permission system for napplets/nsites
Implements per-app permission management for the internal nsec signer when
webapps/napplets/nsites connect via Amethyst's built-in key:

- Three trust levels on first connect (FULL_TRUST, REASONABLE, PARANOID)
  with a UI dialog (NappletConnectActivity) matching the design spec
- Per-operation consent dialogs (NappletSignerConsentActivity) for
  sign-kind/encrypt/decrypt with Allow once, Don't ask again, Deny options
- Per-app DataStore storage (DataStoreNostrSignerPermissionStore) using
  SHA-256-hashed filenames so 1000s of apps don't bloat a single file
- NostrSignerPermissionLedger applies policy decisions: REASONABLE
  auto-allows kinds 1/6/7; FULL_TRUST auto-allows all non-payment ops
- NappletBroker extended with first-connect gate and per-op signer gate,
  serialized by a dedicated signerConsentLock mutex
- Permission management screen (NappletSignerPermissionsScreen) to review
  and revoke stored per-app signer permissions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013hTFpoExYYLYEGGtXBx6ZT
2026-06-27 22:58:50 +00:00
Vitor PamplonaandClaude Opus 4.8 82f40e0ed1 Merge PR: Fix embedded WebView theming (dark-page corruption + live theme switch)
Merges nostr proposal 81ee3e7c into main:
- fix(napplet): drop algorithmic darkening so dark-by-default sites (e.g.
  ditto.pub) aren't corrupted — it collided with nightThemedContext and inverted
  their nav bars to light. prefers-color-scheme: dark still works without it.
- feat(embed): follow the app theme live in embedded web tabs by rebuilding the
  warm sessions on a DARK/LIGHT flip, instead of requiring an app restart.

Device-verified on ditto.pub + brainstorm.nosfabrica.com, Dark<->Light.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:47:05 -04:00
Vitor PamplonaandClaude Opus 4.8 925c5e454a feat(embed): follow the app theme live in embedded web tabs
An embedded tab's WebView resolves its theme from the context it is built with
(nightThemedContext), once, at construction — a runtime config change does not
re-flip the renderer — so a live app-theme switch never reached an already-warm
surface; it took a full app restart.

Watch the resolved DARK/LIGHT theme and, on a real flip, rebuild the warm
sessions in the new theme:
- EmbeddedTabHost.themeEpoch + rebuildAllForTheme() tears down the warm
  controllers but keeps activeId, so the visible tab re-activates the instant its
  screen re-acquires (no blanked-out surface).
- EmbeddedTabThemeWatcher (mounted by AppNavigation next to the tab layer)
  collects uiPrefs.theme + isSystemInDarkTheme() and triggers the rebuild.
- WebAppScreen / NostrAppScreen key their controller on themeEpoch (NostrApp also
  re-mints its launch params); the preloader re-warms off-screen tabs; the tab
  layer keys each surface on (id, controller) so a rebuilt session gets a fresh
  SandboxedSdkView.

The page reloads in the new theme (unavoidable — the theme is fixed at WebView
construction). Device-verified Dark<->Light with no app restart.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:43:05 -04:00
Vitor PamplonaandClaude Opus 4.8 c6575a0888 fix(napplet): drop algorithmic darkening so dark-by-default sites aren't corrupted
setAlgorithmicDarkeningAllowed(true) was added to force-darken pages that don't
implement prefers-color-scheme. Combined with nightThemedContext (which forces the
embed WebView's isLightTheme=false), it now also runs on pages that are ALREADY
dark but don't declare CSS color-scheme support — e.g. ditto.pub, which ships
<html class="dark"> by default — and algorithmically inverts their nav bars to
light, leaving "dark content, light bars".

prefers-color-scheme: dark is driven by isLightTheme (nightThemedContext)
INDEPENDENTLY of algorithmic darkening — device-verified: embedded pages still
report prefersDark=true with darkening off — so dropping it keeps real dark-aware
sites dark while no longer corrupting dark-by-default ones. The trade-off (a site
with no dark mode of its own renders light instead of being force-inverted)
matches how a real mobile browser behaves.

Removed from all four embed/host WebView configs (browser + nsite/napplet,
embedded + full-screen) along with the now-unused WebSettingsCompat import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:43:05 -04:00
Vitor PamplonaandGitHub 4b6e4be942 Merge pull request #3413 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-27 17:46:21 -04:00
vitorpamplonaandgithub-actions[bot] 9792c5c75e chore: sync Crowdin translations and seed translator npub placeholders 2026-06-27 21:03:45 +00:00
Vitor PamplonaandGitHub 6ef7d21132 Merge pull request #3414 from vitorpamplona/claude/search-bar-transparency-75as8b
Add surface background color to SearchBar Column
2026-06-27 17:01:48 -04:00
Vitor PamplonaandClaude Opus 4.8 0e36d416a6 Merge PR: fix(video) — drop errored players from warm pool, crop blurhash to true aspect
Merges nostr proposal 6650c40b into main:
- Square blurhash placeholder: render with ContentScale.Crop when the imeta dim
  is known, so it fills the correctly-sized box instead of letterboxing a
  component-grid-square bitmap inside a taller portrait box.
- "Can't play this video" flash: never return a warm-pooled ExoPlayer carrying a
  stale PlaybackException — releasePlayer drops one that errored before pooling,
  acquirePlayer drops one whose decoder died asynchronously while warm.
- Adds playback-error lifecycle logging used to trace both issues from logcat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 16:56:34 -04:00
Vitor PamplonaandClaude Opus 4.8 9acb53d574 fix(video): drop errored players from warm pool and crop blurhash to true aspect
Two inline-video bugs surfaced by a portrait Damus post (imeta dim 720x1280, a
rotated H.264 file) that showed a square blurhash in a too-tall box and flashed
"Can't play this video":

- Square blurhash placeholder: the placeholder bitmap is decoded at the
  blurhash's DCT component-grid aspect (e.g. a 5x5 grid -> a square bitmap), not
  the real media shape. When the true ratio is known (from imeta dim) the box is
  already sized correctly, so render the placeholder with ContentScale.Crop to
  fill it instead of letting FillWidth letterbox a square inside the taller
  portrait box.

- "Can't play this video" flash: a warm-pooled ExoPlayer could be handed back
  still carrying a stale PlaybackException. releasePlayer now drops a player that
  errored before being pooled; acquirePlayer drops one whose decoder died
  asynchronously while it sat warm (surface reclaim / codec loss). Either way a
  clean cold/fresh player is used and the stale error never reaches a controller.

Also adds playback-error lifecycle logging (PlaybackError tag with a flattened
cause chain, a live-controller counter, and cold-load + acquire-time
stale-error markers) that made both issues traceable from logcat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 16:53:34 -04:00
Claude 393ff9ba8b fix: make search filter bar opaque
The top bar on the Search screen (search field + filter row with the 3
scope buttons) had no background, so the feed scrolled visibly behind
the segmented buttons and the gaps in the bar.

Apply the theme surface color to the SearchBar Column, before
statusBarsPadding() so the status-bar inset is filled too, matching the
default Material3 top-app-bar container color used elsewhere.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LkfRpnNyeeo3AVEaX71oRX
2026-06-27 20:47:07 +00:00
Vitor PamplonaandGitHub 3adce5caf8 Merge pull request #3412 from vitorpamplona/claude/app-ui-theme-customization-evwwkb
Add customizable accent colors, fonts, and font sizes
2026-06-27 16:00:11 -04:00
Vitor PamplonaandGitHub 5f8ce0e692 Merge pull request #3411 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-27 16:00:03 -04:00
vitorpamplonaandgithub-actions[bot] ac255d5cc6 chore: sync Crowdin translations and seed translator npub placeholders 2026-06-27 19:59:26 +00:00
Vitor PamplonaandGitHub e81d76e3f3 Merge pull request #3410 from vitorpamplona/claude/nsites-napplets-preload-iwhh1j
Add loading progress bar and error logging to napplet/browser
2026-06-27 15:57:28 -04:00
Claude 373aa7d740 perf: keep ColorScheme.isLight O(1) after accent-color change
isLight fans out to hundreds of themed-color getters on hot note/chat/feed
render paths. The accent-color work had switched it to background.luminance(),
which adds per-call gamma math. Since the accent never touches background
(only primary/secondary) and the dark palette's background is exactly
Color.Black, a single reference comparison is just as accent-robust and
restores the original constant-time cost.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REGsru6cnm6wUzqm12Rh2d
2026-06-27 19:56:53 +00:00
Vitor PamplonaandGitHub 0ed15be975 Merge pull request #3408 from vitorpamplona/claude/nsite-tor-warning-removal-hp52fw
Remove network routing confirmation dialog from napplet host
2026-06-27 15:55:17 -04:00
Vitor PamplonaandGitHub fb357937b8 Merge pull request #3409 from vitorpamplona/claude/default-webclient-list-3sm1ne
Browser: add Discover section with hardcoded web apps & followed nSites/nApplets
2026-06-27 15:53:05 -04:00
Claude 1069fb0701 refactor: move Profile Gallery Style setting to Profile UI settings
The gallery style selector is profile-specific, so it now lives on the
Profile UI settings screen alongside the other profile display toggles
instead of the general Application Preferences screen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REGsru6cnm6wUzqm12Rh2d
2026-06-27 19:50:51 +00:00
Claude bdacc28663 feat: add app UI theme customization (accent color, font, font size)
Adds three new appearance settings to Application Preferences, alongside
the existing Theme selector:

- Accent Color: Purple (default), Blue, Green, Orange, Red, Pink. Drives
  the Material primary/secondary/tertiary colors so buttons, links, FABs
  and switches follow the chosen hue. Purple preserves the original look
  (purple primary + teal secondary).
- Font: System Default, Sans Serif, Serif, Monospace. Applied to the full
  Material typography and to bare Text via LocalTextStyle.
- Font Size: Small, Normal (default), Large, Huge. Scales all text through
  LocalDensity.fontScale without affecting dp-based layout.

Plumbed through the existing UiSettings -> UiSettingsFlow ->
UiSharedPreferences (DataStore) pipeline and the AmethystTheme composable.
New fields default to the current behavior and are appended, so existing
stored settings deserialize unchanged.

ColorScheme.isLight now derives from background luminance instead of a
fixed primary, so the light/dark check keeps working when a non-purple
accent is selected. The primary-derived tint extensions (links, new-item
background, secondary button) now compute from the live scheme so they
track the accent color.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REGsru6cnm6wUzqm12Rh2d
2026-06-27 19:28:18 +00:00
Claude b01e1eb6bc feat(napplet): show top loading bar, keep splash until first paint, log load errors to console
The napplet/nsite host (NappletHostActivity) removed its loading splash the
moment the index probe succeeded and then mounted a WebView with no progress
tracking at all, so during the seconds the shell + bundle take to load (notably
over Tor) the user saw only the WebView's dark colorBackground — a black screen
with no sign anything was happening, especially in dark theme.

- Add a thin browser-style determinate progress bar pinned to the top edge,
  driven by WebChromeClient.onProgressChanged and hidden at 100%, to both the
  napplet/nsite host and the URL browser (NappletBrowserActivity).
- Mount the WebView under the loading splash and keep the splash (now opaque)
  until first paint (onPageCommitVisible) instead of removing it on mount, so
  there is never a blank/dark gap between probe-success and the shell's first
  frame. This mirrors the pattern the URL browser already used.
- Add a developer console (NappletConsolePanel) to the napplet/nsite host,
  wired through the existing onConsole hook in NappletControlSheet, and forward
  the page's console.* output to it.
- Surface failed resource fetches (onReceivedError / onReceivedHttpError) as
  ERROR lines in the console on both hosts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D4iYA4Qf5guWZyKexkcmhb
2026-06-27 19:20:54 +00:00
Claude fb76705f71 feat: discover followed nsites & napplets in the browser
Add two Discover sections to the browser launcher home that surface the
NIP-5A sites and NIP-5D apps published by the people the user follows,
reusing the same feed + follow-list filter as the dedicated nSites and
nApplets screens (set those to All Follows for a pure follows list).

The launcher subscribes the nsite/napplet assemblers while open, observes
the addressable manifest store, keeps the followed authors' (or own, in
the Mine case), drops ones already pinned, and caps each section. Rows
mirror the web Discover row — manifest icon, title, description, and a
star to pin — launching Nostr-natively through the sandboxed host.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 19:10:57 +00:00
Claude 217f4ad9ca fix: drop confirm dialog on nsite Tor network switch
Tapping the "loads over Tor" row on an nSite's pull-down sheet popped a
confirm dialog explaining the routing change. Users already know what Tor
is, so toggle the routing directly on tap (still relaunches the session to
rebuild the proxy + content server) and remove the now-unused strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177rhf2L93YRcq6NrWkkM4Q
2026-06-27 19:06:37 +00:00
Claude 64abf2d544 feat: search the discover list in the omnibox + add 3-dot menu to results
The omnibox now ranks the hardcoded Discover web apps alongside
favorites and history, so typing finds a suggested app even before its
first visit (the ranker dedupes by host, and favorites/history outscore
a plain default, so an already-pinned/visited app never doubles up).

Search results are split into Favorites / Recent / Discover groups using
the visited-URL set so the headers stay accurate, and every result row
now carries the same 3-dot menu as the idle Recent cards: pin/unpin to
favorites, plus remove-from-history for visited sites. The favorite
toggle is shared with the Recent rows via one helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 18:51:22 +00:00
Vitor PamplonaandGitHub 6dd8771c2a Merge pull request #3407 from vitorpamplona/claude/cashu-icon-alignment-19eflw
Align Cashu icon with reaction gallery icons in Nutzap
2026-06-27 14:50:17 -04:00
Claude 756648aef1 feat: add HiveTalk to discover web apps
HiveTalk (hivetalk.org) — Nostr-native, Lightning-powered video
conferencing. Reachability and own apple-touch-icon verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 18:44:50 +00:00
Claude 152f81602c fix: align cashu nutzap icon with reaction icons in notifications
The nutzap gallery in MultiSetCompose used WidthAuthorPictureModifier
(55dp, flush-right) for its cashu icon column, while the like/boost
reaction galleries above it use NotificationIconModifier (55dp with a
5dp end inset). That left the cashu glyph sitting ~5dp further right
than the reactions it stacks under. Switch the cashu Box to the same
NotificationIconModifier so the icons line up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011qQdaD3DHRQNDKe2BUnEiM
2026-06-27 18:38:20 +00:00
Claude 2d6221fd10 feat: show curated descriptions for discover web apps
Render the browser "Discover" section as full-width rows (icon + name +
one-line description) instead of bare icon cells, matching the Recent
row layout which already carries a subtitle. Each suggestion now has a
short curated description (trimmed from the app's own meta description)
so unfamiliar apps explain themselves; tapping a row opens the app, and
a trailing star pins it to favorites.

Auto-pulling page <title>/description was rejected: many of these apps
are client-rendered SPAs that serve an empty <title>, and several titles
are long marketing strings — curated short names read better in the list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 18:34:53 +00:00
Claude 5029acccee feat: expand suggested web apps list with icons and reachability check
Grow the browser "Discover web apps" list to the full set of
browser-openable Nostr web apps from the nostrapps.com directory plus
several requested additions, and give each entry its own logo.

- Each suggestion now carries iconUrl set to the app's own declared
  apple-touch-icon / icon (PNG or SVG, individually verified to return an
  image), so the grid matches the favicon look of Favorites/Recent
  without any third-party favicon service. Apps whose only icon is an ICO
  (Coil has no ICO decoder) or that couldn't be resolved stay icon-less
  and fall back to the globe glyph until their favicon is captured on
  first visit.
- Added: nymchat, nostr.build, nostrcheck, zap.cooking, x21, divine.video,
  brainstorm, zappix, plektos, zaptrax, zaplytics, podstr, ghostr, mutable,
  metadata, plebsvszombies, blobbi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 18:12:18 +00:00
Claude f206b0bb46 feat: suggest a default list of Nostr web apps in the empty browser
Add a "Discover web apps" section to the browser launcher home, shown
after the Recent block, with a hardcoded list of popular Nostr web apps
drawn from the nostrapps.com directory. Gives new users (whose Favorites
and Recent are empty) somewhere to start instead of a bare empty screen.

- New DefaultWebClients in commons (URL + label entries), grouped by
  category; extensions/signer-only tools are excluded and every URL is a
  confirmed canonical domain. No remote icons are loaded on the idle
  screen — favicons are captured the normal way once a site is opened.
- Render the list via a new suggestedAppItems grid (long-press offers
  "Add to favorites"); already-favorited apps are filtered out.
- FavoriteAppCell now takes a menu slot so the favorites grid and the
  suggestions grid can offer different long-press actions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0151Uczec41LhTogxkgoAhKa
2026-06-27 17:07:18 +00:00
Vitor PamplonaandGitHub 2e47eaf3a6 Merge pull request #3406 from vitorpamplona/claude/git-repositories-feed-7xov6e
Add Git Repositories feed screen with community and author filtering
2026-06-27 12:50:28 -04:00
Vitor PamplonaandGitHub 02aa877f4f Merge pull request #3405 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-27 12:45:07 -04:00
vitorpamplonaandgithub-actions[bot] fc95f64458 chore: sync Crowdin translations and seed translator npub placeholders 2026-06-27 16:40:09 +00:00
Vitor PamplonaandGitHub be1b0bb851 Merge pull request #3404 from vitorpamplona/fix/loading-account-ui-thread-stall
fix(perf): unfreeze the cold-start "Loading account" screen in debug builds
2026-06-27 12:37:41 -04:00
Claude a81825b5cd feat: add Git Repositories feed
Add a new top-level feed for NIP-34 Git repository announcements
(kind 30617), mirroring the Pictures/Videos/Workouts feeds.

- GitRepositoriesFeedFilter scans LocalCache addressables for kind 30617
- Full top-nav filter support (follows, authors, global, hashtag,
  geohash, communities, muted) via a per-relay sub-assembler set
- Wired into AccountFeedContentStates, the relay subscription
  coordinator, bottom-bar preloaders, navigation, drawer and the
  persisted per-feed follow-list setting
- Reuses the shared RenderGitRepositoryEvent card via the standard feed
  render path, enriched with topic chips and a personal-fork badge

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GS371vPHy3PhMfQyeAHmZC
2026-06-27 16:27:48 +00:00
Vitor PamplonaandClaude Opus 4.8 981fe528dc chore(debug): add Compose composition tracing deps (debug-only)
Adds androidx.compose.runtime:runtime-tracing and tracing-perfetto so
recompositions show up as named slices in Perfetto system traces — the
tool used to attribute the cold-start feed first-paint cost to specific
composables. debugImplementation only (not shipped); all Apache-2.0.
Usage (runtime-enable broadcast) documented inline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 12:26:45 -04:00
Vitor PamplonaandClaude Opus 4.8 de1362561f fix(perf): collect debug memory snapshot off the main thread
The debug-only MemoryUsageChip ("X/YMB" top-bar indicator, gated on
isDebug) polls collectMemorySnapshot() every 2s from a produceState
block, which runs on the main thread. That reads coil3.disk.DiskLruCache
.size(), a @Synchronized call. On cold start the Coil disk cache holds
that monitor for several seconds (journal init + the burst of image
writes from the initial relay event flood), so the UI thread blocked
inside size() — the "Loading account" frame couldn't repaint until it
returned. Profiling showed a single ~8s render frame and the UI thread
"blocking from coil3.disk.DiskLruCache.size()".

Collect the snapshot via withContext(Dispatchers.IO) so the synchronized
read blocks a background thread instead of the UI. The "Loading account"
stall on cold start drops from ~15-20s to ~5s. Debug-only path, so this
never affected release builds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 12:26:44 -04:00
Vitor PamplonaandGitHub 9d0f444b6f Merge pull request #3403 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-27 08:56:59 -04:00
vitorpamplonaandgithub-actions[bot] 0afb4ada07 chore: sync Crowdin translations and seed translator npub placeholders 2026-06-27 12:55:24 +00:00
Vitor PamplonaandGitHub 7684c3725f Merge pull request #3400 from roguehashrate/feat/payment-targets
added support for more payment targets
2026-06-27 08:53:33 -04:00
Vitor PamplonaandGitHub 3832f31e52 Merge pull request #3401 from vitorpamplona/fix/video-decode-stall-fallback
fix(video): show browser-fallback overlay when a decoder silently stalls
2026-06-27 08:53:10 -04:00
Vitor PamplonaandGitHub ede3b798a3 Merge pull request #3402 from vitorpamplona/claude/web-app-preload-check-ev4r28
Cache favorited nsite/napplet manifests for offline resolution
2026-06-27 08:52:36 -04:00