diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index 4077320bc..8d06e71c5 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -1,4 +1,4 @@ - + net7.0-windows @@ -54,8 +54,8 @@ - - + + diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index f4d7511c6..1d4db757b 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -1,4 +1,4 @@ - + net7.0-windows @@ -53,7 +53,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 19b69b015..d0fdf136b 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -80,6 +80,17 @@ namespace Flow.Launcher.Plugin /// void ShowMainWindow(); + /// + /// Hide MainWindow + /// + void HideMainWindow(); + + /// + /// Representing whether the main window is visible + /// + /// + bool IsMainWindowVisible(); + /// /// Show message box /// diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index f5d9dea28..d88becad0 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -54,7 +54,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + \ No newline at end of file diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 02930fc25..384df2e62 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -94,10 +94,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 43bd9fd35..1e7735fb2 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -59,14 +59,16 @@ namespace Flow.Launcher private void OnCopy(object sender, ExecutedRoutedEventArgs e) { - if (QueryTextBox.SelectionLength == 0) + var result = _viewModel.Results.SelectedItem?.Result; + if (QueryTextBox.SelectionLength == 0 && result != null) { - _viewModel.ResultCopy(string.Empty); + string copyText = result.CopyText; + _viewModel.ResultCopy(copyText); } else if (!string.IsNullOrEmpty(QueryTextBox.Text)) { - _viewModel.ResultCopy(QueryTextBox.SelectedText); + System.Windows.Clipboard.SetText(QueryTextBox.SelectedText); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 636699ad0..b61e22d5e 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -73,6 +73,10 @@ namespace Flow.Launcher public void ShowMainWindow() => _mainVM.Show(); + public void HideMainWindow() => _mainVM.Hide(); + + public bool IsMainWindowVisible() => _mainVM.MainWindowVisibilityStatus; + public void CheckForNewUpdate() => _settingsVM.UpdateApp(); public void SaveAppAllSettings() @@ -114,7 +118,7 @@ namespace Flow.Launcher public void CopyToClipboard(string text) { - Clipboard.SetDataObject(text); + _mainVM.ResultCopy(text); } public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible; diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 9fa6d25d0..7301be130 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -9,6 +9,7 @@ using Flow.Launcher.ViewModel; using ModernWpf; using ModernWpf.Controls; using System; +using System.ComponentModel; using System.IO; using System.Windows; using System.Windows.Data; @@ -56,12 +57,24 @@ namespace Flow.Launcher pluginListView = (CollectionView)CollectionViewSource.GetDefaultView(Plugins.ItemsSource); pluginListView.Filter = PluginListFilter; - pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); + pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); pluginStoreView.Filter = PluginStoreFilter; + viewModel.PropertyChanged += new PropertyChangedEventHandler(SettingsWindowViewModelChanged); + InitializePosition(); } + private void SettingsWindowViewModelChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(viewModel.ExternalPlugins)) + { + pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource); + pluginStoreView.Filter = PluginStoreFilter; + pluginStoreView.Refresh(); + } + } + private void OnSelectPythonPathClick(object sender, RoutedEventArgs e) { var selectedFile = viewModel.GetFileFromDialog( @@ -255,9 +268,9 @@ namespace Flow.Launcher { var confirmResult = MessageBox.Show( InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), - InternationalizationManager.Instance.GetTranslation("clearlogfolder"), + InternationalizationManager.Instance.GetTranslation("clearlogfolder"), MessageBoxButton.YesNo); - + if (confirmResult == MessageBoxResult.Yes) { viewModel.ClearLogFolder(); @@ -388,7 +401,7 @@ namespace Flow.Launcher } #endregion - + private CollectionView pluginListView; private CollectionView pluginStoreView; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 27809f67b..8529df7b3 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1104,47 +1104,39 @@ namespace Flow.Launcher.ViewModel } /// - /// This is the global copy method for an individual result. If no text is passed, - /// the method will work out what is to be copied based on the result, so plugin can offer the text - /// to be copied via the result model. If the text is a directory/file path, - /// then actual file/folder will be copied instead. - /// The result's subtitle text is the default text to be copied + /// Copies the specified file or folder path to the clipboard, or the specified text if it is not a valid file or folder path. + /// Shows a message indicating whether the operation was completed successfully. /// + /// The file or folder path, or text to copy to the clipboard. + /// Nothing. public void ResultCopy(string stringToCopy) { if (string.IsNullOrEmpty(stringToCopy)) { - var result = Results.SelectedItem?.Result; - if (result != null) - { - string copyText = result.CopyText; - var isFile = File.Exists(copyText); - var isFolder = Directory.Exists(copyText); - if (isFile || isFolder) - { - var paths = new StringCollection - { - copyText - }; - - Clipboard.SetFileDropList(paths); - App.API.ShowMsg( - $"{App.API.GetTranslation("copy")} {(isFile ? App.API.GetTranslation("fileTitle") : App.API.GetTranslation("folderTitle"))}", - App.API.GetTranslation("completedSuccessfully")); - } - else - { - Clipboard.SetDataObject(copyText); - App.API.ShowMsg( - $"{App.API.GetTranslation("copy")} {App.API.GetTranslation("textTitle")}", - App.API.GetTranslation("completedSuccessfully")); - } - } - return; } + var isFile = File.Exists(stringToCopy); + var isFolder = Directory.Exists(stringToCopy); + if (isFile || isFolder) + { + var paths = new StringCollection + { + stringToCopy + }; - Clipboard.SetDataObject(stringToCopy); + Clipboard.SetFileDropList(paths); + App.API.ShowMsg( + $"{App.API.GetTranslation("copy")} {(isFile ? App.API.GetTranslation("fileTitle") : App.API.GetTranslation("folderTitle"))}", + App.API.GetTranslation("completedSuccessfully")); + } + else + { + Clipboard.SetDataObject(stringToCopy); + App.API.ShowMsg( + $"{App.API.GetTranslation("copy")} {App.API.GetTranslation("textTitle")}", + App.API.GetTranslation("completedSuccessfully")); + } + return; } #endregion diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 3eff7e398..be2a2dd66 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -1,7 +1,6 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Flow.Launcher.Infrastructure; -using System.Threading.Tasks; namespace Flow.Launcher.Plugin.ProcessKiller { @@ -89,7 +88,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller Action = (c) => { processHelper.TryKill(p); - _ = DelayAndReQueryAsync(query.RawQuery); // Re-query after killing process to refresh process list + // Re-query to refresh process list + _context.API.ChangeQuery(query.RawQuery, true); return true; } }); @@ -114,7 +114,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller { processHelper.TryKill(p.Process); } - _ = DelayAndReQueryAsync(query.RawQuery); // Re-query after killing process to refresh process list + // Re-query to refresh process list + _context.API.ChangeQuery(query.RawQuery, true); return true; } }); @@ -122,11 +123,5 @@ namespace Flow.Launcher.Plugin.ProcessKiller return sortedResults; } - - private static async Task DelayAndReQueryAsync(string query) - { - await Task.Delay(500); - _context.API.ChangeQuery(query, true); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs index 0932955d6..0acc39fbb 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; @@ -75,6 +75,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller if (!p.HasExited) { p.Kill(); + p.WaitForExit(50); } } catch (Exception e) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 340d882da..ac23534b1 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -88,21 +88,24 @@ namespace Flow.Launcher.Plugin.Program bool cacheEmpty = !_win32s.Any() && !_uwps.Any(); - var a = Task.Run(() => + if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32Programs); - }); - - var b = Task.Run(() => + _ = Task.Run(async () => + { + await IndexProgramsAsync().ConfigureAwait(false); + WatchProgramUpdate(); + }); + } + else { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPPRogram index cost", IndexUwpPrograms); - }); + WatchProgramUpdate(); + } - if (cacheEmpty) - await Task.WhenAll(a, b); - - Win32.WatchProgramUpdate(_settings); - _ = UWP.WatchPackageChange(); + static void WatchProgramUpdate() + { + Win32.WatchProgramUpdate(_settings); + _ = UWP.WatchPackageChange(); + } } public static void IndexWin32Programs() @@ -110,6 +113,8 @@ namespace Flow.Launcher.Plugin.Program var win32S = Win32.All(_settings); _win32s = win32S; ResetCache(); + _win32Storage.Save(_win32s); + _settings.LastIndexTime = DateTime.Now; } public static void IndexUwpPrograms() @@ -117,6 +122,8 @@ namespace Flow.Launcher.Plugin.Program var applications = UWP.All(_settings); _uwps = applications; ResetCache(); + _uwpStorage.Save(_uwps); + _settings.LastIndexTime = DateTime.Now; } public static async Task IndexProgramsAsync() @@ -131,7 +138,6 @@ namespace Flow.Launcher.Plugin.Program Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpPrograms); }); await Task.WhenAll(a, b).ConfigureAwait(false); - _settings.LastIndexTime = DateTime.Today; } internal static void ResetCache() @@ -199,7 +205,6 @@ namespace Flow.Launcher.Plugin.Program _ = Task.Run(() => { IndexUwpPrograms(); - _settings.LastIndexTime = DateTime.Today; }); } else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) @@ -210,7 +215,6 @@ namespace Flow.Launcher.Plugin.Program _ = Task.Run(() => { IndexWin32Programs(); - _settings.LastIndexTime = DateTime.Today; }); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs index f59facaa4..ca203f803 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs @@ -121,13 +121,6 @@ namespace Flow.Launcher.Plugin.Program public bool EnablePathSource { get; set; } = false; public bool EnableUWP { get; set; } = true; - public string CustomizedExplorer { get; set; } = Explorer; - public string CustomizedArgs { get; set; } = ExplorerArgs; - internal const char SuffixSeparator = ';'; - - internal const string Explorer = "explorer"; - - internal const string ExplorerArgs = "%s"; } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 4b63d38a5..156f33ebc 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -87,18 +87,6 @@ namespace Flow.Launcher.Plugin.Program.Views } } - public string CustomizedExplorerPath - { - get => _settings.CustomizedExplorer; - set => _settings.CustomizedExplorer = value; - } - - public string CustomizedExplorerArg - { - get => _settings.CustomizedArgs; - set => _settings.CustomizedArgs = value; - } - public bool ShowUWPCheckbox => UWP.SupportUWP(); public ProgramSetting(PluginInitContext context, Settings settings, Win32[] win32s, UWP.Application[] uwps) diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Helper/ResultHelper.cs b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Helper/ResultHelper.cs index ec9a8224e..9e85a8580 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Helper/ResultHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Helper/ResultHelper.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -200,6 +201,21 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper Process.Start(processStartInfo); return true; } + catch (Win32Exception) + { + try + { + processStartInfo.UseShellExecute = true; + processStartInfo.Verb = "runas"; + Process.Start(processStartInfo); + return true; + } + catch (Exception exception) + { + Log.Exception("can't open settings on elevated permission", exception, typeof(ResultHelper)); + return false; + } + } catch (Exception exception) { Log.Exception("can't open settings", exception, typeof(ResultHelper)); diff --git a/README.md b/README.md index 896d81e8a..fdd33f3f8 100644 --- a/README.md +++ b/README.md @@ -222,9 +222,6 @@ And you can download

-### Everything - - ### SpotifyPremium @@ -341,6 +338,7 @@ And you can download       +

### Mentions diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 23eabedfd..1757ed99e 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -71,7 +71,6 @@ function Pack-Squirrel-Installer ($path, $version, $output) { Write-Host "Packing: $spec" Write-Host "Input path: $input" - New-Alias Nuget $env:USERPROFILE\.nuget\packages\NuGet.CommandLine\6.3.1\tools\NuGet.exe -Force # dotnet pack is not used because ran into issues, need to test installation and starting up if to use it. nuget pack $spec -Version $version -BasePath $input -OutputDirectory $output -Properties Configuration=Release diff --git a/appveyor.yml b/appveyor.yml index a3cc8ecfb..2068cd67b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,7 +51,7 @@ deploy: - provider: NuGet artifact: Plugin nupkg api_key: - secure: EwKxUgjI8VGouFq9fdhI68+uj42amAhwE65JixIbqx8VlqLbyEuW97CLjBBOIL0r + secure: Uho7u3gk4RHzyWGgqgXZuOeI55NbqHLQ9tXahL7xmE4av2oiSldrNiyGgy/0AQYw on: APPVEYOR_REPO_TAG: true