VoicePanel - output in markdown format

This commit is contained in:
dimitrievgs 2026-05-02 00:47:40 +03:00
parent fde784afbf
commit f2afaa4836
2 changed files with 48 additions and 14 deletions

View File

@ -1,4 +1,5 @@
import LLMAgentPlugin from 'main'; import LLMAgentPlugin from 'main';
import { MarkdownRenderer } from 'obsidian';
export class VoicePanel { export class VoicePanel {
private activeTab: 'res1' | 'res2' | 'trans' = 'res1'; private activeTab: 'res1' | 'res2' | 'trans' = 'res1';
@ -30,7 +31,6 @@ export class VoicePanel {
</div> </div>
`; `;
// Навешиваем логику вкладок
this.container.querySelectorAll('.v-tab').forEach((tab) => { this.container.querySelectorAll('.v-tab').forEach((tab) => {
tab.addEventListener('click', (e) => { tab.addEventListener('click', (e) => {
this.container.querySelectorAll('.v-tab').forEach((t) => t.classList.remove('active')); this.container.querySelectorAll('.v-tab').forEach((t) => t.classList.remove('active'));
@ -39,7 +39,6 @@ export class VoicePanel {
}); });
}); });
// Навешиваем управление через API
const control = async (action: string) => { const control = async (action: string) => {
await fetch(`${this.plugin.settings.apiBaseUrl}/voice/control`, { await fetch(`${this.plugin.settings.apiBaseUrl}/voice/control`, {
method: 'POST', method: 'POST',
@ -55,21 +54,49 @@ export class VoicePanel {
async startPolling() { async startPolling() {
setInterval(async () => { setInterval(async () => {
const res = await fetch(`${this.plugin.settings.apiBaseUrl}/voice/status`); try {
const data = await res.json(); const res = await fetch(`${this.plugin.settings.apiBaseUrl}/voice/status`);
this.updateContent(data); const data = await res.json();
}, 3000); this.updateContent(data);
} catch (e) {
console.error("Voice status fetch error", e);
}
}, 1500);
} }
updateContent(data: any) { async updateContent(data: any) {
const body = this.container.querySelector('#v-body'); const body = this.container.querySelector('#v-body') as HTMLElement;
if (!body) return; if (!body) return;
if (data.obsidian_settings_fetched == false) // если это не сделать, то на беке останутся пустые настройки, если обсидиан запущен раньше бека
{ if (data.obsidian_settings_fetched == false) {
this.plugin.syncSettings(); this.plugin.syncSettings();
} }
if (this.activeTab === 'trans') body.textContent = data.transcription;
if (this.activeTab === 'res1') body.textContent = data.response1; // Выбираем контент для отображения
if (this.activeTab === 'res2') body.innerHTML = data.response2.join('<br>---<br>'); let contentToRender = "";
if (this.activeTab === 'trans') {
// Транскрипцию обычно выводим как простой текст (или тоже можно через МК)
body.innerText = data.transcription || "";
return;
}
if (this.activeTab === 'res1') {
contentToRender = data.response1 || "";
} else if (this.activeTab === 'res2') {
// Склеиваем массив ответов через горизонтальную линию Markdown
contentToRender = Array.isArray(data.response2)
? data.response2.join('\n\n---\n\n')
: (data.response2 || "");
}
// Очищаем и рендерим Markdown
body.empty();
await MarkdownRenderer.renderMarkdown(
contentToRender,
body,
'',
this.plugin
);
} }
} }

View File

@ -781,6 +781,8 @@
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
user-select: text; /* Разрешает выделение текста */
-webkit-user-select: text; /* Для совместимости с Obsidian/Electron */
} }
.voice-body { .voice-body {
@ -790,6 +792,9 @@
border: 1px inset var(--background-modifier-border); border: 1px inset var(--background-modifier-border);
margin: 4px; margin: 4px;
padding: 8px; padding: 8px;
user-select: text;
-webkit-user-select: text;
cursor: text; /* Меняет курсор на текстовый при наведении */
} }
.voice-header { .voice-header {
@ -823,6 +828,8 @@
.v-controls button { .v-controls button {
margin-right: 5px; margin-right: 5px;
padding: 4px 10px; padding: 4px 10px;
user-select: none;
-webkit-user-select: none;
} }
.llm-agent-history-sidebar { .llm-agent-history-sidebar {