From cc9e91809bb31917bad2e377d4f9c436622861aa Mon Sep 17 00:00:00 2001 From: Arturo Mejia Date: Wed, 6 Apr 2022 19:12:34 -0400 Subject: [PATCH] Revert "For #24220 and #24223: Connect GleanPlumb messages with the new tab ui card. Co-authored-by: Jonathan Almeida " This reverts commit f953c5ec --- .../java/org/mozilla/fenix/FeatureFlags.kt | 6 - .../org/mozilla/fenix/FenixApplication.kt | 4 - .../java/org/mozilla/fenix/HomeActivity.kt | 18 +- .../org/mozilla/fenix/components/Analytics.kt | 11 - .../mozilla/fenix/components/Components.kt | 6 +- .../fenix/components/appstate/AppAction.kt | 46 +- .../fenix/components/appstate/AppState.kt | 7 +- .../components/appstate/AppStoreReducer.kt | 4 +- .../gleanplumb/CustomAttributeProvider.kt | 34 -- .../gleanplumb/DefaultMessageController.kt | 60 --- .../KeyPairMessageMetadataStorage.kt | 29 -- .../org/mozilla/fenix/gleanplumb/Message.kt | 50 -- .../fenix/gleanplumb/MessageController.kt | 25 - .../gleanplumb/MessageMetadataStorage.kt | 23 - .../fenix/gleanplumb/MessagingFeature.kt | 24 - .../fenix/gleanplumb/MessagingState.kt | 16 - .../gleanplumb/NimbusMessagingStorage.kt | 174 ------- .../gleanplumb/state/MessagingMiddleware.kt | 139 ----- .../gleanplumb/state/MessagingReducer.kt | 42 -- .../org/mozilla/fenix/home/HomeFragment.kt | 18 - .../sessioncontrol/SessionControlAdapter.kt | 18 +- .../SessionControlController.kt | 33 +- .../SessionControlInteractor.kt | 41 +- .../home/sessioncontrol/SessionControlView.kt | 9 +- .../ExperimentDefaultBrowserCardViewHolder.kt | 40 ++ .../onboarding/MessageCardViewHolder.kt | 57 -- .../java/org/mozilla/fenix/utils/Settings.kt | 21 +- ...ard.xml => experiment_default_browser.xml} | 17 +- app/src/main/res/values/preference_keys.xml | 3 + .../mozilla/fenix/components/AppStoreTest.kt | 14 +- .../DefaultMessageControllerTest.kt | 109 ---- .../fenix/gleanplumb/MessagingFeatureTest.kt | 46 -- .../gleanplumb/NimbusMessagingStorageTest.kt | 487 ------------------ .../state/MessagingMiddlewareTest.kt | 327 ------------ .../gleanplumb/state/MessagingReducerTest.kt | 61 --- .../DefaultSessionControlControllerTest.kt | 25 +- .../sessioncontrol/SessionControlViewTest.kt | 47 +- nimbus.fml.yaml | 268 +--------- 38 files changed, 151 insertions(+), 2208 deletions(-) delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/CustomAttributeProvider.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/DefaultMessageController.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/KeyPairMessageMetadataStorage.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/Message.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/MessageController.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/MessageMetadataStorage.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingFeature.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingState.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingMiddleware.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingReducer.kt create mode 100644 app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/ExperimentDefaultBrowserCardViewHolder.kt delete mode 100644 app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/MessageCardViewHolder.kt rename app/src/main/res/layout/{nimbus_message_card.xml => experiment_default_browser.xml} (78%) delete mode 100644 app/src/test/java/org/mozilla/fenix/gleanplumb/DefaultMessageControllerTest.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/gleanplumb/MessagingFeatureTest.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorageTest.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/gleanplumb/state/MessagingMiddlewareTest.kt delete mode 100644 app/src/test/java/org/mozilla/fenix/gleanplumb/state/MessagingReducerTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index cd44dad6b..638f6e2e7 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -109,10 +109,4 @@ object FeatureFlags { * Enables the Unified Search feature. */ val unifiedSearchFeature = Config.channel.isNightlyOrDebug - - /** - * Enables receiving from the messaging framework. - */ - @Suppress("MayBeConst") - val messagingFeature = false } diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 99d81ff22..1bb9f591a 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -66,7 +66,6 @@ import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine import org.mozilla.fenix.GleanMetrics.TopSites import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.Core -import org.mozilla.fenix.components.appstate.AppAction import org.mozilla.fenix.components.metrics.MetricServiceType import org.mozilla.fenix.components.metrics.MozillaProductDetector import org.mozilla.fenix.components.toolbar.ToolbarPosition @@ -156,9 +155,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider { GlobalScope.launch(Dispatchers.IO) { setStartupMetrics(store, settings()) } - if (FeatureFlags.messagingFeature && settings().isExperimentationEnabled) { - components.appStore.dispatch(AppAction.MessagingAction.Restore) - } } @CallSuper diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 227204103..6a65038f1 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -1019,22 +1019,18 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } } - fun processIntent(intent: Intent): Boolean { - return externalSourceIntentProcessors.any { - it.process( - intent, - navHost.navController, - this.intent - ) - } - } - @VisibleForTesting internal fun getSettings(): Settings = settings() private fun shouldNavigateToBrowserOnColdStart(savedInstanceState: Bundle?): Boolean { return isActivityColdStarted(intent, savedInstanceState) && - !processIntent(intent) + !externalSourceIntentProcessors.any { + it.process( + intent, + navHost.navController, + this.intent + ) + } } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt index ecac24732..94e8d3c89 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt @@ -25,8 +25,6 @@ import org.mozilla.fenix.components.metrics.GleanMetricsService import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.experiments.createNimbus import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.gleanplumb.KeyPairMessageMetadataStorage -import org.mozilla.fenix.gleanplumb.NimbusMessagingStorage import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID @@ -126,15 +124,6 @@ class Analytics( FxNimbus.api = api } } - - val messagingStorage by lazyMonitored { - NimbusMessagingStorage( - context = context, - metadataStorage = KeyPairMessageMetadataStorage(), - gleanPlumb = experiments, - messagingFeature = FxNimbus.features.messaging, - ) - } } private fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty() diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 3c2a6259a..1ac60e180 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -32,7 +32,6 @@ import org.mozilla.fenix.ext.asRecentTabs import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.filterState import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.gleanplumb.state.MessagingMiddleware import org.mozilla.fenix.ext.sort import org.mozilla.fenix.home.PocketUpdatesMiddleware import org.mozilla.fenix.home.blocklist.BlocklistHandler @@ -194,7 +193,6 @@ class Components(private val context: Context) { val appStartReasonProvider by lazyMonitored { AppStartReasonProvider() } val startupActivityLog by lazyMonitored { StartupActivityLog() } val startupStateProvider by lazyMonitored { StartupStateProvider(startupActivityLog, appStartReasonProvider) } - val appStore by lazyMonitored { val blocklistHandler = BlocklistHandler(settings) @@ -205,6 +203,7 @@ class Components(private val context: Context) { topSites = core.topSitesStorage.cachedTopSites.sort(), recentBookmarks = emptyList(), showCollectionPlaceholder = settings.showCollectionsPlaceholderOnHome, + showSetAsDefaultBrowserCard = settings.shouldShowSetAsDefaultBrowserCard(), // Provide an initial state for recent tabs to prevent re-rendering on the home screen. // This will otherwise cause a visual jump as the section gets rendered from no state // to some state. @@ -220,8 +219,7 @@ class Components(private val context: Context) { PocketUpdatesMiddleware( core.pocketStoriesService, context.pocketStoriesSelectedCategoriesDataStore - ), - MessagingMiddleware(messagingStorage = analytics.messagingStorage) + ) ) ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt index 1af3c4c14..85568e5e1 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt @@ -16,8 +16,6 @@ import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory import org.mozilla.fenix.home.recentbookmarks.RecentBookmark import org.mozilla.fenix.home.recenttabs.RecentTab import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem -import org.mozilla.fenix.gleanplumb.Message -import org.mozilla.fenix.gleanplumb.MessagingState /** * [Action] implementation related to [AppStore]. @@ -64,47 +62,7 @@ sealed class AppAction : Action { ) : AppAction() object RemoveCollectionsPlaceholder : AppAction() /** - * [Action]s related to interactions with the Messaging Framework. + * [Action] implementation related to remove the DefaultBrowserCard. */ - sealed class MessagingAction : AppAction() { - /** - * Restores the [Message] state from the storage. - */ - object Restore : MessagingAction() - - /** - * Evaluates if a new messages should be shown to users. - */ - object Evaluate : MessagingAction() - - /** - * Updates [MessagingState.messageToShow] with the given [message]. - */ - data class UpdateMessageToShow(val message: Message) : MessagingAction() - - /** - * Updates [MessagingState.messageToShow] with the given [message]. - */ - object ConsumeMessageToShow : MessagingAction() - - /** - * Updates [MessagingState.messages] with the given [messages]. - */ - data class UpdateMessages(val messages: List) : MessagingAction() - - /** - * Indicates the given [message] was clicked. - */ - data class MessageClicked(val message: Message) : MessagingAction() - - /** - * Indicates the given [message] was shown. - */ - data class MessageDisplayed(val message: Message) : MessagingAction() - - /** - * Indicates the given [message] was dismissed. - */ - data class MessageDismissed(val message: Message) : MessagingAction() - } + object RemoveSetDefaultBrowserCard : AppAction() } diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt index 5c226b14e..0f39e2b28 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt @@ -17,7 +17,6 @@ import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory import org.mozilla.fenix.home.recentbookmarks.RecentBookmark import org.mozilla.fenix.home.recenttabs.RecentTab import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem -import org.mozilla.fenix.gleanplumb.MessagingState /** * Value type that represents the state of the tabs tray. @@ -31,12 +30,12 @@ import org.mozilla.fenix.gleanplumb.MessagingState * @property mode The state of the [HomeFragment] UI. * @property topSites The list of [TopSite] in the [HomeFragment]. * @property showCollectionPlaceholder If true, shows a placeholder when there are no collections. + * @property showSetAsDefaultBrowserCard If true, shows the default browser card * @property recentTabs The list of recent [RecentTab] in the [HomeFragment]. * @property recentBookmarks The list of recently saved [BookmarkNode]s to show on the [HomeFragment]. * @property recentHistory The list of [RecentlyVisitedItem]s. * @property pocketStories The list of currently shown [PocketRecommendedStory]s. * @property pocketStoriesCategories All [PocketRecommendedStory] categories. - * @property messaging State related messages. * Also serves as an in memory cache of all stories mapped by category allowing for quick stories filtering. */ data class AppState( @@ -47,11 +46,11 @@ data class AppState( val mode: Mode = Mode.Normal, val topSites: List = emptyList(), val showCollectionPlaceholder: Boolean = false, + val showSetAsDefaultBrowserCard: Boolean = false, val recentTabs: List = emptyList(), val recentBookmarks: List = emptyList(), val recentHistory: List = emptyList(), val pocketStories: List = emptyList(), val pocketStoriesCategories: List = emptyList(), - val pocketStoriesCategoriesSelections: List = emptyList(), - val messaging: MessagingState = MessagingState(), + val pocketStoriesCategoriesSelections: List = emptyList() ) : State diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt index c716d4b80..bcb0c3f96 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt @@ -14,7 +14,6 @@ import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesSelectedCategory import org.mozilla.fenix.home.recenttabs.RecentTab import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryGroup -import org.mozilla.fenix.gleanplumb.state.MessagingReducer /** * Reducer for [AppStore]. @@ -31,8 +30,6 @@ internal object AppStoreReducer { is AppAction.RemoveAllNonFatalCrashes -> state.copy(nonFatalCrashes = emptyList()) - is AppAction.MessagingAction -> MessagingReducer.reduce(state, action) - is AppAction.Change -> state.copy( collections = action.collections, mode = action.mode, @@ -63,6 +60,7 @@ internal object AppStoreReducer { is AppAction.RemoveCollectionsPlaceholder -> { state.copy(showCollectionPlaceholder = false) } + is AppAction.RemoveSetDefaultBrowserCard -> state.copy(showSetAsDefaultBrowserCard = false) is AppAction.RecentTabsChange -> { val recentSearchGroup = action.recentTabs.find { it is RecentTab.SearchGroup } as RecentTab.SearchGroup? state.copy( diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/CustomAttributeProvider.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/CustomAttributeProvider.kt deleted file mode 100644 index d18f2e855..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/CustomAttributeProvider.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* 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.gleanplumb - -import android.content.Context -import org.json.JSONObject -import org.mozilla.fenix.utils.BrowsersCache -import java.text.SimpleDateFormat -import java.util.Locale -import java.util.Calendar - -/** - * Custom attributes that the messaging framework will use to evaluate if message is eligible - * to be shown. - */ -object CustomAttributeProvider { - private val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US) - - /** - * Returns a [JSONObject] that contains all the custom attributes, evaluated when the function - * was called. - */ - fun getCustomAttributes(context: Context): JSONObject { - val now = Calendar.getInstance() - return JSONObject( - mapOf( - "is_default_browser" to BrowsersCache.all(context).isDefaultBrowser, - "date_string" to formatter.format(now.time) - ) - ) - } -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/DefaultMessageController.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/DefaultMessageController.kt deleted file mode 100644 index c555fe6eb..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/DefaultMessageController.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* 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.gleanplumb - -import android.content.Intent -import android.net.Uri -import androidx.annotation.VisibleForTesting -import androidx.core.net.toUri -import org.mozilla.fenix.BuildConfig -import org.mozilla.fenix.HomeActivity -import org.mozilla.fenix.components.AppStore -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed - -/** - * Handles default interactions with the ui of GleanPlumb messages. - */ -class DefaultMessageController( - private val appStore: AppStore, - private val messagingStorage: NimbusMessagingStorage, - private val homeActivity: HomeActivity -) : MessageController { - - override fun onMessagePressed(message: Message) { - // Report telemetry event - // This will be covered on https://github.com/mozilla-mobile/fenix/issues/24224 - val action = messagingStorage.getMessageAction(message) - handleAction(action) - appStore.dispatch(MessageClicked(message)) - } - - override fun onMessageDismissed(message: Message) { - // Report telemetry event - // This will be covered on https://github.com/mozilla-mobile/fenix/issues/24224 - appStore.dispatch(MessageDismissed(message)) - } - - override fun onMessageDisplayed(message: Message) { - // Report telemetry event - // This will be covered on https://github.com/mozilla-mobile/fenix/issues/24224 - appStore.dispatch(MessageDisplayed(message)) - } - - @VisibleForTesting - internal fun handleAction(action: String): Intent { - val partialAction = if (action.startsWith("http", ignoreCase = true)) { - "://open?url=${Uri.encode(action)}" - } else { - action - } - val intent = - Intent(Intent.ACTION_VIEW, "${BuildConfig.DEEP_LINK_SCHEME}$partialAction".toUri()) - homeActivity.processIntent(intent) - - return intent - } -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/KeyPairMessageMetadataStorage.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/KeyPairMessageMetadataStorage.kt deleted file mode 100644 index 3c6942117..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/KeyPairMessageMetadataStorage.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* 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.gleanplumb - -/* Dummy implementation until we provide full implementation. -* This will covered on https://github.com/mozilla-mobile/fenix/issues/24222 -* */ -class KeyPairMessageMetadataStorage : MessageMetadataStorage { - override fun getMetadata(): List { - return listOf( - Message.Metadata( - id = "eu-tracking-protection-for-ireland", - displayCount = 0, - pressed = false, - dismissed = false - ) - ) - } - - override fun addMetadata(metadata: Message.Metadata): Message.Metadata { - return metadata - } - - @SuppressWarnings("EmptyFunctionBlock") - override fun updateMetadata(metadata: Message.Metadata) { - } -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/Message.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/Message.kt deleted file mode 100644 index 9bdc745fd..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/Message.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* 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.gleanplumb - -import org.mozilla.fenix.nimbus.MessageData -import org.mozilla.fenix.nimbus.StyleData - -/** - * A data class that holds a representation of GleanPlum message from Nimbus. - * - * @param id identifies a message as unique. - * @param data Data information provided from Nimbus. - * @param action A strings that represents which action should be performed - * after a message is clicked. - * @param style Indicates how a message should be styled. - * @param triggers A list of strings corresponding to targeting expressions. The message - * will be shown if all expressions `true`. - * @param metadata Metadata that help to identify if a message should shown. - */ -data class Message( - val id: String, - val data: MessageData, - val action: String, - val style: StyleData, - val triggers: List, - val metadata: Metadata -) { - val maxDisplayCount: Int - get() = style.maxDisplayCount - - val priority: Int - get() = style.priority - - /** - * A data class that holds metadata that help to identify if a message should shown. - * - * @param id identifies a message as unique. - * @param displayCount Indicates how many times a message is displayed. - * @param pressed Indicates if a message has been clicked. - * @param dismissed Indicates if a message has been closed. - */ - data class Metadata( - val id: String, - val displayCount: Int = 0, - val pressed: Boolean = false, - val dismissed: Boolean = false - ) -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageController.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageController.kt deleted file mode 100644 index 63a03aaa9..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageController.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* 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.gleanplumb - -/** - * Controls all the interactions with a [Message]. - */ -interface MessageController { - /** - * Indicates the provided [message] was pressed by a user. - */ - fun onMessagePressed(message: Message) - - /** - * Indicates the provided [message] was dismissed by a user. - */ - fun onMessageDismissed(message: Message) - - /** - * Indicates the provided [message] was displayed to a user. - */ - fun onMessageDisplayed(message: Message) -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageMetadataStorage.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageMetadataStorage.kt deleted file mode 100644 index a9ca921d0..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessageMetadataStorage.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* 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.gleanplumb - -interface MessageMetadataStorage { - /** - * Provide all the message metadata saved in the storage. - */ - fun getMetadata(): List - - /** - * Given a [metadata] add the message metadata on the storage. - * @return the added message on the [MessageMetadataStorage] - */ - fun addMetadata(metadata: Message.Metadata): Message.Metadata - - /** - * Given a [metadata] update the message metadata on the storage. - */ - fun updateMetadata(metadata: Message.Metadata) -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingFeature.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingFeature.kt deleted file mode 100644 index f7df88b76..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingFeature.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* 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.gleanplumb - -import mozilla.components.support.base.feature.LifecycleAwareFeature -import org.mozilla.fenix.FeatureFlags -import org.mozilla.fenix.components.AppStore -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction - -/** - * A message observer that updates the provided. - */ -class MessagingFeature(val store: AppStore) : LifecycleAwareFeature { - - override fun start() { - if (FeatureFlags.messagingFeature) { - store.dispatch(MessagingAction.Evaluate) - } - } - - override fun stop() = Unit -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingState.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingState.kt deleted file mode 100644 index c3234a5d2..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/MessagingState.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* 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.gleanplumb - -/** - * Represent all the state related to the Messaging framework. - * @param messages Indicates all the available messages. - * @param messageToShow Indicates the message that should be shown to users, - * if it is null means there is not message that is eligible to be shown to users. - */ -data class MessagingState( - val messages: List = emptyList(), - val messageToShow: Message? = null -) diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt deleted file mode 100644 index 9fe06ad72..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/NimbusMessagingStorage.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* 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.gleanplumb - -import android.content.Context -import androidx.annotation.VisibleForTesting -import mozilla.components.support.base.log.logger.Logger -import org.json.JSONObject -import org.mozilla.experiments.nimbus.GleanPlumbInterface -import org.mozilla.experiments.nimbus.GleanPlumbMessageHelper -import org.mozilla.experiments.nimbus.internal.FeatureHolder -import org.mozilla.experiments.nimbus.internal.NimbusException - -import org.mozilla.fenix.nimbus.Messaging -import org.mozilla.fenix.nimbus.StyleData - -/** - * Provides messages from [messagingFeature] and combine with the metadata store on [metadataStorage]. - */ -class NimbusMessagingStorage( - private val context: Context, - private val metadataStorage: MessageMetadataStorage, - private val gleanPlumb: GleanPlumbInterface, - private val messagingFeature: FeatureHolder -) { - private val logger = Logger("MessagingStorage") - private val nimbusFeature = messagingFeature.value() - private val customAttributes: JSONObject - get() = JSONObject() - - /** - * Returns a list of available messages descending sorted by their priority. - */ - fun getMessages(): List { - val nimbusTriggers = nimbusFeature.triggers - val nimbusStyles = nimbusFeature.styles - val nimbusActions = nimbusFeature.actions - - val nimbusMessages = nimbusFeature.messages - val defaultStyle = StyleData(context) - val storageMetadata = metadataStorage.getMetadata().associateBy { - it.id - } - - return nimbusMessages.mapNotNull { (key, value) -> - val action = sanitizeAction(value.action, nimbusActions) ?: return@mapNotNull null - Message( - id = key, - data = value, - action = action, - style = nimbusStyles[value.style] ?: defaultStyle, - metadata = storageMetadata[key] ?: addMetadata(key), - triggers = sanitizeTriggers(value.trigger, nimbusTriggers) ?: return@mapNotNull null - ) - }.filter { - it.data.maxDisplayCount >= it.metadata.displayCount && - !it.metadata.dismissed && - !it.metadata.pressed - }.sortedByDescending { - it.style.priority - } - } - - /** - * Returns the next higher priority message which all their triggers are true. - */ - fun getNextMessage(availableMessages: List): Message? { - val helper = gleanPlumb.createMessageHelper(customAttributes) - var message = availableMessages.firstOrNull { - isMessageEligible(it, helper) - } ?: return null - - if (isMessageUnderExperiment(message, nimbusFeature.messageUnderExperiment)) { - messagingFeature.recordExposure() - - if (message.data.isControl) { - message = availableMessages.firstOrNull { - !it.data.isControl && isMessageEligible(it, helper) - } ?: return null - } - } - return message - } - - /** - * Returns a valid action for the provided [message]. - */ - fun getMessageAction(message: Message): String { - val helper = gleanPlumb.createMessageHelper(customAttributes) - val uuid = helper.getUuid(message.action) - - return helper.stringFormat(message.action, uuid) - } - - /** - * Updated the provided [metadata] in the storage. - */ - fun updateMetadata(metadata: Message.Metadata) { - metadataStorage.updateMetadata(metadata) - } - - @VisibleForTesting - internal fun sanitizeAction( - unsafeAction: String, - nimbusActions: Map - ): String? { - return if (unsafeAction.startsWith("http")) { - unsafeAction - } else { - val safeAction = nimbusActions[unsafeAction] - if (safeAction.isNullOrBlank() || safeAction.isEmpty()) { - return null - } - safeAction - } - } - - @VisibleForTesting - internal fun sanitizeTriggers( - unsafeTriggers: List, - nimbusTriggers: Map - ): List? { - return unsafeTriggers.map { - val safeTrigger = nimbusTriggers[it] - if (safeTrigger.isNullOrBlank() || safeTrigger.isEmpty()) { - return null - } - safeTrigger - } - } - - @VisibleForTesting - internal fun isMessageUnderExperiment(message: Message, expression: String?): Boolean { - return when { - expression.isNullOrBlank() -> { - false - } - expression.endsWith("-") -> { - message.id.startsWith(expression) - } - else -> { - message.id == expression - } - } - } - - @VisibleForTesting - internal fun isMessageEligible( - message: Message, - helper: GleanPlumbMessageHelper - ): Boolean { - return message.triggers.all { condition -> - try { - helper.evalJexl(condition) - } catch (e: NimbusException.EvaluationException) { - // Report to glean as malformed message - // Will be addressed on https://github.com/mozilla-mobile/fenix/issues/24224 - logger.info("Unable to evaluate $condition") - false - } - } - } - - private fun addMetadata(id: String): Message.Metadata { - // This will be improve on https://github.com/mozilla-mobile/fenix/issues/24222 - return metadataStorage.addMetadata( - Message.Metadata( - id = id, - ) - ) - } -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingMiddleware.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingMiddleware.kt deleted file mode 100644 index 3869c59fa..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingMiddleware.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* 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.gleanplumb.state - -import androidx.annotation.VisibleForTesting -import mozilla.components.lib.state.Middleware -import mozilla.components.lib.state.MiddlewareContext -import org.mozilla.fenix.components.appstate.AppAction -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.ConsumeMessageToShow -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Evaluate -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageClicked -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDismissed -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.MessageDisplayed -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.Restore -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages -import org.mozilla.fenix.components.appstate.AppState -import org.mozilla.fenix.gleanplumb.Message -import org.mozilla.fenix.gleanplumb.NimbusMessagingStorage - -typealias AppStoreMiddlewareContext = MiddlewareContext - -class MessagingMiddleware( - private val messagingStorage: NimbusMessagingStorage -) : Middleware { - - override fun invoke( - context: AppStoreMiddlewareContext, - next: (AppAction) -> Unit, - action: AppAction - ) { - when (action) { - is Restore -> { - val messages = messagingStorage.getMessages() - - context.dispatch(UpdateMessages(messages)) - } - - is Evaluate -> { - val message = messagingStorage.getNextMessage(context.state.messaging.messages) - if (message != null) { - context.dispatch(UpdateMessageToShow(message)) - } else { - context.dispatch(ConsumeMessageToShow) - } - } - - is MessageClicked -> onMessageClicked(action.message, context) - - is MessageDismissed -> onMessageDismissed(context, action.message) - - is MessageDisplayed -> onMessagedDisplayed(action.message, context) - } - next(action) - } - - @VisibleForTesting - internal fun onMessagedDisplayed( - oldMessage: Message, - context: AppStoreMiddlewareContext - ) { - val newMetadata = oldMessage.metadata.copy( - displayCount = oldMessage.metadata.displayCount + 1 - ) - val newMessage = oldMessage.copy( - metadata = newMetadata - ) - val newMessages = if (newMetadata.displayCount < oldMessage.maxDisplayCount) { - updateMessage(context, oldMessage, newMessage) - } else { - consumeMessageToShowIfNeeded(context, oldMessage) - removeMessage(context, oldMessage) - } - context.dispatch(UpdateMessages(newMessages)) - messagingStorage.updateMetadata(newMetadata) - } - - @VisibleForTesting - internal fun onMessageDismissed( - context: AppStoreMiddlewareContext, - message: Message - ) { - val newMessages = removeMessage(context, message) - val updatedMetadata = message.metadata.copy(dismissed = true) - - messagingStorage.updateMetadata(updatedMetadata) - context.dispatch(UpdateMessages(newMessages)) - consumeMessageToShowIfNeeded(context, message) - } - - @VisibleForTesting - internal fun onMessageClicked( - message: Message, - context: AppStoreMiddlewareContext - ) { - // Update Nimbus storage. - val updatedMetadata = message.metadata.copy(pressed = true) - messagingStorage.updateMetadata(updatedMetadata) - - // Update app state. - val newMessages = removeMessage(context, message) - context.dispatch(UpdateMessages(newMessages)) - consumeMessageToShowIfNeeded(context, message) - } - - @VisibleForTesting - internal fun consumeMessageToShowIfNeeded( - context: AppStoreMiddlewareContext, - message: Message - ) { - if (context.state.messaging.messageToShow?.id == message.id) { - context.dispatch(ConsumeMessageToShow) - } - } - - @VisibleForTesting - internal fun removeMessage( - context: AppStoreMiddlewareContext, - message: Message - ): List { - return context.state.messaging.messages.filter { it.id != message.id } - } - - @VisibleForTesting - internal fun updateMessage( - context: AppStoreMiddlewareContext, - oldMessage: Message, - updatedMessage: Message - ): List { - val actualMessageToShow = context.state.messaging.messageToShow - - if (actualMessageToShow?.id == oldMessage.id) { - context.dispatch(UpdateMessageToShow(updatedMessage)) - } - return removeMessage(context, oldMessage) + updatedMessage - } -} diff --git a/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingReducer.kt b/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingReducer.kt deleted file mode 100644 index 209dd1d42..000000000 --- a/app/src/main/java/org/mozilla/fenix/gleanplumb/state/MessagingReducer.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* 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.gleanplumb.state - -import org.mozilla.fenix.components.appstate.AppAction -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.ConsumeMessageToShow -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessageToShow -import org.mozilla.fenix.components.appstate.AppAction.MessagingAction.UpdateMessages -import org.mozilla.fenix.components.appstate.AppState -import org.mozilla.fenix.gleanplumb.MessagingState - -/** - * Reducer for [MessagingState]. - */ -internal object MessagingReducer { - fun reduce(state: AppState, action: AppAction.MessagingAction): AppState = when (action) { - is UpdateMessageToShow -> { - state.copy( - messaging = state.messaging.copy( - messageToShow = action.message - ) - ) - } - is UpdateMessages -> { - state.copy( - messaging = state.messaging.copy( - messages = action.messages - ) - ) - } - is ConsumeMessageToShow -> { - state.copy( - messaging = state.messaging.copy( - messageToShow = null - ) - ) - } - else -> state - } -} diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index e18259dd4..6ed1c592c 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -97,8 +97,6 @@ import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.runIfFragmentIsAttached import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.gleanplumb.DefaultMessageController -import org.mozilla.fenix.gleanplumb.MessagingFeature import org.mozilla.fenix.home.mozonline.showPrivacyPopWindow import org.mozilla.fenix.home.pocket.DefaultPocketStoriesController import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory @@ -174,7 +172,6 @@ class HomeFragment : Fragment() { private lateinit var currentMode: CurrentMode private val topSitesFeature = ViewBoundFeatureWrapper() - private val messagingFeature = ViewBoundFeatureWrapper() private val recentTabsListFeature = ViewBoundFeatureWrapper() private val recentBookmarksFeature = ViewBoundFeatureWrapper() private val historyMetadataFeature = ViewBoundFeatureWrapper() @@ -242,16 +239,6 @@ class HomeFragment : Fragment() { } } - if (requireContext().settings().isExperimentationEnabled) { - messagingFeature.set( - feature = MessagingFeature( - store = requireComponents.appStore, - ), - owner = viewLifecycleOwner, - view = binding.root - ) - } - if (requireContext().settings().showTopSitesFeature) { topSitesFeature.set( feature = TopSitesFeature( @@ -311,11 +298,6 @@ class HomeFragment : Fragment() { settings = components.settings, engine = components.core.engine, metrics = components.analytics.metrics, - messageController = DefaultMessageController( - appStore = components.appStore, - messagingStorage = components.analytics.messagingStorage, - homeActivity = activity - ), store = store, tabCollectionStorage = components.core.tabCollectionStorage, addTabUseCase = components.useCases.tabsUseCases.addTab, diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 3c55059f7..5a25f6a99 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -18,7 +18,6 @@ import mozilla.components.feature.top.sites.TopSite import mozilla.components.ui.widgets.WidgetSiteItemView import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.Components -import org.mozilla.fenix.gleanplumb.Message import org.mozilla.fenix.home.BottomSpacerViewHolder import org.mozilla.fenix.home.TopPlaceholderViewHolder import org.mozilla.fenix.home.pocket.PocketCategoriesViewHolder @@ -36,7 +35,7 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.CustomizeHomeButtonView import org.mozilla.fenix.home.sessioncontrol.viewholders.NoCollectionsMessageViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.PrivateBrowsingDescriptionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder -import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.MessageCardViewHolder +import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.ExperimentDefaultBrowserCardViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingFinishViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingHeaderViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingManualSignInViewHolder @@ -143,12 +142,10 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) { object OnboardingManualSignIn : AdapterItem(OnboardingManualSignInViewHolder.LAYOUT_ID) - data class NimbusMessageCard( - val message: Message - ) : AdapterItem(MessageCardViewHolder.LAYOUT_ID) { - override fun sameAs(other: AdapterItem) = - other is NimbusMessageCard && message.id == other.message.id - } + /** + * AdapterItem for the default browser card. + */ + object ExperimentDefaultBrowserCard : AdapterItem(ExperimentDefaultBrowserCardViewHolder.LAYOUT_ID) object OnboardingThemePicker : AdapterItem(OnboardingThemePickerViewHolder.LAYOUT_ID) object OnboardingTrackingProtection : @@ -308,7 +305,7 @@ class SessionControlAdapter( OnboardingToolbarPositionPickerViewHolder.LAYOUT_ID -> OnboardingToolbarPositionPickerViewHolder( view ) - MessageCardViewHolder.LAYOUT_ID -> MessageCardViewHolder(view, interactor) + ExperimentDefaultBrowserCardViewHolder.LAYOUT_ID -> ExperimentDefaultBrowserCardViewHolder(view, interactor) BottomSpacerViewHolder.LAYOUT_ID -> BottomSpacerViewHolder(view) else -> throw IllegalStateException() } @@ -369,9 +366,6 @@ class SessionControlAdapter( is TopSitePagerViewHolder -> { holder.bind((item as AdapterItem.TopSitePager).topSites) } - is MessageCardViewHolder -> { - holder.bind((item as AdapterItem.NimbusMessageCard).message) - } is CollectionViewHolder -> { val (collection, expanded) = item as AdapterItem.CollectionItem holder.bindSession(collection, expanded) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index 900d8fa57..adc47aeba 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -48,9 +48,8 @@ import org.mozilla.fenix.components.metrics.MetricsUtils import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.ext.openSetDefaultBrowserOption import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.gleanplumb.Message -import org.mozilla.fenix.gleanplumb.MessageController import org.mozilla.fenix.home.HomeFragment import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.Mode @@ -176,19 +175,14 @@ interface SessionControlController { fun handleMenuOpened() /** - * @see [MessageCardInteractor.onMessageClicked] + * @see [ExperimentCardInteractor.onSetDefaultBrowserClicked] */ - fun handleMessageClicked(message: Message) + fun handleSetDefaultBrowser() /** - * @see [MessageCardInteractor.onMessageClosedClicked] + * @see [ExperimentCardInteractor.onCloseExperimentCardClicked] */ - fun handleMessageClosed(message: Message) - - /** - * @see [MessageCardInteractor.onMessageDisplayed] - */ - fun handleMessageDisplayed(message: Message) + fun handleCloseExperimentCard() /** * @see [TabSessionInteractor.onPrivateModeButtonClicked] @@ -211,13 +205,12 @@ interface SessionControlController { fun handleReportSessionMetrics(state: AppState) } -@Suppress("TooManyFunctions", "LargeClass") +@Suppress("TooManyFunctions", "LargeClass", "LongParameterList") class DefaultSessionControlController( private val activity: HomeActivity, private val settings: Settings, private val engine: Engine, private val metrics: MetricController, - private val messageController: MessageController, private val store: BrowserStore, private val tabCollectionStorage: TabCollectionStorage, private val addTabUseCase: TabsUseCases.AddNewTabUseCase, @@ -615,16 +608,14 @@ class DefaultSessionControlController( navController.nav(R.id.homeFragment, directions) } - override fun handleMessageClicked(message: Message) { - messageController.onMessagePressed(message) - } - - override fun handleMessageClosed(message: Message) { - messageController.onMessageDismissed(message) + override fun handleSetDefaultBrowser() { + settings.userDismissedExperimentCard = true + activity.openSetDefaultBrowserOption() } - override fun handleMessageDisplayed(message: Message) { - messageController.onMessageDisplayed(message) + override fun handleCloseExperimentCard() { + settings.userDismissedExperimentCard = true + appStore.dispatch(AppAction.RemoveSetDefaultBrowserCard) } override fun handlePrivateModeButtonClicked( diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt index bc86cd9c7..85fe998b5 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlInteractor.kt @@ -10,7 +10,6 @@ import mozilla.components.feature.top.sites.TopSite import mozilla.components.service.pocket.PocketRecommendedStory import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.appstate.AppState -import org.mozilla.fenix.gleanplumb.Message import org.mozilla.fenix.home.pocket.PocketRecommendedStoriesCategory import org.mozilla.fenix.home.pocket.PocketStoriesController import org.mozilla.fenix.home.pocket.PocketStoriesInteractor @@ -226,21 +225,19 @@ interface TopSiteInteractor { fun onTopSiteMenuOpened() } -interface MessageCardInteractor { - /** - * Called when a [Message]'s button is clicked - */ - fun onMessageClicked(message: Message) - +/** + * Interface for interactions with the default browser card. + */ +interface ExperimentCardInteractor { /** - * Called when close button on a [Message] card. + * Called when set default browser button is clicked */ - fun onMessageClosedClicked(message: Message) + fun onSetDefaultBrowserClicked() /** - * Called when close button on a [Message] card. + * Called when close button on experiment card */ - fun onMessageDisplayed(message: Message) + fun onCloseExperimentCardClicked() } /** @@ -261,7 +258,7 @@ class SessionControlInteractor( TopSiteInteractor, TabSessionInteractor, ToolbarInteractor, - MessageCardInteractor, + ExperimentCardInteractor, RecentTabInteractor, RecentBookmarksInteractor, RecentVisitsInteractor, @@ -368,6 +365,14 @@ class SessionControlInteractor( controller.handleMenuOpened() } + override fun onSetDefaultBrowserClicked() { + controller.handleSetDefaultBrowser() + } + + override fun onCloseExperimentCardClicked() { + controller.handleCloseExperimentCard() + } + override fun onRecentTabClicked(tabId: String) { recentTabController.handleRecentTabClicked(tabId) } @@ -445,16 +450,4 @@ class SessionControlInteractor( override fun reportSessionMetrics(state: AppState) { controller.handleReportSessionMetrics(state) } - - override fun onMessageClicked(message: Message) { - controller.handleMessageClicked(message) - } - - override fun onMessageClosedClicked(message: Message) { - controller.handleMessageClosed(message) - } - - override fun onMessageDisplayed(message: Message) { - controller.handleMessageDisplayed(message) - } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt index 89a70bf54..55b5216cf 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlView.kt @@ -15,7 +15,6 @@ import mozilla.components.feature.top.sites.TopSite import mozilla.components.service.pocket.PocketRecommendedStory import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.appstate.AppState -import org.mozilla.fenix.gleanplumb.Message import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.Mode @@ -37,7 +36,7 @@ internal fun normalModeAdapterItems( expandedCollections: Set, recentBookmarks: List, showCollectionsPlaceholder: Boolean, - nimbusMessageCard: Message? = null, + showSetAsDefaultBrowserCard: Boolean, recentTabs: List, recentVisits: List, pocketStories: List @@ -48,8 +47,8 @@ internal fun normalModeAdapterItems( // Add a synchronous, unconditional and invisible placeholder so home is anchored to the top when created. items.add(AdapterItem.TopPlaceholderItem) - nimbusMessageCard?.let { - items.add(AdapterItem.NimbusMessageCard(it)) + if (showSetAsDefaultBrowserCard) { + items.add(AdapterItem.ExperimentDefaultBrowserCard) } if (settings.showTopSitesFeature && topSites.isNotEmpty()) { @@ -158,7 +157,7 @@ private fun AppState.toAdapterList(settings: Settings): List = when expandedCollections, recentBookmarks, showCollectionPlaceholder, - messaging.messageToShow, + showSetAsDefaultBrowserCard, recentTabs, recentHistory, pocketStories diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/ExperimentDefaultBrowserCardViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/ExperimentDefaultBrowserCardViewHolder.kt new file mode 100644 index 000000000..60a1b10ac --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/ExperimentDefaultBrowserCardViewHolder.kt @@ -0,0 +1,40 @@ +/* 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.home.sessioncontrol.viewholders.onboarding + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.ExperimentDefaultBrowserBinding +import org.mozilla.fenix.ext.increaseTapArea +import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor + +/** + * View holder for the default browser card. + */ +class ExperimentDefaultBrowserCardViewHolder( + view: View, + private val interactor: SessionControlInteractor +) : RecyclerView.ViewHolder(view) { + + init { + val binding = ExperimentDefaultBrowserBinding.bind(view) + binding.setDefaultBrowser.setOnClickListener { + interactor.onSetDefaultBrowserClicked() + } + + binding.close.apply { + increaseTapArea(CLOSE_BUTTON_EXTRA_DPS) + setOnClickListener { + interactor.onCloseExperimentCardClicked() + } + } + } + + companion object { + internal const val LAYOUT_ID = R.layout.experiment_default_browser + private const val CLOSE_BUTTON_EXTRA_DPS = 38 + } +} diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/MessageCardViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/MessageCardViewHolder.kt deleted file mode 100644 index 8af3c3b24..000000000 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/MessageCardViewHolder.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* 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.home.sessioncontrol.viewholders.onboarding - -import android.view.View -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView -import org.mozilla.fenix.R -import org.mozilla.fenix.databinding.NimbusMessageCardBinding -import org.mozilla.fenix.ext.increaseTapArea -import org.mozilla.fenix.gleanplumb.Message -import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor - -class MessageCardViewHolder( - view: View, - private val interactor: SessionControlInteractor -) : RecyclerView.ViewHolder(view) { - - fun bind(message: Message) { - val binding = NimbusMessageCardBinding.bind(itemView) - - if (message.data.title.isNullOrBlank()) { - binding.titleText.isVisible = false - } else { - binding.titleText.text = message.data.title - } - - binding.descriptionText.text = message.data.text - - if (message.data.buttonLabel.isNullOrBlank()) { - binding.messageButton.isVisible = false - binding.experimentCard.setOnClickListener { - interactor.onMessageClicked(message) - } - } else { - binding.messageButton.text = message.data.buttonLabel - binding.messageButton.setOnClickListener { - interactor.onMessageClicked(message) - } - } - - binding.close.apply { - increaseTapArea(CLOSE_BUTTON_EXTRA_DPS) - setOnClickListener { - interactor.onMessageClosedClicked(message) - } - } - interactor.onMessageDisplayed(message) - } - - companion object { - internal const val LAYOUT_ID = R.layout.nimbus_message_card - private const val CLOSE_BUTTON_EXTRA_DPS = 38 - } -} diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index baa83ce89..85a438678 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -71,6 +71,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { private const val ALLOWED_INT = 2 private const val CFR_COUNT_CONDITION_FOCUS_INSTALLED = 1 private const val CFR_COUNT_CONDITION_FOCUS_NOT_INSTALLED = 3 + private const val APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD = 3 private const val INACTIVE_TAB_MINIMUM_TO_SHOW_AUTO_CLOSE_DIALOG = 20 const val FOUR_HOURS_MS = 60 * 60 * 4 * 1000L @@ -311,6 +312,24 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = false ) + /** + * Shows if the user has chosen to close the set default browser experiment card + * on home screen or has clicked the set as default browser button. + */ + var userDismissedExperimentCard by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_experiment_card_home), + default = false + ) + + /** + * Shows if the set default browser experiment card should be shown on home screen. + */ + fun shouldShowSetAsDefaultBrowserCard(): Boolean { + return isDefaultBrowserMessageLocation(MessageSurfaceId.HOMESCREEN_BANNER) && + !userDismissedExperimentCard && + numberOfAppLaunches > APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD + } + private val defaultBrowserFeature: DefaultBrowserMessage by lazy { FxNimbus.features.defaultBrowserMessage.value() } @@ -1209,7 +1228,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) private val homescreenSections: Map by lazy { - FxNimbus.features.homescreen.value(appContext).sectionsEnabled + FxNimbus.features.homescreen.value().sectionsEnabled } var historyMetadataUIFeature by lazyFeatureFlagPreference( diff --git a/app/src/main/res/layout/nimbus_message_card.xml b/app/src/main/res/layout/experiment_default_browser.xml similarity index 78% rename from app/src/main/res/layout/nimbus_message_card.xml rename to app/src/main/res/layout/experiment_default_browser.xml index ea312f331..83dbd9d07 100644 --- a/app/src/main/res/layout/nimbus_message_card.xml +++ b/app/src/main/res/layout/experiment_default_browser.xml @@ -10,18 +10,6 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/home_item_horizontal_margin"> - -