From 51a06cf0b7c365bd5d5b97043ec58f9dc4f26504 Mon Sep 17 00:00:00 2001 From: yet300 <96379204+yet300@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:00:04 +0400 Subject: [PATCH] Refactored BottomSheetTopBar to BitchatSheetTopBar (#601) * 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: Add BitchatSheetTopBar component * Refactor: Use BitchatSheetTopBar in bottom sheets This commit refactors several bottom sheet components to use the new reusable `BitchatSheetTopBar` composable. This change provides a consistent look and feel for top bars across the following sheets: - DebugSettingsSheet - MeshPeerListSheet - LocationNotesSheet - LocationChannelsSheet - LocationNotesSheetPresenter (for the location unavailable state) The `BitchatSheetCenterTopBar` has been removed as its functionality is now covered by the more flexible `BitchatSheetTopBar`. * Refactor: Use BitchatSheetTopBar in MeshPeerListSheet --------- Co-authored-by: GitHub Action --- .../ui/component/sheet/BitchatSheetTopBar.kt | 86 +++++++ .../android/ui/LocationChannelsSheet.kt | 55 ++--- .../bitchat/android/ui/LocationNotesSheet.kt | 54 ++--- .../android/ui/LocationNotesSheetPresenter.kt | 70 +++--- .../bitchat/android/ui/MeshPeerListSheet.kt | 215 ++++++++---------- .../android/ui/debug/DebugSettingsSheet.kt | 73 ++++-- 6 files changed, 312 insertions(+), 241 deletions(-) create mode 100644 app/src/main/java/com/bitchat/android/core/ui/component/sheet/BitchatSheetTopBar.kt diff --git a/app/src/main/java/com/bitchat/android/core/ui/component/sheet/BitchatSheetTopBar.kt b/app/src/main/java/com/bitchat/android/core/ui/component/sheet/BitchatSheetTopBar.kt new file mode 100644 index 00000000..036cf01b --- /dev/null +++ b/app/src/main/java/com/bitchat/android/core/ui/component/sheet/BitchatSheetTopBar.kt @@ -0,0 +1,86 @@ +package com.bitchat.android.core.ui.component.sheet + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.bitchat.android.core.ui.component.button.CloseButton + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BitchatSheetTopBar( + onClose: () -> Unit, + modifier: Modifier = Modifier, + backgroundAlpha: Float = 0.98f, + title: @Composable () -> Unit, + navigationIcon: (@Composable () -> Unit)? = null, + actions: @Composable RowScope.() -> Unit = {} +) { + TopAppBar( + title = title, + navigationIcon = { navigationIcon?.invoke() }, + actions = { + actions() + CloseButton( + onClick = onClose, + modifier = Modifier.padding(horizontal = 16.dp) + ) + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background.copy(alpha = backgroundAlpha), + titleContentColor = MaterialTheme.colorScheme.onSurface, + navigationIconContentColor = MaterialTheme.colorScheme.onSurface, + actionIconContentColor = MaterialTheme.colorScheme.onSurface + ), + modifier = modifier + ) +} +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BitchatSheetCenterTopBar( + onClose: () -> Unit, + modifier: Modifier = Modifier, + backgroundAlpha: Float = 0.98f, + title: @Composable () -> Unit, + navigationIcon: (@Composable () -> Unit)? = null, + actions: @Composable RowScope.() -> Unit = {} +) { + CenterAlignedTopAppBar( + title = title, + navigationIcon = { navigationIcon?.invoke() }, + actions = { + actions() + CloseButton( + onClick = onClose, + modifier = Modifier.padding(horizontal = 16.dp) + ) + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background.copy(alpha = backgroundAlpha), + titleContentColor = MaterialTheme.colorScheme.onSurface, + navigationIconContentColor = MaterialTheme.colorScheme.onSurface, + actionIconContentColor = MaterialTheme.colorScheme.onSurface + ), + modifier = modifier + ) +} + +@Composable +fun BitchatSheetTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleMedium.copy( + fontWeight = FontWeight.Bold, + fontFamily = FontFamily.Monospace + ) + ) +} diff --git a/app/src/main/java/com/bitchat/android/ui/LocationChannelsSheet.kt b/app/src/main/java/com/bitchat/android/ui/LocationChannelsSheet.kt index c15e1788..583cb9e7 100644 --- a/app/src/main/java/com/bitchat/android/ui/LocationChannelsSheet.kt +++ b/app/src/main/java/com/bitchat/android/ui/LocationChannelsSheet.kt @@ -4,7 +4,6 @@ import android.content.Intent import android.net.Uri import android.provider.Settings import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -39,8 +38,9 @@ import com.bitchat.android.ui.theme.BASE_FONT_SIZE import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitchat.android.R -import com.bitchat.android.core.ui.component.button.CloseButton import com.bitchat.android.core.ui.component.sheet.BitchatBottomSheet +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle /** * Location Channels Sheet for selecting geohash-based location channels @@ -125,32 +125,18 @@ fun LocationChannelsSheet( LazyColumn( state = listState, modifier = Modifier.fillMaxSize(), - contentPadding = PaddingValues(top = 48.dp, bottom = 16.dp) + contentPadding = PaddingValues(top = 64.dp, bottom = 16.dp) ) { // Header Section item(key = "header") { - Column( + Text( + text = stringResource(R.string.location_channels_desc), + fontSize = 12.sp, + fontFamily = FontFamily.Monospace, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f), modifier = Modifier - .fillMaxWidth() .padding(horizontal = 24.dp) - .padding(bottom = 8.dp), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - Text( - text = stringResource(R.string.location_channels_title), - style = MaterialTheme.typography.headlineSmall, - fontFamily = FontFamily.Monospace, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - - Text( - text = stringResource(R.string.location_channels_desc), - fontSize = 12.sp, - fontFamily = FontFamily.Monospace, - color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f) - ) - } + ) } // Permission controls if services enabled @@ -515,20 +501,15 @@ fun LocationChannelsSheet( } // TopBar (animated) - Box( - modifier = Modifier - .align(Alignment.TopCenter) - .fillMaxWidth() - .height(56.dp) - .background(MaterialTheme.colorScheme.background.copy(alpha = topBarAlpha)) - ) { - CloseButton( - onClick = onDismiss, - modifier = modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 16.dp), - ) - } + BitchatSheetTopBar( + onClose = onDismiss, + modifier = modifier.align(Alignment.TopCenter), + title = { + BitchatSheetTitle( + text = stringResource(R.string.location_channels_title) + ) + } + ) } } } diff --git a/app/src/main/java/com/bitchat/android/ui/LocationNotesSheet.kt b/app/src/main/java/com/bitchat/android/ui/LocationNotesSheet.kt index 222876f8..c18cb095 100644 --- a/app/src/main/java/com/bitchat/android/ui/LocationNotesSheet.kt +++ b/app/src/main/java/com/bitchat/android/ui/LocationNotesSheet.kt @@ -26,8 +26,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.bitchat.android.core.ui.component.button.CloseButton import com.bitchat.android.core.ui.component.sheet.BitchatBottomSheet +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle import com.bitchat.android.geohash.GeohashChannelLevel import com.bitchat.android.geohash.LocationChannelManager import com.bitchat.android.nostr.LocationNotesManager @@ -112,8 +113,6 @@ fun LocationNotesSheet( ) { item(key = "notes_header") { LocationNotesHeader( - geohash = geohash, - count = count, locationName = displayLocationName, state = state, accentGreen = accentGreen, @@ -164,20 +163,20 @@ fun LocationNotesSheet( } // TopBar (animated) - Box( - modifier = Modifier - .align(Alignment.TopCenter) - .fillMaxWidth() - .height(64.dp) - .background(MaterialTheme.colorScheme.background.copy(alpha = topBarAlpha)) - ) { - CloseButton( - onClick = onDismiss, - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 16.dp) - ) - } + BitchatSheetTopBar( + onClose = onDismiss, + modifier = Modifier.align(Alignment.TopCenter), + title = { + BitchatSheetTitle( + text = pluralStringResource( + id = R.plurals.location_notes_title, + count = count, + geohash, + count + ) + ) + } + ) Box( modifier = Modifier @@ -214,12 +213,10 @@ fun LocationNotesSheet( /** * Header section - matches iOS headerSection exactly - * Shows: "#geohash • X notes", location name, description, and close button + * Shows: "#geohash • X notes", location name, description */ @Composable private fun LocationNotesHeader( - geohash: String, - count: Int, locationName: String?, state: LocationNotesManager.State, accentGreen: Color, @@ -228,22 +225,8 @@ private fun LocationNotesHeader( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp) - .padding(top = 16.dp, bottom = 12.dp) + .padding(bottom = 12.dp) ) { - // Localized title with ±1 and note count - Text( - text = pluralStringResource( - id = R.plurals.location_notes_title, - count = count, - geohash, - count - ), - fontFamily = FontFamily.Monospace, - fontSize = 18.sp, - color = MaterialTheme.colorScheme.onSurface - ) - Spacer(modifier = Modifier.height(8.dp)) - // Location name in green (building or block) locationName?.let { name -> if (name.isNotEmpty()) { @@ -471,6 +454,7 @@ private fun LocationNotesInputSection( Row( modifier = Modifier .fillMaxWidth() + .background(color = colorScheme.background) .padding(horizontal = 12.dp, vertical = 8.dp), // Match main chat padding verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) // Match main chat spacing diff --git a/app/src/main/java/com/bitchat/android/ui/LocationNotesSheetPresenter.kt b/app/src/main/java/com/bitchat/android/ui/LocationNotesSheetPresenter.kt index df86dbdc..9a8cf9e7 100644 --- a/app/src/main/java/com/bitchat/android/ui/LocationNotesSheetPresenter.kt +++ b/app/src/main/java/com/bitchat/android/ui/LocationNotesSheetPresenter.kt @@ -9,10 +9,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp +import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitchat.android.core.ui.component.sheet.BitchatBottomSheet +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle import com.bitchat.android.geohash.GeohashChannelLevel import com.bitchat.android.geohash.LocationChannelManager +import com.bitchat.android.R /** * Presenter component for LocationNotesSheet @@ -107,33 +111,47 @@ private fun LocationNotesErrorSheet( BitchatBottomSheet( onDismissRequest = onDismiss, ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - text = "Location Unavailable", - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.onSurface - ) - Spacer(modifier = Modifier.height(16.dp)) - Text( - text = "Location permission is required for notes", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Spacer(modifier = Modifier.height(24.dp)) - Button(onClick = { - // UNIFIED FIX: Enable location services first (user toggle) - locationManager.enableLocationServices() - // Then request location channels (which will also request permission if needed) - locationManager.enableLocationChannels() - locationManager.refreshChannels() - }) { - Text("Enable Location") + Box(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + .padding(top = 80.dp, bottom = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text( + text = "Location Unavailable", + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onSurface + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + text = "Location permission is required for notes", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(modifier = Modifier.height(24.dp)) + Button(onClick = { + // UNIFIED FIX: Enable location services first (user toggle) + locationManager.enableLocationServices() + // Then request location channels (which will also request permission if needed) + locationManager.enableLocationChannels() + locationManager.refreshChannels() + }) { + Text("Enable Location") + } } + + BitchatSheetTopBar( + onClose = onDismiss, + modifier = Modifier.align(Alignment.TopCenter), + title = { + BitchatSheetTitle( + text = stringResource(R.string.cd_location_notes).uppercase() + ) + } + ) } } } diff --git a/app/src/main/java/com/bitchat/android/ui/MeshPeerListSheet.kt b/app/src/main/java/com/bitchat/android/ui/MeshPeerListSheet.kt index 15c3426b..e5688a4e 100644 --- a/app/src/main/java/com/bitchat/android/ui/MeshPeerListSheet.kt +++ b/app/src/main/java/com/bitchat/android/ui/MeshPeerListSheet.kt @@ -27,6 +27,9 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bitchat.android.core.ui.component.button.CloseButton import com.bitchat.android.core.ui.component.sheet.BitchatBottomSheet +import com.bitchat.android.core.ui.component.sheet.BitchatSheetCenterTopBar +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar import com.bitchat.android.geohash.ChannelID import com.bitchat.android.ui.theme.BASE_FONT_SIZE import com.bitchat.android.nostr.GeohashAliasRegistry @@ -172,32 +175,12 @@ fun MeshPeerListSheet( } // TopBar (animated) - Box( - modifier = Modifier - .align(Alignment.TopCenter) - .fillMaxWidth() - .height(64.dp) - .background(colorScheme.background.copy(alpha = topBarAlpha)) - ) { - Text( - text = stringResource(id = R.string.your_network).uppercase(), - style = MaterialTheme.typography.titleMedium.copy( - fontWeight = FontWeight.Bold, - fontFamily = FontFamily.Monospace - ), - color = colorScheme.onSurface, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(horizontal = 24.dp) - ) - - Row( - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { + BitchatSheetTopBar( + title = { + BitchatSheetTitle(text = stringResource(id = R.string.your_network)) + }, + backgroundAlpha = topBarAlpha, + actions = { if (selectedLocationChannel !is ChannelID.Location) { IconButton( onClick = onShowVerification, @@ -211,12 +194,9 @@ fun MeshPeerListSheet( ) } } - - CloseButton( - onClick = onDismiss - ) - } - } + }, + onClose = onDismiss, + ) } } @@ -790,7 +770,7 @@ fun PrivateChatSheet( } val isNostrPeer = peerID.startsWith("nostr_") || peerID.startsWith("nostr:") - + // Compute display name and title text reactively val displayName = peerNicknames[peerID] ?: peerID.take(12) val titleText = remember(peerID, peerNicknames) { @@ -909,61 +889,57 @@ fun PrivateChatSheet( } // TopBar (fixed at top, iOS-style) - Box( - modifier = Modifier - .align(Alignment.TopCenter) - .fillMaxWidth() - .height(64.dp) - .background(colorScheme.background), - contentAlignment = Alignment.Center - ) { - // Back button - IconButton( - onClick = onDismiss, - modifier = Modifier - .align(Alignment.CenterStart) - .padding(start = 16.dp) - .size(32.dp) - ) { - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = stringResource(R.string.chat_back), - tint = colorScheme.onSurface - ) - } - - // Center content: connection status + name + encryption - Row( - modifier = Modifier.align(Alignment.Center), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(6.dp) - ) { - when { - isDirect -> { - Icon( - imageVector = Icons.Outlined.Bluetooth, - contentDescription = stringResource(R.string.cd_connected_peers), - modifier = Modifier.size(14.dp), - tint = colorScheme.onSurface.copy(alpha = 0.6f) - ) - } - isConnected -> { - Icon( - imageVector = Icons.Filled.Route, - contentDescription = stringResource(R.string.cd_ready_for_handshake), - modifier = Modifier.size(14.dp), - tint = colorScheme.onSurface.copy(alpha = 0.6f) - ) - } - isNostrPeer -> { - Icon( - imageVector = Icons.Filled.Public, - contentDescription = stringResource(R.string.cd_nostr_reachable), - modifier = Modifier.size(14.dp), - tint = Color(0xFF9C27B0) - ) - } + BitchatSheetCenterTopBar( + onClose = onDismiss, + modifier = Modifier.align(Alignment.TopCenter), + navigationIcon = { + IconButton( + onClick = onDismiss, + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 16.dp) + .size(32.dp) + ) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(R.string.chat_back), + tint = colorScheme.onSurface + ) } + }, + title = { + // Center content: connection status + name + encryption + Row( + modifier = Modifier.align(Alignment.Center), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { + when { + isDirect -> { + Icon( + imageVector = Icons.Outlined.SettingsInputAntenna, + contentDescription = stringResource(R.string.cd_connected_peers), + modifier = Modifier.size(14.dp), + tint = colorScheme.onSurface.copy(alpha = 0.6f) + ) + } + isConnected -> { + Icon( + imageVector = Icons.Filled.Route, + contentDescription = stringResource(R.string.cd_ready_for_handshake), + modifier = Modifier.size(14.dp), + tint = colorScheme.onSurface.copy(alpha = 0.6f) + ) + } + isNostrPeer -> { + Icon( + imageVector = Icons.Filled.Public, + contentDescription = stringResource(R.string.cd_nostr_reachable), + modifier = Modifier.size(14.dp), + tint = Color(0xFF9C27B0) + ) + } + } Text( text = titleText, @@ -974,49 +950,42 @@ fun PrivateChatSheet( color = if (isNostrPeer) Color(0xFFFF9500) else colorScheme.onSurface ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.then(securityModifier) - ) { - if (!isNostrPeer) { - NoiseSessionIcon( - sessionState = sessionState, - modifier = Modifier.size(14.dp) - ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.then(securityModifier) + ) { + if (!isNostrPeer) { + NoiseSessionIcon( + sessionState = sessionState, + modifier = Modifier.size(14.dp) + ) + } + + if (isVerified) { + Spacer(modifier = Modifier.width(4.dp)) + Icon( + imageVector = Icons.Filled.Verified, + contentDescription = stringResource(R.string.verify_title), + modifier = Modifier.size(14.dp), + tint = Color(0xFF32D74B) // iOS Green + ) + } } - if (isVerified) { - Spacer(modifier = Modifier.width(4.dp)) + IconButton( + onClick = { viewModel.toggleFavorite(peerID) }, + modifier = Modifier.size(28.dp) + ) { Icon( - imageVector = Icons.Filled.Verified, - contentDescription = stringResource(R.string.verify_title), - modifier = Modifier.size(14.dp), - tint = Color(0xFF32D74B) // iOS Green + imageVector = if (isFavorite) Icons.Filled.Star else Icons.Outlined.Star, + contentDescription = if (isFavorite) stringResource(R.string.cd_remove_favorite) else stringResource(R.string.cd_add_favorite), + modifier = Modifier.size(16.dp), + tint = if (isFavorite) Color(0xFFFFD700) else colorScheme.onSurface.copy(alpha = 0.6f) ) } } - - IconButton( - onClick = { viewModel.toggleFavorite(peerID) }, - modifier = Modifier.size(28.dp) - ) { - Icon( - imageVector = if (isFavorite) Icons.Filled.Star else Icons.Outlined.Star, - contentDescription = if (isFavorite) stringResource(R.string.cd_remove_favorite) else stringResource(R.string.cd_add_favorite), - modifier = Modifier.size(16.dp), - tint = if (isFavorite) Color(0xFFFFD700) else colorScheme.onSurface.copy(alpha = 0.6f) - ) - } } - - CloseButton( - onClick = onDismiss, - modifier = Modifier - .align(Alignment.CenterEnd) - .padding(horizontal = 16.dp) - ) - - } + ) } } } diff --git a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsSheet.kt b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsSheet.kt index ba63df44..672d352a 100644 --- a/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsSheet.kt +++ b/app/src/main/java/com/bitchat/android/ui/debug/DebugSettingsSheet.kt @@ -5,8 +5,10 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bluetooth import androidx.compose.material.icons.filled.BugReport @@ -34,6 +36,8 @@ import androidx.compose.ui.res.stringResource import com.bitchat.android.R import androidx.compose.ui.platform.LocalContext import com.bitchat.android.core.ui.component.sheet.BitchatBottomSheet +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar +import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle @Composable fun MeshTopologySection() { @@ -111,6 +115,16 @@ fun DebugSettingsSheet( val gcsFpr by manager.gcsFprPercent.collectAsState() val context = LocalContext.current // Persistent notification is now controlled solely by MeshServicePreferences.isBackgroundEnabled + val listState = rememberLazyListState() + val isScrolled by remember { + derivedStateOf { + listState.firstVisibleItemIndex > 0 || listState.firstVisibleItemScrollOffset > 0 + } + } + val topBarAlpha by animateFloatAsState( + targetValue = if (isScrolled) 0.95f else 0f, + label = "topBarAlpha" + ) // Push live connected devices from mesh service whenever sheet is visible LaunchedEffect(isPresented) { @@ -151,26 +165,23 @@ fun DebugSettingsSheet( DisposableEffect(Unit) { onDispose { DebugSettingsManager.getInstance().setDebugSheetVisible(false) } } - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - contentPadding = PaddingValues(top = 80.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - item { - Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Icon(Icons.Filled.BugReport, contentDescription = null, tint = Color(0xFFFF9500)) - Text(stringResource(R.string.debug_tools), fontFamily = FontFamily.Monospace, fontSize = 18.sp, fontWeight = FontWeight.Medium) + Box(modifier = Modifier.fillMaxWidth()) { + LazyColumn( + state = listState, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + contentPadding = PaddingValues(top = 80.dp, bottom = 24.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + item { + Text( + text = stringResource(R.string.debug_tools_desc), + fontFamily = FontFamily.Monospace, + fontSize = 12.sp, + color = colorScheme.onSurface.copy(alpha = 0.7f) + ) } - Text( - text = stringResource(R.string.debug_tools_desc), - fontFamily = FontFamily.Monospace, - fontSize = 12.sp, - color = colorScheme.onSurface.copy(alpha = 0.7f) - ) - } - // Verbose logging toggle item { Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) { @@ -627,7 +638,29 @@ fun DebugSettingsSheet( } } - item { Spacer(Modifier.height(16.dp)) } + item { Spacer(Modifier.height(16.dp)) } + } + + BitchatSheetTopBar( + onClose = onDismiss, + modifier = Modifier.align(Alignment.TopCenter), + backgroundAlpha = topBarAlpha, + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Filled.BugReport, + contentDescription = null, + tint = Color(0xFFFF9500) + ) + BitchatSheetTitle( + text = stringResource(R.string.debug_tools) + ) + } + } + ) } } }