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 - name: Setup NodeJS
if: startsWith(matrix.os, 'macOS') != true if: startsWith(matrix.os, 'macOS') != true
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: ${{ env.NODE_VERSION }} node-version: ${{ env.NODE_VERSION }}
cache: 'pnpm' 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. 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) #### [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) - 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) - 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) - 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", "name": "youtube-music",
"productName": "YouTube Music", "productName": "YouTube Music",
"version": "2.1.3", "version": "2.2.0",
"description": "YouTube Music Desktop App - including custom plugins", "description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/index.js", "main": "./dist/index.js",
"license": "MIT", "license": "MIT",
@ -176,7 +176,7 @@
"@types/electron-localshortcut": "3.1.2", "@types/electron-localshortcut": "3.1.2",
"@types/howler": "2.2.10", "@types/howler": "2.2.10",
"@types/html-to-text": "9.0.3", "@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", "auto-changelog": "2.4.0",
"builtin-modules": "^3.3.0", "builtin-modules": "^3.3.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
@ -185,7 +185,7 @@
"electron-builder": "24.6.4", "electron-builder": "24.6.4",
"electron-devtools-installer": "3.2.0", "electron-devtools-installer": "3.2.0",
"eslint": "8.52.0", "eslint": "8.52.0",
"eslint-plugin-import": "2.28.1", "eslint-plugin-import": "2.29.0",
"eslint-plugin-prettier": "5.0.1", "eslint-plugin-prettier": "5.0.1",
"node-gyp": "9.4.0", "node-gyp": "9.4.0",
"playwright": "1.39.0", "playwright": "1.39.0",

89
pnpm-lock.yaml generated
View File

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

View File

@ -81,7 +81,16 @@ const defaultConfig = {
disableDefaultLists: false, disableDefaultLists: false,
}, },
'album-color-theme': {}, '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': {}, 'audio-compressor': {},
'blur-nav-bar': {}, 'blur-nav-bar': {},
'bypass-age-restrictions': {}, 'bypass-age-restrictions': {},

View File

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

View File

@ -1,10 +1,14 @@
import { BrowserWindow } from 'electron'; import { BrowserWindow } from 'electron';
import config from './config';
import style from './style.css'; import style from './style.css';
import { injectCSS } from '../utils'; 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); 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'; import { ConfigType } from '../../config/dynamic';
export default (_: ConfigType<'ambient-mode'>) => { export default (config: ConfigType<'ambient-mode'>) => {
const interpolationTime = 3000; // interpolation time (ms) let interpolationTime = config.interpolationTime; // interpolation time (ms)
const framerate = 30; // frame let buffer = config.buffer; // frame
const qualityRatio = 50; // width size (pixel) 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; let unregister: (() => void) | null = null;
@ -37,7 +43,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
context.globalAlpha = 1; context.globalAlpha = 1;
if (lastImageData) { 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.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1
context.putImageData(lastImageData, 0, 0); context.putImageData(lastImageData, 0, 0);
context.globalAlpha = frameOffset; context.globalAlpha = frameOffset;
@ -61,8 +67,18 @@ export default (_: ConfigType<'ambient-mode'>) => {
blurCanvas.width = qualityRatio; blurCanvas.width = qualityRatio;
blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio); blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio);
blurCanvas.style.width = `${newWidth}px`; blurCanvas.style.width = `${newWidth * sizeRatio}px`;
blurCanvas.style.height = `${newHeight}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) => { const observer = new MutationObserver((mutations) => {
@ -75,10 +91,22 @@ export default (_: ConfigType<'ambient-mode'>) => {
const resizeObserver = new ResizeObserver(() => { const resizeObserver = new ResizeObserver(() => {
applyVideoAttributes(); 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 */ /* hooking */
let canvasInterval: NodeJS.Timeout | null = null; 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(); applyVideoAttributes();
observer.observe(songVideo, { attributes: true }); observer.observe(songVideo, { attributes: true });
resizeObserver.observe(songVideo); resizeObserver.observe(songVideo);
@ -90,7 +118,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
}; };
const onPlay = () => { const onPlay = () => {
if (canvasInterval) clearInterval(canvasInterval); 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('pause', onPause);
songVideo.addEventListener('play', onPlay); songVideo.addEventListener('play', onPlay);
@ -107,6 +135,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
observer.disconnect(); observer.disconnect();
resizeObserver.disconnect(); resizeObserver.disconnect();
ipcRenderer.off('ambient-mode:config-change', onConfigSync);
window.removeEventListener('resize', applyVideoAttributes); window.removeEventListener('resize', applyVideoAttributes);
wrapper.removeChild(blurCanvas); 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{ #song-video canvas.html5-blur-canvas {
position: absolute; filter: blur(var(--blur, 100px));
left: 0; opacity: var(--opacity, 1);
top: 0;
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;
} }