From c5e2373d731b4ac1509be0a034b2fb125b817b45 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Wed, 20 Aug 2025 16:14:43 -0700 Subject: [PATCH] Make khoj obsidian keyboard shortcuts toggle voice chat, chat history Previously hitting voice chat keybinding would just start voice chat, not end it and just open chat history and not close it. This is unintuitive and different from the equivalent button click behaviors. Fix toggles voice chat on/off and shows/hides chat history when hit Ctrl+Alt+V, Ctrl+Alt+O keybindings in khoj obsidian chat view --- src/interface/obsidian/src/chat_view.ts | 7 +++++-- src/interface/obsidian/src/main.ts | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/interface/obsidian/src/chat_view.ts b/src/interface/obsidian/src/chat_view.ts index af88b08c..ebfb36bd 100644 --- a/src/interface/obsidian/src/chat_view.ts +++ b/src/interface/obsidian/src/chat_view.ts @@ -72,6 +72,7 @@ export class KhojChatView extends KhojPaneView { keyPressTimeout: NodeJS.Timeout | null = null; userMessages: string[] = []; // Store user sent messages for input history cycling currentMessageIndex: number = -1; // Track current message index in userMessages array + voiceChatActive: boolean = false; // Flag to track if voice chat is active private currentUserInput: string = ""; // Stores the current user input that is being typed in chat private startingMessage: string = this.getLearningMoment(); chatMessageState: ChatMessageState; @@ -131,7 +132,7 @@ export class KhojChatView extends KhojPaneView { this.scope = new Scope(this.app.scope); this.scope.register(["Ctrl", "Alt"], 'n', (_) => this.createNewConversation(this.currentAgent)); this.scope.register(["Ctrl", "Alt"], 'o', async (_) => await this.toggleChatSessions()); - this.scope.register(["Ctrl", "Alt"], 'v', (_) => this.speechToText(new KeyboardEvent('keydown'))); + this.scope.register(["Ctrl", "Alt"], 'v', (_) => this.speechToText(this.voiceChatActive ? new KeyboardEvent('keyup') : new KeyboardEvent('keydown'))); this.scope.register(["Ctrl"], 'f', (_) => new KhojSearchModal(this.app, this.setting).open()); this.scope.register(["Ctrl"], 'r', (_) => { this.activateView(KhojView.SIMILAR); }); } @@ -340,7 +341,7 @@ export class KhojChatView extends KhojPaneView { attr: { id: "khoj-transcribe", class: "khoj-transcribe khoj-input-row-button clickable-icon ", - title: "Start Voice Chat (Ctrl+Alt+V)", + title: "Hold to Voice Chat (Ctrl+Alt+V)", }, }) transcribe.addEventListener('mousedown', (event) => { this.startSpeechToText(event) }); @@ -1741,6 +1742,7 @@ export class KhojChatView extends KhojPaneView { // Toggle recording if (!this.mediaRecorder || this.mediaRecorder.state === 'inactive' || event.type === 'touchstart' || event.type === 'mousedown' || event.type === 'keydown') { + this.voiceChatActive = true; navigator.mediaDevices .getUserMedia({ audio: true }) ?.then(handleRecording) @@ -1748,6 +1750,7 @@ export class KhojChatView extends KhojPaneView { this.flashStatusInChatInput("⛔️ Failed to access microphone"); }); } else if (this.mediaRecorder?.state === 'recording' || event.type === 'touchend' || event.type === 'touchcancel' || event.type === 'mouseup' || event.type === 'keyup') { + this.voiceChatActive = false; this.mediaRecorder.stop(); this.mediaRecorder.stream.getTracks().forEach(track => track.stop()); this.mediaRecorder = undefined; diff --git a/src/interface/obsidian/src/main.ts b/src/interface/obsidian/src/main.ts index 86342f64..b0c8d7d0 100644 --- a/src/interface/obsidian/src/main.ts +++ b/src/interface/obsidian/src/main.ts @@ -73,7 +73,7 @@ export default class Khoj extends Plugin { this.activateView(KhojView.CHAT).then(() => { const chatView = this.app.workspace.getActiveViewOfType(KhojChatView); if (chatView) { - chatView.toggleChatSessions(true); + chatView.toggleChatSessions(); } }); } @@ -88,8 +88,9 @@ export default class Khoj extends Plugin { this.activateView(KhojView.CHAT).then(() => { const chatView = this.app.workspace.getActiveViewOfType(KhojChatView); if (chatView) { - // Trigger speech to text functionality - chatView.speechToText(new KeyboardEvent('keydown')); + // Toggle speech to text functionality + const toggleEvent = chatView.voiceChatActive ? 'keyup' : 'keydown'; + chatView.speechToText(new KeyboardEvent(toggleEvent)); } }); }