Add settings, cloud places, and optional archive-content indexing.
Keep official clients in charge of sync while Explorer can group locations, persist UI prefs, and list zip/rar/7z members without extracting them. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Explorer.Domain;
|
||||
using Explorer.Presentation;
|
||||
using Explorer.Presentation.ViewModels;
|
||||
@@ -129,6 +130,70 @@ public partial class MainWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTreeContextOpening(object sender, ContextMenuEventArgs e)
|
||||
{
|
||||
var node = FindTreeNode(e.OriginalSource as DependencyObject);
|
||||
if (node is null || !node.CanRemove)
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
node.IsSelected = true;
|
||||
RemoveLocationMenu.Tag = node.Path;
|
||||
}
|
||||
|
||||
private async void OnRemoveLocation(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var path = (sender as FrameworkElement)?.Tag as string
|
||||
?? RemoveLocationMenu.Tag as string
|
||||
?? Vm.ActivePane.SelectedItems.FirstOrDefault()?.FullPath
|
||||
?? (Vm.Tree.Roots.SelectMany(FlattenTree).FirstOrDefault(n => n.IsSelected && n.CanRemove)?.Path);
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var label = Vm.Tree.Roots.SelectMany(FlattenTree).FirstOrDefault(n => NavigationTreeViewModel.PathsEqual(n.Path, path))?.Label
|
||||
?? path;
|
||||
var confirm = MessageBox.Show(
|
||||
this,
|
||||
$"Remove “{label}” from Explorer?\n\nThe link and its index data will be deleted. Files on disk or the server are not touched.\n\nIf Windows still has this location, it will appear again.",
|
||||
"Remove from Explorer",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
if (confirm != MessageBoxResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Vm.ForgetSourceAsync(path).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
private static IEnumerable<NavNodeViewModel> FlattenTree(NavNodeViewModel node)
|
||||
{
|
||||
yield return node;
|
||||
foreach (var child in node.Children.Where(c => !c.IsPlaceholder).SelectMany(FlattenTree))
|
||||
{
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
|
||||
private static NavNodeViewModel? FindTreeNode(DependencyObject? origin)
|
||||
{
|
||||
while (origin is not null)
|
||||
{
|
||||
if (origin is TreeViewItem { DataContext: NavNodeViewModel node })
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
origin = origin is Visual ? VisualTreeHelper.GetParent(origin) : LogicalTreeHelper.GetParent(origin);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async void OnTreeExpanded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is TreeViewItem { DataContext: NavNodeViewModel node })
|
||||
@@ -442,6 +507,13 @@ public partial class MainWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnOpenSettings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new SettingsWindow(Vm) { Owner = this };
|
||||
dlg.ShowDialog();
|
||||
await Vm.RefreshForgetActionAsync().ConfigureAwait(true);
|
||||
}
|
||||
|
||||
private void OnAddNetwork(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var path = PromptWindow.Ask(this, "Add network location", "Network path (\\\\server\\share):", @"\\");
|
||||
@@ -453,10 +525,19 @@ public partial class MainWindow : Window
|
||||
}
|
||||
|
||||
private async void OnAddOneDrive(object sender, RoutedEventArgs e)
|
||||
=> await AddCloudFolderAsync("Add OneDrive folder", MainViewModel.OneDriveProviderId).ConfigureAwait(true);
|
||||
|
||||
private async void OnAddGoogleDrive(object sender, RoutedEventArgs e)
|
||||
=> await AddCloudFolderAsync("Add Google Drive folder", MainViewModel.GoogleDriveProviderId).ConfigureAwait(true);
|
||||
|
||||
private async void OnAddNextcloud(object sender, RoutedEventArgs e)
|
||||
=> await AddCloudFolderAsync("Add Nextcloud folder", MainViewModel.NextcloudProviderId).ConfigureAwait(true);
|
||||
|
||||
private async Task AddCloudFolderAsync(string title, string providerId)
|
||||
{
|
||||
var picker = new Microsoft.Win32.OpenFolderDialog
|
||||
{
|
||||
Title = "Add OneDrive folder",
|
||||
Title = title,
|
||||
Multiselect = false
|
||||
};
|
||||
if (picker.ShowDialog(this) != true || string.IsNullOrWhiteSpace(picker.FolderName))
|
||||
@@ -464,7 +545,7 @@ public partial class MainWindow : Window
|
||||
return;
|
||||
}
|
||||
|
||||
await Vm.AddCloudFolderAsync(picker.FolderName).ConfigureAwait(true);
|
||||
await Vm.AddCloudFolderAsync(picker.FolderName, providerId).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
private async void OnPreviewKeyDown(object sender, KeyEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user