Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "مجلد الملف الأصلي نفسه",
"presets.location.Subfolder": "مجلد فرعي",
"presets.location.CustomFolder": "مجلد ثابت",
"presets.location.Ask": "السؤال في كل مرة",
"ask.save_title": "حفظ النتيجة باسم",
"ask.folder_title": "اختر مكان حفظ النتائج",
"presets.subfolder": "اسم المجلد الفرعي",
"presets.subfolder_only_several": "فقط عندما ينتج أكثر من ملف",
"presets.subfolder_only_several_hint": "إذا نتج عن التحويل ملف واحد فإنه يُحفظ بجانب الأصل؛ ولا يُنشأ المجلد الفرعي إلا عندما ينتج عدة ملفات (مثل تقسيم PDF إلى صفحات).",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "Gleicher Ordner wie die Quelldatei",
"presets.location.Subfolder": "Unterordner",
"presets.location.CustomFolder": "Fester Ordner",
"presets.location.Ask": "Jedes Mal fragen",
"ask.save_title": "Ergebnis speichern unter",
"ask.folder_title": "Wählen Sie, wo die Ergebnisse gespeichert werden",
"presets.subfolder": "Name des Unterordners",
"presets.subfolder_only_several": "Nur wenn aus einer Datei mehrere werden",
"presets.subfolder_only_several_hint": "Wird eine Datei in eine einzelne Datei konvertiert, wird diese neben dem Original gespeichert. Nur wenn mehrere Dateien entstehen (etwa einzelne PDF-Seiten), wird der Unterordner verwendet.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "Same folder as the source",
"presets.location.Subfolder": "A subfolder",
"presets.location.CustomFolder": "A fixed folder",
"presets.location.Ask": "Ask every time",
"ask.save_title": "Save the result as",
"ask.folder_title": "Choose where to save the results",
"presets.subfolder": "Subfolder name",
"presets.subfolder_only_several": "Only when a file becomes several",
"presets.subfolder_only_several_hint": "A file converted to one file is saved next to the original; only one that becomes several files (a PDF split into pages) gets the subfolder.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "La misma carpeta que el original",
"presets.location.Subfolder": "Una subcarpeta",
"presets.location.CustomFolder": "Una carpeta fija",
"presets.location.Ask": "Preguntar cada vez",
"ask.save_title": "Guardar el resultado como",
"ask.folder_title": "Elige dónde guardar los resultados",
"presets.subfolder": "Nombre de la subcarpeta",
"presets.subfolder_only_several": "Solo si salen varios archivos",
"presets.subfolder_only_several_hint": "Si un archivo se convierte en uno solo, se guarda junto al original; la subcarpeta solo se crea cuando salen varios archivos (un PDF dividido en páginas).",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "Même dossier que l'original",
"presets.location.Subfolder": "Un sous-dossier",
"presets.location.CustomFolder": "Un dossier fixe",
"presets.location.Ask": "Demander à chaque fois",
"ask.save_title": "Enregistrer le résultat sous",
"ask.folder_title": "Choisissez où enregistrer les résultats",
"presets.subfolder": "Nom du sous-dossier",
"presets.subfolder_only_several": "Seulement si un fichier en produit plusieurs",
"presets.subfolder_only_several_hint": "Un fichier converti en un seul fichier est enregistré à côté de l'original ; seul celui qui en produit plusieurs (un PDF découpé en pages) va dans le sous-dossier.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "स्रोत वाला ही फ़ोल्डर",
"presets.location.Subfolder": "एक सबफ़ोल्डर",
"presets.location.CustomFolder": "एक तय फ़ोल्डर",
"presets.location.Ask": "हर बार पूछें",
"ask.save_title": "परिणाम को इस रूप में सहेजें",
"ask.folder_title": "चुनें कि परिणाम कहाँ सहेजे जाएँ",
"presets.subfolder": "सबफ़ोल्डर का नाम",
"presets.subfolder_only_several": "सिर्फ़ तब, जब कई फ़ाइलें बनें",
"presets.subfolder_only_several_hint": "एक फ़ाइल बनने पर वह मूल फ़ाइल के पास सेव होती है; सबफ़ोल्डर सिर्फ़ तब बनता है जब कई फ़ाइलें बनें (जैसे PDF को पेजों में बाँटने पर)।",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "元ファイルと同じフォルダー",
"presets.location.Subfolder": "サブフォルダー",
"presets.location.CustomFolder": "指定したフォルダー",
"presets.location.Ask": "毎回確認する",
"ask.save_title": "変換結果を保存",
"ask.folder_title": "変換結果の保存先を選択",
"presets.subfolder": "サブフォルダー名",
"presets.subfolder_only_several": "複数のファイルになるときだけ",
"presets.subfolder_only_several_hint": "1つのファイルに変換されたときは元のファイルの隣に保存し、複数のファイルになるとき(PDFをページごとに分けるときなど)だけサブフォルダーを作ります。",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "원본과 같은 폴더",
"presets.location.Subfolder": "하위 폴더",
"presets.location.CustomFolder": "지정한 폴더",
"presets.location.Ask": "매번 묻기",
"ask.save_title": "결과를 다른 이름으로 저장",
"ask.folder_title": "결과를 저장할 곳을 고르세요",
"presets.subfolder": "하위 폴더 이름",
"presets.subfolder_only_several": "여러 파일이 될 때만",
"presets.subfolder_only_several_hint": "한 파일로 변환되면 원본 옆에 저장하고, 여러 파일이 될 때(PDF를 페이지별로 나눌 때 등)만 하위 폴더를 만듭니다.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/ne.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "स्रोत जस्तै उही फोल्डर",
"presets.location.Subfolder": "एउटा सबफोल्डर",
"presets.location.CustomFolder": "एउटा निश्चित फोल्डर",
"presets.location.Ask": "हरेक पटक सोध्नुहोस्",
"ask.save_title": "नतिजालाई यस रूपमा सेभ गर्नुहोस्",
"ask.folder_title": "नतिजाहरू कहाँ सेभ गर्ने छान्नुहोस्",
"presets.subfolder": "सबफोल्डर नाम",
"presets.subfolder_only_several": "धेरै फाइलहरू बन्दा मात्र",
"presets.subfolder_only_several_hint": "एउटा फाइल रूपान्तरण हुँदा मूल फाइलकै छेउमा सुरक्षित हुन्छ; धेरै फाइलहरू बन्दा मात्र सबफोल्डर बन्छ (जस्तै पृष्ठहरूमा विभाजित गरिएको PDF)।",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "Ten sam folder co źródło",
"presets.location.Subfolder": "Podfolder",
"presets.location.CustomFolder": "Stały folder",
"presets.location.Ask": "Pytaj za każdym razem",
"ask.save_title": "Zapisz wynik jako",
"ask.folder_title": "Wybierz, gdzie zapisać wyniki",
"presets.subfolder": "Nazwa podfolderu",
"presets.subfolder_only_several": "Tylko gdy powstaje kilka plików",
"presets.subfolder_only_several_hint": "Plik przekonwertowany na jeden plik zostaje zapisany obok oryginału; podfolder powstaje tylko wtedy, gdy powstaje kilka plików (PDF podzielony na strony).",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "A mesma pasta da origem",
"presets.location.Subfolder": "Uma subpasta",
"presets.location.CustomFolder": "Uma pasta fixa",
"presets.location.Ask": "Perguntar sempre",
"ask.save_title": "Salvar o resultado como",
"ask.folder_title": "Escolha onde salvar os resultados",
"presets.subfolder": "Nome da subpasta",
"presets.subfolder_only_several": "Só quando um arquivo vira vários",
"presets.subfolder_only_several_hint": "Um arquivo convertido em um único arquivo é salvo ao lado do original; só um que vira vários arquivos (um PDF dividido em páginas) vai para a subpasta.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "Mesma pasta da origem",
"presets.location.Subfolder": "Uma subpasta",
"presets.location.CustomFolder": "Uma pasta fixa",
"presets.location.Ask": "Perguntar sempre",
"ask.save_title": "Guardar o resultado como",
"ask.folder_title": "Escolha onde guardar os resultados",
"presets.subfolder": "Nome da subpasta",
"presets.subfolder_only_several": "Só se resultar em vários ficheiros",
"presets.subfolder_only_several_hint": "Se a conversão gerar um só ficheiro, este é guardado junto ao original. A subpasta só é criada quando gerar vários ficheiros (por exemplo, ao dividir um PDF em páginas).",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "В ту же папку, что исходник",
"presets.location.Subfolder": "Во вложенную папку",
"presets.location.CustomFolder": "В заданную папку",
"presets.location.Ask": "Спрашивать каждый раз",
"ask.save_title": "Сохранить результат как",
"ask.folder_title": "Выберите, куда сохранить результаты",
"presets.subfolder": "Имя вложенной папки",
"presets.subfolder_only_several": "Только если файлов получается несколько",
"presets.subfolder_only_several_hint": "Если из файла получается один файл, он сохраняется рядом с оригиналом; вложенная папка создаётся, только когда файлов несколько (например, PDF разбит на страницы).",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/th.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "โฟลเดอร์เดียวกับต้นฉบับ",
"presets.location.Subfolder": "โฟลเดอร์ย่อย",
"presets.location.CustomFolder": "โฟลเดอร์ที่กำหนดเอง",
"presets.location.Ask": "ถามทุกครั้ง",
"ask.save_title": "บันทึกผลลัพธ์เป็น",
"ask.folder_title": "เลือกที่บันทึกผลลัพธ์",
"presets.subfolder": "ชื่อโฟลเดอร์ย่อย",
"presets.subfolder_only_several": "เฉพาะเมื่อหนึ่งไฟล์แยกเป็นหลายไฟล์",
"presets.subfolder_only_several_hint": "ไฟล์ที่แปลงแล้วได้ไฟล์เดียวจะบันทึกข้างไฟล์ต้นฉบับ มีเฉพาะไฟล์ที่แตกออกเป็นหลายไฟล์ (เช่น PDF ที่แยกหน้า) ที่จะบันทึกลงในโฟลเดอร์ย่อย",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,9 @@
"presets.location.SameFolder": "Kaynakla aynı klasör",
"presets.location.Subfolder": "Alt klasör",
"presets.location.CustomFolder": "Sabit klasör",
"presets.location.Ask": "Her seferinde sor",
"ask.save_title": "Sonucu farklı kaydet",
"ask.folder_title": "Sonuçların kaydedileceği yeri seçin",
"presets.subfolder": "Alt klasör adı",
"presets.subfolder_only_several": "Yalnızca tek dosya birden fazla dosyaya dönüşürse",
"presets.subfolder_only_several_hint": "Tek dosyaya dönüştürülen dosya özgünün yanına kaydedilir; yalnızca birkaç dosyaya dönüşenler (sayfalara bölünen PDF gibi) alt klasöre kaydedilir.",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "与源文件相同的文件夹",
"presets.location.Subfolder": "子文件夹",
"presets.location.CustomFolder": "指定文件夹",
"presets.location.Ask": "每次询问",
"ask.save_title": "将结果另存为",
"ask.folder_title": "选择结果的保存位置",
"presets.subfolder": "子文件夹名称",
"presets.subfolder_only_several": "仅在生成多个文件时",
"presets.subfolder_only_several_hint": "只生成一个文件时保存在原文件旁边,生成多个文件时(例如 PDF 拆分成页面)才新建子文件夹。",
Expand Down
3 changes: 3 additions & 0 deletions src/Filee.App/Assets/i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,9 @@
"presets.location.SameFolder": "與來源檔案相同的資料夾",
"presets.location.Subfolder": "子資料夾",
"presets.location.CustomFolder": "指定資料夾",
"presets.location.Ask": "每次詢問",
"ask.save_title": "將結果另存為",
"ask.folder_title": "選擇結果的儲存位置",
"presets.subfolder": "子資料夾名稱",
"presets.subfolder_only_several": "僅在產生多個檔案時",
"presets.subfolder_only_several_hint": "只產生一個檔案時儲存在原始檔案旁邊,產生多個檔案時(例如 PDF 拆分成頁面)才新增子資料夾。",
Expand Down
31 changes: 30 additions & 1 deletion src/Filee.App/Services/RadialController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,15 @@ private void Convert(int index, int sub, IReadOnlyList<string> files, WebDrop? w
return;
}

// "Ask every time" (#521): the save dialog first; the toast shows the job, the donut has closed for the dialog.
// shortcut: files from a browser aren't asked about, they save into the download folder as "next to the source".
if (preset.Output.AskEveryTime && web is null)
{
Close(animate: false);
_ = AskThenConvertAsync(sources, preset);
return;
}

log.LogInformation("Converting {Count} file(s) with preset {Preset}{Web}", sources.Count, preset.Id,
web is null ? "" : " (from a browser)");
var job = conversions.Start(sources, preset, showInToast: false, web);
Expand All @@ -363,7 +372,9 @@ private async Task MergeInOrderAsync(IReadOnlyList<string> files, Preset preset,
try
{
var ordered = await windows.ChooseMergeOrderAsync(files);
if (ordered is not null)
if (ordered is not null && preset.Output.AskEveryTime && web is null)
await AskThenConvertAsync(ordered, preset);
else if (ordered is not null)
{
conversions.Start(ordered, preset, web: web);
web = null; // the conversion owns the browser drop now
Expand All @@ -379,6 +390,24 @@ private async Task MergeInOrderAsync(IReadOnlyList<string> files, Preset preset,
}
}

private async Task AskThenConvertAsync(IReadOnlyList<string> sources, Preset preset)
{
try
{
// Asked as it will run (a ZIP from Settings › General is a .zip), for one file or a folder as the job makes them.
var running = store.Settings.WithDefaultOutput(preset);
if (await windows.AskSaveLocationAsync(sources, running, AskedLocation.MakesOneResult(running, sources.Count)) is { } asked)
{
log.LogInformation("Converting {Count} file(s) with preset {Preset} where the user chose", sources.Count, preset.Id);
conversions.Start(sources, asked);
}
}
catch (Exception ex) when (ex is not OutOfMemoryException)
{
log.LogError(ex, "Could not ask where to save");
}
}

/// <summary>A tool (crop, clip) on files from a browser: they are saved first, then it opens on them.</summary>
private async Task ShowToolForBrowserFilesAsync(WebDrop web, Filee.Core.Presets.Preset preset, PixelPoint? near)
{
Expand Down
51 changes: 51 additions & 0 deletions src/Filee.App/Services/WindowService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Platform.Storage;
using Filee.App.ViewModels;
using Filee.App.Views;
using Filee.Core.Conversion;
Expand Down Expand Up @@ -67,6 +68,56 @@ public sealed class WindowService(ILocalizer loc, IServiceProvider services, Mem
return dialog.Result;
}

/// <summary>
/// "Ask every time" (#521): one save dialog for the batch, starting in the first source's folder. One result is
/// saved under a name (<see cref="AskedLocation.ForFile"/>), several go into a folder. Null when cancelled.
/// </summary>
/// <param name="oneResult">The batch makes one file (a single source, or a merge of several).</param>
public async Task<Preset?> AskSaveLocationAsync(IReadOnlyList<string> sources, Preset preset, bool oneResult)
{
// The donut has closed and the main window may be in the tray: a small window of its own owns the dialog.
var host = new Window
{
Width = 1,
Height = 1,
Opacity = 0,
ShowInTaskbar = false,
WindowDecorations = WindowDecorations.None,
WindowStartupLocation = WindowStartupLocation.CenterScreen,
Title = "Filee",
};
host.Show();
try
{
var storage = host.StorageProvider;
var start = await storage.TryGetFolderFromPathAsync(Path.GetDirectoryName(Path.GetFullPath(sources[0]))!);
if (oneResult)
{
var extension = AskedLocation.Extension(preset, sources[0]);
var file = await storage.SaveFilePickerAsync(new Avalonia.Platform.Storage.FilePickerSaveOptions
{
Title = loc["ask.save_title"],
SuggestedStartLocation = start,
SuggestedFileName = AskedLocation.SuggestedName(preset, loc.DisplayName(preset), sources[0]),
DefaultExtension = extension.Length == 0 ? null : extension,
ShowOverwritePrompt = true,
});
return file?.TryGetLocalPath() is { } path ? AskedLocation.ForFile(preset, path) : null;
}
var folders = await storage.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions
{
Title = loc["ask.folder_title"],
SuggestedStartLocation = start,
AllowMultiple = false,
});
return folders.FirstOrDefault()?.TryGetLocalPath() is { } folder ? AskedLocation.ForFolder(preset, folder) : null;
}
finally
{
host.Close();
}
}

public MainWindow? Main => _main;

/// <summary>
Expand Down
Loading