mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-15 18:12:54 +00:00
[fenix] Closes https://github.com/mozilla-mobile/fenix/issues/26750: add Wallpapers Onboarding dialog
This commit is contained in:
parent
0168388546
commit
8205e6f907
@ -19,6 +19,7 @@ class FeatureSettingsHelper {
|
|||||||
private var isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature
|
private var isRecentlyVisitedFeatureEnabled: Boolean = settings.historyMetadataUIFeature
|
||||||
private var isUserKnowsAboutPwasTrue: Boolean = settings.userKnowsAboutPwas
|
private var isUserKnowsAboutPwasTrue: Boolean = settings.userKnowsAboutPwas
|
||||||
private var isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR
|
private var isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR
|
||||||
|
private var isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding
|
||||||
|
|
||||||
fun setPocketEnabled(enabled: Boolean) {
|
fun setPocketEnabled(enabled: Boolean) {
|
||||||
settings.showPocketRecommendationsFeature = enabled
|
settings.showPocketRecommendationsFeature = enabled
|
||||||
@ -28,6 +29,10 @@ class FeatureSettingsHelper {
|
|||||||
settings.shouldShowJumpBackInCFR = enabled
|
settings.shouldShowJumpBackInCFR = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setShowWallpaperOnboarding(enabled: Boolean) {
|
||||||
|
settings.showWallpaperOnboarding = enabled
|
||||||
|
}
|
||||||
|
|
||||||
fun setRecentTabsFeatureEnabled(enabled: Boolean) {
|
fun setRecentTabsFeatureEnabled(enabled: Boolean) {
|
||||||
settings.showRecentTabsFeature = enabled
|
settings.showRecentTabsFeature = enabled
|
||||||
}
|
}
|
||||||
@ -65,5 +70,6 @@ class FeatureSettingsHelper {
|
|||||||
settings.historyMetadataUIFeature = isRecentlyVisitedFeatureEnabled
|
settings.historyMetadataUIFeature = isRecentlyVisitedFeatureEnabled
|
||||||
settings.userKnowsAboutPwas = isUserKnowsAboutPwasTrue
|
settings.userKnowsAboutPwas = isUserKnowsAboutPwasTrue
|
||||||
settings.shouldShowTotalCookieProtectionCFR = isTCPCFREnabled
|
settings.shouldShowTotalCookieProtectionCFR = isTCPCFREnabled
|
||||||
|
settings.showWallpaperOnboarding = isWallpaperOnboardingEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ class CrashReportingTest {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setPocketEnabled(false)
|
featureSettingsHelper.setPocketEnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
|
|
||||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||||
mockWebServer = MockWebServer().apply {
|
mockWebServer = MockWebServer().apply {
|
||||||
|
@ -151,6 +151,7 @@ class HomeScreenTest {
|
|||||||
@Test
|
@Test
|
||||||
fun dismissOnboardingUsingHelpTest() {
|
fun dismissOnboardingUsingHelpTest() {
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
|
|
||||||
homeScreen {
|
homeScreen {
|
||||||
verifyWelcomeHeader()
|
verifyWelcomeHeader()
|
||||||
@ -200,6 +201,7 @@ class HomeScreenTest {
|
|||||||
fun verifyCustomizeHomepageTest() {
|
fun verifyCustomizeHomepageTest() {
|
||||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
|
|
||||||
navigationToolbar {
|
navigationToolbar {
|
||||||
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
||||||
|
@ -37,6 +37,7 @@ class NoNetworkAccessStartupTests {
|
|||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -66,6 +66,7 @@ class SearchTest {
|
|||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
featureSettingsHelper.setPocketEnabled(false)
|
featureSettingsHelper.setPocketEnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -70,6 +70,7 @@ class SettingsBasicsTest {
|
|||||||
|
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -44,6 +44,7 @@ class SettingsHomepageTest {
|
|||||||
}
|
}
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -64,6 +64,7 @@ class SettingsPrivacyTest {
|
|||||||
|
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
featureSettingsHelper.disablePwaCFR(true)
|
featureSettingsHelper.disablePwaCFR(true)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
|
||||||
|
@ -34,6 +34,7 @@ class SettingsSearchTest {
|
|||||||
start()
|
start()
|
||||||
}
|
}
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -95,6 +95,7 @@ class SmokeTest {
|
|||||||
// disabling the new homepage pop-up that interferes with the tests.
|
// disabling the new homepage pop-up that interferes with the tests.
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
|
|
||||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||||
mockWebServer = MockWebServer().apply {
|
mockWebServer = MockWebServer().apply {
|
||||||
|
@ -49,6 +49,7 @@ class StrictEnhancedTrackingProtectionTest {
|
|||||||
featureSettingsHelper.setStrictETPEnabled()
|
featureSettingsHelper.setStrictETPEnabled()
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -58,6 +58,7 @@ class TabbedBrowsingTest {
|
|||||||
// disabling the new homepage pop-up that interferes with the tests.
|
// disabling the new homepage pop-up that interferes with the tests.
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
|
|
||||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||||
mockWebServer = MockWebServer().apply {
|
mockWebServer = MockWebServer().apply {
|
||||||
|
@ -55,6 +55,7 @@ class TopSitesTest {
|
|||||||
|
|
||||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||||
featureSettingsHelper.setTCPCFREnabled(false)
|
featureSettingsHelper.setTCPCFREnabled(false)
|
||||||
|
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -56,9 +56,12 @@ import org.mozilla.fenix.gleanplumb.MessageController
|
|||||||
import org.mozilla.fenix.home.HomeFragment
|
import org.mozilla.fenix.home.HomeFragment
|
||||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||||
import org.mozilla.fenix.home.Mode
|
import org.mozilla.fenix.home.Mode
|
||||||
|
import org.mozilla.fenix.onboarding.WallpaperOnboardingDialogFragment
|
||||||
import org.mozilla.fenix.settings.SupportUtils
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.PRIVATE_BROWSING_MYTHS
|
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.PRIVATE_BROWSING_MYTHS
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
import org.mozilla.fenix.wallpapers.Wallpaper
|
||||||
|
import org.mozilla.fenix.wallpapers.WallpaperState
|
||||||
import mozilla.components.feature.tab.collections.Tab as ComponentTab
|
import mozilla.components.feature.tab.collections.Tab as ComponentTab
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,6 +200,11 @@ interface SessionControlController {
|
|||||||
*/
|
*/
|
||||||
fun handleCustomizeHomeTapped()
|
fun handleCustomizeHomeTapped()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see [OnboardingInteractor.showWallpapersOnboardingDialog]
|
||||||
|
*/
|
||||||
|
fun handleShowWallpapersOnboardingDialog(state: WallpaperState): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see [SessionControlInteractor.reportSessionMetrics]
|
* @see [SessionControlInteractor.reportSessionMetrics]
|
||||||
*/
|
*/
|
||||||
@ -501,6 +509,19 @@ class DefaultSessionControlController(
|
|||||||
HomeScreen.customizeHomeClicked.record(NoExtras())
|
HomeScreen.customizeHomeClicked.record(NoExtras())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleShowWallpapersOnboardingDialog(state: WallpaperState): Boolean {
|
||||||
|
if (state.availableWallpapers.all { it.thumbnailFileState == Wallpaper.ImageFileState.Downloaded } &&
|
||||||
|
state.availableWallpapers.size >= WallpaperOnboardingDialogFragment.THUMBNAILS_COUNT
|
||||||
|
) {
|
||||||
|
navController.nav(
|
||||||
|
R.id.homeFragment,
|
||||||
|
HomeFragmentDirections.actionGlobalWallpaperOnboardingDialog(),
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleReadPrivacyNoticeClicked() {
|
override fun handleReadPrivacyNoticeClicked() {
|
||||||
activity.openToBrowserAndLoad(
|
activity.openToBrowserAndLoad(
|
||||||
searchTermOrURL = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
|
searchTermOrURL = SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE),
|
||||||
|
@ -27,6 +27,7 @@ import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryGrou
|
|||||||
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryHighlight
|
import org.mozilla.fenix.home.recentvisits.RecentlyVisitedItem.RecentHistoryHighlight
|
||||||
import org.mozilla.fenix.home.recentvisits.controller.RecentVisitsController
|
import org.mozilla.fenix.home.recentvisits.controller.RecentVisitsController
|
||||||
import org.mozilla.fenix.home.recentvisits.interactor.RecentVisitsInteractor
|
import org.mozilla.fenix.home.recentvisits.interactor.RecentVisitsInteractor
|
||||||
|
import org.mozilla.fenix.wallpapers.WallpaperState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for tab related actions in the [SessionControlInteractor].
|
* Interface for tab related actions in the [SessionControlInteractor].
|
||||||
@ -162,6 +163,15 @@ interface OnboardingInteractor {
|
|||||||
* Opens a custom tab to privacy notice url. Called when a user clicks on the "read our privacy notice" button.
|
* Opens a custom tab to privacy notice url. Called when a user clicks on the "read our privacy notice" button.
|
||||||
*/
|
*/
|
||||||
fun onReadPrivacyNoticeClicked()
|
fun onReadPrivacyNoticeClicked()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Wallpapers onboarding dialog to onboard users about the feature if conditions are met.
|
||||||
|
* Returns true if the call has been passed down to the controller.
|
||||||
|
*
|
||||||
|
* @param state The wallpaper state.
|
||||||
|
* @return Whether the onboarding dialog is currently shown.
|
||||||
|
*/
|
||||||
|
fun showWallpapersOnboardingDialog(state: WallpaperState): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CustomizeHomeIteractor {
|
interface CustomizeHomeIteractor {
|
||||||
@ -322,6 +332,10 @@ class SessionControlInteractor(
|
|||||||
controller.handleReadPrivacyNoticeClicked()
|
controller.handleReadPrivacyNoticeClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showWallpapersOnboardingDialog(state: WallpaperState): Boolean {
|
||||||
|
return controller.handleShowWallpapersOnboardingDialog(state)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onToggleCollectionExpanded(collection: TabCollection, expand: Boolean) {
|
override fun onToggleCollectionExpanded(collection: TabCollection, expand: Boolean) {
|
||||||
controller.handleToggleCollectionExpanded(collection, expand)
|
controller.handleToggleCollectionExpanded(collection, expand)
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,9 @@ class SessionControlView(
|
|||||||
|
|
||||||
val view: RecyclerView = containerView as RecyclerView
|
val view: RecyclerView = containerView as RecyclerView
|
||||||
|
|
||||||
|
// We want to limit feature recommendations to one per HomePage visit.
|
||||||
|
var featureRecommended = false
|
||||||
|
|
||||||
private val sessionControlAdapter = SessionControlAdapter(
|
private val sessionControlAdapter = SessionControlAdapter(
|
||||||
interactor,
|
interactor,
|
||||||
viewLifecycleOwner,
|
viewLifecycleOwner,
|
||||||
@ -206,21 +209,33 @@ class SessionControlView(
|
|||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@Suppress("NestedBlockDepth")
|
||||||
view.apply {
|
view.apply {
|
||||||
adapter = sessionControlAdapter
|
adapter = sessionControlAdapter
|
||||||
layoutManager = object : LinearLayoutManager(containerView.context) {
|
layoutManager = object : LinearLayoutManager(containerView.context) {
|
||||||
override fun onLayoutCompleted(state: RecyclerView.State?) {
|
override fun onLayoutCompleted(state: RecyclerView.State?) {
|
||||||
super.onLayoutCompleted(state)
|
super.onLayoutCompleted(state)
|
||||||
|
|
||||||
if (!context.settings().showHomeOnboardingDialog && (
|
if (!featureRecommended && !context.settings().showHomeOnboardingDialog) {
|
||||||
context.settings().showSyncCFR ||
|
if (!context.settings().showHomeOnboardingDialog && (
|
||||||
context.settings().shouldShowJumpBackInCFR
|
context.settings().showSyncCFR ||
|
||||||
)
|
context.settings().shouldShowJumpBackInCFR
|
||||||
) {
|
)
|
||||||
HomeCFRPresenter(
|
) {
|
||||||
context = context,
|
featureRecommended = HomeCFRPresenter(
|
||||||
recyclerView = view,
|
context = context,
|
||||||
).show()
|
recyclerView = view,
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.settings().shouldShowJumpBackInCFR &&
|
||||||
|
context.settings().showWallpaperOnboarding &&
|
||||||
|
!featureRecommended
|
||||||
|
) {
|
||||||
|
featureRecommended = interactor.showWallpapersOnboardingDialog(
|
||||||
|
context.components.appStore.state.wallpaperState,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want some parts of the home screen UI to be rendered first if they are
|
// We want some parts of the home screen UI to be rendered first if they are
|
||||||
|
@ -38,13 +38,17 @@ class HomeCFRPresenter(
|
|||||||
* Determine the CFR to be shown on the Home screen and show a CFR for the resultant view
|
* Determine the CFR to be shown on the Home screen and show a CFR for the resultant view
|
||||||
* if any.
|
* if any.
|
||||||
*/
|
*/
|
||||||
fun show() {
|
fun show(): Boolean {
|
||||||
when (val result = getCFRToShow()) {
|
return when (val result = getCFRToShow()) {
|
||||||
is Result.SyncedTab -> showSyncedTabCFR(view = result.view)
|
is Result.SyncedTab -> {
|
||||||
is Result.JumpBackIn -> showJumpBackInCFR(view = result.view)
|
showSyncedTabCFR(view = result.view)
|
||||||
else -> {
|
true
|
||||||
// no-op
|
|
||||||
}
|
}
|
||||||
|
is Result.JumpBackIn -> {
|
||||||
|
showJumpBackInCFR(view = result.view)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
/* 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.onboarding
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import mozilla.components.lib.state.ext.observeAsComposableState
|
||||||
|
import org.mozilla.fenix.NavGraphDirections
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
|
import org.mozilla.fenix.ext.settings
|
||||||
|
import org.mozilla.fenix.theme.FirefoxTheme
|
||||||
|
import org.mozilla.fenix.wallpapers.Wallpaper
|
||||||
|
import org.mozilla.fenix.wallpapers.WallpaperOnboarding
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog displaying the wallpapers onboarding.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
|
class WallpaperOnboardingDialogFragment : BottomSheetDialogFragment() {
|
||||||
|
private val appStore by lazy {
|
||||||
|
requireComponents.appStore
|
||||||
|
}
|
||||||
|
|
||||||
|
private val wallpaperUseCases by lazy {
|
||||||
|
requireComponents.useCases.wallpaperUseCases
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setStyle(STYLE_NO_TITLE, R.style.WallpaperOnboardingDialogStyle)
|
||||||
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
requireContext().settings().showWallpaperOnboarding = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?,
|
||||||
|
): View = ComposeView(requireContext()).apply {
|
||||||
|
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
FirefoxTheme {
|
||||||
|
val wallpapers = appStore.observeAsComposableState { state ->
|
||||||
|
state.wallpaperState.availableWallpapers.take(THUMBNAILS_COUNT)
|
||||||
|
}.value ?: listOf()
|
||||||
|
val currentWallpaper = appStore.observeAsComposableState { state ->
|
||||||
|
state.wallpaperState.currentWallpaper
|
||||||
|
}.value ?: Wallpaper.Default
|
||||||
|
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
WallpaperOnboarding(
|
||||||
|
wallpapers = wallpapers,
|
||||||
|
currentWallpaper = currentWallpaper,
|
||||||
|
onCloseClicked = { dismiss() },
|
||||||
|
onExploreMoreButtonClicked = {
|
||||||
|
val directions = NavGraphDirections.actionGlobalWallpaperSettingsFragment()
|
||||||
|
findNavController().navigate(directions)
|
||||||
|
},
|
||||||
|
loadWallpaperResource = { wallpaperUseCases.loadThumbnail(it) },
|
||||||
|
onSelectWallpaper = {
|
||||||
|
coroutineScope.launch { wallpaperUseCases.selectWallpaper(it) }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val THUMBNAILS_COUNT = 6
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@ package org.mozilla.fenix.settings.wallpaper
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@ -91,8 +90,8 @@ fun WallpaperSettings(
|
|||||||
WallpaperThumbnails(
|
WallpaperThumbnails(
|
||||||
wallpapers = wallpapers,
|
wallpapers = wallpapers,
|
||||||
defaultWallpaper = defaultWallpaper,
|
defaultWallpaper = defaultWallpaper,
|
||||||
loadWallpaperResource = loadWallpaperResource,
|
|
||||||
selectedWallpaper = selectedWallpaper,
|
selectedWallpaper = selectedWallpaper,
|
||||||
|
loadWallpaperResource = loadWallpaperResource,
|
||||||
onSelectWallpaper = { updatedWallpaper ->
|
onSelectWallpaper = { updatedWallpaper ->
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
scaffoldState.snackbarHostState.showSnackbar(
|
scaffoldState.snackbarHostState.showSnackbar(
|
||||||
@ -147,19 +146,27 @@ private fun WallpaperSnackbar(
|
|||||||
* @param selectedWallpaper The currently selected wallpaper.
|
* @param selectedWallpaper The currently selected wallpaper.
|
||||||
* @param numColumns The number of columns that will occupy the grid.
|
* @param numColumns The number of columns that will occupy the grid.
|
||||||
* @param onSelectWallpaper Action to take when a new wallpaper is selected.
|
* @param onSelectWallpaper Action to take when a new wallpaper is selected.
|
||||||
|
* @param verticalPadding Vertical content padding inside the block.
|
||||||
|
* @param horizontalPadding Horizontal content padding inside the block.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
private fun WallpaperThumbnails(
|
fun WallpaperThumbnails(
|
||||||
wallpapers: List<Wallpaper>,
|
wallpapers: List<Wallpaper>,
|
||||||
defaultWallpaper: Wallpaper,
|
defaultWallpaper: Wallpaper,
|
||||||
loadWallpaperResource: suspend (Wallpaper) -> Bitmap?,
|
|
||||||
selectedWallpaper: Wallpaper,
|
selectedWallpaper: Wallpaper,
|
||||||
numColumns: Int = 3,
|
loadWallpaperResource: suspend (Wallpaper) -> Bitmap?,
|
||||||
onSelectWallpaper: (Wallpaper) -> Unit,
|
onSelectWallpaper: (Wallpaper) -> Unit,
|
||||||
|
numColumns: Int = 3,
|
||||||
|
verticalPadding: Int = 30,
|
||||||
|
horizontalPadding: Int = 20,
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(vertical = 30.dp, horizontal = 20.dp)) {
|
Column(
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
vertical = verticalPadding.dp,
|
||||||
|
horizontal = horizontalPadding.dp,
|
||||||
|
),
|
||||||
|
) {
|
||||||
val numRows = (wallpapers.size + numColumns - 1) / numColumns
|
val numRows = (wallpapers.size + numColumns - 1) / numColumns
|
||||||
for (rowIndex in 0 until numRows) {
|
for (rowIndex in 0 until numRows) {
|
||||||
Row {
|
Row {
|
||||||
@ -167,7 +174,9 @@ private fun WallpaperThumbnails(
|
|||||||
val itemIndex = rowIndex * numColumns + columnIndex
|
val itemIndex = rowIndex * numColumns + columnIndex
|
||||||
if (itemIndex < wallpapers.size) {
|
if (itemIndex < wallpapers.size) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.weight(1f, fill = true).padding(4.dp),
|
modifier = Modifier
|
||||||
|
.weight(1f, fill = true)
|
||||||
|
.padding(4.dp),
|
||||||
) {
|
) {
|
||||||
WallpaperThumbnailItem(
|
WallpaperThumbnailItem(
|
||||||
wallpaper = wallpapers[itemIndex],
|
wallpaper = wallpapers[itemIndex],
|
||||||
|
@ -210,7 +210,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||||||
/**
|
/**
|
||||||
* Indicates if the wallpaper onboarding dialog should be shown.
|
* Indicates if the wallpaper onboarding dialog should be shown.
|
||||||
*/
|
*/
|
||||||
val showWallpaperOnboarding by lazyFeatureFlagPreference(
|
var showWallpaperOnboarding by lazyFeatureFlagPreference(
|
||||||
key = appContext.getPreferenceKey(R.string.pref_key_wallpapers_onboarding),
|
key = appContext.getPreferenceKey(R.string.pref_key_wallpapers_onboarding),
|
||||||
featureFlag = FeatureFlags.wallpaperOnboardingEnabled,
|
featureFlag = FeatureFlags.wallpaperOnboardingEnabled,
|
||||||
default = { mr2022Sections[Mr2022Section.WALLPAPERS_SELECTION_TOOL] == true },
|
default = { mr2022Sections[Mr2022Section.WALLPAPERS_SELECTION_TOOL] == true },
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
/* 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.wallpapers
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.Surface
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.settings.wallpaper.WallpaperThumbnails
|
||||||
|
import org.mozilla.fenix.theme.FirefoxTheme
|
||||||
|
import org.mozilla.fenix.theme.Theme
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A view that shows content of a WallpaperOnboarding dialog.
|
||||||
|
*
|
||||||
|
* @param wallpapers Wallpapers to add to grid.
|
||||||
|
* @param currentWallpaper The currently selected wallpaper.
|
||||||
|
* @param loadWallpaperResource Callback to handle loading a wallpaper bitmap. Only optional in the default case.
|
||||||
|
* @param onCloseClicked Callback for when the close button is clicked.
|
||||||
|
* @param onExploreMoreButtonClicked Callback for when the bottom text button is clicked.
|
||||||
|
* @param onSelectWallpaper Callback for when a new wallpaper is selected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
|
@ExperimentalMaterialApi
|
||||||
|
@Composable
|
||||||
|
fun WallpaperOnboarding(
|
||||||
|
wallpapers: List<Wallpaper>,
|
||||||
|
currentWallpaper: Wallpaper,
|
||||||
|
loadWallpaperResource: suspend (Wallpaper) -> Bitmap?,
|
||||||
|
onCloseClicked: () -> Unit,
|
||||||
|
onExploreMoreButtonClicked: () -> Unit,
|
||||||
|
onSelectWallpaper: (Wallpaper) -> Unit,
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
color = FirefoxTheme.colors.layer2,
|
||||||
|
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.mozac_ic_close),
|
||||||
|
contentDescription = stringResource(id = R.string.close_tab),
|
||||||
|
tint = FirefoxTheme.colors.iconPrimary,
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable { onCloseClicked() }
|
||||||
|
.size(24.dp)
|
||||||
|
.align(Alignment.End),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.wallpapers_onboarding_dialog_title_text),
|
||||||
|
color = FirefoxTheme.colors.textPrimary,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
style = FirefoxTheme.typography.headline7,
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.wallpapers_onboarding_dialog_body_text),
|
||||||
|
color = FirefoxTheme.colors.textSecondary,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
style = FirefoxTheme.typography.caption,
|
||||||
|
)
|
||||||
|
|
||||||
|
WallpaperThumbnails(
|
||||||
|
wallpapers = wallpapers,
|
||||||
|
defaultWallpaper = Wallpaper.Default,
|
||||||
|
selectedWallpaper = currentWallpaper,
|
||||||
|
loadWallpaperResource = { loadWallpaperResource(it) },
|
||||||
|
onSelectWallpaper = { onSelectWallpaper(it) },
|
||||||
|
verticalPadding = 16,
|
||||||
|
horizontalPadding = 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
TextButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
onClick = { onExploreMoreButtonClicked() },
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.wallpapers_onboarding_dialog_explore_more_button_text),
|
||||||
|
color = FirefoxTheme.colors.textAccent,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
style = FirefoxTheme.typography.button,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@ExperimentalMaterialApi
|
||||||
|
@Composable
|
||||||
|
private fun WallpaperSnackbarPreview() {
|
||||||
|
FirefoxTheme(theme = Theme.getTheme()) {
|
||||||
|
WallpaperOnboarding(
|
||||||
|
wallpapers = listOf(Wallpaper.Default),
|
||||||
|
currentWallpaper = Wallpaper.Default,
|
||||||
|
onCloseClicked = {},
|
||||||
|
onExploreMoreButtonClicked = {},
|
||||||
|
loadWallpaperResource = { null },
|
||||||
|
onSelectWallpaper = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,11 @@
|
|||||||
app:destination="@id/homeOnboardingDialogFragment"
|
app:destination="@id/homeOnboardingDialogFragment"
|
||||||
app:popUpTo="@id/homeFragment" />
|
app:popUpTo="@id/homeFragment" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_wallpaper_onboarding_dialog"
|
||||||
|
app:destination="@id/wallpaperOnboardingDialogFragment"
|
||||||
|
app:popUpTo="@id/homeFragment" />
|
||||||
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_global_search_dialog"
|
android:id="@+id/action_global_search_dialog"
|
||||||
app:destination="@id/searchDialogFragment"
|
app:destination="@id/searchDialogFragment"
|
||||||
@ -189,6 +194,10 @@
|
|||||||
android:id="@+id/homeOnboardingDialogFragment"
|
android:id="@+id/homeOnboardingDialogFragment"
|
||||||
android:name="org.mozilla.fenix.onboarding.HomeOnboardingDialogFragment" />
|
android:name="org.mozilla.fenix.onboarding.HomeOnboardingDialogFragment" />
|
||||||
|
|
||||||
|
<dialog
|
||||||
|
android:id="@+id/wallpaperOnboardingDialogFragment"
|
||||||
|
android:name="org.mozilla.fenix.onboarding.WallpaperOnboardingDialogFragment" />
|
||||||
|
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/searchDialogFragment"
|
android:id="@+id/searchDialogFragment"
|
||||||
android:name="org.mozilla.fenix.search.SearchDialogFragment"
|
android:name="org.mozilla.fenix.search.SearchDialogFragment"
|
||||||
|
@ -458,6 +458,12 @@
|
|||||||
<!-- This is the accessibility content description for the wallpapers functionality. Users are
|
<!-- This is the accessibility content description for the wallpapers functionality. Users are
|
||||||
able to tap on the app logo in the home screen and can switch to different wallpapers by tapping. -->
|
able to tap on the app logo in the home screen and can switch to different wallpapers by tapping. -->
|
||||||
<string name="wallpaper_logo_content_description" moz:removedIn="105" tools:ignore="UnusedResources">Firefox logo - change the wallpaper, button</string>
|
<string name="wallpaper_logo_content_description" moz:removedIn="105" tools:ignore="UnusedResources">Firefox logo - change the wallpaper, button</string>
|
||||||
|
<!-- Wallpaper onboarding dialog header text. -->
|
||||||
|
<string name="wallpapers_onboarding_dialog_title_text">Try a splash of color</string>
|
||||||
|
<!-- Wallpaper onboarding dialog body text. -->
|
||||||
|
<string name="wallpapers_onboarding_dialog_body_text">Choose a wallpaper that speaks to you.</string>
|
||||||
|
<!-- Wallpaper onboarding dialog learn more button text. The button navigates to the wallpaper settings screen. -->
|
||||||
|
<string name="wallpapers_onboarding_dialog_explore_more_button_text">Explore more wallpapers</string>
|
||||||
|
|
||||||
<!-- Add-on Installation from AMO-->
|
<!-- Add-on Installation from AMO-->
|
||||||
<!-- Error displayed when user attempts to install an add-on from AMO (addons.mozilla.org) that is not supported -->
|
<!-- Error displayed when user attempts to install an add-on from AMO (addons.mozilla.org) that is not supported -->
|
||||||
|
@ -564,6 +564,10 @@
|
|||||||
<style name="CreateCollectionDialogStyle" parent="DialogStyleBase"/>
|
<style name="CreateCollectionDialogStyle" parent="DialogStyleBase"/>
|
||||||
<style name="CreateShortcutDialogStyle" parent="DialogStyleBase"/>
|
<style name="CreateShortcutDialogStyle" parent="DialogStyleBase"/>
|
||||||
<style name="HomeOnboardingDialogStyle" parent="DialogStyleBase"/>
|
<style name="HomeOnboardingDialogStyle" parent="DialogStyleBase"/>
|
||||||
|
<style name="WallpaperOnboardingDialogStyle" parent="DialogStyleBase">
|
||||||
|
<item name="android:windowIsFloating">true</item>
|
||||||
|
<item name="android:backgroundDimAmount">0.02</item>
|
||||||
|
</style>
|
||||||
<style name="CreateShortcutDialogButton" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
|
<style name="CreateShortcutDialogButton" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
|
||||||
<item name="android:layout_width">wrap_content</item>
|
<item name="android:layout_width">wrap_content</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user