This commit is contained in:
j-erler 2026-09-24 19:49:01 +02:00 committed by GitHub
commit 2415db72ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 78 additions and 13 deletions

View File

@ -3670,6 +3670,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T3996190985"] = "{0} of {1
-- Start temporary chat -- Start temporary chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "Start temporary chat" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "Start temporary chat"
-- Show all files attached to this chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4183453875"] = "Show all files attached to this chat"
-- Heading -- Heading
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Heading" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Heading"
@ -7432,6 +7435,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2111340711"] = "Th
-- You can drag more files into this window to attach them right away. -- You can drag more files into this window to attach them right away.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "You can drag more files into this window to attach them right away." UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "You can drag more files into this window to attach them right away."
-- Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2713115684"] = "Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name."
-- Document Preview -- Document Preview
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Document Preview" UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Document Preview"

View File

@ -112,6 +112,10 @@
<AttachDocuments Name="File Attachments" DocumentPaths="@this.ComposerState.FileAttachments" DocumentPathsChanged="@this.ComposerAttachmentsChanged" CatchAllDocuments="true" UseSmallForm="true" ShowMediaStatus="false" Provider="@this.Provider" OwnerChat="@this.ChatThread" EnsureOwnerChatAsync="@this.EnsureMediaImportChatAsync" Disabled="@this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner)"/> <AttachDocuments Name="File Attachments" DocumentPaths="@this.ComposerState.FileAttachments" DocumentPathsChanged="@this.ComposerAttachmentsChanged" CatchAllDocuments="true" UseSmallForm="true" ShowMediaStatus="false" Provider="@this.Provider" OwnerChat="@this.ChatThread" EnsureOwnerChatAsync="@this.EnsureMediaImportChatAsync" Disabled="@this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner)"/>
<MudTooltip Text="@T("Show all files attached to this chat")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
<MudIconButton Icon="@Icons.Material.Filled.LibraryBooks" Disabled="@(!this.HasSentFileAttachments)" OnClick="@this.ShowSentFileAttachments"/>
</MudTooltip>
<MudDivider Vertical="true" Style="height: 24px; align-self: center;"/> <MudDivider Vertical="true" Style="height: 24px; align-self: center;"/>
<MudTooltip Text="@T("Bold")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT"> <MudTooltip Text="@T("Bold")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">

View File

@ -673,6 +673,24 @@ public partial class ChatComponent : MSGComponentBase
private bool CanThreadBeCopied => this.CanThreadBeSaved && !this.IsCurrentChatStreaming && !this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner); private bool CanThreadBeCopied => this.CanThreadBeSaved && !this.IsCurrentChatStreaming && !this.MediaTranscriptionService.IsBusy(this.CurrentMediaImportOwner);
/// <summary>
/// The files attached to the messages of this chat which were already sent, each one once.
/// </summary>
/// <remarks>
/// Told apart by their path rather than as records: a file which changed in size between two
/// messages would otherwise appear twice. The draft is left out, because the paperclip right
/// beside the overview already shows it.
/// </remarks>
private HashSet<FileAttachment> SentFileAttachments => this.ChatThread?.Blocks
.Where(block => !block.HideFromUser && block.Content is not null)
.SelectMany(block => block.Content!.FileAttachments)
.DistinctBy(attachment => attachment.FilePath)
.ToHashSet() ?? [];
private bool HasSentFileAttachments => this.ChatThread?.Blocks.Any(block => !block.HideFromUser && block.Content?.FileAttachments.Count > 0) ?? false;
private async Task ShowSentFileAttachments() => await ReviewAttachmentsDialog.OpenDialogAsync(this.DialogService, this.SentFileAttachments, canRemove: false);
private string TooltipAddChatToWorkspace => string.Format(T("Start new chat in workspace '{0}'"), this.currentWorkspaceName); 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; private string UserInputStyle => this.SettingsManager.ConfigurationData.Confidence.ShowProviderConfidence ? this.Provider.UsedLLMProvider.GetConfidence(this.SettingsManager).SetColorStyle(this.SettingsManager) : string.Empty;

View File

@ -9,7 +9,14 @@
Disabled="@this.IsZoneDisabled" Disabled="@this.IsZoneDisabled"
Context="isDropTarget"> Context="isDropTarget">
<MudJustifiedText Typo="Typo.body1" Class="mb-3"> <MudJustifiedText Typo="Typo.body1" Class="mb-3">
@T("Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name. You can remove any attachment using the trash can icon.") @if (this.CanRemove)
{
@T("Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name. You can remove any attachment using the trash can icon.")
}
else
{
@T("Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name.")
}
</MudJustifiedText> </MudJustifiedText>
@if (this.CanAttach) @if (this.CanAttach)
@ -66,11 +73,14 @@
OnClick="@(() => this.InvestigateFile(fileAttachment))"/> OnClick="@(() => this.InvestigateFile(fileAttachment))"/>
</MudTooltip> </MudTooltip>
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom"> @if (this.CanRemove)
<MudIconButton Icon="@Icons.Material.Filled.Delete" {
Color="Color.Error" <MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/> <MudIconButton Icon="@Icons.Material.Filled.Delete"
</MudTooltip> Color="Color.Error"
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
</MudTooltip>
}
</MudToolBar> </MudToolBar>
</MudStack> </MudStack>
} }
@ -93,11 +103,14 @@
Color="Color.Primary" Color="Color.Primary"
Disabled="true"/> Disabled="true"/>
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom"> @if (this.CanRemove)
<MudIconButton Icon="@Icons.Material.Filled.Delete" {
Color="Color.Error" <MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/> <MudIconButton Icon="@Icons.Material.Filled.Delete"
</MudTooltip> Color="Color.Error"
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
</MudTooltip>
}
</MudToolBar> </MudToolBar>
</MudStack> </MudStack>
} }

View File

@ -38,6 +38,16 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
[Parameter] [Parameter]
public Func<bool>? IsAttachingUnavailable { get; set; } public Func<bool>? IsAttachingUnavailable { get; set; }
/// <summary>
/// Whether the user may remove attachments here.
/// </summary>
/// <remarks>
/// False when this dialog gathers the attachments of several messages at once: a removal would
/// reach into a message that was already sent, and nothing here could tell which one.
/// </remarks>
[Parameter]
public bool CanRemove { get; set; } = true;
[Inject] [Inject]
private IDialogService DialogService { get; set; } = null!; private IDialogService DialogService { get; set; } = null!;
@ -120,11 +130,12 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
private async Task PathsDropped(List<string> paths) => await this.AttachPathsAsync(paths); private async Task PathsDropped(List<string> paths) => await this.AttachPathsAsync(paths);
public static async Task<HashSet<FileAttachment>> OpenDialogAsync(IDialogService dialogService, HashSet<FileAttachment> documentPaths, Func<List<string>, Task<IReadOnlyList<FileAttachment>>>? attachPaths = null, Func<bool>? isAttachingUnavailable = null) public static async Task<HashSet<FileAttachment>> OpenDialogAsync(IDialogService dialogService, HashSet<FileAttachment> documentPaths, Func<List<string>, Task<IReadOnlyList<FileAttachment>>>? attachPaths = null, Func<bool>? isAttachingUnavailable = null, bool canRemove = true)
{ {
var dialogParameters = new DialogParameters<ReviewAttachmentsDialog> var dialogParameters = new DialogParameters<ReviewAttachmentsDialog>
{ {
{ x => x.DocumentPaths, documentPaths } { x => x.DocumentPaths, documentPaths },
{ x => x.CanRemove, canRemove },
}; };
if (attachPaths is not null) if (attachPaths is not null)

View File

@ -3672,6 +3672,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T3996190985"] = "{0} von {
-- New disappearing chat -- New disappearing chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "Neuen selbstlöschenden Chat starten" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "Neuen selbstlöschenden Chat starten"
-- Show all files attached to this chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4183453875"] = "Alle an diesen Chat angehängten Dateien anzeigen"
-- Heading -- Heading
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Überschrift" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Überschrift"
@ -7434,6 +7437,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2111340711"] = "De
-- You can drag more files into this window to attach them right away. -- You can drag more files into this window to attach them right away.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "Sie können weitere Dateien in dieses Fenster ziehen, um sie sofort anzuhängen." UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "Sie können weitere Dateien in dieses Fenster ziehen, um sie sofort anzuhängen."
-- Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2713115684"] = "Hier sehen Sie alle angehängten Dateien. Dateien, die nicht mehr gefunden werden können (gelöscht, umbenannt oder verschoben), sind mit einem Warnsymbol und einem durchgestrichenen Namen markiert."
-- Document Preview -- Document Preview
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Dokumentvorschau" UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Dokumentvorschau"

View File

@ -3672,6 +3672,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T3996190985"] = "{0} of {1
-- New disappearing chat -- New disappearing chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "New disappearing chat" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4113970938"] = "New disappearing chat"
-- Show all files attached to this chat
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4183453875"] = "Show all files attached to this chat"
-- Heading -- Heading
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Heading" UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T4231005109"] = "Heading"
@ -7434,6 +7437,9 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2111340711"] = "Th
-- You can drag more files into this window to attach them right away. -- You can drag more files into this window to attach them right away.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "You can drag more files into this window to attach them right away." UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2653077974"] = "You can drag more files into this window to attach them right away."
-- Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name.
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T2713115684"] = "Here you can see all attached files. Files that can no longer be found (deleted, renamed, or moved) are marked with a warning icon and a strikethrough name."
-- Document Preview -- Document Preview
UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Document Preview" UI_TEXT_CONTENT["AISTUDIO::DIALOGS::REVIEWATTACHMENTSDIALOG::T285154968"] = "Document Preview"

View File

@ -1,6 +1,7 @@
# v26.9.1, build 256 (2026-09-xx xx:xx UTC) # v26.9.1, build 256 (2026-09-xx xx:xx UTC)
- Added a way to copy an entire chat, either with the button in the chat toolbar or next to the chat in the chat list. The copy opens right away so you can continue in it, while the original conversation stays exactly as it was. Many thanks to Peer Hogeterp (`peerschuett`) and Jens Erler (`j-erler`) for this feature. - Added a way to copy an entire chat, either with the button in the chat toolbar or next to the chat in the chat list. The copy opens right away so you can continue in it, while the original conversation stays exactly as it was. Many thanks to Peer Hogeterp (`peerschuett`) and Jens Erler (`j-erler`) for this feature.
- Added a way to roll a chat back to an earlier AI response. The response you pick stays, and every message after it is removed permanently, together with the attachments of those messages. - Added a way to roll a chat back to an earlier AI response. The response you pick stays, and every message after it is removed permanently, together with the attachments of those messages.
- Added an overview of all files attached to a chat. The new button next to the paperclip in the chat toolbar lists the files of every message you have sent, grouped by the folder they came from. Files that were moved or deleted since are marked, and for all others you can preview what AI Studio sends to the AI. Each message still shows its own files as before.
- Added a way to save a single code block of an answer. When an answer holds a web page, a LaTeX document, or a Markdown text, the export menu now offers that block as a file of its own. - Added a way to save a single code block of an answer. When an answer holds a web page, a LaTeX document, or a Markdown text, the export menu now offers that block as a file of its own.
- Added tools that AI models can use on their own, starting with Web Search and Read Web Page. When you ask something a model cannot answer from what it knows, it now searches the web, reads the pages it found, and answers with the sources it used. You decide which tools a model may use, right below the message field, and you can watch it work: AI Studio shows which tool is running and, afterward, every call it made with its result. Whether tools are offered at all depends on the model because it has to support them. Read Web Page works right away; for Web Search you pick a search service in the app settings — Tavily or Staan with a free API key, or a SearXNG instance you run yourself. Set up more than one, and they can take turns when one of them finds nothing, or be asked all at once with their results combined. Many thanks to Peer Hogeterp (`peerschuett`) and Nils Kruthoff (`nilskruthoff`) for building this feature. - Added tools that AI models can use on their own, starting with Web Search and Read Web Page. When you ask something a model cannot answer from what it knows, it now searches the web, reads the pages it found, and answers with the sources it used. You decide which tools a model may use, right below the message field, and you can watch it work: AI Studio shows which tool is running and, afterward, every call it made with its result. Whether tools are offered at all depends on the model because it has to support them. Read Web Page works right away; for Web Search you pick a search service in the app settings — Tavily or Staan with a free API key, or a SearXNG instance you run yourself. Set up more than one, and they can take turns when one of them finds nothing, or be asked all at once with their results combined. Many thanks to Peer Hogeterp (`peerschuett`) and Nils Kruthoff (`nilskruthoff`) for building this feature.
- Added answers that appear word by word even while the AI uses its tools. You read along as the model writes, including the short note it puts down before it looks something up, and the answer that follows a tool call arrives the same way instead of all at once at the end. - Added answers that appear word by word even while the AI uses its tools. You read along as the model writes, including the short note it puts down before it looks something up, and the answer that follows a tool call arrives the same way instead of all at once at the end.