namespace FluidExplorer.Navigation; public enum LocationKind { Home, Gallery, QuickAccess, ThisPc, RecycleBin, Network, Drive, Folder, Search } /// 一个可导航的位置(侧边栏节点、面包屑、标签页都基于它)。 public sealed record NavigationLocation(LocationKind Kind, string Path, string DisplayName, string Glyph) { public static NavigationLocation Home { get; } = new(LocationKind.Home, Services.Shell.KnownFolders.HomeParsingName, "主页", "\uE80F"); public static NavigationLocation Gallery { get; } = new(LocationKind.Gallery, Services.Shell.KnownFolders.GalleryParsingName, "图库", "\uE91B"); public static NavigationLocation ThisPc { get; } = new(LocationKind.ThisPc, Services.Shell.KnownFolders.ThisPcParsingName, "此电脑", "\uE977"); public static NavigationLocation RecycleBin { get; } = new(LocationKind.RecycleBin, Services.Shell.KnownFolders.RecycleBinParsingName, "回收站", "\uE74D"); public static NavigationLocation Network { get; } = new(LocationKind.Network, Services.Shell.KnownFolders.NetworkParsingName, "网络", "\uE968"); public static NavigationLocation FromPath(string path, LocationKind kind = LocationKind.Folder) { var normalized = Services.FileSystem.PathHelper.NormalizeDisplay(path); return new NavigationLocation(kind, normalized, Services.FileSystem.PathHelper.GetName(normalized), "\uE8B7"); } public static NavigationLocation FromDrive(DriveItemInfo drive) => new(LocationKind.Drive, drive.RootPath, drive.DisplayName, drive.Glyph); /// 是否是外壳虚拟位置(不能用 System.IO 直接枚举,需要走 shell: 视图)。 public bool IsVirtual => Kind is LocationKind.Home or LocationKind.Gallery or LocationKind.ThisPc or LocationKind.RecycleBin or LocationKind.Network or LocationKind.Search || Path.StartsWith("::", StringComparison.Ordinal) || Path.StartsWith("shell:", StringComparison.OrdinalIgnoreCase); } public readonly record struct DriveItemInfo(string RootPath, string DisplayName, string Glyph); /// 前进/后退历史(资源管理器行为:新导航截断前进栈)。 public sealed class NavigationHistory { private readonly List _back = []; private readonly List _forward = []; private const int Capacity = 64; public bool CanGoBack => _back.Count > 1; public bool CanGoForward => _forward.Count > 0; public NavigationLocation? Current => _back.Count > 0 ? _back[^1] : null; public void Push(NavigationLocation location) { if (_back.Count > 0 && _back[^1] == location) return; _back.Add(location); if (_back.Count > Capacity) _back.RemoveAt(0); _forward.Clear(); } public NavigationLocation? Back() { if (!CanGoBack) return null; var current = _back[^1]; _back.RemoveAt(_back.Count - 1); _forward.Add(current); return _back[^1]; } public NavigationLocation? Forward() { if (_forward.Count == 0) return null; var next = _forward[^1]; _forward.RemoveAt(_forward.Count - 1); _back.Add(next); return next; } public void Reset(NavigationLocation location) { _back.Clear(); _forward.Clear(); _back.Add(location); } }