Implements robust cleanup and timeout logic for location requests.
- SystemLocationProvider: Adds 30s timeout and listener tracking for legacy one-shot requests to prevent memory leaks on pre-Android 11 devices.
- FusedLocationProvider: Adds 30s duration to requests.
- LocationProvider: Adds cancel() method for full resource cleanup.
- LocationChannelManager: Ensures cancel() is called during cleanup.
Replaces manual updatePermissionState calls with a unified checkAndSyncPermission method. This ensures that _permissionState flow always reflects the actual system permission status whenever it is checked (e.g. in requestOneShotLocation), preventing desync issues when permissions are revoked at runtime.
* location manager improvements
* fix: resolve compilation errors and improve location state handling
- Fix missing imports and stray braces in LocationChannelManager
- Implement checkSystemLocationEnabled and BroadcastReceiver for location state
- Order class members for correct initialization
- Consolidate UI refresh logic in LocationChannelsSheet
* fix: guard against stale geocoding results on legacy devices
- Add isActive check after blocking Geocoder.getFromLocation call
- Prevent stale results from overwriting state after job cancellation
* 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
* Automated update of relay data - Sun Jan 4 06:26:28 UTC 2026
* Automated update of relay data - Sun Jan 11 06:26:19 UTC 2026
* feat: Show private chat in sheet from notification
* Refactor: Hoist private chat sheet state to ChatViewModel
* remove icon
* remove old bottom sheet
---------
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
* 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
* Automated update of relay data - Sun Jan 4 06:26:28 UTC 2026
* refactor: Extract CloseButton to core UI components
* feat: Add BitchatBottomSheet component
* refactor: Use BitchatBottomSheet component and minor ui change(CloseButton, colors)
* Refactor: Use BitchatBottomSheet in MeshPeerListSheet
---------
Co-authored-by: GitHub Action <action@github.com>
* 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
* Refactor: Redesign peer and channel list as a bottom sheet
Replaced the right-hand sidebar with a Material 3 `ModalBottomSheet` for displaying mesh peers and channels. This modernizes the UI and improves usability.
- Renamed `SidebarComponents.kt` to `MeshPeerListSheet.kt`.
- Replaced the custom sidebar implementation with `ModalBottomSheet`.
- Added a floating top bar to the sheet that appears on scroll, displaying the title and a close button.
- Updated the row layouts for both channels and peers to use `Surface` for better visual grouping and selection state handling.
- Added a checkmark icon to indicate the currently selected channel or private chat peer.
- Improved styling for section headers, unread badges, and empty-state text.
- Removed the `SignalStrengthIndicator` as it was no longer used.
* Refactor: Remove sidebar state management from ViewModel
This commit removes the state management for the sidebar's visibility from `ChatViewModel` and `ChatState`.
The sidebar's visibility is now a purely UI-level concern and is no longer coupled with the ViewModel's logic. This change simplifies the ViewModel by removing unnecessary LiveData and related methods (`showSidebar`, `hideSidebar`). The back navigation handler has also been updated to remove the case for closing the sidebar.
* Refactor: Replace Sidebar with MeshPeerList Bottom Sheet
* feat: Add nested private chat sheet
* Feat: Enhance UI/UX of LocationNotesSheet
This commit refactors the `LocationNotesSheet` to more closely align with its iOS counterpart, improving both its appearance and user experience.
The layout has been updated to use a `Box` with aligned elements instead of a single `Column`, allowing for a floating input section at the bottom and a floating close button at the top right.
**Key Changes:**
- **Floating Top Bar and Input:**
- The main content is now a `LazyColumn` that scrolls underneath a new floating top bar and a floating input section at the bottom.
- The top bar's background animates from transparent to semi-opaque as the user scrolls, providing a "blur" effect.
- **iOS-Style Close Button:**
- The close button is moved from the header row to the top-right corner of the sheet, where it remains fixed.
- **Structural Refinements:**
- Replaced the main `Column` with a `Box` to manage the layout of the scrollable content, top bar, and input section.
- Removed the `onClose` parameter from `LocationNotesHeader` as the close button is now managed separately.
- Added `statusBarsPadding` to the `ModalBottomSheet` to prevent content from rendering under the system status bar.
- Adjusted spacing and padding for better visual consistency.
* refactor: Use collectAsStateWithLifecycle
Migrates LiveData observation from `observeAsState` to `collectAsStateWithLifecycle` for improved lifecycle-aware state collection in `MeshPeerListSheet`.
This also includes the following related changes:
* Removes an unused `showSidebar` state flow from `ChatViewModel`.
* Replaces fully qualified `com.bitchat.android.ui.splitSuffix` calls with a direct `splitSuffix` call.
* Updates resource string access to use the `R` import.
* feat: Add verification status indicators
- Add peer verification status icons to the peer list.
- Add a button to the channel list to show the verification QR code.
- Remove the unused `SidebarComponents.kt` file.
* Refactor: Add state for mesh peer list visibility
* Refactor: Move mesh peer list state to ViewModel
* refactor: Move QR code icon from channel items to footer
The verification (QR code) icon is relocated from being repeated on each channel list item to a single, centralized position in the sheet's footer.
This icon is now only displayed when not in a location-based channel. The `onShowVerification` parameter has been removed from `ChannelListItem` as it's no longer needed there.
* feat: Show verified status for peers
---------
Co-authored-by: GitHub Action <action@github.com>
* 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
* Automated update of relay data - Sun Jan 4 06:26:28 UTC 2026
* fix bug(568): Improve scroll-to-bottom logic
Replaced the "smart scroll" mechanism with a simpler "follow" behavior. The message list now automatically scrolls to the latest message unless the user has scrolled up.
- A new `followIncomingMessages` state tracks whether to auto-scroll.
- Scrolling now uses `scrollToItem` instead of `animateScrollToItem` for immediate updates.
---------
Co-authored-by: GitHub Action <action@github.com>
* 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.
* try catch the foreground location service if not available
* ask for background permissions
* background permissions in onboarding
* small improvements
* 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>
Robolectric 4.9+ uses Conscrypt as the default security provider, which
requires native libraries that aren't available in the test environment.
Adding @ConscryptMode(Mode.OFF) disables Conscrypt and uses BouncyCastle
instead, which resolves the test failures.
This fixes the build failures in FileTransferTest where all 9 tests were
failing with UnsatisfiedLinkError when Conscrypt tried to load native
libraries.
Fixes#542
* wifi aware wip
* wifi aware wip
* starting to work
* werk
* dms work
* wip
* fix(wifi-aware): use bindSocket and scoped IPv6 instead of bindProcessToNetwork
* Merge branch 'upstream/main' into fix/wifi-aware-socket-binding
* Fix Wi-Fi Aware connectivity and UI integration post-merge
- Replace bindProcessToNetwork with bindSocket for VPN compatibility.
- Implement Scoped IPv6 address resolution (aware0) for mesh routing.
- Bridge Wi-Fi Aware incoming messages to AppStateStore for UI visibility.
- Fix syntax errors and variable name conflicts in Debug UI.
* Enhance Wi-Fi Aware robustness and debug UI display
- Clean up transport resources (sockets, server sockets, network callbacks) immediately on peer disconnection.
- Implement resolveScopedAddress to show scoped IPv6 (e.g., %aware0) in Debug UI.
- Fix Map type mismatch warning in ChatViewModel bridge.
- Filter self-ID from peer cleanup tables to prevent recursive self-removal.
* Share GossipSyncManager across transports to prevent redundant message synchronization
- Registered BluetoothMeshService's GossipSyncManager as a singleton in MeshServiceHolder.
- Modified WifiAwareMeshService to use the shared GossipSyncManager if available.
- Added background cleanup for peer mappings on socket disconnection.
- Fixed Kotlin type mismatch during nickname map merging.
* Restore VPN acquisition logic and improve peer cleanup
- Revert removal of NET_CAPABILITY_NOT_VPN to allow hardware handle acquisition while VPN is active.
- Refactor handlePeerDisconnection to more reliably cleanup initial and routed IDs.
- Switch cleanup logging to debug level to reduce log noise.
---------
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
Co-authored-by: aidenvalue <>
* persistence step 1
* fix build
* messages in the background work, notifications not yet
* app state store
* DM icon shows up
* notification launches when app is closed!
* keep ui updated
* lifecycle fixes
* extensive logging, maybe revert later
* send nickname in announcement
* quit in notification
* setting in about sheet
* fix quit bitchat
* lifecycle fixes
* power mode based on background state
* stats for both direciotns
* fix graph persistence
* better counting
* count per device
* only compute when debug sheet is open? untested
* fix read receipts
* fix read receipts fully
* fix unread badge if messages have been read in focus
* foreground promotion fix
* fix app kill in notification
* adjust to new tor
* nice
* about sheet design
* 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
* Chore: Remove unused `lifecycle-livedata-ktx` dependency
This commit removes the `androidx.lifecycle:lifecycle-livedata-ktx` library from the project's dependencies.
The `[libraries]` and `[bundles]` sections in `gradle/libs.versions.toml` have been updated to reflect this removal, as the dependency is no longer in use.
* Refactor: Remove unused `runtime-livedata` dependency
* Refactor: Migrate `LocationChannelManager` and `GeohashBookmarksStore` to StateFlow
This commit refactors `LocationChannelManager` and `GeohashBookmarksStore` to use `StateFlow` instead of `LiveData` for managing and exposing their state. This change aligns with modern Android development practices and improves testability.
**Key Changes:**
- **`LocationChannelManager`**:
- All `MutableLiveData` properties (`permissionState`, `availableChannels`, `selectedChannel`, etc.) have been replaced with `MutableStateFlow`.
- Consumers now access these properties as `StateFlow`.
- State updates have been changed from `postValue()` to direct `.value` assignments, simplifying thread management within the manager which already uses a dedicated coroutine scope.
- **`GeohashBookmarksStore`**:
- `bookmarks` and `bookmarkNames` are now exposed as `StateFlow` instead of `LiveData`.
- State updates similarly use `.value` assignment.
- **Nullability**:
- The non-nullable nature of `StateFlow`'s value reduces the need for null-checks in both the manager classes and their consumers, leading to safer code.
* Refactor: Migrate from LiveData to StateFlow for Nostr components
This commit replaces `LiveData` with `StateFlow` across core Nostr-related classes to align with modern Android architecture and improve state management. This change affects `NostrClient`, `NostrRelayManager`, `LocationNotesManager`, and `GeohashRepository`.
**Key Changes:**
- **`NostrClient`**:
- `isInitialized` and `currentNpub` are now `StateFlow` instead of `LiveData`.
- `relayConnectionStatus` and `relayInfo` now return `StateFlow` from `NostrRelayManager`.
- **`NostrRelayManager`**:
- Public properties `relays` and `isConnected` are migrated from `MutableLiveData` to `MutableStateFlow`.
- Updates are now pushed using `.value` instead of `.postValue()`.
- **`LocationNotesManager`**:
- All public `LiveData` properties (`notes`, `geohash`, `initialLoadComplete`, `state`, `errorMessage`) are converted to `StateFlow`.
- The class documentation is updated to reflect the use of `StateFlow`.
- **`GeohashRepository`**:
- Methods `updateGeohashPeople` and `updateReactiveParticipantCounts` now call `set...` methods on the `state` object instead of `post...`, reflecting the removal of `LiveData` from the underlying state management.
* Refactor: Migrate ChatState from LiveData to StateFlow
This commit refactors the `ChatState`, `ChatViewModel`, and `GeohashViewModel` to use `StateFlow` instead of `LiveData` for managing and exposing UI state. This migration improves state management by leveraging modern coroutine-based flows.
**Key Changes:**
- **`ChatState.kt`**:
- Replaced all `MutableLiveData` instances with `MutableStateFlow`.
- Exposed state properties as `StateFlow` instead of `LiveData`.
- Removed `MediatorLiveData` for computed properties (`hasUnreadChannels`, `hasUnreadPrivateMessages`) and replaced them with `Flow.combine` to create derivative `StateFlows`.
- Simplified non-nullable `getters` to directly return the `.value` of the `StateFlows`.
- Removed `postValue` helpers that are no longer necessary.
- **`ChatViewModel.kt`**:
- Updated all state properties to be `StateFlow`, reflecting the changes in `ChatState`.
- **`GeohashViewModel.kt`**:
- Changed state properties (`geohashPeople`, `geohashParticipantCounts`, etc.) from `LiveData` to `StateFlow`.
- Replaced `observeForever` on `LiveData` from `LocationChannelManager` with `viewModelScope.launch` blocks that `.collect()` from the underlying flows.
* Refactor: Migrate UI from LiveData to StateFlow
This commit replaces `LiveData.observeAsState()` with `StateFlow.collectAsState()` across various UI components. This change aligns the codebase with modern Android development practices, using Kotlin Flows for reactive UI state management.
No functional changes are intended. The primary goal is to remove the dependency on `androidx.lifecycle.livedata` from the composable functions.
**Affected Components:**
- `ChatScreen`
- `SidebarComponents`
- `ChatHeader`
- `LocationChannelsSheet`
- `LocationNotesSheet`
- `LocationNotesButton`
- `GeohashPeopleList`
- `LocationNotesSheetPresenter`
* Refactor: Use `collectAsStateWithLifecycle` for UI state collection
* Refactor: move CloseButton to core/ui/component
* Refactor: remove AI generated comments
* Refactor: fix combine to map and use WhileSubscribed
* Refactor: Pass CoroutineScope to ChatState
This commit refactors the `ChatState` class to accept a `CoroutineScope` in its constructor instead of creating its own.
**Key Changes:**
- **`ChatState.kt`**: The constructor now requires a `CoroutineScope`. This scope is used for the `stateIn` operators that convert `Flows` into `StateFlows` (`hasUnreadChannels`, `hasUnreadPrivateMessages`), ensuring they operate within the lifecycle of the provided scope.
- **`ChatViewModel.kt`**: The `viewModelScope` is now passed to the `ChatState` constructor during its instantiation. This ties the lifecycle of the state's coroutines directly to the `ViewModel`'s lifecycle.
* Test: Use `TestScope` for coroutines in `CommandProcessorTest`
This commit refactors `CommandProcessorTest` to use a `TestScope` and `UnconfinedTestDispatcher` for managing coroutines.
This ensures that coroutine-based operations within the test are executed in a controlled and predictable manner, improving test reliability. The `coroutineScope` for `CommandProcessor` and the `scope` for `ChatState` are now both configured to use this test-specific scope.
---------
Co-authored-by: GitHub Action <action@github.com>