Skip to content
This repository was archived by the owner on Nov 1, 2022. It is now read-only.

Commit 0f11c79

Browse files
gabrielluongmergify[bot]
authored andcommitted
Issue #10216: Refactor LoginPickerView to a more generic view SelectablePromptView
1 parent 9de5d1b commit 0f11c79

File tree

9 files changed

+109
-99
lines changed

9 files changed

+109
-99
lines changed

components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import mozilla.components.concept.engine.prompt.PromptRequest.TextPrompt
4242
import mozilla.components.concept.engine.prompt.PromptRequest.TimeSelection
4343
import mozilla.components.concept.storage.Login
4444
import mozilla.components.concept.storage.LoginValidationDelegate
45+
import mozilla.components.feature.prompts.concept.SelectablePromptView
4546
import mozilla.components.feature.prompts.dialog.AlertDialogFragment
4647
import mozilla.components.feature.prompts.dialog.AuthenticationDialogFragment
4748
import mozilla.components.feature.prompts.dialog.ChoiceDialogFragment
@@ -60,7 +61,6 @@ import mozilla.components.feature.prompts.dialog.TimePickerDialogFragment
6061
import mozilla.components.feature.prompts.file.FilePicker
6162
import mozilla.components.feature.prompts.login.LoginExceptions
6263
import mozilla.components.feature.prompts.login.LoginPicker
63-
import mozilla.components.feature.prompts.login.LoginPickerView
6464
import mozilla.components.feature.prompts.share.DefaultShareDelegate
6565
import mozilla.components.feature.prompts.share.ShareDelegate
6666
import mozilla.components.lib.state.ext.flowScoped
@@ -107,7 +107,8 @@ internal const val FRAGMENT_TAG = "mozac_feature_prompt_dialog"
107107
* 'save login'prompts will not be shown.
108108
* @property loginExceptionStorage An implementation of [LoginExceptions] that saves and checks origins
109109
* the user does not want to see a save login dialog for.
110-
* @property loginPickerView The [LoginPickerView] used for [LoginPicker] to display select login options.
110+
* @property loginPickerView The [SelectablePromptView] used for [LoginPicker] to display a
111+
* selectable prompt list of login options.
111112
* @property onManageLogins A callback invoked when a user selects "manage logins" from the
112113
* select login prompt.
113114
* @property onNeedToRequestPermissions A callback invoked when permissions
@@ -124,7 +125,7 @@ class PromptFeature private constructor(
124125
override val loginValidationDelegate: LoginValidationDelegate? = null,
125126
private val isSaveLoginEnabled: () -> Boolean = { false },
126127
override val loginExceptionStorage: LoginExceptions? = null,
127-
private val loginPickerView: LoginPickerView? = null,
128+
private val loginPickerView: SelectablePromptView<Login>? = null,
128129
private val onManageLogins: () -> Unit = {},
129130
onNeedToRequestPermissions: OnNeedToRequestPermissions
130131
) : LifecycleAwareFeature, PermissionsFeature, Prompter, ActivityResultHandler,
@@ -151,7 +152,7 @@ class PromptFeature private constructor(
151152
loginValidationDelegate: LoginValidationDelegate? = null,
152153
isSaveLoginEnabled: () -> Boolean = { false },
153154
loginExceptionStorage: LoginExceptions? = null,
154-
loginPickerView: LoginPickerView? = null,
155+
loginPickerView: SelectablePromptView<Login>? = null,
155156
onManageLogins: () -> Unit = {},
156157
onNeedToRequestPermissions: OnNeedToRequestPermissions
157158
) : this(
@@ -177,7 +178,7 @@ class PromptFeature private constructor(
177178
loginValidationDelegate: LoginValidationDelegate? = null,
178179
isSaveLoginEnabled: () -> Boolean = { false },
179180
loginExceptionStorage: LoginExceptions? = null,
180-
loginPickerView: LoginPickerView? = null,
181+
loginPickerView: SelectablePromptView<Login>? = null,
181182
onManageLogins: () -> Unit = {},
182183
onNeedToRequestPermissions: OnNeedToRequestPermissions
183184
) : this(
@@ -201,7 +202,7 @@ class PromptFeature private constructor(
201202
store: BrowserStore,
202203
customTabId: String? = null,
203204
fragmentManager: FragmentManager,
204-
loginPickerView: LoginPickerView? = null,
205+
loginPickerView: SelectablePromptView<Login>? = null,
205206
onManageLogins: () -> Unit = {},
206207
onNeedToRequestPermissions: OnNeedToRequestPermissions
207208
) : this(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
package mozilla.components.feature.prompts.concept
6+
7+
import android.view.View
8+
9+
/**
10+
* An interface for views that can display an option selection prompt.
11+
*/
12+
interface SelectablePromptView<T> {
13+
14+
var listener: Listener<T>?
15+
16+
/**
17+
* Shows an option selection prompt with the provided options.
18+
*
19+
* @param options A list of options to display in the prompt.
20+
*/
21+
fun showPrompt(options: List<T>)
22+
23+
/**
24+
* Hides the option selection prompt.
25+
*/
26+
fun hidePrompt()
27+
28+
/**
29+
* Casts this [SelectablePromptView] interface to an Android [View] object.
30+
*/
31+
fun asView(): View = (this as View)
32+
33+
/**
34+
* Tries to inflate the view if needed.
35+
*
36+
* See: https://github.com/mozilla-mobile/android-components/issues/5491
37+
*
38+
* @return true if the inflation was completed, false if the view was already inflated.
39+
*/
40+
fun tryInflate(): Boolean
41+
42+
/**
43+
* Interface to allow a class to listen to the option selection prompt events.
44+
*/
45+
interface Listener<in T> {
46+
/**
47+
* Called when an user selects an options from the prompt.
48+
*
49+
* @param option The selected option.
50+
*/
51+
fun onOptionSelect(option: T)
52+
53+
/**
54+
* Called when the user invokes the option to manage the list of options.
55+
*/
56+
fun onManageOptions()
57+
}
58+
}

components/feature/prompts/src/main/java/mozilla/components/feature/prompts/login/LoginPicker.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,45 @@ package mozilla.components.feature.prompts.login
77
import mozilla.components.browser.state.store.BrowserStore
88
import mozilla.components.concept.engine.prompt.PromptRequest
99
import mozilla.components.concept.storage.Login
10+
import mozilla.components.feature.prompts.concept.SelectablePromptView
1011
import mozilla.components.feature.prompts.consumePromptFrom
1112
import mozilla.components.support.base.log.logger.Logger
1213

1314
/**
14-
* The [LoginPicker] displays a list of possible logins in a [LoginPickerView] for a site after
15+
* The [LoginPicker] displays a list of possible logins in a [SelectablePromptView] for a site after
1516
* receiving a [PromptRequest.SelectLoginPrompt] when a user clicks into a login field and we have
1617
* matching logins. It allows the user to select which one of these logins they would like to fill,
1718
* or select an option to manage their logins.
1819
*
1920
* @property store The [BrowserStore] this feature should subscribe to.
20-
* @property loginSelectBar The [LoginPickerView] view into which the select login "prompt" will be inflated.
21+
* @property loginSelectBar The [SelectablePromptView] view into which the select login "prompt" will be inflated.
2122
* @property manageLoginsCallback A callback invoked when a user selects "manage logins" from the
2223
* select login prompt.
2324
* @property sessionId This is the id of the session which requested the prompt.
2425
*/
2526
internal class LoginPicker(
2627
private val store: BrowserStore,
27-
private val loginSelectBar: LoginPickerView,
28+
private val loginSelectBar: SelectablePromptView<Login>,
2829
private val manageLoginsCallback: () -> Unit = {},
2930
private var sessionId: String? = null
30-
) : LoginPickerView.Listener {
31+
) : SelectablePromptView.Listener<Login> {
3132

3233
init {
3334
loginSelectBar.listener = this
3435
}
3536

3637
internal fun handleSelectLoginRequest(request: PromptRequest.SelectLoginPrompt) {
37-
loginSelectBar.showPicker(request.logins)
38+
loginSelectBar.showPrompt(request.logins)
3839
}
3940

40-
override fun onLoginSelected(login: Login) {
41+
override fun onOptionSelect(option: Login) {
4142
store.consumePromptFrom(sessionId) {
42-
if (it is PromptRequest.SelectLoginPrompt) it.onConfirm(login)
43+
if (it is PromptRequest.SelectLoginPrompt) it.onConfirm(option)
4344
}
44-
loginSelectBar.hidePicker()
45+
loginSelectBar.hidePrompt()
4546
}
4647

47-
override fun onManageLogins() {
48+
override fun onManageOptions() {
4849
manageLoginsCallback.invoke()
4950
dismissCurrentLoginSelect()
5051
}
@@ -58,6 +59,6 @@ internal class LoginPicker(
5859
} catch (e: RuntimeException) {
5960
Logger.error("Can't dismiss this login select prompt", e)
6061
}
61-
loginSelectBar.hidePicker()
62+
loginSelectBar.hidePrompt()
6263
}
6364
}

components/feature/prompts/src/main/java/mozilla/components/feature/prompts/login/LoginPickerView.kt

Lines changed: 0 additions & 55 deletions
This file was deleted.

components/feature/prompts/src/main/java/mozilla/components/feature/prompts/login/LoginSelectBar.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@ import androidx.recyclerview.widget.LinearLayoutManager
2020
import androidx.recyclerview.widget.RecyclerView
2121
import mozilla.components.concept.storage.Login
2222
import mozilla.components.feature.prompts.R
23+
import mozilla.components.feature.prompts.concept.SelectablePromptView
2324
import mozilla.components.support.ktx.android.view.hideKeyboard
2425

2526
/**
26-
* A customizable multiple login selection bar implementing [LoginPickerView].
27+
* A customizable multiple login selection bar implementing [SelectablePromptView].
2728
*/
2829
class LoginSelectBar @JvmOverloads constructor(
2930
context: Context,
3031
attrs: AttributeSet? = null,
3132
defStyleAttr: Int = 0
32-
) : ConstraintLayout(context, attrs, defStyleAttr), LoginPickerView {
33+
) : ConstraintLayout(context, attrs, defStyleAttr), SelectablePromptView<Login> {
3334

3435
var headerTextStyle: Int? = null
3536

@@ -48,16 +49,16 @@ class LoginSelectBar @JvmOverloads constructor(
4849
}
4950
}
5051

51-
override var listener: LoginPickerView.Listener? = null
52+
override var listener: SelectablePromptView.Listener<Login>? = null
5253

53-
override fun showPicker(list: List<Login>) {
54+
override fun showPrompt(options: List<Login>) {
5455
tryInflate().also {
55-
listAdapter.submitList(list)
56+
listAdapter.submitList(options)
5657
loginPickerView?.isVisible = true
5758
}
5859
}
5960

60-
override fun hidePicker() {
61+
override fun hidePrompt() {
6162
this.isVisible = false
6263
loginsList?.isVisible = false
6364
listAdapter.submitList(mutableListOf())
@@ -76,7 +77,7 @@ class LoginSelectBar @JvmOverloads constructor(
7677
private var expandArrowHead: AppCompatImageView? = null
7778

7879
private var listAdapter = BasicLoginAdapter {
79-
listener?.onLoginSelected(it)
80+
listener?.onOptionSelect(it)
8081
}
8182

8283
override fun tryInflate(): Boolean {
@@ -93,7 +94,7 @@ class LoginSelectBar @JvmOverloads constructor(
9394
private fun bindViews() {
9495
manageLoginsButton = findViewById<AppCompatTextView>(R.id.manage_logins).apply {
9596
setOnClickListener {
96-
listener?.onManageLogins()
97+
listener?.onManageOptions()
9798
}
9899
}
99100
loginsList = findViewById(R.id.logins_list)

components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import mozilla.components.feature.prompts.dialog.PromptDialogFragment
5050
import mozilla.components.feature.prompts.dialog.SaveLoginDialogFragment
5151
import mozilla.components.feature.prompts.file.FilePicker.Companion.FILE_PICKER_ACTIVITY_REQUEST_CODE
5252
import mozilla.components.feature.prompts.login.LoginPicker
53-
import mozilla.components.feature.prompts.login.LoginPickerView
53+
import mozilla.components.feature.prompts.concept.SelectablePromptView
5454
import mozilla.components.feature.prompts.share.ShareDelegate
5555
import mozilla.components.support.test.any
5656
import mozilla.components.support.test.eq
@@ -273,7 +273,7 @@ class PromptFeatureTest {
273273
@Test
274274
fun `GIVEN loginPickerView is visible WHEN dismissLoginSelectPrompt THEN dismissCurrentLoginSelect called and true returned`() {
275275
// given
276-
val loginPickerView: LoginPickerView = mock()
276+
val loginPickerView: SelectablePromptView<Login> = mock()
277277
val feature = spy(
278278
PromptFeature(
279279
mock<Activity>(),
@@ -299,7 +299,7 @@ class PromptFeatureTest {
299299
@Test
300300
fun `GIVEN loginPickerView is not visible WHEN dismissLoginSelectPrompt THEN dismissCurrentLoginSelect called and false returned`() {
301301
// given
302-
val loginPickerView: LoginPickerView = mock()
302+
val loginPickerView: SelectablePromptView<Login> = mock()
303303
val feature = spy(
304304
PromptFeature(
305305
mock<Activity>(),
@@ -324,7 +324,7 @@ class PromptFeatureTest {
324324
@Test
325325
fun `GIVEN PromptFeature WHEN onBackPressed THEN dismissLoginSelectPrompt is called`() {
326326
// given
327-
val loginPickerView: LoginPickerView = mock()
327+
val loginPickerView: SelectablePromptView<Login> = mock()
328328
val feature = spy(
329329
PromptFeature(
330330
mock<Activity>(),
@@ -349,7 +349,7 @@ class PromptFeatureTest {
349349

350350
@Test
351351
fun `Calling dismissLoginSelectPrompt should dismiss the login picker if the login prompt is active`() {
352-
val loginPickerView: LoginPickerView = mock()
352+
val loginPickerView: SelectablePromptView<Login> = mock()
353353
val feature = spy(
354354
PromptFeature(
355355
mock<Activity>(),
@@ -1096,7 +1096,7 @@ class PromptFeatureTest {
10961096

10971097
@Test
10981098
fun `When page is refreshed login dialog is dismissed`() {
1099-
val loginPickerView: LoginPickerView = mock()
1099+
val loginPickerView: SelectablePromptView<Login> = mock()
11001100
val feature =
11011101
PromptFeature(
11021102
activity = mock(), store = store, fragmentManager = fragmentManager,

components/feature/prompts/src/test/java/mozilla/components/feature/prompts/login/LoginPickerTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ class LoginPickerTest {
6161
whenever(state.customTabs).thenReturn(listOf(customTab))
6262
loginPicker = LoginPicker(store, loginSelectBar, onManageLogins, customTab.id)
6363
loginPicker.handleSelectLoginRequest(request)
64-
verify(loginSelectBar).showPicker(request.logins)
64+
verify(loginSelectBar).showPrompt(request.logins)
6565
}
6666

6767
@Test
6868
fun `LoginPicker shows the login select bar on a selected tab`() {
6969
prepareSelectedSession(request)
7070
loginPicker = LoginPicker(store, loginSelectBar, onManageLogins)
7171
loginPicker.handleSelectLoginRequest(request)
72-
verify(loginSelectBar).showPicker(request.logins)
72+
verify(loginSelectBar).showPrompt(request.logins)
7373
}
7474

7575
@Test
@@ -79,10 +79,10 @@ class LoginPickerTest {
7979

8080
loginPicker.handleSelectLoginRequest(request)
8181

82-
loginPicker.onLoginSelected(login)
82+
loginPicker.onOptionSelect(login)
8383

8484
assertEquals(confirmedLogin, login)
85-
verify(loginSelectBar).hidePicker()
85+
verify(loginSelectBar).hidePrompt()
8686
}
8787

8888
@Test
@@ -95,11 +95,11 @@ class LoginPickerTest {
9595

9696
loginPicker.handleSelectLoginRequest(request)
9797

98-
loginPicker.onManageLogins()
98+
loginPicker.onManageOptions()
9999

100100
assertTrue(manageLoginsCalled)
101101
assertTrue(onDismissWasCalled)
102-
verify(loginSelectBar).hidePicker()
102+
verify(loginSelectBar).hidePrompt()
103103
}
104104

105105
private fun prepareSelectedSession(request: PromptRequest? = null): TabSessionState {

0 commit comments

Comments
 (0)