From 3cb9d1dce4b606cc80fb3a7fc9e51da08237c1b8 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 12 Jan 2025 20:04:44 +0800
Subject: [PATCH] Remove IApp & AppExtensions and use dependency injection
instead
---
Flow.Launcher.Core/AppExtensions.cs | 15 ------------
Flow.Launcher.Core/Configuration/Portable.cs | 24 +++++++++++--------
.../Environments/AbstractPluginEnvironment.cs | 11 +++++----
.../Environments/PythonEnvironment.cs | 2 +-
.../Environments/TypeScriptEnvironment.cs | 2 +-
.../Environments/TypeScriptV2Environment.cs | 2 +-
Flow.Launcher.Core/IApp.cs | 13 ----------
Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +-
Flow.Launcher.Core/Plugin/PluginsLoader.cs | 3 ++-
.../Resource/Internationalization.cs | 3 ++-
Flow.Launcher.Core/Resource/Theme.cs | 7 ++++--
Flow.Launcher.Core/Updater.cs | 17 +++++++------
Flow.Launcher/App.xaml.cs | 2 ++
.../ViewModel/SettingWindowViewModel.cs | 10 ++++++--
14 files changed, 54 insertions(+), 59 deletions(-)
delete mode 100644 Flow.Launcher.Core/AppExtensions.cs
delete mode 100644 Flow.Launcher.Core/IApp.cs
diff --git a/Flow.Launcher.Core/AppExtensions.cs b/Flow.Launcher.Core/AppExtensions.cs
deleted file mode 100644
index b02612d72..000000000
--- a/Flow.Launcher.Core/AppExtensions.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.Windows;
-using Flow.Launcher.Plugin;
-
-namespace Flow.Launcher.Core;
-
-///
-/// Extension properties and functions of the current application singleton object.
-///
-public static class AppExtensions
-{
- ///
- /// Gets the public API of the current application singleton object.
- ///
- public static IPublicAPI API => (Application.Current as IApp)!.PublicAPI;
-}
diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs
index cb375c586..069154364 100644
--- a/Flow.Launcher.Core/Configuration/Portable.cs
+++ b/Flow.Launcher.Core/Configuration/Portable.cs
@@ -9,11 +9,15 @@ using Flow.Launcher.Infrastructure.Logger;
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 @@ namespace Flow.Launcher.Core.Configuration
#endif
IndicateDeletion(DataLocation.PortableDataPath);
- AppExtensions.API.ShowMsgBox("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 @@ namespace Flow.Launcher.Core.Configuration
#endif
IndicateDeletion(DataLocation.RoamingDataPath);
- AppExtensions.API.ShowMsgBox("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 @@ namespace Flow.Launcher.Core.Configuration
public void MoveUserDataFolder(string fromLocation, string toLocation)
{
- FilesFolders.CopyAll(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.CopyAll(fromLocation, toLocation, (s) => API.ShowMsgBox(s));
VerifyUserDataAfterMove(fromLocation, toLocation);
}
public void VerifyUserDataAfterMove(string fromLocation, string toLocation)
{
- FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => API.ShowMsgBox(s));
}
public void CreateShortcuts()
@@ -157,13 +161,13 @@ namespace Flow.Launcher.Core.Configuration
// delete it and prompt the user to pick the portable data location
if (File.Exists(roamingDataDeleteFilePath))
{
- FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s));
- if (AppExtensions.API.ShowMsgBox("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, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s));
Environment.Exit(0);
}
@@ -172,9 +176,9 @@ namespace Flow.Launcher.Core.Configuration
// delete it and notify the user about it.
else if (File.Exists(portableDataDeleteFilePath))
{
- FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s));
- AppExtensions.API.ShowMsgBox("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 @@ namespace Flow.Launcher.Core.Configuration
if (roamingLocationExists && portableLocationExists)
{
- AppExtensions.API.ShowMsgBox(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 cada05031..451df6147 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
@@ -8,11 +8,14 @@ using System.Linq;
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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
EnvName,
Environment.NewLine
);
- if (AppExtensions.API.ShowMsgBox(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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
}
else
{
- AppExtensions.API.ShowMsgBox(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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
if (expectedPath == currentPath)
return;
- FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => AppExtensions.API.ShowMsgBox(s));
+ 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 56bc20b4f..607c19062 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs
@@ -28,7 +28,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment()
{
- FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s));
+ 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 1d43b815a..399f7cc03 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs
@@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment()
{
- FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s));
+ 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 49bf4e958..e8cb72e11 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs
@@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment()
{
- FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s));
+ FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait();
diff --git a/Flow.Launcher.Core/IApp.cs b/Flow.Launcher.Core/IApp.cs
deleted file mode 100644
index 233fd5ed1..000000000
--- a/Flow.Launcher.Core/IApp.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Flow.Launcher.Plugin;
-
-namespace Flow.Launcher.Core
-{
- ///
- /// Interface for the current application singleton object exposing the properties
- /// and functions that can be accessed from anywhere in the application.
- ///
- public interface IApp
- {
- public IPublicAPI PublicAPI { get; }
- }
-}
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 9e1cf3b9d..a776c10ab 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -519,7 +519,7 @@ namespace Flow.Launcher.Core.Plugin
var newPluginPath = Path.Combine(installDirectory, folderName);
- FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => AppExtensions.API.ShowMsgBox(s));
+ 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 8cbeb7473..4827cf69d 100644
--- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
@@ -4,6 +4,7 @@ using System.Linq;
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 @@ namespace Flow.Launcher.Core.Plugin
_ = Task.Run(() =>
{
- AppExtensions.API.ShowMsgBox($"{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 a1cefabe3..de066dda1 100644
--- a/Flow.Launcher.Core/Resource/Internationalization.cs
+++ b/Flow.Launcher.Core/Resource/Internationalization.cs
@@ -11,6 +11,7 @@ using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using System.Globalization;
using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.DependencyInjection;
namespace Flow.Launcher.Core.Resource
{
@@ -124,7 +125,7 @@ namespace Flow.Launcher.Core.Resource
// "Do you want to search with pinyin?"
string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ;
- if (AppExtensions.API.ShowMsgBox(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 8622d4caf..2749da532 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -11,6 +11,8 @@ using System.Windows.Media.Effects;
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 @@ namespace Flow.Launcher.Core.Resource
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 @@ namespace Flow.Launcher.Core.Resource
Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found");
if (theme != defaultTheme)
{
- AppExtensions.API.ShowMsgBox(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 @@ namespace Flow.Launcher.Core.Resource
Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse");
if (theme != defaultTheme)
{
- AppExtensions.API.ShowMsgBox(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 8745d54b7..373418055 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -17,14 +17,17 @@ using Flow.Launcher.Infrastructure.UserSettings;
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;
}
@@ -53,7 +56,7 @@ namespace Flow.Launcher.Core
if (newReleaseVersion <= currentVersion)
{
if (!silentUpdate)
- AppExtensions.API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest"));
+ API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest"));
return;
}
@@ -68,9 +71,9 @@ namespace Flow.Launcher.Core
if (DataLocation.PortableDataLocationInUse())
{
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}";
- FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s));
- if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s)))
- AppExtensions.API.ShowMsgBox(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 @@ namespace Flow.Launcher.Core
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
- if (AppExtensions.API.ShowMsgBox(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);
}
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 9b86c6cc4..0d6d9855c 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -74,6 +74,8 @@ namespace Flow.Launcher
Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate();
+ Ioc.Default.GetRequiredService().Initialize();
+
Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index 7549db1a3..bbd47e731 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -8,15 +8,21 @@ namespace Flow.Launcher.ViewModel;
public class SettingWindowViewModel : BaseModel
{
- public Updater Updater { get; }
+ public Updater Updater { get; private set; }
- public IPortable Portable { get; }
+ public IPortable Portable { get; private set; }
public Settings Settings { get; }
public SettingWindowViewModel()
{
Settings = Ioc.Default.GetRequiredService();
+ }
+
+ public void Initialize()
+ {
+ // We don not initialize Updater and Portable in the constructor because we want to avoid
+ // recrusive dependency injection
Updater = Ioc.Default.GetRequiredService();
Portable = Ioc.Default.GetRequiredService();
}