Added a warning when files are removed from the source material

This commit is contained in:
Thorsten Sommer 2026-08-02 16:08:23 +02:00
parent 2707da7ac5
commit dc71c2ba0b
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
6 changed files with 39 additions and 14 deletions

View File

@ -2356,6 +2356,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::
-- Documents, spreadsheets, images, audio, and video are considered as source context.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2228157968"] = "Documents, spreadsheets, images, audio, and video are considered as source context."
-- These files are already attached as visual assets and were removed from the source material: {0}
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2271225937"] = "These files are already attached as visual assets and were removed from the source material: {0}"
-- Target language
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T237828418"] = "Target language"

View File

@ -122,7 +122,7 @@
<AttachDocuments Name="Visual briefing source material"
Layer="@DropLayers.ASSISTANTS"
@bind-DocumentPaths="@this.editor.SourceMaterial"
OnChange="@this.SourceMaterialChangedAsync"
OnChange="@this.EnforceSourceExclusivityAsync"
CatchAllDocuments="true"
UseSmallForm="false"
Provider="@this.editor.Provider"
@ -136,7 +136,7 @@
<AttachDocuments Name="Visual briefing visual assets"
Layer="@DropLayers.ASSISTANTS"
@bind-DocumentPaths="@this.editor.VisualAssets"
OnChange="@this.VisualAssetsChangedAsync"
OnChange="@this.EnforceSourceExclusivityAsync"
CatchAllDocuments="false"
UseSmallForm="false"
AllowedFileTypes="@(new[] { FileTypes.VISUAL_BRIEFING_IMAGE })"

View File

@ -16,22 +16,32 @@ public partial class VisualBriefingAssistant
: MediaImportOwner.ForVisualBriefing(this.selectedBriefing.BriefingId);
/// <summary>
/// Defines <c>SourceMaterialChangedAsync</c> for the visual briefing feature.
/// Keeps source material and visual assets mutually exclusive after either list changed.
/// </summary>
private async Task SourceMaterialChangedAsync(HashSet<FileAttachment> _)
/// <remarks>
/// A file is either source material or a visual asset, never both: visual assets have to appear in
/// the briefing, while source material only feeds the analysis. Visual assets win, so the overlap is
/// always resolved on the source-material side. Both attachment controls route here because either
/// one can create the overlap — the source-material control catches all document kinds, including
/// the image types the visual-asset control is limited to. The warning matters because the file
/// would otherwise vanish from the source-material list without any explanation, possibly leaving
/// the briefing without the source material it requires.
/// </remarks>
/// <param name="_">The changed attachment set. It is ignored because both lists are inspected anyway.</param>
private async Task EnforceSourceExclusivityAsync(HashSet<FileAttachment> _)
{
var visualPaths = this.editor.VisualAssets.Select(attachment => attachment.FilePath).ToHashSet(PathComparer());
this.editor.SourceMaterial.RemoveWhere(attachment => visualPaths.Contains(attachment.FilePath));
await this.SaveCurrentAsync(reload: true);
}
var displaced = this.editor.SourceMaterial.Where(attachment => visualPaths.Contains(attachment.FilePath)).ToArray();
if (displaced.Length > 0)
{
this.editor.SourceMaterial.ExceptWith(displaced);
await this.MessageBus.SendWarning(new(
Icons.Material.Filled.Warning,
string.Format(
T("These files are already attached as visual assets and were removed from the source material: {0}"),
string.Join(", ", displaced.Select(attachment => Path.GetFileName(attachment.FilePath))))));
}
/// <summary>
/// Defines <c>VisualAssetsChangedAsync</c> for the visual briefing feature.
/// </summary>
private async Task VisualAssetsChangedAsync(HashSet<FileAttachment> _)
{
var visualPaths = this.editor.VisualAssets.Select(attachment => attachment.FilePath).ToHashSet(PathComparer());
this.editor.SourceMaterial.RemoveWhere(attachment => visualPaths.Contains(attachment.FilePath));
await this.SaveCurrentAsync(reload: true);
}

View File

@ -7,6 +7,12 @@ namespace AIStudio.Assistants.VisualBriefing;
public partial class VisualBriefingAssistant
{
/// <summary>Gets whether the briefing contains at least one actual source-material file.</summary>
/// <remarks>
/// This deliberately reads the stored manifest instead of the editor state: a build always runs
/// against what the store accepted, and the store drops attachments whose file disappeared before
/// the save. Every path that changes sources therefore has to save with a reload, otherwise this
/// check keeps reporting the state from before the change.
/// </remarks>
private bool HasSourceMaterial => this.selectedBriefing?.Sources.Any(source => source.Kind is VisualBriefingSourceKind.SOURCE_MATERIAL) == true;
/// <summary>Gets all current field, source, and revision issues shown below the actions.</summary>

View File

@ -2358,6 +2358,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::
-- Documents, spreadsheets, images, audio, and video are considered as source context.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2228157968"] = "Dokumente, Tabellenkalkulationen, Bilder, Audio- und Videodateien werden als Ausgangsmaterial berücksichtigt."
-- These files are already attached as visual assets and were removed from the source material: {0}
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2271225937"] = "Diese Dateien sind bereits als visuelle Elemente angehängt und wurden aus dem Ausgangsmaterial entfernt: {0}"
-- Target language
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T237828418"] = "Zielsprache"

View File

@ -2358,6 +2358,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::
-- Documents, spreadsheets, images, audio, and video are considered as source context.
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2228157968"] = "Documents, spreadsheets, images, audio, and video are considered as source context."
-- These files are already attached as visual assets and were removed from the source material: {0}
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T2271225937"] = "These files are already attached as visual assets and were removed from the source material: {0}"
-- Target language
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::VISUALBRIEFING::VISUALBRIEFINGASSISTANT::T237828418"] = "Target language"