From 3260faba985a595b2df48c0541ebb9bef6aea88e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 31 Jan 2025 22:01:29 +0800 Subject: [PATCH 01/28] Add support for changing startup to logon task for faster startup experience --- .../UserSettings/Settings.cs | 1 + Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/Flow.Launcher.csproj | 1 + Flow.Launcher/Helper/AutoStartup.cs | 115 +++++++++++++++++- .../SettingsPaneGeneralViewModel.cs | 34 +++++- .../Views/SettingsPaneGeneral.xaml | 7 ++ 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index c412fb32f..81895fdcc 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -238,6 +238,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool EnableUpdateLog { get; set; } public bool StartFlowLauncherOnSystemStartup { get; set; } = false; + public bool UseLogonTaskForStartup { get; set; } = false; public bool HideOnStartup { get; set; } = true; bool _hideNotifyIcon { get; set; } public bool HideNotifyIcon diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4d1adc6cd..38f846d92 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -119,7 +119,7 @@ namespace Flow.Launcher { try { - Helper.AutoStartup.Enable(); + Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup); } catch (Exception e) { diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 788beddfb..570785be7 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -100,6 +100,7 @@ + diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 4bff30caf..116520ecf 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -1,18 +1,31 @@ using System; +using System.IO; +using System.Linq; +using System.Security.Principal; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; namespace Flow.Launcher.Helper; public class AutoStartup { private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; + private const string LogonTaskName = $"{Constant.FlowLauncher} Startup"; + private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup"; public static bool IsEnabled { get { + // Check if logon task is enabled + if (CheckLogonTask()) + { + return true; + } + + // Check if registry is enabled try { using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); @@ -28,12 +41,45 @@ public class AutoStartup } } - public static void Disable() + private static bool CheckLogonTask() + { + using var taskService = new TaskService(); + var task = taskService.RootFolder.AllTasks.FirstOrDefault(t => t.Name == LogonTaskName); + if (task != null) + { + try + { + // Check if the action is the same as the current executable path + var action = task.Definition.Actions.FirstOrDefault()!.ToString().Trim(); + if (!Constant.ExecutablePath.Equals(action, StringComparison.OrdinalIgnoreCase) && !File.Exists(action)) + { + UnscheduleLogonTask(); + ScheduleLogonTask(); + } + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to check logon task"); + return false; + } + } + + return true; + } + + public static void Disable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.DeleteValue(Constant.FlowLauncher, false); + if (logonTask) + { + UnscheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.DeleteValue(Constant.FlowLauncher, false); + } } catch (Exception e) { @@ -42,12 +88,19 @@ public class AutoStartup } } - internal static void Enable() + internal static void Enable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + if (logonTask) + { + ScheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + } } catch (Exception e) { @@ -55,4 +108,54 @@ public class AutoStartup throw; } } + + private static bool ScheduleLogonTask() + { + using var td = TaskService.Instance.NewTask(); + td.RegistrationInfo.Description = LogonTaskDesc; + td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name, Delay = TimeSpan.FromSeconds(2) }); + td.Actions.Add(Constant.ExecutablePath); + + if (IsCurrentUserIsAdmin()) + { + td.Principal.RunLevel = TaskRunLevel.Highest; + } + + td.Settings.StopIfGoingOnBatteries = false; + td.Settings.DisallowStartIfOnBatteries = false; + td.Settings.ExecutionTimeLimit = TimeSpan.Zero; + + try + { + TaskService.Instance.RootFolder.RegisterTaskDefinition(LogonTaskName, td); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to schedule logon task"); + return false; + } + } + + private static bool UnscheduleLogonTask() + { + using var taskService = new TaskService(); + try + { + taskService.RootFolder.DeleteTask(LogonTaskName); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to unschedule logon task"); + return false; + } + } + + private static bool IsCurrentUserIsAdmin() + { + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 3d94355e6..0aca761a0 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -42,9 +42,16 @@ public partial class SettingsPaneGeneralViewModel : BaseModel try { if (value) - AutoStartup.Enable(); + { + // Enable either registry or task scheduler + AutoStartup.Enable(UseLogonTaskForStartup); + } else - AutoStartup.Disable(); + { + // Disable both registry and task scheduler + AutoStartup.Disable(true); + AutoStartup.Disable(false); + } } catch (Exception e) { @@ -54,6 +61,29 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } } + public bool UseLogonTaskForStartup + { + get => Settings.UseLogonTaskForStartup; + set + { + Settings.UseLogonTaskForStartup = value; + + if (StartFlowLauncherOnSystemStartup) + { + try + { + // Disable and enable to update the startup method + AutoStartup.Disable(!UseLogonTaskForStartup); + AutoStartup.Enable(UseLogonTaskForStartup); + } + catch (Exception e) + { + Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), + e.Message); + } + } + } + } public List SearchWindowScreens { get; } = DropdownDataGeneric.GetValues("SearchWindowScreen"); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 30e065b16..f57eba654 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,6 +36,13 @@ OnContent="{DynamicResource enable}" /> + + + + Date: Fri, 31 Jan 2025 22:06:53 +0800 Subject: [PATCH 02/28] Move string to resources --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/Languages/zh-cn.xaml | 8 ++++++-- Flow.Launcher/Languages/zh-tw.xaml | 8 ++++++-- Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f..8e8c9abef 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -46,6 +46,7 @@ Portable Mode Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup + Use logon task instead of startup entry for faster startup experience Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 681c715fb..d2d1044af 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,5 +1,8 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -44,6 +47,7 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 + 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 44be5257b..b5aa53377 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,5 +1,8 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -44,6 +47,7 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 + 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index f57eba654..e52614e74 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Fri, 31 Jan 2025 22:22:00 +0800 Subject: [PATCH 03/28] Fix issue when checking logon task --- Flow.Launcher/Helper/AutoStartup.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 116520ecf..79466f1fb 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -56,15 +56,16 @@ public class AutoStartup UnscheduleLogonTask(); ScheduleLogonTask(); } + + return true; } catch (Exception) { Log.Error("AutoStartup", "Failed to check logon task"); - return false; } } - return true; + return false; } public static void Disable(bool logonTask) From 1ff8c3620a030294a6d30d9ae2e93ac14438457a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 07:56:24 +0800 Subject: [PATCH 04/28] Revert changes in non-English language files --- Flow.Launcher/Languages/zh-cn.xaml | 8 ++------ Flow.Launcher/Languages/zh-tw.xaml | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index d2d1044af..681c715fb 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,8 +1,5 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -47,7 +44,6 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 - 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index b5aa53377..44be5257b 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,8 +1,5 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -47,7 +44,6 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 - 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 From 585b7015b6236ea7fdbe156c39d468a3ca579ed5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 10 Feb 2025 18:20:50 +0800 Subject: [PATCH 05/28] Add uninstallation tooltip for logon task settings item --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 8e8c9abef..cd9d0b02a 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -47,6 +47,7 @@ Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup Use logon task instead of startup entry for faster startup experience + After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index e52614e74..a80e618e8 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Fri, 21 Feb 2025 20:45:42 +0800 Subject: [PATCH 06/28] Improve code quality --- Flow.Launcher/CustomQueryHotkeySetting.xaml | 5 +---- Flow.Launcher/CustomShortcutSetting.xaml | 5 +---- Flow.Launcher/PriorityChangeWindow.xaml | 5 +---- Flow.Launcher/SelectBrowserWindow.xaml | 5 +---- Flow.Launcher/SelectFileManagerWindow.xaml | 5 +---- Flow.Launcher/WelcomeWindow.xaml | 5 +---- 6 files changed, 6 insertions(+), 24 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml b/Flow.Launcher/CustomQueryHotkeySetting.xaml index 068afda15..70ebb404b 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml @@ -32,14 +32,11 @@ - - - + + + diff --git a/Flow.Launcher/ReportWindow.xaml.cs b/Flow.Launcher/ReportWindow.xaml.cs index a535dfb3e..12ffe3ffc 100644 --- a/Flow.Launcher/ReportWindow.xaml.cs +++ b/Flow.Launcher/ReportWindow.xaml.cs @@ -6,10 +6,10 @@ using System.Text; using System.Linq; using System.Windows; using System.Windows.Documents; -using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; +using Flow.Launcher.Infrastructure.Exception; namespace Flow.Launcher { @@ -43,32 +43,36 @@ namespace Flow.Launcher var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First(); var websiteUrl = exception switch - { - FlowPluginException pluginException =>GetIssuesUrl(pluginException.Metadata.Website), - _ => Constant.IssuesUrl - }; - + { + FlowPluginException pluginException =>GetIssuesUrl(pluginException.Metadata.Website), + _ => Constant.IssuesUrl + }; - var paragraph = Hyperlink("Please open new issue in: ", websiteUrl); - paragraph.Inlines.Add($"1. upload log file: {log.FullName}\n"); - paragraph.Inlines.Add($"2. copy below exception message"); + var paragraph = Hyperlink(App.API.GetTranslation("reportWindow_please_open_issue"), websiteUrl); + paragraph.Inlines.Add(string.Format(App.API.GetTranslation("reportWindow_upload_log"), log.FullName)); + paragraph.Inlines.Add("\n"); + paragraph.Inlines.Add(App.API.GetTranslation("reportWindow_copy_below")); ErrorTextbox.Document.Blocks.Add(paragraph); StringBuilder content = new StringBuilder(); - content.AppendLine(ErrorReporting.RuntimeInfo()); - content.AppendLine(ErrorReporting.DependenciesInfo()); - content.AppendLine($"Date: {DateTime.Now.ToString(CultureInfo.InvariantCulture)}"); - content.AppendLine("Exception:"); + content.AppendLine(RuntimeInfo()); + content.AppendLine(); + content.AppendLine(DependenciesInfo()); + content.AppendLine(); + content.AppendLine(string.Format(App.API.GetTranslation("reportWindow_date"), DateTime.Now.ToString(CultureInfo.InvariantCulture))); + content.AppendLine(App.API.GetTranslation("reportWindow_exception")); content.AppendLine(exception.ToString()); paragraph = new Paragraph(); paragraph.Inlines.Add(content.ToString()); ErrorTextbox.Document.Blocks.Add(paragraph); } - private Paragraph Hyperlink(string textBeforeUrl, string url) + private static Paragraph Hyperlink(string textBeforeUrl, string url) { - var paragraph = new Paragraph(); - paragraph.Margin = new Thickness(0); + var paragraph = new Paragraph + { + Margin = new Thickness(0) + }; var link = new Hyperlink { @@ -79,10 +83,38 @@ namespace Flow.Launcher link.Click += (s, e) => SearchWeb.OpenInBrowserTab(url); paragraph.Inlines.Add(textBeforeUrl); + paragraph.Inlines.Add(" "); paragraph.Inlines.Add(link); paragraph.Inlines.Add("\n"); return paragraph; } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private static string RuntimeInfo() + { + var info = + $""" + Flow Launcher {App.API.GetTranslation("reportWindow_version")}: {Constant.Version} + OS {App.API.GetTranslation("reportWindow_version")}: {ExceptionFormatter.GetWindowsFullVersionFromRegistry()} + IntPtr {App.API.GetTranslation("reportWindow_length")}: {IntPtr.Size} + x64: {Environment.Is64BitOperatingSystem} + """; + return info; + } + + private static string DependenciesInfo() + { + var info = + $""" + {App.API.GetTranslation("pythonFilePath")}: {Constant.PythonPath} + {App.API.GetTranslation("nodeFilePath")}: {Constant.NodePath} + """; + return info; + } } } From 156668e1098287328c691ed2fcb76dcc62490d10 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 22 Feb 2025 16:12:41 +0800 Subject: [PATCH 08/28] Add minimize & background option for progress box ex --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/ProgressBoxEx.xaml | 31 ++++++++++++++++++++++++++++- Flow.Launcher/ProgressBoxEx.xaml.cs | 11 +++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f..d36fd2e90 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -367,6 +367,7 @@ OK Yes No + Background Version diff --git a/Flow.Launcher/ProgressBoxEx.xaml b/Flow.Launcher/ProgressBoxEx.xaml index 3102cfb72..32b0f64b4 100644 --- a/Flow.Launcher/ProgressBoxEx.xaml +++ b/Flow.Launcher/ProgressBoxEx.xaml @@ -35,9 +35,32 @@ + +