mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-19 10:11:13 -05:00
redesign segment controls
This commit is contained in:
@@ -0,0 +1,152 @@
|
|||||||
|
package com.owenlejeune.tvtime.ui.components
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.IntSize
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.owenlejeune.tvtime.extensions.toDp
|
||||||
|
|
||||||
|
@SuppressLint("AutoboxingStateValueProperty")
|
||||||
|
@Composable
|
||||||
|
fun <T> PillSegmentedControl(
|
||||||
|
items: List<T>,
|
||||||
|
itemLabel: (index: Int, item: T) -> String,
|
||||||
|
onItemSelected: (index: Int, item: T) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
defaultSelectedItemIndex: Int = 0,
|
||||||
|
cornerRadius: Int = 50,
|
||||||
|
colors: SegmentControlColors = SegmentControlDefaults.pillSegmentControlColors()
|
||||||
|
) {
|
||||||
|
val selectedIndex = remember { mutableIntStateOf(defaultSelectedItemIndex) }
|
||||||
|
|
||||||
|
val parentBoxSize = remember { mutableStateOf(IntSize.Zero) }
|
||||||
|
val textViewSize = remember { mutableStateOf(IntSize.Zero) }
|
||||||
|
val maxTextViewSize = remember { mutableStateOf(IntSize.Zero) }
|
||||||
|
|
||||||
|
val offsetAnimation by animateDpAsState(targetValue = (selectedIndex.value * textViewSize.value.width).toDp())
|
||||||
|
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = modifier.then(
|
||||||
|
Modifier
|
||||||
|
.border(
|
||||||
|
width = 1.dp,
|
||||||
|
color = colors.borderColor(),
|
||||||
|
shape = RoundedCornerShape(cornerRadius)
|
||||||
|
)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
parentBoxSize.value = it.size
|
||||||
|
}
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset(
|
||||||
|
x = offsetAnimation,
|
||||||
|
y = 0.dp
|
||||||
|
)
|
||||||
|
.clip(RoundedCornerShape(cornerRadius))
|
||||||
|
.width((parentBoxSize.value.width / items.size).toDp())
|
||||||
|
.height(parentBoxSize.value.height.toDp())
|
||||||
|
.background(color = colors.pillColor())
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
items.forEachIndexed { index, item ->
|
||||||
|
Text(
|
||||||
|
text = itemLabel(index, item),
|
||||||
|
color = if (selectedIndex.value == index) colors.selectedTextColor() else colors.textColor(),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
textViewSize.value = it.size
|
||||||
|
if (it.size.width > maxTextViewSize.value.width) {
|
||||||
|
maxTextViewSize.value = it.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clickable(
|
||||||
|
interactionSource = MutableInteractionSource(),
|
||||||
|
indication = null
|
||||||
|
) {
|
||||||
|
selectedIndex.value = index
|
||||||
|
onItemSelected(index, item)
|
||||||
|
}
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SegmentControlColors {
|
||||||
|
@Composable fun borderColor(): Color
|
||||||
|
@Composable fun pillColor(): Color
|
||||||
|
@Composable fun textColor(): Color
|
||||||
|
@Composable fun selectedTextColor(): Color
|
||||||
|
}
|
||||||
|
|
||||||
|
object SegmentControlDefaults {
|
||||||
|
@Composable
|
||||||
|
fun pillSegmentControlColors(
|
||||||
|
borderColor: Color = MaterialTheme.colorScheme.primary,
|
||||||
|
pillColor: Color = MaterialTheme.colorScheme.primary,
|
||||||
|
textColor: Color = MaterialTheme.colorScheme.primary,
|
||||||
|
selectedTextColor: Color = MaterialTheme.colorScheme.background
|
||||||
|
): SegmentControlColors {
|
||||||
|
return object : SegmentControlColors {
|
||||||
|
@Composable override fun borderColor() = borderColor
|
||||||
|
@Composable override fun pillColor() = pillColor
|
||||||
|
@Composable override fun textColor() = textColor
|
||||||
|
@Composable override fun selectedTextColor() = selectedTextColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun PillSegmentControlPreview() {
|
||||||
|
val items = listOf("One", "Two", "Three", "Four")
|
||||||
|
|
||||||
|
val colors = SegmentControlDefaults.pillSegmentControlColors(borderColor = Color.Red, pillColor = Color.Red, textColor = Color.Red, selectedTextColor = Color.White)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
|
modifier = Modifier.background(Color.White)
|
||||||
|
) {
|
||||||
|
PillSegmentedControl(items = items.subList(0, 2), itemLabel = { _, t -> t }, onItemSelected = { _, _ -> }, colors = colors)
|
||||||
|
PillSegmentedControl(items = items.subList(0, 3), itemLabel = { _, t -> t }, onItemSelected = { _, _ -> }, colors = colors)
|
||||||
|
PillSegmentedControl(items = items, itemLabel = { _, t -> t }, onItemSelected = { _, _ -> }, colors = colors)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1116,72 +1116,4 @@ fun SearchBar(
|
|||||||
@Composable
|
@Composable
|
||||||
fun MyDivider(modifier: Modifier = Modifier) {
|
fun MyDivider(modifier: Modifier = Modifier) {
|
||||||
Divider(thickness = 0.5.dp, modifier = modifier, color = MaterialTheme.colorScheme.secondaryContainer)
|
Divider(thickness = 0.5.dp, modifier = modifier, color = MaterialTheme.colorScheme.secondaryContainer)
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SelectableTextItem(
|
|
||||||
selected: Boolean,
|
|
||||||
onSelected: () -> Unit,
|
|
||||||
text: String,
|
|
||||||
selectedColor: Color = MaterialTheme.colorScheme.secondary,
|
|
||||||
unselectedColor: Color = MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.clip(RoundedCornerShape(10.dp))
|
|
||||||
.clickable(onClick = onSelected)
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.spacedBy(6.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
modifier = Modifier.padding(8.dp)
|
|
||||||
) {
|
|
||||||
val size = remember { mutableStateOf(IntSize.Zero) }
|
|
||||||
val color = if (selected) selectedColor else unselectedColor
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
fontWeight = if (selected) FontWeight.Bold else FontWeight.Normal,
|
|
||||||
color = color,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 4.dp)
|
|
||||||
.onGloballyPositioned { size.value = it.size }
|
|
||||||
)
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(height = if (selected) 3.dp else 1.dp)
|
|
||||||
.width(width = size.value.width.toDp().plus(8.dp))
|
|
||||||
.clip(RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp))
|
|
||||||
.background(color = color)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SelectableTextChip(
|
|
||||||
selected: Boolean,
|
|
||||||
onSelected: () -> Unit,
|
|
||||||
text: String,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
selectedColor: Color = MaterialTheme.colorScheme.secondary,
|
|
||||||
unselectedColor: Color = MaterialTheme.colorScheme.surfaceVariant
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
modifier = modifier.then(
|
|
||||||
Modifier
|
|
||||||
.clip(RoundedCornerShape(percent = 25))
|
|
||||||
.border(width = 1.dp, color = selectedColor, shape = RoundedCornerShape(percent = 25))
|
|
||||||
.background(color = if(selected) selectedColor else unselectedColor)
|
|
||||||
.clickable(onClick = onSelected)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
color = if (selected) unselectedColor else selectedColor,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.Center)
|
|
||||||
.padding(12.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@ package com.owenlejeune.tvtime.ui.screens
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@@ -31,14 +30,10 @@ import androidx.navigation.NavController
|
|||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.CrewMember
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.DetailCrew
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCast
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCastMember
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCastMember
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCast
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCastMember
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCastMember
|
||||||
import com.owenlejeune.tvtime.extensions.getCalendarYear
|
|
||||||
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
import com.owenlejeune.tvtime.utils.types.MediaViewType
|
||||||
@@ -99,29 +94,15 @@ fun CastCrewListScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
Row(
|
val labels = listOf(stringResource(id = R.string.actor_label), stringResource(id = R.string.production_label))
|
||||||
modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
|
PillSegmentedControl(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
items = labels,
|
||||||
) {
|
itemLabel = { _, t -> t },
|
||||||
SelectableTextChip(
|
onItemSelected = { i, _ -> castSelected = i == 0 },
|
||||||
selected = castSelected,
|
modifier = Modifier.padding(horizontal = 8.dp)
|
||||||
onSelected = { castSelected = true },
|
)
|
||||||
text = stringResource(id = R.string.actor_label),
|
|
||||||
selectedColor = MaterialTheme.colorScheme.tertiary,
|
|
||||||
unselectedColor = MaterialTheme.colorScheme.background
|
|
||||||
)
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = !castSelected,
|
|
||||||
onSelected = { castSelected = false },
|
|
||||||
text = stringResource(id = R.string.production_label),
|
|
||||||
selectedColor = MaterialTheme.colorScheme.tertiary,
|
|
||||||
unselectedColor = MaterialTheme.colorScheme.background
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
items(items!!) { item ->
|
items(items!!) { item ->
|
||||||
val additionalDetails = emptyList<String>().toMutableList()
|
val additionalDetails = emptyList<String>().toMutableList()
|
||||||
when (item) {
|
when (item) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCast
|
|||||||
import com.owenlejeune.tvtime.extensions.bringToFront
|
import com.owenlejeune.tvtime.extensions.bringToFront
|
||||||
import com.owenlejeune.tvtime.extensions.getCalendarYear
|
import com.owenlejeune.tvtime.extensions.getCalendarYear
|
||||||
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
|
|
||||||
@@ -99,19 +99,11 @@ fun KnownForScreen(
|
|||||||
modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
|
modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
SelectableTextChip(
|
val labels = listOf(stringResource(id = R.string.actor_label), stringResource(id = R.string.production_label))
|
||||||
selected = actorSelected,
|
PillSegmentedControl(
|
||||||
onSelected = { actorSelected = true },
|
items = labels,
|
||||||
text = stringResource(id = R.string.actor_label),
|
itemLabel = { _, t -> t },
|
||||||
selectedColor = MaterialTheme.colorScheme.tertiary,
|
onItemSelected = { i, _ -> actorSelected = i == 0}
|
||||||
unselectedColor = MaterialTheme.colorScheme.background
|
|
||||||
)
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = !actorSelected,
|
|
||||||
onSelected = { actorSelected = false },
|
|
||||||
text = stringResource(id = R.string.production_label),
|
|
||||||
selectedColor = MaterialTheme.colorScheme.tertiary,
|
|
||||||
unselectedColor = MaterialTheme.colorScheme.background
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens
|
package com.owenlejeune.tvtime.ui.screens
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@@ -48,7 +49,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
@@ -112,10 +112,10 @@ import com.owenlejeune.tvtime.ui.components.FullScreenThumbnailVideoPlayer
|
|||||||
import com.owenlejeune.tvtime.ui.components.HtmlText
|
import com.owenlejeune.tvtime.ui.components.HtmlText
|
||||||
import com.owenlejeune.tvtime.ui.components.ImageGalleryOverlay
|
import com.owenlejeune.tvtime.ui.components.ImageGalleryOverlay
|
||||||
import com.owenlejeune.tvtime.ui.components.ListContentCard
|
import com.owenlejeune.tvtime.ui.components.ListContentCard
|
||||||
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.components.PosterItem
|
import com.owenlejeune.tvtime.ui.components.PosterItem
|
||||||
import com.owenlejeune.tvtime.ui.components.RoundedChip
|
import com.owenlejeune.tvtime.ui.components.RoundedChip
|
||||||
import com.owenlejeune.tvtime.ui.components.RoundedTextField
|
import com.owenlejeune.tvtime.ui.components.RoundedTextField
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
|
||||||
import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard
|
import com.owenlejeune.tvtime.ui.components.TwoLineImageTextCard
|
||||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
||||||
@@ -986,6 +986,7 @@ private fun VideoGroup(results: List<Video>, type: Video.Type, title: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("AutoboxingStateValueProperty")
|
||||||
@Composable
|
@Composable
|
||||||
private fun WatchProvidersCard(
|
private fun WatchProvidersCard(
|
||||||
itemId: Int,
|
itemId: Int,
|
||||||
@@ -1012,49 +1013,33 @@ private fun WatchProvidersCard(
|
|||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
|
|
||||||
var selectedIndex by remember { mutableIntStateOf(
|
val itemsMap = mutableMapOf<Int, List<WatchProviderDetails>>().apply {
|
||||||
when {
|
providers.flaterate?.let { put(0, it) }
|
||||||
providers.flaterate != null -> 0
|
providers.rent?.let { put(1, it) }
|
||||||
providers.rent != null -> 1
|
providers.buy?.let { put(2, it) }
|
||||||
providers.buy != null -> 2
|
|
||||||
else -> -1
|
|
||||||
}
|
|
||||||
) }
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
providers.flaterate?.let {
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = selectedIndex == 0,
|
|
||||||
onSelected = { selectedIndex = 0 },
|
|
||||||
text = stringResource(R.string.streaming_label)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
providers.rent?.let {
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = selectedIndex == 1,
|
|
||||||
onSelected = { selectedIndex = 1 },
|
|
||||||
text = stringResource(R.string.rent_label)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
providers.buy?.let {
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = selectedIndex == 2,
|
|
||||||
onSelected = { selectedIndex = 2 },
|
|
||||||
text = stringResource(R.string.buy_label)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
val selected = remember { mutableStateOf(if (itemsMap.isEmpty()) null else itemsMap.values.first()) }
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
PillSegmentedControl(
|
||||||
|
items = itemsMap.values.toList(),
|
||||||
|
itemLabel = { i, _ ->
|
||||||
|
when (i) {
|
||||||
|
0 -> context.getString(R.string.streaming_label)
|
||||||
|
1 -> context.getString(R.string.rent_label)
|
||||||
|
2 -> context.getString(R.string.buy_label)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onItemSelected = { i, _ -> selected.value = itemsMap.values.toList()[i] },
|
||||||
|
modifier = Modifier.padding(all = 8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Crossfade(
|
Crossfade(
|
||||||
modifier = modifier.padding(top = 4.dp, bottom = 12.dp),
|
modifier = modifier.padding(top = 4.dp, bottom = 12.dp),
|
||||||
targetState = selectedIndex
|
targetState = selected.value
|
||||||
) { index ->
|
) { value ->
|
||||||
when (index) {
|
WatchProviderContainer(watchProviders = value!!, link = providers.link)
|
||||||
0 -> WatchProviderContainer(watchProviders = providers.flaterate!!, link = providers.link)
|
|
||||||
1 -> WatchProviderContainer(watchProviders = providers.rent!!, link = providers.link)
|
|
||||||
2 -> WatchProviderContainer(watchProviders = providers.buy!!, link = providers.link)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.*
|
|||||||
import com.owenlejeune.tvtime.extensions.getCalendarYear
|
import com.owenlejeune.tvtime.extensions.getCalendarYear
|
||||||
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
||||||
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
import com.owenlejeune.tvtime.ui.components.MediaResultCard
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.SearchViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.SearchViewModel
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
@@ -106,31 +106,26 @@ fun SearchScreen(
|
|||||||
)
|
)
|
||||||
Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant)
|
Divider(thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
|
||||||
Row(
|
val searchTypes = listOf(MediaViewType.MOVIE, MediaViewType.TV, MediaViewType.PERSON, MediaViewType.MIXED)
|
||||||
modifier = Modifier.padding(start = 12.dp, top = 12.dp, bottom = 12.dp),
|
val selected = remember { mutableStateOf(searchTypes[0]) }
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
val context = LocalContext.current
|
||||||
SelectableTextChip(
|
PillSegmentedControl(
|
||||||
selected = viewType.value == MediaViewType.MOVIE,
|
items = searchTypes,
|
||||||
onSelected = { viewType.value = MediaViewType.MOVIE },
|
itemLabel = { _, i ->
|
||||||
text = stringResource(id = R.string.nav_movies_title)
|
when (i) {
|
||||||
)
|
MediaViewType.MOVIE -> context.getString(R.string.nav_movies_title)
|
||||||
SelectableTextChip(
|
MediaViewType.TV -> context.getString(R.string.nav_tv_title)
|
||||||
selected = viewType.value == MediaViewType.TV,
|
MediaViewType.PERSON -> context.getString(R.string.nav_people_title)
|
||||||
onSelected = { viewType.value = MediaViewType.TV },
|
MediaViewType.MIXED -> context.getString(R.string.search_multi_title)
|
||||||
text = stringResource(id = R.string.nav_tv_title)
|
else -> ""
|
||||||
)
|
}
|
||||||
SelectableTextChip(
|
},
|
||||||
selected = viewType.value == MediaViewType.PERSON,
|
onItemSelected = { _, i ->
|
||||||
onSelected = { viewType.value = MediaViewType.PERSON },
|
selected.value = i
|
||||||
text = stringResource(id = R.string.nav_people_title)
|
},
|
||||||
)
|
modifier = Modifier.padding(start = 12.dp, top = 12.dp, end = 12.dp)
|
||||||
SelectableTextChip(
|
)
|
||||||
selected = viewType.value == MediaViewType.MIXED,
|
|
||||||
onSelected = { viewType.value = MediaViewType.MIXED },
|
|
||||||
text = stringResource(id = R.string.search_multi_title)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (viewType.value) {
|
when (viewType.value) {
|
||||||
MediaViewType.TV -> {
|
MediaViewType.TV -> {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.tabs
|
package com.owenlejeune.tvtime.ui.screens.tabs
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
@@ -21,9 +21,9 @@ import com.google.accompanist.pager.PagerState
|
|||||||
import com.google.accompanist.pager.rememberPagerState
|
import com.google.accompanist.pager.rememberPagerState
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
||||||
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.components.ScrollableTabs
|
import com.owenlejeune.tvtime.ui.components.ScrollableTabs
|
||||||
import com.owenlejeune.tvtime.ui.components.SearchView
|
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
|
||||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel
|
||||||
@@ -102,25 +102,23 @@ fun MediaTabTrendingContent(
|
|||||||
PagingPosterGrid(
|
PagingPosterGrid(
|
||||||
lazyPagingItems = mediaListItems,
|
lazyPagingItems = mediaListItems,
|
||||||
header = {
|
header = {
|
||||||
Row(
|
val options = listOf(TimeWindow.DAY, TimeWindow.WEEK)
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
PillSegmentedControl(
|
||||||
|
items = options,
|
||||||
|
itemLabel = { _, i ->
|
||||||
|
when (i) {
|
||||||
|
TimeWindow.DAY -> context.getString(R.string.time_window_day)
|
||||||
|
TimeWindow.WEEK -> context.getString(R.string.time_window_week)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onItemSelected = { _, i -> timeWindow.value = i },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 4.dp)
|
.padding(horizontal = 4.dp)
|
||||||
.padding(bottom = 4.dp)
|
.padding(bottom = 4.dp)
|
||||||
) {
|
)
|
||||||
SelectableTextChip(
|
|
||||||
selected = timeWindow.value == TimeWindow.DAY,
|
|
||||||
onSelected = { timeWindow.value = TimeWindow.DAY },
|
|
||||||
text = stringResource(id = R.string.time_window_day),
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
SelectableTextChip(
|
|
||||||
selected = timeWindow.value == TimeWindow.WEEK,
|
|
||||||
onSelected = { timeWindow.value = TimeWindow.WEEK },
|
|
||||||
text = stringResource(id = R.string.time_window_week),
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onClick = { id ->
|
onClick = { id ->
|
||||||
appNavController.navigate(
|
appNavController.navigate(
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.tabs
|
package com.owenlejeune.tvtime.ui.screens.tabs
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
@@ -23,8 +22,8 @@ import com.google.accompanist.pager.rememberPagerState
|
|||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.ui.components.PagingPeoplePosterGrid
|
import com.owenlejeune.tvtime.ui.components.PagingPeoplePosterGrid
|
||||||
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
import com.owenlejeune.tvtime.ui.components.PagingPosterGrid
|
||||||
|
import com.owenlejeune.tvtime.ui.components.PillSegmentedControl
|
||||||
import com.owenlejeune.tvtime.ui.components.SearchView
|
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||||
import com.owenlejeune.tvtime.ui.components.SelectableTextChip
|
|
||||||
import com.owenlejeune.tvtime.ui.components.Tabs
|
import com.owenlejeune.tvtime.ui.components.Tabs
|
||||||
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
import com.owenlejeune.tvtime.ui.navigation.AppNavItem
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel
|
import com.owenlejeune.tvtime.ui.viewmodel.HomeScreenViewModel
|
||||||
@@ -91,23 +90,24 @@ fun TrendingPeopleContent(
|
|||||||
val mediaListItems = flow.value.collectAsLazyPagingItems()
|
val mediaListItems = flow.value.collectAsLazyPagingItems()
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Row(
|
val timeWindows = listOf(TimeWindow.DAY, TimeWindow.WEEK)
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
val selected = remember { mutableStateOf(timeWindows[0]) }
|
||||||
modifier = Modifier.padding(all = 12.dp)
|
|
||||||
) {
|
val context = LocalContext.current
|
||||||
SelectableTextChip(
|
PillSegmentedControl(
|
||||||
selected = timeWindow.value == TimeWindow.DAY,
|
items = timeWindows,
|
||||||
onSelected = { timeWindow.value = TimeWindow.DAY },
|
itemLabel = { _, i ->
|
||||||
text = stringResource(id = R.string.time_window_day),
|
when (i) {
|
||||||
modifier = Modifier.weight(1f)
|
TimeWindow.DAY -> context.getString(R.string.time_window_day)
|
||||||
)
|
TimeWindow.WEEK -> context.getString(R.string.time_window_week)
|
||||||
SelectableTextChip(
|
}
|
||||||
selected = timeWindow.value == TimeWindow.WEEK,
|
},
|
||||||
onSelected = { timeWindow.value = TimeWindow.WEEK },
|
onItemSelected = { _, t ->
|
||||||
text = stringResource(id = R.string.time_window_week),
|
selected.value = t
|
||||||
modifier = Modifier.weight(1f)
|
},
|
||||||
)
|
modifier = Modifier.padding(start = 8.dp, end = 8.dp, top = 8.dp)
|
||||||
}
|
)
|
||||||
|
|
||||||
PagingPosterGrid(
|
PagingPosterGrid(
|
||||||
lazyPagingItems = mediaListItems,
|
lazyPagingItems = mediaListItems,
|
||||||
onClick = { id ->
|
onClick = { id ->
|
||||||
|
|||||||
Reference in New Issue
Block a user