98 lines
3.5 KiB
C#
98 lines
3.5 KiB
C#
using System.Collections.ObjectModel;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using FluidExplorer.Navigation;
|
|
using FluidExplorer.Services.FileSystem;
|
|
using FluidExplorer.Services.Search;
|
|
using FluidExplorer.Services.Shell;
|
|
using Microsoft.UI.Xaml.Media;
|
|
|
|
namespace FluidExplorer.ViewModels;
|
|
|
|
/// <summary>侧边栏的一个节点(可展开的"此电脑"、可收藏的文件夹、驱动器等)。</summary>
|
|
public sealed partial class SidebarNode : ObservableObject
|
|
{
|
|
[ObservableProperty] private bool _isExpanded;
|
|
[ObservableProperty] private bool _isSelected;
|
|
|
|
public SidebarNode(string displayName, string glyph, NavigationLocation location, bool isExpandable = false)
|
|
{
|
|
DisplayName = displayName;
|
|
Glyph = glyph;
|
|
Location = location;
|
|
IsExpandable = isExpandable;
|
|
}
|
|
|
|
public string DisplayName { get; }
|
|
public string Glyph { get; }
|
|
public NavigationLocation Location { get; }
|
|
public bool IsExpandable { get; }
|
|
public bool CanPin { get; init; }
|
|
|
|
public ObservableCollection<SidebarNode> Children { get; } = [];
|
|
|
|
public bool HasUnrealizedChildren { get; set; }
|
|
|
|
/// <summary>当前文件夹是否属于该节点(用于侧边栏高亮,对齐资源管理器)。</summary>
|
|
public bool Contains(string path)
|
|
{
|
|
if (string.IsNullOrEmpty(path)) return false;
|
|
if (Location.Kind is LocationKind.ThisPc or LocationKind.RecycleBin or LocationKind.Network or LocationKind.Home)
|
|
return string.Equals(Location.Path, path, StringComparison.OrdinalIgnoreCase);
|
|
var root = Location.Path.TrimEnd('\\');
|
|
return path.StartsWith(root, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
public static SidebarNode Create(string name, string glyph, NavigationLocation location, bool expandable = false, bool canPin = false)
|
|
=> new(name, glyph, location, expandable) { CanPin = canPin };
|
|
}
|
|
|
|
/// <summary>面包屑的一段。</summary>
|
|
public sealed partial class BreadcrumbSegment : ObservableObject
|
|
{
|
|
public BreadcrumbSegment(string displayName, string path, bool isDriveRoot)
|
|
{
|
|
DisplayName = displayName;
|
|
Path = path;
|
|
IsDriveRoot = isDriveRoot;
|
|
}
|
|
|
|
public string DisplayName { get; }
|
|
public string Path { get; }
|
|
public bool IsDriveRoot { get; }
|
|
}
|
|
|
|
/// <summary>搜索结果列表里的一行。</summary>
|
|
public sealed partial class SearchResultItem : ObservableObject
|
|
{
|
|
private ImageSource? _icon;
|
|
private ImageSource? _thumbnail;
|
|
|
|
public SearchResultItem(SearchHit hit) => Hit = hit;
|
|
|
|
public SearchHit Hit { get; }
|
|
public string Name => Hit.Name;
|
|
public string Directory => Hit.Directory;
|
|
public string FullPath => Hit.Path;
|
|
public bool IsDirectory => Hit.IsDirectory;
|
|
public long Size => Hit.Size;
|
|
public string SizeText => Hit.Size < 0 ? "—" : Hit.IsDirectory ? string.Empty : Models.FileEntry.FormatSize(Hit.Size);
|
|
public string ModifiedText => Hit.ModifiedUtc == DateTime.MinValue || Hit.ModifiedUtc == default
|
|
? "—"
|
|
: Hit.ModifiedUtc.ToLocalTime().ToString("yyyy/MM/dd HH:mm");
|
|
public string TypeText => Hit.IsDirectory ? "文件夹" : TypeNameResolver.GetTypeName(Hit.Extension, false);
|
|
|
|
public ImageSource? Icon
|
|
{
|
|
get => _icon;
|
|
set { if (!ReferenceEquals(_icon, value)) { _icon = value; OnPropertyChanged(); } }
|
|
}
|
|
|
|
public ImageSource? Thumbnail
|
|
{
|
|
get => _thumbnail;
|
|
set { if (!ReferenceEquals(_thumbnail, value)) { _thumbnail = value; OnPropertyChanged(); } }
|
|
}
|
|
|
|
public DateTime SortModified => Hit.ModifiedUtc;
|
|
}
|