Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8198: For mozilla-mobile#7134 - Dismiss the current select login prompt request in LoginPicker r=Amejia481 a=ekager



Co-authored-by: ekager <ekager@mozilla.com>
  • Loading branch information
MozLando and ekager committed Aug 26, 2020
2 parents ac895aa + 8e0b301 commit b794c90
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import mozilla.components.concept.storage.Login
import mozilla.components.concept.storage.LoginStorageDelegate
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.Autocomplete
import org.mozilla.geckoview.GeckoResult

/**
* This class exists only to convert incoming [LoginEntry] arguments into [Login]s, then forward
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import androidx.fragment.app.FragmentManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
Expand Down Expand Up @@ -69,16 +67,13 @@ import mozilla.components.support.base.feature.OnNeedToRequestPermissions
import mozilla.components.support.base.feature.PermissionsFeature
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import java.lang.ref.WeakReference
import java.security.InvalidParameterException
import java.util.Date

@VisibleForTesting(otherwise = PRIVATE)
internal const val FRAGMENT_TAG = "mozac_feature_prompt_dialog"

private const val PROGRESS_ALMOST_COMPLETE = 90

/**
* Feature for displaying native dialogs for html elements like: input type
* date, file, time, color, option, menu, authentication, confirmation and alerts.
Expand Down Expand Up @@ -132,7 +127,6 @@ class PromptFeature private constructor(
// These three scopes have identical lifetimes. We do not yet have a way of combining scopes
private var handlePromptScope: CoroutineScope? = null
private var dismissPromptScope: CoroutineScope? = null
private var sessionPromptScope: CoroutineScope? = null
private var activePromptRequest: PromptRequest? = null

internal val promptAbuserDetector = PromptAbuserDetector()
Expand Down Expand Up @@ -243,6 +237,9 @@ class PromptFeature private constructor(
.collect { state ->
state?.content?.let {
if (it.promptRequest != activePromptRequest) {
if (activePromptRequest is SelectLoginPrompt) {
loginPicker?.dismissCurrentLoginSelect(activePromptRequest as SelectLoginPrompt)
}
onPromptRequested(state)
} else if (!it.loading) {
promptAbuserDetector.resetJSAlertAbuseState()
Expand All @@ -252,33 +249,23 @@ class PromptFeature private constructor(
}
}

// Dismiss all prompts when page loads are nearly finished. This prevents prompts from the
// previous page from covering content. See Fenix#5326
// Dismiss all prompts when page URL or session id changes. See Fenix#5326
dismissPromptScope = store.flowScoped { flow ->
flow.mapNotNull { state -> state.findTabOrCustomTabOrSelectedTab(customTabId) }
.ifChanged { it.content.progress }
.filter { it.content.progress >= PROGRESS_ALMOST_COMPLETE }
.collect {
val prompt = activePrompt?.get()
if (prompt?.shouldDismissOnLoad() == true) {
prompt.dismiss()
}
activePrompt?.clear()
loginPicker?.dismissCurrentLoginSelect()
flow.ifAnyChanged { state ->
arrayOf(
state.selectedTabId,
state.findTabOrCustomTabOrSelectedTab(customTabId)?.content?.url
)
}.collect {
if (activePromptRequest is SelectLoginPrompt) {
loginPicker?.dismissCurrentLoginSelect(activePromptRequest as SelectLoginPrompt)
}
}

// Dismiss prompts when a new tab is selected.
sessionPromptScope = store.flowScoped { flow ->
flow.ifChanged { browserState -> browserState.selectedTabId }
.collect {
val prompt = activePrompt?.get()
if (prompt?.shouldDismissOnLoad() == true) {
prompt.dismiss()
}
activePrompt?.clear()
loginPicker?.dismissCurrentLoginSelect()
val prompt = activePrompt?.get()
if (prompt?.shouldDismissOnLoad() == true) {
prompt.dismiss()
}
activePrompt?.clear()
}
}

fragmentManager.findFragmentByTag(FRAGMENT_TAG)?.let { fragment ->
Expand All @@ -295,7 +282,6 @@ class PromptFeature private constructor(
override fun stop() {
handlePromptScope?.cancel()
dismissPromptScope?.cancel()
sessionPromptScope?.cancel()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

package mozilla.components.feature.prompts.login

import androidx.annotation.VisibleForTesting
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.concept.storage.Login
import mozilla.components.feature.prompts.consumePromptFrom
import mozilla.components.support.base.log.logger.Logger

/**
* The [LoginPicker] displays a list of possible logins in a [LoginPickerView] for a site after
Expand All @@ -34,21 +34,13 @@ internal class LoginPicker(
}

internal fun handleSelectLoginRequest(request: PromptRequest.SelectLoginPrompt) {
if (currentRequest != null) {
store.consumePromptFrom(sessionId) {
(it as PromptRequest.SelectLoginPrompt).onDismiss()
}
}
currentRequest = request
loginSelectBar.showPicker(request.logins)
}

@VisibleForTesting
internal var currentRequest: PromptRequest.SelectLoginPrompt? = null

override fun onLoginSelected(login: Login) {
(currentRequest as PromptRequest.SelectLoginPrompt).onConfirm(login)
currentRequest = null
store.consumePromptFrom(sessionId) {
if (it is PromptRequest.SelectLoginPrompt) it.onConfirm(login)
}
loginSelectBar.hidePicker()
}

Expand All @@ -57,13 +49,15 @@ internal class LoginPicker(
dismissCurrentLoginSelect()
}

fun dismissCurrentLoginSelect() {
if (currentRequest != null) {
store.consumePromptFrom(sessionId) {
(it as PromptRequest.SelectLoginPrompt).onDismiss()
@Suppress("TooGenericExceptionCaught")
fun dismissCurrentLoginSelect(promptRequest: PromptRequest.SelectLoginPrompt? = null) {
try {
promptRequest?.let { it.onDismiss() } ?: store.consumePromptFrom(sessionId) {
if (it is PromptRequest.SelectLoginPrompt) it.onDismiss()
}
} catch (e: RuntimeException) {
Logger.error("Can't dismiss this login select prompt", e)
}
currentRequest = null
loginSelectBar.hidePicker()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/login_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingStart="63dp"
android:paddingTop="8dp"
Expand All @@ -18,7 +21,11 @@
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:importantForAutofill="no"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textIsSelectable="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
Expand All @@ -28,12 +35,16 @@
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:importantForAutofill="no"
android:inputType="textPassword"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/username"
tools:text="password"
tools:ignore="TextViewEdits" />
</androidx.constraintlayout.widget.ConstraintLayout>
tools:ignore="TextViewEdits"
tools:text="password" />
</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,78 @@
android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/saved_logins_header"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/mozac_feature_prompts_expand_logins_content_description"
android:drawablePadding="24dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="56dp"
android:text="@string/mozac_feature_prompts_saved_logins"
android:textColor="?android:colorEdgeEffect"
android:textSize="16sp"
app:drawableStartCompat="@drawable/mozac_ic_login"
app:drawableTint="?android:colorEdgeEffect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:id="@+id/login_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mozac_feature_login_multiselect_expand"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:clickable="false"
android:focusable="false"
android:importantForAccessibility="no"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/mozac_ic_arrowhead_down"
app:tint="?android:colorEdgeEffect" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/scroll_child"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/logins_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@id/mozac_feature_login_multiselect_expand"
tools:listitem="@layout/login_selection_list_item" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/saved_logins_header"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/mozac_feature_prompts_expand_logins_content_description"
android:drawablePadding="24dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="56dp"
android:text="@string/mozac_feature_prompts_saved_logins"
android:textColor="?android:colorEdgeEffect"
android:textSize="16sp"
app:drawableStartCompat="@drawable/mozac_ic_login"
app:drawableTint="?android:colorEdgeEffect"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/mozac_feature_login_multiselect_expand"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:clickable="false"
android:focusable="false"
android:importantForAccessibility="no"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/mozac_ic_arrowhead_down"
app:tint="?android:colorEdgeEffect" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/logins_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@id/mozac_feature_login_multiselect_expand"
tools:listitem="@layout/login_selection_list_item" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/manage_logins"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?android:selectableItemBackground"
android:drawablePadding="24dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="0dp"
android:text="@string/mozac_feature_prompts_manage_logins"
android:textColor="?android:textColorPrimary"
android:textSize="16sp"
android:visibility="gone"
app:drawableStartCompat="@drawable/mozac_ic_settings"
app:drawableTint="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/logins_list" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/manage_logins"
android:layout_width="0dp"
android:layout_height="48dp"
android:background="?android:selectableItemBackground"
android:drawablePadding="24dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="0dp"
android:text="@string/mozac_feature_prompts_manage_logins"
android:textColor="?android:textColorPrimary"
android:textSize="16sp"
android:visibility="gone"
app:drawableStartCompat="@drawable/mozac_ic_settings"
app:drawableTint="?android:textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/logins_list" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</merge>
Loading

0 comments on commit b794c90

Please sign in to comment.