Show folder names immediately and refresh stale index sizes without walking the whole drive.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
23
src/Explorer.App/Settings/Pages/AdvancedSettingsPage.xaml
Normal file
23
src/Explorer.App/Settings/Pages/AdvancedSettingsPage.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.AdvancedSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Advanced" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Technical tool paths. Leave a path empty to search Program Files and PATH."/>
|
||||
|
||||
<TextBlock Text="Git" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<TextBlock Style="{StaticResource SettingsPathHelp}"
|
||||
Text="Repository badges and Git actions use git.exe when it is installed. Leave the path empty to look in Program Files and PATH. Git is not bundled. There is no branch UI or credential dialog."/>
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Content="Browse…" MinWidth="88" Height="28"
|
||||
Click="OnBrowseGit" Margin="8,0,0,0"
|
||||
AutomationProperties.Name="Browse for Git"/>
|
||||
<TextBox Text="{Binding GitPath, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutomationProperties.Name="Git path"/>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
24
src/Explorer.App/Settings/Pages/AdvancedSettingsPage.xaml.cs
Normal file
24
src/Explorer.App/Settings/Pages/AdvancedSettingsPage.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Explorer.App.Settings;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class AdvancedSettingsPage : UserControl
|
||||
{
|
||||
public AdvancedSettingsPage() => InitializeComponent();
|
||||
|
||||
private void OnBrowseGit(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is SettingsDraft draft
|
||||
&& SettingsPathBrowse.TryPick(
|
||||
Window.GetWindow(this),
|
||||
"Git executable",
|
||||
"Git|git.exe|Executables|*.exe|All files|*.*",
|
||||
draft.GitPath,
|
||||
out var path))
|
||||
{
|
||||
draft.GitPath = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Explorer.App/Settings/Pages/AppearanceSettingsPage.xaml
Normal file
19
src/Explorer.App/Settings/Pages/AppearanceSettingsPage.xaml
Normal file
@@ -0,0 +1,19 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.AppearanceSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Appearance" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Visual options for Explorer Workbench."/>
|
||||
|
||||
<TextBlock Text="Theme" Foreground="{DynamicResource FgMuted}" Margin="0,0,0,8"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<RadioButton Content="Dark" GroupName="SettingsTheme" Margin="0,0,16,0"
|
||||
IsChecked="{Binding IsDarkTheme, Mode=TwoWay}"/>
|
||||
<RadioButton Content="Light" GroupName="SettingsTheme"
|
||||
IsChecked="{Binding IsLightTheme, Mode=TwoWay}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class AppearanceSettingsPage : UserControl
|
||||
{
|
||||
public AppearanceSettingsPage() => InitializeComponent();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.FileOperationsSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="File Operations" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Queue behavior and tools used for copy, move, archive, and convert work."/>
|
||||
|
||||
<TextBlock Text="File operations queue" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Auto clear queue when done"
|
||||
IsChecked="{Binding AutoClearQueueWhenDone}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="Finished copy, move, delete, and rename steps are removed automatically. Failed items stay until you dismiss or retry them. The queue is restored after restart."/>
|
||||
|
||||
<TextBlock Text="7-Zip" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<TextBlock Style="{StaticResource SettingsPathHelp}"
|
||||
Text="Extract, compress, add, and verify use 7-Zip when it is installed. Leave the path empty to look in Program Files and PATH. 7-Zip is not bundled with Explorer Workbench."/>
|
||||
<DockPanel Margin="0,0,0,18">
|
||||
<Button DockPanel.Dock="Right" Content="Browse…" MinWidth="88" Height="28"
|
||||
Click="OnBrowseSevenZip" Margin="8,0,0,0"
|
||||
AutomationProperties.Name="Browse for 7-Zip"/>
|
||||
<TextBox Text="{Binding SevenZipPath, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutomationProperties.Name="7-Zip path"/>
|
||||
</DockPanel>
|
||||
|
||||
<TextBlock Text="FFmpeg" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<TextBlock Style="{StaticResource SettingsPathHelp}"
|
||||
Text="Convert uses ffmpeg.exe from a Windows zip/build (ffprobe and ffplay are not required). Leave the path empty to look in Program Files\ffmpeg\bin and PATH. FFmpeg is not bundled with Explorer Workbench."/>
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Content="Browse…" MinWidth="88" Height="28"
|
||||
Click="OnBrowseFfmpeg" Margin="8,0,0,0"
|
||||
AutomationProperties.Name="Browse for FFmpeg"/>
|
||||
<TextBox Text="{Binding FfmpegPath, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutomationProperties.Name="FFmpeg path"/>
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Explorer.App.Settings;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class FileOperationsSettingsPage : UserControl
|
||||
{
|
||||
public FileOperationsSettingsPage() => InitializeComponent();
|
||||
|
||||
private void OnBrowseSevenZip(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is SettingsDraft draft
|
||||
&& SettingsPathBrowse.TryPick(
|
||||
Window.GetWindow(this),
|
||||
"7-Zip executable",
|
||||
"7-Zip|7z.exe;7za.exe|Executables|*.exe|All files|*.*",
|
||||
draft.SevenZipPath,
|
||||
out var path))
|
||||
{
|
||||
draft.SevenZipPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBrowseFfmpeg(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is SettingsDraft draft
|
||||
&& SettingsPathBrowse.TryPick(
|
||||
Window.GetWindow(this),
|
||||
"FFmpeg executable",
|
||||
"FFmpeg|ffmpeg.exe|Executables|*.exe|All files|*.*",
|
||||
draft.FfmpegPath,
|
||||
out var path))
|
||||
{
|
||||
draft.FfmpegPath = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Explorer.App/Settings/Pages/GeneralSettingsPage.xaml
Normal file
19
src/Explorer.App/Settings/Pages/GeneralSettingsPage.xaml
Normal file
@@ -0,0 +1,19 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.GeneralSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="General" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Startup and application behavior. These options do not change Windows Explorer settings."/>
|
||||
|
||||
<TextBlock Text="Background host" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Start Explorer.Host.exe at Windows sign-in"
|
||||
IsChecked="{Binding BackgroundHostAtLogon}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}" Margin="24,0,0,0"
|
||||
Text="Adds Explorer.Host.exe to your Windows sign-in programs for this user. No administrator rights. The window connects to Explorer.Host.exe for indexing and the queue. If the host is not running, the window starts it. Only the host opens the index for write. A tray icon stays while the host is running: open the window, or quit the host. File → Stop background host does the same from the window."/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class GeneralSettingsPage : UserControl
|
||||
{
|
||||
public GeneralSettingsPage() => InitializeComponent();
|
||||
}
|
||||
51
src/Explorer.App/Settings/Pages/IndexingSettingsPage.xaml
Normal file
51
src/Explorer.App/Settings/Pages/IndexingSettingsPage.xaml
Normal file
@@ -0,0 +1,51 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.IndexingSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Indexing" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="What Workbench records in the local index. Online-only cloud files are never hydrated."/>
|
||||
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Include archive contents in the index"
|
||||
IsChecked="{Binding IndexArchiveContents}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="When enabled, a scan lists files inside ZIP, RAR, 7z, TAR, and similar archives from the archive catalog — files are not extracted. Individual uncompressed sizes are stored. Folder totals still use the archive’s size on disk. Online-only cloud archives are skipped."/>
|
||||
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Automatically index removable drives when they appear"
|
||||
IsChecked="{Binding AutoIndexRemovable}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="USB and other removable volumes are queued for a full scan when they come online and are not indexed yet. Cloud locations are never auto-indexed. Online-only files are not hydrated."/>
|
||||
|
||||
<TextBlock Text="Idle maintenance" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="When you are not using the PC, the background host can hash duplicates, refresh stale local indexes, and capture history. Copy, move, and other jobs you started keep running. Cloud files are never hydrated. Network and removable locations are not scanned automatically."/>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Enable background maintenance when idle"
|
||||
IsChecked="{Binding BackgroundMaintenanceWhenIdle}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="The host watches Windows idle time even if this window is closed. Conservative defaults wait 10 minutes and prefer AC power."/>
|
||||
<TextBlock Text="Idle for" Foreground="{DynamicResource FgMuted}" Margin="0,0,0,8"
|
||||
IsEnabled="{Binding BackgroundMaintenanceWhenIdle}"/>
|
||||
<DockPanel LastChildFill="False" Margin="0,0,0,14">
|
||||
<ComboBox Width="80" HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding IdleThresholdChoices}"
|
||||
SelectedItem="{Binding IdleMaintenanceMinutes}"
|
||||
IsEnabled="{Binding BackgroundMaintenanceWhenIdle}"
|
||||
AutomationProperties.Name="Idle threshold in minutes"/>
|
||||
<TextBlock Text="minutes" VerticalAlignment="Center" Margin="10,0,0,0"
|
||||
Foreground="{DynamicResource FgMuted}"
|
||||
IsEnabled="{Binding BackgroundMaintenanceWhenIdle}"/>
|
||||
</DockPanel>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Only run expensive maintenance on AC power"
|
||||
IsChecked="{Binding IdleMaintenanceAcOnly}"
|
||||
IsEnabled="{Binding BackgroundMaintenanceWhenIdle}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}" Margin="24,0,0,0"
|
||||
Text="Skips hashing and idle rescans on battery so a laptop is not drained in the background."/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class IndexingSettingsPage : UserControl
|
||||
{
|
||||
public IndexingSettingsPage() => InitializeComponent();
|
||||
}
|
||||
47
src/Explorer.App/Settings/Pages/NavigationSettingsPage.xaml
Normal file
47
src/Explorer.App/Settings/Pages/NavigationSettingsPage.xaml
Normal file
@@ -0,0 +1,47 @@
|
||||
<UserControl x:Class="Explorer.App.Settings.Pages.NavigationSettingsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
DataContext="{Binding Draft, RelativeSource={RelativeSource AncestorType=Window}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Navigation" Style="{StaticResource SettingsHeading}"
|
||||
AutomationProperties.HeadingLevel="Level1"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Locations tree, grouping, and what Workbench shows while browsing. These options only change what Explorer Workbench shows and indexes. Windows settings and files are not modified."/>
|
||||
|
||||
<TextBlock Text="Locations tree" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<TextBlock Style="{StaticResource SettingsIntro}"
|
||||
Text="Choose whether network and cloud locations appear as their own top-level items, or are collected under a group next to This PC."/>
|
||||
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Group network drives under Network"
|
||||
IsChecked="{Binding GroupNetworkPlaces}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="Mapped letters and UNC shares become children of a Network item. This PC then shows only local and removable drives."/>
|
||||
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Group cloud locations under Cloud"
|
||||
IsChecked="{Binding GroupCloudPlaces}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="OneDrive, Google Drive, and Nextcloud become children of a Cloud item. The two options are independent."/>
|
||||
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Prefer Favorites when synchronizing the locations tree"
|
||||
IsChecked="{Binding PreferFavoritesInTree}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="Off (default): keep the current tree context. Opening a folder under This PC, Home, Network, or Cloud does not switch the tree to Favorites just because that folder is also pinned. When you opened the folder from a Favorite, the tree stays under Favorites. On: if the folder is under a pinned Favorite, the tree selects that Favorite. Breadcrumbs and the filesystem path are unchanged."/>
|
||||
|
||||
<TextBlock Text="Filesystem visibility" Style="{StaticResource SettingsHeading}" Margin="0,8,0,10"
|
||||
AutomationProperties.HeadingLevel="Level2"/>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Show hidden files"
|
||||
IsChecked="{Binding ShowHiddenFiles}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}"
|
||||
Text="Items marked Hidden by Windows. Default matches the current Explorer Workbench listing."/>
|
||||
<CheckBox Margin="0,0,0,6"
|
||||
Content="Show protected system locations"
|
||||
IsChecked="{Binding ShowProtectedSystemLocations}"/>
|
||||
<TextBlock Style="{StaticResource SettingsHelp}" Margin="24,0,0,0"
|
||||
Text="System Volume Information, Recycle Bin, Recovery, and similar locations. When a folder cannot be read, its size is shown as access denied — never as 0 bytes. Administrator rights are detected but never requested automatically."/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Explorer.App.Settings.Pages;
|
||||
|
||||
public partial class NavigationSettingsPage : UserControl
|
||||
{
|
||||
public NavigationSettingsPage() => InitializeComponent();
|
||||
}
|
||||
20
src/Explorer.App/Settings/SettingsCatalog.cs
Normal file
20
src/Explorer.App/Settings/SettingsCatalog.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Explorer.App.Settings.Pages;
|
||||
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public static class SettingsCatalog
|
||||
{
|
||||
public static IReadOnlyList<SettingsCategory> Create()
|
||||
{
|
||||
// Storage & Analysis and Network & Cloud stay out of the list until they have settings.
|
||||
return
|
||||
[
|
||||
new(SettingsCategoryId.General, "General", new GeneralSettingsPage()),
|
||||
new(SettingsCategoryId.Appearance, "Appearance", new AppearanceSettingsPage()),
|
||||
new(SettingsCategoryId.Navigation, "Navigation", new NavigationSettingsPage()),
|
||||
new(SettingsCategoryId.FileOperations, "File Operations", new FileOperationsSettingsPage()),
|
||||
new(SettingsCategoryId.Indexing, "Indexing", new IndexingSettingsPage()),
|
||||
new(SettingsCategoryId.Advanced, "Advanced", new AdvancedSettingsPage())
|
||||
];
|
||||
}
|
||||
}
|
||||
17
src/Explorer.App/Settings/SettingsCategory.cs
Normal file
17
src/Explorer.App/Settings/SettingsCategory.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public sealed class SettingsCategory
|
||||
{
|
||||
public SettingsCategory(SettingsCategoryId id, string title, FrameworkElement page)
|
||||
{
|
||||
Id = id;
|
||||
Title = title;
|
||||
Page = page;
|
||||
}
|
||||
|
||||
public SettingsCategoryId Id { get; }
|
||||
public string Title { get; }
|
||||
public FrameworkElement Page { get; }
|
||||
}
|
||||
13
src/Explorer.App/Settings/SettingsCategoryId.cs
Normal file
13
src/Explorer.App/Settings/SettingsCategoryId.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public enum SettingsCategoryId
|
||||
{
|
||||
General,
|
||||
Appearance,
|
||||
Navigation,
|
||||
FileOperations,
|
||||
Indexing,
|
||||
StorageAnalysis,
|
||||
NetworkCloud,
|
||||
Advanced
|
||||
}
|
||||
101
src/Explorer.App/Settings/SettingsDraft.cs
Normal file
101
src/Explorer.App/Settings/SettingsDraft.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Explorer.Application;
|
||||
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public sealed partial class SettingsDraft : ObservableObject
|
||||
{
|
||||
[ObservableProperty] private string _theme = "Dark";
|
||||
[ObservableProperty] private bool _groupNetworkPlaces;
|
||||
[ObservableProperty] private bool _groupCloudPlaces;
|
||||
[ObservableProperty] private bool _preferFavoritesInTree;
|
||||
[ObservableProperty] private bool _showHiddenFiles = true;
|
||||
[ObservableProperty] private bool _showProtectedSystemLocations;
|
||||
[ObservableProperty] private bool _autoClearQueueWhenDone;
|
||||
[ObservableProperty] private bool _indexArchiveContents;
|
||||
[ObservableProperty] private bool _autoIndexRemovable;
|
||||
[ObservableProperty] private bool _backgroundHostAtLogon;
|
||||
[ObservableProperty] private bool _backgroundMaintenanceWhenIdle = true;
|
||||
[ObservableProperty] private int _idleMaintenanceMinutes = 10;
|
||||
[ObservableProperty] private bool _idleMaintenanceAcOnly = true;
|
||||
[ObservableProperty] private string _sevenZipPath = "";
|
||||
[ObservableProperty] private string _gitPath = "";
|
||||
[ObservableProperty] private string _ffmpegPath = "";
|
||||
|
||||
public IReadOnlyList<int> IdleThresholdChoices { get; } = [5, 10, 30];
|
||||
|
||||
public bool IsDarkTheme
|
||||
{
|
||||
get => Theme != "Light";
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Theme = "Dark";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsLightTheme
|
||||
{
|
||||
get => Theme == "Light";
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Theme = "Light";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static SettingsDraft From(UiPreferences preferences)
|
||||
=> new()
|
||||
{
|
||||
Theme = UiPreferencesStore.NormalizeTheme(preferences.Theme),
|
||||
GroupNetworkPlaces = preferences.GroupNetworkPlaces,
|
||||
GroupCloudPlaces = preferences.GroupCloudPlaces,
|
||||
PreferFavoritesInTree = preferences.PreferFavoritesInTree,
|
||||
ShowHiddenFiles = preferences.ShowHiddenFiles,
|
||||
ShowProtectedSystemLocations = preferences.ShowProtectedSystemLocations,
|
||||
AutoClearQueueWhenDone = preferences.AutoClearQueueWhenDone,
|
||||
IndexArchiveContents = preferences.IndexArchiveContents,
|
||||
AutoIndexRemovable = preferences.AutoIndexRemovable,
|
||||
BackgroundHostAtLogon = preferences.BackgroundHostAtLogon,
|
||||
BackgroundMaintenanceWhenIdle = preferences.BackgroundMaintenanceWhenIdle,
|
||||
IdleMaintenanceMinutes = UiPreferencesStore.NormalizeIdleMinutes(preferences.IdleMaintenanceMinutes),
|
||||
IdleMaintenanceAcOnly = preferences.IdleMaintenanceAcOnly,
|
||||
SevenZipPath = preferences.SevenZipPath ?? "",
|
||||
GitPath = preferences.GitPath ?? "",
|
||||
FfmpegPath = preferences.FfmpegPath ?? ""
|
||||
};
|
||||
|
||||
public UiPreferences ApplyTo(UiPreferences stored)
|
||||
=> stored with
|
||||
{
|
||||
Theme = UiPreferencesStore.NormalizeTheme(Theme),
|
||||
GroupNetworkPlaces = GroupNetworkPlaces,
|
||||
GroupCloudPlaces = GroupCloudPlaces,
|
||||
PreferFavoritesInTree = PreferFavoritesInTree,
|
||||
ShowHiddenFiles = ShowHiddenFiles,
|
||||
ShowProtectedSystemLocations = ShowProtectedSystemLocations,
|
||||
AutoClearQueueWhenDone = AutoClearQueueWhenDone,
|
||||
IndexArchiveContents = IndexArchiveContents,
|
||||
AutoIndexRemovable = AutoIndexRemovable,
|
||||
BackgroundHostAtLogon = BackgroundHostAtLogon,
|
||||
BackgroundMaintenanceWhenIdle = BackgroundMaintenanceWhenIdle,
|
||||
IdleMaintenanceMinutes = UiPreferencesStore.NormalizeIdleMinutes(IdleMaintenanceMinutes),
|
||||
IdleMaintenanceAcOnly = IdleMaintenanceAcOnly,
|
||||
SevenZipPath = EmptyToNull(SevenZipPath),
|
||||
GitPath = EmptyToNull(GitPath),
|
||||
FfmpegPath = EmptyToNull(FfmpegPath)
|
||||
};
|
||||
|
||||
partial void OnThemeChanged(string value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsDarkTheme));
|
||||
OnPropertyChanged(nameof(IsLightTheme));
|
||||
}
|
||||
|
||||
private static string? EmptyToNull(string value)
|
||||
=> string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
}
|
||||
25
src/Explorer.App/Settings/SettingsPathBrowse.cs
Normal file
25
src/Explorer.App/Settings/SettingsPathBrowse.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Windows;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
internal static class SettingsPathBrowse
|
||||
{
|
||||
public static bool TryPick(Window? owner, string title, string filter, string? current, out string path)
|
||||
{
|
||||
var dlg = new OpenFileDialog
|
||||
{
|
||||
Title = title,
|
||||
Filter = filter,
|
||||
FileName = current ?? ""
|
||||
};
|
||||
if (dlg.ShowDialog(owner) == true)
|
||||
{
|
||||
path = dlg.FileName;
|
||||
return true;
|
||||
}
|
||||
|
||||
path = "";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
6
src/Explorer.App/Settings/SettingsSession.cs
Normal file
6
src/Explorer.App/Settings/SettingsSession.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public static class SettingsSession
|
||||
{
|
||||
public static SettingsCategoryId? LastCategory { get; set; }
|
||||
}
|
||||
27
src/Explorer.App/Settings/SettingsShell.cs
Normal file
27
src/Explorer.App/Settings/SettingsShell.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Explorer.App.Settings;
|
||||
|
||||
public sealed partial class SettingsShell : ObservableObject
|
||||
{
|
||||
public SettingsShell(SettingsDraft draft, IReadOnlyList<SettingsCategory> categories)
|
||||
{
|
||||
Draft = draft;
|
||||
Categories = categories;
|
||||
_selectedCategory = Restore(categories);
|
||||
}
|
||||
|
||||
public SettingsDraft Draft { get; }
|
||||
public IReadOnlyList<SettingsCategory> Categories { get; }
|
||||
|
||||
[ObservableProperty] private SettingsCategory _selectedCategory;
|
||||
|
||||
partial void OnSelectedCategoryChanged(SettingsCategory value)
|
||||
=> SettingsSession.LastCategory = value.Id;
|
||||
|
||||
private static SettingsCategory Restore(IReadOnlyList<SettingsCategory> categories)
|
||||
{
|
||||
var last = SettingsSession.LastCategory;
|
||||
return categories.FirstOrDefault(c => c.Id == last) ?? categories[0];
|
||||
}
|
||||
}
|
||||
25
src/Explorer.App/Settings/SettingsStyles.xaml
Normal file
25
src/Explorer.App/Settings/SettingsStyles.xaml
Normal file
@@ -0,0 +1,25 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Style x:Key="SettingsHeading" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||
</Style>
|
||||
<Style x:Key="SettingsIntro" TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource FgMuted}"/>
|
||||
<Setter Property="Margin" Value="0,0,0,12"/>
|
||||
</Style>
|
||||
<Style x:Key="SettingsHelp" TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource FgMuted}"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="24,0,0,14"/>
|
||||
</Style>
|
||||
<Style x:Key="SettingsPathHelp" TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource FgMuted}"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Margin" Value="0,0,0,8"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
Reference in New Issue
Block a user