Compare commits

...

4 Commits

Author SHA1 Message Date
Creeper Lv 684dd1bb50 Upgrade Avalonia packages and fixed some of issues with this upgrade. 2026-05-23 00:00:36 +10:00
Creeper Lv d7f2391fe8 ClassicStorageProvider will now being used as much as possible to support setting output directory to anywhere. 2026-03-23 00:34:18 +11:00
Creeper Lv 2b42f43b6e Update Directory.Packages.props 2026-03-22 02:37:00 +11:00
Creeper Lv e5cb9c2d28 Changed the assembly name to allow double-click to open in macOS
Added random number generator in JS engine.
2026-03-22 02:12:35 +11:00
14 changed files with 159 additions and 77 deletions
+34 -33
View File
@@ -1,35 +1,36 @@
<Project> <Project>
<!-- https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management --> <!-- https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
<PropertyGroup> <PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<Version>1.0.0.0</Version> <Version>1.1.1.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<!-- Avalonia packages --> <!-- Avalonia packages -->
<!-- Important: keep version in sync! --> <!-- Important: keep version in sync! -->
<PackageVersion Include="Avalonia" Version="11.3.12" /> <PackageVersion Include="Avalonia" Version="12.0.3" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" /> <PackageVersion Include="Avalonia.AvaloniaEdit" Version="12.0.0" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.12" /> <PackageVersion Include="Avalonia.Themes.Fluent" Version="12.0.3" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.12" /> <PackageVersion Include="Avalonia.Fonts.Inter" Version="12.0.3" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.12" /> <PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.12" /> <PackageVersion Include="Avalonia.Diagnostics" Version="11.3.16" />
<PackageVersion Include="Avalonia.iOS" Version="11.3.12" /> <PackageVersion Include="Avalonia.Desktop" Version="12.0.3" />
<PackageVersion Include="Avalonia.Browser" Version="11.3.12" /> <PackageVersion Include="Avalonia.iOS" Version="12.0.3" />
<PackageVersion Include="Avalonia.Android" Version="11.3.12" /> <PackageVersion Include="Avalonia.Browser" Version="12.0.3" />
<PackageVersion Include="AvaloniaEdit.TextMate" Version="11.4.1" /> <PackageVersion Include="Avalonia.Android" Version="12.0.3" />
<PackageVersion Include="Deadpikle.AvaloniaProgressRing" Version="0.10.11-preview20251127001" /> <PackageVersion Include="AvaloniaEdit.TextMate" Version="12.0.0" />
<PackageVersion Include="DialogHost.Avalonia" Version="0.10.4" /> <PackageVersion Include="Deadpikle.AvaloniaProgressRing" Version="0.11.0" />
<PackageVersion Include="Jint" Version="4.5.0" /> <PackageVersion Include="DialogHost.Avalonia" Version="0.12.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="11.0.0-preview.1.26104.118" /> <PackageVersion Include="Jint" Version="4.5.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="11.0.0-preview.1.26104.118" /> <PackageVersion Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="11.0.0-preview.4.26230.115" />
<PackageVersion Include="Microsoft.Maui.Graphics" Version="10.0.11" /> <PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="11.0.0-preview.4.26230.115" />
<PackageVersion Include="Microsoft.Maui.Graphics.Skia" Version="10.0.11" /> <PackageVersion Include="Microsoft.Maui.Graphics" Version="10.0.11" />
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" /> <PackageVersion Include="Microsoft.Maui.Graphics.Skia" Version="10.0.11" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" /> <PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" />
<PackageVersion Include="PanAndZoom" Version="11.3.9.1" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="SkiaSharp" Version="3.116.1" /> <PackageVersion Include="PanAndZoom" Version="12.0.0.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.116.1" /> <PackageVersion Include="SkiaSharp" Version="3.116.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.116.1" /> <PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="4.147.0-preview.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0.1" /> <PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.116.1" />
</ItemGroup> <PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0.1" />
</ItemGroup>
</Project> </Project>
+22
View File
@@ -0,0 +1,22 @@
using Android.App;
using Android.Runtime;
using Avalonia;
using Avalonia.Android;
using Progrart;
namespace Progrart.Android
{
[Application]
public class Application : AvaloniaAndroidApplication<App>
{
protected Application(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.WithInterFont();
}
}
}
+7 -6
View File
@@ -12,11 +12,12 @@ namespace Progrart.Android;
RoundIcon = "@drawable/app_icon", RoundIcon = "@drawable/app_icon",
MainLauncher = true, MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)] ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App> //public class MainActivity : AvaloniaMainActivity<App>
public class MainActivity : AvaloniaMainActivity//<App>
{ {
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) //protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{ //{
return base.CustomizeAppBuilder(builder) // return base.CustomizeAppBuilder(builder)
.WithInterFont(); // .WithInterFont();
} //}
} }
+3
View File
@@ -11,6 +11,9 @@ internal sealed partial class Program
App.SettingsProvider=new BrowserSettingsProvider(); App.SettingsProvider=new BrowserSettingsProvider();
return BuildAvaloniaApp() return BuildAvaloniaApp()
.WithInterFont() .WithInterFont()
#if DEBUG
.WithDeveloperTools()
#endif
.StartBrowserAppAsync("out"); .StartBrowserAppAsync("out");
} }
-1
View File
@@ -10,7 +10,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Browser" /> <PackageReference Include="Avalonia.Browser" />
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -83,6 +83,36 @@ namespace Progrart.Core.JSExecution
_obj.Set("floor", JsObject.FromObject(Engine, (object)MathFunctions.floor)); _obj.Set("floor", JsObject.FromObject(Engine, (object)MathFunctions.floor));
_obj.Set("sinh", JsObject.FromObject(Engine, (object)MathFunctions.sinh)); _obj.Set("sinh", JsObject.FromObject(Engine, (object)MathFunctions.sinh));
_obj.Set("cosh", JsObject.FromObject(Engine, (object)MathFunctions.cosh)); _obj.Set("cosh", JsObject.FromObject(Engine, (object)MathFunctions.cosh));
Engine.SetValue("random", JsObject.FromObject(Engine, (int seed) =>
{
var obj = new JsObject(Engine);
Random random = new Random(seed);
obj.Set("Next", JsObject.FromObject(Engine, () =>
{
return random.Next();
}));
obj.Set("NextMax", JsObject.FromObject(Engine, (int max) =>
{
return random.Next(max);
}));
obj.Set("NextFloat", JsObject.FromObject(Engine, () => random.NextDouble()));
return obj;
}));
Engine.SetValue("random_undetermined", JsObject.FromObject(Engine, () =>
{
var obj = new JsObject(Engine);
Random random = new Random();
obj.Set("Next", JsObject.FromObject(Engine, () =>
{
return random.Next();
}));
obj.Set("NextMax", JsObject.FromObject(Engine, (int max) =>
{
return random.Next(max);
}));
obj.Set("NextFloat", JsObject.FromObject(Engine, () => random.NextDouble()));
return obj;
}));
} }
string formSymbol(Dictionary<string, string> symbols) string formSymbol(Dictionary<string, string> symbols)
{ {
+19 -4
View File
@@ -1,4 +1,5 @@
using Newtonsoft.Json; using System.Diagnostics;
using Newtonsoft.Json;
using Progrart.Core.JSExecution; using Progrart.Core.JSExecution;
using Progrart.Core.Storage; using Progrart.Core.Storage;
@@ -33,7 +34,14 @@ namespace Progrart.Core.ProjectSystem
return; return;
using var reader = new StreamReader(stream); using var reader = new StreamReader(stream);
var img = executor.RenderImage(item.Size, reader.ReadToEnd(), args); var img = executor.RenderImage(item.Size, reader.ReadToEnd(), args);
var outputFile= Path.Combine(project.OutputDir, item.Target ?? item.Source + ".png"); string outputFile;
if (config.OutputDir != null)
outputFile = Path.Combine(project.OutputDir, config.OutputDir ?? "", item.Target ?? item.Source + ".png");
else
{
outputFile = Path.Combine(project.OutputDir, item.Target ?? item.Source + ".png");
}
using var img_stream = await provider.TryOpenWrite(outputFile); using var img_stream = await provider.TryOpenWrite(outputFile);
if (img_stream is null) if (img_stream is null)
return; return;
@@ -42,7 +50,7 @@ namespace Progrart.Core.ProjectSystem
} }
public async Task Build(string targetConfig, int maxJobCount = 1) public async Task Build(string targetConfig, int maxJobCount = 1)
{ {
int finalJobCount= Math.Max(maxJobCount < 0 ? Environment.ProcessorCount : maxJobCount, 1); int finalJobCount = Math.Max(maxJobCount < 0 ? Environment.ProcessorCount : maxJobCount, 1);
foreach (var config in project.Configurations) foreach (var config in project.Configurations)
{ {
if (config.Name == targetConfig) if (config.Name == targetConfig)
@@ -67,7 +75,14 @@ namespace Progrart.Core.ProjectSystem
await Parallel.ForEachAsync(config.Items, options, async (item, token) => await Parallel.ForEachAsync(config.Items, options, async (item, token) =>
{ {
await Execute(config, item); try
{
await Execute(config, item);
}
catch (Exception e)
{
Trace.WriteLine(e);
}
int currentCount = Interlocked.Increment(ref index); int currentCount = Interlocked.Increment(ref index);
OnProgressUpdate?.Invoke(config.Items.Count, currentCount); OnProgressUpdate?.Invoke(config.Items.Count, currentCount);
+11 -16
View File
@@ -1,39 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType><!--If you are willing to use platform-specific APIs, use conditional compilation.
<!--If you are willing to use platform-specific APIs, use conditional compilation.
See https://docs.avaloniaui.net/docs/guides/platforms/platform-specific-code/dotnet for more details.--> See https://docs.avaloniaui.net/docs/guides/platforms/platform-specific-code/dotnet for more details.-->
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>true</PublishAot> <PublishAot>true</PublishAot>
<AssemblyName>ProgrartDesktop</AssemblyName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest> <ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>progrart_app_icon.ico</ApplicationIcon> <ApplicationIcon>progrart_app_icon.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Content Include="progrart_app_icon.ico" /> <Content Include="progrart_app_icon.ico"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<TrimmerRootAssembly Include="Progrart" /> <TrimmerRootAssembly Include="Progrart"/>
<TrimmerRootAssembly Include="Progrart.Core" /> <TrimmerRootAssembly Include="Progrart.Core"/>
<TrimmerRootAssembly Include="Jint" /> <TrimmerRootAssembly Include="Jint"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.Desktop" /> <PackageReference Include="Avalonia.Desktop"/><!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics"> <PackageReference Include="AvaloniaUI.DiagnosticsSupport" >
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="SkiaSharp.NativeAssets.Linux" /> <PackageReference Include="SkiaSharp.NativeAssets.Linux"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Progrart\Progrart.csproj" /> <ProjectReference Include="..\Progrart\Progrart.csproj"/>
</ItemGroup> </ItemGroup>
</Project> </Project>
+12 -12
View File
@@ -84,7 +84,7 @@ public partial class App : Application
// Avoid duplicate validations from both Avalonia and the CommunityToolkit. // Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
isDesktop = true; isDesktop = true;
DisableAvaloniaDataAnnotationValidation(); //DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow(); desktop.MainWindow = new MainWindow();
} }
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
@@ -95,16 +95,16 @@ public partial class App : Application
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
private void DisableAvaloniaDataAnnotationValidation() //private void DisableAvaloniaDataAnnotationValidation()
{ //{
// Get an array of plugins to remove // // Get an array of plugins to remove
var dataValidationPluginsToRemove = // var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray(); // BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found // // remove each entry found
foreach (var plugin in dataValidationPluginsToRemove) // foreach (var plugin in dataValidationPluginsToRemove)
{ // {
BindingPlugins.DataValidators.Remove(plugin); // BindingPlugins.DataValidators.Remove(plugin);
} // }
} //}
} }
@@ -1,6 +1,7 @@
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -35,6 +36,12 @@ namespace Progrart.Core.Storage
{ {
return await file.OpenWriteAsync(); return await file.OpenWriteAsync();
} }
var parentPath = Path.GetDirectoryName(path);
if (parentPath is not null)
if ((await baseFolder.GetFolderAsync(parentPath)) == null)
{
await baseFolder.CreateFolderAsync(parentPath);
}
file = await baseFolder.CreateFileAsync(path); file = await baseFolder.CreateFileAsync(path);
if (file is not null) if (file is not null)
return await file.OpenWriteAsync(); return await file.OpenWriteAsync();
@@ -202,7 +202,6 @@ public partial class ProgrartEditorPage : UserControl, ITabPage, IEditorPage
{ {
if (LayoutButtonV.IsChecked == true) if (LayoutButtonV.IsChecked == true)
{ {
direction = LayoutDirection.Vertical; direction = LayoutDirection.Vertical;
ApplyLayout(); ApplyLayout();
} }
+1 -1
View File
@@ -21,7 +21,7 @@
<PackageReference Include="Avalonia.Themes.Fluent" /> <PackageReference Include="Avalonia.Themes.Fluent" />
<PackageReference Include="Avalonia.Fonts.Inter" /> <PackageReference Include="Avalonia.Fonts.Inter" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics"> <PackageReference Include="AvaloniaUI.DiagnosticsSupport">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> <IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> <PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference> </PackageReference>
+10 -1
View File
@@ -274,7 +274,16 @@ public partial class MainView : UserControl
{ {
if (App.LoadedProject is not null) if (App.LoadedProject is not null)
{ {
Builder builder = new Builder(App.LoadedProject, new AvaloniaStorageProvider(App.CurrentOpenFolder)); Builder builder;
var localPath = App.CurrentOpenFolder?.TryGetLocalPath();
if (localPath != null)
{
builder = new Builder(App.LoadedProject, new ClassicStorageProvider(new DirectoryInfo(localPath)));
}
else
builder = new Builder(App.LoadedProject, new AvaloniaStorageProvider(App.CurrentOpenFolder));
var config = App.LoadedProject.Configurations[ConfigBox.SelectedIndex]; var config = App.LoadedProject.Configurations[ConfigBox.SelectedIndex];
var name = config.Name; var name = config.Name;
if (config is null) return; if (config is null) return;
+2 -1
View File
@@ -8,7 +8,8 @@ public partial class MainWindow : Window
{ {
InitializeComponent(); InitializeComponent();
this.ExtendClientAreaToDecorationsHint = true; this.ExtendClientAreaToDecorationsHint = true;
this.ExtendClientAreaChromeHints = Avalonia.Platform.ExtendClientAreaChromeHints.PreferSystemChrome; //this.WindowDecorations= WindowDecorations.
//this.ExtendClientAreaChromeHints = Avalonia.Platform.ExtendClientAreaChromeHints.PreferSystemChrome;
this.Closing += MainWindow_Closing; this.Closing += MainWindow_Closing;
} }