From 004647008fd43233eebaf1907db3029e201ad39c Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 24 Apr 2026 11:50:39 +0900 Subject: [PATCH] Refactor PDF file name logic and error checks --- src/MayShow.Shared/Models/ReportPDFCreator.cs | 29 ++----- .../ViewModels/CreatePDFReportViewModel.cs | 75 +++++++++++-------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/MayShow.Shared/Models/ReportPDFCreator.cs b/src/MayShow.Shared/Models/ReportPDFCreator.cs index 897dcfb..d6b71aa 100644 --- a/src/MayShow.Shared/Models/ReportPDFCreator.cs +++ b/src/MayShow.Shared/Models/ReportPDFCreator.cs @@ -83,7 +83,7 @@ class ReportPDFCreator : ChangeNotifier } // https://forum.pdfsharp.net/viewtopic.php?f=2&t=1025 - public async Task CreatePDF(List reportFiles, string reportTitle, string outputFolderPath, PDFFontResolver fontResolver, Settings appSettings) + public async Task CreatePDF(List reportFiles, string reportTitle, string outputFilePathWithName, PDFFontResolver fontResolver, Settings appSettings) { // setup globals and consts... GlobalFontSettings.FontResolver = fontResolver; @@ -102,23 +102,7 @@ class ReportPDFCreator : ChangeNotifier Width = Unit.FromPoint(2), };; // start making PDF! - var outputFileName = reportTitle + ".pdf"; var convertedDir = Utilities.GetTempConvertedImagesFolderPath(); - var folderName = new DirectoryInfo(outputFolderPath).Name; - if (folderName.Contains('-')) - { - // see if year/month format - var parts = folderName.Split('-'); - if (parts[0].Length == 4 && - parts[1].Length <= 2 && - int.TryParse(parts[0], out int year) && int.TryParse(parts[1], out int month)) - { - outputFileName = string.Format("{0} {1} Receipts.pdf", - CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month), - year); - _logger?.LogInfo("Auto-changed output file name to " + outputFileName); - } - } // create doc and setup initial section (for page characteristics) var pdfDoc = new Document(); var section = pdfDoc.AddSection(); @@ -160,10 +144,12 @@ class ReportPDFCreator : ChangeNotifier // First page only: add report title MakeParagraph(section, reportTitle, true, 16, "TitlePar"); // + var outputFilePathNoName = Path.GetDirectoryName(outputFilePathWithName) ?? Utilities.GetInternalDataPath(); + var outputFileName = Path.GetFileName(outputFilePathWithName); var pdfRenderer = new PdfDocumentRenderer { Document = pdfDoc, - WorkingDirectory = outputFolderPath + WorkingDirectory = outputFilePathNoName }; var hasAddedData = false; for (var i = 0; i < reportFiles.Count; i++) @@ -394,13 +380,12 @@ class ReportPDFCreator : ChangeNotifier pdfRenderer.DocumentRenderer.PrepareDocument(); // needed if you make edits after first PrepareDocument() is called pdfRenderer.RenderDocument(); // actually save to disk now - string outputPDFFilePath = Path.Join(outputFolderPath, outputFileName); _logger?.LogInfo("Saving PDF document to disk..."); - pdfRenderer.PdfDocument.Save(outputPDFFilePath); - _logger?.LogInfo("Finished saving PDF output to: " + outputPDFFilePath); + pdfRenderer.PdfDocument.Save(outputFilePathWithName); + _logger?.LogInfo("Finished saving PDF output to: " + outputFilePathWithName); // clean up converted files data dir Directory.Delete(convertedDir, true); // return output path - return outputPDFFilePath; + return outputFilePathWithName; } } \ No newline at end of file diff --git a/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs b/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs index bdab0e9..24dfc84 100644 --- a/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs +++ b/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs @@ -12,6 +12,7 @@ using MayShow.Models; using System.Collections.Generic; using System.Runtime.InteropServices; using Avalonia.Threading; +using MayShow.Enums; namespace MayShow.ViewModels; @@ -454,7 +455,20 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger { try { - await Task.Run(() => CreatePDF()); + var outputFilePath = await DeterminePDFSaveLocation(); + if (outputFilePath == null) + { + await DialogHost.Show(new WarningViewModel("Error: Output file path could not be determined. Current save location set in settings: " + Enum.GetName(_settings.PDFOutputSaveLocation))); + } + else if (_settings.PDFOutputSaveLocation == PDFSaveLocation.OtherChosenDir && + !Directory.Exists(_settings.OutputPdfDir)) + { + await DialogHost.Show(new WarningViewModel("Error: Output directory not found! Please adjust the application Settings before continuing. Output directory: " + _settings.OutputPdfDir)); + } + else + { + await Task.Run(() => CreatePDF(outputFilePath)); + } } catch (Exception e) { LogInfo("PDF process failed! Reason: " + e.Message); @@ -511,18 +525,15 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger } } - private async Task CreatePDF() + private async Task DeterminePDFSaveLocation() { - IsCreatingPDF = true; - var reportCreator = new ReportPDFCreator(this); - var outputDir = ""; + var fileName = ReportTitle + ".pdf"; switch (_settings.PDFOutputSaveLocation) { - case Enums.PDFSaveLocation.BaseFolder: - outputDir = _pdfReport.BaseFolder; - break; - case Enums.PDFSaveLocation.AlwaysAsk: - await Dispatcher.UIThread.InvokeAsync(async () => + case PDFSaveLocation.BaseFolder: + return Path.Combine(_pdfReport.BaseFolder, fileName); + case PDFSaveLocation.AlwaysAsk: + Func> getSaveFilePath = async () => { var topLevel = TopLevelGrabber?.GetTopLevel(); if (topLevel != null) @@ -539,30 +550,34 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger if (result.File is not null) { var path = result.File.Path.AbsolutePath; - Console.WriteLine(path); // <--- this is what I want + if (!path.EndsWith(".pdf")) + { + // should be fine, but juuuust in case... + path += ".pdf"; + } + // Console.WriteLine(path); + return path; } } - }); - IsCreatingPDF = false; - return; - break; - case Enums.PDFSaveLocation.OtherChosenDir: - outputDir = _settings.OutputPdfDir; - break; + return null; + }; + // must invoke on UI thread because getting file picker + return await Dispatcher.UIThread.InvokeAsync(getSaveFilePath); + case PDFSaveLocation.OtherChosenDir: + return Path.Combine(_settings.OutputPdfDir, fileName); } - // safety checks - if (!Directory.Exists(outputDir)) + return null; + } + + private async Task CreatePDF(string outputFilePath) + { + IsCreatingPDF = true; + var reportCreator = new ReportPDFCreator(this); + var outputPdfFile = await reportCreator.CreatePDF(ReportFiles.ToList(), ReportTitle, outputFilePath, new PDFFontResolver(_processDir, this), _settings); + if (!string.IsNullOrWhiteSpace(outputPdfFile)) { - await DialogHost.Show(new WarningViewModel("Output directory not found! Please adjust your application Settings before continuing. Output directory: " + outputDir)); - } - else - { - var outputPdfFile = await reportCreator.CreatePDF(ReportFiles.ToList(), ReportTitle, outputDir, new PDFFontResolver(_processDir, this), _settings); - if (!string.IsNullOrWhiteSpace(outputPdfFile)) - { - await CreateAndSaveReportObjectAfterReportCreation(); - OpenFolderForFileInFileViewer(outputPdfFile); - } + await CreateAndSaveReportObjectAfterReportCreation(); + OpenFolderForFileInFileViewer(outputPdfFile); } IsCreatingPDF = false; }