Loading components/feature/addons/build.gradle +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ android { dependencies { implementation Dependencies.androidx_appcompat implementation Dependencies.kotlin_stdlib implementation Dependencies.kotlin_coroutines Loading samples/browser/src/main/java/org/mozilla/samples/browser/addons/AddOnsFragment.kt +52 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ package org.mozilla.samples.browser.addons import android.content.Intent import android.os.Bundle import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup Loading @@ -22,6 +23,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.feature.addons.AddOn import org.mozilla.samples.browser.R import org.mozilla.samples.browser.addons.PermissionsDialogFragment.PromptsStyling import org.mozilla.samples.browser.ext.components /** Loading @@ -44,6 +46,14 @@ class AddOnsFragment : Fragment(), View.OnClickListener { bindRecyclerView(rootView) } override fun onStart() { super.onStart() findPreviousDialogFragment()?.let { dialog -> dialog.onPositiveButtonClicked = onPositiveButtonClicked dialog.onNegativeButtonClicked = onNegativeButtonClicked } } private fun bindRecyclerView(rootView: View) { recyclerView = rootView.findViewById(R.id.add_ons_list) recyclerView.layoutManager = LinearLayoutManager(requireContext()) Loading Loading @@ -140,8 +150,8 @@ class AddOnsFragment : Fragment(), View.OnClickListener { val context = view.context when (view.id) { R.id.add_button -> { Toast.makeText(this.requireContext(), "Installing add-on", Toast.LENGTH_SHORT) .show() val addOn = (((view.parent) as View).tag as AddOn) showPermissionDialog(addOn) } R.id.add_on_item -> { val intent = Intent(context, InstalledAddOnDetailsActivity::class.java) Loading @@ -152,4 +162,44 @@ class AddOnsFragment : Fragment(), View.OnClickListener { } } } private fun isAlreadyADialogCreated(): Boolean { return findPreviousDialogFragment() != null } private fun findPreviousDialogFragment(): PermissionsDialogFragment? { return fragmentManager?.findFragmentByTag(PERMISSIONS_DIALOG_FRAGMENT_TAG) as? PermissionsDialogFragment } private fun showPermissionDialog(addOn: AddOn) { val dialog = PermissionsDialogFragment.newInstance( addOnId = addOn.id, title = addOn.translatableName.translate(), permissions = addOn.translatePermissions(), promptsStyling = PromptsStyling( gravity = Gravity.BOTTOM, shouldWidthMatchParent = true ), onPositiveButtonClicked = onPositiveButtonClicked, onNegativeButtonClicked = onNegativeButtonClicked ) if (!isAlreadyADialogCreated() && fragmentManager != null) { dialog.show(requireFragmentManager(), PERMISSIONS_DIALOG_FRAGMENT_TAG) } } private val onPositiveButtonClicked: ((String) -> Unit) = { addonId -> Toast.makeText(this.requireContext(), "Installing add-on $addonId", Toast.LENGTH_SHORT) .show() } private val onNegativeButtonClicked = { Toast.makeText(this.requireContext(), "Cancel button clicked", Toast.LENGTH_SHORT) .show() } companion object { private const val PERMISSIONS_DIALOG_FRAGMENT_TAG = "ADDONS_PERMISSIONS_DIALOG_FRAGMENT" } } samples/browser/src/main/java/org/mozilla/samples/browser/addons/PermissionsDialogFragment.kt 0 → 100644 +231 −0 Original line number Diff line number Diff line /* 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 org.mozilla.samples.browser.addons import android.annotation.SuppressLint import android.app.Dialog import android.content.DialogInterface import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.GradientDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.Window import android.widget.TextView import android.view.ViewGroup import android.widget.Button import android.widget.LinearLayout.LayoutParams import androidx.annotation.ColorRes import androidx.appcompat.app.AppCompatDialogFragment import androidx.core.content.ContextCompat import org.mozilla.samples.browser.R internal const val KEY_ADD_ON_ID = "KEY_ADD_ON_ID" internal const val KEY_TITLE = "KEY_TITLE" private const val KEY_DIALOG_GRAVITY = "KEY_DIALOG_GRAVITY" private const val KEY_DIALOG_WIDTH_MATCH_PARENT = "KEY_DIALOG_WIDTH_MATCH_PARENT" private const val KEY_PERMISSIONS = "KEY_PERMISSIONS" private const val KEY_POSITIVE_BUTTON_BACKGROUND_COLOR = "KEY_POSITIVE_BUTTON_BACKGROUND_COLOR" private const val KEY_POSITIVE_BUTTON_TEXT_COLOR = "KEY_POSITIVE_BUTTON_TEXT_COLOR" private const val KEY_POSITIVE_BUTTON_RADIUS = "KEY_POSITIVE_BUTTON_RADIUS" private const val DEFAULT_VALUE = Int.MAX_VALUE internal class PermissionsDialogFragment : AppCompatDialogFragment() { internal var onPositiveButtonClicked: ((String) -> Unit)? = null internal var onNegativeButtonClicked: (() -> Unit)? = null private val safeArguments get() = requireNotNull(arguments) internal val addOnId get() = safeArguments.getString(KEY_ADD_ON_ID, "") internal val positiveButtonRadius get() = safeArguments.getFloat(KEY_POSITIVE_BUTTON_RADIUS, DEFAULT_VALUE.toFloat()) internal val permissions: IntArray get() = safeArguments.getIntArray(KEY_PERMISSIONS) ?: intArrayOf() internal val title: String get() = safeArguments.getString(KEY_TITLE, "") internal val dialogGravity: Int get() = safeArguments.getInt(KEY_DIALOG_GRAVITY, DEFAULT_VALUE) internal val dialogShouldWidthMatchParent: Boolean get() = safeArguments.getBoolean(KEY_DIALOG_WIDTH_MATCH_PARENT) internal val positiveButtonBackgroundColor get() = safeArguments.getInt(KEY_POSITIVE_BUTTON_BACKGROUND_COLOR, DEFAULT_VALUE) internal val positiveButtonTextColor get() = safeArguments.getInt(KEY_POSITIVE_BUTTON_TEXT_COLOR, DEFAULT_VALUE) override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val sheetDialog = Dialog(requireContext()) sheetDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) sheetDialog.setCanceledOnTouchOutside(true) val rootView = createContainer() sheetDialog.setContainerView(rootView) sheetDialog.window?.apply { if (dialogGravity != DEFAULT_VALUE) { setGravity(dialogGravity) } if (dialogShouldWidthMatchParent) { setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // This must be called after addContentView, or it won't fully fill to the edge. setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) } } return sheetDialog } override fun onDismiss(dialog: DialogInterface) { super.onDismiss(dialog) onNegativeButtonClicked?.invoke() } private fun Dialog.setContainerView(rootView: View) { if (dialogShouldWidthMatchParent) { setContentView(rootView) } else { addContentView( rootView, LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) ) } } @SuppressLint("InflateParams") private fun createContainer(): View { val rootView = LayoutInflater.from(requireContext()).inflate( R.layout.fragment_dialog_addon_permissions, null, false ) rootView.findViewById<TextView>(R.id.title).text = requireContext().getString(R.string.addon_permissions_dialog_title, title) rootView.findViewById<TextView>(R.id.permissions).text = buildPermissionsText() val positiveButton = rootView.findViewById<Button>(R.id.allow_button) val negativeButton = rootView.findViewById<Button>(R.id.deny_button) positiveButton.setOnClickListener { onPositiveButtonClicked?.invoke(addOnId) dismiss() } if (positiveButtonBackgroundColor != DEFAULT_VALUE) { val backgroundTintList = ContextCompat.getColorStateList(requireContext(), positiveButtonBackgroundColor) positiveButton.backgroundTintList = backgroundTintList } if (positiveButtonTextColor != DEFAULT_VALUE) { val color = ContextCompat.getColor(requireContext(), positiveButtonTextColor) positiveButton.setTextColor(color) } if (positiveButtonRadius != DEFAULT_VALUE.toFloat()) { val shape = GradientDrawable() shape.shape = GradientDrawable.RECTANGLE shape.setColor( ContextCompat.getColor( requireContext(), positiveButtonBackgroundColor ) ) shape.cornerRadius = positiveButtonRadius positiveButton.background = shape } negativeButton.setOnClickListener { onNegativeButtonClicked?.invoke() dismiss() } return rootView } private fun buildPermissionsText(): String { var permissionsText = getString(R.string.addon_permissions_dialog_subtitle) + "\n\n" permissions.forEachIndexed { index, item -> val brakeLine = if (index + 1 != permissions.size) "\n\n" else "" val permissionText = requireContext().getString(item) permissionsText += "• $permissionText $brakeLine" } return permissionsText } @Suppress("LongParameterList") companion object { fun newInstance( addOnId: String, title: String, permissions: List<Int>, promptsStyling: PromptsStyling? = null, onPositiveButtonClicked: ((String) -> Unit)? = null, onNegativeButtonClicked: (() -> Unit)? = null ): PermissionsDialogFragment { val fragment = PermissionsDialogFragment() val arguments = fragment.arguments ?: Bundle() arguments.apply { putString(KEY_ADD_ON_ID, addOnId) putString(KEY_TITLE, title) putIntArray(KEY_PERMISSIONS, permissions.toIntArray()) promptsStyling?.gravity?.apply { putInt(KEY_DIALOG_GRAVITY, this) } promptsStyling?.shouldWidthMatchParent?.apply { putBoolean(KEY_DIALOG_WIDTH_MATCH_PARENT, this) } promptsStyling?.positiveButtonBackgroundColor?.apply { putInt(KEY_POSITIVE_BUTTON_BACKGROUND_COLOR, this) } promptsStyling?.positiveButtonTextColor?.apply { putInt(KEY_POSITIVE_BUTTON_TEXT_COLOR, this) } println(permissions) } fragment.onPositiveButtonClicked = onPositiveButtonClicked fragment.onNegativeButtonClicked = onNegativeButtonClicked fragment.arguments = arguments return fragment } } /** * Styling for the permissions dialog. */ data class PromptsStyling( val gravity: Int, val shouldWidthMatchParent: Boolean = false, @ColorRes val positiveButtonBackgroundColor: Int? = null, @ColorRes val positiveButtonTextColor: Int? = null, val positiveButtonRadius: Float? = null ) } samples/browser/src/main/res/layout/fragment_dialog_addon_permissions.xml 0 → 100644 +79 −0 Original line number Diff line number Diff line <!-- 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/. --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:windowBackground" android:orientation="vertical" tools:ignore="Overdraw"> <ImageView android:id="@+id/icon" android:layout_width="32dp" android:layout_height="32dp" android:layout_alignParentTop="true" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:importantForAccessibility="no" android:scaleType="center" android:src="@drawable/mozac_ic_extensions" android:tint="?android:attr/textColorPrimary" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@id/icon" android:layout_alignParentTop="true" android:layout_marginStart="3dp" android:layout_marginTop="16dp" android:layout_marginEnd="11dp" android:layout_toEndOf="@id/icon" android:paddingStart="5dp" android:paddingTop="4dp" android:paddingEnd="5dp" android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" tools:text="Add Ublock Origin?" tools:textColor="#000000" /> <TextView android:id="@+id/permissions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/title" android:layout_alignStart="@id/title" android:layout_marginTop="16dp" android:paddingStart="5dp" android:paddingTop="4dp" android:paddingEnd="5dp" android:textColor="?android:attr/textColorPrimary" tools:text="It requires your permission to: \n\n • Access your data for all websites. \n\n • Acess browser tabs. \n\n • Access browser activity during navigation." /> <Button android:id="@+id/deny_button" style="?android:attr/borderlessButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/permissions" android:layout_marginTop="16dp" android:layout_toStartOf="@id/allow_button" android:text="@string/addon_permissions_dialog_cancel" android:textAllCaps="false" /> <Button android:id="@+id/allow_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/permissions" android:layout_alignParentEnd="true" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:text="@string/addon_permissions_dialog_add" android:textAllCaps="false" /> </RelativeLayout> No newline at end of file samples/browser/src/main/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -22,4 +22,8 @@ <string name="add_on_details">Details</string> <string name="add_on_permissions">Permissions</string> <string name="add_on_remove">Remove add-on</string> <string name="addon_permissions_dialog_subtitle">It requires your permission to:</string> <string name="addon_permissions_dialog_title">Add %1$s?</string> <string name="addon_permissions_dialog_add">Add</string> <string name="addon_permissions_dialog_cancel">Cancel</string> </resources> Loading
components/feature/addons/build.gradle +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ android { dependencies { implementation Dependencies.androidx_appcompat implementation Dependencies.kotlin_stdlib implementation Dependencies.kotlin_coroutines Loading
samples/browser/src/main/java/org/mozilla/samples/browser/addons/AddOnsFragment.kt +52 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ package org.mozilla.samples.browser.addons import android.content.Intent import android.os.Bundle import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup Loading @@ -22,6 +23,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.feature.addons.AddOn import org.mozilla.samples.browser.R import org.mozilla.samples.browser.addons.PermissionsDialogFragment.PromptsStyling import org.mozilla.samples.browser.ext.components /** Loading @@ -44,6 +46,14 @@ class AddOnsFragment : Fragment(), View.OnClickListener { bindRecyclerView(rootView) } override fun onStart() { super.onStart() findPreviousDialogFragment()?.let { dialog -> dialog.onPositiveButtonClicked = onPositiveButtonClicked dialog.onNegativeButtonClicked = onNegativeButtonClicked } } private fun bindRecyclerView(rootView: View) { recyclerView = rootView.findViewById(R.id.add_ons_list) recyclerView.layoutManager = LinearLayoutManager(requireContext()) Loading Loading @@ -140,8 +150,8 @@ class AddOnsFragment : Fragment(), View.OnClickListener { val context = view.context when (view.id) { R.id.add_button -> { Toast.makeText(this.requireContext(), "Installing add-on", Toast.LENGTH_SHORT) .show() val addOn = (((view.parent) as View).tag as AddOn) showPermissionDialog(addOn) } R.id.add_on_item -> { val intent = Intent(context, InstalledAddOnDetailsActivity::class.java) Loading @@ -152,4 +162,44 @@ class AddOnsFragment : Fragment(), View.OnClickListener { } } } private fun isAlreadyADialogCreated(): Boolean { return findPreviousDialogFragment() != null } private fun findPreviousDialogFragment(): PermissionsDialogFragment? { return fragmentManager?.findFragmentByTag(PERMISSIONS_DIALOG_FRAGMENT_TAG) as? PermissionsDialogFragment } private fun showPermissionDialog(addOn: AddOn) { val dialog = PermissionsDialogFragment.newInstance( addOnId = addOn.id, title = addOn.translatableName.translate(), permissions = addOn.translatePermissions(), promptsStyling = PromptsStyling( gravity = Gravity.BOTTOM, shouldWidthMatchParent = true ), onPositiveButtonClicked = onPositiveButtonClicked, onNegativeButtonClicked = onNegativeButtonClicked ) if (!isAlreadyADialogCreated() && fragmentManager != null) { dialog.show(requireFragmentManager(), PERMISSIONS_DIALOG_FRAGMENT_TAG) } } private val onPositiveButtonClicked: ((String) -> Unit) = { addonId -> Toast.makeText(this.requireContext(), "Installing add-on $addonId", Toast.LENGTH_SHORT) .show() } private val onNegativeButtonClicked = { Toast.makeText(this.requireContext(), "Cancel button clicked", Toast.LENGTH_SHORT) .show() } companion object { private const val PERMISSIONS_DIALOG_FRAGMENT_TAG = "ADDONS_PERMISSIONS_DIALOG_FRAGMENT" } }
samples/browser/src/main/java/org/mozilla/samples/browser/addons/PermissionsDialogFragment.kt 0 → 100644 +231 −0 Original line number Diff line number Diff line /* 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 org.mozilla.samples.browser.addons import android.annotation.SuppressLint import android.app.Dialog import android.content.DialogInterface import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.GradientDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.Window import android.widget.TextView import android.view.ViewGroup import android.widget.Button import android.widget.LinearLayout.LayoutParams import androidx.annotation.ColorRes import androidx.appcompat.app.AppCompatDialogFragment import androidx.core.content.ContextCompat import org.mozilla.samples.browser.R internal const val KEY_ADD_ON_ID = "KEY_ADD_ON_ID" internal const val KEY_TITLE = "KEY_TITLE" private const val KEY_DIALOG_GRAVITY = "KEY_DIALOG_GRAVITY" private const val KEY_DIALOG_WIDTH_MATCH_PARENT = "KEY_DIALOG_WIDTH_MATCH_PARENT" private const val KEY_PERMISSIONS = "KEY_PERMISSIONS" private const val KEY_POSITIVE_BUTTON_BACKGROUND_COLOR = "KEY_POSITIVE_BUTTON_BACKGROUND_COLOR" private const val KEY_POSITIVE_BUTTON_TEXT_COLOR = "KEY_POSITIVE_BUTTON_TEXT_COLOR" private const val KEY_POSITIVE_BUTTON_RADIUS = "KEY_POSITIVE_BUTTON_RADIUS" private const val DEFAULT_VALUE = Int.MAX_VALUE internal class PermissionsDialogFragment : AppCompatDialogFragment() { internal var onPositiveButtonClicked: ((String) -> Unit)? = null internal var onNegativeButtonClicked: (() -> Unit)? = null private val safeArguments get() = requireNotNull(arguments) internal val addOnId get() = safeArguments.getString(KEY_ADD_ON_ID, "") internal val positiveButtonRadius get() = safeArguments.getFloat(KEY_POSITIVE_BUTTON_RADIUS, DEFAULT_VALUE.toFloat()) internal val permissions: IntArray get() = safeArguments.getIntArray(KEY_PERMISSIONS) ?: intArrayOf() internal val title: String get() = safeArguments.getString(KEY_TITLE, "") internal val dialogGravity: Int get() = safeArguments.getInt(KEY_DIALOG_GRAVITY, DEFAULT_VALUE) internal val dialogShouldWidthMatchParent: Boolean get() = safeArguments.getBoolean(KEY_DIALOG_WIDTH_MATCH_PARENT) internal val positiveButtonBackgroundColor get() = safeArguments.getInt(KEY_POSITIVE_BUTTON_BACKGROUND_COLOR, DEFAULT_VALUE) internal val positiveButtonTextColor get() = safeArguments.getInt(KEY_POSITIVE_BUTTON_TEXT_COLOR, DEFAULT_VALUE) override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val sheetDialog = Dialog(requireContext()) sheetDialog.requestWindowFeature(Window.FEATURE_NO_TITLE) sheetDialog.setCanceledOnTouchOutside(true) val rootView = createContainer() sheetDialog.setContainerView(rootView) sheetDialog.window?.apply { if (dialogGravity != DEFAULT_VALUE) { setGravity(dialogGravity) } if (dialogShouldWidthMatchParent) { setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // This must be called after addContentView, or it won't fully fill to the edge. setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) } } return sheetDialog } override fun onDismiss(dialog: DialogInterface) { super.onDismiss(dialog) onNegativeButtonClicked?.invoke() } private fun Dialog.setContainerView(rootView: View) { if (dialogShouldWidthMatchParent) { setContentView(rootView) } else { addContentView( rootView, LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) ) } } @SuppressLint("InflateParams") private fun createContainer(): View { val rootView = LayoutInflater.from(requireContext()).inflate( R.layout.fragment_dialog_addon_permissions, null, false ) rootView.findViewById<TextView>(R.id.title).text = requireContext().getString(R.string.addon_permissions_dialog_title, title) rootView.findViewById<TextView>(R.id.permissions).text = buildPermissionsText() val positiveButton = rootView.findViewById<Button>(R.id.allow_button) val negativeButton = rootView.findViewById<Button>(R.id.deny_button) positiveButton.setOnClickListener { onPositiveButtonClicked?.invoke(addOnId) dismiss() } if (positiveButtonBackgroundColor != DEFAULT_VALUE) { val backgroundTintList = ContextCompat.getColorStateList(requireContext(), positiveButtonBackgroundColor) positiveButton.backgroundTintList = backgroundTintList } if (positiveButtonTextColor != DEFAULT_VALUE) { val color = ContextCompat.getColor(requireContext(), positiveButtonTextColor) positiveButton.setTextColor(color) } if (positiveButtonRadius != DEFAULT_VALUE.toFloat()) { val shape = GradientDrawable() shape.shape = GradientDrawable.RECTANGLE shape.setColor( ContextCompat.getColor( requireContext(), positiveButtonBackgroundColor ) ) shape.cornerRadius = positiveButtonRadius positiveButton.background = shape } negativeButton.setOnClickListener { onNegativeButtonClicked?.invoke() dismiss() } return rootView } private fun buildPermissionsText(): String { var permissionsText = getString(R.string.addon_permissions_dialog_subtitle) + "\n\n" permissions.forEachIndexed { index, item -> val brakeLine = if (index + 1 != permissions.size) "\n\n" else "" val permissionText = requireContext().getString(item) permissionsText += "• $permissionText $brakeLine" } return permissionsText } @Suppress("LongParameterList") companion object { fun newInstance( addOnId: String, title: String, permissions: List<Int>, promptsStyling: PromptsStyling? = null, onPositiveButtonClicked: ((String) -> Unit)? = null, onNegativeButtonClicked: (() -> Unit)? = null ): PermissionsDialogFragment { val fragment = PermissionsDialogFragment() val arguments = fragment.arguments ?: Bundle() arguments.apply { putString(KEY_ADD_ON_ID, addOnId) putString(KEY_TITLE, title) putIntArray(KEY_PERMISSIONS, permissions.toIntArray()) promptsStyling?.gravity?.apply { putInt(KEY_DIALOG_GRAVITY, this) } promptsStyling?.shouldWidthMatchParent?.apply { putBoolean(KEY_DIALOG_WIDTH_MATCH_PARENT, this) } promptsStyling?.positiveButtonBackgroundColor?.apply { putInt(KEY_POSITIVE_BUTTON_BACKGROUND_COLOR, this) } promptsStyling?.positiveButtonTextColor?.apply { putInt(KEY_POSITIVE_BUTTON_TEXT_COLOR, this) } println(permissions) } fragment.onPositiveButtonClicked = onPositiveButtonClicked fragment.onNegativeButtonClicked = onNegativeButtonClicked fragment.arguments = arguments return fragment } } /** * Styling for the permissions dialog. */ data class PromptsStyling( val gravity: Int, val shouldWidthMatchParent: Boolean = false, @ColorRes val positiveButtonBackgroundColor: Int? = null, @ColorRes val positiveButtonTextColor: Int? = null, val positiveButtonRadius: Float? = null ) }
samples/browser/src/main/res/layout/fragment_dialog_addon_permissions.xml 0 → 100644 +79 −0 Original line number Diff line number Diff line <!-- 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/. --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:windowBackground" android:orientation="vertical" tools:ignore="Overdraw"> <ImageView android:id="@+id/icon" android:layout_width="32dp" android:layout_height="32dp" android:layout_alignParentTop="true" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:importantForAccessibility="no" android:scaleType="center" android:src="@drawable/mozac_ic_extensions" android:tint="?android:attr/textColorPrimary" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@id/icon" android:layout_alignParentTop="true" android:layout_marginStart="3dp" android:layout_marginTop="16dp" android:layout_marginEnd="11dp" android:layout_toEndOf="@id/icon" android:paddingStart="5dp" android:paddingTop="4dp" android:paddingEnd="5dp" android:textColor="?android:attr/textColorPrimary" android:textSize="16sp" tools:text="Add Ublock Origin?" tools:textColor="#000000" /> <TextView android:id="@+id/permissions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/title" android:layout_alignStart="@id/title" android:layout_marginTop="16dp" android:paddingStart="5dp" android:paddingTop="4dp" android:paddingEnd="5dp" android:textColor="?android:attr/textColorPrimary" tools:text="It requires your permission to: \n\n • Access your data for all websites. \n\n • Acess browser tabs. \n\n • Access browser activity during navigation." /> <Button android:id="@+id/deny_button" style="?android:attr/borderlessButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/permissions" android:layout_marginTop="16dp" android:layout_toStartOf="@id/allow_button" android:text="@string/addon_permissions_dialog_cancel" android:textAllCaps="false" /> <Button android:id="@+id/allow_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/permissions" android:layout_alignParentEnd="true" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:text="@string/addon_permissions_dialog_add" android:textAllCaps="false" /> </RelativeLayout> No newline at end of file
samples/browser/src/main/res/values/strings.xml +4 −0 Original line number Diff line number Diff line Loading @@ -22,4 +22,8 @@ <string name="add_on_details">Details</string> <string name="add_on_permissions">Permissions</string> <string name="add_on_remove">Remove add-on</string> <string name="addon_permissions_dialog_subtitle">It requires your permission to:</string> <string name="addon_permissions_dialog_title">Add %1$s?</string> <string name="addon_permissions_dialog_add">Add</string> <string name="addon_permissions_dialog_cancel">Cancel</string> </resources>