From 4eb24038b6f4d67d4147204c9c0ebc246198a535 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Tue, 24 Feb 2026 20:25:38 -0800 Subject: [PATCH] feat: add Alt+P keyboard shortcut for PiP pop-out - Alt+P toggles Picture-in-Picture floating recorder on /voice page - Works from both main window and PiP window - Footer shows new shortcut hint when PiP is supported - Browser extension Ctrl+Shift+V now opens PWA /voice page (with PiP) instead of extension-local voice.html Co-Authored-By: Claude Opus 4.6 --- browser-extension/background.js | 9 +++++---- browser-extension/popup.js | 11 ++++++----- src/app/voice/page.tsx | 23 ++++++++++++++++++++--- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/browser-extension/background.js b/browser-extension/background.js index 20ac1c8..a07f8b3 100644 --- a/browser-extension/background.js +++ b/browser-extension/background.js @@ -293,13 +293,14 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => { // --- Keyboard shortcut handler --- -chrome.commands.onCommand.addListener((command) => { +chrome.commands.onCommand.addListener(async (command) => { if (command === 'open-voice-recorder') { + const settings = await getSettings(); chrome.windows.create({ - url: chrome.runtime.getURL('voice.html'), + url: `${settings.host}/voice`, type: 'popup', - width: 380, - height: 520, + width: 400, + height: 600, focused: true, }); } diff --git a/browser-extension/popup.js b/browser-extension/popup.js index 8639181..4a9f1f7 100644 --- a/browser-extension/popup.js +++ b/browser-extension/popup.js @@ -300,13 +300,14 @@ document.getElementById('unlockBtn').addEventListener('click', async () => { } }); -document.getElementById('voiceBtn').addEventListener('click', () => { - // Open voice recorder in a small popup window +document.getElementById('voiceBtn').addEventListener('click', async () => { + // Open rVoice PWA page in a popup window (supports PiP pop-out) + const settings = await getSettings(); chrome.windows.create({ - url: chrome.runtime.getURL('voice.html'), + url: `${settings.host}/voice`, type: 'popup', - width: 380, - height: 520, + width: 400, + height: 600, focused: true, }); // Close the current popup diff --git a/src/app/voice/page.tsx b/src/app/voice/page.tsx index 94fb9d0..8459708 100644 --- a/src/app/voice/page.tsx +++ b/src/app/voice/page.tsx @@ -666,10 +666,16 @@ export default function VoicePage() { e.preventDefault(); saveToRNotes(); } + // Alt+P toggles PiP + if (e.altKey && e.code === 'KeyP') { + e.preventDefault(); + if (pipWindow) closePiP(); + else openPiP(); + } }; window.addEventListener('keydown', handler); return () => window.removeEventListener('keydown', handler); - }, [toggleRecording, saveToRNotes, state]); + }, [toggleRecording, saveToRNotes, state, pipWindow, openPiP, closePiP]); // Keyboard events inside PiP window useEffect(() => { @@ -687,12 +693,17 @@ export default function VoicePage() { ke.preventDefault(); saveToRNotes(); } + // Alt+P closes PiP from within PiP window + if (ke.altKey && ke.code === 'KeyP') { + ke.preventDefault(); + closePiP(); + } }; pipWindow.document.addEventListener('keydown', handler); return () => { try { pipWindow.document.removeEventListener('keydown', handler); } catch {} }; - }, [pipWindow, toggleRecording, saveToRNotes, state]); + }, [pipWindow, toggleRecording, saveToRNotes, state, closePiP]); // --- Render --- @@ -1032,8 +1043,14 @@ export default function VoicePage() {
Space record - Ctrl+Enter + Ctrl+⏎ save + {pipSupported && ( + <> + Alt+P + pop out + + )}
rNotes.online