{isPopup && (
)}
{notifications.filter((n) => n.action === "reset_settings").length > 0 ?
{
const notificationToRemove = notifications.find((n) => n.action === "reset_settings");
@@ -1143,7 +1146,7 @@ export default function Settings() {
value={t("settings.sections.bottomButtons.confirm.value")}
/>
:
>((resolve) => canvas.toBlob(resolve, "image/png"));
if (!blob) return;
@@ -50,7 +46,6 @@ async function takeScreenshot(videoElement: HTMLVideoElement) {
listener();
const clipboardImage = new ClipboardItem({ "image/png": blob });
void navigator.clipboard.write([clipboardImage]);
- void navigator.clipboard.writeText(dataUrl);
setTimeout(() => {
remove();
}, 1200);
diff --git a/src/i18n/index.ts b/src/i18n/index.ts
index 7d6d30d5..2faa7811 100644
--- a/src/i18n/index.ts
+++ b/src/i18n/index.ts
@@ -2,46 +2,46 @@ import { type Resource, createInstance } from "i18next";
import { waitForSpecificMessage } from "../utils/utilities";
export const availableLocales = [
- "ca-ES",
- "cs-CZ",
- "de-DE",
- "en-GB",
- "en-US",
- "es-ES",
- "fa-IR",
- "fr-FR",
- "he-IL",
- "hi-IN",
- "it-IT",
- "ja-JP",
- "pl-PL",
- "pt-BR",
- "ru-RU",
- "sv-SE",
- "tr-TR",
- "zh-CN",
- "zh-TW"
+ "ca-ES",
+ "cs-CZ",
+ "de-DE",
+ "en-GB",
+ "en-US",
+ "es-ES",
+ "fa-IR",
+ "fr-FR",
+ "he-IL",
+ "hi-IN",
+ "it-IT",
+ "ja-JP",
+ "pl-PL",
+ "pt-BR",
+ "ru-RU",
+ "sv-SE",
+ "tr-TR",
+ "zh-CN",
+ "zh-TW"
] as const;
export const localePercentages: Record
= {
- "ca-ES": 0,
- "cs-CZ": 0,
- "de-DE": 36,
- "en-GB": 2,
- "en-US": 100,
- "es-ES": 63,
- "fa-IR": 0,
- "fr-FR": 67,
- "he-IL": 0,
- "hi-IN": 0,
- "it-IT": 98,
- "ja-JP": 98,
- "pl-PL": 0,
- "pt-BR": 74,
- "ru-RU": 100,
- "sv-SE": 98,
- "tr-TR": 75,
- "zh-CN": 100,
- "zh-TW": 94
+ "en-US": 100,
+ "ca-ES": 0,
+ "cs-CZ": 0,
+ "de-DE": 36,
+ "en-GB": 2,
+ "es-ES": 63,
+ "fa-IR": 0,
+ "fr-FR": 67,
+ "he-IL": 0,
+ "hi-IN": 0,
+ "it-IT": 100,
+ "ja-JP": 100,
+ "pl-PL": 0,
+ "pt-BR": 74,
+ "ru-RU": 100,
+ "sv-SE": 98,
+ "tr-TR": 75,
+ "zh-CN": 100,
+ "zh-TW": 95
};
export const localeDirection: Record = {
"ca-ES": "ltr",
diff --git a/src/manifest.ts b/src/manifest.ts
index b8034413..bc335cf4 100755
--- a/src/manifest.ts
+++ b/src/manifest.ts
@@ -60,7 +60,7 @@ const manifestV3: Manifest.WebExtensionManifest = {
const manifestV2: Manifest.WebExtensionManifest = {
author: pkg.author.name,
background: {
- scripts: ["src/pages/background/index.js"]
+ page: "src/pages/background/index.html"
},
browser_action: action,
browser_specific_settings: {
diff --git a/src/pages/background/index.html b/src/pages/background/index.html
new file mode 100644
index 00000000..b1937ff4
--- /dev/null
+++ b/src/pages/background/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ YouTube Enhancer Background
+
+
+
+
diff --git a/src/pages/background/index.ts b/src/pages/background/index.ts
index 02cd4daa..25d484f3 100644
--- a/src/pages/background/index.ts
+++ b/src/pages/background/index.ts
@@ -1,9 +1,8 @@
-import type { ContentToBackgroundSendOnlyMessageMappings, configuration, configurationKeys } from "@/src/types";
+import type { ContentToBackgroundSendOnlyMessageMappings } from "@/src/types";
-import { defaultConfiguration } from "@/src/utils/constants";
-import { parseStoredValue } from "@/src/utils/utilities";
+import { updateStoredSettings } from "@/src/utils/updateStoredSettings";
-import pkg from "../../../package.json";
+import { version } from "../../../package.json";
chrome.runtime.onInstalled.addListener((details) => {
const { previousVersion, reason } = details;
@@ -15,7 +14,6 @@ chrome.runtime.onInstalled.addListener((details) => {
break;
}
case chrome.runtime.OnInstalledReason.UPDATE: {
- const { version } = pkg;
if (
isNewMajorVersion(previousVersion as VersionString, version as VersionString) ||
isNewMinorVersion(previousVersion as VersionString, version as VersionString)
@@ -89,52 +87,3 @@ chrome.runtime.onMessage.addListener((message: ContentToBackgroundSendOnlyMessag
}
}
});
-const changedKeys = Object.keys({
- osd_display_type: ""
-} satisfies Partial>);
-async function updateStoredSettings() {
- try {
- const settings = await getStoredSettings();
- const removedKeys = Object.keys(settings).filter((key) => !Object.keys(defaultConfiguration).includes(key));
- for (const changedKey of changedKeys) {
- switch (changedKey) {
- case "osd_display_type": {
- if ((settings.osd_display_type as unknown as string) === "round") {
- settings.osd_display_type = "circle";
- }
- break;
- }
- }
- }
- for (const key of removedKeys) {
- delete settings[key];
- }
- await setModifiedSettings(settings);
- } catch (error) {
- console.error("Failed to update stored settings:", error);
- }
-}
-async function setModifiedSettings(settings: Partial) {
- const updates: Record = {};
- for (const [key, value] of Object.entries(settings)) {
- updates[key] = typeof value !== "string" ? JSON.stringify(value) : value;
- }
- await chrome.storage.local.set(updates);
-}
-async function getStoredSettings(): Promise {
- return new Promise((resolve, reject) => {
- chrome.storage.local.get((settings) => {
- try {
- const storedSettings: Partial = (
- Object.keys(settings)
- .filter((key) => typeof key === "string")
- .filter((key) => Object.keys(defaultConfiguration).includes(key as unknown as string)) as configurationKeys[]
- ).reduce((acc, key) => Object.assign(acc, { [key]: parseStoredValue(settings[key] as string) }), {});
- const castedSettings = storedSettings as configuration;
- resolve(castedSettings);
- } catch (error) {
- reject(error);
- }
- });
- });
-}
diff --git a/src/pages/content/index.ts b/src/pages/content/index.ts
index 8a9eb621..54b256bb 100644
--- a/src/pages/content/index.ts
+++ b/src/pages/content/index.ts
@@ -396,7 +396,9 @@ const storageChangeHandler = async (changes: StorageChanges, areaName: string) =
},
volume_boost_amount: (newValue) => {
sendExtensionOnlyMessage("volumeBoostAmountChange", {
- volumeBoostAmount: newValue
+ volumeBoostAmount: newValue,
+ volumeBoostEnabled: options.enable_volume_boost,
+ volumeBoostMode: options.volume_boost_mode
});
},
volume_boost_mode: (__oldValue, newValue) => {
diff --git a/src/pages/embedded/index.ts b/src/pages/embedded/index.ts
index 32d25265..d318819a 100644
--- a/src/pages/embedded/index.ts
+++ b/src/pages/embedded/index.ts
@@ -9,7 +9,7 @@ import { customCSSExists, updateCustomCSS } from "@/src/features/customCSS/utils
import { disableDeepDarkCSS, enableDeepDarkCSS } from "@/src/features/deepDarkCSS";
import { deepDarkCSSExists, getDeepDarkCustomThemeStyle, updateDeepDarkCSS } from "@/src/features/deepDarkCSS/utils";
import { enableFeatureMenu, setupFeatureMenuEventListeners } from "@/src/features/featureMenu";
-import { featuresInMenu, updateFeatureMenuItemLabel, updateFeatureMenuTitle } from "@/src/features/featureMenu/utils";
+import { featuresInMenu, getFeatureMenuItem, updateFeatureMenuItemLabel, updateFeatureMenuTitle } from "@/src/features/featureMenu/utils";
import { enableHideScrollBar } from "@/src/features/hideScrollBar";
import { hideScrollBar, showScrollBar } from "@/src/features/hideScrollBar/utils";
import { disableHideShorts, enableHideShorts } from "@/src/features/hideShorts";
@@ -220,9 +220,24 @@ window.addEventListener("DOMContentLoaded", function () {
}
case "volumeBoostAmountChange": {
const {
- data: { volumeBoostAmount }
+ data: { volumeBoostAmount, volumeBoostEnabled, volumeBoostMode }
} = message;
- applyVolumeBoost(volumeBoostAmount);
+
+ switch (volumeBoostMode) {
+ case "global": {
+ if (!volumeBoostEnabled) return;
+ applyVolumeBoost(volumeBoostAmount);
+ break;
+ }
+ case "per_video": {
+ const volumeBoostButton = getFeatureMenuItem("volumeBoostButton") ?? getFeatureButton("volumeBoostButton");
+ console.log(volumeBoostButton);
+ if (!volumeBoostButton) return;
+ const volumeBoostForVideoEnabled = volumeBoostButton.ariaChecked === "true";
+ console.log(volumeBoostForVideoEnabled, volumeBoostButton.ariaChecked);
+ if (volumeBoostForVideoEnabled) applyVolumeBoost(volumeBoostAmount);
+ }
+ }
break;
}
case "playerSpeedChange": {
diff --git a/src/types/index.ts b/src/types/index.ts
index 5cd2c1cc..d16bdff7 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -306,7 +306,10 @@ export type ExtensionSendOnlyMessageMappings = {
>;
skipContinueWatchingChange: DataResponseMessage<"skipContinueWatchingChange", { skipContinueWatchingEnabled: boolean }>;
videoHistoryChange: DataResponseMessage<"videoHistoryChange", { videoHistoryEnabled: boolean }>;
- volumeBoostAmountChange: DataResponseMessage<"volumeBoostAmountChange", { volumeBoostAmount: number }>;
+ volumeBoostAmountChange: DataResponseMessage<
+ "volumeBoostAmountChange",
+ { volumeBoostAmount: number; volumeBoostEnabled: boolean; volumeBoostMode: VolumeBoostMode }
+ >;
volumeBoostChange: DataResponseMessage<"volumeBoostChange", { volumeBoostEnabled: boolean; volumeBoostMode: VolumeBoostMode }>;
};
export type FilterMessagesBySource = {
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index f590ed0c..d48d8fa7 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -89,7 +89,7 @@ export const defaultConfiguration = {
speed_adjustment_steps: 0.25,
video_history_resume_type: "prompt",
volume_adjustment_steps: 5,
- volume_boost_amount: 1,
+ volume_boost_amount: 5,
volume_boost_mode: "global"
} satisfies configuration;
export const configurationImportSchema: TypeToPartialZodSchema<
diff --git a/src/utils/updateStoredSettings.ts b/src/utils/updateStoredSettings.ts
new file mode 100644
index 00000000..98306528
--- /dev/null
+++ b/src/utils/updateStoredSettings.ts
@@ -0,0 +1,68 @@
+import type { configuration, configurationKeys } from "@/src/types";
+
+import { defaultConfiguration } from "@/src/utils/constants";
+import { parseStoredValue } from "@/src/utils/utilities";
+
+const changedKeys = Object.keys({
+ osd_display_type: ""
+} satisfies Partial>);
+
+export async function updateStoredSettings() {
+ try {
+ const settings = await getStoredSettings();
+
+ const removedKeys = Object.keys(settings).filter((key) => !Object.keys(defaultConfiguration).includes(key));
+
+ for (const changedKey of changedKeys) {
+ switch (changedKey) {
+ case "osd_display_type": {
+ if ((settings.osd_display_type as unknown as string) === "round") {
+ settings.osd_display_type = "circle";
+ }
+
+ break;
+ }
+ }
+ }
+
+ for (const key of removedKeys) {
+ delete settings[key];
+ }
+
+ await setModifiedSettings(settings);
+ } catch (error) {
+ console.error("Failed to update stored settings:", error);
+ }
+}
+
+async function setModifiedSettings(settings: Partial) {
+ const updates: Record = {};
+
+ for (const [key, value] of Object.entries(settings)) {
+ updates[key] = typeof value !== "string" ? JSON.stringify(value) : value;
+ }
+
+ await chrome.storage.local.set(updates);
+}
+
+async function getStoredSettings(): Promise {
+ return new Promise((resolve, reject) => {
+ chrome.storage.local.get((settings) => {
+ try {
+ const storedSettings: Partial = (
+ Object.keys(settings)
+
+ .filter((key) => typeof key === "string")
+
+ .filter((key) => Object.keys(defaultConfiguration).includes(key as unknown as string)) as configurationKeys[]
+ ).reduce((acc, key) => Object.assign(acc, { [key]: parseStoredValue(settings[key] as string) }), {});
+
+ const castedSettings = storedSettings as configuration;
+
+ resolve(castedSettings);
+ } catch (error) {
+ reject(error);
+ }
+ });
+ });
+}
diff --git a/vite.config.ts b/vite.config.ts
index de1309b8..703075b1 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -26,10 +26,11 @@ export default function build() {
return defineConfig({
build: {
emptyOutDir: false,
+ modulePreload: false,
outDir: resolve(outDir, "temp"),
rollupOptions: {
input: {
- background: resolve(pagesDir, "background", "index.ts"),
+ background: resolve(pagesDir, "background", "index.html"),
options: resolve(pagesDir, "options", "index.html"),
popup: resolve(pagesDir, "popup", "index.html")
},