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.).
This commit is contained in:
2026-04-03 18:17:29 +09:00
parent a0ef69e8ea
commit 9391e868a2
3 changed files with 139 additions and 91 deletions
@@ -19,27 +19,22 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
{ {
private bool _isPerformingInitialLoad; private bool _isPerformingInitialLoad;
private string _processDir; private string _processDir;
private string _programLog;
private bool _isCreatingPDF; private bool _isCreatingPDF;
private string _programLog = "";
private string _workingFolder;
private string _reportTitle; private PDFReport _pdfReport;
private ObservableCollection<ReportFile> _reportFiles;
private DateTime? _lastGeneratedTime;
private Settings _settings; private Settings _settings;
private bool _hasUnsavedWork; private bool _hasUnsavedWork;
private CreatePDFReportViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger) private CreatePDFReportViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger)
{ {
_pdfReport = new PDFReport();
_processDir = Path.GetDirectoryName(Environment.ProcessPath) ?? ""; _processDir = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
Console.WriteLine("Internal storage directory is: {0}", Utilities.GetInternalDataPath()); Console.WriteLine("Internal storage directory is: {0}", Utilities.GetInternalDataPath());
_isCreatingPDF = false; _isCreatingPDF = false;
_workingFolder = ""; ReportFiles = [];
ReportFiles = _reportFiles = new ObservableCollection<ReportFile>(); _programLog = "";
_reportTitle = "";
_lastGeneratedTime = null;
_settings = Settings.LoadSettings(); // TODO: needs tweaking _settings = Settings.LoadSettings(); // TODO: needs tweaking
HasUnsavedWork = false; HasUnsavedWork = false;
// setup initial quote and program log data // setup initial quote and program log data
@@ -91,24 +86,12 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
_isPerformingInitialLoad = false; _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 public string ReportTitle
{ {
get => _reportTitle; get => _pdfReport.Title;
set set
{ {
_reportTitle = value; _pdfReport.Title = value;
NotifyPropertyChanged(); NotifyPropertyChanged();
NotifyPropertyChanged(nameof(IsTitleBoxVisible)); NotifyPropertyChanged(nameof(IsTitleBoxVisible));
NotifyPropertyChanged(nameof(CanAddItem)); NotifyPropertyChanged(nameof(CanAddItem));
@@ -140,7 +123,7 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
public bool IsCreatePDFButtonEnabled public bool IsCreatePDFButtonEnabled
{ {
get => !_isCreatingPDF && _reportFiles.Count > 0; get => !_isCreatingPDF && _pdfReport.Files.Count > 0;
} }
public bool HasWorkingFolder public bool HasWorkingFolder
@@ -155,10 +138,20 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
public string WorkingFolder public string WorkingFolder
{ {
get => _workingFolder; get
{
if (string.IsNullOrWhiteSpace(_pdfReport.BaseFolder))
{
return Path.Combine(Utilities.GetInternalDataPath(), _pdfReport.UUID);
}
else
{
return _pdfReport.BaseFolder;
}
}
set set
{ {
_workingFolder = value; _pdfReport.BaseFolder = value;
NotifyPropertyChanged(); NotifyPropertyChanged();
NotifyPropertyChanged(nameof(HasWorkingFolder)); NotifyPropertyChanged(nameof(HasWorkingFolder));
NotifyPropertyChanged(nameof(HasWorkingFolderAndNotMakingPDF)); NotifyPropertyChanged(nameof(HasWorkingFolderAndNotMakingPDF));
@@ -183,12 +176,12 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
public ObservableCollection<ReportFile> ReportFiles public ObservableCollection<ReportFile> ReportFiles
{ {
get => _reportFiles; get => _pdfReport.Files;
set set
{ {
_reportFiles = value; _pdfReport.Files = value;
NotifyPropertyChanged(); NotifyPropertyChanged();
_reportFiles.CollectionChanged += ( sender, e ) => _pdfReport.Files.CollectionChanged += ( sender, e ) =>
{ {
NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled));
HasUnsavedWork = true; 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) public void LogInfo(string message, params object[]? arguments)
{ {
var timestamp = string.Format("[{0:s}]", DateTime.Now); 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) 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(); 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 uuid = "";
var potentialPath = ""; 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 // 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) // (if we ever implement a more robust report system where we keep all files)
Directory.CreateDirectory(potentialPath); Directory.CreateDirectory(potentialPath);
_settings.WorkingFolderToInternalFolderName[folderPath] = uuid; _settings.WorkingFolderToInternalFolderName[workingFolder] = uuid;
_settings.SaveSettingsNotAsync(); // save new key/value pair _settings.SaveSettingsNotAsync(); // save new key/value pair
} }
return Path.Combine( return Path.Combine(
internalPath, internalPath,
_settings.WorkingFolderToInternalFolderName[folderPath], _settings.WorkingFolderToInternalFolderName[workingFolder],
Constants.ReportSavedDataFileName Constants.ReportSavedDataFileName
); );
} }
else 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<ReportFile>(report.Files); ReportFiles = new ObservableCollection<ReportFile>(report.Files);
ReportTitle = report.Title; ReportTitle = report.Title;
WorkingFolder = report.BaseFolder ?? ""; WorkingFolder = report.BaseFolder ?? "";
_lastGeneratedTime = report.LastGenerated ?? null; _pdfReport.LastGenerated = report.LastGenerated ?? null;
LogInfo("Reloaded report last saved at {0}", report.LastSaved); LogInfo("Reloaded report last saved at {0}", report.LastSaved ?? DateTime.Now);
successfullyLoadedPriorReport = true; successfullyLoadedPriorReport = true;
} }
} }
@@ -555,15 +589,15 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
public async Task SaveInterimReportInfo() public async Task SaveInterimReportInfo()
{ {
var report = new PDFReport() _pdfReport.LastSaved = DateTime.Now;
{ await SavePDFReportDataToDisk(_pdfReport);
Title = ReportTitle, }
Files = ReportFiles.ToList(),
BaseFolder = WorkingFolder, private async Task CreateAndSaveReportObjectAfterReportCreation()
LastSaved = DateTime.Now, {
LastGenerated = _lastGeneratedTime, _pdfReport.LastSaved = DateTime.Now;
}; _pdfReport.LastGenerated = DateTime.Now;
await SavePDFReportDataToDisk(report); await SavePDFReportDataToDisk(_pdfReport);
} }
private async Task SavePDFReportDataToDisk(PDFReport report) private async Task SavePDFReportDataToDisk(PDFReport report)
@@ -580,20 +614,6 @@ class CreatePDFReportViewModel : BaseViewModel, ICanCheckShutdown, ILogger
HasUnsavedWork = false; 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 // called from UI button
public async Task CopyLogToClipboard() public async Task CopyLogToClipboard()
{ {
@@ -10,6 +10,7 @@ using MayShow.Helpers;
using MayShows.Helpers; using MayShows.Helpers;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Platform.Storage;
namespace MayShow.ViewModels; namespace MayShow.ViewModels;
@@ -43,48 +44,60 @@ class StartNewChooseReportViewModel : BaseViewModel, ICanCheckShutdown
set { _savedReports = value; NotifyPropertyChanged(); } 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)) if (string.IsNullOrWhiteSpace(CreatingReportTitle))
{ {
await DialogHost.Show(new WarningViewModel("Report title cannot be blank!")); await DialogHost.Show(new WarningViewModel("Report title cannot be blank!"));
return; return;
} }
// TODO: if report with name already exists in system, error
var reportInfo = new PDFReportInfo() var reportInfo = new PDFReportInfo()
{ {
Title = CreatingReportTitle, Title = CreatingReportTitle,
LastSaved = DateTime.Now LastSaved = null,
UUID = Utilities.GetUniqueReportGuid(_settings).ToString()
}; };
// create folder for report data reportInfo.BaseFolder = Path.Combine(Utilities.GetInternalDataPath(), reportInfo.UUID); // default to internal directory
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);
// ... this sort and save is slow, technically, but we're not going to have millions of items here, so... // ... this sort and save is slow, technically, but we're not going to have millions of items here, so...
SavedReports = new ObservableCollection<PDFReportInfo>(_settings.AllReportInfo.OrderBy(x => x.Title)); // TODO: save automatically only if mobile; desktop only saves on command
await _settings.SaveSettingsAsync(); // SavedReports = new ObservableCollection<PDFReportInfo>(_settings.AllReportInfo.OrderBy(x => x.Title));
// await _settings.SaveSettingsAsync();
// now update UI // now update UI
ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger) ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger));
{
ReportTitle = CreatingReportTitle
});
CreatingReportTitle = ""; // when user comes back they can start another new report 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 LoadExistingReport(object info) => LoadExistingReportImpl((PDFReportInfo) info);
public void LoadExistingReportImpl(PDFReportInfo reportInfo) public void LoadExistingReportImpl(PDFReportInfo reportInfo)
{ {
// TODO: load data and send to create PDF report view model ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger));
ViewModelChanger.PushViewModel(new CreatePDFReportViewModel(reportInfo, ViewModelChanger)
{
ReportTitle = CreatingReportTitle
});
} }
public void DeleteExistingReport(object info) => DeleteExistingReportImpl((PDFReportInfo) info); public void DeleteExistingReport(object info) => DeleteExistingReportImpl((PDFReportInfo) info);
@@ -11,7 +11,7 @@
xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia" xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia"
x:DataType="vm:StartNewChooseReportViewModel"> x:DataType="vm:StartNewChooseReportViewModel">
<Grid ColumnDefinitions="100, *, 100" <Grid ColumnDefinitions="100, *, 100"
RowDefinitions="Auto, Auto, Auto, Auto, Auto, *"> RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto, Auto, *">
<TextBlock HorizontalAlignment="Center" <TextBlock HorizontalAlignment="Center"
FontSize="36" FontSize="36"
FontWeight="Bold" FontWeight="Bold"
@@ -28,7 +28,7 @@
Grid.Row="1" /> Grid.Row="1" />
<Label Content="Start New Report" <Label Content="Start New Report"
HorizontalAlignment="Left" HorizontalAlignment="Left"
FontSize="18" FontSize="16"
FontWeight="Bold" FontWeight="Bold"
Margin="0,24,0,0" Margin="0,24,0,0"
Grid.Column="1" Grid.Column="1"
@@ -51,19 +51,34 @@
Grid.Column="1"> Grid.Column="1">
<TextBlock> <TextBlock>
<Run Text="&#xe494;" <Run Text="&#xe494;"
FontFamily="{StaticResource FontAwesomeSolid}" /> Create and Start Report</TextBlock> FontFamily="{StaticResource FontAwesomeSolid}" /> Create Blank Report</TextBlock>
</Button> </Button>
</Grid> </Grid>
<Label Content="Load Existing Report" <Label Content="Start New Report From Existing Files"
FontSize="18" HorizontalAlignment="Left"
FontSize="16"
FontWeight="Bold"
Margin="0,8,0,0"
Grid.Column="1"
Grid.Row="4"/>
<Button Command="{Binding StartReportFromFolder}"
Classes="accent"
Grid.Row="5"
Grid.Column="1">
<TextBlock>
<Run Text="&#xe494;"
FontFamily="{StaticResource FontAwesomeSolid}" /> Create Report from Existing Folder</TextBlock>
</Button>
<Label Content="Load Previously Saved Report"
FontSize="16"
FontWeight="Bold" FontWeight="Bold"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="0,16,0,0" Margin="0,16,0,0"
Grid.Column="1" Grid.Column="1"
Grid.Row="4"/> Grid.Row="6"/>
<ScrollViewer Margin="0,8,0,32" <ScrollViewer Margin="0,8,0,32"
Grid.Column="1" Grid.Column="1"
Grid.Row="5" Grid.Row="7"
VerticalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"
AllowAutoHide="False" AllowAutoHide="False"
HorizontalScrollBarVisibility="Disabled"> HorizontalScrollBarVisibility="Disabled">