/* 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.fenix.settings.quicksettings import android.content.Context import android.view.ViewGroup import androidx.core.net.toUri import mozilla.components.feature.sitepermissions.SitePermissions import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.mvi.Action import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.Change import org.mozilla.fenix.mvi.UIComponent import org.mozilla.fenix.mvi.UIComponentViewModelBase import org.mozilla.fenix.mvi.UIComponentViewModelProvider import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.ViewState import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.toggle class QuickSettingsComponent( private val container: ViewGroup, bus: ActionBusFactory, viewModelProvider: UIComponentViewModelProvider ) : UIComponent( bus.getManagedEmitter(QuickSettingsAction::class.java), bus.getSafeManagedObservable(QuickSettingsChange::class.java), viewModelProvider ) { override fun initView(): UIView { return QuickSettingsUIView(container, actionEmitter, changesObservable, container) } init { bind() } fun toggleSitePermission( context: Context, featurePhone: PhoneFeature, url: String, sitePermissions: SitePermissions? ): SitePermissions { return if (sitePermissions == null) { val settings = context.settings val origin = requireNotNull(url.toUri().host) var location = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION).toStatus() var camera = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA).toStatus() var microphone = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE).toStatus() var notification = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION).toStatus() when (featurePhone) { PhoneFeature.CAMERA -> camera = camera.toggle() PhoneFeature.LOCATION -> location = location.toggle() PhoneFeature.MICROPHONE -> microphone = microphone.toggle() PhoneFeature.NOTIFICATION -> notification = notification.toggle() } context.components.core.permissionStorage .addSitePermissionException(origin, location, notification, microphone, camera) } else { val updatedSitePermissions = sitePermissions.toggle(featurePhone) context.components.core.permissionStorage.updateSitePermissions(updatedSitePermissions) updatedSitePermissions } } } data class QuickSettingsState(val mode: Mode) : ViewState { sealed class Mode { data class Normal( val url: String, val isSecured: Boolean, val isTrackingProtectionOn: Boolean, val sitePermissions: SitePermissions? ) : Mode() data class ActionLabelUpdated( val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions? ) : Mode() data class CheckPendingFeatureBlockedByAndroid(val sitePermissions: SitePermissions?) : Mode() } } sealed class QuickSettingsAction : Action { data class SelectReportProblem(val url: String) : QuickSettingsAction() object SelectTrackingProtectionSettings : QuickSettingsAction() data class ToggleTrackingProtection(val trackingProtection: Boolean) : QuickSettingsAction() data class SelectBlockedByAndroid(val permissions: Array) : QuickSettingsAction() data class TogglePermission(val featurePhone: PhoneFeature) : QuickSettingsAction() } sealed class QuickSettingsChange : Change { data class Change( val url: String, val isSecured: Boolean, val isTrackingProtectionOn: Boolean, val sitePermissions: SitePermissions? ) : QuickSettingsChange() data class PermissionGranted(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) : QuickSettingsChange() data class PromptRestarted(val sitePermissions: SitePermissions?) : QuickSettingsChange() data class Stored(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) : QuickSettingsChange() } class QuickSettingsViewModel( initialState: QuickSettingsState ) : UIComponentViewModelBase(initialState, reducer) { companion object { val reducer: (QuickSettingsState, QuickSettingsChange) -> QuickSettingsState = { state, change -> when (change) { is QuickSettingsChange.Change -> { state.copy( mode = QuickSettingsState.Mode.Normal( change.url, change.isSecured, change.isTrackingProtectionOn, change.sitePermissions ) ) } is QuickSettingsChange.PermissionGranted -> { state.copy( mode = QuickSettingsState.Mode.ActionLabelUpdated(change.phoneFeature, change.sitePermissions) ) } is QuickSettingsChange.PromptRestarted -> { state.copy( mode = QuickSettingsState.Mode.CheckPendingFeatureBlockedByAndroid(change.sitePermissions) ) } is QuickSettingsChange.Stored -> { state.copy( mode = QuickSettingsState.Mode.ActionLabelUpdated(change.phoneFeature, change.sitePermissions) ) } } } } }