Compare commits

...

4 Commits

Author SHA1 Message Date
6288d0b171 Bump version to 2.2.0 2023-10-27 02:01:44 +09:00
4248d20e8e bump deps 2023-10-25 16:46:59 +09:00
0b413492ad feat(ambient-mode): add config for ambient-mode plugin (#1349) 2023-10-25 15:37:51 +09:00
dc73561c8a Update changelog for v2.1.3 2023-10-22 15:50:12 +00:00
11 changed files with 235 additions and 58 deletions

View File

@ -28,7 +28,7 @@ jobs:
- name: Setup NodeJS
if: startsWith(matrix.os, 'macOS') != true
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm'

View File

@ -2,8 +2,18 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v2.1.3](https://github.com/th-ch/youtube-music/compare/v2.1.2...v2.1.3)
- fix: fixed bugs in downloader [`#1342`](https://github.com/th-ch/youtube-music/pull/1342)
- feat(discord): rename `Listen Along` to `Play on YTM` [`#1341`](https://github.com/th-ch/youtube-music/issues/1341)
- chore(deps): bump deps [`4333891`](https://github.com/th-ch/youtube-music/commit/4333891ccabe42aedf756fd48618be715db13262)
- Update changelog for v2.1.2 [`fa4c69d`](https://github.com/th-ch/youtube-music/commit/fa4c69d228d4e06a7858e2b22fcdfa075a8ca766)
- fix(store): fix listenAlong statement [`bceaa05`](https://github.com/th-ch/youtube-music/commit/bceaa05197d47a4a4bbd22e767d1e4d6ec277514)
#### [v2.1.2](https://github.com/th-ch/youtube-music/compare/v2.1.1...v2.1.2)
> 19 October 2023
- feat(in-app-menu): add an option to hide the window controls [`#1335`](https://github.com/th-ch/youtube-music/pull/1335)
- fix: fixed an issue where the album name was missing [`#1334`](https://github.com/th-ch/youtube-music/pull/1334)
- chore(deps): update dependency electron to v27.0.1 [`#1331`](https://github.com/th-ch/youtube-music/pull/1331)

View File

@ -1,7 +1,7 @@
{
"name": "youtube-music",
"productName": "YouTube Music",
"version": "2.1.3",
"version": "2.2.0",
"description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/index.js",
"license": "MIT",
@ -176,7 +176,7 @@
"@types/electron-localshortcut": "3.1.2",
"@types/howler": "2.2.10",
"@types/html-to-text": "9.0.3",
"@typescript-eslint/eslint-plugin": "6.8.0",
"@typescript-eslint/eslint-plugin": "6.9.0",
"auto-changelog": "2.4.0",
"builtin-modules": "^3.3.0",
"cross-env": "7.0.3",
@ -185,7 +185,7 @@
"electron-builder": "24.6.4",
"electron-devtools-installer": "3.2.0",
"eslint": "8.52.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-prettier": "5.0.1",
"node-gyp": "9.4.0",
"playwright": "1.39.0",

89
pnpm-lock.yaml generated
View File

@ -145,8 +145,8 @@ devDependencies:
specifier: 9.0.3
version: 9.0.3
'@typescript-eslint/eslint-plugin':
specifier: 6.8.0
version: 6.8.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)(typescript@5.2.2)
specifier: 6.9.0
version: 6.9.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)(typescript@5.2.2)
auto-changelog:
specifier: 2.4.0
version: 2.4.0
@ -172,8 +172,8 @@ devDependencies:
specifier: 8.52.0
version: 8.52.0
eslint-plugin-import:
specifier: 2.28.1
version: 2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)
specifier: 2.29.0
version: 2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)
eslint-plugin-prettier:
specifier: 5.0.1
version: 5.0.1(eslint@8.52.0)(prettier@3.0.3)
@ -1041,8 +1041,8 @@ packages:
'@types/node': 20.8.6
optional: true
/@typescript-eslint/eslint-plugin@6.8.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==}
/@typescript-eslint/eslint-plugin@6.9.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
@ -1054,10 +1054,10 @@ packages:
dependencies:
'@eslint-community/regexpp': 4.9.1
'@typescript-eslint/parser': 6.7.5(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.8.0
'@typescript-eslint/type-utils': 6.8.0(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.8.0(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.8.0
'@typescript-eslint/scope-manager': 6.9.0
'@typescript-eslint/type-utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.9.0
debug: 4.3.4
eslint: 8.52.0
graphemer: 1.4.0
@ -1099,16 +1099,16 @@ packages:
'@typescript-eslint/visitor-keys': 6.7.5
dev: true
/@typescript-eslint/scope-manager@6.8.0:
resolution: {integrity: sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==}
/@typescript-eslint/scope-manager@6.9.0:
resolution: {integrity: sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.8.0
'@typescript-eslint/visitor-keys': 6.8.0
'@typescript-eslint/types': 6.9.0
'@typescript-eslint/visitor-keys': 6.9.0
dev: true
/@typescript-eslint/type-utils@6.8.0(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==}
/@typescript-eslint/type-utils@6.9.0(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@ -1117,8 +1117,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.8.0(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2)
debug: 4.3.4
eslint: 8.52.0
ts-api-utils: 1.0.3(typescript@5.2.2)
@ -1132,8 +1132,8 @@ packages:
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/types@6.8.0:
resolution: {integrity: sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==}
/@typescript-eslint/types@6.9.0:
resolution: {integrity: sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
@ -1158,8 +1158,8 @@ packages:
- supports-color
dev: true
/@typescript-eslint/typescript-estree@6.8.0(typescript@5.2.2):
resolution: {integrity: sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==}
/@typescript-eslint/typescript-estree@6.9.0(typescript@5.2.2):
resolution: {integrity: sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
@ -1167,8 +1167,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.8.0
'@typescript-eslint/visitor-keys': 6.8.0
'@typescript-eslint/types': 6.9.0
'@typescript-eslint/visitor-keys': 6.9.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -1179,8 +1179,8 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils@6.8.0(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==}
/@typescript-eslint/utils@6.9.0(eslint@8.52.0)(typescript@5.2.2):
resolution: {integrity: sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
@ -1188,9 +1188,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0)
'@types/json-schema': 7.0.13
'@types/semver': 7.5.3
'@typescript-eslint/scope-manager': 6.8.0
'@typescript-eslint/types': 6.8.0
'@typescript-eslint/typescript-estree': 6.8.0(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.9.0
'@typescript-eslint/types': 6.9.0
'@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2)
eslint: 8.52.0
semver: 7.5.4
transitivePeerDependencies:
@ -1206,11 +1206,11 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
/@typescript-eslint/visitor-keys@6.8.0:
resolution: {integrity: sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==}
/@typescript-eslint/visitor-keys@6.9.0:
resolution: {integrity: sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.8.0
'@typescript-eslint/types': 6.9.0
eslint-visitor-keys: 3.4.3
dev: true
@ -2540,7 +2540,7 @@ packages:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
dependencies:
debug: 3.2.7
is-core-module: 2.13.0
is-core-module: 2.13.1
resolve: 1.22.8
transitivePeerDependencies:
- supports-color
@ -2575,8 +2575,8 @@ packages:
- supports-color
dev: true
/eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.5)(eslint@8.52.0):
resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==}
/eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.7.5)(eslint@8.52.0):
resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
@ -2595,8 +2595,8 @@ packages:
eslint: 8.52.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.5)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0)
has: 1.0.4
is-core-module: 2.13.0
hasown: 2.0.0
is-core-module: 2.13.1
is-glob: 4.0.3
minimatch: 3.1.2
object.fromentries: 2.0.7
@ -3260,6 +3260,13 @@ packages:
resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==}
engines: {node: '>= 0.4.0'}
/hasown@2.0.0:
resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
dev: true
/hexy@0.2.11:
resolution: {integrity: sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==}
hasBin: true
@ -3475,6 +3482,12 @@ packages:
has: 1.0.4
dev: true
/is-core-module@2.13.1:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
hasown: 2.0.0
dev: true
/is-date-object@1.0.5:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
engines: {node: '>= 0.4'}
@ -4661,7 +4674,7 @@ packages:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
hasBin: true
dependencies:
is-core-module: 2.13.0
is-core-module: 2.13.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: true

View File

@ -81,7 +81,16 @@ const defaultConfig = {
disableDefaultLists: false,
},
'album-color-theme': {},
'ambient-mode': {},
'ambient-mode': {
enabled: false,
quality: 50,
buffer: 30,
interpolationTime: 1500,
blur: 100,
size: 100,
opacity: 1,
fullscreen: false,
},
'audio-compressor': {},
'blur-nav-bar': {},
'bypass-age-restrictions': {},

View File

@ -8,6 +8,7 @@ import { startingPages } from './providers/extracted-data';
import promptOptions from './providers/prompt-options';
import adblockerMenu from './plugins/adblocker/menu';
import ambientModeMenu from './plugins/ambient-mode/menu';
import captionsSelectorMenu from './plugins/captions-selector/menu';
import crossfadeMenu from './plugins/crossfade/menu';
import disableAutoplayMenu from './plugins/disable-autoplay/menu';
@ -32,6 +33,7 @@ const betaPlugins = ['crossfade', 'lumiastream'];
const pluginMenus = {
'adblocker': adblockerMenu,
'ambient-mode': ambientModeMenu,
'disable-autoplay': disableAutoplayMenu,
'captions-selector': captionsSelectorMenu,
'crossfade': crossfadeMenu,

View File

@ -1,10 +1,14 @@
import { BrowserWindow } from 'electron';
import config from './config';
import style from './style.css';
import { injectCSS } from '../utils';
export default (win: BrowserWindow) => {
config.subscribeAll((newConfig) => {
win.webContents.send('ambient-mode:config-change', newConfig);
});
export default (win: BrowserWindow) => {
injectCSS(win.webContents, style);
};

View File

@ -0,0 +1,4 @@
import { PluginConfig } from '../../config/dynamic';
const config = new PluginConfig('ambient-mode');
export default config;

View File

@ -1,9 +1,15 @@
import { ipcRenderer } from 'electron';
import { ConfigType } from '../../config/dynamic';
export default (_: ConfigType<'ambient-mode'>) => {
const interpolationTime = 3000; // interpolation time (ms)
const framerate = 30; // frame
const qualityRatio = 50; // width size (pixel)
export default (config: ConfigType<'ambient-mode'>) => {
let interpolationTime = config.interpolationTime; // interpolation time (ms)
let buffer = config.buffer; // frame
let qualityRatio = config.quality; // width size (pixel)
let sizeRatio = config.size / 100; // size ratio (percent)
let blur = config.blur; // blur (pixel)
let opacity = config.opacity; // opacity (percent)
let isFullscreen = config.fullscreen; // fullscreen (boolean)
let unregister: (() => void) | null = null;
@ -37,7 +43,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
context.globalAlpha = 1;
if (lastImageData) {
const frameOffset = (1 / framerate) * (1000 / interpolationTime);
const frameOffset = (1 / buffer) * (1000 / interpolationTime);
context.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1
context.putImageData(lastImageData, 0, 0);
context.globalAlpha = frameOffset;
@ -61,8 +67,18 @@ export default (_: ConfigType<'ambient-mode'>) => {
blurCanvas.width = qualityRatio;
blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio);
blurCanvas.style.width = `${newWidth}px`;
blurCanvas.style.height = `${newHeight}px`;
blurCanvas.style.width = `${newWidth * sizeRatio}px`;
blurCanvas.style.height = `${newHeight * sizeRatio}px`;
if (isFullscreen) blurCanvas.classList.add('fullscreen');
else blurCanvas.classList.remove('fullscreen');
const leftOffset = newWidth * (sizeRatio - 1) / 2;
const topOffset = newHeight * (sizeRatio - 1) / 2;
blurCanvas.style.setProperty('--left', `${-1 * leftOffset}px`);
blurCanvas.style.setProperty('--top', `${-1 * topOffset}px`);
blurCanvas.style.setProperty('--blur', `${blur}px`);
blurCanvas.style.setProperty('--opacity', `${opacity}`);
};
const observer = new MutationObserver((mutations) => {
@ -75,10 +91,22 @@ export default (_: ConfigType<'ambient-mode'>) => {
const resizeObserver = new ResizeObserver(() => {
applyVideoAttributes();
});
const onConfigSync = (_: Electron.IpcRendererEvent, newConfig: ConfigType<'ambient-mode'>) => {
if (typeof newConfig.interpolationTime === 'number') interpolationTime = newConfig.interpolationTime;
if (typeof newConfig.buffer === 'number') buffer = newConfig.buffer;
if (typeof newConfig.quality === 'number') qualityRatio = newConfig.quality;
if (typeof newConfig.size === 'number') sizeRatio = newConfig.size / 100;
if (typeof newConfig.blur === 'number') blur = newConfig.blur;
if (typeof newConfig.opacity === 'number') opacity = newConfig.opacity;
if (typeof newConfig.fullscreen === 'boolean') isFullscreen = newConfig.fullscreen;
applyVideoAttributes();
};
ipcRenderer.on('ambient-mode:config-change', onConfigSync);
/* hooking */
let canvasInterval: NodeJS.Timeout | null = null;
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate)));
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / buffer)));
applyVideoAttributes();
observer.observe(songVideo, { attributes: true });
resizeObserver.observe(songVideo);
@ -90,7 +118,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
};
const onPlay = () => {
if (canvasInterval) clearInterval(canvasInterval);
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate)));
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / buffer)));
};
songVideo.addEventListener('pause', onPause);
songVideo.addEventListener('play', onPlay);
@ -107,6 +135,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
observer.disconnect();
resizeObserver.disconnect();
ipcRenderer.off('ambient-mode:config-change', onConfigSync);
window.removeEventListener('resize', applyVideoAttributes);
wrapper.removeChild(blurCanvas);

View File

@ -0,0 +1,87 @@
import config from './config';
import { MenuTemplate } from '../../menu';
const interpolationTimeList = [0, 500, 1000, 1500, 2000, 3000, 4000, 5000];
const qualityList = [10, 25, 50, 100, 200, 500, 1000];
const sizeList = [100, 110, 125, 150, 175, 200, 300];
const bufferList = [1, 5, 10, 20, 30];
const blurAmountList = [0, 5, 10, 25, 50, 100, 150, 200, 500];
const opacityList = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
export default (): MenuTemplate => [
{
label: 'Smoothness transition',
submenu: interpolationTimeList.map((interpolationTime) => ({
label: `During ${interpolationTime / 1000}s`,
type: 'radio',
checked: config.get('interpolationTime') === interpolationTime,
click() {
config.set('interpolationTime', interpolationTime);
},
})),
},
{
label: 'Quality',
submenu: qualityList.map((quality) => ({
label: `${quality} pixels`,
type: 'radio',
checked: config.get('quality') === quality,
click() {
config.set('quality', quality);
},
})),
},
{
label: 'Size',
submenu: sizeList.map((size) => ({
label: `${size}%`,
type: 'radio',
checked: config.get('size') === size,
click() {
config.set('size', size);
},
})),
},
{
label: 'Buffer',
submenu: bufferList.map((buffer) => ({
label: `${buffer}`,
type: 'radio',
checked: config.get('buffer') === buffer,
click() {
config.set('buffer', buffer);
},
})),
},
{
label: 'Opacity',
submenu: opacityList.map((opacity) => ({
label: `${opacity * 100}%`,
type: 'radio',
checked: config.get('opacity') === opacity,
click() {
config.set('opacity', opacity);
},
})),
},
{
label: 'Blur amount',
submenu: blurAmountList.map((blur) => ({
label: `${blur} pixels`,
type: 'radio',
checked: config.get('blur') === blur,
click() {
config.set('blur', blur);
},
})),
},
{
label: 'Using fullscreen',
type: 'checkbox',
checked: config.get('fullscreen'),
click(item) {
config.set('fullscreen', item.checked);
},
},
];

View File

@ -1,7 +1,26 @@
#song-video canvas.html5-blur-canvas{
position: absolute;
left: 0;
top: 0;
#song-video canvas.html5-blur-canvas {
filter: blur(var(--blur, 100px));
opacity: var(--opacity, 1);
filter: blur(100px);
pointer-events: none;
}
#song-video canvas.html5-blur-canvas:not(.fullscreen) {
position: absolute;
left: var(--left, 0px);
top: var(--top, 0px);
}
#song-video canvas.html5-blur-canvas.fullscreen {
position: fixed;
width: 100% !important;
height: 100% !important;
left: 0 !important;
top: 0 !important;
}
#song-video .html5-video-container > video {
top: 0 !important;
}