diff --git a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs index bbe42411..30939446 100644 --- a/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs +++ b/app/MindWork AI Studio/Assistants/AssistantBase.razor.cs @@ -24,10 +24,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher [Inject] protected IJSRuntime JsRuntime { get; init; } = null!; - - [Inject] - protected ISnackbar Snackbar { get; init; } = null!; - + [Inject] protected RustService RustService { get; init; } = null!; @@ -529,7 +526,7 @@ public abstract partial class AssistantBase : AssistantLowerBase wher protected async Task CopyToClipboard() { - await this.RustService.CopyText2Clipboard(this.Snackbar, this.Result2Copy()); + await this.RustService.CopyText2Clipboard(this.Result2Copy()); } private ChatThread CreateSendToChatThread() diff --git a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs index d896d315..0fed4451 100644 --- a/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/DocumentAnalysis/DocumentAnalysisAssistant.razor.cs @@ -795,7 +795,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore #if DEBUG AsyncAction = async () => await this.WriteToPluginFile(), #else - AsyncAction = async () => await this.RustService.CopyText2Clipboard(this.Snackbar, this.finalLuaCode.ToString()), + AsyncAction = async () => await this.RustService.CopyText2Clipboard(this.finalLuaCode.ToString()), #endif DisabledActionParam = () => this.finalLuaCode.Length == 0, }, diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs index ef2fcdea..8a8d46ed 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs @@ -280,9 +280,7 @@ public partial class VisualBriefingAssistant if (this.lastBuildDiagnostics is null) return; - await this.RustService.CopyText2Clipboard( - this.Snackbar, - this.lastBuildDiagnostics.ToClipboardText()); + await this.RustService.CopyText2Clipboard(this.lastBuildDiagnostics.ToClipboardText()); } /// diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs index eb9607a7..a0d7a3d2 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs @@ -57,12 +57,6 @@ public partial class VisualBriefingAssistant : MSGComponentBase [Inject] private IDialogService DialogService { get; init; } = null!; - /// - /// Defines Snackbar for the visual briefing feature. - /// - [Inject] - private ISnackbar Snackbar { get; init; } = null!; - /// /// Defines AssistantSessionService for the visual briefing feature. /// diff --git a/app/MindWork AI Studio/Components/MudCopyClipboardButton.razor.cs b/app/MindWork AI Studio/Components/MudCopyClipboardButton.razor.cs index 3b74a5a3..86c067ba 100644 --- a/app/MindWork AI Studio/Components/MudCopyClipboardButton.razor.cs +++ b/app/MindWork AI Studio/Components/MudCopyClipboardButton.razor.cs @@ -38,10 +38,7 @@ public partial class MudCopyClipboardButton : ComponentBase /// [Parameter] public Size Size { get; set; } = Size.Small; - - [Inject] - private ISnackbar Snackbar { get; init; } = null!; - + [Inject] private RustService RustService { get; init; } = null!; @@ -58,7 +55,7 @@ public partial class MudCopyClipboardButton : ComponentBase /// private async Task CopyToClipboard(string textContent) { - await this.RustService.CopyText2Clipboard(this.Snackbar, textContent); + await this.RustService.CopyText2Clipboard(textContent); } /// @@ -73,7 +70,7 @@ public partial class MudCopyClipboardButton : ComponentBase { case ContentType.TEXT: var textContent = (ContentText) contentToCopy; - await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text); + await this.RustService.CopyText2Clipboard(textContent.Text); break; default: diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs index a467b1e7..3f43d8a3 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelApp.razor.cs @@ -74,7 +74,7 @@ public partial class SettingsPanelApp : SettingsPanelBase private async Task GenerateEncryptionSecret() { var secret = EnterpriseEncryption.GenerateSecret(); - await this.RustService.CopyText2Clipboard(this.Snackbar, secret); + await this.RustService.CopyText2Clipboard(secret); } private string GetStartPageHelpText() diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs index 871d8353..82ffdbb9 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelBase.cs @@ -16,6 +16,4 @@ public abstract class SettingsPanelBase : MSGComponentBase [Inject] protected RustService RustService { get; init; } = null!; - [Inject] - protected ISnackbar Snackbar { get; init; } = null!; } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviderBase.cs b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviderBase.cs index 454197f6..2c7a3c5b 100644 --- a/app/MindWork AI Studio/Components/Settings/SettingsPanelProviderBase.cs +++ b/app/MindWork AI Studio/Components/Settings/SettingsPanelProviderBase.cs @@ -56,6 +56,6 @@ public abstract class SettingsPanelProviderBase : SettingsPanelBase if (string.IsNullOrWhiteSpace(luaCode)) return; - await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode); + await this.RustService.CopyText2Clipboard(luaCode); } } diff --git a/app/MindWork AI Studio/Components/TextInfoLine.razor.cs b/app/MindWork AI Studio/Components/TextInfoLine.razor.cs index 0fb9923d..3abe197b 100644 --- a/app/MindWork AI Studio/Components/TextInfoLine.razor.cs +++ b/app/MindWork AI Studio/Components/TextInfoLine.razor.cs @@ -23,9 +23,6 @@ public partial class TextInfoLine : MSGComponentBase [Inject] private RustService RustService { get; init; } = null!; - - [Inject] - private ISnackbar Snackbar { get; init; } = null!; #region Overrides of ComponentBase @@ -43,5 +40,5 @@ public partial class TextInfoLine : MSGComponentBase private string ClipboardTooltip => string.Format(T("Copy {0} to the clipboard"), this.ClipboardTooltipSubject); - private async Task CopyToClipboard(string content) => await this.RustService.CopyText2Clipboard(this.Snackbar, content); + private async Task CopyToClipboard(string content) => await this.RustService.CopyText2Clipboard(content); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Components/TextInfoLines.razor.cs b/app/MindWork AI Studio/Components/TextInfoLines.razor.cs index 61a4d9c4..e33a78ee 100644 --- a/app/MindWork AI Studio/Components/TextInfoLines.razor.cs +++ b/app/MindWork AI Studio/Components/TextInfoLines.razor.cs @@ -26,9 +26,6 @@ public partial class TextInfoLines : MSGComponentBase [Inject] private RustService RustService { get; init; } = null!; - - [Inject] - private ISnackbar Snackbar { get; init; } = null!; #region Overrides of ComponentBase @@ -46,7 +43,7 @@ public partial class TextInfoLines : MSGComponentBase private string ClipboardTooltip => string.Format(T("Copy {0} to the clipboard"), this.ClipboardTooltipSubject); - private async Task CopyToClipboard(string content) => await this.RustService.CopyText2Clipboard(this.Snackbar, content); + private async Task CopyToClipboard(string content) => await this.RustService.CopyText2Clipboard(content); private string GetColor() { diff --git a/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs b/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs index 1cd1e9fb..975055e3 100644 --- a/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs +++ b/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs @@ -25,9 +25,6 @@ public partial class VoiceRecorder : MSGComponentBase [Inject] private GlobalShortcutService GlobalShortcutService { get; init; } = null!; - [Inject] - private ISnackbar Snackbar { get; init; } = null!; - [Inject] private VoiceRecordingAvailabilityService VoiceRecordingAvailabilityService { get; init; } = null!; @@ -448,7 +445,7 @@ public partial class VoiceRecorder : MSGComponentBase } // Copy the transcribed text to the clipboard: - await this.RustService.CopyText2Clipboard(this.Snackbar, transcribedText); + await this.RustService.CopyText2Clipboard(transcribedText); } catch (Exception ex) diff --git a/app/MindWork AI Studio/Dialogs/AssistantPluginEditorDialog.razor.cs b/app/MindWork AI Studio/Dialogs/AssistantPluginEditorDialog.razor.cs index 40fdbe0f..c759e5ac 100644 --- a/app/MindWork AI Studio/Dialogs/AssistantPluginEditorDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/AssistantPluginEditorDialog.razor.cs @@ -12,10 +12,7 @@ public partial class AssistantPluginEditorDialog : MSGComponentBase { [Inject] protected RustService RustService { get; init; } = null!; - - [Inject] - protected ISnackbar Snackbar { get; init; } = null!; - + private const string PLUGIN_FILE_NAME = "plugin.lua"; private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(AssistantPluginEditorDialog)); @@ -134,7 +131,7 @@ public partial class AssistantPluginEditorDialog : MSGComponentBase private void Cancel() => this.MudDialog.Cancel(); - private async Task CopyToClipboard() => await this.RustService.CopyText2Clipboard(this.Snackbar, this.Result2Copy()); + private async Task CopyToClipboard() => await this.RustService.CopyText2Clipboard(this.Result2Copy()); private static bool AreSamePath(string left, string right) { diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogBase.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogBase.cs index 0b235fd2..bb214e1f 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogBase.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogBase.cs @@ -19,9 +19,6 @@ public abstract class SettingsDialogBase : MSGComponentBase [Inject] protected RustService RustService { get; init; } = null!; - [Inject] - protected ISnackbar Snackbar { get; init; } = null!; - protected readonly List> AvailableLLMProviders = new(); protected readonly List> AvailableEmbeddingProviders = new(); diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs index d6dbb2da..becd4645 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogChatTemplate.razor.cs @@ -172,7 +172,7 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase } if (!string.IsNullOrWhiteSpace(luaCode)) - await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode); + await this.RustService.CopyText2Clipboard(luaCode); } private async Task CopyPackagedChatTemplateLuaToClipboard(ChatTemplate chatTemplate, string pluginDirectory) @@ -187,6 +187,6 @@ public partial class SettingsDialogChatTemplate : SettingsDialogBase } if (!string.IsNullOrWhiteSpace(luaCode)) - await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode); + await this.RustService.CopyText2Clipboard(luaCode); } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs index 1f13fe54..57bcd524 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogDataSources.razor.cs @@ -110,7 +110,7 @@ public partial class SettingsDialogDataSources : SettingsDialogBase { var publicLuaCode = eriDataSource.ExportAsConfigurationSection(); if (!string.IsNullOrWhiteSpace(publicLuaCode)) - await this.RustService.CopyText2Clipboard(this.Snackbar, publicLuaCode); + await this.RustService.CopyText2Clipboard(publicLuaCode); return; } @@ -179,7 +179,7 @@ public partial class SettingsDialogDataSources : SettingsDialogBase if (string.IsNullOrWhiteSpace(luaCode)) return; - await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode); + await this.RustService.CopyText2Clipboard(luaCode); } private async Task EditDataSource(IDataSource dataSource) diff --git a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs index d5387dc0..531583a0 100644 --- a/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs +++ b/app/MindWork AI Studio/Dialogs/Settings/SettingsDialogProfiles.razor.cs @@ -75,7 +75,7 @@ public partial class SettingsDialogProfiles : SettingsDialogBase var luaCode = profile.ExportAsConfigurationSection(); if (!string.IsNullOrWhiteSpace(luaCode)) - await this.RustService.CopyText2Clipboard(this.Snackbar, luaCode); + await this.RustService.CopyText2Clipboard(luaCode); } private async Task DeleteProfile(Profile profile) diff --git a/app/MindWork AI Studio/Layout/MainLayout.razor.cs b/app/MindWork AI Studio/Layout/MainLayout.razor.cs index 5f798655..a28f6a5c 100644 --- a/app/MindWork AI Studio/Layout/MainLayout.razor.cs +++ b/app/MindWork AI Studio/Layout/MainLayout.razor.cs @@ -118,7 +118,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan ]); // Set the snackbar for the update service: - UpdateService.SetBlazorDependencies(this.Snackbar); + UpdateService.MarkBlazorReady(); TemporaryChatService.Initialize(); // Should the navigation bar be open by default? diff --git a/app/MindWork AI Studio/Pages/Information.razor.cs b/app/MindWork AI Studio/Pages/Information.razor.cs index d5d1225d..599cb788 100644 --- a/app/MindWork AI Studio/Pages/Information.razor.cs +++ b/app/MindWork AI Studio/Pages/Information.razor.cs @@ -26,9 +26,6 @@ public partial class Information : MSGComponentBase [Inject] private IDialogService DialogService { get; init; } = null!; - [Inject] - private ISnackbar Snackbar { get; init; } = null!; - [Inject] private UpdatePolicy UpdatePolicy { get; init; } = null!; @@ -488,12 +485,12 @@ public partial class Information : MSGComponentBase private async Task CopyStartupLogPath() { - await this.RustService.CopyText2Clipboard(this.Snackbar, this.logPaths.LogStartupPath); + await this.RustService.CopyText2Clipboard(this.logPaths.LogStartupPath); } private async Task CopyAppLogPath() { - await this.RustService.CopyText2Clipboard(this.Snackbar, this.logPaths.LogAppPath); + await this.RustService.CopyText2Clipboard(this.logPaths.LogAppPath); } private const string LICENSE = """ diff --git a/app/MindWork AI Studio/Tools/Services/MarkdownClipboardService.cs b/app/MindWork AI Studio/Tools/Services/MarkdownClipboardService.cs index b597aa5b..f27f7720 100644 --- a/app/MindWork AI Studio/Tools/Services/MarkdownClipboardService.cs +++ b/app/MindWork AI Studio/Tools/Services/MarkdownClipboardService.cs @@ -6,15 +6,13 @@ namespace AIStudio.Tools.Services; /// Wire up the clipboard service to copy Markdown to the clipboard. /// We use our own Rust-based clipboard service for this. /// -public sealed class MarkdownClipboardService(RustService rust, ISnackbar snackbar) : IMudMarkdownClipboardService +public sealed class MarkdownClipboardService(RustService rust) : IMudMarkdownClipboardService { - private ISnackbar Snackbar { get; } = snackbar; - private RustService Rust { get; } = rust; /// /// Gets called when the user wants to copy the Markdown to the clipboard. /// /// The Markdown text to copy. - public async ValueTask CopyToClipboardAsync(string text) => await this.Rust.CopyText2Clipboard(this.Snackbar, text); + public async ValueTask CopyToClipboardAsync(string text) => await this.Rust.CopyText2Clipboard(text); } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/RustService.Clipboard.cs b/app/MindWork AI Studio/Tools/Services/RustService.Clipboard.cs index baf730bb..773f379f 100644 --- a/app/MindWork AI Studio/Tools/Services/RustService.Clipboard.cs +++ b/app/MindWork AI Studio/Tools/Services/RustService.Clipboard.cs @@ -7,13 +7,16 @@ public sealed partial class RustService /// /// Tries to copy the given text to the clipboard. /// - /// The snackbar to show the result. + /// + /// The outcome is reported through the message bus. Callers used to hand in their snackbar, which + /// was the reason most components injected one at all, and it meant this notification was styled + /// here instead of together with every other notification of the app. + /// /// The text to copy to the clipboard. - public async Task CopyText2Clipboard(ISnackbar snackbar, string text) + public async Task CopyText2Clipboard(string text) { var message = TB("Successfully copied the text to your clipboard"); - var iconColor = Color.Error; - var severity = Severity.Error; + var succeeded = false; try { var encryptedText = await text.Encrypt(this.encryptor!); @@ -32,19 +35,16 @@ public sealed partial class RustService message = TB("Failed to copy the text to your clipboard."); return; } - - iconColor = Color.Success; - severity = Severity.Success; + + succeeded = true; this.logger!.LogDebug("Successfully copied the text to the clipboard."); } finally { - snackbar.Add(message, severity, config => - { - config.Icon = Icons.Material.Filled.ContentCopy; - config.IconSize = Size.Large; - config.IconColor = iconColor; - }); + if (succeeded) + await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.ContentCopy, message)); + else + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.ContentCopy, message)); } } } \ No newline at end of file diff --git a/app/MindWork AI Studio/Tools/Services/UpdateService.cs b/app/MindWork AI Studio/Tools/Services/UpdateService.cs index b7dd124b..195155be 100644 --- a/app/MindWork AI Studio/Tools/Services/UpdateService.cs +++ b/app/MindWork AI Studio/Tools/Services/UpdateService.cs @@ -11,8 +11,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(UpdateService).Namespace, nameof(UpdateService)); private static bool IS_INITIALIZED; - private static ISnackbar? SNACKBAR; - + private readonly SettingsManager settingsManager; private readonly MessageBus messageBus; private readonly RustService rust; @@ -101,12 +100,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver if (notifyUserWhenNoUpdate) { - SNACKBAR!.Add(TB("Failed to check for updates. Please try again later."), Severity.Error, config => - { - config.Icon = Icons.Material.Filled.Error; - config.IconSize = Size.Large; - config.IconColor = Color.Error; - }); + await this.messageBus.SendError(new(Icons.Material.Filled.Error, TB("Failed to check for updates. Please try again later."))); } return; @@ -133,12 +127,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver } catch (Exception) { - SNACKBAR!.Add(TB("Failed to install update automatically. Please try again manually."), Severity.Error, config => - { - config.Icon = Icons.Material.Filled.Error; - config.IconSize = Size.Large; - config.IconColor = Color.Error; - }); + await this.messageBus.SendError(new(Icons.Material.Filled.Error, TB("Failed to install update automatically. Please try again manually."))); } } else @@ -148,12 +137,7 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver { if (notifyUserWhenNoUpdate) { - SNACKBAR!.Add(TB("No update found."), Severity.Normal, config => - { - config.Icon = Icons.Material.Filled.Update; - config.IconSize = Size.Large; - config.IconColor = Color.Primary; - }); + await this.messageBus.SendInfo(new(Icons.Material.Filled.Update, TB("No update found."))); } } } @@ -168,9 +152,8 @@ public sealed class UpdateService : BackgroundService, IMessageBusReceiver _ => Timeout.InfiniteTimeSpan }; - public static void SetBlazorDependencies(ISnackbar snackbar) - { - SNACKBAR = snackbar; - IS_INITIALIZED = true; - } + /// + /// Signals that the Blazor UI is ready, so queued update notifications can be shown. + /// + public static void MarkBlazorReady() => IS_INITIALIZED = true; } \ No newline at end of file