diff --git a/app/MindWork AI Studio/Components/CodeEditor.razor b/app/MindWork AI Studio/Components/CodeEditor.razor new file mode 100644 index 00000000..9dc1692d --- /dev/null +++ b/app/MindWork AI Studio/Components/CodeEditor.razor @@ -0,0 +1 @@ +
diff --git a/app/MindWork AI Studio/Components/CodeEditor.razor.cs b/app/MindWork AI Studio/Components/CodeEditor.razor.cs new file mode 100644 index 00000000..ac7e019a --- /dev/null +++ b/app/MindWork AI Studio/Components/CodeEditor.razor.cs @@ -0,0 +1,103 @@ +using Microsoft.AspNetCore.Components; + +namespace AIStudio.Components; + +public partial class CodeEditor : ComponentBase, IAsyncDisposable +{ + private static readonly CodeEditorTheme DARK_CODE_EDITOR_THEME = new("#191a1c", "#bdbdbd", "#404040", "#85c46c", "#c9a26d", "#ed94c0", "#6c95eb", "#39cc9b", "#66c3cc"); + private static readonly CodeEditorTheme LIGHT_CODE_EDITOR_THEME = new("#fefcf6", "#383838", "#d8d8d8", "#248700", "#8c6c41", "#ab2f6b", "#0f54d6", "#00855f", "#0093a1"); + + [Inject] + private IJSRuntime JsRuntime { get; set; } = null!; + + [Inject] + private global::AIStudio.Settings.SettingsManager SettingsManager { get; init; } = null!; + + [Parameter] + public string Value { get; set; } = string.Empty; + + [Parameter] + public CodeEditorLanguage Language { get; set; } = CodeEditorLanguage.PLAIN_TEXT; + + [Parameter] + public string Class { get; set; } = string.Empty; + + private readonly string editorId = $"code-editor-{Guid.NewGuid():N}"; + private const string CODE_EDITOR_MODULE = "./system/CodeEditor/code-editor.js?v=20260707-3"; + private ElementReference editorElement; + private IJSObjectReference? module; + private string CodeEditorThemeStyle => this.GetCodeEditorThemeStyle(); + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (!firstRender) + return; + + this.module = await this.JsRuntime.InvokeAsync("import", CODE_EDITOR_MODULE); + await this.module.InvokeVoidAsync("init", this.editorId, this.editorElement, this.Value, this.Language.ToString()); + } + + public async ValueTask GetCodeAsync() + { + if (this.module is null) + return this.Value; + + return await this.module.InvokeAsync("getCode", this.editorId); + } + + public async ValueTask SetCodeAsync(string code) + { + this.Value = code; + if (this.module is null) + return; + + await this.module.InvokeVoidAsync("setCode", this.editorId, code); + } + + private string GetCodeEditorThemeStyle() + { + var codeEditorTheme = this.SettingsManager.IsDarkMode ? DARK_CODE_EDITOR_THEME : LIGHT_CODE_EDITOR_THEME; + + return + $"--mw-code-editor-background: {codeEditorTheme.Background}; " + + $"--mw-code-editor-foreground: {codeEditorTheme.Foreground}; " + + $"--mw-code-editor-border: {codeEditorTheme.Border}; " + + $"--mw-code-editor-comment: {codeEditorTheme.Comment}; " + + $"--mw-code-editor-string: {codeEditorTheme.String}; " + + $"--mw-code-editor-number: {codeEditorTheme.Number}; " + + $"--mw-code-editor-keyword: {codeEditorTheme.Keyword}; " + + $"--mw-code-editor-literal: {codeEditorTheme.Keyword}; " + + $"--mw-code-editor-built-in: {codeEditorTheme.Function}; " + + $"--mw-code-editor-constant: {codeEditorTheme.Constant}; " + + $"--mw-code-editor-function: {codeEditorTheme.Function}; " + + $"--mw-code-editor-property: {codeEditorTheme.Function}; " + + $"--mw-code-editor-variable: {codeEditorTheme.Foreground};"; + } + + public async ValueTask DisposeAsync() + { + if (this.module is null) + return; + + try + { + await this.module.InvokeVoidAsync("destroy", this.editorId); + await this.module.DisposeAsync(); + } + catch (JSDisconnectedException) + { + // The circuit can already be gone while Blazor disposes the component. + } + } + + private sealed record CodeEditorTheme( + string Background, + string Foreground, + string Border, + string Comment, + string String, + string Number, + string Keyword, + string Function, + string Constant); +} diff --git a/app/MindWork AI Studio/Components/CodeEditorLanguage.cs b/app/MindWork AI Studio/Components/CodeEditorLanguage.cs new file mode 100644 index 00000000..ddee4b06 --- /dev/null +++ b/app/MindWork AI Studio/Components/CodeEditorLanguage.cs @@ -0,0 +1,12 @@ +namespace AIStudio.Components; + +/// +/// Selects the syntax highlighter used by . +/// The enum value is passed to the JavaScript module as a string, so a new +/// language must also be handled in wwwroot/system/CodeEditor/code-editor.js. +/// +public enum CodeEditorLanguage +{ + PLAIN_TEXT, + LUA, +}