Refactor message handling and UI in Ask.razor

- Introduced a new `MessageStatus` enum to replace the `IsCompleted` boolean in the `Message` class, allowing for better tracking of message states (New, Streaming, Completed).
- Updated UI rendering to enhance message display with new div elements and conditional spinner for streaming messages.
- Modified the `AskQuestion` method to set the status of user and assistant messages appropriately.
- Added new CSS styles for improved layout and alignment of message components.
- Overall improvements enhance functionality and user experience in the messaging system.
This commit is contained in:
Marco Minerva
2025-07-22 10:30:16 +02:00
parent 505ccff8b7
commit d8343b16e5
2 changed files with 47 additions and 8 deletions
@@ -47,10 +47,20 @@
else
{
<div class="card card-text d-inline-block p-2 px-3 m-1">
<div>
<Markdown style="overflow-y:auto;">@message.Text</Markdown>
<div class="message-content">
<div class="streaming-content">
<div class="streaming-text">
<Markdown style="overflow-y:auto;">@message.Text</Markdown>
</div>
@if (message.Status == MessageStatus.Streaming)
{
<div class="streaming-spinner-bottom-right">
<Spinner Size="SpinnerSize.Small" Color="SpinnerColor.Primary" />
</div>
}
</div>
</div>
@if (message.IsCompleted)
@if (message.Status == MessageStatus.Completed)
{
<div class="d-flex justify-content-between">
<div class="text-start bg-transparent mt-3">
@@ -170,10 +180,10 @@
isAsking = true;
var userQuestion = new Question(conversationId, question!);
var userMessage = new Message { Text = userQuestion.Text, Role = "user" };
var userMessage = new Message { Text = userQuestion.Text, Role = "user", Status = MessageStatus.Completed };
messages.Add(userMessage);
var assistantMessage = new Message { Role = "assistant" };
var assistantMessage = new Message { Role = "assistant", Status = MessageStatus.New };
messages.Add(assistantMessage);
question = null;
@@ -193,6 +203,7 @@
{
userMessage.Text = delta.ReformulatedQuestion;
assistantMessage.TokenUsage = FormatTokenUsage(delta.TokenUsage);
assistantMessage.Status = MessageStatus.Streaming;
}
else if (delta.StreamState == StreamState.Append)
{
@@ -212,7 +223,7 @@
IndexOnPage = c.IndexOnPage
});
assistantMessage.IsCompleted = true;
assistantMessage.Status = MessageStatus.Completed;
assistantMessage.TokenUsage += FormatTokenUsage(delta.TokenUsage);
}
@@ -225,7 +236,7 @@
catch (Exception ex)
{
assistantMessage.Text = $"There was an error while processing the question: {ex.Message}";
assistantMessage.IsCompleted = true;
assistantMessage.Status = MessageStatus.Completed;
}
finally
{
@@ -299,13 +310,20 @@
await JSRuntime.InvokeVoidAsync("scrollTo", chat);
}
public enum MessageStatus
{
New,
Streaming,
Completed
}
public class Message
{
public string? Text { get; set; }
public required string Role { get; set; }
public bool IsCompleted { get; set; }
public MessageStatus Status { get; set; } = MessageStatus.New;
public string? TokenUsage { get; set; }
@@ -77,6 +77,27 @@ input[type="checkbox"] + label {
}
}
.message-content {
position: relative;
}
.streaming-content {
display: flex;
align-items: flex-end;
gap: 8px;
min-height: 1.5em;
}
.streaming-text {
flex: 1;
min-width: 0;
}
.streaming-spinner-bottom-right {
flex-shrink: 0;
align-self: flex-end;
}
.btn-clipboard {
line-height: 1;
color: var(--bs-body-color);