Implemented a settings page and settings provider.

This commit is contained in:
Creeper Lv
2026-01-18 03:14:22 +11:00
parent 6dff9b8718
commit 365be0474a
11 changed files with 224 additions and 16 deletions

View File

@@ -19,6 +19,8 @@
<PackageVersion Include="Deadpikle.AvaloniaProgressRing" Version="0.10.11-preview20251127001" />
<PackageVersion Include="DialogHost.Avalonia" Version="0.10.4" />
<PackageVersion Include="Jint" Version="4.5.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
<PackageVersion Include="Microsoft.Maui.Graphics" Version="10.0.11" />
<PackageVersion Include="Microsoft.Maui.Graphics.Skia" Version="10.0.11" />
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" />

View File

@@ -1,14 +1,18 @@
using System.Runtime.Versioning;
using System.Threading.Tasks;
using Avalonia;
using Avalonia;
using Avalonia.Browser;
using Progrart;
using Progrart.Browser.Settings;
using System.Threading.Tasks;
internal sealed partial class Program
{
private static Task Main(string[] args) => BuildAvaloniaApp()
private static Task Main(string[] args)
{
App.SettingsProvider=new BrowserSettingsProvider();
return BuildAvaloniaApp()
.WithInterFont()
.StartBrowserAppAsync("out");
}
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>();

View File

@@ -0,0 +1,29 @@
using Progrart.Core.Settings;
using System.Runtime.InteropServices.JavaScript;
using System.Text.Json;
namespace Progrart.Browser.Settings
{
public partial class BrowserSettingsProvider : ISettingsProvider
{
private SerializeContext context=new SerializeContext();
[JSImport("globalThis.localStorage.setItem")]
private static partial void SetItem(string key, string value);
[JSImport("globalThis.localStorage.getItem")]
private static partial string GetItem(string key);
public AppConfig LoadSettings()
{
var json = GetItem("progrart.settings");
return json != null
? JsonSerializer.Deserialize<AppConfig>(json,context.AppConfig)??new AppConfig()
: new AppConfig();
}
public void SaveSettings(AppConfig config)
{
var json = JsonSerializer.Serialize(config,context.AppConfig)??"";
SetItem("progrart.settings", json);
}
}
}

View File

@@ -2,14 +2,16 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using System.Linq;
using Avalonia.Markup.Xaml;
using Progrart.Views;
using Avalonia.Platform.Storage;
using Microsoft.Extensions.Configuration;
using Progrart.Core.ProjectSystem;
using Progrart.Core.Settings;
using Progrart.Icons;
using Progrart.Pages;
using Avalonia.Platform.Storage;
using Progrart.Views;
using System;
using Progrart.Core.ProjectSystem;
using System.Linq;
namespace Progrart;
@@ -19,6 +21,7 @@ public partial class App : Application
public static IStorageFolder? CurrentOpenFolder = null;
public static Project? LoadedProject = null;
internal static Action? ProjectLoadHandler = null;
public static ISettingsProvider? SettingsProvider = null;
public static void ProjectLoad()
{
ProjectLoadHandler?.Invoke();
@@ -27,7 +30,6 @@ public partial class App : Application
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
IconProvider.Register(new DefaultIconProvider());
@@ -53,6 +55,10 @@ public partial class App : Application
EditorProvider.BindFileType("jpg", "image");
EditorProvider.BindFileType("progrart-project", "project");
EditorProvider.BindFileType("wd", "console");
if (!OperatingSystem.IsBrowser())
{
App.SettingsProvider = new ClassicSettingsProvider();
}
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.

View File

@@ -0,0 +1,33 @@
using System;
using System.IO;
using System.Text.Json;
namespace Progrart.Core.Settings
{
public class ClassicSettingsProvider : ISettingsProvider
{
private readonly string _filePath;
private SerializeContext context = new SerializeContext();
public ClassicSettingsProvider()
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appFolder = Path.Combine(folder, "Progrart");
Directory.CreateDirectory(appFolder);
_filePath = Path.Combine(appFolder, "settings.json");
}
public void SaveSettings(AppConfig settings)
{
var json = JsonSerializer.Serialize(settings, context.AppConfig);
File.WriteAllText(_filePath, json);
}
public AppConfig LoadSettings()
{
if (!File.Exists(_filePath)) return new AppConfig();
var json = File.ReadAllText(_filePath);
return JsonSerializer.Deserialize<AppConfig>(json, context.AppConfig) ?? new AppConfig();
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json.Serialization;
namespace Progrart.Core.Settings
{
public interface ISettingsProvider
{
void SaveSettings(AppConfig config);
AppConfig LoadSettings();
}
[Serializable]
public class AppConfig
{
public bool useParallelBuild { get; set; }
public int JobCount { get; set; }
}
[JsonSerializable(typeof(AppConfig))]
public partial class SerializeContext : JsonSerializerContext
{
}
}

View File

@@ -0,0 +1,47 @@
<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="Progrart.Pages.SettingsPage">
<UserControl.Styles>
<Style Selector="TextBlock.h1">
<Setter Property="FontSize" Value="20"/>
<Setter Property="Margin" Value="5"/>
</Style>
<Style Selector="TextBlock.h2">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Margin" Value="5"/>
</Style>
<Style Selector="Expander">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</UserControl.Styles>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid>
<TextBlock Text="Settings" Classes="h1" VerticalAlignment="Center"/>
<Button Name="SaveSettings" HorizontalAlignment="Right" VerticalAlignment="Center" Click="SaveSettings_Click">
<PathIcon Data="F1 M 3.36 11.959999 C 3.28 11.853333 3.173333 11.799999 3.04 11.799999 C 2.906667 11.799999 2.786666 11.846666 2.68 11.94 C 2.573333 12.033334 2.513333 12.146667 2.5 12.28 C 2.486667 12.413334 2.533333 12.533333 2.64 12.639999 L 6.64 17.119999 C 6.719999 17.226665 6.833333 17.286667 6.98 17.299999 C 7.126667 17.313332 7.253333 17.266666 7.36 17.16 L 17.84 6.639999 C 17.946667 6.56 18 6.446667 18 6.299999 C 18 6.153334 17.953331 6.033334 17.859999 5.94 C 17.766666 5.846666 17.646666 5.799999 17.5 5.799999 C 17.353333 5.799999 17.239998 5.853333 17.16 5.96 L 7.04 16.08 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />
</Button>
</Grid>
<ScrollViewer Grid.Row="1">
<StackPanel>
<Expander>
<Expander.Header>
<TextBlock Text="Builder" Classes="h2"/>
</Expander.Header>
<StackPanel Margin="10">
<TextBlock>Use Parallel Building</TextBlock>
<ToggleSwitch Name="useParallelBuilding"/>
<TextBlock Text="Job Count ( -1 for Processor Count)" VerticalAlignment="Center" TextWrapping="Wrap"/>
<NumericUpDown Minimum="-1" Maximum="1024" Value="-1" Name="JobCont" FormatString="0" HorizontalAlignment="Left"/>
</StackPanel>
</Expander>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,51 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Microsoft.Extensions.Configuration;
using Progrart.Controls.TabSystem;
using Progrart.Core.Settings;
namespace Progrart.Pages;
public partial class SettingsPage : UserControl, ITabPage
{
public SettingsPage()
{
InitializeComponent();
if ((App.SettingsProvider) != null)
{
var settings = App.SettingsProvider.LoadSettings();
{
useParallelBuilding.IsChecked = settings.useParallelBuild;
JobCont.Value = settings.JobCount;
}
}
}
public void BindButton(TabButton button)
{
button.Title = "Settings";
}
public bool IsModified()
{
return false;
}
public void SetHost(TabHost host)
{
}
private void SaveSettings_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
if (App.SettingsProvider is null) return;
AppConfig config = new AppConfig()
{
useParallelBuild = useParallelBuilding.IsChecked ?? false,
JobCount = (int)(JobCont.Value ?? -1)
};
App.SettingsProvider.SaveSettings(config);
}
}

View File

@@ -28,6 +28,8 @@
<PackageReference Include="AvaloniaEdit.TextMate" />
<PackageReference Include="Deadpikle.AvaloniaProgressRing" />
<PackageReference Include="DialogHost.Avalonia" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="PanAndZoom" />
<!--<PackageReference Include="Devolutions.AvaloniaTheme.DevExpress" />
<PackageReference Include="Devolutions.AvaloniaTheme.MacOS" />-->

View File

@@ -50,7 +50,7 @@
<MenuItem Header="Save _As"/>
</MenuItem>
<MenuItem Header="_Tools">
<MenuItem Header="_Settings"/>
<MenuItem Header="_Settings" Name="SettingsMenuItem" Click="SettingsMenuItem_Click"/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About" Name="AboutItem"/>

View File

@@ -2,12 +2,14 @@ using Acornima.Ast;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Progrart.Commands;
using Progrart.Controls;
using Progrart.Core;
using Progrart.Core.JSExecution;
using Progrart.Core.ProjectSystem;
using Progrart.Core.Settings;
using Progrart.Core.Storage;
using Progrart.Pages;
using System;
@@ -248,7 +250,7 @@ public partial class MainView : UserControl
int max = config.Items.Count;
ProgressGrid.IsVisible = true;
MainProgress.Value = sum;
MainProgress.Maximum= max;
MainProgress.Maximum = max;
builder.OnProgressUpdate = (a, b) =>
{
Interlocked.Increment(ref sum);
@@ -257,14 +259,22 @@ public partial class MainView : UserControl
MainProgress.Value = sum;
});
};
builder.OnCompleted= () =>
builder.OnCompleted = () =>
{
Dispatcher.UIThread.Invoke(() =>
{
ProgressGrid.IsVisible = false;
});
};
Task.Run(async () => await builder.Build(name, -1));
AppConfig app_config = new AppConfig();
if (App.SettingsProvider != null)
app_config = App.SettingsProvider.LoadSettings();
Task.Run(async () => await builder.Build(name, app_config.useParallelBuild == false ? 1 : app_config.JobCount));
}
}
private void SettingsMenuItem_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
MainTabHost.AddPage(new SettingsPage());
}
}