UI & Preview Extensions
Result display
ISidebarFilterProvider
Adds categorizing filter groups to the results sidebar (e.g. date-range or size buckets).
interface ISidebarFilterProvider
{
int SortOrder { get; } // default 100; lower renders first
IEnumerable<SidebarFilterGroup> GetFilterGroups();
}SidebarFilterGroup has a Header, an AllowMultiSelect flag (default false; opts the group into letting more than one item be selected at once, combined with OR — leave it off for items whose meaning only makes sense one at a time, e.g. overlapping/cumulative date ranges), and a list of SidebarFilterItems (Id, DisplayName, optional icon, and an optional async FilterPredicate over the current result list). The host shows a clear button on a group once it has a selection, so a provider doesn't need an "All"/"Any" pseudo-item of its own.
IResultColumnProvider
Injects extra columns into the results grid view (file size, modified date, custom metadata, ...).
interface IResultColumnProvider
{
IEnumerable<ResultColumnDefinition> GetColumns();
string GetCellValue(ISearchResult result, string columnId);
}ResultColumnDefinition carries a column id, header text, width, and optional VisibilityPredicate/SortComparer delegates.
Startup Panel
IStartupPanelTabProvider
Contributes a tab to the quick window's Startup Panel — the tab strip shown above the result list when the search box is empty (see Startup Panel). CoreExtensions' History and Favorites tabs are both built on this; see Example Plugins for a walkthrough.
interface IStartupPanelTabProvider : IPluginComponent
{
IEnumerable<ISearchResult> GetItems();
}GetItems() runs synchronously on every panel activation and is expected to be fast with no I/O — it's called each time the search box is cleared, not cached. A tab that returns no items is left out of the strip entirely rather than shown empty. The user can hide a tab from the live panel with its × button independently of disabling the component altogether in Settings → Plugins — the two are deliberately separate; the host uses the component's concrete class type name (GetType().Name) as the stable key to persist the closed state.
Preview & thumbnails
IFilePreviewProvider
Renders a custom WPF UIElement in the QuickLook preview pane (see Actions Menu & Preview) for file types you want to handle specially.
interface IFilePreviewProvider
{
string Name { get; }
int Priority { get; } // default 0; higher runs first
bool CanPreview(string path, bool isDir);
UIElement CreatePreview(string path, bool isDir);
bool RendersExternally { get; } // default false
}Priority is only the default order — the user can freely reorder providers (including relative to yours) from Settings → General → Preview & Thumbnails, which wins over whatever Priority returns. Don't assume your provider's declared priority is the order it actually runs in.
Two optional companion interfaces refine preview behavior:
IPreviewSessionAware— implement this on the preview provider itself if it holds onto expensive out-of-process resources (a hosted native handler, a file lock);EndPreviewSession()is called once the whole preview session ends, not on every individual preview swap. The one exception: for a provider withRendersExternallytrue, the host calls it on every swap away from that provider too, not just session end — see below.IReusablePreview— implement this on theUIElementreturned fromCreatePreviewif it can re-point itself at a new file instead of being rebuilt from scratch:TrySetTarget(path, isDir)returnstrueif it handled the change in place,falseto tell the host to build a fresh preview instead.
RendersExternally is for a provider whose real preview surface is a separate, externally-managed window rather than the UIElement CreatePreview returns — e.g. handing the file off to another application entirely. When the winning provider has this set, the host hides its own preview panel instead of displaying CreatePreview's content (which is then never actually shown, so it can be a trivial placeholder). Pair it with IReceivesPreviewPanelBounds to get the exact screen rectangle (physical pixels) the host's own panel would have occupied, so the external window can be positioned there instead of wherever it would otherwise appear:
interface IReceivesPreviewPanelBounds
{
void OnPreviewPanelBoundsAvailable(int left, int top, int width, int height);
}See the bundled (experimental) QuickLook Bridge plugin for a real example: it detects an external QuickLook app over its own named pipe and, if reachable, docks that app's window into the host panel's spot for every file/folder — see Actions Menu & Preview → External preview via QuickLook for the user-facing behavior. Note this is a different thing from SwiftList's own built-in preview pane, which is also informally called "QuickLook" throughout this codebase and docs.
IThumbnailProvider
Overrides the icon/thumbnail shown for matching results.
interface IThumbnailProvider : IPluginComponent
{
int Priority { get; } // default 0; higher runs first
bool CanProvideThumbnail(string path, bool isDir);
ImageSource? GetThumbnail(string path, int size);
}Same caveat as IFilePreviewProvider.Priority above: it's only the default order, and the user can override it from Settings → General → Preview & Thumbnails (the same tab hosts both providers' order lists).
Themes & localization
IThemeProvider / ITheme
Registers one or more custom WPF resource dictionaries as selectable themes (shown in Settings → General → Interface theme).
interface IThemeProvider
{
string Name { get; }
IEnumerable<ITheme> GetThemes();
}
interface ITheme
{
string Id { get; }
string DisplayName { get; }
bool IsDark { get; }
double WindowOpacity { get; } // default 1.0
ResourceDictionary GetResources();
}ITranslationProvider
Supplies UI strings for a given culture — for the plugin's own UI, or (as with PinyinAlias) just its own display name. See Example Plugins for a plugin that implements this alongside an unrelated interface on the same class.
interface ITranslationProvider
{
string Name { get; }
IReadOnlyList<string> SupportedCultures { get; } // e.g. "zh-CN", "en-US"
IReadOnlyDictionary<string, string> GetTranslations(string cultureName);
}TranslationService.LoadEmbeddedTranslations (see Host Services) is the standard way to back this with JSON files embedded in your plugin DLL.