Merge pull request #1474 from VictoriousRaptor/Shortcut

Custom Shortcut update
This commit is contained in:
Kevin Zhang 2022-10-17 00:05:07 -05:00 committed by GitHub
commit 2489bfad52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 214 additions and 105 deletions

View file

@ -0,0 +1,65 @@
using System;
using System.Text.Json.Serialization;
namespace Flow.Launcher.Infrastructure.UserSettings
{
public abstract class ShortcutBaseModel
{
public string Key { get; set; }
[JsonIgnore]
public Func<string> Expand { get; set; } = () => { return ""; };
public override bool Equals(object obj)
{
return obj is ShortcutBaseModel other &&
Key == other.Key;
}
public override int GetHashCode()
{
return HashCode.Combine(Key);
}
}
public class CustomShortcutModel : ShortcutBaseModel
{
public string Value { get; set; }
[JsonConstructorAttribute]
public CustomShortcutModel(string key, string value)
{
Key = key;
Value = value;
Expand = () => { return Value; };
}
public void Deconstruct(out string key, out string value)
{
key = Key;
value = Value;
}
public static implicit operator (string Key, string Value)(CustomShortcutModel shortcut)
{
return (shortcut.Key, shortcut.Value);
}
public static implicit operator CustomShortcutModel((string Key, string Value) shortcut)
{
return new CustomShortcutModel(shortcut.Key, shortcut.Value);
}
}
public class BuiltinShortcutModel : ShortcutBaseModel
{
public string Description { get; set; }
public BuiltinShortcutModel(string key, string description, Func<string> expand)
{
Key = key;
Description = description;
Expand = expand ?? (() => { return ""; });
}
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Text.Json.Serialization;
using System.Windows;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher;
@ -176,6 +177,13 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public ObservableCollection<CustomPluginHotkey> CustomPluginHotkeys { get; set; } = new ObservableCollection<CustomPluginHotkey>();
public ObservableCollection<CustomShortcutModel> CustomShortcuts { get; set; } = new ObservableCollection<CustomShortcutModel>();
[JsonIgnore]
public ObservableCollection<BuiltinShortcutModel> BuiltinShortcuts { get; set; } = new ObservableCollection<BuiltinShortcutModel>() {
new BuiltinShortcutModel("{clipboard}", "Get text from clipboard.", Clipboard.GetText) // TODO: translation?
};
public bool DontPromptUpdateMsg { get; set; }
public bool EnableUpdateLog { get; set; }
@ -204,7 +212,6 @@ namespace Flow.Launcher.Infrastructure.UserSettings
// This needs to be loaded last by staying at the bottom
public PluginsSettings PluginSettings { get; set; } = new PluginsSettings();
internal ObservableCollection<ShortCutModel> ShortCuts { get; set; } = new();
}
public enum LastQueryMode
@ -220,44 +227,4 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Light,
Dark
}
public struct ShortCutModel
{
public string Key { get; set; }
public string Value { get; set; }
public ShortCutModel(string key, string value)
{
Key = key;
Value = value;
}
public override bool Equals(object obj)
{
return obj is ShortCutModel other &&
Key == other.Key &&
Value == other.Value;
}
public override int GetHashCode()
{
return HashCode.Combine(Key, Value);
}
public void Deconstruct(out string key, out string value)
{
key = Key;
value = Value;
}
public static implicit operator (string Key, string Value)(ShortCutModel value)
{
return (value.Key, value.Value);
}
public static implicit operator ShortCutModel((string Key, string Value) value)
{
return new ShortCutModel(value.Key, value.Value);
}
}
}

View file

@ -3,7 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
Title="{DynamicResource customeQueryHotkeyTitle}"
Title="{DynamicResource customeQueryShortcutTitle}"
Width="530"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
@ -67,13 +67,13 @@
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource customeQueryHotkeyTitle}"
Text="{DynamicResource customQueryShortcut}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource customeQueryHotkeyTips}"
Text="{DynamicResource customeQueryShortcutTips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
@ -110,14 +110,25 @@
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource customShortcutExpansion}" />
<TextBox
<DockPanel
Grid.Row="1"
Grid.Column="1"
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Text="{Binding Value}"/>
</Grid>
LastChildFill="True">
<Button
x:Name="btnTestShortcut"
Padding="10,5,10,5"
Click="BtnTestShortcut_OnClick"
Content="{DynamicResource preview}"
DockPanel.Dock="Right" />
<TextBox
x:Name="tbExpand"
Margin="10"
HorizontalAlignment="Stretch"
Text="{Binding Value}"
VerticalAlignment="Center" />
</DockPanel>
</Grid>
</StackPanel>
</StackPanel>
</StackPanel>
@ -138,7 +149,7 @@
x:Name="btnAdd"
MinWidth="140"
Margin="5,0,10,0"
Click="btnAdd_OnClick"
Click="BtnAdd_OnClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>

View file

@ -1,33 +1,31 @@
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.UserSettings;
using System.Collections.ObjectModel;
using System.Linq;
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using System.Collections.Generic;
namespace Flow.Launcher
{
public partial class CustomShortcutSetting : Window
{
private SettingWindow _settingWidow;
private bool update;
private CustomPluginHotkey updateCustomHotkey;
private Settings _settings;
private bool update = false;
public string Key { get; set; }
public string Value { get; set; }
public ShortCutModel ShortCut => (Key, Value);
public CustomShortcutSetting()
public CustomShortcutModel ShortCut => (Key, Value);
public CustomShortcutSetting(Settings settings)
{
_settings = settings;
InitializeComponent();
}
public CustomShortcutSetting((string, string) shortcut)
public CustomShortcutSetting(CustomShortcutModel shortcut, Settings settings)
{
(Key, Value) = shortcut;
Key = shortcut.Key;
Value = shortcut.Value;
_settings = settings;
update = true;
InitializeComponent();
}
@ -37,8 +35,18 @@ namespace Flow.Launcher
Close();
}
private void btnAdd_OnClick(object sender, RoutedEventArgs e)
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
{
if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value))
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("emptyShortcut"));
return;
}
if (!update && (_settings.CustomShortcuts.Contains(new CustomShortcutModel(Key, Value)) || _settings.BuiltinShortcuts.Contains(new BuiltinShortcutModel(Key, Value, null))))
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("dulplicateShortcut"));
return;
}
DialogResult = true;
Close();
}
@ -48,5 +56,13 @@ namespace Flow.Launcher
DialogResult = false;
Close();
}
private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e)
{
App.API.ChangeQuery(tbExpand.Text);
Application.Current.MainWindow.Show();
Application.Current.MainWindow.Opacity = 1;
Application.Current.MainWindow.Focus();
}
}
}

View file

@ -113,8 +113,9 @@
<system:String x:Key="openResultModifiersToolTip">Select a modifier key to open selected result via keyboard.</system:String>
<system:String x:Key="showOpenResultHotkey">Show Hotkey</system:String>
<system:String x:Key="showOpenResultHotkeyToolTip">Show result selection hotkey with results.</system:String>
<system:String x:Key="customQueryHotkey">Custom Query Hotkey</system:String>
<system:String x:Key="customQuery">Query</system:String>
<system:String x:Key="customQueryHotkey">Custom Query Hotkey</system:String>
<system:String x:Key="customQueryShortcut">Custom Query Shortcut</system:String>
<system:String x:Key="customQuery">Query</system:String>
<system:String x:Key="customShortcut">Shortcut</system:String>
<system:String x:Key="customShortcutExpansion">Expanded</system:String>
<system:String x:Key="delete">Delete</system:String>
@ -211,7 +212,13 @@
<system:String x:Key="invalidPluginHotkey">Invalid plugin hotkey</system:String>
<system:String x:Key="update">Update</system:String>
<!-- Hotkey Control -->
<!-- Custom Query Shortcut Dialog -->
<system:String x:Key="customeQueryShortcutTitle">Custom Query Shortcut</system:String>
<system:String x:Key="customeQueryShortcutTips">Enter a shortcut that automatically expands to the specified query.</system:String>
<system:String x:Key="dulplicateShortcut">Shortcut is dulplicate, please enter a new Shortcut or edit the existing one.</system:String>
<system:String x:Key="emptyShortcut">Shortcut and/or its expansion is empty.</system:String>
<!-- Hotkey Control -->
<system:String x:Key="hotkeyUnavailable">Hotkey Unavailable</system:String>
<!-- Crash Reporter -->

View file

@ -2175,7 +2175,7 @@
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource Color05B}"
Text="Shortcut" />
Text="{DynamicResource customQueryShortcut}" />
<ListView
MinHeight="185"
Margin="0,6,0,0"
@ -2184,18 +2184,17 @@
BorderThickness="1"
ItemsSource="{Binding ShortCuts}"
SelectedItem="{Binding SelectedCustomShortcut}"
SelectedIndex="{Binding SelectCustomShortcutIndex}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Header="Key">
<GridViewColumn Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Mapped Value">
<GridViewColumn Header="{DynamicResource customShortcutExpansion}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" />
@ -2223,10 +2222,45 @@
<Button
MinWidth="100"
Margin="10,10,0,10"
Click="OnAddCustomeShortCutClick"
Click="OnAddCustomShortCutClick"
Content="{DynamicResource add}" />
</StackPanel>
</StackPanel>
<TextBlock
Margin="0,0,12,2"
Padding="0,12,0,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource Color05B}"
Text="Built-in Shortcuts" />
<ListView
MinHeight="185"
Margin="0,6,0,0"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding Settings.BuiltinShortcuts}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Description">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>
</Border>
</ScrollViewer>

View file

@ -365,11 +365,14 @@ namespace Flow.Launcher
restoreButton.Visibility = Visibility.Collapsed;
}
}
private void Window_StateChanged(object sender, EventArgs e)
{
RefreshMaximizeRestoreButton();
}
#region Shortcut
private void OnDeleteCustomShortCutClick(object sender, RoutedEventArgs e)
{
var item = viewModel.SelectedCustomShortcut;
@ -386,33 +389,37 @@ namespace Flow.Launcher
MessageBox.Show(deleteWarning, InternationalizationManager.Instance.GetTranslation("delete"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
settings.ShortCuts.Remove(item.Value);
}
}
private void OnEditCustomShortCutClick(object sender, RoutedEventArgs e)
{
var item = viewModel.SelectedCustomShortcut;
if (item != null)
{
var shortcutSettingWindow = new CustomShortcutSetting(item.Value);
if (shortcutSettingWindow.ShowDialog() == true)
{
settings.ShortCuts[viewModel.SelectCustomShortcutIndex.Value] = shortcutSettingWindow.ShortCut;
}
}
else
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
settings.CustomShortcuts.Remove(item);
}
}
private void OnAddCustomeShortCutClick(object sender, RoutedEventArgs e)
private void OnEditCustomShortCutClick(object sender, RoutedEventArgs e)
{
var shortcutSettingWindow = new CustomShortcutSetting();
var item = viewModel.SelectedCustomShortcut;
if (item == null)
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
return;
}
var shortcutSettingWindow = new CustomShortcutSetting(item, settings);
if (shortcutSettingWindow.ShowDialog() == true)
{
settings.ShortCuts.Add(shortcutSettingWindow.ShortCut);
settings.CustomShortcuts.Remove(item);
settings.CustomShortcuts.Add(shortcutSettingWindow.ShortCut);
}
}
private void OnAddCustomShortCutClick(object sender, RoutedEventArgs e)
{
var shortcutSettingWindow = new CustomShortcutSetting(settings);
if (shortcutSettingWindow.ShowDialog() == true)
{
settings.CustomShortcuts.Add(shortcutSettingWindow.ShortCut);
}
}
#endregion
}
}

View file

@ -554,7 +554,7 @@ namespace Flow.Launcher.ViewModel
return;
}
var query = ConstructQuery(QueryText, _settings.ShortCuts);
var query = ConstructQuery(QueryText, _settings.CustomShortcuts, _settings.BuiltinShortcuts);
_updateSource?.Dispose();
@ -662,21 +662,24 @@ namespace Flow.Launcher.ViewModel
}
}
private static Query ConstructQuery(string queryText, IEnumerable<ShortCutModel> shortcuts)
private static Query ConstructQuery(string queryText, IEnumerable<CustomShortcutModel> customShortcuts, IEnumerable<BuiltinShortcutModel> builtInShortcuts)
{
StringBuilder queryBuilder = new(queryText);
foreach (var (key, value) in shortcuts)
foreach (var shortcut in customShortcuts)
{
if (queryBuilder.Equals(key))
if (queryBuilder.Equals(shortcut.Key))
{
queryBuilder.Replace(key, value);
queryBuilder.Replace(shortcut.Key, shortcut.Expand());
}
queryBuilder.Replace('@' + key, value);
queryBuilder.Replace('@' + shortcut.Key, shortcut.Expand());
}
foreach (var shortcut in builtInShortcuts)
{
queryBuilder.Replace(shortcut.Key, shortcut.Expand());
}
queryBuilder.Replace("{clipboard}", Clipboard.GetText());
var query = QueryBuilder.Build(queryBuilder.ToString().Trim(), PluginManager.NonGlobalPlugins);
return query;

View file

@ -180,7 +180,7 @@ namespace Flow.Launcher.ViewModel
public List<Language> Languages => _translater.LoadAvailableLanguages();
public IEnumerable<int> MaxResultsRange => Enumerable.Range(2, 16);
public ObservableCollection<ShortCutModel> ShortCuts => Settings.ShortCuts;
public ObservableCollection<CustomShortcutModel> ShortCuts => Settings.CustomShortcuts;
public string TestProxy()
{
@ -541,8 +541,7 @@ namespace Flow.Launcher.ViewModel
public CustomPluginHotkey SelectedCustomPluginHotkey { get; set; }
public ShortCutModel? SelectedCustomShortcut { get; set; }
public int? SelectCustomShortcutIndex { get; set; }
public CustomShortcutModel? SelectedCustomShortcut { get; set; }
#endregion