Add setting to show or hide voice panel
This commit is contained in:
parent
89e57198ad
commit
b8382c2d4f
16
main.ts
16
main.ts
|
|
@ -43,6 +43,8 @@ interface LLMAgentSettings {
|
|||
markerStart: string;
|
||||
markerStop: string;
|
||||
|
||||
showVoicePanel: boolean;
|
||||
|
||||
lastActiveGraphId: string | null;
|
||||
lastActiveNodeId: string | null;
|
||||
}
|
||||
|
|
@ -76,6 +78,8 @@ const DEFAULT_SETTINGS: LLMAgentSettings = {
|
|||
markerStart: 'старт',
|
||||
markerStop: 'стоп',
|
||||
|
||||
showVoicePanel: false,
|
||||
|
||||
lastActiveGraphId: null,
|
||||
lastActiveNodeId: null,
|
||||
};
|
||||
|
|
@ -365,6 +369,18 @@ class SampleSettingTab extends PluginSettingTab {
|
|||
|
||||
containerEl.createEl('h2', { text: 'Голосовое управление (Voice Service)' });
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Отображать голосовую панель')
|
||||
.setDesc('Показывать нижнюю панель Voice Service в графе диалогов.')
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.showVoicePanel).onChange(async (value) => {
|
||||
this.plugin.settings.showVoicePanel = value;
|
||||
await this.plugin.saveSettings();
|
||||
// Событие 'settings-changed' уже вызывается внутри saveSettings,
|
||||
// поэтому панель будет скрываться/появляться мгновенно
|
||||
})
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Модель команд')
|
||||
.setDesc('LLM для обработки голосовых команд.')
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { MarkdownRenderer, setIcon, Notice } from 'obsidian';
|
|||
|
||||
export class VoicePanel {
|
||||
private activeTab: 'res1' | 'res2' | 'trans' | 'metrics' = 'res1';
|
||||
private pollInterval: any = null;
|
||||
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
|
|
@ -58,7 +59,9 @@ export class VoicePanel {
|
|||
}
|
||||
|
||||
async startPolling() {
|
||||
setInterval(async () => {
|
||||
if (this.pollInterval) return; // <-- ЗАЩИТА ОТ ДУБЛИКАТОВ ТАЙМЕРА
|
||||
|
||||
this.pollInterval = setInterval(async () => { // <-- ПРИСВАИВАЕМ pollInterval
|
||||
try {
|
||||
const res = await fetch(`${this.plugin.settings.apiBaseUrl}/voice/status`);
|
||||
const data = await res.json();
|
||||
|
|
@ -199,4 +202,16 @@ export class VoicePanel {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
public stopPolling() {
|
||||
if (this.pollInterval) {
|
||||
clearInterval(this.pollInterval);
|
||||
this.pollInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.stopPolling();
|
||||
this.container.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ export class GraphView extends ItemView {
|
|||
toggleButton: HTMLButtonElement;
|
||||
isHistoryCollapsed: boolean;
|
||||
|
||||
resizer: HTMLDivElement;
|
||||
voiceContainer: HTMLDivElement;
|
||||
voicePanelInstance: VoicePanel | null = null;
|
||||
|
||||
// Глобальные кнопки действий
|
||||
copySelectedButton: HTMLButtonElement | null = null;
|
||||
deleteSelectedButton: HTMLButtonElement | null = null;
|
||||
|
|
@ -117,8 +121,8 @@ export class GraphView extends ItemView {
|
|||
this.graphContainer.style.cssText = `flex: 1; position: relative; background-color: var(--background-primary);`;
|
||||
|
||||
// 2. РАЗДЕЛИТЕЛЬ (Resizer)
|
||||
const resizer = mainContainer.createDiv('voice-panel-resizer');
|
||||
resizer.style.cssText = `
|
||||
this.resizer = mainContainer.createDiv('voice-panel-resizer');
|
||||
this.resizer.style.cssText = `
|
||||
height: 4px;
|
||||
width: 100%;
|
||||
cursor: ns-resize;
|
||||
|
|
@ -128,9 +132,9 @@ export class GraphView extends ItemView {
|
|||
`;
|
||||
|
||||
// 3. Нижняя панель
|
||||
const voiceContainer = mainContainer.createDiv('voice-panel-fixed-bottom');
|
||||
this.voiceContainer = mainContainer.createDiv('voice-panel-fixed-bottom');
|
||||
let initialHeight = 150; // Высота по умолчанию
|
||||
voiceContainer.style.cssText = `
|
||||
this.voiceContainer.style.cssText = `
|
||||
height: ${initialHeight}px;
|
||||
width: 100%;
|
||||
background-color: var(--background-secondary);
|
||||
|
|
@ -141,7 +145,7 @@ export class GraphView extends ItemView {
|
|||
// ЛОГИКА ИЗМЕНЕНИЯ ВЫСОТЫ
|
||||
let isResizing = false;
|
||||
|
||||
resizer.addEventListener('mousedown', (e) => {
|
||||
this.resizer.addEventListener('mousedown', (e) => {
|
||||
isResizing = true;
|
||||
document.body.style.cursor = 'ns-resize';
|
||||
// Чтобы iframe/график не перехватывали события мыши
|
||||
|
|
@ -157,7 +161,7 @@ export class GraphView extends ItemView {
|
|||
|
||||
// Ограничения (мин 50px, макс 70% высоты)
|
||||
if (newHeight > 50 && newHeight < containerRect.height * 0.7) {
|
||||
voiceContainer.style.height = `${newHeight}px`;
|
||||
this.voiceContainer.style.height = `${newHeight}px`;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -181,7 +185,12 @@ export class GraphView extends ItemView {
|
|||
this.initializeGraphPanel();
|
||||
|
||||
// Инициализируем VoicePanel
|
||||
new VoicePanel(voiceContainer, this.plugin);
|
||||
if (this.plugin.settings.showVoicePanel) {
|
||||
this.voicePanelInstance = new VoicePanel(this.voiceContainer, this.plugin);
|
||||
} else {
|
||||
this.resizer.style.display = 'none';
|
||||
this.voiceContainer.style.display = 'none';
|
||||
}
|
||||
|
||||
// Подписки на события
|
||||
this.setupEventListeners();
|
||||
|
|
@ -204,6 +213,7 @@ export class GraphView extends ItemView {
|
|||
this.plugin.eventBus.on('ws-node-type-changed', this.handleNodeTypeChanged.bind(this));
|
||||
this.plugin.eventBus.on('stream-started', this.handleStreamStarted.bind(this));
|
||||
this.plugin.eventBus.on('stream-ended', this.handleStreamEnded.bind(this));
|
||||
this.plugin.eventBus.on('settings-changed', this.handleSettingsChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -234,6 +244,13 @@ export class GraphView extends ItemView {
|
|||
|
||||
this.plugin.eventBus.off('stream-started', this.handleStreamStarted);
|
||||
this.plugin.eventBus.off('stream-ended', this.handleStreamEnded);
|
||||
|
||||
this.plugin.eventBus.off('settings-changed', this.handleSettingsChanged);
|
||||
|
||||
if (this.voicePanelInstance) {
|
||||
this.voicePanelInstance.destroy();
|
||||
this.voicePanelInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Save graph id ---------------------------------------------------
|
||||
|
|
@ -815,6 +832,26 @@ export class GraphView extends ItemView {
|
|||
this.activeStreamControllers.delete(data.nodeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрабатывает изменение настроек и мгновенно перерисовывает VoicePanel
|
||||
*/
|
||||
private handleSettingsChanged = () => {
|
||||
if (this.plugin.settings.showVoicePanel) {
|
||||
this.resizer.style.display = '';
|
||||
this.voiceContainer.style.display = 'flex';
|
||||
if (!this.voicePanelInstance) {
|
||||
this.voicePanelInstance = new VoicePanel(this.voiceContainer, this.plugin);
|
||||
}
|
||||
} else {
|
||||
this.resizer.style.display = 'none';
|
||||
this.voiceContainer.style.display = 'none';
|
||||
if (this.voicePanelInstance) {
|
||||
this.voicePanelInstance.destroy();
|
||||
this.voicePanelInstance = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------- WebSocket Event Handlers ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user