Fixed workspace name is not changed (#721)
Some checks are pending
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,deb,updater, appimage,deb) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,deb,updater, appimage,deb) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Sabrina-devops 2026-04-15 09:44:12 +02:00 committed by GitHub
parent e5d8ac4a71
commit d56eb5b4ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -67,6 +67,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
private string currentWorkspaceName = string.Empty; private string currentWorkspaceName = string.Empty;
private Guid currentWorkspaceId = Guid.Empty; private Guid currentWorkspaceId = Guid.Empty;
private Guid currentChatThreadId = Guid.Empty; private Guid currentChatThreadId = Guid.Empty;
private int workspaceHeaderSyncVersion;
private CancellationTokenSource? cancellationTokenSource; private CancellationTokenSource? cancellationTokenSource;
private HashSet<FileAttachment> chatDocumentPaths = []; private HashSet<FileAttachment> chatDocumentPaths = [];
@ -208,12 +209,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// workspace name is loaded: // workspace name is loaded:
// //
if (this.ChatThread is not null) if (this.ChatThread is not null)
{ await this.SyncWorkspaceHeaderWithChatThreadAsync();
this.currentChatThreadId = this.ChatThread.ChatId;
this.currentWorkspaceId = this.ChatThread.WorkspaceId;
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
this.WorkspaceName(this.currentWorkspaceName);
}
// Select the correct provider: // Select the correct provider:
await this.SelectProviderWhenLoadingChat(); await this.SelectProviderWhenLoadingChat();
@ -231,9 +227,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
else else
await WorkspaceBehaviour.StoreChatAsync(this.ChatThread); await WorkspaceBehaviour.StoreChatAsync(this.ChatThread);
this.currentWorkspaceId = this.ChatThread.WorkspaceId; await this.SyncWorkspaceHeaderWithChatThreadAsync();
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
this.WorkspaceName(this.currentWorkspaceName);
} }
if (firstRender && this.mustLoadChat) if (firstRender && this.mustLoadChat)
@ -247,8 +241,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
await this.ChatThreadChanged.InvokeAsync(this.ChatThread); await this.ChatThreadChanged.InvokeAsync(this.ChatThread);
this.Logger.LogInformation($"The chat '{this.ChatThread!.ChatId}' with title '{this.ChatThread.Name}' ({this.ChatThread.Blocks.Count} messages) was loaded successfully."); this.Logger.LogInformation($"The chat '{this.ChatThread!.ChatId}' with title '{this.ChatThread.Name}' ({this.ChatThread.Blocks.Count} messages) was loaded successfully.");
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId); await this.SyncWorkspaceHeaderWithChatThreadAsync();
this.WorkspaceName(this.currentWorkspaceName);
await this.SelectProviderWhenLoadingChat(); await this.SelectProviderWhenLoadingChat();
} }
else else
@ -283,38 +276,57 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
private async Task SyncWorkspaceHeaderWithChatThreadAsync() private async Task SyncWorkspaceHeaderWithChatThreadAsync()
{ {
if (this.ChatThread is null) var syncVersion = Interlocked.Increment(ref this.workspaceHeaderSyncVersion);
var currentChatThread = this.ChatThread;
if (currentChatThread is null)
{ {
if (this.currentChatThreadId != Guid.Empty || this.currentWorkspaceId != Guid.Empty || !string.IsNullOrWhiteSpace(this.currentWorkspaceName)) this.ClearWorkspaceHeaderState();
{
this.currentChatThreadId = Guid.Empty;
this.currentWorkspaceId = Guid.Empty;
this.currentWorkspaceName = string.Empty;
this.WorkspaceName(this.currentWorkspaceName);
}
return; return;
} }
// Guard: If ChatThread ID and WorkspaceId haven't changed, skip entirely. // Guard: If ChatThread ID and WorkspaceId haven't changed, skip entirely.
// Using ID-based comparison instead of name-based to correctly handle // Using ID-based comparison instead of name-based to correctly handle
// temporary chats where the workspace name is always empty. // temporary chats where the workspace name is always empty.
if (this.currentChatThreadId == this.ChatThread.ChatId if (this.currentChatThreadId == currentChatThread.ChatId
&& this.currentWorkspaceId == this.ChatThread.WorkspaceId) && this.currentWorkspaceId == currentChatThread.WorkspaceId)
return; return;
this.currentChatThreadId = this.ChatThread.ChatId; var chatThreadId = currentChatThread.ChatId;
this.currentWorkspaceId = this.ChatThread.WorkspaceId; var workspaceId = currentChatThread.WorkspaceId;
var loadedWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId); var loadedWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(workspaceId);
// Only notify the parent when the name actually changed to prevent // A newer sync request was started while awaiting IO. Ignore stale results.
// an infinite render loop: WorkspaceName → UpdateWorkspaceName → if (syncVersion != this.workspaceHeaderSyncVersion)
// StateHasChanged → re-render → OnParametersSetAsync → WorkspaceName → ... return;
if (this.currentWorkspaceName != loadedWorkspaceName)
{ // The active chat changed while loading the workspace name.
this.currentWorkspaceName = loadedWorkspaceName; if (this.ChatThread is null
this.WorkspaceName(this.currentWorkspaceName); || this.ChatThread.ChatId != chatThreadId
|| this.ChatThread.WorkspaceId != workspaceId)
return;
this.currentChatThreadId = chatThreadId;
this.currentWorkspaceId = workspaceId;
this.PublishWorkspaceNameIfChanged(loadedWorkspaceName);
} }
private void ClearWorkspaceHeaderState()
{
this.currentChatThreadId = Guid.Empty;
this.currentWorkspaceId = Guid.Empty;
this.PublishWorkspaceNameIfChanged(string.Empty);
}
private void PublishWorkspaceNameIfChanged(string workspaceName)
{
// Only notify the parent when the name actually changed to prevent
// an infinite render loop: WorkspaceName -> UpdateWorkspaceName ->
// StateHasChanged -> re-render -> OnParametersSetAsync -> WorkspaceName -> ...
if (this.currentWorkspaceName == workspaceName)
return;
this.currentWorkspaceName = workspaceName;
this.WorkspaceName(this.currentWorkspaceName);
} }
private bool IsProviderSelected => this.Provider.UsedLLMProvider != LLMProviders.NONE; private bool IsProviderSelected => this.Provider.UsedLLMProvider != LLMProviders.NONE;
@ -738,10 +750,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
// to reset the chat thread: // to reset the chat thread:
// //
this.ChatThread = null; this.ChatThread = null;
this.currentChatThreadId = Guid.Empty; this.ClearWorkspaceHeaderState();
this.currentWorkspaceId = Guid.Empty;
this.currentWorkspaceName = string.Empty;
this.WorkspaceName(this.currentWorkspaceName);
} }
else else
{ {
@ -818,9 +827,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
this.ChatThread!.WorkspaceId = workspaceId; this.ChatThread!.WorkspaceId = workspaceId;
await this.SaveThread(); await this.SaveThread();
this.currentWorkspaceId = this.ChatThread.WorkspaceId; await this.SyncWorkspaceHeaderWithChatThreadAsync();
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
this.WorkspaceName(this.currentWorkspaceName);
} }
private async Task LoadedChatChanged() private async Task LoadedChatChanged()
@ -831,18 +838,12 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
if (this.ChatThread is not null) if (this.ChatThread is not null)
{ {
this.currentWorkspaceId = this.ChatThread.WorkspaceId; await this.SyncWorkspaceHeaderWithChatThreadAsync();
this.currentWorkspaceName = await WorkspaceBehaviour.LoadWorkspaceNameAsync(this.ChatThread.WorkspaceId);
this.WorkspaceName(this.currentWorkspaceName);
this.currentChatThreadId = this.ChatThread.ChatId;
this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources); this.dataSourceSelectionComponent?.ChangeOptionWithoutSaving(this.ChatThread.DataSourceOptions, this.ChatThread.AISelectedDataSources);
} }
else else
{ {
this.currentChatThreadId = Guid.Empty; this.ClearWorkspaceHeaderState();
this.currentWorkspaceId = Guid.Empty;
this.currentWorkspaceName = string.Empty;
this.WorkspaceName(this.currentWorkspaceName);
this.ApplyStandardDataSourceOptions(); this.ApplyStandardDataSourceOptions();
} }
@ -861,11 +862,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
this.isStreaming = false; this.isStreaming = false;
this.hasUnsavedChanges = false; this.hasUnsavedChanges = false;
this.userInput = string.Empty; this.userInput = string.Empty;
this.currentChatThreadId = Guid.Empty; this.ClearWorkspaceHeaderState();
this.currentWorkspaceId = Guid.Empty;
this.currentWorkspaceName = string.Empty;
this.WorkspaceName(this.currentWorkspaceName);
this.ChatThread = null; this.ChatThread = null;
this.ApplyStandardDataSourceOptions(); this.ApplyStandardDataSourceOptions();