Markdown rendering of messages in chat panel
This commit is contained in:
parent
23b4ca4571
commit
326198bb1d
|
|
@ -12,6 +12,7 @@ import { ReferenceParser, FileReference, ReferenceMatch } from '../references/Re
|
||||||
import { ReferenceBox } from '../references/ReferenceBox';
|
import { ReferenceBox } from '../references/ReferenceBox';
|
||||||
import { AutocompleteItem } from '../references/AutocompleteManager';
|
import { AutocompleteItem } from '../references/AutocompleteManager';
|
||||||
import LLMAgentPlugin from 'main';
|
import LLMAgentPlugin from 'main';
|
||||||
|
import { MarkdownRenderer } from 'obsidian'; // Добавляем импорт MarkdownRenderer
|
||||||
|
|
||||||
export class ChatPanel {
|
export class ChatPanel {
|
||||||
container: HTMLElement;
|
container: HTMLElement;
|
||||||
|
|
@ -193,29 +194,36 @@ export class ChatPanel {
|
||||||
this.suggestionsContainer.style.display = 'none';
|
this.suggestionsContainer.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHistory(): void {
|
/**
|
||||||
|
* Рендерит историю сообщений в контейнер чата.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async renderHistory(): Promise<void> {
|
||||||
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
||||||
historyContainer.innerHTML = this.chatHistory
|
historyContainer.empty(); // Очищаем контейнер перед добавлением новых сообщений
|
||||||
.map(
|
|
||||||
(msg, index) => `
|
for (const msg of this.chatHistory) {
|
||||||
<div class="message ${msg.role} message-type-${msg.type || 'default'} ">
|
const messageEl = historyContainer.createDiv({ cls: `message ${msg.role} message-type-${msg.type || 'default'}` });
|
||||||
<div class="chat-meta">
|
|
||||||
<div class="chat-sender-info">
|
// Информация об отправителе
|
||||||
<div class="chat-message-icon">
|
const metaDiv = messageEl.createDiv({ cls: 'chat-meta' });
|
||||||
${
|
const senderInfoDiv = metaDiv.createDiv({ cls: 'chat-sender-info' });
|
||||||
msg.role === 'user'
|
const iconDiv = senderInfoDiv.createDiv({ cls: 'chat-message-icon' });
|
||||||
? `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`
|
iconDiv.innerHTML =
|
||||||
: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bot"><path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path></svg>`
|
msg.role === 'user'
|
||||||
}
|
? `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`
|
||||||
</div>
|
: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bot"><path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path></svg>`;
|
||||||
<span class="chat-role-label">${this.getRoleLabel(msg.role)}</span>
|
senderInfoDiv.createSpan({ cls: 'chat-role-label', text: this.getRoleLabel(msg.role) });
|
||||||
</div>
|
|
||||||
</div>
|
// Контент сообщения, рендерится Markdown
|
||||||
<div class="chat-message-content">${this.processMessageContent(msg.content)}</div>
|
const contentDiv = messageEl.createDiv({ cls: 'chat-message-content' });
|
||||||
</div>
|
await MarkdownRenderer.renderMarkdown(
|
||||||
`
|
msg.content,
|
||||||
)
|
contentDiv,
|
||||||
.join('');
|
'', // Путь к источнику, может быть пустым для сообщений чата
|
||||||
|
this.props.plugin // Компонент, необходимый для управления жизненным циклом рендера
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Прокручиваем к самому низу родительского контейнера (view-content)
|
// Прокручиваем к самому низу родительского контейнера (view-content)
|
||||||
if (this.chatHistory.length > 0) {
|
if (this.chatHistory.length > 0) {
|
||||||
|
|
@ -249,9 +257,14 @@ export class ChatPanel {
|
||||||
return content.replace(/<img([^>]*?)>/g, '<img$1 style="max-width: 100%; height: auto;">').replace(/\n/g, '<br>');
|
return content.replace(/<img([^>]*?)>/g, '<img$1 style="max-width: 100%; height: auto;">').replace(/\n/g, '<br>');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHistory(newHistory: ChatHistoryItem[]): void {
|
/**
|
||||||
|
* Обновляет историю чата и перерисовывает её.
|
||||||
|
* @param {ChatHistoryItem[]} newHistory - Новый массив элементов истории чата.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async updateHistory(newHistory: ChatHistoryItem[]): Promise<void> {
|
||||||
this.chatHistory = newHistory;
|
this.chatHistory = newHistory;
|
||||||
this.renderHistory();
|
await this.renderHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAvailableModels(models: string[]): void {
|
updateAvailableModels(models: string[]): void {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ export class ChatView extends ItemView {
|
||||||
type: msg.type || msg.role // Используем type, если есть, иначе role как fallback
|
type: msg.type || msg.role // Используем type, если есть, иначе role как fallback
|
||||||
})) || [];
|
})) || [];
|
||||||
if (this.chatPanel) {
|
if (this.chatPanel) {
|
||||||
this.chatPanel.updateHistory(this.chatHistory);
|
await this.chatPanel.updateHistory(this.chatHistory);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка загрузки сообщений:', error);
|
console.error('Ошибка загрузки сообщений:', error);
|
||||||
|
|
@ -181,9 +181,9 @@ export class ChatView extends ItemView {
|
||||||
this.titleUpdateTimer = setTimeout(() => {
|
this.titleUpdateTimer = setTimeout(() => {
|
||||||
console.log('Обновление графа для получения сгенерированных заголовков...');
|
console.log('Обновление графа для получения сгенерированных заголовков...');
|
||||||
if (this.selectedGraphId && this.currentNode) {
|
if (this.selectedGraphId && this.currentNode) {
|
||||||
this.plugin.eventBus.emit('graph-selected', {
|
this.plugin.eventBus.emit('graph-selected', {
|
||||||
graphId: this.selectedGraphId,
|
graphId: this.selectedGraphId,
|
||||||
currentNode: this.currentNode
|
currentNode: this.currentNode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.titleUpdateTimer = null;
|
this.titleUpdateTimer = null;
|
||||||
|
|
@ -220,12 +220,12 @@ export class ChatView extends ItemView {
|
||||||
* Обрабатывает событие начала нового чата. Сбрасывает текущее состояние чата
|
* Обрабатывает событие начала нового чата. Сбрасывает текущее состояние чата
|
||||||
* и очищает отображение истории.
|
* и очищает отображение истории.
|
||||||
*/
|
*/
|
||||||
handleNewChat(): void {
|
async handleNewChat(): Promise<void> {
|
||||||
this.chatHistory = [];
|
this.chatHistory = [];
|
||||||
this.currentNode = null;
|
this.currentNode = null;
|
||||||
this.selectedGraphId = null;
|
this.selectedGraphId = null;
|
||||||
if (this.chatPanel) {
|
if (this.chatPanel) {
|
||||||
this.chatPanel.updateHistory(this.chatHistory);
|
await this.chatPanel.updateHistory(this.chatHistory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,6 @@ export class GraphView extends ItemView {
|
||||||
*/
|
*/
|
||||||
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
async handleGraphSelected(data: { graphId: string; currentNode: string | null }): Promise<void> {
|
||||||
this.selectedGraphId = data.graphId;
|
this.selectedGraphId = data.graphId;
|
||||||
console.log("11111")
|
|
||||||
// currentNode здесь может быть неактуальным, fetchGraphData загрузит актуальный current_node_id
|
// currentNode здесь может быть неактуальным, fetchGraphData загрузит актуальный current_node_id
|
||||||
await this.fetchGraphData(data.graphId);
|
await this.fetchGraphData(data.graphId);
|
||||||
// Note: Больше не нужно эмитить 'graph-selected' обратно в ChatView, т.к. ChatView уже инициировал это.
|
// Note: Больше не нужно эмитить 'graph-selected' обратно в ChatView, т.к. ChatView уже инициировал это.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user