Merge branch 'dev' into administrator_mode

This commit is contained in:
Jack Ye 2025-06-17 17:13:49 +08:00 committed by GitHub
commit 48ed8979f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 215 additions and 145 deletions

View file

@ -118,24 +118,26 @@
FontSize="14"
Text="{DynamicResource customShortcutExpansion}" />
<DockPanel
Grid.Row="1"
Grid.Column="1"
LastChildFill="True">
<Button
x:Name="btnTestShortcut"
Margin="0 0 10 0"
Padding="10 5 10 5"
Click="BtnTestShortcut_OnClick"
Content="{DynamicResource preview}"
DockPanel.Dock="Right" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox
x:Name="tbExpand"
Grid.Column="0"
Margin="10 0 10 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Text="{Binding Value}" />
</DockPanel>
<Button
x:Name="btnTestShortcut"
Grid.Column="1"
Margin="0 0 10 0"
Padding="10 5 10 5"
Click="BtnTestShortcut_OnClick"
Content="{DynamicResource preview}" />
</Grid>
</Grid>
</StackPanel>
</StackPanel>

View file

@ -95,6 +95,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.3" />
</ItemGroup>

View file

@ -1,12 +1,13 @@
using System.Windows;
using Flow.Launcher.Plugin.BrowserBookmark.Models;
using System.Windows.Input;
using System.ComponentModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Flow.Launcher.Plugin.BrowserBookmark.Models;
namespace Flow.Launcher.Plugin.BrowserBookmark.Views;
public partial class SettingsControl : INotifyPropertyChanged
[INotifyPropertyChanged]
public partial class SettingsControl
{
public Settings Settings { get; }
public CustomBrowser SelectedCustomBrowser { get; set; }
@ -53,12 +54,10 @@ public partial class SettingsControl : INotifyPropertyChanged
set
{
Settings.OpenInNewBrowserWindow = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OpenInNewBrowserWindow)));
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NewCustomBrowser(object sender, RoutedEventArgs e)
{
var newBrowser = new CustomBrowser();

View file

@ -98,8 +98,11 @@
<system:String x:Key="plugin_explorer_deletefilefolder">Delete</system:String>
<system:String x:Key="plugin_explorer_deletefile_subtitle">Permanently delete current file</system:String>
<system:String x:Key="plugin_explorer_deletefolder_subtitle">Permanently delete current folder</system:String>
<system:String x:Key="plugin_explorer_path">Path:</system:String>
<system:String x:Key="plugin_explorer_name">Name:</system:String>
<system:String x:Key="plugin_explorer_name">Name</system:String>
<system:String x:Key="plugin_explorer_type">Type</system:String>
<system:String x:Key="plugin_explorer_path">Path</system:String>
<system:String x:Key="plugin_explorer_file">File</system:String>
<system:String x:Key="plugin_explorer_folder">Folder</system:String>
<system:String x:Key="plugin_explorer_deletefilefolder_subtitle">Delete the selected</system:String>
<system:String x:Key="plugin_explorer_runasdifferentuser">Run as different user</system:String>
<system:String x:Key="plugin_explorer_runasdifferentuser_subtitle">Run the selected using a different user account</system:String>

View file

@ -1,16 +1,11 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
#nullable enable
#nullable enable
namespace Flow.Launcher.Plugin.Explorer.Views
namespace Flow.Launcher.Plugin.Explorer.ViewModels
{
public class ActionKeywordModel : INotifyPropertyChanged
public partial class ActionKeywordModel : BaseModel
{
private static Settings _settings = null!;
public event PropertyChangedEventHandler? PropertyChanged;
public static void Init(Settings settings)
{
_settings = settings;
@ -28,13 +23,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views
internal Settings.ActionKeyword KeywordProperty { get; }
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string? keyword;
public string Keyword
{
get => keyword ??= _settings.GetActionKeyword(KeywordProperty);
@ -45,8 +34,8 @@ namespace Flow.Launcher.Plugin.Explorer.Views
OnPropertyChanged();
}
}
private bool? enabled;
private bool? enabled;
public bool Enabled
{
get => enabled ??= _settings.GetActionKeywordEnabled(KeywordProperty);

View file

@ -1,16 +1,13 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using Flow.Launcher.Plugin.Explorer.ViewModels;
namespace Flow.Launcher.Plugin.Explorer.Views
{
/// <summary>
/// Interaction logic for ActionKeywordSetting.xaml
/// </summary>
public partial class ActionKeywordSetting : INotifyPropertyChanged
[INotifyPropertyChanged]
public partial class ActionKeywordSetting
{
private ActionKeywordModel CurrentActionKeyword { get; }
@ -21,14 +18,14 @@ namespace Flow.Launcher.Plugin.Explorer.Views
{
// Set Enable to be true if user change ActionKeyword
KeywordEnabled = true;
_ = SetField(ref actionKeyword, value);
_ = SetProperty(ref actionKeyword, value);
}
}
public bool KeywordEnabled
{
get => _keywordEnabled;
set => SetField(ref _keywordEnabled, value);
set => _ = SetProperty(ref _keywordEnabled, value);
}
private string actionKeyword;
@ -116,20 +113,5 @@ namespace Flow.Launcher.Plugin.Explorer.Views
e.CancelCommand();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
}

View file

@ -8,7 +8,6 @@
xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:viewModels="clr-namespace:Flow.Launcher.Plugin.Explorer.ViewModels"
xmlns:views="clr-namespace:Flow.Launcher.Plugin.Explorer.Views"
d:DataContext="{d:DesignInstance viewModels:SettingsViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
@ -18,7 +17,7 @@
<DataTemplate x:Key="ListViewTemplateAccessLinks" DataType="qa:AccessLink">
<TextBlock Margin="0 5 0 5" Text="{Binding Path, Mode=OneTime}" />
</DataTemplate>
<DataTemplate x:Key="ListViewActionKeywords" DataType="{x:Type views:ActionKeywordModel}">
<DataTemplate x:Key="ListViewActionKeywords" DataType="{x:Type viewModels:ActionKeywordModel}">
<Grid>
<TextBlock
Margin="0 5 0 0"

View file

@ -3,7 +3,6 @@ using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@ -11,12 +10,14 @@ using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Flow.Launcher.Plugin.Explorer.Search;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Flow.Launcher.Plugin.Explorer.Views;
#nullable enable
public partial class PreviewPanel : UserControl, INotifyPropertyChanged
[INotifyPropertyChanged]
public partial class PreviewPanel : UserControl
{
private static readonly string ClassName = nameof(PreviewPanel);
@ -327,11 +328,4 @@ public partial class PreviewPanel : UserControl, INotifyPropertyChanged
return yearsDiff == 1 ? Main.Context.API.GetTranslation("OneYearAgo") :
string.Format(Main.Context.API.GetTranslation("YearsAgo"), yearsDiff);
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

View file

@ -1,22 +1,23 @@
<Window x:Class="Flow.Launcher.Plugin.Explorer.Views.QuickAccessLinkSettings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Plugin.Explorer.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="{DynamicResource plugin_explorer_manage_quick_access_links_header}"
Width="Auto"
Height="255"
Background="{DynamicResource PopuBGColor}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize"
SizeToContent="Width"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Window
x:Class="Flow.Launcher.Plugin.Explorer.Views.QuickAccessLinkSettings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Plugin.Explorer.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="{DynamicResource plugin_explorer_manage_quick_access_links_header}"
Width="Auto"
Height="300"
Background="{DynamicResource PopuBGColor}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize"
SizeToContent="Width"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
@ -58,55 +59,91 @@
<StackPanel Margin="26 0 26 0">
<StackPanel Margin="0 0 0 12">
<TextBlock
Margin="0 0 0 0"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource plugin_explorer_manage_quick_access_links_header}"
TextAlignment="Left" />
</StackPanel>
<StackPanel Margin="0 10 0 0" Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="100" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Name -->
<TextBlock
MinWidth="150"
Margin="0 10 15 10"
HorizontalAlignment="Left"
Grid.Row="0"
Grid.Column="0"
Margin="0 10 0 0"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource plugin_explorer_name}" />
<TextBox
Margin="10 0 0 0"
Grid.Row="0"
Grid.Column="1"
Margin="10 10 0 0"
VerticalAlignment="Center"
FontSize="12"
Width="250"
Text="{Binding SelectedName, Mode=TwoWay}" />
</StackPanel>
<StackPanel Margin="0 10 0 0" Orientation="Horizontal">
<!-- Type -->
<TextBlock
MinWidth="150"
Margin="0 10 15 10"
HorizontalAlignment="Left"
Grid.Row="1"
Grid.Column="0"
Margin="0 10 0 0"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource plugin_explorer_type}" />
<StackPanel
Grid.Row="1"
Grid.Column="1"
Orientation="Horizontal">
<RadioButton
Margin="10 10 0 0"
Content="{DynamicResource plugin_explorer_file}"
GroupName="PathType"
IsChecked="{Binding IsFileSelected}" />
<RadioButton
Margin="10 10 0 0"
Content="{DynamicResource plugin_explorer_folder}"
GroupName="PathType"
IsChecked="{Binding IsFolderSelected}" />
</StackPanel>
<!-- Path -->
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="0 10 0 0"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource plugin_explorer_path}" />
<TextBox
Margin="10 0 0 0"
Grid.Row="2"
Grid.Column="1"
Width="250"
Margin="10 10 0 0"
VerticalAlignment="Center"
FontSize="12"
Width="250"
Text="{Binding SelectedPath, Mode=TwoWay}"
IsReadOnly="True" />
IsReadOnly="True"
Text="{Binding SelectedPath, Mode=TwoWay}" />
<Button
Width="80"
Grid.Row="2"
Grid.Column="2"
Height="Auto"
Margin="10 0 0 0"
MinWidth="80"
Margin="10 10 0 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{DynamicResource select}"
Click="SelectPath_OnClick" />
</StackPanel>
Click="SelectPath_OnClick"
Content="{DynamicResource select}" />
</Grid>
</StackPanel>
</StackPanel>
<Border
@ -118,15 +155,15 @@
<Button
x:Name="btnCancel"
Width="145"
Height="30"
Margin="0 0 5 0"
Height="34"
Margin="0 0 5 1"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
Name="DownButton"
Width="145"
Height="30"
Margin="5 0 0 0"
Height="34"
Margin="5 0 0 1"
Click="OnDoneButtonClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
@ -134,4 +171,4 @@
</StackPanel>
</Border>
</Grid>
</Window>
</Window>

View file

@ -2,15 +2,17 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Forms;
using Flow.Launcher.Plugin.Explorer.Helper;
using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Flow.Launcher.Plugin.Explorer.Views;
public partial class QuickAccessLinkSettings : INotifyPropertyChanged
[INotifyPropertyChanged]
public partial class QuickAccessLinkSettings
{
private string _selectedPath;
public string SelectedPath
@ -25,6 +27,7 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged
if (string.IsNullOrEmpty(_selectedName))
{
SelectedName = _selectedPath.GetPathName();
_accessLinkType = GetResultType(_selectedPath);
}
}
}
@ -47,11 +50,16 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged
}
}
public bool IsFileSelected { get; set; }
public bool IsFolderSelected { get; set; } = true; // Default to Folder
private bool IsEdit { get; }
private AccessLink SelectedAccessLink { get; }
public ObservableCollection<AccessLink> QuickAccessLinks { get; }
private ResultType _accessLinkType = ResultType.Folder; // Default to Folder
public QuickAccessLinkSettings(ObservableCollection<AccessLink> quickAccessLinks)
{
IsEdit = false;
@ -64,6 +72,9 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged
IsEdit = true;
_selectedName = selectedAccessLink.Name;
_selectedPath = selectedAccessLink.Path;
_accessLinkType = GetResultType(_selectedPath); // Initialize link type
IsFileSelected = selectedAccessLink.Type == ResultType.File; // Initialize default selection
IsFolderSelected = !IsFileSelected;
SelectedAccessLink = selectedAccessLink;
QuickAccessLinks = quickAccessLinks;
InitializeComponent();
@ -96,30 +107,42 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged
}
// If editing, update the existing link
if (IsEdit)
if (IsEdit)
{
if (SelectedAccessLink == null) return;
var index = QuickAccessLinks.IndexOf(SelectedAccessLink);
if (index >= 0)
if (SelectedAccessLink != null)
{
var updatedLink = new AccessLink
var index = QuickAccessLinks.IndexOf(SelectedAccessLink);
if (index >= 0)
{
Name = SelectedName,
Type = SelectedAccessLink.Type,
Path = SelectedPath
};
QuickAccessLinks[index] = updatedLink;
var updatedLink = new AccessLink
{
Name = SelectedName,
Type = _accessLinkType,
Path = SelectedPath
};
QuickAccessLinks[index] = updatedLink;
}
DialogResult = true;
Close();
}
// Add a new one if the selected access link is null (should not happen in edit mode, but just in case)
else
{
AddNewAccessLink();
}
DialogResult = true;
Close();
}
// Otherwise, add a new one
else
{
AddNewAccessLink();
}
void AddNewAccessLink()
{
var newAccessLink = new AccessLink
{
Name = SelectedName,
Type = _accessLinkType,
Path = SelectedPath
};
QuickAccessLinks.Add(newAccessLink);
@ -130,18 +153,59 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged
private void SelectPath_OnClick(object commandParameter, RoutedEventArgs e)
{
var folderBrowserDialog = new FolderBrowserDialog();
// Open file or folder selection dialog based on the selected radio button
if (IsFileSelected)
{
var openFileDialog = new OpenFileDialog
{
Multiselect = false,
CheckFileExists = true,
CheckPathExists = true
};
if (folderBrowserDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
if (openFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK ||
string.IsNullOrEmpty(openFileDialog.FileName))
return;
SelectedPath = folderBrowserDialog.SelectedPath;
SelectedPath = openFileDialog.FileName;
}
else // Folder selection
{
var folderBrowserDialog = new FolderBrowserDialog
{
ShowNewFolderButton = true
};
if (folderBrowserDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK ||
string.IsNullOrEmpty(folderBrowserDialog.SelectedPath))
return;
SelectedPath = folderBrowserDialog.SelectedPath;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
private static ResultType GetResultType(string path)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
// Check if the path is a file or folder
if (System.IO.File.Exists(path))
{
return ResultType.File;
}
else if (System.IO.Directory.Exists(path))
{
if (string.Equals(System.IO.Path.GetPathRoot(path), path, StringComparison.OrdinalIgnoreCase))
{
return ResultType.Volume;
}
else
{
return ResultType.Folder;
}
}
else
{
// This should not happen, but just in case, we assume it's a folder
return ResultType.Folder;
}
}
}