Skip to content

Use async ZIP APIs and improve loading screen UX for import/export#79

Closed
Copilot wants to merge 2 commits intomainfrom
copilot/improve-import-export-ux
Closed

Use async ZIP APIs and improve loading screen UX for import/export#79
Copilot wants to merge 2 commits intomainfrom
copilot/improve-import-export-ux

Conversation

Copy link
Contributor

Copilot AI commented Feb 11, 2026

Import/export blocks the UI thread during ZIP operations, causing the loading spinner to freeze and lag.

Async ZIP operations

Replace synchronous ZipArchive constructor and entry.Open() with .NET 10 async equivalents:

// Before
using var archive = new ZipArchive(stream, ZipArchiveMode.Read);
await using var entryStream = entry.Open();

// After
await using var archive = await ZipArchive.CreateAsync(stream, ZipArchiveMode.Read, leaveOpen: true, entryNameEncoding: null);
await using var entryStream = await entry.OpenAsync();

Loading screen improvements

  • Add await Task.Yield() after StateHasChanged() in StartImport/StartExport so the renderer paints the spinner before heavy work begins
  • Add "Please do not close the app" warning text below the spinner
  • Update .loading-container CSS to vertical flex layout for the new warning element
Original prompt

This section details on the original issue you should resolve

<issue_title>Make import/export UX more responsive</issue_title>
<issue_description>There's a significant amount of UI blocking and lag during import/export. Is there anything else we can do?

Loading screen:

  • The loading screen indicator animation should always play smoothly and never be blocked during work
  • During export, the loading indicator screen should be shown while the archive is being created instead of only while saving
  • There should be a "Do not close the app" warning on the loading screen

Maybe we can improve the actual export/import time as well as it takes several seconds currently.


.NET 10 introduces new asynchronous APIs that make it easier to perform non-blocking operations when reading from or writing to ZIP files. This feature was highly requested by the community.

New async methods are available for extracting, creating, and updating ZIP archives. These methods enable developers to efficiently handle large files and improve application responsiveness, especially in scenarios involving I/O-bound operations. These methods include:

ZipArchive.CreateAsync(Stream, ZipArchiveMode, Boolean, Encoding, CancellationToken)
ZipArchiveEntry.OpenAsync(CancellationToken)
ZipFile.CreateFromDirectoryAsync
ZipFile.ExtractToDirectoryAsync
ZipFile.OpenAsync
ZipFile.OpenReadAsync(String, CancellationToken)
ZipFileExtensions.CreateEntryFromFileAsync
ZipFileExtensions.ExtractToDirectoryAsync
ZipFileExtensions.ExtractToFileAsync

Examples:

// Extract a Zip archive
await ZipFile.ExtractToDirectoryAsync("archive.zip", "destinationFolder", overwriteFiles: true);

// Create a Zip archive
await ZipFile.CreateFromDirectoryAsync("sourceFolder", "archive.zip", CompressionLevel.SmallestSize, includeBaseDirectory: true, entryNameEncoding: Encoding.UTF8);

// Open an archive
await using ZipArchive archive = ZipFile.OpenReadAsync("archive.zip");

// Fine-grained manipulation
using FileStream archiveStream = File.OpenRead("archive.zip");
await using (ZipArchive archive = await ZipArchive.CreateAsync(archiveStream, ZipArchiveMode.Update, leaveOpen: false, entryNameEncoding: Encoding.UTF8))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        // Extract an entry to the filesystem
        await entry.ExtractToFileAsync(destinationFileName: "file.txt", overwrite: true);

        // Open an entry's stream
        await using Stream entryStream = await entry.OpenAsync();

        // Create an entry from a filesystem object
        ZipArchiveEntry createdEntry = await archive.CreateEntryFromFileAsync(sourceFileName "path/to/file.txt", entryName: "file.txt");
    }
}
```</issue_description>

<agent_instructions>Your ultimate goal above everything else is to make the app smoother and more responsive without making any breaking changes to the import/export format or the database</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

- 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>
Copilot AI changed the title [WIP] Improve responsiveness of import/export loading screens Use async ZIP APIs and improve loading screen UX for import/export Feb 11, 2026
Copilot AI requested a review from danielchalmers February 11, 2026 01:44
@danielchalmers danielchalmers marked this pull request as ready for review February 11, 2026 01:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make import/export UX more responsive

2 participants