mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 10:31:47 +00:00
Compare commits
28 Commits
feat/chrom
...
v3.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 192fd0620f | |||
| 00d0b31980 | |||
| 5edb2131d2 | |||
| 4657aeca45 | |||
| 9f5651a8ba | |||
| 570dcfee29 | |||
| 2c130ce80d | |||
| 8457115105 | |||
| fbc02a494a | |||
| 7e2c254ecf | |||
| 11936a889e | |||
| f33970addd | |||
| 2c02b7193d | |||
| 3f80b598ae | |||
| 477068ed49 | |||
| b4083874ac | |||
| c5d0673b2f | |||
| 9ccc44474b | |||
| 98e341f122 | |||
| b23eba51dd | |||
| 980005a58c | |||
| aba58b1d34 | |||
| bb6a127d22 | |||
| ac6e30a6b6 | |||
| 3f23282eed | |||
| 199a77819c | |||
| 89a53b2854 | |||
| c57bf79b08 |
@ -478,7 +478,7 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="footer-copyright">© 2021 th-ch</div>
|
||||
<div class="footer-copyright">© 2024 th-ch</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
22
package.json
22
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "youtube-music",
|
||||
"productName": "YouTube Music",
|
||||
"version": "3.2.2",
|
||||
"version": "3.3.0",
|
||||
"description": "YouTube Music Desktop App - including custom plugins",
|
||||
"main": "./dist/main/index.js",
|
||||
"license": "MIT",
|
||||
@ -132,8 +132,7 @@
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"vudio@2.1.1": "patches/vudio@2.1.1.patch",
|
||||
"@xhayper/discord-rpc@1.1.2": "patches/@xhayper__discord-rpc@1.1.2.patch",
|
||||
"@astronautlabs/mdns@1.0.10": "patches/@astronautlabs__mdns@1.0.10.patch"
|
||||
"@xhayper/discord-rpc@1.1.2": "patches/@xhayper__discord-rpc@1.1.2.patch"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@ -146,7 +145,6 @@
|
||||
"@floating-ui/dom": "1.6.3",
|
||||
"@foobar404/wave": "2.0.5",
|
||||
"@jellybrick/electron-better-web-request": "1.0.4",
|
||||
"@jellybrick/electron-chromecast": "1.2.1",
|
||||
"@jellybrick/mpris-service": "2.1.4",
|
||||
"@xhayper/discord-rpc": "1.1.2",
|
||||
"async-mutex": "0.4.1",
|
||||
@ -168,7 +166,7 @@
|
||||
"filenamify": "6.0.0",
|
||||
"howler": "2.2.4",
|
||||
"html-to-text": "9.0.5",
|
||||
"i18next": "23.8.2",
|
||||
"i18next": "23.8.3",
|
||||
"keyboardevent-from-electron-accelerator": "2.0.0",
|
||||
"keyboardevents-areequal": "0.2.2",
|
||||
"node-html-parser": "6.1.12",
|
||||
@ -178,7 +176,7 @@
|
||||
"serve": "14.2.1",
|
||||
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
|
||||
"solid-floating-ui": "0.3.1",
|
||||
"solid-js": "1.8.14",
|
||||
"solid-js": "1.8.15",
|
||||
"solid-styled-components": "0.28.5",
|
||||
"solid-transition-group": "0.2.3",
|
||||
"ts-morph": "21.0.1",
|
||||
@ -199,8 +197,8 @@
|
||||
"builtin-modules": "3.3.0",
|
||||
"cross-env": "7.0.3",
|
||||
"del-cli": "5.1.0",
|
||||
"discord-api-types": "0.37.69",
|
||||
"electron": "28.2.2",
|
||||
"discord-api-types": "0.37.70",
|
||||
"electron": "28.2.3",
|
||||
"electron-builder": "24.9.1",
|
||||
"electron-devtools-installer": "3.2.0",
|
||||
"electron-vite": "2.0.0",
|
||||
@ -213,13 +211,13 @@
|
||||
"glob": "10.3.10",
|
||||
"node-gyp": "10.0.1",
|
||||
"playwright": "1.41.2",
|
||||
"rollup": "4.10.0",
|
||||
"rollup": "4.12.0",
|
||||
"typescript": "5.3.3",
|
||||
"utf-8-validate": "6.0.3",
|
||||
"vite": "5.1.1",
|
||||
"vite": "5.1.3",
|
||||
"vite-plugin-inspect": "0.8.3",
|
||||
"vite-plugin-resolve": "2.5.1",
|
||||
"vite-plugin-solid": "2.9.1",
|
||||
"vite-plugin-solid": "2.10.1",
|
||||
"ws": "8.16.0"
|
||||
},
|
||||
"auto-changelog": {
|
||||
@ -228,5 +226,5 @@
|
||||
"unreleased": true,
|
||||
"output": "changelog.md"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.1"
|
||||
"packageManager": "pnpm@8.15.3"
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
diff --git a/dist/Responder.js b/dist/Responder.js
|
||||
index 7bb0e4e51f131cf257efc44190cf892ca0f1414e..f71688b8d7dc85bb6e23c9ec2aeec5cb98adc70a 100644
|
||||
--- a/dist/Responder.js
|
||||
+++ b/dist/Responder.js
|
||||
@@ -32,6 +32,7 @@ const StateMachine_1 = require("./StateMachine");
|
||||
const Probe_1 = require("./Probe");
|
||||
const Response_1 = require("./Response");
|
||||
const constants_1 = require("./constants");
|
||||
+const { setTimeout, clearTimeout } = require('node:timers');
|
||||
const ONE_SECOND = 1000;
|
||||
/**
|
||||
* Make ids, just to keep track of which responder is which in debug messages
|
||||
@@ -43,7 +44,7 @@ const uniqueId = () => `id#${++counter}`;
|
||||
* a responder has more than 15 conflicts in a small window then the responder
|
||||
* should be throttled to prevent it from spamming everyone. Conflict count
|
||||
* gets cleared after 15s w/o any conflicts
|
||||
- */
|
||||
+*/
|
||||
class ConflictCounter {
|
||||
constructor() {
|
||||
this._count = 0;
|
||||
diff --git a/dist/sleep.js b/dist/sleep.js
|
||||
index 8e11b3900747a68814697943ec16af3280bca8b3..7896d16b43d3eb8fff175c30ea5903d6237cc634 100644
|
||||
--- a/dist/sleep.js
|
||||
+++ b/dist/sleep.js
|
||||
@@ -5,6 +5,7 @@
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.resetSleep = exports.sleep = void 0;
|
||||
const node_events_1 = require("node:events");
|
||||
+const { setInterval, clearInterval } = require('node:timers');
|
||||
exports.sleep = new node_events_1.EventEmitter();
|
||||
exports.sleep.setMaxListeners(100);
|
||||
let interval;
|
||||
338
pnpm-lock.yaml
generated
338
pnpm-lock.yaml
generated
@ -13,9 +13,6 @@ overrides:
|
||||
'@babel/runtime': 7.23.8
|
||||
|
||||
patchedDependencies:
|
||||
'@astronautlabs/mdns@1.0.10':
|
||||
hash: 7fg7wajlckigozdqgqhsj6kfd4
|
||||
path: patches/@astronautlabs__mdns@1.0.10.patch
|
||||
'@xhayper/discord-rpc@1.1.2':
|
||||
hash: 7eeaht6k4r7cw3nunras7mx7iu
|
||||
path: patches/@xhayper__discord-rpc@1.1.2.patch
|
||||
@ -26,16 +23,16 @@ patchedDependencies:
|
||||
dependencies:
|
||||
'@cliqz/adblocker-electron':
|
||||
specifier: 1.26.15
|
||||
version: 1.26.15(electron@28.2.2)
|
||||
version: 1.26.15(electron@28.2.3)
|
||||
'@cliqz/adblocker-electron-preload':
|
||||
specifier: 1.26.15
|
||||
version: 1.26.15(electron@28.2.2)
|
||||
version: 1.26.15(electron@28.2.3)
|
||||
'@electron-toolkit/tsconfig':
|
||||
specifier: 1.0.1
|
||||
version: 1.0.1(@types/node@20.11.0)
|
||||
'@electron/remote':
|
||||
specifier: 2.1.2
|
||||
version: 2.1.2(electron@28.2.2)
|
||||
version: 2.1.2(electron@28.2.3)
|
||||
'@ffmpeg.wasm/core-mt':
|
||||
specifier: 0.12.0
|
||||
version: 0.12.0
|
||||
@ -51,9 +48,6 @@ dependencies:
|
||||
'@jellybrick/electron-better-web-request':
|
||||
specifier: 1.0.4
|
||||
version: 1.0.4
|
||||
'@jellybrick/electron-chromecast':
|
||||
specifier: 1.2.1
|
||||
version: 1.2.1
|
||||
'@jellybrick/mpris-service':
|
||||
specifier: 2.1.4
|
||||
version: 2.1.4
|
||||
@ -77,7 +71,7 @@ dependencies:
|
||||
version: 10.2.0
|
||||
custom-electron-prompt:
|
||||
specifier: 1.5.7
|
||||
version: 1.5.7(electron@28.2.2)
|
||||
version: 1.5.7(electron@28.2.3)
|
||||
dbus-next:
|
||||
specifier: 0.10.2
|
||||
version: 0.10.2
|
||||
@ -118,8 +112,8 @@ dependencies:
|
||||
specifier: 9.0.5
|
||||
version: 9.0.5
|
||||
i18next:
|
||||
specifier: 23.8.2
|
||||
version: 23.8.2
|
||||
specifier: 23.8.3
|
||||
version: 23.8.3
|
||||
keyboardevent-from-electron-accelerator:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0
|
||||
@ -146,16 +140,16 @@ dependencies:
|
||||
version: github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6
|
||||
solid-floating-ui:
|
||||
specifier: 0.3.1
|
||||
version: 0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.14)
|
||||
version: 0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.15)
|
||||
solid-js:
|
||||
specifier: 1.8.14
|
||||
version: 1.8.14
|
||||
specifier: 1.8.15
|
||||
version: 1.8.15
|
||||
solid-styled-components:
|
||||
specifier: 0.28.5
|
||||
version: 0.28.5(solid-js@1.8.14)
|
||||
version: 0.28.5(solid-js@1.8.15)
|
||||
solid-transition-group:
|
||||
specifier: 0.2.3
|
||||
version: 0.2.3(solid-js@1.8.14)
|
||||
version: 0.2.3(solid-js@1.8.15)
|
||||
ts-morph:
|
||||
specifier: 21.0.1
|
||||
version: 21.0.1
|
||||
@ -207,11 +201,11 @@ devDependencies:
|
||||
specifier: 5.1.0
|
||||
version: 5.1.0
|
||||
discord-api-types:
|
||||
specifier: 0.37.69
|
||||
version: 0.37.69
|
||||
specifier: 0.37.70
|
||||
version: 0.37.70
|
||||
electron:
|
||||
specifier: 28.2.2
|
||||
version: 28.2.2
|
||||
specifier: 28.2.3
|
||||
version: 28.2.3
|
||||
electron-builder:
|
||||
specifier: 24.9.1
|
||||
version: 24.9.1
|
||||
@ -220,7 +214,7 @@ devDependencies:
|
||||
version: 3.2.0
|
||||
electron-vite:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0(vite@5.1.1)
|
||||
version: 2.0.0(vite@5.1.3)
|
||||
esbuild:
|
||||
specifier: 0.20.0
|
||||
version: 0.20.0
|
||||
@ -249,8 +243,8 @@ devDependencies:
|
||||
specifier: 1.41.2
|
||||
version: 1.41.2
|
||||
rollup:
|
||||
specifier: 4.10.0
|
||||
version: 4.10.0
|
||||
specifier: 4.12.0
|
||||
version: 4.12.0
|
||||
typescript:
|
||||
specifier: 5.3.3
|
||||
version: 5.3.3
|
||||
@ -258,17 +252,17 @@ devDependencies:
|
||||
specifier: 6.0.3
|
||||
version: 6.0.3
|
||||
vite:
|
||||
specifier: 5.1.1
|
||||
version: 5.1.1(@types/node@20.11.0)
|
||||
specifier: 5.1.3
|
||||
version: 5.1.3(@types/node@20.11.0)
|
||||
vite-plugin-inspect:
|
||||
specifier: 0.8.3
|
||||
version: 0.8.3(rollup@4.10.0)(vite@5.1.1)
|
||||
version: 0.8.3(rollup@4.12.0)(vite@5.1.3)
|
||||
vite-plugin-resolve:
|
||||
specifier: 2.5.1
|
||||
version: 2.5.1
|
||||
vite-plugin-solid:
|
||||
specifier: 2.9.1
|
||||
version: 2.9.1(solid-js@1.8.14)(vite@5.1.1)
|
||||
specifier: 2.10.1
|
||||
version: 2.10.1(solid-js@1.8.15)(vite@5.1.3)
|
||||
ws:
|
||||
specifier: 8.16.0
|
||||
version: 8.16.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
|
||||
@ -300,11 +294,6 @@ packages:
|
||||
resolution: {integrity: sha512-+PVTOfla/0XMLRTQLJFPg4u40XcdTfon6GGea70hBGi8Pd7ZymIXyVUR+vK8wt5Jb4MVKTKPIz43Myyebw5mZA==}
|
||||
dev: false
|
||||
|
||||
/@astronautlabs/mdns@1.0.10(patch_hash=7fg7wajlckigozdqgqhsj6kfd4):
|
||||
resolution: {integrity: sha512-9bVdQ15Tbzpor1z/bteaemC9NvRDZgMD4Cfbu1/r/6Zv6fCBXvIJJoJ6Dh/BMvTlAiT2Xewm36i0VWRnZ4yw6A==}
|
||||
dev: false
|
||||
patched: true
|
||||
|
||||
/@babel/code-frame@7.23.5:
|
||||
resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@ -589,23 +578,23 @@ packages:
|
||||
'@cliqz/adblocker-extended-selectors': 1.26.15
|
||||
dev: false
|
||||
|
||||
/@cliqz/adblocker-electron-preload@1.26.15(electron@28.2.2):
|
||||
/@cliqz/adblocker-electron-preload@1.26.15(electron@28.2.3):
|
||||
resolution: {integrity: sha512-nGfY84iQitDkiz9JTPdATIGuesPo8xcNJiVjWJ4eVtncNBnVvpGSOBI7HlOAPxKsJMDA42vMujm8dIVavTtnBg==}
|
||||
peerDependencies:
|
||||
electron: '>11'
|
||||
dependencies:
|
||||
'@cliqz/adblocker-content': 1.26.15
|
||||
electron: 28.2.2
|
||||
electron: 28.2.3
|
||||
dev: false
|
||||
|
||||
/@cliqz/adblocker-electron@1.26.15(electron@28.2.2):
|
||||
/@cliqz/adblocker-electron@1.26.15(electron@28.2.3):
|
||||
resolution: {integrity: sha512-pOidIXaKoX7R/i/klVOEj/CVkXvXFPKkDp4UTlSOC5Xn7mRtLia8hNJAuLiL3VsJR18PFhBTaPPipd2aVR2+yA==}
|
||||
peerDependencies:
|
||||
electron: '>11'
|
||||
dependencies:
|
||||
'@cliqz/adblocker': 1.26.15
|
||||
'@cliqz/adblocker-electron-preload': 1.26.15(electron@28.2.2)
|
||||
electron: 28.2.2
|
||||
'@cliqz/adblocker-electron-preload': 1.26.15(electron@28.2.3)
|
||||
electron: 28.2.3
|
||||
tldts-experimental: 6.1.2
|
||||
dev: false
|
||||
|
||||
@ -694,12 +683,12 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@electron/remote@2.1.2(electron@28.2.2):
|
||||
/@electron/remote@2.1.2(electron@28.2.3):
|
||||
resolution: {integrity: sha512-EPwNx+nhdrTBxyCqXt/pftoQg/ybtWDW3DUWHafejvnB1ZGGfMpv6e15D8KeempocjXe78T7WreyGGb3mlZxdA==}
|
||||
peerDependencies:
|
||||
electron: '>= 13.0.0'
|
||||
dependencies:
|
||||
electron: 28.2.2
|
||||
electron: 28.2.3
|
||||
dev: false
|
||||
|
||||
/@electron/universal@2.0.1:
|
||||
@ -1245,15 +1234,6 @@ packages:
|
||||
uuid: 9.0.1
|
||||
dev: false
|
||||
|
||||
/@jellybrick/electron-chromecast@1.2.1:
|
||||
resolution: {integrity: sha512-3w/Z9Q9/A/HLWOAE6yBCm0EzDPi1Tk6MoCtE0Fn7/g+g8P9XPlOyzMf9Q/VQaZ+p6JR3iO7iDiYo5uv/ULmWRQ==}
|
||||
dependencies:
|
||||
'@astronautlabs/mdns': 1.0.10(patch_hash=7fg7wajlckigozdqgqhsj6kfd4)
|
||||
castv2: github.com/metaquanta/node-castv2/71419bd736ac859b18fb84a2c459756f2b9ccb5a
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@jellybrick/mpris-service@2.1.4:
|
||||
resolution: {integrity: sha512-OwSxYeRRss7+ZhZs/n6D0LjUMWp1QIrAfzBZA6zGs62x80QIQlpeMXO2GKxC6UNyi87wJTiSWsUGDM1jO4eCtQ==}
|
||||
dependencies:
|
||||
@ -1382,49 +1362,6 @@ packages:
|
||||
resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==}
|
||||
dev: true
|
||||
|
||||
/@protobufjs/aspromise@1.1.2:
|
||||
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/base64@1.1.2:
|
||||
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/codegen@2.0.4:
|
||||
resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/eventemitter@1.1.0:
|
||||
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/fetch@1.1.0:
|
||||
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
dev: false
|
||||
|
||||
/@protobufjs/float@1.0.2:
|
||||
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/inquire@1.1.0:
|
||||
resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/path@1.1.2:
|
||||
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/pool@1.1.0:
|
||||
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
||||
dev: false
|
||||
|
||||
/@protobufjs/utf8@1.1.0:
|
||||
resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
|
||||
dev: false
|
||||
|
||||
/@remusao/guess-url-type@1.2.1:
|
||||
resolution: {integrity: sha512-rbOqre2jW8STjheOsOaQHLgYBaBZ9Owbdt8NO7WvNZftJlaG3y/K9oOkl8ZUpuFBisIhmBuMEW6c+YrQl5inRA==}
|
||||
dev: false
|
||||
@ -1454,7 +1391,7 @@ packages:
|
||||
resolution: {integrity: sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q==}
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils@5.1.0(rollup@4.10.0):
|
||||
/@rollup/pluginutils@5.1.0(rollup@4.12.0):
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
@ -1466,107 +1403,107 @@ packages:
|
||||
'@types/estree': 1.0.5
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
rollup: 4.10.0
|
||||
rollup: 4.12.0
|
||||
dev: true
|
||||
|
||||
/@rollup/rollup-android-arm-eabi@4.10.0:
|
||||
resolution: {integrity: sha512-/MeDQmcD96nVoRumKUljsYOLqfv1YFJps+0pTrb2Z9Nl/w5qNUysMaWQsrd1mvAlNT4yza1iVyIu4Q4AgF6V3A==}
|
||||
/@rollup/rollup-android-arm-eabi@4.12.0:
|
||||
resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-android-arm64@4.10.0:
|
||||
resolution: {integrity: sha512-lvu0jK97mZDJdpZKDnZI93I0Om8lSDaiPx3OiCk0RXn3E8CMPJNS/wxjAvSJJzhhZpfjXsjLWL8LnS6qET4VNQ==}
|
||||
/@rollup/rollup-android-arm64@4.12.0:
|
||||
resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-darwin-arm64@4.10.0:
|
||||
resolution: {integrity: sha512-uFpayx8I8tyOvDkD7X6n0PriDRWxcqEjqgtlxnUA/G9oS93ur9aZ8c8BEpzFmsed1TH5WZNG5IONB8IiW90TQg==}
|
||||
/@rollup/rollup-darwin-arm64@4.12.0:
|
||||
resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-darwin-x64@4.10.0:
|
||||
resolution: {integrity: sha512-nIdCX03qFKoR/MwQegQBK+qZoSpO3LESurVAC6s6jazLA1Mpmgzo3Nj3H1vydXp/JM29bkCiuF7tDuToj4+U9Q==}
|
||||
/@rollup/rollup-darwin-x64@4.12.0:
|
||||
resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm-gnueabihf@4.10.0:
|
||||
resolution: {integrity: sha512-Fz7a+y5sYhYZMQFRkOyCs4PLhICAnxRX/GnWYReaAoruUzuRtcf+Qnw+T0CoAWbHCuz2gBUwmWnUgQ67fb3FYw==}
|
||||
/@rollup/rollup-linux-arm-gnueabihf@4.12.0:
|
||||
resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm64-gnu@4.10.0:
|
||||
resolution: {integrity: sha512-yPtF9jIix88orwfTi0lJiqINnlWo6p93MtZEoaehZnmCzEmLL0eqjA3eGVeyQhMtxdV+Mlsgfwhh0+M/k1/V7Q==}
|
||||
/@rollup/rollup-linux-arm64-gnu@4.12.0:
|
||||
resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-arm64-musl@4.10.0:
|
||||
resolution: {integrity: sha512-9GW9yA30ib+vfFiwjX+N7PnjTnCMiUffhWj4vkG4ukYv1kJ4T9gHNg8zw+ChsOccM27G9yXrEtMScf1LaCuoWQ==}
|
||||
/@rollup/rollup-linux-arm64-musl@4.12.0:
|
||||
resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-riscv64-gnu@4.10.0:
|
||||
resolution: {integrity: sha512-X1ES+V4bMq2ws5fF4zHornxebNxMXye0ZZjUrzOrf7UMx1d6wMQtfcchZ8SqUnQPPHdOyOLW6fTcUiFgHFadRA==}
|
||||
/@rollup/rollup-linux-riscv64-gnu@4.12.0:
|
||||
resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-x64-gnu@4.10.0:
|
||||
resolution: {integrity: sha512-w/5OpT2EnI/Xvypw4FIhV34jmNqU5PZjZue2l2Y3ty1Ootm3SqhI+AmfhlUYGBTd9JnpneZCDnt3uNOiOBkMyw==}
|
||||
/@rollup/rollup-linux-x64-gnu@4.12.0:
|
||||
resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-linux-x64-musl@4.10.0:
|
||||
resolution: {integrity: sha512-q/meftEe3QlwQiGYxD9rWwB21DoKQ9Q8wA40of/of6yGHhZuGfZO0c3WYkN9dNlopHlNT3mf5BPsUSxoPuVQaw==}
|
||||
/@rollup/rollup-linux-x64-musl@4.12.0:
|
||||
resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-arm64-msvc@4.10.0:
|
||||
resolution: {integrity: sha512-NrR6667wlUfP0BHaEIKgYM/2va+Oj+RjZSASbBMnszM9k+1AmliRjHc3lJIiOehtSSjqYiO7R6KLNrWOX+YNSQ==}
|
||||
/@rollup/rollup-win32-arm64-msvc@4.12.0:
|
||||
resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-ia32-msvc@4.10.0:
|
||||
resolution: {integrity: sha512-FV0Tpt84LPYDduIDcXvEC7HKtyXxdvhdAOvOeWMWbQNulxViH2O07QXkT/FffX4FqEI02jEbCJbr+YcuKdyyMg==}
|
||||
/@rollup/rollup-win32-ia32-msvc@4.12.0:
|
||||
resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@rollup/rollup-win32-x64-msvc@4.10.0:
|
||||
resolution: {integrity: sha512-OZoJd+o5TaTSQeFFQ6WjFCiltiYVjIdsXxwu/XZ8qRpsvMQr4UsVrE5UyT9RIvsnuF47DqkJKhhVZ2Q9YW9IpQ==}
|
||||
/@rollup/rollup-win32-x64-msvc@4.12.0:
|
||||
resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
@ -1584,29 +1521,29 @@ packages:
|
||||
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/@solid-primitives/refs@1.0.6(solid-js@1.8.14):
|
||||
/@solid-primitives/refs@1.0.6(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-ruh4YdVMxThEVnvqbpeLXKojW442vpFU8q7dSKtElGOTa31aKOAkRb9BTbdaTwVjN4BEq79fiiYIXozJNl4dSw==}
|
||||
peerDependencies:
|
||||
solid-js: ^1.6.12
|
||||
dependencies:
|
||||
'@solid-primitives/utils': 6.2.2(solid-js@1.8.14)
|
||||
solid-js: 1.8.14
|
||||
'@solid-primitives/utils': 6.2.2(solid-js@1.8.15)
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/@solid-primitives/transition-group@1.0.4(solid-js@1.8.14):
|
||||
/@solid-primitives/transition-group@1.0.4(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-9nPg6HYAmEi7riH0C2bSCVw/2asgGSzHuN0yFFYyK9JgmXqJgyeyA+6thZbj7GgUQMRhtBxpH8yG7N2nEh8ttA==}
|
||||
peerDependencies:
|
||||
solid-js: ^1.6.12
|
||||
dependencies:
|
||||
solid-js: 1.8.14
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/@solid-primitives/utils@6.2.2(solid-js@1.8.14):
|
||||
/@solid-primitives/utils@6.2.2(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-11ypVbp987XxETeRqY5Y3OmmTpm8/jZqJXRvo6AyqBthzkvvjEdReuUMU2yVb+pwWGxfZpWHZ6EUCcGXUMhfwg==}
|
||||
peerDependencies:
|
||||
solid-js: ^1.6.12
|
||||
dependencies:
|
||||
solid-js: 1.8.14
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/@szmarczak/http-timer@4.0.6:
|
||||
@ -1702,7 +1639,7 @@ packages:
|
||||
/@types/electron-localshortcut@3.1.3:
|
||||
resolution: {integrity: sha512-D+CRdDTRZ4/9UmcSaZ5qvW4uq2VyyVmqsH9cdNReB4CL6MSIgyhr9w2PKeNEb0J/ZS7db7irJM/+ZiA5uSQsLw==}
|
||||
dependencies:
|
||||
electron: 28.2.2
|
||||
electron: 28.2.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -1759,10 +1696,6 @@ packages:
|
||||
dependencies:
|
||||
'@types/node': 20.11.0
|
||||
|
||||
/@types/long@4.0.2:
|
||||
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
|
||||
dev: false
|
||||
|
||||
/@types/minimist@1.2.5:
|
||||
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
|
||||
dev: true
|
||||
@ -2830,12 +2763,12 @@ packages:
|
||||
/csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
/custom-electron-prompt@1.5.7(electron@28.2.2):
|
||||
/custom-electron-prompt@1.5.7(electron@28.2.3):
|
||||
resolution: {integrity: sha512-ptRPJr6CpT06GWLMtg3GD2Lr7gWfXdWI+hR1S39eq+m/mUa2E118YmX6mPCbHdg5QB/W9UVhSpRqBM8FUh1G8w==}
|
||||
peerDependencies:
|
||||
electron: '>=10.0.0'
|
||||
dependencies:
|
||||
electron: 28.2.2
|
||||
electron: 28.2.3
|
||||
dev: false
|
||||
|
||||
/data-uri-to-buffer@4.0.1:
|
||||
@ -3057,8 +2990,8 @@ packages:
|
||||
path-type: 4.0.0
|
||||
dev: true
|
||||
|
||||
/discord-api-types@0.37.69:
|
||||
resolution: {integrity: sha512-c0rHc5YGNIXQkI+V7QwP8y77wxo74ITNeZmMwxtKC/l01aIF/gKBG/U2MKhUt2iaeRH9XwAt9PT3AI9JQVvKVA==}
|
||||
/discord-api-types@0.37.70:
|
||||
resolution: {integrity: sha512-8EtfZR0KwOK+yP5q/llWILdUAPmGmF1LmcVUYf7+gtGigz2pu6WR38ZN+IWtMzohY1Ujl2u3KOdbFvrEz9EC8w==}
|
||||
dev: true
|
||||
|
||||
/dmg-builder@24.9.1:
|
||||
@ -3296,7 +3229,7 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/electron-vite@2.0.0(vite@5.1.1):
|
||||
/electron-vite@2.0.0(vite@5.1.3):
|
||||
resolution: {integrity: sha512-EQiuPVSwJQRPGbZiVrCsCFMDVfNyNtSpDiyUV4fNwPKNadTjBfYMOudnLUpSeBTocKUZYf58SXSzSCAkNg0GTQ==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
hasBin: true
|
||||
@ -3313,13 +3246,13 @@ packages:
|
||||
esbuild: 0.19.12
|
||||
magic-string: 0.30.5
|
||||
picocolors: 1.0.0
|
||||
vite: 5.1.1(@types/node@20.11.0)
|
||||
vite: 5.1.3(@types/node@20.11.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/electron@28.2.2:
|
||||
resolution: {integrity: sha512-8UcvIGFcjplHdjPFNAHVFg5bS0atDyT3Zx21WwuE4iLfxcAMsyMEOgrQX3im5LibA8srwsUZs7Cx0JAUfcQRpw==}
|
||||
/electron@28.2.3:
|
||||
resolution: {integrity: sha512-he9nGphZo03ejDjYBXpmFVw0KBKogXvR2tYxE4dyYvnfw42uaFIBFrwGeenvqoEOfheJfcI0u4rFG6h3QxDwnA==}
|
||||
engines: {node: '>= 12.20.55'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
@ -4394,8 +4327,8 @@ packages:
|
||||
engines: {node: '>=10.17.0'}
|
||||
dev: false
|
||||
|
||||
/i18next@23.8.2:
|
||||
resolution: {integrity: sha512-Z84zyEangrlERm0ZugVy4bIt485e/H8VecGUZkZWrH7BDePG6jT73QdL9EA1tRTTVVMpry/MgWIP1FjEn0DRXA==}
|
||||
/i18next@23.8.3:
|
||||
resolution: {integrity: sha512-IQn6Tfn+XkIRHjC/z3uQSGLhsRC6Y14kgyrsgoPqnFD9MqbNt2B9MF3Ch4p114pEVPQ2qktE2nd0aYr7UxRLKA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.8
|
||||
dev: false
|
||||
@ -5665,26 +5598,6 @@ packages:
|
||||
err-code: 2.0.3
|
||||
retry: 0.12.0
|
||||
|
||||
/protobufjs@6.11.4:
|
||||
resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@protobufjs/aspromise': 1.1.2
|
||||
'@protobufjs/base64': 1.1.2
|
||||
'@protobufjs/codegen': 2.0.4
|
||||
'@protobufjs/eventemitter': 1.1.0
|
||||
'@protobufjs/fetch': 1.1.0
|
||||
'@protobufjs/float': 1.0.2
|
||||
'@protobufjs/inquire': 1.1.0
|
||||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/long': 4.0.2
|
||||
'@types/node': 20.11.0
|
||||
long: 4.0.0
|
||||
dev: false
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
@ -5875,26 +5788,26 @@ packages:
|
||||
sprintf-js: 1.1.3
|
||||
optional: true
|
||||
|
||||
/rollup@4.10.0:
|
||||
resolution: {integrity: sha512-t2v9G2AKxcQ8yrG+WGxctBes1AomT0M4ND7jTFBCVPXQ/WFTvNSefIrNSmLKhIKBrvN8SG+CZslimJcT3W2u2g==}
|
||||
/rollup@4.12.0:
|
||||
resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.10.0
|
||||
'@rollup/rollup-android-arm64': 4.10.0
|
||||
'@rollup/rollup-darwin-arm64': 4.10.0
|
||||
'@rollup/rollup-darwin-x64': 4.10.0
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.10.0
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.10.0
|
||||
'@rollup/rollup-linux-arm64-musl': 4.10.0
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.10.0
|
||||
'@rollup/rollup-linux-x64-gnu': 4.10.0
|
||||
'@rollup/rollup-linux-x64-musl': 4.10.0
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.10.0
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.10.0
|
||||
'@rollup/rollup-win32-x64-msvc': 4.10.0
|
||||
'@rollup/rollup-android-arm-eabi': 4.12.0
|
||||
'@rollup/rollup-android-arm64': 4.12.0
|
||||
'@rollup/rollup-darwin-arm64': 4.12.0
|
||||
'@rollup/rollup-darwin-x64': 4.12.0
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.12.0
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.12.0
|
||||
'@rollup/rollup-linux-arm64-musl': 4.12.0
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.12.0
|
||||
'@rollup/rollup-linux-x64-gnu': 4.12.0
|
||||
'@rollup/rollup-linux-x64-musl': 4.12.0
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.12.0
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.12.0
|
||||
'@rollup/rollup-win32-x64-msvc': 4.12.0
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
@ -6147,7 +6060,7 @@ packages:
|
||||
ip: 2.0.0
|
||||
smart-buffer: 4.2.0
|
||||
|
||||
/solid-floating-ui@0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.14):
|
||||
/solid-floating-ui@0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
@ -6155,17 +6068,17 @@ packages:
|
||||
solid-js: ^1.8
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.6.3
|
||||
solid-js: 1.8.14
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/solid-js@1.8.14:
|
||||
resolution: {integrity: sha512-kDfgHBm+ROVLDVuqaXh/jYz0ZVJ29TYfVsKsgDPtNcjoyaPtOvDX2l0tVnthjLdEXr7vDTYeqEYFfMkZakDsOQ==}
|
||||
/solid-js@1.8.15:
|
||||
resolution: {integrity: sha512-d0QP/efr3UVcwGgWVPveQQ0IHOH6iU7yUhc2piy8arNG8wxKmvUy1kFxyF8owpmfCWGB87usDKMaVnsNYZm+Vw==}
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
seroval: 1.0.4
|
||||
seroval-plugins: 1.0.4(seroval@1.0.4)
|
||||
|
||||
/solid-refresh@0.6.3(solid-js@1.8.14):
|
||||
/solid-refresh@0.6.3(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==}
|
||||
peerDependencies:
|
||||
solid-js: ^1.3
|
||||
@ -6173,28 +6086,28 @@ packages:
|
||||
'@babel/generator': 7.23.6
|
||||
'@babel/helper-module-imports': 7.22.15
|
||||
'@babel/types': 7.23.6
|
||||
solid-js: 1.8.14
|
||||
solid-js: 1.8.15
|
||||
dev: true
|
||||
|
||||
/solid-styled-components@0.28.5(solid-js@1.8.14):
|
||||
/solid-styled-components@0.28.5(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-vwTcdp76wZNnESIzB6rRZ3U55NgcSAQXCiiRIiEFhxTFqT0bEh/warNT1qaRZu4OkAzrBkViOngF35ktI8sc4A==}
|
||||
peerDependencies:
|
||||
solid-js: ^1.4.4
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
goober: 2.1.14(csstype@3.1.3)
|
||||
solid-js: 1.8.14
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/solid-transition-group@0.2.3(solid-js@1.8.14):
|
||||
/solid-transition-group@0.2.3(solid-js@1.8.15):
|
||||
resolution: {integrity: sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==}
|
||||
engines: {node: '>=18.0.0', pnpm: '>=8.6.0'}
|
||||
peerDependencies:
|
||||
solid-js: ^1.6.12
|
||||
dependencies:
|
||||
'@solid-primitives/refs': 1.0.6(solid-js@1.8.14)
|
||||
'@solid-primitives/transition-group': 1.0.4(solid-js@1.8.14)
|
||||
solid-js: 1.8.14
|
||||
'@solid-primitives/refs': 1.0.6(solid-js@1.8.15)
|
||||
'@solid-primitives/transition-group': 1.0.4(solid-js@1.8.15)
|
||||
solid-js: 1.8.15
|
||||
dev: false
|
||||
|
||||
/source-map-js@1.0.2:
|
||||
@ -6585,8 +6498,8 @@ packages:
|
||||
/undici-types@5.26.5:
|
||||
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
|
||||
|
||||
/undici@5.28.2:
|
||||
resolution: {integrity: sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==}
|
||||
/undici@5.28.3:
|
||||
resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==}
|
||||
engines: {node: '>=14.0'}
|
||||
dependencies:
|
||||
'@fastify/busboy': 2.1.0
|
||||
@ -6703,7 +6616,7 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/vite-plugin-inspect@0.8.3(rollup@4.10.0)(vite@5.1.1):
|
||||
/vite-plugin-inspect@0.8.3(rollup@4.12.0)(vite@5.1.3):
|
||||
resolution: {integrity: sha512-SBVzOIdP/kwe6hjkt7LSW4D0+REqqe58AumcnCfRNw4Kt3mbS9pEBkch+nupu2PBxv2tQi69EQHQ1ZA1vgB/Og==}
|
||||
engines: {node: '>=14'}
|
||||
peerDependencies:
|
||||
@ -6714,7 +6627,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@antfu/utils': 0.7.7
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.10.0)
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.12.0)
|
||||
debug: 4.3.4
|
||||
error-stack-parser-es: 0.1.1
|
||||
fs-extra: 11.2.0
|
||||
@ -6722,7 +6635,7 @@ packages:
|
||||
perfect-debounce: 1.0.0
|
||||
picocolors: 1.0.0
|
||||
sirv: 2.0.4
|
||||
vite: 5.1.1(@types/node@20.11.0)
|
||||
vite: 5.1.3(@types/node@20.11.0)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
@ -6734,8 +6647,8 @@ packages:
|
||||
lib-esm: 0.4.2
|
||||
dev: true
|
||||
|
||||
/vite-plugin-solid@2.9.1(solid-js@1.8.14)(vite@5.1.1):
|
||||
resolution: {integrity: sha512-RC4hj+lbvljw57BbMGDApvEOPEh14lwrr/GeXRLNQLcR1qnOdzOwwTSFy13Gj/6FNIZpBEl0bWPU+VYFawrqUw==}
|
||||
/vite-plugin-solid@2.10.1(solid-js@1.8.15)(vite@5.1.3):
|
||||
resolution: {integrity: sha512-kfVdNLWaJqaJVL52U6iCCKNW/nXE7bS1VVGOWPGllOkJfcNILymVSY0LCBLSnyy0iYnRtrXpiHm14rMuzeC7CA==}
|
||||
peerDependencies:
|
||||
'@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.*
|
||||
solid-js: ^1.7.2
|
||||
@ -6748,16 +6661,16 @@ packages:
|
||||
'@types/babel__core': 7.20.5
|
||||
babel-preset-solid: 1.8.12(@babel/core@7.23.7)
|
||||
merge-anything: 5.1.7
|
||||
solid-js: 1.8.14
|
||||
solid-refresh: 0.6.3(solid-js@1.8.14)
|
||||
vite: 5.1.1(@types/node@20.11.0)
|
||||
vitefu: 0.2.5(vite@5.1.1)
|
||||
solid-js: 1.8.15
|
||||
solid-refresh: 0.6.3(solid-js@1.8.15)
|
||||
vite: 5.1.3(@types/node@20.11.0)
|
||||
vitefu: 0.2.5(vite@5.1.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vite@5.1.1(@types/node@20.11.0):
|
||||
resolution: {integrity: sha512-wclpAgY3F1tR7t9LL5CcHC41YPkQIpKUGeIuT8MdNwNZr6OqOTLs7JX5vIHAtzqLWXts0T+GDrh9pN2arneKqg==}
|
||||
/vite@5.1.3(@types/node@20.11.0):
|
||||
resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -6787,12 +6700,12 @@ packages:
|
||||
'@types/node': 20.11.0
|
||||
esbuild: 0.19.12
|
||||
postcss: 8.4.35
|
||||
rollup: 4.10.0
|
||||
rollup: 4.12.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/vitefu@0.2.5(vite@5.1.1):
|
||||
/vitefu@0.2.5(vite@5.1.3):
|
||||
resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==}
|
||||
peerDependencies:
|
||||
vite: ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
@ -6800,7 +6713,7 @@ packages:
|
||||
vite:
|
||||
optional: true
|
||||
dependencies:
|
||||
vite: 5.1.1(@types/node@20.11.0)
|
||||
vite: 5.1.3(@types/node@20.11.0)
|
||||
dev: true
|
||||
|
||||
/vudio@2.1.1(patch_hash=7iux5msqpgl3octdmwy4uspwoe):
|
||||
@ -6983,18 +6896,7 @@ packages:
|
||||
dependencies:
|
||||
jintr: 1.1.0
|
||||
tslib: 2.6.2
|
||||
undici: 5.28.2
|
||||
dev: false
|
||||
|
||||
github.com/metaquanta/node-castv2/71419bd736ac859b18fb84a2c459756f2b9ccb5a:
|
||||
resolution: {tarball: https://codeload.github.com/metaquanta/node-castv2/tar.gz/71419bd736ac859b18fb84a2c459756f2b9ccb5a}
|
||||
name: castv2
|
||||
version: 0.1.10
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
protobufjs: 6.11.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
undici: 5.28.3
|
||||
dev: false
|
||||
|
||||
github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6:
|
||||
|
||||
@ -16,24 +16,42 @@ const migrations = {
|
||||
secret?: string;
|
||||
};
|
||||
if (lastfmConfig) {
|
||||
const scrobblerConfig = store.get(
|
||||
let scrobblerConfig = store.get(
|
||||
'plugins.scrobbler',
|
||||
) as {
|
||||
enabled?: boolean;
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
scrobblers?: {
|
||||
lastfm?: {
|
||||
enabled?: boolean;
|
||||
token?: string;
|
||||
session_key?: string;
|
||||
api_root?: string;
|
||||
api_key?: string;
|
||||
sessionKey?: string;
|
||||
apiRoot?: string;
|
||||
apiKey?: string;
|
||||
secret?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
} | undefined;
|
||||
|
||||
scrobblerConfig.enabled = lastfmConfig.enabled;
|
||||
scrobblerConfig.scrobblers.lastfm = lastfmConfig;
|
||||
if (!scrobblerConfig) {
|
||||
scrobblerConfig = {
|
||||
enabled: lastfmConfig.enabled,
|
||||
};
|
||||
}
|
||||
|
||||
if (!scrobblerConfig.scrobblers) {
|
||||
scrobblerConfig.scrobblers = {
|
||||
lastfm: {},
|
||||
};
|
||||
}
|
||||
|
||||
scrobblerConfig.scrobblers.lastfm = {
|
||||
enabled: lastfmConfig.enabled,
|
||||
token: lastfmConfig.token,
|
||||
sessionKey: lastfmConfig.session_key,
|
||||
apiRoot: lastfmConfig.api_root,
|
||||
apiKey: lastfmConfig.api_key,
|
||||
secret: lastfmConfig.secret,
|
||||
};
|
||||
store.set('plugins.scrobbler', scrobblerConfig);
|
||||
}
|
||||
},
|
||||
|
||||
14
src/electron-chromecast.d.ts
vendored
14
src/electron-chromecast.d.ts
vendored
@ -1,14 +0,0 @@
|
||||
declare module '@jellybrick/electron-chromecast' {
|
||||
export const chrome: typeof window.chrome;
|
||||
export const requestHandler: (receiverList: Array<object>) => Promise<unknown>;
|
||||
export const castSetting: {
|
||||
devMode: boolean;
|
||||
};
|
||||
export const castConsole: {
|
||||
log: (message: unknown[]) => void;
|
||||
info: (message: unknown[]) => void;
|
||||
warn: (message: unknown[]) => void;
|
||||
error: (message: unknown[]) => void;
|
||||
};
|
||||
export const injectChromeCompatToObject: (obj: object) => void;
|
||||
}
|
||||
@ -98,7 +98,7 @@
|
||||
"submenu": {
|
||||
"auto-reset-app-cache": "Mengatur ulang cache aplikasi saat aplikasi dimulai",
|
||||
"disable-hardware-acceleration": "Menonaktifkan akselerasi perangkat keras",
|
||||
"edit-config-json": "Edit config.json",
|
||||
"edit-config-json": "Ubah config.json",
|
||||
"override-user-agent": "Mengesampingkan User-Agent",
|
||||
"restart-on-config-changes": "Mulai ulang pada perubahan konfigurasi",
|
||||
"set-proxy": {
|
||||
@ -194,7 +194,7 @@
|
||||
"show": "Tampilkan jendela",
|
||||
"tooltip": {
|
||||
"default": "YouTube Musik",
|
||||
"with-song-info": "YouTube Music: {{artist}} - {{Judul}}"
|
||||
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -207,7 +207,7 @@
|
||||
"name": "Pemblokir Iklan"
|
||||
},
|
||||
"album-actions": {
|
||||
"description": "Menambahkan tombol Tidak Suka, Tidak Suka, Suka, dan Tidak Suka untuk menerapkannya ke semua lagu dalam daftar putar atau album",
|
||||
"description": "Tambah tombol Suka, Batal Suka, Tidak Suka dan Batal Tidak Suka untuk diterapkan ke semua lagu dalam daftar putar atau album",
|
||||
"name": "Tindakan Album"
|
||||
},
|
||||
"album-color-theme": {
|
||||
@ -398,7 +398,285 @@
|
||||
"video-id-not-found": "Video tidak ditemukan",
|
||||
"writing-id3": "Menulis tanda ID3…"
|
||||
}
|
||||
},
|
||||
"description": "Unduh MP3 / sumber suara secara langsung via antarmuka",
|
||||
"menu": {
|
||||
"choose-download-folder": "Pilih folder unduhan",
|
||||
"download-playlist": "Unduh daftar putar",
|
||||
"presets": "Prasetel",
|
||||
"skip-existing": "Lewati berkas yang sudah ada"
|
||||
},
|
||||
"name": "Pengunduh",
|
||||
"renderer": {
|
||||
"can-not-update-progress": "Tidak dapat memperbarui proses"
|
||||
},
|
||||
"templates": {
|
||||
"button": "Unduh"
|
||||
}
|
||||
},
|
||||
"exponential-volume": {
|
||||
"description": "Buat penggeser volume menjadi eksponen sehingga memudahkan memilih volume yang lebih rendah.",
|
||||
"name": "Volume Eksponen"
|
||||
},
|
||||
"in-app-menu": {
|
||||
"description": "Buat bilah-menu terlihat indah, gelap atau serupa dengan album",
|
||||
"menu": {
|
||||
"hide-dom-window-controls": "Sembunyikan DOM pengendali jendela"
|
||||
},
|
||||
"name": "Menu di Aplikasi"
|
||||
},
|
||||
"lumiastream": {
|
||||
"description": "Tambah dukungan Lumia Stream",
|
||||
"name": "Lumia Stream [Beta]"
|
||||
},
|
||||
"lyrics-genius": {
|
||||
"description": "Tambah dukungan lirik untuk kebanyakan lagu",
|
||||
"menu": {
|
||||
"romanized-lyrics": "Romanisasi Lirik"
|
||||
},
|
||||
"name": "Lirik Genius",
|
||||
"renderer": {
|
||||
"fetched-lyrics": "Lirik yang diambil untuk Genius"
|
||||
}
|
||||
},
|
||||
"music-together": {
|
||||
"description": "Bagikan daftar putar dengan yang lain. Saat host memainkan lagu, semua orang akan mendengarkan lagu yang sama",
|
||||
"dialog": {
|
||||
"enter-host": "Masukkan ID Host"
|
||||
},
|
||||
"internal": {
|
||||
"save": "Simpan",
|
||||
"track-source": "Sumber Trek",
|
||||
"unknown-user": "Pengguna Tidak Diketahui"
|
||||
},
|
||||
"menu": {
|
||||
"click-to-copy-id": "Salin ID Host",
|
||||
"close": "Tutup Musik Bersama",
|
||||
"connected-users": "Pengguna Terhubung",
|
||||
"disconnect": "Putuskan Musik Bersama",
|
||||
"empty-user": "Tidak ada pengguna terhubung",
|
||||
"host": "Host Musik Bersama",
|
||||
"join": "Gabung Musik Bersama",
|
||||
"permission": {
|
||||
"all": "Izinkan tamu untuk mengendalikan daftar putar dan pemutar",
|
||||
"host-only": "Hanya host yang dapat mengendalikan daftar putar dan pemutar",
|
||||
"playlist": "Izinkan tamu untuk mengendalikan daftar putar"
|
||||
},
|
||||
"set-permission": "Ubah Pengendali Izin",
|
||||
"status": {
|
||||
"disconnected": "Terputus",
|
||||
"guest": "Terhubung sebagai Tamu",
|
||||
"host": "Terhubung sebagai Host"
|
||||
}
|
||||
},
|
||||
"name": "Musik Bersama [Beta]",
|
||||
"toast": {
|
||||
"add-song-failed": "Gagal untuk menambahkan lagu",
|
||||
"closed": "Musik Bersama ditutup",
|
||||
"disconnected": "Musik Bersama terputus",
|
||||
"host-failed": "Gagal untuk memulai Musik Bersama",
|
||||
"id-copied": "ID Host tersalin ke papan klip",
|
||||
"id-copy-failed": "Gagal menyalin ID Host ke papan klip",
|
||||
"join-failed": "Gagal untuk bergabung ke Musik Bersama",
|
||||
"joined": "Bergabung ke Musik Bersama",
|
||||
"permission-changed": "Perizinan Musik Bersama diubah ke \"{{permission}}\"",
|
||||
"remove-song-failed": "Gagal menghapus lagu",
|
||||
"user-connected": "{{name}} bergabung ke Musik Bersama",
|
||||
"user-disconnected": "{{name}} meninggalkan Musik Bersama"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"description": "panah navigasi Selanjutnya/Sebelumnya terintegrasi pada antarmuka, layaknya peramban kesukaan Anda",
|
||||
"name": "Navigasi"
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Hapus tombol dan tautan masuk Google dari antarmuka",
|
||||
"name": "Tanpa Google Login"
|
||||
},
|
||||
"notifications": {
|
||||
"description": "Tampilkan pemberitahuan saat lagu dimainkan (pemberitahuan interaktif tersedia di Windows)",
|
||||
"menu": {
|
||||
"interactive": "Pemberitahuan Interaktif",
|
||||
"interactive-settings": {
|
||||
"label": "Pengaturan Interaktif",
|
||||
"submenu": {
|
||||
"hide-button-text": "Sembunyikan teks tombol",
|
||||
"refresh-on-play-pause": "Segarkan saat Putar/Jeda",
|
||||
"tray-controls": "Buka/Tutup saat baki ditekan"
|
||||
}
|
||||
},
|
||||
"priority": "Prioritas Pemberitahuan",
|
||||
"toast-style": "Gaya Toast",
|
||||
"unpause-notification": "Tampilkan pemberitahuan saat tidak dijeda"
|
||||
},
|
||||
"name": "Pemberitahuan"
|
||||
},
|
||||
"picture-in-picture": {
|
||||
"description": "Izinkan untuk memindahkan aplikasi ke mode gambar-dalam-gambar",
|
||||
"menu": {
|
||||
"always-on-top": "Selalu di atas",
|
||||
"hotkey": {
|
||||
"label": "Pintasan",
|
||||
"prompt": {
|
||||
"keybind-options": {
|
||||
"hotkey": "Pintasan"
|
||||
},
|
||||
"label": "Pilih pintasan untuk beralih ke gambar-dalam-gambar",
|
||||
"title": "Pintasan gambar-dalam-gambar"
|
||||
}
|
||||
},
|
||||
"save-window-position": "Simpan posisi jendela",
|
||||
"save-window-size": "Simpan ukuran jendela",
|
||||
"use-native-pip": "Gunakan PiP bawaan peramban"
|
||||
},
|
||||
"name": "Gambar-dalam-gambar",
|
||||
"templates": {
|
||||
"button": "Gambar-dalam-gambar"
|
||||
}
|
||||
},
|
||||
"playback-speed": {
|
||||
"description": "Dengarkan cepat, dengarkan perlahan! Tambahkan penggeser untuk mengendalikan kecepatan lagu",
|
||||
"name": "Kecepatan Pemutar",
|
||||
"templates": {
|
||||
"button": "Kecepatan"
|
||||
}
|
||||
},
|
||||
"precise-volume": {
|
||||
"description": "Kendalikan volume secara presisi menggunakan roda tetikus/pintasan, dengan HUD kustom dan langkah volume yang dapat diatur",
|
||||
"menu": {
|
||||
"arrows-shortcuts": "Kendali Tombol Panah Lokal",
|
||||
"custom-volume-steps": "Atur Langkah Volume Kustom",
|
||||
"global-shortcuts": "Pintasan Global"
|
||||
},
|
||||
"name": "Volume Presisi",
|
||||
"prompt": {
|
||||
"global-shortcuts": {
|
||||
"keybind-options": {
|
||||
"decrease": "Kurangi Volume",
|
||||
"increase": "Tingkatkan Volume"
|
||||
},
|
||||
"label": "Pilih Pintasan Volume Global:",
|
||||
"title": "Pintasan Volume Global"
|
||||
},
|
||||
"volume-steps": {
|
||||
"label": "Pilih Langkah Peningkatan/Pengurangan Volume",
|
||||
"title": "Langkah Volume"
|
||||
}
|
||||
}
|
||||
},
|
||||
"quality-changer": {
|
||||
"backend": {
|
||||
"dialog": {
|
||||
"quality-changer": {
|
||||
"detail": "Kualitas Terkini: {{quality}}",
|
||||
"message": "Pilih Kualitas Video:",
|
||||
"title": "Pilih Kualitas Video"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Izinkan untuk mengubah kualitas video dengan tombol pada hamparan video",
|
||||
"name": "Pengubah Kualitas Video"
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Tambahkan dukungan scrobbling (mis. last.fm, Listenbrainz)",
|
||||
"menu": {
|
||||
"lastfm": {
|
||||
"api-settings": "Pengaturan API Last.fm"
|
||||
},
|
||||
"listenbrainz": {
|
||||
"token": "Masukkan token pengguna ListenBrainz"
|
||||
},
|
||||
"scrobble-other-media": "Scrobble media lain"
|
||||
},
|
||||
"name": "Scrobbler",
|
||||
"prompt": {
|
||||
"lastfm": {
|
||||
"api-key": "Kunci API Last.fm",
|
||||
"api-secret": "Secret API Last.fm"
|
||||
},
|
||||
"listenbrainz": {
|
||||
"token": {
|
||||
"label": "Masukkan token pengguna ListenBrainz Anda:",
|
||||
"title": "Token ListenBrainz"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortcuts": {
|
||||
"description": "Izinkan pengaturan pintasan global untuk pemutar (main/jeda/selanjutnya/sebelumnya) dan mematikan OSD media dengan mengesampingkan tombol media, mengaktifkan Ctrl/CMD + F untuk pencarian, mengaktifkan dukungan MPRIS Linux untuk tombol media, dan tombol pintasan kustom untuk pengguna lanjutan",
|
||||
"menu": {
|
||||
"override-media-keys": "Timpa Tombol Media",
|
||||
"set-keybinds": "Atur Pengendali Lagu Global"
|
||||
},
|
||||
"name": "Pintasan (& MPRIS)",
|
||||
"prompt": {
|
||||
"keybind": {
|
||||
"keybind-options": {
|
||||
"next": "Selanjutnya",
|
||||
"play-pause": "Main / Jeda",
|
||||
"previous": "Sebelumnya"
|
||||
},
|
||||
"label": "Pilih Pintasan Global untuk Pengendali Lagu:",
|
||||
"title": "Pintasan Global"
|
||||
}
|
||||
}
|
||||
},
|
||||
"skip-disliked-songs": {
|
||||
"description": "Lewati lagu yang tidak disukai",
|
||||
"name": "Lewati Lagu yang Tidak Disukai"
|
||||
},
|
||||
"skip-silences": {
|
||||
"description": "Otomatis lewati bagian hening dari lagu",
|
||||
"name": "Lewati Keheningan"
|
||||
},
|
||||
"sponsorblock": {
|
||||
"description": "Otomatis Melewati bagian yang bukan musik seperti intro/outro atau bagian dari video musik di mana lagu tidak dimainkan",
|
||||
"name": "SponsorBlock"
|
||||
},
|
||||
"taskbar-mediacontrol": {
|
||||
"description": "Kendalikan pemutaran dari bilah alat Windows",
|
||||
"name": "Pengendali Media di Bilah Alat"
|
||||
},
|
||||
"touchbar": {
|
||||
"description": "Tambahkan widget TouchBar untuk pengguna macOS",
|
||||
"name": "TouchBar"
|
||||
},
|
||||
"tuna-obs": {
|
||||
"description": "Integrasi dengan plugin Tuna OBS",
|
||||
"name": "Tuna OBS"
|
||||
},
|
||||
"video-toggle": {
|
||||
"description": "Tambahkan tombol untuk beralih antara mode Lagu/Video. secara opsional juga dapat menghapus keseluruhan tab video",
|
||||
"menu": {
|
||||
"align": {
|
||||
"label": "Perataan",
|
||||
"submenu": {
|
||||
"left": "Kiri",
|
||||
"middle": "Tengah",
|
||||
"right": "Kanan"
|
||||
}
|
||||
},
|
||||
"force-hide": "Paksa hapus tab video",
|
||||
"mode": {
|
||||
"label": "Mode",
|
||||
"submenu": {
|
||||
"custom": "Peralih kustom",
|
||||
"disabled": "Mati",
|
||||
"native": "Peralih bawaan"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "Peralih Video",
|
||||
"templates": {
|
||||
"button": "Lagu"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
"description": "Tambahkan visualisator ke pemutar",
|
||||
"menu": {
|
||||
"visualizer-type": "Tipe Visualisator"
|
||||
},
|
||||
"name": "Visualisator"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,6 +212,13 @@
|
||||
},
|
||||
"album-color-theme": {
|
||||
"description": "Stosuje dynamiczny motyw i efekty wizualne w oparciu o paletę kolorów albumu",
|
||||
"menu": {
|
||||
"color-mix-ratio": {
|
||||
"submenu": {
|
||||
"percent": "{{ratio}}%"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "Motyw kolorów albumu"
|
||||
},
|
||||
"ambient-mode": {
|
||||
@ -569,6 +576,24 @@
|
||||
"description": "Umożliwia zmianę jakości wideo za pomocą przycisku na nakładce wideo",
|
||||
"name": "Zmieniacz jakości wideo"
|
||||
},
|
||||
"scrobbler": {
|
||||
"menu": {
|
||||
"listenbrainz": {
|
||||
"token": "Podaj token użytkownika ListenBrainz"
|
||||
}
|
||||
},
|
||||
"prompt": {
|
||||
"lastfm": {
|
||||
"api-key": "klucz API Last.fm"
|
||||
},
|
||||
"listenbrainz": {
|
||||
"token": {
|
||||
"label": "Podaj swój token użytkownika ListenBrainz:",
|
||||
"title": "Token ListenBrainz"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortcuts": {
|
||||
"description": "Umożliwia ustawienie globalnych skrótów klawiszowych do odtwarzania (odtwarzanie/pauza/następny/poprzedni) + wyłączanie OSD multimediów poprzez zastąpienie klawiszy multimediów, włączając kombinację klawiszy Ctrl/CMD + F w celu wyszukiwania, obsługę Linux MPRIS dla klawiszy multimediów oraz niestandardowe skróty klawiszowe dla zaawansowanych użytkowników",
|
||||
"menu": {
|
||||
|
||||
@ -586,7 +586,7 @@ app.whenReady().then(async () => {
|
||||
);
|
||||
try {
|
||||
// Check if shortcut is registered and valid
|
||||
const shortcutDetails = shell.readShortcutLink(shortcutPath); // Throw error if doesn't exist yet
|
||||
const shortcutDetails = shell.readShortcutLink(shortcutPath); // Throw error if it doesn't exist yet
|
||||
if (
|
||||
shortcutDetails.target !== appLocation ||
|
||||
shortcutDetails.appUserModelId !== appID
|
||||
|
||||
@ -30,7 +30,7 @@ import {
|
||||
|
||||
import { fetchFromGenius } from '@/plugins/lyrics-genius/main';
|
||||
import { isEnabled } from '@/config/plugins';
|
||||
import { cleanupName, getImage, SongInfo } from '@/providers/song-info';
|
||||
import { cleanupName, getImage, MediaType, type SongInfo } from '@/providers/song-info';
|
||||
import { getNetFetchAsFetch } from '@/plugins/utils/main';
|
||||
import { cache } from '@/providers/decorators';
|
||||
|
||||
@ -686,6 +686,7 @@ const getMetadata = (info: TrackInfo): CustomSongInfo => ({
|
||||
?.url,
|
||||
views: info.basic_info.view_count!,
|
||||
songDuration: info.basic_info.duration!,
|
||||
mediaType: MediaType.Audio,
|
||||
});
|
||||
|
||||
// This is used to bypass age restrictions
|
||||
|
||||
@ -4,8 +4,24 @@ export interface InAppMenuConfig {
|
||||
}
|
||||
export const defaultInAppMenuConfig: InAppMenuConfig = {
|
||||
enabled:
|
||||
(typeof window !== 'undefined' &&
|
||||
!window.navigator?.userAgent?.includes('mac')) ||
|
||||
(typeof global !== 'undefined' && global.process?.platform !== 'darwin'),
|
||||
(
|
||||
(
|
||||
typeof window !== 'undefined' &&
|
||||
!window.navigator?.userAgent?.includes('mac')
|
||||
) ||
|
||||
(
|
||||
typeof global !== 'undefined' &&
|
||||
global.process?.platform !== 'darwin'
|
||||
)
|
||||
) && (
|
||||
(
|
||||
typeof window !== 'undefined' &&
|
||||
!window.navigator?.userAgent?.includes('linux')
|
||||
) ||
|
||||
(
|
||||
typeof global !== 'undefined' &&
|
||||
global.process?.platform !== 'linux'
|
||||
)
|
||||
),
|
||||
hideDOMWindowControls: false,
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ import is from 'electron-is';
|
||||
|
||||
import { t } from '@/i18n';
|
||||
|
||||
import type { InAppMenuConfig } from './index';
|
||||
import type { InAppMenuConfig } from './constants';
|
||||
import type { MenuContext } from '@/types/contexts';
|
||||
import type { MenuTemplate } from '@/menu';
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { JSX, splitProps } from 'solid-js';
|
||||
import { css } from 'solid-styled-components';
|
||||
|
||||
import { cache } from '@/providers/decorators';
|
||||
|
||||
const menuStyle = cache(() => css`
|
||||
|
||||
@ -4,6 +4,7 @@ import { css } from 'solid-styled-components';
|
||||
import { Transition } from 'solid-transition-group';
|
||||
import { autoUpdate, flip, offset, OffsetOptions, size } from '@floating-ui/dom';
|
||||
import { useFloating } from 'solid-floating-ui';
|
||||
|
||||
import { cache } from '@/providers/decorators';
|
||||
|
||||
const panelStyle = cache(() => css`
|
||||
@ -131,6 +132,7 @@ export const Panel = (props: PanelProps) => {
|
||||
<Show when={local.open}>
|
||||
<ul
|
||||
{...leftProps}
|
||||
id={'sub-panel'}
|
||||
ref={setPanel}
|
||||
class={panelStyle()}
|
||||
style={{
|
||||
|
||||
@ -9,9 +9,10 @@ import { PanelItem } from './PanelItem';
|
||||
import { IconButton } from './IconButton';
|
||||
import { WindowController } from './WindowController';
|
||||
|
||||
import { cache } from '@/providers/decorators';
|
||||
|
||||
import type { RendererContext } from '@/types/contexts';
|
||||
import type { InAppMenuConfig } from '../constants';
|
||||
import { cache } from '@/providers/decorators';
|
||||
|
||||
const titleStyle = cache(() => css`
|
||||
-webkit-app-region: drag;
|
||||
@ -243,6 +244,19 @@ export const TitleBar = (props: TitleBarProps) => {
|
||||
|
||||
props.ipc.on('window-maximize', refetchMaximize);
|
||||
props.ipc.on('window-unmaximize', refetchMaximize);
|
||||
|
||||
// close menu when the outside of the panel or sub-panel is clicked
|
||||
document.body.addEventListener('click', (e) => {
|
||||
if (
|
||||
e.target instanceof HTMLElement &&
|
||||
!(
|
||||
e.target.closest('#main-panel') ||
|
||||
e.target.closest('#sub-panel')
|
||||
)
|
||||
) {
|
||||
setOpenTarget(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
createEffect(() => {
|
||||
@ -252,7 +266,7 @@ export const TitleBar = (props: TitleBarProps) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<nav class={titleStyle()} data-macos={props.isMacOS}>
|
||||
<nav id={'main-panel'} class={titleStyle()} data-macos={props.isMacOS}>
|
||||
<IconButton
|
||||
onClick={() => setCollapsed(!collapsed())}
|
||||
style={{
|
||||
|
||||
@ -38,7 +38,7 @@ export const fetchFromGenius = async (metadata: SongInfo) => {
|
||||
const songArtist = `${cleanupName(metadata.artist)}`;
|
||||
let lyrics: string | null;
|
||||
|
||||
/* Uses Regex to test the title and artist first for said characters if romanization is enabled. Otherwise normal
|
||||
/* Uses Regex to test the title and artist first for said characters if romanization is enabled. Otherwise, normal
|
||||
Genius Lyrics behavior is observed.
|
||||
*/
|
||||
let hasAsianChars = false;
|
||||
|
||||
@ -74,7 +74,7 @@ export class Connection {
|
||||
return conn;
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
disconnect() {
|
||||
if (this._mode === 'disconnected') throw new Error('Already disconnected');
|
||||
|
||||
this._mode = 'disconnected';
|
||||
|
||||
@ -11,7 +11,7 @@ export interface ScrobblerPluginConfig {
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
scrobble_other_media: boolean,
|
||||
scrobbleOtherMedia: boolean,
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
/**
|
||||
@ -27,19 +27,19 @@ export interface ScrobblerPluginConfig {
|
||||
/**
|
||||
* Session key used for scrobbling
|
||||
*/
|
||||
session_key: string | undefined,
|
||||
sessionKey: string | undefined,
|
||||
/**
|
||||
* Root of the Last.fm API
|
||||
*
|
||||
* @default 'http://ws.audioscrobbler.com/2.0/'
|
||||
*/
|
||||
api_root: string,
|
||||
apiRoot: string,
|
||||
/**
|
||||
* Last.fm api key registered by @semvis123
|
||||
*
|
||||
* @default '04d76faaac8726e60988e14c105d421a'
|
||||
*/
|
||||
api_key: string,
|
||||
apiKey: string,
|
||||
/**
|
||||
* Last.fm api secret registered by @semvis123
|
||||
*
|
||||
@ -63,27 +63,27 @@ export interface ScrobblerPluginConfig {
|
||||
*
|
||||
* @default 'https://api.listenbrainz.org/1/'
|
||||
*/
|
||||
api_root: string,
|
||||
apiRoot: string,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultConfig: ScrobblerPluginConfig = {
|
||||
enabled: false,
|
||||
scrobble_other_media: true,
|
||||
scrobbleOtherMedia: true,
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
enabled: false,
|
||||
token: undefined,
|
||||
session_key: undefined,
|
||||
api_root: 'http://ws.audioscrobbler.com/2.0/',
|
||||
api_key: '04d76faaac8726e60988e14c105d421a',
|
||||
sessionKey: undefined,
|
||||
apiRoot: 'https://ws.audioscrobbler.com/2.0/',
|
||||
apiKey: '04d76faaac8726e60988e14c105d421a',
|
||||
secret: 'a5d2a36fdf64819290f6982481eaffa2',
|
||||
},
|
||||
listenbrainz: {
|
||||
enabled: false,
|
||||
token: undefined,
|
||||
api_root: 'https://api.listenbrainz.org/1/',
|
||||
apiRoot: 'https://api.listenbrainz.org/1/',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import registerCallback, { type SongInfo } from '@/providers/song-info';
|
||||
import registerCallback, { MediaType, type SongInfo } from '@/providers/song-info';
|
||||
import { createBackend } from '@/utils';
|
||||
|
||||
import { ScrobblerPluginConfig } from './index';
|
||||
@ -52,7 +52,7 @@ export const backend = createBackend<{
|
||||
if (!songInfo.isPaused) {
|
||||
const configNonnull = this.config!;
|
||||
// Scrobblers normally have no trouble working with official music videos
|
||||
if (!configNonnull.scrobble_other_media && (songInfo.mediaType !== 'AUDIO' && songInfo.mediaType !== 'ORIGINAL_MUSIC_VIDEO')) {
|
||||
if (!configNonnull.scrobble_other_media && (songInfo.mediaType !== MediaType.Audio && songInfo.mediaType !== MediaType.OriginalMusicVideo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -29,20 +29,20 @@ interface LastFmSongData {
|
||||
|
||||
export class LastFmScrobbler extends ScrobblerBase {
|
||||
isSessionCreated(config: ScrobblerPluginConfig): boolean {
|
||||
return !!config.scrobblers.lastfm.session_key;
|
||||
return !!config.scrobblers.lastfm.sessionKey;
|
||||
}
|
||||
|
||||
async createSession(config: ScrobblerPluginConfig, setConfig: SetConfType): Promise<ScrobblerPluginConfig> {
|
||||
// Get and store the session key
|
||||
const data = {
|
||||
api_key: config.scrobblers.lastfm.api_key,
|
||||
api_key: config.scrobblers.lastfm.apiKey,
|
||||
format: 'json',
|
||||
method: 'auth.getsession',
|
||||
token: config.scrobblers.lastfm.token,
|
||||
};
|
||||
const apiSignature = createApiSig(data, config.scrobblers.lastfm.secret);
|
||||
const response = await net.fetch(
|
||||
`${config.scrobblers.lastfm.api_root}${createQueryString(data, apiSignature)}`,
|
||||
`${config.scrobblers.lastfm.apiRoot}${createQueryString(data, apiSignature)}`,
|
||||
);
|
||||
const json = (await response.json()) as {
|
||||
error?: string;
|
||||
@ -56,14 +56,14 @@ export class LastFmScrobbler extends ScrobblerBase {
|
||||
setConfig(config);
|
||||
}
|
||||
if (json.session) {
|
||||
config.scrobblers.lastfm.session_key = json.session.key;
|
||||
config.scrobblers.lastfm.sessionKey = json.session.key;
|
||||
}
|
||||
setConfig(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void {
|
||||
if (!config.scrobblers.lastfm.session_key) {
|
||||
if (!config.scrobblers.lastfm.sessionKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ export class LastFmScrobbler extends ScrobblerBase {
|
||||
}
|
||||
|
||||
addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void {
|
||||
if (!config.scrobblers.lastfm.session_key) {
|
||||
if (!config.scrobblers.lastfm.sessionKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ export class LastFmScrobbler extends ScrobblerBase {
|
||||
setConfig: SetConfType,
|
||||
): Promise<void> {
|
||||
// This sends a post request to the api, and adds the common data
|
||||
if (!config.scrobblers.lastfm.session_key) {
|
||||
if (!config.scrobblers.lastfm.sessionKey) {
|
||||
await this.createSession(config, setConfig);
|
||||
}
|
||||
|
||||
@ -103,8 +103,8 @@ export class LastFmScrobbler extends ScrobblerBase {
|
||||
duration: songInfo.songDuration,
|
||||
artist: songInfo.artist,
|
||||
...(songInfo.album ? { album: songInfo.album } : undefined), // Will be undefined if current song is a video
|
||||
api_key: config.scrobblers.lastfm.api_key,
|
||||
sk: config.scrobblers.lastfm.session_key,
|
||||
api_key: config.scrobblers.lastfm.apiKey,
|
||||
sk: config.scrobblers.lastfm.sessionKey,
|
||||
format: 'json',
|
||||
...data,
|
||||
};
|
||||
@ -126,7 +126,7 @@ export class LastFmScrobbler extends ScrobblerBase {
|
||||
}) => {
|
||||
if (error?.response?.data?.error === 9) {
|
||||
// Session key is invalid, so remove it from the config and reauthenticate
|
||||
config.scrobblers.lastfm.session_key = undefined;
|
||||
config.scrobblers.lastfm.sessionKey = undefined;
|
||||
config.scrobblers.lastfm.token = await createToken(config);
|
||||
await authenticate(config);
|
||||
setConfig(config);
|
||||
@ -188,8 +188,8 @@ const createApiSig = (parameters: LastFmSongData, secret: string) => {
|
||||
const createToken = async ({
|
||||
scrobblers: {
|
||||
lastfm: {
|
||||
api_key: apiKey,
|
||||
api_root: apiRoot,
|
||||
apiKey,
|
||||
apiRoot,
|
||||
secret,
|
||||
}
|
||||
}
|
||||
@ -211,6 +211,6 @@ const createToken = async ({
|
||||
const authenticate = async (config: ScrobblerPluginConfig) => {
|
||||
// Asks the user for authentication
|
||||
await shell.openExternal(
|
||||
`https://www.last.fm/api/auth/?api_key=${config.scrobblers.lastfm.api_key}&token=${config.scrobblers.lastfm.token}`,
|
||||
`https://www.last.fm/api/auth/?api_key=${config.scrobblers.lastfm.apiKey}&token=${config.scrobblers.lastfm.token}`,
|
||||
);
|
||||
};
|
||||
|
||||
@ -36,7 +36,7 @@ export class ListenbrainzScrobbler extends ScrobblerBase {
|
||||
}
|
||||
|
||||
setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void {
|
||||
if (!config.scrobblers.listenbrainz.api_root || !config.scrobblers.listenbrainz.token) {
|
||||
if (!config.scrobblers.listenbrainz.apiRoot || !config.scrobblers.listenbrainz.token) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ export class ListenbrainzScrobbler extends ScrobblerBase {
|
||||
}
|
||||
|
||||
addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void {
|
||||
if (!config.scrobblers.listenbrainz.api_root || !config.scrobblers.listenbrainz.token) {
|
||||
if (!config.scrobblers.listenbrainz.apiRoot || !config.scrobblers.listenbrainz.token) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ function createRequestBody(listenType: string, songInfo: SongInfo): Listenbrainz
|
||||
}
|
||||
|
||||
function submitListen(body: ListenbrainzRequestBody, config: ScrobblerPluginConfig) {
|
||||
net.fetch(config.scrobblers.listenbrainz.api_root + 'submit-listens',
|
||||
net.fetch(config.scrobblers.listenbrainz.apiRoot + 'submit-listens',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
|
||||
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
@ -56,7 +56,7 @@ declare module '@jellybrick/mpris-service' {
|
||||
playbackStatus: string;
|
||||
loopStatus: string;
|
||||
shuffle: boolean;
|
||||
metadata: object;
|
||||
metadata: Track;
|
||||
volume: number;
|
||||
canControl: boolean;
|
||||
canPause: boolean;
|
||||
|
||||
@ -1,37 +1,98 @@
|
||||
import { BrowserWindow, ipcMain } from 'electron';
|
||||
|
||||
import mpris, { Track } from '@jellybrick/mpris-service';
|
||||
import MprisPlayer, { Track } from '@jellybrick/mpris-service';
|
||||
|
||||
import registerCallback from '@/providers/song-info';
|
||||
import registerCallback, { type SongInfo } from '@/providers/song-info';
|
||||
import getSongControls from '@/providers/song-controls';
|
||||
import config from '@/config';
|
||||
import { LoggerPrefix } from '@/utils';
|
||||
|
||||
class YTPlayer extends MprisPlayer {
|
||||
/**
|
||||
* @type {number} The current position in microseconds
|
||||
* @private
|
||||
*/
|
||||
private currentPosition: number;
|
||||
|
||||
constructor(opts: {
|
||||
name: string;
|
||||
identity: string;
|
||||
supportedMimeTypes?: string[];
|
||||
supportedInterfaces?: string[];
|
||||
}) {
|
||||
super(opts);
|
||||
|
||||
this.currentPosition = 0;
|
||||
}
|
||||
|
||||
setPosition(t: number) {
|
||||
this.currentPosition = t;
|
||||
}
|
||||
|
||||
override getPosition(): number {
|
||||
return this.currentPosition;
|
||||
}
|
||||
|
||||
setLoopStatus(status: string) {
|
||||
this.loopStatus = status;
|
||||
}
|
||||
|
||||
isPlaying(): boolean {
|
||||
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_PLAYING;
|
||||
}
|
||||
|
||||
isPaused(): boolean {
|
||||
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_PAUSED;
|
||||
}
|
||||
|
||||
isStopped(): boolean {
|
||||
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_STOPPED;
|
||||
}
|
||||
|
||||
setPlaybackStatus(status: string) {
|
||||
this.playbackStatus = status;
|
||||
}
|
||||
}
|
||||
|
||||
function setupMPRIS() {
|
||||
const instance = new mpris({
|
||||
const instance = new YTPlayer({
|
||||
name: 'youtube-music',
|
||||
identity: 'YouTube Music',
|
||||
supportedMimeTypes: ['audio/mpeg'],
|
||||
supportedInterfaces: ['player'],
|
||||
});
|
||||
instance.canRaise = true;
|
||||
instance.supportedUriSchemes = ['https'];
|
||||
instance.supportedUriSchemes = ['http', 'https'];
|
||||
instance.desktopEntry = 'youtube-music';
|
||||
return instance;
|
||||
}
|
||||
|
||||
function registerMPRIS(win: BrowserWindow) {
|
||||
const songControls = getSongControls(win);
|
||||
const { playPause, next, previous, volumeMinus10, volumePlus10, shuffle } =
|
||||
songControls;
|
||||
const {
|
||||
playPause,
|
||||
next,
|
||||
previous,
|
||||
volumeMinus10,
|
||||
volumePlus10,
|
||||
shuffle,
|
||||
switchRepeat,
|
||||
} = songControls;
|
||||
try {
|
||||
// TODO: "Typing" for this arguments
|
||||
const secToMicro = (n: unknown) => Math.round(Number(n) * 1e6);
|
||||
const microToSec = (n: unknown) => Math.round(Number(n) / 1e6);
|
||||
let currentSongInfo: SongInfo | null = null;
|
||||
const secToMicro = (n: number) => Math.round(Number(n) * 1e6);
|
||||
const microToSec = (n: number) => Math.round(Number(n) / 1e6);
|
||||
|
||||
const seekTo = (e: { position: unknown }) =>
|
||||
win.webContents.send('ytmd:seek-to', microToSec(e.position));
|
||||
const seekBy = (o: unknown) =>
|
||||
win.webContents.send('ytmd:seek-by', microToSec(o));
|
||||
const seekTo = (event: {
|
||||
trackId: string;
|
||||
position: number;
|
||||
}) => {
|
||||
if (event.trackId === currentSongInfo?.videoId) {
|
||||
win.webContents.send('ytmd:seek-to', microToSec(event.position ?? 0));
|
||||
}
|
||||
};
|
||||
const seekBy = (offset: number) =>
|
||||
win.webContents.send('ytmd:seek-by', microToSec(offset));
|
||||
|
||||
const player = setupMPRIS();
|
||||
|
||||
@ -44,21 +105,22 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
|
||||
ipcMain.on('ytmd:seeked', (_, t: number) => player.seeked(secToMicro(t)));
|
||||
|
||||
let currentSeconds = 0;
|
||||
ipcMain.on('ytmd:time-changed', (_, t: number) => (currentSeconds = t));
|
||||
ipcMain.on('ytmd:time-changed', (_, t: number) => {
|
||||
player.setPosition(secToMicro(t));
|
||||
});
|
||||
|
||||
ipcMain.on('ytmd:repeat-changed', (_, mode: string) => {
|
||||
switch (mode) {
|
||||
case 'NONE': {
|
||||
player.loopStatus = mpris.LOOP_STATUS_NONE;
|
||||
player.setLoopStatus(YTPlayer.LOOP_STATUS_NONE);
|
||||
break;
|
||||
}
|
||||
case 'ONE': {
|
||||
player.loopStatus = mpris.LOOP_STATUS_TRACK;
|
||||
player.setLoopStatus(YTPlayer.LOOP_STATUS_TRACK);
|
||||
break;
|
||||
}
|
||||
case 'ALL': {
|
||||
player.loopStatus = mpris.LOOP_STATUS_PLAYLIST;
|
||||
player.setLoopStatus(YTPlayer.LOOP_STATUS_PLAYLIST);
|
||||
// No default
|
||||
break;
|
||||
}
|
||||
@ -67,18 +129,17 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
player.on('loopStatus', (status: string) => {
|
||||
// SwitchRepeat cycles between states in that order
|
||||
const switches = [
|
||||
mpris.LOOP_STATUS_NONE,
|
||||
mpris.LOOP_STATUS_PLAYLIST,
|
||||
mpris.LOOP_STATUS_TRACK,
|
||||
YTPlayer.LOOP_STATUS_NONE,
|
||||
YTPlayer.LOOP_STATUS_PLAYLIST,
|
||||
YTPlayer.LOOP_STATUS_TRACK,
|
||||
];
|
||||
const currentIndex = switches.indexOf(player.loopStatus);
|
||||
const targetIndex = switches.indexOf(status);
|
||||
|
||||
// Get a delta in the range [0,2]
|
||||
const delta = (targetIndex - currentIndex + 3) % 3;
|
||||
songControls.switchRepeat(delta);
|
||||
switchRepeat(delta);
|
||||
});
|
||||
player.getPosition = () => secToMicro(currentSeconds);
|
||||
|
||||
player.on('raise', () => {
|
||||
win.setSkipTaskbar(false);
|
||||
@ -86,22 +147,23 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
});
|
||||
|
||||
player.on('play', () => {
|
||||
if (player.playbackStatus !== mpris.PLAYBACK_STATUS_PLAYING) {
|
||||
player.playbackStatus = mpris.PLAYBACK_STATUS_PLAYING;
|
||||
if (!player.isPlaying()) {
|
||||
player.setPlaybackStatus(YTPlayer.PLAYBACK_STATUS_PLAYING);
|
||||
playPause();
|
||||
}
|
||||
});
|
||||
player.on('pause', () => {
|
||||
if (player.playbackStatus !== mpris.PLAYBACK_STATUS_PAUSED) {
|
||||
player.playbackStatus = mpris.PLAYBACK_STATUS_PAUSED;
|
||||
if (player.playbackStatus !== YTPlayer.PLAYBACK_STATUS_PAUSED) {
|
||||
player.setPlaybackStatus(YTPlayer.PLAYBACK_STATUS_PAUSED);
|
||||
playPause();
|
||||
}
|
||||
});
|
||||
player.on('playpause', () => {
|
||||
player.playbackStatus =
|
||||
player.playbackStatus === mpris.PLAYBACK_STATUS_PLAYING
|
||||
? mpris.PLAYBACK_STATUS_PAUSED
|
||||
: mpris.PLAYBACK_STATUS_PLAYING;
|
||||
player.setPlaybackStatus(
|
||||
player.isPlaying()
|
||||
? YTPlayer.PLAYBACK_STATUS_PAUSED
|
||||
: YTPlayer.PLAYBACK_STATUS_PLAYING
|
||||
);
|
||||
playPause();
|
||||
});
|
||||
|
||||
@ -170,21 +232,32 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
'xesam:title': songInfo.title,
|
||||
'xesam:url': songInfo.url,
|
||||
'xesam:artist': [songInfo.artist],
|
||||
'mpris:trackid': '/',
|
||||
'mpris:trackid': songInfo.videoId,
|
||||
};
|
||||
if (songInfo.album) {
|
||||
data['xesam:album'] = songInfo.album;
|
||||
}
|
||||
currentSongInfo = songInfo;
|
||||
|
||||
player.metadata = data;
|
||||
player.seeked(secToMicro(songInfo.elapsedSeconds));
|
||||
player.playbackStatus = songInfo.isPaused
|
||||
? mpris.PLAYBACK_STATUS_PAUSED
|
||||
: mpris.PLAYBACK_STATUS_PLAYING;
|
||||
|
||||
const currentElapsedMicroSeconds = secToMicro(songInfo.elapsedSeconds ?? 0);
|
||||
player.setPosition(currentElapsedMicroSeconds);
|
||||
player.seeked(currentElapsedMicroSeconds);
|
||||
|
||||
player.setPlaybackStatus(
|
||||
songInfo.isPaused ?
|
||||
YTPlayer.PLAYBACK_STATUS_PAUSED :
|
||||
YTPlayer.PLAYBACK_STATUS_PLAYING
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Error in MPRIS', error);
|
||||
console.error(
|
||||
LoggerPrefix,
|
||||
'Error in MPRIS'
|
||||
);
|
||||
console.trace(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,37 @@
|
||||
import { t } from '@/i18n';
|
||||
import { createPlugin } from '@/utils';
|
||||
|
||||
export default createPlugin({
|
||||
export default createPlugin<
|
||||
unknown,
|
||||
unknown,
|
||||
{
|
||||
observer?: MutationObserver;
|
||||
waitForElem(selector: string): Promise<HTMLElement>;
|
||||
start(): void;
|
||||
stop(): void;
|
||||
}
|
||||
>({
|
||||
name: () => t('plugins.skip-disliked-songs.name'),
|
||||
description: () => t('plugins.skip-disliked-songs.description'),
|
||||
restartNeeded: false,
|
||||
renderer: {
|
||||
observer: null as MutationObserver | null,
|
||||
waitForElem(selector: string) {
|
||||
return new Promise<HTMLElement>((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
const elem = document.querySelector<HTMLElement>(selector);
|
||||
if (!elem) return;
|
||||
|
||||
clearInterval(interval);
|
||||
resolve(elem);
|
||||
});
|
||||
});
|
||||
},
|
||||
start() {
|
||||
this.waitForElem('#like-button-renderer').then((likeBtn) => {
|
||||
this.observer = new MutationObserver(() => {
|
||||
if (likeBtn?.getAttribute('like-status') == 'DISLIKE') {
|
||||
document
|
||||
.querySelector('tp-yt-paper-icon-button.next-button')
|
||||
.querySelector<HTMLButtonElement>('tp-yt-paper-icon-button.next-button')
|
||||
?.click();
|
||||
}
|
||||
});
|
||||
@ -26,16 +45,5 @@ export default createPlugin({
|
||||
stop() {
|
||||
this.observer?.disconnect();
|
||||
},
|
||||
waitForElem(selector) {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
const elem = document.querySelector(selector);
|
||||
if (!elem) return;
|
||||
|
||||
clearInterval(interval);
|
||||
resolve(elem);
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { contextBridge, ipcRenderer, IpcRendererEvent, webFrame } from 'electron';
|
||||
import is from 'electron-is';
|
||||
|
||||
import { injectChromeCompatToObject, chrome } from '@jellybrick/electron-chromecast';
|
||||
|
||||
import config from './config';
|
||||
|
||||
import {
|
||||
@ -55,8 +53,6 @@ contextBridge.exposeInMainWorld(
|
||||
'ELECTRON_RENDERER_URL',
|
||||
process.env.ELECTRON_RENDERER_URL,
|
||||
);
|
||||
injectChromeCompatToObject(global);
|
||||
contextBridge.exposeInMainWorld('caster', chrome);
|
||||
|
||||
const [path, script] = ipcRenderer.sendSync('get-renderer-script') as [string | null, string];
|
||||
let blocked = true;
|
||||
|
||||
@ -3,33 +3,37 @@ import { BrowserWindow, ipcMain } from 'electron';
|
||||
|
||||
export default (win: BrowserWindow) => {
|
||||
const commands = {
|
||||
// Playback
|
||||
previous: () => win.webContents.send('ytmd:previous-video'),
|
||||
next: () => win.webContents.send('ytmd:next-video'),
|
||||
playPause: () => win.webContents.send('ytmd:toggle-play'),
|
||||
like: () => win.webContents.send('ytmd:update-like', 'LIKE'),
|
||||
dislike: () => win.webContents.send('ytmd:update-like', 'DISLIKE'),
|
||||
go10sBack: () => win.webContents.send('ytmd:seek-by', -10),
|
||||
go10sForward: () => win.webContents.send('ytmd:seek-by', 10),
|
||||
go1sBack: () => win.webContents.send('ytmd:seek-by', -1),
|
||||
go1sForward: () => win.webContents.send('ytmd:seek-by', 1),
|
||||
shuffle: () => win.webContents.send('ytmd:shuffle'),
|
||||
switchRepeat: (n = 1) => win.webContents.send('ytmd:switch-repeat', n),
|
||||
// General
|
||||
volumeMinus10: () => {
|
||||
ipcMain.once('ytmd:get-volume-return', (_, volume) => {
|
||||
win.webContents.send('ytmd:update-volume', volume - 10);
|
||||
});
|
||||
win.webContents.send('ytmd:get-volume');
|
||||
},
|
||||
volumePlus10: () => {
|
||||
ipcMain.once('ytmd:get-volume-return', (_, volume) => {
|
||||
win.webContents.send('ytmd:update-volume', volume + 10);
|
||||
});
|
||||
win.webContents.send('ytmd:get-volume');
|
||||
},
|
||||
fullscreen: () => win.webContents.send('ytmd:toggle-fullscreen'),
|
||||
muteUnmute: () => win.webContents.send('ytmd:toggle-mute'),
|
||||
// Playback
|
||||
previous: () => win.webContents.send('ytmd:previous-video'),
|
||||
next: () => win.webContents.send('ytmd:next-video'),
|
||||
playPause: () => win.webContents.send('ytmd:toggle-play'),
|
||||
like: () => win.webContents.send('ytmd:update-like', 'LIKE'),
|
||||
dislike: () => win.webContents.send('ytmd:update-like', 'DISLIKE'),
|
||||
go10sBack: () => win.webContents.send('ytmd:seek-by', -10),
|
||||
go10sForward: () => win.webContents.send('ytmd:seek-by', 10),
|
||||
go1sBack: () => win.webContents.send('ytmd:seek-by', -1),
|
||||
go1sForward: () => win.webContents.send('ytmd:seek-by', 1),
|
||||
shuffle: () => win.webContents.send('ytmd:shuffle'),
|
||||
switchRepeat: (n = 1) => win.webContents.send('ytmd:switch-repeat', n),
|
||||
// General
|
||||
volumeMinus10: () => {
|
||||
ipcMain.once('ytmd:get-volume-return', (_, volume) => {
|
||||
win.webContents.send('ytmd:update-volume', volume - 10);
|
||||
});
|
||||
win.webContents.send('ytmd:get-volume');
|
||||
},
|
||||
volumePlus10: () => {
|
||||
ipcMain.once('ytmd:get-volume-return', (_, volume) => {
|
||||
win.webContents.send('ytmd:update-volume', volume + 10);
|
||||
});
|
||||
win.webContents.send('ytmd:get-volume');
|
||||
},
|
||||
fullscreen: () => win.webContents.send('ytmd:toggle-fullscreen'),
|
||||
muteUnmute: () => win.webContents.send('ytmd:toggle-mute'),
|
||||
search: () => win.webContents.sendInputEvent({
|
||||
type: 'keyDown',
|
||||
keyCode: '/',
|
||||
}),
|
||||
};
|
||||
return {
|
||||
...commands,
|
||||
|
||||
@ -29,8 +29,9 @@ export const setupTimeChangedListener = singleton(() => {
|
||||
const progressObserver = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
const target = mutation.target as Node & { value: string };
|
||||
window.ipcRenderer.send('ytmd:time-changed', target.value);
|
||||
songInfo.elapsedSeconds = Number(target.value);
|
||||
const numberValue = Number(target.value);
|
||||
window.ipcRenderer.send('ytmd:time-changed', numberValue);
|
||||
songInfo.elapsedSeconds = numberValue;
|
||||
}
|
||||
});
|
||||
const progressBar = document.querySelector('#progress-bar');
|
||||
|
||||
@ -7,7 +7,7 @@ import config from '@/config';
|
||||
|
||||
import type { GetPlayerResponse } from '@/types/get-player-response';
|
||||
|
||||
enum MediaType {
|
||||
export enum MediaType {
|
||||
/**
|
||||
* Audio uploaded by the original artist
|
||||
*/
|
||||
@ -125,6 +125,18 @@ const handleData = async (
|
||||
break;
|
||||
default:
|
||||
songInfo.mediaType = MediaType.OtherVideo;
|
||||
// HACK: This is a workaround for "podcast" types where "musicVideoType" doesn't exist. Google :facepalm:
|
||||
if (
|
||||
!config.get('options.usePodcastParticipantAsArtist') &&
|
||||
(
|
||||
data.responseContext.serviceTrackingParams
|
||||
?.at(0)
|
||||
?.params
|
||||
?.find((it) => it.key === 'ipcc')?.value ?? '1'
|
||||
) != '0'
|
||||
) {
|
||||
songInfo.artist = cleanupName(data.microformat.microformatDataRenderer.pageOwnerDetails.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -16,8 +16,6 @@ import { loadI18n, setLanguage, t as i18t } from '@/i18n';
|
||||
import type { PluginConfig } from '@/types/plugins';
|
||||
import type { YoutubePlayer } from '@/types/youtube-player';
|
||||
|
||||
window.chrome.cast = window.caster.cast;
|
||||
|
||||
let api: (Element & YoutubePlayer) | null = null;
|
||||
let isPluginLoaded = false;
|
||||
let isApiLoaded = false;
|
||||
@ -135,7 +133,7 @@ async function onApiLoaded() {
|
||||
// Remove upgrade button
|
||||
if (window.mainConfig.get('options.removeUpgradeButton')) {
|
||||
const styles = document.createElement('style');
|
||||
styles.innerHTML = `ytmusic-guide-signin-promo-renderer {
|
||||
styles.innerHTML = `ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer:last-child {
|
||||
display: none;
|
||||
}`;
|
||||
document.head.appendChild(styles);
|
||||
|
||||
1
src/reset.d.ts
vendored
1
src/reset.d.ts
vendored
@ -22,7 +22,6 @@ declare global {
|
||||
ipcRenderer: typeof electronIpcRenderer;
|
||||
mainConfig: typeof config;
|
||||
electronIs: typeof is;
|
||||
caster: typeof window.chrome;
|
||||
ELECTRON_RENDERER_URL: string | undefined;
|
||||
/**
|
||||
* YouTube Music internal variable (Last interaction time)
|
||||
|
||||
@ -35,6 +35,11 @@ img {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Hide cast button which doesn't work */
|
||||
ytmusic-cast-button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Remove useless inaccessible button on top-right corner of the video player */
|
||||
.ytp-chrome-top-buttons {
|
||||
display: none !important;
|
||||
|
||||
Reference in New Issue
Block a user