Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
Expand All @@ -14,13 +15,15 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bitwarden.ui.platform.base.util.EventsEffect
Expand All @@ -31,6 +34,7 @@ import com.bitwarden.ui.platform.components.button.BitwardenFilledButton
import com.bitwarden.ui.platform.components.button.BitwardenOutlinedButton
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.text.BitwardenClickableText
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.composition.LocalIntentManager
import com.bitwarden.ui.platform.manager.IntentManager
Expand Down Expand Up @@ -64,6 +68,12 @@ fun SetupBrowserAutofillScreen(
browserPackage = event.browserPackage,
)
}

SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo -> {
intentManager.launchUri(
"https://bitwarden.com/help/auto-fill-android/#browser-integrations/".toUri(),
)
}
}
}
SetupBrowserAutofillDialogs(
Expand Down Expand Up @@ -106,6 +116,9 @@ fun SetupBrowserAutofillScreen(
) {
SetupBrowserAutofillContent(
state = state,
onWhyIsThisStepRequiredClick = remember(viewModel) {
{ viewModel.trySendAction(SetupBrowserAutofillAction.WhyIsThisStepRequiredClick) }
},
onBrowserClick = remember(viewModel) {
{ viewModel.trySendAction(SetupBrowserAutofillAction.BrowserIntegrationClick(it)) }
},
Expand All @@ -120,9 +133,11 @@ fun SetupBrowserAutofillScreen(
}
}

@Suppress("LongMethod")
@Composable
private fun SetupBrowserAutofillContent(
state: SetupBrowserAutofillState,
onWhyIsThisStepRequiredClick: () -> Unit,
onBrowserClick: (BrowserPackage) -> Unit,
onContinueClick: () -> Unit,
onTurnOnLaterClick: () -> Unit,
Expand Down Expand Up @@ -154,7 +169,16 @@ private fun SetupBrowserAutofillContent(
.fillMaxWidth()
.standardHorizontalMargin(),
)
Spacer(modifier = Modifier.height(height = 24.dp))
BitwardenClickableText(
label = stringResource(id = BitwardenString.why_is_this_step_required),
style = BitwardenTheme.typography.labelMedium,
onClick = onWhyIsThisStepRequiredClick,
modifier = Modifier
.wrapContentWidth()
.align(alignment = Alignment.CenterHorizontally)
.standardHorizontalMargin(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
BrowserAutofillSettingsCard(
options = state.browserAutofillSettingsOptions,
onOptionClicked = onBrowserClick,
Expand Down Expand Up @@ -221,6 +245,7 @@ private fun SetupBrowserAutofillContent_preview() {
BrowserAutofillSettingsOption.ChromeBeta(enabled = true),
),
),
onWhyIsThisStepRequiredClick = { },
onBrowserClick = { },
onContinueClick = { },
onTurnOnLaterClick = { },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class SetupBrowserAutofillViewModel @Inject constructor(
handleBrowserIntegrationClick(action)
}

SetupBrowserAutofillAction.WhyIsThisStepRequiredClick -> {
handleWhyIsThisStepRequiredClick()
}

SetupBrowserAutofillAction.CloseClick -> handleCloseClick()
SetupBrowserAutofillAction.DismissDialog -> handleDismissDialog()
SetupBrowserAutofillAction.ContinueClick -> handleContinueClick()
Expand All @@ -81,6 +85,10 @@ class SetupBrowserAutofillViewModel @Inject constructor(
)
}

private fun handleWhyIsThisStepRequiredClick() {
sendEvent(SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo)
}

private fun handleCloseClick() {
sendEvent(SetupBrowserAutofillEvent.NavigateBack)
}
Expand Down Expand Up @@ -167,6 +175,11 @@ sealed class SetupBrowserAutofillEvent {
data class NavigateToBrowserAutofillSettings(
val browserPackage: BrowserPackage,
) : SetupBrowserAutofillEvent()

/**
* Navigates to the browser integrations info page.
*/
data object NavigateToBrowserIntegrationsInfo : SetupBrowserAutofillEvent()
}

/**
Expand Down Expand Up @@ -205,6 +218,11 @@ sealed class SetupBrowserAutofillAction {
*/
data object TurnOnLaterConfirmClick : SetupBrowserAutofillAction()

/**
* Indicates that the "Why is this step required?" button was clicked.
*/
data object WhyIsThisStepRequiredClick : SetupBrowserAutofillAction()

/**
* Models actions the [SetupBrowserAutofillViewModel] itself may send.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.core.net.toUri
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.ui.platform.manager.IntentManager
import com.bitwarden.ui.util.assertNoDialogExists
Expand All @@ -34,7 +35,9 @@ import org.junit.Test

class SetupBrowserAutofillScreenTest : BitwardenComposeTest() {
private var onNavigateBackCalled = false
private val intentManager = mockk<IntentManager>()
private val intentManager = mockk<IntentManager> {
every { launchUri(uri = any()) } just runs
}

private val mutableEventFlow = bufferedMutableSharedFlow<SetupBrowserAutofillEvent>()
private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE)
Expand Down Expand Up @@ -68,6 +71,16 @@ class SetupBrowserAutofillScreenTest : BitwardenComposeTest() {
assertTrue(onNavigateBackCalled)
}

@Test
fun `NavigateToBrowserIntegrationsInfo should call onNavigateBack`() {
mutableEventFlow.tryEmit(SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo)
verify(exactly = 1) {
intentManager.launchUri(
uri = "https://bitwarden.com/help/auto-fill-android/#browser-integrations/".toUri(),
)
}
}

@Test
fun `NavigateToBrowserAutofillSettings should start system autofill settings activity`() {
val browserPackage = BrowserPackage.CHROME_STABLE
Expand Down Expand Up @@ -112,6 +125,18 @@ class SetupBrowserAutofillScreenTest : BitwardenComposeTest() {
composeTestRule.onNodeWithContentDescription(label = "Close").assertExists()
}

@Test
fun `why is this step required button click should emit WhyIsThisStepRequiredClick`() {
mutableStateFlow.update { it.copy(isInitialSetup = false) }
composeTestRule
.onNodeWithText(text = "Why is this step required?")
.performScrollTo()
.performClick()
verify(exactly = 1) {
viewModel.trySendAction(SetupBrowserAutofillAction.WhyIsThisStepRequiredClick)
}
}

@Test
fun `close button click should emit CloseClick`() {
mutableStateFlow.update { it.copy(isInitialSetup = false) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,19 @@ class SetupBrowserAutofillViewModelTest {
}
}

@Test
fun `WhyIsThisStepRequiredClick should send NavigateToBrowserIntegrationsInfo event`() =
runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.trySendAction(SetupBrowserAutofillAction.WhyIsThisStepRequiredClick)
assertEquals(
SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo,
awaitItem(),
)
}
}

@Test
fun `BrowserIntegrationClick should send NavigateToBrowserAutofillSettings event`() = runTest {
val browserPackage = BrowserPackage.BRAVE_RELEASE
Expand Down
1 change: 1 addition & 0 deletions ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1130,4 +1130,5 @@ Do you want to switch to this account?</string>
<string name="passwords">Passwords</string>
<string name="passkeys">Passkeys</string>
<string name="import_verb">Import</string>
<string name="why_is_this_step_required">Why is this step required?</string>
</resources>