From 0d09ebb9d337066de02a6a3042435b809618f17c Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 25 Feb 2024 14:08:37 +0100 Subject: [PATCH] Add local release date for movie Select release date region in app settings. Add region flag next to local release date in movie details. If the local date is identical to the original release, both flags are displayed. If the local date is different, both dates are displayed, each with its flag. If no local date exists, this does not change the current app. Update release date when region change. handle when no date use TMDB for more accurate dates poster from selected region FIX: merge --- .../database/migrations/Migrations.kt | 97 +++++++++-------- .../data_local/database/model/Movie.kt | 4 +- .../data_remote/tmdb/TmdbRemoteDataSource.kt | 3 + .../data_remote/tmdb/api/TmdbApi.kt | 3 + .../data_remote/tmdb/api/TmdbService.kt | 8 +- .../data_remote/tmdb/model/ReleaseDate.kt | 7 ++ .../data_remote/tmdb/model/ReleaseInfos.kt | 6 + .../data_remote/tmdb/model/Releases.kt | 6 + .../repository/mappers/MovieMapper.kt | 103 ++++++++++-------- .../movies/MovieDetailsRepository.kt | 25 ++++- .../java/com/michaldrabik/ui_model/Movie.kt | 8 +- .../ui_movie/MovieDetailsFragment.kt | 52 ++++++--- ui-movie/src/main/res/values/strings.xml | 5 +- .../src/main/res/values-fr/strings.xml | 2 +- ui-settings/src/main/res/values/strings.xml | 2 +- .../ui_show/ShowDetailsFragment.kt | 17 +-- 16 files changed, 222 insertions(+), 126 deletions(-) create mode 100644 data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseDate.kt create mode 100644 data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseInfos.kt create mode 100644 data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/Releases.kt diff --git a/data-local/src/main/java/com/michaldrabik/data_local/database/migrations/Migrations.kt b/data-local/src/main/java/com/michaldrabik/data_local/database/migrations/Migrations.kt index 6ce3dbe8cc..67148755e1 100644 --- a/data-local/src/main/java/com/michaldrabik/data_local/database/migrations/Migrations.kt +++ b/data-local/src/main/java/com/michaldrabik/data_local/database/migrations/Migrations.kt @@ -5,7 +5,7 @@ import android.content.Context.MODE_PRIVATE import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase -const val DATABASE_VERSION = 41 +const val DATABASE_VERSION = 42 const val DATABASE_NAME = "SHOWLY2_DB_2" class Migrations( @@ -778,47 +778,56 @@ class Migrations( } } - fun getAll() = - listOf( - migration2, - migration3, - migration4, - migration5, - migration6, - migration7, - migration8, - migration9, - migration10, - migration11, - migration12, - migration13, - migration14, - migration15, - migration16, - migration17, - migration18, - migration19, - migration20, - migration21, - migration22, - migration23, - migration24, - migration25, - migration26, - migration27, - migration28, - migration29, - migration30, - migration31, - migration32, - migration33, - migration34, - migration35, - migration36, - migration37, - migration38, - migration39, - migration40, - migration41, - ) + private val migration42 = object : Migration(41, 42) { + override fun migrate(database: SupportSQLiteDatabase) { + with(database) { + execSQL("ALTER TABLE movies ADD COLUMN original_release TEXT NOT NULL DEFAULT ''") + execSQL("ALTER TABLE movies ADD COLUMN current_country TEXT NOT NULL DEFAULT ''") + } + } + } + + fun getAll() = listOf( + migration2, + migration3, + migration4, + migration5, + migration6, + migration7, + migration8, + migration9, + migration10, + migration11, + migration12, + migration13, + migration14, + migration15, + migration16, + migration17, + migration18, + migration19, + migration20, + migration21, + migration22, + migration23, + migration24, + migration25, + migration26, + migration27, + migration28, + migration29, + migration30, + migration31, + migration32, + migration33, + migration34, + migration35, + migration36, + migration37, + migration38, + migration39, + migration40, + migration41, + migration42 + ) } diff --git a/data-local/src/main/java/com/michaldrabik/data_local/database/model/Movie.kt b/data-local/src/main/java/com/michaldrabik/data_local/database/model/Movie.kt index 0d3e767149..2e003d1aec 100644 --- a/data-local/src/main/java/com/michaldrabik/data_local/database/model/Movie.kt +++ b/data-local/src/main/java/com/michaldrabik/data_local/database/model/Movie.kt @@ -13,9 +13,11 @@ data class Movie( @ColumnInfo(name = "title", defaultValue = "") val title: String, @ColumnInfo(name = "year", defaultValue = "-1") val year: Int, @ColumnInfo(name = "overview", defaultValue = "") val overview: String, - @ColumnInfo(name = "released", defaultValue = "") val released: String, + @ColumnInfo(name = "released", defaultValue = "") var released: String, + @ColumnInfo(name = "original_release", defaultValue = "") val originalRelease: String, @ColumnInfo(name = "runtime", defaultValue = "-1") val runtime: Int, @ColumnInfo(name = "country", defaultValue = "") val country: String, + @ColumnInfo(name = "current_country", defaultValue = "") val currentCountry: String, @ColumnInfo(name = "trailer", defaultValue = "") val trailer: String, @ColumnInfo(name = "language", defaultValue = "") val language: String, @ColumnInfo(name = "homepage", defaultValue = "") val homepage: String, diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/TmdbRemoteDataSource.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/TmdbRemoteDataSource.kt index 186b2c3f77..ca65129f73 100644 --- a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/TmdbRemoteDataSource.kt +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/TmdbRemoteDataSource.kt @@ -1,5 +1,6 @@ package com.michaldrabik.data_remote.tmdb +import com.michaldrabik.data_remote.tmdb.model.Releases import com.michaldrabik.data_remote.tmdb.model.TmdbImage import com.michaldrabik.data_remote.tmdb.model.TmdbImages import com.michaldrabik.data_remote.tmdb.model.TmdbPerson @@ -40,4 +41,6 @@ interface TmdbRemoteDataSource { suspend fun fetchPersonTranslations(id: Long): Map suspend fun fetchPersonImages(tmdbId: Long): TmdbImages + + suspend fun fetchMovieRelease(tmdbId: Long): Releases } diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbApi.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbApi.kt index cdf9dc7f3e..59765eb933 100644 --- a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbApi.kt +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbApi.kt @@ -105,4 +105,7 @@ internal class TmdbApi( } catch (error: Throwable) { TmdbImages.EMPTY } + + override suspend fun fetchMovieRelease(imdbId: Long) = + service.fetchMovieRelease(imdbId) } diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbService.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbService.kt index c635483c75..9210e3992c 100644 --- a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbService.kt +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/api/TmdbService.kt @@ -1,5 +1,6 @@ package com.michaldrabik.data_remote.tmdb.api +import com.michaldrabik.data_remote.tmdb.model.Releases import com.michaldrabik.data_remote.tmdb.model.TmdbImages import com.michaldrabik.data_remote.tmdb.model.TmdbPeople import com.michaldrabik.data_remote.tmdb.model.TmdbPerson @@ -58,7 +59,8 @@ interface TmdbService { ): TmdbStreamings @GET("tv/{tmdbId}/watch/providers") - suspend fun fetchShowWatchProviders( - @Path("tmdbId") tmdbId: Long, - ): TmdbStreamings + suspend fun fetchShowWatchProviders(@Path("tmdbId") tmdbId: Long): TmdbStreamings + + @GET("movie/{tmdbId}/release_dates") + suspend fun fetchMovieRelease(@Path("tmdbId") tmdbId: Long): Releases } diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseDate.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseDate.kt new file mode 100644 index 0000000000..aeb8ea1085 --- /dev/null +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseDate.kt @@ -0,0 +1,7 @@ +package com.michaldrabik.data_remote.tmdb.model + +data class ReleaseDate( + val note: String, + val release_date: Any, + val type: Int +) diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseInfos.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseInfos.kt new file mode 100644 index 0000000000..62304f9857 --- /dev/null +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/ReleaseInfos.kt @@ -0,0 +1,6 @@ +package com.michaldrabik.data_remote.tmdb.model + +data class ReleaseInfo( + val iso_3166_1: String, + val release_dates: List +) diff --git a/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/Releases.kt b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/Releases.kt new file mode 100644 index 0000000000..7f9eb8f261 --- /dev/null +++ b/data-remote/src/main/java/com/michaldrabik/data_remote/tmdb/model/Releases.kt @@ -0,0 +1,6 @@ +package com.michaldrabik.data_remote.tmdb.model + +data class Releases( + val id: Long, + val results: List +) diff --git a/repository/src/main/java/com/michaldrabik/repository/mappers/MovieMapper.kt b/repository/src/main/java/com/michaldrabik/repository/mappers/MovieMapper.kt index 3837672ef5..75e599597c 100644 --- a/repository/src/main/java/com/michaldrabik/repository/mappers/MovieMapper.kt +++ b/repository/src/main/java/com/michaldrabik/repository/mappers/MovieMapper.kt @@ -12,15 +12,19 @@ class MovieMapper @Inject constructor( private val idsMapper: IdsMapper, ) { - fun fromNetwork(movie: MovieNetwork) = - Movie( + fun fromNetwork(movie: MovieNetwork): Movie { + val released: LocalDate? = movie.released?.let { if (it.isNotBlank()) LocalDate.parse(it) else null } + + return Movie( idsMapper.fromNetwork(movie.ids), movie.title ?: "", movie.year ?: -1, movie.overview ?: "", - movie.released?.let { if (it.isNotBlank()) LocalDate.parse(it) else null }, + released, + released, movie.runtime ?: -1, movie.country ?: "", + movie.country, movie.trailer ?: "", movie.homepage ?: "", movie.language ?: "", @@ -30,8 +34,9 @@ class MovieMapper @Inject constructor( movie.comment_count ?: -1, movie.genres ?: emptyList(), nowUtcMillis(), - nowUtcMillis(), + nowUtcMillis() ) + } fun toNetwork(movie: Movie) = MovieNetwork( @@ -52,48 +57,50 @@ class MovieMapper @Inject constructor( movie.language, ) - fun fromDatabase(movie: MovieDb) = - Movie( - idsMapper.fromDatabase(movie), - movie.title, - movie.year, - movie.overview, - if (movie.released.isBlank()) null else LocalDate.parse(movie.released), - movie.runtime, - movie.country, - movie.trailer, - movie.homepage, - movie.language, - MovieStatus.fromKey(movie.status), - movie.rating, - movie.votes, - movie.commentCount, - movie.genres.split(","), - movie.updatedAt, - movie.createdAt, - ) + fun fromDatabase(movie: MovieDb) = Movie( + idsMapper.fromDatabase(movie), + movie.title, + movie.year, + movie.overview, + movie.released.let { if (it.isNotBlank()) LocalDate.parse(it) else null }, + movie.originalRelease.let { if (it.isNotBlank()) LocalDate.parse(it) else null }, + movie.runtime, + movie.country, + movie.currentCountry.let { it.ifBlank { null } }, + movie.trailer, + movie.homepage, + movie.language, + MovieStatus.fromKey(movie.status), + movie.rating, + movie.votes, + movie.commentCount, + movie.genres.split(","), + movie.updatedAt, + movie.createdAt + ) - fun toDatabase(movie: Movie) = - MovieDb( - movie.ids.trakt.id, - movie.ids.tmdb.id, - movie.ids.imdb.id, - movie.ids.slug.id, - movie.title, - movie.year, - movie.overview, - movie.released?.toString() ?: "", - movie.runtime, - movie.country, - movie.trailer, - movie.language, - movie.homepage, - movie.status.key, - movie.rating, - movie.votes, - movie.commentCount, - movie.genres.joinToString(","), - nowUtcMillis(), - movie.createdAt, - ) -} + fun toDatabase(movie: Movie) = MovieDb( + movie.ids.trakt.id, + movie.ids.tmdb.id, + movie.ids.imdb.id, + movie.ids.slug.id, + movie.title, + movie.year, + movie.overview, + movie.released?.toString() ?: "", + movie.originalRelease?.toString() ?: "", + movie.runtime, + movie.country, + movie.currentCountry ?: "", + movie.trailer, + movie.language, + movie.homepage, + movie.status.key, + movie.rating, + movie.votes, + movie.commentCount, + movie.genres.joinToString(","), + nowUtcMillis(), + movie.createdAt + ) +} \ No newline at end of file diff --git a/repository/src/main/java/com/michaldrabik/repository/movies/MovieDetailsRepository.kt b/repository/src/main/java/com/michaldrabik/repository/movies/MovieDetailsRepository.kt index 16188cee34..323537d099 100644 --- a/repository/src/main/java/com/michaldrabik/repository/movies/MovieDetailsRepository.kt +++ b/repository/src/main/java/com/michaldrabik/repository/movies/MovieDetailsRepository.kt @@ -5,18 +5,23 @@ import com.michaldrabik.common.extensions.nowUtcMillis import com.michaldrabik.data_local.LocalDataSource import com.michaldrabik.data_local.database.model.MoviesSyncLog import com.michaldrabik.data_remote.RemoteDataSource +import com.michaldrabik.data_remote.tmdb.model.Releases import com.michaldrabik.repository.mappers.Mappers +import com.michaldrabik.repository.settings.SettingsRepository import com.michaldrabik.ui_model.IdImdb import com.michaldrabik.ui_model.IdSlug import com.michaldrabik.ui_model.IdTmdb import com.michaldrabik.ui_model.IdTrakt import com.michaldrabik.ui_model.Movie +import java.time.LocalDate +import java.time.format.DateTimeFormatter import javax.inject.Inject class MovieDetailsRepository @Inject constructor( private val remoteSource: RemoteDataSource, private val localSource: LocalDataSource, private val mappers: Mappers, + private val settingsRepository: SettingsRepository ) { suspend fun load( @@ -24,9 +29,19 @@ class MovieDetailsRepository @Inject constructor( force: Boolean = false, ): Movie { val local = localSource.movies.getById(idTrakt.id) - if (force || local == null || nowUtcMillis() - local.updatedAt > Config.MOVIE_DETAILS_CACHE_DURATION) { + if (force + || local == null + || (local.currentCountry != settingsRepository.country) + || nowUtcMillis() - local.updatedAt > Config.MOVIE_DETAILS_CACHE_DURATION) { val remote = remoteSource.trakt.fetchMovie(idTrakt.id) val movie = mappers.movie.fromNetwork(remote) + val releases: Releases = remoteSource.tmdb.fetchMovieRelease(movie.ids.tmdb.id) + val localRelease = getLocalReleaseDate(releases) + if (localRelease != null) { + movie.released = localRelease + movie.year = localRelease.year + movie.currentCountry = settingsRepository.country + } else { movie.currentCountry = null } localSource.movies.upsert(listOf(mappers.movie.toDatabase(movie))) localSource.moviesSyncLog.upsert(MoviesSyncLog(movie.traktId, nowUtcMillis())) return movie @@ -34,6 +49,14 @@ class MovieDetailsRepository @Inject constructor( return mappers.movie.fromDatabase(local) } + private fun getLocalReleaseDate(releaseInfos: Releases): LocalDate? { + val countryCode = settingsRepository.country.uppercase() + val localReleases = releaseInfos.results.find { it.iso_3166_1 == countryCode } + val localRelease = localReleases?.release_dates?.find { it.type > 2 } + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + return localRelease?.release_date?.let { LocalDate.parse(it.toString(), formatter) } + } + suspend fun find(idImdb: IdImdb): Movie? { val localMovie = localSource.movies.getById(idImdb.id) if (localMovie != null) { diff --git a/ui-model/src/main/java/com/michaldrabik/ui_model/Movie.kt b/ui-model/src/main/java/com/michaldrabik/ui_model/Movie.kt index 77e0da23e4..c56eb26e39 100644 --- a/ui-model/src/main/java/com/michaldrabik/ui_model/Movie.kt +++ b/ui-model/src/main/java/com/michaldrabik/ui_model/Movie.kt @@ -6,11 +6,13 @@ import java.time.LocalDate data class Movie( val ids: Ids, val title: String, - val year: Int, + var year: Int, val overview: String, - val released: LocalDate?, + var released: LocalDate?, + val originalRelease: LocalDate?, val runtime: Int, val country: String, + var currentCountry: String?, val trailer: String, val homepage: String, val language: String, @@ -48,8 +50,10 @@ data class Movie( -1, "", null, + null, -1, "", + null, "", "", "", diff --git a/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsFragment.kt b/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsFragment.kt index 1fe8828cfc..f3f16b3d32 100644 --- a/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsFragment.kt +++ b/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsFragment.kt @@ -88,7 +88,9 @@ import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_TYPE import com.michaldrabik.ui_navigation.java.NavigationArgs.REQUEST_MANAGE_LISTS import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber +import java.time.LocalDate import java.time.ZoneOffset.UTC +import java.time.format.DateTimeFormatter import java.util.Locale.ENGLISH import java.util.Locale.ROOT @@ -184,6 +186,20 @@ class MovieDetailsFragment : BaseFragment(R.layout.fragme } } + private fun formatDate(date: LocalDate?, format: DateTimeFormatter?, year: Int): String { + return when { + date != null -> String.format(ENGLISH, "%s", format?.format(date)?.capitalizeWords()) + year > 0 -> year.toString() + else -> "" + } + } + + private fun getFlagEmoji(countryCode: String?): String { + if (countryCode == null || countryCode.length != 2) return "" + val codePoints = countryCode.uppercase(ROOT).map { 127397 + it.code } + return String(codePoints.toIntArray(), 0, codePoints.size) + } + private fun render(uiState: MovieDetailsUiState) { uiState.run { with(binding) { @@ -291,29 +307,31 @@ class MovieDetailsFragment : BaseFragment(R.layout.fragme } } - private fun renderExtraInfo( - movie: Movie, - meta: MovieDetailsMeta?, - ) { - val country = if (movie.country.isNotBlank()) String.format(ENGLISH, "(%s)", movie.country) else "" - val releaseDate = when { - movie.released != null -> String.format( - ENGLISH, - "%s", - meta?.dateFormat?.format(movie.released)?.capitalizeWords(), - ) - movie.year > 0 -> movie.year.toString() - else -> "" - } + private fun renderExtraInfo(movie: Movie, meta: MovieDetailsMeta?) { val genres = movie.genres .take(5) .mapNotNull { Genre.fromSlug(it) } .joinToString(", ") { getString(it.displayName) } + val releaseDate = formatDate(movie.released, meta?.dateFormat, movie.year) + val originalRelease = formatDate(movie.originalRelease, meta?.dateFormat, movie.year) + + val country = if (movie.country.isNotBlank()) getFlagEmoji(movie.country) else "" + val currentCountry = if (movie.currentCountry?.isNotBlank() == true) getFlagEmoji(movie.currentCountry) else "" + + val releaseDateText: String = when { + movie.released == movie.originalRelease && movie.country != movie.currentCountry && movie.currentCountry != null -> + getString(R.string.textMovieReleaseDateSame, originalRelease, country, currentCountry) + movie.released != movie.originalRelease && movie.released != null -> + getString(R.string.textMovieReleaseDateMulti, releaseDate, currentCountry, originalRelease, country) + (movie.country == movie.currentCountry || movie.currentCountry == null) && movie.originalRelease != null -> + getString(R.string.textMovieReleaseDate, originalRelease, country) + else -> "" + } + var extraInfoText = getString( R.string.textMovieExtraInfo, - releaseDate, - country.uppercase(ROOT), + releaseDateText, "⏲ ${movie.runtime}", getString(R.string.textMinutesShort), genres, @@ -494,4 +512,4 @@ class MovieDetailsFragment : BaseFragment(R.layout.fragme animation.applyTo(movieDetailsMainContent) } } -} +} \ No newline at end of file diff --git a/ui-movie/src/main/res/values/strings.xml b/ui-movie/src/main/res/values/strings.xml index 655472d98f..feb5b30546 100644 --- a/ui-movie/src/main/res/values/strings.xml +++ b/ui-movie/src/main/res/values/strings.xml @@ -11,7 +11,10 @@ You may also like Collections - %s %s | %s %s | %s + %s %s |\u00A0 + %s %s/%s |\u00A0 + %s %s, %s %s |\u00A0 + %s%s %s | %s Manage Lists Manage Lists (%d) diff --git a/ui-settings/src/main/res/values-fr/strings.xml b/ui-settings/src/main/res/values-fr/strings.xml index d6deded4b5..42b3c3593d 100644 --- a/ui-settings/src/main/res/values-fr/strings.xml +++ b/ui-settings/src/main/res/values-fr/strings.xml @@ -30,7 +30,7 @@ Fond Définir le niveau de transparence du fond des widgets. Région - Sélectionnez la région à utiliser avec les données des services de streaming. + Sélectionnez la région à utiliser avec les données des services de streaming et les dates de sortie des films. Langue Les titres et descriptions seront traduits quand ils seront disponibles. L\'application va redémarrer. Format date / heure diff --git a/ui-settings/src/main/res/values/strings.xml b/ui-settings/src/main/res/values/strings.xml index 6a62629fd5..a0dc9f884b 100644 --- a/ui-settings/src/main/res/values/strings.xml +++ b/ui-settings/src/main/res/values/strings.xml @@ -31,7 +31,7 @@ Background Set level of widgets background transparency. Region - Select region to use with streaming services data. + Select region to use with streaming services data and movie release dates. Language Descriptions and titles will be translated when available. App will restart. Date / Time Format diff --git a/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsFragment.kt b/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsFragment.kt index 7bc8955db9..2fa4a7d002 100644 --- a/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsFragment.kt +++ b/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsFragment.kt @@ -81,6 +81,7 @@ import com.michaldrabik.ui_show.views.AddToShowsButton import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber import java.util.Locale.ENGLISH +import java.util.Locale.ROOT @SuppressLint("SetTextI18n", "DefaultLocale", "SourceLockedOrientationActivity") @AndroidEntryPoint @@ -188,6 +189,12 @@ class ShowDetailsFragment : BaseFragment(R.layout.fragment } } + private fun getFlagEmoji(countryCode: String?): String { + if (countryCode == null || countryCode.length != 2) return "" + val codePoints = countryCode.uppercase(ROOT).map { 127397 + it.code } + return String(codePoints.toIntArray(), 0, codePoints.size) + } + private fun render(uiState: ShowDetailsUiState) { uiState.run { with(binding) { @@ -295,26 +302,22 @@ class ShowDetailsFragment : BaseFragment(R.layout.fragment private fun renderExtraInfo(show: Show) { val year = if (show.year > 0) String.format(ENGLISH, "%d", show.year) else "" - val country = if (show.country.isNotBlank()) String.format(ENGLISH, "(%s)", show.country) else "" + val country = if (show.country.isNotBlank()) String.format(ENGLISH, "%s", getFlagEmoji(show.country)) else "" val genres = show.genres .take(5) .mapNotNull { Genre.fromSlug(it) } .joinToString(", ") { getString(it.displayName) } - var extraInfoText = getString( + val extraInfoText = getString( R.string.textShowExtraInfo, show.network, year, - country.uppercase(), + country, "⏲ ${show.runtime}", getString(R.string.textMinutesShort), genres, ) - if (genres.isEmpty()) { - extraInfoText = extraInfoText.trim().removeSuffix("|") - } - binding.showDetailsExtraInfo.text = extraInfoText }