|
|
|
@ -6,8 +6,8 @@ package org.mozilla.fenix.components.toolbar.navbar
|
|
|
|
|
|
|
|
|
|
import androidx.compose.foundation.background
|
|
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
|
|
|
import androidx.compose.foundation.layout.Box
|
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
|
import androidx.compose.foundation.layout.RowScope
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
|
@ -17,166 +17,337 @@ import androidx.compose.material.IconButton
|
|
|
|
|
import androidx.compose.material.LocalContentColor
|
|
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
|
|
|
import androidx.compose.ui.Alignment
|
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.compose.ui.platform.LocalContext
|
|
|
|
|
import androidx.compose.ui.res.painterResource
|
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
|
|
import androidx.compose.ui.viewinterop.AndroidView
|
|
|
|
|
import androidx.core.content.ContextCompat
|
|
|
|
|
import mozilla.components.browser.menu.view.MenuButton
|
|
|
|
|
import mozilla.components.browser.state.selector.normalTabs
|
|
|
|
|
import mozilla.components.browser.state.selector.privateTabs
|
|
|
|
|
import mozilla.components.browser.state.store.BrowserStore
|
|
|
|
|
import mozilla.components.lib.state.ext.observeAsState
|
|
|
|
|
import org.mozilla.fenix.R
|
|
|
|
|
import org.mozilla.fenix.components.toolbar.navbar.ItemType.STANDARD
|
|
|
|
|
import org.mozilla.fenix.components.toolbar.navbar.ItemType.TAB_COUNTER
|
|
|
|
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
|
|
|
|
import org.mozilla.fenix.compose.LongPressIconButton
|
|
|
|
|
import org.mozilla.fenix.compose.TabCounter
|
|
|
|
|
import org.mozilla.fenix.compose.annotation.LightDarkPreview
|
|
|
|
|
import org.mozilla.fenix.search.SearchDialogFragment
|
|
|
|
|
import org.mozilla.fenix.theme.FirefoxTheme
|
|
|
|
|
import org.mozilla.fenix.theme.Theme
|
|
|
|
|
import org.mozilla.fenix.theme.ThemeManager
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Top-level UI for displaying the navigation bar.
|
|
|
|
|
*
|
|
|
|
|
* @param actionItems A list of [ActionItem] used to populate the bar.
|
|
|
|
|
* @param tabCount The number of opened tabs.
|
|
|
|
|
* @param menuButton A [MenuButton] to be used for [ItemType.MENU].
|
|
|
|
|
* @param isPrivateMode If browsing in [BrowsingMode.Private].
|
|
|
|
|
* @param browserStore The [BrowserStore] instance used to observe tabs state.
|
|
|
|
|
* @param menuButton A [MenuButton] to be used as an [AndroidView]. The view implementation
|
|
|
|
|
* contains the builder for the menu, so for the time being we are not implementing it as a composable.
|
|
|
|
|
* @param onBackButtonClick Invoked when the user clicks the back button in the nav bar.
|
|
|
|
|
* @param onBackButtonLongPress Invoked when the user long-presses the back button in the nav bar.
|
|
|
|
|
* @param onForwardButtonClick Invoked when the user clicks the forward button in the nav bar.
|
|
|
|
|
* @param onForwardButtonLongPress Invoked when the user long-presses the forward button in the nav bar.
|
|
|
|
|
* @param onHomeButtonClick Invoked when the user clicks the home button in the nav bar.
|
|
|
|
|
* @param onTabsButtonClick Invoked when the user clicks the tabs button in the nav bar.
|
|
|
|
|
*/
|
|
|
|
|
@Suppress("LongParameterList")
|
|
|
|
|
@Composable
|
|
|
|
|
fun NavigationBar(
|
|
|
|
|
actionItems: List<ActionItem>,
|
|
|
|
|
tabCount: Int,
|
|
|
|
|
menuButton: MenuButton? = null,
|
|
|
|
|
fun BrowserNavBar(
|
|
|
|
|
isPrivateMode: Boolean,
|
|
|
|
|
browserStore: BrowserStore,
|
|
|
|
|
menuButton: MenuButton,
|
|
|
|
|
onBackButtonClick: () -> Unit,
|
|
|
|
|
onBackButtonLongPress: () -> Unit,
|
|
|
|
|
onForwardButtonClick: () -> Unit,
|
|
|
|
|
onForwardButtonLongPress: () -> Unit,
|
|
|
|
|
onHomeButtonClick: () -> Unit,
|
|
|
|
|
onTabsButtonClick: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
Box(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.background(FirefoxTheme.colors.layer1)
|
|
|
|
|
.height(48.dp)
|
|
|
|
|
.fillMaxWidth(),
|
|
|
|
|
) {
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.align(Alignment.Center)
|
|
|
|
|
.fillMaxWidth()
|
|
|
|
|
.padding(horizontal = 16.dp),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
|
|
|
) {
|
|
|
|
|
actionItems.forEach {
|
|
|
|
|
when (it.type) {
|
|
|
|
|
ItemType.STANDARD -> {
|
|
|
|
|
IconButton(onClick = {}) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(it.iconId),
|
|
|
|
|
stringResource(id = it.descriptionResourceId),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ItemType.TAB_COUNTER -> {
|
|
|
|
|
CompositionLocalProvider(LocalContentColor provides FirefoxTheme.colors.iconPrimary) {
|
|
|
|
|
IconButton(onClick = {}) {
|
|
|
|
|
TabCounter(tabCount = tabCount)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ItemType.MENU -> {
|
|
|
|
|
// [ActionItem] will be refactored here:
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1878827
|
|
|
|
|
if (menuButton != null) {
|
|
|
|
|
AndroidView(
|
|
|
|
|
modifier = Modifier.size(48.dp),
|
|
|
|
|
factory = { _ -> menuButton },
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
IconButton(onClick = {}) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(it.iconId),
|
|
|
|
|
stringResource(id = it.descriptionResourceId),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
val tabCount = browserStore.observeAsState(initialValue = 0) { browserState ->
|
|
|
|
|
if (isPrivateMode) {
|
|
|
|
|
browserState.privateTabs.size
|
|
|
|
|
} else {
|
|
|
|
|
browserState.normalTabs.size
|
|
|
|
|
}
|
|
|
|
|
}.value
|
|
|
|
|
|
|
|
|
|
NavBar {
|
|
|
|
|
BackButton(
|
|
|
|
|
onBackButtonClick = onBackButtonClick,
|
|
|
|
|
onBackButtonLongPress = onBackButtonLongPress,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
ForwardButton(
|
|
|
|
|
onForwardButtonClick = onForwardButtonClick,
|
|
|
|
|
onForwardButtonLongPress = onForwardButtonLongPress,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
HomeButton(
|
|
|
|
|
onHomeButtonClick = onHomeButtonClick,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
TabsButton(
|
|
|
|
|
onTabsButtonClick = onTabsButtonClick,
|
|
|
|
|
tabCount = tabCount,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
MenuButton(menuButton = menuButton)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents a navigation bar element.
|
|
|
|
|
* Top-level UI for displaying the navigation bar.
|
|
|
|
|
*
|
|
|
|
|
* @property iconId Resource ID of the icon that item should display.
|
|
|
|
|
* @property descriptionResourceId Text used as a content description by accessibility services.
|
|
|
|
|
* @property type Type of the item, defaults to [ItemType.STANDARD].
|
|
|
|
|
* @param isPrivateMode If browsing in [BrowsingMode.Private].
|
|
|
|
|
* @param browserStore The [BrowserStore] instance used to observe tabs state.
|
|
|
|
|
* @param menuButton A [MenuButton] to be used as an [AndroidView]. The view implementation
|
|
|
|
|
* contains the builder for the menu, so for the time being we are not implementing it as a composable.
|
|
|
|
|
* @param onSearchButtonClick Invoked when the user clicks the search button in the nav bar. The button
|
|
|
|
|
* is visible only on home screen and activates [SearchDialogFragment].
|
|
|
|
|
* @param onTabsButtonClick Invoked when the user clicks the tabs button in the nav bar.
|
|
|
|
|
*/
|
|
|
|
|
data class ActionItem(
|
|
|
|
|
val iconId: Int,
|
|
|
|
|
val descriptionResourceId: Int,
|
|
|
|
|
val type: ItemType = ItemType.STANDARD,
|
|
|
|
|
)
|
|
|
|
|
@Composable
|
|
|
|
|
fun HomeNavBar(
|
|
|
|
|
isPrivateMode: Boolean,
|
|
|
|
|
browserStore: BrowserStore,
|
|
|
|
|
menuButton: MenuButton,
|
|
|
|
|
onSearchButtonClick: () -> Unit,
|
|
|
|
|
onTabsButtonClick: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
val tabCount = browserStore.observeAsState(initialValue = 0) { browserState ->
|
|
|
|
|
if (isPrivateMode) {
|
|
|
|
|
browserState.privateTabs.size
|
|
|
|
|
} else {
|
|
|
|
|
browserState.normalTabs.size
|
|
|
|
|
}
|
|
|
|
|
}.value
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enumerates the types of items that can be used in a navigation bar.
|
|
|
|
|
*
|
|
|
|
|
* [STANDARD] - Represents a regular navigation item. Used for most navigation actions.
|
|
|
|
|
* [TAB_COUNTER] - Represents a specialized item used to display a count, such as the number of open tabs in a browser.
|
|
|
|
|
*/
|
|
|
|
|
enum class ItemType {
|
|
|
|
|
STANDARD, TAB_COUNTER, MENU
|
|
|
|
|
NavBar {
|
|
|
|
|
BackButton(
|
|
|
|
|
onBackButtonClick = {
|
|
|
|
|
// no-op
|
|
|
|
|
},
|
|
|
|
|
onBackButtonLongPress = {
|
|
|
|
|
// no-op
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
ForwardButton(
|
|
|
|
|
onForwardButtonClick = {
|
|
|
|
|
// no-op
|
|
|
|
|
},
|
|
|
|
|
onForwardButtonLongPress = {
|
|
|
|
|
// no-op
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
SearchWebButton(
|
|
|
|
|
onSearchButtonClick = onSearchButtonClick,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
TabsButton(
|
|
|
|
|
onTabsButtonClick = onTabsButtonClick,
|
|
|
|
|
tabCount = tabCount,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
MenuButton(menuButton = menuButton)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Provides a collection of navigation items used in the application's navigation bar.
|
|
|
|
|
*/
|
|
|
|
|
object NavigationItems {
|
|
|
|
|
val home = ActionItem(
|
|
|
|
|
iconId = R.drawable.mozac_ic_home_24,
|
|
|
|
|
descriptionResourceId = R.string.browser_toolbar_home,
|
|
|
|
|
@Composable
|
|
|
|
|
private fun NavBar(
|
|
|
|
|
content: @Composable RowScope.() -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.background(FirefoxTheme.colors.layer1)
|
|
|
|
|
.height(48.dp)
|
|
|
|
|
.fillMaxWidth()
|
|
|
|
|
.padding(horizontal = 16.dp),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
|
|
|
content = content,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val menu = ActionItem(
|
|
|
|
|
iconId = R.drawable.mozac_ic_ellipsis_vertical_24,
|
|
|
|
|
descriptionResourceId = R.string.mozac_browser_menu_button,
|
|
|
|
|
type = ItemType.MENU,
|
|
|
|
|
)
|
|
|
|
|
@Composable
|
|
|
|
|
private fun BackButton(
|
|
|
|
|
onBackButtonClick: () -> Unit,
|
|
|
|
|
onBackButtonLongPress: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
LongPressIconButton(
|
|
|
|
|
onClick = onBackButtonClick,
|
|
|
|
|
onLongClick = onBackButtonLongPress,
|
|
|
|
|
) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(R.drawable.mozac_ic_back_24),
|
|
|
|
|
stringResource(id = R.string.browser_menu_back),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
private fun ForwardButton(
|
|
|
|
|
onForwardButtonClick: () -> Unit,
|
|
|
|
|
onForwardButtonLongPress: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
LongPressIconButton(
|
|
|
|
|
onClick = onForwardButtonClick,
|
|
|
|
|
onLongClick = onForwardButtonLongPress,
|
|
|
|
|
) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(R.drawable.mozac_ic_forward_24),
|
|
|
|
|
stringResource(id = R.string.browser_menu_forward),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val back = ActionItem(
|
|
|
|
|
iconId = R.drawable.mozac_ic_back_24,
|
|
|
|
|
descriptionResourceId = R.string.browser_menu_back,
|
|
|
|
|
@Composable
|
|
|
|
|
private fun HomeButton(
|
|
|
|
|
onHomeButtonClick: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
IconButton(
|
|
|
|
|
onClick = onHomeButtonClick,
|
|
|
|
|
) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(R.drawable.mozac_ic_home_24),
|
|
|
|
|
stringResource(id = R.string.browser_toolbar_home),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
private fun SearchWebButton(
|
|
|
|
|
onSearchButtonClick: () -> Unit,
|
|
|
|
|
) {
|
|
|
|
|
IconButton(
|
|
|
|
|
onClick = onSearchButtonClick,
|
|
|
|
|
) {
|
|
|
|
|
Icon(
|
|
|
|
|
painter = painterResource(R.drawable.mozac_ic_search_24),
|
|
|
|
|
stringResource(id = R.string.search_hint),
|
|
|
|
|
tint = FirefoxTheme.colors.iconPrimary,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
private fun MenuButton(
|
|
|
|
|
menuButton: MenuButton,
|
|
|
|
|
) {
|
|
|
|
|
// Should refactor it to be a simple IconButton with a click listener
|
|
|
|
|
// once the redesigned menu is implemented.
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1884049
|
|
|
|
|
AndroidView(
|
|
|
|
|
modifier = Modifier.size(48.dp),
|
|
|
|
|
factory = { _ -> menuButton },
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
private fun TabsButton(
|
|
|
|
|
onTabsButtonClick: () -> Unit,
|
|
|
|
|
tabCount: Int,
|
|
|
|
|
) {
|
|
|
|
|
CompositionLocalProvider(LocalContentColor provides FirefoxTheme.colors.iconPrimary) {
|
|
|
|
|
IconButton(onClick = { onTabsButtonClick() }) {
|
|
|
|
|
TabCounter(tabCount = tabCount)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val forward = ActionItem(
|
|
|
|
|
iconId = R.drawable.mozac_ic_forward_24,
|
|
|
|
|
descriptionResourceId = R.string.browser_menu_forward,
|
|
|
|
|
@Composable
|
|
|
|
|
private fun HomeNavBarPreviewRoot(isPrivateMode: Boolean) {
|
|
|
|
|
val context = LocalContext.current
|
|
|
|
|
val colorId = if (isPrivateMode) {
|
|
|
|
|
// private mode preview keeps using black colour as textPrimary
|
|
|
|
|
ThemeManager.resolveAttribute(R.attr.textOnColorPrimary, context)
|
|
|
|
|
} else {
|
|
|
|
|
ThemeManager.resolveAttribute(R.attr.textPrimary, context)
|
|
|
|
|
}
|
|
|
|
|
val menuButton = MenuButton(context).apply {
|
|
|
|
|
setColorFilter(
|
|
|
|
|
ContextCompat.getColor(
|
|
|
|
|
context,
|
|
|
|
|
colorId,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HomeNavBar(
|
|
|
|
|
onSearchButtonClick = {},
|
|
|
|
|
menuButton = menuButton,
|
|
|
|
|
onTabsButtonClick = {},
|
|
|
|
|
isPrivateMode = false,
|
|
|
|
|
browserStore = BrowserStore(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val tabs = ActionItem(
|
|
|
|
|
iconId = R.drawable.mozac_ui_tabcounter_box,
|
|
|
|
|
descriptionResourceId = R.string.mozac_tab_counter_content_description,
|
|
|
|
|
type = TAB_COUNTER,
|
|
|
|
|
@Composable
|
|
|
|
|
private fun OpenTabNavBarNavBarPreviewRoot(isPrivateMode: Boolean) {
|
|
|
|
|
val context = LocalContext.current
|
|
|
|
|
val colorId = if (isPrivateMode) {
|
|
|
|
|
// private mode preview keeps using black colour as textPrimary
|
|
|
|
|
ThemeManager.resolveAttribute(R.attr.textOnColorPrimary, context)
|
|
|
|
|
} else {
|
|
|
|
|
ThemeManager.resolveAttribute(R.attr.textPrimary, context)
|
|
|
|
|
}
|
|
|
|
|
val menuButton = MenuButton(context).apply {
|
|
|
|
|
setColorFilter(
|
|
|
|
|
ContextCompat.getColor(
|
|
|
|
|
context,
|
|
|
|
|
colorId,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BrowserNavBar(
|
|
|
|
|
onBackButtonClick = {},
|
|
|
|
|
onBackButtonLongPress = {},
|
|
|
|
|
onForwardButtonClick = {},
|
|
|
|
|
onForwardButtonLongPress = {},
|
|
|
|
|
onHomeButtonClick = {},
|
|
|
|
|
menuButton = menuButton,
|
|
|
|
|
onTabsButtonClick = {},
|
|
|
|
|
isPrivateMode = false,
|
|
|
|
|
browserStore = BrowserStore(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val defaultItems = listOf(back, forward, home, tabs, menu)
|
|
|
|
|
@LightDarkPreview
|
|
|
|
|
@Composable
|
|
|
|
|
private fun HomeNavBarPreview() {
|
|
|
|
|
FirefoxTheme {
|
|
|
|
|
HomeNavBarPreviewRoot(isPrivateMode = false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Preview
|
|
|
|
|
@Composable
|
|
|
|
|
private fun HomeNavBarPrivatePreview() {
|
|
|
|
|
FirefoxTheme(theme = Theme.Private) {
|
|
|
|
|
HomeNavBarPreviewRoot(isPrivateMode = true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@LightDarkPreview
|
|
|
|
|
@Composable
|
|
|
|
|
private fun NavigationBarPreview() {
|
|
|
|
|
private fun OpenTabNavBarPreview() {
|
|
|
|
|
FirefoxTheme {
|
|
|
|
|
NavigationBar(
|
|
|
|
|
actionItems = NavigationItems.defaultItems,
|
|
|
|
|
tabCount = 0,
|
|
|
|
|
)
|
|
|
|
|
OpenTabNavBarNavBarPreviewRoot(isPrivateMode = false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Preview
|
|
|
|
|
@Composable
|
|
|
|
|
private fun NavigationBarPrivatePreview() {
|
|
|
|
|
private fun OpenTabNavBarPrivatePreview() {
|
|
|
|
|
FirefoxTheme(theme = Theme.Private) {
|
|
|
|
|
NavigationBar(
|
|
|
|
|
actionItems = NavigationItems.defaultItems,
|
|
|
|
|
tabCount = 0,
|
|
|
|
|
)
|
|
|
|
|
OpenTabNavBarNavBarPreviewRoot(isPrivateMode = true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|