From d78d313372dd07aa2df5bd8fc3c27228fa2220a6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 26 Dec 2025 21:37:30 +1100 Subject: [PATCH] update to use IcoAbsoluteLocalPath --- Flow.Launcher.Plugin/Result.cs | 50 +++++++++++-------- .../Views/SettingsPanePluginStore.xaml | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 6 +-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 0f118e36d..e5b3155b6 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Security.Policy; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Media; @@ -21,6 +22,8 @@ namespace Flow.Launcher.Plugin private string _icoPath; + private string _icoAbsoluteFullPath; + private string _copyText = string.Empty; private string _badgeIcoPath; @@ -67,12 +70,17 @@ namespace Flow.Launcher.Plugin /// The image to be displayed for the result. /// /// Can be a local file path or a URL. - /// GlyphInfo is prioritized if not null + /// + /// GlyphInfo is prioritized if not null. + /// Use IcoPathRelative for storage where it needs to be resistant to plugin location change. + /// public string IcoPath { get => _icoPath; set { + _icoPath = value; + // As a standard this property will handle prepping and converting to absolute local path for icon image processing if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(PluginDirectory) @@ -81,40 +89,40 @@ namespace Flow.Launcher.Plugin && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) { - _icoPath = Path.Combine(PluginDirectory, value); + _icoAbsoluteFullPath = Path.Combine(PluginDirectory, value); } else { - _icoPath = value; + _icoAbsoluteFullPath = value; } } } /// - /// Returns the plugin directory relative IcoPath or URL. This path is useful for storage where the it needs - /// to be resistant to changes in plugin location from update or portable mode change. + /// TODO COMMENT + /// + public string IcoAbsoluteFullPath => _icoAbsoluteFullPath; + + /// + /// Returns IcoPath's relative path based on the plugin directory or original value if not file path. + /// This property is useful for storage where it needs to be resistant to changes in plugin location from update + /// or portable mode change. /// - /// Must be a local file path. - /// This will be empty string if IcoPath is a URL, so must check for empty string during usage public string IcoPathRelative { - get => _icoPath; - set + get { - // As a standard this property will handle prepping and converting to absolute local path for icon image processing - if (!string.IsNullOrEmpty(value) - && !string.IsNullOrEmpty(PluginDirectory) - && !Path.IsPathRooted(value) - && !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase) - && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) - && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(IcoAbsoluteFullPath) + || string.IsNullOrEmpty(PluginDirectory) + || !Path.IsPathRooted(IcoAbsoluteFullPath) + || IcoAbsoluteFullPath.StartsWith("http://", StringComparison.OrdinalIgnoreCase) + || IcoAbsoluteFullPath.StartsWith("https://", StringComparison.OrdinalIgnoreCase) + || IcoAbsoluteFullPath.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) { - _icoPath = Path.Combine(PluginDirectory, value); - } - else - { - _icoPath = value; + return IcoAbsoluteFullPath; } + + return Path.GetRelativePath(PluginDirectory, IcoAbsoluteFullPath); } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index aa027e19e..5d8837891 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -333,7 +333,7 @@ Margin="18 24 0 0" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant" - Source="{Binding IcoPath, IsAsync=True}" /> + Source="{Binding IcoAbsoluteFullPath, IsAsync=True}" /> Glyph is not null; - private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null; + private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoAbsoluteFullPath) || Result.Icon is not null; private bool BadgeIconAvailable => !string.IsNullOrEmpty(Result.BadgeIcoPath) || Result.BadgeIcon is not null; @@ -236,7 +236,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadImageAsync() { - var imagePath = Result.IcoPath; + var imagePath = Result.IcoAbsoluteFullPath; var iconDelegate = Result.Icon; if (ImageLoader.TryGetValue(imagePath, false, out var img)) { @@ -266,7 +266,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadPreviewImageAsync() { - var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoPath; + var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoAbsoluteFullPath; var iconDelegate = Result.Preview.PreviewDelegate ?? Result.Icon; if (ImageLoader.TryGetValue(imagePath, true, out var img)) {