mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-19 18:21:19 -05:00
add paging for home page people and option to show titles on home page posters
This commit is contained in:
@@ -35,7 +35,7 @@ class HomePagePagingSource(
|
|||||||
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
||||||
LoadResult.Invalid()
|
LoadResult.Invalid()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class HomePagePeoplePagingSource: PagingSource<Int, HomePagePerson>(), KoinCompo
|
|||||||
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(context, "No more results found", Toast.LENGTH_SHORT).show()
|
||||||
LoadResult.Invalid()
|
LoadResult.Invalid()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.content.Context
|
|||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.kieronquinn.monetcompat.core.MonetCompat
|
import com.kieronquinn.monetcompat.core.MonetCompat
|
||||||
import com.owenlejeune.tvtime.BuildConfig
|
|
||||||
import com.owenlejeune.tvtime.utils.SessionManager
|
import com.owenlejeune.tvtime.utils.SessionManager
|
||||||
|
|
||||||
class AppPreferences(context: Context) {
|
class AppPreferences(context: Context) {
|
||||||
@@ -37,6 +36,7 @@ class AppPreferences(context: Context) {
|
|||||||
private val PEOPLE_TAB_POSITION = "people_tab_position"
|
private val PEOPLE_TAB_POSITION = "people_tab_position"
|
||||||
private val ACCOUNT_TAB_POSITION = "account_tab_position"
|
private val ACCOUNT_TAB_POSITION = "account_tab_position"
|
||||||
private val SHOW_BTAB_LABELS = "show_btab_labels"
|
private val SHOW_BTAB_LABELS = "show_btab_labels"
|
||||||
|
private val SHOW_POSTER_TITLE = "show_poster_titles"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
|
private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE)
|
||||||
@@ -119,6 +119,11 @@ class AppPreferences(context: Context) {
|
|||||||
get() = preferences.getBoolean(SHOW_BTAB_LABELS, showBottomTabLabelsDefault)
|
get() = preferences.getBoolean(SHOW_BTAB_LABELS, showBottomTabLabelsDefault)
|
||||||
set(value) { preferences.put(SHOW_BTAB_LABELS, value) }
|
set(value) { preferences.put(SHOW_BTAB_LABELS, value) }
|
||||||
|
|
||||||
|
val showPosterTitlesDefault: Boolean = false
|
||||||
|
var showPosterTitles: Boolean
|
||||||
|
get() = preferences.getBoolean(SHOW_POSTER_TITLE, showPosterTitlesDefault)
|
||||||
|
set(value) { preferences.put(SHOW_POSTER_TITLE, value) }
|
||||||
|
|
||||||
/******** Dev Preferences ********/
|
/******** Dev Preferences ********/
|
||||||
val firstLaunchTestingDefault: Boolean = false
|
val firstLaunchTestingDefault: Boolean = false
|
||||||
var firstLaunchTesting: Boolean
|
var firstLaunchTesting: Boolean
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ fun TwoLineImageTextCard(
|
|||||||
url = imageUrl,
|
url = imageUrl,
|
||||||
noDataImage = noDataImage,
|
noDataImage = noDataImage,
|
||||||
placeholder = placeholder,
|
placeholder = placeholder,
|
||||||
contentDescription = title,
|
title = title,
|
||||||
elevation = 0.dp
|
elevation = 0.dp
|
||||||
)
|
)
|
||||||
MinLinesText(
|
MinLinesText(
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.owenlejeune.tvtime.ui.components
|
package com.owenlejeune.tvtime.ui.components
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -11,14 +10,16 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.Card
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.IntSize
|
import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -26,19 +27,16 @@ import androidx.paging.LoadState
|
|||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.compose.rememberAsyncImagePainter
|
import coil.compose.rememberAsyncImagePainter
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
|
||||||
import com.google.accompanist.pager.HorizontalPager
|
|
||||||
import com.google.accompanist.pager.rememberPagerState
|
|
||||||
import com.owenlejeune.tvtime.R
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePerson
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePagePerson
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
|
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Person
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.Person
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
||||||
import com.owenlejeune.tvtime.extensions.dpToPx
|
|
||||||
import com.owenlejeune.tvtime.extensions.header
|
import com.owenlejeune.tvtime.extensions.header
|
||||||
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
import com.owenlejeune.tvtime.extensions.lazyPagingItems
|
||||||
import com.owenlejeune.tvtime.extensions.listItems
|
import com.owenlejeune.tvtime.extensions.listItems
|
||||||
|
import com.owenlejeune.tvtime.preferences.AppPreferences
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
|
import org.koin.java.KoinJavaComponent.get
|
||||||
|
|
||||||
private val POSTER_WIDTH = 120.dp
|
private val POSTER_WIDTH = 120.dp
|
||||||
private val POSTER_HEIGHT = 190.dp
|
private val POSTER_HEIGHT = 190.dp
|
||||||
@@ -122,7 +120,7 @@ fun PagingPeoplePosterGrid(
|
|||||||
onClick = {
|
onClick = {
|
||||||
onClick(person.id)
|
onClick(person.id)
|
||||||
},
|
},
|
||||||
contentDescription = person.name
|
title = person.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +157,7 @@ fun PeoplePosterGrid(
|
|||||||
onClick = {
|
onClick = {
|
||||||
onClick(person.id)
|
onClick(person.id)
|
||||||
},
|
},
|
||||||
contentDescription = person.name
|
title = person.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +183,7 @@ fun PosterItem(
|
|||||||
},
|
},
|
||||||
url = mediaItem?.let { TmdbUtils.getFullPosterPath(mediaItem) },
|
url = mediaItem?.let { TmdbUtils.getFullPosterPath(mediaItem) },
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
contentDescription = mediaItem?.title
|
title = mediaItem?.title
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +207,7 @@ fun PosterItem(
|
|||||||
},
|
},
|
||||||
url = person?.let { TmdbUtils.getFullPersonImagePath(person) },
|
url = person?.let { TmdbUtils.getFullPersonImagePath(person) },
|
||||||
elevation = 8.dp,
|
elevation = 8.dp,
|
||||||
contentDescription = person?.name
|
title = person?.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +221,8 @@ fun PosterItem(
|
|||||||
noDataImage: Int = R.drawable.placeholder,
|
noDataImage: Int = R.drawable.placeholder,
|
||||||
placeholder: Int = R.drawable.placeholder,
|
placeholder: Int = R.drawable.placeholder,
|
||||||
elevation: Dp = 8.dp,
|
elevation: Dp = 8.dp,
|
||||||
contentDescription: String?
|
title: String?,
|
||||||
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
@@ -232,31 +231,64 @@ fun PosterItem(
|
|||||||
.wrapContentHeight(),
|
.wrapContentHeight(),
|
||||||
shape = RoundedCornerShape(5.dp)
|
shape = RoundedCornerShape(5.dp)
|
||||||
) {
|
) {
|
||||||
if (url != null) {
|
Box {
|
||||||
AsyncImage(
|
var sizeImage by remember { mutableStateOf(IntSize.Zero) }
|
||||||
modifier = Modifier
|
val gradient = Brush.verticalGradient(
|
||||||
.width(width = width)
|
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.7f)),
|
||||||
.clip(RoundedCornerShape(5.dp))
|
startY = sizeImage.height.toFloat() / 3f,
|
||||||
.clickable(
|
endY = sizeImage.height.toFloat()
|
||||||
onClick = onClick
|
|
||||||
),
|
|
||||||
model = url,
|
|
||||||
placeholder = rememberAsyncImagePainter(model = placeholder),
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
contentScale = ContentScale.FillWidth
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Image(
|
|
||||||
modifier = Modifier
|
|
||||||
.size(width = width, height = height)
|
|
||||||
.clip(RoundedCornerShape(5.dp))
|
|
||||||
.clickable(
|
|
||||||
onClick = onClick
|
|
||||||
),
|
|
||||||
painter = rememberAsyncImagePainter(model = noDataImage),
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
contentScale = ContentScale.FillBounds
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
AsyncImage(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(width = width)
|
||||||
|
.wrapContentHeight()
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.clickable(
|
||||||
|
onClick = onClick
|
||||||
|
)
|
||||||
|
.onGloballyPositioned { sizeImage = it.size },
|
||||||
|
model = url,
|
||||||
|
placeholder = rememberAsyncImagePainter(model = placeholder),
|
||||||
|
contentDescription = title,
|
||||||
|
contentScale = ContentScale.FillWidth
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(width = width)
|
||||||
|
.wrapContentHeight()
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.clickable(
|
||||||
|
onClick = onClick
|
||||||
|
)
|
||||||
|
.onGloballyPositioned { sizeImage = it.size },
|
||||||
|
painter = rememberAsyncImagePainter(model = noDataImage),
|
||||||
|
contentDescription = title,
|
||||||
|
contentScale = ContentScale.FillBounds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preferences.showPosterTitles) {
|
||||||
|
title?.let {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.background(brush = gradient)
|
||||||
|
.matchParentSize()
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomStart)
|
||||||
|
.padding(6.dp),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.main
|
package com.owenlejeune.tvtime.ui.screens.main
|
||||||
|
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
@@ -25,13 +23,11 @@ import com.google.accompanist.pager.HorizontalPager
|
|||||||
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.api.tmdb.api.v3.model.ImageCollection
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.ImageCollection
|
||||||
import com.owenlejeune.tvtime.preferences.AppPreferences
|
|
||||||
import com.owenlejeune.tvtime.ui.components.PosterItem
|
import com.owenlejeune.tvtime.ui.components.PosterItem
|
||||||
import com.owenlejeune.tvtime.ui.components.RatingRing
|
import com.owenlejeune.tvtime.ui.components.RatingRing
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.java.KoinJavaComponent.get
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DetailHeader(
|
fun DetailHeader(
|
||||||
@@ -75,7 +71,7 @@ fun DetailHeader(
|
|||||||
start.linkTo(parent.start, margin = 16.dp)
|
start.linkTo(parent.start, margin = 16.dp)
|
||||||
},
|
},
|
||||||
url = posterUrl,
|
url = posterUrl,
|
||||||
contentDescription = posterContentDescription,
|
title = posterContentDescription,
|
||||||
elevation = 20.dp
|
elevation = 20.dp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -378,6 +378,17 @@ private fun HomeScreenPreferences(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val showPosterTitles = remember { mutableStateOf(preferences.showPosterTitles) }
|
||||||
|
SwitchPreference(
|
||||||
|
titleText = stringResource(R.string.preference_show_poster_titles_title),
|
||||||
|
subtitleText = stringResource(R.string.preference_show_poster_titles_subtitle),
|
||||||
|
checkState = showTabLabels.value,
|
||||||
|
onCheckedChange = { isChecked ->
|
||||||
|
showPosterTitles.value = isChecked
|
||||||
|
preferences.showPosterTitles = isChecked
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
PreferenceHeading(text = stringResource(R.string.preference_home_tab_order_heading))
|
PreferenceHeading(text = stringResource(R.string.preference_home_tab_order_heading))
|
||||||
|
|
||||||
Box(modifier = Modifier
|
Box(modifier = Modifier
|
||||||
|
|||||||
@@ -151,4 +151,6 @@
|
|||||||
<string name="action_skip">Skip</string>
|
<string name="action_skip">Skip</string>
|
||||||
<string name="action_skip_testing">Skip (t)</string>
|
<string name="action_skip_testing">Skip (t)</string>
|
||||||
<string name="popular_today_header">Popular Today</string>
|
<string name="popular_today_header">Popular Today</string>
|
||||||
|
<string name="preference_show_poster_titles_title">Show Poster Titles</string>
|
||||||
|
<string name="preference_show_poster_titles_subtitle">Show titles on home screen posters</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user