mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-13 00:14:26 +00:00
Kept media transcripts when editing a message or moving a chat (#1047)
This commit is contained in:
1 parent
3a1f586f76
commit
5ee4dfa2b5
8 files changed
+461
-28
No files matched your search
@@ -102,7 +102,7 @@
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
{
|
||||
<MudTooltip Text="@T("Move the chat to a workspace, or to another if it is already in one.")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Disabled="@(!this.CanThreadBeSaved || this.IsCurrentChatStreaming)" OnClick="@this.MoveChatToWorkspace"/>
|
||||
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Disabled="@(!this.CanThreadBeMoved)" OnClick="@this.MoveChatToWorkspace"/>
|
||||
</MudTooltip>
|
||||
|
||||
<MudTooltip Text="@T("Copy this chat & continue in the copy.")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
|
||||
@@ -549,6 +549,16 @@ public partial class ChatComponent : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// The same chat in another workspace was moved there, e.g., through the workspace tree. Only
|
||||
// a move changes the workspace of a chat; every other way to open one brings another chat ID:
|
||||
//
|
||||
if (chatId != Guid.Empty && this.loadedParameterChatId == chatId)
|
||||
{
|
||||
await this.FollowMovedChatAsync(this.loadedParameterWorkspaceId);
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadedParameterChatId = chatId;
|
||||
this.loadedParameterWorkspaceId = workspaceId;
|
||||
await this.LoadedChatChanged(notifyParent: false);
|
||||
@@ -673,6 +683,21 @@ public partial class ChatComponent : MSGComponentBase
|
||||
|
||||
private bool CanThreadBeCopied => this.CanThreadBeSaved && !this.IsCurrentChatStreaming && !this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the open chat can move into a workspace, which is exactly when the workspace tree offers it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The tree lists every stored chat, even one without a message yet, such as a chat which was
|
||||
/// stored right away to keep the transcript of an audio or video file. A chat not stored yet has
|
||||
/// no directory to move. While an answer is generated or a transcript is made, the chat stays
|
||||
/// where it is, just like in the tree. The directory check comes last, because this runs with
|
||||
/// every render.
|
||||
/// </remarks>
|
||||
private bool CanThreadBeMoved => this.ChatThread is not null
|
||||
&& !this.IsCurrentChatStreaming
|
||||
&& !this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner)
|
||||
&& WorkspaceBehaviour.IsChatExisting(new LoadChat(this.ChatThread.WorkspaceId, this.ChatThread.ChatId));
|
||||
|
||||
private string TooltipAddChatToWorkspace => string.Format(T("Start new chat in workspace '{0}'"), this.currentWorkspaceName);
|
||||
|
||||
private string UserInputStyle => this.SettingsManager.ConfigurationData.Confidence.ShowProviderConfidence ? this.Provider.UsedLLMProvider.GetConfidence(this.SettingsManager).SetColorStyle(this.SettingsManager) : string.Empty;
|
||||
@@ -1366,9 +1391,35 @@ public partial class ChatComponent : MSGComponentBase
|
||||
if (workspaceId == Guid.Empty)
|
||||
return;
|
||||
|
||||
var previousWorkspaceId = this.ChatThread!.WorkspaceId;
|
||||
await WorkspaceBehaviour.MoveChatAsync(this.ChatThread!, workspaceId);
|
||||
this.MarkCurrentChatAsLoadedParameter();
|
||||
await this.FollowMovedChatAsync(previousWorkspaceId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Follows the open chat into the workspace it was moved to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A move is no other chat being opened, so the message being written stays in the composer,
|
||||
/// whether the user moved the chat from here or through the workspace tree. What has to change are
|
||||
/// the paths of its attachments: the move took the chat directory along, and with it the
|
||||
/// transcripts of audio and video files. Left with their old paths, the composer would send
|
||||
/// references to files which are gone.
|
||||
/// </remarks>
|
||||
/// <param name="previousWorkspaceId">The workspace the chat came from, or Guid.Empty for a temporary chat.</param>
|
||||
private async Task FollowMovedChatAsync(Guid previousWorkspaceId)
|
||||
{
|
||||
var chatId = this.ChatThread!.ChatId;
|
||||
var workspaceId = this.ChatThread.WorkspaceId;
|
||||
var relocatedAttachments = this.ComposerState.FileAttachments
|
||||
.Select(attachment => WorkspaceBehaviour.RelocateAttachmentAfterMove(attachment, chatId, previousWorkspaceId, workspaceId))
|
||||
.ToList();
|
||||
|
||||
this.ComposerState.FileAttachments.Clear();
|
||||
foreach (var attachment in relocatedAttachments)
|
||||
this.ComposerState.FileAttachments.Add(attachment);
|
||||
|
||||
this.MarkCurrentChatAsLoadedParameter();
|
||||
await this.SyncWorkspaceHeaderWithChatThreadAsync();
|
||||
}
|
||||
|
||||
@@ -1558,7 +1609,7 @@ public partial class ChatComponent : MSGComponentBase
|
||||
return Task.CompletedTask;
|
||||
|
||||
this.RestoreComposerFromTextBlock(textBlock);
|
||||
this.ChatThread.Remove(block);
|
||||
this.ChatThread.RemoveForEditing(block);
|
||||
this.ChatThread.Remove(lastBlockContent);
|
||||
this.hasUnsavedChanges = true;
|
||||
this.StateHasChanged();
|
||||
@@ -1574,7 +1625,7 @@ public partial class ChatComponent : MSGComponentBase
|
||||
return Task.CompletedTask;
|
||||
|
||||
this.RestoreComposerFromTextBlock(textBlock);
|
||||
this.ChatThread.Remove(block);
|
||||
this.ChatThread.RemoveForEditing(block);
|
||||
this.hasUnsavedChanges = true;
|
||||
this.StateHasChanged();
|
||||
return Task.CompletedTask;
|
||||
|
||||
@@ -940,10 +940,16 @@ public partial class Workspaces : MSGComponentBase
|
||||
|
||||
private async Task MoveChatAsync(string? chatPath)
|
||||
{
|
||||
var chat = await this.LoadChatAsync(chatPath, false);
|
||||
if (chat is null)
|
||||
var storedChat = await this.LoadChatAsync(chatPath, false);
|
||||
if (storedChat is null)
|
||||
return;
|
||||
|
||||
//
|
||||
// The open chat moves as it stands on the screen, just like with the button in the chat
|
||||
// itself. The copy from the disk lacks whatever is not stored yet, such as a message being
|
||||
// edited, and the chat would continue with that copy afterward:
|
||||
//
|
||||
var chat = this.CurrentChatThread is { } openChat && openChat.ChatId == storedChat.ChatId ? openChat : storedChat;
|
||||
if (this.AIJobService.IsChatGenerationActive(chat.ChatId))
|
||||
return;
|
||||
|
||||
@@ -964,11 +970,8 @@ public partial class Workspaces : MSGComponentBase
|
||||
return;
|
||||
|
||||
await WorkspaceBehaviour.MoveChatAsync(chat, workspaceId);
|
||||
if (this.CurrentChatThread?.ChatId == chat.ChatId)
|
||||
{
|
||||
this.CurrentChatThread = chat;
|
||||
if (ReferenceEquals(chat, this.CurrentChatThread))
|
||||
await this.CurrentChatThreadChanged.InvokeAsync(this.CurrentChatThread);
|
||||
}
|
||||
|
||||
await this.LoadTreeItemsAsync(startPrefetch: false);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user