2025-09-21 03:50:51 +00:00
|
|
|
|
using System;
|
2020-05-24 10:14:36 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2021-08-22 10:36:01 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2024-05-20 17:03:19 +00:00
|
|
|
|
using System.Windows.Controls;
|
2025-04-09 05:05:43 +00:00
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
|
using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
2024-05-20 17:03:19 +00:00
|
|
|
|
using Flow.Launcher.Plugin.Explorer.Views;
|
2025-04-09 05:05:43 +00:00
|
|
|
|
using Flow.Launcher.Plugin.SharedCommands;
|
2025-07-23 05:51:35 +00:00
|
|
|
|
using Flow.Launcher.Plugin.SharedModels;
|
2024-06-08 06:06:35 +00:00
|
|
|
|
using Peter;
|
2025-04-09 05:05:43 +00:00
|
|
|
|
using Path = System.IO.Path;
|
2020-05-24 09:11:40 +00:00
|
|
|
|
|
|
|
|
|
|
namespace Flow.Launcher.Plugin.Explorer.Search
|
|
|
|
|
|
{
|
2021-01-29 10:40:51 +00:00
|
|
|
|
public static class ResultManager
|
2020-05-24 09:11:40 +00:00
|
|
|
|
{
|
2025-06-04 09:26:33 +00:00
|
|
|
|
private static readonly string ClassName = nameof(ResultManager);
|
|
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
private static readonly string[] SizeUnits = { "B", "KB", "MB", "GB", "TB" };
|
2021-01-29 10:40:51 +00:00
|
|
|
|
private static PluginInitContext Context;
|
2021-07-02 03:38:07 +00:00
|
|
|
|
private static Settings Settings { get; set; }
|
2020-06-08 04:20:22 +00:00
|
|
|
|
|
2021-07-02 03:38:07 +00:00
|
|
|
|
public static void Init(PluginInitContext context, Settings settings)
|
2020-06-08 04:20:22 +00:00
|
|
|
|
{
|
2021-01-29 10:40:51 +00:00
|
|
|
|
Context = context;
|
2021-07-02 03:38:07 +00:00
|
|
|
|
Settings = settings;
|
2021-12-06 21:57:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-24 11:51:09 +00:00
|
|
|
|
public static string GetPathWithActionKeyword(string path, ResultType type, string actionKeyword)
|
2021-12-06 21:57:06 +00:00
|
|
|
|
{
|
2022-12-24 11:51:09 +00:00
|
|
|
|
// actionKeyword will be empty string if using global, query.ActionKeyword is ""
|
2021-12-07 21:01:16 +00:00
|
|
|
|
|
2022-12-24 11:51:09 +00:00
|
|
|
|
var usePathSearchActionKeyword = Settings.PathSearchKeywordEnabled && !Settings.SearchActionKeywordEnabled;
|
|
|
|
|
|
|
2023-01-12 21:29:58 +00:00
|
|
|
|
var pathSearchActionKeyword = Settings.PathSearchActionKeyword == Query.GlobalPluginWildcardSign
|
|
|
|
|
|
? string.Empty
|
2022-12-24 11:51:09 +00:00
|
|
|
|
: $"{Settings.PathSearchActionKeyword} ";
|
|
|
|
|
|
|
|
|
|
|
|
var searchActionKeyword = Settings.SearchActionKeyword == Query.GlobalPluginWildcardSign
|
|
|
|
|
|
? string.Empty
|
|
|
|
|
|
: $"{Settings.SearchActionKeyword} ";
|
|
|
|
|
|
|
|
|
|
|
|
var keyword = usePathSearchActionKeyword ? pathSearchActionKeyword : searchActionKeyword;
|
2023-01-12 21:29:58 +00:00
|
|
|
|
|
2023-03-08 12:20:33 +00:00
|
|
|
|
var formattedPath = path;
|
2021-12-07 21:01:16 +00:00
|
|
|
|
|
|
|
|
|
|
if (type == ResultType.Folder)
|
2023-01-13 07:12:45 +00:00
|
|
|
|
// the separator is needed so when navigating the folder structure contents of the folder are listed
|
2023-03-08 12:20:33 +00:00
|
|
|
|
formattedPath = path.EndsWith(Constants.DirectorySeparator) ? path : path + Constants.DirectorySeparator;
|
2021-12-07 21:01:16 +00:00
|
|
|
|
|
2023-03-08 12:20:33 +00:00
|
|
|
|
return $"{keyword}{formattedPath}";
|
2020-06-08 04:20:22 +00:00
|
|
|
|
}
|
2021-01-29 10:40:51 +00:00
|
|
|
|
|
2022-12-24 17:58:37 +00:00
|
|
|
|
public static string GetAutoCompleteText(string title, Query query, string path, ResultType resultType)
|
2022-12-22 11:57:37 +00:00
|
|
|
|
{
|
|
|
|
|
|
return !Settings.PathSearchKeywordEnabled && !Settings.SearchActionKeywordEnabled
|
2023-01-12 21:29:58 +00:00
|
|
|
|
? $"{query.ActionKeyword} {title}" // Only Quick Access action keyword is used in this scenario
|
|
|
|
|
|
: GetPathWithActionKeyword(path, resultType, query.ActionKeyword);
|
2022-12-22 11:57:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-25 21:19:00 +00:00
|
|
|
|
public static Result CreateResult(Query query, SearchResult result)
|
|
|
|
|
|
{
|
|
|
|
|
|
return result.Type switch
|
|
|
|
|
|
{
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ResultType.Folder or ResultType.Volume =>
|
2023-03-05 08:55:09 +00:00
|
|
|
|
CreateFolderResult(Path.GetFileName(result.FullPath), result.FullPath, result.FullPath, query, result.Score, result.WindowsIndexed),
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ResultType.File =>
|
2023-03-05 08:55:09 +00:00
|
|
|
|
CreateFileResult(result.FullPath, query, result.Score, result.WindowsIndexed),
|
2025-04-09 05:05:43 +00:00
|
|
|
|
_ => throw new ArgumentOutOfRangeException(null)
|
2022-03-25 21:19:00 +00:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-08 06:06:35 +00:00
|
|
|
|
internal static void ShowNativeContextMenu(string path, ResultType type)
|
|
|
|
|
|
{
|
2025-07-23 05:51:35 +00:00
|
|
|
|
var screenWithMouseCursor = MonitorInfo.GetCursorDisplayMonitor();
|
2024-06-08 06:06:35 +00:00
|
|
|
|
var xOfScreenCenter = screenWithMouseCursor.WorkingArea.Left + screenWithMouseCursor.WorkingArea.Width / 2;
|
|
|
|
|
|
var yOfScreenCenter = screenWithMouseCursor.WorkingArea.Top + screenWithMouseCursor.WorkingArea.Height / 2;
|
2025-07-23 05:51:35 +00:00
|
|
|
|
var showPosition = new System.Drawing.Point((int)xOfScreenCenter, (int)yOfScreenCenter);
|
2024-06-08 06:06:35 +00:00
|
|
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case ResultType.File:
|
|
|
|
|
|
var fileInfo = new FileInfo[] { new(path) };
|
|
|
|
|
|
new ShellContextMenu().ShowContextMenu(fileInfo, showPosition);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case ResultType.Folder:
|
|
|
|
|
|
var folderInfo = new System.IO.DirectoryInfo[] { new(path) };
|
|
|
|
|
|
new ShellContextMenu().ShowContextMenu(folderInfo, showPosition);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-04 20:06:20 +00:00
|
|
|
|
internal static Result CreateFolderResult(string title, string subtitle, string path, Query query, int score = 0, bool windowsIndexed = false)
|
2020-05-24 09:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
return new Result
|
|
|
|
|
|
{
|
2023-03-08 12:20:33 +00:00
|
|
|
|
Title = title,
|
2020-05-24 09:11:40 +00:00
|
|
|
|
IcoPath = path,
|
2023-01-19 08:04:41 +00:00
|
|
|
|
SubTitle = subtitle,
|
2022-12-22 11:57:37 +00:00
|
|
|
|
AutoCompleteText = GetAutoCompleteText(title, query, path, ResultType.Folder),
|
2025-04-09 05:05:43 +00:00
|
|
|
|
TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData,
|
2022-12-05 03:46:11 +00:00
|
|
|
|
CopyText = path,
|
2025-06-12 06:25:10 +00:00
|
|
|
|
Preview = new Result.PreviewInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
FilePath = path,
|
|
|
|
|
|
},
|
2025-06-04 09:12:53 +00:00
|
|
|
|
PreviewPanel = new Lazy<UserControl>(() => new PreviewPanel(Settings, path, ResultType.Folder)),
|
2020-05-24 09:11:40 +00:00
|
|
|
|
Action = c =>
|
|
|
|
|
|
{
|
2024-06-08 06:06:35 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == ModifierKeys.Alt)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowNativeContextMenu(path, ResultType.Folder);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2023-03-03 12:36:36 +00:00
|
|
|
|
// open folder
|
2023-03-24 07:45:45 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == (ModifierKeys.Control | ModifierKeys.Shift))
|
2020-05-24 09:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-03-14 07:21:03 +00:00
|
|
|
|
OpenFolder(path);
|
2020-05-24 09:11:40 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error());
|
2023-03-24 07:02:11 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Open containing folder
|
2023-03-24 07:45:45 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == ModifierKeys.Control)
|
2023-03-24 07:02:11 +00:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
Context.API.OpenDirectory(Path.GetDirectoryName(path), path);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error());
|
2020-05-24 09:11:40 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-03-14 07:32:47 +00:00
|
|
|
|
|
2023-03-24 07:45:45 +00:00
|
|
|
|
// If path search is disabled just open it in file manager
|
2023-03-29 07:19:55 +00:00
|
|
|
|
if (Settings.DefaultOpenFolderInFileManager || (!Settings.PathSearchKeywordEnabled && !Settings.SearchActionKeywordEnabled))
|
2023-03-24 07:02:11 +00:00
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
OpenFolder(path);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error());
|
2023-03-24 07:02:11 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2023-03-24 07:22:29 +00:00
|
|
|
|
// or make this folder the current query
|
|
|
|
|
|
Context.API.ChangeQuery(GetPathWithActionKeyword(path, ResultType.Folder, query.ActionKeyword));
|
2023-03-24 07:02:11 +00:00
|
|
|
|
}
|
2022-03-25 21:19:00 +00:00
|
|
|
|
|
2020-05-24 09:11:40 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
},
|
2021-04-13 11:40:04 +00:00
|
|
|
|
Score = score,
|
2025-09-21 03:50:51 +00:00
|
|
|
|
TitleToolTip = Localize.plugin_explorer_plugin_ToolTipOpenDirectory(),
|
2025-06-05 03:56:21 +00:00
|
|
|
|
SubTitleToolTip = Settings.DisplayMoreInformationInToolTip ? GetFolderMoreInfoTooltip(path) : path,
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path, WindowsIndexed = windowsIndexed }
|
2020-05-24 09:11:40 +00:00
|
|
|
|
};
|
|
|
|
|
|
}
|
2020-05-24 10:14:36 +00:00
|
|
|
|
|
2025-06-28 03:00:56 +00:00
|
|
|
|
internal static Result CreateDriveSpaceDisplayResult(string path, string actionKeyword, int score)
|
|
|
|
|
|
{
|
|
|
|
|
|
return CreateDriveSpaceDisplayResult(path, actionKeyword, score, SearchManager.UseIndexSearch(path));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-12 03:07:04 +00:00
|
|
|
|
internal static Result CreateDriveSpaceDisplayResult(string path, string actionKeyword, bool windowsIndexed = false)
|
2025-06-28 03:00:56 +00:00
|
|
|
|
{
|
|
|
|
|
|
return CreateDriveSpaceDisplayResult(path, actionKeyword, 500, windowsIndexed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static Result CreateDriveSpaceDisplayResult(string path, string actionKeyword, int score, bool windowsIndexed = false)
|
2022-09-11 22:05:03 +00:00
|
|
|
|
{
|
|
|
|
|
|
var progressBarColor = "#26a0da";
|
|
|
|
|
|
var title = string.Empty; // hide title when use progress bar,
|
2022-10-10 16:11:48 +00:00
|
|
|
|
var driveLetter = path[..1].ToUpper();
|
2022-09-11 22:05:03 +00:00
|
|
|
|
DriveInfo drv = new DriveInfo(driveLetter);
|
2022-12-23 07:15:11 +00:00
|
|
|
|
var freespace = ToReadableSize(drv.AvailableFreeSpace, 2);
|
|
|
|
|
|
var totalspace = ToReadableSize(drv.TotalSize, 2);
|
2025-09-21 03:50:51 +00:00
|
|
|
|
var subtitle = Localize.plugin_explorer_diskfreespace(freespace, totalspace);
|
2022-09-24 19:23:59 +00:00
|
|
|
|
double usingSize = (Convert.ToDouble(drv.TotalSize) - Convert.ToDouble(drv.AvailableFreeSpace)) / Convert.ToDouble(drv.TotalSize) * 100;
|
2022-09-11 22:05:03 +00:00
|
|
|
|
|
2022-09-24 19:23:59 +00:00
|
|
|
|
int? progressValue = Convert.ToInt32(usingSize);
|
2022-09-11 22:05:03 +00:00
|
|
|
|
|
|
|
|
|
|
if (progressValue >= 90)
|
|
|
|
|
|
progressBarColor = "#da2626";
|
|
|
|
|
|
|
2025-06-05 03:56:21 +00:00
|
|
|
|
var tooltip = Settings.DisplayMoreInformationInToolTip
|
|
|
|
|
|
? GetVolumeMoreInfoTooltip(path, freespace, totalspace)
|
|
|
|
|
|
: path;
|
|
|
|
|
|
|
2022-09-11 22:05:03 +00:00
|
|
|
|
return new Result
|
|
|
|
|
|
{
|
|
|
|
|
|
Title = title,
|
|
|
|
|
|
SubTitle = subtitle,
|
2022-12-22 12:20:37 +00:00
|
|
|
|
AutoCompleteText = GetPathWithActionKeyword(path, ResultType.Folder, actionKeyword),
|
2022-09-11 22:05:03 +00:00
|
|
|
|
IcoPath = path,
|
2025-06-28 03:00:56 +00:00
|
|
|
|
Score = score,
|
2022-09-11 22:05:03 +00:00
|
|
|
|
ProgressBar = progressValue,
|
|
|
|
|
|
ProgressBarColor = progressBarColor,
|
2023-04-21 15:52:00 +00:00
|
|
|
|
Preview = new Result.PreviewInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
FilePath = path,
|
|
|
|
|
|
},
|
2023-03-08 12:20:33 +00:00
|
|
|
|
Action = _ =>
|
2022-09-11 22:05:03 +00:00
|
|
|
|
{
|
2023-03-14 07:21:03 +00:00
|
|
|
|
OpenFolder(path);
|
2022-09-11 22:05:03 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
},
|
2025-06-05 03:56:21 +00:00
|
|
|
|
TitleToolTip = tooltip,
|
|
|
|
|
|
SubTitleToolTip = tooltip,
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ContextData = new SearchResult { Type = ResultType.Volume, FullPath = path, WindowsIndexed = windowsIndexed }
|
2022-09-11 22:05:03 +00:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
internal static string ToReadableSize(long sizeOnDrive, int pi)
|
2022-09-06 14:59:33 +00:00
|
|
|
|
{
|
2024-05-20 17:03:19 +00:00
|
|
|
|
var unitIndex = 0;
|
|
|
|
|
|
double readableSize = sizeOnDrive;
|
2022-09-06 14:59:33 +00:00
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
while (readableSize > 1024.0 && unitIndex < SizeUnits.Length - 1)
|
2022-09-06 14:59:33 +00:00
|
|
|
|
{
|
2024-05-20 17:03:19 +00:00
|
|
|
|
readableSize /= 1024.0;
|
|
|
|
|
|
unitIndex++;
|
2022-09-06 14:59:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
var unit = SizeUnits[unitIndex] ?? "";
|
2022-09-06 14:59:33 +00:00
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
var returnStr = $"{Convert.ToInt32(readableSize)} {unit}";
|
|
|
|
|
|
if (unitIndex != 0)
|
2022-09-11 22:05:03 +00:00
|
|
|
|
{
|
2022-10-10 16:11:48 +00:00
|
|
|
|
returnStr = pi switch
|
2022-09-11 22:05:03 +00:00
|
|
|
|
{
|
2024-05-20 17:03:19 +00:00
|
|
|
|
1 => $"{readableSize:F1} {unit}",
|
|
|
|
|
|
2 => $"{readableSize:F2} {unit}",
|
|
|
|
|
|
3 => $"{readableSize:F3} {unit}",
|
|
|
|
|
|
_ => $"{Convert.ToInt32(readableSize)} {unit}"
|
2022-10-10 16:11:48 +00:00
|
|
|
|
};
|
2022-09-11 22:05:03 +00:00
|
|
|
|
}
|
2022-09-06 14:59:33 +00:00
|
|
|
|
|
|
|
|
|
|
return returnStr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-12 03:07:04 +00:00
|
|
|
|
internal static Result CreateOpenCurrentFolderResult(string path, string actionKeyword, bool windowsIndexed = false)
|
2020-05-24 10:14:36 +00:00
|
|
|
|
{
|
2023-01-13 07:12:45 +00:00
|
|
|
|
// Path passed from PathSearchAsync ends with Constants.DirectorySeparator ('\'), need to remove the separator
|
2022-12-12 02:14:21 +00:00
|
|
|
|
// so it's consistent with folder results returned by index search which does not end with one
|
2023-01-13 07:12:45 +00:00
|
|
|
|
var folderPath = path.TrimEnd(Constants.DirectorySeparator);
|
2020-06-01 04:11:51 +00:00
|
|
|
|
|
2020-05-24 10:14:36 +00:00
|
|
|
|
return new Result
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
Title = Localize.plugin_explorer_openresultfolder(),
|
|
|
|
|
|
SubTitle = Localize.plugin_explorer_openresultfolder_subtitle(),
|
2022-12-22 12:20:37 +00:00
|
|
|
|
AutoCompleteText = GetPathWithActionKeyword(folderPath, ResultType.Folder, actionKeyword),
|
2022-12-12 02:14:21 +00:00
|
|
|
|
IcoPath = folderPath,
|
2020-05-24 10:14:36 +00:00
|
|
|
|
Score = 500,
|
2022-12-12 02:14:21 +00:00
|
|
|
|
CopyText = folderPath,
|
2024-06-08 06:06:35 +00:00
|
|
|
|
Action = c =>
|
2020-05-24 10:14:36 +00:00
|
|
|
|
{
|
2024-06-08 06:06:35 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == ModifierKeys.Alt)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowNativeContextMenu(folderPath, ResultType.Folder);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2023-03-14 07:21:03 +00:00
|
|
|
|
OpenFolder(folderPath);
|
2020-05-24 10:14:36 +00:00
|
|
|
|
return true;
|
2020-05-31 19:52:01 +00:00
|
|
|
|
},
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = folderPath, WindowsIndexed = windowsIndexed }
|
2020-05-24 10:14:36 +00:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-12-04 20:06:20 +00:00
|
|
|
|
internal static Result CreateFileResult(string filePath, Query query, int score = 0, bool windowsIndexed = false)
|
2020-05-24 10:14:36 +00:00
|
|
|
|
{
|
2025-07-20 11:11:09 +00:00
|
|
|
|
var isMedia = IsMedia(Path.GetExtension(filePath));
|
|
|
|
|
|
var title = Path.GetFileName(filePath) ?? string.Empty;
|
|
|
|
|
|
var directory = Path.GetDirectoryName(filePath) ?? string.Empty;
|
2022-12-22 11:57:37 +00:00
|
|
|
|
|
2024-05-20 17:03:19 +00:00
|
|
|
|
/* Preview Detail */
|
2024-04-29 22:57:39 +00:00
|
|
|
|
|
2020-05-24 10:14:36 +00:00
|
|
|
|
var result = new Result
|
|
|
|
|
|
{
|
2022-12-22 11:57:37 +00:00
|
|
|
|
Title = title,
|
2025-07-20 11:11:09 +00:00
|
|
|
|
SubTitle = directory,
|
2020-05-24 10:14:36 +00:00
|
|
|
|
IcoPath = filePath,
|
2023-04-21 15:52:00 +00:00
|
|
|
|
Preview = new Result.PreviewInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
IsMedia = isMedia,
|
|
|
|
|
|
PreviewImagePath = isMedia ? filePath : null,
|
|
|
|
|
|
FilePath = filePath,
|
|
|
|
|
|
},
|
2022-12-22 11:57:37 +00:00
|
|
|
|
AutoCompleteText = GetAutoCompleteText(title, query, filePath, ResultType.File),
|
2025-04-09 05:05:43 +00:00
|
|
|
|
TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData,
|
2021-04-13 11:40:04 +00:00
|
|
|
|
Score = score,
|
2022-12-05 03:46:11 +00:00
|
|
|
|
CopyText = filePath,
|
2025-06-04 09:12:53 +00:00
|
|
|
|
PreviewPanel = new Lazy<UserControl>(() => new PreviewPanel(Settings, filePath, ResultType.File)),
|
2020-05-24 10:14:36 +00:00
|
|
|
|
Action = c =>
|
|
|
|
|
|
{
|
2024-06-08 06:06:35 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == ModifierKeys.Alt)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShowNativeContextMenu(filePath, ResultType.File);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2020-05-24 10:14:36 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-03-24 07:02:11 +00:00
|
|
|
|
if (c.SpecialKeyState.ToModifierKeys() == (ModifierKeys.Control | ModifierKeys.Shift))
|
2021-08-22 10:36:01 +00:00
|
|
|
|
{
|
2025-07-20 11:11:09 +00:00
|
|
|
|
OpenFile(filePath, Settings.UseLocationAsWorkingDir ? directory : string.Empty, true);
|
2021-08-22 10:36:01 +00:00
|
|
|
|
}
|
2023-03-24 07:02:11 +00:00
|
|
|
|
else if (c.SpecialKeyState.ToModifierKeys() == ModifierKeys.Control)
|
2020-06-29 22:15:10 +00:00
|
|
|
|
{
|
2023-03-14 07:21:03 +00:00
|
|
|
|
OpenFolder(filePath, filePath);
|
2023-03-14 07:32:47 +00:00
|
|
|
|
}
|
2020-06-29 22:15:10 +00:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-20 11:11:09 +00:00
|
|
|
|
OpenFile(filePath, Settings.UseLocationAsWorkingDir ? directory : string.Empty);
|
2020-06-29 22:15:10 +00:00
|
|
|
|
}
|
2020-05-24 10:14:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_openfile_error());
|
2020-05-24 10:14:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
},
|
2025-09-21 03:50:51 +00:00
|
|
|
|
TitleToolTip = Localize.plugin_explorer_plugin_ToolTipOpenContainingFolder(),
|
2025-06-05 03:56:21 +00:00
|
|
|
|
SubTitleToolTip = Settings.DisplayMoreInformationInToolTip ? GetFileMoreInfoTooltip(filePath) : filePath,
|
2023-03-03 10:30:25 +00:00
|
|
|
|
ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath, WindowsIndexed = windowsIndexed }
|
2020-05-24 10:14:36 +00:00
|
|
|
|
};
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2022-12-05 08:01:20 +00:00
|
|
|
|
|
2023-03-14 07:21:03 +00:00
|
|
|
|
private static bool IsMedia(string extension)
|
2023-03-08 11:35:00 +00:00
|
|
|
|
{
|
2023-03-14 07:32:47 +00:00
|
|
|
|
if (string.IsNullOrEmpty(extension)) { return false; }
|
|
|
|
|
|
|
|
|
|
|
|
return MediaExtensions.Contains(extension.ToLowerInvariant());
|
2023-03-08 11:35:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-24 07:22:29 +00:00
|
|
|
|
private static void OpenFile(string filePath, string workingDir = "", bool asAdmin = false)
|
2023-03-08 11:35:00 +00:00
|
|
|
|
{
|
2023-03-14 07:21:03 +00:00
|
|
|
|
IncrementEverythingRunCounterIfNeeded(filePath);
|
2024-12-01 12:13:13 +00:00
|
|
|
|
FilesFolders.OpenFile(filePath, workingDir, asAdmin, (string str) => Context.API.ShowMsgBox(str));
|
2023-03-08 11:35:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-14 07:21:03 +00:00
|
|
|
|
private static void OpenFolder(string folderPath, string fileNameOrFilePath = null)
|
2023-03-08 11:35:00 +00:00
|
|
|
|
{
|
2023-03-14 07:21:03 +00:00
|
|
|
|
IncrementEverythingRunCounterIfNeeded(folderPath);
|
2023-03-24 07:02:11 +00:00
|
|
|
|
Context.API.OpenDirectory(folderPath, fileNameOrFilePath);
|
2023-03-08 11:35:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-03-14 07:21:03 +00:00
|
|
|
|
private static void IncrementEverythingRunCounterIfNeeded(string fileOrFolder)
|
2023-03-03 10:29:03 +00:00
|
|
|
|
{
|
2024-07-15 06:52:12 +00:00
|
|
|
|
if (Settings.EverythingEnabled && Settings.EverythingEnableRunCount)
|
2023-03-03 12:36:36 +00:00
|
|
|
|
_ = Task.Run(() => EverythingApi.IncrementRunCounterAsync(fileOrFolder));
|
2023-03-03 10:29:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-05 03:56:21 +00:00
|
|
|
|
private static string GetFileMoreInfoTooltip(string filePath)
|
2025-06-04 09:01:46 +00:00
|
|
|
|
{
|
2025-06-05 03:56:21 +00:00
|
|
|
|
try
|
2025-06-04 09:01:46 +00:00
|
|
|
|
{
|
2025-06-05 03:56:21 +00:00
|
|
|
|
var fileSize = PreviewPanel.GetFileSize(filePath);
|
|
|
|
|
|
var fileCreatedAt = PreviewPanel.GetFileCreatedAt(filePath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel);
|
|
|
|
|
|
var fileModifiedAt = PreviewPanel.GetFileLastModifiedAt(filePath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel);
|
2025-09-21 03:50:51 +00:00
|
|
|
|
return Localize.plugin_explorer_plugin_tooltip_more_info(filePath, fileSize, fileCreatedAt, fileModifiedAt, Environment.NewLine);
|
2025-06-05 03:56:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Context.API.LogException(ClassName, $"Failed to load tooltip for {filePath}", e);
|
|
|
|
|
|
return filePath;
|
2025-06-04 09:01:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-05 03:56:21 +00:00
|
|
|
|
private static string GetFolderMoreInfoTooltip(string folderPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var folderSize = PreviewPanel.GetFolderSize(folderPath);
|
|
|
|
|
|
var folderCreatedAt = PreviewPanel.GetFolderCreatedAt(folderPath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel);
|
|
|
|
|
|
var folderModifiedAt = PreviewPanel.GetFolderLastModifiedAt(folderPath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel);
|
2025-09-21 03:50:51 +00:00
|
|
|
|
return Localize.plugin_explorer_plugin_tooltip_more_info(folderPath, folderSize, folderCreatedAt, folderModifiedAt, Environment.NewLine);
|
2025-06-05 03:56:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Context.API.LogException(ClassName, $"Failed to load tooltip for {folderPath}", e);
|
|
|
|
|
|
return folderPath;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string GetVolumeMoreInfoTooltip(string volumePath, string freespace, string totalspace)
|
|
|
|
|
|
{
|
2025-09-21 03:50:51 +00:00
|
|
|
|
return Localize.plugin_explorer_plugin_tooltip_more_info_volume(volumePath, freespace, totalspace, Environment.NewLine);
|
2025-06-05 03:56:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-09 02:06:40 +00:00
|
|
|
|
private static readonly string[] MediaExtensions =
|
|
|
|
|
|
{
|
|
|
|
|
|
".jpg", ".png", ".avi", ".mkv", ".bmp", ".gif", ".wmv", ".mp3", ".flac", ".mp4",
|
|
|
|
|
|
".m4a", ".m4v", ".heic", ".mov", ".flv", ".webm"
|
|
|
|
|
|
};
|
2020-05-24 09:11:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-26 09:01:12 +00:00
|
|
|
|
public enum ResultType
|
2020-05-24 09:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
Volume,
|
|
|
|
|
|
Folder,
|
|
|
|
|
|
File
|
|
|
|
|
|
}
|
2022-09-10 15:45:41 +00:00
|
|
|
|
}
|