Skip to content

Commit

Permalink
Launch import flow from Password management screen
Browse files Browse the repository at this point in the history
  • Loading branch information
CDRussell committed Oct 4, 2024
1 parent 04c0006 commit bdf9d39
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 6 deletions.
1 change: 1 addition & 0 deletions autofill/autofill-impl/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ plugins {
id 'com.android.library'
id 'kotlin-android'
id 'com.squareup.anvil'
id 'kotlin-parcelize'
}

apply from: "$rootProject.projectDir/gradle/android-library.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.duckduckgo.autofill.impl.ui.credential.management

import android.os.Parcelable
import android.util.Patterns
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
Expand All @@ -37,6 +38,7 @@ import com.duckduckgo.autofill.impl.InternalAutofillCapabilityChecker
import com.duckduckgo.autofill.impl.R
import com.duckduckgo.autofill.impl.deviceauth.DeviceAuthenticator
import com.duckduckgo.autofill.impl.deviceauth.DeviceAuthenticator.AuthConfiguration
import com.duckduckgo.autofill.impl.importing.gpm.feature.AutofillImportPasswordsFeature
import com.duckduckgo.autofill.impl.pixel.AutofillPixelNames
import com.duckduckgo.autofill.impl.pixel.AutofillPixelNames.AUTOFILL_DELETE_LOGIN
import com.duckduckgo.autofill.impl.pixel.AutofillPixelNames.AUTOFILL_ENABLE_AUTOFILL_TOGGLE_MANUALLY_DISABLED
Expand Down Expand Up @@ -113,6 +115,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import timber.log.Timber

@ContributesViewModel(ActivityScope::class)
Expand All @@ -135,6 +138,7 @@ class AutofillSettingsViewModel @Inject constructor(
private val autofillBreakageReportDataStore: AutofillSiteBreakageReportingDataStore,
private val autofillBreakageReportCanShowRules: AutofillBreakageReportCanShowRules,
private val autofillCapabilityChecker: InternalAutofillCapabilityChecker,
private val importPasswordsFeature: AutofillImportPasswordsFeature,
) : ViewModel() {

private val _viewState = MutableStateFlow(ViewState())
Expand Down Expand Up @@ -696,7 +700,18 @@ class AutofillSettingsViewModel @Inject constructor(
}

fun onImportPasswords() {
addCommand(LaunchImportPasswords)
viewModelScope.launch(dispatchers.io()) {
with(importPasswordsFeature) {
val csvImport = self().isEnabled() && canImportFromCsvFile().isEnabled()
val gpmImport = self().isEnabled() && canImportFromGooglePasswordManager().isEnabled()
val importConfig = ImportPasswordConfig(canImportFromCsv = csvImport, canImportFromGooglePasswordManager = gpmImport)
addCommand(LaunchImportPasswords(importConfig))

// addCommand(LaunchImportPasswords(ImportPasswordConfig(canImportFromCsv = false, canImportFromGooglePasswordManager = false)))
// addCommand(LaunchImportPasswords(ImportPasswordConfig(canImportFromCsv = false, canImportFromGooglePasswordManager = true)))
// addCommand(LaunchImportPasswords(ImportPasswordConfig(canImportFromCsv = true, canImportFromGooglePasswordManager = false)))
}
}
}

fun onReportBreakageClicked() {
Expand All @@ -708,7 +723,10 @@ class AutofillSettingsViewModel @Inject constructor(
}
}

fun updateCurrentSite(currentUrl: String?, privacyProtectionEnabled: Boolean?) {
fun updateCurrentSite(
currentUrl: String?,
privacyProtectionEnabled: Boolean?,
) {
val updatedReportBreakageState = _viewState.value.reportBreakageState.copy(
currentUrl = currentUrl,
privacyProtectionEnabled = privacyProtectionEnabled,
Expand Down Expand Up @@ -861,12 +879,19 @@ class AutofillSettingsViewModel @Inject constructor(
data object LaunchResetNeverSaveListConfirmation : ListModeCommand()
data class LaunchDeleteAllPasswordsConfirmation(val numberToDelete: Int) : ListModeCommand()
data class PromptUserToAuthenticateMassDeletion(val authConfiguration: AuthConfiguration) : ListModeCommand()
data object LaunchImportPasswords : ListModeCommand()
data class LaunchImportPasswords(val config: ImportPasswordConfig) : ListModeCommand()

data class LaunchReportAutofillBreakageConfirmation(val eTldPlusOne: String) : ListModeCommand()
data object ShowUserReportSentMessage : ListModeCommand()
data object ReevalutePromotions : ListModeCommand()
}

@Parcelize
data class ImportPasswordConfig(
val canImportFromGooglePasswordManager: Boolean,
val canImportFromCsv: Boolean,
) : Parcelable

sealed class DuckAddressStatus {
object NotADuckAddress : DuckAddressStatus()
data class FetchingActivationStatus(val address: String) : DuckAddressStatus()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.BundleCompat
import androidx.core.text.toSpanned
import androidx.core.view.MenuProvider
import androidx.core.view.children
import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMargins
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle.State
import androidx.lifecycle.ViewModelProvider
Expand All @@ -56,6 +58,7 @@ import com.duckduckgo.autofill.impl.ui.credential.management.AutofillManagementR
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillManagementRecyclerAdapter.ContextMenuAction.Delete
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillManagementRecyclerAdapter.ContextMenuAction.Edit
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillSettingsViewModel
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillSettingsViewModel.ImportPasswordConfig
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillSettingsViewModel.ListModeCommand.LaunchDeleteAllPasswordsConfirmation
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillSettingsViewModel.ListModeCommand.LaunchImportPasswords
import com.duckduckgo.autofill.impl.ui.credential.management.AutofillSettingsViewModel.ListModeCommand.LaunchReportAutofillBreakageConfirmation
Expand All @@ -68,6 +71,10 @@ import com.duckduckgo.autofill.impl.ui.credential.management.sorting.CredentialG
import com.duckduckgo.autofill.impl.ui.credential.management.sorting.InitialExtractor
import com.duckduckgo.autofill.impl.ui.credential.management.suggestion.SuggestionListBuilder
import com.duckduckgo.autofill.impl.ui.credential.management.suggestion.SuggestionMatcher
import com.duckduckgo.autofill.impl.ui.credential.management.viewing.SelectImportPasswordMethodDialog.Companion.Result
import com.duckduckgo.autofill.impl.ui.credential.management.viewing.SelectImportPasswordMethodDialog.Companion.Result.UserChoseCsvImport
import com.duckduckgo.autofill.impl.ui.credential.management.viewing.SelectImportPasswordMethodDialog.Companion.Result.UserChoseDesktopSyncImport
import com.duckduckgo.autofill.impl.ui.credential.management.viewing.SelectImportPasswordMethodDialog.Companion.Result.UserChoseGcmImport
import com.duckduckgo.browser.api.ui.BrowserScreens.WebViewActivityWithParams
import com.duckduckgo.common.ui.DuckDuckGoFragment
import com.duckduckgo.common.ui.view.SearchBar
Expand Down Expand Up @@ -243,6 +250,23 @@ class AutofillManagementListMode : DuckDuckGoFragment(R.layout.fragment_autofill
viewModel.onImportPasswords()
pixel.fire(AUTOFILL_IMPORT_PASSWORDS_CTA_BUTTON)
}

setFragmentResultListener(SelectImportPasswordMethodDialog.RESULT_KEY) { _, result ->
when (val importResult = BundleCompat.getParcelable(result, SelectImportPasswordMethodDialog.RESULT_KEY_DETAILS, Result::class.java)) {
is UserChoseGcmImport -> userImportViaGcm(importResult.numberImported)
is UserChoseCsvImport -> userImportedViaCsv(importResult.numberImported)
is UserChoseDesktopSyncImport -> launchImportPasswordsFromDesktopSyncScreen()
else -> {}
}
}
}

private fun userImportedViaCsv(numberImported: Int) {
Snackbar.make(binding.root, getString(R.string.autofillImportCsvPasswordsSuccessMessage, numberImported), Snackbar.LENGTH_LONG).show()
}

private fun userImportViaGcm(numberImported: Int) {
Snackbar.make(binding.root, getString(R.string.autofillImportGooglePasswordsSuccessMessage, numberImported), Snackbar.LENGTH_LONG).show()
}

private fun configureToolbar() {
Expand Down Expand Up @@ -384,7 +408,7 @@ class AutofillManagementListMode : DuckDuckGoFragment(R.layout.fragment_autofill
LaunchResetNeverSaveListConfirmation -> launchResetNeverSavedSitesConfirmation()
is LaunchDeleteAllPasswordsConfirmation -> launchDeleteAllLoginsConfirmationDialog(command.numberToDelete)
is PromptUserToAuthenticateMassDeletion -> promptUserToAuthenticateMassDeletion(command.authConfiguration)
is LaunchImportPasswords -> launchImportPasswordsScreen()
is LaunchImportPasswords -> launchImportPasswordsScreen(command.config)
is LaunchReportAutofillBreakageConfirmation -> launchReportBreakageConfirmation(command.eTldPlusOne)
is ShowUserReportSentMessage -> showUserReportSentMessage()
is ReevalutePromotions -> configurePromotionsContainer()
Expand All @@ -396,7 +420,19 @@ class AutofillManagementListMode : DuckDuckGoFragment(R.layout.fragment_autofill
Snackbar.make(binding.root, R.string.autofillManagementReportBreakageSuccessMessage, Snackbar.LENGTH_LONG).show()
}

private fun launchImportPasswordsScreen() {
private fun launchImportPasswordsScreen(config: ImportPasswordConfig) {
context?.let {
if (!config.canImportFromGooglePasswordManager && !config.canImportFromCsv) {
// fallback to existing import screen
launchImportPasswordsFromDesktopSyncScreen()
} else {
val dialog = SelectImportPasswordMethodDialog.instance(config)
dialog.show(parentFragmentManager, "SelectImportPasswordMethodDialog")
}
}
}

private fun launchImportPasswordsFromDesktopSyncScreen() {
context?.let {
globalActivityStarter.start(it, ImportPasswordActivityParams)
}
Expand Down Expand Up @@ -607,7 +643,11 @@ class AutofillManagementListMode : DuckDuckGoFragment(R.layout.fragment_autofill
}

companion object {
fun instance(currentUrl: String? = null, privacyProtectionEnabled: Boolean?, source: AutofillSettingsLaunchSource? = null) =
fun instance(
currentUrl: String? = null,
privacyProtectionEnabled: Boolean?,
source: AutofillSettingsLaunchSource? = null,
) =
AutofillManagementListMode().apply {
arguments = Bundle().apply {
putString(ARG_CURRENT_URL, currentUrl)
Expand Down
Loading

0 comments on commit bdf9d39

Please sign in to comment.