diff --git a/lib/i18n/de.i18n.json b/lib/i18n/de.i18n.json index 502e0e79..1ed84c3a 100644 --- a/lib/i18n/de.i18n.json +++ b/lib/i18n/de.i18n.json @@ -32,6 +32,7 @@ "delete": "Löschen", "shuffle": "Zufall", "addTo": "Hinzufügen zu...", + "createNew": "Neu erstellen", "remove": "Entfernen", "paste": "Einfügen", "connect": "Verbinden", @@ -634,7 +635,6 @@ "itemAdded": "Zur Wiedergabeliste hinzugefügt", "itemRemoved": "Aus Wiedergabeliste entfernt", "selectPlaylist": "Wiedergabeliste auswählen", - "createNewPlaylist": "Neue Wiedergabeliste erstellen", "errorCreating": "Wiedergabeliste konnte nicht erstellt werden", "errorDeleting": "Wiedergabeliste konnte nicht gelöscht werden", "errorLoading": "Wiedergabelisten konnten nicht geladen werden", @@ -655,7 +655,6 @@ "deleteFailedWithError": "Sammlung konnte nicht gelöscht werden: ${error}", "failedToLoadItems": "Sammlungselemente konnten nicht geladen werden: ${error}", "selectCollection": "Sammlung auswählen", - "createNewCollection": "Neue Sammlung erstellen", "collectionName": "Sammlungsname", "enterCollectionName": "Sammlungsnamen eingeben", "addedToCollection": "Zur Sammlung hinzugefügt", diff --git a/lib/i18n/en.i18n.json b/lib/i18n/en.i18n.json index 48db9325..4c0567b5 100644 --- a/lib/i18n/en.i18n.json +++ b/lib/i18n/en.i18n.json @@ -32,6 +32,7 @@ "delete": "Delete", "shuffle": "Shuffle", "addTo": "Add to...", + "createNew": "Create new", "remove": "Remove", "paste": "Paste", "connect": "Connect", @@ -607,7 +608,6 @@ "deleteFailedWithError": "Failed to delete collection: ${error}", "failedToLoadItems": "Failed to load collection items: ${error}", "selectCollection": "Select Collection", - "createNewCollection": "Create New Collection", "collectionName": "Collection Name", "enterCollectionName": "Enter collection name", "addedToCollection": "Added to collection", @@ -639,7 +639,6 @@ "itemAdded": "Added to playlist", "itemRemoved": "Removed from playlist", "selectPlaylist": "Select Playlist", - "createNewPlaylist": "Create New Playlist", "errorCreating": "Failed to create playlist", "errorDeleting": "Failed to delete playlist", "errorLoading": "Failed to load playlists", diff --git a/lib/i18n/es.i18n.json b/lib/i18n/es.i18n.json index 98ec64f4..186949e9 100644 --- a/lib/i18n/es.i18n.json +++ b/lib/i18n/es.i18n.json @@ -32,6 +32,7 @@ "delete": "Eliminar", "shuffle": "Aleatorio", "addTo": "Añadir a...", + "createNew": "Crear", "remove": "Eliminar", "paste": "Pegar", "connect": "Conectar", @@ -607,7 +608,6 @@ "deleteFailedWithError": "Error al eliminar la colección: ${error}", "failedToLoadItems": "Error al cargar los elementos de la colección: ${error}", "selectCollection": "Seleccionar Colección", - "createNewCollection": "Crear Nueva Colección", "collectionName": "Nombre de la Colección", "enterCollectionName": "Introduce el nombre de la colección", "addedToCollection": "Añadido a la colección", @@ -639,7 +639,6 @@ "itemAdded": "Añadido a la lista", "itemRemoved": "Eliminado de la lista", "selectPlaylist": "Seleccionar Lista", - "createNewPlaylist": "Crear Nueva Lista", "errorCreating": "Error al crear la lista", "errorDeleting": "Error al eliminar la lista", "errorLoading": "Error al cargar las listas", diff --git a/lib/i18n/fr.i18n.json b/lib/i18n/fr.i18n.json index 8d02ebf8..9c355c2a 100644 --- a/lib/i18n/fr.i18n.json +++ b/lib/i18n/fr.i18n.json @@ -32,6 +32,7 @@ "delete": "Supprimer", "shuffle": "Mélanger", "addTo": "Ajouter à...", + "createNew": "Créer", "remove": "Supprimer", "paste": "Coller", "connect": "Connecter", @@ -607,7 +608,6 @@ "deleteFailedWithError": "Échec de la suppression de la collection: ${error}", "failedToLoadItems": "Échec du chargement des éléments de la collection: ${error}", "selectCollection": "Sélectionner une collection", - "createNewCollection": "Créer une nouvelle collection", "collectionName": "Nom de la collection", "enterCollectionName": "Entrez le nom de la collection", "addedToCollection": "Ajouté à la collection", @@ -639,7 +639,6 @@ "itemAdded": "Ajouté à la playlist", "itemRemoved": "Retiré de la playlist", "selectPlaylist": "Select Playlist", - "createNewPlaylist": "Créer une nouvelle playlist", "errorCreating": "Échec de la création de playlist", "errorDeleting": "Échec de suppression de playlist", "errorLoading": "Échec de chargement de playlists", diff --git a/lib/i18n/it.i18n.json b/lib/i18n/it.i18n.json index 3ed6fa0b..da867b4e 100644 --- a/lib/i18n/it.i18n.json +++ b/lib/i18n/it.i18n.json @@ -32,6 +32,7 @@ "delete": "Elimina", "shuffle": "Casuale", "addTo": "Aggiungi a...", + "createNew": "Crea", "remove": "Rimuovi", "paste": "Incolla", "connect": "Connetti", @@ -634,7 +635,6 @@ "itemAdded": "Aggiunto alla playlist", "itemRemoved": "Rimosso dalla playlist", "selectPlaylist": "Seleziona playlist", - "createNewPlaylist": "Crea nuova playlist", "errorCreating": "Errore durante la creazione della playlist", "errorDeleting": "Errore durante l'eliminazione della playlist", "errorLoading": "Errore durante il caricamento delle playlist", @@ -655,7 +655,6 @@ "deleteFailedWithError": "Impossibile eliminare la raccolta: ${error}", "failedToLoadItems": "Impossibile caricare gli elementi della raccolta: ${error}", "selectCollection": "Seleziona raccolta", - "createNewCollection": "Crea nuova raccolta", "collectionName": "Nome raccolta", "enterCollectionName": "Inserisci nome raccolta", "addedToCollection": "Aggiunto alla raccolta", diff --git a/lib/i18n/ko.i18n.json b/lib/i18n/ko.i18n.json index b4c73a04..8a5ee097 100644 --- a/lib/i18n/ko.i18n.json +++ b/lib/i18n/ko.i18n.json @@ -32,6 +32,7 @@ "delete": "삭제", "shuffle": "무작위 재생", "addTo": "추가하기...", + "createNew": "새로 만들기", "remove": "삭제", "paste": "붙여넣기", "connect": "연결", @@ -607,7 +608,6 @@ "deleteFailedWithError": "컬렉션 삭제 실패: ${error}", "failedToLoadItems": "컬렉션 항목 로드 실패: ${error}", "selectCollection": "컬렉션 선택", - "createNewCollection": "새 컬렉션 생성", "collectionName": "컬렉션 이름", "enterCollectionName": "컬렉션 이름 입력", "addedToCollection": "컬렉션에 추가됨", @@ -639,7 +639,6 @@ "itemAdded": "재생 목록에 추가 되었습니다", "itemRemoved": "재생 목록에서 제거됨", "selectPlaylist": "재생 목록 선택", - "createNewPlaylist": "새 재생 목록 생성", "errorCreating": "재생 목록 생성 실패", "errorDeleting": "재생 목록 삭제 실패", "errorLoading": "재생 목록 로드 실패", diff --git a/lib/i18n/nl.i18n.json b/lib/i18n/nl.i18n.json index 36de0242..31a80a73 100644 --- a/lib/i18n/nl.i18n.json +++ b/lib/i18n/nl.i18n.json @@ -32,6 +32,7 @@ "delete": "Verwijderen", "shuffle": "Willekeurig", "addTo": "Toevoegen aan...", + "createNew": "Nieuw aanmaken", "remove": "Verwijderen", "paste": "Plakken", "connect": "Verbinden", @@ -634,7 +635,6 @@ "itemAdded": "Toegevoegd aan afspeellijst", "itemRemoved": "Verwijderd uit afspeellijst", "selectPlaylist": "Selecteer afspeellijst", - "createNewPlaylist": "Nieuwe afspeellijst maken", "errorCreating": "Fout bij maken afspeellijst", "errorDeleting": "Fout bij verwijderen afspeellijst", "errorLoading": "Fout bij laden afspeellijsten", @@ -655,7 +655,6 @@ "deleteFailedWithError": "Collectie verwijderen mislukt: ${error}", "failedToLoadItems": "Collectie-items laden mislukt: ${error}", "selectCollection": "Selecteer collectie", - "createNewCollection": "Nieuwe collectie maken", "collectionName": "Collectienaam", "enterCollectionName": "Voer collectienaam in", "addedToCollection": "Toegevoegd aan collectie", diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart index 25381e77..e0d44f80 100644 --- a/lib/i18n/strings.g.dart +++ b/lib/i18n/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 9 -/// Strings: 7272 (808 per locale) +/// Strings: 7263 (807 per locale) /// -/// Built on 2026-03-02 at 16:42 UTC +/// Built on 2026-03-02 at 20:21 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/lib/i18n/strings_de.g.dart b/lib/i18n/strings_de.g.dart index cf4d5ae2..f539817a 100644 --- a/lib/i18n/strings_de.g.dart +++ b/lib/i18n/strings_de.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonDe implements TranslationsCommonEn { @override String get delete => 'Löschen'; @override String get shuffle => 'Zufall'; @override String get addTo => 'Hinzufügen zu...'; + @override String get createNew => 'Neu erstellen'; @override String get remove => 'Entfernen'; @override String get paste => 'Einfügen'; @override String get connect => 'Verbinden'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsDe implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Video-Zeitleiste'; @override String get volumeSlider => 'Lautstärkepegel'; @override String endsAt({required Object time}) => 'Endet um ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Wiedergabe im Bild-in-Bild-Modus'; @override String get pipFailed => 'Bild-in-Bild konnte nicht gestartet werden'; @override late final _TranslationsVideoControlsPipErrorsDe pipErrors = _TranslationsVideoControlsPipErrorsDe._(_root); @override String get chapters => 'Kapitel'; @@ -888,7 +889,6 @@ class _TranslationsPlaylistsDe implements TranslationsPlaylistsEn { @override String get itemAdded => 'Zur Wiedergabeliste hinzugefügt'; @override String get itemRemoved => 'Aus Wiedergabeliste entfernt'; @override String get selectPlaylist => 'Wiedergabeliste auswählen'; - @override String get createNewPlaylist => 'Neue Wiedergabeliste erstellen'; @override String get errorCreating => 'Wiedergabeliste konnte nicht erstellt werden'; @override String get errorDeleting => 'Wiedergabeliste konnte nicht gelöscht werden'; @override String get errorLoading => 'Wiedergabelisten konnten nicht geladen werden'; @@ -916,7 +916,6 @@ class _TranslationsCollectionsDe implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Sammlung konnte nicht gelöscht werden: ${error}'; @override String failedToLoadItems({required Object error}) => 'Sammlungselemente konnten nicht geladen werden: ${error}'; @override String get selectCollection => 'Sammlung auswählen'; - @override String get createNewCollection => 'Neue Sammlung erstellen'; @override String get collectionName => 'Sammlungsname'; @override String get enterCollectionName => 'Sammlungsnamen eingeben'; @override String get addedToCollection => 'Zur Sammlung hinzugefügt'; @@ -1333,6 +1332,7 @@ extension on TranslationsDe { 'common.delete' => 'Löschen', 'common.shuffle' => 'Zufall', 'common.addTo' => 'Hinzufügen zu...', + 'common.createNew' => 'Neu erstellen', 'common.remove' => 'Entfernen', 'common.paste' => 'Einfügen', 'common.connect' => 'Verbinden', @@ -1628,7 +1628,7 @@ extension on TranslationsDe { 'videoControls.timelineSlider' => 'Video-Zeitleiste', 'videoControls.volumeSlider' => 'Lautstärkepegel', 'videoControls.endsAt' => ({required Object time}) => 'Endet um ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Wiedergabe im Bild-in-Bild-Modus', 'videoControls.pipFailed' => 'Bild-in-Bild konnte nicht gestartet werden', 'videoControls.pipErrors.androidVersion' => 'Erfordert Android 8.0 oder neuer', 'videoControls.pipErrors.iosVersion' => 'Erfordert iOS 15.0 oder neuer', @@ -1816,9 +1816,9 @@ extension on TranslationsDe { 'liveTv.noChannels' => 'Keine Kanäle verfügbar', 'liveTv.noDvr' => 'Kein DVR auf einem Server konfiguriert', 'liveTv.tuneFailed' => 'Kanal konnte nicht eingestellt werden', - 'liveTv.loading' => 'Kanäle werden geladen...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Kanäle werden geladen...', 'liveTv.nowPlaying' => 'Läuft gerade', 'liveTv.noPrograms' => 'Keine Programmdaten verfügbar', 'liveTv.channelNumber' => ({required Object number}) => 'Kanal ${number}', @@ -1873,7 +1873,6 @@ extension on TranslationsDe { 'playlists.itemAdded' => 'Zur Wiedergabeliste hinzugefügt', 'playlists.itemRemoved' => 'Aus Wiedergabeliste entfernt', 'playlists.selectPlaylist' => 'Wiedergabeliste auswählen', - 'playlists.createNewPlaylist' => 'Neue Wiedergabeliste erstellen', 'playlists.errorCreating' => 'Wiedergabeliste konnte nicht erstellt werden', 'playlists.errorDeleting' => 'Wiedergabeliste konnte nicht gelöscht werden', 'playlists.errorLoading' => 'Wiedergabelisten konnten nicht geladen werden', @@ -1892,7 +1891,6 @@ extension on TranslationsDe { 'collections.deleteFailedWithError' => ({required Object error}) => 'Sammlung konnte nicht gelöscht werden: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Sammlungselemente konnten nicht geladen werden: ${error}', 'collections.selectCollection' => 'Sammlung auswählen', - 'collections.createNewCollection' => 'Neue Sammlung erstellen', 'collections.collectionName' => 'Sammlungsname', 'collections.enterCollectionName' => 'Sammlungsnamen eingeben', 'collections.addedToCollection' => 'Zur Sammlung hinzugefügt', diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart index bd09b010..220febec 100644 --- a/lib/i18n/strings_en.g.dart +++ b/lib/i18n/strings_en.g.dart @@ -190,6 +190,9 @@ class TranslationsCommonEn { /// en: 'Add to...' String get addTo => 'Add to...'; + /// en: 'Create new' + String get createNew => 'Create new'; + /// en: 'Remove' String get remove => 'Remove'; @@ -1871,9 +1874,6 @@ class TranslationsCollectionsEn { /// en: 'Select Collection' String get selectCollection => 'Select Collection'; - /// en: 'Create New Collection' - String get createNewCollection => 'Create New Collection'; - /// en: 'Collection Name' String get collectionName => 'Collection Name'; @@ -1970,9 +1970,6 @@ class TranslationsPlaylistsEn { /// en: 'Select Playlist' String get selectPlaylist => 'Select Playlist'; - /// en: 'Create New Playlist' - String get createNewPlaylist => 'Create New Playlist'; - /// en: 'Failed to create playlist' String get errorCreating => 'Failed to create playlist'; @@ -2956,6 +2953,7 @@ extension on Translations { 'common.delete' => 'Delete', 'common.shuffle' => 'Shuffle', 'common.addTo' => 'Add to...', + 'common.createNew' => 'Create new', 'common.remove' => 'Remove', 'common.paste' => 'Paste', 'common.connect' => 'Connect', @@ -3439,9 +3437,9 @@ extension on Translations { 'liveTv.noChannels' => 'No channels available', 'liveTv.noDvr' => 'No DVR configured on any server', 'liveTv.tuneFailed' => 'Failed to tune channel', - 'liveTv.loading' => 'Loading channels...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Loading channels...', 'liveTv.nowPlaying' => 'Now Playing', 'liveTv.noPrograms' => 'No program data available', 'liveTv.channelNumber' => ({required Object number}) => 'Ch. ${number}', @@ -3471,7 +3469,6 @@ extension on Translations { 'collections.deleteFailedWithError' => ({required Object error}) => 'Failed to delete collection: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Failed to load collection items: ${error}', 'collections.selectCollection' => 'Select Collection', - 'collections.createNewCollection' => 'Create New Collection', 'collections.collectionName' => 'Collection Name', 'collections.enterCollectionName' => 'Enter collection name', 'collections.addedToCollection' => 'Added to collection', @@ -3501,7 +3498,6 @@ extension on Translations { 'playlists.itemAdded' => 'Added to playlist', 'playlists.itemRemoved' => 'Removed from playlist', 'playlists.selectPlaylist' => 'Select Playlist', - 'playlists.createNewPlaylist' => 'Create New Playlist', 'playlists.errorCreating' => 'Failed to create playlist', 'playlists.errorDeleting' => 'Failed to delete playlist', 'playlists.errorLoading' => 'Failed to load playlists', diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart index 206f1c4a..feebdd6c 100644 --- a/lib/i18n/strings_es.g.dart +++ b/lib/i18n/strings_es.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonEs implements TranslationsCommonEn { @override String get delete => 'Eliminar'; @override String get shuffle => 'Aleatorio'; @override String get addTo => 'Añadir a...'; + @override String get createNew => 'Crear'; @override String get remove => 'Eliminar'; @override String get paste => 'Pegar'; @override String get connect => 'Conectar'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsEs implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Línea de tiempo del video'; @override String get volumeSlider => 'Nivel de volumen'; @override String endsAt({required Object time}) => 'Termina a las ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Reproduciendo en Imagen en Imagen'; @override String get pipFailed => 'Error al iniciar Imagen en Imagen'; @override late final _TranslationsVideoControlsPipErrorsEs pipErrors = _TranslationsVideoControlsPipErrorsEs._(_root); @override String get chapters => 'Capítulos'; @@ -854,7 +855,6 @@ class _TranslationsCollectionsEs implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Error al eliminar la colección: ${error}'; @override String failedToLoadItems({required Object error}) => 'Error al cargar los elementos de la colección: ${error}'; @override String get selectCollection => 'Seleccionar Colección'; - @override String get createNewCollection => 'Crear Nueva Colección'; @override String get collectionName => 'Nombre de la Colección'; @override String get enterCollectionName => 'Introduce el nombre de la colección'; @override String get addedToCollection => 'Añadido a la colección'; @@ -893,7 +893,6 @@ class _TranslationsPlaylistsEs implements TranslationsPlaylistsEn { @override String get itemAdded => 'Añadido a la lista'; @override String get itemRemoved => 'Eliminado de la lista'; @override String get selectPlaylist => 'Seleccionar Lista'; - @override String get createNewPlaylist => 'Crear Nueva Lista'; @override String get errorCreating => 'Error al crear la lista'; @override String get errorDeleting => 'Error al eliminar la lista'; @override String get errorLoading => 'Error al cargar las listas'; @@ -1333,6 +1332,7 @@ extension on TranslationsEs { 'common.delete' => 'Eliminar', 'common.shuffle' => 'Aleatorio', 'common.addTo' => 'Añadir a...', + 'common.createNew' => 'Crear', 'common.remove' => 'Eliminar', 'common.paste' => 'Pegar', 'common.connect' => 'Conectar', @@ -1628,7 +1628,7 @@ extension on TranslationsEs { 'videoControls.timelineSlider' => 'Línea de tiempo del video', 'videoControls.volumeSlider' => 'Nivel de volumen', 'videoControls.endsAt' => ({required Object time}) => 'Termina a las ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Reproduciendo en Imagen en Imagen', 'videoControls.pipFailed' => 'Error al iniciar Imagen en Imagen', 'videoControls.pipErrors.androidVersion' => 'Requiere Android 8.0 o más reciente', 'videoControls.pipErrors.iosVersion' => 'Requiere iOS 15.0 o más reciente', @@ -1816,9 +1816,9 @@ extension on TranslationsEs { 'liveTv.noChannels' => 'No hay canales disponibles', 'liveTv.noDvr' => 'No hay DVR configurado en ningún servidor', 'liveTv.tuneFailed' => 'Error al sintonizar el canal', - 'liveTv.loading' => 'Cargando canales...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Cargando canales...', 'liveTv.nowPlaying' => 'Reproduciendo ahora', 'liveTv.noPrograms' => 'No hay datos de programación disponibles', 'liveTv.channelNumber' => ({required Object number}) => 'Canal ${number}', @@ -1848,7 +1848,6 @@ extension on TranslationsEs { 'collections.deleteFailedWithError' => ({required Object error}) => 'Error al eliminar la colección: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Error al cargar los elementos de la colección: ${error}', 'collections.selectCollection' => 'Seleccionar Colección', - 'collections.createNewCollection' => 'Crear Nueva Colección', 'collections.collectionName' => 'Nombre de la Colección', 'collections.enterCollectionName' => 'Introduce el nombre de la colección', 'collections.addedToCollection' => 'Añadido a la colección', @@ -1878,7 +1877,6 @@ extension on TranslationsEs { 'playlists.itemAdded' => 'Añadido a la lista', 'playlists.itemRemoved' => 'Eliminado de la lista', 'playlists.selectPlaylist' => 'Seleccionar Lista', - 'playlists.createNewPlaylist' => 'Crear Nueva Lista', 'playlists.errorCreating' => 'Error al crear la lista', 'playlists.errorDeleting' => 'Error al eliminar la lista', 'playlists.errorLoading' => 'Error al cargar las listas', diff --git a/lib/i18n/strings_fr.g.dart b/lib/i18n/strings_fr.g.dart index b20959bc..183c052d 100644 --- a/lib/i18n/strings_fr.g.dart +++ b/lib/i18n/strings_fr.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonFr implements TranslationsCommonEn { @override String get delete => 'Supprimer'; @override String get shuffle => 'Mélanger'; @override String get addTo => 'Ajouter à...'; + @override String get createNew => 'Créer'; @override String get remove => 'Supprimer'; @override String get paste => 'Coller'; @override String get connect => 'Connecter'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsFr implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Timeline vidéo'; @override String get volumeSlider => 'Niveau sonore'; @override String endsAt({required Object time}) => 'Fin à ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Lecture en mode image dans l\'image'; @override String get pipFailed => 'Échec du démarrage du mode image dans l\'image'; @override late final _TranslationsVideoControlsPipErrorsFr pipErrors = _TranslationsVideoControlsPipErrorsFr._(_root); @override String get chapters => 'Chapitres'; @@ -854,7 +855,6 @@ class _TranslationsCollectionsFr implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Échec de la suppression de la collection: ${error}'; @override String failedToLoadItems({required Object error}) => 'Échec du chargement des éléments de la collection: ${error}'; @override String get selectCollection => 'Sélectionner une collection'; - @override String get createNewCollection => 'Créer une nouvelle collection'; @override String get collectionName => 'Nom de la collection'; @override String get enterCollectionName => 'Entrez le nom de la collection'; @override String get addedToCollection => 'Ajouté à la collection'; @@ -893,7 +893,6 @@ class _TranslationsPlaylistsFr implements TranslationsPlaylistsEn { @override String get itemAdded => 'Ajouté à la playlist'; @override String get itemRemoved => 'Retiré de la playlist'; @override String get selectPlaylist => 'Select Playlist'; - @override String get createNewPlaylist => 'Créer une nouvelle playlist'; @override String get errorCreating => 'Échec de la création de playlist'; @override String get errorDeleting => 'Échec de suppression de playlist'; @override String get errorLoading => 'Échec de chargement de playlists'; @@ -1333,6 +1332,7 @@ extension on TranslationsFr { 'common.delete' => 'Supprimer', 'common.shuffle' => 'Mélanger', 'common.addTo' => 'Ajouter à...', + 'common.createNew' => 'Créer', 'common.remove' => 'Supprimer', 'common.paste' => 'Coller', 'common.connect' => 'Connecter', @@ -1628,7 +1628,7 @@ extension on TranslationsFr { 'videoControls.timelineSlider' => 'Timeline vidéo', 'videoControls.volumeSlider' => 'Niveau sonore', 'videoControls.endsAt' => ({required Object time}) => 'Fin à ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Lecture en mode image dans l\'image', 'videoControls.pipFailed' => 'Échec du démarrage du mode image dans l\'image', 'videoControls.pipErrors.androidVersion' => 'Nécessite Android 8.0 ou plus récent', 'videoControls.pipErrors.iosVersion' => 'Nécessite iOS 15.0 ou plus récent', @@ -1816,9 +1816,9 @@ extension on TranslationsFr { 'liveTv.noChannels' => 'Aucune chaîne disponible', 'liveTv.noDvr' => 'Aucun DVR configuré sur les serveurs', 'liveTv.tuneFailed' => 'Impossible de syntoniser la chaîne', - 'liveTv.loading' => 'Chargement des chaînes...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Chargement des chaînes...', 'liveTv.nowPlaying' => 'En cours de lecture', 'liveTv.noPrograms' => 'Aucune donnée de programme disponible', 'liveTv.channelNumber' => ({required Object number}) => 'Ch. ${number}', @@ -1848,7 +1848,6 @@ extension on TranslationsFr { 'collections.deleteFailedWithError' => ({required Object error}) => 'Échec de la suppression de la collection: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Échec du chargement des éléments de la collection: ${error}', 'collections.selectCollection' => 'Sélectionner une collection', - 'collections.createNewCollection' => 'Créer une nouvelle collection', 'collections.collectionName' => 'Nom de la collection', 'collections.enterCollectionName' => 'Entrez le nom de la collection', 'collections.addedToCollection' => 'Ajouté à la collection', @@ -1878,7 +1877,6 @@ extension on TranslationsFr { 'playlists.itemAdded' => 'Ajouté à la playlist', 'playlists.itemRemoved' => 'Retiré de la playlist', 'playlists.selectPlaylist' => 'Select Playlist', - 'playlists.createNewPlaylist' => 'Créer une nouvelle playlist', 'playlists.errorCreating' => 'Échec de la création de playlist', 'playlists.errorDeleting' => 'Échec de suppression de playlist', 'playlists.errorLoading' => 'Échec de chargement de playlists', diff --git a/lib/i18n/strings_it.g.dart b/lib/i18n/strings_it.g.dart index f0aaa4d4..2b4d4e39 100644 --- a/lib/i18n/strings_it.g.dart +++ b/lib/i18n/strings_it.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonIt implements TranslationsCommonEn { @override String get delete => 'Elimina'; @override String get shuffle => 'Casuale'; @override String get addTo => 'Aggiungi a...'; + @override String get createNew => 'Crea'; @override String get remove => 'Rimuovi'; @override String get paste => 'Incolla'; @override String get connect => 'Connetti'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsIt implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Timeline video'; @override String get volumeSlider => 'Livello volume'; @override String endsAt({required Object time}) => 'Finisce alle ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Riproduzione in Picture-in-Picture'; @override String get pipFailed => 'Impossibile avviare la modalità Picture-in-Picture'; @override late final _TranslationsVideoControlsPipErrorsIt pipErrors = _TranslationsVideoControlsPipErrorsIt._(_root); @override String get chapters => 'Capitoli'; @@ -888,7 +889,6 @@ class _TranslationsPlaylistsIt implements TranslationsPlaylistsEn { @override String get itemAdded => 'Aggiunto alla playlist'; @override String get itemRemoved => 'Rimosso dalla playlist'; @override String get selectPlaylist => 'Seleziona playlist'; - @override String get createNewPlaylist => 'Crea nuova playlist'; @override String get errorCreating => 'Errore durante la creazione della playlist'; @override String get errorDeleting => 'Errore durante l\'eliminazione della playlist'; @override String get errorLoading => 'Errore durante il caricamento delle playlist'; @@ -916,7 +916,6 @@ class _TranslationsCollectionsIt implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Impossibile eliminare la raccolta: ${error}'; @override String failedToLoadItems({required Object error}) => 'Impossibile caricare gli elementi della raccolta: ${error}'; @override String get selectCollection => 'Seleziona raccolta'; - @override String get createNewCollection => 'Crea nuova raccolta'; @override String get collectionName => 'Nome raccolta'; @override String get enterCollectionName => 'Inserisci nome raccolta'; @override String get addedToCollection => 'Aggiunto alla raccolta'; @@ -1333,6 +1332,7 @@ extension on TranslationsIt { 'common.delete' => 'Elimina', 'common.shuffle' => 'Casuale', 'common.addTo' => 'Aggiungi a...', + 'common.createNew' => 'Crea', 'common.remove' => 'Rimuovi', 'common.paste' => 'Incolla', 'common.connect' => 'Connetti', @@ -1628,7 +1628,7 @@ extension on TranslationsIt { 'videoControls.timelineSlider' => 'Timeline video', 'videoControls.volumeSlider' => 'Livello volume', 'videoControls.endsAt' => ({required Object time}) => 'Finisce alle ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Riproduzione in Picture-in-Picture', 'videoControls.pipFailed' => 'Impossibile avviare la modalità Picture-in-Picture', 'videoControls.pipErrors.androidVersion' => 'Richiede Android 8.0 o versioni successive', 'videoControls.pipErrors.iosVersion' => 'Richiede iOS 15.0 o versioni successive', @@ -1816,9 +1816,9 @@ extension on TranslationsIt { 'liveTv.noChannels' => 'Nessun canale disponibile', 'liveTv.noDvr' => 'Nessun DVR configurato su nessun server', 'liveTv.tuneFailed' => 'Impossibile sintonizzare il canale', - 'liveTv.loading' => 'Caricamento canali...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Caricamento canali...', 'liveTv.nowPlaying' => 'In riproduzione', 'liveTv.noPrograms' => 'Nessun dato di programma disponibile', 'liveTv.channelNumber' => ({required Object number}) => 'Canale ${number}', @@ -1873,7 +1873,6 @@ extension on TranslationsIt { 'playlists.itemAdded' => 'Aggiunto alla playlist', 'playlists.itemRemoved' => 'Rimosso dalla playlist', 'playlists.selectPlaylist' => 'Seleziona playlist', - 'playlists.createNewPlaylist' => 'Crea nuova playlist', 'playlists.errorCreating' => 'Errore durante la creazione della playlist', 'playlists.errorDeleting' => 'Errore durante l\'eliminazione della playlist', 'playlists.errorLoading' => 'Errore durante il caricamento delle playlist', @@ -1892,7 +1891,6 @@ extension on TranslationsIt { 'collections.deleteFailedWithError' => ({required Object error}) => 'Impossibile eliminare la raccolta: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Impossibile caricare gli elementi della raccolta: ${error}', 'collections.selectCollection' => 'Seleziona raccolta', - 'collections.createNewCollection' => 'Crea nuova raccolta', 'collections.collectionName' => 'Nome raccolta', 'collections.enterCollectionName' => 'Inserisci nome raccolta', 'collections.addedToCollection' => 'Aggiunto alla raccolta', diff --git a/lib/i18n/strings_ko.g.dart b/lib/i18n/strings_ko.g.dart index 713ce0f2..d66826ce 100644 --- a/lib/i18n/strings_ko.g.dart +++ b/lib/i18n/strings_ko.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonKo implements TranslationsCommonEn { @override String get delete => '삭제'; @override String get shuffle => '무작위 재생'; @override String get addTo => '추가하기...'; + @override String get createNew => '새로 만들기'; @override String get remove => '삭제'; @override String get paste => '붙여넣기'; @override String get connect => '연결'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsKo implements TranslationsVideoControlsEn { @override String get timelineSlider => '타임라인'; @override String get volumeSlider => '볼륨 조절'; @override String endsAt({required Object time}) => '${time}에 종료'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => '화면 속 화면으로 재생 중'; @override String get pipFailed => '화면 속 화면 모드를 시작할 수 없습니다'; @override late final _TranslationsVideoControlsPipErrorsKo pipErrors = _TranslationsVideoControlsPipErrorsKo._(_root); @override String get chapters => '챕터'; @@ -854,7 +855,6 @@ class _TranslationsCollectionsKo implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => '컬렉션 삭제 실패: ${error}'; @override String failedToLoadItems({required Object error}) => '컬렉션 항목 로드 실패: ${error}'; @override String get selectCollection => '컬렉션 선택'; - @override String get createNewCollection => '새 컬렉션 생성'; @override String get collectionName => '컬렉션 이름'; @override String get enterCollectionName => '컬렉션 이름 입력'; @override String get addedToCollection => '컬렉션에 추가됨'; @@ -893,7 +893,6 @@ class _TranslationsPlaylistsKo implements TranslationsPlaylistsEn { @override String get itemAdded => '재생 목록에 추가 되었습니다'; @override String get itemRemoved => '재생 목록에서 제거됨'; @override String get selectPlaylist => '재생 목록 선택'; - @override String get createNewPlaylist => '새 재생 목록 생성'; @override String get errorCreating => '재생 목록 생성 실패'; @override String get errorDeleting => '재생 목록 삭제 실패'; @override String get errorLoading => '재생 목록 로드 실패'; @@ -1333,6 +1332,7 @@ extension on TranslationsKo { 'common.delete' => '삭제', 'common.shuffle' => '무작위 재생', 'common.addTo' => '추가하기...', + 'common.createNew' => '새로 만들기', 'common.remove' => '삭제', 'common.paste' => '붙여넣기', 'common.connect' => '연결', @@ -1628,7 +1628,7 @@ extension on TranslationsKo { 'videoControls.timelineSlider' => '타임라인', 'videoControls.volumeSlider' => '볼륨 조절', 'videoControls.endsAt' => ({required Object time}) => '${time}에 종료', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => '화면 속 화면으로 재생 중', 'videoControls.pipFailed' => '화면 속 화면 모드를 시작할 수 없습니다', 'videoControls.pipErrors.androidVersion' => 'Android 8.0 이상이 필요합니다', 'videoControls.pipErrors.iosVersion' => 'iOS 15.0 이상이 필요합니다', @@ -1816,9 +1816,9 @@ extension on TranslationsKo { 'liveTv.noChannels' => '사용 가능한 채널이 없습니다', 'liveTv.noDvr' => '서버에 DVR이 구성되어 있지 않습니다', 'liveTv.tuneFailed' => '채널 튜닝에 실패했습니다', - 'liveTv.loading' => '채널 로딩 중...', _ => null, } ?? switch (path) { + 'liveTv.loading' => '채널 로딩 중...', 'liveTv.nowPlaying' => '현재 재생 중', 'liveTv.noPrograms' => '프로그램 데이터가 없습니다', 'liveTv.channelNumber' => ({required Object number}) => '채널 ${number}', @@ -1848,7 +1848,6 @@ extension on TranslationsKo { 'collections.deleteFailedWithError' => ({required Object error}) => '컬렉션 삭제 실패: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => '컬렉션 항목 로드 실패: ${error}', 'collections.selectCollection' => '컬렉션 선택', - 'collections.createNewCollection' => '새 컬렉션 생성', 'collections.collectionName' => '컬렉션 이름', 'collections.enterCollectionName' => '컬렉션 이름 입력', 'collections.addedToCollection' => '컬렉션에 추가됨', @@ -1878,7 +1877,6 @@ extension on TranslationsKo { 'playlists.itemAdded' => '재생 목록에 추가 되었습니다', 'playlists.itemRemoved' => '재생 목록에서 제거됨', 'playlists.selectPlaylist' => '재생 목록 선택', - 'playlists.createNewPlaylist' => '새 재생 목록 생성', 'playlists.errorCreating' => '재생 목록 생성 실패', 'playlists.errorDeleting' => '재생 목록 삭제 실패', 'playlists.errorLoading' => '재생 목록 로드 실패', diff --git a/lib/i18n/strings_nl.g.dart b/lib/i18n/strings_nl.g.dart index 9f2c2ed6..767c8d5b 100644 --- a/lib/i18n/strings_nl.g.dart +++ b/lib/i18n/strings_nl.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonNl implements TranslationsCommonEn { @override String get delete => 'Verwijderen'; @override String get shuffle => 'Willekeurig'; @override String get addTo => 'Toevoegen aan...'; + @override String get createNew => 'Nieuw aanmaken'; @override String get remove => 'Verwijderen'; @override String get paste => 'Plakken'; @override String get connect => 'Verbinden'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsNl implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Videotijdlijn'; @override String get volumeSlider => 'Volumeniveau'; @override String endsAt({required Object time}) => 'Eindigt om ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Afspelen in beeld-in-beeld'; @override String get pipFailed => 'Beeld-in-beeld kon niet worden gestart'; @override late final _TranslationsVideoControlsPipErrorsNl pipErrors = _TranslationsVideoControlsPipErrorsNl._(_root); @override String get chapters => 'Hoofdstukken'; @@ -888,7 +889,6 @@ class _TranslationsPlaylistsNl implements TranslationsPlaylistsEn { @override String get itemAdded => 'Toegevoegd aan afspeellijst'; @override String get itemRemoved => 'Verwijderd uit afspeellijst'; @override String get selectPlaylist => 'Selecteer afspeellijst'; - @override String get createNewPlaylist => 'Nieuwe afspeellijst maken'; @override String get errorCreating => 'Fout bij maken afspeellijst'; @override String get errorDeleting => 'Fout bij verwijderen afspeellijst'; @override String get errorLoading => 'Fout bij laden afspeellijsten'; @@ -916,7 +916,6 @@ class _TranslationsCollectionsNl implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Collectie verwijderen mislukt: ${error}'; @override String failedToLoadItems({required Object error}) => 'Collectie-items laden mislukt: ${error}'; @override String get selectCollection => 'Selecteer collectie'; - @override String get createNewCollection => 'Nieuwe collectie maken'; @override String get collectionName => 'Collectienaam'; @override String get enterCollectionName => 'Voer collectienaam in'; @override String get addedToCollection => 'Toegevoegd aan collectie'; @@ -1333,6 +1332,7 @@ extension on TranslationsNl { 'common.delete' => 'Verwijderen', 'common.shuffle' => 'Willekeurig', 'common.addTo' => 'Toevoegen aan...', + 'common.createNew' => 'Nieuw aanmaken', 'common.remove' => 'Verwijderen', 'common.paste' => 'Plakken', 'common.connect' => 'Verbinden', @@ -1628,7 +1628,7 @@ extension on TranslationsNl { 'videoControls.timelineSlider' => 'Videotijdlijn', 'videoControls.volumeSlider' => 'Volumeniveau', 'videoControls.endsAt' => ({required Object time}) => 'Eindigt om ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Afspelen in beeld-in-beeld', 'videoControls.pipFailed' => 'Beeld-in-beeld kon niet worden gestart', 'videoControls.pipErrors.androidVersion' => 'Vereist Android 8.0 of nieuwer', 'videoControls.pipErrors.iosVersion' => 'Vereist iOS 15.0 of nieuwer', @@ -1816,9 +1816,9 @@ extension on TranslationsNl { 'liveTv.noChannels' => 'Geen zenders beschikbaar', 'liveTv.noDvr' => 'Geen DVR geconfigureerd op een server', 'liveTv.tuneFailed' => 'Kan zender niet afstemmen', - 'liveTv.loading' => 'Zenders laden...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Zenders laden...', 'liveTv.nowPlaying' => 'Nu aan het afspelen', 'liveTv.noPrograms' => 'Geen programmagegevens beschikbaar', 'liveTv.channelNumber' => ({required Object number}) => 'Kanaal ${number}', @@ -1873,7 +1873,6 @@ extension on TranslationsNl { 'playlists.itemAdded' => 'Toegevoegd aan afspeellijst', 'playlists.itemRemoved' => 'Verwijderd uit afspeellijst', 'playlists.selectPlaylist' => 'Selecteer afspeellijst', - 'playlists.createNewPlaylist' => 'Nieuwe afspeellijst maken', 'playlists.errorCreating' => 'Fout bij maken afspeellijst', 'playlists.errorDeleting' => 'Fout bij verwijderen afspeellijst', 'playlists.errorLoading' => 'Fout bij laden afspeellijsten', @@ -1892,7 +1891,6 @@ extension on TranslationsNl { 'collections.deleteFailedWithError' => ({required Object error}) => 'Collectie verwijderen mislukt: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Collectie-items laden mislukt: ${error}', 'collections.selectCollection' => 'Selecteer collectie', - 'collections.createNewCollection' => 'Nieuwe collectie maken', 'collections.collectionName' => 'Collectienaam', 'collections.enterCollectionName' => 'Voer collectienaam in', 'collections.addedToCollection' => 'Toegevoegd aan collectie', diff --git a/lib/i18n/strings_sv.g.dart b/lib/i18n/strings_sv.g.dart index 996a6c6f..8f7b967c 100644 --- a/lib/i18n/strings_sv.g.dart +++ b/lib/i18n/strings_sv.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonSv implements TranslationsCommonEn { @override String get delete => 'Ta bort'; @override String get shuffle => 'Blanda'; @override String get addTo => 'Lägg till i...'; + @override String get createNew => 'Skapa ny'; @override String get remove => 'Ta bort'; @override String get paste => 'Klistra in'; @override String get connect => 'Anslut'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsSv implements TranslationsVideoControlsEn { @override String get timelineSlider => 'Videotidslinje'; @override String get volumeSlider => 'Volymnivå'; @override String endsAt({required Object time}) => 'Slutar ${time}'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => 'Spelar i bild-i-bild'; @override String get pipFailed => 'Bild-i-bild kunde inte starta'; @override late final _TranslationsVideoControlsPipErrorsSv pipErrors = _TranslationsVideoControlsPipErrorsSv._(_root); @override String get chapters => 'Kapitel'; @@ -888,7 +889,6 @@ class _TranslationsPlaylistsSv implements TranslationsPlaylistsEn { @override String get itemAdded => 'Tillagd i spellista'; @override String get itemRemoved => 'Borttagen från spellista'; @override String get selectPlaylist => 'Välj spellista'; - @override String get createNewPlaylist => 'Skapa ny spellista'; @override String get errorCreating => 'Det gick inte att skapa spellista'; @override String get errorDeleting => 'Det gick inte att ta bort spellista'; @override String get errorLoading => 'Det gick inte att ladda spellistor'; @@ -916,7 +916,6 @@ class _TranslationsCollectionsSv implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => 'Det gick inte att ta bort samlingen: ${error}'; @override String failedToLoadItems({required Object error}) => 'Det gick inte att läsa in samlingsobjekt: ${error}'; @override String get selectCollection => 'Välj samling'; - @override String get createNewCollection => 'Skapa ny samling'; @override String get collectionName => 'Samlingsnamn'; @override String get enterCollectionName => 'Ange samlingsnamn'; @override String get addedToCollection => 'Tillagd i samling'; @@ -1333,6 +1332,7 @@ extension on TranslationsSv { 'common.delete' => 'Ta bort', 'common.shuffle' => 'Blanda', 'common.addTo' => 'Lägg till i...', + 'common.createNew' => 'Skapa ny', 'common.remove' => 'Ta bort', 'common.paste' => 'Klistra in', 'common.connect' => 'Anslut', @@ -1628,7 +1628,7 @@ extension on TranslationsSv { 'videoControls.timelineSlider' => 'Videotidslinje', 'videoControls.volumeSlider' => 'Volymnivå', 'videoControls.endsAt' => ({required Object time}) => 'Slutar ${time}', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => 'Spelar i bild-i-bild', 'videoControls.pipFailed' => 'Bild-i-bild kunde inte starta', 'videoControls.pipErrors.androidVersion' => 'Kräver Android 8.0 eller nyare', 'videoControls.pipErrors.iosVersion' => 'Kräver iOS 15.0 eller nyare', @@ -1816,9 +1816,9 @@ extension on TranslationsSv { 'liveTv.noChannels' => 'Inga kanaler tillgängliga', 'liveTv.noDvr' => 'Ingen DVR konfigurerad på någon server', 'liveTv.tuneFailed' => 'Kunde inte ställa in kanalen', - 'liveTv.loading' => 'Laddar kanaler...', _ => null, } ?? switch (path) { + 'liveTv.loading' => 'Laddar kanaler...', 'liveTv.nowPlaying' => 'Spelas nu', 'liveTv.noPrograms' => 'Ingen programdata tillgänglig', 'liveTv.channelNumber' => ({required Object number}) => 'Kanal ${number}', @@ -1873,7 +1873,6 @@ extension on TranslationsSv { 'playlists.itemAdded' => 'Tillagd i spellista', 'playlists.itemRemoved' => 'Borttagen från spellista', 'playlists.selectPlaylist' => 'Välj spellista', - 'playlists.createNewPlaylist' => 'Skapa ny spellista', 'playlists.errorCreating' => 'Det gick inte att skapa spellista', 'playlists.errorDeleting' => 'Det gick inte att ta bort spellista', 'playlists.errorLoading' => 'Det gick inte att ladda spellistor', @@ -1892,7 +1891,6 @@ extension on TranslationsSv { 'collections.deleteFailedWithError' => ({required Object error}) => 'Det gick inte att ta bort samlingen: ${error}', 'collections.failedToLoadItems' => ({required Object error}) => 'Det gick inte att läsa in samlingsobjekt: ${error}', 'collections.selectCollection' => 'Välj samling', - 'collections.createNewCollection' => 'Skapa ny samling', 'collections.collectionName' => 'Samlingsnamn', 'collections.enterCollectionName' => 'Ange samlingsnamn', 'collections.addedToCollection' => 'Tillagd i samling', diff --git a/lib/i18n/strings_zh.g.dart b/lib/i18n/strings_zh.g.dart index 1e4d57c5..139934c7 100644 --- a/lib/i18n/strings_zh.g.dart +++ b/lib/i18n/strings_zh.g.dart @@ -130,6 +130,7 @@ class _TranslationsCommonZh implements TranslationsCommonEn { @override String get delete => '删除'; @override String get shuffle => '随机播放'; @override String get addTo => '添加到...'; + @override String get createNew => '新建'; @override String get remove => '删除'; @override String get paste => '粘贴'; @override String get connect => '连接'; @@ -506,7 +507,7 @@ class _TranslationsVideoControlsZh implements TranslationsVideoControlsEn { @override String get timelineSlider => '视频时间轴'; @override String get volumeSlider => '音量调节'; @override String endsAt({required Object time}) => '${time} 结束'; - @override String get pipActive => 'Playing in Picture-in-Picture'; + @override String get pipActive => '正在画中画模式中播放'; @override String get pipFailed => '画中画启动失败'; @override late final _TranslationsVideoControlsPipErrorsZh pipErrors = _TranslationsVideoControlsPipErrorsZh._(_root); @override String get chapters => '章节'; @@ -888,7 +889,6 @@ class _TranslationsPlaylistsZh implements TranslationsPlaylistsEn { @override String get itemAdded => '已添加到播放列表'; @override String get itemRemoved => '已从播放列表中移除'; @override String get selectPlaylist => '选择播放列表'; - @override String get createNewPlaylist => '创建新播放列表'; @override String get errorCreating => '创建播放列表失败'; @override String get errorDeleting => '删除播放列表失败'; @override String get errorLoading => '加载播放列表失败'; @@ -916,7 +916,6 @@ class _TranslationsCollectionsZh implements TranslationsCollectionsEn { @override String deleteFailedWithError({required Object error}) => '删除合集失败:${error}'; @override String failedToLoadItems({required Object error}) => '加载合集项目失败:${error}'; @override String get selectCollection => '选择合集'; - @override String get createNewCollection => '创建新合集'; @override String get collectionName => '合集名称'; @override String get enterCollectionName => '输入合集名称'; @override String get addedToCollection => '已添加到合集'; @@ -1333,6 +1332,7 @@ extension on TranslationsZh { 'common.delete' => '删除', 'common.shuffle' => '随机播放', 'common.addTo' => '添加到...', + 'common.createNew' => '新建', 'common.remove' => '删除', 'common.paste' => '粘贴', 'common.connect' => '连接', @@ -1628,7 +1628,7 @@ extension on TranslationsZh { 'videoControls.timelineSlider' => '视频时间轴', 'videoControls.volumeSlider' => '音量调节', 'videoControls.endsAt' => ({required Object time}) => '${time} 结束', - 'videoControls.pipActive' => 'Playing in Picture-in-Picture', + 'videoControls.pipActive' => '正在画中画模式中播放', 'videoControls.pipFailed' => '画中画启动失败', 'videoControls.pipErrors.androidVersion' => '需要 Android 8.0 或更高版本', 'videoControls.pipErrors.iosVersion' => '需要 iOS 15.0 或更高版本', @@ -1816,9 +1816,9 @@ extension on TranslationsZh { 'liveTv.noChannels' => '没有可用的频道', 'liveTv.noDvr' => '没有服务器配置了DVR', 'liveTv.tuneFailed' => '无法调谐频道', - 'liveTv.loading' => '正在加载频道...', _ => null, } ?? switch (path) { + 'liveTv.loading' => '正在加载频道...', 'liveTv.nowPlaying' => '正在播放', 'liveTv.noPrograms' => '没有可用的节目数据', 'liveTv.channelNumber' => ({required Object number}) => '频道 ${number}', @@ -1873,7 +1873,6 @@ extension on TranslationsZh { 'playlists.itemAdded' => '已添加到播放列表', 'playlists.itemRemoved' => '已从播放列表中移除', 'playlists.selectPlaylist' => '选择播放列表', - 'playlists.createNewPlaylist' => '创建新播放列表', 'playlists.errorCreating' => '创建播放列表失败', 'playlists.errorDeleting' => '删除播放列表失败', 'playlists.errorLoading' => '加载播放列表失败', @@ -1892,7 +1891,6 @@ extension on TranslationsZh { 'collections.deleteFailedWithError' => ({required Object error}) => '删除合集失败:${error}', 'collections.failedToLoadItems' => ({required Object error}) => '加载合集项目失败:${error}', 'collections.selectCollection' => '选择合集', - 'collections.createNewCollection' => '创建新合集', 'collections.collectionName' => '合集名称', 'collections.enterCollectionName' => '输入合集名称', 'collections.addedToCollection' => '已添加到合集', diff --git a/lib/i18n/sv.i18n.json b/lib/i18n/sv.i18n.json index 99a4031d..5c17c128 100644 --- a/lib/i18n/sv.i18n.json +++ b/lib/i18n/sv.i18n.json @@ -32,6 +32,7 @@ "delete": "Ta bort", "shuffle": "Blanda", "addTo": "Lägg till i...", + "createNew": "Skapa ny", "remove": "Ta bort", "paste": "Klistra in", "connect": "Anslut", @@ -634,7 +635,6 @@ "itemAdded": "Tillagd i spellista", "itemRemoved": "Borttagen från spellista", "selectPlaylist": "Välj spellista", - "createNewPlaylist": "Skapa ny spellista", "errorCreating": "Det gick inte att skapa spellista", "errorDeleting": "Det gick inte att ta bort spellista", "errorLoading": "Det gick inte att ladda spellistor", @@ -655,7 +655,6 @@ "deleteFailedWithError": "Det gick inte att ta bort samlingen: ${error}", "failedToLoadItems": "Det gick inte att läsa in samlingsobjekt: ${error}", "selectCollection": "Välj samling", - "createNewCollection": "Skapa ny samling", "collectionName": "Samlingsnamn", "enterCollectionName": "Ange samlingsnamn", "addedToCollection": "Tillagd i samling", diff --git a/lib/i18n/zh.i18n.json b/lib/i18n/zh.i18n.json index 6193d691..8289c01a 100644 --- a/lib/i18n/zh.i18n.json +++ b/lib/i18n/zh.i18n.json @@ -32,6 +32,7 @@ "delete": "删除", "shuffle": "随机播放", "addTo": "添加到...", + "createNew": "新建", "remove": "删除", "paste": "粘贴", "connect": "连接", @@ -634,7 +635,6 @@ "itemAdded": "已添加到播放列表", "itemRemoved": "已从播放列表中移除", "selectPlaylist": "选择播放列表", - "createNewPlaylist": "创建新播放列表", "errorCreating": "创建播放列表失败", "errorDeleting": "删除播放列表失败", "errorLoading": "加载播放列表失败", @@ -655,7 +655,6 @@ "deleteFailedWithError": "删除合集失败:${error}", "failedToLoadItems": "加载合集项目失败:${error}", "selectCollection": "选择合集", - "createNewCollection": "创建新合集", "collectionName": "合集名称", "enterCollectionName": "输入合集名称", "addedToCollection": "已添加到合集", diff --git a/lib/widgets/media_context_menu.dart b/lib/widgets/media_context_menu.dart index 1f997cf1..0dd9a75a 100644 --- a/lib/widgets/media_context_menu.dart +++ b/lib/widgets/media_context_menu.dart @@ -314,6 +314,7 @@ class MediaContextMenuState extends State { if (useBottomSheet) { selected = await OverlaySheetController.showAdaptive( context, + showDragHandle: true, builder: (context) => _FocusableContextMenuSheet( title: widget.item.title, actions: menuActions, @@ -576,7 +577,6 @@ class MediaContextMenuState extends State { await OverlaySheetController.showAdaptive( context, isScrollControlled: true, - backgroundColor: Colors.transparent, builder: (context) => FileInfoBottomSheet(fileInfo: fileInfo, title: metadata.title), ); } else if (context.mounted) { @@ -611,58 +611,27 @@ class MediaContextMenuState extends State { /// Show submenu for Add to... (Playlist or Collection) Future _showAddToSubmenu(BuildContext context) async { - final useBottomSheet = Platform.isIOS || Platform.isAndroid; - final submenuActions = [ _MenuAction(value: 'playlist', icon: Symbols.playlist_play_rounded, label: t.playlists.playlist), _MenuAction(value: 'collection', icon: Symbols.collections_rounded, label: t.collections.collection), ]; - String? selected; - if (useBottomSheet) { - selected = await OverlaySheetController.pushAdaptive( - context, - builder: (context) => SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Text(t.common.addTo, style: Theme.of(context).textTheme.titleMedium), - ), - ...submenuActions.map((action) { - return ListTile( - leading: AppIcon(action.icon, fill: 1), - title: Text(action.label), - onTap: () => OverlaySheetController.popAdaptive(context, action.value), - ); - }), - const SizedBox(height: 8), - ], - ), - ), - ); - } else { - selected = await showMenu( - context: context, - position: RelativeRect.fromLTRB( - _tapPosition?.dx ?? 0, - _tapPosition?.dy ?? 0, - _tapPosition?.dx ?? 0, - _tapPosition?.dy ?? 0, - ), - items: submenuActions.map((action) { - return PopupMenuItem( - value: action.value, + final selected = await showDialog( + context: context, + builder: (dialogContext) => SimpleDialog( + title: Text(t.common.addTo), + contentPadding: const EdgeInsets.symmetric(vertical: 8), + children: submenuActions.map((action) { + return SimpleDialogOption( + onPressed: () => Navigator.pop(dialogContext, action.value), + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Row( - mainAxisSize: MainAxisSize.min, - children: [AppIcon(action.icon, fill: 1, size: 20), const SizedBox(width: 12), Text(action.label)], + children: [AppIcon(action.icon, fill: 1, size: 24), const SizedBox(width: 16), Text(action.label, style: Theme.of(dialogContext).textTheme.bodyLarge)], ), ); }).toList(), - ); - } + ), + ); // Handle the submenu selection if (selected == 'playlist' && context.mounted) { @@ -839,7 +808,7 @@ class MediaContextMenuState extends State { // Create new collection flow final collectionName = await showTextInputDialog( context, - title: t.collections.createNewCollection, + title: t.common.createNew, labelText: t.collections.collectionName, hintText: t.collections.enterCollectionName, ); @@ -932,8 +901,9 @@ class MediaContextMenuState extends State { final currentStarValue = (metadata.userRating != null && metadata.userRating! > 0) ? metadata.userRating! / 2.0 : 0.0; - await showModalBottomSheet( - context: context, + await OverlaySheetController.showAdaptive( + context, + showDragHandle: true, builder: (context) => RatingBottomSheet( currentRating: currentStarValue, onRate: (stars) async { @@ -1212,7 +1182,7 @@ class _PlaylistSelectionDialog extends StatelessWidget { // Create new playlist option (always shown first) return ListTile( leading: const AppIcon(Symbols.add_rounded, fill: 1), - title: Text(t.playlists.createNewPlaylist), + title: Text(t.common.createNew), onTap: () => Navigator.pop(context, '_create_new'), ); } @@ -1266,7 +1236,7 @@ class _CollectionSelectionDialog extends StatelessWidget { // Create new collection option (always shown first) return ListTile( leading: const AppIcon(Symbols.add_rounded, fill: 1), - title: Text(t.collections.createNewCollection), + title: Text(t.common.createNew), onTap: () => Navigator.pop(context, '_create_new'), ); } @@ -1325,7 +1295,7 @@ class _FocusableContextMenuSheetState extends State<_FocusableContextMenuSheet> mainAxisSize: MainAxisSize.min, children: [ Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), child: Text( widget.title, style: Theme.of(context).textTheme.titleMedium, diff --git a/lib/widgets/overlay_sheet.dart b/lib/widgets/overlay_sheet.dart index b0f718c5..29cf280e 100644 --- a/lib/widgets/overlay_sheet.dart +++ b/lib/widgets/overlay_sheet.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -60,6 +61,7 @@ class OverlaySheetController { bool barrierDismissible = true, FocusNode? initialFocusNode, Alignment alignment = Alignment.bottomCenter, + bool showDragHandle = false, }) { return _state._show( builder: builder, @@ -68,6 +70,7 @@ class OverlaySheetController { barrierDismissible: barrierDismissible, initialFocusNode: initialFocusNode, alignment: alignment, + showDragHandle: showDragHandle, ); } @@ -104,6 +107,7 @@ class OverlaySheetController { bool isScrollControlled = false, FocusNode? initialFocusNode, Alignment alignment = Alignment.bottomCenter, + bool showDragHandle = false, }) { final controller = maybeOf(context); if (controller != null) { @@ -114,6 +118,7 @@ class OverlaySheetController { barrierDismissible: barrierDismissible, initialFocusNode: initialFocusNode, alignment: alignment, + showDragHandle: showDragHandle, ); } return showModalBottomSheet( @@ -193,6 +198,7 @@ class _OverlaySheetHostState extends State with SingleTickerPr bool _isOpen = false; bool _isClosing = false; bool _barrierDismissible = true; + bool _showDragHandle = false; BoxConstraints? _constraints; Color? _explicitBackgroundColor; Alignment _alignment = Alignment.bottomCenter; @@ -200,6 +206,7 @@ class _OverlaySheetHostState extends State with SingleTickerPr // Drag-to-dismiss state double _dragOffset = 0; bool _isDragging = false; + final _sheetKey = GlobalKey(); @override void initState() { @@ -240,6 +247,7 @@ class _OverlaySheetHostState extends State with SingleTickerPr bool barrierDismissible = true, FocusNode? initialFocusNode, Alignment alignment = Alignment.bottomCenter, + bool showDragHandle = false, }) { // If already open, close first (instant) if (_isOpen) { @@ -260,6 +268,7 @@ class _OverlaySheetHostState extends State with SingleTickerPr _isOpen = true; _isClosing = false; _barrierDismissible = barrierDismissible; + _showDragHandle = showDragHandle; _constraints = constraints; _explicitBackgroundColor = backgroundColor; _alignment = alignment; @@ -458,10 +467,28 @@ class _OverlaySheetHostState extends State with SingleTickerPr ); } + double _getSheetHeight() { + final renderBox = _sheetKey.currentContext?.findRenderObject() as RenderBox?; + return renderBox?.size.height ?? 300; + } + + void _checkDismiss(double velocity) { + final sheetHeight = _getSheetHeight(); + if (_dragOffset > sheetHeight * 0.25 || velocity > 500) { + _close(); + } else { + setState(() { + _dragOffset = 0; + }); + } + } + Widget _buildSheet(BuildContext context) { final size = MediaQuery.of(context).size; final isDesktop = size.width > 600; final isTop = _alignment.y < 0; + final isTV = PlatformDetector.isTV(); + final showHandle = _showDragHandle && !isTV && !isTop; final effectiveConstraints = _constraints ?? @@ -473,6 +500,73 @@ class _OverlaySheetHostState extends State with SingleTickerPr ? const BorderRadius.vertical(bottom: Radius.circular(16)) : const BorderRadius.vertical(top: Radius.circular(16)); + final colorScheme = Theme.of(context).colorScheme; + + Widget content = _pageStack.isNotEmpty ? _pageStack.last.builder(context) : const SizedBox.shrink(); + + // Wrap content in NotificationListener for scroll-aware drag-to-dismiss + if (showHandle) { + content = NotificationListener( + onNotification: (notification) { + if (notification is OverscrollNotification) { + // Android (ClampingScrollPhysics): overscroll fires reliably + if (notification.overscroll < 0) { + setState(() { + _dragOffset += -notification.overscroll; + }); + return true; + } + } else if (notification is ScrollUpdateNotification) { + // iOS (BouncingScrollPhysics): pixels go negative when bouncing past top + if (notification.metrics.pixels < 0) { + setState(() { + _dragOffset = -notification.metrics.pixels; + }); + return true; + } + // If user scrolled back down from overscroll, reset drag offset + if (_dragOffset > 0 && notification.metrics.pixels >= 0) { + setState(() { + _dragOffset = 0; + }); + } + } else if (notification is ScrollEndNotification) { + if (_dragOffset > 0) { + _checkDismiss(0); + return true; + } + } + return false; + }, + child: content, + ); + } + + // Build the sheet content column (handle + content) + Widget sheetContent; + if (showHandle) { + sheetContent = Column( + mainAxisSize: MainAxisSize.min, + children: [ + // M3 drag handle: 32x4, rounded, with 12dp top / 4dp bottom margin + Padding( + padding: const EdgeInsets.only(top: 12, bottom: 4), + child: Container( + width: 32, + height: 4, + decoration: BoxDecoration( + color: colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + borderRadius: const BorderRadius.all(Radius.circular(2)), + ), + ), + ), + Flexible(child: content), + ], + ); + } else { + sheetContent = content; + } + Widget sheet = FocusScope( node: _sheetFocusScopeNode, child: Focus( @@ -493,15 +587,16 @@ class _OverlaySheetHostState extends State with SingleTickerPr child: Transform.translate( offset: Offset(0, _dragOffset.clamp(0, double.infinity)), child: Material( - color: _explicitBackgroundColor ?? Theme.of(context).colorScheme.surface, + key: _sheetKey, + color: _explicitBackgroundColor ?? colorScheme.surface, borderRadius: borderRadius, clipBehavior: Clip.antiAlias, child: SafeArea( - top: !isTop, - bottom: isTop, + top: isTop, + bottom: !isTop, child: ConstrainedBox( constraints: effectiveConstraints, - child: _pageStack.isNotEmpty ? _pageStack.last.builder(context) : const SizedBox.shrink(), + child: sheetContent, ), ), ), @@ -511,33 +606,31 @@ class _OverlaySheetHostState extends State with SingleTickerPr ), ); - // Swipe-down-to-dismiss (skip on TV and for top-aligned sheets) - if (!PlatformDetector.isTV() && !isTop) { - sheet = GestureDetector( - onVerticalDragStart: (_) { - _isDragging = true; - _dragOffset = 0; - }, - onVerticalDragUpdate: (details) { - if (!_isDragging) return; - setState(() { - _dragOffset += details.delta.dy; - }); - }, - onVerticalDragEnd: (details) { - if (!_isDragging) return; - _isDragging = false; - - final sheetHeight = effectiveConstraints.minHeight; - final velocity = details.primaryVelocity ?? 0; - - if (_dragOffset > sheetHeight * 0.25 || velocity > 500) { - _close(); - } else { - setState(() { - _dragOffset = 0; - }); - } + // Swipe-down-to-dismiss on non-scrollable areas (skip on TV and top-aligned) + if (showHandle) { + sheet = RawGestureDetector( + gestures: { + VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers( + () => VerticalDragGestureRecognizer()..onlyAcceptDragOnThreshold = true, + (instance) { + instance + ..onStart = (_) { + _isDragging = true; + _dragOffset = 0; + } + ..onUpdate = (details) { + if (!_isDragging) return; + setState(() { + _dragOffset += details.delta.dy; + }); + } + ..onEnd = (details) { + if (!_isDragging) return; + _isDragging = false; + _checkDismiss(details.primaryVelocity ?? 0); + }; + }, + ), }, child: sheet, ); diff --git a/lib/widgets/rating_bottom_sheet.dart b/lib/widgets/rating_bottom_sheet.dart index 86b035cd..2a36b8fd 100644 --- a/lib/widgets/rating_bottom_sheet.dart +++ b/lib/widgets/rating_bottom_sheet.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:material_symbols_icons/symbols.dart'; import '../widgets/app_icon.dart'; +import '../widgets/overlay_sheet.dart'; import '../focus/dpad_navigator.dart'; import '../i18n/strings.g.dart'; @@ -44,116 +45,105 @@ class _RatingBottomSheetState extends State { @override Widget build(BuildContext context) { final theme = Theme.of(context); - return SafeArea( - child: Padding( - padding: const EdgeInsets.fromLTRB(24, 16, 24, 24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 32, - height: 4, - decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), - borderRadius: const BorderRadius.all(Radius.circular(2)), - ), - ), - const SizedBox(height: 20), - Text( - _selectedRating > 0 - ? '${formatRating(_selectedRating)} / 5' - : t.mediaMenu.rate, - style: theme.textTheme.titleMedium, - ), - const SizedBox(height: 16), - Focus( - focusNode: _starsFocusNode, - autofocus: true, - onKeyEvent: _handleStarsKeyEvent, - child: LayoutBuilder( - builder: (context, constraints) { - final starSize = (constraints.maxWidth / 5).clamp(0.0, 48.0); - return GestureDetector( - onTapDown: (details) => _handleStarTap(details.localPosition.dx, starSize), - onPanUpdate: (details) => _handleStarTap(details.localPosition.dx, starSize), - child: AnimatedBuilder( - animation: _starsFocusNode, - builder: (context, child) { - final hasFocus = _starsFocusNode.hasFocus; - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - color: hasFocus - ? theme.colorScheme.primary.withValues(alpha: 0.12) - : null, - ), - child: child, - ); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: List.generate(5, (i) { - final starIndex = i + 1; - final IconData icon; - if (_selectedRating >= starIndex) { - icon = Symbols.star_rounded; - } else if (_selectedRating >= starIndex - 0.5) { - icon = Symbols.star_half_rounded; - } else { - icon = Symbols.star_rounded; - } - return SizedBox( - width: starSize, - height: starSize, - child: Center( - child: AppIcon( - icon, - fill: _selectedRating >= starIndex - 0.5 ? 1 : 0, - color: _selectedRating >= starIndex - 0.5 - ? Colors.amber - : theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.3), - size: starSize * 0.8, - ), + return Padding( + padding: const EdgeInsets.fromLTRB(24, 4, 24, 24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + _selectedRating > 0 + ? '${formatRating(_selectedRating)} / 5' + : t.mediaMenu.rate, + style: theme.textTheme.titleMedium, + ), + const SizedBox(height: 16), + Focus( + focusNode: _starsFocusNode, + autofocus: true, + onKeyEvent: _handleStarsKeyEvent, + child: LayoutBuilder( + builder: (context, constraints) { + final starSize = (constraints.maxWidth / 5).clamp(0.0, 48.0); + return GestureDetector( + onTapDown: (details) => _handleStarTap(details.localPosition.dx, starSize), + onPanUpdate: (details) => _handleStarTap(details.localPosition.dx, starSize), + child: AnimatedBuilder( + animation: _starsFocusNode, + builder: (context, child) { + final hasFocus = _starsFocusNode.hasFocus; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(12)), + color: hasFocus + ? theme.colorScheme.primary.withValues(alpha: 0.12) + : null, + ), + child: child, + ); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: List.generate(5, (i) { + final starIndex = i + 1; + final IconData icon; + if (_selectedRating >= starIndex) { + icon = Symbols.star_rounded; + } else if (_selectedRating >= starIndex - 0.5) { + icon = Symbols.star_half_rounded; + } else { + icon = Symbols.star_rounded; + } + return SizedBox( + width: starSize, + height: starSize, + child: Center( + child: AppIcon( + icon, + fill: _selectedRating >= starIndex - 0.5 ? 1 : 0, + color: _selectedRating >= starIndex - 0.5 + ? Colors.amber + : theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.3), + size: starSize * 0.8, ), - ); - }), - ), - ), - ); - }, - ), - ), - const SizedBox(height: 20), - Row( - children: [ - if (widget.currentRating > 0) - Expanded( - child: OutlinedButton( - onPressed: () { - widget.onClear(); - Navigator.pop(context); - }, - child: Text(t.common.clear), + ), + ); + }), ), ), - if (widget.currentRating > 0) const SizedBox(width: 12), + ); + }, + ), + ), + const SizedBox(height: 20), + Row( + children: [ + if (widget.currentRating > 0) Expanded( - child: FilledButton( - onPressed: _selectedRating > 0 - ? () { - widget.onRate(_selectedRating); - Navigator.pop(context); - } - : null, - child: Text(t.mediaMenu.rate), + child: OutlinedButton( + onPressed: () { + widget.onClear(); + OverlaySheetController.closeAdaptive(context); + }, + child: Text(t.common.clear), ), ), - ], - ), - ], - ), + if (widget.currentRating > 0) const SizedBox(width: 12), + Expanded( + child: FilledButton( + onPressed: _selectedRating > 0 + ? () { + widget.onRate(_selectedRating); + OverlaySheetController.closeAdaptive(context); + } + : null, + child: Text(t.mediaMenu.rate), + ), + ), + ], + ), + ], ), ); } @@ -177,7 +167,7 @@ class _RatingBottomSheetState extends State { if (key == LogicalKeyboardKey.select || key == LogicalKeyboardKey.enter) { if (_selectedRating > 0) { widget.onRate(_selectedRating); - Navigator.pop(context); + OverlaySheetController.closeAdaptive(context); } return KeyEventResult.handled; }