Browse Source

Merge pull request #915 from PixiEditor/fixes/30.04.2025

Fixes/30.04.2025
Krzysztof Krysiński 3 months ago
parent
commit
93835892f5

+ 6 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/RemoveClosePointsNode.cs

@@ -31,7 +31,12 @@ public class RemoveClosePointsNode : ShapeNode<PointsVectorData>
         var distance = MinDistance.Value;
         var distance = MinDistance.Value;
         var minDistanceSquared = distance * distance;
         var minDistanceSquared = distance * distance;
 
 
-        if (distance == 0 || data == null || data.Points == null)
+        if (distance == 0)
+        {
+            return data;
+        }
+
+        if (data?.Points == null)
         {
         {
             return null;
             return null;
         }
         }

+ 2 - 2
src/PixiEditor.Windows/WindowsOperatingSystem.cs

@@ -37,7 +37,7 @@ public sealed class WindowsOperatingSystem : IOperatingSystem
     public void OpenFolder(string path)
     public void OpenFolder(string path)
     {
     {
         string dirName = Path.GetDirectoryName(path);
         string dirName = Path.GetDirectoryName(path);
-        string fileName = Path.GetFileName(path);
+        string fileName = !string.IsNullOrEmpty(Path.GetExtension(path)) ? Path.GetFileName(path) : null;
 
 
         if (dirName == null)
         if (dirName == null)
         {
         {
@@ -50,7 +50,7 @@ public sealed class WindowsOperatingSystem : IOperatingSystem
             return;
             return;
         }
         }
 
 
-        WindowsProcessUtility.ShellExecuteEV(dirName);
+        WindowsProcessUtility.ShellExecuteEV(path);
     }
     }
 
 
     public bool HandleNewInstance(Dispatcher? dispatcher, Action<string, bool> openInExistingAction, IApplicationLifetime lifetime)
     public bool HandleNewInstance(Dispatcher? dispatcher, Action<string, bool> openInExistingAction, IApplicationLifetime lifetime)

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1032,5 +1032,8 @@
   "CUSTOM_BACKGROUND_SCALE": "Custom background scale",
   "CUSTOM_BACKGROUND_SCALE": "Custom background scale",
   "PRIMARY_BG_COLOR": "Primary background color",
   "PRIMARY_BG_COLOR": "Primary background color",
   "SECONDARY_BG_COLOR": "Secondary background color",
   "SECONDARY_BG_COLOR": "Secondary background color",
-  "RESET": "Reset"
+  "RESET": "Reset",
+  "AUTOSAVE_OPEN_FOLDER": "Open autosave folder",
+   "AUTOSAVE_OPEN_FOLDER_DESCRIPTIVE": "Open the folder where autosaves are stored",
+  "AUTOSAVE_TOGGLE_DESCRIPTIVE": "Enable/disable autosave"
 }
 }

+ 3 - 1
src/PixiEditor/Helpers/Extensions/PixiParserPixiV4DocumentEx.cs

@@ -162,7 +162,9 @@ internal static class PixiParserPixiV4DocumentEx
                     new KeyFrameData()
                     new KeyFrameData()
                     {
                     {
                         AffectedElement = ImageLayerNode.ImageLayerKey,
                         AffectedElement = ImageLayerNode.ImageLayerKey,
-                        Data = new ChunkyImage(Surface.Load(layer.ImageBytes), ColorSpace.CreateSrgb()),
+                        Data = layer is { Width: > 0, Height: > 0, ImageBytes.Length: > 0 }
+                            ? new ChunkyImage(Surface.Load(layer.ImageBytes), ColorSpace.CreateSrgb()) :
+                            new ChunkyImage(new VecI(document.Width, document.Height), ColorSpace.CreateSrgb()),
                         Duration = 0,
                         Duration = 0,
                         StartFrame = 0,
                         StartFrame = 0,
                         IsVisible = true
                         IsVisible = true

+ 8 - 3
src/PixiEditor/Initialization/ClassicDesktopEntry.cs

@@ -61,6 +61,8 @@ internal class ClassicDesktopEntry
 
 
         InitOperatingSystem();
         InitOperatingSystem();
 
 
+        bool safeMode = arguments.Contains("--safeMode", StringComparison.OrdinalIgnoreCase);
+
         if (ParseArgument(@"--crash (""?)([\w:\/\ -_.]+)\1", arguments, out Group[] groups))
         if (ParseArgument(@"--crash (""?)([\w:\/\ -_.]+)\1", arguments, out Group[] groups))
         {
         {
             try
             try
@@ -92,7 +94,7 @@ internal class ClassicDesktopEntry
         }
         }
 #endif
 #endif
 
 
-        var extensionLoader = InitApp();
+        var extensionLoader = InitApp(safeMode);
 
 
         desktop.MainWindow = new MainWindow(extensionLoader);
         desktop.MainWindow = new MainWindow(extensionLoader);
         desktop.MainWindow.Show();
         desktop.MainWindow.Show();
@@ -105,7 +107,7 @@ internal class ClassicDesktopEntry
         platform.PerformHandshake();
         platform.PerformHandshake();
     }
     }
 
 
-    public ExtensionLoader InitApp()
+    public ExtensionLoader InitApp(bool safeMode)
     {
     {
         LoadingWindow.ShowInNewThread();
         LoadingWindow.ShowInNewThread();
 
 
@@ -116,7 +118,10 @@ internal class ClassicDesktopEntry
         extensionLoader.AddOfficialExtension("pixieditor.supporterpack",
         extensionLoader.AddOfficialExtension("pixieditor.supporterpack",
             new OfficialExtensionData("supporter-pack.snk", AdditionalContentProduct.SupporterPack));
             new OfficialExtensionData("supporter-pack.snk", AdditionalContentProduct.SupporterPack));
         extensionLoader.AddOfficialExtension("pixieditor.beta", new OfficialExtensionData());
         extensionLoader.AddOfficialExtension("pixieditor.beta", new OfficialExtensionData());
-        extensionLoader.LoadExtensions();
+        if (!safeMode)
+        {
+            extensionLoader.LoadExtensions();
+        }
 
 
         return extensionLoader;
         return extensionLoader;
     }
     }

+ 2 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/SelectToolExecutor.cs

@@ -7,6 +7,7 @@ using PixiEditor.Models.Handlers.Tools;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
 using PixiEditor.Models.Tools;
 using Drawie.Numerics;
 using Drawie.Numerics;
+using PixiEditor.Views.Overlays.SelectionOverlay;
 
 
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 namespace PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
 #nullable enable
 #nullable enable
@@ -65,6 +66,7 @@ internal class SelectToolExecutor : UpdateableChangeExecutor
 
 
     public override void ForceStop()
     public override void ForceStop()
     {
     {
+
         IAction action = CreateEndAction(selectShape);
         IAction action = CreateEndAction(selectShape);
         internals!.ActionAccumulator.AddFinishedActions(action);
         internals!.ActionAccumulator.AddFinishedActions(action);
     }
     }

+ 14 - 13
src/PixiEditor/ViewModels/CrashReportViewModel.cs

@@ -1,12 +1,12 @@
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Threading.Tasks;
+using System.Diagnostics;
 using Avalonia;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls;
-using Avalonia.Threading;
+using Avalonia.Controls.ApplicationLifetimes;
 using CommunityToolkit.Mvvm.Input;
 using CommunityToolkit.Mvvm.Input;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
+using PixiEditor.Initialization;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.ExceptionHandling;
 using PixiEditor.Models.ExceptionHandling;
 using PixiEditor.Views;
 using PixiEditor.Views;
@@ -79,6 +79,16 @@ internal partial class CrashReportViewModel : Window
         Application.Current.Run(window);
         Application.Current.Run(window);
     }
     }
 
 
+    [RelayCommand]
+    public void RunInSafeMode()
+    {
+        var app = (App)Application.Current;
+        ClassicDesktopEntry entry = new(app.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime);
+        StartupArgs.Args = new List<string> { "--safeMode" };
+        var window = new MainWindow(entry.InitApp(true), null);
+        Application.Current.Run(window);
+    }
+
     public bool CanRecoverDocuments()
     public bool CanRecoverDocuments()
     {
     {
         return hasRecoveredDocuments;
         return hasRecoveredDocuments;
@@ -109,13 +119,4 @@ internal partial class CrashReportViewModel : Window
     {
     {
         IsDebugBuild = true;
         IsDebugBuild = true;
     }
     }
-
-    [RelayCommand]
-    private void AttachDebugger()
-    {
-        if (!Debugger.Launch())
-        {
-            /*TODO: MessageBox.Show("Starting debugger failed", "Starting debugger failed", MessageBoxButton.OK, MessageBoxImage.Error);*/
-        }
-    }
 }
 }

+ 13 - 1
src/PixiEditor/ViewModels/SubViewModels/AutosaveViewModel.cs

@@ -5,6 +5,8 @@ using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Evaluators;
 using PixiEditor.Models.Commands.Attributes.Evaluators;
 using PixiEditor.Models.DocumentModels.Autosave;
 using PixiEditor.Models.DocumentModels.Autosave;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
+using PixiEditor.OperatingSystem;
+using PixiEditor.UI.Common.Fonts;
 using PixiEditor.ViewModels.Document;
 using PixiEditor.ViewModels.Document;
 
 
 namespace PixiEditor.ViewModels.SubViewModels;
 namespace PixiEditor.ViewModels.SubViewModels;
@@ -13,7 +15,17 @@ internal class AutosaveViewModel(ViewModelMain owner, DocumentManagerViewModel d
 {
 {
     public static bool SaveSessionStateEnabled => IPreferences.Current!.GetPreference(PreferencesConstants.SaveSessionStateEnabled, PreferencesConstants.SaveSessionStateDefault);
     public static bool SaveSessionStateEnabled => IPreferences.Current!.GetPreference(PreferencesConstants.SaveSessionStateEnabled, PreferencesConstants.SaveSessionStateDefault);
 
 
-    [Command.Basic("PixiEditor.Autosave.ToggleAutosave", "AUTOSAVE_TOGGLE", "AUTOSAVE_TOGGLE_DESCRIPTION",
+    [Command.Basic("PixiEditor.Autosave.OpenAutosaveFolder", "AUTOSAVE_OPEN_FOLDER", "AUTOSAVE_OPEN_FOLDER_DESCRIPTIVE",
+        Icon = PixiPerfectIcons.Folder)]
+    public void OpenAutosaveFolder()
+    {
+        if (Directory.Exists(Paths.PathToUnsavedFilesFolder))
+        {
+            IOperatingSystem.Current.OpenFolder(Paths.PathToUnsavedFilesFolder);
+        }
+    }
+
+    [Command.Basic("PixiEditor.Autosave.ToggleAutosave", "AUTOSAVE_TOGGLE", "AUTOSAVE_TOGGLE_DESCRIPTIVE",
         CanExecute = "PixiEditor.Autosave.HasDocumentAndAutosaveEnabled")]
         CanExecute = "PixiEditor.Autosave.HasDocumentAndAutosaveEnabled")]
     public void ToggleAutosave()
     public void ToggleAutosave()
     {
     {

+ 1 - 1
src/PixiEditor/ViewModels/SubViewModels/FileViewModel.cs

@@ -117,7 +117,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
 
 
         try
         try
         {
         {
-            if (!args.Contains("--crash"))
+            if (!args.Contains("--crash") && !args.Contains("--safeMode"))
             {
             {
                 var lastCrash = preferences!.GetLocalPreference<string>(PreferencesConstants.LastCrashFile);
                 var lastCrash = preferences!.GetLocalPreference<string>(PreferencesConstants.LastCrashFile);
 
 

+ 12 - 6
src/PixiEditor/Views/Dialogs/CrashReportDialog.axaml

@@ -22,19 +22,25 @@
             <Grid Background="{DynamicResource ThemeBackgroundBrush}">
             <Grid Background="{DynamicResource ThemeBackgroundBrush}">
                 <StackPanel Margin="7" VerticalAlignment="Center">
                 <StackPanel Margin="7" VerticalAlignment="Center">
                     <TextBlock Text="{Binding DocumentCount, StringFormat={}{0} file(s) might be recoverable}"
                     <TextBlock Text="{Binding DocumentCount, StringFormat={}{0} file(s) might be recoverable}"
-                               d:Text="2 file(s) can be recovered"/>
+                               d:Text="2 file(s) can be recovered" />
                     <TextBlock TextWrapping="Wrap">You can help the developers fix this bug by sending a crash report that was generated (you will still be able to recover the files).</TextBlock>
                     <TextBlock TextWrapping="Wrap">You can help the developers fix this bug by sending a crash report that was generated (you will still be able to recover the files).</TextBlock>
                 </StackPanel>
                 </StackPanel>
             </Grid>
             </Grid>
 
 
             <WrapPanel Margin="0,20,0,5" Orientation="Horizontal" HorizontalAlignment="Center">
             <WrapPanel Margin="0,20,0,5" Orientation="Horizontal" HorizontalAlignment="Center">
                 <Button Command="{Binding OpenSendCrashReportCommand}"
                 <Button Command="{Binding OpenSendCrashReportCommand}"
-                        Width="120">Send report</Button>
+                        Width="120">
+                    Send report
+                </Button>
                 <Button Margin="5,0,5,0" Width="120"
                 <Button Margin="5,0,5,0" Width="120"
-                        Command="{Binding RecoverDocumentsCommand}">Recover files</Button>
-                <Button IsVisible="{Binding IsDebugBuild}" Width="170"
-                        Command="{Binding AttachDebuggerCommand}">(Re)Attach debugger</Button>
+                        Command="{Binding RecoverDocumentsCommand}">
+                    Recover files
+                </Button>
+                <Button Margin="5,0,5,0" Width="120"
+                        Command="{Binding RunInSafeModeCommand}">
+                    Safe mode
+                </Button>
             </WrapPanel>
             </WrapPanel>
         </StackPanel>
         </StackPanel>
     </Grid>
     </Grid>
-</Window>
+</Window>

+ 2 - 2
src/PixiEditor/Views/Main/ViewportControls/ViewportOverlays.cs

@@ -147,8 +147,8 @@ internal class ViewportOverlays
     {
     {
         Binding showFillBinding = new()
         Binding showFillBinding = new()
         {
         {
-            Source = Viewport,
-            Path = "Document.ToolsSubViewModel.ActiveTool",
+            Source = ViewModelMain.Current,
+            Path = "ToolsSubViewModel.ActiveTool",
             Converter = new IsSelectionToolConverter(),
             Converter = new IsSelectionToolConverter(),
             Mode = BindingMode.OneWay
             Mode = BindingMode.OneWay
         };
         };

+ 1 - 1
src/PixiEditor/Views/MainWindow.axaml.cs

@@ -110,7 +110,7 @@ internal partial class MainWindow : Window
             {
             {
                 var app = (App)Application.Current;
                 var app = (App)Application.Current;
                 ClassicDesktopEntry entry = new(app.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime);
                 ClassicDesktopEntry entry = new(app.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime);
-                return new MainWindow(entry.InitApp(), analyticsSession);
+                return new MainWindow(entry.InitApp(false), analyticsSession);
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {

+ 1 - 1
src/PixiEditor/Views/Windows/HelloTherePopup.axaml.cs

@@ -227,7 +227,7 @@ internal partial class HelloTherePopup : PixiEditorPopup
 
 
     private void CheckHasClipboardInImage()
     private void CheckHasClipboardInImage()
     {
     {
-        Task.Run(async () =>
+        Dispatcher.UIThread.InvokeAsync(async () =>
         {
         {
             hasImageInClipboard = await ClipboardController.IsImageInClipboard();
             hasImageInClipboard = await ClipboardController.IsImageInClipboard();
         }).ContinueWith(_ =>
         }).ContinueWith(_ =>

+ 1 - 1
src/global.json

@@ -1,7 +1,7 @@
 {
 {
   "sdk": {
   "sdk": {
     "version": "8.0.405",
     "version": "8.0.405",
-    "rollForward": "latestMajor",
+    "rollForward": "latestMinor",
     "allowPrerelease": false
     "allowPrerelease": false
   }
   }
 }
 }