Files
fluid-explorer/ViewModels/ExplorerTabViewModel.cs

112 lines
3.7 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using FluidExplorer.Navigation;
using FluidExplorer.Services;
using FluidExplorer.Services.FileSystem;
using FluidExplorer.Services.ItemVisuals;
using FluidExplorer.Services.Operations;
using FluidExplorer.Services.Search;
using Microsoft.UI.Dispatching;
using PathHelper = FluidExplorer.Services.FileSystem.PathHelper;
namespace FluidExplorer.ViewModels;
/// <summary>一个标签页:包含主窗格,可选第二窗格(双窗格模式,搬文件不用来回切)。</summary>
public sealed partial class ExplorerTabViewModel : ObservableObject
{
private readonly IFileSystemService _fs;
private readonly SearchService _search;
private readonly IFileOperationService _operations;
private readonly ItemVisualService _visuals;
private readonly IFileClipboard _clipboard;
private readonly AppSettings _settings;
private readonly DispatcherQueue _ui;
[ObservableProperty] private bool _isDualPane;
[ObservableProperty] private bool _isActivePaneSecondary;
[ObservableProperty] private string _header = "新标签页";
[ObservableProperty] private string _glyph = "\uE8B7";
public ExplorerTabViewModel(
IFileSystemService fs,
SearchService search,
IFileOperationService operations,
ItemVisualService visuals,
IFileClipboard clipboard,
AppSettings settings,
DispatcherQueue ui,
NavigationLocation start)
{
_fs = fs;
_search = search;
_operations = operations;
_visuals = visuals;
_clipboard = clipboard;
_settings = settings;
_ui = ui;
Primary = new ExplorerPaneViewModel(fs, search, operations, visuals, clipboard, settings, ui);
Primary.PropertyChanged += (_, e) =>
{
if (e.PropertyName == nameof(ExplorerPaneViewModel.Title)) UpdateHeader();
};
Primary.SettingsChanged += (_, _) => UpdateHeader();
_ = Primary.NavigateAsync(start);
UpdateHeader();
}
public ExplorerPaneViewModel Primary { get; }
[ObservableProperty] private ExplorerPaneViewModel? _secondary;
public ExplorerPaneViewModel ActivePane => IsDualPane && IsActivePaneSecondary && Secondary is not null ? Secondary : Primary;
public ExplorerPaneViewModel EnsureSecondary()
{
if (Secondary is not null) return Secondary;
var pane = new ExplorerPaneViewModel(_fs, _search, _operations, _visuals, _clipboard, _settings, _ui)
{
ShowSidebar = false
};
pane.PropertyChanged += (_, e) =>
{
if (e.PropertyName == nameof(ExplorerPaneViewModel.Title)) UpdateHeader();
};
Secondary = pane;
return pane;
}
public void ToggleDualPane()
{
if (IsDualPane)
{
IsDualPane = false;
IsActivePaneSecondary = false;
return;
}
var secondary = EnsureSecondary();
if (string.IsNullOrEmpty(secondary.CurrentPath) || secondary.CurrentPath.StartsWith("::", StringComparison.Ordinal))
{
// 第二个窗格默认停在与主窗格同级的目录,便于对拖
var parent = PathHelper.GetParent(Primary.CurrentPath);
_ = secondary.NavigateAsync(NavigationLocation.FromPath(
Directory.Exists(parent) ? parent : Primary.CurrentPath));
}
IsDualPane = true;
}
private void UpdateHeader()
{
Header = Primary.IsSearchActive && !string.IsNullOrWhiteSpace(Primary.SearchText)
? $"搜索:{Primary.SearchText}"
: Primary.Title;
Glyph = Primary.Glyph;
}
public void Dispose()
{
Primary.Dispose();
Secondary?.Dispose();
}
}