Unified the copy to clipboard functionality

This commit is contained in:
Peer Schütt 2025-07-25 10:58:23 +02:00
parent 609be6ad5d
commit 87bc18b8f9
6 changed files with 72 additions and 65 deletions

View File

@ -1315,9 +1315,6 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CHATROLEEXTENSIONS::T601166687"] = "AI"
-- Edit Message
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1183581066"] = "Edit Message"
-- Copies the content to the clipboard
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T12948066"] = "Copies the content to the clipboard"
-- Do you really want to remove this message?
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1347427447"] = "Do you really want to remove this message?"
@ -1351,9 +1348,6 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3587744975"] = "Regener
-- Do you really want to regenerate this message?
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3878878761"] = "Do you really want to regenerate this message?"
-- Cannot copy this content type to clipboard!
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4021525742"] = "Cannot copy this content type to clipboard!"
-- Remove Message
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4070211974"] = "Remove Message"
@ -1591,11 +1585,8 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platfor
-- Copies the content to the clipboard
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"
-- Successfully copied the content to your clipboard
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T2721950880"] = "Successfully copied the content to your clipboard"
-- Failed to copy the content to your clipboard
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T424495418"] = "Failed to copy the content to your clipboard"
-- Cannot copy this content type to clipboard!
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T4021525742"] = "Cannot copy this content type to clipboard!"
-- Alpha phase means that we are working on the last details before the beta phase.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PREVIEWALPHA::T166807685"] = "Alpha phase means that we are working on the last details before the beta phase."

View File

@ -1,5 +1,7 @@
@using System.Runtime.CompilerServices
@using AIStudio.Tools
@using MudBlazor
@using AIStudio.Components
@inherits AIStudio.Components.MSGComponentBase
<MudCard Class="@this.CardClasses" Outlined="@true">
<MudCardHeader>
@ -38,9 +40,8 @@
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@this.RemoveBlock"/>
</MudTooltip>
}
<MudTooltip Text="@T("Copies the content to the clipboard")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Color="Color.Default" OnClick="@this.CopyToClipboard"/>
</MudTooltip>
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type"/>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>

View File

@ -1,5 +1,4 @@
using AIStudio.Components;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
@ -61,12 +60,6 @@ public partial class ContentBlockComponent : MSGComponentBase
[Parameter]
public Func<bool> RegenerateEnabled { get; set; } = () => false;
[Inject]
private RustService RustService { get; init; } = null!;
[Inject]
private ISnackbar Snackbar { get; init; } = null!;
[Inject]
private IDialogService DialogService { get; init; } = null!;
@ -115,29 +108,6 @@ public partial class ContentBlockComponent : MSGComponentBase
}
#endregion
/// <summary>
/// Copy this block's content to the clipboard.
/// </summary>
private async Task CopyToClipboard()
{
switch (this.Type)
{
case ContentType.TEXT:
var textContent = (ContentText) this.Content;
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text);
break;
default:
this.Snackbar.Add(T("Cannot copy this content type to clipboard!"), Severity.Error, config =>
{
config.Icon = Icons.Material.Filled.ContentCopy;
config.IconSize = Size.Large;
config.IconColor = Color.Error;
});
break;
}
}
private string CardClasses => $"my-2 rounded-lg {this.Class}";

View File

@ -1,5 +1,6 @@
<MudTooltip Text=@ToolTipMessage>
@using AIStudio.Chat
<MudTooltip Text="@this.ToolTipMessage" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
Size="Size.Small"
OnClick="@(() => CopyToClipboard(this.CopyableContent))"/>
OnClick="@(() => HandleCopyClick())"/>
</MudTooltip>

View File

@ -1,5 +1,7 @@
using AIStudio.Pages;
using AIStudio.Chat;
using AIStudio.Pages;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components;
@ -7,12 +9,24 @@ namespace AIStudio.Components;
public partial class MudCopyClipboardButton : ComponentBase
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(About).Namespace, nameof(About));
/// <summary>
/// The string that will be copied when the button is clicked.
/// The string, if you want to copy a string.
/// </summary>
[Parameter]
public required string CopyableContent { get; set; }
public string StringContent { get; set; } = string.Empty;
/// <summary>
/// The content, if you want to copy content.
/// </summary>
[Parameter]
public IContent? Content { get; init; }
/// <summary>
/// The content type, if you want to copy Content.
/// </summary>
[Parameter]
public ContentType Type { get; init; } = ContentType.NONE;
/// <summary>
/// The tooltip that should be shown to the user.
@ -20,22 +34,52 @@ public partial class MudCopyClipboardButton : ComponentBase
[Parameter]
public string ToolTipMessage { get; set; } = TB("Copies the content to the clipboard");
[Inject]
private IJSRuntime JsRuntime { get; set; } = null!;
[Inject]
private ISnackbar Snackbar { get; init; } = null!;
private async Task CopyToClipboard(string text)
[Inject]
private RustService RustService { get; init; } = null!;
private async Task HandleCopyClick()
{
try
if (this.Type == ContentType.NONE)
{
await this.JsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
this.Snackbar.Add(TB("Successfully copied the content to your clipboard"), Severity.Success);
await this.CopyToClipboard(this.StringContent);
}
catch (Exception)
else
{
this.Snackbar.Add(TB("Failed to copy the content to your clipboard"), Severity.Error);
await this.CopyToClipboard(this.Content!);
}
}
/// <summary>
/// Copy this the string to the clipboard.
/// </summary>
private async Task CopyToClipboard(string textContent)
{
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent);
}
/// <summary>
/// Copy this block's content to the clipboard.
/// </summary>
private async Task CopyToClipboard(IContent contentToCopy)
{
switch (this.Type)
{
case ContentType.TEXT:
var textContent = (ContentText) contentToCopy;
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text);
break;
default:
this.Snackbar.Add(TB("Cannot copy this content type to clipboard!"), Severity.Error, config =>
{
config.Icon = Icons.Material.Filled.ContentCopy;
config.IconSize = Size.Large;
config.IconColor = Color.Error;
});
break;
}
}

View File

@ -33,7 +33,7 @@
<MudText>@T("AI Studio runs with an enterprise configuration using the configuration plugin, without central configuration management.")</MudText>
<MudCollapse Expanded="@showConfigDetails">
<MudText>@T("Configuration Plugin ID:") @configPlug!.Id
<MudCopyClipboardButton CopyableContent=@configPlug!.Id.ToString()/>
<MudCopyClipboardButton StringContent=@configPlug!.Id.ToString()/>
</MudText>
</MudCollapse>
break;
@ -41,11 +41,11 @@
<MudText>@T("AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.")</MudText>
<MudCollapse Expanded="@showConfigDetails">
<MudText>@T("Enterprise Configuration ID:") @currentEnvironment.ConfigurationId
<MudCopyClipboardButton ToolTipMessage="@T("Copies the config ID to the clipboard")" CopyableContent=@currentEnvironment.ConfigurationId.ToString()/>
<MudCopyClipboardButton ToolTipMessage="@T("Copies the config ID to the clipboard")" StringContent=@currentEnvironment.ConfigurationId.ToString()/>
</MudText>
<MudText>@T("Configuration Server:") @currentEnvironment.ConfigurationServerUrl
<MudCopyClipboardButton ToolTipMessage="@T("Copies the server URL to the clipboard")" CopyableContent=@currentEnvironment.ConfigurationServerUrl/>
<MudCopyClipboardButton ToolTipMessage="@T("Copies the server URL to the clipboard")" StringContent=@currentEnvironment.ConfigurationServerUrl/>
</MudText>
</MudCollapse>
break;
@ -53,11 +53,11 @@
<MudText>@T("AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.")</MudText>
<MudCollapse Expanded="@showConfigDetails">
<MudText Class="ml-4">@T("Enterprise Configuration ID:") @currentEnvironment.ConfigurationId
<MudCopyClipboardButton ToolTipMessage="@T("Copies the config ID to the clipboard")" CopyableContent=@currentEnvironment.ConfigurationId.ToString()/>
<MudCopyClipboardButton ToolTipMessage="@T("Copies the config ID to the clipboard")" StringContent=@currentEnvironment.ConfigurationId.ToString()/>
</MudText>
<MudText Class="ml-4">@T("Configuration Server:") @currentEnvironment.ConfigurationServerUrl
<MudCopyClipboardButton ToolTipMessage="@T("Copies the server URL to the clipboard")" CopyableContent=@currentEnvironment.ConfigurationServerUrl/>
<MudCopyClipboardButton ToolTipMessage="@T("Copies the server URL to the clipboard")" StringContent=@currentEnvironment.ConfigurationServerUrl/>
</MudText>
</MudCollapse>
break;