Merge branch 'feature/delete-media'
This commit is contained in:
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "Zur Serie",
|
||||
"goToSeason": "Zur Staffel",
|
||||
"shufflePlay": "Zufallswiedergabe",
|
||||
"fileInfo": "Dateiinfo"
|
||||
"fileInfo": "Dateiinfo",
|
||||
"confirmDelete": "Sind Sie sicher, dass Sie dieses Element aus Ihrem Dateisystem löschen möchten?",
|
||||
"deleteMultipleWarning": "Mehrere Elemente können gelöscht werden.",
|
||||
"mediaDeletedSuccessfully": "Medienelement erfolgreich gelöscht",
|
||||
"mediaFailedToDelete": "Löschen des Medienelements fehlgeschlagen"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, Film",
|
||||
|
||||
@@ -240,7 +240,11 @@
|
||||
"goToSeries": "Go to series",
|
||||
"goToSeason": "Go to season",
|
||||
"shufflePlay": "Shuffle Play",
|
||||
"fileInfo": "File Info"
|
||||
"fileInfo": "File Info",
|
||||
"confirmDelete": "Are you sure you want to delete this item from your filesystem?",
|
||||
"deleteMultipleWarning": "Multiple items may be deleted.",
|
||||
"mediaDeletedSuccessfully": "Media item deleted successfully",
|
||||
"mediaFailedToDelete": "Failed to delete media item"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, movie",
|
||||
|
||||
@@ -240,7 +240,11 @@
|
||||
"goToSeries": "Aller à la série",
|
||||
"goToSeason": "Aller à la saison",
|
||||
"shufflePlay": "Lecture aléatoire",
|
||||
"fileInfo": "Informations sur le fichier"
|
||||
"fileInfo": "Informations sur le fichier",
|
||||
"confirmDelete": "Êtes-vous sûr de vouloir supprimer cet élément de votre système de fichiers?",
|
||||
"deleteMultipleWarning": "Plusieurs éléments peuvent être supprimés.",
|
||||
"mediaDeletedSuccessfully": "Élément média supprimé avec succès",
|
||||
"mediaFailedToDelete": "Échec de la suppression de l'élément média"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, film",
|
||||
|
||||
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "Vai alle serie",
|
||||
"goToSeason": "Vai alla stagione",
|
||||
"shufflePlay": "Riproduzione casuale",
|
||||
"fileInfo": "Info sul file"
|
||||
"fileInfo": "Info sul file",
|
||||
"confirmDelete": "Sei sicuro di voler eliminare questo elemento dal tuo filesystem?",
|
||||
"deleteMultipleWarning": "Potrebbero essere eliminati più elementi.",
|
||||
"mediaDeletedSuccessfully": "Elemento multimediale eliminato con successo",
|
||||
"mediaFailedToDelete": "Impossibile eliminare l'elemento multimediale"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, film",
|
||||
|
||||
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "시리즈로 이동",
|
||||
"goToSeason": "시즌으로 이동",
|
||||
"shufflePlay": "무작위 재생",
|
||||
"fileInfo": "파일 정보"
|
||||
"fileInfo": "파일 정보",
|
||||
"confirmDelete": "파일 시스템에서 이 항목을 삭제하시겠습니까?",
|
||||
"deleteMultipleWarning": "여러 항목이 삭제될 수 있습니다.",
|
||||
"mediaDeletedSuccessfully": "미디어 항목이 성공적으로 삭제되었습니다",
|
||||
"mediaFailedToDelete": "미디어 항목 삭제 실패"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, 영화",
|
||||
|
||||
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "Ga naar serie",
|
||||
"goToSeason": "Ga naar seizoen",
|
||||
"shufflePlay": "Willekeurig afspelen",
|
||||
"fileInfo": "Bestand info"
|
||||
"fileInfo": "Bestand info",
|
||||
"confirmDelete": "Weet je zeker dat je dit item van je bestandssysteem wilt verwijderen?",
|
||||
"deleteMultipleWarning": "Meerdere items kunnen worden verwijderd.",
|
||||
"mediaDeletedSuccessfully": "Media-item succesvol verwijderd",
|
||||
"mediaFailedToDelete": "Verwijderen van media-item mislukt"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, film",
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 8
|
||||
/// Strings: 4548 (568 per locale)
|
||||
/// Strings: 4580 (572 per locale)
|
||||
///
|
||||
/// Built on 2026-02-01 at 12:48 UTC
|
||||
/// Built on 2026-02-02 at 01:38 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint, unused_import
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuDe implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => 'Zur Staffel';
|
||||
@override String get shufflePlay => 'Zufallswiedergabe';
|
||||
@override String get fileInfo => 'Dateiinfo';
|
||||
@override String get confirmDelete => 'Sind Sie sicher, dass Sie dieses Element aus Ihrem Dateisystem löschen möchten?';
|
||||
@override String get deleteMultipleWarning => 'Mehrere Elemente können gelöscht werden.';
|
||||
@override String get mediaDeletedSuccessfully => 'Medienelement erfolgreich gelöscht';
|
||||
@override String get mediaFailedToDelete => 'Löschen des Medienelements fehlgeschlagen';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsDe {
|
||||
'mediaMenu.goToSeason' => 'Zur Staffel',
|
||||
'mediaMenu.shufflePlay' => 'Zufallswiedergabe',
|
||||
'mediaMenu.fileInfo' => 'Dateiinfo',
|
||||
'mediaMenu.confirmDelete' => 'Sind Sie sicher, dass Sie dieses Element aus Ihrem Dateisystem löschen möchten?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Mehrere Elemente können gelöscht werden.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Medienelement erfolgreich gelöscht',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Löschen des Medienelements fehlgeschlagen',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, Film',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, Serie',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsDe {
|
||||
'collections.selectCollection' => 'Sammlung auswählen',
|
||||
'collections.createNewCollection' => 'Neue Sammlung erstellen',
|
||||
'collections.collectionName' => 'Sammlungsname',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.enterCollectionName' => 'Sammlungsnamen eingeben',
|
||||
'collections.addedToCollection' => 'Zur Sammlung hinzugefügt',
|
||||
'collections.errorAddingToCollection' => 'Fehler beim Hinzufügen zur Sammlung',
|
||||
'collections.created' => 'Sammlung erstellt',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.removeFromCollection' => 'Aus Sammlung entfernen',
|
||||
'collections.removeFromCollectionConfirm' => ({required Object title}) => '"${title}" aus dieser Sammlung entfernen?',
|
||||
'collections.removedFromCollection' => 'Aus Sammlung entfernt',
|
||||
|
||||
@@ -777,6 +777,18 @@ class TranslationsMediaMenuEn {
|
||||
|
||||
/// en: 'File Info'
|
||||
String get fileInfo => 'File Info';
|
||||
|
||||
/// en: 'Are you sure you want to delete this item from your filesystem?'
|
||||
String get confirmDelete => 'Are you sure you want to delete this item from your filesystem?';
|
||||
|
||||
/// en: 'Multiple items may be deleted.'
|
||||
String get deleteMultipleWarning => 'Multiple items may be deleted.';
|
||||
|
||||
/// en: 'Media item deleted successfully'
|
||||
String get mediaDeletedSuccessfully => 'Media item deleted successfully';
|
||||
|
||||
/// en: 'Failed to delete media item'
|
||||
String get mediaFailedToDelete => 'Failed to delete media item';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -2343,6 +2355,10 @@ extension on Translations {
|
||||
'mediaMenu.goToSeason' => 'Go to season',
|
||||
'mediaMenu.shufflePlay' => 'Shuffle Play',
|
||||
'mediaMenu.fileInfo' => 'File Info',
|
||||
'mediaMenu.confirmDelete' => 'Are you sure you want to delete this item from your filesystem?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Multiple items may be deleted.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Media item deleted successfully',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Failed to delete media item',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, movie',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV show',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -2632,12 +2648,12 @@ extension on Translations {
|
||||
'watchTogether.joinSession' => 'Join Session',
|
||||
'watchTogether.joining' => 'Joining...',
|
||||
'watchTogether.controlMode' => 'Control Mode',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.controlModeQuestion' => 'Who can control playback?',
|
||||
'watchTogether.hostOnly' => 'Host Only',
|
||||
'watchTogether.anyone' => 'Anyone',
|
||||
'watchTogether.hostingSession' => 'Hosting Session',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.inSession' => 'In Session',
|
||||
'watchTogether.sessionCode' => 'Session Code',
|
||||
'watchTogether.hostControlsPlayback' => 'Host controls playback',
|
||||
|
||||
@@ -371,6 +371,10 @@ class _TranslationsMediaMenuFr implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => 'Aller à la saison';
|
||||
@override String get shufflePlay => 'Lecture aléatoire';
|
||||
@override String get fileInfo => 'Informations sur le fichier';
|
||||
@override String get confirmDelete => 'Êtes-vous sûr de vouloir supprimer cet élément de votre système de fichiers?';
|
||||
@override String get deleteMultipleWarning => 'Plusieurs éléments peuvent être supprimés.';
|
||||
@override String get mediaDeletedSuccessfully => 'Élément média supprimé avec succès';
|
||||
@override String get mediaFailedToDelete => 'Échec de la suppression de l\'élément média';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1203,6 +1207,10 @@ extension on TranslationsFr {
|
||||
'mediaMenu.goToSeason' => 'Aller à la saison',
|
||||
'mediaMenu.shufflePlay' => 'Lecture aléatoire',
|
||||
'mediaMenu.fileInfo' => 'Informations sur le fichier',
|
||||
'mediaMenu.confirmDelete' => 'Êtes-vous sûr de vouloir supprimer cet élément de votre système de fichiers?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Plusieurs éléments peuvent être supprimés.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Élément média supprimé avec succès',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Échec de la suppression de l\'élément média',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, film',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, show TV',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1492,12 +1500,12 @@ extension on TranslationsFr {
|
||||
'watchTogether.joinSession' => 'Rejoindre la session',
|
||||
'watchTogether.joining' => 'Rejoindre...',
|
||||
'watchTogether.controlMode' => 'Mode de contrôle',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.controlModeQuestion' => 'Qui peut contrôler la lecture ?',
|
||||
'watchTogether.hostOnly' => 'Hôte uniquement',
|
||||
'watchTogether.anyone' => 'N\'importe qui',
|
||||
'watchTogether.hostingSession' => 'Session d\'hébergement',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.inSession' => 'En session',
|
||||
'watchTogether.sessionCode' => 'Code de session',
|
||||
'watchTogether.hostControlsPlayback' => 'L\'hôte contrôle la lecture',
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuIt implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => 'Vai alla stagione';
|
||||
@override String get shufflePlay => 'Riproduzione casuale';
|
||||
@override String get fileInfo => 'Info sul file';
|
||||
@override String get confirmDelete => 'Sei sicuro di voler eliminare questo elemento dal tuo filesystem?';
|
||||
@override String get deleteMultipleWarning => 'Potrebbero essere eliminati più elementi.';
|
||||
@override String get mediaDeletedSuccessfully => 'Elemento multimediale eliminato con successo';
|
||||
@override String get mediaFailedToDelete => 'Impossibile eliminare l\'elemento multimediale';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsIt {
|
||||
'mediaMenu.goToSeason' => 'Vai alla stagione',
|
||||
'mediaMenu.shufflePlay' => 'Riproduzione casuale',
|
||||
'mediaMenu.fileInfo' => 'Info sul file',
|
||||
'mediaMenu.confirmDelete' => 'Sei sicuro di voler eliminare questo elemento dal tuo filesystem?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Potrebbero essere eliminati più elementi.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Elemento multimediale eliminato con successo',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Impossibile eliminare l\'elemento multimediale',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, film',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, serie TV',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsIt {
|
||||
'collections.selectCollection' => 'Seleziona raccolta',
|
||||
'collections.createNewCollection' => 'Crea nuova raccolta',
|
||||
'collections.collectionName' => 'Nome raccolta',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.enterCollectionName' => 'Inserisci nome raccolta',
|
||||
'collections.addedToCollection' => 'Aggiunto alla raccolta',
|
||||
'collections.errorAddingToCollection' => 'Errore nell\'aggiunta alla raccolta',
|
||||
'collections.created' => 'Raccolta creata',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.removeFromCollection' => 'Rimuovi dalla raccolta',
|
||||
'collections.removeFromCollectionConfirm' => ({required Object title}) => 'Rimuovere "${title}" da questa raccolta?',
|
||||
'collections.removedFromCollection' => 'Rimosso dalla raccolta',
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuKo implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => '시즌으로 이동';
|
||||
@override String get shufflePlay => '무작위 재생';
|
||||
@override String get fileInfo => '파일 정보';
|
||||
@override String get confirmDelete => '파일 시스템에서 이 항목을 삭제하시겠습니까?';
|
||||
@override String get deleteMultipleWarning => '여러 항목이 삭제될 수 있습니다.';
|
||||
@override String get mediaDeletedSuccessfully => '미디어 항목이 성공적으로 삭제되었습니다';
|
||||
@override String get mediaFailedToDelete => '미디어 항목 삭제 실패';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsKo {
|
||||
'mediaMenu.goToSeason' => '시즌으로 이동',
|
||||
'mediaMenu.shufflePlay' => '무작위 재생',
|
||||
'mediaMenu.fileInfo' => '파일 정보',
|
||||
'mediaMenu.confirmDelete' => '파일 시스템에서 이 항목을 삭제하시겠습니까?',
|
||||
'mediaMenu.deleteMultipleWarning' => '여러 항목이 삭제될 수 있습니다.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => '미디어 항목이 성공적으로 삭제되었습니다',
|
||||
'mediaMenu.mediaFailedToDelete' => '미디어 항목 삭제 실패',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, 영화',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV 프로그램',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsKo {
|
||||
'watchTogether.createSession' => '세션 생성',
|
||||
'watchTogether.creating' => '생성 중...',
|
||||
'watchTogether.joinSession' => '세션 참여',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.joining' => '참가 중...',
|
||||
'watchTogether.controlMode' => '제어 모드',
|
||||
'watchTogether.controlModeQuestion' => '누가 재생을 제어할 수 있나요?',
|
||||
'watchTogether.hostOnly' => '호스트만',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'watchTogether.anyone' => '누구나',
|
||||
'watchTogether.hostingSession' => '세션 호스팅',
|
||||
'watchTogether.inSession' => '세션 중',
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuNl implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => 'Ga naar seizoen';
|
||||
@override String get shufflePlay => 'Willekeurig afspelen';
|
||||
@override String get fileInfo => 'Bestand info';
|
||||
@override String get confirmDelete => 'Weet je zeker dat je dit item van je bestandssysteem wilt verwijderen?';
|
||||
@override String get deleteMultipleWarning => 'Meerdere items kunnen worden verwijderd.';
|
||||
@override String get mediaDeletedSuccessfully => 'Media-item succesvol verwijderd';
|
||||
@override String get mediaFailedToDelete => 'Verwijderen van media-item mislukt';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsNl {
|
||||
'mediaMenu.goToSeason' => 'Ga naar seizoen',
|
||||
'mediaMenu.shufflePlay' => 'Willekeurig afspelen',
|
||||
'mediaMenu.fileInfo' => 'Bestand info',
|
||||
'mediaMenu.confirmDelete' => 'Weet je zeker dat je dit item van je bestandssysteem wilt verwijderen?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Meerdere items kunnen worden verwijderd.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Media-item succesvol verwijderd',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Verwijderen van media-item mislukt',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, film',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV-serie',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsNl {
|
||||
'collections.selectCollection' => 'Selecteer collectie',
|
||||
'collections.createNewCollection' => 'Nieuwe collectie maken',
|
||||
'collections.collectionName' => 'Collectienaam',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.enterCollectionName' => 'Voer collectienaam in',
|
||||
'collections.addedToCollection' => 'Toegevoegd aan collectie',
|
||||
'collections.errorAddingToCollection' => 'Fout bij toevoegen aan collectie',
|
||||
'collections.created' => 'Collectie gemaakt',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.removeFromCollection' => 'Verwijderen uit collectie',
|
||||
'collections.removeFromCollectionConfirm' => ({required Object title}) => '"${title}" uit deze collectie verwijderen?',
|
||||
'collections.removedFromCollection' => 'Uit collectie verwijderd',
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuSv implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => 'Gå till säsong';
|
||||
@override String get shufflePlay => 'Blanda uppspelning';
|
||||
@override String get fileInfo => 'Filinformation';
|
||||
@override String get confirmDelete => 'Är du säker på att du vill ta bort detta objekt från ditt filsystem?';
|
||||
@override String get deleteMultipleWarning => 'Flera objekt kan komma att tas bort.';
|
||||
@override String get mediaDeletedSuccessfully => 'Mediaobjekt borttaget';
|
||||
@override String get mediaFailedToDelete => 'Kunde inte ta bort mediaobjekt';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsSv {
|
||||
'mediaMenu.goToSeason' => 'Gå till säsong',
|
||||
'mediaMenu.shufflePlay' => 'Blanda uppspelning',
|
||||
'mediaMenu.fileInfo' => 'Filinformation',
|
||||
'mediaMenu.confirmDelete' => 'Är du säker på att du vill ta bort detta objekt från ditt filsystem?',
|
||||
'mediaMenu.deleteMultipleWarning' => 'Flera objekt kan komma att tas bort.',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => 'Mediaobjekt borttaget',
|
||||
'mediaMenu.mediaFailedToDelete' => 'Kunde inte ta bort mediaobjekt',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, film',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, TV-serie',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsSv {
|
||||
'collections.selectCollection' => 'Välj samling',
|
||||
'collections.createNewCollection' => 'Skapa ny samling',
|
||||
'collections.collectionName' => 'Samlingsnamn',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.enterCollectionName' => 'Ange samlingsnamn',
|
||||
'collections.addedToCollection' => 'Tillagd i samling',
|
||||
'collections.errorAddingToCollection' => 'Fel vid tillägg i samling',
|
||||
'collections.created' => 'Samling skapad',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.removeFromCollection' => 'Ta bort från samling',
|
||||
'collections.removeFromCollectionConfirm' => ({required Object title}) => 'Ta bort "${title}" från denna samling?',
|
||||
'collections.removedFromCollection' => 'Borttagen från samling',
|
||||
|
||||
@@ -372,6 +372,10 @@ class _TranslationsMediaMenuZh implements TranslationsMediaMenuEn {
|
||||
@override String get goToSeason => '转到季';
|
||||
@override String get shufflePlay => '随机播放';
|
||||
@override String get fileInfo => '文件信息';
|
||||
@override String get confirmDelete => '确定要从文件系统中删除此项吗?';
|
||||
@override String get deleteMultipleWarning => '可能会删除多个项目。';
|
||||
@override String get mediaDeletedSuccessfully => '媒体项已成功删除';
|
||||
@override String get mediaFailedToDelete => '删除媒体项失败';
|
||||
}
|
||||
|
||||
// Path: accessibility
|
||||
@@ -1206,6 +1210,10 @@ extension on TranslationsZh {
|
||||
'mediaMenu.goToSeason' => '转到季',
|
||||
'mediaMenu.shufflePlay' => '随机播放',
|
||||
'mediaMenu.fileInfo' => '文件信息',
|
||||
'mediaMenu.confirmDelete' => '确定要从文件系统中删除此项吗?',
|
||||
'mediaMenu.deleteMultipleWarning' => '可能会删除多个项目。',
|
||||
'mediaMenu.mediaDeletedSuccessfully' => '媒体项已成功删除',
|
||||
'mediaMenu.mediaFailedToDelete' => '删除媒体项失败',
|
||||
'accessibility.mediaCardMovie' => ({required Object title}) => '${title}, 电影',
|
||||
'accessibility.mediaCardShow' => ({required Object title}) => '${title}, 电视剧',
|
||||
'accessibility.mediaCardEpisode' => ({required Object title, required Object episodeInfo}) => '${title}, ${episodeInfo}',
|
||||
@@ -1494,12 +1502,12 @@ extension on TranslationsZh {
|
||||
'collections.selectCollection' => '选择合集',
|
||||
'collections.createNewCollection' => '创建新合集',
|
||||
'collections.collectionName' => '合集名称',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.enterCollectionName' => '输入合集名称',
|
||||
'collections.addedToCollection' => '已添加到合集',
|
||||
'collections.errorAddingToCollection' => '添加到合集失败',
|
||||
'collections.created' => '已创建合集',
|
||||
_ => null,
|
||||
} ?? switch (path) {
|
||||
'collections.removeFromCollection' => '从合集移除',
|
||||
'collections.removeFromCollectionConfirm' => ({required Object title}) => '将“${title}”从此合集移除?',
|
||||
'collections.removedFromCollection' => '已从合集移除',
|
||||
|
||||
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "Gå till serie",
|
||||
"goToSeason": "Gå till säsong",
|
||||
"shufflePlay": "Blanda uppspelning",
|
||||
"fileInfo": "Filinformation"
|
||||
"fileInfo": "Filinformation",
|
||||
"confirmDelete": "Är du säker på att du vill ta bort detta objekt från ditt filsystem?",
|
||||
"deleteMultipleWarning": "Flera objekt kan komma att tas bort.",
|
||||
"mediaDeletedSuccessfully": "Mediaobjekt borttaget",
|
||||
"mediaFailedToDelete": "Kunde inte ta bort mediaobjekt"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, film",
|
||||
|
||||
@@ -241,7 +241,11 @@
|
||||
"goToSeries": "转到系列",
|
||||
"goToSeason": "转到季",
|
||||
"shufflePlay": "随机播放",
|
||||
"fileInfo": "文件信息"
|
||||
"fileInfo": "文件信息",
|
||||
"confirmDelete": "确定要从文件系统中删除此项吗?",
|
||||
"deleteMultipleWarning": "可能会删除多个项目。",
|
||||
"mediaDeletedSuccessfully": "媒体项已成功删除",
|
||||
"mediaFailedToDelete": "删除媒体项失败"
|
||||
},
|
||||
"accessibility": {
|
||||
"mediaCardMovie": "${title}, 电影",
|
||||
|
||||
@@ -774,6 +774,7 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
|
||||
_lastFocusedContentVersion = _contentVersion;
|
||||
}
|
||||
},
|
||||
onListRefresh: _loadItems,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,6 +934,13 @@ class _MediaDetailScreenState extends State<MediaDetailScreen> with WatchStateAw
|
||||
_watchStateChanged = true;
|
||||
_updateWatchState();
|
||||
},
|
||||
onListRefresh: () {
|
||||
if (widget.isOffline) {
|
||||
_loadSeasonsFromDownloads();
|
||||
} else {
|
||||
_loadSeasons();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -969,6 +976,13 @@ class _MediaDetailScreenState extends State<MediaDetailScreen> with WatchStateAw
|
||||
_watchStateChanged = true;
|
||||
_updateWatchState();
|
||||
},
|
||||
onListRefresh: () {
|
||||
if (widget.isOffline) {
|
||||
_loadSeasonsFromDownloads();
|
||||
} else {
|
||||
_loadSeasons();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1589,11 +1603,7 @@ class _MediaDetailScreenState extends State<MediaDetailScreen> with WatchStateAw
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom)),
|
||||
],
|
||||
),
|
||||
// Sticky top bar with fading background
|
||||
@@ -1717,6 +1727,7 @@ class _SeasonCard extends StatefulWidget {
|
||||
final PlexClient? client;
|
||||
final VoidCallback onTap;
|
||||
final VoidCallback onRefresh;
|
||||
final VoidCallback? onListRefresh;
|
||||
final bool isOffline;
|
||||
final String? localPosterPath;
|
||||
|
||||
@@ -1725,6 +1736,7 @@ class _SeasonCard extends StatefulWidget {
|
||||
this.client,
|
||||
required this.onTap,
|
||||
required this.onRefresh,
|
||||
this.onListRefresh,
|
||||
this.isOffline = false,
|
||||
this.localPosterPath,
|
||||
});
|
||||
@@ -1753,6 +1765,7 @@ class _SeasonCardState extends State<_SeasonCard> {
|
||||
key: _contextMenuKey,
|
||||
item: widget.season,
|
||||
onRefresh: (ratingKey) => widget.onRefresh(),
|
||||
onListRefresh: widget.onListRefresh,
|
||||
onTap: widget.onTap,
|
||||
child: Semantics(
|
||||
label: "media-season-${widget.season.ratingKey}",
|
||||
|
||||
@@ -234,14 +234,11 @@ class _SeasonDetailScreenState extends State<SeasonDetailScreen> with ItemUpdata
|
||||
);
|
||||
},
|
||||
onRefresh: widget.isOffline ? null : updateItem,
|
||||
onListRefresh: widget.isOffline ? null : _loadEpisodes,
|
||||
);
|
||||
}, childCount: _episodes.length),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
),
|
||||
SliverPadding(padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -266,6 +263,7 @@ class _EpisodeCard extends StatefulWidget {
|
||||
final PlexClient? client;
|
||||
final VoidCallback onTap;
|
||||
final Future<void> Function(String)? onRefresh;
|
||||
final Future<void> Function()? onListRefresh;
|
||||
final bool autofocus;
|
||||
final bool isOffline;
|
||||
final String? localPosterPath;
|
||||
@@ -275,6 +273,7 @@ class _EpisodeCard extends StatefulWidget {
|
||||
this.client,
|
||||
required this.onTap,
|
||||
this.onRefresh,
|
||||
this.onListRefresh,
|
||||
this.autofocus = false,
|
||||
this.isOffline = false,
|
||||
this.localPosterPath,
|
||||
@@ -338,6 +337,7 @@ class _EpisodeCardState extends State<_EpisodeCard> {
|
||||
key: _contextMenuKey,
|
||||
item: widget.episode,
|
||||
onRefresh: widget.onRefresh,
|
||||
onListRefresh: widget.onListRefresh,
|
||||
onTap: widget.onTap,
|
||||
child: InkWell(
|
||||
key: Key(widget.episode.ratingKey),
|
||||
|
||||
@@ -1095,6 +1095,13 @@ class PlexClient {
|
||||
await _dio.put('/actions/removeFromContinueWatching', queryParameters: {'ratingKey': ratingKey});
|
||||
}
|
||||
|
||||
/// Delete a media item from the library
|
||||
/// This permanently removes the item and its associated files from the server
|
||||
/// Returns true if deletion was successful, false otherwise
|
||||
Future<bool> deleteMediaItem(String ratingKey) async {
|
||||
return _wrapBoolApiCall(() => _dio.delete('/library/metadata/$ratingKey'), 'Failed to delete media item');
|
||||
}
|
||||
|
||||
/// Get server preferences
|
||||
Future<Map<String, dynamic>> getServerPreferences() async {
|
||||
final response = await _dio.get('/:/prefs');
|
||||
|
||||
@@ -45,6 +45,9 @@ class FocusableListTile extends StatefulWidget {
|
||||
/// If true, consumes the first select key event to avoid accidental activation.
|
||||
final bool suppressInitialSelect;
|
||||
|
||||
/// An optional color to display behind the menu item when being hovered.
|
||||
final Color? hoverColor;
|
||||
|
||||
const FocusableListTile({
|
||||
super.key,
|
||||
this.title,
|
||||
@@ -60,6 +63,7 @@ class FocusableListTile extends StatefulWidget {
|
||||
this.autofocus = false,
|
||||
this.contentPadding,
|
||||
this.suppressInitialSelect = false,
|
||||
this.hoverColor,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -84,6 +88,7 @@ class _FocusableListTileState extends State<FocusableListTile> {
|
||||
contentPadding: widget.contentPadding,
|
||||
focusNode: widget.suppressInitialSelect ? null : widget.focusNode,
|
||||
autofocus: widget.suppressInitialSelect ? false : widget.autofocus,
|
||||
hoverColor: widget.hoverColor,
|
||||
);
|
||||
|
||||
if (!widget.suppressInitialSelect) {
|
||||
|
||||
@@ -31,8 +31,9 @@ class _MenuAction {
|
||||
final String value;
|
||||
final IconData icon;
|
||||
final String label;
|
||||
final Color? hoverColor;
|
||||
|
||||
_MenuAction({required this.value, required this.icon, required this.label});
|
||||
_MenuAction({required this.value, required this.icon, required this.label, this.hoverColor});
|
||||
}
|
||||
|
||||
/// A reusable wrapper widget that adds a context menu (long press / right click)
|
||||
@@ -244,6 +245,21 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
mediaType == PlexMediaType.season) {
|
||||
menuActions.add(_MenuAction(value: 'add_to', icon: Symbols.add_rounded, label: t.common.addTo));
|
||||
}
|
||||
|
||||
// Delete media item (for episodes, movies, shows, and seasons)
|
||||
if (mediaType == PlexMediaType.episode ||
|
||||
mediaType == PlexMediaType.movie ||
|
||||
mediaType == PlexMediaType.show ||
|
||||
mediaType == PlexMediaType.season) {
|
||||
menuActions.add(
|
||||
_MenuAction(
|
||||
value: 'delete_media',
|
||||
icon: Symbols.delete_rounded,
|
||||
label: t.common.delete,
|
||||
hoverColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
} // End of regular menu items else block
|
||||
|
||||
String? selected;
|
||||
@@ -411,6 +427,10 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
case 'delete_download':
|
||||
await _handleDeleteDownload(context);
|
||||
break;
|
||||
|
||||
case 'delete_media':
|
||||
await _handleDeleteMediaItem(context, mediaType);
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
_isContextMenuOpen = false;
|
||||
@@ -1028,6 +1048,42 @@ class MediaContextMenuState extends State<MediaContextMenu> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle delete media item action
|
||||
/// This permanently removes the media item and its associated files from the server
|
||||
Future<void> _handleDeleteMediaItem(BuildContext context, PlexMediaType? mediaType) async {
|
||||
final metadata = widget.item as PlexMetadata;
|
||||
final isMultipleMediaItems = mediaType == PlexMediaType.show || mediaType == PlexMediaType.season;
|
||||
|
||||
// Show confirmation dialog
|
||||
final confirmed = await showDeleteConfirmation(
|
||||
context,
|
||||
title: t.common.delete,
|
||||
message: "${t.mediaMenu.confirmDelete}${isMultipleMediaItems ? "\n${t.mediaMenu.deleteMultipleWarning}" : ""}",
|
||||
);
|
||||
|
||||
if (!confirmed || !context.mounted) return;
|
||||
|
||||
try {
|
||||
final client = _getClientForItem();
|
||||
final success = await client.deleteMediaItem(metadata.ratingKey);
|
||||
|
||||
if (context.mounted) {
|
||||
if (success) {
|
||||
showSuccessSnackBar(context, t.mediaMenu.mediaDeletedSuccessfully);
|
||||
// Trigger list refresh to remove the item from the view
|
||||
widget.onListRefresh?.call();
|
||||
} else {
|
||||
showErrorSnackBar(context, t.mediaMenu.mediaFailedToDelete);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
appLogger.e(t.mediaMenu.mediaFailedToDelete, error: e);
|
||||
if (context.mounted) {
|
||||
showErrorSnackBar(context, t.mediaMenu.mediaFailedToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
@@ -1187,6 +1243,7 @@ class _FocusableContextMenuSheetState extends State<_FocusableContextMenuSheet>
|
||||
leading: AppIcon(action.icon, fill: 1),
|
||||
title: Text(action.label),
|
||||
onTap: () => Navigator.pop(context, action.value),
|
||||
hoverColor: action.hoverColor,
|
||||
);
|
||||
}),
|
||||
],
|
||||
@@ -1293,6 +1350,7 @@ class _FocusablePopupMenuState extends State<_FocusablePopupMenu> {
|
||||
leading: AppIcon(action.icon, fill: 1, size: 20),
|
||||
title: Text(action.label),
|
||||
onTap: () => Navigator.pop(context, action.value),
|
||||
hoverColor: action.hoverColor,
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user