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