diff --git a/src/components/VoicePanel.ts b/src/components/VoicePanel.ts
index c4cf4bd..657beda 100644
--- a/src/components/VoicePanel.ts
+++ b/src/components/VoicePanel.ts
@@ -1,4 +1,5 @@
import LLMAgentPlugin from 'main';
+import { MarkdownRenderer } from 'obsidian';
export class VoicePanel {
private activeTab: 'res1' | 'res2' | 'trans' = 'res1';
@@ -30,7 +31,6 @@ export class VoicePanel {
`;
- // Навешиваем логику вкладок
this.container.querySelectorAll('.v-tab').forEach((tab) => {
tab.addEventListener('click', (e) => {
this.container.querySelectorAll('.v-tab').forEach((t) => t.classList.remove('active'));
@@ -39,7 +39,6 @@ export class VoicePanel {
});
});
- // Навешиваем управление через API
const control = async (action: string) => {
await fetch(`${this.plugin.settings.apiBaseUrl}/voice/control`, {
method: 'POST',
@@ -55,21 +54,49 @@ export class VoicePanel {
async startPolling() {
setInterval(async () => {
- const res = await fetch(`${this.plugin.settings.apiBaseUrl}/voice/status`);
- const data = await res.json();
- this.updateContent(data);
- }, 3000);
+ try {
+ const res = await fetch(`${this.plugin.settings.apiBaseUrl}/voice/status`);
+ const data = await res.json();
+ this.updateContent(data);
+ } catch (e) {
+ console.error("Voice status fetch error", e);
+ }
+ }, 1500);
}
- updateContent(data: any) {
- const body = this.container.querySelector('#v-body');
+ async updateContent(data: any) {
+ const body = this.container.querySelector('#v-body') as HTMLElement;
if (!body) return;
- if (data.obsidian_settings_fetched == false) // если это не сделать, то на беке останутся пустые настройки, если обсидиан запущен раньше бека
- {
+
+ if (data.obsidian_settings_fetched == false) {
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('
---
');
+
+ // Выбираем контент для отображения
+ 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
+ );
}
-}
+}
\ No newline at end of file
diff --git a/src/css/styles.css b/src/css/styles.css
index 2c2b641..ac22bfd 100644
--- a/src/css/styles.css
+++ b/src/css/styles.css
@@ -781,6 +781,8 @@
height: 100%;
display: flex;
flex-direction: column;
+ user-select: text; /* Разрешает выделение текста */
+ -webkit-user-select: text; /* Для совместимости с Obsidian/Electron */
}
.voice-body {
@@ -790,6 +792,9 @@
border: 1px inset var(--background-modifier-border);
margin: 4px;
padding: 8px;
+ user-select: text;
+ -webkit-user-select: text;
+ cursor: text; /* Меняет курсор на текстовый при наведении */
}
.voice-header {
@@ -823,6 +828,8 @@
.v-controls button {
margin-right: 5px;
padding: 4px 10px;
+ user-select: none;
+ -webkit-user-select: none;
}
.llm-agent-history-sidebar {