瀏覽代碼

Fixed wrong error being passed when PixiEditor has no right to write to a file

CPKreuz 1 年之前
父節點
當前提交
e19c7e5a0a

+ 37 - 14
src/PixiEditor/Models/IO/Exporter.cs

@@ -92,26 +92,23 @@ internal class Exporter
 
         var typeFromPath = SupportedFilesHelper.ParseImageFormat(Path.GetExtension(pathWithExtension));
 
-        if (typeFromPath != FileType.Pixi)
+        if (typeFromPath == FileType.Pixi)
         {
-            var maybeBitmap = document.MaybeRenderWholeImage();
-            if (maybeBitmap.IsT0)
-                return SaveResult.ConcurrencyError;
-            var bitmap = maybeBitmap.AsT1;
+            return TrySaveAsPixi(document, pathWithExtension);
+        }
 
-            if (!encodersFactory.ContainsKey(typeFromPath))
-            {
-                return SaveResult.UnknownError;
-            }
+        var maybeBitmap = document.MaybeRenderWholeImage();
+        if (maybeBitmap.IsT0)
+            return SaveResult.ConcurrencyError;
+        var bitmap = maybeBitmap.AsT1;
 
-            return TrySaveAs(encodersFactory[typeFromPath](), pathWithExtension, bitmap, exportSize);
-        }
-        else
+        if (!encodersFactory.ContainsKey(typeFromPath))
         {
-            Parser.PixiParser.Serialize(document.ToSerializable(), pathWithExtension);
+            return SaveResult.UnknownError;
         }
 
-        return SaveResult.Success;
+        return TrySaveAs(encodersFactory[typeFromPath](), pathWithExtension, bitmap, exportSize);
+
     }
 
     static Dictionary<FileType, Func<BitmapEncoder>> encodersFactory = new Dictionary<FileType, Func<BitmapEncoder>>();
@@ -172,6 +169,10 @@ internal class Exporter
         {
             return SaveResult.SecurityError;
         }
+        catch (UnauthorizedAccessException e)
+        {
+            return SaveResult.SecurityError;
+        }
         catch (IOException)
         {
             return SaveResult.IoError;
@@ -182,4 +183,26 @@ internal class Exporter
         }
         return SaveResult.Success;
     }
+
+    private static SaveResult TrySaveAsPixi(DocumentViewModel document, string pathWithExtension)
+    {
+        try
+        {
+            Parser.PixiParser.Serialize(document.ToSerializable(), pathWithExtension);
+        }
+        catch (UnauthorizedAccessException e)
+        {
+            return SaveResult.SecurityError;
+        }
+        catch (IOException)
+        {
+            return SaveResult.IoError;
+        }
+        catch
+        {
+            return SaveResult.UnknownError;
+        }
+
+        return SaveResult.Success;
+    }
 }

+ 43 - 4
src/PixiEditor/ViewModels/SubViewModels/Document/AutosaveViewModel.cs

@@ -13,7 +13,9 @@ internal class AutosaveViewModel : NotifyableObject
 {
     private readonly Timer savingTimer;
     private readonly Timer updateTextTimer;
+    private readonly Timer busyTimer;
     private bool saveAfterNextFinish;
+    private bool reenableAfterNextSave;
     private string mainMenuText;
     private int savingFailed;
     private DateTime nextSave;
@@ -39,6 +41,13 @@ internal class AutosaveViewModel : NotifyableObject
         savingTimer.Elapsed += (_, _) => TryAutosave();
         savingTimer.AutoReset = false;
 
+        busyTimer = new Timer(TimeSpan.FromMilliseconds(80));
+        busyTimer.AutoReset = false;
+        busyTimer.Elapsed += (_, _) =>
+        {
+            Document.Busy = true;
+        };
+
         updateTextTimer.Elapsed += (_, _) => SetAutosaveText();
 
         var preferences = IPreferences.Current;
@@ -57,6 +66,17 @@ internal class AutosaveViewModel : NotifyableObject
         SafeAutosave();
     }
 
+    public void HintSave()
+    {
+        if (!reenableAfterNextSave)
+            return;
+
+        reenableAfterNextSave = false;
+        
+        RestartTimers();
+        SetAutosaveText();
+    }
+
     private void SetAutosaveText()
     {
         var timeLeft = nextSave - DateTime.Now;
@@ -110,7 +130,17 @@ internal class AutosaveViewModel : NotifyableObject
         catch (Exception e)
         {
             savingFailed++;
-            UpdateMainMenuTextSave("AUTOSAVE_FAILED_RETRYING");
+            
+            var minute = AutosavePeriodMinutes <= 1
+                ? new LocalizedString("MINUTE_SINGULAR")
+                : new LocalizedString("MINUTE_PLURAL");
+
+            UpdateMainMenuTextSave(new LocalizedString("AUTOSAVE_FAILED_RETRYING", AutosavePeriodMinutes.ToString("0"), minute));
+        
+            busyTimer.Stop();
+            Document.Busy = false;
+
+            RestartTimers();
 
             if (savingFailed == 1)
             {
@@ -122,7 +152,6 @@ internal class AutosaveViewModel : NotifyableObject
     private void Autosave()
     {
         saveAfterNextFinish = false;
-        Document.Busy = true;
         
         UpdateMainMenuTextSave("AUTOSAVE_SAVING");
 
@@ -133,27 +162,34 @@ internal class AutosaveViewModel : NotifyableObject
             var root = Path.Combine(Path.GetTempPath(), "PixiEditor", "autosave");
             Directory.CreateDirectory(root);
             filePath = Path.Combine(root, $"autosave-{tempGuid}.pixi");
-            Document.MarkAsSaved();
         }
         else
         {
             filePath = Document.FullFilePath;
         }
         
+        busyTimer.Start();
         var result = Exporter.TrySave(Document, filePath);
 
         if (result == SaveResult.Success)
         {
             savingFailed = 0;
             UpdateMainMenuTextSave("AUTOSAVE_SAVED");
+            Document.MarkAsSaved();
         }
         else if (result is SaveResult.InvalidPath or SaveResult.SecurityError)
         {
             UpdateMainMenuTextSave("AUTOSAVE_PLEASE_RESAVE");
+            busyTimer.Stop();
+            Document.Busy = false;
+            reenableAfterNextSave = true;
             return;
         }
         else
         {
+            busyTimer.Stop();
+            Document.Busy = false;
+            
             var minute = AutosavePeriodMinutes <= 1
                 ? new LocalizedString("MINUTE_SINGULAR")
                 : new LocalizedString("MINUTE_PLURAL");
@@ -166,9 +202,12 @@ internal class AutosaveViewModel : NotifyableObject
                 CrashHelper.SendExceptionInfoToWebhook(new Exception($"Failed to autosave 3 times in a row due to {result}"));
             }
         }
+        
+        busyTimer.Stop();
+        Document.Busy = false;
 
         RestartTimers();
-        Document.Busy = false;
+        
     }
 
     private void RestartTimers()

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

@@ -335,6 +335,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
 
         document.FullFilePath = finalPath;
         document.MarkAsSaved();
+        document.AutosaveViewModel.HintSave();
         return true;
     }