Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose for tv beta migration #73

Merged
merged 8 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ dependencies {
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)

implementation(libs.tv.foundation)
// implementation(libs.tv.foundation)
implementation(libs.tv.material)

implementation(libs.navigation.compose)
Expand Down
50 changes: 49 additions & 1 deletion app/src/main/kotlin/com/muedsa/compose/tv/Modifier.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
package com.muedsa.compose.tv

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.relocation.BringIntoViewResponder
import androidx.compose.foundation.relocation.bringIntoViewResponder
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.toSize

inline fun Modifier.conditional(
condition: Boolean,
Expand Down Expand Up @@ -50,4 +61,41 @@ fun Modifier.focusOnMount(itemKey: String): Modifier {
isInitialFocusTransferred.value = true
}
}
}
}

@Suppress("IllegalExperimentalApiUsage") // TODO (b/233188423): Address before moving to beta
@OptIn(ExperimentalFoundationApi::class)
// ToDo: Migrate to Modifier.Node and stop using composed function.
internal fun Modifier.bringIntoViewIfChildrenAreFocused(
paddingValues: PaddingValues = PaddingValues()
): Modifier = composed(
inspectorInfo = debugInspectorInfo { name = "bringIntoViewIfChildrenAreFocused" },
factory = {
val pxOffset = with(LocalDensity.current) {
val y = (paddingValues.calculateBottomPadding() - paddingValues.calculateTopPadding())
.toPx()
Offset.Zero.copy(y = y)
}
var myRect: Rect = Rect.Zero
val responder = object : BringIntoViewResponder {
// return the current rectangle and ignoring the child rectangle received.
@ExperimentalFoundationApi
override fun calculateRectForParent(localRect: Rect): Rect {
return myRect
}

// The container is not expected to be scrollable. Hence the child is
// already in view with respect to the container.
@ExperimentalFoundationApi
override suspend fun bringChildIntoView(localRect: () -> Rect?) {
}
}

this
.onSizeChanged {
val size = it.toSize()
myRect = Rect(pxOffset, size)
}
.bringIntoViewResponder(responder)
}
)
14 changes: 2 additions & 12 deletions app/src/main/kotlin/com/muedsa/compose/tv/theme/Color.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ package com.muedsa.compose.tv.theme

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.tv.foundation.lazy.list.TvLazyColumn
import androidx.tv.material3.ColorScheme
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import androidx.tv.material3.darkColorScheme


@OptIn(ExperimentalTvMaterial3Api::class)
val TvDarkColorScheme = darkColorScheme(
// background = background,
// onBackground = onBackground,
Expand All @@ -25,38 +23,30 @@ val TvDarkColorScheme = darkColorScheme(
// onSurfaceVariant = onSurfaceVariant
)

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.surfaceContainerLowest: Color
get() = Color(red = 14, green = 14, blue = 14) // N-4 0E0E0E

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.surfaceContainerLowe: Color
get() = Color(red = 27, green = 27, blue = 27) // N-10 1B1B1B

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.surfaceContainer: Color
get() = Color(red = 30, green = 31, blue = 32) // N-12 1E1F20

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.surfaceContainerHigh: Color
get() = Color(red = 40, green = 42, blue = 44) // N-17 282A2C

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.surfaceContainerHighest: Color
get() = Color(red = 51, green = 53, blue = 55) // N-22 333537

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.outline: Color
get() = Color(red = 147, green = 143, blue = 153) // PaletteTokens.NeutralVariant60

@OptIn(ExperimentalTvMaterial3Api::class)
val ColorScheme.outlineVariant: Color
get() = Color(red = 73, green = 69, blue = 79) // PaletteTokens.NeutralVariant30

@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun TvColorPreview(modifier: Modifier = Modifier) {
TvLazyColumn(modifier) {
LazyColumn(modifier) {
item {
Text(
modifier = Modifier
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/kotlin/com/muedsa/compose/tv/theme/Theme.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.muedsa.compose.tv.theme

import androidx.compose.runtime.Composable
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme


@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun TvTheme(
content: @Composable () -> Unit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.muedsa.compose.tv.widget

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
Expand All @@ -10,13 +9,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import com.muedsa.compose.tv.model.ContentModel
import com.muedsa.compose.tv.theme.TvTheme

@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun ContentBlock(
modifier: Modifier = Modifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.unit.dp
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme
import kotlinx.coroutines.delay
import kotlin.time.Duration.Companion.seconds

@OptIn(ExperimentalTvMaterial3Api::class)

@Composable
fun ErrorMessageBox(
state: ErrorMessageBoxController = remember { ErrorMessageBoxController() },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Icon
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.OutlinedIconButton
Expand All @@ -40,7 +39,7 @@ fun EmptyDataScreen(model: Boolean = false) {
FillTextScreen(context = "Empty(っ °Д °;)っ", model = model)
}

@OptIn(ExperimentalTvMaterial3Api::class)

@Composable
fun ErrorScreen(onRefresh: (() -> Unit)? = null) {
Column(
Expand All @@ -60,7 +59,7 @@ fun ErrorScreen(onRefresh: (() -> Unit)? = null) {
}
}

@OptIn(ExperimentalTvMaterial3Api::class)

@Composable
fun FillTextScreen(context: String, model: Boolean = false) {
var modifier = Modifier.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.tv.material3.Card
import androidx.tv.material3.ExperimentalTvMaterial3Api
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.muedsa.compose.tv.model.ContentModel
Expand Down Expand Up @@ -92,7 +91,7 @@ enum class CardType {
WIDE_STANDARD
}

@OptIn(ExperimentalTvMaterial3Api::class)

@Composable
fun ImageCard(
modifier: Modifier = Modifier,
Expand Down
19 changes: 9 additions & 10 deletions app/src/main/kotlin/com/muedsa/compose/tv/widget/ImageCardsRow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ 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.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
Expand All @@ -18,10 +21,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.tv.foundation.lazy.list.TvLazyListState
import androidx.tv.foundation.lazy.list.TvLazyRow
import androidx.tv.foundation.lazy.list.rememberTvLazyListState
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import com.muedsa.compose.tv.model.ContentModel
Expand All @@ -34,11 +33,11 @@ import com.muedsa.compose.tv.theme.VerticalPosterSize
import com.muedsa.uitl.anyMatchWithIndex


@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun <T> ImageCardsRow(
modifier: Modifier = Modifier,
state: TvLazyListState = rememberTvLazyListState(),
state: LazyListState = rememberLazyListState(),
title: String,
modelList: List<T> = listOf(),
imageFn: (index: Int, item: T) -> String,
Expand All @@ -60,7 +59,7 @@ fun <T> ImageCardsRow(
maxLines = 1
)
Spacer(modifier = Modifier.height(ImageCardRowCardPadding))
TvLazyRow(
LazyRow(
modifier = Modifier
.focusRequester(rowFR)
.focusRestorer {
Expand Down Expand Up @@ -99,11 +98,11 @@ fun <T> ImageCardsRow(
}
}

@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun <T> StandardImageCardsRow(
modifier: Modifier = Modifier,
state: TvLazyListState = rememberTvLazyListState(),
state: LazyListState = rememberLazyListState(),
title: String,
modelList: List<T> = listOf(),
imageFn: (index: Int, item: T) -> String,
Expand All @@ -130,7 +129,7 @@ fun <T> StandardImageCardsRow(
maxLines = 1
)
Spacer(modifier = Modifier.height(10.dp))
TvLazyRow(
LazyRow(
modifier = Modifier
.focusRequester(rowFR)
.focusRestorer {
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/kotlin/com/muedsa/compose/tv/widget/ImmersiveList.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.muedsa.compose.tv.widget

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.muedsa.compose.tv.bringIntoViewIfChildrenAreFocused

/**
* A replacement for ImmersiveList.
*/
@Composable
fun ImmersiveList(
modifier: Modifier = Modifier,
background: @Composable BoxScope.() -> Unit,
list: @Composable BoxScope.() -> Unit
) {
Box(modifier.bringIntoViewIfChildrenAreFocused()) {
background()
Box(
contentAlignment = Alignment.BottomEnd,
content = list
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.tv.material3.Border
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Icon
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.NonInteractiveSurfaceDefaults
import androidx.tv.material3.OutlinedIconButtonDefaults
import androidx.tv.material3.Surface
import androidx.tv.material3.SurfaceDefaults
import com.muedsa.compose.tv.theme.TvTheme

@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun OutlinedIconBox(
modifier: Modifier = Modifier,
Expand All @@ -48,7 +46,7 @@ fun OutlinedIconBox(
),
shape = CircleShape
),
colors = NonInteractiveSurfaceDefaults.colors(
colors = SurfaceDefaults.colors(
containerColor = if (inverse) MaterialTheme.colorScheme.onSurface else Color.Transparent,
contentColor = if (inverse) MaterialTheme.colorScheme.inverseOnSurface else MaterialTheme.colorScheme.onSurface,
)
Expand All @@ -61,7 +59,6 @@ fun OutlinedIconBox(
}
}

@OptIn(ExperimentalTvMaterial3Api::class)
@Preview
@Composable
fun OutlinedIconBoxPreview() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.tv.material3.DrawerState
import androidx.tv.material3.DrawerValue
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.ModalNavigationDrawer
import androidx.tv.material3.NonInteractiveSurfaceDefaults
import androidx.tv.material3.Surface
import androidx.tv.material3.SurfaceDefaults
import com.muedsa.compose.tv.theme.surfaceContainer

@OptIn(ExperimentalTvMaterial3Api::class)

@Composable
fun RightSideDrawer(
controller: RightSideDrawerController = RightSideDrawerController(),
Expand All @@ -48,7 +46,7 @@ fun RightSideDrawer(
Surface(
modifier = Modifier
.fillMaxHeight(),
colors = NonInteractiveSurfaceDefaults.colors(
colors = SurfaceDefaults.colors(
containerColor = MaterialTheme.colorScheme.surfaceContainer,
contentColor = MaterialTheme.colorScheme.onSurface
)
Expand Down Expand Up @@ -79,7 +77,6 @@ fun RightSideDrawer(
}


@OptIn(ExperimentalTvMaterial3Api::class)
open class RightSideDrawerController {
private val contentState: MutableState<@Composable () -> Unit> = mutableStateOf({})
val drawerState: DrawerState = DrawerState(DrawerValue.Closed)
Expand Down
Loading