diff --git a/app/MindWork AI Studio/Components/InnerScrolling.razor b/app/MindWork AI Studio/Components/InnerScrolling.razor
index f0c66d6..bad2c09 100644
--- a/app/MindWork AI Studio/Components/InnerScrolling.razor
+++ b/app/MindWork AI Studio/Components/InnerScrolling.razor
@@ -3,6 +3,10 @@
@this.ChildContent
+
+
+
+
@this.FooterContent
diff --git a/app/MindWork AI Studio/Components/InnerScrolling.razor.cs b/app/MindWork AI Studio/Components/InnerScrolling.razor.cs
index b204f4e..42d75a0 100644
--- a/app/MindWork AI Studio/Components/InnerScrolling.razor.cs
+++ b/app/MindWork AI Studio/Components/InnerScrolling.razor.cs
@@ -26,6 +26,11 @@ public partial class InnerScrolling : MSGComponentBase
[CascadingParameter]
private MainLayout MainLayout { get; set; } = null!;
+
+ [Inject]
+ private IJSRuntime JsRuntime { get; init; } = null!;
+
+ private ElementReference AnchorAfterChildContent { get; set; }
#region Overrides of ComponentBase
@@ -59,4 +64,9 @@ public partial class InnerScrolling : MSGComponentBase
#endregion
private string Height => $"height: calc(100vh - {this.HeaderHeight} - {this.MainLayout.AdditionalHeight});";
+
+ public async Task ScrollToBottom()
+ {
+ await this.AnchorAfterChildContent.ScrollIntoViewAsync(this.JsRuntime);
+ }
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Pages/Chat.razor b/app/MindWork AI Studio/Pages/Chat.razor
index d8e2d99..beb5266 100644
--- a/app/MindWork AI Studio/Pages/Chat.razor
+++ b/app/MindWork AI Studio/Pages/Chat.razor
@@ -16,7 +16,7 @@
-
+
@if (this.chatThread is not null)
{
diff --git a/app/MindWork AI Studio/Pages/Chat.razor.cs b/app/MindWork AI Studio/Pages/Chat.razor.cs
index 9d22184..b9b1c3f 100644
--- a/app/MindWork AI Studio/Pages/Chat.razor.cs
+++ b/app/MindWork AI Studio/Pages/Chat.razor.cs
@@ -29,6 +29,8 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
[Inject]
public IDialogService DialogService { get; set; } = null!;
+
+ private InnerScrolling scrollingArea = null!;
private const Placement TOOLBAR_TOOLTIP_PLACEMENT = Placement.Bottom;
private static readonly Dictionary USER_INPUT_ATTRIBUTES = new();
@@ -42,6 +44,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
private Guid currentWorkspaceId = Guid.Empty;
private bool workspacesVisible;
private Workspaces? workspaces;
+ private bool mustScrollToBottomAfterRender;
// Unfortunately, we need the input field reference to clear it after sending a message.
// This is necessary because we have to handle the key events ourselves. Otherwise,
@@ -83,6 +86,17 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
await base.OnInitializedAsync();
}
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if(this.mustScrollToBottomAfterRender)
+ {
+ await this.scrollingArea.ScrollToBottom();
+ this.mustScrollToBottomAfterRender = false;
+ }
+
+ await base.OnAfterRenderAsync(firstRender);
+ }
+
#endregion
private bool IsProviderSelected => this.providerSettings.UsedProvider != Providers.NONE;
@@ -372,6 +386,11 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
this.currentWorkspaceName = this.chatThread is null ? string.Empty : await this.workspaces.LoadWorkspaceName(this.chatThread.WorkspaceId);
await this.inputField.Clear();
+ if (this.SettingsManager.ConfigurationData.Chat.ShowLatestMessageAfterLoading)
+ {
+ this.mustScrollToBottomAfterRender = true;
+ this.StateHasChanged();
+ }
}
private void ResetState()
diff --git a/app/MindWork AI Studio/Pages/Settings.razor b/app/MindWork AI Studio/Pages/Settings.razor
index 4a7bd8c..68cad51 100644
--- a/app/MindWork AI Studio/Pages/Settings.razor
+++ b/app/MindWork AI Studio/Pages/Settings.razor
@@ -77,6 +77,7 @@
+
diff --git a/app/MindWork AI Studio/Settings/DataModel/DataChat.cs b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs
index 825bfc9..4671d12 100644
--- a/app/MindWork AI Studio/Settings/DataModel/DataChat.cs
+++ b/app/MindWork AI Studio/Settings/DataModel/DataChat.cs
@@ -16,4 +16,9 @@ public sealed class DataChat
/// Should we preselect a provider for the chat?
///
public string PreselectedProvider { get; set; } = string.Empty;
+
+ ///
+ /// Should we show the latest message after loading? When false, we show the first (aka oldest) message.
+ ///
+ public bool ShowLatestMessageAfterLoading { get; set; } = true;
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Tools/ElementReferenceExtensions.cs b/app/MindWork AI Studio/Tools/ElementReferenceExtensions.cs
new file mode 100644
index 0000000..fe46acf
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/ElementReferenceExtensions.cs
@@ -0,0 +1,11 @@
+using Microsoft.AspNetCore.Components;
+
+namespace AIStudio.Tools;
+
+public static class ElementReferenceExtensions
+{
+ public static async ValueTask ScrollIntoViewAsync(this ElementReference elementReference, IJSRuntime jsRuntime)
+ {
+ await jsRuntime.InvokeVoidAsync("scrollToBottom", elementReference);
+ }
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/wwwroot/app.js b/app/MindWork AI Studio/wwwroot/app.js
index 61a5241..42b43f0 100644
--- a/app/MindWork AI Studio/wwwroot/app.js
+++ b/app/MindWork AI Studio/wwwroot/app.js
@@ -21,4 +21,8 @@ window.generateDiff = function (text1, text2, divDiff, divLegend) {
window.clearDiv = function (divName) {
let targetDiv = document.getElementById(divName);
targetDiv.innerHTML = '';
+}
+
+window.scrollToBottom = function(element) {
+ element.scrollIntoView();
}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.8.12.md b/app/MindWork AI Studio/wwwroot/changelog/v0.8.12.md
index de1b9d9..6185dff 100644
--- a/app/MindWork AI Studio/wwwroot/changelog/v0.8.12.md
+++ b/app/MindWork AI Studio/wwwroot/changelog/v0.8.12.md
@@ -1,7 +1,8 @@
# v0.8.12, build 174
- Added an e-mail writing assistant.
- Added the possibility to preselect some e-mail writing assistant options.
-- Improved: all assistants now have a button to copy their respective result to the clipboard.
+- Improved chat page by scrolling to the bottom after loading (configurable; default is on).
+- Improved all assistants to provide a button to copy their respective result to the clipboard.
- Improved the content validation for the agenda assistant.
- Improved the language handling of the agenda assistant.
- Refactored the "send to" implementation of assistants.
\ No newline at end of file