Save/load settings, Move about window to dialog
This commit is contained in:
@@ -94,6 +94,9 @@
|
|||||||
<DataTemplate DataType="{x:Type viewModels:EditFileViewModel}">
|
<DataTemplate DataType="{x:Type viewModels:EditFileViewModel}">
|
||||||
<views:EditFile/>
|
<views:EditFile/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type viewModels:AboutViewModel}">
|
||||||
|
<views:AboutView/>
|
||||||
|
</DataTemplate>
|
||||||
</Application.DataTemplates>
|
</Application.DataTemplates>
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
|||||||
+3
-1
@@ -3,7 +3,9 @@ using Avalonia;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using DialogHostAvalonia;
|
||||||
using ReceiptPDFBuilder;
|
using ReceiptPDFBuilder;
|
||||||
|
using ReceiptPDFBuilder.ViewModels;
|
||||||
|
|
||||||
namespace ReceiptPDFBuilder;
|
namespace ReceiptPDFBuilder;
|
||||||
|
|
||||||
@@ -26,6 +28,6 @@ public partial class App : Application
|
|||||||
|
|
||||||
public void AboutOnClick(object? sender, EventArgs args)
|
public void AboutOnClick(object? sender, EventArgs args)
|
||||||
{
|
{
|
||||||
new AboutWindow().Show();
|
DialogHost.Show(new AboutViewModel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
using ReceiptPDFBuilder.Helpers;
|
using ReceiptPDFBuilder.Helpers;
|
||||||
|
|
||||||
namespace ReceiptPDFBuilder.Models;
|
namespace ReceiptPDFBuilder.Models;
|
||||||
@@ -44,6 +45,7 @@ class ReportFile : ChangeNotifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public DateOnly ReceiptDate
|
public DateOnly ReceiptDate
|
||||||
{
|
{
|
||||||
get => DateOnly.FromDateTime(_receiptDateTime);
|
get => DateOnly.FromDateTime(_receiptDateTime);
|
||||||
@@ -61,6 +63,7 @@ class ReportFile : ChangeNotifier
|
|||||||
set { _filePath = value; NotifyPropertyChanged(); }
|
set { _filePath = value; NotifyPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public string FileName
|
public string FileName
|
||||||
{
|
{
|
||||||
get => Path.GetFileName(_filePath);
|
get => Path.GetFileName(_filePath);
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ReceiptPDFBuilder.Helpers;
|
||||||
|
|
||||||
|
namespace ReceiptPDFBuilder.Models;
|
||||||
|
|
||||||
|
class Settings : ChangeNotifier
|
||||||
|
{
|
||||||
|
private string _lastUsedPath;
|
||||||
|
|
||||||
|
public Settings()
|
||||||
|
{
|
||||||
|
_lastUsedPath = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
public string LastUsedPath
|
||||||
|
{
|
||||||
|
get => _lastUsedPath;
|
||||||
|
set { _lastUsedPath = value; NotifyPropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetSettingsFileName()
|
||||||
|
{
|
||||||
|
return "settings.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetSettingsPath()
|
||||||
|
{
|
||||||
|
var path = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
"ReceiptPDFBuilder"
|
||||||
|
);
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
return Path.Combine(path, GetSettingsFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonSerializerOptions GetSerializerOptions()
|
||||||
|
{
|
||||||
|
var opts = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||||
|
};
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> SaveSettingsAsync()
|
||||||
|
{
|
||||||
|
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
||||||
|
using MemoryStream memoryStream = new MemoryStream();
|
||||||
|
await JsonSerializer.SerializeAsync(memoryStream, this, jsonContext.Settings);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
using var reader = new StreamReader(memoryStream);
|
||||||
|
var json = await reader.ReadToEndAsync();
|
||||||
|
await File.WriteAllTextAsync(GetSettingsPath(), json);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Settings LoadSettings()
|
||||||
|
{
|
||||||
|
var path = GetSettingsPath();
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
return new Settings();
|
||||||
|
}
|
||||||
|
var json = File.ReadAllText(GetSettingsPath());
|
||||||
|
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
||||||
|
return JsonSerializer.Deserialize<Settings>(json, jsonContext.Settings) ?? new Settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<Settings> LoadSettingsAsync()
|
||||||
|
{
|
||||||
|
using FileStream fileStream = File.OpenRead(GetSettingsPath());
|
||||||
|
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
||||||
|
var output = await JsonSerializer.DeserializeAsync<Settings>(fileStream, jsonContext.Settings) ?? new Settings();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
using Avalonia.Themes.Fluent;
|
||||||
|
using DialogHostAvalonia;
|
||||||
|
using ImageMagick;
|
||||||
|
using MigraDoc.DocumentObjectModel;
|
||||||
|
using MigraDoc.Rendering;
|
||||||
|
using PdfSharp.Fonts;
|
||||||
|
using PdfSharp.Pdf.IO;
|
||||||
|
using PdfSharp.Snippets.Font;
|
||||||
|
using ReceiptPDFBuilder.Interfaces;
|
||||||
|
using ReceiptPDFBuilder.Models;
|
||||||
|
|
||||||
|
namespace ReceiptPDFBuilder.ViewModels;
|
||||||
|
|
||||||
|
class AboutViewModel
|
||||||
|
{
|
||||||
|
public AboutViewModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
DialogHost.Close("DialogHost", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
-14
@@ -30,6 +30,8 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
private string _reportTitle;
|
private string _reportTitle;
|
||||||
private ObservableCollection<ReportFile> _reportFiles;
|
private ObservableCollection<ReportFile> _reportFiles;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
public MainViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger)
|
public MainViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger)
|
||||||
{
|
{
|
||||||
_baseDir = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
|
_baseDir = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
|
||||||
@@ -39,6 +41,12 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
_reportFiles = new ObservableCollection<ReportFile>();
|
_reportFiles = new ObservableCollection<ReportFile>();
|
||||||
_reportFiles.CollectionChanged += ( sender, e ) => { NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); };
|
_reportFiles.CollectionChanged += ( sender, e ) => { NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); };
|
||||||
_reportTitle = "";
|
_reportTitle = "";
|
||||||
|
_settings = Settings.LoadSettings();
|
||||||
|
if (!string.IsNullOrWhiteSpace(_settings.LastUsedPath))
|
||||||
|
{
|
||||||
|
LogInfo("Loading data at last used path of {0}", _settings.LastUsedPath);
|
||||||
|
ScanFolder(_settings.LastUsedPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ReportTitle
|
public string ReportTitle
|
||||||
@@ -95,20 +103,27 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
if (folders.Count == 1)
|
if (folders.Count == 1)
|
||||||
{
|
{
|
||||||
var folder = folders[0];
|
var folder = folders[0];
|
||||||
LogInfo("Chosen folder: " + folder.Path.LocalPath);
|
LogInfo("Loading items in folder: " + folder.Path.LocalPath);
|
||||||
if (Directory.Exists(folder.Path.LocalPath))
|
ScanFolder(folder.Path.LocalPath);
|
||||||
{
|
_settings.LastUsedPath = folder.Path.LocalPath;
|
||||||
_workingFolder = folder.Path.LocalPath;
|
await _settings.SaveSettingsAsync();
|
||||||
NotifyPropertyChanged(nameof(IsTitleBoxVisible));
|
}
|
||||||
// TODO: Scan folder for saved info from previous reports and reload that first
|
}
|
||||||
// Scan folder for files and display in DataGrid
|
}
|
||||||
var filePaths = Directory.GetFiles(_workingFolder);
|
|
||||||
filePaths.Sort();
|
private void ScanFolder(string path)
|
||||||
foreach (var filePath in filePaths)
|
{
|
||||||
{
|
if (Directory.Exists(path))
|
||||||
AddFileBasedOnPath(filePath);
|
{
|
||||||
}
|
_workingFolder = path;
|
||||||
}
|
NotifyPropertyChanged(nameof(IsTitleBoxVisible));
|
||||||
|
// TODO: Scan folder for saved info from previous reports and reload that first
|
||||||
|
// Scan folder for files and display in DataGrid
|
||||||
|
var filePaths = Directory.GetFiles(_workingFolder);
|
||||||
|
filePaths.Sort();
|
||||||
|
foreach (var filePath in filePaths)
|
||||||
|
{
|
||||||
|
AddFileBasedOnPath(filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="ReceiptPDFBuilder.Views.AboutView"
|
||||||
|
xmlns:models="clr-namespace:ReceiptPDFBuilder.Models"
|
||||||
|
xmlns:vm="clr-namespace:ReceiptPDFBuilder.ViewModels"
|
||||||
|
xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia"
|
||||||
|
x:DataType="vm:AboutViewModel">
|
||||||
|
<StackPanel Orientation="Vertical"
|
||||||
|
Spacing="4">
|
||||||
|
<TextBlock Text="Receipt PDF Builder was built by MB for A in 2026. May the quacking of ducks always be in your favor. Thanks for using!"
|
||||||
|
MaxWidth="300"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
FontSize="14"/>
|
||||||
|
<Button Command="{Binding Close}"
|
||||||
|
Classes="accent"
|
||||||
|
Content="Close"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,4,4"/>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace ReceiptPDFBuilder.Views
|
||||||
|
{
|
||||||
|
public partial class AboutView : UserControl
|
||||||
|
{
|
||||||
|
public AboutView()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<Window xmlns="https://github.com/avaloniaui"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
|
||||||
x:Class="ReceiptPDFBuilder.AboutWindow"
|
|
||||||
Title="About Receipt PDF Builder"
|
|
||||||
Width="300"
|
|
||||||
Height="300"
|
|
||||||
MaxHeight="400"
|
|
||||||
MaxWidth="400"
|
|
||||||
MinWidth="300"
|
|
||||||
MinHeight="300">
|
|
||||||
<TextBlock Text="Receipt PDF Builder was built by MB for A in 2026. Thanks for using!"
|
|
||||||
TextWrapping="Wrap"/>
|
|
||||||
</Window>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
|
|
||||||
namespace ReceiptPDFBuilder;
|
|
||||||
|
|
||||||
public partial class AboutWindow : Window
|
|
||||||
{
|
|
||||||
public AboutWindow()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user