From 0229ccaa1ea5f69b37db415fac3ae033439a639e Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 20:08:08 +0200 Subject: [PATCH 1/9] Fixed canvas injected at the wrong position #1234 --- plugins/visualizer/empty-player.css | 12 ++++-------- plugins/visualizer/front.ts | 4 +--- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/visualizer/empty-player.css b/plugins/visualizer/empty-player.css index 15b4043b..d7d112d8 100644 --- a/plugins/visualizer/empty-player.css +++ b/plugins/visualizer/empty-player.css @@ -1,9 +1,5 @@ -#player { - margin: 0 !important; - background: black; -} - -#song-image, -#song-video { - display: none !important; +#visualizer { + position: absolute; + z-index: 1; + background-color: black; } diff --git a/plugins/visualizer/front.ts b/plugins/visualizer/front.ts index 7720d9ed..eeec5bd4 100644 --- a/plugins/visualizer/front.ts +++ b/plugins/visualizer/front.ts @@ -40,9 +40,7 @@ export default (options: ConfigType<'visualizer'>) => { if (!canvas) { canvas = document.createElement('canvas'); canvas.id = 'visualizer'; - canvas.style.position = 'absolute'; - canvas.style.background = 'black'; - visualizerContainer?.append(canvas); + visualizerContainer.prepend(canvas); } const resizeCanvas = () => { From 063ba1b6c7c7f8e3454e3b4536705f6399c217ab Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 20:20:03 +0200 Subject: [PATCH 2/9] Backport album color theme plugin --- config/defaults.ts | 1 + package-lock.json | 305 ++++++++++++++++++++++++++-- package.json | 1 + plugins/album-color-theme/back.ts | 9 + plugins/album-color-theme/front.ts | 127 ++++++++++++ plugins/album-color-theme/style.css | 29 +++ 6 files changed, 456 insertions(+), 16 deletions(-) create mode 100644 plugins/album-color-theme/back.ts create mode 100644 plugins/album-color-theme/front.ts create mode 100644 plugins/album-color-theme/style.css diff --git a/config/defaults.ts b/config/defaults.ts index e32f9857..dd74fb5b 100644 --- a/config/defaults.ts +++ b/config/defaults.ts @@ -79,6 +79,7 @@ const defaultConfig = { additionalBlockLists: [], // Additional list of filters, e.g "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt" disableDefaultLists: [], }, + 'album-color-theme': {}, // Disabled plugins 'shortcuts': { enabled: false, diff --git a/package-lock.json b/package-lock.json index 62f29ac1..64cb8c92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "electron-store": "8.1.0", "electron-unhandled": "4.0.1", "electron-updater": "6.1.4", + "fast-average-color-node": "^2.6.0", "filenamify": "4.3.0", "howler": "2.2.4", "html-to-text": "9.0.5", @@ -2350,7 +2351,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -2384,6 +2384,16 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -2442,7 +2452,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -2457,7 +2466,6 @@ "url": "https://feross.org/support" } ], - "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -2903,11 +2911,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2918,8 +2937,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/color-support": { "version": "1.1.3", @@ -3302,6 +3329,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3441,6 +3476,14 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -4567,6 +4610,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/exponential-backoff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", @@ -4602,6 +4653,27 @@ ], "optional": true }, + "node_modules/fast-average-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/fast-average-color/-/fast-average-color-9.4.0.tgz", + "integrity": "sha512-bvM8vV6YwK07dPbzFz77zJaBcfF6ABVfgNwaxVgXc2G+o0e/tzLCF9WU8Ryp1r0Nkk6JuJNsWCzbb4cLOMlB+Q==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/fast-average-color-node": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/fast-average-color-node/-/fast-average-color-node-2.6.0.tgz", + "integrity": "sha512-dn7ps7AhcsO8Gq4468aAeSVMtYWAGjTIjQ6J83+QueA6UYZ22YeKfIrfKjQiYAjBt+oBWskZ5e1fXtmsm24xMg==", + "dependencies": { + "fast-average-color": "^9.3.0", + "node-fetch": "^2.6.7", + "sharp": "^0.31.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4843,6 +4915,11 @@ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -5000,6 +5077,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -5471,7 +5553,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -5485,8 +5566,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "optional": true + ] }, "node_modules/ignore": { "version": "5.2.4", @@ -5553,8 +5633,12 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/internal-slot": { "version": "1.0.5", @@ -6527,7 +6611,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6714,6 +6797,11 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/mpris-service": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/mpris-service/-/mpris-service-2.1.2.tgz", @@ -6735,6 +6823,11 @@ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", "optional": true }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6756,6 +6849,17 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-abi": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.47.0.tgz", + "integrity": "sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", @@ -7424,6 +7528,31 @@ "node": ">=10.4.0" } }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7541,6 +7670,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-config-file": { "version": "6.3.2", "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", @@ -7621,7 +7772,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -8031,6 +8181,33 @@ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "dev": true }, + "node_modules/sharp": { + "version": "0.31.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.31.3.tgz", + "integrity": "sha512-XcR4+FCLBFKw1bdB+GEhnUNXNXvnt0tDo4WsBsraKymuo/IAuPuCBVAL2wIkUw2r/dwFW5Q5+g66Kwl2dgDFVg==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.1", + "node-addon-api": "^5.0.0", + "prebuild-install": "^7.1.1", + "semver": "^7.3.8", + "simple-get": "^4.0.1", + "tar-fs": "^2.1.1", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/sharp/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8072,6 +8249,62 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -8277,7 +8510,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -8516,6 +8748,37 @@ "node": ">=10" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tar/node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -8791,6 +9054,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9020,8 +9294,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { "version": "3.4.0", diff --git a/package.json b/package.json index 6c3fdff5..cfbeef69 100644 --- a/package.json +++ b/package.json @@ -150,6 +150,7 @@ "electron-store": "8.1.0", "electron-unhandled": "4.0.1", "electron-updater": "6.1.4", + "fast-average-color-node": "^2.6.0", "filenamify": "4.3.0", "howler": "2.2.4", "html-to-text": "9.0.5", diff --git a/plugins/album-color-theme/back.ts b/plugins/album-color-theme/back.ts new file mode 100644 index 00000000..91ec6826 --- /dev/null +++ b/plugins/album-color-theme/back.ts @@ -0,0 +1,9 @@ +import { join } from 'node:path'; + +import { BrowserWindow } from 'electron'; + +import { injectCSS } from '../utils'; + +export default (win: BrowserWindow) => { + injectCSS(win.webContents, join(__dirname, 'style.css')); +}; diff --git a/plugins/album-color-theme/front.ts b/plugins/album-color-theme/front.ts new file mode 100644 index 00000000..a068bf47 --- /dev/null +++ b/plugins/album-color-theme/front.ts @@ -0,0 +1,127 @@ +import { FastAverageColor } from 'fast-average-color'; + +import { ConfigType } from '../../config/dynamic'; + +function hexToHSL(H: string) { + // Convert hex to RGB first + let r = 0; + let g = 0; + let b = 0; + if (H.length == 4) { + r = Number('0x' + H[1] + H[1]); + g = Number('0x' + H[2] + H[2]); + b = Number('0x' + H[3] + H[3]); + } else if (H.length == 7) { + r = Number('0x' + H[1] + H[2]); + g = Number('0x' + H[3] + H[4]); + b = Number('0x' + H[5] + H[6]); + } + // Then to HSL + r /= 255; + g /= 255; + b /= 255; + const cmin = Math.min(r, g, b); + const cmax = Math.max(r, g, b); + const delta = cmax - cmin; + let h: number; + let s: number; + let l: number; + + if (delta == 0) { + h = 0; + } else if (cmax == r) { + h = ((g - b) / delta) % 6; + } else if (cmax == g) { + h = ((b - r) / delta) + 2; + } else { + h = ((r - g) / delta) + 4; + } + + h = Math.round(h * 60); + + if (h < 0) { + h += 360; + } + + l = (cmax + cmin) / 2; + s = delta == 0 ? 0 : delta / (1 - Math.abs((2 * l) - 1)); + s = +(s * 100).toFixed(1); + l = +(l * 100).toFixed(1); + + //return "hsl(" + h + "," + s + "%," + l + "%)"; + return [h,s,l]; +} + +let hue = 0; +let saturation = 0; +let lightness = 0; + +function changeElementColor(element: HTMLElement | null, hue: number, saturation: number, lightness: number){ + if (element) { + element.style.backgroundColor = `hsl(${hue}, ${saturation}%, ${lightness}%)`; + } +} + +export default (_: ConfigType<'album-color-theme'>) => { + // updated elements + const playerPage = document.querySelector('#player-page'); + const navBarBackground = document.querySelector('#nav-bar-background'); + const ytmusicPlayerBar = document.querySelector('ytmusic-player-bar'); + const playerBarBackground = document.querySelector('#player-bar-background'); + const sidebarBig = document.querySelector('#guide-wrapper'); + const sidebarSmall = document.querySelector('#mini-guide-background'); + const ytmusicAppLayout = document.querySelector('#layout'); + + const observer = new MutationObserver((mutationsList) => { + for (const mutation of mutationsList) { + if (mutation.type === 'attributes') { + const isPageOpen = ytmusicAppLayout?.hasAttribute('player-page-open'); + if (isPageOpen) { + changeElementColor(sidebarSmall, hue, saturation, lightness - 30); + } else { + if (sidebarSmall) { + sidebarSmall.style.backgroundColor = 'black'; + } + } + } + } + }); + + if (playerPage) { + observer.observe(playerPage, { attributes: true }); + } + + document.addEventListener('apiLoaded', (apiEvent) => { + const fastAverageColor = new FastAverageColor(); + + apiEvent.detail.addEventListener('videodatachange', (name: string) => { + if (name === 'dataloaded') { + const playerResponse = apiEvent.detail.getPlayerResponse(); + const thumbnail = playerResponse?.videoDetails?.thumbnail?.thumbnails?.at(0); + if (thumbnail) { + fastAverageColor.getColorAsync(thumbnail.url) + .then((albumColor) => { + if (albumColor) { + [hue, saturation, lightness] = hexToHSL(albumColor.hex); + changeElementColor(playerPage, hue, saturation, lightness - 30); + changeElementColor(navBarBackground, hue, saturation, lightness - 15); + changeElementColor(ytmusicPlayerBar, hue, saturation, lightness - 15); + changeElementColor(playerBarBackground, hue, saturation, lightness - 15); + changeElementColor(sidebarBig, hue, saturation, lightness - 15); + if (ytmusicAppLayout?.hasAttribute('player-page-open')) { + changeElementColor(sidebarSmall, hue, saturation, lightness - 30); + } + const ytRightClickList = document.querySelector('tp-yt-paper-listbox'); + changeElementColor(ytRightClickList, hue, saturation, lightness - 15); + } else { + if (playerPage) { + playerPage.style.backgroundColor = '#000000'; + } + } + }) + .catch((e) => console.error(e)); + } + } + }); + }); +}; diff --git a/plugins/album-color-theme/style.css b/plugins/album-color-theme/style.css new file mode 100644 index 00000000..83fe51bc --- /dev/null +++ b/plugins/album-color-theme/style.css @@ -0,0 +1,29 @@ +yt-page-navigation-progress { + --yt-page-navigation-container-color: #00000046 !important; + --yt-page-navigation-progress-color: white !important; +} + +#player-page { + transition: transform 300ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important; +} + +#nav-bar-background { + transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important; +} + +#mini-guide-background { + transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important; + border-right: 0px !important; +} + +#guide-wrapper { + transition: opacity 200ms,background-color 300ms cubic-bezier(0.2,0,0.6,1) !important; +} + +#img, #player, .song-media-controls.style-scope.ytmusic-player { + border-radius: 2% !important; +} + +#items { + border-radius: 10px !important; +} From 22acaf688ff901c2a612765e8a035f53fbc8aac4 Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 20:33:49 +0200 Subject: [PATCH 3/9] Backport ambient mode plugin --- config/defaults.ts | 1 + plugins/ambient-mode/back.ts | 10 +++ plugins/ambient-mode/front.ts | 138 +++++++++++++++++++++++++++++++++ plugins/ambient-mode/style.css | 7 ++ 4 files changed, 156 insertions(+) create mode 100644 plugins/ambient-mode/back.ts create mode 100644 plugins/ambient-mode/front.ts create mode 100644 plugins/ambient-mode/style.css diff --git a/config/defaults.ts b/config/defaults.ts index dd74fb5b..11a36ccf 100644 --- a/config/defaults.ts +++ b/config/defaults.ts @@ -80,6 +80,7 @@ const defaultConfig = { disableDefaultLists: [], }, 'album-color-theme': {}, + 'ambient-mode': {}, // Disabled plugins 'shortcuts': { enabled: false, diff --git a/plugins/ambient-mode/back.ts b/plugins/ambient-mode/back.ts new file mode 100644 index 00000000..44f870d3 --- /dev/null +++ b/plugins/ambient-mode/back.ts @@ -0,0 +1,10 @@ +import { join } from 'node:path'; + +import { BrowserWindow } from 'electron'; + +import { injectCSS } from '../utils'; + + +export default (win: BrowserWindow) => { + injectCSS(win.webContents, join(__dirname, 'style.css')); +}; diff --git a/plugins/ambient-mode/front.ts b/plugins/ambient-mode/front.ts new file mode 100644 index 00000000..253d32b0 --- /dev/null +++ b/plugins/ambient-mode/front.ts @@ -0,0 +1,138 @@ +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) + + let unregister: (() => void) | null = null; + + const injectBlurVideo = (): (() => void) | null => { + const songVideo = document.querySelector('#song-video'); + const video = document.querySelector('#song-video .html5-video-container > video'); + const wrapper = document.querySelector('#song-video > .player-wrapper'); + + if (!songVideo) return null; + if (!video) return null; + if (!wrapper) return null; + + const blurCanvas = document.createElement('canvas'); + blurCanvas.classList.add('html5-blur-canvas'); + + const context = blurCanvas.getContext('2d', { willReadFrequently: true }); + + /* effect */ + let lastEffectWorkId: number | null = null; + let lastImageData: ImageData | null = null; + + const onSync = () => { + if (typeof lastEffectWorkId === 'number') cancelAnimationFrame(lastEffectWorkId); + + lastEffectWorkId = requestAnimationFrame(() => { + if (!context) return; + + const width = qualityRatio; + let height = Math.max(Math.floor(blurCanvas.height / blurCanvas.width * width), 1); + if (!Number.isFinite(height)) height = width; + + context.globalAlpha = 1; + if (lastImageData) { + const frameOffset = (1 / framerate) * (1000 / interpolationTime); + context.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1 + context.putImageData(lastImageData, 0, 0); + context.globalAlpha = frameOffset; + } + context.drawImage(video, 0, 0, width, height); + + const nowImageData = context.getImageData(0, 0, width, height); + lastImageData = nowImageData; + + lastEffectWorkId = null; + }); + }; + + const applyVideoAttributes = () => { + const rect = video.getBoundingClientRect(); + + const newWidth = Math.floor(video.width || rect.width); + const newHeight = Math.floor(video.height || rect.height); + + if (newWidth === 0 || newHeight === 0) return; + + blurCanvas.width = qualityRatio; + blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio); + blurCanvas.style.width = `${newWidth}px`; + blurCanvas.style.height = `${newHeight}px`; + }; + + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes') { + applyVideoAttributes(); + } + }); + }); + const resizeObserver = new ResizeObserver(() => { + applyVideoAttributes(); + }); + + /* hooking */ + let canvasInterval: NodeJS.Timeout | null = null; + canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate))); + applyVideoAttributes(); + observer.observe(songVideo, { attributes: true }); + resizeObserver.observe(songVideo); + window.addEventListener('resize', applyVideoAttributes); + + const onPause = () => { + if (canvasInterval) clearInterval(canvasInterval); + canvasInterval = null; + }; + const onPlay = () => { + if (canvasInterval) clearInterval(canvasInterval); + canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate))); + }; + songVideo.addEventListener('pause', onPause); + songVideo.addEventListener('play', onPlay); + + /* injecting */ + wrapper.prepend(blurCanvas); + + /* cleanup */ + return () => { + if (canvasInterval) clearInterval(canvasInterval); + + songVideo.removeEventListener('pause', onPause); + songVideo.removeEventListener('play', onPlay); + + observer.disconnect(); + resizeObserver.disconnect(); + window.removeEventListener('resize', applyVideoAttributes); + + wrapper.removeChild(blurCanvas); + }; + }; + + + const playerPage = document.querySelector('#player-page'); + const ytmusicAppLayout = document.querySelector('#layout'); + + const observer = new MutationObserver((mutationsList) => { + for (const mutation of mutationsList) { + if (mutation.type === 'attributes') { + const isPageOpen = ytmusicAppLayout?.hasAttribute('player-page-open'); + if (isPageOpen) { + unregister?.(); + unregister = injectBlurVideo() ?? null; + } else { + unregister?.(); + unregister = null; + } + } + } + }); + + if (playerPage) { + observer.observe(playerPage, { attributes: true }); + } +}; \ No newline at end of file diff --git a/plugins/ambient-mode/style.css b/plugins/ambient-mode/style.css new file mode 100644 index 00000000..44f90164 --- /dev/null +++ b/plugins/ambient-mode/style.css @@ -0,0 +1,7 @@ +#song-video canvas.html5-blur-canvas{ + position: absolute; + left: 0; + top: 0; + + filter: blur(100px); +} From da9cb8e2f5c82d5bb6c4761db8a6d315b6f83a80 Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 20:58:18 +0200 Subject: [PATCH 4/9] Add lumiastream beta plugin --- config/defaults.ts | 1 + menu.ts | 14 ++++--- plugins/lumiastream/back.ts | 82 +++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 plugins/lumiastream/back.ts diff --git a/config/defaults.ts b/config/defaults.ts index 11a36ccf..3075a55b 100644 --- a/config/defaults.ts +++ b/config/defaults.ts @@ -81,6 +81,7 @@ const defaultConfig = { }, 'album-color-theme': {}, 'ambient-mode': {}, + 'lumiastream': {}, // Disabled plugins 'shortcuts': { enabled: false, diff --git a/menu.ts b/menu.ts index fca99e6d..adb92065 100644 --- a/menu.ts +++ b/menu.ts @@ -16,6 +16,8 @@ export type MenuTemplate = (Electron.MenuItemConstructorOptions | Electron.MenuI // True only if in-app-menu was loaded on launch const inAppMenuActive = config.plugins.isEnabled('in-app-menu'); +const betaPlugins = ['crossfade', 'lumiastream']; + const pluginEnabledMenu = (plugin: string, label = '', hasSubmenu = false, refreshMenu: (() => void ) | undefined = undefined): Electron.MenuItemConstructorOptions => ({ label: label || plugin, type: 'checkbox', @@ -46,13 +48,13 @@ export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => { label: 'Plugins', submenu: getAllPlugins().map((plugin) => { + let pluginLabel = plugin; + if (betaPlugins.includes(plugin)) { + pluginLabel += ' [beta]'; + } + const pluginPath = path.join(__dirname, 'plugins', plugin, 'menu.js'); if (existsSync(pluginPath)) { - let pluginLabel = plugin; - if (pluginLabel === 'crossfade') { - pluginLabel = 'crossfade [beta]'; - } - if (!config.plugins.isEnabled(plugin)) { return pluginEnabledMenu(plugin, pluginLabel, true, refreshMenu); } @@ -71,7 +73,7 @@ export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => { } satisfies Electron.MenuItemConstructorOptions; } - return pluginEnabledMenu(plugin); + return pluginEnabledMenu(plugin, pluginLabel); }), }, { diff --git a/plugins/lumiastream/back.ts b/plugins/lumiastream/back.ts new file mode 100644 index 00000000..a026dbac --- /dev/null +++ b/plugins/lumiastream/back.ts @@ -0,0 +1,82 @@ +import { BrowserWindow , net } from 'electron'; + +import registerCallback from '../../providers/song-info'; + +const secToMilisec = (t?: number) => t ? Math.round(Number(t) * 1e3) : undefined; +const previousStatePaused = null; + +type LumiaData = { + origin: string; + eventType: string; + url?: string; + videoId?: string; + playlistId?: string; + cover?: string|null; + cover_url?: string|null; + title?: string; + artists?: string[]; + status?: string; + progress?: number; + duration?: number; + album_url?: string|null; + album?: string|null; + views?: number; + isPaused?: boolean; +} +const data: LumiaData = { + origin: 'youtubemusic', + eventType: 'switchSong', +}; + + +const post = (data: LumiaData) => { + const port = 39231; + const headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Access-Control-Allow-Headers': '*', + 'Access-Control-Allow-Origin': '*', + }; + const url = `http://localhost:${port}/api/media`; + + net.fetch(url, { method: 'POST', body: JSON.stringify({ token: 'lsmedia_ytmsI7812', data }), headers }) + .catch((error: { code: number, errno: number }) => { + console.log( + `Error: '${ + error.code || error.errno + }' - when trying to access lumiastream webserver at port ${port}` + ); + }); +}; + +export default (_: BrowserWindow) => { + registerCallback((songInfo) => { + if (!songInfo.title && !songInfo.artist) { + return; + } + + if (previousStatePaused === null) { + data.eventType = 'switchSong'; + } else if (previousStatePaused !== songInfo.isPaused) { + data.eventType = 'playPause'; + } + + data.duration = secToMilisec(songInfo.songDuration); + data.progress = secToMilisec(songInfo.elapsedSeconds); + data.url = songInfo.url; + data.videoId = songInfo.videoId; + data.playlistId = songInfo.playlistId; + data.cover = songInfo.imageSrc; + data.cover_url = songInfo.imageSrc; + data.album_url = songInfo.imageSrc; + data.title = songInfo.title; + data.artists = [songInfo.artist]; + data.status = songInfo.isPaused ? 'stopped' : 'playing'; + data.isPaused = songInfo.isPaused; + data.album = songInfo.album; + data.views = songInfo.views; + post(data); + }); +}; + + From 07853d8b39f43826bebe4928abb82bf6a293b8de Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 21:00:50 +0200 Subject: [PATCH 5/9] Changed ZoomIn ZoomOut Shortcuts to Ctrl+I/Ctrl+O --- menu.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/menu.ts b/menu.ts index adb92065..c0d2ac37 100644 --- a/menu.ts +++ b/menu.ts @@ -345,8 +345,8 @@ export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => { { role: 'reload' }, { role: 'forceReload' }, { type: 'separator' }, - { role: 'zoomIn' }, - { role: 'zoomOut' }, + { role: 'zoomIn', accelerator: process.platform === 'darwin' ? 'Cmd+I' : 'Ctrl+I' }, + { role: 'zoomOut', accelerator: process.platform === 'darwin' ? 'Cmd+O' : 'Ctrl+O' }, { role: 'resetZoom' }, { type: 'separator' }, { role: 'togglefullscreen' }, From 575a643e55f7fe5bd89fc432ca29abbf596318ab Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 21:04:11 +0200 Subject: [PATCH 6/9] Enhance Discord RPC Presence with direct link to Git Repository --- plugins/discord/back.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/discord/back.ts b/plugins/discord/back.ts index 35947c00..6fb34675 100644 --- a/plugins/discord/back.ts +++ b/plugins/discord/back.ts @@ -161,9 +161,10 @@ export default ( state: songInfo.artist, largeImageKey: songInfo.imageSrc ?? '', largeImageText: songInfo.album ?? '', - buttons: options.listenAlong ? [ - { label: 'Listen Along', url: songInfo.url ?? '' }, - ] : undefined, + buttons: [ + ...(options.listenAlong ? [{ label: 'Listen Along', url: songInfo.url ?? '' }] : []), + { label: 'View App On GitHub', url: 'https://github.com/th-ch/youtube-music' }, + ], }; if (songInfo.isPaused) { From d36fb592d0ad12152e2d46429bbb8bb13519e63e Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 21:06:36 +0200 Subject: [PATCH 7/9] Fix for windows zoom (ScaleFactor) #1159 --- index.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/index.ts b/index.ts index 38b0851d..57b62238 100644 --- a/index.ts +++ b/index.ts @@ -182,6 +182,26 @@ function createMainWindow() { win.webContents.loadURL(urlToLoad); win.on('closed', onClosed); + const scaleFactor = electron.screen.getAllDisplays().length > 1 ? electron.screen.getPrimaryDisplay().scaleFactor : 1; + const size = config.get('window-size'); + const position = config.get('window-position'); + + if (size && size.width && size.height) { + const scaledSize = { + width: size.width / scaleFactor, + height: size.height / scaleFactor, + }; + win.setSize(scaledSize.width, scaledSize.height); + } + + if (position && position.x && position.y) { + const scaledPosition = { + x: position.x / scaleFactor, + y: position.y / scaleFactor, + }; + win.setPosition(scaledPosition.x, scaledPosition.y); + } + type PiPOptions = typeof config.defaultConfig.plugins['picture-in-picture']; const setPiPOptions = config.plugins.isEnabled('picture-in-picture') // eslint-disable-next-line @typescript-eslint/no-var-requires From 8b65f1d6e408bc110f5c412b0b1a151194062329 Mon Sep 17 00:00:00 2001 From: TC Date: Fri, 6 Oct 2023 21:10:58 +0200 Subject: [PATCH 8/9] add player method "open" for mpris #1155 --- plugins/shortcuts/mpris.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/shortcuts/mpris.ts b/plugins/shortcuts/mpris.ts index 5c7d3dad..df299e98 100644 --- a/plugins/shortcuts/mpris.ts +++ b/plugins/shortcuts/mpris.ts @@ -110,6 +110,7 @@ function registerMPRIS(win: BrowserWindow) { shuffle(); } }); + player.on('open', (args: { uri: string}) => { win.loadURL(args.uri); }); let mprisVolNewer = false; let autoUpdate = false; From 375fb082f0bff90cd41d3693098d826c8a2420ae Mon Sep 17 00:00:00 2001 From: Su-Yong Date: Mon, 2 Oct 2023 21:00:53 +0900 Subject: [PATCH 9/9] fix(lyrics-genius): fix th-ch/youtube-music#1253 --- plugins/lyrics-genius/front.ts | 160 +++++++++++++++++---------------- 1 file changed, 81 insertions(+), 79 deletions(-) diff --git a/plugins/lyrics-genius/front.ts b/plugins/lyrics-genius/front.ts index 8e54ac94..ebfc0071 100644 --- a/plugins/lyrics-genius/front.ts +++ b/plugins/lyrics-genius/front.ts @@ -4,103 +4,105 @@ import is from 'electron-is'; import type { SongInfo } from '../../providers/song-info'; export default () => { - ipcRenderer.on('update-song-info', (_, extractedSongInfo: SongInfo) => setTimeout(async () => { - const tabList = document.querySelectorAll('tp-yt-paper-tab'); - const tabs = { - upNext: tabList[0], - lyrics: tabList[1], - discover: tabList[2], - }; + const setLyrics = (lyricsContainer: Element, lyrics: string | null) => { + lyricsContainer.innerHTML = ` +
+ ${lyrics?.replaceAll(/\r\n|\r|\n/g, '
') ?? 'Could not retrieve lyrics from genius'} +
+ + + `; - // Check if disabled - if (!tabs.lyrics?.hasAttribute('disabled')) { - return; + if (lyrics) { + const footer = lyricsContainer.querySelector('.footer'); + + if (footer) { + footer.textContent = 'Source: Genius'; + } } + }; - let hasLyrics = true; + let unregister: (() => void) | null = null; - const lyrics = await ipcRenderer.invoke( - 'search-genius-lyrics', - extractedSongInfo, - ) as string; - if (!lyrics) { - // Delete previous lyrics if tab is open and couldn't get new lyrics - checkLyricsContainer(() => { - hasLyrics = false; - setTabsOnclick(undefined); - }); - return; - } + ipcRenderer.on('update-song-info', (_, extractedSongInfo: SongInfo) => { + unregister?.(); - if (is.dev()) { - console.log('Fetched lyrics from Genius'); - } + setTimeout(async () => { + const tabList = document.querySelectorAll('tp-yt-paper-tab'); + const tabs = { + upNext: tabList[0], + lyrics: tabList[1], + discover: tabList[2], + }; - enableLyricsTab(); + // Check if disabled + if (!tabs.lyrics?.hasAttribute('disabled')) return; - setTabsOnclick(enableLyricsTab); + const lyrics = await ipcRenderer.invoke( + 'search-genius-lyrics', + extractedSongInfo, + ) as string | null; - checkLyricsContainer(); + if (!lyrics) { + // Delete previous lyrics if tab is open and couldn't get new lyrics + tabs.upNext.click(); + + return; + } + + if (is.dev()) { + console.log('Fetched lyrics from Genius'); + } + + const tryToInjectLyric = (callback?: () => void) => { + const lyricsContainer = document.querySelector( + '[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer', + ); + + if (lyricsContainer) { + callback?.(); + + setLyrics(lyricsContainer, lyrics); + applyLyricsTabState(); + } + }; + const applyLyricsTabState = () => { + if (lyrics) { + tabs.lyrics.removeAttribute('disabled'); + tabs.lyrics.removeAttribute('aria-disabled'); + } else { + tabs.lyrics.setAttribute('disabled', ''); + tabs.lyrics.setAttribute('aria-disabled', ''); + } + }; + const lyricsTabHandler = () => { + const tabContainer = document.querySelector('ytmusic-tab-renderer'); + if (!tabContainer) return; - const lyricsTabHandler = () => { - const tabContainer = document.querySelector('ytmusic-tab-renderer'); - if (tabContainer) { const observer = new MutationObserver((_, observer) => { - checkLyricsContainer(() => observer.disconnect()); + tryToInjectLyric(() => observer.disconnect()); }); + observer.observe(tabContainer, { attributes: true, childList: true, subtree: true, }); - } - }; + }; - tabs.lyrics.addEventListener('click', lyricsTabHandler); + applyLyricsTabState(); - function checkLyricsContainer(callback = () => { - }) { - const lyricsContainer = document.querySelector( - '[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer', - ); - if (lyricsContainer) { - callback(); - setLyrics(lyricsContainer); - } - } + tabs.discover.addEventListener('click', applyLyricsTabState); + tabs.lyrics.addEventListener('click', lyricsTabHandler); + tabs.upNext.addEventListener('click', applyLyricsTabState); - function setLyrics(lyricsContainer: Element) { - lyricsContainer.innerHTML = `
- ${ - hasLyrics - ? lyrics.replaceAll(/\r\n|\r|\n/g, '
') - : 'Could not retrieve lyrics from genius' - } + tryToInjectLyric(); -
- `; - if (hasLyrics) { - const footer = lyricsContainer.querySelector('.footer'); - if (footer) { - footer.textContent = 'Source: Genius'; - enableLyricsTab(); - } - } - } - - const defaultHandler = () => {}; - - function setTabsOnclick(callback: EventListenerOrEventListenerObject | undefined) { - for (const tab of [tabs.upNext, tabs.discover]) { - if (tab) { - tab.addEventListener('click', callback ?? defaultHandler); - } - } - } - - function enableLyricsTab() { - tabs.lyrics.removeAttribute('disabled'); - tabs.lyrics.removeAttribute('aria-disabled'); - } - }, 500)); + unregister = () => { + tabs.discover.removeEventListener('click', applyLyricsTabState); + tabs.lyrics.removeEventListener('click', lyricsTabHandler); + tabs.upNext.removeEventListener('click', applyLyricsTabState); + }; + }, 500); + }); };