Add APK sharing feature with local HTTP server and QR code#430
Merged
torlando-tech merged 8 commits intomainfrom Feb 16, 2026
Merged
Add APK sharing feature with local HTTP server and QR code#430torlando-tech merged 8 commits intomainfrom
torlando-tech merged 8 commits intomainfrom
Conversation
Contributor
Greptile SummaryAdds a local WiFi-based APK sharing feature that allows users to share the Columba app with nearby devices using a QR code. The implementation addresses all previously identified threading and race condition issues. Key improvements from review feedback:
Implementation highlights:
Architecture:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Settings
participant VM as ApkSharingViewModel
participant Server as ApkSharingServer
participant Client as Receiver Browser
User->>Settings: Tap "Share Columba APK"
Settings->>VM: Navigate to APK Sharing
VM->>VM: prepareApkFile()
VM->>VM: Copy APK to cache
VM->>Server: prepareStart()
Server-->>VM: Return CompletableDeferred
VM->>Server: launch start(apkFile)
Server->>Server: Bind to port 0 (random)
Server->>Server: Complete deferred with port
VM->>VM: await portDeferred
VM->>VM: Build download URL
VM->>User: Display QR code
Client->>Client: Scan QR code
Client->>Server: GET /
Server-->>Client: HTML download page
Client->>Server: GET /columba.apk
Server->>Server: handleClient() in thread pool
Server-->>Client: APK file with headers
User->>VM: Navigate away
VM->>Server: stop()
Server->>Server: Close socket & executor
VM->>VM: Delete cached APK
Last reviewed commit: 9a8fc19 |
app/src/main/java/com/lxmf/messenger/service/ApkSharingServer.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/lxmf/messenger/viewmodel/ApkSharingViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/lxmf/messenger/viewmodel/ApkSharingViewModel.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/lxmf/messenger/viewmodel/ApkSharingViewModel.kt
Outdated
Show resolved
Hide resolved
Owner
Author
|
@greptileai review |
Contributor
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
app/src/main/java/com/lxmf/messenger/service/ApkSharingServer.kt
Outdated
Show resolved
Hide resolved
4d14c63 to
9a8fc19
Compare
Owner
Author
Adds the ability to share the Columba APK directly from within the app. Two sharing methods are provided: 1. WiFi sharing (QR code): Starts a lightweight HTTP server on the device that serves the APK. A QR code with the download URL is displayed. The receiver scans it, opens the link in their browser, and downloads the APK. Both devices must be on the same WiFi network. 2. Android share sheet: Share the APK file via Bluetooth, Nearby Share, or any other installed sharing app. Works fully offline. New files: - ApkSharingServer.kt: Minimal HTTP server using ServerSocket - ApkSharingViewModel.kt: Manages server lifecycle and APK preparation - ApkSharingScreen.kt: Compose screen with QR code and share button - ShareColumbaCard.kt: Settings card for accessing the feature Closes #303 https://claude.ai/code/session_01Vhz4fTDD87Tq6RP5i9tcaR
- Handle clients concurrently: each accepted socket is now dispatched to its own thread with a 30s read timeout, so a slow client no longer blocks the accept loop from serving other receivers. - Replace racy delay(100) with CompletableDeferred<Int> (awaitPort): the ViewModel now suspends until the server socket is actually bound, eliminating false "failed to start" on slower devices. - Guard against leaking parallel servers: startServer() now checks serverJob?.isActive before launching, preventing duplicate server instances from rapid recomposition or double-navigation. - Fix all detekt violations in getLocalIpAddress: refactored into small helper functions (findWifiAddress, findAnyAddress, firstIpv4Address, isUsableInterface, isWifiInterface) to reduce cyclomatic complexity, return count, and loop jump statements. https://claude.ai/code/session_01Vhz4fTDD87Tq6RP5i9tcaR
…rver The previous awaitPort()/start() pattern had a race condition where the ViewModel would await on a stale CompletableDeferred that start() would then reassign. This commit introduces prepareStart() which returns the CompletableDeferred before launching, so both caller and server operate on the same instance. Also fixes detekt LoopWithTooManyJumpStatements in findWifiAddress(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unbounded Thread-per-client with a fixed pool of 4 threads to prevent thread exhaustion when many devices connect simultaneously. Add 13 unit tests covering server lifecycle, HTTP responses, and edge cases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use BuildConfig.VERSION_NAME in the APK filename (e.g. columba-0.8.0.apk) - Add downloadFileName property to ApkSharingServer for Content-Disposition - Fix test hangs: replace Thread.sleep with job.join(), remove withTimeout (incompatible with runTest virtual time when awaiting real IO threads) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds 29 new tests covering: - ApkSharingScreen (15 tests): all UI states (loading, error, server running), QR code display, instructions, alternative sharing section - ShareColumbaCard (6 tests): rendering, expansion, navigation callback - ApkSharingViewModel (8 tests): state management, error handling, createShareIntent, idempotent startServer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1d431c9 to
ccfccf5
Compare
… suite The test suite accumulated Robolectric/Compose resources across 5800+ tests in a single JVM, causing PagingData rendering failures in MessagingScreenTest. Setting forkEvery=100 restarts the JVM periodically. Also adds missing Dispatchers.resetMain() in ApkSharingViewModelTest to prevent test dispatcher pollution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Robolectric/Compose resource exhaustion causes PagingData rendering failures in MessagingScreenTest when 10+ Compose test classes share a JVM. The new APK sharing tests pushed the suite past this threshold. - Add test sharding via -PtestShard/-PtestShardTotal Gradle properties that distribute test classes across parallel CI jobs - Replace single kotlin-tests job with 4-shard matrix (fail-fast: false) - Reduce forkEvery from 100 to 10 classes: sharding concentrates Compose test classes (modulo distribution groups alphabetically adjacent UI tests), requiring more frequent JVM restarts - Remove Robolectric from ApkSharingServerTest (pure Java networking) and add proper coroutine teardown to prevent thread leaks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new APK sharing feature that allows users to share the Columba messenger app with nearby devices over WiFi. The implementation includes a lightweight HTTP server that serves the APK file and a UI screen with QR code generation for easy discovery.
Key Changes
ApkSharingServer: New service that runs a lightweight HTTP server on a random available port
/columba.apkwith proper HTTP headersApkSharingViewModel: Manages the server lifecycle and APK file preparation
ApkSharingScreen: New UI screen for the sharing feature
ShareColumbaCard: New settings card in the Settings screen
Navigation: Integrated into the main navigation graph
apk_sharingto the navigation controlleronNavigateToApkSharingcallbackFileProvider: Updated
file_paths.xmlto allow sharing APK files from cache directoryImplementation Details
Dispatchers.IOto avoid blocking the UIhttps://claude.ai/code/session_01Vhz4fTDD87Tq6RP5i9tcaR