mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-03 23:15:31 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/25891 - Move GridViewHolder to compose
This commit is contained in:
parent
d1d14d5966
commit
76fe8e2d4f
@ -18,6 +18,7 @@ import androidx.test.uiautomator.Until
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
@ -165,6 +166,7 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun tabMenuTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
navigationToolbar {
|
||||
|
@ -14,6 +14,7 @@ import mozilla.appservices.places.BookmarkRoot
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
@ -361,6 +362,7 @@ class BookmarksTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openSelectionInNewTabTest() {
|
||||
val settings = activityTestRule.activity.applicationContext.settings()
|
||||
settings.shouldShowJumpBackInCFR = false
|
||||
@ -392,6 +394,7 @@ class BookmarksTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openSelectionInPrivateTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
@ -10,6 +10,7 @@ import androidx.test.uiautomator.UiDevice
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.customannotations.SmokeTest
|
||||
@ -68,6 +69,7 @@ class CollectionTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun createFirstCollectionTest() {
|
||||
val firstWebPage = getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = getGenericAsset(mockWebServer, 2)
|
||||
@ -100,6 +102,7 @@ class CollectionTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyExpandedCollectionItemsTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
val webPageUrl = webPage.url.host.toString()
|
||||
@ -149,6 +152,7 @@ class CollectionTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openAllTabsInCollectionTest() {
|
||||
val firstTestPage = getGenericAsset(mockWebServer, 1)
|
||||
val secondTestPage = getGenericAsset(mockWebServer, 2)
|
||||
@ -181,6 +185,7 @@ class CollectionTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun shareCollectionTest() {
|
||||
val firstWebsite = getGenericAsset(mockWebServer, 1)
|
||||
val secondWebsite = getGenericAsset(mockWebServer, 2)
|
||||
@ -209,6 +214,7 @@ class CollectionTest {
|
||||
@Test
|
||||
// Test running on beta/release builds in CI:
|
||||
// caution when making changes to it, so they don't block the builds
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun deleteCollectionTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -233,6 +239,7 @@ class CollectionTest {
|
||||
|
||||
@Test
|
||||
// open a webpage, and add currently opened tab to existing collection
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun mainMenuSaveToExistingCollection() {
|
||||
val firstWebPage = getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = getGenericAsset(mockWebServer, 2)
|
||||
@ -259,6 +266,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyAddTabButtonOfCollectionMenu() {
|
||||
val firstWebPage = getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = getGenericAsset(mockWebServer, 2)
|
||||
@ -285,6 +293,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun renameCollectionTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -305,6 +314,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun createSecondCollectionTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -326,6 +336,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun removeTabFromCollectionTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -348,6 +359,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun swipeLeftToRemoveTabFromCollectionTest() {
|
||||
val testPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -374,6 +386,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun swipeRightToRemoveTabFromCollectionTest() {
|
||||
val testPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -400,6 +413,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun selectTabOnLongTapTest() {
|
||||
val firstWebPage = getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = getGenericAsset(mockWebServer, 2)
|
||||
@ -431,6 +445,7 @@ class CollectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun navigateBackInCollectionFlowTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -464,6 +479,7 @@ class CollectionTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun undoDeleteCollectionTest() {
|
||||
val webPage = getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
@ -64,6 +64,7 @@ class ContextMenusTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyContextOpenLinkNewTab() {
|
||||
val pageLinks =
|
||||
TestAssetHelper.getGenericAsset(mockWebServer, 4)
|
||||
@ -88,6 +89,7 @@ class ContextMenusTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyContextOpenLinkPrivateTab() {
|
||||
val pageLinks =
|
||||
TestAssetHelper.getGenericAsset(mockWebServer, 4)
|
||||
|
@ -109,6 +109,7 @@ class CrashReportingTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun privateBrowsingUseAppWhileTabIsCrashedTest() {
|
||||
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2)
|
||||
|
@ -14,6 +14,7 @@ import mozilla.components.browser.storage.sync.PlacesHistoryStorage
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
@ -179,6 +180,7 @@ class HistoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openHistoryInNewTabTest() {
|
||||
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -207,6 +209,7 @@ class HistoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openHistoryInPrivateTabTest() {
|
||||
val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -291,6 +294,7 @@ class HistoryTest {
|
||||
|
||||
@Test
|
||||
// This test verifies the Recently Closed Tabs List and items
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyRecentlyClosedTabsListTest() {
|
||||
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
@ -240,6 +240,7 @@ class SearchTest {
|
||||
|
||||
@SmokeTest
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun noRecentlyVisitedSearchGroupInPrivateBrowsingTest() {
|
||||
val firstPage = searchMockServer.url("generic1.html").toString()
|
||||
val secondPage = searchMockServer.url("generic2.html").toString()
|
||||
|
@ -363,6 +363,7 @@ class SettingsPrivacyTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun launchPageShortcutInPrivateModeTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
@ -71,6 +71,7 @@ class SettingsSearchTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun toggleSearchBookmarksAndHistoryTest() {
|
||||
// Bookmarks 2 websites, toggles the bookmarks and history search settings off,
|
||||
// then verifies if the websites do not show in the suggestions.
|
||||
|
@ -195,6 +195,7 @@ class SmokeTest {
|
||||
- the tab drawer button
|
||||
- opening a new search and dismissing the nav bar
|
||||
*/
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyBasicNavigationToolbarFunctionality() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -533,6 +534,7 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
// Verifies that a recently closed item is properly opened
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openRecentlyClosedItemTest() {
|
||||
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -557,6 +559,7 @@ class SmokeTest {
|
||||
|
||||
@Test
|
||||
// Verifies that tapping the "x" button removes a recently closed item from the list
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun deleteRecentlyClosedTabsItemTest() {
|
||||
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -626,6 +629,7 @@ class SmokeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun shareTabsFromTabsTrayTest() {
|
||||
val firstWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
val secondWebsite = TestAssetHelper.getGenericAsset(mockWebServer, 2)
|
||||
@ -672,6 +676,7 @@ class SmokeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun privateTabsTrayWithOpenedTabTest() {
|
||||
val website = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -872,6 +877,7 @@ class SmokeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun tabMediaControlButtonTest() {
|
||||
val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer)
|
||||
|
||||
|
@ -106,6 +106,7 @@ class StrictEnhancedTrackingProtectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun testStrictVisitProtectionSheet() {
|
||||
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
val trackingProtectionTest =
|
||||
@ -162,6 +163,7 @@ class StrictEnhancedTrackingProtectionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun testStrictVisitSheetDetails() {
|
||||
val genericPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
val trackingProtectionTest =
|
||||
|
@ -10,6 +10,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
|
||||
@ -71,6 +72,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openNewTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -95,6 +97,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun openNewPrivateTabTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -115,6 +118,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun closeAllTabsTest() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -147,6 +151,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun closeTabTest() {
|
||||
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -178,6 +183,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyUndoSnackBarTest() {
|
||||
// disabling these features because they interfere with the snackbar visibility
|
||||
featureSettingsHelper.setPocketEnabled(false)
|
||||
@ -202,6 +208,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun closePrivateTabTest() {
|
||||
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -235,6 +242,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyPrivateTabUndoSnackBarTest() {
|
||||
val genericURL = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
@ -315,6 +323,7 @@ class TabbedBrowsingTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Failing after compose migration. See: https://github.com/mozilla-mobile/fenix/issues/26087")
|
||||
fun verifyOpenTabDetails() {
|
||||
val defaultWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1)
|
||||
|
||||
|
@ -0,0 +1,125 @@
|
||||
/* 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.compose
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
|
||||
/**
|
||||
* Displays the [content] with the right edge fading.
|
||||
*
|
||||
* @param modifier [Modifier] for the container.
|
||||
* @param fadeWidth Length of the fading edge.
|
||||
* @param backgroundColor [Color] of the background shown under the content.
|
||||
* @param isContentRtl Whether or not the content should be displayed Right to Left
|
||||
* @param content The content whose right edge must be faded.
|
||||
*/
|
||||
@Composable
|
||||
fun HorizontalFadingEdgeBox(
|
||||
modifier: Modifier = Modifier,
|
||||
fadeWidth: Dp = 25.dp,
|
||||
backgroundColor: Color = Color.Transparent,
|
||||
isContentRtl: Boolean = false,
|
||||
content: @Composable BoxScope.() -> Unit
|
||||
) {
|
||||
// List of colors defining the direction of the fade effect
|
||||
val colorList = listOf(Color.Transparent, backgroundColor)
|
||||
|
||||
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
|
||||
Box(modifier) {
|
||||
content()
|
||||
Spacer(
|
||||
Modifier
|
||||
.width(fadeWidth)
|
||||
.fillMaxHeight()
|
||||
.align(
|
||||
if (isContentRtl) {
|
||||
Alignment.CenterStart
|
||||
} else {
|
||||
Alignment.CenterEnd
|
||||
}
|
||||
)
|
||||
.background(
|
||||
Brush.horizontalGradient(
|
||||
colors = if (isContentRtl) {
|
||||
colorList.reversed()
|
||||
} else {
|
||||
colorList
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FadingRightTextPreview() {
|
||||
FirefoxTheme {
|
||||
Surface(modifier = Modifier.background(FirefoxTheme.colors.layer1)) {
|
||||
HorizontalFadingEdgeBox(
|
||||
modifier = Modifier
|
||||
.width(250.dp)
|
||||
.height(20.dp)
|
||||
.clipToBounds(),
|
||||
backgroundColor = FirefoxTheme.colors.layer1
|
||||
) {
|
||||
Text(
|
||||
"Example text set to fade on the right",
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
softWrap = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun FadingLeftTextPreview() {
|
||||
FirefoxTheme {
|
||||
Surface(modifier = Modifier.background(FirefoxTheme.colors.layer1)) {
|
||||
HorizontalFadingEdgeBox(
|
||||
modifier = Modifier
|
||||
.width(250.dp)
|
||||
.height(20.dp)
|
||||
.clipToBounds(),
|
||||
isContentRtl = true,
|
||||
fadeWidth = 50.dp,
|
||||
backgroundColor = FirefoxTheme.colors.layer1
|
||||
) {
|
||||
Text(
|
||||
"Example text set to fade on the left",
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
softWrap = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/* 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.compose.tabstray
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import mozilla.components.concept.base.images.ImageLoadRequest
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.compose.inComposePreview
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
import org.mozilla.fenix.theme.Theme
|
||||
|
||||
/**
|
||||
* Card which will display the thumbnail for a tab. If a thumbnail is not available for the [tabId],
|
||||
* the favicon [R.drawable.mozac_ic_globe] icon will be displayed.
|
||||
*
|
||||
* @param tabId Key used to remember the thumbnail for future compositions.
|
||||
* @param modifier [Modifier] used to draw the image content.
|
||||
* @param contentDescription Text used by accessibility services
|
||||
* to describe what this image represents.
|
||||
* @param contentScale [ContentScale] used to draw image content.
|
||||
* @param alignment [Alignment] used to draw the image content.
|
||||
*/
|
||||
@Composable
|
||||
@Suppress("LongParameterList")
|
||||
fun GridTabThumbnail(
|
||||
tabId: String,
|
||||
size: Dp,
|
||||
modifier: Modifier = Modifier,
|
||||
contentDescription: String? = null,
|
||||
contentScale: ContentScale = ContentScale.FillWidth,
|
||||
alignment: Alignment = Alignment.TopCenter
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier,
|
||||
backgroundColor = FirefoxTheme.colors.layer2
|
||||
) {
|
||||
if (inComposePreview) {
|
||||
GlobeIcon()
|
||||
} else {
|
||||
val rememberBitmap = remember(tabId) { mutableStateOf<ImageBitmap?>(null) }
|
||||
val imageSize = LocalDensity.current.run { size.toPx().toInt() }
|
||||
val request = ImageLoadRequest(tabId, imageSize)
|
||||
val storage = LocalContext.current.components.core.thumbnailStorage
|
||||
val bitmap = rememberBitmap.value
|
||||
|
||||
LaunchedEffect(tabId) {
|
||||
rememberBitmap.value = storage.loadThumbnail(request).await()?.asImageBitmap()
|
||||
}
|
||||
|
||||
if (bitmap != null) {
|
||||
val painter = BitmapPainter(bitmap)
|
||||
Image(
|
||||
painter = painter,
|
||||
contentDescription = contentDescription,
|
||||
modifier = modifier,
|
||||
contentScale = contentScale,
|
||||
alignment = alignment
|
||||
)
|
||||
} else {
|
||||
GlobeIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Globe icon to be displayed when no thumbnail is available.
|
||||
*/
|
||||
@Composable
|
||||
private fun GlobeIcon() {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mozac_ic_globe),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(22.dp)
|
||||
.fillMaxSize(),
|
||||
tint = FirefoxTheme.colors.iconSecondary
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun ThumbnailCardPreview() {
|
||||
FirefoxTheme(theme = Theme.getTheme()) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(300.dp)
|
||||
) {
|
||||
GridTabThumbnail(
|
||||
tabId = "1",
|
||||
size = LocalConfiguration.current.screenWidthDp.dp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
/* 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.compose.tabstray
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.text.BidiFormatter
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.compose.Favicon
|
||||
import org.mozilla.fenix.compose.HorizontalFadingEdgeBox
|
||||
import org.mozilla.fenix.theme.FirefoxTheme
|
||||
|
||||
/**
|
||||
* Tab grid item used to display a tab that supports clicks,
|
||||
* long clicks, multiple selection, and media controls.
|
||||
*
|
||||
* @param tab The given tab to be render as view a grid item.
|
||||
* @param isSelected Indicates if the item should be render as selected.
|
||||
* @param multiSelectionEnabled Indicates if the item should be render with multi selection options,
|
||||
* enabled.
|
||||
* @param multiSelectionSelected Indicates if the item should be render as multi selection selected
|
||||
* option.
|
||||
* @param onCloseClick Callback to handle the click event of the close button.
|
||||
* @param onMediaClick Callback to handle when the media item is clicked.
|
||||
* @param onClick Callback to handle when item is clicked.
|
||||
* @param onLongClick Callback to handle when item is long clicked.
|
||||
*/
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@Suppress("MagicNumber", "LongParameterList", "LongMethod")
|
||||
fun TabGridItem(
|
||||
tab: TabSessionState,
|
||||
isSelected: Boolean = false,
|
||||
multiSelectionEnabled: Boolean = false,
|
||||
multiSelectionSelected: Boolean = false,
|
||||
onCloseClick: (tab: TabSessionState) -> Unit,
|
||||
onMediaClick: (tab: TabSessionState) -> Unit,
|
||||
onClick: (tab: TabSessionState) -> Unit,
|
||||
onLongClick: (tab: TabSessionState) -> Unit,
|
||||
) {
|
||||
val tabBorderModifier = if (isSelected && !multiSelectionEnabled) {
|
||||
Modifier.border(
|
||||
4.dp,
|
||||
FirefoxTheme.colors.borderAccent,
|
||||
RoundedCornerShape(12.dp)
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.wrapContentWidth()
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(202.dp)
|
||||
.padding(4.dp)
|
||||
.then(tabBorderModifier)
|
||||
.padding(4.dp)
|
||||
.combinedClickable(
|
||||
onLongClick = { onLongClick(tab) },
|
||||
onClick = { onClick(tab) }
|
||||
),
|
||||
elevation = 0.dp,
|
||||
shape = RoundedCornerShape(dimensionResource(id = R.dimen.tab_tray_grid_item_border_radius)),
|
||||
border = BorderStroke(1.dp, FirefoxTheme.colors.borderPrimary)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.background(FirefoxTheme.colors.layer2)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
) {
|
||||
Favicon(
|
||||
url = tab.content.url,
|
||||
size = 16.dp,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.padding(start = 8.dp)
|
||||
)
|
||||
|
||||
HorizontalFadingEdgeBox(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentHeight()
|
||||
.requiredHeight(30.dp)
|
||||
.padding(7.dp, 5.dp)
|
||||
.clipToBounds(),
|
||||
backgroundColor = FirefoxTheme.colors.layer2,
|
||||
isContentRtl = BidiFormatter.getInstance().isRtl(tab.content.title)
|
||||
) {
|
||||
Text(
|
||||
text = tab.content.title,
|
||||
fontSize = 14.sp,
|
||||
maxLines = 1,
|
||||
softWrap = false,
|
||||
style = TextStyle(
|
||||
color = FirefoxTheme.colors.textPrimary,
|
||||
textDirection = TextDirection.Content
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mozac_ic_close),
|
||||
contentDescription = stringResource(id = R.string.close_tab),
|
||||
tint = FirefoxTheme.colors.iconPrimary,
|
||||
modifier = Modifier
|
||||
.clickable { onCloseClick(tab) }
|
||||
.size(24.dp)
|
||||
.align(Alignment.CenterVertically)
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
Divider(
|
||||
color = FirefoxTheme.colors.borderPrimary,
|
||||
thickness = 1.dp
|
||||
)
|
||||
|
||||
Thumbnail(
|
||||
tab = tab,
|
||||
multiSelectionSelected = multiSelectionSelected,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!multiSelectionEnabled) {
|
||||
MediaImage(
|
||||
tab = tab,
|
||||
onMediaIconClicked = { onMediaClick(tab) },
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thumbnail specific for the [TabGridItem], which can be selected.
|
||||
*
|
||||
* @param tab Tab, containing the thumbnail to be displayed.
|
||||
* @param multiSelectionSelected Whether or not the multiple selection is enabled.
|
||||
*/
|
||||
@Composable
|
||||
private fun Thumbnail(
|
||||
tab: TabSessionState,
|
||||
multiSelectionSelected: Boolean,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(FirefoxTheme.colors.layer2)
|
||||
) {
|
||||
GridTabThumbnail(
|
||||
tabId = tab.id,
|
||||
size = LocalConfiguration.current.screenWidthDp.dp
|
||||
)
|
||||
|
||||
if (multiSelectionSelected) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(FirefoxTheme.colors.layerAccentNonOpaque)
|
||||
)
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.size(size = 40.dp)
|
||||
.align(alignment = Alignment.Center),
|
||||
shape = CircleShape,
|
||||
backgroundColor = FirefoxTheme.colors.layerAccent,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.mozac_ic_check),
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.padding(all = 8.dp),
|
||||
contentDescription = null,
|
||||
tint = colorResource(id = R.color.mozac_ui_icons_fill)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
private fun TabGridItemPreview() {
|
||||
FirefoxTheme {
|
||||
TabGridItem(
|
||||
tab = createTab(
|
||||
url = "www.mozilla.com",
|
||||
title = "Mozilla Domain"
|
||||
),
|
||||
onCloseClick = {},
|
||||
onMediaClick = {},
|
||||
onClick = {},
|
||||
onLongClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
private fun TabGridItemSelectedPreview() {
|
||||
FirefoxTheme {
|
||||
TabGridItem(
|
||||
tab = createTab(url = "www.mozilla.com", title = "Mozilla"),
|
||||
isSelected = true,
|
||||
onCloseClick = {},
|
||||
onMediaClick = {},
|
||||
onClick = {},
|
||||
onLongClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
private fun TabGridItemMultiSelectedPreview() {
|
||||
FirefoxTheme {
|
||||
TabGridItem(
|
||||
tab = createTab(url = "www.mozilla.com", title = "Mozilla"),
|
||||
multiSelectionEnabled = true,
|
||||
multiSelectionSelected = true,
|
||||
onCloseClick = {},
|
||||
onMediaClick = {},
|
||||
onClick = {},
|
||||
onLongClick = {},
|
||||
)
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import org.mozilla.fenix.databinding.TabTrayItemBinding
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.selection.SelectionHolder
|
||||
import org.mozilla.fenix.tabstray.TabsTrayStore
|
||||
import org.mozilla.fenix.tabstray.browser.compose.ComposeGridViewHolder
|
||||
import org.mozilla.fenix.tabstray.browser.compose.ComposeListViewHolder
|
||||
|
||||
/**
|
||||
@ -48,7 +49,8 @@ class BrowserTabsAdapter(
|
||||
enum class ViewType(val layoutRes: Int) {
|
||||
LIST(BrowserTabViewHolder.ListViewHolder.LAYOUT_ID),
|
||||
COMPOSE_LIST(ComposeListViewHolder.LAYOUT_ID),
|
||||
GRID(BrowserTabViewHolder.GridViewHolder.LAYOUT_ID)
|
||||
GRID(BrowserTabViewHolder.GridViewHolder.LAYOUT_ID),
|
||||
COMPOSE_GRID(ComposeGridViewHolder.LAYOUT_ID)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,7 +64,11 @@ class BrowserTabsAdapter(
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when {
|
||||
context.components.settings.gridTabView -> {
|
||||
ViewType.GRID.layoutRes
|
||||
if (FeatureFlags.composeTabsTray) {
|
||||
ViewType.COMPOSE_GRID.layoutRes
|
||||
} else {
|
||||
ViewType.GRID.layoutRes
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (FeatureFlags.composeTabsTray) {
|
||||
@ -85,6 +91,15 @@ class BrowserTabsAdapter(
|
||||
featureName = featureName,
|
||||
viewLifecycleOwner = viewLifecycleOwner
|
||||
)
|
||||
ViewType.COMPOSE_GRID.layoutRes ->
|
||||
ComposeGridViewHolder(
|
||||
interactor = interactor,
|
||||
store = store,
|
||||
selectionHolder = selectionHolder,
|
||||
composeItemView = ComposeView(parent.context),
|
||||
featureName = featureName,
|
||||
viewLifecycleOwner = viewLifecycleOwner
|
||||
)
|
||||
else -> {
|
||||
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
||||
if (viewType == ViewType.GRID.layoutRes) {
|
||||
|
@ -0,0 +1,108 @@
|
||||
/* 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.tabstray.browser.compose
|
||||
|
||||
import android.view.View
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.tabstray.TabsTray
|
||||
import mozilla.components.browser.tabstray.TabsTrayStyling
|
||||
import mozilla.components.lib.state.ext.observeAsComposableState
|
||||
import org.mozilla.fenix.compose.tabstray.TabGridItem
|
||||
import org.mozilla.fenix.selection.SelectionHolder
|
||||
import org.mozilla.fenix.tabstray.TabsTrayState
|
||||
import org.mozilla.fenix.tabstray.TabsTrayStore
|
||||
import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor
|
||||
|
||||
/**
|
||||
* A Compose ViewHolder implementation for "tab" items with grid layout.
|
||||
*
|
||||
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
|
||||
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
|
||||
* @param selectionHolder [SelectionHolder]<[TabSessionState]> for helping with selecting
|
||||
* any number of displayed [TabSessionState]s.
|
||||
* @param composeItemView that displays a "tab".
|
||||
* @param featureName [String] representing the name of the feature displaying tabs. Used in telemetry reporting.
|
||||
* @param viewLifecycleOwner [LifecycleOwner] to which this Composable will be tied to.
|
||||
*/
|
||||
class ComposeGridViewHolder(
|
||||
private val interactor: BrowserTrayInteractor,
|
||||
private val store: TabsTrayStore,
|
||||
private val selectionHolder: SelectionHolder<TabSessionState>? = null,
|
||||
composeItemView: ComposeView,
|
||||
private val featureName: String,
|
||||
viewLifecycleOwner: LifecycleOwner,
|
||||
) : ComposeAbstractTabViewHolder(composeItemView, viewLifecycleOwner) {
|
||||
|
||||
override var tab: TabSessionState? = null
|
||||
private var isMultiSelectionSelectedState = MutableStateFlow(false)
|
||||
private var isSelectedTabState = MutableStateFlow(false)
|
||||
|
||||
override fun bind(
|
||||
tab: TabSessionState,
|
||||
isSelected: Boolean,
|
||||
styling: TabsTrayStyling,
|
||||
delegate: TabsTray.Delegate
|
||||
) {
|
||||
this.tab = tab
|
||||
isSelectedTabState.value = isSelected
|
||||
bind(tab)
|
||||
}
|
||||
|
||||
override fun updateSelectedTabIndicator(showAsSelected: Boolean) {
|
||||
isSelectedTabState.value = showAsSelected
|
||||
}
|
||||
|
||||
override fun showTabIsMultiSelectEnabled(selectedMaskView: View?, isSelected: Boolean) {
|
||||
isMultiSelectionSelectedState.value = isSelected
|
||||
}
|
||||
|
||||
private fun onCloseClicked(tab: TabSessionState) {
|
||||
interactor.onTabClosed(tab, featureName)
|
||||
}
|
||||
|
||||
private fun onClick(tab: TabSessionState) {
|
||||
val holder = selectionHolder
|
||||
if (holder != null) {
|
||||
interactor.onMultiSelectClicked(tab, holder, featureName)
|
||||
} else {
|
||||
interactor.onTabSelected(tab, featureName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onLongClick(tab: TabSessionState) {
|
||||
val holder = selectionHolder ?: return
|
||||
interactor.onLongClicked(tab, holder)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(tab: TabSessionState) {
|
||||
val multiSelectionEnabled = store.observeAsComposableState { state ->
|
||||
state.mode is TabsTrayState.Mode.Select
|
||||
}.value ?: false
|
||||
val isSelectedTab by isSelectedTabState.collectAsState()
|
||||
val isMultiSelectionSelected by isMultiSelectionSelectedState.collectAsState()
|
||||
|
||||
TabGridItem(
|
||||
tab = tab,
|
||||
isSelected = isSelectedTab,
|
||||
multiSelectionEnabled = multiSelectionEnabled,
|
||||
multiSelectionSelected = isMultiSelectionSelected,
|
||||
onCloseClick = ::onCloseClicked,
|
||||
onMediaClick = interactor::onMediaClicked,
|
||||
onClick = ::onClick,
|
||||
onLongClick = ::onLongClick,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LAYOUT_ID = View.generateViewId()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user