mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-10 21:47:21 +00:00
Added an overview of all files attached to a chat (#1002)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
31862f5ecd
commit
9d1768e2f4
10 files changed
+281
-15
No files matched your search
@@ -9,7 +9,14 @@
|
||||
Disabled="@this.IsZoneDisabled"
|
||||
Context="isDropTarget">
|
||||
<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>
|
||||
|
||||
@if (this.CanAttach)
|
||||
@@ -31,8 +38,10 @@
|
||||
|
||||
@{
|
||||
var currentFolder = string.Empty;
|
||||
var pathsWithSeveralVersions = this.PathsWithSeveralVersions;
|
||||
foreach (var fileAttachment in this.OrderedAttachments)
|
||||
{
|
||||
var versionLabel = this.VersionLabel(fileAttachment, pathsWithSeveralVersions);
|
||||
var folderPath = Path.GetDirectoryName(fileAttachment.FilePath);
|
||||
if (folderPath != currentFolder)
|
||||
{
|
||||
@@ -55,6 +64,12 @@
|
||||
<MudText Style="white-space: nowrap;">
|
||||
@fileAttachment.FileName
|
||||
</MudText>
|
||||
@if (versionLabel is not null)
|
||||
{
|
||||
<MudText Typo="Typo.body2" Class="ml-2 mud-text-secondary" Style="white-space: nowrap;">
|
||||
@versionLabel
|
||||
</MudText>
|
||||
}
|
||||
</span>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
@@ -66,11 +81,14 @@
|
||||
OnClick="@(() => this.InvestigateFile(fileAttachment))"/>
|
||||
</MudTooltip>
|
||||
|
||||
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Error"
|
||||
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
|
||||
</MudTooltip>
|
||||
@if (this.CanRemove)
|
||||
{
|
||||
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Error"
|
||||
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudToolBar>
|
||||
</MudStack>
|
||||
}
|
||||
@@ -84,6 +102,12 @@
|
||||
<MudText Style="white-space: nowrap;">
|
||||
<s>@fileAttachment.FileName</s>
|
||||
</MudText>
|
||||
@if (versionLabel is not null)
|
||||
{
|
||||
<MudText Typo="Typo.body2" Class="ml-2 mud-text-secondary" Style="white-space: nowrap;">
|
||||
@versionLabel
|
||||
</MudText>
|
||||
}
|
||||
</span>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
@@ -105,11 +129,14 @@
|
||||
Disabled="true"/>
|
||||
}
|
||||
|
||||
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Error"
|
||||
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
|
||||
</MudTooltip>
|
||||
@if (this.CanRemove)
|
||||
{
|
||||
<MudTooltip Text="@T("Remove this attachment.")" Placement="Placement.Bottom">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Error"
|
||||
OnClick="@(() => this.DeleteAttachment(fileAttachment))"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
</MudToolBar>
|
||||
</MudStack>
|
||||
}
|
||||
|
||||
@@ -47,6 +47,16 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
|
||||
[Parameter]
|
||||
public Func<FileAttachment, string, FileVersion, Task>? KeepReadText { 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]
|
||||
private IDialogService DialogService { get; set; } = null!;
|
||||
|
||||
@@ -83,7 +93,7 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The attachments, sorted by their folder and, within it, by their file name.
|
||||
/// The attachments, sorted by their folder and, within it, by their file name, the latest version of a file first.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The list below starts a new heading whenever the folder changes from one attachment to the
|
||||
@@ -95,7 +105,37 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
|
||||
/// </remarks>
|
||||
private IEnumerable<FileAttachment> OrderedAttachments => this.DocumentPaths
|
||||
.OrderBy(attachment => Path.GetDirectoryName(attachment.FilePath) ?? string.Empty, StringComparer.OrdinalIgnoreCase)
|
||||
.ThenBy(attachment => attachment.FileName, StringComparer.OrdinalIgnoreCase);
|
||||
.ThenBy(attachment => attachment.FileName, StringComparer.OrdinalIgnoreCase)
|
||||
.ThenByDescending(attachment => attachment.Version?.LastWriteUtc);
|
||||
|
||||
/// <summary>
|
||||
/// The paths which the list holds more than once, i.e., the files which were sent in several versions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only the overview of all files of a chat holds a file more than once, see
|
||||
/// ChatThread.CollectSentFileAttachments: the draft and a single message hold each file once, see
|
||||
/// SetFileAttachmentExtensions.AttachInPlaceOfSameFile. The other uses of this dialog therefore
|
||||
/// stay as they were. Asked once for each rendering, not once for each attachment.
|
||||
/// </remarks>
|
||||
private IReadOnlySet<string> PathsWithSeveralVersions => this.DocumentPaths
|
||||
.GroupBy(attachment => attachment.FilePath)
|
||||
.Where(group => group.Count() > 1)
|
||||
.Select(group => group.Key)
|
||||
.ToHashSet();
|
||||
|
||||
/// <summary>
|
||||
/// Tells apart the versions of a file which the list holds more than once, by the time their file was saved.
|
||||
/// </summary>
|
||||
/// <param name="attachment">The attachment.</param>
|
||||
/// <param name="pathsWithSeveralVersions">The paths which the list holds more than once, see PathsWithSeveralVersions.</param>
|
||||
/// <returns>The label, or null for a file listed once, and for a version whose state AI Studio did not note.</returns>
|
||||
private string? VersionLabel(FileAttachment attachment, IReadOnlySet<string> pathsWithSeveralVersions)
|
||||
{
|
||||
if (attachment.Version is not { } version || !pathsWithSeveralVersions.Contains(attachment.FilePath))
|
||||
return null;
|
||||
|
||||
return string.Format(T("Version from {0}"), CommonTools.FormatTimestampToGeneral(version.LastWriteUtc.ToLocalTime(), I18N.I.Culture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches what the user dropped onto this dialog and answers which files that became.
|
||||
@@ -129,11 +169,12 @@ public partial class ReviewAttachmentsDialog : MSGComponentBase
|
||||
|
||||
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, Func<FileAttachment, string, FileVersion, Task>? keepReadText = 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, Func<FileAttachment, string, FileVersion, Task>? keepReadText = null, bool canRemove = true)
|
||||
{
|
||||
var dialogParameters = new DialogParameters<ReviewAttachmentsDialog>
|
||||
{
|
||||
{ x => x.DocumentPaths, documentPaths }
|
||||
{ x => x.DocumentPaths, documentPaths },
|
||||
{ x => x.CanRemove, canRemove },
|
||||
};
|
||||
|
||||
if (attachPaths is not null)
|
||||
|
||||
Reference in new issue
Block a user