Improve file operations, layout memory, and drive status.

Add a sequential file-operations queue with pause, reorder, and optional auto-clear; persist window size and tree width; show free space; and clear leftover indexing status.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-24 01:52:30 +02:00
parent d79605cde9
commit 9bf451932f
41 changed files with 2855 additions and 275 deletions

View File

@@ -6,22 +6,53 @@ namespace Explorer.Presentation;
public sealed partial class FolderItemViewModel : ObservableObject
{
[ObservableProperty] private bool _isSelected;
[ObservableProperty] private bool _isRenaming;
[ObservableProperty] private bool _isDropTarget;
[ObservableProperty] private string _editName = "";
public FolderItemViewModel(FileSystemItem item, bool sizeFromIndex)
{
Item = item;
SizeFromIndex = sizeFromIndex;
_editName = item.Name;
}
public void BeginRename()
{
EditName = Item.Name;
IsRenaming = true;
}
public void CancelRename()
{
IsRenaming = false;
EditName = Item.Name;
}
public FileSystemItem Item { get; }
public bool SizeFromIndex { get; }
public string Name => Item.Name;
public string Name => Item.DisplayName ?? Item.Name;
public string FullPath => Item.FullPath;
public bool IsDirectory => Item.IsDirectory;
public string TypeLabel => Item.IsDirectory ? "File folder" : (Item.ExtensionDisplay());
public string SizeLabel => Item.IsDirectory && !SizeFromIndex && Item.SizeBytes == 0
? ""
: Formatters.Size(Item.SizeBytes);
public string TypeLabel => Item.Location.IsRecycleBin
? "Recycle Bin"
: Item.IsDirectory ? "File folder" : (Item.ExtensionDisplay());
public string SizeLabel => Item.SizeKnowledge switch
{
SizeKnowledge.Unknown when Item.Location.AccessDenied => "Access denied",
SizeKnowledge.Unknown => "",
SizeKnowledge.Partial when Item.SizeBytes > 0 => $"{Formatters.Size(Item.SizeBytes)} (partial)",
SizeKnowledge.Partial => "Access denied",
_ when Item.IsDirectory && !SizeFromIndex && Item.SizeBytes == 0 => "",
_ => Formatters.Size(Item.SizeBytes)
};
public string FreeSpaceLabel => Item.FreeSpaceBytes is long free ? Formatters.Size(free) : "";
public string FreeSpaceTooltip
=> Item.FreeSpaceBytes is long free && Item.CapacityBytes is long total && total > 0
? $"{Formatters.Size(free)} free of {Formatters.Size(total)}"
: FreeSpaceLabel;
public string StatusGlyph => Item.Location.IsRecycleBin ? "🗑" : Item.Location.IsProtected || Item.Location.AccessDenied ? "⚠" : "";
public bool HasStatusGlyph => StatusGlyph.Length > 0;
public string ModifiedLabel => Formatters.Date(Item.ModifiedUtc);
public string CreatedLabel => Formatters.Date(Item.CreatedUtc);
public string IconGlyph => Item.IsDirectory ? "\uE8B7" : "\uE8A5";
@@ -44,6 +75,11 @@ public sealed partial class FolderItemViewModel : ObservableObject
: $"{CloudStatus} · Size {logical} · On disk {Formatters.Size(disk)}";
}
if (Item.Location.AccessDenied)
{
return string.IsNullOrEmpty(CloudStatus) ? "Access denied" : $"{CloudStatus} · Access denied";
}
return string.IsNullOrEmpty(CloudStatus) ? logical : $"{CloudStatus} · {logical}";
}
}