diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs new file mode 100644 index 00000000000..c0cd022eaa7 --- /dev/null +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -0,0 +1,57 @@ +using Flow.Launcher.Infrastructure.Http; +using Flow.Launcher.Infrastructure.Logger; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Flow.Launcher.Core.ExternalPlugins +{ + public static class PluginsManifest + { + static PluginsManifest() + { + UpdateTask = UpdateManifestAsync(); + } + + public static List UserPlugins { get; private set; } = new List(); + + public static Task UpdateTask { get; private set; } + + private static readonly SemaphoreSlim manifestUpdateLock = new(1); + + public static Task UpdateManifestAsync() + { + if (manifestUpdateLock.CurrentCount == 0) + { + return UpdateTask; + } + + return UpdateTask = DownloadManifestAsync(); + } + + private async static Task DownloadManifestAsync() + { + try + { + await manifestUpdateLock.WaitAsync().ConfigureAwait(false); + + await using var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json") + .ConfigureAwait(false); + + UserPlugins = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); + } + catch (Exception e) + { + Log.Exception("|PluginManagement.GetManifest|Encountered error trying to download plugins manifest", e); + + UserPlugins = new List(); + } + finally + { + manifestUpdateLock.Release(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs similarity index 77% rename from Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs rename to Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs index c1af3014bf9..f98815c1a9f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/UserPlugin.cs +++ b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs @@ -1,7 +1,6 @@ - -namespace Flow.Launcher.Plugin.PluginsManager.Models +namespace Flow.Launcher.Core.ExternalPlugins { - public class UserPlugin + public record UserPlugin { public string ID { get; set; } public string Name { get; set; } @@ -12,5 +11,6 @@ public class UserPlugin public string Website { get; set; } public string UrlDownload { get; set; } public string UrlSourceCode { get; set; } + public string IcoPath { get; set; } } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index d9cdf5581d0..974eafa9646 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -59,6 +59,11 @@ public interface IPublicAPI /// Optional message subtitle void ShowMsgError(string title, string subTitle = ""); + /// + /// Show the MainWindow when hiding + /// + void ShowMainWindow(); + /// /// Show message box /// diff --git a/Flow.Launcher/App.xaml b/Flow.Launcher/App.xaml index 18addac7398..13d88e1c6f9 100644 --- a/Flow.Launcher/App.xaml +++ b/Flow.Launcher/App.xaml @@ -6,6 +6,227 @@ Startup="OnStartupAsync"> + + + + + + + + diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 4d871b345fa..ff6b2a5a5ee 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -6,6 +6,8 @@ using Flow.Launcher.Core.Resource; using System.Windows; using Flow.Launcher.ViewModel; +using System.Threading.Tasks; +using System.Threading; namespace Flow.Launcher.Helper { @@ -19,7 +21,7 @@ internal static void Initialize(MainViewModel mainVM) mainViewModel = mainVM; settings = mainViewModel._settings; - SetHotkey(settings.Hotkey, OnHotkey); + SetHotkey(settings.Hotkey, mainViewModel.OnHotkey); LoadCustomPluginHotkey(); } @@ -53,44 +55,6 @@ internal static void RemoveHotkey(string hotkeyStr) } } - internal static void OnHotkey(object sender, HotkeyEventArgs e) - { - if (!ShouldIgnoreHotkeys()) - { - UpdateLastQUeryMode(); - - mainViewModel.ToggleFlowLauncher(); - e.Handled = true; - } - } - - /// - /// Checks if Flow Launcher should ignore any hotkeys - /// - private static bool ShouldIgnoreHotkeys() - { - return settings.IgnoreHotkeysOnFullscreen && WindowsInteropHelper.IsWindowFullscreen(); - } - - private static void UpdateLastQUeryMode() - { - switch(settings.LastQueryMode) - { - case LastQueryMode.Empty: - mainViewModel.ChangeQueryText(string.Empty); - break; - case LastQueryMode.Preserved: - mainViewModel.LastQuerySelected = true; - break; - case LastQueryMode.Selected: - mainViewModel.LastQuerySelected = false; - break; - default: - throw new ArgumentException($"wrong LastQueryMode: <{settings.LastQueryMode}>"); - - } - } - internal static void LoadCustomPluginHotkey() { if (settings.CustomPluginHotkeys == null) @@ -106,7 +70,7 @@ internal static void SetCustomQueryHotkey(CustomPluginHotkey hotkey) { SetHotkey(hotkey.Hotkey, (s, e) => { - if (ShouldIgnoreHotkeys()) + if (mainViewModel.ShouldIgnoreHotkeys()) return; mainViewModel.MainWindowVisibility = Visibility.Visible; diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4a9b9270071..4d24a7c330a 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -42,18 +42,18 @@ Shadow effect is not allowed while current theme has blur effect enabled - Plugin + Plugins Find more plugins - Enable - Disable - Action keyword: + On + Off + Action keyword Current action keyword: New action keyword: Current Priority: New Priority: - Priority: + Priority Plugin Directory - Author + Author: Init time: Query time: diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index e84a3148e2d..99eed45a6f5 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -30,7 +30,9 @@ public partial class MainWindow private bool isProgressBarStoryboardPaused; private Settings _settings; private NotifyIcon _notifyIcon; + private ContextMenu contextMenu; private MainViewModel _viewModel; + #endregion @@ -159,14 +161,19 @@ private void InitializePosition() private void UpdateNotifyIconText() { - var menu = _notifyIcon.ContextMenuStrip; - var open = menu.Items[0]; - var setting = menu.Items[1]; - var exit = menu.Items[2]; - - open.Text = InternationalizationManager.Instance.GetTranslation("iconTrayOpen"); - setting.Text = InternationalizationManager.Instance.GetTranslation("iconTraySettings"); - exit.Text = InternationalizationManager.Instance.GetTranslation("iconTrayExit"); + var menu = contextMenu; + + var header = new MenuItem() { Header = "Flow Launcher", IsEnabled = false }; + var open = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") }; + var settings = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings") }; + var exit = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit") }; + menu.Items[0] = header; + menu.Items[1] = open; + menu.Items[2] = settings; + menu.Items[3] = exit; + open.Click += (o, e) => Visibility = Visibility.Visible; + settings.Click += (o, e) => App.API.OpenSettingDialog(); + exit.Click += (o, e) => Close(); } private void InitializeNotifyIcon() @@ -178,33 +185,38 @@ private void InitializeNotifyIcon() Visible = !_settings.HideNotifyIcon }; var menu = new ContextMenuStrip(); - var items = menu.Items; + contextMenu = new ContextMenu(); + + MenuItem header = new MenuItem() { Header = "Flow Launcher", IsEnabled = false }; + MenuItem open = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") }; + MenuItem settings = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings") }; + MenuItem exit = new MenuItem() { Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit") }; - var open = items.Add(InternationalizationManager.Instance.GetTranslation("iconTrayOpen")); open.Click += (o, e) => Visibility = Visibility.Visible; - var setting = items.Add(InternationalizationManager.Instance.GetTranslation("iconTraySettings")); - setting.Click += (o, e) => App.API.OpenSettingDialog(); - var exit = items.Add(InternationalizationManager.Instance.GetTranslation("iconTrayExit")); + settings.Click += (o, e) => App.API.OpenSettingDialog(); exit.Click += (o, e) => Close(); + contextMenu.Items.Add(header); + contextMenu.Items.Add(open); + contextMenu.Items.Add(settings); + contextMenu.Items.Add(exit); - _notifyIcon.ContextMenuStrip = menu; + _notifyIcon.ContextMenuStrip = menu; /*it need for close the context menu. if not, context menu can't close. */ _notifyIcon.MouseClick += (o, e) => { - if (e.Button == MouseButtons.Left) + switch (e.Button) { - if (menu.Visible) - { - menu.Close(); - } - else - { - var p = System.Windows.Forms.Cursor.Position; - menu.Show(p); - } + case MouseButtons.Left: + _viewModel.ToggleFlowLauncher(); + break; + + case MouseButtons.Right: + contextMenu.IsOpen = true; + break; } }; } + private void InitProgressbarAnimation() { var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150, @@ -262,7 +274,7 @@ private void OnDeactivated(object sender, EventArgs e) { if (_settings.HideWhenDeactive) { - Hide(); + _viewModel.Hide(); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 6f995671dd2..70d54619d9d 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -68,6 +68,8 @@ public void RestartApp() public void RestarApp() => RestartApp(); + public void ShowMainWindow() => _mainVM.MainWindowVisibility = Visibility.Visible; + public void CheckForNewUpdate() => _settingsVM.UpdateApp(); public void SaveAppAllSettings() diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 7dc8829bec7..e6612e4dc97 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -17,43 +17,40 @@ ResizeMode="CanResizeWithGrip" WindowStartupLocation="CenterScreen" Height="700" Width="1000" - MinWidth="850" + MinWidth="900" MinHeight="600" - Loaded="OnLoaded" + Loaded="OnLoaded" Closed="OnClosed" d:DataContext="{d:DesignInstance vm:SettingWindowViewModel}"> - + - + - + - + + @@ -64,13 +61,15 @@ + + - + + + + + + + + + + - - - + + + - - - + + + - + + - - + + - - + +  + + - - + + - + - + - - - + + @@ -245,11 +427,13 @@ - + - - - + + @@ -258,10 +442,11 @@ - + - - + @@ -269,31 +454,35 @@ - + - - + - + - - + - + - - - + + @@ -302,12 +491,16 @@ - - + + - - - + + @@ -316,10 +509,13 @@ - + - - + + @@ -328,10 +524,13 @@ - + - - + + @@ -341,29 +540,36 @@ - + + ItemsSource="{Binding QuerySearchPrecisionStrings}" + SelectedItem="{Binding Settings.QuerySearchPrecisionString}" + Grid.Column="2" /> - + - + + ItemsSource="{Binding LastQueryModes}" + SelectedValue="{Binding Settings.LastQueryMode}" + DisplayMemberPath="Display" SelectedValuePath="Value" Grid.Column="2" /> - + - - - -  + + + +  @@ -373,12 +579,15 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - + + + + + +  + + + - + - - + + - + - + - + HorizontalAlignment="Center" VerticalAlignment="Center"> + - - - + + + - + + Text="{DynamicResource hiThere}" IsReadOnly="True" + Style="{DynamicResource QueryBoxStyle}" /> - + - + - + @@ -600,26 +1104,49 @@ + + + + + + + + + +  + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -