mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-03-30 20:51:38 +00:00
Works now
This commit is contained in:
parent
1c52d6f199
commit
8a5539cdfd
@ -1594,15 +1594,30 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1142475422"] = "Are you s
|
||||
-- Stop generation
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1317408357"] = "Stop generation"
|
||||
|
||||
-- Insert heading formatting
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1347686985"] = "Insert heading formatting"
|
||||
|
||||
-- Save chat
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1516264254"] = "Save chat"
|
||||
|
||||
-- Insert italic formatting
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T182467363"] = "Insert italic formatting"
|
||||
|
||||
-- Type your input here...
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1849313532"] = "Type your input here..."
|
||||
|
||||
-- Insert bulleted list formatting
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1850228954"] = "Insert bulleted list formatting"
|
||||
|
||||
-- Your Prompt (use selected instance '{0}', provider '{1}')
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T1967611328"] = "Your Prompt (use selected instance '{0}', provider '{1}')"
|
||||
|
||||
-- Insert code formatting
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2278685708"] = "Insert code formatting"
|
||||
|
||||
-- Insert bold formatting
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T265791106"] = "Insert bold formatting"
|
||||
|
||||
-- Profile usage is disabled according to your chat template settings.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::CHATCOMPONENT::T2670286472"] = "Profile usage is disabled according to your chat template settings."
|
||||
|
||||
|
||||
@ -55,6 +55,22 @@
|
||||
Style="@this.UserInputStyle"/>
|
||||
</MudElement>
|
||||
<MudToolBar WrapContent="true" Gutters="@false" Class="border border-solid rounded" Style="border-color: lightgrey;">
|
||||
<MudTooltip Text="@T("Insert code formatting")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Code" OnClick="() => this.ApplyMarkdownFormat(MARKDOWN_CODE)" Disabled="@this.IsInputForbidden()"/>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="@T("Insert bold formatting")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.FormatBold" OnClick="() => this.ApplyMarkdownFormat(MARKDOWN_BOLD)" Disabled="@this.IsInputForbidden()"/>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="@T("Insert italic formatting")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.FormatItalic" OnClick="() => this.ApplyMarkdownFormat(MARKDOWN_ITALIC)" Disabled="@this.IsInputForbidden()"/>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="@T("Insert heading formatting")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.TextFields" OnClick="() => this.ApplyMarkdownFormat(MARKDOWN_HEADING)" Disabled="@this.IsInputForbidden()"/>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="@T("Insert bulleted list formatting")" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.FormatListBulleted" OnClick="() => this.ApplyMarkdownFormat(MARKDOWN_BULLET_LIST)" Disabled="@this.IsInputForbidden()"/>
|
||||
</MudTooltip>
|
||||
|
||||
@if (
|
||||
this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES
|
||||
&& this.SettingsManager.ConfigurationData.Workspace.DisplayBehavior is WorkspaceDisplayBehavior.TOGGLE_OVERLAY)
|
||||
|
||||
@ -6,6 +6,7 @@ using AIStudio.Settings.DataModel;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
using DialogOptions = AIStudio.Dialogs.DialogOptions;
|
||||
|
||||
@ -13,6 +14,13 @@ namespace AIStudio.Components;
|
||||
|
||||
public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
{
|
||||
private const string CHAT_INPUT_ID = "chat-user-input";
|
||||
private const string MARKDOWN_CODE = "code";
|
||||
private const string MARKDOWN_BOLD = "bold";
|
||||
private const string MARKDOWN_ITALIC = "italic";
|
||||
private const string MARKDOWN_HEADING = "heading";
|
||||
private const string MARKDOWN_BULLET_LIST = "bullet_list";
|
||||
|
||||
[Parameter]
|
||||
public ChatThread? ChatThread { get; set; }
|
||||
|
||||
@ -37,6 +45,9 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JsRuntime { get; init; } = null!;
|
||||
|
||||
private const Placement TOOLBAR_TOOLTIP_PLACEMENT = Placement.Top;
|
||||
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
|
||||
@ -73,6 +84,7 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
// Configure the spellchecking for the user input:
|
||||
this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES);
|
||||
USER_INPUT_ATTRIBUTES["id"] = CHAT_INPUT_ID;
|
||||
|
||||
// Get the preselected profile:
|
||||
this.currentProfile = this.SettingsManager.GetPreselectedProfile(Tools.Components.CHAT);
|
||||
@ -464,6 +476,18 @@ public partial class ChatComponent : MSGComponentBase, IAsyncDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyMarkdownFormat(string formatType)
|
||||
{
|
||||
if (this.IsInputForbidden())
|
||||
return;
|
||||
|
||||
if(this.dataSourceSelectionComponent?.IsVisible ?? false)
|
||||
this.dataSourceSelectionComponent.Hide();
|
||||
|
||||
this.userInput = await this.JsRuntime.InvokeAsync<string>("formatChatInputMarkdown", CHAT_INPUT_ID, formatType);
|
||||
this.hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
private async Task SendMessage(bool reuseLastUserPrompt = false)
|
||||
{
|
||||
if (!this.IsProviderSelected)
|
||||
|
||||
@ -26,3 +26,108 @@ window.clearDiv = function (divName) {
|
||||
window.scrollToBottom = function(element) {
|
||||
element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' });
|
||||
}
|
||||
|
||||
window.formatChatInputMarkdown = function (inputId, formatType) {
|
||||
let input = document.getElementById(inputId)
|
||||
if (input && input.tagName !== 'TEXTAREA' && input.tagName !== 'INPUT')
|
||||
input = input.querySelector('textarea, input')
|
||||
|
||||
if (!input)
|
||||
return ''
|
||||
|
||||
input.focus()
|
||||
|
||||
const value = input.value ?? ''
|
||||
const start = input.selectionStart ?? value.length
|
||||
const end = input.selectionEnd ?? value.length
|
||||
const hasSelection = end > start
|
||||
const selectedText = value.substring(start, end)
|
||||
|
||||
let insertedText = ''
|
||||
let selectionStart = start
|
||||
let selectionEnd = start
|
||||
|
||||
switch (formatType) {
|
||||
case 'bold': {
|
||||
const text = hasSelection ? selectedText : 'bold text'
|
||||
insertedText = `**${text}**`
|
||||
selectionStart = start + 2
|
||||
selectionEnd = selectionStart + text.length
|
||||
break
|
||||
}
|
||||
|
||||
case 'italic': {
|
||||
const text = hasSelection ? selectedText : 'italic text'
|
||||
insertedText = `*${text}*`
|
||||
selectionStart = start + 1
|
||||
selectionEnd = selectionStart + text.length
|
||||
break
|
||||
}
|
||||
|
||||
case 'heading': {
|
||||
if (hasSelection) {
|
||||
insertedText = selectedText
|
||||
.split('\n')
|
||||
.map(line => line.startsWith('# ') ? line : `# ${line}`)
|
||||
.join('\n')
|
||||
|
||||
selectionStart = start
|
||||
selectionEnd = start + insertedText.length
|
||||
} else {
|
||||
const text = 'Heading'
|
||||
insertedText = `# ${text}`
|
||||
selectionStart = start + 2
|
||||
selectionEnd = selectionStart + text.length
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'bullet_list': {
|
||||
if (hasSelection) {
|
||||
insertedText = selectedText
|
||||
.split('\n')
|
||||
.map(line => line.startsWith('- ') ? line : `- ${line}`)
|
||||
.join('\n')
|
||||
|
||||
selectionStart = start
|
||||
selectionEnd = start + insertedText.length
|
||||
} else {
|
||||
insertedText = '- '
|
||||
selectionStart = start + 2
|
||||
selectionEnd = start + insertedText.length
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'code':
|
||||
default: {
|
||||
if (hasSelection) {
|
||||
if (selectedText.includes('\n')) {
|
||||
insertedText = `\`\`\`\n${selectedText}\n\`\`\``
|
||||
selectionStart = start + 4
|
||||
selectionEnd = selectionStart + selectedText.length
|
||||
} else {
|
||||
insertedText = `\`${selectedText}\``
|
||||
selectionStart = start + 1
|
||||
selectionEnd = selectionStart + selectedText.length
|
||||
}
|
||||
} else {
|
||||
const text = 'code'
|
||||
insertedText = `\`\`\`\n${text}\n\`\`\``
|
||||
selectionStart = start + 4
|
||||
selectionEnd = selectionStart + text.length
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const nextValue = value.slice(0, start) + insertedText + value.slice(end)
|
||||
input.value = nextValue
|
||||
input.setSelectionRange(selectionStart, selectionEnd)
|
||||
input.dispatchEvent(new Event('input', { bubbles: true }))
|
||||
|
||||
return nextValue
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user