56 Commits

Author SHA1 Message Date
callebtc
97026d7bbb fix: lock wear dependencies in CI 2026-07-29 12:20:48 +02:00
callebtc
3f8b596361 build: enable reproducible Android releases 2026-07-28 14:29:49 +02:00
Moe Hamade
4a34408db9
Enhancement/apk sharing (#632)
* feat: Add QR code generator for Wi-Fi and URLs

This commit introduces a `QrCodeGenerator` utility object to create QR code bitmaps for both Wi-Fi credentials and URLs.

Key features:
- **`generateWifiQr`**: Creates a QR code using the standard `WIFI:` format, allowing other devices to connect to a hotspot by scanning the code. It properly escapes special characters in the SSID and password.
- **`generateUrlQr`**: Generates a standard QR code for any given URL.
- **Implementation**: Uses the `zxing` library to encode the data and converts the resulting `BitMatrix` into an Android `Bitmap`.

* feat: Add manager for universal APK sharing

This commit introduces a comprehensive system for fetching, downloading, caching, and managing a "universal" APK of the app, intended for offline sharing with new users.

The core components are:
- `GitHubReleaseClient`: A new client to fetch the latest release information from the project's GitHub repository. It specifically looks for a universal APK asset in the release, parses its download URL, and attempts to extract its SHA256 checksum from the release notes.
- `UniversalApkManager`: Manages the entire lifecycle of the universal APK. It handles:
    - Checking for new versions by comparing the cached APK version against the latest GitHub release.
    - Downloading the APK with progress reporting.
    - Verifying the downloaded file against the SHA256 checksum, if available.
    - Caching the APK and its metadata (version, checksum, size) locally.
    - Cleaning up old APK versions to conserve space.

* feat: Add offline APK sharing via Wi-Fi hotspot

This commit introduces a comprehensive feature for sharing the BitChat application offline using a self-hosted Wi-Fi Direct hotspot. This enables mesh network expansion by allowing users to distribute the app without requiring an internet connection.

Key components:
- **`HotspotManager`**: A new class that manages the creation and lifecycle of a Wi-Fi P2P (Wi-Fi Direct) group. It handles generating secure credentials (SSID/password), acquiring WakeLocks, and monitoring connected peers. It supports custom credentials on Android 10+ and falls back to system-generated ones on older versions.
- **`ApkWebServer`**: A lightweight HTTP server based on `NanoHTTPD` that serves the APK file and a user-friendly HTML landing page to connected devices.
- **`ApkSharingUtils`**: A utility to detect whether the app is installed as a single or split APK, collect the necessary files, and copy them to a cache directory for sharing.
- **`ApkInstaller`**: A utility using the `PackageInstaller` API to handle the installation of single or split APKs received from another user.
- **`HotspotActivity`**: A new Compose-based UI that guides the user through starting the hotspot, displays connection details (Wi-Fi credentials, QR codes for Wi-Fi and the download URL), and shows the number of connected peers. It also handles the necessary runtime permissions (`NEARBY_WIFI_DEVICES` or `ACCESS_FINE_LOCATION`).
- **Configuration**:
    - Adds necessary Wi-Fi and P2P permissions to `AndroidManifest.xml`.
    - Defines a `FileProvider` path for APK sharing in `file_paths.xml`.
    - Adds numerous string resources for the new UI.

* feat: Add offline and online app sharing features

This commit introduces a comprehensive feature set for sharing the application, both offline via a Wi-Fi hotspot and online through standard Android sharing mechanisms.

Key additions:

- **Prepare for Sharing UI:**
    - Adds a "Prepare App for Sharing" option in the settings sheet.
    - This feature downloads a universal APK from a remote source, suitable for all Android devices.
    - The UI displays the status: not downloaded, downloading (with progress), ready, or if an update is available.
    - Users can download, update, or delete the cached universal APK.

- **Offline Sharing via Wi-Fi Hotspot:**
    - Adds a "Share via Wi-Fi Hotspot" option.
    - This launches a new `HotspotActivity` to share the prepared universal APK with nearby devices without an internet connection.
    - A dialog informs the user if the APK hasn't been prepared yet.

- **Online & Local Sharing:**
    - Adds an option to share via Bluetooth, email, etc., using the standard Android share sheet.
    - This method shares the *installed* version of the app, which may be a split APK.
    - An explanatory dialog is shown first, instructing the receiver on how to install split APKs if necessary.
    - Implements logic to correctly package and share single or multiple split APK files using `FileProvider`.

* feat: Add NanoHTTPD for hotspot APK sharing

This commit introduces the `nanohttpd` library, which will be used to implement an HTTP server for sharing the application's APK over a local hotspot.

The specific dependency added is `org.nanohttpd:nanohttpd:2.3.1`.

* refactor: Improve hotspot and APK sharing stability

This commit introduces several fixes and refinements to the hotspot sharing and APK handling features, improving stability, user experience, and robustness.

Key changes:

-   **Hotspot Flow:**
    -   Automatically starts the hotspot after the user grants the required Wi-Fi permission, removing the need for a second button press.
    -   Ensures all `HotspotManager` callbacks in `HotspotViewModel` are executed within `viewModelScope` to prevent threading issues and ensure safe UI updates.
    -   Fixes a potential `BroadcastReceiver` leak in `HotspotManager` by tracking its registration state, preventing crashes and resource leaks when stopping the hotspot.
    -   Changes the hotspot `WakeLock` to be non-expiring to prevent the CPU from sleeping while the hotspot is active.

-   **APK Handling & Installation:**
    -   Adds a pre-download disk space check in `UniversalApkManager` to prevent download failures on devices with insufficient storage.
    -   Improves the file move logic after download by falling back to a copy-and-delete strategy if a direct rename fails, making it more robust across different filesystems.
    -   Introduces `InstallResultReceiver` to provide clear Toast notifications to the user about the success or failure of an APK installation, including specific error reasons (e.g., "Not enough storage").

-   **Performance & UI:**
    -   Caches the generated HTML in `ApkWebServer` to improve performance by avoiding regeneration on every request.
    -   Throttles the APK download progress updates to prevent UI jankiness from too-frequent state changes.
    -   Moves hardcoded strings in the "Share App" UI to `strings.xml` for better localization and maintenance.

* feat: Refactor APK sharing to use universal APK

This commit refactors the "Share App" functionality to exclusively use the new universal APK system, removing the previous logic that shared the installed split APKs. This simplifies the sharing process and ensures a consistent, single-file sharing experience for all users.

Key changes:
- Deletes `ApkSharingUtils.kt`, which was responsible for detecting and copying split APKs from the device's installation directory.
- Updates `AboutSheet.kt` to use `UniversalApkManager` for all sharing actions (Hotspot and "Quick Share").
- Simplifies the sharing intent logic, as it now only needs to handle a single APK file (`ACTION_SEND`) instead of multiple files (`ACTION_SEND_MULTIPLE`).
- The UI for sharing options (Hotspot, Quick Share) is now dynamically hidden until the universal APK is prepared, preventing user confusion.
- Replaces hardcoded strings with string resources for better localization.

* refactor: Remove InstallResultReceiver

Deletes the `InstallResultReceiver` broadcast receiver.

This component was responsible for handling the results of an APK installation initiated via `PackageInstaller`, but it is no longer used in the current implementation.

* feat: Move APK download to resumable WorkManager pipeline

Replaces the ViewModel-scoped coroutine download with a WorkManager-backed
downloader so downloads survive app backgrounding and process death:

- New ApkDownloader interface with WorkManagerApkDownloader implementation
  and ApkDownloadWorker (CoroutineWorker); transient IO errors return
  Result.retry() and resume via HTTP Range requests from the partial file.
- UniversalApkManager gains resume support (Range header + persisted resume
  metadata) and verifies the downloaded APK is signed with the same
  certificate as the running app (no hardcoded fingerprint; debug-signed
  builds skip enforcement).
- APK downloads now go through the shared OkHttpProvider so they respect
  the app's Tor proxy configuration instead of leaking the direct IP.
- AboutSheet logic extracted into ApkDownloadViewModel (MVI: state/event/
  effect), removing ~240 lines of UI-embedded logic.
- Removes unused ApkInstaller (receivers install via the system installer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Harden hotspot server and release metadata fetching

- ApkWebServer only serves the exact /bitchat.apk path instead of any
  *.apk-suffixed URI.
- GitHubReleaseClient uses the shared OkHttpProvider (respects Tor proxy)
  and drops the loose 'any lone 64-hex string in the release notes is the
  checksum' fallback, which was spoofable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Address review findings in HotspotManager

- Keep polling for group info while the group is still forming instead of
  silently stopping when the first requestGroupInfo() returns null, with a
  15s formation timeout (Codex P1).
- Release wake/wifi locks and unregister the broadcast receiver on terminal
  startup failures via failStartup(), so a failed attempt no longer leaks
  resources or blocks subsequent attempts (Codex P2).
- Use PARTIAL_WAKE_LOCK with a 30-minute timeout instead of the deprecated
  FULL_WAKE_LOCK held indefinitely.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: harden offline APK sharing

* fix: Handle fully-downloaded temp file before adding Range header

If the process died after download_temp.apk was fully written but before
verification/promotion, the next attempt sent "Range: bytes=<size>-",
GitHub answered 416, and the worker retried the same request forever,
leaving the user stuck on an unresumable download.

- Skip the network entirely when the temp file already holds the full
  asset and go straight to checksum/signature verification.
- Treat an HTTP 416 response as an invalid resume offset: discard the
  partial state so the retry restarts from scratch instead of looping.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Allow sharing when the GitHub release lags the installed version

Upstream bumps versionName in main before tagging the GitHub release, so
there is a recurring window where the installed app is newer than the
latest published universal APK. The hard version guard disabled the whole
sharing feature during that window (including for reviewers building this
branch at 1.7.5 while GitHub's latest is 1.7.4).

An older release is still a genuine, signed, checksum-verified universal
artifact, and Android already refuses downgrade installs on receivers, so:

- checkForUpdate now logs (instead of erroring) when the latest release is
  older than the installed app and proceeds normally.
- downloadUniversalApk no longer fails for an older-than-installed release.
- A cached artifact stays shareable regardless of the installed version.

The cached-artifact preference (never replace a newer cached APK with an
older one) and all signature/checksum verification are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: Run APK download as foreground (dataSync) work

Long transfers — especially over Tor — can exceed WorkManager's
~10-minute background execution window, getting the worker stopped and
rescheduled repeatedly. Promote the download to foreground work with a
progress notification (cancel action included) so it can run to
completion.

- setForeground() with FOREGROUND_SERVICE_TYPE_DATA_SYNC; the manifest
  already holds the FOREGROUND_SERVICE_DATA_SYNC permission, and the
  WorkManager SystemForegroundService is merged with type dataSync.
- If Android 12+ rejects the promotion (app backgrounded), the worker
  logs and continues as regular background work, relying on Range-resume.
- Notification updates are throttled to 5% steps and degrade gracefully
  without POST_NOTIFICATIONS.

Addresses the Codex review finding on ApkDownloadWorker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Move temp APK into place instead of copying it

replaceFileSafely copied the source into a .new candidate before the
atomic move, doubling peak disk usage: with free space between 1.5x and
2x the APK size, the download completed and then promotion failed on the
copy, retrying against the same full temp file.

Source and target always live in the same cache directory, so a direct
ATOMIC_MOVE (rename) needs no extra space and keeps the same guarantee:
it either fully succeeds or leaves both files intact. The existing 1.5x
margin in checkDiskSpace is now genuinely sufficient.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: Base the disk space check on remaining bytes when resuming

The check ran before resume state was read and always demanded 1.5x the
full APK size. Bytes already sitting in download_temp.apk have already
consumed storage, so on a low-storage device an interrupted download
could fail every resume with "Insufficient storage" even when only a
small tail was left to fetch.

Read the resume state first and check space for the remaining bytes
only. A fresh download still checks the full size, and a complete temp
file needs no extra space since promotion is a rename.

Addresses the Codex review finding on UniversalApkManager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: cancel APK downloads promptly

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2026-07-27 02:45:07 +02:00
Moe Hamade
61588db474
chore(deps): upgrade to AGP 9.3.1, Gradle 9.6.1, Kotlin 2.4.10, SDK 37 (#750)
* chore(deps): upgrade to AGP 9.3.1, Gradle 9.6.1, Kotlin 2.4.10, SDK 37

Bring the toolchain and every dependency to latest stable. No app source
changes were required.

Toolchain:
- AGP 8.10.1 -> 9.3.1, Gradle 8.13 -> 9.6.1, Kotlin 2.2.0 -> 2.4.10
- compileSdk 35 -> 37, targetSdk 35 -> 37 (Android 17, stable)
- Java 8 -> 11

AGP 9 migration (built-in Kotlin):
- Drop org.jetbrains.kotlin.android; AGP 9 provides Kotlin natively and the
  plugin is incompatible with the new DSL
- Migrate kotlinOptions.jvmTarget to kotlin.compilerOptions (the String
  setter is a hard error in Kotlin 2.4)
- Drop android.enableJetifier (deprecated, removed in AGP 10, no support
  library deps remain)

Libraries:
- Compose BOM 2025.06.01 -> 2026.06.01, activity-compose 1.10.1 -> 1.13.0
- core-ktx 1.16.0 -> 1.19.0, lifecycle 2.9.1 -> 2.11.0 (unified with
  lifecycle-process, which had drifted to 2.8.7)
- okhttp 4.12.0 -> 5.4.0, coroutines 1.10.2 -> 1.11.0, gson 2.13.1 -> 2.14.0
- BouncyCastle 1.70 -> 1.85, switching bcprov-jdk15on -> bcprov-jdk18on
  (jdk15on is abandoned; same org.bouncycastle packages)
- Tink 1.10.0 -> 1.23.0, CameraX 1.5.2 -> 1.6.1, gms-location 21.3.0 -> 21.4.0
- security-crypto 1.1.0-beta01 -> 1.1.0, navigation-compose 2.9.1 -> 2.9.8
- exifinterface 1.3.7 -> 1.4.2, moved from a hardcoded coordinate into the
  version catalog
- Tests: espresso 3.6.1 -> 3.7.0, test-ext 1.2.1 -> 1.3.0, mockito-kotlin
  4.1.0 -> 6.3.0; mockito-inline (deprecated) -> mockito-core 5.23.0;
  coroutines-test 1.6 -> 1.11.0, now sharing the coroutines version ref
  instead of drifting

Robolectric stays pinned at 4.15: 4.16+ breaks EncryptionServiceTest with
"AndroidKeyStore not found". Bisected away from security-crypto and shown not
to be SDK-level related. Unpinning needs an EncryptionService refactor, which
is deliberately left to a follow-up PR.

targetSdk behaviour changes for API 36 and 37 were audited against the source:
edge-to-edge and predictive back are already handled, ACCESS_LOCAL_NETWORK is
not needed (loopback only, for Arti's SOCKS proxy), the reflection in
ChatViewModel touches instance rather than static final fields, and there is
no RFCOMM or scheduleAtFixedRate usage.

Verified: compileDebugKotlin, testDebugUnitTest (96 tests, 0 failures),
bundleRelease with R8, gradlew help, and build --dry-run. The 6 R8 "cannot
parse kotlin metadata" warnings present under AGP 8.13.2 are gone under 9.3.1.

Not verified on hardware. BLE mesh, foreground services, Nostr relay
websockets, Tor, and the Noise handshake still need a device smoke test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: declare ACCESS_LOCAL_NETWORK for Wi-Fi Aware on Android 17

Android 17 (API 37) makes local network protection mandatory for apps
targeting it. WifiAwareMeshService reaches peers over link-local IPv6 TCP
sockets (connectAwareClientSocket), which may be gated by the new
ACCESS_LOCAL_NETWORK runtime permission once targetSdk is raised to 37.

The official local network permission documentation frames the feature as
LAN access and does not explicitly state whether Wi-Fi Aware peer-to-peer
networks are in scope, so this is defensive rather than confirmed-necessary.
The sockets are bound to a dedicated Aware Network obtained via
requestNetwork, not the user's subnet.

Declaring it costs nothing: ACCESS_LOCAL_NETWORK shares the NEARBY_DEVICES
group with NEARBY_WIFI_DEVICES, so users who have already granted the latter
are not prompted again. The runtime request is gated on SDK_INT >= 37 so
older devices are unaffected.

Raised by automated review on #750.

Verified: compileDebugKotlin, testDebugUnitTest (124 tests, 0 failures),
bundleRelease, and ACCESS_LOCAL_NETWORK present in the merged manifest.
Not verified on an Android 17 device.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: correct ACCESS_LOCAL_NETWORK permission-group claim

Device testing on Android 17 (API 37) disproved the earlier claim that
ACCESS_LOCAL_NETWORK is effectively free because it shares the NEARBY_DEVICES
group with NEARBY_WIFI_DEVICES.

Granting NEARBY_WIFI_DEVICES alone leaves ACCESS_LOCAL_NETWORK denied:

  pm grant ... NEARBY_WIFI_DEVICES
  -> NEARBY_WIFI_DEVICES:  granted=true
  -> ACCESS_LOCAL_NETWORK: granted=false

The two are tracked and granted independently, so ACCESS_LOCAL_NETWORK has to
be requested explicitly. That is exactly what the wifiAwarePermissions() list
already does, so no behavioural change is needed — only the comments were
wrong. Whether the runtime dialog bundles the two into a single prompt remains
unverified, since enabling Wi-Fi Aware from Debug Settings after onboarding
never triggers a permission request at all (pre-existing, unrelated to this
branch).

Comment-only change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: request Wi-Fi Aware permissions when enabling it from Debug Settings

Enabling Wi-Fi Aware from the Debug Settings sheet never requested the
permissions it needs. The permission flow is reachable only through
PermissionManager.getRequiredPermissions(), which gates the Wi-Fi Aware entries
behind shouldRequireWifiAwarePermission() — and that returns false unless the
debug toggle is already on. Since the toggle defaults to off, onboarding never
asks, and flipping it later starts WifiAwareController directly, which only
checks the permission and bails.

The result was a silent dead end: Wi-Fi Aware could never start, and the
controller logged "Missing NEARBY_WIFI_DEVICES permission" on a 5s retry loop
indefinitely. Reproduced on a Pixel 9a (Android 17) and a Samsung SM-A366E
(Android 16); both needed adb grants to get the transport running at all.

The toggle and the Start chip now request the permissions first and only enable
the transport once NEARBY_WIFI_DEVICES is granted. ACCESS_LOCAL_NETWORK is
treated as best-effort since it does not exist below API 37 — confirmed by
`pm grant` rejecting it as an unknown permission on the Android 16 device. The
list comes from PermissionManager.wifiAwarePermissions() so the API 37 gate has
a single definition.

Also corrects the permission-group comments now that both levels are verified
on Android 17: grants are tracked independently (granting NEARBY_WIFI_DEVICES
alone leaves ACCESS_LOCAL_NETWORK denied), but the two share the NEARBY_DEVICES
group so requesting them together produces a single "Nearby devices" prompt.

Verified on device: after a clean uninstall/reinstall, toggling Wi-Fi Aware
produced one prompt and left both permissions granted with the USER_SET flag.

Addresses the second automated review finding on #750.

Verified: compileDebugKotlin, testDebugUnitTest (124 tests, 0 failures).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: version-gate Wi-Fi Aware permissions, check live grant state

Two issues from automated review of ee1ee3ad.

wifiAwarePermissions() returned NEARBY_WIFI_DEVICES unconditionally, but that
permission only exists from API 33 while minSdk is 26 and Wi-Fi Aware is
available from API 26. On an API 26-32 device the new enable path would request
an unknown permission, receive a denial, and never enable a transport that
needs no runtime permission there at all — a regression introduced by the
previous commit. Both entries are now version-gated.

The result callback also inferred the Nearby grant from the result map, which
omits permissions that were already held and so filtered out before launching.
It now reads the live permission state instead.

A denied ACCESS_LOCAL_NETWORK still does not block enabling: the controller
starts fine without it (verified on Android 17), and its necessity for
link-local sockets remains unproven, so a denial should not disable a transport
that otherwise works.

Also trims the comments added in the last two commits down to the density of
the surrounding code.

Verified: compileDebugKotlin, testDebugUnitTest (124 tests, 0 failures).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 23:34:08 +02:00
jack
84b24e347f
Bind Noise sessions to claimed peer identities (#730)
* Bind Noise sessions to claimed peer identities

* Make Wi-Fi peer rebinding atomic

* Migrate private media without silent downgrades (#728)

* Migrate private media without silent downgrades

* Accept prerelease private media payloads

* Authenticate private media capability per Noise session

* updates

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: jack <jack@deck.local>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>

* Authenticate BLE links before peer binding (#749)

* Authenticate BLE links before peer binding

* Fix BLE link authentication races

---------

Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>

* Use canonical Maven repository for Robolectric

---------

Co-authored-by: jack <jack@deck.local>
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
Co-authored-by: a1denvalu3 <43107113+a1denvalu3@users.noreply.github.com>
2026-07-26 23:29:57 +02:00
callebtc
b7f0b33d3a
bump to 1.7.5 (#723) 2026-06-25 22:48:26 +02:00
callebtc
ffe62bf1fd
bump to 1.7.4 (#715)
Co-authored-by: CC <cc@ggg.local>
2026-06-17 12:27:54 -05:00
callebtc
9e0a919cb8
bump version (#713)
Co-authored-by: CC <cc@ggg.local>
2026-06-16 12:49:36 -05:00
callebtc
be1a2ec914
update version (#688) 2026-03-30 10:14:32 +02:00
callebtc
390f264987
bump (#661) 2026-02-01 13:33:22 +01:00
callebtc
e3056d70c0
bump to 1.7.0 (#624) 2026-01-16 01:13:33 +07:00
Moe Hamade
5013b32ca9
feat: Introduce Gradle property to control APK splits (#560)
* feat: Introduce Gradle property to control APK splits

This commit introduces a new Gradle project property, `buildSplitApks`, to conditionally enable or disable the generation of ABI-specific (arm64, x86_64) and universal APKs.

Key changes:
- In `app/build.gradle.kts`, the `splits.abi.isEnable` flag is now dynamically set based on the `buildSplitApks` property.
- APK splitting is disabled by default to support standard Android App Bundle (`bundleRelease`) builds.
- The release workflow (`release.yml`) is updated to pass `-PbuildSplitApks=true` when building release APKs for GitHub.
- The general Android build workflow (`android-build.yml`) is also modified to enable splits only for the `Release` variant, ensuring debug builds are not affected.

* chore: Simplify and automate APK split builds

This commit simplifies the build process by automatically enabling ABI splits for APKs (`assemble`) and disabling them for AABs (`bundle`).

This removes the need to manually pass the `-PbuildSplitApks=true` property. The build script now intelligently determines whether to create architecture-specific APKs based on the task being executed (e.g., `assembleRelease` vs. `bundleRelease`).

The GitHub Actions workflows (`release.yml`, `android-build.yml`) have been updated to remove this now-redundant property, streamlining the CI configuration.
2026-01-16 01:06:15 +07:00
callebtc
829fb52a04
Update arti to 1.9.0 and produce 32 bit builds (#585)
* x86

* update arti to 1.9.0
2026-01-14 14:58:26 +07:00
callebtc
5dc6369b8f
bump vc to 30 (#559) 2026-01-05 17:30:28 +07:00
Moe Hamade
68407e3b47
feat: Build and release per-architecture APKs (#550)
* feat: Build and release per-architecture APKs

This commit modifies the build process to generate separate APKs for different CPU architectures (arm64-v8a, x86_64) and a universal APK. This allows for smaller, optimized downloads for users and provides specific builds for platforms like Chromebooks.

Key changes:
- In `app/build.gradle.kts`, enables ABI splits to create `arm64-v8a`, `x86_64`, and `universal` APKs during the `assembleRelease` task.
- Updates the `release.yml` GitHub Actions workflow to rename and upload each of these APKs as distinct release assets.
- Removes the previous `arm64-v8a` only filter to allow for multi-architecture builds.

* feat: Allow manual triggering of Android CI workflow

This adds the `workflow_dispatch` event to the `android-build.yml` GitHub Actions workflow.

This change enables the Android CI pipeline to be run manually from the GitHub UI, in addition to the existing triggers for pushes and pull requests.
2026-01-05 17:28:53 +07:00
callebtc
eef831fe60
scan duration fix (#557) 2026-01-05 16:41:41 +07:00
callebtc
9733806610
bump to 29 (#553) 2026-01-05 11:39:13 +07:00
callebtc
eeaabf487f
bump versioncode to 28 (#551) 2026-01-05 10:42:35 +07:00
yet300
c663e8ede0
QR and Verification feature (#529)
* Automated update of relay data - Sun Sep 21 06:21:05 UTC 2025

* Automated update of relay data - Sun Sep 28 06:20:40 UTC 2025

* refactor: new close button like ios(but not liquid glass)

* Automated update of relay data - Sun Oct  5 06:20:09 UTC 2025

* Automated update of relay data - Sun Oct 12 06:20:12 UTC 2025

* Automated update of relay data - Sun Oct 19 06:21:51 UTC 2025

* Automated update of relay data - Sun Oct 26 06:21:31 UTC 2025

* Automated update of relay data - Sun Nov  2 06:22:16 UTC 2025

* Automated update of relay data - Sun Nov  9 06:21:43 UTC 2025

* Automated update of relay data - Sun Nov 16 06:22:37 UTC 2025

* Automated update of relay data - Sun Nov 23 06:22:51 UTC 2025

* Automated update of relay data - Sun Nov 30 06:24:08 UTC 2025

* Automated update of relay data - Sun Dec  7 06:22:59 UTC 2025

* Automated update of relay data - Sun Dec 14 06:24:33 UTC 2025

* Automated update of relay data - Sun Dec 21 06:24:49 UTC 2025

* Automated update of relay data - Sun Dec 28 06:25:38 UTC 2025

* feat: Add ZXing dependency for QR code scanning

* feat: Request camera permission for QR verification

* Add QR verification payloads and mesh wiring

* Wire verification state, system messages, and notifications

* Add verification sheets and UI affordances

* Show verified badges in sidebar and add strings

* Persist fingerprint caches for offline verification

* Handle bitchat://verify deep links

* feat: Replace zxing-android-embedded with ML Kit and CameraX

* Refactor(Verification): Replace zxing with MLKit for QR scanning

* Replace `AndroidView` with `CameraXViewfinder` for camera preview

* Refactor QR verification: Extract VerificationHandler and fix concurrency issues

* Extract and translate strings for QR verification feature

* Fix build errors: Escape ampersands in strings and restore missing methods in ChatViewModel

* return to main

* return to main 2

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2026-01-04 16:29:07 +07:00
callebtc
8767cfdea3
bump version 1.6.0 (#524) 2025-12-13 16:46:09 +07:00
Moe Hamade
b2febcee88
feat: add product flavors and TorProvider abstraction (#508)
* feat: add product flavors and TorProvider abstraction

Introduces build flavors to separate Tor functionality from the standard build, reducing APK size for users who don't need Tor.

- Creates `standard` and `tor` product flavors.
- The `standard` flavor is the default, lightweight build.
- The `tor` flavor includes the Arti (Tor) dependency and is identified by the `.tor` application ID suffix.
- Adds a `TorProvider` interface and a `TorProviderFactory` to abstract Tor implementation details between flavors.

Prepares architecture for optional Tor support to reduce APK size
from 142MB to ~4-5MB for standard builds

Related to #454

* Refactor: implement StandardTorProvider and RealTorProvider

This commit refactors the Tor integration by introducing a `TorProvider` interface and creating separate implementations for 'tor' and 'standard' product flavors.

- The original `TorManager` singleton has been moved into `RealTorProvider` for the 'tor' flavor.
- A no-op `StandardTorProvider` is introduced for the 'standard' flavor, which reports Tor as unavailable.
- A `TorProviderFactory` is used to create the appropriate provider at runtime based on the build variant.

* refactor: migrate to TorProvider abstraction

Replaced direct calls to the static `TorManager` with an instance obtained from `TorProviderFactory`.

This change allows for different Tor implementations based on build flavors, improving modularity and abstracting the Tor provider logic.

Updated `BitchatApplication`, `ChatHeader`, `OkHttpProvider`, and `AboutSheet` to use the new factory pattern for accessing Tor functionalities.

* build: add flavor-specific ProGuard rules and CI/CD

 - Split ProGuard rules: base, standard-specific, tor-specific
  - Move Arti/Guardian Project rules to proguard-tor.pro
  - Update CI/CD workflow to build both flavors
  - Add separate artifact uploads for each flavor
  - Add descriptive release notes template

  CI now builds both standard (~4-5MB) and tor (~140MB) APKs."

  resolves #454

* refactor: centralize network reset logic

Extracts the repeated network connection reset logic into a new private function `resetNetworkConnections()`.

This change also replaces direct `_statusFlow.value = ...` assignments with the safer `_statusFlow.update { ... }` function to prevent race conditions.

* ci: run separate build steps for flavors

* feat: disable Tor toggle if not available in build

* ci: parallelize builds and add conditional tor lint

Optimizes CI workflow:
- Parallel matrix builds (4 runners instead of sequential)
- Conditional tor lint only when app/src/tor/ changes in PRs
- Merged test+lint jobs to reduce setup overhead

Reduces CI time by ~50% (8-11 min vs 18-26 min)

* refactor: Unify Tor implementation and remove build flavors

This commit refactors the Tor integration by removing the `standard` and `tor` product flavors in favor of a single, unified build that always includes a custom-built Arti (Tor) library.

Key changes include:
*   **Removed Build Flavors:** Deleted the `standard` and `tor` product flavors from `build.gradle.kts`, simplifying the build process and CI configuration.
*   **Unified Tor Manager:** Replaced the `TorProvider` interface and flavor-specific implementations (`StandardTorProvider`, `RealTorProvider`) with a new singleton, `ArtiTorManager`. This class now manages the Arti lifecycle for all builds.
*   **Custom Arti Wrapper:** Introduced a new `ArtiProxy` class to provide a compatible API wrapper around the custom-built native Arti library (`libarti_android.so`). This replaces the dependency on the external `arti-mobile-ex` library.
*   **Updated Proguard:** Consolidated and updated Proguard rules into the main `proguard-rules.pro` file to keep the necessary `ArtiTorManager` and native library classes.
*   **CI/CD Simplification:** Updated GitHub Actions workflows (`release.yml`, `android-build.yml`) to build and release a single APK instead of separate ones for each flavor.

* build: Configure ABI filters for debug and release builds

For debug builds, include `x86_64` to support emulators.

For release builds, only include `arm64-v8a` to minimize the final APK size.

* feat: Ignore jniLibs directory

This change adds the `app/src/main/jniLibs/` directory to the `.gitignore` file to prevent native libraries from being committed to the repository.

* feat: Refine .gitignore for Arti build artifacts

Improves the `.gitignore` file by:
- Ignoring all `build/` directories except for `tools/arti-build/`.
- Adding specific ignores for Arti build artifacts, including the cloned source repository and the Rust build cache directory.

* feat: Update arti android native library

* feat: add build script and JNI wrapper for Arti

Adds a comprehensive build system for creating custom Arti (Tor in Rust) shared libraries for Android. This replaces the dependency on external, outdated AARs with a fully transparent and reproducible build process.

Key changes:
- Introduces `build-arti.sh`, a script to clone the official Arti repository, apply a JNI wrapper, and build `.so` files for Android.
- Adds `ARTI_VERSION` to pin the build to a specific Arti release (v1.7.0).
- Implements a new Rust JNI wrapper (`src/lib.rs`) that exposes core functions like `initialize`, `startSocksProxy`, and `stop` to the Android app.
- Includes a `Cargo.toml` with release profile optimizations for size (`lto`, `strip`, `opt-level = "z"`).
- Provides detailed documentation in `README.md` explaining the build process, prerequisites, and architecture.

* build script for mac

* consolidate both scripts

* improve script

---------

Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2025-12-12 23:27:52 +07:00
callebtc
f633509848
bump to 1.5.1 (#488) 2025-10-19 12:43:55 +02:00
callebtc
2869a2b192
actually 1.5.0 (#485) 2025-10-18 15:03:45 +02:00
callebtc
20342351a5
Camera take picture (#484)
* camera capture

* icon change

* image preview great

* remove string
2025-10-18 15:03:32 +02:00
callebtc
e8862d5128
versioncode 24 (#479) 2025-10-16 14:26:13 +02:00
callebtc
4a6fe922f3
bump version 1.4.0 (#470) 2025-10-14 13:02:12 +02:00
callebtc
7061a96cce
bump to 1.3.1 (#432) 2025-09-15 12:43:58 +02:00
callebtc
382d29e03f
bump versioncode (#419) 2025-09-14 05:12:42 +02:00
callebtc
deba156711
bumo to 1.3.0 (#416) 2025-09-14 04:26:04 +02:00
callebtc
9b8f98ec7c
bump version 1.2.3 (#384) 2025-09-06 14:49:00 +02:00
callebtc
202c8edc53
bump version (#354) 2025-08-30 13:47:22 +02:00
callebtc
686e2e78ec
Bundle tor (#339)
* tor started

* tor works

* tor code

* improve manager

* works

* move tor icon

* werks

* arti works

* arti works

* arti works with reconnect

* delay fix

* refactor
2025-08-29 14:37:35 +02:00
callebtc
63d6649ab4
bump to 1.2.1 (#332) 2025-08-29 00:50:53 +02:00
callebtc
941be1b98f bump to 1.2.0 2025-08-25 10:20:18 +02:00
callebtc
e92266c025
bump version (#293) 2025-08-23 11:52:06 +02:00
callebtc
fa2e3fa0b2
bump version code (#283) 2025-08-22 22:36:23 +02:00
callebtc
d3e2dce27b
bump version (#277) 2025-08-22 19:10:12 +02:00
callebtc
7243d841a3
Nostr geohash (#276)
* first nostr build

* add test file

* internet access

* fix relay manager

* fix serialization

* demo service - remove later

* fix nostr

* event dedupe

* dedupe

* ui wip

* can send messages

* subscription works

* works

* favs

* works

* delete chat on change

* fix mentions

* remove autojoin channels

* styling

* adjust colors

* ui changes

* live updates working

* use local timestamp

* message history in background

* robust

* fixes

* nicknames refresh optimization

* nostr service

* refactor nostr

* style

* geohash works

* centralize colors

* refactoring

* disable DMs for now: click on peer nickname doesnt open chat list in geohash mode

* use local time

* less logging

* robustness

* scroll nickname

* adjust some text
2025-08-22 19:09:18 +02:00
callebtc
848cffee07
bump (#274) 2025-08-22 08:31:35 +02:00
callebtc
98706acfa5
change app ID to com.bitchat.droid (#270) 2025-08-21 00:08:43 +02:00
callebtc
b4f080ff32
bump to 0.9 (#269) 2025-08-20 23:54:10 +02:00
callebtc
9795e2ce8a
Changes bitchat protocol (#265)
* create payload

* compiles and can send messages

* identityannouncement

* DMs work, read receipt not sent yet

* works

* delete old code

* simplify

* working

* fragment wip

* compression wip

* use zlib compression

* clean

* nice

* mesh

* remove comments
2025-08-18 21:16:27 +02:00
callebtc
b34ef896c7
0.8.1 (#242) 2025-08-07 12:14:04 +03:00
Moritz Warning
1d1a91108e
f-droid: add metadata folder (#134)
* add fastlane metadata for f-droid and gplay

* remove google signing block

Needed to be removed for F-Droid.
See https://gitlab.com/fdroid/admin/-/issues/367
2025-08-06 01:08:16 +02:00
callebtc
9025aae3d1
bump to 0.8.1 (#206) 2025-07-31 06:53:40 +02:00
callebtc
34d00839b2
bump to 0.8 (#188) 2025-07-25 20:04:43 +02:00
callebtc
93de0f2037 bump to 0.7.2 2025-07-20 11:10:04 +02:00
callebtc
d8d834b713 bump to 0.7.1 2025-07-19 09:20:57 +02:00
callebtc
5da4cd27ec bump to 0.7 2025-07-14 00:29:01 +02:00
callebtc
0d54d60dd5
Merge pull request #60 from prudhvir3ddy/prudhvir3ddy/upgrade_deps
Upgrade compileSDK, kotlin, AGP, compose, core libs
2025-07-13 17:09:00 +02:00