feat(app): add authenticated app shell with top bar and bottom navigation #6

Merged
KremeCN merged 5 commits from feat/authenticated-app-shell into main 2026-08-25 10:50:00 +08:00
Showing only changes of commit 6dab84506e - Show all commits
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -19,6 +18,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -56,6 +56,7 @@ fun MainAppShell(
) { ) {
Outdated
Review

状态重置

activeTab 仅通过 remember 保存,Activity 配置变更或进程重建后会重置为 initialTab。例如用户在“情景”页旋转屏幕后会被带回“设备”页。请使用 rememberSaveable,或将当前 Tab 上提为可持久化状态。

**状态重置** `activeTab` 仅通过 `remember` 保存,Activity 配置变更或进程重建后会重置为 `initialTab`。例如用户在“情景”页旋转屏幕后会被带回“设备”页。请使用 `rememberSaveable`,或将当前 Tab 上提为可持久化状态。 <!-- pr-agent-dedup: 56cc895a0f00 --> <!-- pr-agent-key-issue-location: 3ff2c58208f0 -->
var activeTab by rememberSaveable { mutableStateOf(initialTab) } var activeTab by rememberSaveable { mutableStateOf(initialTab) }
var showAccountSheet by remember { mutableStateOf(false) } var showAccountSheet by remember { mutableStateOf(false) }
val tabStateHolder = rememberSaveableStateHolder()
Scaffold( Scaffold(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
@@ -77,9 +78,7 @@ fun MainAppShell(
} }
}, },
bottomBar = { bottomBar = {
ABoxNavigationBar( ABoxNavigationBar {
Outdated
Review

重复边距

Material 3 的 NavigationBar 默认已通过自身的 windowInsets 处理底部系统栏,这里再次应用 navigationBarsPadding() 会重复计算底部 inset。在手势导航或三键导航设备上,底栏会异常增高,并进一步放大内容的 innerPadding。请移除额外 padding,或让封装只处理一次 inset。

**重复边距** Material 3 的 `NavigationBar` 默认已通过自身的 `windowInsets` 处理底部系统栏,这里再次应用 `navigationBarsPadding()` 会重复计算底部 inset。在手势导航或三键导航设备上,底栏会异常增高,并进一步放大内容的 `innerPadding`。请移除额外 padding,或让封装只处理一次 inset。 <!-- pr-agent-dedup: b63e434b0fbe --> <!-- pr-agent-key-issue-location: 2a72dfc37a05 -->
modifier = Modifier.navigationBarsPadding(),
) {
MainTab.values().forEach { tab -> MainTab.values().forEach { tab ->
val isSelected = (tab == activeTab) val isSelected = (tab == activeTab)
ABoxNavigationBarItem( ABoxNavigationBarItem(
@@ -111,10 +110,12 @@ fun MainAppShell(
targetState = activeTab, targetState = activeTab,
label = "MainTabCrossfade", label = "MainTabCrossfade",
) { tab -> ) { tab ->
when (tab) { tabStateHolder.SaveableStateProvider(tab) {
MainTab.DEVICES -> devicesSlot() when (tab) {
MainTab.SCENES -> scenesSlot() MainTab.DEVICES -> devicesSlot()
MainTab.ACTIVITY -> activitySlot() MainTab.SCENES -> scenesSlot()
MainTab.ACTIVITY -> activitySlot()
}
} }
} }
} }