From 9f56624788c2589992e83ceca048386d86efa4fa Mon Sep 17 00:00:00 2001 From: Mugurell Date: Wed, 16 Oct 2019 20:16:21 +0300 Subject: [PATCH] For #4126 - Document the newly introduced public APIs Now that the code should be in a ready-to-ship form it would be nice to have all the major functionalities properly documented. --- .../quicksettings/QuickSettingsController.kt | 87 +++++++++ .../QuickSettingsFragmentStore.kt | 181 +++++++++++++++++- .../quicksettings/QuickSettingsInteractor.kt | 9 + .../QuickSettingsSheetDialogFragment.kt | 6 + .../quicksettings/TrackingProtectionView.kt | 30 +++ .../settings/quicksettings/WebsiteInfoView.kt | 12 ++ .../quicksettings/WebsitePermissionsView.kt | 35 ++++ .../quicksettings/ext/PhoneFeatureExt.kt | 18 ++ 8 files changed, 377 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt index 3cb31265e..483ed95ff 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt @@ -25,16 +25,79 @@ import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled import org.mozilla.fenix.settings.toggle import org.mozilla.fenix.utils.Settings +/** + * [QuickSettingsSheetDialogFragment] controller. + * + * Delegated by View Interactors, handles container business logic and operates changes on it, + * complex Android interactions or communication with other features. + */ interface QuickSettingsController { + /** + * Handles turning on/off tracking protection. + * + * @param websiteUrl [String] the website URL for which to toggle tracking protection. + */ fun handleTrackingProtectionToggled(websiteUrl: String, trackingEnabled: Boolean) + + /** + * Handles showing the tracking protection settings. + */ fun handleTrackingProtectionSettingsSelected() + + /** + * Handles reporting a webcompat issue for the indicated website. + * + * @param websiteUrl [String] the URL of the web page for which to report a site issue. + */ fun handleReportTrackingProblem(websiteUrl: String) + + /** + * Handles the case of the [TrackingProtectionView] needed to be displayed to the user. + */ fun handleTrackingProtectionShown() + + /** + * Handles the case of the [WebsitePermissionsView] needed to be displayed to the user. + */ fun handlePermissionsShown() + + /** + * Handles toggling a [WebsitePermission]. + * + * @param permission [WebsitePermission] needing to be toggled. + */ fun handlePermissionToggled(permission: WebsitePermission) + + /** + * Handles a certain set of Android permissions being explicitly granted by the user. + * + * feature [PhoneFeature] which the user granted Android permission(s) for. + */ fun handleAndroidPermissionGranted(feature: PhoneFeature) } +/** + * Default behavior of [QuickSettingsController]. Other implementations are possible. + * + * @param context [Context] used for various Android interactions. + * @param quickSettingsStore [QuickSettingsFragmentStore] holding the [State] for all Views displayed + * in this Controller's Fragment. + * @param coroutineScope [CoroutineScope] used for structed concurrency. + * @param navController NavController] used for navigation. + * @param session [Session]? current browser state. + * @param sitePermissions [SitePermissions]? list of website permissions and their status. + * @param settings [Settings] application settings. + * @param permissionStorage [PermissionStorage] app state for website permissions exception. + * @param trackingExceptions [ExceptionDomains] allows setting whether to allow trackers or not. + * @param reload [ReloadUrlUseCase] callback allowing for reloading the current web page. + * @param addNewTab [AddNewTabUseCase] callback allowing for loading a URL in a new tab. + * @param requestRuntimePermissions [OnNeedToRequestPermissions] callback allowing for requesting + * specific Android runtime permissions. + * @param reportSiteIssue callback allowing to report an issue with the current web page. + * @param displayTrackingProtection callback for when the [TrackingProtectionView] needs to be displayed. + * @param displayPermissions callback for when [WebsitePermissionsView] needs to be displayed. + * @param dismiss callback allowing to request this entire Fragment to be dismissed. + */ @Suppress("TooManyFunctions") class DefaultQuickSettingsController( private val context: Context, @@ -127,10 +190,23 @@ class DefaultQuickSettingsController( ) } + /** + * Request a certain set of runtime Android permissions. + * + * User's approval should be received in the [handleAndroidPermissionGranted] method but this is not enforced. + * + * @param requestedPermissions [Array]<[String]> runtime permissions needed to be requested. + */ private fun handleAndroidPermissionRequest(requestedPermissions: Array) { requestRuntimePermissions(requestedPermissions) } + /** + * Updates the list of [SitePermissions] for this current website and reloads it to allow / block + * new functionality in the web page. + * + * @param updatedPermissions [SitePermissions] updated website permissions. + */ private fun handlePermissionsChange(updatedPermissions: SitePermissions) { coroutineScope.launch(Dispatchers.IO) { permissionStorage.updateSitePermissions(updatedPermissions) @@ -138,6 +214,11 @@ class DefaultQuickSettingsController( } } + /** + * Each [WebsitePermission] is mapped after a [PhoneFeature]. + * + * Get this [WebsitePermission]'s [PhoneFeature]. + */ private fun WebsitePermission.getBackingFeature(): PhoneFeature = when (this) { is WebsitePermission.Camera -> PhoneFeature.CAMERA is WebsitePermission.Microphone -> PhoneFeature.MICROPHONE @@ -145,6 +226,12 @@ class DefaultQuickSettingsController( is WebsitePermission.Location -> PhoneFeature.LOCATION } + /** + * Get the specific [WebsitePermission] implementation which this [PhoneFeature] is tied to. + * + * **The result only informs about the type of [WebsitePermission]. + * The resulting object's properties are just stubs and not dependable.** + */ private fun PhoneFeature.getCorrespondingPermission(): WebsitePermission { val defaultStatus = "" val defaultEnabled = false diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStore.kt index 792d7b861..3a8cb65fd 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsFragmentStore.kt @@ -10,6 +10,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.lib.state.Action +import mozilla.components.lib.state.Reducer import mozilla.components.lib.state.State import mozilla.components.lib.state.Store import org.mozilla.fenix.FeatureFlags @@ -19,6 +20,18 @@ import org.mozilla.fenix.settings.quicksettings.ext.shouldBeEnabled import org.mozilla.fenix.settings.quicksettings.ext.shouldBeVisible import org.mozilla.fenix.utils.Settings +/** + * [QuickSettingsSheetDialogFragment]'s unique [Store]. + * Encompasses it's own: + * - [State] for all Views displayed in this Fragment. + * - [Action]s mapping a user / system interaction to an intention to modify the above State. + * - [Reducer]s for modifying the above State based on the above Actions. + * + * The [createStore] helper method can be used for creating one such [State] based on all current + * conditions of the app and web page visited. + * + * @param initialState [QuickSettingsFragmentState] that will be shown initially to the user. + */ class QuickSettingsFragmentStore( initialState: QuickSettingsFragmentState ) : Store( @@ -26,18 +39,37 @@ class QuickSettingsFragmentStore( ::quickSettingsFragmentReducer ) { companion object { + /** + * String, Drawable & Drawable Tint color used to display that the current website connection is secured. + */ private val getSecuredWebsiteUiValues = Triple( R.string.quick_settings_sheet_secure_connection, R.drawable.mozac_ic_lock, R.color.photonGreen50 ) + /** + * String, Drawable & Drawable Tint color used to display that the current website connection is + * **not** secured. + */ private val getInsecureWebsiteUiValues = Triple( R.string.quick_settings_sheet_insecure_connection, R.drawable.mozac_ic_globe, R.color.photonRed50 ) + /** + * Construct an initial [QuickSettingsFragmentState] for all Views displayed by the + * [QuickSettingsSheetDialogFragment]. + * + * @param context [Context] used for access to various Android resources. + * @param websiteUrl [String] the URL of the current web page. + * @param isSecured [Boolean] whether the connection is secured (TLS) or not. + * @param isTrackingProtectionOn [Boolean] whether the "Standard" (as in not "Strict") + * tracking protection is enabled for the current website or not. + * @param permissions [SitePermissions]? list of website permissions and their status. + * @param settings [Settings] application settings. + */ @Suppress("LongParameterList") fun createStore( context: Context, @@ -54,6 +86,17 @@ class QuickSettingsFragmentStore( ) ) + /** + * Construct an initial [TrackingProtectionState] to be rendered by [TrackingProtectionView] + * based on the current state of the app / website. + * + * Users can modify the returned [TrackingProtectionState] after it is initially displayed. + * + * @param websiteUrl [String] the URL of the current web page. + * @param isTrackingProtectionOn [Boolean] whether the "Standard" (as in not "Strict") + * tracking protection is enabled for the current website or not. + * @param settings [Settings] application settings. + */ private fun createTrackingProtectionState( websiteUrl: String, isTrackingProtectionOn: Boolean, @@ -65,6 +108,15 @@ class QuickSettingsFragmentStore( isTrackingProtectionEnabledPerWebsite = isTrackingProtectionOn ) + /** + * Construct an initial [WebsiteInfoState] to be rendered by [WebsiteInfoView] + * based on the current website's status and connection. + * + * While being displayed users have no way of modifying it. + * + * @param websiteUrl [String] the URL of the current web page. + * @param isSecured [Boolean] whether the connection is secured (TLS) or not. + */ private fun createWebsiteInfoState( websiteUrl: String, isSecured: Boolean @@ -76,6 +128,16 @@ class QuickSettingsFragmentStore( return WebsiteInfoState(websiteUrl, stringRes, iconRes, colorRes) } + /** + * Construct an initial [WebsitePermissionsState] to be rendered by [WebsitePermissionsView] + * containing the permissions requested by the current website. + * + * Users can modify the returned [WebsitePermissionsState] after it is initially displayed. + * + * @param context [Context] used for various Android interactions. + * @param permissions [SitePermissions]? list of website permissions and their status. + * @param settings [Settings] application settings. + */ private fun createWebsitePermissionState( context: Context, permissions: SitePermissions?, @@ -93,6 +155,9 @@ class QuickSettingsFragmentStore( ) } + /** + * [PhoneFeature] to a [WebsitePermission] mapper. + */ private fun PhoneFeature.toWebsitePermission( context: Context, permissions: SitePermissions?, @@ -117,6 +182,9 @@ class QuickSettingsFragmentStore( } } + /** + * Helper method for getting the [WebsitePermission] properties based on a specific [PhoneFeature]. + */ private fun PhoneFeature.getPermissionStatus( context: Context, permissions: SitePermissions?, @@ -128,6 +196,9 @@ class QuickSettingsFragmentStore( isBlockedByAndroid = !isAndroidPermissionGranted(context) ) + /** + * Helper class acting as a temporary container of [WebsitePermission] properties. + */ private data class PermissionStatus( val status: String, val isVisible: Boolean, @@ -141,12 +212,27 @@ class QuickSettingsFragmentStore( // States // ------------------------------------------------------------------------------------------------- +/** + * [State] containing all data displayed to the user by this Fragment. + * + * Partitioned further to contain mutiple states for each standalone View this Fragment holds. + */ data class QuickSettingsFragmentState( val trackingProtectionState: TrackingProtectionState, val webInfoState: WebsiteInfoState, val websitePermissionsState: WebsitePermissionsState ) : State +/** + * [State] to be rendered by [TrackingProtectionView] indicating the app is blocking certain tracking + * functionality or not. + * + * @param isVisible [Boolean] whether this contains data that needs to be displayed to the user. + * @param websiteUrl [String] the URL of the current web page. + * @param isTrackingProtectionEnabledPerApp [Boolean] whether tracking protection is on/off globally. + * @param isTrackingProtectionEnabledPerWebsite [Boolean] whether the "Standard" (as in not "Strict") + * tracking protection is enabled for the current website or not. + */ data class TrackingProtectionState( val isVisible: Boolean, val websiteUrl: String, @@ -154,6 +240,14 @@ data class TrackingProtectionState( val isTrackingProtectionEnabledPerWebsite: Boolean ) : State +/** + * [State] to be rendered by [WebsiteInfoView] indicating whether the connection is secure or not. + * + * @param websiteUrl [String] the URL of the current web page. + * @param securityInfoRes [StringRes] for the connection description. + * @param iconRes [DrawableRes] image indicating the connection status. + * @param iconTintRes [ColorRes] icon color. + */ data class WebsiteInfoState( val websiteUrl: String, @StringRes val securityInfoRes: Int, @@ -161,6 +255,18 @@ data class WebsiteInfoState( @ColorRes val iconTintRes: Int ) : State +/** + * /** + * [State] to be rendered by [WebsitePermissionsView] displaying all explicitly allowed or blocked + * website permissions. + * + * @param isVisible [Boolean] whether this contains data that needs to be displayed to the user. + * @param camera [WebsitePermission] containing all information about the *camera* permission. + * @param microphone [WebsitePermission] containing all information about the *microphone* permission. + * @param notification [notification] containing all information about the *notification* permission. + * @param location [WebsitePermission] containing all information about the *location* permission. +*/ + */ data class WebsitePermissionsState( val isVisible: Boolean, val camera: WebsitePermission, @@ -169,12 +275,37 @@ data class WebsitePermissionsState( val location: WebsitePermission ) : State +/** + * Wrapper over a website permission encompassing all it's needed state to be rendered on the screen. + * + * Contains a limited number of implementations because there is a known, finite number of permissions + * we need to display to the user. + */ sealed class WebsitePermission { + /** + * The *allowed* / *blocked* permission status to be shown to the user. + */ abstract val status: String + + /** + * Whether this permission should be shown to the user. + */ abstract val isVisible: Boolean + + /** + * Visual indication about whether this permission is *enabled* / *disabled* + */ abstract val isEnabled: Boolean + + /** + * Whether the corresponding *dangerous* Android permission is granted for the app by the user or not. + */ abstract val isBlockedByAndroid: Boolean + /** + * Helper method mimicking the default generated *copy()* method for a data class. + * Allows us using a familiar API in the reducer. + */ abstract fun copy( status: String = this.status, isVisible: Boolean = this.isVisible, @@ -182,6 +313,9 @@ sealed class WebsitePermission { isBlockedByAndroid: Boolean = this.isBlockedByAndroid ): WebsitePermission + /** + * Contains all information about the *camera* permission. + */ data class Camera( override val status: String, override val isVisible: Boolean, @@ -203,6 +337,9 @@ sealed class WebsitePermission { ) } + /** + * Contains all information about the *microphone* permission. + */ data class Microphone( override val status: String, override val isVisible: Boolean, @@ -224,6 +361,9 @@ sealed class WebsitePermission { ) } + /** + * Contains all information about the *notification* permission. + */ data class Notification( override val status: String, override val isVisible: Boolean, @@ -245,6 +385,9 @@ sealed class WebsitePermission { ) } + /** + * Contains all information about the *location* permission. + */ data class Location( override val status: String, override val isVisible: Boolean, @@ -271,15 +414,39 @@ sealed class WebsitePermission { // Actions // ------------------------------------------------------------------------------------------------- +/** + * Parent [Action] for all the [QuickSettingsFragmentState] changes. + */ sealed class QuickSettingsFragmentAction : Action +/** + * All possible [TrackingProtectionState] changes as result of user / system interactions. + */ sealed class TrackingProtectionAction : QuickSettingsFragmentAction() { + /** + * Change resulting from toggling the tracking protection status for the current website. + */ class TrackingProtectionToggled(val trackingEnabled: Boolean) : TrackingProtectionAction() } +/** + * All possible [WebsiteInfoState] changes as result of user / system interactions. + */ sealed class WebsiteInfoAction : QuickSettingsFragmentAction() +/** + * All possible [WebsitePermissionsState] changes as result of user / system interactions. + */ sealed class WebsitePermissionAction : QuickSettingsFragmentAction() { + /** + * Change resulting from toggling a specific [WebsitePermission] for the current website. + * + * @param updatedFeature [PhoneFeature] backing a certain [WebsitePermission]. + * Allows to easily identify which permission changed + * **Must be the name of one of the properties of [WebsitePermissionsState]**. + * @param updatedStatus [String] the new [WebsitePermission#status] which will be shown to the user. + * @param updatedEnabledStatus [Boolean] the new [WebsitePermission#enabled] which will be shown to the user. + */ class TogglePermission( val websitePermission: WebsitePermission, val updatedStatus: String, @@ -291,6 +458,9 @@ sealed class WebsitePermissionAction : QuickSettingsFragmentAction() { // Reducers // ------------------------------------------------------------------------------------------------- +/** + * Parent [Reducer] for all [QuickSettingsFragmentState]s of all Views shown in this Fragment. + */ fun quickSettingsFragmentReducer( state: QuickSettingsFragmentState, action: QuickSettingsFragmentAction @@ -318,6 +488,9 @@ fun quickSettingsFragmentReducer( } object TrackingProtectionStateReducer { + /** + * Handles creating a new [TrackingProtectionState] based on the specific [TrackingProtectionAction] + */ fun reduce( state: TrackingProtectionState, action: TrackingProtectionAction @@ -330,8 +503,11 @@ object TrackingProtectionStateReducer { } } -@Suppress("UNUSED_PARAMETER") +@Suppress("UNUSED_PARAMETER") // the action paramater is unused object WebsiteInfoStateReducer { + /** + * Handles creating a new [WebsiteInfoState] based on the specific [WebsiteInfoAction] + */ fun reduce( state: WebsiteInfoState, action: WebsiteInfoAction @@ -344,6 +520,9 @@ object WebsiteInfoStateReducer { } object WebsitePermissionsStateReducer { + /** + * Handles creating a new [WebsitePermissionsState] based on the specific [WebsitePermissionAction] + */ fun reduce( state: WebsitePermissionsState, action: WebsitePermissionAction diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsInteractor.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsInteractor.kt index a34c611cc..6dc4db233 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsInteractor.kt @@ -4,6 +4,15 @@ package org.mozilla.fenix.settings.quicksettings +/** + * [QuickSettingsSheetDialogFragment] interactor. + * + * Implements callbacks for each of [QuickSettingsSheetDialogFragment]'s Views declared possible user interactions, + * delegates all such user events to the [QuickSettingsController]. + * + * @param controller [QuickSettingsController] which will be delegated for all users interactions, + * it expected to contain all business logic for how to act in response. + */ class QuickSettingsInteractor( private val controller: QuickSettingsController ) : WebsitePermissionInteractor, TrackingProtectionInteractor { diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt index e78cac523..4f6978968 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt @@ -36,6 +36,12 @@ import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.utils.Settings import com.google.android.material.R as MaterialR +/** + * Dialog that presents the user with information about + * - the current website and whether the connection is secured or not. + * - website tracking protection. + * - website permission. + */ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() { private lateinit var quickSettingsStore: QuickSettingsFragmentStore private lateinit var quickSettingsController: QuickSettingsController diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/TrackingProtectionView.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/TrackingProtectionView.kt index c21532c29..b169d2db7 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/TrackingProtectionView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/TrackingProtectionView.kt @@ -14,13 +14,38 @@ import kotlinx.android.synthetic.main.quicksettings_tracking_protection.* import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R +/** + * Contract declaring all possible user interactions with [TrackingProtectionView] + */ interface TrackingProtectionInteractor { + /** + * Indicates the user wants to report a problem with the current website. + */ fun onReportProblemSelected(websiteUrl: String) + + /** + * Indicates the user want to toggle the tracking protection on / off. + */ fun onProtectionToggled(websiteUrl: String, trackingEnabled: Boolean) + + /** + * Indicates the user want to see all tracking protection settings. + */ fun onProtectionSettingsSelected() + + /** + * Indicates the tracking protection status for the current website is shown to the user. + */ fun onTrackingProtectionShown() } +/** + * MVI View that knows to display a "normal" (as in not "enhanced") tracking protection panel + * containing the tracking protection status and also allowing on / off toggling. + * + * @param containerView [ViewGroup] in which this View will inflate itself. + * @param interactor [TrackingProtectionInteractor] which will have delegated to all user interactions. + */ class TrackingProtectionView( override val containerView: ViewGroup, val interactor: TrackingProtectionInteractor @@ -38,6 +63,11 @@ class TrackingProtectionView( ) } + /** + * Allows changing what this View displays. + * + * @param state [TrackingProtectionState] to be rendered. + */ fun update(state: TrackingProtectionState) { if (state.isVisible) { interactor.onTrackingProtectionShown() diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsiteInfoView.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsiteInfoView.kt index f0399281b..0914ee3ac 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsiteInfoView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsiteInfoView.kt @@ -18,12 +18,24 @@ import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R +/** + * MVI View that knows to display a whether the current website uses a secure connection or not. + * + * Currently it does not support any user interaction. + * + * @param containerView [ViewGroup] in which this View will inflate itself. + */ class WebsiteInfoView( override val containerView: ViewGroup ) : LayoutContainer { val view: View = LayoutInflater.from(containerView.context) .inflate(R.layout.quicksettings_website_info, containerView, true) + /** + * Allows changing what this View displays. + * + * @param state [WebsiteInfoState] to be rendered. + */ fun update(state: WebsiteInfoState) { bindUrl(state.websiteUrl) bindSecurityInfo(state.securityInfoRes, state.iconRes, state.iconTintRes) diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsitePermissionsView.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsitePermissionsView.kt index 06db57f61..4231fcc80 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsitePermissionsView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/WebsitePermissionsView.kt @@ -12,11 +12,34 @@ import androidx.core.view.isVisible import kotlinx.android.extensions.LayoutContainer import org.mozilla.fenix.R +/** + * Contract declaring all possible user interactions with [WebsitePermissionsView] + */ interface WebsitePermissionInteractor { + /** + * Indicates there are website permissions allowed / blocked for the current website. + * which, status which is shown to the user. + */ fun onPermissionsShown() + + /** + * Indicates the user changed the status of a certain website permission. + * + * @param permissionState current [WebsitePermission] that the user wants toggled. + */ fun onPermissionToggled(permissionState: WebsitePermission) } +/** + * MVI View that knows to display a list of specific website permissions (hardcoded): + * - location + * - notification + * - microphone + * - camera + * + * @param containerView [ViewGroup] in which this View will inflate itself. + * @param interactor [WebsitePermissionInteractor] which will have delegated to all user interactions. + */ class WebsitePermissionsView( override val containerView: ViewGroup, val interactor: WebsitePermissionInteractor @@ -26,6 +49,11 @@ class WebsitePermissionsView( val view: View = LayoutInflater.from(context) .inflate(R.layout.quicksettings_permissions, containerView, true) + /** + * Allows changing what this View displays. + * + * @param state [WebsitePermissionsState] to be rendered. + */ fun update(state: WebsitePermissionsState) { if (state.isVisible) { interactor.onPermissionsShown() @@ -43,6 +71,13 @@ class WebsitePermissionsView( Pair(view.findViewById(R.id.notificationLabel), view.findViewById(R.id.notificationStatus))) } + /** + * Helper method that can map a specific website permission to a dedicated permission row + * which will display permission's [icon, label, status] and register user inputs. + * + * @param permissionState [WebsitePermission] specific permission that can be shown to the user. + * @param permissionViews Views that will render [WebsitePermission]'s state. + */ private fun bindPermission(permissionState: WebsitePermission, permissionViews: Pair) { val (label, status) = permissionViews diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ext/PhoneFeatureExt.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ext/PhoneFeatureExt.kt index 6a904e49a..0958209f8 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ext/PhoneFeatureExt.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ext/PhoneFeatureExt.kt @@ -9,17 +9,35 @@ import mozilla.components.feature.sitepermissions.SitePermissions import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.utils.Settings +/** + * Common [PhoneFeature] extensions used for **quicksettings**. + * + * Whether the website permission associated with this [PhoneFeature] should be shown to the user. + */ fun PhoneFeature.shouldBeVisible( sitePermissions: SitePermissions?, settings: Settings ) = getStatus(sitePermissions, settings) != SitePermissions.Status.NO_DECISION +/** + * Common [PhoneFeature] extensions used for **quicksettings**. + * + * Whether the website permission associated with this [PhoneFeature] should allow user interaction. + */ fun PhoneFeature.shouldBeEnabled( context: Context, sitePermissions: SitePermissions?, settings: Settings ) = isAndroidPermissionGranted(context) && isUserPermissionGranted(sitePermissions, settings) +/** + * Common [PhoneFeature] extensions used for **quicksettings**. + * + * Whether the website permission associated with this [PhoneFeature] was specifically allowed by the user. + * + * To check whether the needed Android permission is also allowed [PhoneFeature#isAndroidPermissionGranted()] + * can be used. + */ fun PhoneFeature.isUserPermissionGranted( sitePermissions: SitePermissions?, settings: Settings