From fdd877b49a5da97abc34f363a3b4e76513a08b55 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 9 Mar 2026 21:16:06 +0300 Subject: [PATCH] android: add top app bars and safe-area pass for main pages --- android/CHANGELOG.md | 5 ++++ .../messenger/ui/chats/ChatListScreen.kt | 24 ++++++++++--------- .../messenger/ui/contacts/ContactsScreen.kt | 8 ++++--- .../messenger/ui/profile/ProfileScreen.kt | 8 ++++--- .../messenger/ui/settings/SettingsScreen.kt | 8 ++++--- docs/android-ui-batch-1-checklist.md | 2 +- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index 5d291d9..77edd45 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -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. diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chats/ChatListScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chats/ChatListScreen.kt index 61f018e..10bbbac 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chats/ChatListScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chats/ChatListScreen.kt @@ -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( diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt index 0551436..e0855d9 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/contacts/ContactsScreen.kt @@ -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, diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/profile/ProfileScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/profile/ProfileScreen.kt index aed2e17..352a9ae 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/profile/ProfileScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/profile/ProfileScreen.kt @@ -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( diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/settings/SettingsScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/settings/SettingsScreen.kt index c228b6c..2ac5cbe 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/settings/SettingsScreen.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/settings/SettingsScreen.kt @@ -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)) { diff --git a/docs/android-ui-batch-1-checklist.md b/docs/android-ui-batch-1-checklist.md index ad03b50..a5c7ad4 100644 --- a/docs/android-ui-batch-1-checklist.md +++ b/docs/android-ui-batch-1-checklist.md @@ -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 (а не плоский список).