Commit Graph

121 Commits

Author SHA1 Message Date
Vitor Pamplona e5dd70b12c Merge pull request #1983 from vitorpamplona/claude/always-on-notification-service-NuW9I
Add always-on notification service for real-time Nostr relay connections
2026-04-22 09:54:57 -04:00
Claude 64b3367472 feat: AudioRoomConnectionViewModel + connection chip in stage
Phase 3d-3 of the Clubhouse/nests integration. Wires the
nestsClient.connectNestsListener() facade into AudioRoomStage via a
dedicated Android ViewModel, and surfaces the listener's StateFlow
through a small assist chip so the user sees connection progress and
failure modes.

amethyst/audiorooms/room:
- New `AudioRoomConnectionViewModel` (Android `ViewModel`):
  * Owns one `NestsListener` + one `AudioRoomPlayer` per host/speaker.
  * `connect(event, signer)` resolves the room HTTP-side, opens
    WebTransport, runs MoQ SETUP, then subscribes to every host +
    speaker pubkey from the 30312 event and wires their Opus stream
    through `MediaCodecOpusDecoder` -> `AudioTrackPlayer`.
  * `disconnect()` is idempotent, also called from `onCleared()`.
  * Mirrors the underlying NestsListener.state into its own
    StateFlow so callers observe one source.
  * Audience members are skipped — they don't publish audio.
- `AudioRoomStage` now mounts the ViewModel keyed by the room
  address, auto-calls `connect()` in a LaunchedEffect, and
  disconnects in a DisposableEffect.
- New `ConnectionChip` composable renders the listener state with
  retry-on-tap for Idle / Failed / Closed, and color-codes Connected
  (primary) and Failed (error) states.

amethyst:
- Added `:nestsClient` to the project's dependencies.

res:
- New strings for the five connection-chip states.

Behavior today: on opening an audio-room, the chip will report
`Connecting (OpeningTransport)` then immediately
`Failed: WebTransport NotImplemented: ...` because the Kwik handshake
in `KwikWebTransportFactory` is the next phase. Tapping the chip
retries — same outcome until 3b-2 ships. Everything else (presence,
chat, hand-raise, mute) is unaffected.

https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
2026-04-22 07:29:42 +00:00
Claude ae548a851d feat: add always-on notification relay service
Implements a 5-layer always-on notification system that maintains
persistent WebSocket connections to the user's inbox relays for
real-time notification delivery, eliminating the dependency on the
external push server seeing all relays.

Layer architecture:
- L1: Foreground service (specialUse type, no Android 15 time limit)
  keeps the shared NostrClient alive by collecting relayServices flow
- L2: FCM/UnifiedPush (existing, unchanged) as wakeup trigger
- L3: WorkManager periodic worker (15-min catch-up safety net)
- L4: BOOT_COMPLETED receiver (restart service after reboot)
- L5: AlarmManager watchdog (5-min health check for OEM killers)

Key design: the foreground service shares the same NostrClient as the
UI. When the app foregrounds, both the UI and service are subscribers
to the relay pool. When the app backgrounds, UI subscriptions drop
but service subscriptions remain — zero reconnection needed.

New files:
- NotificationRelayService: foreground service with persistent notification
- BootCompletedReceiver: restarts service on device boot
- NotificationCatchUpWorker: WorkManager fallback for missed events
- ServiceWatchdogManager: AlarmManager-based health monitor
- AlwaysOnNotificationServiceManager: coordinates all 5 layers

Settings: opt-in toggle in App Settings, persisted per-account.

https://claude.ai/code/session_01LEPfmgGnwjB9a5SDFw5U8t
2026-04-21 23:24:10 +00:00
nrobi144 da1037423c feat(desktop): version source-of-truth + RPM + AppImage packaging
Phase 1+2 of multi-platform distribution plan:
- gradle/libs.versions.toml: add `app = "1.08.0"` as single source of truth
- Root build.gradle: allprojects { version = libs.versions.app.get() }
- amethyst/build.gradle: versionName from catalog (versionCode stays local)
- desktopApp/build.gradle.kts: drop hardcoded "1.0.0"; inherit project.version;
  add TargetFormat.Rpm; add linux DSL (menuGroup, appCategory, debMaintainer,
  rpmLicenseType, rpmPackageVersion with dashes stripped)
- desktopApp/build.gradle.kts: new createReleaseAppImage task wrapping
  createReleaseDistributable with linuxdeploy (TargetFormat.AppImage is
  broken in Compose 1.10.x — CMP-7101)
- packaging/appimage/: AppRun launcher (sets LD_LIBRARY_PATH for bundled VLC),
  amethyst.desktop XDG entry, 512x512 icon extracted from icon.icns
- scripts/asset-name.sh: single source for release asset naming contract
2026-04-16 14:35:01 +03:00
Claude 7ae536e80d feat: add AI writing help to new post screen
Add on-device AI writing assistance using ML Kit GenAI APIs (Rewriting,
Proofreading) powered by Gemini Nano via Android AICore. Users can tap
the sparkle button in the compose toolbar to access tone chips (Correct,
Rephrase, Shorter, Elaborate, Friendly, Professional, More Direct,
Punchy, + Emoji) that transform their post text. Results appear in a
card with Use/Dismiss actions.

- Play flavor: MLKitWritingAssistant using on-device Gemini Nano
- F-Droid flavor: NoOpWritingAssistant stub (returns unavailable)
- WritingAssistant interface for future DVM/NIP90 integration
- AI button hidden on unsupported devices

Also fixes pre-existing exhaustive when expression in
DecryptAndIndexProcessor for GroupEventResult.Duplicate.

https://claude.ai/code/session_01RbCYGrbbapRMike8WQy41F
2026-04-08 12:47:23 +00:00
Claude 12b2731eb5 feat: add WebRTC voice/video call infrastructure
Implements P2P calling over Nostr relays using WebRTC for media
transport and NIP-59 Gift Wraps for encrypted signaling. No custom
server required — only public STUN servers for NAT traversal.

Protocol layer (quartz/nip100WebRtcCalls):
- 6 new event kinds (25050-25055): offer, answer, ICE candidate,
  hangup, reject, renegotiate
- WebRtcCallFactory for creating and gift-wrapping signaling events
- CallIdTag and CallTypeTag for event metadata
- Events registered in EventFactory

Call state machine (commons/call):
- CallState sealed interface with full lifecycle states
- CallManager orchestrating signaling and state transitions
- Follow-gate spam prevention: only followed users can ring,
  non-follows are silently ignored

Android WebRTC integration (amethyst/service/call):
- WebRtcCallSession wrapping Google WebRTC PeerConnection
- CallForegroundService for keeping calls alive in background
- IceServerConfig with default public STUN servers
- User-configurable TURN server support

Android UI (amethyst/ui/call):
- CallScreen with offering, connecting, connected, and ended states
- IncomingCallUI with accept/reject buttons
- ConnectedCallUI with mute, video toggle, speaker, and timer
- Call button added to 1-on-1 DM chat header
- ActiveCall route added to navigation

https://claude.ai/code/session_017hZm7yu7CzmcQgZGSaqSXS
2026-04-01 23:28:39 +00:00
Vitor Pamplona 0f7bcdba38 Redesigns the GeoHash library for performance. 2026-04-01 18:01:39 -04:00
Vitor Pamplona 9587026abc v1.08.0 2026-04-01 15:45:46 -04: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 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 cd11503b1e v1.07.5 2026-03-31 20:18:34 -04:00
Vitor Pamplona 5cd83bbaa4 v1.07.4 2026-03-31 19:19:24 -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 8e4ee7a618 v1.07.2 2026-03-30 16:46:01 -04:00
Vitor Pamplona 640c47e29f v1.07.1 2026-03-30 13:53:25 -04:00
Vitor Pamplona 0c4e5be1ea v1.07.0 2026-03-30 12:29:41 -04:00
Vitor Pamplona f42881a48e v1.06.3 2026-03-24 20:55:04 -04:00
Vitor Pamplona 1f2e24bc1f v1.06.2 2026-03-24 19:36:30 -04:00
Vitor Pamplona 7874893938 v1.06.1 2026-03-23 18:19:42 -04:00
Vitor Pamplona 7af1be7363 v1.06.0 2026-03-23 11:23:44 -04:00
Vitor Pamplona 9d086df37a Updating all dependencies 2026-03-23 10:28:33 -04:00
Vitor Pamplona 91994a0b74 Merge branch 'main' into claude/strip-file-metadata-sVIEd 2026-03-17 13:25:54 -04:00
Vitor Pamplona d0297b7e34 Fixes stability plugin for AGP9 2026-03-16 19:44:51 -04:00
Vitor Pamplona 81ecaa82ff Migrates to vico charts 3.0 2026-03-16 12:53:54 -04:00
Claude cf922a064b feat: Strip sensitive metadata from media files before upload
Adds a MetadataStripper that removes GPS location, camera info, timestamps,
and other sensitive EXIF/metadata from images, videos, and audio files before
uploading. This protects user privacy by default.

- Creates MetadataStripper using AndroidX ExifInterface for images and
  MediaMuxer for video/audio remuxing
- Adds "Strip location metadata" toggle to all upload dialogs (NewMediaView,
  ChatFileUploadDialog) so users can disable stripping per upload
- Persists the setting in AccountSettings (stripLocationOnUpload, default true)
- Integrates stripping into UploadOrchestrator before compression
- Covers all upload paths: media posts, DM attachments, channel uploads,
  profile pictures, list/channel metadata images

https://claude.ai/code/session_01974zpAMSRD9GeqBt9ax6XD
2026-03-14 03:50:34 +00:00
Vitor Pamplona 4c81ef19df Fixes build.gradle to add dependencies for the Gallery 2026-02-24 17:02:03 -05:00
Vitor Pamplona 6125394354 Migrates to AGP 9 2026-02-08 16:33:39 -05:00
davotoula bfd0fc01b9 add TarsosDSP dependency for voice anonymization 2026-01-12 23:03:51 +01:00
Vitor Pamplona 54c1605de7 v1.05.1 2026-01-08 19:01:01 -05:00
Vitor Pamplona bb01918120 v1.05.0 2026-01-08 16:21:30 -05:00
Vitor Pamplona 15ee49282d Adds the stability plugin to allow traces in debug 2025-12-09 11:01:03 -05:00
Vitor Pamplona ae6f37a52f v1.04.2 to appease the PlayStore 2025-11-15 17:28:55 -05:00
Vitor Pamplona 5264bd2cbc v1.04.1 2025-11-15 16:51:45 -05:00
Vitor Pamplona a86f64fce5 Fixes release Id for the zap the devs button 2025-11-15 12:01:17 -05:00
Vitor Pamplona 075a92a709 Version 1.04 2025-11-15 11:45:26 -05:00
Vitor Pamplona b1d3aa968d Merge branch 'main' into bugfix-dont-render-gallery-for-mixed-images-and-videos 2025-10-14 09:48:58 -04:00
davotoula 133c897731 Added junit and mockK for androidTest UI dependencies
Added failing androidTest for mixed image/video parsing
2025-10-13 18:38:14 +02:00
davotoula 2a3c31cc5b Use latest LightCompressor-enhanced:
Fix for Progressive download
Replaced obsolete MP4 parser libraries with native MediaMuxer/MediaCodec
2025-10-12 21:13:12 +02:00
Vitor Pamplona 93f33cca70 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	gradle/libs.versions.toml
#	quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/relay/client/accessories/NostrClientSendAndWaitExt.kt
2025-10-03 16:46:03 -04:00
davotoula a6e306f3de Update to use lightcompressor library version that supports h265
Add h265 toggle to NewMediaView.kt and ImageVideoDescription.kt
Touch many files to add optional h265 boolean (default is false)
2025-09-30 22:02:18 +02:00
davotoula 4c3eaf972c move to LightCompressor-enhanced fork
corrected image vs video compressor library names
2025-09-25 22:01:25 +02:00
Vitor Pamplona f31292a201 Updates compose, navigation, windowCore and tests 2025-09-25 12:59:24 -04:00
Vitor Pamplona 7a280a3cde - Migrates Quartz from Android to CommonMain
- Fully converts OpenTimestamp Java codebase to Kotlin, migrating the sync and async HTTP call interfaces to OkHttp and coroutines
- Redesigns parsing of relay commands, messages and filters for performance in Jackson.
- Starts the use of KotlinX Serialization when speed is not a requirement
- Migrates all Jackson field annotations to Kotlin Serialization
- Migrates Regex use in Quarts to Kotlin's Regex class
- Migrates Base64 from Android to Kotlin
- Migrates UUID from Android/Java to Kotlin
- Migrates LRUCache usage from Android/Java to Kotlin collections
- Migrates all String to bytearray conversions to Kotlin methods
- Migrates all System.arraycopy calls to kotlin native ones.
- Separates parsing code from the data classes Companion objects
- Exposes Rfc3986 normalizations to each platform.
- Exposes URI parsing classes to each platform.
- Exposes URL Encoders to each platform.
- Exposes BigDecimal to each platform.
- Exposes the Url Detector to each platform.
- Exposes MacInstances to each platform
- Exposes Diggest instances to each platform.
- Exposes a BitSet to each platform.
- Exposes GZip to each platform.
- Exposes Secp256k1 to each platform.
- Exposes SecureRandom to each platform.
- Exposes Time in seconds to each platform.
- Exposes the LargeCache to each platform.
- Exposes AES CBC and AES GCM encryption/decryption to each platform
- Migrate test assertions to Kotlin Tests
- Exposes Address class to each platform because of the Parceleable
- Creates our own ByteArrayOutputStream.
- Removes Lock features inside the Bloomfilters because we don't need data consistency/
- Migrates UserMetadata parser from Jackson to Kotlin serialization
- Removes the need for Static methods in each tag.
- Adds an event template serializer
- Adds KotlinX Datetime to migrate some of the date-based logs
- Adds support for LibSodium in the JVM platform
- Creates a shared test build for iOS targets
- Fixes several usages of Reflection when serializing classes
- Fixes a bug on loading RelayDB for the HintBloom filter test
- Increases the Bloom filter space to better use hints in the app.
- Removes support for iOS in x86
- Creates a Jackson mapper just for NIP-55, which stays in the Android build only.
- Keeps the event store in the android build as well.
- Removes @Syncronized tags in favor of Mutexes.
- Improved sendAndWaitForResponse NostrClient method to properly account for returns from each relay.
- Removes the need for GlobalScope and async calls in the downloadFirstEvent method.
- Restructures the parser and serialization of the relay messages and commands for performance with Jackson
- Removes the dependency on Jackson's error classes across the codebase.
- Moves the hint to quote tag extension methods to their own packages.
- Speeds up the generation of Bech32 addresses
- Migrates NIP-6 and Blossom uploads to use Kotlin Serialization
2025-09-22 19:44:51 -04:00
Vitor Pamplona 501fa25e98 v1.03.0 2025-09-02 14:01:15 -04:00
Vitor Pamplona 7f7debbb73 v1.02.1 2025-08-29 07:38:42 -04:00
Vitor Pamplona 0fe01696a5 v1.02.0 2025-08-28 17:02:55 -04:00
Vitor Pamplona d2214889b6 Version 1.01.0 2025-08-27 09:10:11 -04:00
Vitor Pamplona d90618f7f3 Corrected version 1.00.5 2025-08-23 11:06:45 -04:00
Vitor Pamplona 41ca6d281e Revert "Version 1.00.5"
This reverts commit 83870cd06b.
2025-08-23 11:06:11 -04:00