New MeshPeerListSheet as Ios like (#498)

* 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>
This commit is contained in:
yet300
2026-01-12 15:10:07 +07:00
committed by GitHub
co-authored by GitHub Action
parent c7e20a9590
commit e40fd106d7
6 changed files with 1214 additions and 958 deletions
@@ -157,7 +157,6 @@ class ChatViewModel(
val passwordProtectedChannels: StateFlow<Set<String>> = state.passwordProtectedChannels
val showPasswordPrompt: StateFlow<Boolean> = state.showPasswordPrompt
val passwordPromptChannel: StateFlow<String?> = state.passwordPromptChannel
val showSidebar: StateFlow<Boolean> = state.showSidebar
val hasUnreadChannels = state.hasUnreadChannels
val hasUnreadPrivateMessages = state.hasUnreadPrivateMessages
val showCommandSuggestions: StateFlow<Boolean> = state.showCommandSuggestions
@@ -171,6 +170,7 @@ class ChatViewModel(
val peerRSSI: StateFlow<Map<String, Int>> = state.peerRSSI
val peerDirect: StateFlow<Map<String, Boolean>> = state.peerDirect
val showAppInfo: StateFlow<Boolean> = state.showAppInfo
val showMeshPeerList: StateFlow<Boolean> = state.showMeshPeerList
val showVerificationSheet: StateFlow<Boolean> = state.showVerificationSheet
val showSecurityVerificationSheet: StateFlow<Boolean> = state.showSecurityVerificationSheet
val selectedLocationChannel: StateFlow<com.bitchat.android.geohash.ChannelID?> = state.selectedLocationChannel
@@ -452,11 +452,6 @@ class ChatViewModel(
}
startPrivateChat(openPeer)
// If sidebar visible, hide it to focus on the private chat
if (state.getShowSidebarValue()) {
state.setShowSidebar(false)
}
} catch (e: Exception) {
Log.w(TAG, "openLatestUnreadPrivateChat failed: ${e.message}")
}
@@ -783,7 +778,7 @@ class ChatViewModel(
state.setShowVerificationSheet(false)
if (reopenSidebarAfterVerification) {
reopenSidebarAfterVerification = false
state.setShowSidebar(true)
state.setShowMeshPeerList(true)
}
}
@@ -795,6 +790,14 @@ class ChatViewModel(
state.setShowSecurityVerificationSheet(false)
}
fun showMeshPeerList() {
state.setShowMeshPeerList(true)
}
fun hideMeshPeerList() {
state.setShowMeshPeerList(false)
}
fun getPeerFingerprintForDisplay(peerID: String): String? {
return verificationHandler.getPeerFingerprintForDisplay(peerID)
}
@@ -1027,15 +1030,7 @@ class ChatViewModel(
fun hideAppInfo() {
state.setShowAppInfo(false)
}
fun showSidebar() {
state.setShowSidebar(true)
}
fun hideSidebar() {
state.setShowSidebar(false)
}
/**
* Handle Android back navigation
* Returns true if the back press was handled, false if it should be passed to the system
@@ -1047,11 +1042,6 @@ class ChatViewModel(
hideAppInfo()
true
}
// Close sidebar
state.getShowSidebarValue() -> {
hideSidebar()
true
}
// Close password dialog
state.getShowPasswordPromptValue() -> {
state.setShowPasswordPrompt(false)