mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-10 05:42:43 -05:00
refactor main view titles and poster placeholders
This commit is contained in:
@@ -92,13 +92,13 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
val currentRoute = navBackStackEntry?.destination?.route
|
val currentRoute = navBackStackEntry?.destination?.route
|
||||||
|
|
||||||
val appBarTitle = rememberSaveable { mutableStateOf(BottomNavItem.getByRoute(currentRoute)?.name ?: BottomNavItem.SortedItems[0].name) }
|
|
||||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||||
val scrollBehavior = remember(decayAnimationSpec) {
|
val scrollBehavior = remember(decayAnimationSpec) {
|
||||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val appBarTitle = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||||
val appBarActions = remember { mutableStateOf<@Composable RowScope.() -> Unit>({}) }
|
val appBarActions = remember { mutableStateOf<@Composable RowScope.() -> Unit>({}) }
|
||||||
val fab = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
val fab = remember { mutableStateOf<@Composable () -> Unit>({}) }
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
if (windowSize != WindowSizeClass.Expanded) {
|
if (windowSize != WindowSizeClass.Expanded) {
|
||||||
TopBar(
|
TopBar(
|
||||||
appNavController = appNavController,
|
appNavController = appNavController,
|
||||||
title = appBarTitle,
|
title = appBarTitle.value,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
appBarActions = appBarActions
|
appBarActions = appBarActions
|
||||||
)
|
)
|
||||||
@@ -119,7 +119,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
if (windowSize != WindowSizeClass.Expanded) {
|
if (windowSize != WindowSizeClass.Expanded) {
|
||||||
BottomNavBar(navController = navController, appBarTitle = appBarTitle)
|
BottomNavBar(navController = navController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
@@ -141,7 +141,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(
|
private fun TopBar(
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
title: MutableState<String>,
|
title: @Composable () -> Unit,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({})
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({})
|
||||||
) {
|
) {
|
||||||
@@ -155,7 +155,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LargeTopAppBar(
|
LargeTopAppBar(
|
||||||
title = { Text(text = title.value) },
|
title = title,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
colors = TopAppBarDefaults
|
colors = TopAppBarDefaults
|
||||||
.largeTopAppBarColors(
|
.largeTopAppBarColors(
|
||||||
@@ -171,7 +171,6 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun BottomNavBar(
|
private fun BottomNavBar(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
appBarTitle: MutableState<String>,
|
|
||||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
) {
|
) {
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
@@ -192,25 +191,12 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
selected = isSelected,
|
selected = isSelected,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (!isSelected) {
|
if (!isSelected) {
|
||||||
onBottomAppBarItemClicked(
|
|
||||||
navController = navController,
|
|
||||||
appBarTitle = appBarTitle,
|
|
||||||
item = item
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onBottomAppBarItemClicked(
|
|
||||||
navController: NavController,
|
|
||||||
appBarTitle: MutableState<String>,
|
|
||||||
item: BottomNavItem
|
|
||||||
) {
|
|
||||||
navController.navigateInBottomBar(item.route)
|
navController.navigateInBottomBar(item.route)
|
||||||
appBarTitle.value = item.name
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -220,7 +206,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>,
|
fab: MutableState<@Composable () -> Unit>,
|
||||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||||
) {
|
) {
|
||||||
@@ -251,7 +237,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>,
|
fab: MutableState<@Composable () -> Unit>,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||||
) {
|
) {
|
||||||
@@ -271,7 +257,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>,
|
fab: MutableState<@Composable () -> Unit>,
|
||||||
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
topBarScrollBehaviour: TopAppBarScrollBehavior,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route,
|
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route,
|
||||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
@@ -290,11 +276,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
selected = isSelected,
|
selected = isSelected,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (!isSelected) {
|
if (!isSelected) {
|
||||||
onBottomAppBarItemClicked(
|
navController.navigateInBottomBar(item.route)
|
||||||
navController = navController,
|
|
||||||
appBarTitle = appBarTitle,
|
|
||||||
item = item
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -307,7 +289,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
Column {
|
Column {
|
||||||
TopBar(
|
TopBar(
|
||||||
appNavController = appNavController,
|
appNavController = appNavController,
|
||||||
title = appBarTitle,
|
title = appBarTitle.value,
|
||||||
scrollBehavior = topBarScrollBehaviour,
|
scrollBehavior = topBarScrollBehaviour,
|
||||||
appBarActions = appBarActions
|
appBarActions = appBarActions
|
||||||
)
|
)
|
||||||
@@ -328,7 +310,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>,
|
fab: MutableState<@Composable () -> Unit>,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<RowScope.() -> Unit> = mutableStateOf({}),
|
appBarActions: MutableState<RowScope.() -> Unit> = mutableStateOf({}),
|
||||||
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
mainNavStartRoute: String = BottomNavItem.SortedItems[0].route
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
package com.owenlejeune.tvtime.api.tmdb.api.v3.model
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
|
import com.owenlejeune.tvtime.R
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
||||||
import org.koin.core.Koin
|
import org.koin.core.Koin
|
||||||
@@ -13,9 +15,14 @@ import retrofit2.Response
|
|||||||
|
|
||||||
class HomePagePagingSource(
|
class HomePagePagingSource(
|
||||||
private val service: HomePageService,
|
private val service: HomePageService,
|
||||||
private val mediaFetch: MediaFetchFun
|
private val mediaFetch: MediaFetchFun,
|
||||||
|
private val tag: String
|
||||||
): PagingSource<Int, TmdbItem>(), KoinComponent {
|
): PagingSource<Int, TmdbItem>(), KoinComponent {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val TAG = HomePagePagingSource::class.java.simpleName
|
||||||
|
}
|
||||||
|
|
||||||
private val context: Context by inject()
|
private val context: Context by inject()
|
||||||
|
|
||||||
override fun getRefreshKey(state: PagingState<Int, TmdbItem>): Int? {
|
override fun getRefreshKey(state: PagingState<Int, TmdbItem>): Int? {
|
||||||
@@ -25,17 +32,26 @@ class HomePagePagingSource(
|
|||||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, TmdbItem> {
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, TmdbItem> {
|
||||||
return try {
|
return try {
|
||||||
val nextPage = params.key ?: 1
|
val nextPage = params.key ?: 1
|
||||||
|
Log.d(TAG, "Loading $tag page $nextPage")
|
||||||
val mediaResponse = mediaFetch.invoke(service, nextPage)
|
val mediaResponse = mediaFetch.invoke(service, nextPage)
|
||||||
if (mediaResponse.isSuccessful) {
|
if (mediaResponse.isSuccessful) {
|
||||||
val responseBody = mediaResponse.body()
|
val responseBody = mediaResponse.body()
|
||||||
val results = responseBody?.results ?: emptyList()
|
val results = responseBody?.results ?: emptyList()
|
||||||
LoadResult.Page(
|
LoadResult.Page(
|
||||||
data = results,
|
data = results,
|
||||||
prevKey = if (nextPage == 1) null else nextPage - 1,
|
prevKey = if (nextPage == 1) {
|
||||||
nextKey = if (results.isEmpty() || responseBody == null) null else responseBody.page + 1
|
null
|
||||||
|
} else {
|
||||||
|
nextPage - 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, context.getString(R.string.no_result_found), Toast.LENGTH_SHORT).show()
|
||||||
LoadResult.Invalid()
|
LoadResult.Invalid()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.owenlejeune.tvtime.ui.viewmodel
|
package com.owenlejeune.tvtime.api.tmdb.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
@@ -14,18 +14,19 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
|||||||
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
import com.owenlejeune.tvtime.ui.navigation.MediaFetchFun
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
sealed class MediaTabViewModel(service: HomePageService, mediaFetchFun: MediaFetchFun): ViewModel() {
|
sealed class MediaTabViewModel(service: HomePageService, mediaFetchFun: MediaFetchFun, tag: String): ViewModel() {
|
||||||
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
|
||||||
HomePagePagingSource(service = service, mediaFetch = mediaFetchFun)
|
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) {
|
||||||
|
HomePagePagingSource(service = service, mediaFetch = mediaFetchFun, tag = tag)
|
||||||
}.flow.cachedIn(viewModelScope)
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
object PopularMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getPopular(p) })
|
object PopularMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getPopular(p) }, PopularMoviesVM::class.java.simpleName)
|
||||||
object TopRatedMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getTopRated(p) })
|
object TopRatedMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getTopRated(p) }, TopRatedMoviesVM::class.java.simpleName)
|
||||||
object NowPlayingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getNowPlaying(p) })
|
object NowPlayingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getNowPlaying(p) }, NowPlayingMoviesVM::class.java.simpleName)
|
||||||
object UpcomingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getUpcoming(p) })
|
object UpcomingMoviesVM: MediaTabViewModel(MoviesService(), { s, p -> s.getUpcoming(p) }, UpcomingMoviesVM::class.java.simpleName)
|
||||||
object PopularTvVM: MediaTabViewModel(TvService(), { s, p -> s.getPopular(p) })
|
object PopularTvVM: MediaTabViewModel(TvService(), { s, p -> s.getPopular(p) }, PopularTvVM::class.java.simpleName)
|
||||||
object TopRatedTvVM: MediaTabViewModel(TvService(), { s, p -> s.getTopRated(p) })
|
object TopRatedTvVM: MediaTabViewModel(TvService(), { s, p -> s.getTopRated(p) }, TopRatedTvVM::class.java.simpleName)
|
||||||
object AiringTodayTvVM: MediaTabViewModel(TvService(), { s, p -> s.getNowPlaying(p) })
|
object AiringTodayTvVM: MediaTabViewModel(TvService(), { s, p -> s.getNowPlaying(p) }, AiringTodayTvVM::class.java.simpleName)
|
||||||
object OnTheAirTvVM: MediaTabViewModel(TvService(), { s, p -> s.getUpcoming(p) })
|
object OnTheAirTvVM: MediaTabViewModel(TvService(), { s, p -> s.getUpcoming(p) }, OnTheAirTvVM::class.java.simpleName)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.owenlejeune.tvtime.ui.viewmodel
|
package com.owenlejeune.tvtime.api.tmdb.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
@@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
|
|
||||||
class PeopleTabViewModel: ViewModel() {
|
class PeopleTabViewModel: ViewModel() {
|
||||||
|
|
||||||
val popularPeople: Flow<PagingData<HomePagePerson>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
val popularPeople: Flow<PagingData<HomePagePerson>> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) {
|
||||||
HomePagePeoplePagingSource()
|
HomePagePeoplePagingSource()
|
||||||
}.flow.cachedIn(viewModelScope)
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
//package com.owenlejeune.tvtime.api.tmdb.viewmodel
|
|
||||||
//
|
|
||||||
//import androidx.lifecycle.ViewModel
|
|
||||||
//import androidx.lifecycle.viewModelScope
|
|
||||||
//import androidx.paging.Pager
|
|
||||||
//import androidx.paging.PagingConfig
|
|
||||||
//import androidx.paging.PagingData
|
|
||||||
//import androidx.paging.cachedIn
|
|
||||||
//import com.owenlejeune.tvtime.api.tmdb.api.v3.model.PopularMovie
|
|
||||||
//import com.owenlejeune.tvtime.api.tmdb.paging.PopularMovieSource
|
|
||||||
//import kotlinx.coroutines.flow.Flow
|
|
||||||
//
|
|
||||||
//class PopularMovieViewModel: ViewModel() {
|
|
||||||
// val moviePage: Flow<PagingData<PopularMovie>> = Pager(PagingConfig(pageSize = PopularMovieSource.MAX_PAGE)) {
|
|
||||||
// PopularMovieSource()
|
|
||||||
// }.flow.cachedIn(viewModelScope)
|
|
||||||
//}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.owenlejeune.tvtime.ui.viewmodel
|
package com.owenlejeune.tvtime.api.tmdb.viewmodel
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
@@ -8,14 +8,13 @@ import androidx.paging.PagingData
|
|||||||
import androidx.paging.cachedIn
|
import androidx.paging.cachedIn
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RecommendedMediaPagingSource
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.RecommendedMediaPagingSource
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TmdbItem
|
||||||
import com.owenlejeune.tvtime.api.tmdb.api.v4.model.RecommendedMedia
|
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
|
|
||||||
sealed class RecommendedMediaViewModel(mediaType: MediaViewType): ViewModel(), KoinComponent {
|
sealed class RecommendedMediaViewModel(mediaType: MediaViewType): ViewModel(), KoinComponent {
|
||||||
|
|
||||||
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = Int.MAX_VALUE)) {
|
val mediaItems: Flow<PagingData<TmdbItem>> = Pager(PagingConfig(pageSize = ViewModelConstants.PAGING_SIZE)) {
|
||||||
RecommendedMediaPagingSource(mediaType)
|
RecommendedMediaPagingSource(mediaType)
|
||||||
}.flow.cachedIn(viewModelScope)
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.owenlejeune.tvtime.api.tmdb.viewmodel
|
||||||
|
|
||||||
|
object ViewModelConstants {
|
||||||
|
|
||||||
|
const val PAGING_SIZE = 6
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,6 +16,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.FractionalThreshold
|
import androidx.compose.material.FractionalThreshold
|
||||||
import androidx.compose.material.ThresholdConfig
|
import androidx.compose.material.ThresholdConfig
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.material.rememberSwipeableState
|
import androidx.compose.material.rememberSwipeableState
|
||||||
import androidx.compose.material.swipeable
|
import androidx.compose.material.swipeable
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
@@ -25,6 +27,7 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.graphics.Shape
|
import androidx.compose.ui.graphics.Shape
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
@@ -187,8 +190,7 @@ fun TwoLineImageTextCard(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
subtitle: String? = null,
|
subtitle: String? = null,
|
||||||
imageUrl: String? = null,
|
imageUrl: String? = null,
|
||||||
noDataImage: Int = R.drawable.placeholder,
|
placeholder: ImageVector = Icons.Filled.Person,
|
||||||
placeholder: Int = R.drawable.placeholder,
|
|
||||||
titleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
titleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
subtitleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
subtitleTextColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
onItemClicked: () -> Unit = {}
|
onItemClicked: () -> Unit = {}
|
||||||
@@ -198,7 +200,6 @@ fun TwoLineImageTextCard(
|
|||||||
width = 120.dp,
|
width = 120.dp,
|
||||||
onClick = onItemClicked,
|
onClick = onItemClicked,
|
||||||
url = imageUrl,
|
url = imageUrl,
|
||||||
noDataImage = noDataImage,
|
|
||||||
placeholder = placeholder,
|
placeholder = placeholder,
|
||||||
title = title,
|
title = title,
|
||||||
elevation = 0.dp,
|
elevation = 0.dp,
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
package com.owenlejeune.tvtime.ui.components
|
package com.owenlejeune.tvtime.ui.components
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
|
||||||
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
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.focusable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.magnifier
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.Card
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.BrokenImage
|
||||||
|
import androidx.compose.material.icons.filled.Movie
|
||||||
|
import androidx.compose.material.icons.filled.Person
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@@ -19,9 +27,11 @@ 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.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
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.res.painterResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
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
|
||||||
@@ -118,7 +128,7 @@ fun PagingPeoplePosterGrid(
|
|||||||
person?.let {
|
person?.let {
|
||||||
PosterItem(
|
PosterItem(
|
||||||
url = TmdbUtils.getFullPersonImagePath(person.profilePath),
|
url = TmdbUtils.getFullPersonImagePath(person.profilePath),
|
||||||
noDataImage = R.drawable.no_person_photo,
|
placeholder = Icons.Filled.Person,
|
||||||
modifier = Modifier.padding(5.dp),
|
modifier = Modifier.padding(5.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
onClick(person.id)
|
onClick(person.id)
|
||||||
@@ -155,7 +165,7 @@ fun PeoplePosterGrid(
|
|||||||
listItems(peopleList.value) { person ->
|
listItems(peopleList.value) { person ->
|
||||||
PosterItem(
|
PosterItem(
|
||||||
url = TmdbUtils.getFullPersonImagePath(person.profilePath),
|
url = TmdbUtils.getFullPersonImagePath(person.profilePath),
|
||||||
noDataImage = R.drawable.no_person_photo,
|
placeholder = Icons.Filled.Person,
|
||||||
modifier = Modifier.padding(5.dp),
|
modifier = Modifier.padding(5.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
onClick(person.id)
|
onClick(person.id)
|
||||||
@@ -209,6 +219,7 @@ fun PosterItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PosterItem(
|
fun PosterItem(
|
||||||
url: String?,
|
url: String?,
|
||||||
@@ -216,59 +227,68 @@ fun PosterItem(
|
|||||||
width: Dp = POSTER_WIDTH,
|
width: Dp = POSTER_WIDTH,
|
||||||
onClick: () -> Unit = {},
|
onClick: () -> Unit = {},
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
noDataImage: Int = R.drawable.placeholder,
|
placeholder: ImageVector = Icons.Filled.Movie,
|
||||||
placeholder: Int = R.drawable.placeholder,
|
|
||||||
elevation: Dp = 8.dp,
|
elevation: Dp = 8.dp,
|
||||||
title: String?,
|
title: String?,
|
||||||
overrideShowTitle: Boolean? = null,
|
overrideShowTitle: Boolean? = null,
|
||||||
preferences: AppPreferences = get(AppPreferences::class.java)
|
preferences: AppPreferences = get(AppPreferences::class.java)
|
||||||
) {
|
) {
|
||||||
|
var sizeImage by remember { mutableStateOf(IntSize.Zero) }
|
||||||
Card(
|
Card(
|
||||||
elevation = elevation,
|
elevation = CardDefaults.elevatedCardElevation(defaultElevation = elevation),
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.width(width = width)
|
.width(width = width)
|
||||||
.wrapContentHeight(),
|
.wrapContentHeight()
|
||||||
shape = RoundedCornerShape(5.dp)
|
.clickable(
|
||||||
) {
|
enabled = enabled,
|
||||||
Box(
|
|
||||||
modifier = Modifier.clickable(
|
|
||||||
enabled = true,
|
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
)
|
),
|
||||||
|
shape = RoundedCornerShape(5.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = Color.Transparent)
|
||||||
) {
|
) {
|
||||||
var sizeImage by remember { mutableStateOf(IntSize.Zero) }
|
var backgroundColor by remember { mutableStateOf(Color.Gray) }
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(width = width)
|
||||||
|
.height(height = POSTER_HEIGHT)
|
||||||
|
.background(color = backgroundColor)
|
||||||
|
.clip(RoundedCornerShape(5.dp))
|
||||||
|
.onGloballyPositioned { sizeImage = it.size }
|
||||||
|
) {
|
||||||
|
var bgIcon by remember { mutableStateOf(placeholder) }
|
||||||
|
Icon(
|
||||||
|
imageVector = bgIcon,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.focusable(enabled = false)
|
||||||
|
.size(36.dp)
|
||||||
|
.align(Alignment.Center),
|
||||||
|
tint = MaterialTheme.colorScheme.background
|
||||||
|
)
|
||||||
|
|
||||||
val gradient = Brush.verticalGradient(
|
val gradient = Brush.verticalGradient(
|
||||||
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.7f)),
|
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.7f)),
|
||||||
startY = sizeImage.height.toFloat() / 3f,
|
startY = sizeImage.height.toFloat() / 3f,
|
||||||
endY = sizeImage.height.toFloat()
|
endY = sizeImage.height.toFloat()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (url != null) {
|
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(width = width)
|
.width(width = width)
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.clip(RoundedCornerShape(5.dp))
|
.clip(RoundedCornerShape(5.dp))
|
||||||
.onGloballyPositioned { sizeImage = it.size },
|
.onGloballyPositioned { sizeImage = it.size },
|
||||||
onError = { Log.d("Poster", "Error loading: $url") },
|
onError = {
|
||||||
error = rememberAsyncImagePainter(model = noDataImage),
|
if (url != null) {
|
||||||
model = url,
|
bgIcon = Icons.Filled.BrokenImage
|
||||||
placeholder = rememberAsyncImagePainter(model = placeholder),
|
Log.d("Poster", "Error loading: $url")
|
||||||
contentDescription = title,
|
|
||||||
contentScale = ContentScale.FillWidth
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Image(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(width = width)
|
|
||||||
.height(height = POSTER_HEIGHT)
|
|
||||||
.clip(RoundedCornerShape(5.dp))
|
|
||||||
.onGloballyPositioned { sizeImage = it.size },
|
|
||||||
painter = rememberAsyncImagePainter(model = noDataImage),
|
|
||||||
contentDescription = title,
|
|
||||||
contentScale = ContentScale.FillBounds
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
model = url,
|
||||||
|
contentDescription = title,
|
||||||
|
contentScale = ContentScale.FillWidth,
|
||||||
|
onSuccess = { backgroundColor = Color.Transparent }
|
||||||
|
)
|
||||||
|
|
||||||
val showTitle = overrideShowTitle ?: preferences.showPosterTitles
|
val showTitle = overrideShowTitle ?: preferences.showPosterTitles
|
||||||
if (showTitle) {
|
if (showTitle) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.HomePageService
|
|||||||
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse
|
import com.owenlejeune.tvtime.api.tmdb.api.v3.model.HomePageResponse
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaTabContent
|
import com.owenlejeune.tvtime.ui.screens.main.MediaTabContent
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
import com.owenlejeune.tvtime.ui.screens.main.MediaViewType
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel
|
import com.owenlejeune.tvtime.api.tmdb.viewmodel.MediaTabViewModel
|
||||||
import com.owenlejeune.tvtime.utils.ResourceUtils
|
import com.owenlejeune.tvtime.utils.ResourceUtils
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fun MainNavGraph(
|
|||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>,
|
fab: MutableState<@Composable () -> Unit>,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||||
startDestination: String = BottomNavItem.SortedItems[0].route
|
startDestination: String = BottomNavItem.SortedItems[0].route
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem
|
|||||||
import com.owenlejeune.tvtime.ui.navigation.ListFetchFun
|
import com.owenlejeune.tvtime.ui.navigation.ListFetchFun
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.ScrollableTabs
|
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.ScrollableTabs
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.RecommendedMediaViewModel
|
import com.owenlejeune.tvtime.api.tmdb.viewmodel.RecommendedMediaViewModel
|
||||||
import com.owenlejeune.tvtime.utils.SessionManager
|
import com.owenlejeune.tvtime.utils.SessionManager
|
||||||
import com.owenlejeune.tvtime.utils.TmdbUtils
|
import com.owenlejeune.tvtime.utils.TmdbUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -50,7 +50,7 @@ import kotlin.reflect.KClass
|
|||||||
@Composable
|
@Composable
|
||||||
fun AccountTab(
|
fun AccountTab(
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
appBarActions: MutableState<@Composable (RowScope.() -> Unit)> = mutableStateOf({}),
|
||||||
doSignInPartTwo: Boolean = false
|
doSignInPartTwo: Boolean = false
|
||||||
) {
|
) {
|
||||||
@@ -60,7 +60,7 @@ fun AccountTab(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
if (currentSession?.isAuthorized == false) {
|
if (currentSession?.isAuthorized == false) {
|
||||||
appBarTitle.value = stringResource(id = R.string.account_not_logged_in)
|
appBarTitle.value = { Text(text = stringResource(id = R.string.account_not_logged_in)) }
|
||||||
if (doSignInPartTwo) {
|
if (doSignInPartTwo) {
|
||||||
AccountLoadingView()
|
AccountLoadingView()
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -72,13 +72,9 @@ fun AccountTab(
|
|||||||
} else {
|
} else {
|
||||||
if (currentSession?.isAuthorized == true) {
|
if (currentSession?.isAuthorized == true) {
|
||||||
val accountDetails = remember { currentSession.accountDetails }
|
val accountDetails = remember { currentSession.accountDetails }
|
||||||
appBarTitle.value =
|
appBarTitle.value = { Text(text = stringResource(id = R.string.account_header_title_formatted, getAccountName(accountDetails.value))) }
|
||||||
stringResource(
|
|
||||||
id = R.string.account_header_title_formatted,
|
|
||||||
getAccountName(accountDetails.value)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
appBarTitle.value = stringResource(id = R.string.account_not_logged_in)
|
appBarTitle.value = { Text(text = stringResource(id = R.string.account_not_logged_in)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
appBarActions.value = {
|
appBarActions.value = {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.compose.foundation.shape.CircleShape
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
|
import androidx.compose.material.icons.filled.Movie
|
||||||
import androidx.compose.material.icons.filled.Send
|
import androidx.compose.material.icons.filled.Send
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@@ -849,7 +850,6 @@ private fun CastCrewCard(appNavController: NavController, person: Person) {
|
|||||||
else -> null
|
else -> null
|
||||||
},
|
},
|
||||||
imageUrl = TmdbUtils.getFullPersonImagePath(person),
|
imageUrl = TmdbUtils.getFullPersonImagePath(person),
|
||||||
noDataImage = R.drawable.no_person_photo,
|
|
||||||
titleTextColor = MaterialTheme.colorScheme.onPrimary,
|
titleTextColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
subtitleTextColor = MaterialTheme.colorScheme.onSecondary,
|
subtitleTextColor = MaterialTheme.colorScheme.onSecondary,
|
||||||
onItemClicked = {
|
onItemClicked = {
|
||||||
@@ -899,7 +899,8 @@ fun SimilarContentCard(
|
|||||||
appNavController.navigate(
|
appNavController.navigate(
|
||||||
"${MainNavItem.DetailView.route}/${mediaType}/${content.id}"
|
"${MainNavItem.DetailView.route}/${mediaType}/${content.id}"
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
placeholder = Icons.Filled.Movie
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens.main
|
package com.owenlejeune.tvtime.ui.screens.main
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -17,25 +18,26 @@ import com.owenlejeune.tvtime.ui.components.SearchView
|
|||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MediaTabNavItem
|
||||||
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
import com.owenlejeune.tvtime.ui.screens.main.tabs.top.Tabs
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.MediaTabViewModel
|
import com.owenlejeune.tvtime.api.tmdb.viewmodel.MediaTabViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalPagerApi::class)
|
@OptIn(ExperimentalPagerApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MediaTab(
|
fun MediaTab(
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
mediaType: MediaViewType,
|
mediaType: MediaViewType,
|
||||||
fab: MutableState<@Composable () -> Unit>
|
fab: MutableState<@Composable () -> Unit>
|
||||||
) {
|
) {
|
||||||
appBarTitle.value = when (mediaType) {
|
val titleText = when (mediaType) {
|
||||||
MediaViewType.MOVIE -> stringResource(id = R.string.nav_movies_title)
|
MediaViewType.MOVIE -> stringResource(id = R.string.nav_movies_title)
|
||||||
MediaViewType.TV -> stringResource(id = R.string.nav_tv_title)
|
MediaViewType.TV -> stringResource(id = R.string.nav_tv_title)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
|
appBarTitle.value = @Composable { Text(text = titleText) }
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
SearchView(
|
SearchView(
|
||||||
title = appBarTitle.value,
|
title = titleText,
|
||||||
appNavController = appNavController,
|
appNavController = appNavController,
|
||||||
mediaType = mediaType,
|
mediaType = mediaType,
|
||||||
fab = fab
|
fab = fab
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fun PersonDetailView(
|
|||||||
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
|
||||||
val topAppBarScrollState = rememberTopAppBarScrollState()
|
val topAppBarScrollState = rememberTopAppBarScrollState()
|
||||||
val scrollBehaviour = remember(decayAnimationSpec) {
|
val scrollBehaviour = remember(decayAnimationSpec) {
|
||||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec, topAppBarScrollState)
|
TopAppBarDefaults.pinnedScrollBehavior(topAppBarScrollState)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -58,7 +58,7 @@ fun PersonDetailView(
|
|||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
scrollBehavior = scrollBehaviour,
|
scrollBehavior = scrollBehaviour,
|
||||||
colors = TopAppBarDefaults
|
colors = TopAppBarDefaults
|
||||||
.largeTopAppBarColors(
|
.smallTopAppBarColors(
|
||||||
scrolledContainerColor = MaterialTheme.colorScheme.background,
|
scrolledContainerColor = MaterialTheme.colorScheme.background,
|
||||||
titleContentColor = MaterialTheme.colorScheme.primary
|
titleContentColor = MaterialTheme.colorScheme.primary
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -14,19 +14,20 @@ 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.SearchView
|
import com.owenlejeune.tvtime.ui.components.SearchView
|
||||||
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
import com.owenlejeune.tvtime.ui.navigation.MainNavItem
|
||||||
import com.owenlejeune.tvtime.ui.viewmodel.PeopleTabViewModel
|
import com.owenlejeune.tvtime.api.tmdb.viewmodel.PeopleTabViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PeopleTab(
|
fun PeopleTab(
|
||||||
appBarTitle: MutableState<String>,
|
appBarTitle: MutableState<@Composable () -> Unit>,
|
||||||
appNavController: NavHostController,
|
appNavController: NavHostController,
|
||||||
fab: MutableState<@Composable () -> Unit>
|
fab: MutableState<@Composable () -> Unit>
|
||||||
) {
|
) {
|
||||||
appBarTitle.value = stringResource(id = R.string.nav_people_title)
|
val titleText = stringResource(id = R.string.nav_people_title)
|
||||||
|
appBarTitle.value = { Text(text = titleText) }
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
SearchView(
|
SearchView(
|
||||||
title = appBarTitle.value,
|
title = titleText,
|
||||||
appNavController = appNavController,
|
appNavController = appNavController,
|
||||||
mediaType = MediaViewType.PERSON,
|
mediaType = MediaViewType.PERSON,
|
||||||
fab = fab
|
fab = fab
|
||||||
|
|||||||
5
app/src/main/res/drawable/ic_broken_image.xml
Normal file
5
app/src/main/res/drawable/ic_broken_image.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="@android:color/darker_gray"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M21,5v6.59l-3,-3.01 -4,4.01 -4,-4 -4,4 -3,-3.01L3,5c0,-1.1 0.9,-2 2,-2h14c1.1,0 2,0.9 2,2zM18,11.42l3,3.01L21,19c0,1.1 -0.9,2 -2,2L5,21c-1.1,0 -2,-0.9 -2,-2v-6.58l3,2.99 4,-4 4,4 4,-3.99z"/>
|
||||||
|
</vector>
|
||||||
5
app/src/main/res/drawable/ic_rectangle.xml
Normal file
5
app/src/main/res/drawable/ic_rectangle.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="@android:color/darker_gray"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M2,4h20v16h-20z"/>
|
||||||
|
</vector>
|
||||||
@@ -212,4 +212,5 @@
|
|||||||
<string name="no_recommended_movies">No Recommended Movies</string>
|
<string name="no_recommended_movies">No Recommended Movies</string>
|
||||||
<string name="recommended_tv_title">Recommended TV</string>
|
<string name="recommended_tv_title">Recommended TV</string>
|
||||||
<string name="no_recommended_tv">No Recommended TV</string>
|
<string name="no_recommended_tv">No Recommended TV</string>
|
||||||
|
<string name="no_result_found">No more results found</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user