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 isUserKnowsAboutPwasTrue: Boolean = settings.userKnowsAboutPwas
|
||||
private var isTCPCFREnabled: Boolean = settings.shouldShowTotalCookieProtectionCFR
|
||||
private var isWallpaperOnboardingEnabled: Boolean = settings.showWallpaperOnboarding
|
||||
|
||||
fun setPocketEnabled(enabled: Boolean) {
|
||||
settings.showPocketRecommendationsFeature = enabled
|
||||
@ -28,6 +29,10 @@ class FeatureSettingsHelper {
|
||||
settings.shouldShowJumpBackInCFR = enabled
|
||||
}
|
||||
|
||||
fun setShowWallpaperOnboarding(enabled: Boolean) {
|
||||
settings.showWallpaperOnboarding = enabled
|
||||
}
|
||||
|
||||
fun setRecentTabsFeatureEnabled(enabled: Boolean) {
|
||||
settings.showRecentTabsFeature = enabled
|
||||
}
|
||||
@ -65,5 +70,6 @@ class FeatureSettingsHelper {
|
||||
settings.historyMetadataUIFeature = isRecentlyVisitedFeatureEnabled
|
||||
settings.userKnowsAboutPwas = isUserKnowsAboutPwasTrue
|
||||
settings.shouldShowTotalCookieProtectionCFR = isTCPCFREnabled
|
||||
settings.showWallpaperOnboarding = isWallpaperOnboardingEnabled
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class CrashReportingTest {
|
||||
fun setUp() {
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setPocketEnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
|
||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
mockWebServer = MockWebServer().apply {
|
||||
|
@ -151,6 +151,7 @@ class HomeScreenTest {
|
||||
@Test
|
||||
fun dismissOnboardingUsingHelpTest() {
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
|
||||
homeScreen {
|
||||
verifyWelcomeHeader()
|
||||
@ -200,6 +201,7 @@ class HomeScreenTest {
|
||||
fun verifyCustomizeHomepageTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
|
||||
navigationToolbar {
|
||||
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
||||
|
@ -37,6 +37,7 @@ class NoNetworkAccessStartupTests {
|
||||
@Before
|
||||
fun setUp() {
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -66,6 +66,7 @@ class SearchTest {
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setPocketEnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -70,6 +70,7 @@ class SettingsBasicsTest {
|
||||
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -44,6 +44,7 @@ class SettingsHomepageTest {
|
||||
}
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -64,6 +64,7 @@ class SettingsPrivacyTest {
|
||||
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
featureSettingsHelper.disablePwaCFR(true)
|
||||
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
|
||||
|
@ -34,6 +34,7 @@ class SettingsSearchTest {
|
||||
start()
|
||||
}
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -95,6 +95,7 @@ class SmokeTest {
|
||||
// disabling the new homepage pop-up that interferes with the tests.
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
|
||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
mockWebServer = MockWebServer().apply {
|
||||
|
@ -49,6 +49,7 @@ class StrictEnhancedTrackingProtectionTest {
|
||||
featureSettingsHelper.setStrictETPEnabled()
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -58,6 +58,7 @@ class TabbedBrowsingTest {
|
||||
// disabling the new homepage pop-up that interferes with the tests.
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
|
||||
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
mockWebServer = MockWebServer().apply {
|
||||
|
@ -55,6 +55,7 @@ class TopSitesTest {
|
||||
|
||||
featureSettingsHelper.setJumpBackCFREnabled(false)
|
||||
featureSettingsHelper.setTCPCFREnabled(false)
|
||||
featureSettingsHelper.setShowWallpaperOnboarding(false)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -56,9 +56,12 @@ import org.mozilla.fenix.gleanplumb.MessageController
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
import org.mozilla.fenix.home.Mode
|
||||
import org.mozilla.fenix.onboarding.WallpaperOnboardingDialogFragment
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
import org.mozilla.fenix.settings.SupportUtils.SumoTopic.PRIVATE_BROWSING_MYTHS
|
||||
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
|
||||
|
||||
/**
|
||||
@ -197,6 +200,11 @@ interface SessionControlController {
|
||||
*/
|
||||
fun handleCustomizeHomeTapped()
|
||||
|
||||
/**
|
||||
* @see [OnboardingInteractor.showWallpapersOnboardingDialog]
|
||||
*/
|
||||
fun handleShowWallpapersOnboardingDialog(state: WallpaperState): Boolean
|
||||
|
||||
/**
|
||||
* @see [SessionControlInteractor.reportSessionMetrics]
|
||||
*/
|
||||
@ -501,6 +509,19 @@ class DefaultSessionControlController(
|
||||
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() {
|
||||
activity.openToBrowserAndLoad(
|
||||
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.controller.RecentVisitsController
|
||||
import org.mozilla.fenix.home.recentvisits.interactor.RecentVisitsInteractor
|
||||
import org.mozilla.fenix.wallpapers.WallpaperState
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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 {
|
||||
@ -322,6 +332,10 @@ class SessionControlInteractor(
|
||||
controller.handleReadPrivacyNoticeClicked()
|
||||
}
|
||||
|
||||
override fun showWallpapersOnboardingDialog(state: WallpaperState): Boolean {
|
||||
return controller.handleShowWallpapersOnboardingDialog(state)
|
||||
}
|
||||
|
||||
override fun onToggleCollectionExpanded(collection: TabCollection, expand: Boolean) {
|
||||
controller.handleToggleCollectionExpanded(collection, expand)
|
||||
}
|
||||
|
@ -199,6 +199,9 @@ class SessionControlView(
|
||||
|
||||
val view: RecyclerView = containerView as RecyclerView
|
||||
|
||||
// We want to limit feature recommendations to one per HomePage visit.
|
||||
var featureRecommended = false
|
||||
|
||||
private val sessionControlAdapter = SessionControlAdapter(
|
||||
interactor,
|
||||
viewLifecycleOwner,
|
||||
@ -206,21 +209,33 @@ class SessionControlView(
|
||||
)
|
||||
|
||||
init {
|
||||
@Suppress("NestedBlockDepth")
|
||||
view.apply {
|
||||
adapter = sessionControlAdapter
|
||||
layoutManager = object : LinearLayoutManager(containerView.context) {
|
||||
override fun onLayoutCompleted(state: RecyclerView.State?) {
|
||||
super.onLayoutCompleted(state)
|
||||
|
||||
if (!context.settings().showHomeOnboardingDialog && (
|
||||
context.settings().showSyncCFR ||
|
||||
context.settings().shouldShowJumpBackInCFR
|
||||
)
|
||||
) {
|
||||
HomeCFRPresenter(
|
||||
context = context,
|
||||
recyclerView = view,
|
||||
).show()
|
||||
if (!featureRecommended && !context.settings().showHomeOnboardingDialog) {
|
||||
if (!context.settings().showHomeOnboardingDialog && (
|
||||
context.settings().showSyncCFR ||
|
||||
context.settings().shouldShowJumpBackInCFR
|
||||
)
|
||||
) {
|
||||
featureRecommended = HomeCFRPresenter(
|
||||
context = context,
|
||||
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
|
||||
|
@ -38,13 +38,17 @@ class HomeCFRPresenter(
|
||||
* Determine the CFR to be shown on the Home screen and show a CFR for the resultant view
|
||||
* if any.
|
||||
*/
|
||||
fun show() {
|
||||
when (val result = getCFRToShow()) {
|
||||
is Result.SyncedTab -> showSyncedTabCFR(view = result.view)
|
||||
is Result.JumpBackIn -> showJumpBackInCFR(view = result.view)
|
||||
else -> {
|
||||
// no-op
|
||||
fun show(): Boolean {
|
||||
return when (val result = getCFRToShow()) {
|
||||
is Result.SyncedTab -> {
|
||||
showSyncedTabCFR(view = result.view)
|
||||
true
|
||||
}
|
||||
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.graphics.Bitmap
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -91,8 +90,8 @@ fun WallpaperSettings(
|
||||
WallpaperThumbnails(
|
||||
wallpapers = wallpapers,
|
||||
defaultWallpaper = defaultWallpaper,
|
||||
loadWallpaperResource = loadWallpaperResource,
|
||||
selectedWallpaper = selectedWallpaper,
|
||||
loadWallpaperResource = loadWallpaperResource,
|
||||
onSelectWallpaper = { updatedWallpaper ->
|
||||
coroutineScope.launch {
|
||||
scaffoldState.snackbarHostState.showSnackbar(
|
||||
@ -147,19 +146,27 @@ private fun WallpaperSnackbar(
|
||||
* @param selectedWallpaper The currently selected wallpaper.
|
||||
* @param numColumns The number of columns that will occupy the grid.
|
||||
* @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
|
||||
@Suppress("LongParameterList")
|
||||
private fun WallpaperThumbnails(
|
||||
fun WallpaperThumbnails(
|
||||
wallpapers: List<Wallpaper>,
|
||||
defaultWallpaper: Wallpaper,
|
||||
loadWallpaperResource: suspend (Wallpaper) -> Bitmap?,
|
||||
selectedWallpaper: Wallpaper,
|
||||
numColumns: Int = 3,
|
||||
loadWallpaperResource: suspend (Wallpaper) -> Bitmap?,
|
||||
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
|
||||
for (rowIndex in 0 until numRows) {
|
||||
Row {
|
||||
@ -167,7 +174,9 @@ private fun WallpaperThumbnails(
|
||||
val itemIndex = rowIndex * numColumns + columnIndex
|
||||
if (itemIndex < wallpapers.size) {
|
||||
Box(
|
||||
modifier = Modifier.weight(1f, fill = true).padding(4.dp),
|
||||
modifier = Modifier
|
||||
.weight(1f, fill = true)
|
||||
.padding(4.dp),
|
||||
) {
|
||||
WallpaperThumbnailItem(
|
||||
wallpaper = wallpapers[itemIndex],
|
||||
|
@ -210,7 +210,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
||||
/**
|
||||
* 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),
|
||||
featureFlag = FeatureFlags.wallpaperOnboardingEnabled,
|
||||
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:popUpTo="@id/homeFragment" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_wallpaper_onboarding_dialog"
|
||||
app:destination="@id/wallpaperOnboardingDialogFragment"
|
||||
app:popUpTo="@id/homeFragment" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_global_search_dialog"
|
||||
app:destination="@id/searchDialogFragment"
|
||||
@ -189,6 +194,10 @@
|
||||
android:id="@+id/homeOnboardingDialogFragment"
|
||||
android:name="org.mozilla.fenix.onboarding.HomeOnboardingDialogFragment" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/wallpaperOnboardingDialogFragment"
|
||||
android:name="org.mozilla.fenix.onboarding.WallpaperOnboardingDialogFragment" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/searchDialogFragment"
|
||||
android:name="org.mozilla.fenix.search.SearchDialogFragment"
|
||||
|
@ -458,6 +458,12 @@
|
||||
<!-- 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. -->
|
||||
<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-->
|
||||
<!-- 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="CreateShortcutDialogStyle" 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">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
|
Loading…
Reference in New Issue
Block a user