Skip to content

Commit

Permalink
feat(scroll wheel volume control): modifier key enables volume adjust…
Browse files Browse the repository at this point in the history
…ment with scroll

Require a modifier key to be held

to adjust volume with scroll

Closes #104, #110
  • Loading branch information
VampireChicken12 committed Nov 20, 2023
1 parent 12a80ea commit 4a11654
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 165 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ YouTube Enhancer is a browser extension that aims to improve your YouTube experi

- **Enable Scroll Wheel Volume Control:** Control video volume with your mouse's scroll wheel for quick and easy adjustments.

- **Scroll Wheel Volume Control Modifier Key**: Optionally, enable a modifier key to adjust the volume only when the specified key is held down during scroll wheel actions.

- **OSD Color:** Choose the color of the On-Screen Display (OSD) for volume control.

- **OSD Type:** Define the type of OSD, including text, line, round, or no display.
Expand Down
16 changes: 16 additions & 0 deletions public/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,22 @@
"line": "Line",
"round": "Round"
}
},
"modifierKey": {
"title": "Scroll Wheel Modifier Key",
"enable": {
"title": "Press a modifier key to enable volume adjustment with the scroll wheel.",
"label": "Enable modifier key"
},
"options": {
"altKey": "{{KEY}} key",
"ctrlKey": "{{KEY}} key",
"shiftKey": "{{KEY}} key"
},
"select": {
"label": "Modifier key",
"title": "The modifier key to use"
}
}
},
"automaticQuality": {
Expand Down
9 changes: 9 additions & 0 deletions public/locales/en-US.json.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ interface EnUS {
label: "Enable scroll wheel volume control";
title: "Lets you use the scroll wheel to control the volume of the video you're watching";
};
modifierKey: {
enable: {
label: "Enable modifier key";
title: "Press a modifier key to enable volume adjustment with the scroll wheel.";
};
options: { altKey: "{{KEY}} key"; ctrlKey: "{{KEY}} key"; shiftKey: "{{KEY}} key" };
select: { label: "Modifier key"; title: "The modifier key to use" };
title: "Scroll Wheel Modifier Key";
};
onScreenDisplay: {
colors: {
blue: "Blue";
Expand Down
45 changes: 44 additions & 1 deletion src/components/Settings/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { configuration, configurationKeys } from "@/src/types";
import type { ModifierKey, configuration, configurationKeys } from "@/src/types";
import type EnUS from "public/locales/en-US.json";
import type { ChangeEvent, Dispatch, SetStateAction } from "react";

Expand Down Expand Up @@ -71,6 +71,7 @@ export default function Settings({
selectedDisplayPosition,
selectedDisplayType,
selectedLanguage,
selectedModifierKey,
selectedPlayerQuality,
selectedPlayerSpeed,
selectedScreenshotFormat,
Expand All @@ -79,6 +80,7 @@ export default function Settings({
setSelectedDisplayPosition,
setSelectedDisplayType,
setSelectedLanguage,
setSelectedModifierKey,
setSelectedPlayerQuality,
setSelectedPlayerSpeed,
setSelectedScreenshotFormat,
Expand All @@ -92,6 +94,7 @@ export default function Settings({
selectedDisplayPosition: string | undefined;
selectedDisplayType: string | undefined;
selectedLanguage: string | undefined;
selectedModifierKey: string | undefined;
selectedPlayerQuality: string | undefined;
selectedPlayerSpeed: string | undefined;
selectedScreenshotFormat: string | undefined;
Expand All @@ -100,6 +103,7 @@ export default function Settings({
setSelectedDisplayPosition: Dispatch<SetStateAction<string | undefined>>;
setSelectedDisplayType: Dispatch<SetStateAction<string | undefined>>;
setSelectedLanguage: Dispatch<SetStateAction<string | undefined>>;
setSelectedModifierKey: Dispatch<SetStateAction<string | undefined>>;
setSelectedPlayerQuality: Dispatch<SetStateAction<string | undefined>>;
setSelectedPlayerSpeed: Dispatch<SetStateAction<string | undefined>>;
setSelectedScreenshotFormat: Dispatch<SetStateAction<string | undefined>>;
Expand Down Expand Up @@ -168,6 +172,26 @@ export default function Settings({
defaultValue: {},
returnObjects: true
});
const scrollWheelVolumeControlModifierKeyOptions = [
{
label: t("settings.sections.scrollWheelVolumeControl.modifierKey.options.altKey", {
KEY: "Alt"
}),
value: "altKey"
},
{
label: t("settings.sections.scrollWheelVolumeControl.modifierKey.options.ctrlKey", {
KEY: "Ctrl"
}),
value: "ctrlKey"
},
{
label: t("settings.sections.scrollWheelVolumeControl.modifierKey.options.shiftKey", {
KEY: "Shift"
}),
value: "shiftKey"
}
] as { label: string; value: ModifierKey }[] as SelectOption[];
const colorOptions: SelectOption[] = [
{
element: <div className={cn("m-2 h-3 w-3 rounded-[50%] border-black border-[1px] border-solid", "bg-[red]")}></div>,
Expand Down Expand Up @@ -416,6 +440,25 @@ export default function Settings({
title={t("settings.sections.scrollWheelVolumeControl.enable.title")}
type="checkbox"
/>
<Setting
checked={settings.enable_scroll_wheel_volume_control_modifier_key?.toString() === "true"}
id="enable_scroll_wheel_volume_control_modifier_key"
label={t("settings.sections.scrollWheelVolumeControl.modifierKey.enable.label")}
onChange={setCheckboxOption("enable_scroll_wheel_volume_control_modifier_key")}
title={t("settings.sections.scrollWheelVolumeControl.modifierKey.enable.title")}
type="checkbox"
/>
<Setting
disabled={settings.enable_scroll_wheel_volume_control_modifier_key.toString() !== "true"}
id="scroll_wheel_volume_control_modifier_key"
label={t("settings.sections.scrollWheelVolumeControl.modifierKey.select.label")}
onChange={setValueOption("scroll_wheel_volume_control_modifier_key")}
options={scrollWheelVolumeControlModifierKeyOptions}
selectedOption={selectedModifierKey}
setSelectedOption={setSelectedModifierKey}
title={t("settings.sections.scrollWheelVolumeControl.modifierKey.select.title")}
type="select"
/>
<Setting
disabled={settings.enable_scroll_wheel_volume_control.toString() !== "true"}
id="osd_display_color"
Expand Down
23 changes: 14 additions & 9 deletions src/components/SettingsWrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,25 @@ export default function SettingsWrapper(): JSX.Element {
const [selectedScreenshotSaveAs, setSelectedScreenshotSaveAs] = useState<string | undefined>();
const [selectedScreenshotFormat, setSelectedScreenshotFormat] = useState<string | undefined>();
const [selectedLanguage, setSelectedLanguage] = useState<string | undefined>();
const [selectedModifierKey, setSelectedModifierKey] = useState<string | undefined>();
const [i18nInstance, setI18nInstance] = useState<i18nInstanceType | null>(null);
useEffect(() => {
const fetchSettings = () => {
chrome.storage.local.get((settings) => {
for (const [key, value] of Object.entries(settings)) {
settings[key] = parseStoredValue(value);
}
setSettings({ ...settings } as configuration);
setSelectedColor(settings.osd_display_color);
setSelectedDisplayType(settings.osd_display_type);
setSelectedDisplayPosition(settings.osd_display_position);
setSelectedPlayerQuality(settings.player_quality);
setSelectedPlayerSpeed(settings.player_speed);
setSelectedScreenshotSaveAs(settings.screenshot_save_as);
setSelectedScreenshotFormat(settings.screenshot_format);
setSelectedLanguage(settings.language);
const castedSettings = settings as configuration;
setSettings({ ...castedSettings });
setSelectedColor(castedSettings.osd_display_color);
setSelectedDisplayType(castedSettings.osd_display_type);
setSelectedDisplayPosition(castedSettings.osd_display_position);
setSelectedPlayerQuality(castedSettings.player_quality);
setSelectedPlayerSpeed(castedSettings.player_speed.toString());
setSelectedScreenshotSaveAs(castedSettings.screenshot_save_as);
setSelectedScreenshotFormat(castedSettings.screenshot_format);
setSelectedLanguage(castedSettings.language);
setSelectedModifierKey(castedSettings.scroll_wheel_volume_control_modifier_key);
});
};

Expand Down Expand Up @@ -116,6 +119,7 @@ export default function SettingsWrapper(): JSX.Element {
selectedDisplayPosition={selectedDisplayPosition}
selectedDisplayType={selectedDisplayType}
selectedLanguage={selectedLanguage}
selectedModifierKey={selectedModifierKey}
selectedPlayerQuality={selectedPlayerQuality}
selectedPlayerSpeed={selectedPlayerSpeed}
selectedScreenshotFormat={selectedScreenshotFormat}
Expand All @@ -124,6 +128,7 @@ export default function SettingsWrapper(): JSX.Element {
setSelectedDisplayPosition={setSelectedDisplayPosition}
setSelectedDisplayType={setSelectedDisplayType}
setSelectedLanguage={setSelectedLanguage}
setSelectedModifierKey={setSelectedModifierKey}
setSelectedPlayerQuality={setSelectedPlayerQuality}
setSelectedPlayerSpeed={setSelectedPlayerSpeed}
setSelectedScreenshotFormat={setSelectedScreenshotFormat}
Expand Down
43 changes: 29 additions & 14 deletions src/features/scrollWheelVolumeControl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import type { YouTubePlayerDiv } from "@/src/types";

import { isShortsPage, isWatchPage, waitForAllElements, waitForSpecificMessage } from "@/src/utils/utilities";

import { adjustVolume, drawVolumeDisplay, getScrollDirection, setupScrollListeners } from "./utils";
import { adjustVolume, drawVolumeDisplay, setupScrollListeners } from "./utils";

function preventScroll(event: Event) {
event.preventDefault();
event.stopImmediatePropagation();
event.stopPropagation();
}
/**
* Adjusts the volume on scroll wheel events.
* It listens for scroll wheel events on specified container selectors,
Expand All @@ -28,10 +33,26 @@ export default async function adjustVolumeOnScrollWheel(): Promise<void> {

// Define the event handler for the scroll wheel events
const handleWheel = async (event: Event) => {
const wheelEvent = event as WheelEvent | undefined;

// If it's not a wheel event, return
if (!wheelEvent) return;
preventScroll(event);
// Wait for the "options" message from the content script
const optionsData = await waitForSpecificMessage("options", "request_data", "content");
if (!optionsData) return;
const {
data: { options }
} = optionsData;
// Extract the necessary properties from the options object
const { enable_scroll_wheel_volume_control, enable_scroll_wheel_volume_control_modifier_key, scroll_wheel_volume_control_modifier_key } = options;
const wheelEvent = event as WheelEvent;
if (
!(
(enable_scroll_wheel_volume_control &&
enable_scroll_wheel_volume_control_modifier_key &&
scroll_wheel_volume_control_modifier_key &&
wheelEvent[scroll_wheel_volume_control_modifier_key]) ||
(enable_scroll_wheel_volume_control && !enable_scroll_wheel_volume_control_modifier_key)
)
)
return;
// Get the player element
const playerContainer = isWatchPage()
? (document.querySelector("div#movie_player") as YouTubePlayerDiv | null)
Expand All @@ -42,15 +63,9 @@ export default async function adjustVolumeOnScrollWheel(): Promise<void> {
if (!playerContainer) return;

// Adjust the volume based on the scroll direction
const scrollDelta = getScrollDirection(wheelEvent.deltaY);
// Wait for the "options" message from the content script
const optionsData = await waitForSpecificMessage("options", "request_data", "content");
if (!optionsData) return;
const {
data: { options }
} = optionsData;
const scrollDelta = wheelEvent.deltaY < 0 ? 1 : -1;
// Adjust the volume based on the scroll direction and options
const { newVolume } = await adjustVolume(scrollDelta, options.volume_adjustment_steps);
const { newVolume } = await adjustVolume(playerContainer, scrollDelta, options.volume_adjustment_steps);

// Update the volume display
drawVolumeDisplay({
Expand All @@ -60,7 +75,7 @@ export default async function adjustVolumeOnScrollWheel(): Promise<void> {
displayPadding: options.osd_display_padding,
displayPosition: options.osd_display_position,
displayType: options.osd_display_type,
playerContainer: playerContainer || null,
playerContainer: playerContainer,
volume: newVolume
});
};
Expand Down
Loading

0 comments on commit 4a11654

Please sign in to comment.