Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Bug 1875465 - Part 3: Add tab strip ui for tablets
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulsainani committed Feb 16, 2024
1 parent 02e7419 commit 7556e1a
Show file tree
Hide file tree
Showing 6 changed files with 548 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
Expand All @@ -35,7 +37,9 @@ import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.GleanMetrics.ReaderMode
import org.mozilla.fenix.GleanMetrics.Shopping
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.tabstrip.TabsStrip
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.appstate.AppAction
Expand All @@ -46,11 +50,13 @@ 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.home.HomeFragment
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.settings.quicksettings.protections.cookiebanners.getCookieBannerUIMode
import org.mozilla.fenix.shopping.DefaultShoppingExperienceFeature
import org.mozilla.fenix.shopping.ReviewQualityCheckFeature
import org.mozilla.fenix.shortcut.PwaOnboardingObserver
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.theme.ThemeManager

/**
Expand Down Expand Up @@ -82,6 +88,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {

val context = requireContext()
val components = context.components
initTabStrip()

if (context.settings().isSwipeToolbarToSwitchTabsEnabled) {
binding.gestureLayout.addGestureListener(
Expand Down Expand Up @@ -213,6 +220,35 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
)
}

private fun initTabStrip() {
if (!resources.getBoolean(R.bool.tablet)) {
return
}

binding.tabStripView.isVisible = true
binding.tabStripView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
FirefoxTheme {
TabsStrip(
onAddTabClick = {
findNavController().navigate(
NavGraphDirections.actionGlobalHome(
focusOnAddressBar = true,
),
)
},
onLastTabClose = {
findNavController().navigate(
BrowserFragmentDirections.actionGlobalHome(),
)
},
)
}
}
}
}

private fun initTranslationsAction(context: Context) {
if (!context.settings().enableTranslations) {
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* 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.browser.tabstrip

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.theme.FirefoxTheme

private val cardShape = RoundedCornerShape(8.dp)
internal val defaultTabStripCardElevation = 0.dp
internal val selectedTabStripCardElevation = 1.dp

/**
* Card composable used in Tab Strip items.
*
* @param modifier The modifier to be applied to the card.
* @param backgroundColor The background color of the card.
* @param elevation The elevation of the card.
* @param content The content of the card.
*/
@Composable
fun TabStripCard(
modifier: Modifier = Modifier,
backgroundColor: Color = FirefoxTheme.colors.layer3,
elevation: Dp = defaultTabStripCardElevation,
content: @Composable () -> Unit,
) {
Card(
shape = cardShape,
backgroundColor = backgroundColor,
elevation = elevation,
modifier = modifier,
content = content,
)
}

@LightDarkPreview
@Composable
private fun TabStripCardPreview() {
FirefoxTheme {
TabStripCard {
Box(
modifier = Modifier
.height(56.dp)
.width(200.dp)
.padding(8.dp),
contentAlignment = Alignment.Center,
) {
Text(
text = "Tab Strip Card",
color = FirefoxTheme.colors.textPrimary,
style = FirefoxTheme.typography.subtitle1,
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* 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.browser.tabstrip

import android.graphics.Bitmap
import mozilla.components.browser.state.state.BrowserState

/**
* The ui state of the tabs strip.
*
* @property tabs The list of [TabUIState].
*/
data class TabsStripState(
val tabs: List<TabUIState>,
) {
companion object {
val initial = TabsStripState(tabs = emptyList())
}
}

/**
* The ui state of a tab.
*
* @property id The id of the tab.
* @property title The title of the tab.
* @property icon The icon of the tab.
* @property isPrivate Whether or not the tab is private.
* @property isSelected Whether or not the tab is selected.
*/
data class TabUIState(
val id: String,
val title: String,
val icon: Bitmap? = null,
val isPrivate: Boolean,
val isSelected: Boolean,
)

/**
* Converts [BrowserState] to [TabsStripState] that contains the information needed to render the
* tabs strip.
*/
internal fun BrowserState.toTabsStripState(
onHome: Boolean,
isPrivateMode: Boolean,
): TabsStripState {
return TabsStripState(
tabs = tabs
.filter {
if (isPrivateMode) {
it.content.private
} else {
!it.content.private
}
}
.map {
TabUIState(
id = it.id,
title = it.content.title,
icon = it.content.icon,
isPrivate = it.content.private,
isSelected = !onHome && it.id == selectedTabId,
)
},
)
}
Loading

0 comments on commit 7556e1a

Please sign in to comment.