Initial commit: FluidExplorer:从零实现的 WinUI 3 文件资源管理器替代品(Mica、命令栏、面包屑)
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using FluidExplorer.Models;
|
||||
|
||||
namespace FluidExplorer.Services;
|
||||
|
||||
/// <summary>外观模式:默认跟随系统(深浅色自动切换)。</summary>
|
||||
public enum AppThemeMode
|
||||
{
|
||||
System,
|
||||
Light,
|
||||
Dark
|
||||
}
|
||||
|
||||
public enum SearchScope
|
||||
{
|
||||
/// <summary>全盘(走 NTFS 索引,Everything 式,毫秒级)。</summary>
|
||||
Global,
|
||||
/// <summary>仅当前文件夹及其子目录。</summary>
|
||||
CurrentFolder
|
||||
}
|
||||
|
||||
public sealed class FolderViewState
|
||||
{
|
||||
public ViewMode ViewMode { get; set; } = ViewMode.Details;
|
||||
public SortColumn SortColumn { get; set; } = SortColumn.Name;
|
||||
public SortDirection SortDirection { get; set; } = SortDirection.Ascending;
|
||||
public GroupBy GroupBy { get; set; } = GroupBy.None;
|
||||
}
|
||||
|
||||
/// <summary>用户设置(%LOCALAPPDATA%\FluidExplorer\settings.json),失败时退回程序目录。</summary>
|
||||
public sealed class AppSettings
|
||||
{
|
||||
public AppThemeMode ThemeMode { get; set; } = AppThemeMode.System;
|
||||
|
||||
// 视图
|
||||
public bool ShowHiddenFiles { get; set; }
|
||||
public bool ShowSystemFiles { get; set; }
|
||||
public bool ShowFileExtensions { get; set; } = true;
|
||||
public bool AlwaysShowCheckBoxes { get; set; }
|
||||
public bool ShowStatusBar { get; set; } = true;
|
||||
|
||||
// 浏览
|
||||
public bool OpenFoldersInNewTab { get; set; }
|
||||
public bool DoubleClickToOpen { get; set; } = true;
|
||||
public bool RestoreTabsOnStartup { get; set; } = true;
|
||||
public string DefaultStartPath { get; set; } = "";
|
||||
public List<string> PinnedFolders { get; set; } = [];
|
||||
public List<string> RecentFolders { get; set; } = [];
|
||||
public List<string> OpenTabs { get; set; } = [];
|
||||
public bool DualPane { get; set; }
|
||||
|
||||
// 搜索
|
||||
public SearchScope SearchScope { get; set; } = SearchScope.Global;
|
||||
public List<string> IndexedVolumes { get; set; } = [];
|
||||
public bool IndexOnStartup { get; set; } = true;
|
||||
public bool SearchAsYouType { get; set; } = true;
|
||||
|
||||
// 文件操作
|
||||
public bool DeleteToRecycleBin { get; set; } = true;
|
||||
public ConflictPolicySetting DefaultConflictPolicy { get; set; } = ConflictPolicySetting.Ask;
|
||||
public bool ConfirmPermanentDelete { get; set; } = true;
|
||||
public bool KeepWindowOpenDuringOperations { get; set; } = true;
|
||||
|
||||
// 动效(克制:只保留系统原生的必要动画)
|
||||
public bool AnimationsEnabled { get; set; } = true;
|
||||
|
||||
// 窗口
|
||||
public double WindowLeft { get; set; } = double.NaN;
|
||||
public double WindowTop { get; set; } = double.NaN;
|
||||
public double WindowWidth { get; set; } = 1280;
|
||||
public double WindowHeight { get; set; } = 800;
|
||||
public bool WindowMaximized { get; set; }
|
||||
|
||||
/// <summary>按文件夹记住视图方式(对齐资源管理器的"按文件夹记住视图设置")。</summary>
|
||||
public Dictionary<string, FolderViewState> FolderViews { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
[JsonIgnore]
|
||||
public string SettingsFilePath { get; private set; } = string.Empty;
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
};
|
||||
|
||||
public static AppSettings Load()
|
||||
{
|
||||
foreach (var candidate in CandidatePaths())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(candidate)) continue;
|
||||
var json = File.ReadAllText(candidate);
|
||||
var loaded = JsonSerializer.Deserialize<AppSettings>(json, JsonOptions);
|
||||
if (loaded is null) continue;
|
||||
loaded.SettingsFilePath = candidate;
|
||||
return loaded;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 设置文件损坏时忽略,使用默认值
|
||||
}
|
||||
}
|
||||
|
||||
var settings = new AppSettings();
|
||||
settings.SettingsFilePath = CandidatePaths().First();
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
foreach (var target in CandidatePaths())
|
||||
{
|
||||
try
|
||||
{
|
||||
var dir = Path.GetDirectoryName(target);
|
||||
if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir);
|
||||
SettingsFilePath = target;
|
||||
File.WriteAllText(target, JsonSerializer.Serialize(this, JsonOptions));
|
||||
return;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 换下一个候选位置(例如沙箱/只读环境)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FolderViewState GetFolderView(string path)
|
||||
{
|
||||
if (FolderViews.TryGetValue(path, out var state)) return state;
|
||||
state = new FolderViewState();
|
||||
FolderViews[path] = state;
|
||||
return state;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> CandidatePaths()
|
||||
{
|
||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
if (!string.IsNullOrEmpty(localAppData))
|
||||
yield return Path.Combine(localAppData, "FluidExplorer", "settings.json");
|
||||
yield return Path.Combine(AppContext.BaseDirectory, "settings.json");
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConflictPolicySetting
|
||||
{
|
||||
Ask,
|
||||
Replace,
|
||||
Skip,
|
||||
KeepBoth
|
||||
}
|
||||
Reference in New Issue
Block a user