Changed all icons of AI Studio to Lucide (#1187)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-11 14:20:49 +01:00
1 parent 9a676101f7
commit 7ef26cd5c8
352 files changed
+6261 -1620

No files matched your search

@@ -41,11 +41,11 @@ public static class ChatRoleExtensions
/// <value>The icon of the role.</value>
public string Icon => role switch
{
ChatRole.SYSTEM => Icons.Material.Filled.Settings,
ChatRole.USER => Icons.Material.Filled.Person,
ChatRole.AI => Icons.Material.Filled.AutoAwesome,
ChatRole.SYSTEM => AppIcons.SYSTEM_ROLE,
ChatRole.USER => AppIcons.USER,
ChatRole.AI => AppIcons.AI,
_ => Icons.Material.Filled.Help,
_ => AppIcons.UNKNOWN,
};
/// <summary>
@@ -25,8 +25,8 @@
Style="min-width:auto; border-width:1px; text-transform:none;"
OnClick="@this.ToggleToolTrace">
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
<MudIcon Icon="@Icons.Material.Filled.Build" Color="Color.Default" Size="Size.Small" />
<MudIcon Icon="@(this.showToolTrace ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)" Size="Size.Small" />
<MudIcon Icon="@AppIcons.TOOL" Color="Color.Default" Size="Size.Small" />
<MudIcon Icon="@(this.showToolTrace ? AppIcons.EXPAND_LESS : AppIcons.EXPAND_MORE)" Size="Size.Small" />
</MudStack>
</MudButton>
</MudTooltip>
@@ -39,7 +39,7 @@
{
<MudTooltip Text="@T("Number of attachments")" Placement="Placement.Bottom">
<MudBadge Content="@this.Content.FileAttachments.Count" Color="Color.Primary" Overlap="true" BadgeClass="sources-card-header">
<MudIconButton Icon="@Icons.Material.Filled.AttachFile"
<MudIconButton Icon="@AppIcons.ATTACH_FILE"
OnClick="@this.OpenAttachmentsDialog"/>
</MudBadge>
</MudTooltip>
@@ -48,45 +48,45 @@
{
<MudTooltip Text="@T("Number of sources")" Placement="Placement.Bottom">
<MudBadge Content="@this.Content.Sources.Count" Color="Color.Primary" Overlap="true" BadgeClass="sources-card-header">
<MudIconButton Icon="@Icons.Material.Filled.Link" Disabled="@(!this.HasSourcesToShow)" OnClick="@this.ShowSources"/>
<MudIconButton Icon="@AppIcons.SOURCES" Disabled="@(!this.HasSourcesToShow)" OnClick="@this.ShowSources"/>
</MudBadge>
</MudTooltip>
}
@if (this.IsSecondToLastBlock && this.Role is ChatRole.USER && this.EditLastUserBlockFunc is not null)
{
<MudTooltip Text="@T("Edit")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.EditLastUserBlock"/>
<MudIconButton Icon="@AppIcons.EDIT" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.EditLastUserBlock"/>
</MudTooltip>
}
@if (this.IsLastContentBlock && this.Role is ChatRole.USER && this.EditLastBlockFunc is not null)
{
<MudTooltip Text="@T("Edit")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.EditLastBlock"/>
<MudIconButton Icon="@AppIcons.EDIT" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.EditLastBlock"/>
</MudTooltip>
}
@if (this.IsLastContentBlock && this.Role is ChatRole.AI && this.RegenerateFunc is not null)
{
<MudTooltip Text="@T("Regenerate")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Recycling" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled() || !this.RegenerateEnabled())" OnClick="@this.RegenerateBlock"/>
<MudIconButton Icon="@AppIcons.REGENERATE" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled() || !this.RegenerateEnabled())" OnClick="@this.RegenerateBlock"/>
</MudTooltip>
}
@if (!this.IsLastContentBlock && this.Role is ChatRole.AI && this.RollbackFunc is not null)
{
<MudTooltip Text="@T("Roll back to this response")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Restore" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.RollbackBlock"/>
<MudIconButton Icon="@AppIcons.ROLLBACK" Color="Color.Default" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.RollbackBlock"/>
</MudTooltip>
}
@if (this.RemoveBlockFunc is not null)
{
<MudTooltip Text="@T("Removes this block")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.RemoveBlock"/>
<MudIconButton Icon="@AppIcons.DELETE" Color="Color.Error" Disabled="@(!this.BlockActionsEnabled())" OnClick="@this.RemoveBlock"/>
</MudTooltip>
}
@if (this.CanExportAnswer)
{
<MudTooltip Text="@this.EffectiveExportTitle" Placement="Placement.Bottom">
<MudMenu Icon="@Icons.Material.Filled.Save" MaxHeight="@MenuDefaults.MAX_HEIGHT">
<MudMenu Icon="@AppIcons.EXPORT" MaxHeight="@MenuDefaults.MAX_HEIGHT">
@foreach (var documentFormat in FileExportFormat.DocumentFormats)
{
<MudMenuItem OnClick="@(() => this.ExportDocument(documentFormat))" Icon="@documentFormat.Icon" Label="@documentFormat.Name"/>
@@ -123,7 +123,7 @@
@if (this.CanSendTo)
{
<MudTooltip Text="@T("Send to ...")" Placement="Placement.Bottom">
<MudMenu Icon="@Icons.Material.Filled.Apps" Disabled="@(!this.IsSendToEnabled)" MaxHeight="@MenuDefaults.MAX_HEIGHT">
<MudMenu Icon="@AppIcons.SEND_TO" Disabled="@(!this.IsSendToEnabled)" MaxHeight="@MenuDefaults.MAX_HEIGHT">
@foreach (var destination in this.SendToDestinations)
{
<MudMenuItem OnClick="@(() => this.SendTo(destination))" Label="@destination.Name"/>
@@ -178,7 +178,7 @@
@this.GetTraceStatusText(invocation)
</MudChip>
</MudStack>
<MudIcon Icon="@(this.IsToolInvocationExpanded(invocation.Order) ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)" Size="Size.Small" />
<MudIcon Icon="@(this.IsToolInvocationExpanded(invocation.Order) ? AppIcons.EXPAND_LESS : AppIcons.EXPAND_MORE)" Size="Size.Small" />
</MudStack>
</MudButton>
@@ -243,7 +243,7 @@
var renderPlan = this.GetMarkdownRenderPlan(textContent.Text);
RenderFragment<MessageFile> saveButton = file =>
@<MudTooltip Text="@this.SaveAsLabel(file)" Placement="Placement.Top">
<MudIconButton Icon="@Icons.Material.Filled.Save" Color="Color.Primary" Variant="Variant.Filled" Class="ma-2" OnClick="@(() => this.ExportFile(file))"/>
<MudIconButton Icon="@AppIcons.EXPORT" Color="Color.Primary" Variant="Variant.Filled" Class="ma-2" OnClick="@(() => this.ExportFile(file))"/>
</MudTooltip>;
}
@foreach (var segment in renderPlan.Segments)
@@ -689,7 +689,7 @@ public partial class ContentBlockComponent : MSGComponentBase
private async Task ReportUnknownExportFormat(ArgumentOutOfRangeException exception, FileExportFormat format)
{
await this.MessageBus.SendError(new(Icons.Material.Filled.Error, string.Format(this.T("Failed to export this message, because the file format '{0}' is unknown."), format)));
await this.MessageBus.SendError(new(AppIcons.ERROR, string.Format(this.T("Failed to export this message, because the file format '{0}' is unknown."), format)));
this.Logger.LogError(exception, "Failed to export the content, because no exporter writes the format {ExportFormat}.", format);
}
+10 -10
View File
@@ -139,7 +139,7 @@ public sealed class ContentText : IContent
}
if (Interlocked.Exchange(ref UNSTORED_CONTENT_REPORTED, 1) is 0)
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.Storage, TB("AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it.")));
await MessageBus.INSTANCE.SendWarning(new(AppIcons.PROVENANCE_STORE, TB("AI Studio could not store what the AI received separately from your chat. It remains in the chat itself, so you can still read it.")));
}
/// <summary>
@@ -347,7 +347,7 @@ public sealed class ContentText : IContent
// The answer is about to be created without the data the user expected it to use.
// Without this message, that answer is indistinguishable from one that did use it:
//
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.Source, TB("Your data sources could not be used. This answer was created without them.")));
await MessageBus.INSTANCE.SendWarning(new(AppIcons.DATA_SOURCE, TB("Your data sources could not be used. This answer was created without them.")));
}
}
@@ -491,7 +491,7 @@ public sealed class ContentText : IContent
{
var userMessage = modelLoadResult.FailureReason.ToUserMessage(provider.InstanceName);
if (!string.IsNullOrWhiteSpace(userMessage))
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, userMessage));
await MessageBus.INSTANCE.SendError(new(AppIcons.PROVIDER_ERROR, userMessage));
LOGGER.LogWarning("Skipping selected model availability check for '{ProviderInstanceName}' (provider={ProviderType}) because loading the model list failed with reason {FailureReason}.", provider.InstanceName, provider.Provider, modelLoadResult.FailureReason);
return false;
@@ -516,7 +516,7 @@ public sealed class ContentText : IContent
TB("We could load models from '{0}', but the provider did not return any usable text models."),
provider.InstanceName);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, emptyModelsMessage));
await MessageBus.INSTANCE.SendError(new(AppIcons.PROVIDER_ERROR, emptyModelsMessage));
LOGGER.LogWarning("Skipping AI request because there are no models available from '{ProviderInstanceName}' (provider={ProviderType}).", provider.InstanceName, provider.Provider);
return false;
}
@@ -530,7 +530,7 @@ public sealed class ContentText : IContent
provider.InstanceName,
provider.Provider);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, message));
await MessageBus.INSTANCE.SendError(new(AppIcons.PROVIDER_ERROR, message));
LOGGER.LogWarning("Skipping AI request because model '{ModelId}' is not available from '{ProviderInstanceName}' (provider={ProviderType}).", chatModel.Id, provider.InstanceName, provider.Provider);
return false;
}
@@ -684,14 +684,14 @@ public sealed class ContentText : IContent
if (extraction.Outcome is FileExtractionOutcome.PARTIAL)
{
LOGGER.LogWarning("Parts of the file attachment '{FilePath}' could not be read: pages={FailedPages}.", document.FilePath, string.Join(", ", extraction.FailedPages));
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.Description, extraction.ToPartialUserMessage(document.FileName)));
await MessageBus.INSTANCE.SendWarning(new(AppIcons.DOCUMENT, extraction.ToPartialUserMessage(document.FileName)));
}
// The file was read correctly, but its extension lies about what it contains:
if (extraction.HasExtensionMismatch)
{
LOGGER.LogWarning("The file attachment '{FilePath}' is actually a '{DetectedFormat}'.", document.FilePath, extraction.DetectedFormat);
await MessageBus.INSTANCE.SendWarning(new(Icons.Material.Filled.RuleFolder, extraction.ToExtensionMismatchUserMessage(document.FileName)));
await MessageBus.INSTANCE.SendWarning(new(AppIcons.FILE_TYPE_MISMATCH, extraction.ToExtensionMismatchUserMessage(document.FileName)));
}
}
@@ -797,7 +797,7 @@ public sealed class ContentText : IContent
foreach (var missingDocument in missingDocuments)
{
LOGGER.LogWarning("File attachment no longer exists and will be skipped: '{MissingDocument}'.", missingDocument.FilePath);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.FindInPage, string.Format(TB("The file '{0}' is currently not available and was not sent."), missingDocument.FileName)));
await MessageBus.INSTANCE.SendError(new(AppIcons.FILE_NOT_FOUND, string.Format(TB("The file '{0}' is currently not available and was not sent."), missingDocument.FileName)));
}
// Only proceed if there are existing, allowed documents:
@@ -840,7 +840,7 @@ public sealed class ContentText : IContent
if (!pandocIsUsable && FileTypes.RequiresPandoc(document.FilePath))
{
LOGGER.LogWarning("The file attachment '{FilePath}' needs Pandoc and will be skipped.", document.FilePath);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Description, FileExtractionErrorCode.PANDOC_UNAVAILABLE.ToUserMessage(document.FileName)));
await MessageBus.INSTANCE.SendError(new(AppIcons.DOCUMENT, FileExtractionErrorCode.PANDOC_UNAVAILABLE.ToUserMessage(document.FileName)));
continue;
}
@@ -848,7 +848,7 @@ public sealed class ContentText : IContent
if (!extraction.HasUsableContent)
{
LOGGER.LogError("Reading the file attachment '{FilePath}' failed and it will not be sent: code={ErrorCode}, message='{ErrorMessage}'.", document.FilePath, extraction.ErrorCode, extraction.ErrorMessage);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Description, extraction.ToUserMessage(document.FileName)));
await MessageBus.INSTANCE.SendError(new(AppIcons.DOCUMENT, extraction.ToUserMessage(document.FileName)));
continue;
}
@@ -70,7 +70,7 @@ public static class IImageSourceExtensions
var lengthBytes = response.Content.Headers.ContentLength;
if(lengthBytes > MAX_IMAGE_SIZE_BYTES)
{
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ImageNotSupported, TB("The image at the URL is too large (>10 MB). Skipping the image.")));
await MessageBus.INSTANCE.SendError(new(AppIcons.IMAGE_NOT_SUPPORTED, TB("The image at the URL is too large (>10 MB). Skipping the image.")));
return (success: false, string.Empty);
}
@@ -78,7 +78,7 @@ public static class IImageSourceExtensions
return (success: true, Convert.ToBase64String(bytes));
}
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ImageNotSupported, TB("Failed to download the image from the URL. Skipping the image.")));
await MessageBus.INSTANCE.SendError(new(AppIcons.IMAGE_NOT_SUPPORTED, TB("Failed to download the image from the URL. Skipping the image.")));
return (success: false, string.Empty);
}
@@ -89,7 +89,7 @@ public static class IImageSourceExtensions
var length = new FileInfo(image.Source).Length;
if(length > MAX_IMAGE_SIZE_BYTES)
{
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ImageNotSupported, TB("The local image file is too large (>10 MB). Skipping the image.")));
await MessageBus.INSTANCE.SendError(new(AppIcons.IMAGE_NOT_SUPPORTED, TB("The local image file is too large (>10 MB). Skipping the image.")));
return (success: false, string.Empty);
}
@@ -97,7 +97,7 @@ public static class IImageSourceExtensions
return (success: true, Convert.ToBase64String(bytes));
}
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ImageNotSupported, TB("The local image file does not exist. Skipping the image.")));
await MessageBus.INSTANCE.SendError(new(AppIcons.IMAGE_NOT_SUPPORTED, TB("The local image file does not exist. Skipping the image.")));
return (success: false, string.Empty);
default:
@@ -118,7 +118,7 @@ public static class ListContentBlockExtensions
if (prepared.IsPrepared)
return imageSubContentFactory(prepared);
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ImageNotSupported, prepared.ErrorCode.ToUserMessage(image.FileName)));
await MessageBus.INSTANCE.SendError(new(AppIcons.IMAGE_NOT_SUPPORTED, prepared.ErrorCode.ToUserMessage(image.FileName)));
return null;
}
}