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 { AutocompleteItem } from '../references/AutocompleteManager';
|
||||
import LLMAgentPlugin from 'main';
|
||||
import { MarkdownRenderer } from 'obsidian'; // Добавляем импорт MarkdownRenderer
|
||||
|
||||
export class ChatPanel {
|
||||
container: HTMLElement;
|
||||
|
|
@ -193,29 +194,36 @@ export class ChatPanel {
|
|||
this.suggestionsContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
renderHistory(): void {
|
||||
/**
|
||||
* Рендерит историю сообщений в контейнер чата.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async renderHistory(): Promise<void> {
|
||||
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
||||
historyContainer.innerHTML = this.chatHistory
|
||||
.map(
|
||||
(msg, index) => `
|
||||
<div class="message ${msg.role} message-type-${msg.type || 'default'} ">
|
||||
<div class="chat-meta">
|
||||
<div class="chat-sender-info">
|
||||
<div class="chat-message-icon">
|
||||
${
|
||||
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>`
|
||||
: `<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>`
|
||||
}
|
||||
</div>
|
||||
<span class="chat-role-label">${this.getRoleLabel(msg.role)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-message-content">${this.processMessageContent(msg.content)}</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join('');
|
||||
historyContainer.empty(); // Очищаем контейнер перед добавлением новых сообщений
|
||||
|
||||
for (const msg of this.chatHistory) {
|
||||
const messageEl = historyContainer.createDiv({ cls: `message ${msg.role} message-type-${msg.type || 'default'}` });
|
||||
|
||||
// Информация об отправителе
|
||||
const metaDiv = messageEl.createDiv({ cls: 'chat-meta' });
|
||||
const senderInfoDiv = metaDiv.createDiv({ cls: 'chat-sender-info' });
|
||||
const iconDiv = senderInfoDiv.createDiv({ cls: 'chat-message-icon' });
|
||||
iconDiv.innerHTML =
|
||||
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>`
|
||||
: `<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>`;
|
||||
senderInfoDiv.createSpan({ cls: 'chat-role-label', text: this.getRoleLabel(msg.role) });
|
||||
|
||||
// Контент сообщения, рендерится Markdown
|
||||
const contentDiv = messageEl.createDiv({ cls: 'chat-message-content' });
|
||||
await MarkdownRenderer.renderMarkdown(
|
||||
msg.content,
|
||||
contentDiv,
|
||||
'', // Путь к источнику, может быть пустым для сообщений чата
|
||||
this.props.plugin // Компонент, необходимый для управления жизненным циклом рендера
|
||||
);
|
||||
}
|
||||
|
||||
// Прокручиваем к самому низу родительского контейнера (view-content)
|
||||
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>');
|
||||
}
|
||||
|
||||
updateHistory(newHistory: ChatHistoryItem[]): void {
|
||||
/**
|
||||
* Обновляет историю чата и перерисовывает её.
|
||||
* @param {ChatHistoryItem[]} newHistory - Новый массив элементов истории чата.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async updateHistory(newHistory: ChatHistoryItem[]): Promise<void> {
|
||||
this.chatHistory = newHistory;
|
||||
this.renderHistory();
|
||||
await this.renderHistory();
|
||||
}
|
||||
|
||||
updateAvailableModels(models: string[]): void {
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ export class ChatView extends ItemView {
|
|||
type: msg.type || msg.role // Используем type, если есть, иначе role как fallback
|
||||
})) || [];
|
||||
if (this.chatPanel) {
|
||||
this.chatPanel.updateHistory(this.chatHistory);
|
||||
await this.chatPanel.updateHistory(this.chatHistory);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки сообщений:', error);
|
||||
|
|
@ -181,9 +181,9 @@ export class ChatView extends ItemView {
|
|||
this.titleUpdateTimer = setTimeout(() => {
|
||||
console.log('Обновление графа для получения сгенерированных заголовков...');
|
||||
if (this.selectedGraphId && this.currentNode) {
|
||||
this.plugin.eventBus.emit('graph-selected', {
|
||||
graphId: this.selectedGraphId,
|
||||
currentNode: this.currentNode
|
||||
this.plugin.eventBus.emit('graph-selected', {
|
||||
graphId: this.selectedGraphId,
|
||||
currentNode: this.currentNode
|
||||
});
|
||||
}
|
||||
this.titleUpdateTimer = null;
|
||||
|
|
@ -220,12 +220,12 @@ export class ChatView extends ItemView {
|
|||
* Обрабатывает событие начала нового чата. Сбрасывает текущее состояние чата
|
||||
* и очищает отображение истории.
|
||||
*/
|
||||
handleNewChat(): void {
|
||||
async handleNewChat(): Promise<void> {
|
||||
this.chatHistory = [];
|
||||
this.currentNode = null;
|
||||
this.selectedGraphId = null;
|
||||
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> {
|
||||
this.selectedGraphId = data.graphId;
|
||||
console.log("11111")
|
||||
// currentNode здесь может быть неактуальным, fetchGraphData загрузит актуальный current_node_id
|
||||
await this.fetchGraphData(data.graphId);
|
||||
// Note: Больше не нужно эмитить 'graph-selected' обратно в ChatView, т.к. ChatView уже инициировал это.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user