Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
739bdb1
Initial version works, but needs a lot of refinement
peerschuett Jul 24, 2025
7f367d8
Created custom CopyToClipboard button and made refinements
peerschuett Jul 24, 2025
05696a5
Added translations
peerschuett Jul 24, 2025
c43abaa
Minor text changes
peerschuett Jul 24, 2025
609be6a
Minor change
peerschuett Jul 24, 2025
87bc18b
Unified the copy to clipboard functionality
peerschuett Jul 25, 2025
c9dd01a
Refactored about page to consistently use `this` for member reference…
SommerEngineering Aug 9, 2025
0e9b977
Improved formatting
SommerEngineering Aug 9, 2025
10cea3d
Enhanced About page layout and formatting for improved consistency an…
SommerEngineering Aug 9, 2025
98e2796
Added configuration plugin ID to the full enterprise config case
SommerEngineering Aug 9, 2025
2f47cc6
Conditionally render enterprise configuration details button in the a…
SommerEngineering Aug 9, 2025
8bec202
Renamed variable
SommerEngineering Aug 9, 2025
60f7743
Added configurable size to MudCopyClipboardButton and updated usage i…
SommerEngineering Aug 9, 2025
e4cd2a7
Removed left indent
SommerEngineering Aug 9, 2025
eca0d33
Handled nullable content and improved null checks in MudCopyClipboard…
SommerEngineering Aug 9, 2025
6a62a69
Refactored about page to streamline environment usage and added plugi…
SommerEngineering Aug 9, 2025
339dc08
Updated I18N
SommerEngineering Aug 10, 2025
873d2fa
Fixed I18N
SommerEngineering Aug 10, 2025
e1a650f
Updated changelog
SommerEngineering Aug 10, 2025
6f1fc6e
Merge branch 'main' into hide_config
SommerEngineering Aug 10, 2025
265aee4
Fixed layout
SommerEngineering Aug 10, 2025
4b284ed
Fixed tooltip
SommerEngineering Aug 10, 2025
39347c6
Remove unused namespace imports
SommerEngineering Aug 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions app/MindWork AI Studio/Assistants/I18N/allTexts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1315,9 +1315,6 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CHATROLEEXTENSIONS::T601166687"] = "AI"
-- Edit Message
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1183581066"] = "Edit Message"

-- Copies the content to the clipboard
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T12948066"] = "Copies the content to the clipboard"

-- Do you really want to remove this message?
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T1347427447"] = "Do you really want to remove this message?"

Expand Down Expand Up @@ -1351,9 +1348,6 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3587744975"] = "Regener
-- Do you really want to regenerate this message?
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T3878878761"] = "Do you really want to regenerate this message?"

-- Cannot copy this content type to clipboard!
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4021525742"] = "Cannot copy this content type to clipboard!"

-- Remove Message
UI_TEXT_CONTENT["AISTUDIO::CHAT::CONTENTBLOCKCOMPONENT::T4070211974"] = "Remove Message"

Expand Down Expand Up @@ -1591,6 +1585,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T372007989"] = "Relying on we
-- Cross-Platform and Modern Development
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T843057510"] = "Cross-Platform and Modern Development"

-- Copies the content to the clipboard
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T12948066"] = "Copies the content to the clipboard"

-- Cannot copy this content type to clipboard.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MUDCOPYCLIPBOARDBUTTON::T3937637647"] = "Cannot copy this content type to clipboard."

-- Alpha phase means that we are working on the last details before the beta phase.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PREVIEWALPHA::T166807685"] = "Alpha phase means that we are working on the last details before the beta phase."

Expand Down Expand Up @@ -4186,21 +4186,18 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1020427799"] = "About MindWork AI Stud
-- Browse AI Studio's source code on GitHub — we welcome your contributions.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1107156991"] = "Browse AI Studio's source code on GitHub — we welcome your contributions."

-- AI Studio runs with an enterprise configuration id '{0}' and configuration server URL '{1}'. The configuration plugin is not yet available.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1297057566"] = "AI Studio runs with an enterprise configuration id '{0}' and configuration server URL '{1}'. The configuration plugin is not yet available."
-- This is a private AI Studio installation. It runs without an enterprise configuration.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."

-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1282228996"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is not yet available."

-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."

-- This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1421513382"] = "This library is used to extend the MudBlazor library. It provides additional components that are not part of the MudBlazor library."

-- AI Studio runs with an enterprise configuration id '{0}' and configuration server URL '{1}'. The configuration plugin is active.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1454889560"] = "AI Studio runs with an enterprise configuration id '{0}' and configuration server URL '{1}'. The configuration plugin is active."

-- AI Studio runs with an enterprise configuration using the configuration plugin '{0}', without central configuration management.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1530477579"] = "AI Studio runs with an enterprise configuration using the configuration plugin '{0}', without central configuration management."

-- We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T162898512"] = "We use Lua as the language for plugins. Lua-CSharp lets Lua scripts communicate with AI Studio and vice versa. Thank you, Yusuke Nakada, for this great library."

Expand All @@ -4219,6 +4216,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1806897624"] = "By clicking on the res
-- Pandoc Installation
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T185447014"] = "Pandoc Installation"

-- Copies the configuration plugin ID to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1859295819"] = "Copies the configuration plugin ID to the clipboard"

-- Check for updates
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1890416390"] = "Check for updates"

Expand All @@ -4234,21 +4234,30 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1924365263"] = "This library is used t
-- We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T1943216839"] = "We use Rocket to implement the runtime API. This is necessary because the runtime must be able to communicate with the user interface (IPC). Rocket is a great framework for implementing web APIs in Rust."

-- Copies the server URL to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2037899437"] = "Copies the server URL to the clipboard"

-- This library is used to determine the file type of a file. This is necessary, e.g., when we want to stream a file.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2173617769"] = "This library is used to determine the file type of a file. This is necessary, e.g., when we want to stream a file."

-- For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2174764529"] = "For the secure communication between the user interface and the runtime, we need to create certificates. This Rust library is great for this purpose."

-- AI Studio runs without an enterprise configuration.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2244723851"] = "AI Studio runs without an enterprise configuration."

-- OK
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2246359087"] = "OK"

-- Configuration server:
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2272122662"] = "Configuration server:"

-- We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2273492381"] = "We must generate random numbers, e.g., for securing the interprocess communication between the user interface and the runtime. The rand library is great for this purpose."

-- AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2280402765"] = "AI Studio runs with an enterprise configuration using a configuration plugin, without central configuration management."

-- Configuration plugin ID:
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2301484629"] = "Configuration plugin ID:"

-- The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2329884315"] = "The C# language is used for the implementation of the user interface and the backend. To implement the user interface with C#, the Blazor technology from ASP.NET Core is used. All these technologies are integrated into the .NET SDK."

Expand Down Expand Up @@ -4288,6 +4297,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2765814390"] = "Determine Pandoc versi
-- Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2777988282"] = "Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor."

-- Show Details
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T27924674"] = "Show Details"

-- View our project roadmap and help shape AI Studio's future development.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2829971158"] = "View our project roadmap and help shape AI Studio's future development."

Expand All @@ -4303,12 +4315,18 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T2868174483"] = "The .NET backend canno
-- Changelog
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3017574265"] = "Changelog"

-- Enterprise configuration ID:
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3092349641"] = "Enterprise configuration ID:"

-- Connect AI Studio to your organization's data with our External Retrieval Interface (ERI).
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T313276297"] = "Connect AI Studio to your organization's data with our External Retrieval Interface (ERI)."

-- Have feature ideas? Submit suggestions for future AI Studio enhancements.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3178730036"] = "Have feature ideas? Submit suggestions for future AI Studio enhancements."

-- Hide Details
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3183837919"] = "Hide Details"

-- Update Pandoc
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3249965383"] = "Update Pandoc"

Expand All @@ -4333,6 +4351,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3563271893"] = "Motivation"
-- This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3722989559"] = "This library is used to read Excel and OpenDocument spreadsheet files. This is necessary, e.g., for using spreadsheets as a data source for a chat."

-- AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3741877842"] = "AI Studio runs with an enterprise configuration and a configuration server. The configuration plugin is active."

-- this version does not met the requirements
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T3813932670"] = "this version does not met the requirements"

Expand Down Expand Up @@ -4375,6 +4396,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T639371534"] = "Did you find a bug or a
-- This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible.
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T64689067"] = "This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible."

-- Copies the config ID to the clipboard
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T788846912"] = "Copies the config ID to the clipboard"

-- installed by AI Studio
UI_TEXT_CONTENT["AISTUDIO::PAGES::ABOUT::T833849470"] = "installed by AI Studio"

Expand Down
5 changes: 2 additions & 3 deletions app/MindWork AI Studio/Chat/ContentBlockComponent.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@using AIStudio.Tools
@using MudBlazor
@using AIStudio.Components
@inherits AIStudio.Components.MSGComponentBase
<MudCard Class="@this.CardClasses" Outlined="@true">
<MudCardHeader>
Expand Down Expand Up @@ -38,9 +39,7 @@
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@this.RemoveBlock"/>
</MudTooltip>
}
<MudTooltip Text="@T("Copies the content to the clipboard")" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Color="Color.Default" OnClick="@this.CopyToClipboard"/>
</MudTooltip>
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type" Size="Size.Medium"/>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
Expand Down
30 changes: 0 additions & 30 deletions app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AIStudio.Components;
using AIStudio.Tools.Services;

using Microsoft.AspNetCore.Components;

Expand Down Expand Up @@ -61,12 +60,6 @@ public partial class ContentBlockComponent : MSGComponentBase
[Parameter]
public Func<bool> RegenerateEnabled { get; set; } = () => false;

[Inject]
private RustService RustService { get; init; } = null!;

[Inject]
private ISnackbar Snackbar { get; init; } = null!;

[Inject]
private IDialogService DialogService { get; init; } = null!;

Expand Down Expand Up @@ -115,29 +108,6 @@ await this.InvokeAsync(async () =>
}

#endregion

/// <summary>
/// Copy this block's content to the clipboard.
/// </summary>
private async Task CopyToClipboard()
{
switch (this.Type)
{
case ContentType.TEXT:
var textContent = (ContentText) this.Content;
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text);
break;

default:
this.Snackbar.Add(T("Cannot copy this content type to clipboard!"), Severity.Error, config =>
{
config.Icon = Icons.Material.Filled.ContentCopy;
config.IconSize = Size.Large;
config.IconColor = Color.Error;
});
break;
}
}

private string CardClasses => $"my-2 rounded-lg {this.Class}";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<MudTooltip Text="@this.TooltipMessage" Placement="Placement.Bottom">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Size="@this.Size" OnClick="@(() => this.HandleCopyClick())"/>
</MudTooltip>
90 changes: 90 additions & 0 deletions app/MindWork AI Studio/Components/MudCopyClipboardButton.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using AIStudio.Chat;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;

namespace AIStudio.Components;

public partial class MudCopyClipboardButton : ComponentBase
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(MudCopyClipboardButton).Namespace, nameof(MudCopyClipboardButton));

/// <summary>
/// The string, if you want to copy a string.
/// </summary>
[Parameter]
public string StringContent { get; set; } = string.Empty;

/// <summary>
/// The content, if you want to copy content.
/// </summary>
[Parameter]
public IContent? Content { get; init; }

/// <summary>
/// The content type, if you want to copy Content.
/// </summary>
[Parameter]
public ContentType Type { get; init; } = ContentType.NONE;

/// <summary>
/// The tooltip that should be shown to the user.
/// </summary>
[Parameter]
public string TooltipMessage { get; set; } = TB("Copies the content to the clipboard");

/// <summary>
/// The size of the button. The default size is small.
/// </summary>
[Parameter]
public Size Size { get; set; } = Size.Small;

[Inject]
private ISnackbar Snackbar { get; init; } = null!;

[Inject]
private RustService RustService { get; init; } = null!;

private async Task HandleCopyClick()
{
if (this.Type is ContentType.NONE)
await this.CopyToClipboard(this.StringContent);
else
await this.CopyToClipboard(this.Content);
}

/// <summary>
/// Copy this the string to the clipboard.
/// </summary>
private async Task CopyToClipboard(string textContent)
{
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent);
}

/// <summary>
/// Copy this block's content to the clipboard.
/// </summary>
private async Task CopyToClipboard(IContent? contentToCopy)
{
if (contentToCopy is null)
return;

switch (this.Type)
{
case ContentType.TEXT:
var textContent = (ContentText) contentToCopy;
await this.RustService.CopyText2Clipboard(this.Snackbar, textContent.Text);
break;

default:
this.Snackbar.Add(TB("Cannot copy this content type to clipboard."), Severity.Error, config =>
{
config.Icon = Icons.Material.Filled.ContentCopy;
config.IconSize = Size.Large;
config.IconColor = Color.Error;
});
break;
}
}

}
Loading