diff --git a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs
index 310c1e33af2..e93c341dcd7 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs
@@ -30,5 +30,6 @@ public static bool PortableDataLocationInUse()
}
public static readonly string PluginsDirectory = Path.Combine(DataDirectory(), Constant.Plugins);
+ public static readonly string PluginSettingsDirectory = Path.Combine(DataDirectory(), "Settings", Constant.Plugins);
}
}
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 98cd777aac4..13905788a90 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -11,6 +11,12 @@ public static class FilesFolders
private const string FileExplorerProgramEXE = "explorer.exe";
+ ///
+ /// Copies the folder and all of its files and folders
+ /// including subfolders to the target location
+ ///
+ ///
+ ///
public static void Copy(this string sourcePath, string targetPath)
{
// Get the subdirectories for the specified directory.
@@ -172,7 +178,7 @@ public static bool IsLocationPathString(string querySearchString)
///
/// Gets the previous level directory from a path string.
/// Checks that previous level directory exists and returns it
- /// as a path string, or empty string if doesn't exit
+ /// as a path string, or empty string if doesn't exist
///
public static string GetPreviousExistingDirectory(Func locationExists, string path)
{
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
index f1ae5bc3541..c2ed7df3140 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml
@@ -25,6 +25,7 @@
Please enter a URL
Action keyword already exists, please enter a different one
Success
+ Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location.
Web Searches
Allows to perform web searches
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs
index 3fdb26c93c6..3c4d4c67dbf 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs
@@ -8,6 +8,7 @@
using System.Windows.Controls;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Storage;
+using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Plugin.WebSearch
@@ -21,8 +22,9 @@ public class Main : IPlugin, ISettingProvider, IPluginI18n, ISavable, IResultUpd
private CancellationTokenSource _updateSource;
private CancellationToken _updateToken;
- public const string Images = "Images";
- public static string ImagesDirectory;
+ internal const string Images = "Images";
+ internal static string DefaultImagesDirectory;
+ internal static string CustomImagesDirectory;
private readonly string SearchSourceGlobalPluginWildCardSign = "*";
@@ -172,8 +174,14 @@ public void Init(PluginInitContext context)
_context = context;
var pluginDirectory = _context.CurrentPluginMetadata.PluginDirectory;
var bundledImagesDirectory = Path.Combine(pluginDirectory, Images);
- ImagesDirectory = Path.Combine(_context.CurrentPluginMetadata.PluginDirectory, Images);
- Helper.ValidateDataDirectory(bundledImagesDirectory, ImagesDirectory);
+
+ // Default images directory is in the WebSearch's application folder
+ DefaultImagesDirectory = Path.Combine(pluginDirectory, Images);
+ Helper.ValidateDataDirectory(bundledImagesDirectory, DefaultImagesDirectory);
+
+ // Custom images directory is in the WebSearch's data location folder
+ var name = Path.GetFileNameWithoutExtension(_context.CurrentPluginMetadata.ExecuteFileName);
+ CustomImagesDirectory = Path.Combine(DataLocation.PluginSettingsDirectory, name, "CustomIcons");
}
#region ISettingProvider Members
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
index 20d0dd5a454..c7ccb4d51fe 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs
@@ -1,29 +1,38 @@
-using System.IO;
+using System.IO;
using System.Windows.Media;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Flow.Launcher.Infrastructure.Image;
+using Flow.Launcher.Infrastructure;
+using System.Reflection;
namespace Flow.Launcher.Plugin.WebSearch
{
public class SearchSource : BaseModel
{
- public const string DefaultIcon = "web_search.png";
public string Title { get; set; }
public string ActionKeyword { get; set; }
[NotNull]
- public string Icon { get; set; } = DefaultIcon;
+ public string Icon { get; set; } = "web_search.png";
+
+ public bool CustomIcon { get; set; } = false;
///
- /// All icon should be put under Images directory
+ /// Default icons are placed in Images directory in the app location.
+ /// Custom icons are placed in the user data directory
///
- [NotNull]
[JsonIgnore]
- internal string IconPath => Path.Combine(Main.ImagesDirectory, Icon);
+ public string IconPath
+ {
+ get
+ {
+ if (CustomIcon)
+ return Path.Combine(Main.CustomImagesDirectory, Icon);
- [JsonIgnore]
- public ImageSource Image => ImageLoader.Load(IconPath);
+ return Path.Combine(Main.DefaultImagesDirectory, Icon);
+ }
+ }
public string Url { get; set; }
public bool Enabled { get; set; }
@@ -36,6 +45,7 @@ public SearchSource DeepCopy()
ActionKeyword = string.Copy(ActionKeyword),
Url = string.Copy(Url),
Icon = string.Copy(Icon),
+ CustomIcon = CustomIcon,
Enabled = Enabled
};
return webSearch;
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml
index 0f17d21f5ca..02809be3ad9 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml
@@ -47,7 +47,7 @@
-
+
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
index 9ecdda23f00..fd0701c012a 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.IO;
using System.Windows;
using Microsoft.Win32;
using Flow.Launcher.Core.Plugin;
@@ -15,6 +14,7 @@ public partial class SearchSourceSettingWindow
private PluginInitContext _context;
private IPublicAPI _api;
private SearchSourceViewModel _viewModel;
+ private string selectedNewIconImageFullPath;
public SearchSourceSettingWindow(IList sources, PluginInitContext context, SearchSource old)
@@ -39,6 +39,10 @@ private void Initilize(IList sources, PluginInitContext context, A
_action = action;
_context = context;
_api = _context.API;
+
+ _viewModel.SetupCustomImagesDirectory();
+
+ imgPreviewIcon.Source = _viewModel.LoadPreviewIcon(_searchSource.IconPath);
}
private void OnCancelButtonClick(object sender, RoutedEventArgs e)
@@ -111,26 +115,32 @@ private void EditSearchSource()
var warning = _api.GetTranslation("newActionKeywordsHasBeenAssigned");
MessageBox.Show(warning);
}
+
+ if (!string.IsNullOrEmpty(selectedNewIconImageFullPath))
+ {
+ _viewModel.UpdateIconAttributes(_searchSource, selectedNewIconImageFullPath);
+
+ _viewModel.CopyNewImageToUserDataDirectoryIfRequired(
+ _searchSource, selectedNewIconImageFullPath, _oldSearchSource.IconPath);
+ }
}
private void OnSelectIconClick(object sender, RoutedEventArgs e)
{
- var directory = Main.ImagesDirectory;
const string filter = "Image files (*.jpg, *.jpeg, *.gif, *.png, *.bmp) |*.jpg; *.jpeg; *.gif; *.png; *.bmp";
- var dialog = new OpenFileDialog {InitialDirectory = directory, Filter = filter};
+ var dialog = new OpenFileDialog {InitialDirectory = Main.CustomImagesDirectory, Filter = filter};
var result = dialog.ShowDialog();
if (result == true)
{
- var fullpath = dialog.FileName;
- if (!string.IsNullOrEmpty(fullpath))
+ selectedNewIconImageFullPath = dialog.FileName;
+
+ if (!string.IsNullOrEmpty(selectedNewIconImageFullPath))
{
- _searchSource.Icon = Path.GetFileName(fullpath);
- if (!File.Exists(_searchSource.IconPath))
- {
- _searchSource.Icon = SearchSource.DefaultIcon;
- MessageBox.Show($"The file should be put under {directory}");
- }
+ if (_viewModel.ShouldProvideHint(selectedNewIconImageFullPath))
+ MessageBox.Show(_api.GetTranslation("flowlauncher_plugin_websearch_iconpath_hint"));
+
+ imgPreviewIcon.Source = _viewModel.LoadPreviewIcon(selectedNewIconImageFullPath);
}
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
index 049c50560bb..f54dbc13c9e 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
@@ -1,7 +1,65 @@
-namespace Flow.Launcher.Plugin.WebSearch
+using Flow.Launcher.Infrastructure.Image;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Windows;
+using System.Windows.Media;
+
+namespace Flow.Launcher.Plugin.WebSearch
{
- public class SearchSourceViewModel
+ public class SearchSourceViewModel : BaseModel
{
public SearchSource SearchSource { get; set; }
+
+ public void UpdateIconAttributes(SearchSource selectedSearchSource, string fullpathToSelectedImage)
+ {
+ var parentDirectorySelectedImg = Directory.GetParent(fullpathToSelectedImage).ToString();
+
+ selectedSearchSource.CustomIcon = parentDirectorySelectedImg != Main.DefaultImagesDirectory;
+
+ var iconFileName = Path.GetFileName(fullpathToSelectedImage);
+ selectedSearchSource.Icon = iconFileName;
+ }
+
+ public void CopyNewImageToUserDataDirectoryIfRequired(
+ SearchSource selectedSearchSource, string fullpathToSelectedImage, string fullPathToOriginalImage)
+ {
+ var destinationFileNameFullPath = Path.Combine(Main.CustomImagesDirectory, Path.GetFileName(fullpathToSelectedImage));
+
+ var parentDirectorySelectedImg = Directory.GetParent(fullpathToSelectedImage).ToString();
+
+ if (parentDirectorySelectedImg != Main.CustomImagesDirectory && parentDirectorySelectedImg != Main.DefaultImagesDirectory)
+ {
+ try
+ {
+ File.Copy(fullpathToSelectedImage, destinationFileNameFullPath);
+ }
+ catch (Exception e)
+ {
+#if DEBUG
+ throw e;
+#else
+ MessageBox.Show(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath));
+ UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage);
+#endif
+ }
+ }
+ }
+
+ internal void SetupCustomImagesDirectory()
+ {
+ if (!Directory.Exists(Main.CustomImagesDirectory))
+ Directory.CreateDirectory(Main.CustomImagesDirectory);
+ }
+
+ internal bool ShouldProvideHint(string fullPathToSelectedImage)
+ {
+ return Directory.GetParent(fullPathToSelectedImage).ToString() == Main.DefaultImagesDirectory;
+ }
+
+ internal ImageSource LoadPreviewIcon(string pathToPreviewIconImage)
+ {
+ return ImageLoader.Load(pathToPreviewIconImage);
+ }
}
}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
index 9784cfefecb..a91e42f45e1 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json
@@ -25,7 +25,7 @@
"Name": "Web Searches",
"Description": "Provide the web search ability",
"Author": "qianlifeng",
- "Version": "1.0.0",
+ "Version": "1.0.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll",