Close popup automatically after a successful save
This commit is contained in:
1 parent
b2082d0624
commit
646a106e93
4 files changed
+39
-1
No files matched your search
@@ -26,6 +26,8 @@ A small Chrome extension that automatically clicks "Skip Intro" and "Skip Credit
|
|||||||
|
|
||||||
Changing the Plex URL takes effect on your next page load — refresh your Plex tab after saving a new one. Toggle and delay changes apply immediately, no refresh needed.
|
Changing the Plex URL takes effect on your next page load — refresh your Plex tab after saving a new one. Toggle and delay changes apply immediately, no refresh needed.
|
||||||
|
|
||||||
|
Clicking **Save** closes the popup automatically shortly after confirming the save, so you don't have to click elsewhere to dismiss it. If something's wrong with what you entered (like a blank or invalid custom URL), the popup shows an error and stays open instead.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
The extension's content script runs on every page but only activates once the page's hostname matches your configured Plex URL. From there it uses a `MutationObserver` to watch the page for any `<button>` or `[role="button"]` element whose visible text contains "skip intro" or "skip credit" (case-insensitive, so it still matches if Plex appends a countdown like "Skip Intro 0:05"). When a match appears and is actually visible, it schedules a click — immediately if its delay is 0, or after the configured delay otherwise. Right before a delayed click actually fires, it re-checks that the button is still present, visible, still says "Skip Intro"/"Skip Credits", and that its toggle is still on — so turning a toggle off, or Plex removing the button, cancels a pending click instead of firing it late. A short cooldown per element stops a single button from being double-clicked in one burst, but still allows a later click if Plex reuses the same button element for the next episode.
|
The extension's content script runs on every page but only activates once the page's hostname matches your configured Plex URL. From there it uses a `MutationObserver` to watch the page for any `<button>` or `[role="button"]` element whose visible text contains "skip intro" or "skip credit" (case-insensitive, so it still matches if Plex appends a countdown like "Skip Intro 0:05"). When a match appears and is actually visible, it schedules a click — immediately if its delay is 0, or after the configured delay otherwise. Right before a delayed click actually fires, it re-checks that the button is still present, visible, still says "Skip Intro"/"Skip Credits", and that its toggle is still on — so turning a toggle off, or Plex removing the button, cancels a pending click instead of firing it late. A short cooldown per element stops a single button from being double-clicked in one burst, but still allows a later click if Plex reuses the same button element for the next episode.
|
||||||
@@ -41,7 +43,7 @@ npm install
|
|||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
The suite covers: clicking Skip Intro/Skip Credits, ignoring non-Plex pages, respecting the on/off toggles, matching a custom server URL, reacting to buttons added dynamically after page load, ignoring unrelated buttons, handling countdown suffixes in the button text, not clicking hidden buttons, correctly re-clicking a reused button after its cooldown, delayed clicks (including cancellation when a toggle turns off or the button disappears mid-delay), and the settings popup's save/validation/load behavior for both the URL and the delay sliders.
|
The suite covers: clicking Skip Intro/Skip Credits, ignoring non-Plex pages, respecting the on/off toggles, matching a custom server URL, reacting to buttons added dynamically after page load, ignoring unrelated buttons, handling countdown suffixes in the button text, not clicking hidden buttons, correctly re-clicking a reused button after its cooldown, delayed clicks (including cancellation when a toggle turns off or the button disappears mid-delay), and the settings popup's save/validation/load behavior for the URL, the delay sliders, and auto-close on save.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
showStatus("Saved", false);
|
showStatus("Saved", false);
|
||||||
|
setTimeout(() => {
|
||||||
|
window.close();
|
||||||
|
}, 600);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ function loadPopupScript({ initialSettings } = {}) {
|
|||||||
);
|
);
|
||||||
const savedCalls = [];
|
const savedCalls = [];
|
||||||
|
|
||||||
|
window.__closeCalled = false;
|
||||||
|
window.close = () => {
|
||||||
|
window.__closeCalled = true;
|
||||||
|
};
|
||||||
|
|
||||||
window.chrome = {
|
window.chrome = {
|
||||||
storage: {
|
storage: {
|
||||||
sync: {
|
sync: {
|
||||||
|
|||||||
@@ -133,3 +133,31 @@ test("unchecking a toggle and saving persists it as false", async () => {
|
|||||||
assert.strictEqual(savedCalls[0].skipCredits, false);
|
assert.strictEqual(savedCalls[0].skipCredits, false);
|
||||||
assert.strictEqual(savedCalls[0].skipIntro, true);
|
assert.strictEqual(savedCalls[0].skipIntro, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("closes the popup shortly after a successful save", async () => {
|
||||||
|
const { window } = loadPopupScript();
|
||||||
|
await wait(20);
|
||||||
|
|
||||||
|
window.document.getElementById("saveBtn").click();
|
||||||
|
|
||||||
|
await wait(50);
|
||||||
|
assert.strictEqual(window.__closeCalled, false, "should not close instantly, so the Saved message is visible");
|
||||||
|
|
||||||
|
await wait(700);
|
||||||
|
assert.strictEqual(window.__closeCalled, true, "should close shortly after saving");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not close the popup when the save is rejected for a blank custom URL", async () => {
|
||||||
|
const { window } = loadPopupScript();
|
||||||
|
await wait(20);
|
||||||
|
|
||||||
|
const urlPreset = window.document.getElementById("urlPreset");
|
||||||
|
urlPreset.value = "custom";
|
||||||
|
urlPreset.dispatchEvent(new window.Event("change"));
|
||||||
|
window.document.getElementById("customUrl").value = " ";
|
||||||
|
|
||||||
|
window.document.getElementById("saveBtn").click();
|
||||||
|
await wait(700);
|
||||||
|
|
||||||
|
assert.strictEqual(window.__closeCalled, false);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user