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 <noreply@anthropic.com>
This commit is contained in:
parent
a6ae90fd62
commit
4eb24038b6
|
|
@ -293,13 +293,14 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => {
|
||||||
|
|
||||||
// --- Keyboard shortcut handler ---
|
// --- Keyboard shortcut handler ---
|
||||||
|
|
||||||
chrome.commands.onCommand.addListener((command) => {
|
chrome.commands.onCommand.addListener(async (command) => {
|
||||||
if (command === 'open-voice-recorder') {
|
if (command === 'open-voice-recorder') {
|
||||||
|
const settings = await getSettings();
|
||||||
chrome.windows.create({
|
chrome.windows.create({
|
||||||
url: chrome.runtime.getURL('voice.html'),
|
url: `${settings.host}/voice`,
|
||||||
type: 'popup',
|
type: 'popup',
|
||||||
width: 380,
|
width: 400,
|
||||||
height: 520,
|
height: 600,
|
||||||
focused: true,
|
focused: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -300,13 +300,14 @@ document.getElementById('unlockBtn').addEventListener('click', async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('voiceBtn').addEventListener('click', () => {
|
document.getElementById('voiceBtn').addEventListener('click', async () => {
|
||||||
// Open voice recorder in a small popup window
|
// Open rVoice PWA page in a popup window (supports PiP pop-out)
|
||||||
|
const settings = await getSettings();
|
||||||
chrome.windows.create({
|
chrome.windows.create({
|
||||||
url: chrome.runtime.getURL('voice.html'),
|
url: `${settings.host}/voice`,
|
||||||
type: 'popup',
|
type: 'popup',
|
||||||
width: 380,
|
width: 400,
|
||||||
height: 520,
|
height: 600,
|
||||||
focused: true,
|
focused: true,
|
||||||
});
|
});
|
||||||
// Close the current popup
|
// Close the current popup
|
||||||
|
|
|
||||||
|
|
@ -666,10 +666,16 @@ export default function VoicePage() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
saveToRNotes();
|
saveToRNotes();
|
||||||
}
|
}
|
||||||
|
// Alt+P toggles PiP
|
||||||
|
if (e.altKey && e.code === 'KeyP') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (pipWindow) closePiP();
|
||||||
|
else openPiP();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('keydown', handler);
|
window.addEventListener('keydown', handler);
|
||||||
return () => window.removeEventListener('keydown', handler);
|
return () => window.removeEventListener('keydown', handler);
|
||||||
}, [toggleRecording, saveToRNotes, state]);
|
}, [toggleRecording, saveToRNotes, state, pipWindow, openPiP, closePiP]);
|
||||||
|
|
||||||
// Keyboard events inside PiP window
|
// Keyboard events inside PiP window
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -687,12 +693,17 @@ export default function VoicePage() {
|
||||||
ke.preventDefault();
|
ke.preventDefault();
|
||||||
saveToRNotes();
|
saveToRNotes();
|
||||||
}
|
}
|
||||||
|
// Alt+P closes PiP from within PiP window
|
||||||
|
if (ke.altKey && ke.code === 'KeyP') {
|
||||||
|
ke.preventDefault();
|
||||||
|
closePiP();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pipWindow.document.addEventListener('keydown', handler);
|
pipWindow.document.addEventListener('keydown', handler);
|
||||||
return () => {
|
return () => {
|
||||||
try { pipWindow.document.removeEventListener('keydown', handler); } catch {}
|
try { pipWindow.document.removeEventListener('keydown', handler); } catch {}
|
||||||
};
|
};
|
||||||
}, [pipWindow, toggleRecording, saveToRNotes, state]);
|
}, [pipWindow, toggleRecording, saveToRNotes, state, closePiP]);
|
||||||
|
|
||||||
// --- Render ---
|
// --- Render ---
|
||||||
|
|
||||||
|
|
@ -1032,8 +1043,14 @@ export default function VoicePage() {
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<kbd className="px-1.5 py-0.5 bg-slate-900 border border-slate-700 rounded text-[10px]">Space</kbd>
|
<kbd className="px-1.5 py-0.5 bg-slate-900 border border-slate-700 rounded text-[10px]">Space</kbd>
|
||||||
<span>record</span>
|
<span>record</span>
|
||||||
<kbd className="px-1.5 py-0.5 bg-slate-900 border border-slate-700 rounded text-[10px]">Ctrl+Enter</kbd>
|
<kbd className="px-1.5 py-0.5 bg-slate-900 border border-slate-700 rounded text-[10px]">Ctrl+⏎</kbd>
|
||||||
<span>save</span>
|
<span>save</span>
|
||||||
|
{pipSupported && (
|
||||||
|
<>
|
||||||
|
<kbd className="px-1.5 py-0.5 bg-slate-900 border border-slate-700 rounded text-[10px]">Alt+P</kbd>
|
||||||
|
<span>pop out</span>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<a href="/" className="hover:text-amber-400 transition-colors">rNotes.online</a>
|
<a href="/" className="hover:text-amber-400 transition-colors">rNotes.online</a>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue