Commit Graph

10532 Commits

Author SHA1 Message Date
Claude eb19fc69ae fix: disable slug field when editing an existing article
The d-tag is the article's identity in Nostr addressable events.
Changing it on edit would create a new article instead of updating
the existing one. The slug field is now disabled when isEditing is true.

https://claude.ai/code/session_011JuQbdA12WdPxC7aGvUBqJ
2026-04-02 14:50:51 +00:00
Claude 10bcbdcd8c feat: redesign article creation screen with banner, tags, and slug
Redesigns the LongFormPostScreen to match the reference UI with:
- Visual banner image placeholder with dashed border (clickable to upload)
- Borderless large title field with placeholder styling
- Labeled Summary section
- URL Slug field mapped to the d-tag for user-defined article identifiers
- Tag/hashtag chip input with add button and removable chips
- Tags are included as hashtags in the published event

Adds tags and slug state to LongFormPostViewModel, wires them into
createTemplate() for event publishing, and loads them from drafts.

https://claude.ai/code/session_011JuQbdA12WdPxC7aGvUBqJ
2026-04-02 14:29:37 +00:00
Vitor Pamplona 217389ecb7 Merge pull request #2067 from vitorpamplona/claude/implement-nip51-kinds-53nfc
Add NIP-51 list event types for content curation and management
2026-04-02 09:55:08 -04:00
Claude 662e870f2a feat: implement all missing NIP-51 list event kinds
Add 14 missing NIP-51 event kinds with full CRUD support:

Replaceable lists:
- 10009 SimpleGroupListEvent (NIP-29 group membership)
- 10017 GitAuthorListEvent (NIP-34 code follows)
- 10018 GitRepositoryListEvent (NIP-34 repo follows)
- 10020 MediaFollowListEvent (multimedia follows)
- 10101 GoodWikiAuthorListEvent (NIP-54 wiki authors)
- 10102 GoodWikiRelayListEvent (NIP-54 wiki relays)

Addressable sets:
- 30004 ArticleCurationSetEvent (curated articles)
- 30005 VideoCurationSetEvent (curated videos)
- 30006 PictureCurationSetEvent (curated pictures)
- 30007 KindMuteSetEvent (kind-specific mutes)
- 30015 InterestSetEvent (hashtag interest groups)
- 30063 ReleaseArtifactSetEvent (software release artifacts)
- 30267 AppCurationSetEvent (software app curation)
- 39092 MediaStarterPackEvent (media starter packs)

All events follow existing patterns with NIP-44 private tag
encryption, ALT tags, hint providers, and TagArrayBuilder extensions.
Registered all new kinds in EventFactory.

https://claude.ai/code/session_01QrYyt6KQepNGtRMDcCr5zM
2026-04-02 04:01:03 +00:00
Vitor Pamplona 0f7bcdba38 Redesigns the GeoHash library for performance. 2026-04-01 18:01:39 -04:00
Vitor Pamplona 6d1b7c518b Merge pull request #2066 from vitorpamplona/claude/zap-notification-routing-MBmaw
Add scroll-to-event functionality for push notifications
2026-04-01 16:38:02 -04:00
Vitor Pamplona 9587026abc v1.08.0 2026-04-01 15:45:46 -04:00
Vitor Pamplona 6ee19506ad Merge pull request #2065 from vitorpamplona/claude/fix-addstyle-indexing-9t4Ew
Fix mention styling by deferring style application until after text mutations
2026-04-01 15:32:27 -04:00
Claude 09fb10220b fix: apply addStyle after all text mutations in OutputTransformation
TextFieldBuffer.addStyle() positions are not adjusted by subsequent
replace() calls. When multiple mentions had different-length display
names, styles for later mentions became misaligned. Split into two
phases: all replace() calls first, then all addStyle() calls with
cumulative-shift-corrected positions.

https://claude.ai/code/session_01SSsxsfJLbRiesBBhQFEVUd
2026-04-01 19:15:47 +00:00
Vitor Pamplona b2be345979 Merge pull request #2064 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-01 14:05:21 -04:00
Crowdin Bot 6ed251f7b9 New Crowdin translations by GitHub Action 2026-04-01 18:03:07 +00:00
Vitor Pamplona 391475e75e Merge pull request #2063 from vitorpamplona/claude/migrate-to-arti-tor-voQeh
Replace Android TorService with ArtiProxy for Tor connectivity
2026-04-01 14:01:05 -04:00
Claude 8e6d2164d7 fix: move ArtiNative initialization off main thread
System.loadLibrary("arti_android") runs when ArtiNative is first
accessed. Previously this happened in TorService.init (via
setLogCallback), which ran on main thread during AppModules creation.

Moved setLogCallback into start(), which runs on Dispatchers.IO.
Now all JNI calls — including the native library load — happen off
main thread.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 17:56:22 +00:00
Vitor Pamplona 45f1d79410 Adding compiled libs and customizing the log message. 2026-04-01 13:50:36 -04:00
Claude bc24434f1c refactor: remove duplicate android_logger from native Arti wrapper
All log messages go through send_log_to_java() → Kotlin ArtiLogCallback
→ Log.d("TorService"), which already writes to logcat. The android_logger
module was a second FFI call to __android_log_write that duplicated
every line.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 17:32:38 +00:00
Claude 2429e695ce chore: bump Arti to 2.2.0 (arti-client/tor-rtcompat 0.41)
All features and APIs verified present in 0.41:
- tokio, rustls, compression, onion-service-client, static-sqlite
- TorClient::create_bootstrapped, from_directories, connect()

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 17:18:25 +00:00
Claude 53ae87aa9d chore: trim unnecessary Arti features to reduce binary size
- Set default-features = false on arti-client and tor-rtcompat
- Removed bridge-client (UI doesn't expose bridge config yet)
- Narrowed tokio features from "full" to only what the SOCKS proxy
  needs: rt-multi-thread, net, io-util, time, macros

Kept: tokio, rustls, compression, onion-service-client, static-sqlite
(all required for Amethyst's .onion relay support)

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 17:12:35 +00:00
Claude 35bf16b63e docs: add README for Arti Android build tools
Covers prerequisites, build commands, output verification, version
updates, architecture decisions, Cargo features, and troubleshooting.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 17:03:47 +00:00
Claude 035c570902 chore: bump Arti version to 1.9.0 (arti-client/tor-rtcompat 0.38)
https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 16:55:03 +00:00
Claude e50ae0fb1e feat: replace arti-mobile-ex with custom-built Arti native library
The Guardian Project's arti-mobile-ex AAR has three problems:
1. No 16KB page-aligned binaries (required for Google Play)
2. ArtiProxy's stop()+start() causes state file lock conflicts
   (lock is tied to TorClient object lifetime, released only on GC)
3. ~140MB AAR size

Replace with a custom JNI bridge built from Arti source, following
BitChat's proven approach:

Build tooling (tools/arti-build/):
- build-arti.sh: Clones official Arti, compiles with cargo-ndk
  for ARM64 + x86_64, NDK 25+ for 16KB page alignment
- Cargo.toml: Minimal deps with size-optimized release profile
- src/lib.rs: Custom SOCKS5 proxy with proper lifecycle:
  - initialize() creates TorClient once (holds state lock forever)
  - startSocksProxy() binds port and accepts connections
  - stopSocksProxy() aborts listener only (TorClient stays alive)
  This cleanly separates "stop routing traffic" from "destroy client"

Kotlin side:
- ArtiNative.kt: JNI declarations + ArtiLogCallback interface
- TorService.kt: Uses ArtiNative directly, start() initializes +
  starts proxy, stop() only stops proxy (no lock issues)
- TorManager.kt: Restored stop() calls for OFF/EXTERNAL modes
  since our native stop is now safe

Removed: arti-mobile-ex dependency from build.gradle and version catalog

Native libraries must be built separately:
  cd tools/arti-build && ./build-arti.sh

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 16:37:44 +00:00
Vitor Pamplona abe1082121 Fixes the default port. 2026-04-01 11:03:35 -04:00
Claude 4f92878146 fix: never stop ArtiProxy — Arti's lock is tied to object lifetime
Arti's state file lock is released when the TorClient object is
garbage collected, not when stop() is called. Calling stop()+start()
on the same ArtiProxy creates a new internal TorClient that conflicts
with the old lock that hasn't been GC'd yet.

Solution: start ArtiProxy once, let it run for the process lifetime.
When the user turns Tor OFF or EXTERNAL, TorManager simply stops
emitting Active status — OkHttp stops routing through the proxy.
The idle proxy uses negligible resources and drops circuits when no
SOCKS connections are active.

This removes stop(), Mutex, NonCancellable, CompletableDeferred — all
the complexity that was trying to work around a fundamental Arti
design constraint.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:29:22 +00:00
Claude 14f8bf1245 fix: create ArtiProxy once and reuse — never recreate
The root cause of file lock conflicts was creating new ArtiProxy
objects on each start. Even after stop() confirmed, build() could
race with OS-level lock release.

Now ArtiProxy is created once in the TorService constructor and
reused for the app's lifetime. start() and stop() just toggle it
on/off on the same instance. No more file lock conflicts.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:25:28 +00:00
Claude 7cac95726b fix: wait for Arti to confirm stop before allowing restart
The fixed 2s delay was insufficient — Arti's native layer releases
file locks asynchronously. Now stop() waits for the actual
"state changed to Stopped" log confirmation via CompletableDeferred,
with a 10s timeout as safety net. This ensures the file lock is
truly released before start() creates a new ArtiProxy instance.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:21:33 +00:00
Claude 388a02b60c fix: stop Arti when switching to EXTERNAL Tor mode
EXTERNAL means another Tor process (e.g., Orbot) is running on the
device. No reason to keep our internal Arti alive alongside it.

Also removed the fallback that started Arti when the external port
was invalid — if the user chose EXTERNAL with a bad port, Tor should
be off, not silently falling back to internal.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:11:29 +00:00
Claude 1c33dde81a fix: restore service.stop() on explicit Tor OFF for safety
Users in restrictive countries need Tor circuits torn down when they
switch to OFF — an idle proxy still maintains detectable connections.

stop() is now called only on explicit OFF toggle (user action), not on
flow pause/resume (app lifecycle). This avoids file lock races on
resume while ensuring OFF truly disconnects from the Tor network.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:09:22 +00:00
Claude dd3f90aee9 refactor: remove unused lastLogTime from TorService
Dead code from the earlier callbackFlow version that had a bootstrap
stall monitor. No longer needed with the MutableStateFlow design.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:04:44 +00:00
Claude d94d8776eb fix: keep ArtiProxy alive across mode switches to avoid file lock conflicts
ArtiProxy holds an exclusive filesystem lock. Destroying it on OFF and
recreating on INTERNAL caused lock conflicts because the native layer
needs time to release the lock.

Instead, create ArtiProxy once and never destroy it. When Tor is OFF
or EXTERNAL, the proxy sits idle with no SOCKS connections — negligible
resource usage. This eliminates all file lock race conditions.

Also wrap start/stop in NonCancellable to prevent transformLatest
cancellation from leaking half-initialized proxy instances.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 13:01:31 +00:00
Claude c83256bac2 fix: singleton ArtiProxy lifecycle to prevent state file lock conflicts
The callbackFlow-based TorService created a new ArtiProxy on every flow
collection. When the app paused and resumed, the old instance's file lock
wasn't released before the new one started, causing "Another process has
the lock on our state files" errors.

Redesigned TorService to own a single ArtiProxy with explicit start/stop:
- ArtiProxy is created once and reused across flow re-collections
- State exposed via MutableStateFlow instead of callbackFlow
- Mutex guards start/stop to prevent races
- TorManager calls service.start() and service.stop() explicitly when
  switching between INTERNAL/OFF/EXTERNAL modes
- stop() includes a 2s settle delay for native file lock release

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 12:44:24 +00:00
Claude c7176805b2 feat: route zap push notification tap to notification screen with scroll and highlight
When a zap push notification is tapped, the app now navigates to the
Notifications screen and scrolls to the specific zap event, highlighting
it briefly to draw the user's attention.

- Change Route.Notification from object to data class with optional scrollToEventId
- Include zap/reaction event ID in notification URI (scrollTo param)
- Parse scrollTo from URI in uriToRoute() and pass through navigation
- Scroll to matching card in the feed and animate a highlight that fades

https://claude.ai/code/session_01Dk9vVKQKDtLLgvJPUCfKSs
2026-04-01 04:16:18 +00:00
Claude 293fd39a68 fix: harden TorService with bootstrap timeout, thread safety, and error recovery
Address gaps found in code review:
- Use AtomicBoolean/AtomicLong for state accessed from native Arti
  log callback thread (was a data race)
- Add bootstrap timeout monitor (120s) that restarts Arti once if
  bootstrapping stalls, following BitChat's inactivity pattern
- Clean up failed ArtiProxy instances before port retry
- Detect "Another process has the lock" fatal error from Arti logs

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-04-01 00:23:52 +00:00
Vitor Pamplona cd11503b1e v1.07.5 2026-03-31 20:18:34 -04:00
Vitor Pamplona 9b2fbcbf56 Fixes image uploading crash 2026-03-31 20:17:14 -04:00
Vitor Pamplona 5cd83bbaa4 v1.07.4 2026-03-31 19:19:24 -04:00
Vitor Pamplona 91dfda3480 Merge pull request #2061 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-31 19:13:59 -04:00
Crowdin Bot b1b2825dd6 New Crowdin translations by GitHub Action 2026-03-31 23:12:49 +00:00
Vitor Pamplona 48d90a8252 Fixes Wallet import encoding bug 2026-03-31 19:10:15 -04:00
Claude 11af50e0ad feat: migrate Tor implementation from tor-android to Arti (Rust)
Replace Guardian Project's tor-android (C Tor) and jtorctl with
arti-mobile-ex, a Rust-based Tor implementation. This eliminates
the Android Service binding complexity in favor of an in-process
ArtiProxy object.

Key changes:
- TorService: Replace ServiceConnection to org.torproject.jni.TorService
  with direct ArtiProxy.Builder/start/stop API. Bootstrap state detected
  via log parsing (following BitChat's pattern).
- TorServiceStatus: Remove TorControlConnection field (Arti doesn't
  support jtorctl control protocol).
- RelayProxyClientConnector: Remove DORMANT/ACTIVE/NEWNYM control
  signals. Arti manages its own circuit lifecycle internally.
- Dependencies: Replace tor-android + jtorctl with arti-mobile-ex 1.2.3.

TorManager's external API (status/activePortOrNull StateFlows) and all
downstream consumers (DualHttpClientManager, TorSettings, UI) are
unchanged.

https://claude.ai/code/session_01BApgDd5udqBzMqysSRMpZu
2026-03-31 22:00:48 +00:00
Vitor Pamplona 69099728b2 v1.07.3 2026-03-31 17:32:23 -04:00
Vitor Pamplona 190b99d55a Merge pull request #2060 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-31 17:31:30 -04:00
Crowdin Bot 95adb53640 New Crowdin translations by GitHub Action 2026-03-31 21:29:37 +00:00
davotoula 25a4b68958 update translations: CZ, DE, PT, SE 2026-03-31 23:26:48 +02:00
David Kaspar e91c793f73 Merge pull request #2059 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-31 23:21:41 +02:00
David Kaspar 5b477c64cf Merge branch 'main' into l10n_crowdin_translations 2026-03-31 23:21:32 +02:00
Crowdin Bot 11ca2c14be New Crowdin translations by GitHub Action 2026-03-31 21:07:39 +00:00
Vitor Pamplona 1b39bf1d52 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-03-31 17:05:26 -04:00
Vitor Pamplona a4e3625f26 Migrates to the new 10008 profile badges kind 2026-03-31 16:52:24 -04:00
Crowdin Bot e75b5d173b New Crowdin translations by GitHub Action 2026-03-31 20:25:02 +00:00
Vitor Pamplona 027cc660e2 Merge pull request #2058 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-31 16:24:28 -04:00
Vitor Pamplona 49850e773f Adds a space after inserting the username to avoid issues in some keyboards. 2026-03-31 16:22:57 -04:00