diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index d7c73fb46ac..069154364ab 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -9,11 +9,15 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.SharedCommands; using System.Linq; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Configuration { public class Portable : IPortable { + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); + /// /// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish /// @@ -40,7 +44,7 @@ public void DisablePortableMode() #endif IndicateDeletion(DataLocation.PortableDataPath); - MessageBoxEx.Show("Flow Launcher needs to restart to finish disabling portable mode, " + + API.ShowMsgBox("Flow Launcher needs to restart to finish disabling portable mode, " + "after the restart your portable data profile will be deleted and roaming data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -64,7 +68,7 @@ public void EnablePortableMode() #endif IndicateDeletion(DataLocation.RoamingDataPath); - MessageBoxEx.Show("Flow Launcher needs to restart to finish enabling portable mode, " + + API.ShowMsgBox("Flow Launcher needs to restart to finish enabling portable mode, " + "after the restart your roaming data profile will be deleted and portable data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -95,13 +99,13 @@ public void RemoveUninstallerEntry() public void MoveUserDataFolder(string fromLocation, string toLocation) { - FilesFolders.CopyAll(fromLocation, toLocation, MessageBoxEx.Show); + FilesFolders.CopyAll(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); VerifyUserDataAfterMove(fromLocation, toLocation); } public void VerifyUserDataAfterMove(string fromLocation, string toLocation) { - FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, MessageBoxEx.Show); + FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); } public void CreateShortcuts() @@ -157,13 +161,13 @@ public void PreStartCleanUpAfterPortabilityUpdate() // delete it and prompt the user to pick the portable data location if (File.Exists(roamingDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(roamingDataDir, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s)); - if (MessageBoxEx.Show("Flow Launcher has detected you enabled portable mode, " + + if (API.ShowMsgBox("Flow Launcher has detected you enabled portable mode, " + "would you like to move it to a different location?", string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - FilesFolders.OpenPath(Constant.RootDirectory, MessageBoxEx.Show); + FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); Environment.Exit(0); } @@ -172,9 +176,9 @@ public void PreStartCleanUpAfterPortabilityUpdate() // delete it and notify the user about it. else if (File.Exists(portableDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(portableDataDir, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s)); - MessageBoxEx.Show("Flow Launcher has detected you disabled portable mode, " + + API.ShowMsgBox("Flow Launcher has detected you disabled portable mode, " + "the relevant shortcuts and uninstaller entry have been created"); } } @@ -186,7 +190,7 @@ public bool CanUpdatePortability() if (roamingLocationExists && portableLocationExists) { - MessageBoxEx.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " + + API.ShowMsgBox(string.Format("Flow Launcher detected your user data exists both in {0} and " + "{1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred.", DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 6d41e23834e..451df6147fa 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -8,11 +8,14 @@ using System.Windows; using System.Windows.Forms; using Flow.Launcher.Core.Resource; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.ExternalPlugins.Environments { public abstract class AbstractPluginEnvironment { + protected readonly IPublicAPI API = Ioc.Default.GetRequiredService(); + internal abstract string Language { get; } internal abstract string EnvName { get; } @@ -25,7 +28,7 @@ public abstract class AbstractPluginEnvironment internal virtual string FileDialogFilter => string.Empty; - internal abstract string PluginsSettingsFilePath { get; set; } + internal abstract string PluginsSettingsFilePath { get; set; } internal List PluginMetadataList; @@ -57,7 +60,7 @@ internal IEnumerable Setup() EnvName, Environment.NewLine ); - if (MessageBoxEx.Show(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); string selectedFile; @@ -82,7 +85,7 @@ internal IEnumerable Setup() } else { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); Log.Error("PluginsLoader", $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -98,7 +101,7 @@ private void EnsureLatestInstalled(string expectedPath, string currentPath, stri if (expectedPath == currentPath) return; - FilesFolders.RemoveFolderIfExists(installedDirPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => API.ShowMsgBox(s)); InstallEnvironment(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index 96c29646e8f..607c1906215 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -28,7 +28,7 @@ internal PythonEnvironment(List pluginMetadataList, PluginsSetti internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); // Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and // uses Python plugin they need to custom install and use v3.8.9 diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 0d6f109e07f..399f7cc03fd 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -25,7 +25,7 @@ internal TypeScriptEnvironment(List pluginMetadataList, PluginsS internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index 582a4407c45..e8cb72e11d6 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -25,7 +25,7 @@ internal TypeScriptV2Environment(List pluginMetadataList, Plugin internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 5c4eaa1dadc..0e8a4b7764b 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -14,6 +14,7 @@ using Flow.Launcher.Plugin.SharedCommands; using System.Text.Json; using Flow.Launcher.Core.Resource; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Plugin { @@ -28,7 +29,7 @@ public static class PluginManager public static readonly HashSet GlobalPlugins = new(); public static readonly Dictionary NonGlobalPlugins = new(); - public static IPublicAPI API { private set; get; } + public static IPublicAPI API { get; private set; } = Ioc.Default.GetRequiredService(); private static PluginsSettings Settings; private static List _metadatas; @@ -158,9 +159,8 @@ public static void LoadPlugins(PluginsSettings settings) /// Call initialize for all plugins /// /// return the list of failed to init plugins or null for none - public static async Task InitializePluginsAsync(IPublicAPI api) + public static async Task InitializePluginsAsync() { - API = api; var failedPlugins = new ConcurrentQueue(); var InitTasks = AllPlugins.Select(pair => Task.Run(async delegate @@ -519,7 +519,7 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c var newPluginPath = Path.Combine(installDirectory, folderName); - FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show); + FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => API.ShowMsgBox(s)); Directory.Delete(tempFolderPluginPath, true); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 7973c66baa7..4827cf69d41 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Threading.Tasks; using System.Windows; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.ExternalPlugins.Environments; #pragma warning disable IDE0005 using Flow.Launcher.Infrastructure.Logger; @@ -119,7 +120,7 @@ public static IEnumerable DotNetPlugins(List source) _ = Task.Run(() => { - MessageBoxEx.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + + Ioc.Default.GetRequiredService().ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + $"Please refer to the logs for more information", "", MessageBoxButton.OK, MessageBoxImage.Warning); diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index ef38e8be097..884276f03c6 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -11,6 +11,7 @@ using Flow.Launcher.Plugin; using System.Globalization; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Resource { @@ -162,7 +163,7 @@ public bool PromptShouldUsePinyin(string languageCodeToSet) // "Do you want to search with pinyin?" string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ; - if (MessageBoxEx.Show(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (Ioc.Default.GetRequiredService().ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) return false; return true; diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 1d840930663..2749da53209 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -11,6 +11,8 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { @@ -22,6 +24,7 @@ public class Theme private const int ShadowExtraMargin = 32; + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); private readonly List _themeDirectories = new List(); private ResourceDictionary _oldResource; private string _oldTheme; @@ -108,7 +111,7 @@ public bool ChangeTheme(string theme) Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); if (theme != defaultTheme) { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); ChangeTheme(defaultTheme); } return false; @@ -118,7 +121,7 @@ public bool ChangeTheme(string theme) Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); if (theme != defaultTheme) { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); ChangeTheme(defaultTheme); } return false; diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index b92d8656873..7a25447b4d3 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -17,28 +17,31 @@ using Flow.Launcher.Plugin; using System.Text.Json.Serialization; using System.Threading; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core { public class Updater { - public string GitHubRepository { get; } + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); - public Updater(string gitHubRepository) + public string GitHubRepository { get; set; } + + public void Initialize(string gitHubRepository) { GitHubRepository = gitHubRepository; } private SemaphoreSlim UpdateLock { get; } = new SemaphoreSlim(1); - public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) + public async Task UpdateAppAsync(bool silentUpdate = true) { await UpdateLock.WaitAsync().ConfigureAwait(false); try { if (!silentUpdate) - api.ShowMsg(api.GetTranslation("pleaseWait"), - api.GetTranslation("update_flowlauncher_update_check")); + API.ShowMsg(API.GetTranslation("pleaseWait"), + API.GetTranslation("update_flowlauncher_update_check")); using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false); @@ -53,13 +56,13 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) if (newReleaseVersion <= currentVersion) { if (!silentUpdate) - MessageBoxEx.Show(api.GetTranslation("update_flowlauncher_already_on_latest")); + API.ShowMsgBox(API.GetTranslation("update_flowlauncher_already_on_latest")); return; } if (!silentUpdate) - api.ShowMsg(api.GetTranslation("update_flowlauncher_update_found"), - api.GetTranslation("update_flowlauncher_updating")); + API.ShowMsg(API.GetTranslation("update_flowlauncher_update_found"), + API.GetTranslation("update_flowlauncher_updating")); await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false); @@ -68,9 +71,9 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) if (DataLocation.PortableDataLocationInUse()) { var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; - FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show); - if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show)) - MessageBoxEx.Show(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), + FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => API.ShowMsgBox(s)); + if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => API.ShowMsgBox(s))) + API.ShowMsgBox(string.Format(API.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), DataLocation.PortableDataPath, targetDestination)); } @@ -83,7 +86,7 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); - if (MessageBoxEx.Show(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (API.ShowMsgBox(newVersionTips, API.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UpdateManager.RestartApp(Constant.ApplicationFileName); } @@ -96,8 +99,8 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) Log.Exception($"|Updater.UpdateApp|Error Occurred", e); if (!silentUpdate) - api.ShowMsg(api.GetTranslation("update_flowlauncher_fail"), - api.GetTranslation("update_flowlauncher_check_connection")); + API.ShowMsg(API.GetTranslation("update_flowlauncher_fail"), + API.GetTranslation("update_flowlauncher_check_connection")); } finally { diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 1d6ee5c86aa..5d8b264251a 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -54,6 +54,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 14b8eef4e16..78545a87b76 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -8,6 +8,7 @@ using System; using System.Threading; using Flow.Launcher.Plugin; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Infrastructure.Http { @@ -17,8 +18,6 @@ public static class Http private static HttpClient client = new HttpClient(); - public static IPublicAPI API { get; set; } - static Http() { // need to be added so it would work on a win10 machine @@ -78,7 +77,7 @@ var userName when string.IsNullOrEmpty(userName) => } catch (UriFormatException e) { - API.ShowMsg("Please try again", "Unable to parse Http Proxy"); + Ioc.Default.GetRequiredService().ShowMsg("Please try again", "Unable to parse Http Proxy"); Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); } } diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 7d72359684d..8eaa757bec1 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -6,6 +6,7 @@ using JetBrains.Annotations; using Flow.Launcher.Infrastructure.UserSettings; using ToolGood.Words.Pinyin; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Infrastructure { @@ -129,7 +130,12 @@ public class PinyinAlphabet : IAlphabet private Settings _settings; - public void Initialize([NotNull] Settings settings) + public PinyinAlphabet() + { + Initialize(Ioc.Default.GetRequiredService()); + } + + private void Initialize([NotNull] Settings settings) { _settings = settings ?? throw new ArgumentNullException(nameof(settings)); } diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index bd5dbdda9be..f5f02cbfcae 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Plugin.SharedModels; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin.SharedModels; using System; using System.Collections.Generic; using System.Linq; @@ -7,13 +8,19 @@ namespace Flow.Launcher.Infrastructure { public class StringMatcher { - private readonly MatchOption _defaultMatchOption = new MatchOption(); + private readonly MatchOption _defaultMatchOption = new(); public SearchPrecisionScore UserSettingSearchPrecision { get; set; } private readonly IAlphabet _alphabet; - public StringMatcher(IAlphabet alphabet = null) + public StringMatcher() + { + _alphabet = Ioc.Default.GetRequiredService(); + } + + // This is a workaround to allow unit tests to set the instance + public StringMatcher(IAlphabet alphabet) { _alphabet = alphabet; } @@ -241,16 +248,16 @@ private bool IsAcronymCount(string stringToCompare, int compareStringIndex) return false; } - private bool IsAcronymChar(string stringToCompare, int compareStringIndex) + private static bool IsAcronymChar(string stringToCompare, int compareStringIndex) => char.IsUpper(stringToCompare[compareStringIndex]) || compareStringIndex == 0 || // 0 index means char is the start of the compare string, which is an acronym char.IsWhiteSpace(stringToCompare[compareStringIndex - 1]); - private bool IsAcronymNumber(string stringToCompare, int compareStringIndex) + private static bool IsAcronymNumber(string stringToCompare, int compareStringIndex) => stringToCompare[compareStringIndex] >= 0 && stringToCompare[compareStringIndex] <= 9; // To get the index of the closest space which preceeds the first matching index - private int CalculateClosestSpaceIndex(List spaceIndices, int firstMatchIndex) + private static int CalculateClosestSpaceIndex(List spaceIndices, int firstMatchIndex) { var closestSpaceIndex = -1; diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index c412fb32f5a..2a9d901fa92 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Text.Json.Serialization; using System.Windows; using Flow.Launcher.Infrastructure.Hotkey; +using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; @@ -13,6 +13,18 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public class Settings : BaseModel, IHotkeySettings { + private FlowLauncherJsonStorage _storage; + + public void Initialize(FlowLauncherJsonStorage storage) + { + _storage = storage; + } + + public void Save() + { + _storage.Save(); + } + private string language = Constant.SystemLanguageCode; private string _theme = Constant.DefaultTheme; public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}"; diff --git a/Flow.Launcher.Test/FuzzyMatcherTest.cs b/Flow.Launcher.Test/FuzzyMatcherTest.cs index d7f1432184c..d97ce227c1a 100644 --- a/Flow.Launcher.Test/FuzzyMatcherTest.cs +++ b/Flow.Launcher.Test/FuzzyMatcherTest.cs @@ -21,6 +21,8 @@ public class FuzzyMatcherTest private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio"; private const string VisualStudioCode = "Visual Studio Code"; + private readonly IAlphabet alphabet = null; + public List GetSearchStrings() => new List { @@ -59,7 +61,7 @@ public void MatchTest() }; var results = new List(); - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); foreach (var str in sources) { results.Add(new Result @@ -81,7 +83,7 @@ public void MatchTest() public void WhenNotAllCharactersFoundInSearchString_ThenShouldReturnZeroScore(string searchString) { var compareString = "Can have rum only in my glass"; - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var scoreResult = matcher.FuzzyMatch(searchString, compareString).RawScore; Assert.True(scoreResult == 0); @@ -97,7 +99,7 @@ public void GivenQueryString_WhenAppliedPrecisionFiltering_ThenShouldReturnGreat string searchTerm) { var results = new List(); - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); foreach (var str in GetSearchStrings()) { results.Add(new Result @@ -147,7 +149,7 @@ public void WhenGivenQueryString_ThenShouldReturn_TheDesiredScoring( string queryString, string compareString, int expectedScore) { // When, Given - var matcher = new StringMatcher {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; var rawScore = matcher.FuzzyMatch(queryString, compareString).RawScore; // Should @@ -181,7 +183,7 @@ public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual( bool expectedPrecisionResult) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = expectedPrecisionScore}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = expectedPrecisionScore}; // Given var matchResult = matcher.FuzzyMatch(queryString, compareString); @@ -232,7 +234,7 @@ public void WhenGivenQuery_ShouldReturnResults_ContainingAllQuerySubstrings( bool expectedPrecisionResult) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = expectedPrecisionScore}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = expectedPrecisionScore}; // Given var matchResult = matcher.FuzzyMatch(queryString, compareString); @@ -260,7 +262,7 @@ public void WhenGivenAQuery_Scoring_ShouldGiveMoreWeightToStartOfNewWord( string queryString, string compareString1, string compareString2) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; // Given var compareString1Result = matcher.FuzzyMatch(queryString, compareString1); @@ -293,7 +295,7 @@ public void WhenGivenTwoStrings_Scoring_ShouldGiveMoreWeightToTheStringCloserToI string queryString, string compareString1, string compareString2) { // When - var matcher = new StringMatcher { UserSettingSearchPrecision = SearchPrecisionScore.Regular }; + var matcher = new StringMatcher(alphabet) { UserSettingSearchPrecision = SearchPrecisionScore.Regular }; // Given var compareString1Result = matcher.FuzzyMatch(queryString, compareString1); @@ -323,7 +325,7 @@ public void WhenMultipleResults_ExactMatchingResult_ShouldHaveGreatestScore( string secondName, string secondDescription, string secondExecutableName) { // Act - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var firstNameMatch = matcher.FuzzyMatch(queryString, firstName).RawScore; var firstDescriptionMatch = matcher.FuzzyMatch(queryString, firstDescription).RawScore; var firstExecutableNameMatch = matcher.FuzzyMatch(queryString, firstExecutableName).RawScore; @@ -358,7 +360,7 @@ public void WhenMultipleResults_ExactMatchingResult_ShouldHaveGreatestScore( public void WhenGivenAnAcronymQuery_ShouldReturnAcronymScore(string queryString, string compareString, int desiredScore) { - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var score = matcher.FuzzyMatch(queryString, compareString).Score; Assert.IsTrue(score == desiredScore, $@"Query: ""{queryString}"" diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index ba47a4ded22..c3966e61850 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -44,7 +44,7 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) else { string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned"); - MessageBoxEx.Show(msg); + App.API.ShowMsgBox(msg); } } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4d1adc6cd51..5f7f097e0dd 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Core.ExternalPlugins.Environments; @@ -14,24 +15,49 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { public partial class App : IDisposable, ISingleInstanceApp { - public static PublicAPIInstance API { get; private set; } + public static IPublicAPI API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; - private Settings _settings; - private MainViewModel _mainVM; - private SettingWindowViewModel _settingsVM; - private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo); - private readonly Portable _portable = new Portable(); - private readonly PinyinAlphabet _alphabet = new PinyinAlphabet(); - private StringMatcher _stringMatcher; + private readonly Settings _settings; + + public App() + { + // Initialize settings + var storage = new FlowLauncherJsonStorage(); + _settings = storage.Load(); + _settings.Initialize(storage); + _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); + + // Configure the dependency injection container + var host = Host.CreateDefaultBuilder() + .UseContentRoot(AppContext.BaseDirectory) + .ConfigureServices(services => services + .AddSingleton(_ => _settings) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ).Build(); + Ioc.Default.ConfigureServices(host.Services); + + // Initialize the public API first + API = Ioc.Default.GetRequiredService(); + } [STAThread] public static void Main() @@ -50,49 +76,43 @@ private async void OnStartupAsync(object sender, StartupEventArgs e) { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { - _portable.PreStartCleanUpAfterPortabilityUpdate(); + Ioc.Default.GetRequiredService().Initialize(Launcher.Properties.Settings.Default.GithubRepo); - Log.Info( - "|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); + Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); + + Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); + RegisterAppDomainExceptions(); RegisterDispatcherUnhandledException(); var imageLoadertask = ImageLoader.InitializeAsync(); - _settingsVM = new SettingWindowViewModel(_updater, _portable); - _settings = _settingsVM.Settings; - _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); - AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings); - _alphabet.Initialize(_settings); - _stringMatcher = new StringMatcher(_alphabet); - StringMatcher.Instance = _stringMatcher; - _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; + var stringMatcher = Ioc.Default.GetRequiredService(); + StringMatcher.Instance = stringMatcher; + stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; InternationalizationManager.Instance.Settings = _settings; InternationalizationManager.Instance.ChangeLanguage(_settings.Language); PluginManager.LoadPlugins(_settings.PluginSettings); - _mainVM = new MainViewModel(_settings); - - API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet); - Http.API = API; Http.Proxy = _settings.Proxy; - await PluginManager.InitializePluginsAsync(API); + await PluginManager.InitializePluginsAsync(); await imageLoadertask; - var window = new MainWindow(_settings, _mainVM); + var mainVM = Ioc.Default.GetRequiredService(); + var window = new MainWindow(_settings, mainVM); Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); Current.MainWindow = window; Current.MainWindow.Title = Constant.FlowLauncher; - HotKeyMapper.Initialize(_mainVM); + HotKeyMapper.Initialize(mainVM); // main windows needs initialized before theme change because of blur settings ThemeManager.Instance.Settings = _settings; @@ -141,11 +161,11 @@ private void AutoUpdates() { // check update every 5 hours var timer = new PeriodicTimer(TimeSpan.FromHours(5)); - await _updater.UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(); while (await timer.WaitForNextTickAsync()) // check updates on startup - await _updater.UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(); } }); } @@ -188,7 +208,7 @@ public void Dispose() public void OnSecondAppStarted() { - _mainVM.Show(); + Ioc.Default.GetRequiredService().Show(); } } } diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 81e7600b8fa..eab2705d004 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -6,20 +6,17 @@ using System.Windows; using System.Windows.Input; using System.Windows.Controls; -using Flow.Launcher.Core; namespace Flow.Launcher { public partial class CustomQueryHotkeySetting : Window { - private SettingWindow _settingWidow; private bool update; private CustomPluginHotkey updateCustomHotkey; public Settings Settings { get; } - public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings) + public CustomQueryHotkeySetting(Settings settings) { - _settingWidow = settingWidow; Settings = settings; InitializeComponent(); } @@ -63,7 +60,7 @@ public void UpdateItem(CustomPluginHotkey item) o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); if (updateCustomHotkey == null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); Close(); return; } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index dec3506eb35..4589b45ec72 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -43,13 +43,13 @@ private void BtnAdd_OnClick(object sender, RoutedEventArgs e) { if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value)) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); return; } // Check if key is modified or adding a new one if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key)) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); return; } DialogResult = !update || originalKey != Key || originalValue != Value; diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 788beddfb37..f0a8c120200 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -83,12 +83,13 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive + + all diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 8b30b8be1f5..b40406e4282 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -46,7 +46,7 @@ internal static void SetHotkey(HotkeyModel hotkey, EventHandler { string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); - MessageBoxEx.Show(errorMsg, errorMsgTitle); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } diff --git a/Flow.Launcher.Core/MessageBoxEx.xaml b/Flow.Launcher/MessageBoxEx.xaml similarity index 98% rename from Flow.Launcher.Core/MessageBoxEx.xaml rename to Flow.Launcher/MessageBoxEx.xaml index fff107a68a4..be12ca16c20 100644 --- a/Flow.Launcher.Core/MessageBoxEx.xaml +++ b/Flow.Launcher/MessageBoxEx.xaml @@ -1,9 +1,9 @@ (); + _mainVM = Ioc.Default.GetRequiredService(); GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } @@ -78,14 +77,14 @@ public void RestartApp() public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; } - public void CheckForNewUpdate() => _settingsVM.UpdateApp(); + public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false); public void SaveAppAllSettings() { PluginManager.Save(); _mainVM.Save(); _settingsVM.Save(); - ImageLoader.Save(); + _ = ImageLoader.Save(); } public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); @@ -105,7 +104,7 @@ public void OpenSettingDialog() { Application.Current.Dispatcher.Invoke(() => { - SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); + SettingWindow sw = SingletonWindowOpener.Open(); }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 6e81db5e00d..cb434f399f0 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -62,7 +62,7 @@ private void OpenWelcomeWindow() [RelayCommand] private void AskClearLogFolderConfirmation() { - var confirmResult = MessageBoxEx.Show( + var confirmResult = App.API.ShowMsgBox( InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), InternationalizationManager.Instance.GetTranslation("clearlogfolder"), MessageBoxButton.YesNo @@ -96,7 +96,7 @@ private void OpenLogsFolder() } [RelayCommand] - private Task UpdateApp() => _updater.UpdateAppAsync(App.API, false); + private Task UpdateApp() => _updater.UpdateAppAsync(false); private void ClearLogFolder() { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 3d94355e687..4e498ba23fa 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -160,7 +160,7 @@ private string GetFileFromDialog(string title, string filter = "") private void UpdateApp() { - _ = _updater.UpdateAppAsync(App.API, false); + _ = _updater.UpdateAppAsync(false); } public bool AutoUpdates diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index 6d8af9a3f62..b13aaefe3e9 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -7,7 +7,6 @@ using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using Flow.Launcher.Core; namespace Flow.Launcher.SettingPages.ViewModels; @@ -42,11 +41,11 @@ private void CustomHotkeyDelete() var item = SelectedCustomPluginHotkey; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } - var result = MessageBoxEx.Show( + var result = App.API.ShowMsgBox( string.Format( InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey ), @@ -67,11 +66,11 @@ private void CustomHotkeyEdit() var item = SelectedCustomPluginHotkey; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } - var window = new CustomQueryHotkeySetting(null, Settings); + var window = new CustomQueryHotkeySetting(Settings); window.UpdateItem(item); window.ShowDialog(); } @@ -79,7 +78,7 @@ private void CustomHotkeyEdit() [RelayCommand] private void CustomHotkeyAdd() { - new CustomQueryHotkeySetting(null, Settings).ShowDialog(); + new CustomQueryHotkeySetting(Settings).ShowDialog(); } [RelayCommand] @@ -88,11 +87,11 @@ private void CustomShortcutDelete() var item = SelectedCustomShortcut; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } - var result = MessageBoxEx.Show( + var result = App.API.ShowMsgBox( string.Format( InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value ), @@ -112,7 +111,7 @@ private void CustomShortcutEdit() var item = SelectedCustomShortcut; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs index 1c840fb2703..e2f9e516ca4 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs @@ -22,7 +22,7 @@ public SettingsPaneProxyViewModel(Settings settings, Updater updater) private void OnTestProxyClicked() { var message = TestProxy(); - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation(message)); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation(message)); } private string TestProxy() diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 8d8ccb78041..980b2a811a4 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -49,7 +49,7 @@ public bool DropShadowEffect { if (ThemeManager.Instance.BlurEnabled && value) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); return; } diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index cb3f1e4a113..ab639e987ed 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -3,6 +3,7 @@ using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Helper; @@ -17,16 +18,21 @@ namespace Flow.Launcher; public partial class SettingWindow { + private readonly Updater _updater; + private readonly IPortable _portable; private readonly IPublicAPI _api; private readonly Settings _settings; private readonly SettingWindowViewModel _viewModel; - public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) + public SettingWindow() { + var viewModel = Ioc.Default.GetRequiredService(); _settings = viewModel.Settings; DataContext = viewModel; _viewModel = viewModel; - _api = api; + _updater = Ioc.Default.GetRequiredService(); + _portable = Ioc.Default.GetRequiredService(); + _api = Ioc.Default.GetRequiredService(); InitializePosition(); InitializeComponent(); } @@ -125,7 +131,7 @@ public void InitializePosition() WindowState = _settings.SettingWindowState; } - private bool IsPositionValid(double top, double left) + private static bool IsPositionValid(double top, double left) { foreach (var screen in Screen.AllScreens) { @@ -145,7 +151,7 @@ private double WindowLeft() var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); - var left = (dip2.X - this.ActualWidth) / 2 + dip1.X; + var left = (dip2.X - ActualWidth) / 2 + dip1.X; return left; } @@ -154,13 +160,13 @@ private double WindowTop() var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); - var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20; + var top = (dip2.Y - ActualHeight) / 2 + dip1.Y - 20; return top; } private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { - var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable); + var paneData = new PaneData(_settings, _updater, _portable); if (args.IsSettingsSelected) { ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 55bc8d1b3f8..f5141a8fa58 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -25,6 +25,7 @@ using System.ComponentModel; using Flow.Launcher.Infrastructure.Image; using System.Windows.Media; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.ViewModel { @@ -58,13 +59,13 @@ public partial class MainViewModel : BaseModel, ISavable #region Constructor - public MainViewModel(Settings settings) + public MainViewModel() { _queryTextBeforeLeaveResults = ""; _queryText = ""; _lastQuery = new Query(); - Settings = settings; + Settings = Ioc.Default.GetRequiredService(); Settings.PropertyChanged += (_, args) => { switch (args.PropertyName) diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 04dd6312b37..37276a1addf 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,43 +1,24 @@ -using Flow.Launcher.Core; -using Flow.Launcher.Core.Configuration; -using Flow.Launcher.Infrastructure.Storage; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; namespace Flow.Launcher.ViewModel; -public class SettingWindowViewModel : BaseModel +public partial class SettingWindowViewModel : BaseModel { - private readonly FlowLauncherJsonStorage _storage; + public Settings Settings { get; init; } - public Updater Updater { get; } - - public IPortable Portable { get; } - - public Settings Settings { get; } - - public SettingWindowViewModel(Updater updater, IPortable portable) + public SettingWindowViewModel() { - _storage = new FlowLauncherJsonStorage(); - - Updater = updater; - Portable = portable; - Settings = _storage.Load(); + Settings = Ioc.Default.GetRequiredService(); } - public async void UpdateApp() - { - await Updater.UpdateAppAsync(App.API, false); - } - - - /// /// Save Flow settings. Plugins settings are not included. /// public void Save() { - _storage.Save(); + Settings.Save(); } public double SettingWindowWidth