@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Неуспешно опресняване на метаданни: ${error}",
|
"metadataRefreshFailed": "Неуспешно опресняване на метаданни: ${error}",
|
||||||
"logoutConfirm": "Сигурни ли сте, че искате да излезете?",
|
"logoutConfirm": "Сигурни ли сте, че искате да излезете?",
|
||||||
"noSeasonsFound": "Не са намерени сезони",
|
"noSeasonsFound": "Не са намерени сезони",
|
||||||
|
"seasonsLoadFailed": "Неуспешно зареждане на сезони",
|
||||||
"noEpisodesFound": "Не са намерени епизоди в първия сезон",
|
"noEpisodesFound": "Не са намерени епизоди в първия сезон",
|
||||||
"noEpisodesFoundGeneral": "Не са намерени епизоди",
|
"noEpisodesFoundGeneral": "Не са намерени епизоди",
|
||||||
|
"episodesLoadFailed": "Неуспешно зареждане на епизоди",
|
||||||
"noResultsFound": "Няма намерени резултати",
|
"noResultsFound": "Няма намерени резултати",
|
||||||
"sleepTimerSet": "Таймерът за заспиване е зададен за ${label}",
|
"sleepTimerSet": "Таймерът за заспиване е зададен за ${label}",
|
||||||
"noItemsAvailable": "Няма налични елементи",
|
"noItemsAvailable": "Няма налични елементи",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Kunne ikke opdatere metadata: ${error}",
|
"metadataRefreshFailed": "Kunne ikke opdatere metadata: ${error}",
|
||||||
"logoutConfirm": "Er du sikker på, at du vil logge ud?",
|
"logoutConfirm": "Er du sikker på, at du vil logge ud?",
|
||||||
"noSeasonsFound": "Ingen sæsoner fundet",
|
"noSeasonsFound": "Ingen sæsoner fundet",
|
||||||
|
"seasonsLoadFailed": "Kunne ikke indlæse sæsoner",
|
||||||
"noEpisodesFound": "Ingen episoder fundet i første sæson",
|
"noEpisodesFound": "Ingen episoder fundet i første sæson",
|
||||||
"noEpisodesFoundGeneral": "Ingen episoder fundet",
|
"noEpisodesFoundGeneral": "Ingen episoder fundet",
|
||||||
|
"episodesLoadFailed": "Kunne ikke indlæse episoder",
|
||||||
"noResultsFound": "Ingen resultater fundet",
|
"noResultsFound": "Ingen resultater fundet",
|
||||||
"sleepTimerSet": "Sove-timer indstillet til ${label}",
|
"sleepTimerSet": "Sove-timer indstillet til ${label}",
|
||||||
"noItemsAvailable": "Ingen elementer tilgængelige",
|
"noItemsAvailable": "Ingen elementer tilgængelige",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Metadaten konnten nicht aktualisiert werden: ${error}",
|
"metadataRefreshFailed": "Metadaten konnten nicht aktualisiert werden: ${error}",
|
||||||
"logoutConfirm": "Abmeldung wirklich durchführen?",
|
"logoutConfirm": "Abmeldung wirklich durchführen?",
|
||||||
"noSeasonsFound": "Keine Staffeln gefunden",
|
"noSeasonsFound": "Keine Staffeln gefunden",
|
||||||
|
"seasonsLoadFailed": "Staffeln konnten nicht geladen werden",
|
||||||
"noEpisodesFound": "Keine Episoden in der ersten Staffel gefunden",
|
"noEpisodesFound": "Keine Episoden in der ersten Staffel gefunden",
|
||||||
"noEpisodesFoundGeneral": "Keine Episoden gefunden",
|
"noEpisodesFoundGeneral": "Keine Episoden gefunden",
|
||||||
|
"episodesLoadFailed": "Episoden konnten nicht geladen werden",
|
||||||
"noResultsFound": "Keine Ergebnisse gefunden",
|
"noResultsFound": "Keine Ergebnisse gefunden",
|
||||||
"sleepTimerSet": "Sleep-Timer gesetzt auf ${label}",
|
"sleepTimerSet": "Sleep-Timer gesetzt auf ${label}",
|
||||||
"noItemsAvailable": "Keine Elemente verfügbar",
|
"noItemsAvailable": "Keine Elemente verfügbar",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Failed to refresh metadata: ${error}",
|
"metadataRefreshFailed": "Failed to refresh metadata: ${error}",
|
||||||
"logoutConfirm": "Are you sure you want to logout?",
|
"logoutConfirm": "Are you sure you want to logout?",
|
||||||
"noSeasonsFound": "No seasons found",
|
"noSeasonsFound": "No seasons found",
|
||||||
|
"seasonsLoadFailed": "Couldn't load seasons",
|
||||||
"noEpisodesFound": "No episodes found in first season",
|
"noEpisodesFound": "No episodes found in first season",
|
||||||
"noEpisodesFoundGeneral": "No episodes found",
|
"noEpisodesFoundGeneral": "No episodes found",
|
||||||
|
"episodesLoadFailed": "Couldn't load episodes",
|
||||||
"noResultsFound": "No results found",
|
"noResultsFound": "No results found",
|
||||||
"sleepTimerSet": "Sleep timer set for ${label}",
|
"sleepTimerSet": "Sleep timer set for ${label}",
|
||||||
"noItemsAvailable": "No items available",
|
"noItemsAvailable": "No items available",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Error al actualizar metadatos: ${error}",
|
"metadataRefreshFailed": "Error al actualizar metadatos: ${error}",
|
||||||
"logoutConfirm": "¿Estás seguro de que quieres cerrar sesión?",
|
"logoutConfirm": "¿Estás seguro de que quieres cerrar sesión?",
|
||||||
"noSeasonsFound": "No se encontraron temporadas",
|
"noSeasonsFound": "No se encontraron temporadas",
|
||||||
|
"seasonsLoadFailed": "No se pudieron cargar las temporadas",
|
||||||
"noEpisodesFound": "No se encontraron episodios en la primera temporada",
|
"noEpisodesFound": "No se encontraron episodios en la primera temporada",
|
||||||
"noEpisodesFoundGeneral": "No se encontraron episodios",
|
"noEpisodesFoundGeneral": "No se encontraron episodios",
|
||||||
|
"episodesLoadFailed": "No se pudieron cargar los episodios",
|
||||||
"noResultsFound": "No se encontraron resultados",
|
"noResultsFound": "No se encontraron resultados",
|
||||||
"sleepTimerSet": "Temporizador establecido en ${label}",
|
"sleepTimerSet": "Temporizador establecido en ${label}",
|
||||||
"noItemsAvailable": "No hay elementos disponibles",
|
"noItemsAvailable": "No hay elementos disponibles",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Échec de l'actualisation des métadonnées: ${error}",
|
"metadataRefreshFailed": "Échec de l'actualisation des métadonnées: ${error}",
|
||||||
"logoutConfirm": "Êtes-vous sûr de vouloir vous déconnecter ?",
|
"logoutConfirm": "Êtes-vous sûr de vouloir vous déconnecter ?",
|
||||||
"noSeasonsFound": "Aucune saison trouvée",
|
"noSeasonsFound": "Aucune saison trouvée",
|
||||||
|
"seasonsLoadFailed": "Impossible de charger les saisons",
|
||||||
"noEpisodesFound": "Aucun épisode trouvé dans la première saison",
|
"noEpisodesFound": "Aucun épisode trouvé dans la première saison",
|
||||||
"noEpisodesFoundGeneral": "Aucun épisode trouvé",
|
"noEpisodesFoundGeneral": "Aucun épisode trouvé",
|
||||||
|
"episodesLoadFailed": "Impossible de charger les épisodes",
|
||||||
"noResultsFound": "Aucun résultat trouvé",
|
"noResultsFound": "Aucun résultat trouvé",
|
||||||
"sleepTimerSet": "Minuterie de mise en veille réglée sur ${label}",
|
"sleepTimerSet": "Minuterie de mise en veille réglée sur ${label}",
|
||||||
"noItemsAvailable": "Aucun élément disponible",
|
"noItemsAvailable": "Aucun élément disponible",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Errore aggiornamento metadati: ${error}",
|
"metadataRefreshFailed": "Errore aggiornamento metadati: ${error}",
|
||||||
"logoutConfirm": "Sei sicuro di volerti disconnettere?",
|
"logoutConfirm": "Sei sicuro di volerti disconnettere?",
|
||||||
"noSeasonsFound": "Nessuna stagione trovata",
|
"noSeasonsFound": "Nessuna stagione trovata",
|
||||||
|
"seasonsLoadFailed": "Impossibile caricare le stagioni",
|
||||||
"noEpisodesFound": "Nessun episodio trovato nella prima stagione",
|
"noEpisodesFound": "Nessun episodio trovato nella prima stagione",
|
||||||
"noEpisodesFoundGeneral": "Nessun episodio trovato",
|
"noEpisodesFoundGeneral": "Nessun episodio trovato",
|
||||||
|
"episodesLoadFailed": "Impossibile caricare gli episodi",
|
||||||
"noResultsFound": "Nessun risultato",
|
"noResultsFound": "Nessun risultato",
|
||||||
"sleepTimerSet": "Imposta timer spegnimento per ${label}",
|
"sleepTimerSet": "Imposta timer spegnimento per ${label}",
|
||||||
"noItemsAvailable": "Nessun elemento disponibile",
|
"noItemsAvailable": "Nessun elemento disponibile",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "メタデータの更新に失敗しました: ${error}",
|
"metadataRefreshFailed": "メタデータの更新に失敗しました: ${error}",
|
||||||
"logoutConfirm": "ログアウトしてもよろしいですか?",
|
"logoutConfirm": "ログアウトしてもよろしいですか?",
|
||||||
"noSeasonsFound": "シーズンが見つかりません",
|
"noSeasonsFound": "シーズンが見つかりません",
|
||||||
|
"seasonsLoadFailed": "シーズンを読み込めませんでした",
|
||||||
"noEpisodesFound": "最初のシーズンにエピソードが見つかりません",
|
"noEpisodesFound": "最初のシーズンにエピソードが見つかりません",
|
||||||
"noEpisodesFoundGeneral": "エピソードが見つかりません",
|
"noEpisodesFoundGeneral": "エピソードが見つかりません",
|
||||||
|
"episodesLoadFailed": "エピソードを読み込めませんでした",
|
||||||
"noResultsFound": "結果が見つかりません",
|
"noResultsFound": "結果が見つかりません",
|
||||||
"sleepTimerSet": "スリープタイマーを${label}に設定しました",
|
"sleepTimerSet": "スリープタイマーを${label}に設定しました",
|
||||||
"noItemsAvailable": "アイテムがありません",
|
"noItemsAvailable": "アイテムがありません",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "메타데이터 새로고침 실패: ${error}",
|
"metadataRefreshFailed": "메타데이터 새로고침 실패: ${error}",
|
||||||
"logoutConfirm": "로그아웃 하시겠습니까?",
|
"logoutConfirm": "로그아웃 하시겠습니까?",
|
||||||
"noSeasonsFound": "시즌을 찾을 수 없음",
|
"noSeasonsFound": "시즌을 찾을 수 없음",
|
||||||
|
"seasonsLoadFailed": "시즌을 불러오지 못했습니다",
|
||||||
"noEpisodesFound": "시즌 1에서 에피소드를 찾을 수 없습니다",
|
"noEpisodesFound": "시즌 1에서 에피소드를 찾을 수 없습니다",
|
||||||
"noEpisodesFoundGeneral": "에피소드를 찾을 수 없습니다",
|
"noEpisodesFoundGeneral": "에피소드를 찾을 수 없습니다",
|
||||||
|
"episodesLoadFailed": "에피소드를 불러오지 못했습니다",
|
||||||
"noResultsFound": "결과를 찾을 수 없습니다",
|
"noResultsFound": "결과를 찾을 수 없습니다",
|
||||||
"sleepTimerSet": "수면 타이머가 ${label}로 설정 되었습니다",
|
"sleepTimerSet": "수면 타이머가 ${label}로 설정 되었습니다",
|
||||||
"noItemsAvailable": "사용 가능한 항목이 없습니다",
|
"noItemsAvailable": "사용 가능한 항목이 없습니다",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Kunne ikke oppdatere metadata: ${error}",
|
"metadataRefreshFailed": "Kunne ikke oppdatere metadata: ${error}",
|
||||||
"logoutConfirm": "Er du sikker på at du vil logge ut?",
|
"logoutConfirm": "Er du sikker på at du vil logge ut?",
|
||||||
"noSeasonsFound": "Ingen sesonger funnet",
|
"noSeasonsFound": "Ingen sesonger funnet",
|
||||||
|
"seasonsLoadFailed": "Kunne ikke laste sesonger",
|
||||||
"noEpisodesFound": "Ingen episoder funnet i første sesong",
|
"noEpisodesFound": "Ingen episoder funnet i første sesong",
|
||||||
"noEpisodesFoundGeneral": "Ingen episoder funnet",
|
"noEpisodesFoundGeneral": "Ingen episoder funnet",
|
||||||
|
"episodesLoadFailed": "Kunne ikke laste episoder",
|
||||||
"noResultsFound": "Ingen resultater funnet",
|
"noResultsFound": "Ingen resultater funnet",
|
||||||
"sleepTimerSet": "Søvntimer satt til ${label}",
|
"sleepTimerSet": "Søvntimer satt til ${label}",
|
||||||
"noItemsAvailable": "Ingen elementer tilgjengelig",
|
"noItemsAvailable": "Ingen elementer tilgjengelig",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Kon metadata niet vernieuwen: ${error}",
|
"metadataRefreshFailed": "Kon metadata niet vernieuwen: ${error}",
|
||||||
"logoutConfirm": "Weet je zeker dat je wilt uitloggen?",
|
"logoutConfirm": "Weet je zeker dat je wilt uitloggen?",
|
||||||
"noSeasonsFound": "Geen seizoenen gevonden",
|
"noSeasonsFound": "Geen seizoenen gevonden",
|
||||||
|
"seasonsLoadFailed": "Kan seizoenen niet laden",
|
||||||
"noEpisodesFound": "Geen afleveringen gevonden in eerste seizoen",
|
"noEpisodesFound": "Geen afleveringen gevonden in eerste seizoen",
|
||||||
"noEpisodesFoundGeneral": "Geen afleveringen gevonden",
|
"noEpisodesFoundGeneral": "Geen afleveringen gevonden",
|
||||||
|
"episodesLoadFailed": "Kan afleveringen niet laden",
|
||||||
"noResultsFound": "Geen resultaten gevonden",
|
"noResultsFound": "Geen resultaten gevonden",
|
||||||
"sleepTimerSet": "Slaap timer ingesteld voor ${label}",
|
"sleepTimerSet": "Slaap timer ingesteld voor ${label}",
|
||||||
"noItemsAvailable": "Geen items beschikbaar",
|
"noItemsAvailable": "Geen items beschikbaar",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Nie udało się odświeżyć metadanych: ${error}",
|
"metadataRefreshFailed": "Nie udało się odświeżyć metadanych: ${error}",
|
||||||
"logoutConfirm": "Czy na pewno chcesz się wylogować?",
|
"logoutConfirm": "Czy na pewno chcesz się wylogować?",
|
||||||
"noSeasonsFound": "Nie znaleziono sezonów",
|
"noSeasonsFound": "Nie znaleziono sezonów",
|
||||||
|
"seasonsLoadFailed": "Nie udało się załadować sezonów",
|
||||||
"noEpisodesFound": "Nie znaleziono odcinków w pierwszym sezonie",
|
"noEpisodesFound": "Nie znaleziono odcinków w pierwszym sezonie",
|
||||||
"noEpisodesFoundGeneral": "Nie znaleziono odcinków",
|
"noEpisodesFoundGeneral": "Nie znaleziono odcinków",
|
||||||
|
"episodesLoadFailed": "Nie udało się załadować odcinków",
|
||||||
"noResultsFound": "Nie znaleziono wyników",
|
"noResultsFound": "Nie znaleziono wyników",
|
||||||
"sleepTimerSet": "Wyłącznik czasowy ustawiony na ${label}",
|
"sleepTimerSet": "Wyłącznik czasowy ustawiony na ${label}",
|
||||||
"noItemsAvailable": "Brak dostępnych elementów",
|
"noItemsAvailable": "Brak dostępnych elementów",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Falha ao atualizar metadados: ${error}",
|
"metadataRefreshFailed": "Falha ao atualizar metadados: ${error}",
|
||||||
"logoutConfirm": "Tem certeza que deseja sair?",
|
"logoutConfirm": "Tem certeza que deseja sair?",
|
||||||
"noSeasonsFound": "Nenhuma temporada encontrada",
|
"noSeasonsFound": "Nenhuma temporada encontrada",
|
||||||
|
"seasonsLoadFailed": "Não foi possível carregar as temporadas",
|
||||||
"noEpisodesFound": "Nenhum episódio encontrado na primeira temporada",
|
"noEpisodesFound": "Nenhum episódio encontrado na primeira temporada",
|
||||||
"noEpisodesFoundGeneral": "Nenhum episódio encontrado",
|
"noEpisodesFoundGeneral": "Nenhum episódio encontrado",
|
||||||
|
"episodesLoadFailed": "Não foi possível carregar os episódios",
|
||||||
"noResultsFound": "Nenhum resultado encontrado",
|
"noResultsFound": "Nenhum resultado encontrado",
|
||||||
"sleepTimerSet": "Timer de sono definido para ${label}",
|
"sleepTimerSet": "Timer de sono definido para ${label}",
|
||||||
"noItemsAvailable": "Nenhum item disponível",
|
"noItemsAvailable": "Nenhum item disponível",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Не удалось обновить метаданные: ${error}",
|
"metadataRefreshFailed": "Не удалось обновить метаданные: ${error}",
|
||||||
"logoutConfirm": "Вы уверены, что хотите выйти?",
|
"logoutConfirm": "Вы уверены, что хотите выйти?",
|
||||||
"noSeasonsFound": "Сезоны не найдены",
|
"noSeasonsFound": "Сезоны не найдены",
|
||||||
|
"seasonsLoadFailed": "Не удалось загрузить сезоны",
|
||||||
"noEpisodesFound": "Эпизоды в первом сезоне не найдены",
|
"noEpisodesFound": "Эпизоды в первом сезоне не найдены",
|
||||||
"noEpisodesFoundGeneral": "Эпизоды не найдены",
|
"noEpisodesFoundGeneral": "Эпизоды не найдены",
|
||||||
|
"episodesLoadFailed": "Не удалось загрузить эпизоды",
|
||||||
"noResultsFound": "Результаты не найдены",
|
"noResultsFound": "Результаты не найдены",
|
||||||
"sleepTimerSet": "Таймер сна установлен на ${label}",
|
"sleepTimerSet": "Таймер сна установлен на ${label}",
|
||||||
"noItemsAvailable": "Нет доступных элементов",
|
"noItemsAvailable": "Нет доступных элементов",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/// To regenerate, run: `dart run slang`
|
/// To regenerate, run: `dart run slang`
|
||||||
///
|
///
|
||||||
/// Locales: 16
|
/// Locales: 16
|
||||||
/// Strings: 19072 (1192 per locale)
|
/// Strings: 19104 (1194 per locale)
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint, unused_import
|
// ignore_for_file: type=lint, unused_import
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesBg extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Неуспешно опресняване на метаданни: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Неуспешно опресняване на метаданни: ${error}';
|
||||||
@override String get logoutConfirm => 'Сигурни ли сте, че искате да излезете?';
|
@override String get logoutConfirm => 'Сигурни ли сте, че искате да излезете?';
|
||||||
@override String get noSeasonsFound => 'Не са намерени сезони';
|
@override String get noSeasonsFound => 'Не са намерени сезони';
|
||||||
|
@override String get seasonsLoadFailed => 'Неуспешно зареждане на сезони';
|
||||||
@override String get noEpisodesFound => 'Не са намерени епизоди в първия сезон';
|
@override String get noEpisodesFound => 'Не са намерени епизоди в първия сезон';
|
||||||
@override String get noEpisodesFoundGeneral => 'Не са намерени епизоди';
|
@override String get noEpisodesFoundGeneral => 'Не са намерени епизоди';
|
||||||
|
@override String get episodesLoadFailed => 'Неуспешно зареждане на епизоди';
|
||||||
@override String get noResultsFound => 'Няма намерени резултати';
|
@override String get noResultsFound => 'Няма намерени резултати';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Таймерът за заспиване е зададен за ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Таймерът за заспиване е зададен за ${label}';
|
||||||
@override String get noItemsAvailable => 'Няма налични елементи';
|
@override String get noItemsAvailable => 'Няма налични елементи';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsBg {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Неуспешно опресняване на метаданни: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Неуспешно опресняване на метаданни: ${error}',
|
||||||
'messages.logoutConfirm' => 'Сигурни ли сте, че искате да излезете?',
|
'messages.logoutConfirm' => 'Сигурни ли сте, че искате да излезете?',
|
||||||
'messages.noSeasonsFound' => 'Не са намерени сезони',
|
'messages.noSeasonsFound' => 'Не са намерени сезони',
|
||||||
|
'messages.seasonsLoadFailed' => 'Неуспешно зареждане на сезони',
|
||||||
'messages.noEpisodesFound' => 'Не са намерени епизоди в първия сезон',
|
'messages.noEpisodesFound' => 'Не са намерени епизоди в първия сезон',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Не са намерени епизоди',
|
'messages.noEpisodesFoundGeneral' => 'Не са намерени епизоди',
|
||||||
|
'messages.episodesLoadFailed' => 'Неуспешно зареждане на епизоди',
|
||||||
'messages.noResultsFound' => 'Няма намерени резултати',
|
'messages.noResultsFound' => 'Няма намерени резултати',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Таймерът за заспиване е зададен за ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Таймерът за заспиване е зададен за ${label}',
|
||||||
'messages.noItemsAvailable' => 'Няма налични елементи',
|
'messages.noItemsAvailable' => 'Няма налични елементи',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsBg {
|
|||||||
'mpvConfig.loadPreset' => 'Зареди',
|
'mpvConfig.loadPreset' => 'Зареди',
|
||||||
'mpvConfig.deletePreset' => 'Изтрий',
|
'mpvConfig.deletePreset' => 'Изтрий',
|
||||||
'mpvConfig.presetSaved' => 'Пресетът е запазен',
|
'mpvConfig.presetSaved' => 'Пресетът е запазен',
|
||||||
'mpvConfig.presetLoaded' => 'Пресетът е зареден',
|
|
||||||
'mpvConfig.presetDeleted' => 'Пресетът е изтрит',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Пресетът е зареден',
|
||||||
|
'mpvConfig.presetDeleted' => 'Пресетът е изтрит',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Сигурни ли сте, че искате да изтриете този пресет?',
|
'mpvConfig.confirmDeletePreset' => 'Сигурни ли сте, че искате да изтриете този пресет?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Потвърждение на действие',
|
'dialog.confirmAction' => 'Потвърждение на действие',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsBg {
|
|||||||
'externalPlayer.playerPackage' => 'Име на пакет',
|
'externalPlayer.playerPackage' => 'Име на пакет',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL схема',
|
'externalPlayer.playerUrlScheme' => 'URL схема',
|
||||||
'externalPlayer.off' => 'Изключено',
|
'externalPlayer.off' => 'Изключено',
|
||||||
'externalPlayer.launchFailed' => 'Неуспешно отваряне на външен плеър',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не е инсталиран',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Неуспешно отваряне на външен плеър',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не е инсталиран',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Пусни във външен плеър',
|
'externalPlayer.playInExternalPlayer' => 'Пусни във външен плеър',
|
||||||
'metadataEdit.editMetadata' => 'Редактирай...',
|
'metadataEdit.editMetadata' => 'Редактирай...',
|
||||||
'metadataEdit.screenTitle' => 'Редактиране на метаданни',
|
'metadataEdit.screenTitle' => 'Редактиране на метаданни',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesDa extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Kunne ikke opdatere metadata: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Kunne ikke opdatere metadata: ${error}';
|
||||||
@override String get logoutConfirm => 'Er du sikker på, at du vil logge ud?';
|
@override String get logoutConfirm => 'Er du sikker på, at du vil logge ud?';
|
||||||
@override String get noSeasonsFound => 'Ingen sæsoner fundet';
|
@override String get noSeasonsFound => 'Ingen sæsoner fundet';
|
||||||
|
@override String get seasonsLoadFailed => 'Kunne ikke indlæse sæsoner';
|
||||||
@override String get noEpisodesFound => 'Ingen episoder fundet i første sæson';
|
@override String get noEpisodesFound => 'Ingen episoder fundet i første sæson';
|
||||||
@override String get noEpisodesFoundGeneral => 'Ingen episoder fundet';
|
@override String get noEpisodesFoundGeneral => 'Ingen episoder fundet';
|
||||||
|
@override String get episodesLoadFailed => 'Kunne ikke indlæse episoder';
|
||||||
@override String get noResultsFound => 'Ingen resultater fundet';
|
@override String get noResultsFound => 'Ingen resultater fundet';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Sove-timer indstillet til ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Sove-timer indstillet til ${label}';
|
||||||
@override String get noItemsAvailable => 'Ingen elementer tilgængelige';
|
@override String get noItemsAvailable => 'Ingen elementer tilgængelige';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsDa {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kunne ikke opdatere metadata: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kunne ikke opdatere metadata: ${error}',
|
||||||
'messages.logoutConfirm' => 'Er du sikker på, at du vil logge ud?',
|
'messages.logoutConfirm' => 'Er du sikker på, at du vil logge ud?',
|
||||||
'messages.noSeasonsFound' => 'Ingen sæsoner fundet',
|
'messages.noSeasonsFound' => 'Ingen sæsoner fundet',
|
||||||
|
'messages.seasonsLoadFailed' => 'Kunne ikke indlæse sæsoner',
|
||||||
'messages.noEpisodesFound' => 'Ingen episoder fundet i første sæson',
|
'messages.noEpisodesFound' => 'Ingen episoder fundet i første sæson',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Ingen episoder fundet',
|
'messages.noEpisodesFoundGeneral' => 'Ingen episoder fundet',
|
||||||
|
'messages.episodesLoadFailed' => 'Kunne ikke indlæse episoder',
|
||||||
'messages.noResultsFound' => 'Ingen resultater fundet',
|
'messages.noResultsFound' => 'Ingen resultater fundet',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Sove-timer indstillet til ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Sove-timer indstillet til ${label}',
|
||||||
'messages.noItemsAvailable' => 'Ingen elementer tilgængelige',
|
'messages.noItemsAvailable' => 'Ingen elementer tilgængelige',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsDa {
|
|||||||
'mpvConfig.loadPreset' => 'Indlæs',
|
'mpvConfig.loadPreset' => 'Indlæs',
|
||||||
'mpvConfig.deletePreset' => 'Slet',
|
'mpvConfig.deletePreset' => 'Slet',
|
||||||
'mpvConfig.presetSaved' => 'Forudindstilling gemt',
|
'mpvConfig.presetSaved' => 'Forudindstilling gemt',
|
||||||
'mpvConfig.presetLoaded' => 'Forudindstilling indlæst',
|
|
||||||
'mpvConfig.presetDeleted' => 'Forudindstilling slettet',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Forudindstilling indlæst',
|
||||||
|
'mpvConfig.presetDeleted' => 'Forudindstilling slettet',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Er du sikker på, at du vil slette denne forudindstilling?',
|
'mpvConfig.confirmDeletePreset' => 'Er du sikker på, at du vil slette denne forudindstilling?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Bekræft handling',
|
'dialog.confirmAction' => 'Bekræft handling',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsDa {
|
|||||||
'externalPlayer.playerPackage' => 'Pakkenavn',
|
'externalPlayer.playerPackage' => 'Pakkenavn',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-skema',
|
'externalPlayer.playerUrlScheme' => 'URL-skema',
|
||||||
'externalPlayer.off' => 'Fra',
|
'externalPlayer.off' => 'Fra',
|
||||||
'externalPlayer.launchFailed' => 'Kunne ikke åbne ekstern afspiller',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installeret',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Kunne ikke åbne ekstern afspiller',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installeret',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Afspil i ekstern afspiller',
|
'externalPlayer.playInExternalPlayer' => 'Afspil i ekstern afspiller',
|
||||||
'metadataEdit.editMetadata' => 'Redigér...',
|
'metadataEdit.editMetadata' => 'Redigér...',
|
||||||
'metadataEdit.screenTitle' => 'Redigér metadata',
|
'metadataEdit.screenTitle' => 'Redigér metadata',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesDe extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Metadaten konnten nicht aktualisiert werden: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Metadaten konnten nicht aktualisiert werden: ${error}';
|
||||||
@override String get logoutConfirm => 'Abmeldung wirklich durchführen?';
|
@override String get logoutConfirm => 'Abmeldung wirklich durchführen?';
|
||||||
@override String get noSeasonsFound => 'Keine Staffeln gefunden';
|
@override String get noSeasonsFound => 'Keine Staffeln gefunden';
|
||||||
|
@override String get seasonsLoadFailed => 'Staffeln konnten nicht geladen werden';
|
||||||
@override String get noEpisodesFound => 'Keine Episoden in der ersten Staffel gefunden';
|
@override String get noEpisodesFound => 'Keine Episoden in der ersten Staffel gefunden';
|
||||||
@override String get noEpisodesFoundGeneral => 'Keine Episoden gefunden';
|
@override String get noEpisodesFoundGeneral => 'Keine Episoden gefunden';
|
||||||
|
@override String get episodesLoadFailed => 'Episoden konnten nicht geladen werden';
|
||||||
@override String get noResultsFound => 'Keine Ergebnisse gefunden';
|
@override String get noResultsFound => 'Keine Ergebnisse gefunden';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Sleep-Timer gesetzt auf ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Sleep-Timer gesetzt auf ${label}';
|
||||||
@override String get noItemsAvailable => 'Keine Elemente verfügbar';
|
@override String get noItemsAvailable => 'Keine Elemente verfügbar';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsDe {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Metadaten konnten nicht aktualisiert werden: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Metadaten konnten nicht aktualisiert werden: ${error}',
|
||||||
'messages.logoutConfirm' => 'Abmeldung wirklich durchführen?',
|
'messages.logoutConfirm' => 'Abmeldung wirklich durchführen?',
|
||||||
'messages.noSeasonsFound' => 'Keine Staffeln gefunden',
|
'messages.noSeasonsFound' => 'Keine Staffeln gefunden',
|
||||||
|
'messages.seasonsLoadFailed' => 'Staffeln konnten nicht geladen werden',
|
||||||
'messages.noEpisodesFound' => 'Keine Episoden in der ersten Staffel gefunden',
|
'messages.noEpisodesFound' => 'Keine Episoden in der ersten Staffel gefunden',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Keine Episoden gefunden',
|
'messages.noEpisodesFoundGeneral' => 'Keine Episoden gefunden',
|
||||||
|
'messages.episodesLoadFailed' => 'Episoden konnten nicht geladen werden',
|
||||||
'messages.noResultsFound' => 'Keine Ergebnisse gefunden',
|
'messages.noResultsFound' => 'Keine Ergebnisse gefunden',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Sleep-Timer gesetzt auf ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Sleep-Timer gesetzt auf ${label}',
|
||||||
'messages.noItemsAvailable' => 'Keine Elemente verfügbar',
|
'messages.noItemsAvailable' => 'Keine Elemente verfügbar',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsDe {
|
|||||||
'mpvConfig.loadPreset' => 'Laden',
|
'mpvConfig.loadPreset' => 'Laden',
|
||||||
'mpvConfig.deletePreset' => 'Löschen',
|
'mpvConfig.deletePreset' => 'Löschen',
|
||||||
'mpvConfig.presetSaved' => 'Voreinstellung gespeichert',
|
'mpvConfig.presetSaved' => 'Voreinstellung gespeichert',
|
||||||
'mpvConfig.presetLoaded' => 'Voreinstellung geladen',
|
|
||||||
'mpvConfig.presetDeleted' => 'Voreinstellung gelöscht',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Voreinstellung geladen',
|
||||||
|
'mpvConfig.presetDeleted' => 'Voreinstellung gelöscht',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Möchten Sie diese Voreinstellung wirklich löschen?',
|
'mpvConfig.confirmDeletePreset' => 'Möchten Sie diese Voreinstellung wirklich löschen?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Aktion bestätigen',
|
'dialog.confirmAction' => 'Aktion bestätigen',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsDe {
|
|||||||
'externalPlayer.playerPackage' => 'Paketname',
|
'externalPlayer.playerPackage' => 'Paketname',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-Schema',
|
'externalPlayer.playerUrlScheme' => 'URL-Schema',
|
||||||
'externalPlayer.off' => 'Aus',
|
'externalPlayer.off' => 'Aus',
|
||||||
'externalPlayer.launchFailed' => 'Externer Player konnte nicht geöffnet werden',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} ist nicht installiert',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Externer Player konnte nicht geöffnet werden',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} ist nicht installiert',
|
||||||
'externalPlayer.playInExternalPlayer' => 'In externem Player abspielen',
|
'externalPlayer.playInExternalPlayer' => 'In externem Player abspielen',
|
||||||
'metadataEdit.editMetadata' => 'Bearbeiten...',
|
'metadataEdit.editMetadata' => 'Bearbeiten...',
|
||||||
'metadataEdit.screenTitle' => 'Metadaten bearbeiten',
|
'metadataEdit.screenTitle' => 'Metadaten bearbeiten',
|
||||||
|
|||||||
@@ -1560,12 +1560,18 @@ class TranslationsMessagesEn {
|
|||||||
/// en: 'No seasons found'
|
/// en: 'No seasons found'
|
||||||
String get noSeasonsFound => 'No seasons found';
|
String get noSeasonsFound => 'No seasons found';
|
||||||
|
|
||||||
|
/// en: 'Couldn't load seasons'
|
||||||
|
String get seasonsLoadFailed => 'Couldn\'t load seasons';
|
||||||
|
|
||||||
/// en: 'No episodes found in first season'
|
/// en: 'No episodes found in first season'
|
||||||
String get noEpisodesFound => 'No episodes found in first season';
|
String get noEpisodesFound => 'No episodes found in first season';
|
||||||
|
|
||||||
/// en: 'No episodes found'
|
/// en: 'No episodes found'
|
||||||
String get noEpisodesFoundGeneral => 'No episodes found';
|
String get noEpisodesFoundGeneral => 'No episodes found';
|
||||||
|
|
||||||
|
/// en: 'Couldn't load episodes'
|
||||||
|
String get episodesLoadFailed => 'Couldn\'t load episodes';
|
||||||
|
|
||||||
/// en: 'No results found'
|
/// en: 'No results found'
|
||||||
String get noResultsFound => 'No results found';
|
String get noResultsFound => 'No results found';
|
||||||
|
|
||||||
@@ -4685,8 +4691,10 @@ extension on Translations {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Failed to refresh metadata: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Failed to refresh metadata: ${error}',
|
||||||
'messages.logoutConfirm' => 'Are you sure you want to logout?',
|
'messages.logoutConfirm' => 'Are you sure you want to logout?',
|
||||||
'messages.noSeasonsFound' => 'No seasons found',
|
'messages.noSeasonsFound' => 'No seasons found',
|
||||||
|
'messages.seasonsLoadFailed' => 'Couldn\'t load seasons',
|
||||||
'messages.noEpisodesFound' => 'No episodes found in first season',
|
'messages.noEpisodesFound' => 'No episodes found in first season',
|
||||||
'messages.noEpisodesFoundGeneral' => 'No episodes found',
|
'messages.noEpisodesFoundGeneral' => 'No episodes found',
|
||||||
|
'messages.episodesLoadFailed' => 'Couldn\'t load episodes',
|
||||||
'messages.noResultsFound' => 'No results found',
|
'messages.noResultsFound' => 'No results found',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Sleep timer set for ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Sleep timer set for ${label}',
|
||||||
'messages.noItemsAvailable' => 'No items available',
|
'messages.noItemsAvailable' => 'No items available',
|
||||||
@@ -4721,10 +4729,10 @@ extension on Translations {
|
|||||||
'mpvConfig.loadPreset' => 'Load',
|
'mpvConfig.loadPreset' => 'Load',
|
||||||
'mpvConfig.deletePreset' => 'Delete',
|
'mpvConfig.deletePreset' => 'Delete',
|
||||||
'mpvConfig.presetSaved' => 'Preset saved',
|
'mpvConfig.presetSaved' => 'Preset saved',
|
||||||
'mpvConfig.presetLoaded' => 'Preset loaded',
|
|
||||||
'mpvConfig.presetDeleted' => 'Preset deleted',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Preset loaded',
|
||||||
|
'mpvConfig.presetDeleted' => 'Preset deleted',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Are you sure you want to delete this preset?',
|
'mpvConfig.confirmDeletePreset' => 'Are you sure you want to delete this preset?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Confirm Action',
|
'dialog.confirmAction' => 'Confirm Action',
|
||||||
@@ -5235,10 +5243,10 @@ extension on Translations {
|
|||||||
'externalPlayer.playerPackage' => 'Package Name',
|
'externalPlayer.playerPackage' => 'Package Name',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL Scheme',
|
'externalPlayer.playerUrlScheme' => 'URL Scheme',
|
||||||
'externalPlayer.off' => 'Off',
|
'externalPlayer.off' => 'Off',
|
||||||
'externalPlayer.launchFailed' => 'Failed to open external player',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is not installed',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Failed to open external player',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is not installed',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Play in External Player',
|
'externalPlayer.playInExternalPlayer' => 'Play in External Player',
|
||||||
'metadataEdit.editMetadata' => 'Edit...',
|
'metadataEdit.editMetadata' => 'Edit...',
|
||||||
'metadataEdit.screenTitle' => 'Edit Metadata',
|
'metadataEdit.screenTitle' => 'Edit Metadata',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesEs extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Error al actualizar metadatos: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Error al actualizar metadatos: ${error}';
|
||||||
@override String get logoutConfirm => '¿Estás seguro de que quieres cerrar sesión?';
|
@override String get logoutConfirm => '¿Estás seguro de que quieres cerrar sesión?';
|
||||||
@override String get noSeasonsFound => 'No se encontraron temporadas';
|
@override String get noSeasonsFound => 'No se encontraron temporadas';
|
||||||
|
@override String get seasonsLoadFailed => 'No se pudieron cargar las temporadas';
|
||||||
@override String get noEpisodesFound => 'No se encontraron episodios en la primera temporada';
|
@override String get noEpisodesFound => 'No se encontraron episodios en la primera temporada';
|
||||||
@override String get noEpisodesFoundGeneral => 'No se encontraron episodios';
|
@override String get noEpisodesFoundGeneral => 'No se encontraron episodios';
|
||||||
|
@override String get episodesLoadFailed => 'No se pudieron cargar los episodios';
|
||||||
@override String get noResultsFound => 'No se encontraron resultados';
|
@override String get noResultsFound => 'No se encontraron resultados';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Temporizador establecido en ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Temporizador establecido en ${label}';
|
||||||
@override String get noItemsAvailable => 'No hay elementos disponibles';
|
@override String get noItemsAvailable => 'No hay elementos disponibles';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsEs {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Error al actualizar metadatos: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Error al actualizar metadatos: ${error}',
|
||||||
'messages.logoutConfirm' => '¿Estás seguro de que quieres cerrar sesión?',
|
'messages.logoutConfirm' => '¿Estás seguro de que quieres cerrar sesión?',
|
||||||
'messages.noSeasonsFound' => 'No se encontraron temporadas',
|
'messages.noSeasonsFound' => 'No se encontraron temporadas',
|
||||||
|
'messages.seasonsLoadFailed' => 'No se pudieron cargar las temporadas',
|
||||||
'messages.noEpisodesFound' => 'No se encontraron episodios en la primera temporada',
|
'messages.noEpisodesFound' => 'No se encontraron episodios en la primera temporada',
|
||||||
'messages.noEpisodesFoundGeneral' => 'No se encontraron episodios',
|
'messages.noEpisodesFoundGeneral' => 'No se encontraron episodios',
|
||||||
|
'messages.episodesLoadFailed' => 'No se pudieron cargar los episodios',
|
||||||
'messages.noResultsFound' => 'No se encontraron resultados',
|
'messages.noResultsFound' => 'No se encontraron resultados',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Temporizador establecido en ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Temporizador establecido en ${label}',
|
||||||
'messages.noItemsAvailable' => 'No hay elementos disponibles',
|
'messages.noItemsAvailable' => 'No hay elementos disponibles',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsEs {
|
|||||||
'mpvConfig.loadPreset' => 'Cargar',
|
'mpvConfig.loadPreset' => 'Cargar',
|
||||||
'mpvConfig.deletePreset' => 'Eliminar',
|
'mpvConfig.deletePreset' => 'Eliminar',
|
||||||
'mpvConfig.presetSaved' => 'Ajuste guardado',
|
'mpvConfig.presetSaved' => 'Ajuste guardado',
|
||||||
'mpvConfig.presetLoaded' => 'Ajuste cargado',
|
|
||||||
'mpvConfig.presetDeleted' => 'Ajuste eliminado',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Ajuste cargado',
|
||||||
|
'mpvConfig.presetDeleted' => 'Ajuste eliminado',
|
||||||
'mpvConfig.confirmDeletePreset' => '¿Estás seguro de que quieres eliminar este ajuste?',
|
'mpvConfig.confirmDeletePreset' => '¿Estás seguro de que quieres eliminar este ajuste?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Confirmar Acción',
|
'dialog.confirmAction' => 'Confirmar Acción',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsEs {
|
|||||||
'externalPlayer.playerPackage' => 'Nombre del paquete',
|
'externalPlayer.playerPackage' => 'Nombre del paquete',
|
||||||
'externalPlayer.playerUrlScheme' => 'Esquema URL',
|
'externalPlayer.playerUrlScheme' => 'Esquema URL',
|
||||||
'externalPlayer.off' => 'Desactivado',
|
'externalPlayer.off' => 'Desactivado',
|
||||||
'externalPlayer.launchFailed' => 'No se pudo abrir el reproductor externo',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} no está instalado',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'No se pudo abrir el reproductor externo',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} no está instalado',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Reproducir en reproductor externo',
|
'externalPlayer.playInExternalPlayer' => 'Reproducir en reproductor externo',
|
||||||
'metadataEdit.editMetadata' => 'Editar...',
|
'metadataEdit.editMetadata' => 'Editar...',
|
||||||
'metadataEdit.screenTitle' => 'Editar metadatos',
|
'metadataEdit.screenTitle' => 'Editar metadatos',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesFr extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Échec de l\'actualisation des métadonnées: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Échec de l\'actualisation des métadonnées: ${error}';
|
||||||
@override String get logoutConfirm => 'Êtes-vous sûr de vouloir vous déconnecter ?';
|
@override String get logoutConfirm => 'Êtes-vous sûr de vouloir vous déconnecter ?';
|
||||||
@override String get noSeasonsFound => 'Aucune saison trouvée';
|
@override String get noSeasonsFound => 'Aucune saison trouvée';
|
||||||
|
@override String get seasonsLoadFailed => 'Impossible de charger les saisons';
|
||||||
@override String get noEpisodesFound => 'Aucun épisode trouvé dans la première saison';
|
@override String get noEpisodesFound => 'Aucun épisode trouvé dans la première saison';
|
||||||
@override String get noEpisodesFoundGeneral => 'Aucun épisode trouvé';
|
@override String get noEpisodesFoundGeneral => 'Aucun épisode trouvé';
|
||||||
|
@override String get episodesLoadFailed => 'Impossible de charger les épisodes';
|
||||||
@override String get noResultsFound => 'Aucun résultat trouvé';
|
@override String get noResultsFound => 'Aucun résultat trouvé';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Minuterie de mise en veille réglée sur ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Minuterie de mise en veille réglée sur ${label}';
|
||||||
@override String get noItemsAvailable => 'Aucun élément disponible';
|
@override String get noItemsAvailable => 'Aucun élément disponible';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsFr {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Échec de l\'actualisation des métadonnées: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Échec de l\'actualisation des métadonnées: ${error}',
|
||||||
'messages.logoutConfirm' => 'Êtes-vous sûr de vouloir vous déconnecter ?',
|
'messages.logoutConfirm' => 'Êtes-vous sûr de vouloir vous déconnecter ?',
|
||||||
'messages.noSeasonsFound' => 'Aucune saison trouvée',
|
'messages.noSeasonsFound' => 'Aucune saison trouvée',
|
||||||
|
'messages.seasonsLoadFailed' => 'Impossible de charger les saisons',
|
||||||
'messages.noEpisodesFound' => 'Aucun épisode trouvé dans la première saison',
|
'messages.noEpisodesFound' => 'Aucun épisode trouvé dans la première saison',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Aucun épisode trouvé',
|
'messages.noEpisodesFoundGeneral' => 'Aucun épisode trouvé',
|
||||||
|
'messages.episodesLoadFailed' => 'Impossible de charger les épisodes',
|
||||||
'messages.noResultsFound' => 'Aucun résultat trouvé',
|
'messages.noResultsFound' => 'Aucun résultat trouvé',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Minuterie de mise en veille réglée sur ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Minuterie de mise en veille réglée sur ${label}',
|
||||||
'messages.noItemsAvailable' => 'Aucun élément disponible',
|
'messages.noItemsAvailable' => 'Aucun élément disponible',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsFr {
|
|||||||
'mpvConfig.loadPreset' => 'Charger',
|
'mpvConfig.loadPreset' => 'Charger',
|
||||||
'mpvConfig.deletePreset' => 'Supprimer',
|
'mpvConfig.deletePreset' => 'Supprimer',
|
||||||
'mpvConfig.presetSaved' => 'Préréglage enregistré',
|
'mpvConfig.presetSaved' => 'Préréglage enregistré',
|
||||||
'mpvConfig.presetLoaded' => 'Préréglage chargé',
|
|
||||||
'mpvConfig.presetDeleted' => 'Préréglage supprimé',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Préréglage chargé',
|
||||||
|
'mpvConfig.presetDeleted' => 'Préréglage supprimé',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Êtes-vous sûr de vouloir supprimer ce préréglage ?',
|
'mpvConfig.confirmDeletePreset' => 'Êtes-vous sûr de vouloir supprimer ce préréglage ?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Confirmer l\'action',
|
'dialog.confirmAction' => 'Confirmer l\'action',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsFr {
|
|||||||
'externalPlayer.playerPackage' => 'Nom du paquet',
|
'externalPlayer.playerPackage' => 'Nom du paquet',
|
||||||
'externalPlayer.playerUrlScheme' => 'Schéma URL',
|
'externalPlayer.playerUrlScheme' => 'Schéma URL',
|
||||||
'externalPlayer.off' => 'Désactivé',
|
'externalPlayer.off' => 'Désactivé',
|
||||||
'externalPlayer.launchFailed' => 'Impossible d\'ouvrir le lecteur externe',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} n\'est pas installé',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Impossible d\'ouvrir le lecteur externe',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} n\'est pas installé',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Lire dans un lecteur externe',
|
'externalPlayer.playInExternalPlayer' => 'Lire dans un lecteur externe',
|
||||||
'metadataEdit.editMetadata' => 'Modifier...',
|
'metadataEdit.editMetadata' => 'Modifier...',
|
||||||
'metadataEdit.screenTitle' => 'Modifier les métadonnées',
|
'metadataEdit.screenTitle' => 'Modifier les métadonnées',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesIt extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Errore aggiornamento metadati: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Errore aggiornamento metadati: ${error}';
|
||||||
@override String get logoutConfirm => 'Sei sicuro di volerti disconnettere?';
|
@override String get logoutConfirm => 'Sei sicuro di volerti disconnettere?';
|
||||||
@override String get noSeasonsFound => 'Nessuna stagione trovata';
|
@override String get noSeasonsFound => 'Nessuna stagione trovata';
|
||||||
|
@override String get seasonsLoadFailed => 'Impossibile caricare le stagioni';
|
||||||
@override String get noEpisodesFound => 'Nessun episodio trovato nella prima stagione';
|
@override String get noEpisodesFound => 'Nessun episodio trovato nella prima stagione';
|
||||||
@override String get noEpisodesFoundGeneral => 'Nessun episodio trovato';
|
@override String get noEpisodesFoundGeneral => 'Nessun episodio trovato';
|
||||||
|
@override String get episodesLoadFailed => 'Impossibile caricare gli episodi';
|
||||||
@override String get noResultsFound => 'Nessun risultato';
|
@override String get noResultsFound => 'Nessun risultato';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Imposta timer spegnimento per ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Imposta timer spegnimento per ${label}';
|
||||||
@override String get noItemsAvailable => 'Nessun elemento disponibile';
|
@override String get noItemsAvailable => 'Nessun elemento disponibile';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsIt {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Errore aggiornamento metadati: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Errore aggiornamento metadati: ${error}',
|
||||||
'messages.logoutConfirm' => 'Sei sicuro di volerti disconnettere?',
|
'messages.logoutConfirm' => 'Sei sicuro di volerti disconnettere?',
|
||||||
'messages.noSeasonsFound' => 'Nessuna stagione trovata',
|
'messages.noSeasonsFound' => 'Nessuna stagione trovata',
|
||||||
|
'messages.seasonsLoadFailed' => 'Impossibile caricare le stagioni',
|
||||||
'messages.noEpisodesFound' => 'Nessun episodio trovato nella prima stagione',
|
'messages.noEpisodesFound' => 'Nessun episodio trovato nella prima stagione',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Nessun episodio trovato',
|
'messages.noEpisodesFoundGeneral' => 'Nessun episodio trovato',
|
||||||
|
'messages.episodesLoadFailed' => 'Impossibile caricare gli episodi',
|
||||||
'messages.noResultsFound' => 'Nessun risultato',
|
'messages.noResultsFound' => 'Nessun risultato',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Imposta timer spegnimento per ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Imposta timer spegnimento per ${label}',
|
||||||
'messages.noItemsAvailable' => 'Nessun elemento disponibile',
|
'messages.noItemsAvailable' => 'Nessun elemento disponibile',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsIt {
|
|||||||
'mpvConfig.loadPreset' => 'Carica',
|
'mpvConfig.loadPreset' => 'Carica',
|
||||||
'mpvConfig.deletePreset' => 'Elimina',
|
'mpvConfig.deletePreset' => 'Elimina',
|
||||||
'mpvConfig.presetSaved' => 'Preset salvato',
|
'mpvConfig.presetSaved' => 'Preset salvato',
|
||||||
'mpvConfig.presetLoaded' => 'Preset caricato',
|
|
||||||
'mpvConfig.presetDeleted' => 'Preset eliminato',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Preset caricato',
|
||||||
|
'mpvConfig.presetDeleted' => 'Preset eliminato',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Sei sicuro di voler eliminare questo preset?',
|
'mpvConfig.confirmDeletePreset' => 'Sei sicuro di voler eliminare questo preset?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Conferma azione',
|
'dialog.confirmAction' => 'Conferma azione',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsIt {
|
|||||||
'externalPlayer.playerPackage' => 'Nome pacchetto',
|
'externalPlayer.playerPackage' => 'Nome pacchetto',
|
||||||
'externalPlayer.playerUrlScheme' => 'Schema URL',
|
'externalPlayer.playerUrlScheme' => 'Schema URL',
|
||||||
'externalPlayer.off' => 'Disattivato',
|
'externalPlayer.off' => 'Disattivato',
|
||||||
'externalPlayer.launchFailed' => 'Impossibile aprire il lettore esterno',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} non è installato',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Impossibile aprire il lettore esterno',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} non è installato',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Riproduci in lettore esterno',
|
'externalPlayer.playInExternalPlayer' => 'Riproduci in lettore esterno',
|
||||||
'metadataEdit.editMetadata' => 'Modifica...',
|
'metadataEdit.editMetadata' => 'Modifica...',
|
||||||
'metadataEdit.screenTitle' => 'Modifica metadati',
|
'metadataEdit.screenTitle' => 'Modifica metadati',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesJa extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'メタデータの更新に失敗しました: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'メタデータの更新に失敗しました: ${error}';
|
||||||
@override String get logoutConfirm => 'ログアウトしてもよろしいですか?';
|
@override String get logoutConfirm => 'ログアウトしてもよろしいですか?';
|
||||||
@override String get noSeasonsFound => 'シーズンが見つかりません';
|
@override String get noSeasonsFound => 'シーズンが見つかりません';
|
||||||
|
@override String get seasonsLoadFailed => 'シーズンを読み込めませんでした';
|
||||||
@override String get noEpisodesFound => '最初のシーズンにエピソードが見つかりません';
|
@override String get noEpisodesFound => '最初のシーズンにエピソードが見つかりません';
|
||||||
@override String get noEpisodesFoundGeneral => 'エピソードが見つかりません';
|
@override String get noEpisodesFoundGeneral => 'エピソードが見つかりません';
|
||||||
|
@override String get episodesLoadFailed => 'エピソードを読み込めませんでした';
|
||||||
@override String get noResultsFound => '結果が見つかりません';
|
@override String get noResultsFound => '結果が見つかりません';
|
||||||
@override String sleepTimerSet({required Object label}) => 'スリープタイマーを${label}に設定しました';
|
@override String sleepTimerSet({required Object label}) => 'スリープタイマーを${label}に設定しました';
|
||||||
@override String get noItemsAvailable => 'アイテムがありません';
|
@override String get noItemsAvailable => 'アイテムがありません';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsJa {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'メタデータの更新に失敗しました: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'メタデータの更新に失敗しました: ${error}',
|
||||||
'messages.logoutConfirm' => 'ログアウトしてもよろしいですか?',
|
'messages.logoutConfirm' => 'ログアウトしてもよろしいですか?',
|
||||||
'messages.noSeasonsFound' => 'シーズンが見つかりません',
|
'messages.noSeasonsFound' => 'シーズンが見つかりません',
|
||||||
|
'messages.seasonsLoadFailed' => 'シーズンを読み込めませんでした',
|
||||||
'messages.noEpisodesFound' => '最初のシーズンにエピソードが見つかりません',
|
'messages.noEpisodesFound' => '最初のシーズンにエピソードが見つかりません',
|
||||||
'messages.noEpisodesFoundGeneral' => 'エピソードが見つかりません',
|
'messages.noEpisodesFoundGeneral' => 'エピソードが見つかりません',
|
||||||
|
'messages.episodesLoadFailed' => 'エピソードを読み込めませんでした',
|
||||||
'messages.noResultsFound' => '結果が見つかりません',
|
'messages.noResultsFound' => '結果が見つかりません',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'スリープタイマーを${label}に設定しました',
|
'messages.sleepTimerSet' => ({required Object label}) => 'スリープタイマーを${label}に設定しました',
|
||||||
'messages.noItemsAvailable' => 'アイテムがありません',
|
'messages.noItemsAvailable' => 'アイテムがありません',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsJa {
|
|||||||
'mpvConfig.loadPreset' => '読み込み',
|
'mpvConfig.loadPreset' => '読み込み',
|
||||||
'mpvConfig.deletePreset' => '削除',
|
'mpvConfig.deletePreset' => '削除',
|
||||||
'mpvConfig.presetSaved' => 'プリセットを保存しました',
|
'mpvConfig.presetSaved' => 'プリセットを保存しました',
|
||||||
'mpvConfig.presetLoaded' => 'プリセットを読み込みました',
|
|
||||||
'mpvConfig.presetDeleted' => 'プリセットを削除しました',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'プリセットを読み込みました',
|
||||||
|
'mpvConfig.presetDeleted' => 'プリセットを削除しました',
|
||||||
'mpvConfig.confirmDeletePreset' => 'このプリセットを削除してもよろしいですか?',
|
'mpvConfig.confirmDeletePreset' => 'このプリセットを削除してもよろしいですか?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => '操作の確認',
|
'dialog.confirmAction' => '操作の確認',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsJa {
|
|||||||
'externalPlayer.playerPackage' => 'パッケージ名',
|
'externalPlayer.playerPackage' => 'パッケージ名',
|
||||||
'externalPlayer.playerUrlScheme' => 'URLスキーム',
|
'externalPlayer.playerUrlScheme' => 'URLスキーム',
|
||||||
'externalPlayer.off' => 'オフ',
|
'externalPlayer.off' => 'オフ',
|
||||||
'externalPlayer.launchFailed' => '外部プレーヤーの起動に失敗しました',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}がインストールされていません',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => '外部プレーヤーの起動に失敗しました',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}がインストールされていません',
|
||||||
'externalPlayer.playInExternalPlayer' => '外部プレーヤーで再生',
|
'externalPlayer.playInExternalPlayer' => '外部プレーヤーで再生',
|
||||||
'metadataEdit.editMetadata' => '編集...',
|
'metadataEdit.editMetadata' => '編集...',
|
||||||
'metadataEdit.screenTitle' => 'メタデータを編集',
|
'metadataEdit.screenTitle' => 'メタデータを編集',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesKo extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => '메타데이터 새로고침 실패: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => '메타데이터 새로고침 실패: ${error}';
|
||||||
@override String get logoutConfirm => '로그아웃 하시겠습니까?';
|
@override String get logoutConfirm => '로그아웃 하시겠습니까?';
|
||||||
@override String get noSeasonsFound => '시즌을 찾을 수 없음';
|
@override String get noSeasonsFound => '시즌을 찾을 수 없음';
|
||||||
|
@override String get seasonsLoadFailed => '시즌을 불러오지 못했습니다';
|
||||||
@override String get noEpisodesFound => '시즌 1에서 에피소드를 찾을 수 없습니다';
|
@override String get noEpisodesFound => '시즌 1에서 에피소드를 찾을 수 없습니다';
|
||||||
@override String get noEpisodesFoundGeneral => '에피소드를 찾을 수 없습니다';
|
@override String get noEpisodesFoundGeneral => '에피소드를 찾을 수 없습니다';
|
||||||
|
@override String get episodesLoadFailed => '에피소드를 불러오지 못했습니다';
|
||||||
@override String get noResultsFound => '결과를 찾을 수 없습니다';
|
@override String get noResultsFound => '결과를 찾을 수 없습니다';
|
||||||
@override String sleepTimerSet({required Object label}) => '수면 타이머가 ${label}로 설정 되었습니다';
|
@override String sleepTimerSet({required Object label}) => '수면 타이머가 ${label}로 설정 되었습니다';
|
||||||
@override String get noItemsAvailable => '사용 가능한 항목이 없습니다';
|
@override String get noItemsAvailable => '사용 가능한 항목이 없습니다';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsKo {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => '메타데이터 새로고침 실패: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => '메타데이터 새로고침 실패: ${error}',
|
||||||
'messages.logoutConfirm' => '로그아웃 하시겠습니까?',
|
'messages.logoutConfirm' => '로그아웃 하시겠습니까?',
|
||||||
'messages.noSeasonsFound' => '시즌을 찾을 수 없음',
|
'messages.noSeasonsFound' => '시즌을 찾을 수 없음',
|
||||||
|
'messages.seasonsLoadFailed' => '시즌을 불러오지 못했습니다',
|
||||||
'messages.noEpisodesFound' => '시즌 1에서 에피소드를 찾을 수 없습니다',
|
'messages.noEpisodesFound' => '시즌 1에서 에피소드를 찾을 수 없습니다',
|
||||||
'messages.noEpisodesFoundGeneral' => '에피소드를 찾을 수 없습니다',
|
'messages.noEpisodesFoundGeneral' => '에피소드를 찾을 수 없습니다',
|
||||||
|
'messages.episodesLoadFailed' => '에피소드를 불러오지 못했습니다',
|
||||||
'messages.noResultsFound' => '결과를 찾을 수 없습니다',
|
'messages.noResultsFound' => '결과를 찾을 수 없습니다',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => '수면 타이머가 ${label}로 설정 되었습니다',
|
'messages.sleepTimerSet' => ({required Object label}) => '수면 타이머가 ${label}로 설정 되었습니다',
|
||||||
'messages.noItemsAvailable' => '사용 가능한 항목이 없습니다',
|
'messages.noItemsAvailable' => '사용 가능한 항목이 없습니다',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsKo {
|
|||||||
'mpvConfig.loadPreset' => '로드',
|
'mpvConfig.loadPreset' => '로드',
|
||||||
'mpvConfig.deletePreset' => '삭제',
|
'mpvConfig.deletePreset' => '삭제',
|
||||||
'mpvConfig.presetSaved' => '프리셋이 저장 되었습니다',
|
'mpvConfig.presetSaved' => '프리셋이 저장 되었습니다',
|
||||||
'mpvConfig.presetLoaded' => '프리셋이 로드 되었습니다',
|
|
||||||
'mpvConfig.presetDeleted' => '프리셋이 삭제 되었습니다',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => '프리셋이 로드 되었습니다',
|
||||||
|
'mpvConfig.presetDeleted' => '프리셋이 삭제 되었습니다',
|
||||||
'mpvConfig.confirmDeletePreset' => '이 프리셋을 삭제 하시겠습니까?',
|
'mpvConfig.confirmDeletePreset' => '이 프리셋을 삭제 하시겠습니까?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => '확인',
|
'dialog.confirmAction' => '확인',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsKo {
|
|||||||
'externalPlayer.playerPackage' => '패키지 이름',
|
'externalPlayer.playerPackage' => '패키지 이름',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL 스킴',
|
'externalPlayer.playerUrlScheme' => 'URL 스킴',
|
||||||
'externalPlayer.off' => '꺼짐',
|
'externalPlayer.off' => '꺼짐',
|
||||||
'externalPlayer.launchFailed' => '외부 플레이어를 열 수 없습니다',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}이(가) 설치되어 있지 않습니다',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => '외부 플레이어를 열 수 없습니다',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name}이(가) 설치되어 있지 않습니다',
|
||||||
'externalPlayer.playInExternalPlayer' => '외부 플레이어에서 재생',
|
'externalPlayer.playInExternalPlayer' => '외부 플레이어에서 재생',
|
||||||
'metadataEdit.editMetadata' => '편집...',
|
'metadataEdit.editMetadata' => '편집...',
|
||||||
'metadataEdit.screenTitle' => '메타데이터 편집',
|
'metadataEdit.screenTitle' => '메타데이터 편집',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesNb extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Kunne ikke oppdatere metadata: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Kunne ikke oppdatere metadata: ${error}';
|
||||||
@override String get logoutConfirm => 'Er du sikker på at du vil logge ut?';
|
@override String get logoutConfirm => 'Er du sikker på at du vil logge ut?';
|
||||||
@override String get noSeasonsFound => 'Ingen sesonger funnet';
|
@override String get noSeasonsFound => 'Ingen sesonger funnet';
|
||||||
|
@override String get seasonsLoadFailed => 'Kunne ikke laste sesonger';
|
||||||
@override String get noEpisodesFound => 'Ingen episoder funnet i første sesong';
|
@override String get noEpisodesFound => 'Ingen episoder funnet i første sesong';
|
||||||
@override String get noEpisodesFoundGeneral => 'Ingen episoder funnet';
|
@override String get noEpisodesFoundGeneral => 'Ingen episoder funnet';
|
||||||
|
@override String get episodesLoadFailed => 'Kunne ikke laste episoder';
|
||||||
@override String get noResultsFound => 'Ingen resultater funnet';
|
@override String get noResultsFound => 'Ingen resultater funnet';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Søvntimer satt til ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Søvntimer satt til ${label}';
|
||||||
@override String get noItemsAvailable => 'Ingen elementer tilgjengelig';
|
@override String get noItemsAvailable => 'Ingen elementer tilgjengelig';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsNb {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kunne ikke oppdatere metadata: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kunne ikke oppdatere metadata: ${error}',
|
||||||
'messages.logoutConfirm' => 'Er du sikker på at du vil logge ut?',
|
'messages.logoutConfirm' => 'Er du sikker på at du vil logge ut?',
|
||||||
'messages.noSeasonsFound' => 'Ingen sesonger funnet',
|
'messages.noSeasonsFound' => 'Ingen sesonger funnet',
|
||||||
|
'messages.seasonsLoadFailed' => 'Kunne ikke laste sesonger',
|
||||||
'messages.noEpisodesFound' => 'Ingen episoder funnet i første sesong',
|
'messages.noEpisodesFound' => 'Ingen episoder funnet i første sesong',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Ingen episoder funnet',
|
'messages.noEpisodesFoundGeneral' => 'Ingen episoder funnet',
|
||||||
|
'messages.episodesLoadFailed' => 'Kunne ikke laste episoder',
|
||||||
'messages.noResultsFound' => 'Ingen resultater funnet',
|
'messages.noResultsFound' => 'Ingen resultater funnet',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Søvntimer satt til ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Søvntimer satt til ${label}',
|
||||||
'messages.noItemsAvailable' => 'Ingen elementer tilgjengelig',
|
'messages.noItemsAvailable' => 'Ingen elementer tilgjengelig',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsNb {
|
|||||||
'mpvConfig.loadPreset' => 'Last inn',
|
'mpvConfig.loadPreset' => 'Last inn',
|
||||||
'mpvConfig.deletePreset' => 'Slett',
|
'mpvConfig.deletePreset' => 'Slett',
|
||||||
'mpvConfig.presetSaved' => 'Forhåndsinnstilling lagret',
|
'mpvConfig.presetSaved' => 'Forhåndsinnstilling lagret',
|
||||||
'mpvConfig.presetLoaded' => 'Forhåndsinnstilling lastet inn',
|
|
||||||
'mpvConfig.presetDeleted' => 'Forhåndsinnstilling slettet',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Forhåndsinnstilling lastet inn',
|
||||||
|
'mpvConfig.presetDeleted' => 'Forhåndsinnstilling slettet',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Er du sikker på at du vil slette denne forhåndsinnstillingen?',
|
'mpvConfig.confirmDeletePreset' => 'Er du sikker på at du vil slette denne forhåndsinnstillingen?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# kommentar',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# kommentar',
|
||||||
'dialog.confirmAction' => 'Bekreft handling',
|
'dialog.confirmAction' => 'Bekreft handling',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsNb {
|
|||||||
'externalPlayer.playerPackage' => 'Pakkenavn',
|
'externalPlayer.playerPackage' => 'Pakkenavn',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-skjema',
|
'externalPlayer.playerUrlScheme' => 'URL-skjema',
|
||||||
'externalPlayer.off' => 'Av',
|
'externalPlayer.off' => 'Av',
|
||||||
'externalPlayer.launchFailed' => 'Kunne ikke åpne ekstern spiller',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installert',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Kunne ikke åpne ekstern spiller',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} er ikke installert',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Spill av i ekstern spiller',
|
'externalPlayer.playInExternalPlayer' => 'Spill av i ekstern spiller',
|
||||||
'metadataEdit.editMetadata' => 'Rediger...',
|
'metadataEdit.editMetadata' => 'Rediger...',
|
||||||
'metadataEdit.screenTitle' => 'Rediger metadata',
|
'metadataEdit.screenTitle' => 'Rediger metadata',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesNl extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Kon metadata niet vernieuwen: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Kon metadata niet vernieuwen: ${error}';
|
||||||
@override String get logoutConfirm => 'Weet je zeker dat je wilt uitloggen?';
|
@override String get logoutConfirm => 'Weet je zeker dat je wilt uitloggen?';
|
||||||
@override String get noSeasonsFound => 'Geen seizoenen gevonden';
|
@override String get noSeasonsFound => 'Geen seizoenen gevonden';
|
||||||
|
@override String get seasonsLoadFailed => 'Kan seizoenen niet laden';
|
||||||
@override String get noEpisodesFound => 'Geen afleveringen gevonden in eerste seizoen';
|
@override String get noEpisodesFound => 'Geen afleveringen gevonden in eerste seizoen';
|
||||||
@override String get noEpisodesFoundGeneral => 'Geen afleveringen gevonden';
|
@override String get noEpisodesFoundGeneral => 'Geen afleveringen gevonden';
|
||||||
|
@override String get episodesLoadFailed => 'Kan afleveringen niet laden';
|
||||||
@override String get noResultsFound => 'Geen resultaten gevonden';
|
@override String get noResultsFound => 'Geen resultaten gevonden';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Slaap timer ingesteld voor ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Slaap timer ingesteld voor ${label}';
|
||||||
@override String get noItemsAvailable => 'Geen items beschikbaar';
|
@override String get noItemsAvailable => 'Geen items beschikbaar';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsNl {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kon metadata niet vernieuwen: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Kon metadata niet vernieuwen: ${error}',
|
||||||
'messages.logoutConfirm' => 'Weet je zeker dat je wilt uitloggen?',
|
'messages.logoutConfirm' => 'Weet je zeker dat je wilt uitloggen?',
|
||||||
'messages.noSeasonsFound' => 'Geen seizoenen gevonden',
|
'messages.noSeasonsFound' => 'Geen seizoenen gevonden',
|
||||||
|
'messages.seasonsLoadFailed' => 'Kan seizoenen niet laden',
|
||||||
'messages.noEpisodesFound' => 'Geen afleveringen gevonden in eerste seizoen',
|
'messages.noEpisodesFound' => 'Geen afleveringen gevonden in eerste seizoen',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Geen afleveringen gevonden',
|
'messages.noEpisodesFoundGeneral' => 'Geen afleveringen gevonden',
|
||||||
|
'messages.episodesLoadFailed' => 'Kan afleveringen niet laden',
|
||||||
'messages.noResultsFound' => 'Geen resultaten gevonden',
|
'messages.noResultsFound' => 'Geen resultaten gevonden',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Slaap timer ingesteld voor ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Slaap timer ingesteld voor ${label}',
|
||||||
'messages.noItemsAvailable' => 'Geen items beschikbaar',
|
'messages.noItemsAvailable' => 'Geen items beschikbaar',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsNl {
|
|||||||
'mpvConfig.loadPreset' => 'Laden',
|
'mpvConfig.loadPreset' => 'Laden',
|
||||||
'mpvConfig.deletePreset' => 'Verwijderen',
|
'mpvConfig.deletePreset' => 'Verwijderen',
|
||||||
'mpvConfig.presetSaved' => 'Voorinstelling opgeslagen',
|
'mpvConfig.presetSaved' => 'Voorinstelling opgeslagen',
|
||||||
'mpvConfig.presetLoaded' => 'Voorinstelling geladen',
|
|
||||||
'mpvConfig.presetDeleted' => 'Voorinstelling verwijderd',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Voorinstelling geladen',
|
||||||
|
'mpvConfig.presetDeleted' => 'Voorinstelling verwijderd',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Weet je zeker dat je deze voorinstelling wilt verwijderen?',
|
'mpvConfig.confirmDeletePreset' => 'Weet je zeker dat je deze voorinstelling wilt verwijderen?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Bevestig actie',
|
'dialog.confirmAction' => 'Bevestig actie',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsNl {
|
|||||||
'externalPlayer.playerPackage' => 'Pakketnaam',
|
'externalPlayer.playerPackage' => 'Pakketnaam',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-schema',
|
'externalPlayer.playerUrlScheme' => 'URL-schema',
|
||||||
'externalPlayer.off' => 'Uit',
|
'externalPlayer.off' => 'Uit',
|
||||||
'externalPlayer.launchFailed' => 'Kan externe speler niet openen',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is niet geïnstalleerd',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Kan externe speler niet openen',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} is niet geïnstalleerd',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Afspelen in externe speler',
|
'externalPlayer.playInExternalPlayer' => 'Afspelen in externe speler',
|
||||||
'metadataEdit.editMetadata' => 'Bewerken...',
|
'metadataEdit.editMetadata' => 'Bewerken...',
|
||||||
'metadataEdit.screenTitle' => 'Metadata bewerken',
|
'metadataEdit.screenTitle' => 'Metadata bewerken',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesPl extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Nie udało się odświeżyć metadanych: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Nie udało się odświeżyć metadanych: ${error}';
|
||||||
@override String get logoutConfirm => 'Czy na pewno chcesz się wylogować?';
|
@override String get logoutConfirm => 'Czy na pewno chcesz się wylogować?';
|
||||||
@override String get noSeasonsFound => 'Nie znaleziono sezonów';
|
@override String get noSeasonsFound => 'Nie znaleziono sezonów';
|
||||||
|
@override String get seasonsLoadFailed => 'Nie udało się załadować sezonów';
|
||||||
@override String get noEpisodesFound => 'Nie znaleziono odcinków w pierwszym sezonie';
|
@override String get noEpisodesFound => 'Nie znaleziono odcinków w pierwszym sezonie';
|
||||||
@override String get noEpisodesFoundGeneral => 'Nie znaleziono odcinków';
|
@override String get noEpisodesFoundGeneral => 'Nie znaleziono odcinków';
|
||||||
|
@override String get episodesLoadFailed => 'Nie udało się załadować odcinków';
|
||||||
@override String get noResultsFound => 'Nie znaleziono wyników';
|
@override String get noResultsFound => 'Nie znaleziono wyników';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Wyłącznik czasowy ustawiony na ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Wyłącznik czasowy ustawiony na ${label}';
|
||||||
@override String get noItemsAvailable => 'Brak dostępnych elementów';
|
@override String get noItemsAvailable => 'Brak dostępnych elementów';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsPl {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Nie udało się odświeżyć metadanych: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Nie udało się odświeżyć metadanych: ${error}',
|
||||||
'messages.logoutConfirm' => 'Czy na pewno chcesz się wylogować?',
|
'messages.logoutConfirm' => 'Czy na pewno chcesz się wylogować?',
|
||||||
'messages.noSeasonsFound' => 'Nie znaleziono sezonów',
|
'messages.noSeasonsFound' => 'Nie znaleziono sezonów',
|
||||||
|
'messages.seasonsLoadFailed' => 'Nie udało się załadować sezonów',
|
||||||
'messages.noEpisodesFound' => 'Nie znaleziono odcinków w pierwszym sezonie',
|
'messages.noEpisodesFound' => 'Nie znaleziono odcinków w pierwszym sezonie',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Nie znaleziono odcinków',
|
'messages.noEpisodesFoundGeneral' => 'Nie znaleziono odcinków',
|
||||||
|
'messages.episodesLoadFailed' => 'Nie udało się załadować odcinków',
|
||||||
'messages.noResultsFound' => 'Nie znaleziono wyników',
|
'messages.noResultsFound' => 'Nie znaleziono wyników',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Wyłącznik czasowy ustawiony na ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Wyłącznik czasowy ustawiony na ${label}',
|
||||||
'messages.noItemsAvailable' => 'Brak dostępnych elementów',
|
'messages.noItemsAvailable' => 'Brak dostępnych elementów',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsPl {
|
|||||||
'mpvConfig.loadPreset' => 'Załaduj',
|
'mpvConfig.loadPreset' => 'Załaduj',
|
||||||
'mpvConfig.deletePreset' => 'Usuń',
|
'mpvConfig.deletePreset' => 'Usuń',
|
||||||
'mpvConfig.presetSaved' => 'Preset zapisany',
|
'mpvConfig.presetSaved' => 'Preset zapisany',
|
||||||
'mpvConfig.presetLoaded' => 'Preset załadowany',
|
|
||||||
'mpvConfig.presetDeleted' => 'Preset usunięty',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Preset załadowany',
|
||||||
|
'mpvConfig.presetDeleted' => 'Preset usunięty',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Czy na pewno chcesz usunąć ten preset?',
|
'mpvConfig.confirmDeletePreset' => 'Czy na pewno chcesz usunąć ten preset?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Potwierdź działanie',
|
'dialog.confirmAction' => 'Potwierdź działanie',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsPl {
|
|||||||
'externalPlayer.playerPackage' => 'Nazwa pakietu',
|
'externalPlayer.playerPackage' => 'Nazwa pakietu',
|
||||||
'externalPlayer.playerUrlScheme' => 'Schemat URL',
|
'externalPlayer.playerUrlScheme' => 'Schemat URL',
|
||||||
'externalPlayer.off' => 'Wyłączony',
|
'externalPlayer.off' => 'Wyłączony',
|
||||||
'externalPlayer.launchFailed' => 'Nie udało się otworzyć zewnętrznego odtwarzacza',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} nie jest zainstalowany',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Nie udało się otworzyć zewnętrznego odtwarzacza',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} nie jest zainstalowany',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Odtwórz w zewnętrznym odtwarzaczu',
|
'externalPlayer.playInExternalPlayer' => 'Odtwórz w zewnętrznym odtwarzaczu',
|
||||||
'metadataEdit.editMetadata' => 'Edytuj...',
|
'metadataEdit.editMetadata' => 'Edytuj...',
|
||||||
'metadataEdit.screenTitle' => 'Edytuj metadane',
|
'metadataEdit.screenTitle' => 'Edytuj metadane',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesPt extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Falha ao atualizar metadados: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Falha ao atualizar metadados: ${error}';
|
||||||
@override String get logoutConfirm => 'Tem certeza que deseja sair?';
|
@override String get logoutConfirm => 'Tem certeza que deseja sair?';
|
||||||
@override String get noSeasonsFound => 'Nenhuma temporada encontrada';
|
@override String get noSeasonsFound => 'Nenhuma temporada encontrada';
|
||||||
|
@override String get seasonsLoadFailed => 'Não foi possível carregar as temporadas';
|
||||||
@override String get noEpisodesFound => 'Nenhum episódio encontrado na primeira temporada';
|
@override String get noEpisodesFound => 'Nenhum episódio encontrado na primeira temporada';
|
||||||
@override String get noEpisodesFoundGeneral => 'Nenhum episódio encontrado';
|
@override String get noEpisodesFoundGeneral => 'Nenhum episódio encontrado';
|
||||||
|
@override String get episodesLoadFailed => 'Não foi possível carregar os episódios';
|
||||||
@override String get noResultsFound => 'Nenhum resultado encontrado';
|
@override String get noResultsFound => 'Nenhum resultado encontrado';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Timer de sono definido para ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Timer de sono definido para ${label}';
|
||||||
@override String get noItemsAvailable => 'Nenhum item disponível';
|
@override String get noItemsAvailable => 'Nenhum item disponível';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsPt {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Falha ao atualizar metadados: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Falha ao atualizar metadados: ${error}',
|
||||||
'messages.logoutConfirm' => 'Tem certeza que deseja sair?',
|
'messages.logoutConfirm' => 'Tem certeza que deseja sair?',
|
||||||
'messages.noSeasonsFound' => 'Nenhuma temporada encontrada',
|
'messages.noSeasonsFound' => 'Nenhuma temporada encontrada',
|
||||||
|
'messages.seasonsLoadFailed' => 'Não foi possível carregar as temporadas',
|
||||||
'messages.noEpisodesFound' => 'Nenhum episódio encontrado na primeira temporada',
|
'messages.noEpisodesFound' => 'Nenhum episódio encontrado na primeira temporada',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Nenhum episódio encontrado',
|
'messages.noEpisodesFoundGeneral' => 'Nenhum episódio encontrado',
|
||||||
|
'messages.episodesLoadFailed' => 'Não foi possível carregar os episódios',
|
||||||
'messages.noResultsFound' => 'Nenhum resultado encontrado',
|
'messages.noResultsFound' => 'Nenhum resultado encontrado',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Timer de sono definido para ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Timer de sono definido para ${label}',
|
||||||
'messages.noItemsAvailable' => 'Nenhum item disponível',
|
'messages.noItemsAvailable' => 'Nenhum item disponível',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsPt {
|
|||||||
'mpvConfig.loadPreset' => 'Carregar',
|
'mpvConfig.loadPreset' => 'Carregar',
|
||||||
'mpvConfig.deletePreset' => 'Excluir',
|
'mpvConfig.deletePreset' => 'Excluir',
|
||||||
'mpvConfig.presetSaved' => 'Predefinição salva',
|
'mpvConfig.presetSaved' => 'Predefinição salva',
|
||||||
'mpvConfig.presetLoaded' => 'Predefinição carregada',
|
|
||||||
'mpvConfig.presetDeleted' => 'Predefinição excluída',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Predefinição carregada',
|
||||||
|
'mpvConfig.presetDeleted' => 'Predefinição excluída',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Tem certeza que deseja excluir esta predefinição?',
|
'mpvConfig.confirmDeletePreset' => 'Tem certeza que deseja excluir esta predefinição?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Confirmar Ação',
|
'dialog.confirmAction' => 'Confirmar Ação',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsPt {
|
|||||||
'externalPlayer.playerPackage' => 'Nome do Pacote',
|
'externalPlayer.playerPackage' => 'Nome do Pacote',
|
||||||
'externalPlayer.playerUrlScheme' => 'Esquema de URL',
|
'externalPlayer.playerUrlScheme' => 'Esquema de URL',
|
||||||
'externalPlayer.off' => 'Desativado',
|
'externalPlayer.off' => 'Desativado',
|
||||||
'externalPlayer.launchFailed' => 'Falha ao abrir player externo',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} não está instalado',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Falha ao abrir player externo',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} não está instalado',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Reproduzir no Player Externo',
|
'externalPlayer.playInExternalPlayer' => 'Reproduzir no Player Externo',
|
||||||
'metadataEdit.editMetadata' => 'Editar...',
|
'metadataEdit.editMetadata' => 'Editar...',
|
||||||
'metadataEdit.screenTitle' => 'Editar Metadados',
|
'metadataEdit.screenTitle' => 'Editar Metadados',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesRu extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Не удалось обновить метаданные: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Не удалось обновить метаданные: ${error}';
|
||||||
@override String get logoutConfirm => 'Вы уверены, что хотите выйти?';
|
@override String get logoutConfirm => 'Вы уверены, что хотите выйти?';
|
||||||
@override String get noSeasonsFound => 'Сезоны не найдены';
|
@override String get noSeasonsFound => 'Сезоны не найдены';
|
||||||
|
@override String get seasonsLoadFailed => 'Не удалось загрузить сезоны';
|
||||||
@override String get noEpisodesFound => 'Эпизоды в первом сезоне не найдены';
|
@override String get noEpisodesFound => 'Эпизоды в первом сезоне не найдены';
|
||||||
@override String get noEpisodesFoundGeneral => 'Эпизоды не найдены';
|
@override String get noEpisodesFoundGeneral => 'Эпизоды не найдены';
|
||||||
|
@override String get episodesLoadFailed => 'Не удалось загрузить эпизоды';
|
||||||
@override String get noResultsFound => 'Результаты не найдены';
|
@override String get noResultsFound => 'Результаты не найдены';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Таймер сна установлен на ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Таймер сна установлен на ${label}';
|
||||||
@override String get noItemsAvailable => 'Нет доступных элементов';
|
@override String get noItemsAvailable => 'Нет доступных элементов';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsRu {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Не удалось обновить метаданные: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Не удалось обновить метаданные: ${error}',
|
||||||
'messages.logoutConfirm' => 'Вы уверены, что хотите выйти?',
|
'messages.logoutConfirm' => 'Вы уверены, что хотите выйти?',
|
||||||
'messages.noSeasonsFound' => 'Сезоны не найдены',
|
'messages.noSeasonsFound' => 'Сезоны не найдены',
|
||||||
|
'messages.seasonsLoadFailed' => 'Не удалось загрузить сезоны',
|
||||||
'messages.noEpisodesFound' => 'Эпизоды в первом сезоне не найдены',
|
'messages.noEpisodesFound' => 'Эпизоды в первом сезоне не найдены',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Эпизоды не найдены',
|
'messages.noEpisodesFoundGeneral' => 'Эпизоды не найдены',
|
||||||
|
'messages.episodesLoadFailed' => 'Не удалось загрузить эпизоды',
|
||||||
'messages.noResultsFound' => 'Результаты не найдены',
|
'messages.noResultsFound' => 'Результаты не найдены',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Таймер сна установлен на ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Таймер сна установлен на ${label}',
|
||||||
'messages.noItemsAvailable' => 'Нет доступных элементов',
|
'messages.noItemsAvailable' => 'Нет доступных элементов',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsRu {
|
|||||||
'mpvConfig.loadPreset' => 'Загрузить',
|
'mpvConfig.loadPreset' => 'Загрузить',
|
||||||
'mpvConfig.deletePreset' => 'Удалить',
|
'mpvConfig.deletePreset' => 'Удалить',
|
||||||
'mpvConfig.presetSaved' => 'Пресет сохранён',
|
'mpvConfig.presetSaved' => 'Пресет сохранён',
|
||||||
'mpvConfig.presetLoaded' => 'Пресет загружен',
|
|
||||||
'mpvConfig.presetDeleted' => 'Пресет удалён',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Пресет загружен',
|
||||||
|
'mpvConfig.presetDeleted' => 'Пресет удалён',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Вы уверены, что хотите удалить этот пресет?',
|
'mpvConfig.confirmDeletePreset' => 'Вы уверены, что хотите удалить этот пресет?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Подтвердить действие',
|
'dialog.confirmAction' => 'Подтвердить действие',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsRu {
|
|||||||
'externalPlayer.playerPackage' => 'Имя пакета',
|
'externalPlayer.playerPackage' => 'Имя пакета',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-схема',
|
'externalPlayer.playerUrlScheme' => 'URL-схема',
|
||||||
'externalPlayer.off' => 'Выкл.',
|
'externalPlayer.off' => 'Выкл.',
|
||||||
'externalPlayer.launchFailed' => 'Не удалось открыть внешний плеер',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не установлен',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Не удалось открыть внешний плеер',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} не установлен',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Воспроизвести во внешнем плеере',
|
'externalPlayer.playInExternalPlayer' => 'Воспроизвести во внешнем плеере',
|
||||||
'metadataEdit.editMetadata' => 'Редактировать...',
|
'metadataEdit.editMetadata' => 'Редактировать...',
|
||||||
'metadataEdit.screenTitle' => 'Редактировать метаданные',
|
'metadataEdit.screenTitle' => 'Редактировать метаданные',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesSv extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => 'Misslyckades att uppdatera metadata: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => 'Misslyckades att uppdatera metadata: ${error}';
|
||||||
@override String get logoutConfirm => 'Är du säker på att du vill logga ut?';
|
@override String get logoutConfirm => 'Är du säker på att du vill logga ut?';
|
||||||
@override String get noSeasonsFound => 'Inga säsonger hittades';
|
@override String get noSeasonsFound => 'Inga säsonger hittades';
|
||||||
|
@override String get seasonsLoadFailed => 'Det gick inte att läsa in säsonger';
|
||||||
@override String get noEpisodesFound => 'Inga avsnitt hittades i första säsongen';
|
@override String get noEpisodesFound => 'Inga avsnitt hittades i första säsongen';
|
||||||
@override String get noEpisodesFoundGeneral => 'Inga avsnitt hittades';
|
@override String get noEpisodesFoundGeneral => 'Inga avsnitt hittades';
|
||||||
|
@override String get episodesLoadFailed => 'Det gick inte att läsa in avsnitt';
|
||||||
@override String get noResultsFound => 'Inga resultat hittades';
|
@override String get noResultsFound => 'Inga resultat hittades';
|
||||||
@override String sleepTimerSet({required Object label}) => 'Sovtimer inställd för ${label}';
|
@override String sleepTimerSet({required Object label}) => 'Sovtimer inställd för ${label}';
|
||||||
@override String get noItemsAvailable => 'Inga objekt tillgängliga';
|
@override String get noItemsAvailable => 'Inga objekt tillgängliga';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsSv {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => 'Misslyckades att uppdatera metadata: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => 'Misslyckades att uppdatera metadata: ${error}',
|
||||||
'messages.logoutConfirm' => 'Är du säker på att du vill logga ut?',
|
'messages.logoutConfirm' => 'Är du säker på att du vill logga ut?',
|
||||||
'messages.noSeasonsFound' => 'Inga säsonger hittades',
|
'messages.noSeasonsFound' => 'Inga säsonger hittades',
|
||||||
|
'messages.seasonsLoadFailed' => 'Det gick inte att läsa in säsonger',
|
||||||
'messages.noEpisodesFound' => 'Inga avsnitt hittades i första säsongen',
|
'messages.noEpisodesFound' => 'Inga avsnitt hittades i första säsongen',
|
||||||
'messages.noEpisodesFoundGeneral' => 'Inga avsnitt hittades',
|
'messages.noEpisodesFoundGeneral' => 'Inga avsnitt hittades',
|
||||||
|
'messages.episodesLoadFailed' => 'Det gick inte att läsa in avsnitt',
|
||||||
'messages.noResultsFound' => 'Inga resultat hittades',
|
'messages.noResultsFound' => 'Inga resultat hittades',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => 'Sovtimer inställd för ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => 'Sovtimer inställd för ${label}',
|
||||||
'messages.noItemsAvailable' => 'Inga objekt tillgängliga',
|
'messages.noItemsAvailable' => 'Inga objekt tillgängliga',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsSv {
|
|||||||
'mpvConfig.loadPreset' => 'Ladda',
|
'mpvConfig.loadPreset' => 'Ladda',
|
||||||
'mpvConfig.deletePreset' => 'Ta bort',
|
'mpvConfig.deletePreset' => 'Ta bort',
|
||||||
'mpvConfig.presetSaved' => 'Förval sparat',
|
'mpvConfig.presetSaved' => 'Förval sparat',
|
||||||
'mpvConfig.presetLoaded' => 'Förval laddat',
|
|
||||||
'mpvConfig.presetDeleted' => 'Förval borttaget',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => 'Förval laddat',
|
||||||
|
'mpvConfig.presetDeleted' => 'Förval borttaget',
|
||||||
'mpvConfig.confirmDeletePreset' => 'Är du säker på att du vill ta bort detta förval?',
|
'mpvConfig.confirmDeletePreset' => 'Är du säker på att du vill ta bort detta förval?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => 'Bekräfta åtgärd',
|
'dialog.confirmAction' => 'Bekräfta åtgärd',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsSv {
|
|||||||
'externalPlayer.playerPackage' => 'Paketnamn',
|
'externalPlayer.playerPackage' => 'Paketnamn',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL-schema',
|
'externalPlayer.playerUrlScheme' => 'URL-schema',
|
||||||
'externalPlayer.off' => 'Av',
|
'externalPlayer.off' => 'Av',
|
||||||
'externalPlayer.launchFailed' => 'Kunde inte öppna extern spelare',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} är inte installerad',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => 'Kunde inte öppna extern spelare',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} är inte installerad',
|
||||||
'externalPlayer.playInExternalPlayer' => 'Spela i extern spelare',
|
'externalPlayer.playInExternalPlayer' => 'Spela i extern spelare',
|
||||||
'metadataEdit.editMetadata' => 'Redigera...',
|
'metadataEdit.editMetadata' => 'Redigera...',
|
||||||
'metadataEdit.screenTitle' => 'Redigera metadata',
|
'metadataEdit.screenTitle' => 'Redigera metadata',
|
||||||
|
|||||||
@@ -672,8 +672,10 @@ class _TranslationsMessagesZh extends TranslationsMessagesEn {
|
|||||||
@override String metadataRefreshFailed({required Object error}) => '无法刷新元数据: ${error}';
|
@override String metadataRefreshFailed({required Object error}) => '无法刷新元数据: ${error}';
|
||||||
@override String get logoutConfirm => '你确定要登出吗?';
|
@override String get logoutConfirm => '你确定要登出吗?';
|
||||||
@override String get noSeasonsFound => '未找到季';
|
@override String get noSeasonsFound => '未找到季';
|
||||||
|
@override String get seasonsLoadFailed => '无法加载季';
|
||||||
@override String get noEpisodesFound => '在第一季中未找到剧集';
|
@override String get noEpisodesFound => '在第一季中未找到剧集';
|
||||||
@override String get noEpisodesFoundGeneral => '未找到剧集';
|
@override String get noEpisodesFoundGeneral => '未找到剧集';
|
||||||
|
@override String get episodesLoadFailed => '无法加载剧集';
|
||||||
@override String get noResultsFound => '未找到结果';
|
@override String get noResultsFound => '未找到结果';
|
||||||
@override String sleepTimerSet({required Object label}) => '睡眠定时器已设置为 ${label}';
|
@override String sleepTimerSet({required Object label}) => '睡眠定时器已设置为 ${label}';
|
||||||
@override String get noItemsAvailable => '没有可用的项目';
|
@override String get noItemsAvailable => '没有可用的项目';
|
||||||
@@ -2295,8 +2297,10 @@ extension on TranslationsZh {
|
|||||||
'messages.metadataRefreshFailed' => ({required Object error}) => '无法刷新元数据: ${error}',
|
'messages.metadataRefreshFailed' => ({required Object error}) => '无法刷新元数据: ${error}',
|
||||||
'messages.logoutConfirm' => '你确定要登出吗?',
|
'messages.logoutConfirm' => '你确定要登出吗?',
|
||||||
'messages.noSeasonsFound' => '未找到季',
|
'messages.noSeasonsFound' => '未找到季',
|
||||||
|
'messages.seasonsLoadFailed' => '无法加载季',
|
||||||
'messages.noEpisodesFound' => '在第一季中未找到剧集',
|
'messages.noEpisodesFound' => '在第一季中未找到剧集',
|
||||||
'messages.noEpisodesFoundGeneral' => '未找到剧集',
|
'messages.noEpisodesFoundGeneral' => '未找到剧集',
|
||||||
|
'messages.episodesLoadFailed' => '无法加载剧集',
|
||||||
'messages.noResultsFound' => '未找到结果',
|
'messages.noResultsFound' => '未找到结果',
|
||||||
'messages.sleepTimerSet' => ({required Object label}) => '睡眠定时器已设置为 ${label}',
|
'messages.sleepTimerSet' => ({required Object label}) => '睡眠定时器已设置为 ${label}',
|
||||||
'messages.noItemsAvailable' => '没有可用的项目',
|
'messages.noItemsAvailable' => '没有可用的项目',
|
||||||
@@ -2331,10 +2335,10 @@ extension on TranslationsZh {
|
|||||||
'mpvConfig.loadPreset' => '加载',
|
'mpvConfig.loadPreset' => '加载',
|
||||||
'mpvConfig.deletePreset' => '删除',
|
'mpvConfig.deletePreset' => '删除',
|
||||||
'mpvConfig.presetSaved' => '预设已保存',
|
'mpvConfig.presetSaved' => '预设已保存',
|
||||||
'mpvConfig.presetLoaded' => '预设已加载',
|
|
||||||
'mpvConfig.presetDeleted' => '预设已删除',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'mpvConfig.presetLoaded' => '预设已加载',
|
||||||
|
'mpvConfig.presetDeleted' => '预设已删除',
|
||||||
'mpvConfig.confirmDeletePreset' => '确定要删除此预设吗?',
|
'mpvConfig.confirmDeletePreset' => '确定要删除此预设吗?',
|
||||||
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
'mpvConfig.configPlaceholder' => 'gpu-api=vulkan\nhwdec=auto\n# comment',
|
||||||
'dialog.confirmAction' => '确认操作',
|
'dialog.confirmAction' => '确认操作',
|
||||||
@@ -2845,10 +2849,10 @@ extension on TranslationsZh {
|
|||||||
'externalPlayer.playerPackage' => '包名',
|
'externalPlayer.playerPackage' => '包名',
|
||||||
'externalPlayer.playerUrlScheme' => 'URL 方案',
|
'externalPlayer.playerUrlScheme' => 'URL 方案',
|
||||||
'externalPlayer.off' => '关闭',
|
'externalPlayer.off' => '关闭',
|
||||||
'externalPlayer.launchFailed' => '无法打开外部播放器',
|
|
||||||
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} 未安装',
|
|
||||||
_ => null,
|
_ => null,
|
||||||
} ?? switch (path) {
|
} ?? switch (path) {
|
||||||
|
'externalPlayer.launchFailed' => '无法打开外部播放器',
|
||||||
|
'externalPlayer.appNotInstalled' => ({required Object name}) => '${name} 未安装',
|
||||||
'externalPlayer.playInExternalPlayer' => '在外部播放器中播放',
|
'externalPlayer.playInExternalPlayer' => '在外部播放器中播放',
|
||||||
'metadataEdit.editMetadata' => '编辑...',
|
'metadataEdit.editMetadata' => '编辑...',
|
||||||
'metadataEdit.screenTitle' => '编辑元数据',
|
'metadataEdit.screenTitle' => '编辑元数据',
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "Misslyckades att uppdatera metadata: ${error}",
|
"metadataRefreshFailed": "Misslyckades att uppdatera metadata: ${error}",
|
||||||
"logoutConfirm": "Är du säker på att du vill logga ut?",
|
"logoutConfirm": "Är du säker på att du vill logga ut?",
|
||||||
"noSeasonsFound": "Inga säsonger hittades",
|
"noSeasonsFound": "Inga säsonger hittades",
|
||||||
|
"seasonsLoadFailed": "Det gick inte att läsa in säsonger",
|
||||||
"noEpisodesFound": "Inga avsnitt hittades i första säsongen",
|
"noEpisodesFound": "Inga avsnitt hittades i första säsongen",
|
||||||
"noEpisodesFoundGeneral": "Inga avsnitt hittades",
|
"noEpisodesFoundGeneral": "Inga avsnitt hittades",
|
||||||
|
"episodesLoadFailed": "Det gick inte att läsa in avsnitt",
|
||||||
"noResultsFound": "Inga resultat hittades",
|
"noResultsFound": "Inga resultat hittades",
|
||||||
"sleepTimerSet": "Sovtimer inställd för ${label}",
|
"sleepTimerSet": "Sovtimer inställd för ${label}",
|
||||||
"noItemsAvailable": "Inga objekt tillgängliga",
|
"noItemsAvailable": "Inga objekt tillgängliga",
|
||||||
|
|||||||
@@ -508,8 +508,10 @@
|
|||||||
"metadataRefreshFailed": "无法刷新元数据: ${error}",
|
"metadataRefreshFailed": "无法刷新元数据: ${error}",
|
||||||
"logoutConfirm": "你确定要登出吗?",
|
"logoutConfirm": "你确定要登出吗?",
|
||||||
"noSeasonsFound": "未找到季",
|
"noSeasonsFound": "未找到季",
|
||||||
|
"seasonsLoadFailed": "无法加载季",
|
||||||
"noEpisodesFound": "在第一季中未找到剧集",
|
"noEpisodesFound": "在第一季中未找到剧集",
|
||||||
"noEpisodesFoundGeneral": "未找到剧集",
|
"noEpisodesFoundGeneral": "未找到剧集",
|
||||||
|
"episodesLoadFailed": "无法加载剧集",
|
||||||
"noResultsFound": "未找到结果",
|
"noResultsFound": "未找到结果",
|
||||||
"sleepTimerSet": "睡眠定时器已设置为 ${label}",
|
"sleepTimerSet": "睡眠定时器已设置为 ${label}",
|
||||||
"noItemsAvailable": "没有可用的项目",
|
"noItemsAvailable": "没有可用的项目",
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import 'library_query.dart';
|
||||||
|
import 'media_item.dart';
|
||||||
|
import 'media_kind.dart';
|
||||||
|
import 'media_server_client.dart';
|
||||||
|
|
||||||
|
/// Collect every episode of a show into [out] using the backend's one-shot
|
||||||
|
/// recursive-leaves call ([MediaServerClient.fetchPlayableDescendants] —
|
||||||
|
/// Plex's `/library/metadata/{id}/allLeaves`, Jellyfin's
|
||||||
|
/// `/Items?Recursive=true&IncludeItemTypes=Movie,Episode`). Avoids walking
|
||||||
|
/// show → seasons → episodes client-side, so large series come back in one
|
||||||
|
/// trip and aren't capped by any per-page Limit.
|
||||||
|
///
|
||||||
|
/// A failure of the underlying call propagates to the caller — both
|
||||||
|
/// `DownloadProvider.queueDownload` and the sync rule executor wrap their
|
||||||
|
/// invocations so the user-facing error surfaces / the rule run is rolled
|
||||||
|
/// back.
|
||||||
|
Future<void> collectEpisodesForShow(
|
||||||
|
MediaServerClient client,
|
||||||
|
String showRatingKey, {
|
||||||
|
required bool unwatchedOnly,
|
||||||
|
required List<MediaItem> out,
|
||||||
|
MediaItem? fallback,
|
||||||
|
}) {
|
||||||
|
return _collectPlayable(client, showRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect every episode of a single season into [out] via the same
|
||||||
|
/// one-shot endpoint. On a season the leaves *are* the episodes, so the
|
||||||
|
/// shape matches the show case.
|
||||||
|
Future<void> collectEpisodesForSeason(
|
||||||
|
MediaServerClient client,
|
||||||
|
String seasonRatingKey, {
|
||||||
|
required bool unwatchedOnly,
|
||||||
|
required List<MediaItem> out,
|
||||||
|
MediaItem? fallback,
|
||||||
|
}) {
|
||||||
|
return _collectPlayable(client, seasonRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch just the first episode of a season without walking the entire season.
|
||||||
|
/// Use this for representative lookups and immediate "play first" actions.
|
||||||
|
Future<MediaItem?> fetchFirstEpisodeForSeason(MediaServerClient client, String seasonRatingKey) async {
|
||||||
|
final page = await client.fetchChildrenPage(seasonRatingKey, start: 0, size: 1);
|
||||||
|
for (final item in page.items) {
|
||||||
|
if (item.kind == MediaKind.episode) return item;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prefer the first regular season over specials, falling back to the first
|
||||||
|
/// season row when a show only has specials or lacks season indexes.
|
||||||
|
int defaultPlaybackSeasonIndex(List<MediaItem> seasons) {
|
||||||
|
if (seasons.isEmpty) return 0;
|
||||||
|
final regularSeasonIndex = seasons.indexWhere((season) => season.kind == MediaKind.season && (season.index ?? 0) > 0);
|
||||||
|
if (regularSeasonIndex != -1) return regularSeasonIndex;
|
||||||
|
final firstSeasonIndex = seasons.indexWhere((season) => season.kind == MediaKind.season);
|
||||||
|
return firstSeasonIndex == -1 ? 0 : firstSeasonIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaItem? defaultPlaybackSeason(List<MediaItem> seasons) {
|
||||||
|
if (seasons.isEmpty) return null;
|
||||||
|
final index = defaultPlaybackSeasonIndex(seasons);
|
||||||
|
if (index < 0 || index >= seasons.length) return null;
|
||||||
|
final season = seasons[index];
|
||||||
|
return season.kind == MediaKind.season ? season : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the season index matching an explicit navigation target or on-deck
|
||||||
|
/// episode, then fall back to [defaultPlaybackSeasonIndex].
|
||||||
|
int preferredSeasonIndex(List<MediaItem> seasons, {int? initialSeasonIndex, MediaItem? onDeckEpisode}) {
|
||||||
|
if (seasons.isEmpty) return 0;
|
||||||
|
if (initialSeasonIndex != null) {
|
||||||
|
final idx = seasons.indexWhere((season) => season.kind == MediaKind.season && season.index == initialSeasonIndex);
|
||||||
|
if (idx != -1) return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onDeckEpisode != null) {
|
||||||
|
final parentId = onDeckEpisode.parentId;
|
||||||
|
if (parentId != null) {
|
||||||
|
final idx = seasons.indexWhere((season) => season.kind == MediaKind.season && season.id == parentId);
|
||||||
|
if (idx != -1) return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
final parentIndex = onDeckEpisode.parentIndex;
|
||||||
|
if (parentIndex != null) {
|
||||||
|
final idx = seasons.indexWhere((season) => season.kind == MediaKind.season && season.index == parentIndex);
|
||||||
|
if (idx != -1) return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultPlaybackSeasonIndex(seasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch a page of direct season children and normalize the episode identity
|
||||||
|
/// fields detail rows depend on. Local/session progress stays layered in UI.
|
||||||
|
Future<LibraryPage<MediaItem>> fetchSeasonEpisodePage(
|
||||||
|
MediaServerClient client, {
|
||||||
|
required MediaItem show,
|
||||||
|
required MediaItem season,
|
||||||
|
required int start,
|
||||||
|
required int size,
|
||||||
|
}) async {
|
||||||
|
final page = await client.fetchChildrenPage(season.id, start: start, size: size);
|
||||||
|
return LibraryPage<MediaItem>(
|
||||||
|
items: normalizeSeasonEpisodes(page.items, show: show, season: season),
|
||||||
|
totalCount: page.totalCount,
|
||||||
|
offset: page.offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<MediaItem> normalizeSeasonEpisodes(
|
||||||
|
List<MediaItem> episodes, {
|
||||||
|
required MediaItem show,
|
||||||
|
required MediaItem season,
|
||||||
|
}) {
|
||||||
|
return episodes
|
||||||
|
.map(
|
||||||
|
(episode) => _withFallbackLibrary(
|
||||||
|
episode.copyWith(
|
||||||
|
serverId: show.serverId ?? episode.serverId,
|
||||||
|
serverName: show.serverName ?? episode.serverName,
|
||||||
|
grandparentId: show.id,
|
||||||
|
grandparentTitle: show.title ?? episode.grandparentTitle,
|
||||||
|
parentId: episode.parentId ?? season.id,
|
||||||
|
parentIndex: episode.parentIndex ?? season.index,
|
||||||
|
),
|
||||||
|
season.libraryId != null ? season : show,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _collectPlayable(
|
||||||
|
MediaServerClient client,
|
||||||
|
String parentId, {
|
||||||
|
required bool unwatchedOnly,
|
||||||
|
required List<MediaItem> out,
|
||||||
|
MediaItem? fallback,
|
||||||
|
}) async {
|
||||||
|
final leaves = await client.fetchPlayableDescendants(parentId);
|
||||||
|
for (final ep in leaves) {
|
||||||
|
if (ep.kind != MediaKind.episode) continue;
|
||||||
|
if (unwatchedOnly && ep.isWatched && !ep.hasActiveProgress) continue;
|
||||||
|
out.add(_withFallbackLibrary(ep, fallback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaItem _withFallbackLibrary(MediaItem item, MediaItem? fallback) {
|
||||||
|
if (fallback == null) return item;
|
||||||
|
final fallbackIsSeason = fallback.kind == MediaKind.season;
|
||||||
|
final fallbackIsShow = fallback.kind == MediaKind.show;
|
||||||
|
return item.copyWith(
|
||||||
|
serverId: item.serverId ?? fallback.serverId,
|
||||||
|
serverName: item.serverName ?? fallback.serverName,
|
||||||
|
libraryId: item.libraryId ?? fallback.libraryId,
|
||||||
|
libraryTitle: item.libraryTitle ?? fallback.libraryTitle,
|
||||||
|
parentId: item.parentId ?? (fallbackIsSeason ? fallback.id : null),
|
||||||
|
parentTitle: item.parentTitle ?? (fallbackIsSeason ? fallback.title : null),
|
||||||
|
grandparentId: item.grandparentId ?? _fallbackGrandparentId(fallback, isShow: fallbackIsShow),
|
||||||
|
grandparentTitle: item.grandparentTitle ?? _fallbackGrandparentTitle(fallback, isShow: fallbackIsShow),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _fallbackGrandparentId(MediaItem fallback, {required bool isShow}) {
|
||||||
|
if (isShow) return fallback.id;
|
||||||
|
return fallback.grandparentId ?? fallback.parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _fallbackGrandparentTitle(MediaItem fallback, {required bool isShow}) {
|
||||||
|
if (isShow) return fallback.title;
|
||||||
|
return fallback.grandparentTitle ?? fallback.parentTitle;
|
||||||
|
}
|
||||||
@@ -169,9 +169,15 @@ abstract class MediaServerClient {
|
|||||||
/// show, tracks of an album, items of a collection.
|
/// show, tracks of an album, items of a collection.
|
||||||
Future<List<MediaItem>> fetchChildren(String parentId);
|
Future<List<MediaItem>> fetchChildren(String parentId);
|
||||||
|
|
||||||
/// Page through playable descendants of [parentId]. Used by large show /
|
/// Page through direct children of [parentId]. Unlike
|
||||||
/// season detail views so episodes can render before the full list has
|
/// [fetchPlayableDescendantsPage], this preserves container shape and is used
|
||||||
/// loaded. [fetchPlayableDescendants] remains the complete-list helper for
|
/// for large season episode lists where the children endpoint is the correct
|
||||||
|
/// backend primitive.
|
||||||
|
Future<LibraryPage<MediaItem>> fetchChildrenPage(String parentId, {int? start, int? size, AbortController? abort});
|
||||||
|
|
||||||
|
/// Page through playable descendants of [parentId]. Used by flattened show /
|
||||||
|
/// season detail views so episodes can render before the full list has loaded.
|
||||||
|
/// [fetchPlayableDescendants] remains the complete-list helper for
|
||||||
/// playback/download/sync paths.
|
/// playback/download/sync paths.
|
||||||
Future<LibraryPage<MediaItem>> fetchPlayableDescendantsPage(
|
Future<LibraryPage<MediaItem>> fetchPlayableDescendantsPage(
|
||||||
String parentId, {
|
String parentId, {
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/// Immutable state for a list loaded in pages.
|
||||||
|
class PagedMediaListState<T> {
|
||||||
|
const PagedMediaListState({
|
||||||
|
this.items = const [],
|
||||||
|
this.totalCount = 0,
|
||||||
|
this.isInitialLoading = false,
|
||||||
|
this.isLoadingMore = false,
|
||||||
|
this.initialLoadFailed = false,
|
||||||
|
this.pageLoadFailed = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<T> items;
|
||||||
|
final int totalCount;
|
||||||
|
final bool isInitialLoading;
|
||||||
|
final bool isLoadingMore;
|
||||||
|
final bool initialLoadFailed;
|
||||||
|
final bool pageLoadFailed;
|
||||||
|
|
||||||
|
bool get hasMore => items.length < totalCount;
|
||||||
|
bool get hasItems => items.isNotEmpty;
|
||||||
|
|
||||||
|
PagedMediaListState<T> copyWith({
|
||||||
|
List<T>? items,
|
||||||
|
int? totalCount,
|
||||||
|
bool? isInitialLoading,
|
||||||
|
bool? isLoadingMore,
|
||||||
|
bool? initialLoadFailed,
|
||||||
|
bool? pageLoadFailed,
|
||||||
|
}) {
|
||||||
|
return PagedMediaListState<T>(
|
||||||
|
items: items ?? this.items,
|
||||||
|
totalCount: totalCount ?? this.totalCount,
|
||||||
|
isInitialLoading: isInitialLoading ?? this.isInitialLoading,
|
||||||
|
isLoadingMore: isLoadingMore ?? this.isLoadingMore,
|
||||||
|
initialLoadFailed: initialLoadFailed ?? this.initialLoadFailed,
|
||||||
|
pageLoadFailed: pageLoadFailed ?? this.pageLoadFailed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> startInitialLoad() {
|
||||||
|
return copyWith(isInitialLoading: true, isLoadingMore: false, initialLoadFailed: false, pageLoadFailed: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> completeInitialLoad(List<T> pageItems, int total) {
|
||||||
|
return copyWith(
|
||||||
|
items: List<T>.of(pageItems),
|
||||||
|
totalCount: total,
|
||||||
|
isInitialLoading: false,
|
||||||
|
isLoadingMore: false,
|
||||||
|
initialLoadFailed: false,
|
||||||
|
pageLoadFailed: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> failInitialLoad() {
|
||||||
|
return copyWith(isInitialLoading: false, isLoadingMore: false, initialLoadFailed: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> startLoadMore() {
|
||||||
|
return copyWith(isLoadingMore: true, pageLoadFailed: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> completeLoadMore({
|
||||||
|
required int expectedOffset,
|
||||||
|
required List<T> pageItems,
|
||||||
|
required int total,
|
||||||
|
}) {
|
||||||
|
if (items.length != expectedOffset) {
|
||||||
|
return copyWith(isLoadingMore: false);
|
||||||
|
}
|
||||||
|
final nextTotal = pageItems.isEmpty ? expectedOffset : total;
|
||||||
|
return copyWith(
|
||||||
|
items: <T>[...items, ...pageItems],
|
||||||
|
totalCount: nextTotal,
|
||||||
|
isLoadingMore: false,
|
||||||
|
pageLoadFailed: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> failLoadMore() {
|
||||||
|
return copyWith(isLoadingMore: false, pageLoadFailed: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> replaceItems(List<T> nextItems) {
|
||||||
|
final nextTotal = totalCount < nextItems.length ? nextItems.length : totalCount;
|
||||||
|
return copyWith(items: List<T>.of(nextItems), totalCount: nextTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<T> removeWhere(bool Function(T item) test) {
|
||||||
|
var removed = 0;
|
||||||
|
final nextItems = <T>[];
|
||||||
|
for (final item in items) {
|
||||||
|
if (test(item)) {
|
||||||
|
removed++;
|
||||||
|
} else {
|
||||||
|
nextItems.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed == 0) return this;
|
||||||
|
final decrementedTotal = totalCount - removed;
|
||||||
|
final nextTotal = decrementedTotal < nextItems.length ? nextItems.length : decrementedTotal;
|
||||||
|
return copyWith(items: nextItems, totalCount: nextTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedMediaListState<R> mapItems<R>(R Function(T item) map) {
|
||||||
|
return PagedMediaListState<R>(
|
||||||
|
items: items.map(map).toList(),
|
||||||
|
totalCount: totalCount,
|
||||||
|
isInitialLoading: isInitialLoading,
|
||||||
|
isLoadingMore: isLoadingMore,
|
||||||
|
initialLoadFailed: initialLoadFailed,
|
||||||
|
pageLoadFailed: pageLoadFailed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import '../media/media_server_client.dart';
|
|||||||
import '../services/sync_rule_executor.dart';
|
import '../services/sync_rule_executor.dart';
|
||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
import '../utils/deletion_notifier.dart';
|
import '../utils/deletion_notifier.dart';
|
||||||
import '../utils/episode_collection.dart';
|
import '../media/episode_collection.dart';
|
||||||
import '../utils/global_key_utils.dart';
|
import '../utils/global_key_utils.dart';
|
||||||
import '../utils/watch_state_notifier.dart';
|
import '../utils/watch_state_notifier.dart';
|
||||||
import '../mixins/disposable_change_notifier_mixin.dart';
|
import '../mixins/disposable_change_notifier_mixin.dart';
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -523,6 +523,82 @@ mixin _JellyfinBrowseMethods on MediaServerCacheMixin {
|
|||||||
return _mapItems(allRaw);
|
return _mapItems(allRaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<LibraryPage<MediaItem>> fetchChildrenPage(
|
||||||
|
String parentId, {
|
||||||
|
int? start,
|
||||||
|
int? size,
|
||||||
|
AbortController? abort,
|
||||||
|
}) async {
|
||||||
|
final offset = start ?? 0;
|
||||||
|
final pageSize = size ?? _pagedListPageSize;
|
||||||
|
final seasonsKey = '/Shows/$parentId/Seasons?userId=${connection.userId}';
|
||||||
|
final childrenKey = '/Items?ParentId=$parentId&userId=${connection.userId}';
|
||||||
|
|
||||||
|
if (isOfflineMode) {
|
||||||
|
final cachedSeasons = await cache.get(ServerId(cacheServerId), seasonsKey);
|
||||||
|
if (cachedSeasons != null) {
|
||||||
|
final allSeasons = _mapItems(_itemsArray(cachedSeasons));
|
||||||
|
if (allSeasons.isNotEmpty) {
|
||||||
|
final safeOffset = offset.clamp(0, allSeasons.length).toInt();
|
||||||
|
final end = (safeOffset + pageSize).clamp(0, allSeasons.length).toInt();
|
||||||
|
return LibraryPage<MediaItem>(
|
||||||
|
items: allSeasons.sublist(safeOffset, end),
|
||||||
|
totalCount: allSeasons.length,
|
||||||
|
offset: offset,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final cached = await cache.get(ServerId(cacheServerId), childrenKey);
|
||||||
|
final all = cached == null ? const <MediaItem>[] : _mapItems(_itemsArray(cached));
|
||||||
|
final safeOffset = offset.clamp(0, all.length).toInt();
|
||||||
|
final end = (safeOffset + pageSize).clamp(0, all.length).toInt();
|
||||||
|
final pageItems = all.sublist(safeOffset, end);
|
||||||
|
return LibraryPage<MediaItem>(items: pageItems, totalCount: all.length, offset: offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final seasons = await _http.get(
|
||||||
|
'/Shows/${_segment(parentId)}/Seasons',
|
||||||
|
queryParameters: {
|
||||||
|
'userId': connection.userId,
|
||||||
|
'StartIndex': offset.toString(),
|
||||||
|
'Limit': pageSize.toString(),
|
||||||
|
'EnableTotalRecordCount': 'true',
|
||||||
|
'Fields': _browseFields,
|
||||||
|
...jellyfinImageQueryParameters,
|
||||||
|
},
|
||||||
|
abort: abort,
|
||||||
|
);
|
||||||
|
if (seasons.statusCode == 200) {
|
||||||
|
final data = seasons.data;
|
||||||
|
final items = _itemsArray(data);
|
||||||
|
final rawTotal = data is Map<String, dynamic> ? data['TotalRecordCount'] : null;
|
||||||
|
if (items.isNotEmpty || (rawTotal is int && rawTotal > 0)) {
|
||||||
|
return _pagedMediaItems(data, offset: offset, requestedSize: pageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on MediaServerHttpException {
|
||||||
|
// Not a series — fall through to the generic ParentId query.
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await _http.get(
|
||||||
|
'/Items',
|
||||||
|
queryParameters: {
|
||||||
|
'userId': connection.userId,
|
||||||
|
'ParentId': parentId,
|
||||||
|
'StartIndex': offset.toString(),
|
||||||
|
'Limit': pageSize.toString(),
|
||||||
|
'EnableTotalRecordCount': 'true',
|
||||||
|
'Fields': _episodeRowFields,
|
||||||
|
...jellyfinImageQueryParameters,
|
||||||
|
},
|
||||||
|
abort: abort,
|
||||||
|
);
|
||||||
|
throwIfHttpError(response);
|
||||||
|
return _pagedMediaItems(response.data, offset: offset, requestedSize: pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
/// Jellyfin folder browsing mirrors Jellyfin Web/Findroid/Swiftfin: query
|
/// Jellyfin folder browsing mirrors Jellyfin Web/Findroid/Swiftfin: query
|
||||||
/// direct children of the library/folder with `Recursive=false`. This is
|
/// direct children of the library/folder with `Recursive=false`. This is
|
||||||
/// distinct from [fetchLibraryContent], which intentionally recurses through
|
/// distinct from [fetchLibraryContent], which intentionally recurses through
|
||||||
|
|||||||
@@ -1206,6 +1206,56 @@ class PlexClient
|
|||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Walk every page of [path] and return a single synthesized response whose
|
||||||
|
/// `MediaContainer.Metadata` concatenates all pages. Lets a caller (and its
|
||||||
|
/// cache layer) treat a large, server-paginated collection as one complete
|
||||||
|
/// response while each network request stays small. Raw-response analog of
|
||||||
|
/// [_fetchAllPages]; errors propagate.
|
||||||
|
Future<MediaServerResponse> _getAllPagesResponse(
|
||||||
|
String path, {
|
||||||
|
Map<String, dynamic>? queryParameters,
|
||||||
|
AbortController? abort,
|
||||||
|
}) async {
|
||||||
|
MediaServerResponse? firstResponse;
|
||||||
|
Map<String, dynamic>? firstContainer;
|
||||||
|
final allMetadata = <dynamic>[];
|
||||||
|
var start = 0;
|
||||||
|
while (true) {
|
||||||
|
final response = await _getWithFailover(
|
||||||
|
path,
|
||||||
|
queryParameters: {...?queryParameters, ..._buildPaginationParams(start, _fetchAllPageSize)},
|
||||||
|
abort: abort,
|
||||||
|
);
|
||||||
|
final container = _getMediaContainer(response);
|
||||||
|
final metadata = container?['Metadata'];
|
||||||
|
final pageItems = metadata is List ? metadata : const [];
|
||||||
|
firstResponse ??= response;
|
||||||
|
firstContainer ??= container;
|
||||||
|
allMetadata.addAll(pageItems);
|
||||||
|
final total = _responseTotalSize(
|
||||||
|
response,
|
||||||
|
itemCount: pageItems.length,
|
||||||
|
start: start,
|
||||||
|
requestedSize: _fetchAllPageSize,
|
||||||
|
);
|
||||||
|
start += pageItems.length;
|
||||||
|
if (pageItems.isEmpty || start >= total) break;
|
||||||
|
}
|
||||||
|
return MediaServerResponse(
|
||||||
|
statusCode: firstResponse.statusCode,
|
||||||
|
data: {
|
||||||
|
'MediaContainer': {
|
||||||
|
...?firstContainer,
|
||||||
|
'Metadata': allMetadata,
|
||||||
|
'size': allMetadata.length,
|
||||||
|
'totalSize': allMetadata.length,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headers: firstResponse.headers,
|
||||||
|
requestUri: firstResponse.requestUri,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Set per-media language preferences (audio and subtitle)
|
/// Set per-media language preferences (audio and subtitle)
|
||||||
/// For TV shows, use grandparentRatingKey to set preference for the entire series
|
/// For TV shows, use grandparentRatingKey to set preference for the entire series
|
||||||
/// For movies, use the movie's ratingKey
|
/// For movies, use the movie's ratingKey
|
||||||
@@ -1412,20 +1462,35 @@ class PlexClient
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get children of a metadata item (e.g., seasons for a show, episodes for a season)
|
/// Get children of a metadata item (e.g., seasons for a show, episodes for a season).
|
||||||
/// Uses cache when offline or as fallback on network error
|
/// Walks every page so large shows (many seasons) aren't truncated by a
|
||||||
|
/// server-forced container limit; uses cache when offline or as fallback on
|
||||||
|
/// network error. (Large *episode* lists load lazily via [fetchChildrenPage];
|
||||||
|
/// this full-fetch is for the seasons list and other complete-list callers.)
|
||||||
Future<List<PlexMetadataDto>> _getChildren(String ratingKey) async {
|
Future<List<PlexMetadataDto>> _getChildren(String ratingKey) async {
|
||||||
final endpoint = '/library/metadata/$ratingKey/children';
|
final endpoint = '/library/metadata/$ratingKey/children';
|
||||||
|
|
||||||
return await fetchWithCacheFallback<List<PlexMetadataDto>>(
|
return await fetchWithCacheFallback<List<PlexMetadataDto>>(
|
||||||
cacheKey: endpoint,
|
cacheKey: endpoint,
|
||||||
networkCall: () => _http.get(endpoint, queryParameters: {'includeStreams': 1}),
|
networkCall: () => _getAllPagesResponse(endpoint, queryParameters: {'includeStreams': 1}),
|
||||||
parseCache: (cachedData) => _parseMetadataListFromCachedResponse(cachedData),
|
parseCache: (cachedData) => _parseMetadataListFromCachedResponse(cachedData),
|
||||||
parseResponse: (response) => _extractMetadataList(response),
|
parseResponse: (response) => _extractMetadataList(response),
|
||||||
) ??
|
) ??
|
||||||
[];
|
[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Page through direct children of a metadata item (e.g. episodes of a
|
||||||
|
/// season). This uses `/children`; playable descendant paging uses
|
||||||
|
/// `/grandchildren` and intentionally has different semantics.
|
||||||
|
Future<_LibraryContentResult> _getChildrenPage(String ratingKey, {int? start, int? size, AbortController? abort}) =>
|
||||||
|
_fetchPaginatedList(
|
||||||
|
'/library/metadata/$ratingKey/children',
|
||||||
|
start: start,
|
||||||
|
size: size,
|
||||||
|
abort: abort,
|
||||||
|
queryParameters: {'includeStreams': 1},
|
||||||
|
);
|
||||||
|
|
||||||
/// Page through playable episodes beneath a show or season. Uses
|
/// Page through playable episodes beneath a show or season. Uses
|
||||||
/// `/grandchildren` rather than `/allLeaves` because the live server returns
|
/// `/grandchildren` rather than `/allLeaves` because the live server returns
|
||||||
/// 0 items for `/allLeaves` on a season.
|
/// 0 items for `/allLeaves` on a season.
|
||||||
@@ -3264,6 +3329,21 @@ class PlexClient
|
|||||||
return children.map((m) => PlexMappers.mediaItem(m)).toList();
|
return children.map((m) => PlexMappers.mediaItem(m)).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<LibraryPage<MediaItem>> fetchChildrenPage(
|
||||||
|
String parentId, {
|
||||||
|
int? start,
|
||||||
|
int? size,
|
||||||
|
AbortController? abort,
|
||||||
|
}) async {
|
||||||
|
final result = await _getChildrenPage(parentId, start: start, size: size, abort: abort);
|
||||||
|
return LibraryPage<MediaItem>(
|
||||||
|
items: result.items.map((m) => PlexMappers.mediaItem(m)).toList(),
|
||||||
|
totalCount: result.totalSize,
|
||||||
|
offset: start ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<MediaItem>> fetchPlayableDescendants(String parentId) async {
|
Future<List<MediaItem>> fetchPlayableDescendants(String parentId) async {
|
||||||
final leaves = await _fetchAllPages(
|
final leaves = await _fetchAllPages(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import '../media/media_server_client.dart';
|
|||||||
import '../models/download_models.dart';
|
import '../models/download_models.dart';
|
||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
import '../utils/content_utils.dart';
|
import '../utils/content_utils.dart';
|
||||||
import '../utils/episode_collection.dart';
|
import '../media/episode_collection.dart';
|
||||||
import '../utils/global_key_utils.dart';
|
import '../utils/global_key_utils.dart';
|
||||||
import 'download_manager_service.dart';
|
import 'download_manager_service.dart';
|
||||||
import 'multi_server_manager.dart';
|
import 'multi_server_manager.dart';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import '../../media/media_kind.dart';
|
|||||||
import '../../media/media_server_client.dart';
|
import '../../media/media_server_client.dart';
|
||||||
import '../../models/trackers/tracker_context.dart';
|
import '../../models/trackers/tracker_context.dart';
|
||||||
import '../../utils/app_logger.dart';
|
import '../../utils/app_logger.dart';
|
||||||
import '../../utils/episode_collection.dart';
|
import '../../media/episode_collection.dart';
|
||||||
import 'anime_episode_progress_resolver.dart';
|
import 'anime_episode_progress_resolver.dart';
|
||||||
import 'anime_lists_mapping_store.dart';
|
import 'anime_lists_mapping_store.dart';
|
||||||
import 'anilist/anilist_tracker.dart';
|
import 'anilist/anilist_tracker.dart';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import '../../media/media_server_client.dart';
|
|||||||
import '../../models/trakt/trakt_ids.dart';
|
import '../../models/trakt/trakt_ids.dart';
|
||||||
import '../../models/trakt/trakt_scrobble_request.dart';
|
import '../../models/trakt/trakt_scrobble_request.dart';
|
||||||
import '../../utils/app_logger.dart';
|
import '../../utils/app_logger.dart';
|
||||||
import '../../utils/episode_collection.dart';
|
import '../../media/episode_collection.dart';
|
||||||
import '../../utils/watch_state_notifier.dart';
|
import '../../utils/watch_state_notifier.dart';
|
||||||
import '../multi_server_manager.dart';
|
import '../multi_server_manager.dart';
|
||||||
import '../settings_service.dart';
|
import '../settings_service.dart';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import '../media/media_item.dart';
|
|||||||
import '../media/media_kind.dart';
|
import '../media/media_kind.dart';
|
||||||
import '../media/media_server_client.dart';
|
import '../media/media_server_client.dart';
|
||||||
import '../media/media_version.dart';
|
import '../media/media_version.dart';
|
||||||
|
import '../media/episode_collection.dart';
|
||||||
import '../utils/app_logger.dart';
|
import '../utils/app_logger.dart';
|
||||||
import '../utils/dialogs.dart';
|
import '../utils/dialogs.dart';
|
||||||
import '../utils/media_version_resolver.dart';
|
import '../utils/media_version_resolver.dart';
|
||||||
@@ -97,18 +98,13 @@ Future<List<MediaVersion>?> fetchRepresentativeVersions(MediaServerClient client
|
|||||||
String? episodeRatingKey;
|
String? episodeRatingKey;
|
||||||
|
|
||||||
if (metadata.kind == MediaKind.season) {
|
if (metadata.kind == MediaKind.season) {
|
||||||
final episodes = await client.fetchChildren(metadata.id);
|
final firstEpisode = await fetchFirstEpisodeForSeason(client, metadata.id);
|
||||||
final firstEpisode = episodes.where((e) => e.kind == MediaKind.episode).firstOrNull;
|
|
||||||
episodeRatingKey = firstEpisode?.id;
|
episodeRatingKey = firstEpisode?.id;
|
||||||
} else if (metadata.kind == MediaKind.show) {
|
} else if (metadata.kind == MediaKind.show) {
|
||||||
final seasons = await client.fetchChildren(metadata.id);
|
final seasons = await client.fetchChildren(metadata.id);
|
||||||
// Skip Season 0 (Specials) as it may have different encoding
|
final firstSeason = defaultPlaybackSeason(seasons);
|
||||||
final firstSeason =
|
|
||||||
seasons.where((s) => s.kind == MediaKind.season && (s.index ?? 0) > 0).firstOrNull ??
|
|
||||||
seasons.where((s) => s.kind == MediaKind.season).firstOrNull;
|
|
||||||
if (firstSeason != null) {
|
if (firstSeason != null) {
|
||||||
final episodes = await client.fetchChildren(firstSeason.id);
|
final firstEpisode = await fetchFirstEpisodeForSeason(client, firstSeason.id);
|
||||||
final firstEpisode = episodes.where((e) => e.kind == MediaKind.episode).firstOrNull;
|
|
||||||
episodeRatingKey = firstEpisode?.id;
|
episodeRatingKey = firstEpisode?.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
import '../media/media_item.dart';
|
|
||||||
import '../media/media_kind.dart';
|
|
||||||
import '../media/media_server_client.dart';
|
|
||||||
|
|
||||||
/// Collect every episode of a show into [out] using the backend's one-shot
|
|
||||||
/// recursive-leaves call ([MediaServerClient.fetchPlayableDescendants] —
|
|
||||||
/// Plex's `/library/metadata/{id}/allLeaves`, Jellyfin's
|
|
||||||
/// `/Items?Recursive=true&IncludeItemTypes=Movie,Episode`). Avoids walking
|
|
||||||
/// show → seasons → episodes client-side, so large series come back in one
|
|
||||||
/// trip and aren't capped by any per-page Limit.
|
|
||||||
///
|
|
||||||
/// A failure of the underlying call propagates to the caller — both
|
|
||||||
/// [DownloadProvider.queueDownload] and the sync rule executor wrap their
|
|
||||||
/// invocations so the user-facing error surfaces / the rule run is rolled
|
|
||||||
/// back.
|
|
||||||
Future<void> collectEpisodesForShow(
|
|
||||||
MediaServerClient client,
|
|
||||||
String showRatingKey, {
|
|
||||||
required bool unwatchedOnly,
|
|
||||||
required List<MediaItem> out,
|
|
||||||
MediaItem? fallback,
|
|
||||||
}) {
|
|
||||||
return _collectPlayable(client, showRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Collect every episode of a single season into [out] via the same
|
|
||||||
/// one-shot endpoint. On a season the leaves *are* the episodes, so the
|
|
||||||
/// shape matches the show case.
|
|
||||||
Future<void> collectEpisodesForSeason(
|
|
||||||
MediaServerClient client,
|
|
||||||
String seasonRatingKey, {
|
|
||||||
required bool unwatchedOnly,
|
|
||||||
required List<MediaItem> out,
|
|
||||||
MediaItem? fallback,
|
|
||||||
}) {
|
|
||||||
return _collectPlayable(client, seasonRatingKey, unwatchedOnly: unwatchedOnly, out: out, fallback: fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _collectPlayable(
|
|
||||||
MediaServerClient client,
|
|
||||||
String parentId, {
|
|
||||||
required bool unwatchedOnly,
|
|
||||||
required List<MediaItem> out,
|
|
||||||
MediaItem? fallback,
|
|
||||||
}) async {
|
|
||||||
final leaves = await client.fetchPlayableDescendants(parentId);
|
|
||||||
for (final ep in leaves) {
|
|
||||||
if (ep.kind != MediaKind.episode) continue;
|
|
||||||
if (unwatchedOnly && ep.isWatched && !ep.hasActiveProgress) continue;
|
|
||||||
out.add(_withFallbackLibrary(ep, fallback));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaItem _withFallbackLibrary(MediaItem item, MediaItem? fallback) {
|
|
||||||
if (fallback == null) return item;
|
|
||||||
final fallbackIsSeason = fallback.kind == MediaKind.season;
|
|
||||||
final fallbackIsShow = fallback.kind == MediaKind.show;
|
|
||||||
return item.copyWith(
|
|
||||||
serverId: item.serverId ?? fallback.serverId,
|
|
||||||
serverName: item.serverName ?? fallback.serverName,
|
|
||||||
libraryId: item.libraryId ?? fallback.libraryId,
|
|
||||||
libraryTitle: item.libraryTitle ?? fallback.libraryTitle,
|
|
||||||
parentId: item.parentId ?? (fallbackIsSeason ? fallback.id : null),
|
|
||||||
parentTitle: item.parentTitle ?? (fallbackIsSeason ? fallback.title : null),
|
|
||||||
grandparentId: item.grandparentId ?? _fallbackGrandparentId(fallback, isShow: fallbackIsShow),
|
|
||||||
grandparentTitle: item.grandparentTitle ?? _fallbackGrandparentTitle(fallback, isShow: fallbackIsShow),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String? _fallbackGrandparentId(MediaItem fallback, {required bool isShow}) {
|
|
||||||
if (isShow) return fallback.id;
|
|
||||||
return fallback.grandparentId ?? fallback.parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
String? _fallbackGrandparentTitle(MediaItem fallback, {required bool isShow}) {
|
|
||||||
if (isShow) return fallback.title;
|
|
||||||
return fallback.grandparentTitle ?? fallback.parentTitle;
|
|
||||||
}
|
|
||||||
+187
-38
@@ -137,7 +137,11 @@ class TvBrowseRailLayout {
|
|||||||
final railEdgePadding = focusExtra + (12 * scale);
|
final railEdgePadding = focusExtra + (12 * scale);
|
||||||
final itemGap = fullCardLayout ? fullCardItemGapForScale(scale) : itemGapForScale(scale);
|
final itemGap = fullCardLayout ? fullCardItemGapForScale(scale) : itemGapForScale(scale);
|
||||||
final isPersonHub = TvBrowseRailLayout.isPersonHub(hub);
|
final isPersonHub = TvBrowseRailLayout.isPersonHub(hub);
|
||||||
final hasWide = !isPersonHub && hub.items.any((item) => item.usesWideAspectRatio(episodePosterMode));
|
final emptyEpisodeThumbnailHub =
|
||||||
|
hub.items.isEmpty && hub.type == 'episode' && episodePosterMode == EpisodePosterMode.episodeThumbnail;
|
||||||
|
final hasWide =
|
||||||
|
!isPersonHub &&
|
||||||
|
(emptyEpisodeThumbnailHub || hub.items.any((item) => item.usesWideAspectRatio(episodePosterMode)));
|
||||||
final hasTall = !isPersonHub && hub.items.any((item) => !item.usesWideAspectRatio(episodePosterMode));
|
final hasTall = !isPersonHub && hub.items.any((item) => !item.usesWideAspectRatio(episodePosterMode));
|
||||||
final isMixedHub = hasWide && hasTall;
|
final isMixedHub = hasWide && hasTall;
|
||||||
final useWideLayout = hasWide && (!hasTall || episodePosterMode == EpisodePosterMode.episodeThumbnail);
|
final useWideLayout = hasWide && (!hasTall || episodePosterMode == EpisodePosterMode.episodeThumbnail);
|
||||||
@@ -205,9 +209,11 @@ class TvBrowseRailLayout {
|
|||||||
required TvBrowseRailLayoutMetrics metrics,
|
required TvBrowseRailLayoutMetrics metrics,
|
||||||
required double viewportWidth,
|
required double viewportWidth,
|
||||||
required double scale,
|
required double scale,
|
||||||
|
bool? hasTrailing,
|
||||||
}) {
|
}) {
|
||||||
|
final showTrailing = hasTrailing ?? hub.more;
|
||||||
final itemContentWidth = hub.items.length * (metrics.cardWidth + metrics.itemGap);
|
final itemContentWidth = hub.items.length * (metrics.cardWidth + metrics.itemGap);
|
||||||
final moreContentWidth = hub.more ? viewAllItemWidthForScale(scale) + metrics.itemGap : 0.0;
|
final moreContentWidth = showTrailing ? viewAllItemWidthForScale(scale) + metrics.itemGap : 0.0;
|
||||||
final contentWidth = (metrics.railEdgePadding * 2) + itemContentWidth + moreContentWidth;
|
final contentWidth = (metrics.railEdgePadding * 2) + itemContentWidth + moreContentWidth;
|
||||||
return (contentWidth - viewportWidth).clamp(0.0, double.infinity).toDouble();
|
return (contentWidth - viewportWidth).clamp(0.0, double.infinity).toDouble();
|
||||||
}
|
}
|
||||||
@@ -217,8 +223,10 @@ class TvBrowseRailLayout {
|
|||||||
required int index,
|
required int index,
|
||||||
required TvBrowseRailLayoutMetrics metrics,
|
required TvBrowseRailLayoutMetrics metrics,
|
||||||
required double scale,
|
required double scale,
|
||||||
|
bool? hasTrailing,
|
||||||
}) {
|
}) {
|
||||||
if (index == hub.items.length && hub.more) return viewAllItemWidthForScale(scale) + metrics.itemGap;
|
final showTrailing = hasTrailing ?? hub.more;
|
||||||
|
if (index == hub.items.length && showTrailing) return viewAllItemWidthForScale(scale) + metrics.itemGap;
|
||||||
return metrics.cardWidth + metrics.itemGap;
|
return metrics.cardWidth + metrics.itemGap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,15 +237,23 @@ class TvBrowseRailLayout {
|
|||||||
required double viewportWidth,
|
required double viewportWidth,
|
||||||
required double maxScrollExtent,
|
required double maxScrollExtent,
|
||||||
required double scale,
|
required double scale,
|
||||||
|
bool? hasTrailing,
|
||||||
}) {
|
}) {
|
||||||
final totalCount = hub.items.length + (hub.more ? 1 : 0);
|
final showTrailing = hasTrailing ?? hub.more;
|
||||||
|
final totalCount = hub.items.length + (showTrailing ? 1 : 0);
|
||||||
if (totalCount == 0) return 0;
|
if (totalCount == 0) return 0;
|
||||||
|
|
||||||
final clampedIndex = index.clamp(0, totalCount - 1).toInt();
|
final clampedIndex = index.clamp(0, totalCount - 1).toInt();
|
||||||
final normalItemExtent = metrics.cardWidth + metrics.itemGap;
|
final normalItemExtent = metrics.cardWidth + metrics.itemGap;
|
||||||
final normalItemsBefore = clampedIndex < hub.items.length ? clampedIndex : hub.items.length;
|
final normalItemsBefore = clampedIndex < hub.items.length ? clampedIndex : hub.items.length;
|
||||||
final leadingOffset = metrics.railEdgePadding + (normalItemsBefore * normalItemExtent);
|
final leadingOffset = metrics.railEdgePadding + (normalItemsBefore * normalItemExtent);
|
||||||
final targetExtent = itemExtentForIndex(hub: hub, index: clampedIndex, metrics: metrics, scale: scale);
|
final targetExtent = itemExtentForIndex(
|
||||||
|
hub: hub,
|
||||||
|
index: clampedIndex,
|
||||||
|
metrics: metrics,
|
||||||
|
scale: scale,
|
||||||
|
hasTrailing: showTrailing,
|
||||||
|
);
|
||||||
final targetCenter = leadingOffset + (targetExtent / 2);
|
final targetCenter = leadingOffset + (targetExtent / 2);
|
||||||
return (targetCenter - (viewportWidth / 2)).clamp(0.0, maxScrollExtent).toDouble();
|
return (targetCenter - (viewportWidth / 2)).clamp(0.0, maxScrollExtent).toDouble();
|
||||||
}
|
}
|
||||||
@@ -280,6 +296,9 @@ class TvBrowseRailLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What [TvBrowseRail] renders in a hub's trailing slot (after the last item).
|
||||||
|
enum TvRailTrailing { none, loading, error, viewAll }
|
||||||
|
|
||||||
class TvBrowseRail extends StatefulWidget {
|
class TvBrowseRail extends StatefulWidget {
|
||||||
final List<MediaHub> hubs;
|
final List<MediaHub> hubs;
|
||||||
final IconData Function(MediaHub hub, int index) iconForHub;
|
final IconData Function(MediaHub hub, int index) iconForHub;
|
||||||
@@ -289,6 +308,13 @@ class TvBrowseRail extends StatefulWidget {
|
|||||||
final VoidCallback? onRemoveFromContinueWatching;
|
final VoidCallback? onRemoveFromContinueWatching;
|
||||||
final bool Function(MediaHub hub)? isContinueWatchingHub;
|
final bool Function(MediaHub hub)? isContinueWatchingHub;
|
||||||
final Future<List<MediaItem>> Function(MediaHub hub)? loadMoreItems;
|
final Future<List<MediaItem>> Function(MediaHub hub)? loadMoreItems;
|
||||||
|
|
||||||
|
/// Optional per-hub trailing-slot state (loading/error/viewAll). When null the
|
||||||
|
/// rail keeps the legacy "[MediaHub.more] → View All" behavior.
|
||||||
|
final TvRailTrailing Function(MediaHub hub)? trailingForHub;
|
||||||
|
|
||||||
|
/// Invoked when the user activates a hub's trailing retry tile.
|
||||||
|
final void Function(MediaHub hub)? onRetryHub;
|
||||||
final void Function(MediaHub hub, int index)? onActiveHubChanged;
|
final void Function(MediaHub hub, int index)? onActiveHubChanged;
|
||||||
final VoidCallback? onNavigateUp;
|
final VoidCallback? onNavigateUp;
|
||||||
final VoidCallback? onNavigateToSidebar;
|
final VoidCallback? onNavigateToSidebar;
|
||||||
@@ -313,6 +339,8 @@ class TvBrowseRail extends StatefulWidget {
|
|||||||
this.onRemoveFromContinueWatching,
|
this.onRemoveFromContinueWatching,
|
||||||
this.isContinueWatchingHub,
|
this.isContinueWatchingHub,
|
||||||
this.loadMoreItems,
|
this.loadMoreItems,
|
||||||
|
this.trailingForHub,
|
||||||
|
this.onRetryHub,
|
||||||
this.onActiveHubChanged,
|
this.onActiveHubChanged,
|
||||||
this.onNavigateUp,
|
this.onNavigateUp,
|
||||||
this.onNavigateToSidebar,
|
this.onNavigateToSidebar,
|
||||||
@@ -347,6 +375,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
final Map<String, GlobalKey<MediaCardState>> _mediaCardKeys = {};
|
final Map<String, GlobalKey<MediaCardState>> _mediaCardKeys = {};
|
||||||
final Map<String, TvBrowseRailLayoutMetrics> _metricsByHub = {};
|
final Map<String, TvBrowseRailLayoutMetrics> _metricsByHub = {};
|
||||||
final Map<String, double> _scaleByHub = {};
|
final Map<String, double> _scaleByHub = {};
|
||||||
|
final Map<String, TvRailTrailing> _lastTrailingByHubId = {};
|
||||||
|
|
||||||
int _hubIndex = 0;
|
int _hubIndex = 0;
|
||||||
int _itemIndex = 0;
|
int _itemIndex = 0;
|
||||||
@@ -382,6 +411,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
_focusNode.addListener(_handleFocusChange);
|
_focusNode.addListener(_handleFocusChange);
|
||||||
_selectInitialHubIfPossible();
|
_selectInitialHubIfPossible();
|
||||||
final selectedInitialItem = _selectInitialItemIfPossible();
|
final selectedInitialItem = _selectInitialItemIfPossible();
|
||||||
|
_rememberTrailingStates();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted || widget.hubs.isEmpty) return;
|
if (!mounted || widget.hubs.isEmpty) return;
|
||||||
if (selectedInitialItem) _scrollToItem(animate: false);
|
if (selectedInitialItem) _scrollToItem(animate: false);
|
||||||
@@ -395,11 +425,13 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant TvBrowseRail oldWidget) {
|
void didUpdateWidget(covariant TvBrowseRail oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
final hubStateChanged = !_hasSameHubState(oldWidget.hubs, widget.hubs);
|
final trailingStateChanged = _hasTrailingStateChanged(widget.hubs);
|
||||||
|
final hubStateChanged = trailingStateChanged || !_hasSameHubState(oldWidget.hubs, widget.hubs);
|
||||||
final initialSelectionChanged =
|
final initialSelectionChanged =
|
||||||
oldWidget.initialHubId != widget.initialHubId || oldWidget.initialItemId != widget.initialItemId;
|
oldWidget.initialHubId != widget.initialHubId || oldWidget.initialItemId != widget.initialItemId;
|
||||||
|
|
||||||
if (!hubStateChanged && !initialSelectionChanged) {
|
if (!hubStateChanged && !initialSelectionChanged) {
|
||||||
|
_rememberTrailingStates();
|
||||||
if (!oldWidget.autofocus && widget.autofocus) {
|
if (!oldWidget.autofocus && widget.autofocus) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (mounted) _focusNode.requestFocus();
|
if (mounted) _focusNode.requestFocus();
|
||||||
@@ -415,6 +447,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
if (widget.hubs.isEmpty) {
|
if (widget.hubs.isEmpty) {
|
||||||
_hubIndex = 0;
|
_hubIndex = 0;
|
||||||
_itemIndex = 0;
|
_itemIndex = 0;
|
||||||
|
_rememberTrailingStates();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,11 +468,20 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
_itemIndex = _itemIndex.clamp(0, _totalItemCount(hub) == 0 ? 0 : _totalItemCount(hub) - 1);
|
_itemIndex = _itemIndex.clamp(0, _totalItemCount(hub) == 0 ? 0 : _totalItemCount(hub) - 1);
|
||||||
final selectedInitialItem = _selectInitialItemIfPossible();
|
final selectedInitialItem = _selectInitialItemIfPossible();
|
||||||
final activeHubChanged = oldActiveHubId != _activeHub?.id;
|
final activeHubChanged = oldActiveHubId != _activeHub?.id;
|
||||||
final shouldAlignActiveHub = selectedInitialHub || activeHubChanged || !_hasUserChangedHub;
|
final activeHubStateChanged =
|
||||||
|
_hubStateChanged(oldWidget.hubs, widget.hubs, _hubIndex) ||
|
||||||
|
(_activeHub != null && _trailingStateChanged(_activeHub!));
|
||||||
|
final shouldJumpAlignActiveHub = selectedInitialHub || activeHubChanged || !_hasUserChangedHub;
|
||||||
|
final shouldAnimateAlignActiveHub = !shouldJumpAlignActiveHub && activeHubStateChanged;
|
||||||
|
_rememberTrailingStates();
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (selectedInitialItem) _scrollToItem(animate: false);
|
if (selectedInitialItem) _scrollToItem(animate: false);
|
||||||
if (shouldAlignActiveHub) _scrollActiveHubToTop(animate: false);
|
if (shouldJumpAlignActiveHub) {
|
||||||
|
_scrollActiveHubToTop(animate: false);
|
||||||
|
} else if (shouldAnimateAlignActiveHub) {
|
||||||
|
_scrollActiveHubToTop();
|
||||||
|
}
|
||||||
if (!oldWidget.autofocus && widget.autofocus) _focusNode.requestFocus();
|
if (!oldWidget.autofocus && widget.autofocus) _focusNode.requestFocus();
|
||||||
if (activeHubChanged) _notifyActiveHubChanged();
|
if (activeHubChanged) _notifyActiveHubChanged();
|
||||||
_notifyFocusedItem();
|
_notifyFocusedItem();
|
||||||
@@ -449,18 +491,42 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
bool _hasSameHubState(List<MediaHub> oldHubs, List<MediaHub> newHubs) {
|
bool _hasSameHubState(List<MediaHub> oldHubs, List<MediaHub> newHubs) {
|
||||||
if (oldHubs.length != newHubs.length) return false;
|
if (oldHubs.length != newHubs.length) return false;
|
||||||
for (var i = 0; i < oldHubs.length; i++) {
|
for (var i = 0; i < oldHubs.length; i++) {
|
||||||
final oldHub = oldHubs[i];
|
if (_hubStateChanged(oldHubs, newHubs, i)) return false;
|
||||||
final newHub = newHubs[i];
|
|
||||||
if (oldHub.id != newHub.id || oldHub.more != newHub.more || oldHub.items.length != newHub.items.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (var j = 0; j < oldHub.items.length; j++) {
|
|
||||||
if (oldHub.items[j].globalKey != newHub.items[j].globalKey) return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _hubStateChanged(List<MediaHub> oldHubs, List<MediaHub> newHubs, int index) {
|
||||||
|
if (index < 0 || index >= oldHubs.length || index >= newHubs.length) return true;
|
||||||
|
final oldHub = oldHubs[index];
|
||||||
|
final newHub = newHubs[index];
|
||||||
|
if (oldHub.id != newHub.id || oldHub.more != newHub.more || oldHub.items.length != newHub.items.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (var j = 0; j < oldHub.items.length; j++) {
|
||||||
|
if (oldHub.items[j].globalKey != newHub.items[j].globalKey) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _hasTrailingStateChanged(List<MediaHub> hubs) {
|
||||||
|
for (final hub in hubs) {
|
||||||
|
if (_trailingStateChanged(hub)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _trailingStateChanged(MediaHub hub) {
|
||||||
|
final previous = _lastTrailingByHubId[hub.id];
|
||||||
|
return previous != null && previous != _trailingFor(hub);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _rememberTrailingStates() {
|
||||||
|
_lastTrailingByHubId
|
||||||
|
..clear()
|
||||||
|
..addEntries(widget.hubs.map((hub) => MapEntry(hub.id, _trailingFor(hub))));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_longPressTimer?.cancel();
|
_longPressTimer?.cancel();
|
||||||
@@ -492,7 +558,9 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
_suppressSelectUntilKeyUp = false;
|
_suppressSelectUntilKeyUp = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _totalItemCount(MediaHub hub) => hub.items.length + (hub.more ? 1 : 0);
|
bool _hasTrailingFor(MediaHub hub) => _trailingFor(hub) != TvRailTrailing.none;
|
||||||
|
|
||||||
|
int _totalItemCount(MediaHub hub) => hub.items.length + (_hasTrailingFor(hub) ? 1 : 0);
|
||||||
|
|
||||||
bool _isPersonHub(MediaHub hub) => TvBrowseRailLayout.isPersonHub(hub);
|
bool _isPersonHub(MediaHub hub) => TvBrowseRailLayout.isPersonHub(hub);
|
||||||
|
|
||||||
@@ -735,6 +803,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
viewportWidth: viewportWidth,
|
viewportWidth: viewportWidth,
|
||||||
maxScrollExtent: maxScrollExtent,
|
maxScrollExtent: maxScrollExtent,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
hasTrailing: _hasTrailingFor(hub),
|
||||||
);
|
);
|
||||||
|
|
||||||
final distance = (position.pixels - target).abs();
|
final distance = (position.pixels - target).abs();
|
||||||
@@ -766,6 +835,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
viewportWidth: viewportWidth,
|
viewportWidth: viewportWidth,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
hasTrailing: _hasTrailingFor(hub),
|
||||||
);
|
);
|
||||||
final initialScrollOffset = TvBrowseRailLayout.scrollOffsetForIndex(
|
final initialScrollOffset = TvBrowseRailLayout.scrollOffsetForIndex(
|
||||||
hub: hub,
|
hub: hub,
|
||||||
@@ -774,6 +844,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
viewportWidth: viewportWidth,
|
viewportWidth: viewportWidth,
|
||||||
maxScrollExtent: maxScrollExtent,
|
maxScrollExtent: maxScrollExtent,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
|
hasTrailing: _hasTrailingFor(hub),
|
||||||
);
|
);
|
||||||
return ScrollController(initialScrollOffset: initialScrollOffset);
|
return ScrollController(initialScrollOffset: initialScrollOffset);
|
||||||
});
|
});
|
||||||
@@ -793,8 +864,17 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
Future<void> _activateCurrentItem() async {
|
Future<void> _activateCurrentItem() async {
|
||||||
final hub = _activeHub;
|
final hub = _activeHub;
|
||||||
if (hub == null) return;
|
if (hub == null) return;
|
||||||
if (_itemIndex == hub.items.length && hub.more) {
|
if (_itemIndex == hub.items.length && _hasTrailingFor(hub)) {
|
||||||
_navigateToHubDetail(hub);
|
switch (_trailingFor(hub)) {
|
||||||
|
case TvRailTrailing.error:
|
||||||
|
widget.onRetryHub?.call(hub);
|
||||||
|
break;
|
||||||
|
case TvRailTrailing.loading:
|
||||||
|
break; // no-op while the page loads
|
||||||
|
case TvRailTrailing.viewAll:
|
||||||
|
case TvRailTrailing.none:
|
||||||
|
_navigateToHubDetail(hub);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_itemIndex >= hub.items.length) return;
|
if (_itemIndex >= hub.items.length) return;
|
||||||
@@ -1055,7 +1135,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (hub.more) ...[
|
if (_trailingFor(hub) == TvRailTrailing.viewAll) ...[
|
||||||
SizedBox(width: 8 * scale),
|
SizedBox(width: 8 * scale),
|
||||||
AppIcon(Symbols.chevron_right_rounded, fill: 1, size: 20 * scale, color: iconColor),
|
AppIcon(Symbols.chevron_right_rounded, fill: 1, size: 20 * scale, color: iconColor),
|
||||||
SizedBox(width: 30 * scale),
|
SizedBox(width: 30 * scale),
|
||||||
@@ -1108,8 +1188,13 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
padding: .fromLTRB(metrics.railEdgePadding, 2 * scale, metrics.railEdgePadding, 6 * scale),
|
padding: .fromLTRB(metrics.railEdgePadding, 2 * scale, metrics.railEdgePadding, 6 * scale),
|
||||||
itemExtentBuilder: (itemIndex, _) =>
|
itemExtentBuilder: (itemIndex, _) => TvBrowseRailLayout.itemExtentForIndex(
|
||||||
TvBrowseRailLayout.itemExtentForIndex(hub: hub, index: itemIndex, metrics: metrics, scale: scale),
|
hub: hub,
|
||||||
|
index: itemIndex,
|
||||||
|
metrics: metrics,
|
||||||
|
scale: scale,
|
||||||
|
hasTrailing: _hasTrailingFor(hub),
|
||||||
|
),
|
||||||
itemCount: totalCount,
|
itemCount: totalCount,
|
||||||
itemBuilder: (context, itemIndex) {
|
itemBuilder: (context, itemIndex) {
|
||||||
final isFocused = hasFocus && isActiveHub && itemIndex == _itemIndex;
|
final isFocused = hasFocus && isActiveHub && itemIndex == _itemIndex;
|
||||||
@@ -1118,15 +1203,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
padding: .only(right: metrics.itemGap),
|
padding: .only(right: metrics.itemGap),
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: .centerLeft,
|
alignment: .centerLeft,
|
||||||
child: _buildViewAllButton(
|
child: _buildTrailingSlot(context, hub, hubIndex, itemIndex, isFocused: isFocused, scale: scale),
|
||||||
context,
|
|
||||||
isFocused: isFocused,
|
|
||||||
scale: scale,
|
|
||||||
onTap: () {
|
|
||||||
_selectHubItem(hub, hubIndex, itemIndex);
|
|
||||||
_navigateToHubDetail(hub);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1316,11 +1393,88 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve the trailing-slot state for [hub], defaulting to the legacy
|
||||||
|
/// "[MediaHub.more] → View All" behavior when no resolver was supplied.
|
||||||
|
TvRailTrailing _trailingFor(MediaHub hub) =>
|
||||||
|
widget.trailingForHub?.call(hub) ?? (hub.more ? TvRailTrailing.viewAll : TvRailTrailing.none);
|
||||||
|
|
||||||
|
Widget _buildTrailingSlot(
|
||||||
|
BuildContext context,
|
||||||
|
MediaHub hub,
|
||||||
|
int hubIndex,
|
||||||
|
int itemIndex, {
|
||||||
|
required bool isFocused,
|
||||||
|
required double scale,
|
||||||
|
}) {
|
||||||
|
switch (_trailingFor(hub)) {
|
||||||
|
case TvRailTrailing.loading:
|
||||||
|
return _buildTrailingSpinner(context, isFocused: isFocused, scale: scale);
|
||||||
|
case TvRailTrailing.error:
|
||||||
|
return _buildViewAllButton(
|
||||||
|
context,
|
||||||
|
isFocused: isFocused,
|
||||||
|
scale: scale,
|
||||||
|
label: t.common.retry,
|
||||||
|
icon: Symbols.refresh_rounded,
|
||||||
|
onTap: () {
|
||||||
|
_selectHubItem(hub, hubIndex, itemIndex);
|
||||||
|
widget.onRetryHub?.call(hub);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
case TvRailTrailing.viewAll:
|
||||||
|
return _buildViewAllButton(
|
||||||
|
context,
|
||||||
|
isFocused: isFocused,
|
||||||
|
scale: scale,
|
||||||
|
onTap: () {
|
||||||
|
_selectHubItem(hub, hubIndex, itemIndex);
|
||||||
|
_navigateToHubDetail(hub);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
case TvRailTrailing.none:
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTrailingSpinner(BuildContext context, {required bool isFocused, required double scale}) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final duration = FocusTheme.getAnimationDuration(context);
|
||||||
|
final width = TvBrowseRailLayout.viewAllItemWidthForScale(scale);
|
||||||
|
final height = TvBrowseRailLayout.viewAllPillHeightForScale(scale);
|
||||||
|
final foreground = isFocused ? theme.colorScheme.primary : theme.colorScheme.onSurface.withValues(alpha: 0.78);
|
||||||
|
final background = isFocused
|
||||||
|
? theme.colorScheme.primary.withValues(alpha: 0.2)
|
||||||
|
: theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.18);
|
||||||
|
return AnimatedScale(
|
||||||
|
scale: isFocused ? 1.04 : 1.0,
|
||||||
|
duration: duration,
|
||||||
|
curve: Curves.easeOutCubic,
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: duration,
|
||||||
|
curve: Curves.easeOutCubic,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: background,
|
||||||
|
borderRadius: BorderRadius.circular(height / 2),
|
||||||
|
boxShadow: isFocused
|
||||||
|
? [BoxShadow(color: theme.colorScheme.primary.withValues(alpha: 0.2), blurRadius: 18, spreadRadius: 1)]
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(width: 22, height: 22, child: CircularProgressIndicator(strokeWidth: 2, color: foreground)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildViewAllButton(
|
Widget _buildViewAllButton(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
required bool isFocused,
|
required bool isFocused,
|
||||||
required double scale,
|
required double scale,
|
||||||
required VoidCallback onTap,
|
required VoidCallback onTap,
|
||||||
|
String? label,
|
||||||
|
IconData icon = Symbols.arrow_forward_rounded,
|
||||||
}) {
|
}) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final duration = FocusTheme.getAnimationDuration(context);
|
final duration = FocusTheme.getAnimationDuration(context);
|
||||||
@@ -1362,7 +1516,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
t.common.viewAll,
|
label ?? t.common.viewAll,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: .ellipsis,
|
overflow: .ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -1374,12 +1528,7 @@ class TvBrowseRailState extends State<TvBrowseRail> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: (5 * scale).clamp(4, 7).toDouble()),
|
SizedBox(width: (5 * scale).clamp(4, 7).toDouble()),
|
||||||
AppIcon(
|
AppIcon(icon, fill: 1, size: (18 * scale).clamp(16, 22).toDouble(), color: foreground),
|
||||||
Symbols.arrow_forward_rounded,
|
|
||||||
fill: 1,
|
|
||||||
size: (18 * scale).clamp(16, 22).toDouble(),
|
|
||||||
color: foreground,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user