147 lines
5.6 KiB
C#
147 lines
5.6 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using Explorer.Domain;
|
|
|
|
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; private set; }
|
|
public bool SizeFromIndex { get; private set; }
|
|
|
|
public void Apply(FileSystemItem item, bool? sizeFromIndex = null)
|
|
{
|
|
Item = item;
|
|
if (sizeFromIndex is bool value)
|
|
{
|
|
SizeFromIndex = value;
|
|
}
|
|
|
|
OnPropertyChanged(string.Empty);
|
|
}
|
|
public string Name => Item.DisplayName ?? Item.Name;
|
|
public string FullPath => Item.FullPath;
|
|
public bool IsDirectory => Item.IsDirectory;
|
|
public string TypeLabel => Item.AvailableToImport
|
|
? "Available in Windows"
|
|
: 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";
|
|
public bool IsImage => !Item.IsDirectory && MediaKinds.IsImage(Item.Name);
|
|
public bool IsVideo => !Item.IsDirectory && MediaKinds.IsVideo(Item.Name);
|
|
public bool MayHydrateOnRead => Item.Cloud?.MayHydrateOnRead == true
|
|
|| AttributeFlags.MayHydrateOnRead(Item.Attributes);
|
|
public string CloudStatus => Item.Cloud?.StatusText ?? "";
|
|
public string CloudLabel => Item.Cloud?.Availability switch
|
|
{
|
|
CloudAvailability.OnlineOnly => "Online-only",
|
|
CloudAvailability.LocallyAvailable => "Local",
|
|
CloudAvailability.Pinned => "Pinned",
|
|
CloudAvailability.Syncing => "Syncing",
|
|
CloudAvailability.Error => "Error",
|
|
_ => ""
|
|
};
|
|
public bool HasCloudStatus => !string.IsNullOrEmpty(CloudLabel);
|
|
|
|
[ObservableProperty] private string _gitLabel = "";
|
|
public bool HasGitLabel => !string.IsNullOrEmpty(GitLabel);
|
|
|
|
[ObservableProperty] private object? _thumbnail;
|
|
public bool HasThumbnail => Thumbnail is not null;
|
|
|
|
public void SetGit(string? label) => GitLabel = label ?? "";
|
|
|
|
public void SetThumbnail(object? image) => Thumbnail = image;
|
|
|
|
partial void OnGitLabelChanged(string value) => OnPropertyChanged(nameof(HasGitLabel));
|
|
partial void OnThumbnailChanged(object? value) => OnPropertyChanged(nameof(HasThumbnail));
|
|
public string SizeTooltip
|
|
{
|
|
get
|
|
{
|
|
var logical = SizeLabel;
|
|
var allocated = Item.AllocatedSizeBytes ?? Item.Cloud?.AllocatedSizeBytes;
|
|
if (allocated is long disk && disk != Item.SizeBytes && !Item.IsDirectory)
|
|
{
|
|
return string.IsNullOrEmpty(CloudStatus)
|
|
? $"Size {logical} · On disk {Formatters.Size(disk)}"
|
|
: $"{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}";
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static class MediaKinds
|
|
{
|
|
private static readonly HashSet<string> Images = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tif", ".tiff", ".ico", ".jfif"
|
|
};
|
|
|
|
private static readonly HashSet<string> Videos = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
".mp4", ".mkv", ".avi", ".mov", ".wmv", ".webm", ".m4v", ".mpg", ".mpeg"
|
|
};
|
|
|
|
public static bool IsImage(string name) => Images.Contains(Path.GetExtension(name));
|
|
public static bool IsVideo(string name) => Videos.Contains(Path.GetExtension(name));
|
|
}
|
|
|
|
file static class ItemExt
|
|
{
|
|
public static string ExtensionDisplay(this FileSystemItem item)
|
|
{
|
|
var ext = NameNormalizer.Extension(item.Name);
|
|
return string.IsNullOrEmpty(ext) ? "File" : ext.ToUpperInvariant() + " file";
|
|
}
|
|
}
|