Fixed plugin action buttons disappearing while sharing a plugin

This commit is contained in:
Thorsten Sommer 2026-08-05 16:53:02 +02:00
parent a4db045881
commit 38710fdd08
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
2 changed files with 16 additions and 11 deletions

View File

@ -118,21 +118,21 @@
@if (context is IAvailablePlugin editablePlugin && CanEditAssistantPlugin(editablePlugin)) @if (context is IAvailablePlugin editablePlugin && CanEditAssistantPlugin(editablePlugin))
{ {
<MudTooltip Text="@T("Edit assistant plugin")"> <MudTooltip Text="@T("Edit assistant plugin")">
<MudIconButton Icon="@Icons.Material.Filled.Code" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginEditorDialogAsync(editablePlugin))" Disabled="@(!CanEditAssistantPlugin(editablePlugin))"/> <MudIconButton Icon="@Icons.Material.Filled.Code" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginEditorDialogAsync(editablePlugin))"/>
</MudTooltip> </MudTooltip>
} }
@if (context is IAvailablePlugin shareablePlugin && CanSharePlugin(shareablePlugin)) @if (context is IAvailablePlugin shareablePlugin && CanSharePlugin(shareablePlugin))
{ {
<MudTooltip Text="@(this.AllowPluginSharing ? this.SharePluginTooltip : this.SharePluginLockText)"> <MudTooltip Text="@(this.AllowPluginSharing ? this.SharePluginTooltip : this.SharePluginLockText)">
<MudIconButton Icon="@SharePluginIcon" Size="Size.Medium" OnClick="@(() => this.SharePluginAsync(shareablePlugin))" Disabled="@(!this.AllowPluginSharing || !CanSharePlugin(shareablePlugin))"/> <MudIconButton Icon="@SharePluginIcon" Size="Size.Medium" OnClick="@(() => this.SharePluginAsync(shareablePlugin))" Disabled="@(this.isSharingPlugin || !this.AllowPluginSharing)"/>
</MudTooltip> </MudTooltip>
} }
@if (context is IAvailablePlugin revisionPlugin && CanReviseAssistantPlugin(revisionPlugin)) @if (context is IAvailablePlugin revisionPlugin && CanReviseAssistantPlugin(revisionPlugin))
{ {
<MudTooltip Text="@T("Revise assistant plugin with AI")"> <MudTooltip Text="@T("Revise assistant plugin with AI")">
<MudIconButton Icon="@Icons.Material.Filled.AutoMode" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginRevisionDialogAsync(revisionPlugin))" Disabled="@(!CanReviseAssistantPlugin(revisionPlugin))"/> <MudIconButton Icon="@Icons.Material.Filled.AutoMode" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginRevisionDialogAsync(revisionPlugin))"/>
</MudTooltip> </MudTooltip>
} }

View File

@ -40,7 +40,7 @@ public partial class Plugins : MSGComponentBase
private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(nameof(Plugins)); private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(nameof(Plugins));
private static bool IS_SHARING_PLUGIN; private bool isSharingPlugin;
private const string IMPORT_ICON = private const string IMPORT_ICON =
@"<svg class=""mud-icon-root mud-svg-icon mud-dark-text mud-icon-size-medium"" focusable=""false"" viewBox=""0 0 24 24"" aria-hidden=""true"" role=""img""> @"<svg class=""mud-icon-root mud-svg-icon mud-dark-text mud-icon-size-medium"" focusable=""false"" viewBox=""0 0 24 24"" aria-hidden=""true"" role=""img"">
@ -204,15 +204,20 @@ public partial class Plugins : MSGComponentBase
: this.T("Enable plugin"); : this.T("Enable plugin");
} }
private static bool CanEditAssistantPlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath) && !IS_SHARING_PLUGIN; //
// These methods decide whether an action exists for a plugin at all. They must not depend on
// transient state like an ongoing share: they gate the markup, so a transient value would make
// the action buttons disappear and reappear. Transient state belongs into the buttons' Disabled.
//
private static bool CanEditAssistantPlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath);
private static bool CanReviseAssistantPlugin(IAvailablePlugin plugin) private static bool CanReviseAssistantPlugin(IAvailablePlugin plugin)
{ {
var assistantPlugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>().FirstOrDefault(x => x.Id == plugin.Id); var assistantPlugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>().FirstOrDefault(x => x.Id == plugin.Id);
return plugin is { IsInternal: false, IsManagedByConfigServer: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath) && assistantPlugin?.IsManagedByConfigServer is false && !IS_SHARING_PLUGIN; return plugin is { IsInternal: false, IsManagedByConfigServer: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath) && assistantPlugin?.IsManagedByConfigServer is false;
} }
private static bool CanSharePlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, IsManagedByConfigServer: false } && !string.IsNullOrWhiteSpace(plugin.LocalPath) && !IS_SHARING_PLUGIN; private static bool CanSharePlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, IsManagedByConfigServer: false } && !string.IsNullOrWhiteSpace(plugin.LocalPath);
/// <summary> /// <summary>
/// Organizations may disable importing plugin archives by using a configuration plugin. /// Organizations may disable importing plugin archives by using a configuration plugin.
@ -275,10 +280,10 @@ public partial class Plugins : MSGComponentBase
private async Task SharePluginAsync(IAvailablePlugin plugin) private async Task SharePluginAsync(IAvailablePlugin plugin)
{ {
if (IS_SHARING_PLUGIN) if (this.isSharingPlugin)
return; return;
IS_SHARING_PLUGIN = true; this.isSharingPlugin = true;
// invoke a state change right away to guard action buttons // invoke a state change right away to guard action buttons
await this.InvokeAsync(this.StateHasChanged); await this.InvokeAsync(this.StateHasChanged);
@ -301,7 +306,7 @@ public partial class Plugins : MSGComponentBase
} }
finally finally
{ {
IS_SHARING_PLUGIN = false; this.isSharingPlugin = false;
await this.InvokeAsync(this.StateHasChanged); await this.InvokeAsync(this.StateHasChanged);
} }
} }