mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-02-05 21:49:06 +00:00
110 lines
3.1 KiB
C#
110 lines
3.1 KiB
C#
using AIStudio.Tools;
|
|
|
|
using Microsoft.AspNetCore.Components;
|
|
|
|
namespace AIStudio.Chat;
|
|
|
|
/// <summary>
|
|
/// The UI component for a chat content block, i.e., for any IContent.
|
|
/// </summary>
|
|
public partial class ContentBlockComponent : ComponentBase
|
|
{
|
|
/// <summary>
|
|
/// The role of the chat content block.
|
|
/// </summary>
|
|
[Parameter]
|
|
public ChatRole Role { get; init; } = ChatRole.NONE;
|
|
|
|
/// <summary>
|
|
/// The content.
|
|
/// </summary>
|
|
[Parameter]
|
|
public IContent Content { get; init; } = new ContentText();
|
|
|
|
/// <summary>
|
|
/// The content type.
|
|
/// </summary>
|
|
[Parameter]
|
|
public ContentType Type { get; init; } = ContentType.NONE;
|
|
|
|
/// <summary>
|
|
/// When was the content created?
|
|
/// </summary>
|
|
[Parameter]
|
|
public DateTimeOffset Time { get; init; }
|
|
|
|
[Inject]
|
|
private Rust Rust { get; init; } = null!;
|
|
|
|
[Inject]
|
|
private IJSRuntime JsRuntime { get; init; } = null!;
|
|
|
|
[Inject]
|
|
private ISnackbar Snackbar { get; init; } = null!;
|
|
|
|
private bool HideContent { get; set; }
|
|
|
|
#region Overrides of ComponentBase
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
// Register the streaming events:
|
|
this.Content.StreamingDone = this.AfterStreaming;
|
|
this.Content.StreamingEvent = () => this.InvokeAsync(this.StateHasChanged);
|
|
|
|
await base.OnInitializedAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets called when the content stream ended.
|
|
/// </summary>
|
|
private async Task AfterStreaming()
|
|
{
|
|
// Might be called from a different thread, so we need to invoke the UI thread:
|
|
await this.InvokeAsync(() =>
|
|
{
|
|
//
|
|
// Issue we try to solve: When the content changes during streaming,
|
|
// Blazor might fail to see all changes made to the render tree.
|
|
// This happens mostly when Markdown code blocks are streamed.
|
|
//
|
|
|
|
// Hide the content for a short time:
|
|
this.HideContent = true;
|
|
|
|
// Let Blazor update the UI, i.e., to see the render tree diff:
|
|
this.StateHasChanged();
|
|
|
|
// Show the content again:
|
|
this.HideContent = false;
|
|
|
|
// Let Blazor update the UI, i.e., to see the render tree diff:
|
|
this.StateHasChanged();
|
|
});
|
|
}
|
|
|
|
#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.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, textContent.Text);
|
|
break;
|
|
|
|
default:
|
|
this.Snackbar.Add("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;
|
|
}
|
|
}
|
|
} |