Skip to content
3 changes: 3 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,9 @@
"volume": {
"message": "Volume"
},
"ctrlWheelVolume": {
"message": "Ctrl + mouse wheel for changing volume"
},
"watchedVideos": {
"message": "Watched videos"
},
Expand Down
10 changes: 8 additions & 2 deletions js&css/web-accessible/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ var ImprovedTube = {
wheel: 0,
alt: false,
ctrl: false,
shift: false
shift: false,
ctrlSide: null
},
cancelled: new Set(),
ignoreElements: ['EMBED', 'INPUT', 'OBJECT', 'TEXTAREA', 'IFRAME'],
Expand Down Expand Up @@ -528,7 +529,12 @@ document.addEventListener('it-message-from-extension', function () {
}

// dont trigger shortcuts on config change, reinitialize handler instead
if (message.key.startsWith('shortcut_')) camelized_key = 'shortcuts';
if (message.key.startsWith('shortcut_') || message.key === 'shortcuts_volume_wheel_ctrl') {
camelized_key = 'shortcuts';
if (typeof ImprovedTube.shortcutsInit === 'function') {
ImprovedTube.shortcutsInit();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shortcutsInit can be called when shortcuts change,
not required again for every shortcut pressed.

}
}
if (ImprovedTube[camelized_key]) {
try { ImprovedTube[camelized_key]() } catch { };
}
Expand Down
60 changes: 56 additions & 4 deletions js&css/web-accessible/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,63 @@ ImprovedTube.showStatus = function (value) {
this.elements.status.id = 'it-status';
}

if (typeof value === 'number') {
value = value.toFixed(2);
}
if (typeof value === 'object' && value?.type === 'volume') {
const player = this.elements.player;
const bezel = player?.querySelector('.ytp-bezel');
if (bezel) {
let bezelIcon = bezel.querySelector('.ytp-bezel-icon');
if (!bezelIcon) {
bezelIcon = document.createElement('div');
bezelIcon.className = 'ytp-bezel-icon';
bezel.appendChild(bezelIcon);
}

const iconSource = player?.querySelector('.ytp-volume-panel .ytp-volume-icon')
|| player?.querySelector('.ytp-mute-button');
if (iconSource) {
const svg = iconSource.querySelector('svg')?.cloneNode(true) || iconSource.cloneNode(true);
while (bezelIcon.firstChild) bezelIcon.firstChild.remove();
bezelIcon.appendChild(svg);
}

const bezelText = bezel.querySelector('.ytp-bezel-text');
if (bezelText) {
const volumeValue = typeof value.value === 'number' ? value.value : (player?.getVolume ? player.getVolume() : 0);
bezelText.textContent = `${Math.round(volumeValue)}%`;
}

bezel.classList.add('ytp-bezel-showing');
clearTimeout(ImprovedTube.status_timer);
ImprovedTube.status_timer = setTimeout(function () {
bezel.classList.remove('ytp-bezel-showing');
}, 500);
return;
}

this.elements.status.textContent = '';

this.elements.status.textContent = value;
const iconSource = player?.querySelector('.ytp-volume-panel .ytp-volume-icon')
|| player?.querySelector('.ytp-mute-button');
let iconElement;

if (iconSource) {
iconElement = iconSource.cloneNode(true);
iconElement.removeAttribute('id');
iconElement.removeAttribute('aria-label');
iconElement.removeAttribute('title');
} else {
iconElement = document.createElement('div');
iconElement.textContent = (value.muted || value.value === 0) ? '🔇' : (value.value <= 50 ? '🔈' : '🔊');
}

this.elements.status.appendChild(iconElement);
} else {
if (typeof value === 'number') {
value = value.toFixed(2);
}

this.elements.status.textContent = value;
}

if (ImprovedTube.status_timer) {
clearTimeout(ImprovedTube.status_timer);
Expand Down
73 changes: 72 additions & 1 deletion js&css/web-accessible/www.youtube.com/shortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,29 @@ ImprovedTube.shortcutsInit = function () {
// those four are _references_ to source Objects, not copies
const listening = ImprovedTube.input.listening,
listeners = ImprovedTube.input.listeners;
const volumeWheelEnabled = this.storage.shortcuts_volume_wheel_ctrl === true;
const volumeWheelDefaults = {
shortcut_increase_volume_wheel_ctrl: {
alt: false,
ctrl: true,
shift: false,
keys: {},
wheel: -1
},
shortcut_decrease_volume_wheel_ctrl: {
alt: false,
ctrl: true,
shift: false,
keys: {},
wheel: 1
}
};

// reset 'listening' shortcuts
for (var key in listening) delete listening[key];
// extract shortcuts from User Settings and initialize 'listening'
for (const [name, keys] of Object.entries(this.storage).filter(v => v[0].startsWith('shortcut_'))) {
if (!volumeWheelEnabled && (name in volumeWheelDefaults)) continue;
if (!keys) continue;
// camelCase(name)
const camelName = name.replace(/_(.)/g, (m, l) => l.toUpperCase());
Expand All @@ -40,6 +58,33 @@ ImprovedTube.shortcutsInit = function () {
}
if (potentialShortcut['keys'].size || potentialShortcut['wheel']) listening[camelName] = potentialShortcut;
}
// inject defaults for Ctrl+wheel volume if enabled and unset
if (volumeWheelEnabled) {
for (const [name, keys] of Object.entries(volumeWheelDefaults)) {
if (this.storage[name]) continue;
const camelName = name.replace(/_(.)/g, (m, l) => l.toUpperCase());
let potentialShortcut = {};
for (const button of ['alt', 'ctrl', 'shift', 'wheel', 'keys', 'toggle']) {
switch (button) {
case 'alt':
case 'ctrl':
case 'shift':
case 'toggle':
potentialShortcut[button] = keys[button] || false;
break

case 'wheel':
potentialShortcut[button] = keys[button] || 0;
break

case 'keys':
potentialShortcut[button] = keys[button] ? new Set(Object.keys(keys[button]).map(s=>Number(s))) : new Set();
break
}
}
if (potentialShortcut['keys'].size || potentialShortcut['wheel']) listening[camelName] = potentialShortcut;
}
}
// initialize 'listeners' only if there are actual shortcuts active
if (Object.keys(listening).length) {
for (const [name, handler] of Object.entries(this.shortcutsListeners)) {
Expand Down Expand Up @@ -72,6 +117,9 @@ ImprovedTube.shortcutsHandler = function () {
if (!shortcut.keys.has(pressedKey)) continue check;
}

const requiresLeftCtrl = key === 'shortcutIncreaseVolumeWheelCtrl' || key === 'shortcutDecreaseVolumeWheelCtrl';
if (requiresLeftCtrl && ImprovedTube.input.pressed.ctrlSide !== 'left') continue;

// cancel keydown/wheel event before we call target handler
// this way crashing handler wont keep 'cancelled' keys stuck
event.preventDefault();
Expand Down Expand Up @@ -104,6 +152,11 @@ ImprovedTube.shortcutsListeners = {
ImprovedTube.input.pressed.alt = event.altKey;
ImprovedTube.input.pressed.ctrl = event.ctrlKey;
ImprovedTube.input.pressed.shift = event.shiftKey;
if (event.code === 'ControlLeft') {
ImprovedTube.input.pressed.ctrlSide = 'left';
} else if (event.code === 'ControlRight') {
ImprovedTube.input.pressed.ctrlSide = 'right';
}

ImprovedTube.shortcutsHandler();
},
Expand All @@ -113,6 +166,9 @@ ImprovedTube.shortcutsListeners = {
ImprovedTube.input.pressed.alt = event.altKey;
ImprovedTube.input.pressed.ctrl = event.ctrlKey;
ImprovedTube.input.pressed.shift = event.shiftKey;
if (event.code === 'ControlLeft' || event.code === 'ControlRight') {
ImprovedTube.input.pressed.ctrlSide = null;
}

// cancel keyup events corresponding to keys that triggered one of our shortcuts
if (ImprovedTube.input.cancelled.has(event.keyCode)) {
Expand Down Expand Up @@ -146,6 +202,7 @@ ImprovedTube.shortcutsListeners = {
ImprovedTube.input.pressed.alt = false;
ImprovedTube.input.pressed.ctrl = false;
ImprovedTube.input.pressed.shift = false;
ImprovedTube.input.pressed.ctrlSide = null;
}
};
/*--- jump To Key Scene ----*/
Expand Down Expand Up @@ -356,7 +413,11 @@ ImprovedTube.shortcutIncreaseVolume = function (decrease) {

sessionStorage['yt-player-volume'] = localStorage['yt-player-volume'];

this.showStatus(player.getVolume());
this.showStatus({
type: 'volume',
value: player.getVolume(),
muted: player.isMuted ? player.isMuted() : player.getVolume() === 0
});
};
/*------------------------------------------------------------------------------
4.7.14 DECREASE VOLUME
Expand All @@ -365,6 +426,16 @@ ImprovedTube.shortcutDecreaseVolume = function () {
ImprovedTube.shortcutIncreaseVolume(true);
};
/*------------------------------------------------------------------------------
CTRL + WHEEL VOLUME
------------------------------------------------------------------------------*/
ImprovedTube.shortcutIncreaseVolumeWheelCtrl = function () {
ImprovedTube.shortcutIncreaseVolume(false);
};

ImprovedTube.shortcutDecreaseVolumeWheelCtrl = function () {
ImprovedTube.shortcutIncreaseVolume(true);
};
/*------------------------------------------------------------------------------
4.7.15 SCREENSHOT
------------------------------------------------------------------------------*/
ImprovedTube.shortcutScreenshot = ImprovedTube.screenshot;
Expand Down
29 changes: 28 additions & 1 deletion menu/skeleton-parts/shortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ extension.skeleton.main.layers.section.shortcuts = {
max: 25,
step: 1,
value: 5
},
shortcuts_volume_wheel_ctrl: {
component: 'checkbox',
text: 'ctrlWheelVolume',
value: false
}
},

Expand Down Expand Up @@ -111,7 +116,29 @@ extension.skeleton.main.layers.section.shortcuts = {
}
}
}
}
},
shortcut_increase_volume_wheel_ctrl: {
component: 'shortcut',
text: 'increaseVolume',
value: {
alt: false,
ctrl: true,
shift: false,
keys: {},
wheel: -1
}
},
shortcut_decrease_volume_wheel_ctrl: {
component: 'shortcut',
text: 'decreaseVolume',
value: {
alt: false,
ctrl: true,
shift: false,
keys: {},
wheel: 1
}
},
}
}
}
Expand Down