mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-04 22:47:21 +00:00
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
98 lines
3.3 KiB
C#
98 lines
3.3 KiB
C#
namespace AIStudio.Components;
|
|
|
|
/// <summary>
|
|
/// Presents the existing exclusion string as two editable groups without losing the other group
|
|
/// or letting delayed parameter echoes overwrite newer edits.
|
|
/// </summary>
|
|
internal sealed class FileExclusionEditorState
|
|
{
|
|
private string? receivedText;
|
|
private readonly HashSet<string> pendingValues = new(StringComparer.Ordinal);
|
|
|
|
public string Text { get; private set; } = string.Empty;
|
|
|
|
public string FolderText { get; private set; } = string.Empty;
|
|
|
|
public string FileText { get; private set; } = string.Empty;
|
|
|
|
public bool IsValid => FileExclusions.IsValidFolders(this.FolderText) && FileExclusions.IsValidFiles(this.FileText);
|
|
|
|
/// <summary>
|
|
/// Takes over the text of the parent, which renders again after every published edit and passes
|
|
/// that edit back, possibly only after the user typed on. Such an echo must not replace the newer
|
|
/// draft; any other text does, e.g., a change by a configuration plugin.
|
|
/// </summary>
|
|
/// <param name="text">The text the parent passes in.</param>
|
|
/// <param name="discardDraft">Whether to take over the text in any case, e.g., while the editor is disabled.</param>
|
|
/// <returns>Whether the text replaced the draft.</returns>
|
|
public bool Receive(string? text, bool discardDraft = false)
|
|
{
|
|
text ??= string.Empty;
|
|
if (discardDraft)
|
|
{
|
|
var changed = !string.Equals(text, this.Text, StringComparison.Ordinal);
|
|
this.receivedText = text;
|
|
this.Reset(text);
|
|
return changed;
|
|
}
|
|
|
|
// The parent passes the same text with every render; only a different one counts:
|
|
if (string.Equals(text, this.receivedText, StringComparison.Ordinal))
|
|
return false;
|
|
|
|
this.receivedText = text;
|
|
|
|
// The parent caught up with the draft. Its renders arrive in order, so no older echo follows:
|
|
if (string.Equals(text, this.Text, StringComparison.Ordinal))
|
|
{
|
|
this.pendingValues.Clear();
|
|
return false;
|
|
}
|
|
|
|
// The echo of an earlier edit, which a later one replaced already:
|
|
if (this.pendingValues.Remove(text))
|
|
return false;
|
|
|
|
this.Reset(text);
|
|
return true;
|
|
}
|
|
|
|
public void Reset(string text)
|
|
{
|
|
this.pendingValues.Clear();
|
|
this.Text = text;
|
|
this.Regroup();
|
|
}
|
|
|
|
public void EditFolders(string? text)
|
|
{
|
|
this.FolderText = text ?? string.Empty;
|
|
this.UpdateText();
|
|
}
|
|
|
|
public void EditFiles(string? text)
|
|
{
|
|
this.FileText = text ?? string.Empty;
|
|
this.UpdateText();
|
|
}
|
|
|
|
public void RestoreFolders(string defaults) => this.EditFolders(FileExclusions.Group(defaults).Folders);
|
|
|
|
public void RestoreFiles(string defaults) => this.EditFiles(FileExclusions.Group(defaults).Files);
|
|
|
|
private void Regroup()
|
|
{
|
|
var groups = FileExclusions.Group(this.Text);
|
|
this.FolderText = groups.Folders;
|
|
this.FileText = groups.Files;
|
|
}
|
|
|
|
private void UpdateText()
|
|
{
|
|
this.Text = string.Join(FileExclusions.ENTRY_SEPARATOR, FileExclusions.Parse(this.FolderText)
|
|
.Concat(FileExclusions.Parse(this.FileText))
|
|
.Distinct(StringComparer.OrdinalIgnoreCase));
|
|
this.pendingValues.Add(this.Text);
|
|
}
|
|
}
|