WIP: Add iOS version #10
@@ -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<ReportFile> _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<ReportFile>();
|
||||
_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<ReportFile> 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<ReportFile>(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()
|
||||
_pdfReport.LastSaved = DateTime.Now;
|
||||
await SavePDFReportDataToDisk(_pdfReport);
|
||||
}
|
||||
|
||||
private async Task CreateAndSaveReportObjectAfterReportCreation()
|
||||
{
|
||||
Title = ReportTitle,
|
||||
Files = ReportFiles.ToList(),
|
||||
BaseFolder = WorkingFolder,
|
||||
LastSaved = DateTime.Now,
|
||||
LastGenerated = _lastGeneratedTime,
|
||||
};
|
||||
await SavePDFReportDataToDisk(report);
|
||||
_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()
|
||||
{
|
||||
|
||||
@@ -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<PDFReportInfo>(_settings.AllReportInfo.OrderBy(x => x.Title));
|
||||
await _settings.SaveSettingsAsync();
|
||||
// TODO: save automatically only if mobile; desktop only saves on command
|
||||
// SavedReports = new ObservableCollection<PDFReportInfo>(_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);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia"
|
||||
x:DataType="vm:StartNewChooseReportViewModel">
|
||||
<Grid ColumnDefinitions="100, *, 100"
|
||||
RowDefinitions="Auto, Auto, Auto, Auto, Auto, *">
|
||||
RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto, Auto, *">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
FontSize="36"
|
||||
FontWeight="Bold"
|
||||
@@ -28,7 +28,7 @@
|
||||
Grid.Row="1" />
|
||||
<Label Content="Start New Report"
|
||||
HorizontalAlignment="Left"
|
||||
FontSize="18"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
Margin="0,24,0,0"
|
||||
Grid.Column="1"
|
||||
@@ -51,19 +51,34 @@
|
||||
Grid.Column="1">
|
||||
<TextBlock>
|
||||
<Run Text=""
|
||||
FontFamily="{StaticResource FontAwesomeSolid}" /> Create and Start Report</TextBlock>
|
||||
FontFamily="{StaticResource FontAwesomeSolid}" /> Create Blank Report</TextBlock>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Label Content="Load Existing Report"
|
||||
FontSize="18"
|
||||
<Label Content="Start New Report From Existing Files"
|
||||
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=""
|
||||
FontFamily="{StaticResource FontAwesomeSolid}" /> Create Report from Existing Folder</TextBlock>
|
||||
</Button>
|
||||
<Label Content="Load Previously Saved Report"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,16,0,0"
|
||||
Grid.Column="1"
|
||||
Grid.Row="4"/>
|
||||
Grid.Row="6"/>
|
||||
<ScrollViewer Margin="0,8,0,32"
|
||||
Grid.Column="1"
|
||||
Grid.Row="5"
|
||||
Grid.Row="7"
|
||||
VerticalScrollBarVisibility="Visible"
|
||||
AllowAutoHide="False"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
|
||||
Reference in New Issue
Block a user