mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 09:56:45 -06:00
PM-26312: Add browser integration help link (#5963)
This commit is contained in:
parent
6ca8a39355
commit
116bfd6351
@ -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
|
||||
@ -14,6 +15,7 @@ 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
|
||||
@ -21,6 +23,7 @@ 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
|
||||
@ -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
|
||||
@ -64,6 +68,12 @@ fun SetupBrowserAutofillScreen(
|
||||
browserPackage = event.browserPackage,
|
||||
)
|
||||
}
|
||||
|
||||
SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo -> {
|
||||
intentManager.launchUri(
|
||||
"https://bitwarden.com/help/auto-fill-android/#browser-integrations/".toUri(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
SetupBrowserAutofillDialogs(
|
||||
@ -106,6 +116,9 @@ fun SetupBrowserAutofillScreen(
|
||||
) {
|
||||
SetupBrowserAutofillContent(
|
||||
state = state,
|
||||
onWhyIsThisStepRequiredClick = remember(viewModel) {
|
||||
{ viewModel.trySendAction(SetupBrowserAutofillAction.WhyIsThisStepRequiredClick) }
|
||||
},
|
||||
onBrowserClick = remember(viewModel) {
|
||||
{ viewModel.trySendAction(SetupBrowserAutofillAction.BrowserIntegrationClick(it)) }
|
||||
},
|
||||
@ -120,9 +133,11 @@ fun SetupBrowserAutofillScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun SetupBrowserAutofillContent(
|
||||
state: SetupBrowserAutofillState,
|
||||
onWhyIsThisStepRequiredClick: () -> Unit,
|
||||
onBrowserClick: (BrowserPackage) -> Unit,
|
||||
onContinueClick: () -> Unit,
|
||||
onTurnOnLaterClick: () -> Unit,
|
||||
@ -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,
|
||||
@ -221,6 +245,7 @@ private fun SetupBrowserAutofillContent_preview() {
|
||||
BrowserAutofillSettingsOption.ChromeBeta(enabled = true),
|
||||
),
|
||||
),
|
||||
onWhyIsThisStepRequiredClick = { },
|
||||
onBrowserClick = { },
|
||||
onContinueClick = { },
|
||||
onTurnOnLaterClick = { },
|
||||
|
||||
@ -56,6 +56,10 @@ class SetupBrowserAutofillViewModel @Inject constructor(
|
||||
handleBrowserIntegrationClick(action)
|
||||
}
|
||||
|
||||
SetupBrowserAutofillAction.WhyIsThisStepRequiredClick -> {
|
||||
handleWhyIsThisStepRequiredClick()
|
||||
}
|
||||
|
||||
SetupBrowserAutofillAction.CloseClick -> handleCloseClick()
|
||||
SetupBrowserAutofillAction.DismissDialog -> handleDismissDialog()
|
||||
SetupBrowserAutofillAction.ContinueClick -> handleContinueClick()
|
||||
@ -81,6 +85,10 @@ class SetupBrowserAutofillViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun handleWhyIsThisStepRequiredClick() {
|
||||
sendEvent(SetupBrowserAutofillEvent.NavigateToBrowserIntegrationsInfo)
|
||||
}
|
||||
|
||||
private fun handleCloseClick() {
|
||||
sendEvent(SetupBrowserAutofillEvent.NavigateBack)
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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
|
||||
@ -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) }
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user