diff --git a/src/Filee.App/Assets/i18n/ar.json b/src/Filee.App/Assets/i18n/ar.json
index 3de1151e..b5b4fede 100644
--- a/src/Filee.App/Assets/i18n/ar.json
+++ b/src/Filee.App/Assets/i18n/ar.json
@@ -44,6 +44,11 @@
"home.clear_history": "مسح",
"home.files": "عدد الملفات: {0}",
"home.failed_files": "فشل: {0}",
+ "home.undo": "تراجع",
+ "home.undo_hint": "نقل النتائج إلى سلة المحذوفات",
+ "home.undone": "تم التراجع: النتائج في سلة المحذوفات",
+ "home.undone_original": "تم التراجع: النتائج في سلة المحذوفات، وكذلك الملفات الأصلية التي حلّت محلها",
+ "home.undo_failed": "تعذّر نقل {0} إلى سلة المحذوفات: {1}",
"donut.center_drag": "اسحب الملفات إلى هنا",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "عدد الملفات: {0}",
@@ -119,6 +124,7 @@
"trash.no_folder": "لا يوجد مجلد لسلة المحذوفات",
"trash.failed": "تعذّر نقله إلى سلة المحذوفات",
"trash.cannot_place": "تعذّر حفظ النتيجة في مجلد الأصل",
+ "trash.changed": "تغيّر بعد التحويل",
"notice.empty_spreadsheet_pages_removed": "تمت إزالة صفحات جدول البيانات الفارغة",
"notice.ocr_has_text": "كل الصفحات تحتوي على نص بالفعل، لذا نُسخ الملف كما هو",
"notice.live_photo_pair": "حُفظ كصورة وملف MOV بالاسم نفسه. استوردهما معًا (صور iCloud أو AirDrop أو تطبيق الصور على Mac) لتحصل على Live Photo",
diff --git a/src/Filee.App/Assets/i18n/de.json b/src/Filee.App/Assets/i18n/de.json
index fc742a82..47839db8 100644
--- a/src/Filee.App/Assets/i18n/de.json
+++ b/src/Filee.App/Assets/i18n/de.json
@@ -44,6 +44,11 @@
"home.clear_history": "Leeren",
"home.files": "{0} Dateien",
"home.failed_files": "{0} fehlgeschlagen",
+ "home.undo": "Rückgängig",
+ "home.undo_hint": "Die Ergebnisse in den Papierkorb verschieben",
+ "home.undone": "Rückgängig gemacht: Die Ergebnisse sind im Papierkorb",
+ "home.undone_original": "Rückgängig gemacht: Die Ergebnisse sind im Papierkorb, ebenso die Originale, die sie ersetzt hatten",
+ "home.undo_failed": "{0} konnte nicht in den Papierkorb verschoben werden: {1}",
"donut.center_drag": "Dateien hierher ziehen",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} Dateien",
@@ -119,6 +124,7 @@
"trash.no_folder": "es gibt keinen Papierkorbordner",
"trash.failed": "die Datei konnte nicht in den Papierkorb verschoben werden",
"trash.cannot_place": "das Ergebnis konnte nicht im Ordner des Originals gespeichert werden",
+ "trash.changed": "die Datei wurde nach der Umwandlung geändert",
"notice.empty_spreadsheet_pages_removed": "Leere Tabellenseiten wurden entfernt",
"notice.ocr_has_text": "Alle Seiten enthalten bereits Text. Die Datei wurde unverändert kopiert",
"notice.live_photo_pair": "Als Foto und MOV-Datei mit gleichem Namen gespeichert. Importiere beide zusammen (über iCloud-Fotos, AirDrop oder Fotos auf einem Mac), um ein Live Photo zu erhalten",
diff --git a/src/Filee.App/Assets/i18n/en.json b/src/Filee.App/Assets/i18n/en.json
index 75d0ee92..7ed76479 100644
--- a/src/Filee.App/Assets/i18n/en.json
+++ b/src/Filee.App/Assets/i18n/en.json
@@ -47,6 +47,11 @@
"home.clear_history": "Clear",
"home.files": "{0} files",
"home.failed_files": "{0} failed",
+ "home.undo": "Undo",
+ "home.undo_hint": "Move the results to the Recycle Bin / Trash",
+ "home.undone": "Undone: the results are in the Recycle Bin / Trash",
+ "home.undone_original": "Undone: the results are in the Recycle Bin / Trash, and so are the originals they replaced",
+ "home.undo_failed": "{0} couldn't be moved to the Recycle Bin / Trash: {1}",
"donut.center_drag": "Bring files here",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "there is no Trash folder",
"trash.failed": "it couldn't be moved to the Recycle Bin / Trash",
"trash.cannot_place": "the result couldn't be saved in the original's folder",
+ "trash.changed": "it was changed after the conversion",
"notice.empty_spreadsheet_pages_removed": "Empty spreadsheet pages were removed",
"notice.ocr_has_text": "Every page already has text, so it was copied as it is",
"notice.live_photo_pair": "Saved as a photo and a MOV with the same name. Import both together (iCloud Photos, AirDrop or Photos on a Mac) to get a Live Photo",
diff --git a/src/Filee.App/Assets/i18n/es.json b/src/Filee.App/Assets/i18n/es.json
index c074a17f..b43e1cff 100644
--- a/src/Filee.App/Assets/i18n/es.json
+++ b/src/Filee.App/Assets/i18n/es.json
@@ -44,6 +44,11 @@
"home.clear_history": "Borrar",
"home.files": "{0} archivos",
"home.failed_files": "{0} con error",
+ "home.undo": "Deshacer",
+ "home.undo_hint": "Mover los resultados a la Papelera de reciclaje",
+ "home.undone": "Deshecho: los resultados están en la Papelera de reciclaje",
+ "home.undone_original": "Deshecho: los resultados están en la Papelera de reciclaje, igual que los originales que reemplazaron",
+ "home.undo_failed": "No se pudo mover {0} a la Papelera de reciclaje: {1}",
"donut.center_drag": "Trae los archivos aquí",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} archivos",
@@ -119,6 +124,7 @@
"trash.no_folder": "no hay carpeta de Papelera",
"trash.failed": "no se pudo mover a la Papelera de reciclaje",
"trash.cannot_place": "no se pudo guardar el resultado en la carpeta del original",
+ "trash.changed": "cambió después de la conversión",
"notice.empty_spreadsheet_pages_removed": "Se eliminaron las páginas vacías de la hoja de cálculo",
"notice.ocr_has_text": "Todas las páginas ya tienen texto, así que se copió tal cual",
"notice.live_photo_pair": "Guardado como una foto y un MOV con el mismo nombre. Impórtalos juntos (Fotos de iCloud, AirDrop o Fotos en un Mac) para obtener una Live Photo",
diff --git a/src/Filee.App/Assets/i18n/fr.json b/src/Filee.App/Assets/i18n/fr.json
index 68101164..38cc052c 100644
--- a/src/Filee.App/Assets/i18n/fr.json
+++ b/src/Filee.App/Assets/i18n/fr.json
@@ -47,6 +47,11 @@
"home.clear_history": "Effacer",
"home.files": "{0} fichiers",
"home.failed_files": "{0} en échec",
+ "home.undo": "Annuler",
+ "home.undo_hint": "Déplacer les résultats dans la Corbeille",
+ "home.undone": "Annulé : les résultats sont dans la Corbeille",
+ "home.undone_original": "Annulé : les résultats sont dans la Corbeille, tout comme les originaux qu'ils avaient remplacés",
+ "home.undo_failed": "Impossible de déplacer {0} dans la Corbeille : {1}",
"donut.center_drag": "Amenez les fichiers ici",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "il n'y a pas de dossier Corbeille",
"trash.failed": "impossible de le déplacer dans la Corbeille",
"trash.cannot_place": "impossible d'enregistrer le résultat dans le dossier de l'original",
+ "trash.changed": "il a été modifié après la conversion",
"notice.empty_spreadsheet_pages_removed": "Les pages vides de la feuille de calcul ont été supprimées",
"notice.ocr_has_text": "Toutes les pages ont déjà du texte : copié tel quel",
"notice.live_photo_pair": "Enregistré en une photo et un MOV de même nom. Importez-les ensemble (Photos iCloud, AirDrop ou Photos sur Mac) pour obtenir une Live Photo",
diff --git a/src/Filee.App/Assets/i18n/hi.json b/src/Filee.App/Assets/i18n/hi.json
index 957153f4..c4569867 100644
--- a/src/Filee.App/Assets/i18n/hi.json
+++ b/src/Filee.App/Assets/i18n/hi.json
@@ -44,6 +44,11 @@
"home.clear_history": "साफ़ करें",
"home.files": "{0} फ़ाइलें",
"home.failed_files": "{0} विफल",
+ "home.undo": "पूर्ववत करें",
+ "home.undo_hint": "परिणामों को रीसायकल बिन / ट्रैश में ले जाएँ",
+ "home.undone": "पूर्ववत किया गया: परिणाम रीसायकल बिन / ट्रैश में हैं",
+ "home.undone_original": "पूर्ववत किया गया: परिणाम रीसायकल बिन / ट्रैश में हैं, और जिन मूल फ़ाइलों की जगह उन्होंने ली थी वे भी वहीं हैं",
+ "home.undo_failed": "{0} को रीसायकल बिन / ट्रैश में नहीं ले जाया जा सका: {1}",
"donut.center_drag": "फ़ाइलें यहाँ लाएँ",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} फ़ाइलें",
@@ -119,6 +124,7 @@
"trash.no_folder": "ट्रैश फ़ोल्डर नहीं है",
"trash.failed": "इसे रीसायकल बिन / ट्रैश में नहीं ले जाया जा सका",
"trash.cannot_place": "परिणाम मूल फ़ाइल के फ़ोल्डर में सेव नहीं हो सका",
+ "trash.changed": "रूपांतरण के बाद इसे बदला गया",
"notice.empty_spreadsheet_pages_removed": "स्प्रेडशीट के खाली पृष्ठ हटा दिए गए",
"notice.ocr_has_text": "हर पेज में पहले से टेक्स्ट है, इसलिए फ़ाइल जैसी थी वैसी कॉपी की गई",
"notice.live_photo_pair": "एक ही नाम की फ़ोटो और MOV के रूप में सहेजा गया। लाइव फ़ोटो पाने के लिए दोनों को साथ में इम्पोर्ट करें (iCloud Photos, AirDrop या Mac पर Photos)",
diff --git a/src/Filee.App/Assets/i18n/ja.json b/src/Filee.App/Assets/i18n/ja.json
index 5dcc03f9..a86f97dc 100644
--- a/src/Filee.App/Assets/i18n/ja.json
+++ b/src/Filee.App/Assets/i18n/ja.json
@@ -44,6 +44,11 @@
"home.clear_history": "消去",
"home.files": "{0}個のファイル",
"home.failed_files": "{0}件失敗",
+ "home.undo": "元に戻す",
+ "home.undo_hint": "結果をごみ箱に移動します",
+ "home.undone": "元に戻しました: 結果はごみ箱にあります",
+ "home.undone_original": "元に戻しました: 結果はごみ箱にあり、置き換えられた元のファイルもごみ箱にあります",
+ "home.undo_failed": "{0} をごみ箱に移動できませんでした: {1}",
"donut.center_drag": "ここにファイルをドラッグ",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0}ファイル",
@@ -119,6 +124,7 @@
"trash.no_folder": "ごみ箱フォルダーがありません",
"trash.failed": "ごみ箱に移動できませんでした",
"trash.cannot_place": "元のファイルのフォルダーに結果を保存できませんでした",
+ "trash.changed": "変換後に変更されています",
"notice.empty_spreadsheet_pages_removed": "スプレッドシートの空白ページを削除しました",
"notice.ocr_has_text": "すべてのページにテキストがあるため、元のままコピーしました",
"notice.live_photo_pair": "同じ名前の写真とMOVとして保存しました。両方を一緒に取り込むと(iCloud写真、AirDrop、Macの写真アプリ)Live Photoになります",
diff --git a/src/Filee.App/Assets/i18n/ko.json b/src/Filee.App/Assets/i18n/ko.json
index 5e899b54..3ab3e257 100644
--- a/src/Filee.App/Assets/i18n/ko.json
+++ b/src/Filee.App/Assets/i18n/ko.json
@@ -47,6 +47,11 @@
"home.clear_history": "지우기",
"home.files": "파일 {0}개",
"home.failed_files": "{0}개 실패",
+ "home.undo": "되돌리기",
+ "home.undo_hint": "결과를 휴지통으로 옮겨요",
+ "home.undone": "되돌렸어요: 결과는 휴지통에 있어요",
+ "home.undone_original": "되돌렸어요: 결과는 휴지통에 있고, 결과가 대신했던 원본도 휴지통에 있어요",
+ "home.undo_failed": "{0}을(를) 휴지통으로 옮기지 못했어요: {1}",
"donut.center_drag": "파일을 이쪽으로",
"donut.files_same": "{1} {0}개",
@@ -125,6 +130,7 @@
"trash.no_folder": "휴지통 폴더가 없어요",
"trash.failed": "휴지통으로 옮기지 못했어요",
"trash.cannot_place": "원본 폴더에 결과를 저장하지 못했어요",
+ "trash.changed": "변환한 뒤에 바뀌었어요",
"notice.empty_spreadsheet_pages_removed": "스프레드시트의 빈 페이지를 제거했어요",
"notice.ocr_has_text": "모든 페이지에 이미 텍스트가 있어서 그대로 복사했어요",
"notice.live_photo_pair": "같은 이름의 사진과 MOV로 저장했어요. 두 파일을 함께 가져오면(iCloud 사진, AirDrop, Mac의 사진 앱) 라이브 포토가 돼요",
diff --git a/src/Filee.App/Assets/i18n/ne.json b/src/Filee.App/Assets/i18n/ne.json
index a9a85890..8b9d011a 100644
--- a/src/Filee.App/Assets/i18n/ne.json
+++ b/src/Filee.App/Assets/i18n/ne.json
@@ -44,6 +44,11 @@
"home.clear_history": "खाली गर्नुहोस्",
"home.files": "{0} फाइलहरू",
"home.failed_files": "{0} असफल",
+ "home.undo": "पूर्ववत गर्नुहोस्",
+ "home.undo_hint": "नतिजाहरूलाई रिसाइकल बिन / ट्र्यासमा सार्नुहोस्",
+ "home.undone": "पूर्ववत गरियो: नतिजाहरू रिसाइकल बिन / ट्र्यासमा छन्",
+ "home.undone_original": "पूर्ववत गरियो: नतिजाहरू रिसाइकल बिन / ट्र्यासमा छन्, र तिनले बदलेका मूल फाइलहरू पनि त्यहीँ छन्",
+ "home.undo_failed": "{0} लाई रिसाइकल बिन / ट्र्यासमा सार्न सकिएन: {1}",
"donut.center_drag": "फाइलहरू यहाँ ल्याउनुहोस्",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} फाइलहरू",
@@ -119,6 +124,7 @@
"trash.no_folder": "ट्र्यास फोल्डर छैन",
"trash.failed": "यसलाई रिसाइकल बिन / ट्र्यासमा सार्न सकिएन",
"trash.cannot_place": "नतिजा मूल फाइलको फोल्डरमा सेभ गर्न सकिएन",
+ "trash.changed": "रूपान्तरणपछि यसलाई परिवर्तन गरिएको छ",
"notice.ocr_has_text": "हरेक पृष्ठमा पहिले नै पाठ छ, त्यसैले जस्तो छ त्यस्तै प्रतिलिपि गरियो",
"notice.empty_spreadsheet_pages_removed": "स्प्रेडसिटका खाली पृष्ठहरू हटाइए",
"notice.live_photo_pair": "एउटै नामको फोटो र MOV का रूपमा सुरक्षित गरियो। लाइभ फोटो पाउन दुवैलाई सँगै आयात गर्नुहोस् (iCloud Photos, AirDrop वा Mac मा Photos)",
diff --git a/src/Filee.App/Assets/i18n/pl.json b/src/Filee.App/Assets/i18n/pl.json
index 72f4aa02..8aa702f2 100644
--- a/src/Filee.App/Assets/i18n/pl.json
+++ b/src/Filee.App/Assets/i18n/pl.json
@@ -47,6 +47,11 @@
"home.clear_history": "Wyczyść",
"home.files": "Pliki: {0}",
"home.failed_files": "Błędy: {0}",
+ "home.undo": "Cofnij",
+ "home.undo_hint": "Przenieś wyniki do Kosza",
+ "home.undone": "Cofnięto: wyniki są w Koszu",
+ "home.undone_original": "Cofnięto: wyniki są w Koszu, tak jak oryginały, które zastąpiły",
+ "home.undo_failed": "Nie udało się przenieść {0} do Kosza: {1}",
"donut.center_drag": "Przenieś pliki tutaj",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "nie ma folderu Kosza",
"trash.failed": "nie udało się przenieść go do Kosza",
"trash.cannot_place": "nie udało się zapisać wyniku w folderze oryginału",
+ "trash.changed": "zmieniono go po konwersji",
"notice.empty_spreadsheet_pages_removed": "Usunięto puste strony arkusza kalkulacyjnego",
"notice.ocr_has_text": "Każda strona ma już tekst, więc skopiowano bez zmian",
"notice.live_photo_pair": "Zapisano jako zdjęcie i plik MOV o tej samej nazwie. Zaimportuj je razem (Zdjęcia iCloud, AirDrop lub Zdjęcia na Macu), aby otrzymać Live Photo",
diff --git a/src/Filee.App/Assets/i18n/pt-BR.json b/src/Filee.App/Assets/i18n/pt-BR.json
index 75099813..b15db430 100644
--- a/src/Filee.App/Assets/i18n/pt-BR.json
+++ b/src/Filee.App/Assets/i18n/pt-BR.json
@@ -47,6 +47,11 @@
"home.clear_history": "Limpar",
"home.files": "{0} arquivos",
"home.failed_files": "{0} falharam",
+ "home.undo": "Desfazer",
+ "home.undo_hint": "Mover os resultados para a Lixeira",
+ "home.undone": "Desfeito: os resultados estão na Lixeira",
+ "home.undone_original": "Desfeito: os resultados estão na Lixeira, assim como os originais que eles substituíram",
+ "home.undo_failed": "Não foi possível mover {0} para a Lixeira: {1}",
"donut.center_drag": "Traga os arquivos para cá",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "não há pasta de Lixeira",
"trash.failed": "não foi possível movê-lo para a Lixeira",
"trash.cannot_place": "não foi possível salvar o resultado na pasta do original",
+ "trash.changed": "ele foi alterado depois da conversão",
"notice.empty_spreadsheet_pages_removed": "As páginas vazias da planilha foram removidas",
"notice.ocr_has_text": "Todas as páginas já têm texto, então foi copiado como está",
"notice.live_photo_pair": "Salvo como uma foto e um MOV com o mesmo nome. Importe os dois juntos (Fotos do iCloud, AirDrop ou Fotos no Mac) para obter uma Live Photo",
diff --git a/src/Filee.App/Assets/i18n/pt-PT.json b/src/Filee.App/Assets/i18n/pt-PT.json
index e6ca7c15..e67c02ea 100644
--- a/src/Filee.App/Assets/i18n/pt-PT.json
+++ b/src/Filee.App/Assets/i18n/pt-PT.json
@@ -47,6 +47,11 @@
"home.clear_history": "Limpar",
"home.files": "{0} ficheiros",
"home.failed_files": "Falhas: {0}",
+ "home.undo": "Anular",
+ "home.undo_hint": "Mover os resultados para a Reciclagem ou para o Lixo",
+ "home.undone": "Anulado: os resultados estão na Reciclagem ou no Lixo",
+ "home.undone_original": "Anulado: os resultados estão na Reciclagem ou no Lixo, tal como os originais que substituíram",
+ "home.undo_failed": "Não foi possível mover {0} para a Reciclagem ou para o Lixo: {1}",
"donut.center_drag": "Arrasta ficheiros para aqui",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "não existe uma pasta de Lixo",
"trash.failed": "não foi possível movê-lo para a Reciclagem ou para o Lixo",
"trash.cannot_place": "não foi possível guardar o resultado na pasta do original",
+ "trash.changed": "foi alterado depois da conversão",
"notice.empty_spreadsheet_pages_removed": "Foram removidas as páginas vazias das folhas de cálculo",
"notice.ocr_has_text": "Todas as páginas já têm texto, pelo que o ficheiro foi copiado sem alterações",
"notice.live_photo_pair": "Foi guardada uma fotografia e um MOV com o mesmo nome. Importa ambos em conjunto (Fotografias em iCloud, AirDrop ou Fotografias num Mac) para obteres uma Live Photo",
diff --git a/src/Filee.App/Assets/i18n/ru.json b/src/Filee.App/Assets/i18n/ru.json
index 29acdd1e..45dd75dd 100644
--- a/src/Filee.App/Assets/i18n/ru.json
+++ b/src/Filee.App/Assets/i18n/ru.json
@@ -47,6 +47,11 @@
"home.clear_history": "Очистить",
"home.files": "Файлов: {0}",
"home.failed_files": "Ошибок: {0}",
+ "home.undo": "Отменить",
+ "home.undo_hint": "Переместить результаты в Корзину",
+ "home.undone": "Отменено: результаты в Корзине",
+ "home.undone_original": "Отменено: результаты в Корзине, как и оригиналы, которые они заменили",
+ "home.undo_failed": "Не удалось переместить {0} в Корзину: {1}",
"donut.center_drag": "Перетащите сюда",
"donut.files_same": "{0} × {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "нет папки Корзины",
"trash.failed": "не удалось переместить его в Корзину",
"trash.cannot_place": "не удалось сохранить результат в папке оригинала",
+ "trash.changed": "он изменился после преобразования",
"notice.empty_spreadsheet_pages_removed": "Пустые страницы таблицы удалены",
"notice.ocr_has_text": "На всех страницах уже есть текст, поэтому файл скопирован как есть",
"notice.live_photo_pair": "Сохранено как фото и MOV с одинаковым именем. Импортируйте их вместе (Фото iCloud, AirDrop или «Фото» на Mac), чтобы получить Live Photo",
diff --git a/src/Filee.App/Assets/i18n/th.json b/src/Filee.App/Assets/i18n/th.json
index 8c419e6b..d6d11bc7 100644
--- a/src/Filee.App/Assets/i18n/th.json
+++ b/src/Filee.App/Assets/i18n/th.json
@@ -44,6 +44,11 @@
"home.clear_history": "ล้างประวัติ",
"home.files": "{0} ไฟล์",
"home.failed_files": "ล้มเหลว {0} ไฟล์",
+ "home.undo": "เลิกทำ",
+ "home.undo_hint": "ย้ายผลลัพธ์ไปที่ถังรีไซเคิล / ถังขยะ",
+ "home.undone": "เลิกทำแล้ว: ผลลัพธ์อยู่ในถังรีไซเคิล / ถังขยะ",
+ "home.undone_original": "เลิกทำแล้ว: ผลลัพธ์อยู่ในถังรีไซเคิล / ถังขยะ และต้นฉบับที่ถูกแทนที่ก็อยู่ที่นั่นด้วย",
+ "home.undo_failed": "ย้าย {0} ไปที่ถังรีไซเคิล / ถังขยะไม่ได้: {1}",
"donut.center_drag": "ลากไฟล์มาที่นี่",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} ไฟล์",
@@ -119,6 +124,7 @@
"trash.no_folder": "ไม่มีโฟลเดอร์ถังขยะ",
"trash.failed": "ย้ายไปที่ถังรีไซเคิล / ถังขยะไม่ได้",
"trash.cannot_place": "บันทึกผลลัพธ์ในโฟลเดอร์ของไฟล์ต้นฉบับไม่ได้",
+ "trash.changed": "ไฟล์ถูกแก้ไขหลังการแปลง",
"notice.ocr_has_text": "ทุกหน้ามีข้อความอยู่แล้ว จึงคัดลอกไฟล์ตามเดิม",
"notice.empty_spreadsheet_pages_removed": "ลบหน้าว่างของสเปรดชีตออกแล้ว",
"notice.live_photo_pair": "บันทึกเป็นรูปภาพและไฟล์ MOV ที่มีชื่อเดียวกัน นำเข้าทั้งสองไฟล์พร้อมกัน (ผ่านรูปภาพ iCloud, AirDrop หรือ Photos บน Mac) เพื่อใช้งานเป็น Live Photo",
diff --git a/src/Filee.App/Assets/i18n/tr.json b/src/Filee.App/Assets/i18n/tr.json
index 62a8e5e1..87babf8f 100644
--- a/src/Filee.App/Assets/i18n/tr.json
+++ b/src/Filee.App/Assets/i18n/tr.json
@@ -44,6 +44,11 @@
"home.clear_history": "Temizle",
"home.files": "{0} dosya",
"home.failed_files": "{0} başarısız",
+ "home.undo": "Geri al",
+ "home.undo_hint": "Sonuçları Geri Dönüşüm Kutusu'na / Çöp Sepeti'ne taşı",
+ "home.undone": "Geri alındı: sonuçlar Geri Dönüşüm Kutusu'nda / Çöp Sepeti'nde",
+ "home.undone_original": "Geri alındı: sonuçlar ve yerini aldıkları orijinaller Geri Dönüşüm Kutusu'nda / Çöp Sepeti'nde",
+ "home.undo_failed": "{0} Geri Dönüşüm Kutusu'na / Çöp Sepeti'ne taşınamadı: {1}",
"donut.center_drag": "Dosyaları buraya getirin",
"donut.files_same": "{0} × {1}",
"donut.files_mixed": "{0} dosya",
@@ -119,6 +124,7 @@
"trash.no_folder": "Çöp Sepeti klasörü yok",
"trash.failed": "Geri Dönüşüm Kutusu'na / Çöp Sepeti'ne taşınamadı",
"trash.cannot_place": "sonuç özgün dosyanın klasörüne kaydedilemedi",
+ "trash.changed": "dönüştürmeden sonra değiştirildi",
"notice.empty_spreadsheet_pages_removed": "Elektronik tablodaki boş sayfalar kaldırıldı",
"notice.ocr_has_text": "Her sayfada zaten metin olduğu için dosya olduğu gibi kopyalandı",
"notice.live_photo_pair": "Aynı adlı fotoğraf ve MOV dosyası olarak kaydedildi. Live Photo elde etmek için ikisini birlikte içe aktarın (iCloud Fotoğrafları, AirDrop veya Mac'teki Fotoğraflar ile)",
diff --git a/src/Filee.App/Assets/i18n/zh-CN.json b/src/Filee.App/Assets/i18n/zh-CN.json
index 340de83b..4ff4f9ac 100644
--- a/src/Filee.App/Assets/i18n/zh-CN.json
+++ b/src/Filee.App/Assets/i18n/zh-CN.json
@@ -47,6 +47,11 @@
"home.clear_history": "清除",
"home.files": "{0} 个文件",
"home.failed_files": "{0} 个失败",
+ "home.undo": "撤销",
+ "home.undo_hint": "将结果移到回收站/废纸篓",
+ "home.undone": "已撤销:结果已在回收站/废纸篓中",
+ "home.undone_original": "已撤销:结果已在回收站/废纸篓中,被替换的原文件也在那里",
+ "home.undo_failed": "无法将 {0} 移到回收站/废纸篓:{1}",
"donut.center_drag": "把文件拖到这里",
"donut.files_same": "{0} 个 {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "没有废纸篓文件夹",
"trash.failed": "无法移到回收站/废纸篓",
"trash.cannot_place": "无法将结果保存到原文件所在的文件夹",
+ "trash.changed": "转换后它被修改过",
"notice.empty_spreadsheet_pages_removed": "已移除电子表格中的空白页面",
"notice.ocr_has_text": "每页都已有文字,已原样复制",
"notice.live_photo_pair": "已保存为同名的照片和 MOV。将两者一起导入(iCloud 照片、隔空投送或 Mac 上的“照片”)即可得到实况照片",
diff --git a/src/Filee.App/Assets/i18n/zh-TW.json b/src/Filee.App/Assets/i18n/zh-TW.json
index ee508a74..d9f1c979 100644
--- a/src/Filee.App/Assets/i18n/zh-TW.json
+++ b/src/Filee.App/Assets/i18n/zh-TW.json
@@ -47,6 +47,11 @@
"home.clear_history": "清除",
"home.files": "{0} 個檔案",
"home.failed_files": "{0} 個失敗",
+ "home.undo": "復原",
+ "home.undo_hint": "將結果移到資源回收筒/垃圾桶",
+ "home.undone": "已復原:結果已在資源回收筒/垃圾桶中",
+ "home.undone_original": "已復原:結果已在資源回收筒/垃圾桶中,被取代的原始檔也在那裡",
+ "home.undo_failed": "無法將 {0} 移到資源回收筒/垃圾桶:{1}",
"donut.center_drag": "把檔案拖到這裡",
"donut.files_same": "{0} 個 {1}",
@@ -125,6 +130,7 @@
"trash.no_folder": "沒有垃圾桶資料夾",
"trash.failed": "無法移到資源回收筒/垃圾桶",
"trash.cannot_place": "無法將結果儲存到原始檔案所在的資料夾",
+ "trash.changed": "轉換後已被修改",
"notice.empty_spreadsheet_pages_removed": "已移除試算表中的空白頁面",
"notice.ocr_has_text": "每頁都已有文字,已原樣複製",
"notice.live_photo_pair": "已儲存為同名的照片和 MOV。將兩者一起匯入(iCloud 照片、隔空投送或 Mac 上的「照片」)即可得到原況照片",
diff --git a/src/Filee.App/Styles/Icons.axaml b/src/Filee.App/Styles/Icons.axaml
index 21ca4ad7..c8c0588b 100644
--- a/src/Filee.App/Styles/Icons.axaml
+++ b/src/Filee.App/Styles/Icons.axaml
@@ -33,6 +33,7 @@
M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2ZM12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35ZM17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z
+ M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8ZM12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,7A5,5 0 0,1 17,12A5,5 0 0,1 12,17A5,5 0 0,1 7,12A5,5 0 0,1 12,7ZM7,17V1H5V5H1V7H5V17A2,2 0 0,0 7,19H17V23H19V19H23V17M17,15H19V7C19,5.89 18.1,5 17,5H9V7H17V15ZM9.64,7.64C9.87,7.14 10,6.59 10,6A4,4 0 0,0 6,2A4,4 0 0,0 2,6A4,4 0 0,0 6,10C6.59,10 7.14,9.87 7.64,9.64L10,12L7.64,14.36C7.14,14.13 6.59,14 6,14A4,4 0 0,0 2,18A4,4 0 0,0 6,22A4,4 0 0,0 10,18C10,17.41 9.87,16.86 9.64,16.36L12,14L19,21H22V20L9.64,7.64M6,8A2,2 0 0,1 4,6A2,2 0 0,1 6,4A2,2 0 0,1 8,6A2,2 0 0,1 6,8M6,20A2,2 0 0,1 4,18A2,2 0 0,1 6,16A2,2 0 0,1 8,18A2,2 0 0,1 6,20M19,3L13,9L15,11L22,4V3H19Z
diff --git a/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs b/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
index 447facf1..663c6bfd 100644
--- a/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
+++ b/src/Filee.App/ViewModels/Pages/HomePageViewModel.cs
@@ -18,17 +18,22 @@ namespace Filee.App.ViewModels.Pages;
public sealed partial class HistoryItemViewModel : ObservableObject
{
private readonly HistoryEntry _entry;
+ private readonly ILocalizer _loc;
private readonly IPlatformServices _platform;
private readonly ConversionService? _conversions;
+ private readonly UserDataStore? _store;
/// The first output still on disk (the one the buttons open), or null.
private readonly string? _output;
- public HistoryItemViewModel(HistoryEntry entry, ILocalizer loc, IPlatformServices platform, ConversionService? conversions = null)
+ public HistoryItemViewModel(HistoryEntry entry, ILocalizer loc, IPlatformServices platform, ConversionService? conversions = null,
+ UserDataStore? store = null)
{
_entry = entry;
+ _loc = loc;
_platform = platform;
_conversions = conversions;
+ _store = store;
Title = entry.PresetName;
Subtitle = entry.Sources.Count == 1 ? Path.GetFileName(entry.Sources[0]) : loc.Format("home.files", entry.Sources.Count);
Time = entry.FinishedAt.Date == DateTime.Today ? entry.FinishedAt.ToString("t") : entry.FinishedAt.ToString("d");
@@ -52,8 +57,17 @@ public HistoryItemViewModel(HistoryEntry entry, ILocalizer loc, IPlatformService
ThumbnailSource = picture is not null && HistoryThumbnails.CanShow(picture) ? picture : null;
// Only entries that remember their preset (Filee 1.8 and later) and still have a failed file to convert.
CanRetry = conversions is not null && entry.Preset is not null && entry.Failures.Any(f => ConversionService.Exists(f.Source));
+ CanUndo = store is not null && UndoLeft();
+ UndoneText = entry.Undone ? loc[entry.OriginalsInTrash ? "home.undone_original" : "home.undone"] : "";
}
+ ///
+ /// Undo (#553) is offered while the results not moved yet are all as the job left them, so a file changed since is
+ /// never moved; after an Undo that stopped half-way, for the ones it didn't get to.
+ ///
+ private bool UndoLeft() =>
+ !_entry.Undone && _entry.Undoable.Where(o => !o.Trashed).ToList() is { Count: > 0 } left && left.All(o => o.Unchanged());
+
public string Title { get; }
public string Subtitle { get; }
public string Time { get; }
@@ -101,6 +115,62 @@ private void Retry()
_conversions.Retry(_entry.Failures.Select(f => f.Source), _entry.Preset, _entry.WatchRuleId);
}
+ [ObservableProperty] private bool _canUndo;
+
+ /// "Undone: the results are in the Recycle Bin / Trash", or empty.
+ public string UndoneText { get; }
+
+ public bool IsUndone => UndoneText.Length > 0;
+
+ /// Why a result couldn't be moved to the Recycle Bin / Trash, or empty.
+ [ObservableProperty, NotifyPropertyChangedFor(nameof(HasUndoError))] private string _undoError = "";
+
+ public bool HasUndoError => UndoError.Length > 0;
+
+ ///
+ /// Moves the job's results to the Recycle Bin / Trash, off the UI thread (Windows' Recycle Bin takes a moment per
+ /// file); the button is disabled meanwhile. Every result is checked first, so a changed one stops it with nothing
+ /// moved. Each result moved is saved as such, so an Undo the Trash stops half-way can be tried again for the rest.
+ /// "Replace the original" sent the originals there already: they stay, and the card says so.
+ ///
+ [RelayCommand]
+ private async Task UndoAsync()
+ {
+ if (!CanUndo || _store is null)
+ return;
+ UndoError = "";
+ var left = _entry.Undoable.Where(o => !o.Trashed).ToList();
+ if (left.FirstOrDefault(o => !o.Unchanged()) is { } changed)
+ {
+ Refused(changed, new TrashRefusal("trash.changed"));
+ return;
+ }
+ var refused = await Task.Run(() =>
+ {
+ foreach (var output in left)
+ {
+ if (_platform.MoveToTrash(output.Path) is { } refusal)
+ return (output, refusal);
+ output.Trashed = true;
+ }
+ return default((HistoryOutput, TrashRefusal)?);
+ });
+ if (refused is { } stop)
+ {
+ _store.SaveHistory(notify: false); // the moved ones stay moved; this card says why it stopped
+ Refused(stop.Item1, stop.Item2);
+ return;
+ }
+ _entry.Undone = true;
+ _store.SaveHistory();
+ }
+
+ private void Refused(HistoryOutput output, TrashRefusal refusal)
+ {
+ UndoError = _loc.Format("home.undo_failed", Path.GetFileName(output.Path), _loc[refusal.ReasonKey]);
+ CanUndo = UndoLeft();
+ }
+
[RelayCommand]
private void OpenFolder()
{
@@ -223,7 +293,7 @@ private void Reload()
.ToList();
History.Clear();
foreach (var entry in entries)
- History.Add(new HistoryItemViewModel(entry, _loc, _platform, _conversions));
+ History.Add(new HistoryItemViewModel(entry, _loc, _platform, _conversions, _store));
IsEmpty = _store.History.Count == 0;
NoMatches = !IsEmpty && History.Count == 0;
LoadThumbnails();
diff --git a/src/Filee.App/Views/Pages/HomePage.axaml b/src/Filee.App/Views/Pages/HomePage.axaml
index a83a3d28..aae555da 100644
--- a/src/Filee.App/Views/Pages/HomePage.axaml
+++ b/src/Filee.App/Views/Pages/HomePage.axaml
@@ -113,6 +113,13 @@
+
+
@@ -156,6 +163,9 @@
+
+
+