From 862dfb2341d50df0fdcc7640a1d5e6860439c2cc Mon Sep 17 00:00:00 2001 From: Owen LeJeune Date: Fri, 14 Jul 2023 00:25:52 -0400 Subject: [PATCH] some small ui fixes --- .../api/tmdb/api/v3/model/DetailPerson.kt | 3 +++ .../tvtime/ui/components/Buttons.kt | 4 ++-- .../tvtime/ui/screens/CastCrewListScreen.kt | 2 +- .../tvtime/ui/screens/GalleryScreen.kt | 3 ++- .../tvtime/ui/screens/KnownForScreen.kt | 15 ++++++++---- .../tvtime/ui/screens/MediaDetailScreen.kt | 2 +- .../tvtime/ui/screens/PeopleDetailScreen.kt | 24 +++++++++---------- .../tvtime/ui/screens/SeasonListScreen.kt | 15 ++++++++---- .../tvtime/ui/screens/SettingsScreen.kt | 9 +++++-- .../ui/viewmodel/ApplicationViewModel.kt | 11 +++++---- app/src/main/res/values/strings.xml | 5 +++- 11 files changed, 61 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/DetailPerson.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/DetailPerson.kt index 7996487..bd03f84 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/DetailPerson.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/model/DetailPerson.kt @@ -10,6 +10,9 @@ class DetailPerson( @SerializedName("biography") val biography: String, @SerializedName("place_of_birth") val birthplace: String?, @SerializedName("adult") val isAdult: Boolean, + @SerializedName("also_known_as") val alsoKnownAs: List, + @SerializedName("homepage") val homepage: String?, + @SerializedName("popularity") val popularity: Float, id: Int, name: String, gender: Gender, diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Buttons.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Buttons.kt index e1dda3f..e476eed 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/components/Buttons.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/components/Buttons.kt @@ -35,11 +35,11 @@ fun StoreRouteButton() { modifier = Modifier .combinedClickable( onClick = { - applicationViewModel.storedRoute.value = applicationViewModel.currentRoute.value + applicationViewModel.setStoredRoute(applicationViewModel.currentRoute.value) Toast.makeText(context, "Stored route \"${applicationViewModel.storedRoute.value}\"", Toast.LENGTH_SHORT).show() }, onLongClick = { - applicationViewModel.storedRoute.value = "" + applicationViewModel.setStoredRoute("") Toast.makeText(context, "Stored route \"\"", Toast.LENGTH_SHORT).show() } ) diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/CastCrewListScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/CastCrewListScreen.kt index 96d0e53..9d48ea5 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/CastCrewListScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/CastCrewListScreen.kt @@ -104,7 +104,7 @@ fun CastCrewListScreen( MediaResultCard( appNavController = appNavController, - mediaViewType = type, + mediaViewType = MediaViewType.PERSON, id = item.id, backdropPath = null, posterPath = TmdbUtils.getFullPosterPath(item.profilePath), diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/GalleryScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/GalleryScreen.kt index 5992029..c5285d0 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/GalleryScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/GalleryScreen.kt @@ -95,7 +95,8 @@ private fun PersonGalleryView( width = 120.dp, url = TmdbUtils.getFullPersonImagePath(image.filePath), placeholder = Icons.Filled.Person, - title = "" + title = "", + modifier = Modifier.padding(5.dp) ) } } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/KnownForScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/KnownForScreen.kt index e487ebe..9fa9637 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/KnownForScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/KnownForScreen.kt @@ -13,6 +13,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -29,6 +30,7 @@ import com.owenlejeune.tvtime.api.tmdb.api.v3.model.MovieCast import com.owenlejeune.tvtime.api.tmdb.api.v3.model.TvCast import com.owenlejeune.tvtime.extensions.bringToFront import com.owenlejeune.tvtime.extensions.getCalendarYear +import com.owenlejeune.tvtime.extensions.unlessEmpty import com.owenlejeune.tvtime.ui.components.BackButton import com.owenlejeune.tvtime.ui.components.MediaResultCard import com.owenlejeune.tvtime.ui.components.PillSegmentedControl @@ -36,6 +38,7 @@ import com.owenlejeune.tvtime.ui.components.TVTTopAppBar import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.utils.TmdbUtils +import com.owenlejeune.tvtime.utils.types.MediaViewType @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -46,6 +49,10 @@ fun KnownForScreen( val mainViewModel = viewModel() val applicationViewModel = viewModel() + LaunchedEffect(Unit) { + mainViewModel.getCastAndCrew(id, MediaViewType.PERSON) + } + applicationViewModel.statusBarColor.value = MaterialTheme.colorScheme.background applicationViewModel.navigationBarColor.value = MaterialTheme.colorScheme.background @@ -83,7 +90,7 @@ fun KnownForScreen( ) { item { Row( - modifier = Modifier.padding(start = 16.dp, top = 12.dp, bottom = 12.dp), + modifier = Modifier.padding(start = 16.dp, top = 12.dp, end = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { val labels = listOf(stringResource(id = R.string.actor_label), stringResource(id = R.string.production_label)) @@ -98,12 +105,12 @@ fun KnownForScreen( items(items) { item -> val additionalDetails = emptyList().toMutableList() when (item) { - is MovieCast -> additionalDetails.add(stringResource(id = R.string.cast_character_template, item.character)) - is TvCast -> additionalDetails.add(stringResource(id = R.string.cast_tv_character_template, item.character, item.episodeCount)) + is MovieCast -> additionalDetails.add(stringResource(id = R.string.cast_character_template, item.character.unlessEmpty("-"))) + is TvCast -> additionalDetails.add(stringResource(id = R.string.cast_tv_character_template, item.character.unlessEmpty("-"), item.episodeCount)) is DetailCrew -> additionalDetails.add(stringResource(id = R.string.crew_template, item.job)) } - val releaseYear = item.releaseDate?.getCalendarYear() ?: "" + val releaseYear = item.releaseDate?.getCalendarYear() ?: stringResource(id = R.string.tba) MediaResultCard( appNavController = appNavController, diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt index 9375734..5bd1045 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt @@ -729,7 +729,7 @@ private fun CastCard( } Text( - text = "See all cast and crew", + text = stringResource(R.string.see_all_cast_and_crew), fontSize = 12.sp, color = MaterialTheme.colorScheme.inversePrimary, modifier = Modifier diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/PeopleDetailScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/PeopleDetailScreen.kt index cd07bdc..e598f3d 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/PeopleDetailScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/PeopleDetailScreen.kt @@ -56,20 +56,23 @@ import com.owenlejeune.tvtime.ui.viewmodel.ApplicationViewModel import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.types.MediaViewType +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.lang.Integer.min private const val TAG = "PeopleDetailScreen" -private suspend fun fetchData( +private fun fetchData( mainViewModel: MainViewModel, id: Int, force: Boolean = false ) { - mainViewModel.getById(id, MediaViewType.PERSON, force) - mainViewModel.getExternalIds(id, MediaViewType.PERSON, force) - mainViewModel.getCastAndCrew(id, MediaViewType.PERSON, force) - mainViewModel.getImages(id, MediaViewType.PERSON, force) + val scope = CoroutineScope(Dispatchers.IO) + scope.launch { mainViewModel.getById(id, MediaViewType.PERSON, force) } + scope.launch { mainViewModel.getExternalIds(id, MediaViewType.PERSON, force) } + scope.launch { mainViewModel.getCastAndCrew(id, MediaViewType.PERSON, force) } + scope.launch { mainViewModel.getImages(id, MediaViewType.PERSON, force) } } @OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class, ExperimentalMaterialApi::class) @@ -78,8 +81,6 @@ fun PersonDetailScreen( appNavController: NavController, personId: Int ) { - val scope = rememberCoroutineScope() - val mainViewModel = viewModel() LaunchedEffect(Unit) { fetchData(mainViewModel, personId) @@ -100,9 +101,7 @@ fun PersonDetailScreen( val pullRefreshState = rememberPullRefreshState( refreshing = isRefreshing.value, onRefresh = { - scope.launch { - fetchData(mainViewModel, personId, true) - } + fetchData(mainViewModel, personId, true) } ) @@ -191,6 +190,7 @@ private fun CreditsCard( val creditsMap = remember { mainViewModel.peopleCastMap } val credits = creditsMap[personId] ?: emptyList() + val sortedCredits = credits.sortedByDescending { it.popularity } ContentCard( title = stringResource(R.string.known_for_label) @@ -205,8 +205,8 @@ private fun CreditsCard( item { Spacer(modifier = Modifier.width(8.dp)) } - items(min(credits.size, 15)) { i -> - val content = credits[i] + items(min(sortedCredits.size, 15)) { i -> + val content = sortedCredits[i] TwoLineImageTextCard( title = content.title, diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SeasonListScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SeasonListScreen.kt index dde31c4..85a3f83 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SeasonListScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SeasonListScreen.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -109,19 +110,21 @@ fun SeasonListScreen( .verticalScroll(state = rememberScrollState()) ) { val seasonsMap = remember { mainViewModel.tvSeasons } - val seasons = seasonsMap[id] ?: emptyList() + val seasons = seasonsMap[id] ?: emptySet() seasons.sortedBy { it.seasonNumber }.forEach { season -> - SeasonSection(season = season) + SeasonSection(season = season, singleSeason = isSingleSeason(seasons)) } + + Spacer(modifier = Modifier.height(6.dp)) } } } } @Composable -private fun SeasonSection(season: Season) { - var isExpanded by remember { mutableStateOf(false) } +private fun SeasonSection(season: Season, singleSeason: Boolean) { + var isExpanded by remember { mutableStateOf(singleSeason) } Row( modifier = Modifier.padding(horizontal = 12.dp), @@ -253,4 +256,8 @@ private fun EpisodeItem(episode: Episode) { } } } +} + +private fun isSingleSeason(seasons: Set): Boolean { + return seasons.size == 1 || (seasons.size == 2 && seasons.any { it.seasonNumber == 0 }) } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt index 914e295..97d91ad 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt @@ -1,5 +1,6 @@ package com.owenlejeune.tvtime.ui.screens +import android.annotation.SuppressLint import android.app.Activity import android.os.Build import android.widget.Toast @@ -43,6 +44,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -82,6 +84,7 @@ import com.owenlejeune.tvtime.ui.views.HomeTabRecyclerAdapter import com.owenlejeune.tvtime.ui.views.ItemMoveCallback import com.owenlejeune.tvtime.utils.SessionManager import kotlinx.coroutines.launch +import org.koin.java.KoinJavaComponent.get @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -436,7 +439,7 @@ fun SpecialFeaturePreferences() { } @Composable -fun DevPreferences() { +fun DevPreferences(preferences: AppPreferences = get(AppPreferences::class.java)) { if (BuildConfig.DEBUG) { val settingsViewModel = viewModel() @@ -525,6 +528,7 @@ fun DevPreferences() { Column { Text(text = "Current stored test route", fontSize = 18.sp) Text(text = currentStoredRoute.value.unlessEmpty("---")) + Text(text = preferences.storedTestRoute.unlessEmpty("--")) } Spacer(modifier = Modifier.weight(1f)) IconButton( @@ -542,6 +546,7 @@ fun DevPreferences() { } } +@SuppressLint("AutoboxingStateValueProperty") @Composable private fun WallpaperPicker( showPopup: MutableState @@ -551,7 +556,7 @@ private fun WallpaperPicker( val settingsViewModel = viewModel() val wallpaperColors = remember { mutableStateOf>(emptyList()) } - val selectedWallpaperColor = remember { mutableStateOf(0) } + val selectedWallpaperColor = remember { mutableIntStateOf(0) } LaunchedEffect(true) { val colors = MonetCompat.getInstance().getAvailableWallpaperColors() ?: emptyList() if (colors.isEmpty()) { diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ApplicationViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ApplicationViewModel.kt index 2131ef4..3c76de9 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ApplicationViewModel.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/ApplicationViewModel.kt @@ -1,5 +1,6 @@ package com.owenlejeune.tvtime.ui.viewmodel +import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.graphics.Color import androidx.lifecycle.ViewModel @@ -11,20 +12,22 @@ class ApplicationViewModel: ViewModel(), KoinComponent { private val preferences: AppPreferences by inject() - private object Backer { + private object Backer: KoinComponent { + private val preferences: AppPreferences by inject() + val statusBarColor = mutableStateOf(Color.Transparent) val navigationBarColor = mutableStateOf(Color.Transparent) val currentRoute = mutableStateOf("") - val storedRoute = mutableStateOf("") + val storedRoute = mutableStateOf(preferences.storedTestRoute) } val statusBarColor = Backer.statusBarColor val navigationBarColor = Backer.navigationBarColor val currentRoute = Backer.currentRoute - val storedRoute = Backer.storedRoute + val storedRoute: State = Backer.storedRoute fun setStoredRoute(route: String) { - storedRoute.value = route + Backer.storedRoute.value = route preferences.storedTestRoute = route } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b41c5c0..eb29be1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -252,5 +252,8 @@ You don\'t have any lists yet %1$s (%2$d items) %1$d days - Next in the MCU... + Next in the MCU… + See all cast and crew + Unreleased + TBA \ No newline at end of file