Sv443 hai 11 meses
pai
achega
954a17867f
Modificáronse 1 ficheiros con 137 adicións e 108 borrados
  1. 137 108
      dist/BetterYTM.user.js

+ 137 - 108
dist/BetterYTM.user.js

@@ -17,7 +17,7 @@
 // @license           AGPL-3.0-only
 // @author            Sv443
 // @copyright         Sv443 (https://github.com/Sv443)
-// @icon              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/logo/logo_dev_48.png
+// @icon              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/logo/logo_dev_48.png
 // @match             https://music.youtube.com/*
 // @match             https://www.youtube.com/*
 // @run-at            document-start
@@ -35,47 +35,47 @@
 // @grant             GM.openInTab
 // @grant             unsafeWindow
 // @noframes
-// @resource          css-bundle              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/dist/BetterYTM.css
-// @resource          css-above_queue_btns    https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/style/aboveQueueBtns.css
-// @resource          css-anchor_improvements https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/style/anchorImprovements.css
-// @resource          css-fix_hdr             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/style/fixHDR.css
-// @resource          css-fix_spacing         https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/style/fixSpacing.css
-// @resource          css-vol_slider_size     https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/style/volSliderSize.css
-// @resource          doc-changelog           https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/changelog.md
-// @resource          icon-advanced_mode      https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/plus_circle_small.svg
-// @resource          icon-arrow_down         https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/arrow_down.svg
-// @resource          icon-auto_like_enabled  https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/auto_like_enabled.svg
-// @resource          icon-auto_like          https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/auto_like.svg
-// @resource          icon-clear_list         https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/clear_list.svg
-// @resource          icon-delete             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/delete.svg
-// @resource          icon-error              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/error.svg
-// @resource          icon-experimental       https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/beaker_small.svg
-// @resource          icon-globe_small        https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/globe_small.svg
-// @resource          icon-globe              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/globe.svg
-// @resource          icon-help               https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/help.svg
-// @resource          icon-image_filled       https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/image_filled.svg
-// @resource          icon-image              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/image.svg
-// @resource          icon-link               https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/link.svg
-// @resource          icon-lyrics             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/lyrics.svg
-// @resource          icon-reload             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/refresh.svg
-// @resource          icon-skip_to            https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/skip_to.svg
-// @resource          icon-spinner            https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/icons/spinner.svg
-// @resource          img-close               https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/close.png
-// @resource          img-discord             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/external/discord.png
-// @resource          img-github              https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/external/github.png
-// @resource          img-greasyfork          https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/external/greasyfork.png
-// @resource          img-logo_dev            https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/logo/logo_dev_48.png
-// @resource          img-logo                https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/logo/logo_48.png
-// @resource          img-openuserjs          https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/images/external/openuserjs.png
-// @resource          trans-de_DE             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/de_DE.json
-// @resource          trans-en_US             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/en_US.json
-// @resource          trans-en_UK             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/en_UK.json
-// @resource          trans-es_ES             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/es_ES.json
-// @resource          trans-fr_FR             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/fr_FR.json
-// @resource          trans-hi_IN             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/hi_IN.json
-// @resource          trans-ja_JA             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/ja_JA.json
-// @resource          trans-pt_BR             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/pt_BR.json
-// @resource          trans-zh_CN             https://raw.githubusercontent.com/Sv443/BetterYTM/f90f8a44/assets/translations/zh_CN.json
+// @resource          css-bundle              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/dist/BetterYTM.css
+// @resource          css-above_queue_btns    https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/style/aboveQueueBtns.css
+// @resource          css-anchor_improvements https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/style/anchorImprovements.css
+// @resource          css-fix_hdr             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/style/fixHDR.css
+// @resource          css-fix_spacing         https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/style/fixSpacing.css
+// @resource          css-vol_slider_size     https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/style/volSliderSize.css
+// @resource          doc-changelog           https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/changelog.md
+// @resource          icon-advanced_mode      https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/plus_circle_small.svg
+// @resource          icon-arrow_down         https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/arrow_down.svg
+// @resource          icon-auto_like_enabled  https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/auto_like_enabled.svg
+// @resource          icon-auto_like          https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/auto_like.svg
+// @resource          icon-clear_list         https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/clear_list.svg
+// @resource          icon-delete             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/delete.svg
+// @resource          icon-error              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/error.svg
+// @resource          icon-experimental       https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/beaker_small.svg
+// @resource          icon-globe_small        https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/globe_small.svg
+// @resource          icon-globe              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/globe.svg
+// @resource          icon-help               https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/help.svg
+// @resource          icon-image_filled       https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/image_filled.svg
+// @resource          icon-image              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/image.svg
+// @resource          icon-link               https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/link.svg
+// @resource          icon-lyrics             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/lyrics.svg
+// @resource          icon-reload             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/refresh.svg
+// @resource          icon-skip_to            https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/skip_to.svg
+// @resource          icon-spinner            https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/icons/spinner.svg
+// @resource          img-close               https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/close.png
+// @resource          img-discord             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/external/discord.png
+// @resource          img-github              https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/external/github.png
+// @resource          img-greasyfork          https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/external/greasyfork.png
+// @resource          img-logo_dev            https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/logo/logo_dev_48.png
+// @resource          img-logo                https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/logo/logo_48.png
+// @resource          img-openuserjs          https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/images/external/openuserjs.png
+// @resource          trans-de_DE             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/de_DE.json
+// @resource          trans-en_US             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/en_US.json
+// @resource          trans-en_UK             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/en_UK.json
+// @resource          trans-es_ES             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/es_ES.json
+// @resource          trans-fr_FR             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/fr_FR.json
+// @resource          trans-hi_IN             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/hi_IN.json
+// @resource          trans-ja_JA             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/ja_JA.json
+// @resource          trans-pt_BR             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/pt_BR.json
+// @resource          trans-zh_CN             https://raw.githubusercontent.com/Sv443/BetterYTM/4485ad95/assets/translations/zh_CN.json
 // @require           https://cdn.jsdelivr.net/npm/@sv443-network/[email protected]/dist/index.global.js
 // @require           https://cdn.jsdelivr.net/npm/[email protected]/dist/fuse.basic.js
 // @require           https://cdn.jsdelivr.net/npm/[email protected]/lib/marked.umd.js
@@ -159,26 +159,7 @@ function __asyncValues(o) {
 typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
     var e = new Error(message);
     return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
-};let createNanoEvents = () => ({
-  emit(event, ...args) {
-    for (
-      let i = 0,
-        callbacks = this.events[event] || [],
-        length = callbacks.length;
-      i < length;
-      i++
-    ) {
-      callbacks[i](...args);
-    }
-  },
-  events: {},
-  on(event, cb) {
-(this.events[event] ||= []).push(cb);
-    return () => {
-      this.events[event] = this.events[event]?.filter(i => cb !== i);
-    }
-  }
-});// I know TS enums are impure but it doesn't really matter here, plus they look cooler
+};// I know TS enums are impure but it doesn't really matter here, plus they look cooler
 var LogLevel;
 (function (LogLevel) {
     LogLevel[LogLevel["Debug"] = 0] = "Debug";
@@ -205,7 +186,7 @@ var PluginIntent;
 })(PluginIntent || (PluginIntent = {}));const modeRaw = "development";
 const branchRaw = "develop";
 const hostRaw = "github";
-const buildNumberRaw = "f90f8a44";
+const buildNumberRaw = "4485ad95";
 /** The mode in which the script was built (production or development) */
 const mode = (modeRaw.match(/^#{{.+}}$/) ? "production" : modeRaw);
 /** The branch to use in various URLs that point to the GitHub repo */
@@ -361,7 +342,26 @@ function addLyricsCacheEntryPenalized(artist, song, url, penaltyFr = 0) {
     log("Added penalized cache entry for", artist, "-", song, "with penalty fraction", penaltyFr, "\n", entry);
     emitInterface("bytm:lyricsCacheEntryAdded", { entry, type: "penalized" });
     return lyricsCacheMgr.setData({ cache });
-}/** Class that can be extended or instantiated by itself to create an event emitter with helper methods and a strongly typed event map */
+}let createNanoEvents = () => ({
+  emit(event, ...args) {
+    for (
+      let i = 0,
+        callbacks = this.events[event] || [],
+        length = callbacks.length;
+      i < length;
+      i++
+    ) {
+      callbacks[i](...args);
+    }
+  },
+  events: {},
+  on(event, cb) {
+(this.events[event] ||= []).push(cb);
+    return () => {
+      this.events[event] = this.events[event]?.filter(i => cb !== i);
+    }
+  }
+});/** Class that can be extended or instantiated by itself to create an event emitter with helper methods and a strongly typed event map */
 class NanoEmitter {
     constructor(settings = {}) {
         Object.defineProperty(this, "events", {
@@ -781,7 +781,7 @@ function createCircularBtn(_a) {
         return btnElem;
     });
 }/** EventEmitter instance that is used to detect changes to the site */
-const siteEvents = createNanoEvents();
+const siteEvents = new NanoEmitter({ publicEmit: true });
 let observers = [];
 let lastWatchId = null;
 let lastPathname = null;
@@ -2122,23 +2122,11 @@ function addCfgMenu() {
         });
         reloadFooterEl.appendChild(reloadTxtEl);
         reloadFooterCont.appendChild(reloadFooterEl);
-        const resetElem = document.createElement("button");
-        resetElem.classList.add("bytm-btn");
-        resetElem.ariaLabel = resetElem.title = t("reset_tooltip");
-        resetElem.textContent = t("reset");
-        resetElem.addEventListener("click", () => __awaiter(this, void 0, void 0, function* () {
-            if (confirm(t("reset_confirm"))) {
-                yield setDefaultFeatures();
-                closeCfgMenu();
-                disableBeforeUnload();
-                location.reload();
-            }
-        }));
         const exportElem = document.createElement("button");
         exportElem.classList.add("bytm-btn");
         exportElem.ariaLabel = exportElem.title = t("export_tooltip");
         exportElem.textContent = t("export");
-        exportElem.addEventListener("click", () => __awaiter(this, void 0, void 0, function* () {
+        onInteraction(exportElem, () => __awaiter(this, void 0, void 0, function* () {
             const dlg = yield getExportDialog();
             dlg.on("close", openCfgMenu);
             yield dlg.mount();
@@ -2149,7 +2137,7 @@ function addCfgMenu() {
         importElem.classList.add("bytm-btn");
         importElem.ariaLabel = importElem.title = t("import_tooltip");
         importElem.textContent = t("import");
-        importElem.addEventListener("click", () => __awaiter(this, void 0, void 0, function* () {
+        onInteraction(importElem, () => __awaiter(this, void 0, void 0, function* () {
             const dlg = yield getImportDialog();
             dlg.on("close", openCfgMenu);
             yield dlg.mount();
@@ -2160,7 +2148,6 @@ function addCfgMenu() {
         buttonsCont.id = "bytm-menu-footer-buttons-cont";
         buttonsCont.appendChild(exportElem);
         buttonsCont.appendChild(importElem);
-        buttonsCont.appendChild(resetElem);
         footerCont.appendChild(reloadFooterCont);
         footerCont.appendChild(buttonsCont);
         //#region feature list
@@ -3868,7 +3855,7 @@ function switchSite(newDomain) {
 }
 //#region num keys skip
 const numKeysIgnoreTagNames = [...inputIgnoreTagNames, "TP-YT-PAPER-TAB"];
-const numKeysIgnoreIds = ["progress-bar", "song-media-window"];
+const numKeysIgnoreIds = ["song-media-window"];
 /** Adds the ability to skip to a certain time in the video by pressing a number key (0-9) */
 function initNumKeysSkip() {
     return __awaiter(this, void 0, void 0, function* () {
@@ -3881,10 +3868,9 @@ function initNumKeysSkip() {
             if (isCfgMenuOpen)
                 return;
             // discard the event when an unexpected element is currently active or in focus, like when editing a playlist or when the search bar is focused
-            if (document.activeElement !== document.body // short-circuit if nothing is active
-                || numKeysIgnoreIds.includes((_b = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : "") // video element or player bar active
-                || numKeysIgnoreTagNames.includes((_d = (_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.tagName) !== null && _d !== void 0 ? _d : "") // other element active
-            )
+            const ignoreElement = numKeysIgnoreIds.includes((_b = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : "") // video element or player bar active
+                || numKeysIgnoreTagNames.includes((_d = (_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.tagName) !== null && _d !== void 0 ? _d : ""); // other element active
+            if ((document.activeElement !== document.body && ignoreElement) || ignoreElement)
                 return info("Captured valid key to skip video to, but ignored it since an unexpected element is active:", document.activeElement);
             const vidElem = document.querySelector(getVideoSelector());
             if (!vidElem)
@@ -4290,10 +4276,8 @@ function fetchLyricsUrls(artist, song) {
             const startTs = Date.now();
             const fetchUrl = constructUrl(`${getFeature("geniUrlBase")}/search`, {
                 disableFuzzy: null,
-                utm_source: scriptInfo.name,
-                utm_content: `v${scriptInfo.version}${mode === "development" ? "-dev" : ""}`,
-                artist,
-                song,
+                utm_source: `${scriptInfo.name} v${scriptInfo.version}${mode === "development" ? "-pre" : ""}`,
+                q: `${artist} ${song}`,
             });
             log("Requesting lyrics from geniURL:", fetchUrl);
             const token = getFeature("geniUrlToken");
@@ -5044,7 +5028,7 @@ const featInfo = {
         category: "volume",
         min: 1,
         max: 25,
-        default: 10,
+        default: 4,
         unit: "%",
         textAdornment: adornments.reloadRequired,
     },
@@ -5403,6 +5387,12 @@ const featInfo = {
         advanced: true,
         textAdornment: () => combineAdornments([adornments.advanced, adornments.reloadRequired]),
     },
+    resetConfig: {
+        type: "button",
+        category: "general",
+        click: promptResetConfig,
+        textAdornment: adornments.reloadRequired,
+    },
     advancedMode: {
         type: "toggle",
         category: "general",
@@ -5414,7 +5404,14 @@ const featInfo = {
 };
 function noop() {
 }/** If this number is incremented, the features object data will be migrated to the new format */
-const formatVersion = 5;
+const formatVersion = 6;
+const defaultData = Object.keys(featInfo)
+    .reduce((acc, key) => {
+    var _a;
+    // @ts-ignore
+    acc[key] = (_a = featInfo === null || featInfo === void 0 ? void 0 : featInfo[key]) === null || _a === void 0 ? void 0 : _a.default;
+    return acc;
+}, {});
 /** Config data format migration dictionary */
 const migrations = {
     // 1 -> 2 (<=v1.0)
@@ -5458,24 +5455,18 @@ const migrations = {
         "closeToastsTimeout", "disableDarkReaderSites",
     ]),
     // 5 -> 6 (v2.1)
-    6: (oldData) => useDefaultConfig(oldData, [
+    6: (oldData) => useNewDefaultIfUnchanged(useDefaultConfig(oldData, [
         "autoLikeChannels", "autoLikeChannelToggleBtn",
         "autoLikePlayerBarToggleBtn", "autoLikeTimeout",
         "autoLikeShowToast", "autoLikeOpenMgmtDialog",
-        // reset existing:
-        "rememberSongTimeSites",
+    ]), [
+        { key: "rememberSongTimeSites", oldDefault: "ytm" },
+        { key: "volumeSliderScrollStep", oldDefault: 10 },
     ]),
     // TODO: once advanced filtering is fully implemented, clear cache on migration to fv6
     // 6 -> 7 (v2.x)
     // 7: (oldData: FeatureConfig) => 
 };
-const defaultData = Object.keys(featInfo)
-    .reduce((acc, key) => {
-    var _a;
-    // @ts-ignore
-    acc[key] = (_a = featInfo === null || featInfo === void 0 ? void 0 : featInfo[key]) === null || _a === void 0 ? void 0 : _a.default;
-    return acc;
-}, {});
 /** Uses the default config as the base, then overwrites all values with the passed {@linkcode baseData}, then sets all passed {@linkcode resetKeys} to their default values */
 function useDefaultConfig(baseData, resetKeys) {
     var _a;
@@ -5484,6 +5475,22 @@ function useDefaultConfig(baseData, resetKeys) {
         newData[key] = (_a = featInfo === null || featInfo === void 0 ? void 0 : featInfo[key]) === null || _a === void 0 ? void 0 : _a.default; // typescript funny moments
     return newData;
 }
+/**
+ * Uses {@linkcode oldData} as the base, then sets all keys provided in {@linkcode defaults} to their old default values, as long as their current value is equal to the provided old default.
+ * This essentially means if someone has changed a feature's value from its old default value, that decision will be respected. Only if it has been left on its default value, it will be reset to the new default value.
+ * Returns a copy of the object.
+ */
+function useNewDefaultIfUnchanged(oldData, defaults) {
+    var _a;
+    const newData = Object.assign({}, oldData);
+    for (const { key, oldDefault } of defaults) {
+        // @ts-ignore
+        const defaultVal = (_a = featInfo === null || featInfo === void 0 ? void 0 : featInfo[key]) === null || _a === void 0 ? void 0 : _a.default;
+        if (newData[key] === oldDefault)
+            newData[key] = defaultVal; // we love TS
+    }
+    return newData;
+}
 let canCompress = true;
 const cfgDataStore = new UserUtils.DataStore({
     id: "bytm-config",
@@ -5557,6 +5564,25 @@ function setDefaultFeatures() {
     info("Reset feature config to its default values");
     return res;
 }
+function promptResetConfig() {
+    return __awaiter(this, void 0, void 0, function* () {
+        if (confirm(t("reset_config_confirm"))) {
+            closeCfgMenu();
+            disableBeforeUnload();
+            yield setDefaultFeatures();
+            if (location.pathname.startsWith("/watch")) {
+                const videoTime = yield getVideoTime(0);
+                const url = new URL(location.href);
+                url.searchParams.delete("t");
+                if (videoTime)
+                    url.searchParams.set("t", String(videoTime));
+                location.replace(url.href);
+            }
+            else
+                location.reload();
+        }
+    });
+}
 /** Clears the feature config from the persistent storage - since the cache will be out of whack, this should only be run before a site re-/unload */
 function clearConfig() {
     return __awaiter(this, void 0, void 0, function* () {
@@ -5717,7 +5743,7 @@ function registerPlugin(def) {
         error(`Failed to register plugin${((_a = def === null || def === void 0 ? void 0 : def.plugin) === null || _a === void 0 ? void 0 : _a.name) ? ` '${(_b = def === null || def === void 0 ? void 0 : def.plugin) === null || _b === void 0 ? void 0 : _b.name}'` : ""} with invalid definition:\n- ${validationErrors.join("\n- ")}`, LogLevel.Info);
         throw new Error(`Invalid plugin definition:\n- ${validationErrors.join("\n- ")}`);
     }
-    const events = createNanoEvents();
+    const events = new NanoEmitter({ publicEmit: true });
     const token = randomId(32, 36);
     const { plugin: { name } } = def;
     pluginsQueued.set(getPluginKey(def), {
@@ -5953,10 +5979,9 @@ const getVideoSelector = () => getDomain() === "ytm" ? "ytmusic-player video" :
  */
 function getVideoTime(precision = 2) {
     return new Promise((res) => __awaiter(this, void 0, void 0, function* () {
-        const domain = getDomain();
         yield waitVideoElementReady();
         try {
-            if (domain === "ytm") {
+            if (getDomain() === "ytm") {
                 const vidElem = document.querySelector(getVideoSelector());
                 if (vidElem)
                     return res(Number(precision <= 0 ? Math.floor(vidElem.currentTime) : vidElem.currentTime.toFixed(precision)));
@@ -5964,7 +5989,7 @@ function getVideoTime(precision = 2) {
                     listener: (pbEl) => res(!isNaN(Number(pbEl.value)) ? Math.floor(Number(pbEl.value)) : null)
                 });
             }
-            else if (domain === "yt") {
+            else if (getDomain() === "yt") {
                 const vidElem = document.querySelector(getVideoSelector());
                 if (vidElem)
                     return res(Number(precision <= 0 ? Math.floor(vidElem.currentTime) : vidElem.currentTime.toFixed(precision)));
@@ -6025,7 +6050,7 @@ function ytForceShowVideoTime() {
 /** Waits for the video element to be in its readyState 4 / canplay state and returns it - resolves immediately if the video is already ready */
 function waitVideoElementReady() {
     return new Promise((res) => {
-        addSelectorListener("body", getVideoSelector(), {
+        const waitForEl = () => addSelectorListener("body", getVideoSelector(), {
             listener: (vidElem) => __awaiter(this, void 0, void 0, function* () {
                 if (vidElem) {
                     // this is just after YT has finished doing their own shenanigans with the video time and volume
@@ -6036,6 +6061,10 @@ function waitVideoElementReady() {
                 }
             }),
         });
+        if (location.pathname.startsWith("/watch"))
+            waitForEl();
+        else
+            siteEvents.once("watchIdChanged", waitForEl);
     });
 }
 //#region other
@@ -6356,7 +6385,7 @@ function getChangelogHtmlWithDetails() {
     });
 }/**
  * Constructs a URL from a base URL and a record of query parameters.
- * If a value is null, the parameter will be valueless.
+ * If a value is null, the parameter will be valueless. If a value is undefined, the parameter will be omitted.
  * All values will be stringified using their `toString()` method and then URI-encoded.
  * @returns Returns a string instead of a URL object
  */
@@ -6368,7 +6397,7 @@ function constructUrlString(baseUrl, params) {
 }
 /**
  * Constructs a URL object from a base URL and a record of query parameters.
- * If a value is null, the parameter will be valueless.
+ * If a value is null, the parameter will be valueless. If a value is undefined, the parameter will be omitted.
  * All values will be URI-encoded.
  * @returns Returns a URL object instead of a string
  */