Skip to content

Commit a1d50dd

Browse files
author
Oscar
committed
keyboard shortcut for run code item
1 parent 9c0206f commit a1d50dd

2 files changed

Lines changed: 75 additions & 0 deletions

File tree

src/popup/popup.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ body.save-to-unsorted-dialog-open {
4444

4545
#runCodeList .run-code-item {
4646
--run-code-chip-height: 1.45rem;
47+
display: inline-flex;
48+
align-items: center;
49+
gap: 0.35rem;
4750
min-width: 0;
4851
max-width: 100%;
4952
overflow: hidden;
@@ -59,6 +62,14 @@ body.save-to-unsorted-dialog-open {
5962
line-height: 1.1;
6063
}
6164

65+
#runCodeList .run-code-shortcut-key {
66+
font-weight: 700;
67+
font-size: 0.68rem;
68+
line-height: 1;
69+
text-transform: uppercase;
70+
opacity: 0.72;
71+
}
72+
6273
#runCodeList .run-code-item.is-running {
6374
display: inline-flex;
6475
align-items: center;

src/popup/popup.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,33 @@ function getPinnedItemIndexFromEvent(event) {
107107
return -1;
108108
}
109109

110+
/**
111+
* Resolve a visible Run Code item button from Alt+Q/W/E/R/T/Y/U/I/O/P.
112+
* @param {KeyboardEvent} event
113+
* @returns {HTMLButtonElement | null}
114+
*/
115+
function getRunCodeButtonFromEvent(event) {
116+
if (
117+
!event.altKey ||
118+
event.metaKey ||
119+
event.ctrlKey ||
120+
event.shiftKey ||
121+
event.isComposing
122+
) {
123+
return null;
124+
}
125+
126+
const key = getShortcutKeyFromEvent(event);
127+
if (!RUN_CODE_SHORTCUT_KEYS.includes(key)) {
128+
return null;
129+
}
130+
131+
const button = runCodeList?.querySelector(
132+
`[data-run-code-shortcut="${key}"]`,
133+
);
134+
return button instanceof HTMLButtonElement ? button : null;
135+
}
136+
110137
/**
111138
* Determine whether the popup search field is currently the active element.
112139
* @returns {boolean}
@@ -141,6 +168,10 @@ function shouldSuppressSearchInputAltShortcut(event) {
141168
return true;
142169
}
143170

171+
if (getRunCodeButtonFromEvent(event)) {
172+
return true;
173+
}
174+
144175
return Object.values(SHORTCUT_CONFIG).some((config) => config.key === key);
145176
}
146177

@@ -278,6 +309,19 @@ const PINNED_SEARCH_RESULTS_STORAGE_KEY = 'pinnedSearchResults';
278309
const SEARCH_RESULT_WEIGHTS_KEY = 'searchResultWeights';
279310
const RUN_CODE_IN_PAGE_RULES_STORAGE_KEY = 'runCodeInPageRules';
280311
const RUN_CODE_IN_PAGE_EXECUTE_MESSAGE = 'runCodeInPage:execute';
312+
/** @type {string[]} */
313+
const RUN_CODE_SHORTCUT_KEYS = [
314+
'q',
315+
'w',
316+
'e',
317+
'r',
318+
't',
319+
'y',
320+
'u',
321+
'i',
322+
'o',
323+
'p',
324+
];
281325

282326
/** @type {string[]} Default pinned shortcuts */
283327
const DEFAULT_PINNED_SHORTCUTS = [
@@ -1060,24 +1104,36 @@ async function refreshMatchingRunCodeSection() {
10601104
}
10611105

10621106
runCodeList.textContent = '';
1107+
let renderedRunCodeItemCount = 0;
10631108
matchingRules.forEach((rule) => {
10641109
if (!rule.id) {
10651110
return;
10661111
}
10671112
const title = getRunCodeRuleTitle(rule);
1113+
const shortcutKey =
1114+
RUN_CODE_SHORTCUT_KEYS[renderedRunCodeItemCount] || '';
10681115
const button = document.createElement('button');
10691116
button.type = 'button';
10701117
button.className =
10711118
'badge cursor-pointer hover:opacity-80 border-none transition-all duration-200 run-code-item';
10721119
button.setAttribute('role', 'listitem');
10731120
button.title = title;
1121+
if (shortcutKey) {
1122+
button.dataset.runCodeShortcut = shortcutKey;
1123+
}
10741124
button.innerHTML = `
1125+
${
1126+
shortcutKey
1127+
? `<span class="run-code-shortcut-key pointer-events-none">${shortcutKey}</span>`
1128+
: ''
1129+
}
10751130
<span class="truncate pointer-events-none">${escapeHtml(title)}</span>
10761131
`;
10771132
button.addEventListener('click', () => {
10781133
void runCodeInPage(rule, button, tabId);
10791134
});
10801135
runCodeList.appendChild(button);
1136+
renderedRunCodeItemCount += 1;
10811137
});
10821138

10831139
setRunCodeSectionHidden(runCodeList.children.length === 0);
@@ -3958,6 +4014,14 @@ async function initializeBookmarksSearch(
39584014
return;
39594015
}
39604016

4017+
const runCodeButton = getRunCodeButtonFromEvent(event);
4018+
if (runCodeButton) {
4019+
event.preventDefault();
4020+
event.stopPropagation();
4021+
runCodeButton.click();
4022+
return;
4023+
}
4024+
39614025
const matchedShortcut = getPinnedShortcutActionFromEvent(event);
39624026
if (!matchedShortcut) {
39634027
return;

0 commit comments

Comments
 (0)