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

Commit

Permalink
Closes #9471: Fix Confirm and Alert js dialogs don't show buttons whe…
Browse files Browse the repository at this point in the history
…n the message is too long.
  • Loading branch information
Amejia481 authored and mergify[bot] committed Jan 25, 2021
1 parent 72a4f34 commit d63d0c5
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 153 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.feature.prompts.dialog

import android.annotation.SuppressLint
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.widget.CheckBox
import android.widget.TextView
import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import mozilla.components.feature.prompts.R

internal const val KEY_MANY_ALERTS = "KEY_MANY_ALERTS"
internal const val KEY_USER_CHECK_BOX = "KEY_USER_CHECK_BOX"
/**
* An abstract alert for showing a text message plus a checkbox for handling [hasShownManyDialogs].
*/
internal abstract class AbstractPromptTextDialogFragment : PromptDialogFragment() {

/**
* Tells if a checkbox should be shown for preventing this [sessionId] from showing more dialogs.
*/
internal val hasShownManyDialogs: Boolean by lazy { safeArguments.getBoolean(KEY_MANY_ALERTS) }

/**
* Stores the user's decision from the checkbox
* for preventing this [sessionId] from showing more dialogs.
*/
internal var userSelectionNoMoreDialogs: Boolean
get() = safeArguments.getBoolean(KEY_USER_CHECK_BOX)
set(value) {
safeArguments.putBoolean(KEY_USER_CHECK_BOX, value)
}

/**
* Creates custom view that adds a [TextView] + [CheckBox] and attach the corresponding
* events for handling [hasShownManyDialogs].
*/
@SuppressLint("InflateParams")
internal fun setCustomMessageView(builder: AlertDialog.Builder): AlertDialog.Builder {
val inflater = LayoutInflater.from(requireContext())
val view = inflater.inflate(R.layout.mozac_feature_prompt_with_check_box, null)
val textView = view.findViewById<TextView>(R.id.message)
textView.text = message
textView.movementMethod = ScrollingMovementMethod()

addCheckBoxIfNeeded(view)

builder.setView(view)

return builder
}

internal fun addCheckBoxIfNeeded(
view: View,
@IdRes id: Int = R.id.mozac_feature_prompts_no_more_dialogs_check_box
) {
if ((hasShownManyDialogs)) {
val checkBox = view.findViewById<CheckBox>(id)
checkBox.isVisible = true
checkBox.setOnCheckedChangeListener { _, isChecked ->
userSelectionNoMoreDialogs = isChecked
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,25 @@

package mozilla.components.feature.prompts.dialog

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.CheckBox
import androidx.appcompat.app.AlertDialog
import mozilla.components.feature.prompts.R

private const val KEY_MANY_ALERTS = "KEY_MANY_ALERTS"
private const val KEY_USER_CHECK_BOX = "KEY_USER_CHECK_BOX"

/**
* [android.support.v4.app.DialogFragment] implementation to display web Alerts with native dialogs.
*/
internal class AlertDialogFragment : PromptDialogFragment() {

/**
* Tells if a checkbox should be shown for preventing this [sessionId] from showing more dialogs.
*/
internal val hasShownManyDialogs: Boolean by lazy { safeArguments.getBoolean(KEY_MANY_ALERTS) }

/**
* Stores the user's decision from the checkbox
* for preventing this [sessionId] from showing more dialogs.
*/
private var userSelectionNoMoreDialogs: Boolean
get() = safeArguments.getBoolean(KEY_USER_CHECK_BOX)
set(value) {
safeArguments.putBoolean(KEY_USER_CHECK_BOX, value)
}
internal class AlertDialogFragment : AbstractPromptTextDialogFragment() {

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

val builder = AlertDialog.Builder(requireContext())
.setTitle(title)
.setCancelable(true)
.setMessage(message)
.setPositiveButton(android.R.string.ok) { _, _ ->
onPositiveClickAction()
}
return (if (hasShownManyDialogs) addCheckbox(builder) else builder)
return setCustomMessageView(builder)
.create()
}

Expand All @@ -61,19 +39,6 @@ internal class AlertDialogFragment : PromptDialogFragment() {
}
}

@SuppressLint("InflateParams")
private fun addCheckbox(builder: AlertDialog.Builder): AlertDialog.Builder {
val inflater = LayoutInflater.from(requireContext())
val view = inflater.inflate(R.layout.mozac_feature_many_dialogs_checkbox_dialogs, null)
val checkBox = view.findViewById<CheckBox>(R.id.no_more_dialogs_check_box)
checkBox.setOnCheckedChangeListener { _, isChecked ->
userSelectionNoMoreDialogs = isChecked
}
builder.setView(view)

return builder
}

companion object {
/**
* A builder method for creating a [AlertDialogFragment]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@

package mozilla.components.feature.prompts.dialog

import android.annotation.SuppressLint
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.CheckBox
import androidx.appcompat.app.AlertDialog
import mozilla.components.feature.prompts.R

private const val KEY_MANY_ALERTS = "KEY_MANY_ALERTS"
private const val KEY_SHOULD_DISMISS_ON_LOAD = "KEY_SHOULD_DISMISS_ON_LOAD"
private const val KEY_USER_CHECK_BOX = "KEY_USER_CHECK_BOX"
private const val KEY_POSITIVE_BUTTON_TITLE = "KEY_POSITIVE_BUTTON_TITLE"
private const val KEY_NEGATIVE_BUTTON_TITLE = "KEY_NEGATIVE_BUTTON_TITLE"
private const val KEY_NEUTRAL_BUTTON_TITLE = "KEY_NEUTRAL_BUTTON_TITLE"
Expand All @@ -24,12 +18,7 @@ private const val KEY_NEUTRAL_BUTTON_TITLE = "KEY_NEUTRAL_BUTTON_TITLE"
* [android.support.v4.app.DialogFragment] implementation to display a confirm dialog,
* it can have up to three buttons, they could be positive, negative or neutral.
*/
internal class MultiButtonDialogFragment : PromptDialogFragment() {

/**
* Tells if a checkbox should be shown for preventing this [sessionId] from showing more dialogs.
*/
internal val hasShownManyDialogs: Boolean by lazy { safeArguments.getBoolean(KEY_MANY_ALERTS) }
internal class MultiButtonDialogFragment : AbstractPromptTextDialogFragment() {

internal val positiveButtonTitle: String? by lazy { safeArguments.getString(KEY_POSITIVE_BUTTON_TITLE) }

Expand All @@ -39,23 +28,12 @@ internal class MultiButtonDialogFragment : PromptDialogFragment() {

override fun shouldDismissOnLoad() = safeArguments.getBoolean(KEY_SHOULD_DISMISS_ON_LOAD, true)

/**
* Stores the user's decision from the checkbox
* for preventing this [sessionId] from showing more dialogs.
*/
private var userSelectionNoMoreDialogs: Boolean
get() = safeArguments.getBoolean(KEY_USER_CHECK_BOX)
set(value) {
safeArguments.putBoolean(KEY_USER_CHECK_BOX, value)
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireContext())
.setTitle(title)
.setCancelable(true)
.setMessage(message)
.setupButtons()
return (if (hasShownManyDialogs) addCheckbox(builder) else builder)
return setCustomMessageView(builder)
.create()
}

Expand All @@ -64,19 +42,6 @@ internal class MultiButtonDialogFragment : PromptDialogFragment() {
feature?.onCancel(sessionId)
}

@SuppressLint("InflateParams")
private fun addCheckbox(builder: AlertDialog.Builder): AlertDialog.Builder {
val inflater = LayoutInflater.from(requireContext())
val view = inflater.inflate(R.layout.mozac_feature_many_dialogs_checkbox_dialogs, null)
val checkBox = view.findViewById<CheckBox>(R.id.no_more_dialogs_check_box)
checkBox.setOnCheckedChangeListener { _, isChecked ->
userSelectionNoMoreDialogs = isChecked
}
builder.setView(view)

return builder
}

private fun AlertDialog.Builder.setupButtons(): AlertDialog.Builder {
if (!positiveButtonTitle.isNullOrBlank()) {
setPositiveButton(positiveButtonTitle) { _, _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.View.VISIBLE
import android.widget.CheckBox
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import mozilla.components.feature.prompts.R

private const val KEY_MANY_ALERTS = "KEY_MANY_ALERTS"
private const val KEY_USER_CHECK_BOX = "KEY_USER_CHECK_BOX"
private const val KEY_USER_EDIT_TEXT = "KEY_USER_EDIT_TEXT"
private const val KEY_LABEL_INPUT = "KEY_LABEL_INPUT"
private const val KEY_DEFAULT_INPUT_VALUE = "KEY_DEFAULT_INPUT_VALUE"
Expand All @@ -29,13 +24,7 @@ private const val KEY_DEFAULT_INPUT_VALUE = "KEY_DEFAULT_INPUT_VALUE"
* [androidx.fragment.app.DialogFragment] implementation to display a
* <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt">Window.prompt()</a> with native dialogs.
*/
internal class TextPromptDialogFragment : PromptDialogFragment(), TextWatcher {

/**
* Tells if a checkbox should be shown for preventing this [sessionId] from showing more dialogs.
*/
internal val hasShownManyDialogs: Boolean by lazy { safeArguments.getBoolean(KEY_MANY_ALERTS) }

internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), TextWatcher {
/**
* Contains the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt#Parameters">default()</a>
* value provided by this [sessionId].
Expand All @@ -48,16 +37,6 @@ internal class TextPromptDialogFragment : PromptDialogFragment(), TextWatcher {
*/
internal val labelInput: String? by lazy { safeArguments.getString(KEY_LABEL_INPUT) }

/**
* Stores the user's decision from the checkbox
* for preventing this [sessionId] from showing more dialogs.
*/
internal var userSelectionNoMoreDialogs: Boolean
get() = safeArguments.getBoolean(KEY_USER_CHECK_BOX)
set(value) {
safeArguments.putBoolean(KEY_USER_CHECK_BOX, value)
}

private var userSelectionEditText: String
get() = safeArguments.getString(KEY_USER_EDIT_TEXT, defaultInputValue)
set(value) {
Expand Down Expand Up @@ -94,24 +73,11 @@ internal class TextPromptDialogFragment : PromptDialogFragment(), TextWatcher {
editText.setText(defaultInputValue)
editText.addTextChangedListener(this)

if (hasShownManyDialogs) {
addCheckBox(view)
}
addCheckBoxIfNeeded(view)

return builder.setView(view)
}

@SuppressLint("InflateParams")
private fun addCheckBox(view: View) {
if (hasShownManyDialogs) {
val checkBox = view.findViewById<CheckBox>(R.id.no_more_dialogs_check_box)
checkBox.setOnCheckedChangeListener { _, isChecked ->
userSelectionNoMoreDialogs = isChecked
}
checkBox.visibility = VISIBLE
}
}

override fun afterTextChanged(editable: Editable) {
userSelectionEditText = editable.toString()
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->

<ScrollView 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="?android:attr/listPreferredItemPaddingLeft"
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
android:paddingEnd="?android:attr/listPreferredItemPaddingLeft">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingLeft"
android:paddingEnd="?android:attr/listPreferredItemPaddingLeft">

<TextView
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:maxLines="30"
android:scrollbars="vertical"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Message" />

<CheckBox
android:id="@id/mozac_feature_prompts_no_more_dialogs_check_box"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/mozac_feature_prompts_no_more_dialogs"
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/message"
tools:visibility="visible" />

</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
android:inputType="text"/>

<CheckBox
android:id="@+id/no_more_dialogs_check_box"
android:id="@id/mozac_feature_prompts_no_more_dialogs_check_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/mozac_feature_prompts_no_more_dialogs"
Expand Down
7 changes: 7 additions & 0 deletions components/feature/prompts/src/main/res/values/ids.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<item name="mozac_feature_prompts_no_more_dialogs_check_box" type="id"/>
</resources>
Loading

0 comments on commit d63d0c5

Please sign in to comment.