Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions SharpFM.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpFM.Plugin.XmlViewer",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpFM.Model", "src\SharpFM.Model\SharpFM.Model.csproj", "{E0FF2DD8-E4B8-4495-92FA-F17AF9B78086}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpFM.Plugin.UI", "src\SharpFM.Plugin.UI\SharpFM.Plugin.UI.csproj", "{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -115,6 +117,18 @@ Global
{E0FF2DD8-E4B8-4495-92FA-F17AF9B78086}.Release|x64.Build.0 = Release|Any CPU
{E0FF2DD8-E4B8-4495-92FA-F17AF9B78086}.Release|x86.ActiveCfg = Release|Any CPU
{E0FF2DD8-E4B8-4495-92FA-F17AF9B78086}.Release|x86.Build.0 = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|x64.ActiveCfg = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|x64.Build.0 = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|x86.ActiveCfg = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Debug|x86.Build.0 = Debug|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|Any CPU.Build.0 = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|x64.ActiveCfg = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|x64.Build.0 = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|x86.ActiveCfg = Release|Any CPU
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -126,5 +140,6 @@ Global
{74337D8E-5EC6-4E5F-9E9E-F2B59E8ECABB} = {E2FF2BB3-AF37-44BA-BD84-999B352D814E}
{E988ECF3-E096-4F29-88C0-27B50FD6C703} = {1515B0F2-1419-4778-92A8-430A8B4931F7}
{E0FF2DD8-E4B8-4495-92FA-F17AF9B78086} = {1515B0F2-1419-4778-92A8-430A8B4931F7}
{8DDBA57D-48E1-400C-A9F6-F02DEFD35EFE} = {1515B0F2-1419-4778-92A8-430A8B4931F7}
EndGlobalSection
EndGlobal
2 changes: 2 additions & 0 deletions src/SharpFM.Plugin.Sample/ClipInspectorPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
using Avalonia.Controls;
using SharpFM.Model;
using SharpFM.Plugin;
using SharpFM.Plugin.UI;

namespace SharpFM.Plugin.Sample;

public class ClipInspectorPlugin : IPanelPlugin
{
public string Id => "clip-inspector";
public string DisplayName => "Clip Inspector";
public string Description => "Displays clip metadata including name, type, element count, and size.";
public string Version => GetType().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "0.0.0";
public IReadOnlyList<PluginKeyBinding> KeyBindings => [];
public IReadOnlyList<PluginMenuAction> MenuActions => [];
Expand Down
2 changes: 1 addition & 1 deletion src/SharpFM.Plugin.Sample/SharpFM.Plugin.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SharpFM.Plugin\SharpFM.Plugin.csproj" />
<ProjectReference Include="..\SharpFM.Plugin.UI\SharpFM.Plugin.UI.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Avalonia.Controls;

namespace SharpFM.Plugin;
namespace SharpFM.Plugin.UI;

/// <summary>
/// A plugin that provides a dockable side panel in the SharpFM UI.
Expand Down
18 changes: 18 additions & 0 deletions src/SharpFM.Plugin.UI/IPluginUIHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Threading.Tasks;
using Avalonia.Controls;

namespace SharpFM.Plugin.UI;

/// <summary>
/// Extended host interface for plugins that need UI capabilities beyond
/// the simple dialogs on <see cref="IPluginHost"/>. Provides content
/// dialog hosting backed by Avalonia.
/// </summary>
public interface IPluginUIHost : IPluginHost
{
/// <summary>
/// Show a modal dialog containing plugin-provided content.
/// Returns true if the user accepted (OK), false if cancelled.
/// </summary>
Task<bool> ShowContentDialogAsync(string title, Control content);
}
25 changes: 25 additions & 0 deletions src/SharpFM.Plugin.UI/SharpFM.Plugin.UI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup>

<PropertyGroup>
<MinVerMinimumMajorMinor>2.0</MinVerMinimumMajorMinor>
<MinVerTagPrefix>v</MinVerTagPrefix>
<MinVerDefaultPreReleaseIdentifiers>beta.0</MinVerDefaultPreReleaseIdentifiers>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SharpFM.Plugin\SharpFM.Plugin.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.4" />
<PackageReference Include="MinVer" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SharpFM.Plugin\SharpFM.Plugin.csproj" />
<ProjectReference Include="..\SharpFM.Plugin.UI\SharpFM.Plugin.UI.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions src/SharpFM.Plugin.XmlViewer/XmlViewerPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
using Avalonia.Controls;
using SharpFM.Model;
using SharpFM.Plugin;
using SharpFM.Plugin.UI;

namespace SharpFM.Plugin.XmlViewer;

public class XmlViewerPlugin : IPanelPlugin
{
public string Id => "xml-viewer";
public string DisplayName => "XML Viewer";
public string Description => "Live XML panel with syntax highlighting and bidirectional sync.";
public string Version => GetType().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "0.0.0";

private IPluginHost? _host;
Expand Down
2 changes: 1 addition & 1 deletion src/SharpFM.Plugin/ClipContentChangedArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ namespace SharpFM.Plugin;
/// Event arguments for <see cref="IPluginHost.ClipContentChanged"/>.
/// </summary>
/// <param name="Clip">Fresh snapshot of the clip with synced XML.</param>
/// <param name="Origin">"editor" for user edits, or the originating plugin's <see cref="IPanelPlugin.Id"/>.</param>
/// <param name="Origin">"editor" for user edits, or the originating plugin's <see cref="IPlugin.Id"/>.</param>
/// <param name="IsPartial">True if the XML was produced from an incomplete parse (e.g. mid-typing).</param>
public record ClipContentChangedArgs(ClipData Clip, string Origin, bool IsPartial);
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
namespace SharpFM.Plugin;

/// <summary>
/// A plugin that transforms clip XML during import or export operations.
/// Transforms run in plugin load order. Use <see cref="IsEnabled"/> to allow
/// users to toggle transforms without uninstalling.
/// A clip transform that runs during import/export operations.
/// Register instances with <see cref="IPluginHost.RegisterTransform"/>.
/// </summary>
public interface IClipTransformPlugin : IPlugin
public interface IClipTransform
{
/// <summary>
/// Transform clip XML when a clip is imported (pasted from FileMaker or loaded from storage).
Expand All @@ -22,8 +21,7 @@ public interface IClipTransformPlugin : IPlugin
Task<string> OnExportAsync(string clipType, string xml);

/// <summary>
/// Whether this transformer is currently enabled.
/// The user can toggle transformers on/off without uninstalling them.
/// Whether this transform is currently enabled.
/// </summary>
bool IsEnabled { get; set; }
}
8 changes: 0 additions & 8 deletions src/SharpFM.Plugin/IEventPlugin.cs

This file was deleted.

17 changes: 0 additions & 17 deletions src/SharpFM.Plugin/IPersistencePlugin.cs

This file was deleted.

5 changes: 5 additions & 0 deletions src/SharpFM.Plugin/IPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public interface IPlugin : IDisposable
/// </summary>
string DisplayName { get; }

/// <summary>
/// Short description of what this plugin does, shown in the Plugin Manager UI.
/// </summary>
string Description { get; }

/// <summary>
/// Plugin version string (e.g. "2.0.0-beta.0"). Shown in the Plugin Manager UI.
/// </summary>
Expand Down
25 changes: 25 additions & 0 deletions src/SharpFM.Plugin/IPluginHost.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SharpFM.Model;
using SharpFM.Model.Schema;
Expand Down Expand Up @@ -77,4 +78,28 @@ public interface IPluginHost
/// Remove a clip from the loaded collection by name.
/// </summary>
bool RemoveClip(string clipName);

/// <summary>
/// Register a clip repository provided by this plugin.
/// The host adds it to the list of available storage backends.
/// </summary>
void RegisterRepository(IClipRepository repository);

/// <summary>
/// Register a clip transform provided by this plugin.
/// Transforms run during import/export in registration order.
/// </summary>
void RegisterTransform(IClipTransform transform);

/// <summary>
/// Show a simple modal dialog with a message and buttons.
/// Returns the label of the clicked button, or null if cancelled.
/// </summary>
Task<string?> ShowDialogAsync(string title, string message, string[] buttons);

/// <summary>
/// Show a modal input dialog prompting the user for text.
/// Returns the entered text, or null if cancelled.
/// </summary>
Task<string?> ShowInputDialogAsync(string title, string prompt, string? defaultValue = null);
}
1 change: 0 additions & 1 deletion src/SharpFM.Plugin/SharpFM.Plugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.4" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.*" />
<PackageReference Include="MinVer" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
15 changes: 7 additions & 8 deletions src/SharpFM/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,21 @@ public override void OnFrameworkInitializationCompleted()

// Load plugins
var pluginHost = new PluginHost(viewModel, loggerFactory);
var pluginUIHost = new PluginUIHost(pluginHost);
var pluginService = new PluginService(logger);
pluginService.LoadPlugins(pluginHost);
pluginService.LoadPlugins(pluginUIHost);

// Wire up all plugin types
viewModel.PanelPlugins = pluginService.PanelPlugins;
viewModel.TransformPlugins = pluginService.TransformPlugins;
viewModel.AllPlugins = pluginService.AllPlugins;
viewModel.PluginUI = pluginUIHost;

// Build repository list: built-in + plugin-provided
// Build repository list: built-in + plugin-registered
var repos = new List<IClipRepository> { viewModel.ActiveRepository };
foreach (var pp in pluginService.PersistencePlugins)
repos.Add(pp.CreateRepository());
repos.AddRange(pluginHost.Repositories);
viewModel.AvailableRepositories = repos;

// Give the window access to plugin services for the manager dialog
if (desktop.MainWindow is MainWindow mainWindow)
mainWindow.SetPluginServices(pluginService, pluginHost);
mainWindow.SetPluginServices(pluginService, pluginUIHost);

desktop.MainWindow.DataContext = viewModel;

Expand Down
Loading
Loading