Upgraded to MudBlazor 9 (#1137)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-10-31 10:48:20 +01:00
1 parent e0337a99bc
commit aeba1fbccc
625 files changed
+408 -882

No files matched your search

@@ -46,7 +46,7 @@
@ref="@this.inputField"
@bind-Text="@this.UserInput"
Variant="Variant.Outlined"
AutoGrow="@true"
Sizing="InputSizing.Auto"
Lines="3"
MaxLines="12"
Label="@this.InputLabel"
@@ -6,13 +6,13 @@
<ActivatorContent>
@if (this.CurrentChatTemplate != ChatTemplate.NO_CHAT_TEMPLATE)
{
<MudButton IconSize="Size.Large" StartIcon="@this.ChatTemplateIcon(this.CurrentChatTemplate)" IconColor="Color.Default">
<MudButton IconSize="Size.Large" StartIcon="@this.ChatTemplateIcon(this.CurrentChatTemplate)" IconColor="Color.Default" OnClick="@context.ToggleAsync">
@this.CurrentChatTemplate.GetSafeName()
</MudButton>
}
else
{
<MudIconButton Icon="@Icons.Material.Filled.RateReview" />
<MudIconButton Icon="@Icons.Material.Filled.RateReview" OnClick="@context.ToggleAsync" />
}
</ActivatorContent>
<ChildContent>
@@ -1,4 +1,4 @@
<MudTabs ActivePanelIndex="this.SelectedIndex" ActivePanelIndexChanged="async idx => await this.TabChanged(idx)" PanelClass="code-block mt-1" MinimumTabWidth="30px" Class="mt-2">
<MudTabs ActivePanelIndex="this.SelectedIndex" ActivePanelIndexChanged="async idx => await this.TabChanged(idx)" TabPanelsClass="code-block mt-1" MinimumTabWidth="30px" Class="mt-2">
@foreach (var block in this.blocks)
{
<MudTabPanel Text="@block.Title">
@@ -79,10 +79,10 @@ public partial class ConfigurationDirectory : ConfigurationBaseCore
#endregion
private void InternalUpdate(string text)
private void InternalUpdate(string? text)
{
this.timer.Stop();
this.internalText = text;
this.internalText = text ?? string.Empty;
this.timer.Start();
}
@@ -85,10 +85,10 @@ public partial class ConfigurationFile : ConfigurationBaseCore
#endregion
private void InternalUpdate(string text)
private void InternalUpdate(string? text)
{
this.timer.Stop();
this.internalText = text;
this.internalText = text ?? string.Empty;
this.timer.Start();
}
@@ -53,8 +53,12 @@ public partial class ConfigurationSelect<TConfig> : ConfigurationBaseCore
#endregion
private async Task OptionChanged(TConfig updatedValue)
private async Task OptionChanged(TConfig? updatedValue)
{
// The select hands out null only when it has no value at all, which leaves nothing to store:
if (updatedValue is null)
return;
this.SelectionUpdate(updatedValue);
await this.SelectionUpdateAsync(updatedValue);
await this.SettingsManager.StoreSettings();
@@ -12,7 +12,7 @@
AdornmentColor="@this.IconColor"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
Lines="@this.NumLines"
AutoGrow="@this.AutoGrow"
Sizing="@this.Sizing"
MaxLines="@this.GetMaxLines"
Class="@this.InputClass"
Immediate="@true"
@@ -36,7 +36,7 @@ else
AdornmentColor="@this.IconColor"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
Lines="@this.NumLines"
AutoGrow="@this.AutoGrow"
Sizing="@this.Sizing"
MaxLines="@this.GetMaxLines"
Class="@this.InputClass"
Immediate="@true"
@@ -128,7 +128,9 @@ public partial class ConfigurationText : ConfigurationBaseCore
#endregion
private bool AutoGrow => this.ExpandToContent || this.NumLines > 1;
private InputSizing Sizing => this.AutoGrow ? InputSizing.Auto : InputSizing.Fixed;
private int GetMaxLines => this.ExpandToContent ? FilePatternSelection.MAX_FIELD_LINES : this.AutoGrow ? this.MaxLines : 1;
private string InputClass => this.ExpandToContent ? "pattern-text-field" : string.Empty;
@@ -139,13 +141,13 @@ public partial class ConfigurationText : ConfigurationBaseCore
//
private Adornment IconAdornment => this.NumLines == 1 ? Adornment.Start : Adornment.None;
protected void InternalUpdate(string text)
protected void InternalUpdate(string? text)
{
if (this.IsDisabled)
return;
this.timer.Stop();
this.internalText = text;
this.internalText = text ?? string.Empty;
this.timer.Start();
}
@@ -1,7 +1,7 @@
@using AIStudio.Tools.ChatArchive
@inherits MSGComponentBase
<MudTabs Elevation="0" Rounded="@true" ApplyEffectsToContainer="@true" Outlined="@true" PanelClass="pa-4">
<MudTabs Elevation="0" Rounded="@true" ApplyEffectsToContainer="@true" Outlined="@true" TabPanelsClass="pa-4">
<MudTabPanel Text="@T("Back up")" Icon="@Icons.Material.Filled.Archive" Disabled="@(this.isBusy || this.DataRestoreService.IsPreparing)">
<MudText Typo="Typo.body1" Class="mb-3">
@@ -206,7 +206,7 @@ public partial class DataSourceManagement : MSGComponentBase
if (eriDataSource.AuthMethod is AuthMethod.KERBEROS)
{
await this.DialogService.ShowMessageBox(
await this.DialogService.ShowMessageBoxAsync(
T("Export ERI Data Source"),
T("Kerberos/SSO ERI data sources cannot be exported yet. Please configure them manually in the configuration plugin."),
T("Close"));
@@ -226,7 +226,7 @@ public partial class DataSourceManagement : MSGComponentBase
var secretResponse = await this.RustService.GetSecret(eriDataSource, SecretStoreType.DATA_SOURCE, isTrying: true);
if (!secretResponse.Success)
{
await this.DialogService.ShowMessageBox(
await this.DialogService.ShowMessageBoxAsync(
T("Export ERI Data Source"),
string.Format(T("Cannot export this ERI data source because no authentication secret is configured. The issue was: {0}"), secretResponse.Issue),
T("Close"));
@@ -236,7 +236,7 @@ public partial class DataSourceManagement : MSGComponentBase
var encryption = PluginFactory.EnterpriseEncryption;
if (encryption?.IsAvailable != true)
{
await this.DialogService.ShowMessageBox(
await this.DialogService.ShowMessageBoxAsync(
T("Export ERI Data Source"),
T("Cannot export this ERI data source because no enterprise encryption secret is configured."),
T("Close"));
@@ -274,7 +274,7 @@ public partial class DataSourceManagement : MSGComponentBase
var decryptedSecret = await secretResponse.Secret.Decrypt(Program.ENCRYPTION);
if (!encryption.TryEncrypt(decryptedSecret, this.SettingsManager.ConfigurationData.App.EnterpriseEncryptionExportFormat, out var encryptedSecret))
{
await this.DialogService.ShowMessageBox(
await this.DialogService.ShowMessageBoxAsync(
T("Export ERI Data Source"),
T("Cannot export this ERI data source because the authentication secret could not be encrypted."),
T("Close"));
@@ -353,7 +353,7 @@ public partial class DataSourceManagement : MSGComponentBase
if (!this.DataSourceEmbeddingService.IsIndexingPaused)
return false;
await this.DialogService.ShowMessageBox(title, T("AI Studio is backing up or restoring the indexes of your data sources right now. Please try again once that is done."), T("Close"));
await this.DialogService.ShowMessageBoxAsync(title, T("AI Studio is backing up or restoring the indexes of your data sources right now. Please try again once that is done."), T("Close"));
return true;
}
@@ -413,7 +413,7 @@ public partial class DataSourceManagement : MSGComponentBase
var deleteSecretResponse = await this.RustService.DeleteSecret(mailbox, SecretStoreType.DATA_SOURCE);
if (!deleteSecretResponse.Success)
{
await this.DialogService.ShowMessageBox(
await this.DialogService.ShowMessageBoxAsync(
T("Delete Mailbox"),
string.Format(T("The password of this mailbox could not be deleted from the operating system, so the mailbox was kept. The issue was: {0}"), deleteSecretResponse.Issue),
T("Close"));
@@ -1,3 +1,3 @@
@inherits MudComponentBase
<MudTextField T="string" Disabled="@this.Disabled" Text="@this.text" TextChanged="@this.OnTextChanged" Validation="@this.ValidationFunc" Label="@this.Label" Variant="Variant.Outlined" Lines="@this.Lines" MaxLines="@this.MaxLines" AutoGrow="@(this.MaxLines > this.Lines)" Margin="Margin.Dense" UserAttributes="@this.Attributes" HelperText="@this.HelpText" Placeholder="@this.Placeholder" Class="mb-3" Immediate="true" Adornment="Adornment.Start" AdornmentIcon="@this.Icon"/>
<MudTextField T="string" Disabled="@this.Disabled" Text="@this.text" TextChanged="@this.OnTextChanged" Validation="@this.ValidationFunc" Label="@this.Label" Variant="Variant.Outlined" Lines="@this.Lines" MaxLines="@this.MaxLines" Sizing="@(this.MaxLines > this.Lines ? InputSizing.Auto : InputSizing.Fixed)" Margin="Margin.Dense" UserAttributes="@this.Attributes" HelperText="@this.HelpText" Placeholder="@this.Placeholder" Class="mb-3" Immediate="true" Adornment="Adornment.Start" AdornmentIcon="@this.Icon"/>
@@ -97,9 +97,9 @@ public partial class DebouncedTextField : MudComponentBase, IDisposable
#endregion
private void OnTextChanged(string value)
private void OnTextChanged(string? value)
{
this.text = value;
this.text = value ?? string.Empty;
this.debounceTimer.Stop();
this.debounceTimer.Start();
}
@@ -60,10 +60,10 @@ public partial class DirectChatLauncherForm : MSGComponentBase
/// The data sources the chat starts with. An empty selection keeps the normal chat defaults.
/// </summary>
[Parameter]
public IEnumerable<string> DataSourceIds { get; set; } = [];
public IReadOnlyCollection<string> DataSourceIds { get; set; } = [];
[Parameter]
public EventCallback<IEnumerable<string>> DataSourceIdsChanged { get; set; }
public EventCallback<IReadOnlyCollection<string>> DataSourceIdsChanged { get; set; }
/// <summary>
/// The tools preselected for the chat. An empty selection keeps the normal chat defaults.
@@ -102,29 +102,29 @@ public partial class DirectChatLauncherForm : MSGComponentBase
await this.WorkspaceNameChanged.InvokeAsync(workspaceName);
}
private async Task SetProviderId(string providerId)
private async Task SetProviderId(string? providerId)
{
this.ProviderId = providerId;
await this.ProviderIdChanged.InvokeAsync(providerId);
this.ProviderId = providerId ?? string.Empty;
await this.ProviderIdChanged.InvokeAsync(this.ProviderId);
}
private async Task SetProfileId(string profileId)
private async Task SetProfileId(string? profileId)
{
this.ProfileId = profileId;
await this.ProfileIdChanged.InvokeAsync(profileId);
this.ProfileId = profileId ?? string.Empty;
await this.ProfileIdChanged.InvokeAsync(this.ProfileId);
}
private async Task SetChatTemplateId(string chatTemplateId)
private async Task SetChatTemplateId(string? chatTemplateId)
{
this.ChatTemplateId = chatTemplateId;
await this.ChatTemplateIdChanged.InvokeAsync(chatTemplateId);
this.ChatTemplateId = chatTemplateId ?? string.Empty;
await this.ChatTemplateIdChanged.InvokeAsync(this.ChatTemplateId);
}
//
// MudSelect hands out its selection as a lazy sequence of nullable strings. We materialize it
// once and drop empty entries, so the host always receives a stable list of usable IDs:
// MudSelect hands out its selection as a collection of nullable strings. We copy it and drop
// empty entries, so the host always receives a stable list of usable IDs:
//
private async Task SetDataSourceIds(IEnumerable<string?>? dataSourceIds)
private async Task SetDataSourceIds(IReadOnlyCollection<string?>? dataSourceIds)
{
var selectedDataSourceIds = dataSourceIds is null ? [] : dataSourceIds.Where(id => !string.IsNullOrWhiteSpace(id)).Select(id => id!).ToArray();
@@ -138,7 +138,7 @@ public partial class DirectChatLauncherForm : MSGComponentBase
await this.ToolIdsChanged.InvokeAsync(toolIds);
}
private string GetSelectedDataSourceText(List<string?>? selectedValues)
private string GetSelectedDataSourceText(IReadOnlyList<string?>? selectedValues)
{
if (selectedValues is null || selectedValues.Count == 0)
return T("Use the normal chat data source defaults");
@@ -62,8 +62,9 @@ namespace AIStudio.Components
[Parameter]
public string Style { get; set; } = string.Empty;
private async Task OnValueChanged(string newValue)
private async Task OnValueChanged(string? changedValue)
{
var newValue = changedValue ?? string.Empty;
if (this.Value != newValue)
{
this.Value = newValue;
@@ -97,7 +98,7 @@ namespace AIStudio.Components
return [this.Default, .. items];
}
private string GetMultiSelectionText(List<string?>? selectedValues)
private string GetMultiSelectionText(IReadOnlyList<string?>? selectedValues)
{
if (selectedValues is null || selectedValues.Count == 0)
return this.Default.Display;
@@ -80,9 +80,9 @@ public partial class EnumSelection<T> : EnumSelectionBase where T : struct, Enum
await this.SelectionUpdated(value);
}
private async Task OtherValueChanged(string value)
private async Task OtherValueChanged(string? value)
{
await this.OtherInputChanged.InvokeAsync(value);
await this.OtherInputChanged.InvokeAsync(value ?? string.Empty);
await this.SelectionUpdated(this.Value);
}
}
@@ -12,8 +12,8 @@
</MudStack>
<MudStack Spacing="1">
<MudTextField T="string" InputId="@this.folderInputId" Text="@this.state.FolderText" TextChanged="@this.ChangeFoldersAsync" Immediate="@true" Disabled="@this.Disabled" Label="@T("Folders")" Lines="1" AutoGrow="@true" MaxLines="@FilePatternSelection.MAX_FIELD_LINES" Class="pattern-text-field" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@FileExclusions.ValidateFolders" UserAttributes="@INPUT_ATTRIBUTES" Placeholder="node_modules/;bin/;cmake-build-*/" Adornment="@(this.ShowReset ? Adornment.End : Adornment.None)" AdornmentIcon="@Icons.Material.Filled.Restore" OnAdornmentClick="@(() => this.RestoreDefaultsAsync(true))" AdornmentAriaLabel="@this.FolderRestoreLabel"/>
<MudTextField T="string" InputId="@this.fileInputId" Text="@this.state.FileText" TextChanged="@this.ChangeFilesAsync" Immediate="@true" Disabled="@this.Disabled" Label="@T("Files")" Lines="1" AutoGrow="@true" MaxLines="@FilePatternSelection.MAX_FIELD_LINES" Class="pattern-text-field" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@FileExclusions.ValidateFiles" UserAttributes="@INPUT_ATTRIBUTES" Placeholder="*.min.js;*.webm;draft-*" Adornment="@(this.ShowReset ? Adornment.End : Adornment.None)" AdornmentIcon="@Icons.Material.Filled.Restore" OnAdornmentClick="@(() => this.RestoreDefaultsAsync(false))" AdornmentAriaLabel="@this.FileRestoreLabel"/>
<MudTextField T="string" InputId="@this.folderInputId" Text="@this.state.FolderText" TextChanged="@this.ChangeFoldersAsync" Immediate="@true" Disabled="@this.Disabled" Label="@T("Folders")" Lines="1" Sizing="InputSizing.Auto" MaxLines="@FilePatternSelection.MAX_FIELD_LINES" Class="pattern-text-field" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@FileExclusions.ValidateFolders" UserAttributes="@INPUT_ATTRIBUTES" Placeholder="node_modules/;bin/;cmake-build-*/" Adornment="@(this.ShowReset ? Adornment.End : Adornment.None)" AdornmentIcon="@Icons.Material.Filled.Restore" OnAdornmentClick="@(() => this.RestoreDefaultsAsync(true))" AdornmentAriaLabel="@this.FolderRestoreLabel"/>
<MudTextField T="string" InputId="@this.fileInputId" Text="@this.state.FileText" TextChanged="@this.ChangeFilesAsync" Immediate="@true" Disabled="@this.Disabled" Label="@T("Files")" Lines="1" Sizing="InputSizing.Auto" MaxLines="@FilePatternSelection.MAX_FIELD_LINES" Class="pattern-text-field" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@FileExclusions.ValidateFiles" UserAttributes="@INPUT_ATTRIBUTES" Placeholder="*.min.js;*.webm;draft-*" Adornment="@(this.ShowReset ? Adornment.End : Adornment.None)" AdornmentIcon="@Icons.Material.Filled.Restore" OnAdornmentClick="@(() => this.RestoreDefaultsAsync(false))" AdornmentAriaLabel="@this.FileRestoreLabel"/>
</MudStack>
<MudText Typo="Typo.caption" Class="mud-text-secondary mt-1">@T("These files and folders are left out, even when a file pattern selects them. Separate entries with a semicolon or a line break. End an entry with a slash to exclude every folder of that name, e.g., node_modules/.")</MudText>
@@ -70,9 +70,9 @@ public partial class FileExclusionEditor : MSGComponentBase
base.OnParametersSet();
}
protected Task ChangeFoldersAsync(string text) => this.ChangePatternsAsync(text, folders: true);
protected Task ChangeFoldersAsync(string? text) => this.ChangePatternsAsync(text ?? string.Empty, folders: true);
protected Task ChangeFilesAsync(string text) => this.ChangePatternsAsync(text, folders: false);
protected Task ChangeFilesAsync(string? text) => this.ChangePatternsAsync(text ?? string.Empty, folders: false);
private async Task ChangePatternsAsync(string text, bool folders)
{
@@ -24,10 +24,10 @@ public partial class ProfileFormSelection : MSGComponentBase
[Inject]
public IDialogService DialogService { get; init; } = null!;
private async Task SelectionChanged(Profile profile)
private async Task SelectionChanged(Profile? profile)
{
this.Profile = profile;
await this.ProfileChanged.InvokeAsync(profile);
this.Profile = profile ?? Profile.NO_PROFILE;
await this.ProfileChanged.InvokeAsync(this.Profile);
}
private async Task OpenSettingsDialog()
@@ -5,13 +5,13 @@
<ActivatorContent>
@if (this.CurrentProfile != Profile.NO_PROFILE)
{
<MudButton IconSize="Size.Large" StartIcon="@Icons.Material.Filled.Person4" IconColor="Color.Default">
<MudButton IconSize="Size.Large" StartIcon="@Icons.Material.Filled.Person4" IconColor="Color.Default" OnClick="@context.ToggleAsync">
@this.CurrentProfile.GetSafeName()
</MudButton>
}
else
{
<MudIconButton Icon="@Icons.Material.Filled.Person4" Color="Color.Default" />
<MudIconButton Icon="@Icons.Material.Filled.Person4" Color="Color.Default" OnClick="@context.ToggleAsync" />
}
</ActivatorContent>
<ChildContent>
@@ -57,13 +57,13 @@ public partial class ProviderSelection : MSGComponentBase
#endregion
private async Task SelectionChanged(AIStudio.Settings.Provider provider)
private async Task SelectionChanged(AIStudio.Settings.Provider? provider)
{
if (this.Disabled)
return;
this.ProviderSettings = provider;
await this.ProviderSettingsChanged.InvokeAsync(provider);
this.ProviderSettings = provider ?? AIStudio.Settings.Provider.NONE;
await this.ProviderSettingsChanged.InvokeAsync(this.ProviderSettings);
}
private IEnumerable<ProviderSelectionItem> GetAvailableProviderSelectionItems()
@@ -247,9 +247,9 @@ public partial class ReadWebContent : MSGComponentBase
/// </remarks>
private bool UrlIsValid => this.ValidateURL(this.URL) is null;
private async Task URLValueChanged(string url)
private async Task URLValueChanged(string? url)
{
await this.URLChanged.InvokeAsync(url);
await this.URLChanged.InvokeAsync(url ?? string.Empty);
}
private async Task ShowWebContentReaderChanged(bool state)
@@ -44,10 +44,10 @@ public partial class SecretInputField : MSGComponentBase
private string ToggleVisibilityTooltip => this.isSecretVisible ? T("Hide content") : T("Show content");
private Task OnSecretChanged(string arg)
private Task OnSecretChanged(string? arg)
{
this.Secret = arg;
return this.SecretChanged.InvokeAsync(arg);
this.Secret = arg ?? string.Empty;
return this.SecretChanged.InvokeAsync(this.Secret);
}
private void ToggleVisibility() => this.isSecretVisible = !this.isSecretVisible;
@@ -210,20 +210,20 @@ public partial class SettingsPanelEmbeddings : SettingsPanelProviderBase
// sentence below, which used to be the same one for a missing API key, an unreachable
// provider and a provider which cannot embed anything at all:
//
await this.DialogService.ShowMessageBox(T("Embedding Result"), exception.UserMessage, T("Close"));
await this.DialogService.ShowMessageBoxAsync(T("Embedding Result"), exception.UserMessage, T("Close"));
return;
}
if (embeddings.Count == 0)
{
await this.DialogService.ShowMessageBox(T("Embedding Result"), T("No embedding was returned."), T("Close"));
await this.DialogService.ShowMessageBoxAsync(T("Embedding Result"), T("No embedding was returned."), T("Close"));
return;
}
var vector = embeddings.FirstOrDefault();
if (vector is null || vector.Count == 0)
{
await this.DialogService.ShowMessageBox(T("Embedding Result"), T("No embedding was returned."), T("Close"));
await this.DialogService.ShowMessageBoxAsync(T("Embedding Result"), T("No embedding was returned."), T("Close"));
return;
}
@@ -9,7 +9,7 @@
Margin="Margin.Dense"
Lines="@this.Lines"
MaxLines="@this.MaxLines"
AutoGrow="@true"
Sizing="InputSizing.Auto"
Adornment="@(string.IsNullOrEmpty(this.Icon) ? Adornment.None : Adornment.Start)"
AdornmentIcon="@this.Icon"
Style="@this.GetColor()"
@@ -91,7 +91,7 @@ public partial class WorkspaceNameField : MSGComponentBase
// Picking an existing workspace fills the name field. Clearing the select must not wipe a name
// the user typed, though, so an empty selection is ignored:
//
private async Task SelectExistingWorkspace(string workspaceName)
private async Task SelectExistingWorkspace(string? workspaceName)
{
if (string.IsNullOrWhiteSpace(workspaceName))
return;
@@ -99,9 +99,9 @@ public partial class WorkspaceNameField : MSGComponentBase
await this.SetWorkspaceName(workspaceName);
}
private async Task SetWorkspaceName(string workspaceName)
private async Task SetWorkspaceName(string? workspaceName)
{
this.WorkspaceName = workspaceName;
await this.WorkspaceNameChanged.InvokeAsync(workspaceName);
this.WorkspaceName = workspaceName ?? string.Empty;
await this.WorkspaceNameChanged.InvokeAsync(this.WorkspaceName);
}
}
@@ -54,7 +54,7 @@ else
case TreeItemData treeItem:
@if (treeItem.Type is TreeItemType.LOADING)
{
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@false" Items="@(treeItem.Children!)">
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@false" Items="@treeItem.Children">
<BodyContent>
<MudSkeleton Width="85%" Height="22px"/>
</BodyContent>
@@ -62,7 +62,7 @@ else
}
else if (treeItem.Type is TreeItemType.CHAT)
{
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@(treeItem.Children!)" OnClick="@(() => this.LoadChatAsync(treeItem.Path, true))">
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="@(() => this.LoadChatAsync(treeItem.Path, true))">
<BodyContent>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<MudText Style="@this.GetChatTreeItemTextStyle(treeItem)">
@@ -99,7 +99,7 @@ else
}
else if (treeItem.Type is TreeItemType.WORKSPACE)
{
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@(treeItem.Children!)" OnClick="@(() => this.OnWorkspaceClicked(treeItem))">
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children" OnClick="@(() => this.OnWorkspaceClicked(treeItem))">
<BodyContent>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<MudText Style="justify-self: start;">
@@ -127,7 +127,7 @@ else
}
else
{
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@(treeItem.Children!)">
<MudTreeViewItem T="ITreeItem" Icon="@this.GetTreeItemIcon(treeItem)" Value="@item.Value" Expanded="@item.Expanded" CanExpand="@treeItem.Expandable" Items="@treeItem.Children">
<BodyContent>
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
<MudText Style="justify-self: start;">
@@ -536,9 +536,9 @@ public partial class Workspaces : MSGComponentBase
}
}
private async Task OnSearchTextChanged(string value)
private async Task OnSearchTextChanged(string? value)
{
this.searchText = value;
this.searchText = value ?? string.Empty;
if (string.IsNullOrWhiteSpace(this.searchText))
{
await this.CancelSearchAsync();