feat: load the FileDialog drive list asynchronously

This commit is contained in:
karashiiro 2023-05-04 20:59:26 -07:00
parent 59de22b192
commit b1551150c7
4 changed files with 81 additions and 7 deletions

View file

@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading.Tasks;
namespace Dalamud.Interface.ImGuiFileDialog;
/// <summary>
/// A drive list loader. Thread-safety guaranteed.
/// </summary>
public class DriveListLoader
{
private bool initialized;
/// <summary>
/// Initializes a new instance of the <see cref="DriveListLoader"/> class.
/// </summary>
public DriveListLoader()
{
this.Drives = ImmutableArray<DriveInfo>.Empty;
}
/// <summary>
/// Gets the drive list. This may be incomplete if the loader is still loading.
/// </summary>
public IReadOnlyList<DriveInfo> Drives { get; private set; }
/// <summary>
/// Gets a value indicating whether or not the loader is loading.
/// </summary>
public bool Loading { get; private set; }
/// <summary>
/// Loads the drive list, asynchronously.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task LoadDrivesAsync()
{
this.Loading = true;
try
{
await this.InitDrives();
}
finally
{
this.Loading = false;
}
}
private async Task InitDrives()
{
var drives = ImmutableArray<DriveInfo>.Empty;
foreach (var drive in DriveInfo.GetDrives())
{
drives = drives.Add(drive);
if (!this.initialized)
{
// Show results as soon as they load initially, but otherwise keep
// the existing drive list
this.Drives = drives;
}
// Force async to avoid this being invoked synchronously unless it's awaited
await Task.Yield();
}
// Replace the whole drive list
this.Drives = drives;
this.initialized = true;
}
}

View file

@ -12,11 +12,13 @@ public partial class FileDialog
{
private readonly object filesLock = new();
private readonly DriveListLoader driveListLoader = new();
private List<FileStruct> files = new();
private List<FileStruct> filteredFiles = new();
private SortingField currentSortingField = SortingField.FileName;
private bool[] sortDescending = new[] { false, false, false, false };
private bool[] sortDescending = { false, false, false, false };
private enum FileStructType
{
@ -296,12 +298,14 @@ public partial class FileDialog
}
}
private IEnumerable<SideBarItem> GetDrives()
{
return this.driveListLoader.Drives.Select(drive => new SideBarItem(drive.Name, drive.Name, FontAwesomeIcon.Server));
}
private void SetupSideBar()
{
foreach (var drive in DriveInfo.GetDrives())
{
this.drives.Add(new SideBarItem(drive.Name, drive.Name, FontAwesomeIcon.Server));
}
_ = this.driveListLoader.LoadDrivesAsync();
var personal = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Personal));

View file

@ -316,7 +316,7 @@ public partial class FileDialog
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + Scaled(5));
var idx = 0;
foreach (var qa in this.drives.Concat(this.quickAccess).Where(qa => qa.Exists))
foreach (var qa in this.GetDrives().Concat(this.quickAccess).Where(qa => qa.Exists))
{
ImGui.PushID(idx++);
ImGui.SetCursorPosX(Scaled(25));

View file

@ -52,7 +52,6 @@ public partial class FileDialog
private float footerHeight = 0;
private string selectedSideBar = string.Empty;
private List<SideBarItem> drives = new();
private List<SideBarItem> quickAccess = new();
/// <summary>