android: add top app bars and safe-area pass for main pages
This commit is contained in:
@@ -494,3 +494,8 @@
|
||||
- unified selected/unselected item colors,
|
||||
- stable 4-item navigation with icons + labels.
|
||||
- Kept scroll-hide/show behavior and page-level navigation unchanged.
|
||||
|
||||
### Step 79 - Main pages app bars + safe-area pass
|
||||
- Added top app bars for all 4 main pages (`Chats`, `Contacts`, `Settings`, `Profile`) to make them feel like proper standalone sections.
|
||||
- Moved chats management toggle action into chats app bar.
|
||||
- Kept safe-area handling and bottom insets consistent with shared floating tabs bar to avoid overlap.
|
||||
|
||||
@@ -26,12 +26,14 @@ import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Tab
|
||||
import androidx.compose.material3.TabRow
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -172,6 +174,17 @@ fun ChatListScreen(
|
||||
.then(if (isTabletLayout) Modifier.widthIn(max = 820.dp) else Modifier)
|
||||
.padding(bottom = 92.dp),
|
||||
) {
|
||||
TopAppBar(
|
||||
title = { Text("Chats") },
|
||||
actions = {
|
||||
IconButton(onClick = { managementExpanded = !managementExpanded }) {
|
||||
Icon(
|
||||
imageVector = if (managementExpanded) Icons.Filled.Close else Icons.Filled.Add,
|
||||
contentDescription = if (managementExpanded) "Close management" else "Open management",
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
TabRow(
|
||||
selectedTabIndex = if (state.selectedTab == ChatTab.ALL) 0 else 1,
|
||||
) {
|
||||
@@ -315,17 +328,6 @@ fun ChatListScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
Button(
|
||||
onClick = { managementExpanded = !managementExpanded },
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(end = 16.dp, bottom = 112.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (managementExpanded) Icons.Filled.Close else Icons.Filled.Add,
|
||||
contentDescription = if (managementExpanded) "Close management" else "Open management",
|
||||
)
|
||||
}
|
||||
}
|
||||
if (managementExpanded) {
|
||||
Surface(
|
||||
|
||||
@@ -16,6 +16,8 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -38,6 +40,7 @@ fun ContactsRoute(
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
private fun ContactsScreen(
|
||||
onMainBarVisibilityChanged: (Boolean) -> Unit,
|
||||
) {
|
||||
@@ -87,9 +90,8 @@ private fun ContactsScreen(
|
||||
.padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 96.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Contacts",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
TopAppBar(
|
||||
title = { Text("Contacts") },
|
||||
)
|
||||
OutlinedTextField(
|
||||
value = query,
|
||||
|
||||
@@ -28,10 +28,12 @@ import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -67,6 +69,7 @@ fun ProfileRoute(
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun ProfileScreen(
|
||||
onBackToChats: () -> Unit,
|
||||
onOpenSettings: () -> Unit,
|
||||
@@ -128,9 +131,8 @@ fun ProfileScreen(
|
||||
.padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 96.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Profile",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
TopAppBar(
|
||||
title = { Text("Profile") },
|
||||
)
|
||||
if (!avatarUrl.isBlank()) {
|
||||
Box(
|
||||
|
||||
@@ -16,10 +16,12 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -56,6 +58,7 @@ fun SettingsRoute(
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun SettingsScreen(
|
||||
onBackToChats: () -> Unit,
|
||||
onOpenProfile: () -> Unit,
|
||||
@@ -108,9 +111,8 @@ fun SettingsScreen(
|
||||
.padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 96.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Settings",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
TopAppBar(
|
||||
title = { Text("Settings") },
|
||||
)
|
||||
Text("Appearance", style = MaterialTheme.typography.titleMedium)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- [x] Активный tab в фиолетовом pill-состоянии, неактивные — белые/серые.
|
||||
- [x] Глобальная панель `Chats / Contacts / Settings / Profile` на уровне app-shell (одна на все 4 страницы).
|
||||
- [x] Поведение панели: скрывается только при скролле вниз, возвращается при скролле вверх/в начале списка.
|
||||
- [ ] Safe area для status/nav bars на всех экранах списка/настроек/профиля.
|
||||
- [x] Safe area для status/nav bars на всех экранах списка/настроек/профиля.
|
||||
|
||||
## P0 — Settings Visual System
|
||||
- [ ] Экран настроек из секционных rounded cards (а не плоский список).
|
||||
|
||||
Reference in New Issue
Block a user