mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
Merge branch 'NuvioMedia:cmp-rewrite' into cmp-rewrite
This commit is contained in:
commit
7a0cc2c03b
30 changed files with 2742 additions and 130 deletions
|
|
@ -272,7 +272,7 @@ kotlin {
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
dependencies {
|
dependencies {
|
||||||
add("fullImplementation", libs.quickjs.kt)
|
add("fullImplementation", files("libs/quickjs-kt-android-1.0.5-nuvio.aar"))
|
||||||
add("fullImplementation", libs.ksoup)
|
add("fullImplementation", libs.ksoup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
BIN
composeApp/libs/quickjs-kt-android-1.0.5-nuvio.aar
Normal file
BIN
composeApp/libs/quickjs-kt-android-1.0.5-nuvio.aar
Normal file
Binary file not shown.
|
|
@ -18,7 +18,8 @@ actual object ThemeSettingsStorage {
|
||||||
private const val selectedThemeKey = "selected_theme"
|
private const val selectedThemeKey = "selected_theme"
|
||||||
private const val amoledEnabledKey = "amoled_enabled"
|
private const val amoledEnabledKey = "amoled_enabled"
|
||||||
private const val selectedAppLanguageKey = "selected_app_language"
|
private const val selectedAppLanguageKey = "selected_app_language"
|
||||||
private val syncKeys = listOf(selectedThemeKey, amoledEnabledKey, selectedAppLanguageKey)
|
private val profileScopedSyncKeys = listOf(selectedThemeKey, amoledEnabledKey)
|
||||||
|
private val globalSyncKeys = listOf(selectedAppLanguageKey)
|
||||||
|
|
||||||
private var preferences: SharedPreferences? = null
|
private var preferences: SharedPreferences? = null
|
||||||
|
|
||||||
|
|
@ -50,13 +51,18 @@ actual object ThemeSettingsStorage {
|
||||||
?.apply()
|
?.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun loadSelectedAppLanguage(): String? =
|
actual fun loadSelectedAppLanguage(): String? {
|
||||||
preferences?.getString(ProfileScopedKey.of(selectedAppLanguageKey), null)
|
val value = preferences?.getString(selectedAppLanguageKey, null)
|
||||||
|
if (value != null) return value
|
||||||
|
val legacy = preferences?.getString(ProfileScopedKey.of(selectedAppLanguageKey), null)
|
||||||
|
if (legacy != null) saveSelectedAppLanguage(legacy)
|
||||||
|
return legacy
|
||||||
|
}
|
||||||
|
|
||||||
actual fun saveSelectedAppLanguage(languageCode: String) {
|
actual fun saveSelectedAppLanguage(languageCode: String) {
|
||||||
preferences
|
preferences
|
||||||
?.edit()
|
?.edit()
|
||||||
?.putString(ProfileScopedKey.of(selectedAppLanguageKey), languageCode)
|
?.putString(selectedAppLanguageKey, languageCode)
|
||||||
?.apply()
|
?.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +80,8 @@ actual object ThemeSettingsStorage {
|
||||||
|
|
||||||
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
||||||
preferences?.edit()?.apply {
|
preferences?.edit()?.apply {
|
||||||
syncKeys.forEach { remove(ProfileScopedKey.of(it)) }
|
profileScopedSyncKeys.forEach { remove(ProfileScopedKey.of(it)) }
|
||||||
|
globalSyncKeys.forEach { remove(it) }
|
||||||
}?.apply()
|
}?.apply()
|
||||||
|
|
||||||
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<locale android:name="en"/>
|
<locale android:name="en"/>
|
||||||
|
<locale android:name="fr"/>
|
||||||
<locale android:name="es"/>
|
<locale android:name="es"/>
|
||||||
|
<locale android:name="pt-PT"/>
|
||||||
<locale android:name="tr"/>
|
<locale android:name="tr"/>
|
||||||
<locale android:name="it"/>
|
<locale android:name="it"/>
|
||||||
<locale android:name="el"/>
|
<locale android:name="el"/>
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Ποσοστό</string>
|
<string name="settings_playback_threshold_mode_percentage">Ποσοστό</string>
|
||||||
<string name="settings_playback_threshold_percentage">Ποσοστό κατωφλίου</string>
|
<string name="settings_playback_threshold_percentage">Ποσοστό κατωφλίου</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Εμφάνιση κάρτας επόμενου επεισοδίου όταν η αναπαραγωγή φτάσει σε αυτό το ποσοστό.</string>
|
<string name="settings_playback_threshold_percentage_description">Εμφάνιση κάρτας επόμενου επεισοδίου όταν η αναπαραγωγή φτάσει σε αυτό το ποσοστό.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Άμεσα</string>
|
<string name="settings_playback_timeout_instant">Άμεσα</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Απεριόριστο</string>
|
<string name="settings_playback_timeout_unlimited">Απεριόριστο</string>
|
||||||
|
|
@ -774,7 +774,7 @@
|
||||||
<string name="episode_mark_unwatched">Σήμανση ως μη παρακολουθηθέν</string>
|
<string name="episode_mark_unwatched">Σήμανση ως μη παρακολουθηθέν</string>
|
||||||
<string name="episode_mark_watched">Σήμανση ως παρακολουθηθέν</string>
|
<string name="episode_mark_watched">Σήμανση ως παρακολουθηθέν</string>
|
||||||
<string name="home_continue_watching_up_next">Επόμενο</string>
|
<string name="home_continue_watching_up_next">Επόμενο</string>
|
||||||
<string name="home_continue_watching_watched">%1$d%% παρακολουθήθηκε</string>
|
<string name="home_continue_watching_watched">%1$s παρακολουθήθηκε</string>
|
||||||
<string name="home_empty_no_active_addons_message">Εγκαταστήστε και επικυρώστε τουλάχιστον ένα πρόσθετο πριν φορτώσετε γραμμές καταλόγου στην Αρχική.</string>
|
<string name="home_empty_no_active_addons_message">Εγκαταστήστε και επικυρώστε τουλάχιστον ένα πρόσθετο πριν φορτώσετε γραμμές καταλόγου στην Αρχική.</string>
|
||||||
<string name="home_empty_no_rows_message">Τα εγκατεστημένα πρόσθετα δεν παρέχουν αυτή τη στιγμή καταλόγους συμβατούς με πίνακα χωρίς απαιτούμενα extras.</string>
|
<string name="home_empty_no_rows_message">Τα εγκατεστημένα πρόσθετα δεν παρέχουν αυτή τη στιγμή καταλόγους συμβατούς με πίνακα χωρίς απαιτούμενα extras.</string>
|
||||||
<string name="home_empty_no_rows_title">Δεν υπάρχουν διαθέσιμες γραμμές αρχικής</string>
|
<string name="home_empty_no_rows_title">Δεν υπάρχουν διαθέσιμες γραμμές αρχικής</string>
|
||||||
|
|
@ -866,7 +866,7 @@
|
||||||
<string name="streams_no_direct_link">Δεν υπάρχει διαθέσιμος άμεσος σύνδεσμος ροής</string>
|
<string name="streams_no_direct_link">Δεν υπάρχει διαθέσιμος άμεσος σύνδεσμος ροής</string>
|
||||||
<string name="streams_no_metadata">Δεν υπάρχουν διαθέσιμα μεταδεδομένα</string>
|
<string name="streams_no_metadata">Δεν υπάρχουν διαθέσιμα μεταδεδομένα</string>
|
||||||
<string name="streams_refresh">Ανανέωση ροών</string>
|
<string name="streams_refresh">Ανανέωση ροών</string>
|
||||||
<string name="streams_resume_from_percent">Συνέχεια από %1$d%%</string>
|
<string name="streams_resume_from_percent">Συνέχεια από %1$d%</string>
|
||||||
<string name="streams_resume_from_time">Συνέχεια από %1$s</string>
|
<string name="streams_resume_from_time">Συνέχεια από %1$s</string>
|
||||||
<string name="streams_size">ΜΕΓΕΘΟΣ %1$s</string>
|
<string name="streams_size">ΜΕΓΕΘΟΣ %1$s</string>
|
||||||
<string name="trailer_close">Κλείσιμο τρέιλερ</string>
|
<string name="trailer_close">Κλείσιμο τρέιλερ</string>
|
||||||
|
|
@ -876,7 +876,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Ο έλεγχος ενημερώσεων απέτυχε</string>
|
<string name="updates_check_failed">Ο έλεγχος ενημερώσεων απέτυχε</string>
|
||||||
<string name="updates_download_failed">Η λήψη απέτυχε</string>
|
<string name="updates_download_failed">Η λήψη απέτυχε</string>
|
||||||
<string name="updates_downloading_progress">Λήψη %1$d%%</string>
|
<string name="updates_downloading_progress">Λήψη %1$d%</string>
|
||||||
<string name="updates_install_failed">Αδυναμία εκκίνησης εγκατάστασης</string>
|
<string name="updates_install_failed">Αδυναμία εκκίνησης εγκατάστασης</string>
|
||||||
<string name="updates_latest_version">Χρησιμοποιείτε την τελευταία έκδοση.</string>
|
<string name="updates_latest_version">Χρησιμοποιείτε την τελευταία έκδοση.</string>
|
||||||
<string name="updates_message_allow_installs">Ενεργοποιήστε τις εγκαταστάσεις εφαρμογών για το Nuvio και επιστρέψτε για να συνεχίσετε.</string>
|
<string name="updates_message_allow_installs">Ενεργοποιήστε τις εγκαταστάσεις εφαρμογών για το Nuvio και επιστρέψτε για να συνεχίσετε.</string>
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@
|
||||||
<string name="collections_editor_tmdb_subtitle_movie_collection">Colección de películas de TMDB</string>
|
<string name="collections_editor_tmdb_subtitle_movie_collection">Colección de películas de TMDB</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_production">Producción</string>
|
<string name="collections_editor_tmdb_subtitle_production">Producción</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_network">Cadena</string>
|
<string name="collections_editor_tmdb_subtitle_network">Cadena</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_discover">Discover de TMDB</string>
|
<string name="collections_editor_tmdb_subtitle_discover">Descubrir de TMDB</string>
|
||||||
<string name="collections_empty_subtitle">Crea una para organizar tus catálogos.</string>
|
<string name="collections_empty_subtitle">Crea una para organizar tus catálogos.</string>
|
||||||
<string name="collections_empty_title">Aún no hay colecciones</string>
|
<string name="collections_empty_title">Aún no hay colecciones</string>
|
||||||
<string name="collections_folder_count">%1$d carpeta(s)</string>
|
<string name="collections_folder_count">%1$d carpeta(s)</string>
|
||||||
|
|
@ -298,7 +298,7 @@
|
||||||
<string name="compose_player_seek_forward_10">Avanzar 10 segundos</string>
|
<string name="compose_player_seek_forward_10">Avanzar 10 segundos</string>
|
||||||
<string name="compose_player_sources">Fuentes</string>
|
<string name="compose_player_sources">Fuentes</string>
|
||||||
<string name="compose_player_style">Estilo</string>
|
<string name="compose_player_style">Estilo</string>
|
||||||
<string name="compose_player_subs">Subs</string>
|
<string name="compose_player_subs">Subtítulos</string>
|
||||||
<string name="compose_player_subtitles">Subtítulos</string>
|
<string name="compose_player_subtitles">Subtítulos</string>
|
||||||
<string name="compose_player_brightness_level">Brillo %1$s</string>
|
<string name="compose_player_brightness_level">Brillo %1$s</string>
|
||||||
<string name="compose_player_volume_level">Volumen %1$s</string>
|
<string name="compose_player_volume_level">Volumen %1$s</string>
|
||||||
|
|
@ -424,12 +424,12 @@
|
||||||
<string name="settings_homescreen_display_name">Nombre visible</string>
|
<string name="settings_homescreen_display_name">Nombre visible</string>
|
||||||
<string name="settings_homescreen_empty_message">Instala un complemento con catálogos compatibles con tableros para configurar las filas de la pantalla de inicio.</string>
|
<string name="settings_homescreen_empty_message">Instala un complemento con catálogos compatibles con tableros para configurar las filas de la pantalla de inicio.</string>
|
||||||
<string name="settings_homescreen_empty_title">No hay catálogos de inicio</string>
|
<string name="settings_homescreen_empty_title">No hay catálogos de inicio</string>
|
||||||
<string name="settings_homescreen_hero_source">Fuente del Hero</string>
|
<string name="settings_homescreen_hero_source">Fuente de Destacado</string>
|
||||||
<string name="settings_homescreen_hidden">Oculto</string>
|
<string name="settings_homescreen_hidden">Oculto</string>
|
||||||
<string name="settings_homescreen_keep_home_focused">Mantener Inicio enfocado</string>
|
<string name="settings_homescreen_keep_home_focused">Mantener Inicio enfocado</string>
|
||||||
<string name="settings_homescreen_limit_reached">%1$s • Límite alcanzado (máx. %2$d)</string>
|
<string name="settings_homescreen_limit_reached">%1$s • Límite alcanzado (máx. %2$d)</string>
|
||||||
<string name="settings_homescreen_no_sources_selected">No hay fuentes Hero seleccionadas</string>
|
<string name="settings_homescreen_no_sources_selected">No hay fuentes de Destacado seleccionadas</string>
|
||||||
<string name="settings_homescreen_not_in_hero">No está en Hero</string>
|
<string name="settings_homescreen_not_in_hero">No está en Destacado</string>
|
||||||
<string name="settings_homescreen_pin_to_move_toast">Quita fijar arriba de la colección para moverla</string>
|
<string name="settings_homescreen_pin_to_move_toast">Quita fijar arriba de la colección para moverla</string>
|
||||||
<string name="settings_homescreen_pinned">Fijado</string>
|
<string name="settings_homescreen_pinned">Fijado</string>
|
||||||
<string name="settings_homescreen_pinned_to_top">Fijado arriba</string>
|
<string name="settings_homescreen_pinned_to_top">Fijado arriba</string>
|
||||||
|
|
@ -437,12 +437,12 @@
|
||||||
<string name="settings_homescreen_section_catalogs">CATÁLOGOS</string>
|
<string name="settings_homescreen_section_catalogs">CATÁLOGOS</string>
|
||||||
<string name="settings_homescreen_section_catalogs_collections">CATÁLOGOS Y COLECCIONES</string>
|
<string name="settings_homescreen_section_catalogs_collections">CATÁLOGOS Y COLECCIONES</string>
|
||||||
<string name="settings_homescreen_section_collections">COLECCIONES</string>
|
<string name="settings_homescreen_section_collections">COLECCIONES</string>
|
||||||
<string name="settings_homescreen_section_hero">HERO</string>
|
<string name="settings_homescreen_section_hero">DESTACADO</string>
|
||||||
<string name="settings_homescreen_section_hero_sources">FUENTES DEL HERO</string>
|
<string name="settings_homescreen_section_hero_sources">FUENTES DE DESTACADO</string>
|
||||||
<string name="settings_homescreen_selected_count">%1$d de %2$d seleccionados</string>
|
<string name="settings_homescreen_selected_count">%1$d de %2$d seleccionados</string>
|
||||||
<string name="settings_homescreen_show_hero">Mostrar Hero</string>
|
<string name="settings_homescreen_show_hero">Mostrar Destacado</string>
|
||||||
<string name="settings_homescreen_show_hero_description">Mostrar un carrusel Hero destacado en la parte superior del inicio. Elige hasta 2 catálogos fuente abajo.</string>
|
<string name="settings_homescreen_show_hero_description">Mostrar un carrusel destacado en la parte superior del inicio. Elige hasta 2 catálogos de origen abajo.</string>
|
||||||
<string name="settings_homescreen_summary">%1$d de %2$d catálogos visibles • %3$d fuentes Hero seleccionadas</string>
|
<string name="settings_homescreen_summary">%1$d de %2$d catálogos visibles • %3$d fuentes de Destacado seleccionadas</string>
|
||||||
<string name="settings_homescreen_summary_hint">Abre un catálogo solo cuando necesites cambiarle el nombre o reordenarlo.</string>
|
<string name="settings_homescreen_summary_hint">Abre un catálogo solo cuando necesites cambiarle el nombre o reordenarlo.</string>
|
||||||
<string name="settings_homescreen_visible">Visible</string>
|
<string name="settings_homescreen_visible">Visible</string>
|
||||||
<string name="settings_playback_subtitle">Reproductor, subtítulos y reproducción automática</string>
|
<string name="settings_playback_subtitle">Reproductor, subtítulos y reproducción automática</string>
|
||||||
|
|
@ -488,7 +488,7 @@
|
||||||
<string name="settings_content_discovery_addons_description">Instala, elimina, actualiza y ordena tus fuentes de contenido.</string>
|
<string name="settings_content_discovery_addons_description">Instala, elimina, actualiza y ordena tus fuentes de contenido.</string>
|
||||||
<string name="settings_content_discovery_plugins_description">Instala repositorios de scrapers en JavaScript y prueba proveedores internamente.</string>
|
<string name="settings_content_discovery_plugins_description">Instala repositorios de scrapers en JavaScript y prueba proveedores internamente.</string>
|
||||||
<string name="settings_content_discovery_homescreen_description">Controla qué catálogos aparecen en Inicio y en qué orden.</string>
|
<string name="settings_content_discovery_homescreen_description">Controla qué catálogos aparecen en Inicio y en qué orden.</string>
|
||||||
<string name="settings_content_discovery_meta_screen_description">Desactiva secciones de detalles y reordena todo debajo del Hero.</string>
|
<string name="settings_content_discovery_meta_screen_description">Desactiva secciones de detalles y reordena todo debajo del Destacado.</string>
|
||||||
<string name="settings_content_discovery_collections_description">Crea agrupaciones de catálogos personalizadas con carpetas mostradas en Inicio.</string>
|
<string name="settings_content_discovery_collections_description">Crea agrupaciones de catálogos personalizadas con carpetas mostradas en Inicio.</string>
|
||||||
<string name="settings_integrations_section_title">INTEGRACIONES</string>
|
<string name="settings_integrations_section_title">INTEGRACIONES</string>
|
||||||
<string name="settings_integrations_tmdb_description">Mejora las páginas de detalles con arte, créditos, metadatos de episodios y más desde TMDB.</string>
|
<string name="settings_integrations_tmdb_description">Mejora las páginas de detalles con arte, créditos, metadatos de episodios y más desde TMDB.</string>
|
||||||
|
|
@ -641,7 +641,7 @@
|
||||||
<string name="settings_playback_regex_preset_quality_720p_smaller">720p / más pequeño</string>
|
<string name="settings_playback_regex_preset_quality_720p_smaller">720p / más pequeño</string>
|
||||||
<string name="settings_playback_regex_preset_web_sources">Fuentes WEB</string>
|
<string name="settings_playback_regex_preset_web_sources">Fuentes WEB</string>
|
||||||
<string name="settings_playback_render_type">Tipo de renderizado</string>
|
<string name="settings_playback_render_type">Tipo de renderizado</string>
|
||||||
<string name="settings_playback_render_type_cues">Estándar (Cues)</string>
|
<string name="settings_playback_render_type_cues">Estándar (marcas)</string>
|
||||||
<string name="settings_playback_render_type_effects_canvas">Canvas con efectos</string>
|
<string name="settings_playback_render_type_effects_canvas">Canvas con efectos</string>
|
||||||
<string name="settings_playback_render_type_effects_opengl">OpenGL con efectos</string>
|
<string name="settings_playback_render_type_effects_opengl">OpenGL con efectos</string>
|
||||||
<string name="settings_playback_render_type_overlay_canvas">Canvas superpuesto</string>
|
<string name="settings_playback_render_type_overlay_canvas">Canvas superpuesto</string>
|
||||||
|
|
@ -687,7 +687,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Porcentaje</string>
|
<string name="settings_playback_threshold_mode_percentage">Porcentaje</string>
|
||||||
<string name="settings_playback_threshold_percentage">Porcentaje de umbral</string>
|
<string name="settings_playback_threshold_percentage">Porcentaje de umbral</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Mostrar la tarjeta del siguiente episodio cuando la reproducción alcance este porcentaje.</string>
|
<string name="settings_playback_threshold_percentage_description">Mostrar la tarjeta del siguiente episodio cuando la reproducción alcance este porcentaje.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Instantáneo</string>
|
<string name="settings_playback_timeout_instant">Instantáneo</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Ilimitado</string>
|
<string name="settings_playback_timeout_unlimited">Ilimitado</string>
|
||||||
|
|
@ -877,7 +877,7 @@
|
||||||
<string name="discover_empty_load_failed_message">El catálogo seleccionado no devolvió elementos de descubrimiento.</string>
|
<string name="discover_empty_load_failed_message">El catálogo seleccionado no devolvió elementos de descubrimiento.</string>
|
||||||
<string name="discover_empty_load_failed_title">No se pudo cargar Descubrir</string>
|
<string name="discover_empty_load_failed_title">No se pudo cargar Descubrir</string>
|
||||||
<string name="discover_empty_no_catalogs_message">Los addons instalados no exponen catálogos compatibles con el tablero para Descubrir.</string>
|
<string name="discover_empty_no_catalogs_message">Los addons instalados no exponen catálogos compatibles con el tablero para Descubrir.</string>
|
||||||
<string name="discover_empty_no_catalogs_title">No hay catálogos de descubrir</string>
|
<string name="discover_empty_no_catalogs_title">No hay catálogos de Descubrir</string>
|
||||||
<string name="discover_empty_no_results_message">El catálogo y los filtros seleccionados no devolvieron ningún elemento.</string>
|
<string name="discover_empty_no_results_message">El catálogo y los filtros seleccionados no devolvieron ningún elemento.</string>
|
||||||
<string name="discover_empty_no_results_title">No se encontraron títulos</string>
|
<string name="discover_empty_no_results_title">No se encontraron títulos</string>
|
||||||
<string name="discover_empty_no_active_addons_message">Instala y valida al menos un addon antes de explorar catálogos en Descubrir.</string>
|
<string name="discover_empty_no_active_addons_message">Instala y valida al menos un addon antes de explorar catálogos en Descubrir.</string>
|
||||||
|
|
@ -892,7 +892,7 @@
|
||||||
<string name="episode_mark_unwatched">Marcar como no visto</string>
|
<string name="episode_mark_unwatched">Marcar como no visto</string>
|
||||||
<string name="episode_mark_watched">Marcar como visto</string>
|
<string name="episode_mark_watched">Marcar como visto</string>
|
||||||
<string name="home_continue_watching_up_next">Siguiente</string>
|
<string name="home_continue_watching_up_next">Siguiente</string>
|
||||||
<string name="home_continue_watching_watched">%1$d%% visto</string>
|
<string name="home_continue_watching_watched">%1$s visto</string>
|
||||||
<string name="home_empty_no_active_addons_message">Instala y valida al menos un addon antes de cargar filas de catálogo en Inicio.</string>
|
<string name="home_empty_no_active_addons_message">Instala y valida al menos un addon antes de cargar filas de catálogo en Inicio.</string>
|
||||||
<string name="home_empty_no_rows_message">Los addons instalados no exponen actualmente catálogos compatibles con el tablero sin extras requeridos.</string>
|
<string name="home_empty_no_rows_message">Los addons instalados no exponen actualmente catálogos compatibles con el tablero sin extras requeridos.</string>
|
||||||
<string name="home_empty_no_rows_title">No hay filas de inicio disponibles</string>
|
<string name="home_empty_no_rows_title">No hay filas de inicio disponibles</string>
|
||||||
|
|
@ -948,8 +948,8 @@
|
||||||
<string name="profile_manage_profiles">Gestionar perfiles</string>
|
<string name="profile_manage_profiles">Gestionar perfiles</string>
|
||||||
<string name="profile_name_placeholder">Nombre del perfil</string>
|
<string name="profile_name_placeholder">Nombre del perfil</string>
|
||||||
<string name="profile_new">Perfil nuevo</string>
|
<string name="profile_new">Perfil nuevo</string>
|
||||||
<string name="profile_primary_addons_off">Addons principales desactivados</string>
|
<string name="profile_primary_addons_off">Complementos principales desactivados</string>
|
||||||
<string name="profile_primary_addons_on">Addons principales activados</string>
|
<string name="profile_primary_addons_on">Complementos principales activados</string>
|
||||||
<string name="profile_remove_pin_for">Quitar PIN para %1$s</string>
|
<string name="profile_remove_pin_for">Quitar PIN para %1$s</string>
|
||||||
<string name="profile_remove_pin_lock">Quitar bloqueo PIN</string>
|
<string name="profile_remove_pin_lock">Quitar bloqueo PIN</string>
|
||||||
<string name="profile_saving">Guardando...</string>
|
<string name="profile_saving">Guardando...</string>
|
||||||
|
|
@ -984,7 +984,7 @@
|
||||||
<string name="streams_no_direct_link">No hay enlace directo del stream disponible</string>
|
<string name="streams_no_direct_link">No hay enlace directo del stream disponible</string>
|
||||||
<string name="streams_no_metadata">No hay metadatos disponibles</string>
|
<string name="streams_no_metadata">No hay metadatos disponibles</string>
|
||||||
<string name="streams_refresh">Actualizar streams</string>
|
<string name="streams_refresh">Actualizar streams</string>
|
||||||
<string name="streams_resume_from_percent">Reanudar desde %1$d%%</string>
|
<string name="streams_resume_from_percent">Reanudar desde %1$d%</string>
|
||||||
<string name="streams_resume_from_time">Reanudar desde %1$s</string>
|
<string name="streams_resume_from_time">Reanudar desde %1$s</string>
|
||||||
<string name="streams_size">TAMAÑO %1$s</string>
|
<string name="streams_size">TAMAÑO %1$s</string>
|
||||||
<string name="trailer_close">Cerrar tráiler</string>
|
<string name="trailer_close">Cerrar tráiler</string>
|
||||||
|
|
@ -994,7 +994,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Falló la comprobación de actualizaciones</string>
|
<string name="updates_check_failed">Falló la comprobación de actualizaciones</string>
|
||||||
<string name="updates_download_failed">La descarga falló</string>
|
<string name="updates_download_failed">La descarga falló</string>
|
||||||
<string name="updates_downloading_progress">Descargando %1$d%%</string>
|
<string name="updates_downloading_progress">Descargando %1$d%</string>
|
||||||
<string name="updates_install_failed">No se pudo iniciar la instalación</string>
|
<string name="updates_install_failed">No se pudo iniciar la instalación</string>
|
||||||
<string name="updates_latest_version">Estás usando la versión más reciente.</string>
|
<string name="updates_latest_version">Estás usando la versión más reciente.</string>
|
||||||
<string name="updates_message_allow_installs">Activa la instalación de apps para Nuvio y luego vuelve para continuar.</string>
|
<string name="updates_message_allow_installs">Activa la instalación de apps para Nuvio y luego vuelve para continuar.</string>
|
||||||
|
|
@ -1021,7 +1021,7 @@
|
||||||
<string name="detail_logo_content_description">logotipo de %1$s</string>
|
<string name="detail_logo_content_description">logotipo de %1$s</string>
|
||||||
<string name="details_comments_load_failed">No se pudieron cargar los comentarios</string>
|
<string name="details_comments_load_failed">No se pudieron cargar los comentarios</string>
|
||||||
<string name="details_load_failed_all_addons">No se pudieron cargar los detalles desde ningún complemento.</string>
|
<string name="details_load_failed_all_addons">No se pudieron cargar los detalles desde ningún complemento.</string>
|
||||||
<string name="details_networks">Redes</string>
|
<string name="details_networks">Cadenas</string>
|
||||||
<string name="details_no_addon_meta">Ningún complemento proporciona metadatos para este contenido.</string>
|
<string name="details_no_addon_meta">Ningún complemento proporciona metadatos para este contenido.</string>
|
||||||
<string name="download_failed">Descarga fallida</string>
|
<string name="download_failed">Descarga fallida</string>
|
||||||
<string name="downloads_channel_description">Muestra el progreso en vivo y los controles de descarga.</string>
|
<string name="downloads_channel_description">Muestra el progreso en vivo y los controles de descarga.</string>
|
||||||
|
|
@ -1039,7 +1039,7 @@
|
||||||
<string name="notifications_test_preview_body">Vista previa de la alerta de estreno de episodio.</string>
|
<string name="notifications_test_preview_body">Vista previa de la alerta de estreno de episodio.</string>
|
||||||
<string name="notifications_test_send_failed">No se pudo enviar una notificación de prueba.</string>
|
<string name="notifications_test_send_failed">No se pudo enviar una notificación de prueba.</string>
|
||||||
<string name="notifications_test_sent_for">Notificación de prueba enviada para %1$s.</string>
|
<string name="notifications_test_sent_for">Notificación de prueba enviada para %1$s.</string>
|
||||||
<string name="player_unable_to_play_stream">No se puede reproducir esta transmisión.</string>
|
<string name="player_unable_to_play_stream">No se puede reproducir este stream.</string>
|
||||||
<string name="profile_pin_changed_requires_refresh">El PIN de este perfil cambió. Conéctate una vez para actualizar el bloqueo en este dispositivo.</string>
|
<string name="profile_pin_changed_requires_refresh">El PIN de este perfil cambió. Conéctate una vez para actualizar el bloqueo en este dispositivo.</string>
|
||||||
<string name="profile_pin_clear_failed">No se pudo quitar el bloqueo por PIN. Inténtalo de nuevo.</string>
|
<string name="profile_pin_clear_failed">No se pudo quitar el bloqueo por PIN. Inténtalo de nuevo.</string>
|
||||||
<string name="profile_pin_clear_requires_internet">Conéctate a internet para quitar el bloqueo por PIN.</string>
|
<string name="profile_pin_clear_requires_internet">Conéctate a internet para quitar el bloqueo por PIN.</string>
|
||||||
|
|
@ -1107,7 +1107,7 @@
|
||||||
<string name="details_browse_rail_popular">Popular</string>
|
<string name="details_browse_rail_popular">Popular</string>
|
||||||
<string name="details_browse_rail_recent">Reciente</string>
|
<string name="details_browse_rail_recent">Reciente</string>
|
||||||
<string name="details_browse_rail_title">%1$s • %2$s</string>
|
<string name="details_browse_rail_title">%1$s • %2$s</string>
|
||||||
<string name="details_browse_rail_top_rated">Mejor valorado</string>
|
<string name="details_browse_rail_top_rated">Mejor valorados</string>
|
||||||
<string name="details_certification">Clasificación</string>
|
<string name="details_certification">Clasificación</string>
|
||||||
<string name="details_movie_details">Detalles de la película</string>
|
<string name="details_movie_details">Detalles de la película</string>
|
||||||
<string name="details_original_language">Idioma original</string>
|
<string name="details_original_language">Idioma original</string>
|
||||||
|
|
|
||||||
1162
composeApp/src/commonMain/composeResources/values-fr/strings.xml
Normal file
1162
composeApp/src/commonMain/composeResources/values-fr/strings.xml
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -29,11 +29,11 @@
|
||||||
<string name="addons_delete">Cancella addon</string>
|
<string name="addons_delete">Cancella addon</string>
|
||||||
<string name="addons_empty_subtitle">Aggiungi un manifest URL per iniziare a caricare cataloghi , metadata, flussi o sottotitoli dentro Nuvio.</string>
|
<string name="addons_empty_subtitle">Aggiungi un manifest URL per iniziare a caricare cataloghi , metadata, flussi o sottotitoli dentro Nuvio.</string>
|
||||||
<string name="addons_empty_title">Nessun addon installato ancora.</string>
|
<string name="addons_empty_title">Nessun addon installato ancora.</string>
|
||||||
<string name="addons_error_enter_url">Inserisci l\'URL dell\'addon.</string>
|
<string name="addons_error_enter_url">Inserisci l'URL dell'addon.</string>
|
||||||
<string name="addons_input_placeholder">URL Addon</string>
|
<string name="addons_input_placeholder">URL Addon</string>
|
||||||
<string name="addons_install_button">Installa Addon</string>
|
<string name="addons_install_button">Installa Addon</string>
|
||||||
<string name="addons_loading_manifest_details">Caricamento dettagli manifest...</string>
|
<string name="addons_loading_manifest_details">Caricamento dettagli manifest...</string>
|
||||||
<string name="addons_modal_checking_message">Validazione dell\'URL del manifest e caricamento dei dettagli dell\'addon prima dell\'installazione.</string>
|
<string name="addons_modal_checking_message">Validazione dell'URL del manifest e caricamento dei dettagli dell'addon prima dell'installazione.</string>
|
||||||
<string name="addons_modal_checking_title">Verifica Addon</string>
|
<string name="addons_modal_checking_title">Verifica Addon</string>
|
||||||
<string name="addons_modal_failure_title">Installazione Fallita</string>
|
<string name="addons_modal_failure_title">Installazione Fallita</string>
|
||||||
<string name="addons_modal_success_message">%1$s è stato validato e aggiunto con successo.</string>
|
<string name="addons_modal_success_message">%1$s è stato validato e aggiunto con successo.</string>
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
<string name="cd_selected">Selezionato</string>
|
<string name="cd_selected">Selezionato</string>
|
||||||
<string name="collections_copy_json">Copia JSON</string>
|
<string name="collections_copy_json">Copia JSON</string>
|
||||||
<string name="collections_count_summary">%1$d collezioni, %2$d cartelle</string>
|
<string name="collections_count_summary">%1$d collezioni, %2$d cartelle</string>
|
||||||
<string name="collections_delete_message">Eliminare "%1$s"? L\'azione è irreversibile.</string>
|
<string name="collections_delete_message">Eliminare "%1$s"? L'azione è irreversibile.</string>
|
||||||
<string name="collections_delete_title">Elimina Collezione</string>
|
<string name="collections_delete_title">Elimina Collezione</string>
|
||||||
<string name="collections_editor_add_catalog">Aggiungi Catalogo</string>
|
<string name="collections_editor_add_catalog">Aggiungi Catalogo</string>
|
||||||
<string name="collections_editor_add_folder">Aggiungi Cartella</string>
|
<string name="collections_editor_add_folder">Aggiungi Cartella</string>
|
||||||
|
|
@ -68,15 +68,15 @@
|
||||||
<string name="collections_editor_done">Fatto</string>
|
<string name="collections_editor_done">Fatto</string>
|
||||||
<string name="collections_editor_edit_collection">Modifica Collezione</string>
|
<string name="collections_editor_edit_collection">Modifica Collezione</string>
|
||||||
<string name="collections_editor_edit_folder">Modifica Cartella</string>
|
<string name="collections_editor_edit_folder">Modifica Cartella</string>
|
||||||
<string name="collections_editor_folder_editor_help">Imposta l\'identità della cartella, la presentazione e le sorgenti del catalogo con la stessa struttura dell\'editor principale delle collezioni.</string>
|
<string name="collections_editor_folder_editor_help">Imposta l'identità della cartella, la presentazione e le sorgenti del catalogo con la stessa struttura dell'editor principale delle collezioni.</string>
|
||||||
<string name="collections_editor_folder_empty_subtitle">Aggiungine una per iniziare.</string>
|
<string name="collections_editor_folder_empty_subtitle">Aggiungine una per iniziare.</string>
|
||||||
<string name="collections_editor_folder_empty_title">Ancora nessuna cartella</string>
|
<string name="collections_editor_folder_empty_title">Ancora nessuna cartella</string>
|
||||||
<string name="collections_editor_folders">Cartelle</string>
|
<string name="collections_editor_folders">Cartelle</string>
|
||||||
<string name="collections_editor_genre_filter">Filtro Genere</string>
|
<string name="collections_editor_genre_filter">Filtro Genere</string>
|
||||||
<string name="collections_editor_hide_title_desc">Mostra solo l\'immagine di copertina</string>
|
<string name="collections_editor_hide_title_desc">Mostra solo l'immagine di copertina</string>
|
||||||
<string name="collections_editor_hide_title">Nascondi Titolo</string>
|
<string name="collections_editor_hide_title">Nascondi Titolo</string>
|
||||||
<string name="collections_editor_new_folder">Nuova Cartella</string>
|
<string name="collections_editor_new_folder">Nuova Cartella</string>
|
||||||
<string name="collections_editor_pin_above_desc">Mostra questa collezione sopra tutti i normali cataloghi della home. In presenza di multiple collezioni fissate si seguirà l\'ordine di creazione.</string>
|
<string name="collections_editor_pin_above_desc">Mostra questa collezione sopra tutti i normali cataloghi della home. In presenza di multiple collezioni fissate si seguirà l'ordine di creazione.</string>
|
||||||
<string name="collections_editor_pin_above">Fissa sopra i cataloghi</string>
|
<string name="collections_editor_pin_above">Fissa sopra i cataloghi</string>
|
||||||
<string name="collections_editor_placeholder_backdrop">URL backdrop (opzionale)</string>
|
<string name="collections_editor_placeholder_backdrop">URL backdrop (opzionale)</string>
|
||||||
<string name="collections_editor_placeholder_folder">Nome cartella</string>
|
<string name="collections_editor_placeholder_folder">Nome cartella</string>
|
||||||
|
|
@ -229,14 +229,14 @@
|
||||||
<string name="compose_settings_root_account_description">Gestisci il tuo account, disconnettiti o eliminalo.</string>
|
<string name="compose_settings_root_account_description">Gestisci il tuo account, disconnettiti o eliminalo.</string>
|
||||||
<string name="compose_settings_root_account_section">ACCOUNT</string>
|
<string name="compose_settings_root_account_section">ACCOUNT</string>
|
||||||
<string name="compose_settings_root_appearance_description">Regola la presentazione della home e le preferenze visive.</string>
|
<string name="compose_settings_root_appearance_description">Regola la presentazione della home e le preferenze visive.</string>
|
||||||
<string name="compose_settings_root_check_updates_description">Controlla se ci sono nuove versioni dell\'app.</string>
|
<string name="compose_settings_root_check_updates_description">Controlla se ci sono nuove versioni dell'app.</string>
|
||||||
<string name="compose_settings_root_check_updates_title">Verifica aggiornamenti</string>
|
<string name="compose_settings_root_check_updates_title">Verifica aggiornamenti</string>
|
||||||
<string name="compose_settings_root_content_discovery_description">Gestisci gli addon e le sorgenti di scoperta.</string>
|
<string name="compose_settings_root_content_discovery_description">Gestisci gli addon e le sorgenti di scoperta.</string>
|
||||||
<string name="compose_settings_root_downloads_description">Gestisci i film e gli episodi scaricati.</string>
|
<string name="compose_settings_root_downloads_description">Gestisci i film e gli episodi scaricati.</string>
|
||||||
<string name="compose_settings_root_downloads_title">Download</string>
|
<string name="compose_settings_root_downloads_title">Download</string>
|
||||||
<string name="compose_settings_root_general_section">GENERALI</string>
|
<string name="compose_settings_root_general_section">GENERALI</string>
|
||||||
<string name="compose_settings_root_integrations_description">Collega i servizi TMDB e MDBList.</string>
|
<string name="compose_settings_root_integrations_description">Collega i servizi TMDB e MDBList.</string>
|
||||||
<string name="compose_settings_root_notifications_description">Gestisci gli avvisi per l\'uscita di nuovi episodi e invia una notifica di test.</string>
|
<string name="compose_settings_root_notifications_description">Gestisci gli avvisi per l'uscita di nuovi episodi e invia una notifica di test.</string>
|
||||||
<string name="compose_settings_root_switch_profile_description">Passa a un profilo diverso.</string>
|
<string name="compose_settings_root_switch_profile_description">Passa a un profilo diverso.</string>
|
||||||
<string name="compose_settings_root_switch_profile_title">Cambia profilo</string>
|
<string name="compose_settings_root_switch_profile_title">Cambia profilo</string>
|
||||||
<string name="compose_settings_root_trakt_description">Collega Trakt, sincronizza la lista dei desideri e salva i titoli direttamente su Trakt.</string>
|
<string name="compose_settings_root_trakt_description">Collega Trakt, sincronizza la lista dei desideri e salva i titoli direttamente su Trakt.</string>
|
||||||
|
|
@ -245,7 +245,7 @@
|
||||||
<string name="action_donate">Dona</string>
|
<string name="action_donate">Dona</string>
|
||||||
<string name="cw_action_go_to_details">Vai ai dettagli</string>
|
<string name="cw_action_go_to_details">Vai ai dettagli</string>
|
||||||
<string name="cw_action_remove">Rimuovi</string>
|
<string name="cw_action_remove">Rimuovi</string>
|
||||||
<string name="cw_action_start_from_beginning">Riproduci dall\'inizio</string>
|
<string name="cw_action_start_from_beginning">Riproduci dall'inizio</string>
|
||||||
<string name="detail_btn_play">Riproduci</string>
|
<string name="detail_btn_play">Riproduci</string>
|
||||||
<string name="detail_comments_badge_rating">%1$d/10</string>
|
<string name="detail_comments_badge_rating">%1$d/10</string>
|
||||||
<string name="detail_comments_badge_review">Recensione</string>
|
<string name="detail_comments_badge_review">Recensione</string>
|
||||||
|
|
@ -284,7 +284,7 @@
|
||||||
<string name="settings_account_delete_account">Elimina account</string>
|
<string name="settings_account_delete_account">Elimina account</string>
|
||||||
<string name="settings_account_delete_account_description">Questo eliminerà permanentemente il tuo account e tutti i dati associati.</string>
|
<string name="settings_account_delete_account_description">Questo eliminerà permanentemente il tuo account e tutti i dati associati.</string>
|
||||||
<string name="settings_account_delete_confirm_message">Questa azione non può essere annullata. Tutti i tuoi dati, profili e la cronologia di sincronizzazione saranno rimossi per sempre.</string>
|
<string name="settings_account_delete_confirm_message">Questa azione non può essere annullata. Tutti i tuoi dati, profili e la cronologia di sincronizzazione saranno rimossi per sempre.</string>
|
||||||
<string name="settings_account_delete_confirm_title">Eliminare l\'account?</string>
|
<string name="settings_account_delete_confirm_title">Eliminare l'account?</string>
|
||||||
<string name="settings_account_email">Email</string>
|
<string name="settings_account_email">Email</string>
|
||||||
<string name="settings_account_not_signed_in">Accesso non effettuato</string>
|
<string name="settings_account_not_signed_in">Accesso non effettuato</string>
|
||||||
<string name="settings_account_sign_out">Disconnetti</string>
|
<string name="settings_account_sign_out">Disconnetti</string>
|
||||||
|
|
@ -332,7 +332,7 @@
|
||||||
<string name="settings_poster_card_style">STILE LOCANDINA</string>
|
<string name="settings_poster_card_style">STILE LOCANDINA</string>
|
||||||
<string name="settings_poster_card_width">Larghezza locandina</string>
|
<string name="settings_poster_card_width">Larghezza locandina</string>
|
||||||
<string name="settings_poster_custom">Personalizzato</string>
|
<string name="settings_poster_custom">Personalizzato</string>
|
||||||
<string name="settings_poster_description">Personalizza la larghezza e il raggio degli angoli delle locandine in tutta l\'app.</string>
|
<string name="settings_poster_description">Personalizza la larghezza e il raggio degli angoli delle locandine in tutta l'app.</string>
|
||||||
<string name="settings_poster_hide_labels">Nascondi etichette</string>
|
<string name="settings_poster_hide_labels">Nascondi etichette</string>
|
||||||
<string name="settings_poster_landscape_mode">Modalità orizzontale per le locandine della riga</string>
|
<string name="settings_poster_landscape_mode">Modalità orizzontale per le locandine della riga</string>
|
||||||
<string name="settings_poster_live_preview">Anteprima in tempo reale</string>
|
<string name="settings_poster_live_preview">Anteprima in tempo reale</string>
|
||||||
|
|
@ -351,10 +351,10 @@
|
||||||
<string name="settings_poster_width_dense">Denso</string>
|
<string name="settings_poster_width_dense">Denso</string>
|
||||||
<string name="settings_poster_width_large">Grande</string>
|
<string name="settings_poster_width_large">Grande</string>
|
||||||
<string name="settings_poster_width_standard">Standard</string>
|
<string name="settings_poster_width_standard">Standard</string>
|
||||||
<string name="settings_continue_watching_resume_prompt_description">Mostra un popup per riprendere la visione all\'apertura dell\'app se eri uscito dal player.</string>
|
<string name="settings_continue_watching_resume_prompt_description">Mostra un popup per riprendere la visione all'apertura dell'app se eri uscito dal player.</string>
|
||||||
<string name="settings_continue_watching_resume_prompt_title">Richiesta ripresa all\'avvio</string>
|
<string name="settings_continue_watching_resume_prompt_title">Richiesta ripresa all'avvio</string>
|
||||||
<string name="settings_continue_watching_section_card_style">STILE SCHEDA</string>
|
<string name="settings_continue_watching_section_card_style">STILE SCHEDA</string>
|
||||||
<string name="settings_continue_watching_section_on_launch">ALL\'AVVIO</string>
|
<string name="settings_continue_watching_section_on_launch">ALL'AVVIO</string>
|
||||||
<string name="settings_continue_watching_section_up_next_behavior">COMPORTAMENTO \"PROSSIMO EPISODIO\"</string>
|
<string name="settings_continue_watching_section_up_next_behavior">COMPORTAMENTO \"PROSSIMO EPISODIO\"</string>
|
||||||
<string name="settings_continue_watching_section_visibility">VISIBILITÀ</string>
|
<string name="settings_continue_watching_section_visibility">VISIBILITÀ</string>
|
||||||
<string name="settings_continue_watching_show_description">Mostra la riga \"Continua a guardare\" nella schermata Home.</string>
|
<string name="settings_continue_watching_show_description">Mostra la riga \"Continua a guardare\" nella schermata Home.</string>
|
||||||
|
|
@ -363,14 +363,14 @@
|
||||||
<string name="settings_continue_watching_style_poster_description">Scheda focalizzata sulla locandina</string>
|
<string name="settings_continue_watching_style_poster_description">Scheda focalizzata sulla locandina</string>
|
||||||
<string name="settings_continue_watching_style_wide">Orizzontale</string>
|
<string name="settings_continue_watching_style_wide">Orizzontale</string>
|
||||||
<string name="settings_continue_watching_style_wide_description">Scheda orizzontale ricca di informazioni</string>
|
<string name="settings_continue_watching_style_wide_description">Scheda orizzontale ricca di informazioni</string>
|
||||||
<string name="settings_continue_watching_up_next_description">Se abilitato, \"Prossimo episodio\" continua sempre dall\'ultimo episodio visto. Se disabilitato, segue l\'episodio visto più di recente. Utile se riguardi spesso episodi precedenti.</string>
|
<string name="settings_continue_watching_up_next_description">Se abilitato, \"Prossimo episodio\" continua sempre dall'ultimo episodio visto. Se disabilitato, segue l'episodio visto più di recente. Utile se riguardi spesso episodi precedenti.</string>
|
||||||
<string name="settings_continue_watching_up_next_title">Prossimo episodio dall\'ultimo visto</string>
|
<string name="settings_continue_watching_up_next_title">Prossimo episodio dall'ultimo visto</string>
|
||||||
<string name="settings_content_discovery_section_home">HOME</string>
|
<string name="settings_content_discovery_section_home">HOME</string>
|
||||||
<string name="settings_content_discovery_section_sources">SORGENTI</string>
|
<string name="settings_content_discovery_section_sources">SORGENTI</string>
|
||||||
<string name="settings_content_discovery_addons_description">Installa, rimuovi, aggiorna e ordina le tue sorgenti di contenuto.</string>
|
<string name="settings_content_discovery_addons_description">Installa, rimuovi, aggiorna e ordina le tue sorgenti di contenuto.</string>
|
||||||
<string name="settings_content_discovery_plugins_description">Installa repository di scraper JavaScript e testa i provider internamente.</string>
|
<string name="settings_content_discovery_plugins_description">Installa repository di scraper JavaScript e testa i provider internamente.</string>
|
||||||
<string name="settings_content_discovery_homescreen_description">Controlla quali cataloghi appaiono in Home e in quale ordine.</string>
|
<string name="settings_content_discovery_homescreen_description">Controlla quali cataloghi appaiono in Home e in quale ordine.</string>
|
||||||
<string name="settings_content_discovery_meta_screen_description">Disabilita le sezioni dei dettagli e riordina tutto ciò che sta sotto l\'elemento Hero.</string>
|
<string name="settings_content_discovery_meta_screen_description">Disabilita le sezioni dei dettagli e riordina tutto ciò che sta sotto l'elemento Hero.</string>
|
||||||
<string name="settings_content_discovery_collections_description">Crea raggruppamenti di cataloghi personalizzati con cartelle mostrate in Home.</string>
|
<string name="settings_content_discovery_collections_description">Crea raggruppamenti di cataloghi personalizzati con cartelle mostrate in Home.</string>
|
||||||
<string name="settings_integrations_section_title">INTEGRAZIONI</string>
|
<string name="settings_integrations_section_title">INTEGRAZIONI</string>
|
||||||
<string name="settings_integrations_tmdb_description">Migliora le pagine dei dettagli con immagini, crediti, metadati degli episodi di TMDB e altro ancora.</string>
|
<string name="settings_integrations_tmdb_description">Migliora le pagine dei dettagli con immagini, crediti, metadati degli episodi di TMDB e altro ancora.</string>
|
||||||
|
|
@ -416,7 +416,7 @@
|
||||||
<string name="settings_meta_section_sections">SEZIONI</string>
|
<string name="settings_meta_section_sections">SEZIONI</string>
|
||||||
<string name="settings_meta_tab_group_format">Gruppo schede %1$d</string>
|
<string name="settings_meta_tab_group_format">Gruppo schede %1$d</string>
|
||||||
<string name="settings_meta_tab_layout">Layout a schede</string>
|
<string name="settings_meta_tab_layout">Layout a schede</string>
|
||||||
<string name="settings_meta_tab_layout_description">Raggruppa le sezioni in schede (tab) come nell\'app TV. Assegna fino a 3 sezioni per ogni gruppo.</string>
|
<string name="settings_meta_tab_layout_description">Raggruppa le sezioni in schede (tab) come nell'app TV. Assegna fino a 3 sezioni per ogni gruppo.</string>
|
||||||
<string name="settings_meta_trailers">Trailer</string>
|
<string name="settings_meta_trailers">Trailer</string>
|
||||||
<string name="settings_meta_trailers_description">Riga dei trailer e scorciatoie di riproduzione.</string>
|
<string name="settings_meta_trailers_description">Riga dei trailer e scorciatoie di riproduzione.</string>
|
||||||
<string name="settings_notifications_disabled_in_app">Le notifiche sono attualmente disabilitate in Nuvio.</string>
|
<string name="settings_notifications_disabled_in_app">Le notifiche sono attualmente disabilitate in Nuvio.</string>
|
||||||
|
|
@ -433,7 +433,7 @@
|
||||||
<string name="settings_notifications_test_title">Notifica di test</string>
|
<string name="settings_notifications_test_title">Notifica di test</string>
|
||||||
<string name="community_section_title">Community</string>
|
<string name="community_section_title">Community</string>
|
||||||
<string name="community_section_description">Scopri le persone che sviluppano e supportano Nuvio su Mobile, TV e Web.</string>
|
<string name="community_section_description">Scopri le persone che sviluppano e supportano Nuvio su Mobile, TV e Web.</string>
|
||||||
<string name="community_supporters_not_configured">L\'API dei sostenitori non è configurata. Aggiungi DONATIONS_BASE_URL a local.properties.</string>
|
<string name="community_supporters_not_configured">L'API dei sostenitori non è configurata. Aggiungi DONATIONS_BASE_URL a local.properties.</string>
|
||||||
<string name="community_tab_contributors">Collaboratori</string>
|
<string name="community_tab_contributors">Collaboratori</string>
|
||||||
<string name="community_tab_supporters">Sostenitori</string>
|
<string name="community_tab_supporters">Sostenitori</string>
|
||||||
<string name="community_open_github">Apri GitHub</string>
|
<string name="community_open_github">Apri GitHub</string>
|
||||||
|
|
@ -472,7 +472,7 @@
|
||||||
<string name="settings_playback_anime_skip_client_id_description">Inserisci il tuo ID client API AnimeSkip. Ottienine uno su anime-skip.com.</string>
|
<string name="settings_playback_anime_skip_client_id_description">Inserisci il tuo ID client API AnimeSkip. Ottienine uno su anime-skip.com.</string>
|
||||||
<string name="settings_playback_anime_skip_description">Cerca anche su AnimeSkip i timestamp per saltare le sigle (richiede ID client).</string>
|
<string name="settings_playback_anime_skip_description">Cerca anche su AnimeSkip i timestamp per saltare le sigle (richiede ID client).</string>
|
||||||
<string name="settings_playback_auto_play_next_episode">Riproduzione automatica prossimo episodio</string>
|
<string name="settings_playback_auto_play_next_episode">Riproduzione automatica prossimo episodio</string>
|
||||||
<string name="settings_playback_auto_play_next_episode_description">Trova e riproduce automaticamente l\'episodio successivo al raggiungimento della soglia.</string>
|
<string name="settings_playback_auto_play_next_episode_description">Trova e riproduce automaticamente l'episodio successivo al raggiungimento della soglia.</string>
|
||||||
<string name="settings_playback_decoder_device_only">Solo dispositivo</string>
|
<string name="settings_playback_decoder_device_only">Solo dispositivo</string>
|
||||||
<string name="settings_playback_decoder_prefer_app">Preferisci App (FFmpeg)</string>
|
<string name="settings_playback_decoder_prefer_app">Preferisci App (FFmpeg)</string>
|
||||||
<string name="settings_playback_decoder_prefer_device">Preferisci dispositivo</string>
|
<string name="settings_playback_decoder_prefer_device">Preferisci dispositivo</string>
|
||||||
|
|
@ -493,7 +493,7 @@
|
||||||
<string name="settings_playback_map_dv7_to_hevc">Mappa DV7 su HEVC</string>
|
<string name="settings_playback_map_dv7_to_hevc">Mappa DV7 su HEVC</string>
|
||||||
<string name="settings_playback_map_dv7_to_hevc_description">Fallback da Dolby Vision Profile 7 a HEVC per i dispositivi non supportati.</string>
|
<string name="settings_playback_map_dv7_to_hevc_description">Fallback da Dolby Vision Profile 7 a HEVC per i dispositivi non supportati.</string>
|
||||||
<string name="settings_playback_minutes_before_end">Minuti prima della fine</string>
|
<string name="settings_playback_minutes_before_end">Minuti prima della fine</string>
|
||||||
<string name="settings_playback_minutes_before_end_description">Mostra la scheda dell\'episodio successivo questo numero di minuti prima della fine.</string>
|
<string name="settings_playback_minutes_before_end_description">Mostra la scheda dell'episodio successivo questo numero di minuti prima della fine.</string>
|
||||||
<string name="settings_playback_minutes_value">%1$d min</string>
|
<string name="settings_playback_minutes_value">%1$d min</string>
|
||||||
<string name="settings_playback_no_items_available">Nessun elemento disponibile</string>
|
<string name="settings_playback_no_items_available">Nessun elemento disponibile</string>
|
||||||
<string name="settings_playback_not_set">Non impostato</string>
|
<string name="settings_playback_not_set">Non impostato</string>
|
||||||
|
|
@ -528,8 +528,8 @@
|
||||||
<string name="settings_playback_render_type_effects_opengl">Effetti OpenGL</string>
|
<string name="settings_playback_render_type_effects_opengl">Effetti OpenGL</string>
|
||||||
<string name="settings_playback_render_type_overlay_canvas">Overlay Canvas</string>
|
<string name="settings_playback_render_type_overlay_canvas">Overlay Canvas</string>
|
||||||
<string name="settings_playback_render_type_overlay_opengl">Overlay OpenGL</string>
|
<string name="settings_playback_render_type_overlay_opengl">Overlay OpenGL</string>
|
||||||
<string name="settings_playback_reuse_last_link">Riusa l\'ultimo link</string>
|
<string name="settings_playback_reuse_last_link">Riusa l'ultimo link</string>
|
||||||
<string name="settings_playback_reuse_last_link_description">Riproduci automaticamente l\'ultimo flusso funzionante per lo stesso film/episodio se la cache è ancora valida.</string>
|
<string name="settings_playback_reuse_last_link_description">Riproduci automaticamente l'ultimo flusso funzionante per lo stesso film/episodio se la cache è ancora valida.</string>
|
||||||
<string name="settings_playback_secondary_audio_language">Lingua audio secondaria</string>
|
<string name="settings_playback_secondary_audio_language">Lingua audio secondaria</string>
|
||||||
<string name="settings_playback_secondary_subtitle_language">Lingua sottotitoli secondaria</string>
|
<string name="settings_playback_secondary_subtitle_language">Lingua sottotitoli secondaria</string>
|
||||||
<string name="settings_playback_section_decoder">DECODER</string>
|
<string name="settings_playback_section_decoder">DECODER</string>
|
||||||
|
|
@ -542,7 +542,7 @@
|
||||||
<string name="settings_playback_section_subtitle_rendering">RENDERING SOTTOTITOLI</string>
|
<string name="settings_playback_section_subtitle_rendering">RENDERING SOTTOTITOLI</string>
|
||||||
<string name="settings_playback_selected_count">%1$d selezionati</string>
|
<string name="settings_playback_selected_count">%1$d selezionati</string>
|
||||||
<string name="settings_playback_show_loading_overlay">Mostra overlay di caricamento</string>
|
<string name="settings_playback_show_loading_overlay">Mostra overlay di caricamento</string>
|
||||||
<string name="settings_playback_show_loading_overlay_description">Mostra una schermata di caricamento all\'avvio della riproduzione di un flusso.</string>
|
<string name="settings_playback_show_loading_overlay_description">Mostra una schermata di caricamento all'avvio della riproduzione di un flusso.</string>
|
||||||
<string name="settings_playback_skip_intro_outro_recap">Salta Intro/Outro/Recap</string>
|
<string name="settings_playback_skip_intro_outro_recap">Salta Intro/Outro/Recap</string>
|
||||||
<string name="settings_playback_skip_intro_outro_recap_description">Mostra il pulsante \"salta\" durante i segmenti rilevati di introduzione, chiusura e riassunto.</string>
|
<string name="settings_playback_skip_intro_outro_recap_description">Mostra il pulsante \"salta\" durante i segmenti rilevati di introduzione, chiusura e riassunto.</string>
|
||||||
<string name="settings_playback_source_scope">Ambito sorgente</string>
|
<string name="settings_playback_source_scope">Ambito sorgente</string>
|
||||||
|
|
@ -568,14 +568,14 @@
|
||||||
<string name="settings_playback_threshold_mode_minutes_before_end">Minuti prima della fine</string>
|
<string name="settings_playback_threshold_mode_minutes_before_end">Minuti prima della fine</string>
|
||||||
<string name="settings_playback_threshold_mode_percentage">Percentuale</string>
|
<string name="settings_playback_threshold_mode_percentage">Percentuale</string>
|
||||||
<string name="settings_playback_threshold_percentage">Percentuale di soglia</string>
|
<string name="settings_playback_threshold_percentage">Percentuale di soglia</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Mostra la scheda dell\'episodio successivo quando la riproduzione raggiunge questa percentuale.</string>
|
<string name="settings_playback_threshold_percentage_description">Mostra la scheda dell'episodio successivo quando la riproduzione raggiunge questa percentuale.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Istantaneo</string>
|
<string name="settings_playback_timeout_instant">Istantaneo</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Illimitato</string>
|
<string name="settings_playback_timeout_unlimited">Illimitato</string>
|
||||||
<string name="settings_playback_tunneled_playback">Riproduzione Tunneled</string>
|
<string name="settings_playback_tunneled_playback">Riproduzione Tunneled</string>
|
||||||
<string name="settings_playback_tunneled_playback_description">Abilita la riproduzione tunneled per una minore latenza nella sincronizzazione audio/video.</string>
|
<string name="settings_playback_tunneled_playback_description">Abilita la riproduzione tunneled per una minore latenza nella sincronizzazione audio/video.</string>
|
||||||
<string name="settings_tmdb_add_api_key_first">Aggiungi la tua chiave API TMDB qui sotto prima di attivare l\'arricchimento.</string>
|
<string name="settings_tmdb_add_api_key_first">Aggiungi la tua chiave API TMDB qui sotto prima di attivare l'arricchimento.</string>
|
||||||
<string name="settings_tmdb_api_key_label">Chiave API TMDB</string>
|
<string name="settings_tmdb_api_key_label">Chiave API TMDB</string>
|
||||||
<string name="settings_tmdb_enable_enrichment">Abilita arricchimento TMDB</string>
|
<string name="settings_tmdb_enable_enrichment">Abilita arricchimento TMDB</string>
|
||||||
<string name="settings_tmdb_enable_enrichment_description">Usa la tua chiave API TMDB per arricchire i metadati degli addon nella schermata dei dettagli quando è disponibile un ID TMDB o IMDb.</string>
|
<string name="settings_tmdb_enable_enrichment_description">Usa la tua chiave API TMDB per arricchire i metadati degli addon nella schermata dei dettagli quando è disponibile un ID TMDB o IMDb.</string>
|
||||||
|
|
@ -590,7 +590,7 @@
|
||||||
<string name="settings_tmdb_module_credits">Crediti</string>
|
<string name="settings_tmdb_module_credits">Crediti</string>
|
||||||
<string name="settings_tmdb_module_credits_description">Usa creatori, registi, sceneggiatori e foto del cast di TMDB.</string>
|
<string name="settings_tmdb_module_credits_description">Usa creatori, registi, sceneggiatori e foto del cast di TMDB.</string>
|
||||||
<string name="settings_tmdb_module_details">Dettagli</string>
|
<string name="settings_tmdb_module_details">Dettagli</string>
|
||||||
<string name="settings_tmdb_module_details_description">Usa info su rilascio, durata, classificazione d\'età, stato, paese e lingua di TMDB.</string>
|
<string name="settings_tmdb_module_details_description">Usa info su rilascio, durata, classificazione d'età, stato, paese e lingua di TMDB.</string>
|
||||||
<string name="settings_tmdb_module_episodes">Episodi</string>
|
<string name="settings_tmdb_module_episodes">Episodi</string>
|
||||||
<string name="settings_tmdb_module_episodes_description">Usa titoli, miniature, descrizioni e durate degli episodi di TMDB per le serie.</string>
|
<string name="settings_tmdb_module_episodes_description">Usa titoli, miniature, descrizioni e durate degli episodi di TMDB per le serie.</string>
|
||||||
<string name="settings_tmdb_module_more_like_this">Altri titoli simili</string>
|
<string name="settings_tmdb_module_more_like_this">Altri titoli simili</string>
|
||||||
|
|
@ -610,7 +610,7 @@
|
||||||
<string name="settings_tmdb_section_localization">LOCALIZZAZIONE</string>
|
<string name="settings_tmdb_section_localization">LOCALIZZAZIONE</string>
|
||||||
<string name="settings_tmdb_section_modules">MODULI</string>
|
<string name="settings_tmdb_section_modules">MODULI</string>
|
||||||
<string name="settings_tmdb_section_title">TMDB</string>
|
<string name="settings_tmdb_section_title">TMDB</string>
|
||||||
<string name="settings_trakt_approval_redirect">Dopo l\'approvazione, verrai reindirizzato automaticamente.</string>
|
<string name="settings_trakt_approval_redirect">Dopo l'approvazione, verrai reindirizzato automaticamente.</string>
|
||||||
<string name="settings_trakt_authentication">AUTENTICAZIONE</string>
|
<string name="settings_trakt_authentication">AUTENTICAZIONE</string>
|
||||||
<string name="settings_trakt_comments">Commenti</string>
|
<string name="settings_trakt_comments">Commenti</string>
|
||||||
<string name="settings_trakt_comments_description">Mostra i commenti di Trakt nei dettagli di film e serie TV.</string>
|
<string name="settings_trakt_comments_description">Mostra i commenti di Trakt nei dettagli di film e serie TV.</string>
|
||||||
|
|
@ -620,7 +620,7 @@
|
||||||
<string name="settings_trakt_disconnect">Disconnetti</string>
|
<string name="settings_trakt_disconnect">Disconnetti</string>
|
||||||
<string name="settings_trakt_failed_open_browser">Impossibile aprire il browser</string>
|
<string name="settings_trakt_failed_open_browser">Impossibile aprire il browser</string>
|
||||||
<string name="settings_trakt_features">FUNZIONALITÀ</string>
|
<string name="settings_trakt_features">FUNZIONALITÀ</string>
|
||||||
<string name="settings_trakt_finish_sign_in">Completa l\'accesso a Trakt nel tuo browser</string>
|
<string name="settings_trakt_finish_sign_in">Completa l'accesso a Trakt nel tuo browser</string>
|
||||||
<string name="settings_trakt_intro_description">Tieni traccia di ciò che guardi, salva contenuti nella watchlist o in liste personalizzate e mantieni la tua libreria sincronizzata con Trakt.</string>
|
<string name="settings_trakt_intro_description">Tieni traccia di ciò che guardi, salva contenuti nella watchlist o in liste personalizzate e mantieni la tua libreria sincronizzata con Trakt.</string>
|
||||||
<string name="settings_trakt_missing_credentials">Credenziali Trakt mancanti in local.properties (TRAKT_CLIENT_ID / TRAKT_CLIENT_SECRET).</string>
|
<string name="settings_trakt_missing_credentials">Credenziali Trakt mancanti in local.properties (TRAKT_CLIENT_ID / TRAKT_CLIENT_SECRET).</string>
|
||||||
<string name="settings_trakt_open_login">Apri Login Trakt</string>
|
<string name="settings_trakt_open_login">Apri Login Trakt</string>
|
||||||
|
|
@ -737,8 +737,8 @@
|
||||||
<string name="action_no">No</string>
|
<string name="action_no">No</string>
|
||||||
<string name="action_update">Aggiorna</string>
|
<string name="action_update">Aggiorna</string>
|
||||||
<string name="action_yes">Sì</string>
|
<string name="action_yes">Sì</string>
|
||||||
<string name="app_exit_message">Vuoi uscire dall\'app?</string>
|
<string name="app_exit_message">Vuoi uscire dall'app?</string>
|
||||||
<string name="app_exit_title">Esci dall\'app</string>
|
<string name="app_exit_title">Esci dall'app</string>
|
||||||
<string name="catalog_empty_message">Questo catalogo non ha restituito alcun elemento.</string>
|
<string name="catalog_empty_message">Questo catalogo non ha restituito alcun elemento.</string>
|
||||||
<string name="catalog_empty_title">Nessun titolo trovato</string>
|
<string name="catalog_empty_title">Nessun titolo trovato</string>
|
||||||
<string name="details_check_connection">Controlla la tua connessione Wi-Fi o dati mobili e riprova.</string>
|
<string name="details_check_connection">Controlla la tua connessione Wi-Fi o dati mobili e riprova.</string>
|
||||||
|
|
@ -746,8 +746,8 @@
|
||||||
<string name="details_failed_to_load">Caricamento fallito</string>
|
<string name="details_failed_to_load">Caricamento fallito</string>
|
||||||
<string name="details_more_like_this">Altri titoli simili</string>
|
<string name="details_more_like_this">Altri titoli simili</string>
|
||||||
<string name="details_seasons">Stagioni</string>
|
<string name="details_seasons">Stagioni</string>
|
||||||
<string name="details_series_missing_numbers">L\'addon ha restituito i video per questa serie, ma nessuno include numeri di stagione o episodio.</string>
|
<string name="details_series_missing_numbers">L'addon ha restituito i video per questa serie, ma nessuno include numeri di stagione o episodio.</string>
|
||||||
<string name="details_series_no_metadata">L\'addon non ha fornito metadati sugli episodi per questa serie.</string>
|
<string name="details_series_no_metadata">L'addon non ha fornito metadati sugli episodi per questa serie.</string>
|
||||||
<string name="details_series_unpublished">Gli episodi non sono ancora stati pubblicati da questo addon.</string>
|
<string name="details_series_unpublished">Gli episodi non sono ancora stati pubblicati da questo addon.</string>
|
||||||
<string name="details_servers_unreachable">Il dispositivo è online, ma Nuvio non è riuscito a raggiungere i server richiesti.</string>
|
<string name="details_servers_unreachable">Il dispositivo è online, ma Nuvio non è riuscito a raggiungere i server richiesti.</string>
|
||||||
<string name="details_show_less">Mostra meno</string>
|
<string name="details_show_less">Mostra meno</string>
|
||||||
|
|
@ -774,7 +774,7 @@
|
||||||
<string name="episode_mark_unwatched">Segna come non visto</string>
|
<string name="episode_mark_unwatched">Segna come non visto</string>
|
||||||
<string name="episode_mark_watched">Segna come visto</string>
|
<string name="episode_mark_watched">Segna come visto</string>
|
||||||
<string name="home_continue_watching_up_next">Prossimo episodio</string>
|
<string name="home_continue_watching_up_next">Prossimo episodio</string>
|
||||||
<string name="home_continue_watching_watched">%1$d%% visto</string>
|
<string name="home_continue_watching_watched">%1$s visto</string>
|
||||||
<string name="home_empty_no_active_addons_message">Installa e convalida almeno un addon prima di caricare le righe del catalogo in Home.</string>
|
<string name="home_empty_no_active_addons_message">Installa e convalida almeno un addon prima di caricare le righe del catalogo in Home.</string>
|
||||||
<string name="home_empty_no_rows_message">Gli addon installati non espongono attualmente cataloghi compatibili con la bacheca senza gli extra richiesti.</string>
|
<string name="home_empty_no_rows_message">Gli addon installati non espongono attualmente cataloghi compatibili con la bacheca senza gli extra richiesti.</string>
|
||||||
<string name="home_empty_no_rows_title">Nessuna riga disponibile in Home</string>
|
<string name="home_empty_no_rows_title">Nessuna riga disponibile in Home</string>
|
||||||
|
|
@ -866,7 +866,7 @@
|
||||||
<string name="streams_no_direct_link">Nessun link diretto disponibile</string>
|
<string name="streams_no_direct_link">Nessun link diretto disponibile</string>
|
||||||
<string name="streams_no_metadata">Nessun metadato disponibile</string>
|
<string name="streams_no_metadata">Nessun metadato disponibile</string>
|
||||||
<string name="streams_refresh">Aggiorna flussi</string>
|
<string name="streams_refresh">Aggiorna flussi</string>
|
||||||
<string name="streams_resume_from_percent">Riprendi dal %1$d%%</string>
|
<string name="streams_resume_from_percent">Riprendi dal %1$d%</string>
|
||||||
<string name="streams_resume_from_time">Riprendi da %1$s</string>
|
<string name="streams_resume_from_time">Riprendi da %1$s</string>
|
||||||
<string name="streams_size">DIMENSIONE %1$s</string>
|
<string name="streams_size">DIMENSIONE %1$s</string>
|
||||||
<string name="trailer_close">Chiudi trailer</string>
|
<string name="trailer_close">Chiudi trailer</string>
|
||||||
|
|
@ -876,13 +876,13 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Controllo aggiornamenti fallito</string>
|
<string name="updates_check_failed">Controllo aggiornamenti fallito</string>
|
||||||
<string name="updates_download_failed">Download fallito</string>
|
<string name="updates_download_failed">Download fallito</string>
|
||||||
<string name="updates_downloading_progress">Download in corso: %1$d%%</string>
|
<string name="updates_downloading_progress">Download in corso: %1$d%</string>
|
||||||
<string name="updates_install_failed">Impossibile avviare l\'installazione</string>
|
<string name="updates_install_failed">Impossibile avviare l'installazione</string>
|
||||||
<string name="updates_latest_version">Stai utilizzando l\'ultima versione.</string>
|
<string name="updates_latest_version">Stai utilizzando l'ultima versione.</string>
|
||||||
<string name="updates_message_allow_installs">Abilita l\'installazione di app per Nuvio, quindi torna qui e continua.</string>
|
<string name="updates_message_allow_installs">Abilita l'installazione di app per Nuvio, quindi torna qui e continua.</string>
|
||||||
<string name="updates_message_downloading">Download aggiornamento in corso...</string>
|
<string name="updates_message_downloading">Download aggiornamento in corso...</string>
|
||||||
<string name="updates_message_no_updates">Nessun aggiornamento trovato.</string>
|
<string name="updates_message_no_updates">Nessun aggiornamento trovato.</string>
|
||||||
<string name="updates_message_ready">Una nuova versione è pronta per l\'installazione.</string>
|
<string name="updates_message_ready">Una nuova versione è pronta per l'installazione.</string>
|
||||||
<string name="updates_not_available">Gli aggiornamenti in-app non sono disponibili in questa versione.</string>
|
<string name="updates_not_available">Gli aggiornamenti in-app non sono disponibili in questa versione.</string>
|
||||||
<string name="updates_preparing_download">Preparazione del download</string>
|
<string name="updates_preparing_download">Preparazione del download</string>
|
||||||
<string name="updates_release_notes">Note di rilascio</string>
|
<string name="updates_release_notes">Note di rilascio</string>
|
||||||
|
|
@ -918,7 +918,7 @@
|
||||||
<string name="library_remove_title">Rimuovere dalla libreria?</string>
|
<string name="library_remove_title">Rimuovere dalla libreria?</string>
|
||||||
<string name="media_movie">Film</string>
|
<string name="media_movie">Film</string>
|
||||||
<string name="notifications_channel_episode_releases_description">Avvisi quando viene rilasciato un nuovo episodio di una serie salvata.</string>
|
<string name="notifications_channel_episode_releases_description">Avvisi quando viene rilasciato un nuovo episodio di una serie salvata.</string>
|
||||||
<string name="notifications_test_preview_body">Anteprima dell\'avviso di uscita episodio.</string>
|
<string name="notifications_test_preview_body">Anteprima dell'avviso di uscita episodio.</string>
|
||||||
<string name="notifications_test_send_failed">Impossibile inviare la notifica di test.</string>
|
<string name="notifications_test_send_failed">Impossibile inviare la notifica di test.</string>
|
||||||
<string name="notifications_test_sent_for">Notifica di test inviata per %1$s.</string>
|
<string name="notifications_test_sent_for">Notifica di test inviata per %1$s.</string>
|
||||||
<string name="player_unable_to_play_stream">Impossibile riprodurre questo flusso.</string>
|
<string name="player_unable_to_play_stream">Impossibile riprodurre questo flusso.</string>
|
||||||
|
|
@ -933,7 +933,7 @@
|
||||||
<string name="stream_default_name">Flusso</string>
|
<string name="stream_default_name">Flusso</string>
|
||||||
<string name="source_embedded">Incorporato (Embedded)</string>
|
<string name="source_embedded">Incorporato (Embedded)</string>
|
||||||
<string name="trakt_authorization_denied">Autorizzazione negata</string>
|
<string name="trakt_authorization_denied">Autorizzazione negata</string>
|
||||||
<string name="trakt_complete_sign_in_browser">Completa l\'accesso a Trakt nel tuo browser</string>
|
<string name="trakt_complete_sign_in_browser">Completa l'accesso a Trakt nel tuo browser</string>
|
||||||
<string name="trakt_invalid_callback">Callback Trakt non valido</string>
|
<string name="trakt_invalid_callback">Callback Trakt non valido</string>
|
||||||
<string name="trakt_invalid_callback_state">Stato callback Trakt non valido</string>
|
<string name="trakt_invalid_callback_state">Stato callback Trakt non valido</string>
|
||||||
<string name="trakt_invalid_token_response">Risposta token Trakt non valida</string>
|
<string name="trakt_invalid_token_response">Risposta token Trakt non valida</string>
|
||||||
|
|
@ -942,7 +942,7 @@
|
||||||
<string name="trakt_missing_auth_code">Trakt non ha restituito un codice di autorizzazione</string>
|
<string name="trakt_missing_auth_code">Trakt non ha restituito un codice di autorizzazione</string>
|
||||||
<string name="trakt_missing_credentials">Credenziali Trakt mancanti</string>
|
<string name="trakt_missing_credentials">Credenziali Trakt mancanti</string>
|
||||||
<string name="trakt_progress_load_failed">Impossibile caricare i progressi di Trakt</string>
|
<string name="trakt_progress_load_failed">Impossibile caricare i progressi di Trakt</string>
|
||||||
<string name="trakt_sign_in_complete_failed">Impossibile completare l\'accesso a Trakt</string>
|
<string name="trakt_sign_in_complete_failed">Impossibile completare l'accesso a Trakt</string>
|
||||||
<string name="trakt_user_fallback">Utente Trakt</string>
|
<string name="trakt_user_fallback">Utente Trakt</string>
|
||||||
<string name="trakt_watchlist">Watchlist</string>
|
<string name="trakt_watchlist">Watchlist</string>
|
||||||
<string name="generic_trailer">Trailer</string>
|
<string name="generic_trailer">Trailer</string>
|
||||||
|
|
@ -953,10 +953,10 @@
|
||||||
<string name="action_resume_episode">Riprendi %1$s</string>
|
<string name="action_resume_episode">Riprendi %1$s</string>
|
||||||
<string name="collections_import_error_empty_json">Il file JSON è vuoto.</string>
|
<string name="collections_import_error_empty_json">Il file JSON è vuoto.</string>
|
||||||
<string name="collections_import_error_collection_blank_id">La collezione %1$d ha un ID vuoto.</string>
|
<string name="collections_import_error_collection_blank_id">La collezione %1$d ha un ID vuoto.</string>
|
||||||
<string name="collections_import_error_collection_blank_title">La collezione \'%1$s\' ha un titolo vuoto.</string>
|
<string name="collections_import_error_collection_blank_title">La collezione '%1$s' ha un titolo vuoto.</string>
|
||||||
<string name="collections_import_error_folder_blank_id">La cartella %1$d in \'%2$s\' ha un ID vuoto.</string>
|
<string name="collections_import_error_folder_blank_id">La cartella %1$d in '%2$s' ha un ID vuoto.</string>
|
||||||
<string name="collections_import_error_folder_blank_title">La cartella \'%1$s\' in \'%2$s\' ha un titolo vuoto.</string>
|
<string name="collections_import_error_folder_blank_title">La cartella '%1$s' in '%2$s' ha un titolo vuoto.</string>
|
||||||
<string name="collections_import_error_source_blank_fields">La sorgente %1$d nella cartella \'%2$s\' presenta campi vuoti.</string>
|
<string name="collections_import_error_source_blank_fields">La sorgente %1$d nella cartella '%2$s' presenta campi vuoti.</string>
|
||||||
<string name="collections_import_error_invalid_json">JSON non valido: %1$s</string>
|
<string name="collections_import_error_invalid_json">JSON non valido: %1$s</string>
|
||||||
<string name="collections_folder_addon_not_found">Addon non trovato: %1$s</string>
|
<string name="collections_folder_addon_not_found">Addon non trovato: %1$s</string>
|
||||||
<string name="date_month_january">Gennaio</string>
|
<string name="date_month_january">Gennaio</string>
|
||||||
|
|
@ -993,7 +993,7 @@
|
||||||
<string name="details_certification">Certificazione</string>
|
<string name="details_certification">Certificazione</string>
|
||||||
<string name="details_movie_details">Dettagli film</string>
|
<string name="details_movie_details">Dettagli film</string>
|
||||||
<string name="details_original_language">Lingua originale</string>
|
<string name="details_original_language">Lingua originale</string>
|
||||||
<string name="details_origin_country">Paese d\'origine</string>
|
<string name="details_origin_country">Paese d'origine</string>
|
||||||
<string name="details_release_info">Info rilascio</string>
|
<string name="details_release_info">Info rilascio</string>
|
||||||
<string name="details_runtime">Durata</string>
|
<string name="details_runtime">Durata</string>
|
||||||
<string name="details_season_view_posters">Locandine</string>
|
<string name="details_season_view_posters">Locandine</string>
|
||||||
|
|
|
||||||
|
|
@ -687,7 +687,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Procent</string>
|
<string name="settings_playback_threshold_mode_percentage">Procent</string>
|
||||||
<string name="settings_playback_threshold_percentage">Próg procentowy</string>
|
<string name="settings_playback_threshold_percentage">Próg procentowy</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Pokaż kartę następnego odcinka, gdy odtwarzanie osiągnie ten procent.</string>
|
<string name="settings_playback_threshold_percentage_description">Pokaż kartę następnego odcinka, gdy odtwarzanie osiągnie ten procent.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Natychmiast</string>
|
<string name="settings_playback_timeout_instant">Natychmiast</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Bez limitu</string>
|
<string name="settings_playback_timeout_unlimited">Bez limitu</string>
|
||||||
|
|
@ -892,7 +892,7 @@
|
||||||
<string name="episode_mark_unwatched">Oznacz jako nieobejrzane</string>
|
<string name="episode_mark_unwatched">Oznacz jako nieobejrzane</string>
|
||||||
<string name="episode_mark_watched">Oznacz jako obejrzane</string>
|
<string name="episode_mark_watched">Oznacz jako obejrzane</string>
|
||||||
<string name="home_continue_watching_up_next">Następny</string>
|
<string name="home_continue_watching_up_next">Następny</string>
|
||||||
<string name="home_continue_watching_watched">%1$d%% obejrzane</string>
|
<string name="home_continue_watching_watched">%1$s obejrzane</string>
|
||||||
<string name="home_empty_no_active_addons_message">Zainstaluj i sprawdź co najmniej jeden dodatek przed ładowaniem wierszy katalogów na ekranie głównym.</string>
|
<string name="home_empty_no_active_addons_message">Zainstaluj i sprawdź co najmniej jeden dodatek przed ładowaniem wierszy katalogów na ekranie głównym.</string>
|
||||||
<string name="home_empty_no_rows_message">Zainstalowane dodatki nie udostępniają obecnie katalogów kompatybilnych z tablicą bez wymaganych dodatków.</string>
|
<string name="home_empty_no_rows_message">Zainstalowane dodatki nie udostępniają obecnie katalogów kompatybilnych z tablicą bez wymaganych dodatków.</string>
|
||||||
<string name="home_empty_no_rows_title">Brak dostępnych wierszy ekranu głównego</string>
|
<string name="home_empty_no_rows_title">Brak dostępnych wierszy ekranu głównego</string>
|
||||||
|
|
@ -984,7 +984,7 @@
|
||||||
<string name="streams_no_direct_link">Brak bezpośredniego linku strumienia</string>
|
<string name="streams_no_direct_link">Brak bezpośredniego linku strumienia</string>
|
||||||
<string name="streams_no_metadata">Brak dostępnych metadanych</string>
|
<string name="streams_no_metadata">Brak dostępnych metadanych</string>
|
||||||
<string name="streams_refresh">Odśwież strumienie</string>
|
<string name="streams_refresh">Odśwież strumienie</string>
|
||||||
<string name="streams_resume_from_percent">Wznów od %1$d%%</string>
|
<string name="streams_resume_from_percent">Wznów od %1$d%</string>
|
||||||
<string name="streams_resume_from_time">Wznów od %1$s</string>
|
<string name="streams_resume_from_time">Wznów od %1$s</string>
|
||||||
<string name="streams_size">ROZMIAR %1$s</string>
|
<string name="streams_size">ROZMIAR %1$s</string>
|
||||||
<string name="trailer_close">Zamknij zwiastun</string>
|
<string name="trailer_close">Zamknij zwiastun</string>
|
||||||
|
|
@ -994,7 +994,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Sprawdzanie aktualizacji nie powiodło się</string>
|
<string name="updates_check_failed">Sprawdzanie aktualizacji nie powiodło się</string>
|
||||||
<string name="updates_download_failed">Pobieranie nie powiodło się</string>
|
<string name="updates_download_failed">Pobieranie nie powiodło się</string>
|
||||||
<string name="updates_downloading_progress">Pobieranie %1$d%%</string>
|
<string name="updates_downloading_progress">Pobieranie %1$d%</string>
|
||||||
<string name="updates_install_failed">Nie można rozpocząć instalacji</string>
|
<string name="updates_install_failed">Nie można rozpocząć instalacji</string>
|
||||||
<string name="updates_latest_version">Używasz najnowszej wersji.</string>
|
<string name="updates_latest_version">Używasz najnowszej wersji.</string>
|
||||||
<string name="updates_message_allow_installs">Zezwól na instalację aplikacji dla Nuvio, a następnie wróć i kontynuuj.</string>
|
<string name="updates_message_allow_installs">Zezwól na instalację aplikacji dla Nuvio, a następnie wróć i kontynuuj.</string>
|
||||||
|
|
@ -1158,4 +1158,4 @@
|
||||||
<string name="unit_bytes_kb">KB</string>
|
<string name="unit_bytes_kb">KB</string>
|
||||||
<string name="unit_bytes_mb">MB</string>
|
<string name="unit_bytes_mb">MB</string>
|
||||||
<string name="unit_bytes_gb">GB</string>
|
<string name="unit_bytes_gb">GB</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
1161
composeApp/src/commonMain/composeResources/values-pt-rPT/strings.xml
Normal file
1161
composeApp/src/commonMain/composeResources/values-pt-rPT/strings.xml
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -569,7 +569,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Yüzde</string>
|
<string name="settings_playback_threshold_mode_percentage">Yüzde</string>
|
||||||
<string name="settings_playback_threshold_percentage">Eşik yüzdesi</string>
|
<string name="settings_playback_threshold_percentage">Eşik yüzdesi</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Oynatma bu yüzdeye ulaşınca sonraki bölüm kartını göster.</string>
|
<string name="settings_playback_threshold_percentage_description">Oynatma bu yüzdeye ulaşınca sonraki bölüm kartını göster.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Hemen</string>
|
<string name="settings_playback_timeout_instant">Hemen</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$dsn</string>
|
<string name="settings_playback_timeout_seconds">%1$dsn</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Sınırsız</string>
|
<string name="settings_playback_timeout_unlimited">Sınırsız</string>
|
||||||
|
|
@ -774,7 +774,7 @@
|
||||||
<string name="episode_mark_unwatched">İzlenmedi olarak işaretle</string>
|
<string name="episode_mark_unwatched">İzlenmedi olarak işaretle</string>
|
||||||
<string name="episode_mark_watched">İzlendi olarak işaretle</string>
|
<string name="episode_mark_watched">İzlendi olarak işaretle</string>
|
||||||
<string name="home_continue_watching_up_next">Sıradaki</string>
|
<string name="home_continue_watching_up_next">Sıradaki</string>
|
||||||
<string name="home_continue_watching_watched">%%%1$d izlendi</string>
|
<string name="home_continue_watching_watched">%1$s izlendi</string>
|
||||||
<string name="home_empty_no_active_addons_message">Ana sayfada katalog satırlarını yüklemeden önce en az bir eklenti kurup doğrula.</string>
|
<string name="home_empty_no_active_addons_message">Ana sayfada katalog satırlarını yüklemeden önce en az bir eklenti kurup doğrula.</string>
|
||||||
<string name="home_empty_no_rows_message">Kurulu eklentiler şu anda gerekli ek bilgiler olmadan ana sayfaya uyumlu katalog sunmuyor.</string>
|
<string name="home_empty_no_rows_message">Kurulu eklentiler şu anda gerekli ek bilgiler olmadan ana sayfaya uyumlu katalog sunmuyor.</string>
|
||||||
<string name="home_empty_no_rows_title">Ana sayfa satırı yok</string>
|
<string name="home_empty_no_rows_title">Ana sayfa satırı yok</string>
|
||||||
|
|
@ -866,7 +866,7 @@
|
||||||
<string name="streams_no_direct_link">Doğrudan yayın bağlantısı yok</string>
|
<string name="streams_no_direct_link">Doğrudan yayın bağlantısı yok</string>
|
||||||
<string name="streams_no_metadata">Meta veri yok</string>
|
<string name="streams_no_metadata">Meta veri yok</string>
|
||||||
<string name="streams_refresh">Yayınları yenile</string>
|
<string name="streams_refresh">Yayınları yenile</string>
|
||||||
<string name="streams_resume_from_percent">%%%1$d konumundan devam et</string>
|
<string name="streams_resume_from_percent">%1$d% konumundan devam et</string>
|
||||||
<string name="streams_resume_from_time">%1$s konumundan devam et</string>
|
<string name="streams_resume_from_time">%1$s konumundan devam et</string>
|
||||||
<string name="streams_size">BOYUT %1$s</string>
|
<string name="streams_size">BOYUT %1$s</string>
|
||||||
<string name="trailer_close">Fragmanı kapat</string>
|
<string name="trailer_close">Fragmanı kapat</string>
|
||||||
|
|
@ -876,7 +876,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Güncelleme kontrolü olmadı</string>
|
<string name="updates_check_failed">Güncelleme kontrolü olmadı</string>
|
||||||
<string name="updates_download_failed">İndirme olmadı</string>
|
<string name="updates_download_failed">İndirme olmadı</string>
|
||||||
<string name="updates_downloading_progress">İndiriliyor %%%1$d</string>
|
<string name="updates_downloading_progress">İndiriliyor %1$d%</string>
|
||||||
<string name="updates_install_failed">Kurulum başlatılamadı</string>
|
<string name="updates_install_failed">Kurulum başlatılamadı</string>
|
||||||
<string name="updates_latest_version">En güncel sürümü kullanıyorsun.</string>
|
<string name="updates_latest_version">En güncel sürümü kullanıyorsun.</string>
|
||||||
<string name="updates_message_allow_installs">Nuvio için uygulama kurulumlarına izin ver, sonra geri gelip devam et.</string>
|
<string name="updates_message_allow_installs">Nuvio için uygulama kurulumlarına izin ver, sonra geri gelip devam et.</string>
|
||||||
|
|
|
||||||
|
|
@ -110,29 +110,38 @@
|
||||||
<string name="collections_editor_tmdb_production_mode">Production</string>
|
<string name="collections_editor_tmdb_production_mode">Production</string>
|
||||||
<string name="collections_editor_tmdb_network_mode">Network</string>
|
<string name="collections_editor_tmdb_network_mode">Network</string>
|
||||||
<string name="collections_editor_tmdb_collection_mode">Collection</string>
|
<string name="collections_editor_tmdb_collection_mode">Collection</string>
|
||||||
|
<string name="collections_editor_tmdb_person_mode">Person</string>
|
||||||
|
<string name="collections_editor_tmdb_director_mode">Director</string>
|
||||||
<string name="collections_editor_tmdb_custom_mode">Custom</string>
|
<string name="collections_editor_tmdb_custom_mode">Custom</string>
|
||||||
<string name="collections_editor_tmdb_help_presets">Pick a ready-made source. You can edit or remove it after adding.</string>
|
<string name="collections_editor_tmdb_help_presets">Pick a ready-made source. You can edit or remove it after adding.</string>
|
||||||
<string name="collections_editor_tmdb_help_list">Paste a public TMDB list URL or only the number from the URL.</string>
|
<string name="collections_editor_tmdb_help_list">Paste a public TMDB list URL or only the number from the URL.</string>
|
||||||
<string name="collections_editor_tmdb_help_production">Search by studio name, or paste a TMDB company ID/URL and add it directly.</string>
|
<string name="collections_editor_tmdb_help_production">Search by studio name, or paste a TMDB company ID/URL and add it directly.</string>
|
||||||
<string name="collections_editor_tmdb_help_network">Enter a network ID. Common networks are available in Presets and quick filters.</string>
|
<string name="collections_editor_tmdb_help_network">Enter a network ID. Common networks are available in Presets and quick filters.</string>
|
||||||
<string name="collections_editor_tmdb_help_collection">Search a movie collection name or paste the collection ID from TMDB.</string>
|
<string name="collections_editor_tmdb_help_collection">Search a movie collection name or paste the collection ID from TMDB.</string>
|
||||||
|
<string name="collections_editor_tmdb_help_person">Enter a TMDB person ID or URL to build a row from cast credits.</string>
|
||||||
|
<string name="collections_editor_tmdb_help_director">Enter a TMDB person ID or URL to build a row from director credits.</string>
|
||||||
<string name="collections_editor_tmdb_help_discover">Build a live TMDB row using optional filters. Leave fields empty when you do not need that filter.</string>
|
<string name="collections_editor_tmdb_help_discover">Build a live TMDB row using optional filters. Leave fields empty when you do not need that filter.</string>
|
||||||
<string name="collections_editor_tmdb_public_list">Public TMDB list</string>
|
<string name="collections_editor_tmdb_public_list">Public TMDB list</string>
|
||||||
<string name="collections_editor_tmdb_network_id">Network ID</string>
|
<string name="collections_editor_tmdb_network_id">Network ID</string>
|
||||||
<string name="collections_editor_tmdb_collection_id">Collection ID</string>
|
<string name="collections_editor_tmdb_collection_id">Collection ID</string>
|
||||||
|
<string name="collections_editor_tmdb_person_id">Person ID</string>
|
||||||
<string name="collections_editor_tmdb_company_search">Production company name, ID, or URL</string>
|
<string name="collections_editor_tmdb_company_search">Production company name, ID, or URL</string>
|
||||||
<string name="collections_editor_tmdb_id_or_url">TMDB ID or URL</string>
|
<string name="collections_editor_tmdb_id_or_url">TMDB ID or URL</string>
|
||||||
<string name="collections_editor_tmdb_list_placeholder">https://www.themoviedb.org/list/8504994 or 8504994</string>
|
<string name="collections_editor_tmdb_list_placeholder">https://www.themoviedb.org/list/8504994 or 8504994</string>
|
||||||
<string name="collections_editor_tmdb_network_placeholder">213 for Netflix, 49 for HBO, 2739 for Disney+</string>
|
<string name="collections_editor_tmdb_network_placeholder">213 for Netflix, 49 for HBO, 2739 for Disney+</string>
|
||||||
<string name="collections_editor_tmdb_collection_placeholder">10 for Star Wars Collection</string>
|
<string name="collections_editor_tmdb_collection_placeholder">10 for Star Wars Collection</string>
|
||||||
<string name="collections_editor_tmdb_company_placeholder">Marvel Studios, 420, or company URL</string>
|
<string name="collections_editor_tmdb_company_placeholder">Marvel Studios, 420, or company URL</string>
|
||||||
|
<string name="collections_editor_tmdb_person_placeholder">31 for Tom Hanks, or person URL</string>
|
||||||
<string name="collections_editor_tmdb_search_helper">Examples: Marvel Studios, 420, or https://www.themoviedb.org/company/420.</string>
|
<string name="collections_editor_tmdb_search_helper">Examples: Marvel Studios, 420, or https://www.themoviedb.org/company/420.</string>
|
||||||
<string name="collections_editor_tmdb_collection_helper">Example: Star Wars Collection, Harry Potter Collection, or a collection URL.</string>
|
<string name="collections_editor_tmdb_collection_helper">Example: Star Wars Collection, Harry Potter Collection, or a collection URL.</string>
|
||||||
<string name="collections_editor_tmdb_network_helper">Example IDs: Netflix 213, HBO 49, Disney+ 2739.</string>
|
<string name="collections_editor_tmdb_network_helper">Example IDs: Netflix 213, HBO 49, Disney+ 2739.</string>
|
||||||
<string name="collections_editor_tmdb_list_helper">Example: https://www.themoviedb.org/list/8504994 or 8504994.</string>
|
<string name="collections_editor_tmdb_list_helper">Example: https://www.themoviedb.org/list/8504994 or 8504994.</string>
|
||||||
|
<string name="collections_editor_tmdb_person_helper">Example: https://www.themoviedb.org/person/31-tom-hanks or 31.</string>
|
||||||
<string name="collections_editor_tmdb_display_title">Display title</string>
|
<string name="collections_editor_tmdb_display_title">Display title</string>
|
||||||
<string name="collections_editor_tmdb_title_helper">Shown as the row/tab name. If blank, Nuvio creates one from the source.</string>
|
<string name="collections_editor_tmdb_title_helper">Shown as the row/tab name. If blank, Nuvio creates one from the source.</string>
|
||||||
<string name="collections_editor_tmdb_title_placeholder">Marvel Movies, Netflix Originals, Pixar</string>
|
<string name="collections_editor_tmdb_title_placeholder">Marvel Movies, Netflix Originals, Pixar</string>
|
||||||
|
<string name="collections_editor_tmdb_person_title_placeholder">Tom Hanks Movies, Favorite Actors</string>
|
||||||
|
<string name="collections_editor_tmdb_director_title_placeholder">Christopher Nolan Movies, Favorite Directors</string>
|
||||||
<string name="collections_editor_tmdb_discover_title_placeholder">Best Action Movies, Korean Dramas, 2024 Animation</string>
|
<string name="collections_editor_tmdb_discover_title_placeholder">Best Action Movies, Korean Dramas, 2024 Animation</string>
|
||||||
<string name="collections_editor_tmdb_search_results">Search Results</string>
|
<string name="collections_editor_tmdb_search_results">Search Results</string>
|
||||||
<string name="collections_editor_tmdb_collection">TMDB Collection</string>
|
<string name="collections_editor_tmdb_collection">TMDB Collection</string>
|
||||||
|
|
@ -212,6 +221,7 @@
|
||||||
<string name="collections_editor_tmdb_network_disney_plus">Disney+</string>
|
<string name="collections_editor_tmdb_network_disney_plus">Disney+</string>
|
||||||
<string name="collections_editor_tmdb_network_prime_video">Prime Video</string>
|
<string name="collections_editor_tmdb_network_prime_video">Prime Video</string>
|
||||||
<string name="collections_editor_tmdb_network_hulu">Hulu</string>
|
<string name="collections_editor_tmdb_network_hulu">Hulu</string>
|
||||||
|
<string name="collections_editor_tmdb_sort_original">Original</string>
|
||||||
<string name="collections_editor_tmdb_sort_popular">Popular</string>
|
<string name="collections_editor_tmdb_sort_popular">Popular</string>
|
||||||
<string name="collections_editor_tmdb_sort_top_rated">Top Rated</string>
|
<string name="collections_editor_tmdb_sort_top_rated">Top Rated</string>
|
||||||
<string name="collections_editor_tmdb_sort_recent">Recent</string>
|
<string name="collections_editor_tmdb_sort_recent">Recent</string>
|
||||||
|
|
@ -219,6 +229,8 @@
|
||||||
<string name="collections_editor_tmdb_subtitle_movie_collection">TMDB Movie Collection</string>
|
<string name="collections_editor_tmdb_subtitle_movie_collection">TMDB Movie Collection</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_production">Production</string>
|
<string name="collections_editor_tmdb_subtitle_production">Production</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_network">Network</string>
|
<string name="collections_editor_tmdb_subtitle_network">Network</string>
|
||||||
|
<string name="collections_editor_tmdb_subtitle_person">Person</string>
|
||||||
|
<string name="collections_editor_tmdb_subtitle_director">Director</string>
|
||||||
<string name="collections_editor_tmdb_subtitle_discover">TMDB Discover</string>
|
<string name="collections_editor_tmdb_subtitle_discover">TMDB Discover</string>
|
||||||
<string name="collections_empty_subtitle">Create one to organize your catalogs.</string>
|
<string name="collections_empty_subtitle">Create one to organize your catalogs.</string>
|
||||||
<string name="collections_empty_title">No collections yet</string>
|
<string name="collections_empty_title">No collections yet</string>
|
||||||
|
|
@ -687,7 +699,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Percentage</string>
|
<string name="settings_playback_threshold_mode_percentage">Percentage</string>
|
||||||
<string name="settings_playback_threshold_percentage">Threshold Percentage</string>
|
<string name="settings_playback_threshold_percentage">Threshold Percentage</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Show next episode card when playback reaches this percentage.</string>
|
<string name="settings_playback_threshold_percentage_description">Show next episode card when playback reaches this percentage.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$d%%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$d%</string>
|
||||||
<string name="settings_playback_timeout_instant">Instant</string>
|
<string name="settings_playback_timeout_instant">Instant</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
<string name="settings_playback_timeout_seconds">%1$ds</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Unlimited</string>
|
<string name="settings_playback_timeout_unlimited">Unlimited</string>
|
||||||
|
|
@ -892,7 +904,7 @@
|
||||||
<string name="episode_mark_unwatched">Mark as unwatched</string>
|
<string name="episode_mark_unwatched">Mark as unwatched</string>
|
||||||
<string name="episode_mark_watched">Mark as watched</string>
|
<string name="episode_mark_watched">Mark as watched</string>
|
||||||
<string name="home_continue_watching_up_next">Up next</string>
|
<string name="home_continue_watching_up_next">Up next</string>
|
||||||
<string name="home_continue_watching_watched">%1$d%% watched</string>
|
<string name="home_continue_watching_watched">%1$s watched</string>
|
||||||
<string name="home_empty_no_active_addons_message">Install and validate at least one addon before loading catalog rows on Home.</string>
|
<string name="home_empty_no_active_addons_message">Install and validate at least one addon before loading catalog rows on Home.</string>
|
||||||
<string name="home_empty_no_rows_message">Installed addons do not currently expose board-compatible catalogs without required extras.</string>
|
<string name="home_empty_no_rows_message">Installed addons do not currently expose board-compatible catalogs without required extras.</string>
|
||||||
<string name="home_empty_no_rows_title">No home rows available</string>
|
<string name="home_empty_no_rows_title">No home rows available</string>
|
||||||
|
|
@ -984,7 +996,7 @@
|
||||||
<string name="streams_no_direct_link">No direct stream link available</string>
|
<string name="streams_no_direct_link">No direct stream link available</string>
|
||||||
<string name="streams_no_metadata">No metadata available</string>
|
<string name="streams_no_metadata">No metadata available</string>
|
||||||
<string name="streams_refresh">Refresh streams</string>
|
<string name="streams_refresh">Refresh streams</string>
|
||||||
<string name="streams_resume_from_percent">Resume from %1$d%%</string>
|
<string name="streams_resume_from_percent">Resume from %1$d%</string>
|
||||||
<string name="streams_resume_from_time">Resume from %1$s</string>
|
<string name="streams_resume_from_time">Resume from %1$s</string>
|
||||||
<string name="streams_size">SIZE %1$s</string>
|
<string name="streams_size">SIZE %1$s</string>
|
||||||
<string name="trailer_close">Close trailer</string>
|
<string name="trailer_close">Close trailer</string>
|
||||||
|
|
@ -994,7 +1006,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Update check failed</string>
|
<string name="updates_check_failed">Update check failed</string>
|
||||||
<string name="updates_download_failed">Download failed</string>
|
<string name="updates_download_failed">Download failed</string>
|
||||||
<string name="updates_downloading_progress">Downloading %1$d%%</string>
|
<string name="updates_downloading_progress">Downloading %1$d%</string>
|
||||||
<string name="updates_install_failed">Unable to start installation</string>
|
<string name="updates_install_failed">Unable to start installation</string>
|
||||||
<string name="updates_latest_version">You're using the latest version.</string>
|
<string name="updates_latest_version">You're using the latest version.</string>
|
||||||
<string name="updates_message_allow_installs">Enable app installs for Nuvio, then come back and continue.</string>
|
<string name="updates_message_allow_installs">Enable app installs for Nuvio, then come back and continue.</string>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.nuvio.app.features.collection
|
||||||
|
|
||||||
|
import com.nuvio.app.features.addons.AddonCatalog
|
||||||
|
import com.nuvio.app.features.addons.ManagedAddon
|
||||||
|
|
||||||
|
internal data class ResolvedCollectionCatalog(
|
||||||
|
val addon: ManagedAddon,
|
||||||
|
val catalog: AddonCatalog,
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun List<ManagedAddon>.findCollectionCatalog(
|
||||||
|
source: CollectionCatalogSource,
|
||||||
|
): ResolvedCollectionCatalog? {
|
||||||
|
val declaredAddon = firstOrNull { it.manifest?.id == source.addonId }
|
||||||
|
val declaredCatalog = declaredAddon?.manifest?.catalogs?.findSourceCatalog(source)
|
||||||
|
if (declaredAddon != null && declaredCatalog != null) {
|
||||||
|
return ResolvedCollectionCatalog(addon = declaredAddon, catalog = declaredCatalog)
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstNotNullOfOrNull { addon ->
|
||||||
|
val catalog = addon.manifest?.catalogs?.find {
|
||||||
|
it.id == source.catalogId && it.type == source.type
|
||||||
|
} ?: return@firstNotNullOfOrNull null
|
||||||
|
ResolvedCollectionCatalog(addon = addon, catalog = catalog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun List<AvailableCatalog>.findAvailableCatalog(
|
||||||
|
source: CollectionCatalogSource,
|
||||||
|
): AvailableCatalog? {
|
||||||
|
val declaredCatalogs = filter { it.addonId == source.addonId }
|
||||||
|
return declaredCatalogs.findSourceCatalog(source)
|
||||||
|
?: firstOrNull { it.catalogId == source.catalogId && it.type == source.type }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<AddonCatalog>.findSourceCatalog(source: CollectionCatalogSource): AddonCatalog? =
|
||||||
|
find { it.id == source.catalogId && it.type == source.type }
|
||||||
|
?: find { it.id == source.catalogId.substringBefore(",") && it.type == source.type }
|
||||||
|
|
||||||
|
private fun List<AvailableCatalog>.findSourceCatalog(source: CollectionCatalogSource): AvailableCatalog? =
|
||||||
|
find { it.catalogId == source.catalogId && it.type == source.type }
|
||||||
|
?: find { it.catalogId == source.catalogId.substringBefore(",") && it.type == source.type }
|
||||||
|
|
||||||
|
|
@ -46,6 +46,8 @@ enum class TmdbBuilderMode {
|
||||||
PRODUCTION,
|
PRODUCTION,
|
||||||
NETWORK,
|
NETWORK,
|
||||||
COLLECTION,
|
COLLECTION,
|
||||||
|
PERSON,
|
||||||
|
DIRECTOR,
|
||||||
DISCOVER,
|
DISCOVER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,9 +342,15 @@ object CollectionEditorRepository {
|
||||||
} else {
|
} else {
|
||||||
_uiState.value.tmdbMediaType
|
_uiState.value.tmdbMediaType
|
||||||
}
|
}
|
||||||
|
val sortBy = when (mode) {
|
||||||
|
TmdbBuilderMode.LIST,
|
||||||
|
TmdbBuilderMode.COLLECTION -> TmdbCollectionSort.ORIGINAL.value
|
||||||
|
else -> TmdbCollectionSort.POPULAR_DESC.value
|
||||||
|
}
|
||||||
_uiState.value = _uiState.value.copy(
|
_uiState.value = _uiState.value.copy(
|
||||||
tmdbBuilderMode = mode,
|
tmdbBuilderMode = mode,
|
||||||
tmdbMediaType = mediaType,
|
tmdbMediaType = mediaType,
|
||||||
|
tmdbSortBy = sortBy,
|
||||||
tmdbMediaBoth = if (
|
tmdbMediaBoth = if (
|
||||||
mode == TmdbBuilderMode.NETWORK ||
|
mode == TmdbBuilderMode.NETWORK ||
|
||||||
mode == TmdbBuilderMode.LIST ||
|
mode == TmdbBuilderMode.LIST ||
|
||||||
|
|
@ -459,6 +467,8 @@ object CollectionEditorRepository {
|
||||||
TmdbBuilderMode.COLLECTION -> TmdbCollectionSourceType.COLLECTION
|
TmdbBuilderMode.COLLECTION -> TmdbCollectionSourceType.COLLECTION
|
||||||
TmdbBuilderMode.PRODUCTION -> TmdbCollectionSourceType.COMPANY
|
TmdbBuilderMode.PRODUCTION -> TmdbCollectionSourceType.COMPANY
|
||||||
TmdbBuilderMode.NETWORK -> TmdbCollectionSourceType.NETWORK
|
TmdbBuilderMode.NETWORK -> TmdbCollectionSourceType.NETWORK
|
||||||
|
TmdbBuilderMode.PERSON -> TmdbCollectionSourceType.PERSON
|
||||||
|
TmdbBuilderMode.DIRECTOR -> TmdbCollectionSourceType.DIRECTOR
|
||||||
TmdbBuilderMode.DISCOVER -> TmdbCollectionSourceType.DISCOVER
|
TmdbBuilderMode.DISCOVER -> TmdbCollectionSourceType.DISCOVER
|
||||||
}
|
}
|
||||||
val id = TmdbCollectionSourceResolver.parseTmdbId(state.tmdbInput)
|
val id = TmdbCollectionSourceResolver.parseTmdbId(state.tmdbInput)
|
||||||
|
|
@ -473,6 +483,8 @@ object CollectionEditorRepository {
|
||||||
TmdbCollectionSourceType.COLLECTION -> "TMDB Collection ${id ?: ""}".trim()
|
TmdbCollectionSourceType.COLLECTION -> "TMDB Collection ${id ?: ""}".trim()
|
||||||
TmdbCollectionSourceType.COMPANY -> "TMDB Production ${id ?: ""}".trim()
|
TmdbCollectionSourceType.COMPANY -> "TMDB Production ${id ?: ""}".trim()
|
||||||
TmdbCollectionSourceType.NETWORK -> "TMDB Network ${id ?: ""}".trim()
|
TmdbCollectionSourceType.NETWORK -> "TMDB Network ${id ?: ""}".trim()
|
||||||
|
TmdbCollectionSourceType.PERSON -> "TMDB Person ${id ?: ""}".trim()
|
||||||
|
TmdbCollectionSourceType.DIRECTOR -> "TMDB Director ${id ?: ""}".trim()
|
||||||
TmdbCollectionSourceType.DISCOVER -> "TMDB Discover"
|
TmdbCollectionSourceType.DISCOVER -> "TMDB Discover"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -561,6 +573,8 @@ private val coverMetadataSourceTypes = setOf(
|
||||||
TmdbCollectionSourceType.COLLECTION,
|
TmdbCollectionSourceType.COLLECTION,
|
||||||
TmdbCollectionSourceType.COMPANY,
|
TmdbCollectionSourceType.COMPANY,
|
||||||
TmdbCollectionSourceType.NETWORK,
|
TmdbCollectionSourceType.NETWORK,
|
||||||
|
TmdbCollectionSourceType.PERSON,
|
||||||
|
TmdbCollectionSourceType.DIRECTOR,
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun CollectionCatalogSource.toCollectionSource(): CollectionSource =
|
private fun CollectionCatalogSource.toCollectionSource(): CollectionSource =
|
||||||
|
|
@ -591,6 +605,8 @@ private fun selectedMediaTypes(
|
||||||
): List<TmdbCollectionMediaType> =
|
): List<TmdbCollectionMediaType> =
|
||||||
when (sourceType) {
|
when (sourceType) {
|
||||||
TmdbCollectionSourceType.COMPANY,
|
TmdbCollectionSourceType.COMPANY,
|
||||||
|
TmdbCollectionSourceType.PERSON,
|
||||||
|
TmdbCollectionSourceType.DIRECTOR,
|
||||||
TmdbCollectionSourceType.DISCOVER -> if (state.tmdbMediaBoth) {
|
TmdbCollectionSourceType.DISCOVER -> if (state.tmdbMediaBoth) {
|
||||||
listOf(TmdbCollectionMediaType.MOVIE, TmdbCollectionMediaType.TV)
|
listOf(TmdbCollectionMediaType.MOVIE, TmdbCollectionMediaType.TV)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -111,9 +111,7 @@ fun CollectionEditorScreen(
|
||||||
val genrePickerSource = genrePickerIndex?.let { editingFolder.resolvedSources.getOrNull(it) }
|
val genrePickerSource = genrePickerIndex?.let { editingFolder.resolvedSources.getOrNull(it) }
|
||||||
val genrePickerCatalogSource = genrePickerSource?.addonCatalogSource()
|
val genrePickerCatalogSource = genrePickerSource?.addonCatalogSource()
|
||||||
val genrePickerCatalog = genrePickerCatalogSource?.let { source ->
|
val genrePickerCatalog = genrePickerCatalogSource?.let { source ->
|
||||||
state.availableCatalogs.find {
|
state.availableCatalogs.findAvailableCatalog(source)
|
||||||
it.addonId == source.addonId && it.type == source.type && it.catalogId == source.catalogId
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FolderEditorPage(
|
FolderEditorPage(
|
||||||
|
|
@ -757,11 +755,7 @@ private fun FolderEditorPage(
|
||||||
} else if (addonSource != null) {
|
} else if (addonSource != null) {
|
||||||
FolderCatalogSourceCard(
|
FolderCatalogSourceCard(
|
||||||
source = addonSource,
|
source = addonSource,
|
||||||
matchingCatalog = state.availableCatalogs.find {
|
matchingCatalog = state.availableCatalogs.findAvailableCatalog(addonSource),
|
||||||
it.addonId == addonSource.addonId &&
|
|
||||||
it.type == addonSource.type &&
|
|
||||||
it.catalogId == addonSource.catalogId
|
|
||||||
},
|
|
||||||
onRemove = { CollectionEditorRepository.removeCatalogSource(index) },
|
onRemove = { CollectionEditorRepository.removeCatalogSource(index) },
|
||||||
onOpenGenrePicker = { CollectionEditorRepository.showGenrePicker(index) },
|
onOpenGenrePicker = { CollectionEditorRepository.showGenrePicker(index) },
|
||||||
)
|
)
|
||||||
|
|
@ -897,13 +891,19 @@ private fun TmdbSourcePickerScreen(
|
||||||
TmdbBuilderMode.COLLECTION -> TmdbCollectionSourceType.COLLECTION
|
TmdbBuilderMode.COLLECTION -> TmdbCollectionSourceType.COLLECTION
|
||||||
TmdbBuilderMode.PRODUCTION -> TmdbCollectionSourceType.COMPANY
|
TmdbBuilderMode.PRODUCTION -> TmdbCollectionSourceType.COMPANY
|
||||||
TmdbBuilderMode.NETWORK -> TmdbCollectionSourceType.NETWORK
|
TmdbBuilderMode.NETWORK -> TmdbCollectionSourceType.NETWORK
|
||||||
|
TmdbBuilderMode.PERSON -> TmdbCollectionSourceType.PERSON
|
||||||
|
TmdbBuilderMode.DIRECTOR -> TmdbCollectionSourceType.DIRECTOR
|
||||||
TmdbBuilderMode.DISCOVER -> TmdbCollectionSourceType.DISCOVER
|
TmdbBuilderMode.DISCOVER -> TmdbCollectionSourceType.DISCOVER
|
||||||
}
|
}
|
||||||
val requiresId = sourceType != TmdbCollectionSourceType.DISCOVER
|
val requiresId = sourceType != TmdbCollectionSourceType.DISCOVER
|
||||||
val showMediaControls = state.tmdbBuilderMode == TmdbBuilderMode.PRODUCTION ||
|
val showMediaControls = state.tmdbBuilderMode == TmdbBuilderMode.PRODUCTION ||
|
||||||
|
state.tmdbBuilderMode == TmdbBuilderMode.PERSON ||
|
||||||
|
state.tmdbBuilderMode == TmdbBuilderMode.DIRECTOR ||
|
||||||
state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
||||||
val showSortControls = state.tmdbBuilderMode == TmdbBuilderMode.PRODUCTION ||
|
val showSortControls = state.tmdbBuilderMode == TmdbBuilderMode.PRODUCTION ||
|
||||||
state.tmdbBuilderMode == TmdbBuilderMode.NETWORK ||
|
state.tmdbBuilderMode == TmdbBuilderMode.NETWORK ||
|
||||||
|
state.tmdbBuilderMode == TmdbBuilderMode.PERSON ||
|
||||||
|
state.tmdbBuilderMode == TmdbBuilderMode.DIRECTOR ||
|
||||||
state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
||||||
val showFilterControls = state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
val showFilterControls = state.tmdbBuilderMode == TmdbBuilderMode.DISCOVER
|
||||||
|
|
||||||
|
|
@ -1892,6 +1892,8 @@ private fun tmdbBuilderModeLabel(mode: TmdbBuilderMode): String =
|
||||||
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_production_mode)
|
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_production_mode)
|
||||||
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_mode)
|
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_mode)
|
||||||
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_mode)
|
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_mode)
|
||||||
|
TmdbBuilderMode.PERSON -> stringResource(Res.string.collections_editor_tmdb_person_mode)
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_director_mode)
|
||||||
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_custom_mode)
|
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_custom_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1903,6 +1905,8 @@ private fun tmdbModeHelpText(mode: TmdbBuilderMode): String =
|
||||||
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_help_production)
|
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_help_production)
|
||||||
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_help_network)
|
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_help_network)
|
||||||
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_help_collection)
|
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_help_collection)
|
||||||
|
TmdbBuilderMode.PERSON -> stringResource(Res.string.collections_editor_tmdb_help_person)
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_help_director)
|
||||||
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_help_discover)
|
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_help_discover)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1913,6 +1917,8 @@ private fun tmdbInputLabel(mode: TmdbBuilderMode): String =
|
||||||
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_id)
|
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_id)
|
||||||
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_id)
|
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_id)
|
||||||
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_company_search)
|
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_company_search)
|
||||||
|
TmdbBuilderMode.PERSON,
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_person_id)
|
||||||
else -> stringResource(Res.string.collections_editor_tmdb_id_or_url)
|
else -> stringResource(Res.string.collections_editor_tmdb_id_or_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1923,6 +1929,8 @@ private fun tmdbInputPlaceholder(mode: TmdbBuilderMode): String =
|
||||||
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_placeholder)
|
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_placeholder)
|
||||||
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_placeholder)
|
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_placeholder)
|
||||||
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_company_placeholder)
|
TmdbBuilderMode.PRODUCTION -> stringResource(Res.string.collections_editor_tmdb_company_placeholder)
|
||||||
|
TmdbBuilderMode.PERSON,
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_person_placeholder)
|
||||||
else -> stringResource(Res.string.collections_editor_tmdb_id_or_url)
|
else -> stringResource(Res.string.collections_editor_tmdb_id_or_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1933,6 +1941,8 @@ private fun tmdbInputHelper(mode: TmdbBuilderMode): String =
|
||||||
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_helper)
|
TmdbBuilderMode.COLLECTION -> stringResource(Res.string.collections_editor_tmdb_collection_helper)
|
||||||
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_helper)
|
TmdbBuilderMode.NETWORK -> stringResource(Res.string.collections_editor_tmdb_network_helper)
|
||||||
TmdbBuilderMode.LIST -> stringResource(Res.string.collections_editor_tmdb_list_helper)
|
TmdbBuilderMode.LIST -> stringResource(Res.string.collections_editor_tmdb_list_helper)
|
||||||
|
TmdbBuilderMode.PERSON,
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_person_helper)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1940,12 +1950,15 @@ private fun tmdbInputHelper(mode: TmdbBuilderMode): String =
|
||||||
private fun tmdbTitlePlaceholder(mode: TmdbBuilderMode): String =
|
private fun tmdbTitlePlaceholder(mode: TmdbBuilderMode): String =
|
||||||
when (mode) {
|
when (mode) {
|
||||||
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_discover_title_placeholder)
|
TmdbBuilderMode.DISCOVER -> stringResource(Res.string.collections_editor_tmdb_discover_title_placeholder)
|
||||||
|
TmdbBuilderMode.PERSON -> stringResource(Res.string.collections_editor_tmdb_person_title_placeholder)
|
||||||
|
TmdbBuilderMode.DIRECTOR -> stringResource(Res.string.collections_editor_tmdb_director_title_placeholder)
|
||||||
else -> stringResource(Res.string.collections_editor_tmdb_title_placeholder)
|
else -> stringResource(Res.string.collections_editor_tmdb_title_placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun tmdbSortLabel(sort: TmdbCollectionSort): String =
|
private fun tmdbSortLabel(sort: TmdbCollectionSort): String =
|
||||||
when (sort) {
|
when (sort) {
|
||||||
|
TmdbCollectionSort.ORIGINAL -> stringResource(Res.string.collections_editor_tmdb_sort_original)
|
||||||
TmdbCollectionSort.POPULAR_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_popular)
|
TmdbCollectionSort.POPULAR_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_popular)
|
||||||
TmdbCollectionSort.VOTE_AVERAGE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_top_rated)
|
TmdbCollectionSort.VOTE_AVERAGE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_top_rated)
|
||||||
TmdbCollectionSort.RELEASE_DATE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_recent)
|
TmdbCollectionSort.RELEASE_DATE_DESC -> stringResource(Res.string.collections_editor_tmdb_sort_recent)
|
||||||
|
|
@ -1979,6 +1992,16 @@ private fun tmdbSourceSubtitle(source: CollectionSource): String {
|
||||||
stringResource(Res.string.collections_editor_tmdb_series),
|
stringResource(Res.string.collections_editor_tmdb_series),
|
||||||
sort,
|
sort,
|
||||||
).joinToString(" • ")
|
).joinToString(" • ")
|
||||||
|
TmdbCollectionSourceType.PERSON -> listOf(
|
||||||
|
stringResource(Res.string.collections_editor_tmdb_subtitle_person),
|
||||||
|
media,
|
||||||
|
sort,
|
||||||
|
).joinToString(" • ")
|
||||||
|
TmdbCollectionSourceType.DIRECTOR -> listOf(
|
||||||
|
stringResource(Res.string.collections_editor_tmdb_subtitle_director),
|
||||||
|
media,
|
||||||
|
sort,
|
||||||
|
).joinToString(" • ")
|
||||||
TmdbCollectionSourceType.DISCOVER -> listOf(
|
TmdbCollectionSourceType.DISCOVER -> listOf(
|
||||||
stringResource(Res.string.collections_editor_tmdb_subtitle_discover),
|
stringResource(Res.string.collections_editor_tmdb_subtitle_discover),
|
||||||
media,
|
media,
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ enum class TmdbCollectionSourceType {
|
||||||
COMPANY,
|
COMPANY,
|
||||||
NETWORK,
|
NETWORK,
|
||||||
DISCOVER,
|
DISCOVER,
|
||||||
|
PERSON,
|
||||||
|
DIRECTOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
@ -86,6 +88,7 @@ enum class TmdbCollectionMediaType(val value: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class TmdbCollectionSort(val value: String) {
|
enum class TmdbCollectionSort(val value: String) {
|
||||||
|
ORIGINAL("original"),
|
||||||
POPULAR_DESC("popularity.desc"),
|
POPULAR_DESC("popularity.desc"),
|
||||||
VOTE_AVERAGE_DESC("vote_average.desc"),
|
VOTE_AVERAGE_DESC("vote_average.desc"),
|
||||||
RELEASE_DATE_DESC("primary_release_date.desc"),
|
RELEASE_DATE_DESC("primary_release_date.desc"),
|
||||||
|
|
@ -133,6 +136,7 @@ data class CollectionFolder(
|
||||||
val sources: List<CollectionSource> = emptyList(),
|
val sources: List<CollectionSource> = emptyList(),
|
||||||
val catalogSources: List<CollectionCatalogSource> = emptyList(),
|
val catalogSources: List<CollectionCatalogSource> = emptyList(),
|
||||||
val heroBackdropUrl: String? = null,
|
val heroBackdropUrl: String? = null,
|
||||||
|
val heroVideoUrl: String? = null,
|
||||||
val titleLogoUrl: String? = null,
|
val titleLogoUrl: String? = null,
|
||||||
) {
|
) {
|
||||||
val posterShape: PosterShape
|
val posterShape: PosterShape
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ import co.touchlab.kermit.Logger
|
||||||
import com.nuvio.app.features.addons.AddonRepository
|
import com.nuvio.app.features.addons.AddonRepository
|
||||||
import com.nuvio.app.features.addons.ManagedAddon
|
import com.nuvio.app.features.addons.ManagedAddon
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
|
|
@ -33,6 +36,8 @@ object CollectionRepository {
|
||||||
|
|
||||||
private val _collections = MutableStateFlow<List<Collection>>(emptyList())
|
private val _collections = MutableStateFlow<List<Collection>>(emptyList())
|
||||||
val collections: StateFlow<List<Collection>> = _collections.asStateFlow()
|
val collections: StateFlow<List<Collection>> = _collections.asStateFlow()
|
||||||
|
private val _localChangeEvents = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||||
|
internal val localChangeEvents: SharedFlow<Unit> = _localChangeEvents.asSharedFlow()
|
||||||
private var rawCollectionsJson: JsonElement = JsonArray(emptyList())
|
private var rawCollectionsJson: JsonElement = JsonArray(emptyList())
|
||||||
|
|
||||||
private var hasLoaded = false
|
private var hasLoaded = false
|
||||||
|
|
@ -244,16 +249,19 @@ object CollectionRepository {
|
||||||
internal fun applyFromRemote(collections: List<Collection>, rawJson: JsonElement) {
|
internal fun applyFromRemote(collections: List<Collection>, rawJson: JsonElement) {
|
||||||
rawCollectionsJson = rawJson
|
rawCollectionsJson = rawJson
|
||||||
_collections.value = collections
|
_collections.value = collections
|
||||||
persist()
|
persist(sync = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ensureLoaded() {
|
private fun ensureLoaded() {
|
||||||
if (!hasLoaded) initialize()
|
if (!hasLoaded) initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun persist() {
|
private fun persist(sync: Boolean = true) {
|
||||||
runCatching {
|
runCatching {
|
||||||
CollectionStorage.savePayload(mergedCollectionsJson().toString())
|
CollectionStorage.savePayload(mergedCollectionsJson().toString())
|
||||||
|
if (sync) {
|
||||||
|
_localChangeEvents.tryEmit(Unit)
|
||||||
|
}
|
||||||
}.onFailure { e ->
|
}.onFailure { e ->
|
||||||
log.e(e) { "Failed to persist collections" }
|
log.e(e) { "Failed to persist collections" }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.drop
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonArray
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
|
@ -125,9 +123,7 @@ object CollectionSyncService {
|
||||||
@OptIn(FlowPreview::class)
|
@OptIn(FlowPreview::class)
|
||||||
private fun observeLocalChangesAndPush() {
|
private fun observeLocalChangesAndPush() {
|
||||||
observeJob = scope.launch {
|
observeJob = scope.launch {
|
||||||
CollectionRepository.collections
|
CollectionRepository.localChangeEvents
|
||||||
.drop(1)
|
|
||||||
.distinctUntilChanged()
|
|
||||||
.debounce(PUSH_DEBOUNCE_MS)
|
.debounce(PUSH_DEBOUNCE_MS)
|
||||||
.collect {
|
.collect {
|
||||||
if (isSyncingFromRemote) return@collect
|
if (isSyncingFromRemote) return@collect
|
||||||
|
|
|
||||||
|
|
@ -140,16 +140,19 @@ object FolderDetailRepository {
|
||||||
source = source,
|
source = source,
|
||||||
type = type,
|
type = type,
|
||||||
catalogId = tmdbCatalogId(source),
|
catalogId = tmdbCatalogId(source),
|
||||||
supportsPagination = source.tmdbSourceType != TmdbCollectionSourceType.COLLECTION.name,
|
supportsPagination = source.tmdbSourceType !in setOf(
|
||||||
|
TmdbCollectionSourceType.COLLECTION.name,
|
||||||
|
TmdbCollectionSourceType.PERSON.name,
|
||||||
|
TmdbCollectionSourceType.DIRECTOR.name,
|
||||||
|
),
|
||||||
isLoading = true,
|
isLoading = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val catalogSource = source.addonCatalogSource() ?: return@forEach
|
val catalogSource = source.addonCatalogSource() ?: return@forEach
|
||||||
val addon = addons.find { it.manifest?.id == catalogSource.addonId }
|
val resolvedCatalog = addons.findCollectionCatalog(catalogSource)
|
||||||
val catalog = addon?.manifest?.catalogs?.find {
|
val addon = resolvedCatalog?.addon
|
||||||
it.id == catalogSource.catalogId && it.type == catalogSource.type
|
val catalog = resolvedCatalog?.catalog
|
||||||
}
|
|
||||||
val label = catalog?.name ?: catalogSource.catalogId
|
val label = catalog?.name ?: catalogSource.catalogId
|
||||||
val typeLabel = localizedMediaTypeLabel(catalogSource.type)
|
val typeLabel = localizedMediaTypeLabel(catalogSource.type)
|
||||||
val genreSuffix = if (catalogSource.genre != null) " · ${catalogSource.genre}" else ""
|
val genreSuffix = if (catalogSource.genre != null) " · ${catalogSource.genre}" else ""
|
||||||
|
|
@ -184,8 +187,8 @@ object FolderDetailRepository {
|
||||||
sources.forEachIndexed { sourceIndex, source ->
|
sources.forEachIndexed { sourceIndex, source ->
|
||||||
val tabIndex = if (showAll) sourceIndex + 1 else sourceIndex
|
val tabIndex = if (showAll) sourceIndex + 1 else sourceIndex
|
||||||
val catalogSource = source.addonCatalogSource()
|
val catalogSource = source.addonCatalogSource()
|
||||||
val addon = catalogSource?.let { value -> addons.find { it.manifest?.id == value.addonId } }
|
val resolvedCatalog = catalogSource?.let { addons.findCollectionCatalog(it) }
|
||||||
if (!source.isTmdb && addon == null) {
|
if (!source.isTmdb && resolvedCatalog == null) {
|
||||||
updateTab(tabIndex) {
|
updateTab(tabIndex) {
|
||||||
it.copy(
|
it.copy(
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ object TmdbCollectionSourceResolver {
|
||||||
when (sourceType) {
|
when (sourceType) {
|
||||||
TmdbCollectionSourceType.LIST -> resolveList(source, apiKey, language, page)
|
TmdbCollectionSourceType.LIST -> resolveList(source, apiKey, language, page)
|
||||||
TmdbCollectionSourceType.COLLECTION -> resolveCollection(source, apiKey, language)
|
TmdbCollectionSourceType.COLLECTION -> resolveCollection(source, apiKey, language)
|
||||||
|
TmdbCollectionSourceType.PERSON,
|
||||||
|
TmdbCollectionSourceType.DIRECTOR -> resolvePersonCredits(source, apiKey, language)
|
||||||
TmdbCollectionSourceType.COMPANY,
|
TmdbCollectionSourceType.COMPANY,
|
||||||
TmdbCollectionSourceType.NETWORK,
|
TmdbCollectionSourceType.NETWORK,
|
||||||
TmdbCollectionSourceType.DISCOVER -> resolveDiscover(source, apiKey, language, page)
|
TmdbCollectionSourceType.DISCOVER -> resolveDiscover(source, apiKey, language, page)
|
||||||
|
|
@ -85,6 +87,19 @@ object TmdbCollectionSourceResolver {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TmdbCollectionSourceType.PERSON,
|
||||||
|
TmdbCollectionSourceType.DIRECTOR -> {
|
||||||
|
val body = fetch<TmdbPersonResponse>(
|
||||||
|
endpoint = "person/$id",
|
||||||
|
apiKey = apiKey,
|
||||||
|
query = mapOf("language" to language),
|
||||||
|
) ?: error("TMDB person not found")
|
||||||
|
TmdbSourceImportMetadata(
|
||||||
|
title = body.name?.takeIf { it.isNotBlank() },
|
||||||
|
coverImageUrl = imageUrl(body.profilePath, "w500"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
TmdbCollectionSourceType.DISCOVER -> TmdbSourceImportMetadata(title = "TMDB Discover")
|
TmdbCollectionSourceType.DISCOVER -> TmdbSourceImportMetadata(title = "TMDB Discover")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +168,7 @@ object TmdbCollectionSourceResolver {
|
||||||
fun parseTmdbId(input: String): Int? {
|
fun parseTmdbId(input: String): Int? {
|
||||||
val trimmed = input.trim()
|
val trimmed = input.trim()
|
||||||
trimmed.toIntOrNull()?.let { return it }
|
trimmed.toIntOrNull()?.let { return it }
|
||||||
return Regex("""(?:list|collection|company|network)/(\d+)""")
|
return Regex("""(?:list|collection|company|network|person)/(\d+)""")
|
||||||
.find(trimmed)
|
.find(trimmed)
|
||||||
?.groupValues
|
?.groupValues
|
||||||
?.getOrNull(1)
|
?.getOrNull(1)
|
||||||
|
|
@ -193,6 +208,7 @@ object TmdbCollectionSourceResolver {
|
||||||
) ?: error("TMDB list not found")
|
) ?: error("TMDB list not found")
|
||||||
val items = body.items.orEmpty()
|
val items = body.items.orEmpty()
|
||||||
.mapNotNull { it.toPreview() }
|
.mapNotNull { it.toPreview() }
|
||||||
|
.sortedFor(source.sortBy)
|
||||||
.distinctBy { "${it.type}:${it.id}" }
|
.distinctBy { "${it.type}:${it.id}" }
|
||||||
return CatalogPage(
|
return CatalogPage(
|
||||||
items = items,
|
items = items,
|
||||||
|
|
@ -213,12 +229,35 @@ object TmdbCollectionSourceResolver {
|
||||||
query = mapOf("language" to language),
|
query = mapOf("language" to language),
|
||||||
) ?: error("TMDB collection not found")
|
) ?: error("TMDB collection not found")
|
||||||
val items = body.parts.orEmpty()
|
val items = body.parts.orEmpty()
|
||||||
.sortedBy { it.releaseDate ?: "9999" }
|
|
||||||
.mapNotNull { it.toPreview(TmdbCollectionMediaType.MOVIE) }
|
.mapNotNull { it.toPreview(TmdbCollectionMediaType.MOVIE) }
|
||||||
|
.sortedFor(source.sortBy)
|
||||||
.distinctBy { it.id }
|
.distinctBy { it.id }
|
||||||
return CatalogPage(items = items, rawItemCount = items.size, nextSkip = null)
|
return CatalogPage(items = items, rawItemCount = items.size, nextSkip = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun resolvePersonCredits(
|
||||||
|
source: CollectionSource,
|
||||||
|
apiKey: String,
|
||||||
|
language: String,
|
||||||
|
): CatalogPage {
|
||||||
|
val id = source.tmdbId ?: error("Missing TMDB person ID")
|
||||||
|
val mediaType = source.tmdbMediaType()
|
||||||
|
val body = fetch<TmdbPersonCreditsResponse>(
|
||||||
|
endpoint = "person/$id/combined_credits",
|
||||||
|
apiKey = apiKey,
|
||||||
|
query = mapOf("language" to language),
|
||||||
|
) ?: error("TMDB person credits not found")
|
||||||
|
val items = when (source.tmdbType()) {
|
||||||
|
TmdbCollectionSourceType.DIRECTOR -> body.crew.orEmpty()
|
||||||
|
.filter { it.job.equals("Director", ignoreCase = true) }
|
||||||
|
.mapNotNull { it.toPreview(mediaType) }
|
||||||
|
else -> body.cast.orEmpty().mapNotNull { it.toPreview(mediaType) }
|
||||||
|
}
|
||||||
|
.distinctBy { "${it.type}:${it.id}" }
|
||||||
|
.sortedFor(source.sortBy)
|
||||||
|
return CatalogPage(items = items, rawItemCount = items.size, nextSkip = null)
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun resolveDiscover(
|
private suspend fun resolveDiscover(
|
||||||
source: CollectionSource,
|
source: CollectionSource,
|
||||||
apiKey: String,
|
apiKey: String,
|
||||||
|
|
@ -312,6 +351,21 @@ object TmdbCollectionSourceResolver {
|
||||||
}.getOrNull()
|
}.getOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<MetaPreview>.sortedFor(sortBy: String?): List<MetaPreview> =
|
||||||
|
when (sortBy) {
|
||||||
|
TmdbCollectionSort.ORIGINAL.value -> this
|
||||||
|
TmdbCollectionSort.VOTE_AVERAGE_DESC.value -> sortedWith(
|
||||||
|
compareByDescending<MetaPreview> { it.imdbRating?.toDoubleOrNull() ?: -1.0 }
|
||||||
|
.thenByDescending { it.rawReleaseDate ?: it.releaseInfo.orEmpty() },
|
||||||
|
)
|
||||||
|
TmdbCollectionSort.RELEASE_DATE_DESC.value,
|
||||||
|
TmdbCollectionSort.FIRST_AIR_DATE_DESC.value -> sortedByDescending { it.rawReleaseDate ?: it.releaseInfo.orEmpty() }
|
||||||
|
TmdbCollectionSort.POPULAR_DESC.value,
|
||||||
|
null,
|
||||||
|
"" -> this
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
|
||||||
private fun TmdbListItem.toPreview(): MetaPreview? {
|
private fun TmdbListItem.toPreview(): MetaPreview? {
|
||||||
val media = mediaType?.lowercase()
|
val media = mediaType?.lowercase()
|
||||||
val contentType = if (media == "tv") TmdbCollectionMediaType.TV else TmdbCollectionMediaType.MOVIE
|
val contentType = if (media == "tv") TmdbCollectionMediaType.TV else TmdbCollectionMediaType.MOVIE
|
||||||
|
|
@ -362,6 +416,62 @@ object TmdbCollectionSourceResolver {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun TmdbPersonCreditCast.toPreview(mediaType: TmdbCollectionMediaType): MetaPreview? {
|
||||||
|
if (!matchesMediaType(mediaType, this.mediaType)) return null
|
||||||
|
val title = title?.takeIf { it.isNotBlank() }
|
||||||
|
?: name?.takeIf { it.isNotBlank() }
|
||||||
|
?: originalTitle?.takeIf { it.isNotBlank() }
|
||||||
|
?: originalName?.takeIf { it.isNotBlank() }
|
||||||
|
?: return null
|
||||||
|
return MetaPreview(
|
||||||
|
id = "tmdb:$id",
|
||||||
|
type = if (mediaType == TmdbCollectionMediaType.TV) "series" else "movie",
|
||||||
|
name = title,
|
||||||
|
poster = imageUrl(posterPath, "w500") ?: imageUrl(backdropPath, "w780"),
|
||||||
|
banner = imageUrl(backdropPath, "w1280"),
|
||||||
|
posterShape = PosterShape.Poster,
|
||||||
|
description = overview?.takeIf { it.isNotBlank() },
|
||||||
|
releaseInfo = when (mediaType) {
|
||||||
|
TmdbCollectionMediaType.MOVIE -> releaseDate?.take(4)
|
||||||
|
TmdbCollectionMediaType.TV -> firstAirDate?.take(4)
|
||||||
|
},
|
||||||
|
rawReleaseDate = when (mediaType) {
|
||||||
|
TmdbCollectionMediaType.MOVIE -> releaseDate
|
||||||
|
TmdbCollectionMediaType.TV -> firstAirDate
|
||||||
|
},
|
||||||
|
popularity = popularity,
|
||||||
|
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TmdbPersonCreditCrew.toPreview(mediaType: TmdbCollectionMediaType): MetaPreview? {
|
||||||
|
if (!matchesMediaType(mediaType, this.mediaType)) return null
|
||||||
|
val title = title?.takeIf { it.isNotBlank() }
|
||||||
|
?: name?.takeIf { it.isNotBlank() }
|
||||||
|
?: originalTitle?.takeIf { it.isNotBlank() }
|
||||||
|
?: originalName?.takeIf { it.isNotBlank() }
|
||||||
|
?: return null
|
||||||
|
return MetaPreview(
|
||||||
|
id = "tmdb:$id",
|
||||||
|
type = if (mediaType == TmdbCollectionMediaType.TV) "series" else "movie",
|
||||||
|
name = title,
|
||||||
|
poster = imageUrl(posterPath, "w500") ?: imageUrl(backdropPath, "w780"),
|
||||||
|
banner = imageUrl(backdropPath, "w1280"),
|
||||||
|
posterShape = PosterShape.Poster,
|
||||||
|
description = overview?.takeIf { it.isNotBlank() },
|
||||||
|
releaseInfo = when (mediaType) {
|
||||||
|
TmdbCollectionMediaType.MOVIE -> releaseDate?.take(4)
|
||||||
|
TmdbCollectionMediaType.TV -> firstAirDate?.take(4)
|
||||||
|
},
|
||||||
|
rawReleaseDate = when (mediaType) {
|
||||||
|
TmdbCollectionMediaType.MOVIE -> releaseDate
|
||||||
|
TmdbCollectionMediaType.TV -> firstAirDate
|
||||||
|
},
|
||||||
|
popularity = popularity,
|
||||||
|
imdbRating = voteAverage?.let { ((it * 10).roundToInt() / 10.0).toString() },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun CollectionSource.tmdbType(): TmdbCollectionSourceType =
|
private fun CollectionSource.tmdbType(): TmdbCollectionSourceType =
|
||||||
tmdbSourceType
|
tmdbSourceType
|
||||||
?.let { raw -> runCatching { TmdbCollectionSourceType.valueOf(raw.uppercase()) }.getOrNull() }
|
?.let { raw -> runCatching { TmdbCollectionSourceType.valueOf(raw.uppercase()) }.getOrNull() }
|
||||||
|
|
@ -370,6 +480,12 @@ object TmdbCollectionSourceResolver {
|
||||||
private fun CollectionSource.tmdbMediaType(): TmdbCollectionMediaType =
|
private fun CollectionSource.tmdbMediaType(): TmdbCollectionMediaType =
|
||||||
TmdbCollectionMediaType.fromString(mediaType)
|
TmdbCollectionMediaType.fromString(mediaType)
|
||||||
|
|
||||||
|
private fun matchesMediaType(expected: TmdbCollectionMediaType, actual: String?): Boolean =
|
||||||
|
when (expected) {
|
||||||
|
TmdbCollectionMediaType.MOVIE -> actual == "movie"
|
||||||
|
TmdbCollectionMediaType.TV -> actual == "tv"
|
||||||
|
}
|
||||||
|
|
||||||
private fun company(title: String, id: Int) = CollectionSource(
|
private fun company(title: String, id: Int) = CollectionSource(
|
||||||
provider = "tmdb",
|
provider = "tmdb",
|
||||||
tmdbSourceType = TmdbCollectionSourceType.COMPANY.name,
|
tmdbSourceType = TmdbCollectionSourceType.COMPANY.name,
|
||||||
|
|
@ -391,6 +507,7 @@ object TmdbCollectionSourceResolver {
|
||||||
private fun movieSort(sortBy: String?): String =
|
private fun movieSort(sortBy: String?): String =
|
||||||
when (sortBy) {
|
when (sortBy) {
|
||||||
TmdbCollectionSort.FIRST_AIR_DATE_DESC.value -> TmdbCollectionSort.RELEASE_DATE_DESC.value
|
TmdbCollectionSort.FIRST_AIR_DATE_DESC.value -> TmdbCollectionSort.RELEASE_DATE_DESC.value
|
||||||
|
TmdbCollectionSort.ORIGINAL.value -> TmdbCollectionSort.POPULAR_DESC.value
|
||||||
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
|
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
|
||||||
else -> sortBy
|
else -> sortBy
|
||||||
}
|
}
|
||||||
|
|
@ -398,6 +515,7 @@ object TmdbCollectionSourceResolver {
|
||||||
private fun tvSort(sortBy: String?): String =
|
private fun tvSort(sortBy: String?): String =
|
||||||
when (sortBy) {
|
when (sortBy) {
|
||||||
TmdbCollectionSort.RELEASE_DATE_DESC.value -> TmdbCollectionSort.FIRST_AIR_DATE_DESC.value
|
TmdbCollectionSort.RELEASE_DATE_DESC.value -> TmdbCollectionSort.FIRST_AIR_DATE_DESC.value
|
||||||
|
TmdbCollectionSort.ORIGINAL.value -> TmdbCollectionSort.POPULAR_DESC.value
|
||||||
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
|
null, "" -> TmdbCollectionSort.POPULAR_DESC.value
|
||||||
else -> sortBy
|
else -> sortBy
|
||||||
}
|
}
|
||||||
|
|
@ -449,6 +567,12 @@ private data class TmdbNetworkResponse(
|
||||||
@SerialName("logo_path") val logoPath: String? = null,
|
@SerialName("logo_path") val logoPath: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class TmdbPersonResponse(
|
||||||
|
val name: String? = null,
|
||||||
|
@SerialName("profile_path") val profilePath: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TmdbCompanySearchResult(
|
data class TmdbCompanySearchResult(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
|
|
@ -496,6 +620,47 @@ private data class TmdbGenreItem(
|
||||||
val name: String,
|
val name: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class TmdbPersonCreditsResponse(
|
||||||
|
val cast: List<TmdbPersonCreditCast>? = null,
|
||||||
|
val crew: List<TmdbPersonCreditCrew>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class TmdbPersonCreditCast(
|
||||||
|
val id: Int,
|
||||||
|
@SerialName("media_type") val mediaType: String? = null,
|
||||||
|
val title: String? = null,
|
||||||
|
val name: String? = null,
|
||||||
|
@SerialName("original_title") val originalTitle: String? = null,
|
||||||
|
@SerialName("original_name") val originalName: String? = null,
|
||||||
|
val overview: String? = null,
|
||||||
|
@SerialName("poster_path") val posterPath: String? = null,
|
||||||
|
@SerialName("backdrop_path") val backdropPath: String? = null,
|
||||||
|
@SerialName("release_date") val releaseDate: String? = null,
|
||||||
|
@SerialName("first_air_date") val firstAirDate: String? = null,
|
||||||
|
@SerialName("vote_average") val voteAverage: Double? = null,
|
||||||
|
val popularity: Double? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
private data class TmdbPersonCreditCrew(
|
||||||
|
val id: Int,
|
||||||
|
@SerialName("media_type") val mediaType: String? = null,
|
||||||
|
val title: String? = null,
|
||||||
|
val name: String? = null,
|
||||||
|
@SerialName("original_title") val originalTitle: String? = null,
|
||||||
|
@SerialName("original_name") val originalName: String? = null,
|
||||||
|
val overview: String? = null,
|
||||||
|
@SerialName("poster_path") val posterPath: String? = null,
|
||||||
|
@SerialName("backdrop_path") val backdropPath: String? = null,
|
||||||
|
@SerialName("release_date") val releaseDate: String? = null,
|
||||||
|
@SerialName("first_air_date") val firstAirDate: String? = null,
|
||||||
|
val job: String? = null,
|
||||||
|
@SerialName("vote_average") val voteAverage: Double? = null,
|
||||||
|
val popularity: Double? = null,
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
private data class TmdbListItem(
|
private data class TmdbListItem(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
|
|
|
||||||
|
|
@ -365,7 +365,7 @@ private fun ContinueWatchingWideCard(
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(
|
text = stringResource(
|
||||||
Res.string.home_continue_watching_watched,
|
Res.string.home_continue_watching_watched,
|
||||||
continueWatchingProgressPercent(item.progressFraction),
|
"${continueWatchingProgressPercent(item.progressFraction)}%",
|
||||||
),
|
),
|
||||||
style = MaterialTheme.typography.labelSmall.copy(
|
style = MaterialTheme.typography.labelSmall.copy(
|
||||||
fontSize = layout.progressLabelSize,
|
fontSize = layout.progressLabelSize,
|
||||||
|
|
|
||||||
|
|
@ -657,7 +657,6 @@ fun PlayerScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
playerController?.seekTo(targetPositionMs)
|
playerController?.seekTo(targetPositionMs)
|
||||||
controlsVisible = true
|
|
||||||
showSeekFeedback(direction, nextState.amountMs)
|
showSeekFeedback(direction, nextState.amountMs)
|
||||||
|
|
||||||
accumulatedSeekResetJob?.cancel()
|
accumulatedSeekResetJob?.cancel()
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ object ProfileRepository {
|
||||||
val stored = decodeStoredPayload() ?: return false
|
val stored = decodeStoredPayload() ?: return false
|
||||||
loadedCacheForUserId = stored.userId
|
loadedCacheForUserId = stored.userId
|
||||||
applyStoredPayload(stored)
|
applyStoredPayload(stored)
|
||||||
|
ThemeSettingsRepository.onProfileChanged()
|
||||||
return _state.value.profiles.isNotEmpty()
|
return _state.value.profiles.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package com.nuvio.app.features.settings
|
||||||
|
|
||||||
import nuvio.composeapp.generated.resources.Res
|
import nuvio.composeapp.generated.resources.Res
|
||||||
import nuvio.composeapp.generated.resources.lang_english
|
import nuvio.composeapp.generated.resources.lang_english
|
||||||
|
import nuvio.composeapp.generated.resources.lang_french
|
||||||
import nuvio.composeapp.generated.resources.lang_spanish
|
import nuvio.composeapp.generated.resources.lang_spanish
|
||||||
|
import nuvio.composeapp.generated.resources.lang_portuguese_portugal
|
||||||
import nuvio.composeapp.generated.resources.lang_turkish
|
import nuvio.composeapp.generated.resources.lang_turkish
|
||||||
import nuvio.composeapp.generated.resources.lang_italian
|
import nuvio.composeapp.generated.resources.lang_italian
|
||||||
import nuvio.composeapp.generated.resources.lang_greek
|
import nuvio.composeapp.generated.resources.lang_greek
|
||||||
|
|
@ -14,6 +16,7 @@ enum class AppLanguage(
|
||||||
val labelRes: StringResource,
|
val labelRes: StringResource,
|
||||||
) {
|
) {
|
||||||
ENGLISH("en", Res.string.lang_english),
|
ENGLISH("en", Res.string.lang_english),
|
||||||
|
FRENCH("fr", Res.string.lang_french),
|
||||||
SPANISH("es", Res.string.lang_spanish),
|
SPANISH("es", Res.string.lang_spanish),
|
||||||
TURKISH("tr", Res.string.lang_turkish),
|
TURKISH("tr", Res.string.lang_turkish),
|
||||||
ITALIAN("it", Res.string.lang_italian),
|
ITALIAN("it", Res.string.lang_italian),
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ actual object ThemeSettingsStorage {
|
||||||
private const val selectedThemeKey = "selected_theme"
|
private const val selectedThemeKey = "selected_theme"
|
||||||
private const val amoledEnabledKey = "amoled_enabled"
|
private const val amoledEnabledKey = "amoled_enabled"
|
||||||
private const val selectedAppLanguageKey = "selected_app_language"
|
private const val selectedAppLanguageKey = "selected_app_language"
|
||||||
private val syncKeys = listOf(selectedThemeKey, amoledEnabledKey, selectedAppLanguageKey)
|
private val profileScopedSyncKeys = listOf(selectedThemeKey, amoledEnabledKey)
|
||||||
|
private val globalSyncKeys = listOf(selectedAppLanguageKey)
|
||||||
|
|
||||||
actual fun loadSelectedTheme(): String? =
|
actual fun loadSelectedTheme(): String? =
|
||||||
NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(selectedThemeKey))
|
NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(selectedThemeKey))
|
||||||
|
|
@ -37,11 +38,16 @@ actual object ThemeSettingsStorage {
|
||||||
NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(amoledEnabledKey))
|
NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(amoledEnabledKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun loadSelectedAppLanguage(): String? =
|
actual fun loadSelectedAppLanguage(): String? {
|
||||||
NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(selectedAppLanguageKey))
|
val value = NSUserDefaults.standardUserDefaults.stringForKey(selectedAppLanguageKey)
|
||||||
|
if (value != null) return value
|
||||||
|
val legacy = NSUserDefaults.standardUserDefaults.stringForKey(ProfileScopedKey.of(selectedAppLanguageKey))
|
||||||
|
if (legacy != null) saveSelectedAppLanguage(legacy)
|
||||||
|
return legacy
|
||||||
|
}
|
||||||
|
|
||||||
actual fun saveSelectedAppLanguage(languageCode: String) {
|
actual fun saveSelectedAppLanguage(languageCode: String) {
|
||||||
NSUserDefaults.standardUserDefaults.setObject(languageCode, forKey = ProfileScopedKey.of(selectedAppLanguageKey))
|
NSUserDefaults.standardUserDefaults.setObject(languageCode, forKey = selectedAppLanguageKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun applySelectedAppLanguage(languageCode: String) = Unit
|
actual fun applySelectedAppLanguage(languageCode: String) = Unit
|
||||||
|
|
@ -53,9 +59,12 @@ actual object ThemeSettingsStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
||||||
syncKeys.forEach { key ->
|
profileScopedSyncKeys.forEach { key ->
|
||||||
NSUserDefaults.standardUserDefaults.removeObjectForKey(ProfileScopedKey.of(key))
|
NSUserDefaults.standardUserDefaults.removeObjectForKey(ProfileScopedKey.of(key))
|
||||||
}
|
}
|
||||||
|
globalSyncKeys.forEach { key ->
|
||||||
|
NSUserDefaults.standardUserDefaults.removeObjectForKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
||||||
payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled)
|
payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ ktor = "3.4.1"
|
||||||
material3 = "1.11.0-alpha07"
|
material3 = "1.11.0-alpha07"
|
||||||
androidx-media3 = "1.8.0"
|
androidx-media3 = "1.8.0"
|
||||||
supabase = "3.4.1"
|
supabase = "3.4.1"
|
||||||
quickjsKt = "1.0.1"
|
quickjsKt = "1.0.5"
|
||||||
ksoup = "0.2.6"
|
ksoup = "0.2.6"
|
||||||
reorderable = "3.0.0"
|
reorderable = "3.0.0"
|
||||||
desugarJdkLibs = "2.1.5"
|
desugarJdkLibs = "2.1.5"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
CURRENT_PROJECT_VERSION=40
|
CURRENT_PROJECT_VERSION=42
|
||||||
MARKETING_VERSION=0.1.9
|
MARKETING_VERSION=0.1.10
|
||||||
|
|
||||||
|
|
|
||||||
1
mediamp
1
mediamp
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit df33966d7fbc6eb14e43fb1892e062417d76e7f5
|
|
||||||
1
vendor/mpv-kt-upstream
vendored
1
vendor/mpv-kt-upstream
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 8a8ddddf430555878273da13006fc57e182b0c0c
|
|
||||||
Loading…
Reference in a new issue