diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 8e5a7e484..84ed104fe 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -7,11 +7,12 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Windows.Forms; namespace Flow.Launcher.Core.ExternalPlugins.Environments { - internal abstract class AbstractPluginEnvironment + public abstract class AbstractPluginEnvironment { internal abstract string Language { get; } @@ -31,6 +32,12 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal PluginsSettings PluginSettings; + private const string updatePythonIndicatorFilename = ".updatePythonPath"; + + private const string updateNodeIndicatorFilename = ".updateNodePath"; + + private const string appDataRegex = @"app-\d\.\d\.\d"; + internal AbstractPluginEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) { PluginMetadataList = pluginMetadataList; @@ -149,5 +156,117 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments return string.Empty; } } + + public static void IndicatePluginEnvPathsUpdate(Settings settings, string newVer) + { + var appVer = $"app-{newVer}"; + var updatePythonIndicatorFilePath + = Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename), appDataRegex, appVer); + var updateNodeIndicatorFilePath + = Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename), appDataRegex, appVer); + + if (!string.IsNullOrEmpty(settings.PluginSettings.PythonExecutablePath) + && settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PluginEnvironments)) + using (var _ = File.CreateText(updatePythonIndicatorFilePath)) { } + + if (!string.IsNullOrEmpty(settings.PluginSettings.NodeExecutablePath) + && settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PluginEnvironments)) + using (var _ = File.CreateText(updateNodeIndicatorFilePath)) { } + } + + public static void PreStartPluginFilePathCorrection(Settings settings) + { + PreStartCorrectionAfterUpdate(settings); + PreStartCorrectionAfterModeChange(settings); + } + + private static void PreStartCorrectionAfterUpdate(Settings settings) + { + // After updating flow, update plugin env paths. + var appVer = $"app-{Constant.Version}"; + var updatePythonIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename); + var updateNodeIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename); + + if (File.Exists(updatePythonIndicatorFilePath)) + { + settings.PluginSettings.PythonExecutablePath + = Regex.Replace(settings.PluginSettings.PythonExecutablePath, appDataRegex, appVer); + + File.Delete(updatePythonIndicatorFilePath); + } + + if (File.Exists(updateNodeIndicatorFilePath)) + { + settings.PluginSettings.NodeExecutablePath + = Regex.Replace(settings.PluginSettings.NodeExecutablePath, appDataRegex, appVer); + + File.Delete(updateNodeIndicatorFilePath); + } + } + + private static void PreStartCorrectionAfterModeChange(Settings settings) + { + // After enabling/disabling portable mode, update plugin env paths. + if (DataLocation.PortableDataLocationInUse()) + { + // When user is using portable but has moved flow to a different location + if (IsUsingPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName) + && !settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PortableDataPath)) + { + settings.PluginSettings.PythonExecutablePath + = GetUpdatedPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName); + } + + if (IsUsingPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName) + && !settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PortableDataPath)) + { + settings.PluginSettings.NodeExecutablePath + = GetUpdatedPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName); + } + + // When user has switched from roaming to portable + if (IsUsingRoamingPath(settings.PluginSettings.PythonExecutablePath)) + { + settings.PluginSettings.PythonExecutablePath + = settings.PluginSettings.PythonExecutablePath.Replace(DataLocation.RoamingDataPath, DataLocation.PortableDataPath); + } + + if (IsUsingRoamingPath(settings.PluginSettings.NodeExecutablePath)) + { + settings.PluginSettings.NodeExecutablePath + = settings.PluginSettings.NodeExecutablePath.Replace(DataLocation.RoamingDataPath, DataLocation.PortableDataPath); + } + } + else + { + if (IsUsingPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName)) + settings.PluginSettings.PythonExecutablePath + = GetUpdatedPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName); + + if (IsUsingPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName)) + settings.PluginSettings.NodeExecutablePath + = GetUpdatedPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName); + } + } + + private static bool IsUsingPortablePath(string filePath, string pluginEnvironmentName) + { + var portableAppEnvLocation = $"UserData\\{DataLocation.PluginEnvironments}\\{pluginEnvironmentName}"; + + return filePath.Contains(portableAppEnvLocation); + } + + private static bool IsUsingRoamingPath(string filePath) + { + return filePath.StartsWith(DataLocation.RoamingDataPath); + } + + private static string GetUpdatedPortablePath(string filePath, string pluginEnvironmentName) + { + var index = filePath.IndexOf(DataLocation.PluginEnvironments); + // get the substring after "Environments" because we can not determine it + var updatedPath = filePath.Substring(index + DataLocation.PluginEnvironments.Count()); + return $"{DataLocation.PluginEnvironmentsPath}{updatedPath}"; + } } } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index e0eebe30e..55b3b60bd 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -12,9 +12,9 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { internal override string Language => AllowedLanguage.Python; - internal override string EnvName => "Python"; + internal override string EnvName => DataLocation.PythonEnvironmentName; - internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironments, EnvName); + internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironmentsPath, EnvName); internal override string InstallPath => Path.Combine(EnvPath, "PythonEmbeddable-v3.8.9"); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index ab021afe3..70341f711 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -12,9 +12,9 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { internal override string Language => AllowedLanguage.TypeScript; - internal override string EnvName => "Node.js"; + internal override string EnvName => DataLocation.NodeEnvironmentName; - internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironments, EnvName); + internal override string EnvPath => Path.Combine(DataLocation.PluginEnvironmentsPath, EnvName); internal override string InstallPath => Path.Combine(EnvPath, "Node-v16.18.0"); internal override string ExecutablePath => Path.Combine(InstallPath, "node-v16.18.0-win-x64\\node.exe"); diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index e9f25b3ee..882cabb2d 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -17,8 +17,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Text.Json.Serialization; using System.Threading; -using System.IO; -using System.Text.RegularExpressions; +using Flow.Launcher.Core.ExternalPlugins.Environments; namespace Flow.Launcher.Core { @@ -26,12 +25,6 @@ namespace Flow.Launcher.Core { public string GitHubRepository { get; } - private string updatePythonIndicatorFilename = ".updatePythonPath"; - - private string updateNodeIndicatorFilename = ".updateNodePath"; - - private string appDataRegex = @"app-\d\.\d\.\d"; - public Updater(string gitHubRepository) { GitHubRepository = gitHubRepository; @@ -82,7 +75,7 @@ namespace Flow.Launcher.Core DataLocation.PortableDataPath, targetDestination)); - UpdatePluginEnvPaths(settings, newReleaseVersion.ToString()); + AbstractPluginEnvironment.IndicatePluginEnvPathsUpdate(settings, newReleaseVersion.ToString()); } else { @@ -154,45 +147,5 @@ namespace Flow.Launcher.Core return tips; } - - private void UpdatePluginEnvPaths(Settings settings, string newVer) - { - var appVer = $"app-{newVer}"; - var updatePythonIndicatorFilePath - = Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename), appDataRegex, appVer); - var updateNodeIndicatorFilePath - = Regex.Replace(Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename), appDataRegex, appVer); - - if (!string.IsNullOrEmpty(settings.PluginSettings.PythonExecutablePath) - && settings.PluginSettings.PythonExecutablePath.StartsWith(DataLocation.PluginEnvironments)) - using (var _ = File.CreateText(updatePythonIndicatorFilePath)){} - - if (!string.IsNullOrEmpty(settings.PluginSettings.NodeExecutablePath) - && settings.PluginSettings.NodeExecutablePath.StartsWith(DataLocation.PluginEnvironments)) - using (var _ = File.CreateText(updateNodeIndicatorFilePath)) { } - } - - public void PreStartSetupAfterAppUpdate(Settings settings) - { - var appVer = $"app-{Constant.Version}"; - var updatePythonIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updatePythonIndicatorFilename); - var updateNodeIndicatorFilePath = Path.Combine(DataLocation.PluginEnvironments, updateNodeIndicatorFilename); - - if (File.Exists(updatePythonIndicatorFilePath)) - { - settings.PluginSettings.PythonExecutablePath - = Regex.Replace(settings.PluginSettings.PythonExecutablePath, appDataRegex, appVer); - - File.Delete(updatePythonIndicatorFilePath); - } - - if (File.Exists(updateNodeIndicatorFilePath)) - { - settings.PluginSettings.NodeExecutablePath - = Regex.Replace(settings.PluginSettings.NodeExecutablePath, appDataRegex, appVer); - - File.Delete(updateNodeIndicatorFilePath); - } - } } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs index 0eeafabd4..e294f52b8 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Flow.Launcher.Infrastructure.UserSettings { @@ -32,6 +28,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings public static readonly string PluginsDirectory = Path.Combine(DataDirectory(), Constant.Plugins); public static readonly string PluginSettingsDirectory = Path.Combine(DataDirectory(), "Settings", Constant.Plugins); - public static readonly string PluginEnvironments = Path.Combine(DataDirectory(), "Environments"); + public const string PythonEnvironmentName = "Python"; + public const string NodeEnvironmentName = "Node.js"; + public const string PluginEnvironments = "Environments"; + public static readonly string PluginEnvironmentsPath = Path.Combine(DataDirectory(), PluginEnvironments); } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 3fa69262d..c35727b36 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -6,6 +6,7 @@ using System.Timers; using System.Windows; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; +using Flow.Launcher.Core.ExternalPlugins.Environments; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; @@ -61,7 +62,7 @@ namespace Flow.Launcher _settingsVM = new SettingWindowViewModel(_updater, _portable); _settings = _settingsVM.Settings; - _updater.PreStartSetupAfterAppUpdate(_settings); + AbstractPluginEnvironment.PreStartPluginFilePathCorrection(_settings); _alphabet.Initialize(_settings); _stringMatcher = new StringMatcher(_alphabet);