[#1015] Custom TopAppBar UI component

- Covers all the necessary states and sub-components defined in the design document
- Closes #1015
This commit is contained in:
Honza Rychnovský 2023-10-20 15:44:57 +02:00 committed by GitHub
parent a70586d8b6
commit f9f6334f16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 348 additions and 116 deletions

View File

@ -10,6 +10,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -118,12 +119,19 @@ fun ListHeader(
fun Reference(
text: String,
modifier: Modifier = Modifier,
textAlign: TextAlign = TextAlign.Start,
onClick: () -> Unit
) {
ClickableText(
text = AnnotatedString(text),
style = MaterialTheme.typography.bodyLarge
.merge(TextStyle(color = ZcashTheme.colors.reference)),
.merge(
TextStyle(
color = ZcashTheme.colors.reference,
textAlign = textAlign,
textDecoration = TextDecoration.Underline
)
),
modifier = modifier,
onClick = {
onClick()

View File

@ -0,0 +1,234 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.internal.SecondaryTypography
@Preview
@Composable
private fun TopAppBarTextComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
SmallTopAppBar(titleText = "Screen A", backText = "Back")
}
}
}
@Preview
@Composable
private fun TopAppBarLogoComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
SmallTopAppBar(showTitleLogo = true, backText = "Back")
}
}
}
@Preview
@Composable
private fun TopAppBarRegularMenuComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
SmallTopAppBar(
titleText = "Screen B",
regularActions = {
TopBarRegularMenuExample(
actionOneCallback = {},
actionTwoCallback = {}
)
}
)
}
}
}
@Preview
@Composable
private fun TopAppBarOneVisibleActionMenuComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
SmallTopAppBar(
titleText = "Screen C",
backText = "Back",
regularActions = {
TopBarOneVisibleActionMenuExample(
actionCallback = {}
)
}
)
}
}
}
@Preview
@Composable
private fun TopAppBarHamburgerMenuComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
SmallTopAppBar(
titleText = "Screen D",
backText = "Back",
hamburgerMenuActions = {
TopBarHamburgerMenuExample(
actionCallback = {}
)
}
)
}
}
}
@Composable
private fun TopBarHamburgerMenuExample(
modifier: Modifier = Modifier,
actionCallback: () -> Unit
) {
Column(
modifier = modifier
) {
var expanded by rememberSaveable { mutableStateOf(false) }
IconButton(
onClick = {
expanded = true
actionCallback()
}
) {
Icon(
painter = painterResource(id = R.drawable.hamburger_menu_icon),
contentDescription = "Content description text"
)
}
}
}
@Composable
private fun TopBarRegularMenuExample(
actionOneCallback: () -> Unit,
actionTwoCallback: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(
modifier = modifier
) {
var expanded by rememberSaveable { mutableStateOf(false) }
IconButton(onClick = { expanded = true }) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Content description text"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text("Action One") },
onClick = {
actionOneCallback()
expanded = false
}
)
DropdownMenuItem(
text = { Text("Action Two") },
onClick = {
actionTwoCallback()
expanded = false
}
)
}
}
}
@Composable
private fun TopBarOneVisibleActionMenuExample(
modifier: Modifier = Modifier,
actionCallback: () -> Unit
) {
Reference(
text = "Action 1",
onClick = actionCallback,
textAlign = TextAlign.Center,
modifier = modifier.then(
Modifier.padding(all = ZcashTheme.dimens.spacingDefault)
)
)
}
@Composable
@Suppress("LongParameterList")
@OptIn(ExperimentalMaterial3Api::class)
fun SmallTopAppBar(
modifier: Modifier = Modifier,
titleText: String? = null,
showTitleLogo: Boolean = false,
backText: String? = null,
backContentDescriptionText: String? = null,
onBack: (() -> Unit)? = null,
hamburgerMenuActions: (@Composable RowScope.() -> Unit)? = null,
regularActions: (@Composable RowScope.() -> Unit)? = null,
) {
CenterAlignedTopAppBar(
title = {
if (titleText != null) {
Text(
text = titleText.uppercase(),
style = SecondaryTypography.headlineSmall
)
} else if (showTitleLogo) {
Icon(
painter = painterResource(id = R.drawable.zashi_text_logo),
contentDescription = null,
modifier = Modifier.height(ZcashTheme.dimens.topAppBarZcashLogoHeight)
)
}
},
navigationIcon = {
backText?.let {
Row(
verticalAlignment = Alignment.CenterVertically
) {
IconButton(
onClick = if (onBack != null) {
onBack
} else {
{}
}
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = backContentDescriptionText
)
}
Text(text = backText.uppercase())
}
}
},
actions = hamburgerMenuActions ?: regularActions ?: {},
modifier = modifier
)
}

View File

@ -20,14 +20,21 @@ data class Dimens(
val spacingHuge: Dp,
// List of custom spacings:
// Button:
val shadowOffsetX: Dp,
val shadowOffsetY: Dp,
val shadowSpread: Dp,
val defaultButtonWidth: Dp,
val defaultButtonHeight: Dp,
val zcashLogoHeight: Dp,
val zcashLogoWidth: Dp,
val zcashTextLogoHeight: Dp
// TopAppBar:
val topAppBarZcashLogoHeight: Dp,
// In screen custom spacings:
val inScreenZcashLogoHeight: Dp,
val inScreenZcashLogoWidth: Dp,
val inScreenZcashTextLogoHeight: Dp
)
private val defaultDimens = Dimens(
@ -44,9 +51,10 @@ private val defaultDimens = Dimens(
shadowSpread = 10.dp,
defaultButtonWidth = 230.dp,
defaultButtonHeight = 50.dp,
zcashLogoHeight = 100.dp,
zcashLogoWidth = 60.dp,
zcashTextLogoHeight = 30.dp
topAppBarZcashLogoHeight = 24.dp,
inScreenZcashLogoHeight = 100.dp,
inScreenZcashLogoWidth = 60.dp,
inScreenZcashTextLogoHeight = 30.dp
)
private val normalDimens = defaultDimens

View File

@ -53,7 +53,7 @@ internal object Dark {
val dangerous = Color(0xFFEC0008)
val onDangerous = Color(0xFFFFFFFF)
val reference = Color(0xFF10A5FF)
val reference = Color(0xFFFFFFFF)
val disabledButtonColor = Color(0xFFB7B7B7)
val disabledButtonTextColor = Color(0xFFDDDDDD)
@ -117,7 +117,7 @@ internal object Light {
val dangerous = Color(0xFFEC0008)
val onDangerous = Color(0xFFFFFFFF)
val reference = Color(0xFF10A5FF)
val reference = Color(0xFF000000)
val disabledButtonColor = Color(0xFFB7B7B7)
val disabledButtonTextColor = Color(0xFFDDDDDD)

View File

@ -78,6 +78,18 @@ internal val SecondaryTypography = Typography(
fontWeight = FontWeight.SemiBold,
fontSize = 30.sp
),
headlineMedium = TextStyle(
fontFamily = ArchivoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 25.sp,
textAlign = TextAlign.Center
),
headlineSmall = TextStyle(
fontFamily = ArchivoFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
textAlign = TextAlign.Center
),
bodyLarge = TextStyle(
fontFamily = ArchivoFontFamily,
fontWeight = FontWeight.Normal,
@ -92,12 +104,6 @@ internal val SecondaryTypography = Typography(
fontFamily = ArchivoFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
headlineMedium = TextStyle(
fontFamily = ArchivoFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 25.sp,
textAlign = TextAlign.Center
)
)

View File

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18dp"
android:height="16dp"
android:viewportWidth="18"
android:viewportHeight="16">
<path
android:pathData="M2,2H16"
android:strokeWidth="3"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M2,8H16"
android:strokeWidth="3"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:pathData="M2,14H16"
android:strokeWidth="3"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="169dp"
android:height="47dp"
android:viewportWidth="169"
android:viewportHeight="47">
<path
android:pathData="M51.32,2.33L60.18,0.99L75.78,46.08L65.64,47M65.64,46.92L61.16,35.39L45.94,34.49L41.46,46.11L34.3,46.93L51.31,2.33M48.63,28.25L58.39,28.26L53.1,14.84L48.62,28.24L48.63,28.25Z"
android:fillColor="#000000"/>
<path
android:pathData="M93.16,46.93C86.35,46.93 80.09,44.94 76.5,40.15L85.13,32.87C87.69,36.14 90.03,38.28 93.99,39.85L101.86,39.78C102.58,38.38 102.89,37.05 102.89,35.77C102.89,31.65 100.7,30.38 92.55,28.79C83.25,27.03 77.54,23.7 77.54,16.17C77.54,13.44 78.94,10.17 81.12,7.8L95.47,0.99C101.48,0.99 108.24,3.07 111.82,7.86L103.18,15.14C100.63,11.86 98.08,9.8 94.13,8.22H86.71C86.04,9.38 85.68,10.65 85.68,11.93C85.68,15.81 88.41,17.02 97.22,18.6C107.19,20.24 111.08,23.88 111.08,31.1C111.08,33.83 109.87,37.04 107.86,40.02L93.15,46.92L93.16,46.93Z"
android:fillColor="#000000"/>
<path
android:pathData="M142.35,0.99L152.88,2.33V46.11L142.35,46.92V26.74L126.02,26.45V46.1L115.28,46.92V2.22L126.02,0.99V20.19L142.35,20.06V0.99Z"
android:fillColor="#000000"/>
<path
android:pathData="M158.26,2.21L169,1V46.93L158.26,46.11V2.21Z"
android:fillColor="#000000"/>
<path
android:pathData="M13.43,36H34.02L30.4,45.87H0V43.15L21.49,10.98H1.79L4.47,2.05H34.91"
android:fillColor="#000000"/>
</vector>

View File

@ -1,7 +1,6 @@
package co.electriccoin.zcash.ui.screen.about.view
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@ -12,12 +11,9 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
@ -38,6 +34,7 @@ import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@ -89,40 +86,17 @@ fun About(
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun AboutTopAppBar(
onBack: () -> Unit,
versionInfo: VersionInfo,
configInfo: ConfigInfo
) {
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(id = R.string.about_title).uppercase(),
style = ZcashTheme.typography.primary.titleSmall,
color = ZcashTheme.colors.screenTitleColor
)
},
navigationIcon = {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
IconButton(
onClick = onBack
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(R.string.about_back_content_description)
)
}
Text(
text = stringResource(id = R.string.about_back).uppercase(),
style = ZcashTheme.typography.primary.bodyMedium
)
}
},
actions = {
SmallTopAppBar(
titleText = stringResource(id = R.string.about_title).uppercase(),
backText = stringResource(id = R.string.about_back).uppercase(),
backContentDescriptionText = stringResource(R.string.about_back_content_description),
onBack = onBack,
regularActions = {
if (versionInfo.isDebuggable) {
DebugMenu(versionInfo, configInfo)
}
@ -178,14 +152,14 @@ fun AboutMainContent(
painter = painterResource(id = R.drawable.zashi_logo_without_text),
contentDescription = null,
Modifier
.height(ZcashTheme.dimens.zcashLogoHeight)
.width(ZcashTheme.dimens.zcashLogoWidth)
.height(ZcashTheme.dimens.inScreenZcashLogoHeight)
.width(ZcashTheme.dimens.inScreenZcashLogoWidth)
)
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingDefault))
Image(
painter = painterResource(id = R.drawable.zashi_text_logo),
contentDescription = null,
modifier = Modifier.height(ZcashTheme.dimens.zcashTextLogoHeight)
modifier = Modifier.height(ZcashTheme.dimens.inScreenZcashTextLogoHeight)
)
}

View File

@ -121,8 +121,8 @@ private fun OnboardingMainContent(
painterResource(id = R.drawable.zashi_logo_without_text),
stringResource(R.string.zcash_logo_onboarding_content_description),
Modifier
.height(ZcashTheme.dimens.zcashLogoHeight)
.width(ZcashTheme.dimens.zcashLogoWidth)
.height(ZcashTheme.dimens.inScreenZcashLogoHeight)
.width(ZcashTheme.dimens.inScreenZcashLogoWidth)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))

View File

@ -11,16 +11,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
@ -41,6 +35,7 @@ import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.CheckBox
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@ -97,27 +92,13 @@ fun SecurityWarning(
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun SecurityWarningTopAppBar(
onBack: () -> Unit,
) {
TopAppBar(
title = {
Text(
text = stringResource(R.string.security_warning_back).uppercase(),
style = ZcashTheme.typography.primary.bodyMedium
)
},
navigationIcon = {
IconButton(
onClick = onBack
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(R.string.security_warning_back_content_description)
)
}
}
SmallTopAppBar(
backText = stringResource(R.string.security_warning_back).uppercase(),
backContentDescriptionText = stringResource(R.string.security_warning_back_content_description),
onBack = onBack,
)
}

View File

@ -5,4 +5,5 @@ package co.electriccoin.zcash.ui.screen.settings
*/
object SettingsTag {
const val TROUBLESHOOTING_MENU = "troubleshooting_menu"
const val SETTINGS_TOP_APP_BAR = "settings_top_app_bar"
}

View File

@ -1,9 +1,7 @@
package co.electriccoin.zcash.ui.screen.settings.view
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
@ -12,14 +10,11 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Cancel
import androidx.compose.material.icons.outlined.CheckCircle
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
@ -38,6 +33,7 @@ import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.ZcashTheme.dimens
import co.electriccoin.zcash.ui.screen.settings.SettingsTag
@ -117,7 +113,6 @@ fun Settings(
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
@Suppress("LongParameterList")
private fun SettingsTopAppBar(
troubleshootingParameters: TroubleshootingParameters,
@ -127,34 +122,12 @@ private fun SettingsTopAppBar(
onRescanWallet: () -> Unit,
onBack: () -> Unit,
) {
CenterAlignedTopAppBar(
title = {
Text(
text = stringResource(id = R.string.settings_header).uppercase(),
style = ZcashTheme.typography.primary.titleSmall,
color = ZcashTheme.colors.screenTitleColor
)
},
navigationIcon = {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
IconButton(
onClick = onBack
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(R.string.settings_back_content_description)
)
}
Text(
text = stringResource(id = R.string.settings_back).uppercase(),
style = ZcashTheme.typography.primary.bodyMedium
)
}
},
actions = {
SmallTopAppBar(
backText = stringResource(id = R.string.settings_back).uppercase(),
backContentDescriptionText = stringResource(R.string.settings_back_content_description),
onBack = onBack,
showTitleLogo = true,
regularActions = {
if (troubleshootingParameters.isEnabled) {
TroubleshootingMenu(
troubleshootingParameters,
@ -164,7 +137,8 @@ private fun SettingsTopAppBar(
onRescanWallet
)
}
}
},
modifier = Modifier.testTag(SettingsTag.SETTINGS_TOP_APP_BAR)
)
}

View File

@ -1,5 +1,4 @@
<resources>
<string name="settings_header">Settings</string>
<string name="settings_back">Back</string>
<string name="settings_back_content_description">Back</string>

View File

@ -49,6 +49,7 @@ import co.electriccoin.zcash.ui.screen.backup.BackupTag
import co.electriccoin.zcash.ui.screen.home.viewmodel.SecretState
import co.electriccoin.zcash.ui.screen.restore.RestoreTag
import co.electriccoin.zcash.ui.screen.restore.viewmodel.RestoreViewModel
import co.electriccoin.zcash.ui.screen.settings.SettingsTag
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
@ -303,7 +304,7 @@ class ScreenshotTest : UiTestPrerequisites() {
seedScreenshots(resContext, tag, composeTestRule)
navigateTo(NavigationTargets.SETTINGS)
settingsScreenshots(resContext, tag, composeTestRule)
settingsScreenshots(tag, composeTestRule)
navigateTo(NavigationTargets.SUPPORT)
supportScreenshots(resContext, tag, composeTestRule)
@ -542,8 +543,8 @@ private fun homeScreenshots(
}
}
private fun settingsScreenshots(resContext: Context, tag: String, composeTestRule: ComposeTestRule) {
composeTestRule.onNode(hasText(resContext.getString(R.string.settings_header), ignoreCase = true)).also {
private fun settingsScreenshots(tag: String, composeTestRule: ComposeTestRule) {
composeTestRule.onNode(hasTestTag(SettingsTag.SETTINGS_TOP_APP_BAR)).also {
it.assertExists()
}