mirror of
https://github.com/SoPat712/Speeder.git
synced 2026-08-19 11:52:31 -04:00
fix(shortcuts): ignore editable control events
This commit is contained in:
@@ -6,7 +6,7 @@ Constraints: local commits only; no push; no browser testing; one commit per fea
|
||||
|
||||
- [x] Keep the controller visible for its own video in element and ancestor fullscreen.
|
||||
- [x] Target popup actions at the frame represented by the displayed speed; keep “all videos” intentional.
|
||||
- [ ] Ignore shortcuts originating from editable controls, including shadow-DOM inputs.
|
||||
- [x] Ignore shortcuts originating from editable controls, including shadow-DOM inputs.
|
||||
|
||||
## Accessibility and usability
|
||||
|
||||
|
||||
@@ -4373,6 +4373,32 @@ function inIframe() {
|
||||
}
|
||||
}
|
||||
|
||||
function isEditableShortcutTarget(event) {
|
||||
var path =
|
||||
event && typeof event.composedPath === "function"
|
||||
? event.composedPath()
|
||||
: [event && event.target];
|
||||
|
||||
return path.some(function(target) {
|
||||
if (!target || target.nodeType !== 1) return false;
|
||||
var nodeName = target.nodeName;
|
||||
var role = target.getAttribute && target.getAttribute("role");
|
||||
var contentEditable =
|
||||
target.getAttribute && target.getAttribute("contenteditable");
|
||||
return (
|
||||
nodeName === "INPUT" ||
|
||||
nodeName === "TEXTAREA" ||
|
||||
nodeName === "SELECT" ||
|
||||
target.isContentEditable ||
|
||||
(contentEditable !== null && contentEditable !== "false") ||
|
||||
role === "textbox" ||
|
||||
role === "searchbox" ||
|
||||
role === "combobox" ||
|
||||
role === "spinbutton"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function attachKeydownListeners(doc) {
|
||||
// Content scripts already run in every frame. Keeping each listener scoped
|
||||
// to its own frame avoids duplicate shortcuts and stale iframe ownership.
|
||||
@@ -4396,13 +4422,7 @@ function attachKeydownListeners(doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
event.target.nodeName === "INPUT" ||
|
||||
event.target.nodeName === "TEXTAREA" ||
|
||||
event.target.isContentEditable
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isEditableShortcutTarget(event)) return;
|
||||
|
||||
if (
|
||||
!siteRuleUtils.isSpeederActiveForSite(
|
||||
|
||||
@@ -414,6 +414,30 @@ describe("inject.js media/controller lifecycle regressions", () => {
|
||||
expect(video.currentTime).toBe(63);
|
||||
});
|
||||
|
||||
it("ignores shortcuts from selects and shadow-DOM edit fields", async () => {
|
||||
bootInject();
|
||||
await settleLifecycle();
|
||||
const { video } = createControlledVideo();
|
||||
const select = document.createElement("select");
|
||||
const host = document.createElement("site-editor");
|
||||
const input = document.createElement("input");
|
||||
host.attachShadow({ mode: "open" }).appendChild(input);
|
||||
document.body.append(select, host);
|
||||
|
||||
[select, input].forEach((target) => {
|
||||
target.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
code: "KeyD",
|
||||
key: "d"
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
expect(video.playbackRate).toBe(1);
|
||||
});
|
||||
|
||||
it("finishes a forced SPA initialization after settings hydration", async () => {
|
||||
vi.useFakeTimers();
|
||||
bootInject({
|
||||
|
||||
Reference in New Issue
Block a user