Skip to content

Commit be40149

Browse files
authored
[PM-16905] Add back button to new device notice (#4570)
1 parent 5840bcd commit be40149

File tree

6 files changed

+86
-5
lines changed

6 files changed

+86
-5
lines changed

app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorNavigation.kt

+2
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ fun NavController.navigateToNewDeviceNoticeTwoFactor(
2424
*/
2525
fun NavGraphBuilder.newDeviceNoticeTwoFactorDestination(
2626
onNavigateBackToVault: () -> Unit,
27+
onNavigateBack: () -> Unit,
2728
) {
2829
composableWithSlideTransitions(
2930
route = NEW_DEVICE_NOTICE_TWO_FACTOR_ROUTE,
3031
) {
3132
NewDeviceNoticeTwoFactorScreen(
3233
onNavigateBackToVault = onNavigateBackToVault,
34+
onNavigateBack = onNavigateBack,
3335
)
3436
}
3537
}

app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreen.kt

+32-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ import androidx.compose.foundation.layout.navigationBarsPadding
1111
import androidx.compose.foundation.layout.size
1212
import androidx.compose.foundation.rememberScrollState
1313
import androidx.compose.foundation.verticalScroll
14+
import androidx.compose.material3.ExperimentalMaterial3Api
1415
import androidx.compose.material3.Text
16+
import androidx.compose.material3.TopAppBarDefaults
1517
import androidx.compose.runtime.Composable
1618
import androidx.compose.runtime.getValue
19+
import androidx.compose.runtime.remember
1720
import androidx.compose.ui.Alignment
1821
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.input.nestedscroll.nestedScroll
1923
import androidx.compose.ui.res.stringResource
2024
import androidx.compose.ui.text.style.TextAlign
2125
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
@@ -27,13 +31,16 @@ import com.x8bit.bitwarden.R
2731
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ChangeAccountEmailClick
2832
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ContinueDialogClick
2933
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.DismissDialogClick
34+
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.NavigateBackClick
3035
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.RemindMeLaterClick
3136
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.TurnOnTwoFactorClick
3237
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorEvent.NavigateBackToVault
3338
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorEvent.NavigateToChangeAccountEmail
3439
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorEvent.NavigateToTurnOnTwoFactor
3540
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
3641
import com.x8bit.bitwarden.ui.platform.base.util.standardHorizontalMargin
42+
import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
43+
import com.x8bit.bitwarden.ui.platform.components.appbar.NavigationIcon
3744
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenFilledButton
3845
import com.x8bit.bitwarden.ui.platform.components.button.BitwardenOutlinedButton
3946
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
@@ -46,9 +53,12 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
4653
/**
4754
* The top level composable for the new device notice two factor screen.
4855
*/
56+
@OptIn(ExperimentalMaterial3Api::class)
57+
@Suppress("LongMethod")
4958
@Composable
5059
fun NewDeviceNoticeTwoFactorScreen(
5160
onNavigateBackToVault: () -> Unit,
61+
onNavigateBack: () -> Unit,
5262
intentManager: IntentManager = LocalIntentManager.current,
5363
viewModel: NewDeviceNoticeTwoFactorViewModel = hiltViewModel(),
5464
) {
@@ -64,6 +74,8 @@ fun NewDeviceNoticeTwoFactorScreen(
6474
}
6575

6676
NavigateBackToVault -> onNavigateBackToVault()
77+
78+
NewDeviceNoticeTwoFactorEvent.NavigateBack -> onNavigateBack()
6779
}
6880
}
6981

@@ -85,7 +97,26 @@ fun NewDeviceNoticeTwoFactorScreen(
8597
null -> Unit
8698
}
8799

88-
BitwardenScaffold {
100+
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
101+
BitwardenScaffold(
102+
modifier = Modifier
103+
.nestedScroll(scrollBehavior.nestedScrollConnection),
104+
topBar = {
105+
BitwardenTopAppBar(
106+
title = "",
107+
scrollBehavior = scrollBehavior,
108+
navigationIcon = NavigationIcon(
109+
navigationIcon = rememberVectorPainter(R.drawable.ic_back),
110+
navigationIconContentDescription = stringResource(id = R.string.back),
111+
onNavigationIconClick = remember(viewModel) {
112+
{
113+
viewModel.trySendAction(NavigateBackClick)
114+
}
115+
},
116+
),
117+
)
118+
},
119+
) {
89120
NewDeviceNoticeTwoFactorContent(
90121
onTurnOnTwoFactorClick = {
91122
viewModel.trySendAction(TurnOnTwoFactorClick)

app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorViewModel.kt

+13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.x8bit.bitwarden.data.vault.repository.VaultRepository
1515
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ChangeAccountEmailClick
1616
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.ContinueDialogClick
1717
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.DismissDialogClick
18+
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.NavigateBackClick
1819
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.RemindMeLaterClick
1920
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorAction.TurnOnTwoFactorClick
2021
import com.x8bit.bitwarden.ui.auth.feature.newdevicenotice.NewDeviceNoticeTwoFactorDialogState.ChangeAccountEmailDialog
@@ -90,6 +91,8 @@ class NewDeviceNoticeTwoFactorViewModel @Inject constructor(
9091
DismissDialogClick -> updateDialogState(newState = null)
9192

9293
ContinueDialogClick -> handleContinueDialog()
94+
95+
NavigateBackClick -> sendEvent(NewDeviceNoticeTwoFactorEvent.NavigateBack)
9396
}
9497
}
9598

@@ -154,6 +157,11 @@ sealed class NewDeviceNoticeTwoFactorEvent {
154157
* Navigates back to vault.
155158
*/
156159
data object NavigateBackToVault : NewDeviceNoticeTwoFactorEvent()
160+
161+
/**
162+
* Navigates back to previous screen.
163+
*/
164+
data object NavigateBack : NewDeviceNoticeTwoFactorEvent()
157165
}
158166

159167
/**
@@ -184,6 +192,11 @@ sealed class NewDeviceNoticeTwoFactorAction {
184192
* User tapped the continue dialog button.
185193
*/
186194
data object ContinueDialogClick : NewDeviceNoticeTwoFactorAction()
195+
196+
/**
197+
* User tapped the back button.
198+
*/
199+
data object NavigateBackClick : NewDeviceNoticeTwoFactorAction()
187200
}
188201

189202
/**

app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/vaultunlocked/VaultUnlockedNavigation.kt

+1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ fun NavGraphBuilder.vaultUnlockedGraph(
241241
)
242242
newDeviceNoticeTwoFactorDestination(
243243
onNavigateBackToVault = { navController.navigateToVaultUnlockedGraph() },
244+
onNavigateBack = { navController.popBackStack() },
244245
)
245246
}
246247
}

app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorScreenTest.kt

+25-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.compose.ui.test.assert
44
import androidx.compose.ui.test.assertIsDisplayed
55
import androidx.compose.ui.test.hasAnyAncestor
66
import androidx.compose.ui.test.isDialog
7+
import androidx.compose.ui.test.onNodeWithContentDescription
78
import androidx.compose.ui.test.onNodeWithText
89
import androidx.compose.ui.test.performClick
910
import androidx.compose.ui.test.performScrollTo
@@ -20,13 +21,15 @@ import junit.framework.TestCase.assertTrue
2021
import kotlinx.coroutines.flow.MutableStateFlow
2122
import kotlinx.coroutines.flow.update
2223
import org.junit.After
24+
import org.junit.Assert
2325
import org.junit.Before
2426
import org.junit.Test
2527

2628
class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
2729
private val intentManager = mockk<IntentManager>(relaxed = true) {
2830
every { startCustomTabsActivity(any()) } just runs
2931
}
32+
private var onNavigateBackToVaultCalled = false
3033
private var onNavigateBackCalled = false
3134
private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE)
3235
private val mutableEventFlow = bufferedMutableSharedFlow<NewDeviceNoticeTwoFactorEvent>()
@@ -39,7 +42,8 @@ class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
3942
fun setUp() {
4043
composeTestRule.setContent {
4144
NewDeviceNoticeTwoFactorScreen(
42-
onNavigateBackToVault = { onNavigateBackCalled = true },
45+
onNavigateBackToVault = { onNavigateBackToVaultCalled = true },
46+
onNavigateBack = { onNavigateBackCalled = true },
4347
intentManager,
4448
viewModel = viewModel,
4549
)
@@ -48,9 +52,21 @@ class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
4852

4953
@After
5054
fun tearDown() {
55+
onNavigateBackToVaultCalled = false
5156
onNavigateBackCalled = false
5257
}
5358

59+
@Test
60+
fun `onNavigateBack should send action to viewModel`() {
61+
composeTestRule
62+
.onNodeWithContentDescription("Back")
63+
.performClick()
64+
65+
verify {
66+
viewModel.trySendAction(NewDeviceNoticeTwoFactorAction.NavigateBackClick)
67+
}
68+
}
69+
5470
@Test
5571
fun `Turn on two-step verification click should send TurnOnTwoFactorClick action`() {
5672
composeTestRule
@@ -117,7 +133,13 @@ class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
117133
@Test
118134
fun `RemindMeLaterClick should call OnNavigateBack`() {
119135
mutableEventFlow.tryEmit(NewDeviceNoticeTwoFactorEvent.NavigateBackToVault)
120-
assertTrue(onNavigateBackCalled)
136+
assertTrue(onNavigateBackToVaultCalled)
137+
}
138+
139+
@Test
140+
fun `onNavigateBack should set onNavigateBackCalled to true`() {
141+
mutableEventFlow.tryEmit(NewDeviceNoticeTwoFactorEvent.NavigateBack)
142+
Assert.assertTrue(onNavigateBackCalled)
121143
}
122144

123145
@Test
@@ -157,7 +179,7 @@ class NewDeviceNoticeTwoFactorScreenTest : BaseComposeTest() {
157179
"Make your account more secure by setting up two-step login in the Bitwarden web app.",
158180
substring = true,
159181
ignoreCase = true,
160-
)
182+
)
161183
.assert(hasAnyAncestor(isDialog()))
162184
.assertIsDisplayed()
163185
composeTestRule

app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/newdevicenotice/NewDeviceNoticeTwoFactorViewModelTest.kt

+13-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
127127
}
128128

129129
@Test
130-
fun `RemindMeLaterClick should emit NavigateBack`() = runTest {
130+
fun `RemindMeLaterClick should emit NavigateBackToVault`() = runTest {
131131
val viewModel = createViewModel()
132132
viewModel.eventFlow.test {
133133
viewModel.trySendAction(NewDeviceNoticeTwoFactorAction.RemindMeLaterClick)
@@ -146,6 +146,18 @@ class NewDeviceNoticeTwoFactorViewModelTest : BaseViewModelTest() {
146146
}
147147
}
148148

149+
@Test
150+
fun `NavigateBackClick should send NavigateBack event`() = runTest {
151+
val viewModel = createViewModel()
152+
viewModel.trySendAction(NewDeviceNoticeTwoFactorAction.NavigateBackClick)
153+
viewModel.eventFlow.test {
154+
assertEquals(
155+
NewDeviceNoticeTwoFactorEvent.NavigateBack,
156+
awaitItem(),
157+
)
158+
}
159+
}
160+
149161
@Test
150162
@Suppress("MaxLineLength")
151163
fun `ContinueDialogClick should emit NavigateToTurnOnTwoFactor if dialog state is TurnOnTwoFactorDialog`() =

0 commit comments

Comments
 (0)