From 64fb694a83430abd56c8550bc8b30b23a93b02f0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 01:35:33 +0000 Subject: [PATCH 1/2] Initial plan From e0d518743b6b9d749b31ad2c1c5836829033643c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 01:40:34 +0000 Subject: [PATCH 2/2] Use async ZIP APIs and improve loading screen UX for import/export - Replace synchronous ZipArchive constructor with ZipArchive.CreateAsync() in BackupFile.cs - Use entry.OpenAsync() instead of entry.Open() for non-blocking ZIP operations - Add "Please do not close the app" warning to the loading screen - Add Task.Yield() after StateHasChanged() to ensure spinner renders before heavy work - Update loading container CSS for proper vertical layout with warning text Co-authored-by: danielchalmers <7112040+danielchalmers@users.noreply.github.com> --- JournalApp/Data/BackupFile.cs | 8 ++++---- JournalApp/Pages/SettingsPage.razor | 3 +++ JournalApp/Pages/SettingsPage.razor.css | 7 +++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/JournalApp/Data/BackupFile.cs b/JournalApp/Data/BackupFile.cs index 0fddb160..a4d140d4 100644 --- a/JournalApp/Data/BackupFile.cs +++ b/JournalApp/Data/BackupFile.cs @@ -31,13 +31,13 @@ public class BackupFile /// public static async Task ReadArchive(Stream stream) { - using var archive = new ZipArchive(stream, ZipArchiveMode.Read); + await using var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Read, leaveOpen: true, entryNameEncoding: null); foreach (var entry in archive.Entries) { if (entry.FullName == InternalBackupFileName) { - await using var entryStream = entry.Open(); + await using var entryStream = await entry.OpenAsync(); return await JsonSerializer.DeserializeAsync(entryStream, SerializerOptions); } @@ -60,10 +60,10 @@ public static async Task ReadArchive(string path) /// public async Task WriteArchive(Stream stream) { - using var archive = new ZipArchive(stream, ZipArchiveMode.Create); + await using var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Create, leaveOpen: true, entryNameEncoding: null); var entry = archive.CreateEntry(InternalBackupFileName); - await using var entryStream = entry.Open(); + await using var entryStream = await entry.OpenAsync(); await JsonSerializer.SerializeAsync(entryStream, this, SerializerOptions); } diff --git a/JournalApp/Pages/SettingsPage.razor b/JournalApp/Pages/SettingsPage.razor index 6de22f6b..b6829f82 100644 --- a/JournalApp/Pages/SettingsPage.razor +++ b/JournalApp/Pages/SettingsPage.razor @@ -11,6 +11,7 @@ @* TODO: Replace with separate page so we can change state of inline fields and have it updated properly in settings *@
+ Please do not close the app
} else @@ -177,6 +178,7 @@ else { _busy = true; StateHasChanged(); + await Task.Yield(); var path = App.ActivatedFilePath; @@ -195,6 +197,7 @@ else { _busy = true; StateHasChanged(); + await Task.Yield(); await AppDataUIService.StartExportWizard(DialogService); } diff --git a/JournalApp/Pages/SettingsPage.razor.css b/JournalApp/Pages/SettingsPage.razor.css index c6d95157..3069bb9b 100644 --- a/JournalApp/Pages/SettingsPage.razor.css +++ b/JournalApp/Pages/SettingsPage.razor.css @@ -13,6 +13,8 @@ .loading-container { display: flex; + flex-direction: column; + align-items: center; justify-content: center; } @@ -21,3 +23,8 @@ width: 33vw; margin-top: 10vh; } + +.loading-warning { + margin-top: 24px; + opacity: 0.7; +}