From 9391e868a26a62c6ce98a7ea82a45df2335c126d Mon Sep 17 00:00:00 2001 From: Michael Babienco Date: Fri, 3 Apr 2026 18:17:29 +0900 Subject: [PATCH] Continue tweaking code to work with main menu Main menu now allows start blank, start with existing, and load previous. Going to rework the CreatePDFReportViewModel to basically take that report obj and run with it (scan the folder, etc.). --- .../ViewModels/CreatePDFReportViewModel.cs | 140 ++++++++++-------- .../StartNewChooseReportViewModel.cs | 61 +++++--- .../Views/StartNewChooseReport.axaml | 29 +++- 3 files changed, 139 insertions(+), 91 deletions(-) diff --git a/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs b/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs index 5a86751..b14979d 100644 --- a/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs +++ b/src/MayShow.Shared/ViewModels/CreatePDFReportViewModel.cs @@ -19,27 +19,22 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger { private bool _isPerformingInitialLoad; private string _processDir; + private string _programLog; private bool _isCreatingPDF; - private string _programLog = ""; - private string _workingFolder; - private string _reportTitle; - private ObservableCollection _reportFiles; - private DateTime? _lastGeneratedTime; + private PDFReport _pdfReport; private Settings _settings; - private bool _hasUnsavedWork; private CreatePDFReportViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger) { + _pdfReport = new PDFReport(); _processDir = Path.GetDirectoryName(Environment.ProcessPath) ?? ""; Console.WriteLine("Internal storage directory is: {0}", Utilities.GetInternalDataPath()); _isCreatingPDF = false; - _workingFolder = ""; - ReportFiles = _reportFiles = new ObservableCollection(); - _reportTitle = ""; - _lastGeneratedTime = null; + ReportFiles = []; + _programLog = ""; _settings = Settings.LoadSettings(); // TODO: needs tweaking HasUnsavedWork = false; // setup initial quote and program log data @@ -91,24 +86,12 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger _isPerformingInitialLoad = false; } - private void InitializeProgramLog() - { - var quotes = Constants.GetQuotes(); - var random = new Random(); - var quoteIndex = random.Next(0, quotes.Length); - _programLog = "----- MayShow v" + Constants.AppVersion + " ------" + Environment.NewLine; - _programLog += quotes[quoteIndex] + Environment.NewLine; - _programLog += "---------------------------------------" + Environment.NewLine; - _programLog += "Loaded and ready to create report!" + Environment.NewLine; - _programLog += "Please copy and send this Program Log when reporting any issues with the software."; - } - public string ReportTitle { - get => _reportTitle; + get => _pdfReport.Title; set { - _reportTitle = value; + _pdfReport.Title = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(IsTitleBoxVisible)); NotifyPropertyChanged(nameof(CanAddItem)); @@ -140,7 +123,7 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger public bool IsCreatePDFButtonEnabled { - get => !_isCreatingPDF && _reportFiles.Count > 0; + get => !_isCreatingPDF && _pdfReport.Files.Count > 0; } public bool HasWorkingFolder @@ -155,10 +138,20 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger public string WorkingFolder { - get => _workingFolder; + get + { + if (string.IsNullOrWhiteSpace(_pdfReport.BaseFolder)) + { + return Path.Combine(Utilities.GetInternalDataPath(), _pdfReport.UUID); + } + else + { + return _pdfReport.BaseFolder; + } + } set { - _workingFolder = value; + _pdfReport.BaseFolder = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(HasWorkingFolder)); NotifyPropertyChanged(nameof(HasWorkingFolderAndNotMakingPDF)); @@ -183,12 +176,12 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger public ObservableCollection ReportFiles { - get => _reportFiles; + get => _pdfReport.Files; set { - _reportFiles = value; + _pdfReport.Files = value; NotifyPropertyChanged(); - _reportFiles.CollectionChanged += ( sender, e ) => + _pdfReport.Files.CollectionChanged += ( sender, e ) => { NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); HasUnsavedWork = true; @@ -196,6 +189,18 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger } } + private void InitializeProgramLog() + { + var quotes = Constants.GetQuotes(); + var random = new Random(); + var quoteIndex = random.Next(0, quotes.Length); + _programLog = "----- MayShow v" + Constants.AppVersion + " ------" + Environment.NewLine; + _programLog += quotes[quoteIndex] + Environment.NewLine; + _programLog += "---------------------------------------" + Environment.NewLine; + _programLog += "Loaded and ready to create report!" + Environment.NewLine; + _programLog += "Please copy and send this Program Log when reporting any issues with the software."; + } + public void LogInfo(string message, params object[]? arguments) { var timestamp = string.Format("[{0:s}]", DateTime.Now); @@ -227,12 +232,41 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger } } - private string GetReportSavedDataPath(string folderPath) + private string GetReportSavedDataPath(string workingFolder) { if (_settings.SaveReportJsonDataInInternalDir) { + // TODO: keep thinking through how this is going to work and sync back + // to the main new/load screen and all that. + // cause at this point there may already be a dir...depending on flow... + + // ....... + // basically we need to decide when report data is first saved to disk, + // when a unique UUID is chosen, and how to sync data back to the overall + // settings object so the main menu continues to function. + // and need to get rid of all use of WorkingFolderToInternalFolderName. + // and fix/finish up fixing constructor(s). + // ....... + + // some tmp code follows var internalPath = Utilities.GetInternalDataPath(); - if (!_settings.WorkingFolderToInternalFolderName.ContainsKey(folderPath)) + var didFind = false; + foreach (var report in _settings.AllReportInfo) + { + if (report.UUID == _pdfReport.UUID) + { + didFind = true; + break; + } + } + if (!didFind) + { + var reportPath = Path.Combine(internalPath, _pdfReport.UUID); + Directory.CreateDirectory(reportPath); + } + + // if we already don't know about this working folder, make sure we have a folder for its files. + if (!_settings.WorkingFolderToInternalFolderName.ContainsKey(workingFolder)) { var uuid = ""; var potentialPath = ""; @@ -247,18 +281,18 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger // make internal dir -- using dir so we have option to copy data into dir later if needed // (if we ever implement a more robust report system where we keep all files) Directory.CreateDirectory(potentialPath); - _settings.WorkingFolderToInternalFolderName[folderPath] = uuid; + _settings.WorkingFolderToInternalFolderName[workingFolder] = uuid; _settings.SaveSettingsNotAsync(); // save new key/value pair } return Path.Combine( internalPath, - _settings.WorkingFolderToInternalFolderName[folderPath], + _settings.WorkingFolderToInternalFolderName[workingFolder], Constants.ReportSavedDataFileName ); } else { - return Path.Combine(folderPath, Constants.ReportSavedDataFileName); + return Path.Combine(workingFolder, Constants.ReportSavedDataFileName); } } @@ -283,8 +317,8 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger ReportFiles = new ObservableCollection(report.Files); ReportTitle = report.Title; WorkingFolder = report.BaseFolder ?? ""; - _lastGeneratedTime = report.LastGenerated ?? null; - LogInfo("Reloaded report last saved at {0}", report.LastSaved); + _pdfReport.LastGenerated = report.LastGenerated ?? null; + LogInfo("Reloaded report last saved at {0}", report.LastSaved ?? DateTime.Now); successfullyLoadedPriorReport = true; } } @@ -555,15 +589,15 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger public async Task SaveInterimReportInfo() { - var report = new PDFReport() - { - Title = ReportTitle, - Files = ReportFiles.ToList(), - BaseFolder = WorkingFolder, - LastSaved = DateTime.Now, - LastGenerated = _lastGeneratedTime, - }; - await SavePDFReportDataToDisk(report); + _pdfReport.LastSaved = DateTime.Now; + await SavePDFReportDataToDisk(_pdfReport); + } + + private async Task CreateAndSaveReportObjectAfterReportCreation() + { + _pdfReport.LastSaved = DateTime.Now; + _pdfReport.LastGenerated = DateTime.Now; + await SavePDFReportDataToDisk(_pdfReport); } private async Task SavePDFReportDataToDisk(PDFReport report) @@ -580,20 +614,6 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger HasUnsavedWork = false; } - private async Task CreateAndSaveReportObjectAfterReportCreation() - { - var report = new PDFReport() - { - Title = ReportTitle, - Files = ReportFiles.ToList(), - BaseFolder = WorkingFolder, - LastSaved = DateTime.Now, - LastGenerated = DateTime.Now, - }; - _lastGeneratedTime = DateTime.Now; - await SavePDFReportDataToDisk(report); - } - // called from UI button public async Task CopyLogToClipboard() { diff --git a/src/MayShow.Shared/ViewModels/StartNewChooseReportViewModel.cs b/src/MayShow.Shared/ViewModels/StartNewChooseReportViewModel.cs index 33021de..1f922c6 100644 --- a/src/MayShow.Shared/ViewModels/StartNewChooseReportViewModel.cs +++ b/src/MayShow.Shared/ViewModels/StartNewChooseReportViewModel.cs @@ -10,6 +10,7 @@ using MayShow.Helpers; using MayShows.Helpers; using System; using System.Threading.Tasks; +using Avalonia.Platform.Storage; namespace MayShow.ViewModels; @@ -43,48 +44,60 @@ class StartNewChooseReportViewModel : BaseViewModel, ICanCheckShutdown set { _savedReports = value; NotifyPropertyChanged(); } } - public async void StartReport() + public async void StartReport() // start a new report based on a title alone { if (string.IsNullOrWhiteSpace(CreatingReportTitle)) { await DialogHost.Show(new WarningViewModel("Report title cannot be blank!")); return; } - // TODO: if report with name already exists in system, error var reportInfo = new PDFReportInfo() { Title = CreatingReportTitle, - LastSaved = DateTime.Now + LastSaved = null, + UUID = Utilities.GetUniqueReportGuid(_settings).ToString() }; - // create folder for report data - var path = Path.Combine(Utilities.GetInternalDataPath(), reportInfo.UUID); - while (Directory.Exists(path)) - { - reportInfo.ResetUUID(); - path = Path.Combine(Utilities.GetInternalDataPath(), reportInfo.UUID); - } - Directory.CreateDirectory(path); - reportInfo.BaseFolder = path; // default to internal directory - _settings.AllReportInfo.Add(reportInfo); + reportInfo.BaseFolder = Path.Combine(Utilities.GetInternalDataPath(), reportInfo.UUID); // default to internal directory // ... this sort and save is slow, technically, but we're not going to have millions of items here, so... - SavedReports = new ObservableCollection(_settings.AllReportInfo.OrderBy(x => x.Title)); - await _settings.SaveSettingsAsync(); + // TODO: save automatically only if mobile; desktop only saves on command + // SavedReports = new ObservableCollection(_settings.AllReportInfo.OrderBy(x => x.Title)); + // await _settings.SaveSettingsAsync(); // now update UI - ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger) - { - ReportTitle = CreatingReportTitle - }); + ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger)); CreatingReportTitle = ""; // when user comes back they can start another new report } + public async void StartReportFromFolder() + { + // pick folder, then create new report based on folder + // use folder name as report title for now + var topLevel = TopLevelGrabber?.GetTopLevel(); + if (topLevel is not null) + { + var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions() + { + Title = "Pick a folder of files...", + AllowMultiple = false, + }); + if (folders.Count == 1) + { + var folder = folders[0]; + var reportInfo = new PDFReportInfo() + { + Title = Path.GetDirectoryName(folder.Path.LocalPath) ?? "", + LastSaved = null, + UUID = Utilities.GetUniqueReportGuid(_settings).ToString(), + BaseFolder = folder.Path.LocalPath + }; + ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger)); + } + } + } + public void LoadExistingReport(object info) => LoadExistingReportImpl((PDFReportInfo) info); public void LoadExistingReportImpl(PDFReportInfo reportInfo) { - // TODO: load data and send to create PDF report view model - ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger) - { - ReportTitle = CreatingReportTitle - }); + ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger)); } public void DeleteExistingReport(object info) => DeleteExistingReportImpl((PDFReportInfo) info); diff --git a/src/MayShow.Shared/Views/StartNewChooseReport.axaml b/src/MayShow.Shared/Views/StartNewChooseReport.axaml index dbb9329..d79c81b 100644 --- a/src/MayShow.Shared/Views/StartNewChooseReport.axaml +++ b/src/MayShow.Shared/Views/StartNewChooseReport.axaml @@ -11,7 +11,7 @@ xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia" x:DataType="vm:StartNewChooseReportViewModel"> + RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto, Auto, *"> -