Commit Graph
24 Commits
Author SHA1 Message Date
Barry Deen 28cb2dad42 feat(tor): embedded Tor with fail-closed routing for all connections
Add an embedded Tor daemon (kmp-tor) with an onion toggle in the sidebar
drawer and on the pre-login Splash/Auth screens. When enabled, every
connection — relay WebSockets, Coil images, ExoPlayer media, NIP-05/NIP-11,
LNURL/zaps, Blossom uploads, link previews, exchange rates, DM media, live
metrics — routes through Tor's SOCKS proxy.

Routing is fail-closed: from the moment the toggle flips, new clients point
at a dead loopback port until bootstrap completes, and existing clients have
their in-flight requests cancelled and keep-alive pools evicted so no
pre-toggle socket survives. OkHttp passes unresolved hostnames to SOCKS
proxies, so DNS also resolves inside Tor.

- TorManager: kmp-tor runtime in a foreground service; state machine
  (Off/Starting %/On/Stopping/Error) observed by all toggles; start retries
  around kmp-tor's fixed 1s service-bind timeout, which a busy main thread
  misses during cold start
- TorPreferences: device-level pref so the toggle works pre-login and
  survives logout
- HttpClientFactory: single proxy choke point; client registry +
  setTorSocks() invalidation; new getRelayClient/getLoopbackClient/
  getDmMediaClient
- Relay/RelayPool: clients resolved through providers on every (re)connect;
  suspendForTorSwitch/resumeAfterTorSwitch tear down sockets and suppress
  reconnects during bootstrap so the 5-min relay cooldown can't trip; local
  relay stays direct (Tor refuses loopback/LAN targets)
- Captured-client fixes so a mid-session toggle can't leak: Coil delegating
  Call.Factory (it caches its lambda forever), ZapSender, DmBubble,
  NwcRepository, SplashViewModel raw client, ExchangeRateRepository refetch
- Cold start with Tor on: relay init gated on bootstrap
- kmp-tor pinned to 2.4.x: 2.5+ needs Kotlin 2.2 metadata, unreadable by
  this project's Kotlin 2.0.21

Verified on-device by socket-inode audit: app process held 43 sockets, all
to 127.0.0.1:<socks>; only the tor child process held external connections.

Known gaps: Breez/Spark SDK (own Rust networking) and ML Kit model
downloads bypass OkHttp and are not routed.
2026-06-10 13:00:23 -04:00
Barry Deen e0a889d2be fix: revert 16KB packaging changes behind GrapheneOS perf regression
Fully revert f68b40f, which shipped in 1.0.2 alongside reports of severe
slowdown and freezes on GrapheneOS:

- jniLibs.useLegacyPackaging back to true: compressed native libs cut the
  download from 82MB to 37MB, and uncompressed 16KB-aligned packaging is
  only needed for Google Play, which this build no longer targets
- secp256k1-kmp pinned back to known-good 0.16.0 (0.19.0 = libsecp256k1
  0.7.0 rebuilt with NDK 28; runs once per relay event on the verify path)

Also fix adjacent issues found while auditing every shipped release APK
(all were clean: release-signed, R8-minified, correctly aligned — ruling
out a malformed artifact as the cause):

- baseline-prof.txt still targeted com/wisp/app after the rebrand; the
  next release would have shipped zero app AOT rules. Fixed paths now
  yield 12,888 app rules; verified on-device (cold start 2048ms -> 830ms
  once compiled, ProfileVerifier reports compiledWithProfile=true)
- release signing moved into Gradle (RELEASE_STORE_* via local.properties
  or env) so the published APK is exactly what assembleRelease emits
- tools/audit-apk.sh: pre-release gate checking debuggable flag, lib
  packaging consistency, alignment, R8, baseline profile, signing cert
- ProfileVerifier status logged at startup for field diagnostics
- <profileable android:shell="true"/> so testers can capture simpleperf/
  Perfetto traces from release builds
- docs/grapheneos-perf-investigation.md: full findings plus the A/B
  attribution matrix (incl. GrapheneOS MTE toggle test) for confirming
  which half of f68b40f was guilty
2026-06-10 11:48:57 -04:00
Barry Deen 0223e1b9e7 refactor: remove Tor functionality
Drops the embedded kmp-tor client, all .onion relay support, the Tor
toggle UI on splash/auth/drawer screens, the SOCKS proxy plumbing in
HttpClientFactory, all Tor-related strings across 11 locales, the
TorManager singleton, and the kmp-tor dependencies and ProGuard rules.

Relay URL validation now accepts only wss:// (with hostname, no port,
non-localhost, non-IP). The cleartextTrafficPermitted network security
flag stays — still needed for local relays on RFC1918 / loopback.
2026-05-03 21:14:51 -04:00
Barry Deen f68b40f5a7 fix: support 16 KB page size for Android 15+
Disable legacy jniLibs packaging so native libraries are stored
uncompressed and page-aligned in the APK. Bump secp256k1-kmp to 0.19.0
and kmp-tor-resource to 408.16.4 since the prior versions shipped
ELF binaries with 4 KB LOAD alignment. All 13 .so files in the release
APK now report 2**14 alignment.
2026-04-23 11:03:17 -04:00
Barry Deen 4d3673f2ba Revert "Merge pull request #446 from fiatjaf/ktlint"
This reverts commit 1b346197c8, reversing
changes made to 80fb1da0e7.
2026-04-15 21:48:04 -04:00
fiatjaf dc24b43f0e run ktlint after every change. 2026-04-09 13:26:55 -03:00
Barry DeenandClaude Opus 4.6 77148d127f feat: keep screen awake during fullscreen video and show media controls
Prevent the device from sleeping during fullscreen video playback with
FLAG_KEEP_SCREEN_ON. Add a MediaSessionService so Android shows media
controls in the notification shade and lock screen when the app is
backgrounded, covering both fullscreen and PiP video modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:38:07 -04:00
The Daniel 28ce05f815 chore: bump AGP to 8.13.2 and Gradle wrapper to 8.13 2026-04-01 13:02:42 -04:00
The Daniel 278208115c chore: update Breez SDK to 0.11.0, dynamic version display
Read SDK version from BuildConfig instead of hardcoding in wallet
settings screen so it stays in sync with libs.versions.toml.
2026-03-15 13:20:59 -04:00
The Daniel 6b8f88b0df feat: add QR scanning, tx fees, zap user profiles in wallet history
- Add CameraX + ML Kit barcode scanning to send flow (scan QR / import from gallery)
- Show fee for outgoing transactions in history
- Associate zap counterparties (sender/recipient) with transactions using:
  - Persisted ZapSender map (SharedPreferences, survives restarts)
  - ObjectBox zap receipt queries (kind 9735)
  - One-shot relay fetch for user's incoming zap receipts (#p filter)
- Show counterparty avatar and display name in transaction rows
- Enable Spark SDK LNURL verify support (NIP-57 zap receipts)
- Sync wallet before listing transactions for freshest data
- Cache zap receipt counterparty maps to avoid repeated bolt11 parsing
- Move heavy transaction processing to Dispatchers.IO
2026-03-12 20:50:27 -04:00
The Daniel 19ca8fe76b feat: add Breez Spark non-custodial Lightning wallet
Integrate Breez SDK Spark as a second wallet backend alongside NWC.
Users can create/restore a non-custodial Lightning wallet directly
in the app with seamless onboarding (no forced backup on first use).

- WalletProvider interface abstracts NWC and Spark backends
- WalletModeRepository persists active wallet mode
- SparkRepository wraps Breez SDK: connect, send, receive, transactions
- Wallet mode selection UI with back navigation
- Receive flow auto-detects payment via sync polling + SDK events
- Payment received success screen with auto-navigation
- Dynamic wallet provider resolution for zaps (no stale captures)
- Proper SDK lifecycle: disconnect on app exit, cleanup on teardown
- 60s connection timeout for Spark (vs 20s for NWC)
- Wallet-connected indicator works for both providers
- BIP39 mnemonic generation with bundled English wordlist
- ProGuard rules for UniFFI/JNA bindings
2026-03-11 21:47:15 -04:00
Barry Deen ad235610ae fix: route video playback through Tor proxy when Tor mode is enabled
ExoPlayer was using its default HTTP stack, bypassing the SOCKS proxy
entirely and leaking the user's IP to video servers even with Tor active.
Added media3-datasource-okhttp to pipe video traffic through the same
Tor-aware OkHttpClient used by image loading and relay connections.
2026-03-10 18:48:02 -04:00
Barry Deen 8e4cda2951 feat: add ObjectBox event persistence (write-behind)
Add ObjectBox as a write-behind persistence layer for Nostr events.
Events flowing through the relay pipeline are asynchronously batched
and written to ObjectBox on Dispatchers.IO. The LRU cache remains the
hot read path — no startup seeding or feed changes in this PR.

What's persisted: user's own events (all kinds), notes (kind 1),
profiles (kind 0), reposts (kind 6), reactions (kind 7), and zap
receipts (kind 9735).

Search now merges LRU cache results with ObjectBox for cross-session
note search. Old events are pruned on startup (50k cap, 90-day TTL,
user's own events exempt).
2026-03-05 20:06:52 -05:00
Barry DeenandClaude Opus 4.6 9fd63c7181 feat: add media tab to user profiles with video thumbnails and reply animations
Add a Media tab to user profile screens showing an Instagram-style grid
of images and videos extracted from the user's notes. Videos display
actual frame thumbnails via Coil's VideoFrameDecoder with a play icon
overlay. The grid supports infinite scroll.

Also adds ICQ-style flower burst animation for reply notifications,
restores the shared OkHttpClient for image loading (fixes GC thrashing
from per-request client creation), and separates reply vs generic
notification sounds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:05:35 -05:00
Barry Deen 44c0d7e6af perf: add baseline profile installer and shrink resources
Add profileinstaller library so baseline profiles are applied on
sideloaded APKs (not just Play Store installs). Add app-specific
baseline-prof.txt covering startup-critical paths. Enable resource
shrinking for release builds.
2026-03-01 21:18:40 -05:00
Barry DeenandClaude Opus 4.6 fb0dedeab9 feat: add on-device translation to feed posts
Use Google ML Kit for on-device translation with no API keys required.
Adds a "Translate" option to the post overflow menu that detects the
source language, downloads the model if needed, and displays the
translated text inline below the original content.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:56:26 -05:00
Barry DeenandClaude Opus 4.6 287cf9e2eb feat: add Tor connectivity with embedded SOCKS5 proxy
Route all network traffic through Tor when enabled — relay WebSockets,
NIP-05, NIP-11, image loading, media uploads, and zaps. Uses kmp-tor
to embed the Tor runtime with automatic SOCKS5 port discovery.

- Add TorManager singleton for Tor lifecycle management
- Add HttpClientFactory to centralize OkHttpClient creation with
  Tor proxy and DNS leak prevention (custom Dns resolver forces
  hostname resolution through SOCKS5 tunnel)
- Migrate all OkHttpClient creation sites to use HttpClientFactory
- Add Tor-aware Coil image loading via Call.Factory
- Support .onion relay addresses when Tor is active
- Add onion icon toggle in navigation drawer with status indication
- Persist Tor enabled state across app restarts
- RelayPool hot-swaps clients on Tor state changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 21:09:18 -05:00
Barry Deen 6979d6250e fix: add missing media3 HLS dependency to prevent video playback crash
Videos hosted on HLS streams crash the app because the HLS exoplayer
module was not included as a dependency.
2026-02-26 11:53:21 -05:00
Barry Deen 6ff4de8d61 Revert "event store"
This reverts commit f7ee50ff93.
2026-02-22 01:15:23 -05:00
Barry Deen f7ee50ff93 event store 2026-02-21 23:55:50 -05:00
Barry Deen d4d1a7b621 notification grouping, highlight recent notification, gif support 2026-02-20 23:39:12 -05:00
Barry Deen acd7dfd4ce new onboarding experience 2026-02-19 23:40:15 -05:00
Barry Deen e1f724c510 a lot of stuff 2026-02-19 03:18:37 -05:00
Barry Deen bc5e311e48 Initial commit: Wisp - minimal Android Nostr client 2026-02-18 22:30:54 -05:00