mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
Compare commits
42 Commits
b48e05ab28
...
v3.10.0
| Author | SHA1 | Date | |
|---|---|---|---|
| adb88991d9 | |||
| 4dad68d255 | |||
| 33a09cc8e1 | |||
| e2c849f6c4 | |||
| 7b41775b26 | |||
| 6284b87fc7 | |||
| f3f63d4fcd | |||
| cf80dd396c | |||
| c79fc799b2 | |||
| 7789d5d444 | |||
| e0dbd4b88f | |||
| 1c74bbd954 | |||
| d949e3550f | |||
| d76115ab5d | |||
| 5be467a869 | |||
| b2dfbe1ed3 | |||
| a9e9e0bdc2 | |||
| 93ce9cc359 | |||
| 2a626a5ff1 | |||
| 1ccabb8e25 | |||
| 2dae8688c2 | |||
| 65459726a4 | |||
| 0c21accb10 | |||
| 125d2d5163 | |||
| 6c1855b5a5 | |||
| 82c5222610 | |||
| 0d0e2a11e1 | |||
| daf724f9dc | |||
| be2cdb4cb5 | |||
| ff2fdab77d | |||
| 9047169a39 | |||
| 9525df343f | |||
| be2abee85d | |||
| 7d5f7a9527 | |||
| b53ece5836 | |||
| c04dc92d39 | |||
| 78acd2ddbb | |||
| 7126c290e2 | |||
| 58651857e2 | |||
| 8e7c95e68f | |||
| 1c68c5637d | |||
| c44d5ea111 |
22
package.json
22
package.json
@ -2,7 +2,7 @@
|
||||
"name": "youtube-music",
|
||||
"desktopName": "com.github.th_ch.youtube_music",
|
||||
"productName": "YouTube Music",
|
||||
"version": "3.9.0",
|
||||
"version": "3.10.0",
|
||||
"description": "YouTube Music Desktop App - including custom plugins",
|
||||
"main": "./dist/main/index.js",
|
||||
"type": "module",
|
||||
@ -68,11 +68,11 @@
|
||||
"@ffmpeg.wasm/main": "0.12.0",
|
||||
"@floating-ui/dom": "1.7.2",
|
||||
"@foobar404/wave": "2.0.5",
|
||||
"@ghostery/adblocker-electron": "2.11.0",
|
||||
"@ghostery/adblocker-electron-preload": "2.11.0",
|
||||
"@ghostery/adblocker-electron": "2.11.1",
|
||||
"@ghostery/adblocker-electron-preload": "2.11.1",
|
||||
"@hono/node-server": "1.15.0",
|
||||
"@hono/swagger-ui": "0.5.2",
|
||||
"@hono/zod-openapi": "0.19.9",
|
||||
"@hono/zod-openapi": "1.0.0-beta.1",
|
||||
"@hono/zod-validator": "0.7.0",
|
||||
"@jellybrick/dbus-next": "0.10.3",
|
||||
"@jellybrick/electron-better-web-request": "1.0.4",
|
||||
@ -82,7 +82,7 @@
|
||||
"@xhayper/discord-rpc": "1.2.2",
|
||||
"async-mutex": "0.5.0",
|
||||
"bgutils-js": "3.2.0",
|
||||
"butterchurn": "3.0.0-beta.4",
|
||||
"butterchurn": "3.0.0-beta.5",
|
||||
"butterchurn-presets": "3.0.0-beta.4",
|
||||
"color": "5.0.0",
|
||||
"conf": "14.0.0",
|
||||
@ -136,9 +136,9 @@
|
||||
"zod": "4.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.30.1",
|
||||
"@eslint/js": "9.31.0",
|
||||
"@malept/flatpak-bundler": "0.4.0",
|
||||
"@playwright/test": "1.53.2",
|
||||
"@playwright/test": "1.54.1",
|
||||
"@stylistic/eslint-plugin": "5.1.0",
|
||||
"@total-typescript/ts-reset": "0.6.1",
|
||||
"@types/electron-localshortcut": "3.1.3",
|
||||
@ -151,13 +151,13 @@
|
||||
"cross-env": "7.0.3",
|
||||
"del-cli": "6.0.0",
|
||||
"discord-api-types": "0.38.15",
|
||||
"electron": "37.2.0",
|
||||
"electron": "38.0.0-alpha.5",
|
||||
"electron-builder": "26.0.12",
|
||||
"electron-builder-squirrel-windows": "26.0.12",
|
||||
"electron-devtools-installer": "4.0.0",
|
||||
"electron-vite": "4.0.0",
|
||||
"esbuild": "0.25.6",
|
||||
"eslint": "9.30.1",
|
||||
"eslint": "9.31.0",
|
||||
"eslint-config-prettier": "10.1.5",
|
||||
"eslint-import-resolver-exports": "1.0.0-beta.5",
|
||||
"eslint-import-resolver-typescript": "4.4.4",
|
||||
@ -166,8 +166,8 @@
|
||||
"eslint-plugin-solid": "0.14.5",
|
||||
"glob": "11.0.3",
|
||||
"node-gyp": "11.2.0",
|
||||
"playwright": "1.53.2",
|
||||
"rollup": "4.44.2",
|
||||
"playwright": "1.54.1",
|
||||
"rollup": "4.45.0",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "8.36.0",
|
||||
"utf-8-validate": "6.0.5",
|
||||
|
||||
473
pnpm-lock.yaml
generated
473
pnpm-lock.yaml
generated
@ -36,7 +36,7 @@ importers:
|
||||
version: 1.0.1(@types/node@22.13.5)
|
||||
'@electron/remote':
|
||||
specifier: 2.1.3
|
||||
version: 2.1.3(electron@37.2.0)
|
||||
version: 2.1.3(electron@38.0.0-alpha.5)
|
||||
'@ffmpeg.wasm/core-mt':
|
||||
specifier: 0.12.0
|
||||
version: 0.12.0
|
||||
@ -50,11 +50,11 @@ importers:
|
||||
specifier: 2.0.5
|
||||
version: 2.0.5
|
||||
'@ghostery/adblocker-electron':
|
||||
specifier: 2.11.0
|
||||
version: 2.11.0(electron@37.2.0)
|
||||
specifier: 2.11.1
|
||||
version: 2.11.1(electron@38.0.0-alpha.5)
|
||||
'@ghostery/adblocker-electron-preload':
|
||||
specifier: 2.11.0
|
||||
version: 2.11.0(electron@37.2.0)
|
||||
specifier: 2.11.1
|
||||
version: 2.11.1(electron@38.0.0-alpha.5)
|
||||
'@hono/node-server':
|
||||
specifier: 1.15.0
|
||||
version: 1.15.0(hono@4.8.4)
|
||||
@ -62,8 +62,8 @@ importers:
|
||||
specifier: 0.5.2
|
||||
version: 0.5.2(hono@4.8.4)
|
||||
'@hono/zod-openapi':
|
||||
specifier: 0.19.9
|
||||
version: 0.19.9(hono@4.8.4)(zod@4.0.5)
|
||||
specifier: 1.0.0-beta.1
|
||||
version: 1.0.0-beta.1(hono@4.8.4)(zod@4.0.5)
|
||||
'@hono/zod-validator':
|
||||
specifier: 0.7.0
|
||||
version: 0.7.0(hono@4.8.4)(zod@4.0.5)
|
||||
@ -92,8 +92,8 @@ importers:
|
||||
specifier: 3.2.0
|
||||
version: 3.2.0
|
||||
butterchurn:
|
||||
specifier: 3.0.0-beta.4
|
||||
version: 3.0.0-beta.4
|
||||
specifier: 3.0.0-beta.5
|
||||
version: 3.0.0-beta.5
|
||||
butterchurn-presets:
|
||||
specifier: 3.0.0-beta.4
|
||||
version: 3.0.0-beta.4
|
||||
@ -105,7 +105,7 @@ importers:
|
||||
version: 14.0.0
|
||||
custom-electron-prompt:
|
||||
specifier: 1.5.8
|
||||
version: 1.5.8(electron@37.2.0)
|
||||
version: 1.5.8(electron@38.0.0-alpha.5)
|
||||
deepmerge-ts:
|
||||
specifier: 7.1.5
|
||||
version: 7.1.5
|
||||
@ -249,17 +249,17 @@ importers:
|
||||
version: 4.0.5
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: 9.30.1
|
||||
version: 9.30.1
|
||||
specifier: 9.31.0
|
||||
version: 9.31.0
|
||||
'@malept/flatpak-bundler':
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(patch_hash=c787371eeb2af011ea934e8818a0dad6d7dcb2df31bbb1686babc7231af0183c)
|
||||
'@playwright/test':
|
||||
specifier: 1.53.2
|
||||
version: 1.53.2
|
||||
specifier: 1.54.1
|
||||
version: 1.54.1
|
||||
'@stylistic/eslint-plugin':
|
||||
specifier: 5.1.0
|
||||
version: 5.1.0(eslint@9.30.1)
|
||||
version: 5.1.0(eslint@9.31.0)
|
||||
'@total-typescript/ts-reset':
|
||||
specifier: 0.6.1
|
||||
version: 0.6.1
|
||||
@ -294,8 +294,8 @@ importers:
|
||||
specifier: 0.38.15
|
||||
version: 0.38.15
|
||||
electron:
|
||||
specifier: 37.2.0
|
||||
version: 37.2.0
|
||||
specifier: 38.0.0-alpha.5
|
||||
version: 38.0.0-alpha.5
|
||||
electron-builder:
|
||||
specifier: 26.0.12
|
||||
version: 26.0.12(electron-builder-squirrel-windows@26.0.12)
|
||||
@ -312,26 +312,26 @@ importers:
|
||||
specifier: 0.25.6
|
||||
version: 0.25.6
|
||||
eslint:
|
||||
specifier: 9.30.1
|
||||
version: 9.30.1
|
||||
specifier: 9.31.0
|
||||
version: 9.31.0
|
||||
eslint-config-prettier:
|
||||
specifier: 10.1.5
|
||||
version: 10.1.5(eslint@9.30.1)
|
||||
version: 10.1.5(eslint@9.31.0)
|
||||
eslint-import-resolver-exports:
|
||||
specifier: 1.0.0-beta.5
|
||||
version: 1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.30.1)
|
||||
version: 1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.31.0)
|
||||
eslint-import-resolver-typescript:
|
||||
specifier: 4.4.4
|
||||
version: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.30.1)
|
||||
version: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.31.0)
|
||||
eslint-plugin-import:
|
||||
specifier: 2.32.0
|
||||
version: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1)
|
||||
version: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0)
|
||||
eslint-plugin-prettier:
|
||||
specifier: 5.5.1
|
||||
version: 5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.30.1))(eslint@9.30.1)(prettier@3.5.2)
|
||||
version: 5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.31.0))(eslint@9.31.0)(prettier@3.5.2)
|
||||
eslint-plugin-solid:
|
||||
specifier: 0.14.5
|
||||
version: 0.14.5(eslint@9.30.1)(typescript@5.8.3)
|
||||
version: 0.14.5(eslint@9.31.0)(typescript@5.8.3)
|
||||
glob:
|
||||
specifier: 11.0.3
|
||||
version: 11.0.3
|
||||
@ -339,17 +339,17 @@ importers:
|
||||
specifier: 11.2.0
|
||||
version: 11.2.0
|
||||
playwright:
|
||||
specifier: 1.53.2
|
||||
version: 1.53.2
|
||||
specifier: 1.54.1
|
||||
version: 1.54.1
|
||||
rollup:
|
||||
specifier: 4.44.2
|
||||
version: 4.44.2
|
||||
specifier: 4.45.0
|
||||
version: 4.45.0
|
||||
typescript:
|
||||
specifier: 5.8.3
|
||||
version: 5.8.3
|
||||
typescript-eslint:
|
||||
specifier: 8.36.0
|
||||
version: 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
version: 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
utf-8-validate:
|
||||
specifier: 6.0.5
|
||||
version: 6.0.5
|
||||
@ -381,10 +381,10 @@ packages:
|
||||
'@assemblyscript/loader@0.17.14':
|
||||
resolution: {integrity: sha512-+PVTOfla/0XMLRTQLJFPg4u40XcdTfon6GGea70hBGi8Pd7ZymIXyVUR+vK8wt5Jb4MVKTKPIz43Myyebw5mZA==}
|
||||
|
||||
'@asteasolutions/zod-to-openapi@7.3.0':
|
||||
resolution: {integrity: sha512-7tE/r1gXwMIvGnXVUdIqUhCU1RevEFC4Jk6Bussa0fk1ecbnnINkZzj1EOAJyE/M3AI25DnHT/zKQL1/FPFi8Q==}
|
||||
'@asteasolutions/zod-to-openapi@8.0.0-beta.4':
|
||||
resolution: {integrity: sha512-om7KH4B6/Rd/jjrxUjV3yC7vUwKKQcM1m7R8jd12uZyBqYd4ihqa1mMHp9MG3Hau8M/ha6teNJLouDUvwZXpNg==}
|
||||
peerDependencies:
|
||||
zod: ^3.20.2
|
||||
zod: ~3.25.1
|
||||
|
||||
'@babel/code-frame@7.27.1':
|
||||
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
|
||||
@ -741,12 +741,16 @@ packages:
|
||||
resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/core@0.15.1':
|
||||
resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/eslintrc@3.3.1':
|
||||
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/js@9.30.1':
|
||||
resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==}
|
||||
'@eslint/js@9.31.0':
|
||||
resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@eslint/object-schema@2.1.6':
|
||||
@ -783,24 +787,24 @@ packages:
|
||||
'@gar/promisify@1.1.3':
|
||||
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
|
||||
|
||||
'@ghostery/adblocker-content@2.11.0':
|
||||
resolution: {integrity: sha512-2TIxD5OC9lQpCq1SNC9mu4M37pZf1+1LDJCd4yM8gTGc927xMwNVkUBNDmi1aEH2r+PMtmJu4xtHN+YFhgns6A==}
|
||||
'@ghostery/adblocker-content@2.11.1':
|
||||
resolution: {integrity: sha512-KF1vjwp/YNzgjLKOMh+FjGcXbliZHIJnh2A9+dLgL8Fe+HCK1h49p7xa7FFa0c2pO45GDfI2LgsAiqhHSYZP6A==}
|
||||
|
||||
'@ghostery/adblocker-electron-preload@2.11.0':
|
||||
resolution: {integrity: sha512-sI3571exKBH1MYz74QEADKhJkqayWZoawIfjm3rBrFxtuppHOIEgiMgYbg+KxdprBohXkRLknrAUWMEj27oBZA==}
|
||||
'@ghostery/adblocker-electron-preload@2.11.1':
|
||||
resolution: {integrity: sha512-5bJFfvxml4g/hyfnG3cVm3Y85gdjscRhKA80OjtF2xmEBzEnQbM2rWUkq2dV1peURcPeK53D+jGhOjROGa3OHQ==}
|
||||
peerDependencies:
|
||||
electron: '>11'
|
||||
|
||||
'@ghostery/adblocker-electron@2.11.0':
|
||||
resolution: {integrity: sha512-RMwwwWOrF2efl4u0ry1dJOFu5Hfl1Qgr5rEQKnZvG8U6my+C4HyQIsmbhr7qhviTGpPUYO16FoWrsX7rG05i5w==}
|
||||
'@ghostery/adblocker-electron@2.11.1':
|
||||
resolution: {integrity: sha512-Nr4jOBMZkCBciMRMrUtsHHFI3d4mGfcQJi1TYmhu8oPGnDTfSPnddFLRYwoefsnSReZJNy4IuHBYQjV2NUeB9A==}
|
||||
peerDependencies:
|
||||
electron: '>11'
|
||||
|
||||
'@ghostery/adblocker-extended-selectors@2.11.0':
|
||||
resolution: {integrity: sha512-yl7Ygs+TFrG2ZbxynUG8Tyt3mI4WPb4Gzy4VgVXV29SYwUbok0md0Hp7vHSYeURlSzEMMa/KqgjFoZr3GY49XA==}
|
||||
'@ghostery/adblocker-extended-selectors@2.11.1':
|
||||
resolution: {integrity: sha512-T0UpheA3cd9T/4feJkJR+i5QaDvRt5gHcFWKh7DAstdYPqbKxqDG0U2RgY1Z8PtG2dVmIzBlQ0QPUB7gCF6nyw==}
|
||||
|
||||
'@ghostery/adblocker@2.11.0':
|
||||
resolution: {integrity: sha512-7FW/Hd/lYp2OLDw6JknYLIhEoFTkcGTC3PqMu9JiOYV1CgUJ/PKhcsRsmdm1lAbhmL9Rq86z1/bhn8CZXSPZ/w==}
|
||||
'@ghostery/adblocker@2.11.1':
|
||||
resolution: {integrity: sha512-bROAa2LayP0CfY6dJodMkV/DN7/0OgSEOrj/TnTWrOAkiSrH4rGpO3G1NlIAyF4uK9IZNOWDzcZt7/vv9qy0zA==}
|
||||
|
||||
'@ghostery/url-parser@1.3.0':
|
||||
resolution: {integrity: sha512-FEzdSeiva0Mt3bR4xePFzthhjT4IzvA5QTvS1xXkNyLpMGeq40mb3V2fSs0ZItRaP9IybZthDfHUSbQ1HLdx4Q==}
|
||||
@ -816,12 +820,12 @@ packages:
|
||||
peerDependencies:
|
||||
hono: '*'
|
||||
|
||||
'@hono/zod-openapi@0.19.9':
|
||||
resolution: {integrity: sha512-TonPfh8xUdsdzWNMiKOYSG4Wk2DkZIShHZoXkdOSjPmqpnobXpvSQU3w3XmB7N2t12I2NnnoGSHyMj+BXk+1bw==}
|
||||
'@hono/zod-openapi@1.0.0-beta.1':
|
||||
resolution: {integrity: sha512-4GYMrB1+Ni0kCCBLUOPlVEGA5XcYzBShKheoXoxJjpitcxgZPwwoinunhgNqGCOF/VY0oLw5GXOiKtK0tkpOhA==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
peerDependencies:
|
||||
hono: '>=4.3.6'
|
||||
zod: 3.*
|
||||
zod: ^3.25.0
|
||||
|
||||
'@hono/zod-validator@0.7.0':
|
||||
resolution: {integrity: sha512-qe2ZE6sHFE98dcUrbYMtS3bAV8hqcCOflykvZga2S7XhmNSZzT+dIz4OuMILsjLHkJw9JMn912/dB7dQOmuPvg==}
|
||||
@ -1067,8 +1071,8 @@ packages:
|
||||
resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==}
|
||||
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
|
||||
|
||||
'@playwright/test@1.53.2':
|
||||
resolution: {integrity: sha512-tEB2U5z74ebBeyfGNZ3Jfg29AnW+5HlWhvHtb/Mqco9pFdZU1ZLNdVb2UtB5CvmiilNr2ZfVH/qMmAROG/XTzw==}
|
||||
'@playwright/test@1.54.1':
|
||||
resolution: {integrity: sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
@ -1156,103 +1160,103 @@ packages:
|
||||
'@rolldown/pluginutils@1.0.0-beta.26':
|
||||
resolution: {integrity: sha512-r/5po89voz/QRPDmoErL10+hVuTAuz1SHvokx+yWBlOIPB5C41jC7QhLqq9kaebx/+EHyoV3z22/qBfX81Ns8A==}
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.44.2':
|
||||
resolution: {integrity: sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==}
|
||||
'@rollup/rollup-android-arm-eabi@4.45.0':
|
||||
resolution: {integrity: sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.44.2':
|
||||
resolution: {integrity: sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==}
|
||||
'@rollup/rollup-android-arm64@4.45.0':
|
||||
resolution: {integrity: sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.44.2':
|
||||
resolution: {integrity: sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==}
|
||||
'@rollup/rollup-darwin-arm64@4.45.0':
|
||||
resolution: {integrity: sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.44.2':
|
||||
resolution: {integrity: sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==}
|
||||
'@rollup/rollup-darwin-x64@4.45.0':
|
||||
resolution: {integrity: sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.44.2':
|
||||
resolution: {integrity: sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==}
|
||||
'@rollup/rollup-freebsd-arm64@4.45.0':
|
||||
resolution: {integrity: sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.44.2':
|
||||
resolution: {integrity: sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==}
|
||||
'@rollup/rollup-freebsd-x64@4.45.0':
|
||||
resolution: {integrity: sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.44.2':
|
||||
resolution: {integrity: sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==}
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.45.0':
|
||||
resolution: {integrity: sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.44.2':
|
||||
resolution: {integrity: sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==}
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.45.0':
|
||||
resolution: {integrity: sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==}
|
||||
'@rollup/rollup-linux-arm64-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.44.2':
|
||||
resolution: {integrity: sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==}
|
||||
'@rollup/rollup-linux-arm64-musl@4.45.0':
|
||||
resolution: {integrity: sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==}
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==}
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==}
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.44.2':
|
||||
resolution: {integrity: sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==}
|
||||
'@rollup/rollup-linux-riscv64-musl@4.45.0':
|
||||
resolution: {integrity: sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==}
|
||||
'@rollup/rollup-linux-s390x-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.44.2':
|
||||
resolution: {integrity: sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==}
|
||||
'@rollup/rollup-linux-x64-gnu@4.45.0':
|
||||
resolution: {integrity: sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.44.2':
|
||||
resolution: {integrity: sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==}
|
||||
'@rollup/rollup-linux-x64-musl@4.45.0':
|
||||
resolution: {integrity: sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.44.2':
|
||||
resolution: {integrity: sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==}
|
||||
'@rollup/rollup-win32-arm64-msvc@4.45.0':
|
||||
resolution: {integrity: sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.44.2':
|
||||
resolution: {integrity: sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==}
|
||||
'@rollup/rollup-win32-ia32-msvc@4.45.0':
|
||||
resolution: {integrity: sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.44.2':
|
||||
resolution: {integrity: sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==}
|
||||
'@rollup/rollup-win32-x64-msvc@4.45.0':
|
||||
resolution: {integrity: sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
@ -1839,8 +1843,8 @@ packages:
|
||||
butterchurn-presets@3.0.0-beta.4:
|
||||
resolution: {integrity: sha512-TbQLUPvGOYMZAtWKoCmBtludh9aQZ6NaMGQU4lvPeadBPy3Du3yNmwBjlTMLP5c5mRWElxQPjTL1PtR7FZK3OQ==}
|
||||
|
||||
butterchurn@3.0.0-beta.4:
|
||||
resolution: {integrity: sha512-hiY1ktHYHQ8MT65nnZi7GjrgZZ6sl/ipT5rBqEfaYJd90L4SvOtB6lVxtKadtzAyJo2TQJc4gJfEca4cpZo0DA==}
|
||||
butterchurn@3.0.0-beta.5:
|
||||
resolution: {integrity: sha512-BStK4OAbBb9Pvt8PuQlS4WVmYBwU1KuDMRHF1V89QjoIFauAqq7tpV4EpYXj7K563r5daLrMX+2y5DBhZZ9Xig==}
|
||||
|
||||
bytes@3.0.0:
|
||||
resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
|
||||
@ -2251,8 +2255,8 @@ packages:
|
||||
ecma-proposal-math-extensions@0.0.2:
|
||||
resolution: {integrity: sha512-80BnDp2Fn7RxXlEr5HHZblniY4aQ97MOAicdWWpSo0vkQiISSE9wLR4SqxKsu4gCtXFBIPPzy8JMhay4NWRg/Q==}
|
||||
|
||||
eel-wasm@0.0.15:
|
||||
resolution: {integrity: sha512-FSTWf6lwGn7Zc3QiV+KxWTznIqq4j9eST/aXmyN/cC39+1Arqs13YOMosHQ7tqUt+OjQmG79Vd41f9gu+w1lvA==}
|
||||
eel-wasm@0.0.16:
|
||||
resolution: {integrity: sha512-1tkId7I7E1Vs4fXTRsH83Sjn2S/AbzrVQKLBRGys6NLc3eVH4NBffJsdEeLHOWWUgQpVXBEP3CV/srUZNIuBnw==}
|
||||
|
||||
ejs@3.1.10:
|
||||
resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
|
||||
@ -2322,8 +2326,13 @@ packages:
|
||||
resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
electron@37.2.0:
|
||||
resolution: {integrity: sha512-dE6+qeg6SBUVd5d8CD2+GH82kh+gF1v40+hs+U+UOno681NMSGmBtgqwldQRpbvtnQDD7V2M9Cpfr3+Abw7aBg==}
|
||||
electron@37.2.1:
|
||||
resolution: {integrity: sha512-ae2EbzRNqIAHlftfCHtbbt6EgJUW8+zxWLONqNnn2iSrLF0O/pbxbff3xcpZYPpmFBs4uqjoi+s4QS7DQ+zZ/w==}
|
||||
engines: {node: '>= 12.20.55'}
|
||||
hasBin: true
|
||||
|
||||
electron@38.0.0-alpha.5:
|
||||
resolution: {integrity: sha512-h3IB0Z5hGf5zjBDVM9H/B6mNGS8m5NCPcNDe+nOg8qyI3yfKPcE3VVDb8RpAc9cqFhhCvyN7pCt8o5z9a8gejQ==}
|
||||
engines: {node: '>= 12.20.55'}
|
||||
hasBin: true
|
||||
|
||||
@ -2519,8 +2528,8 @@ packages:
|
||||
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
eslint@9.30.1:
|
||||
resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==}
|
||||
eslint@9.31.0:
|
||||
resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -3908,13 +3917,13 @@ packages:
|
||||
resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==}
|
||||
hasBin: true
|
||||
|
||||
playwright-core@1.53.2:
|
||||
resolution: {integrity: sha512-ox/OytMy+2w1jcYEYlOo1Hhp8hZkLCximMTUTMBXjGUA1KoFfiSZ+DU+3a739jsPY0yoKH2TFy9S2fsJas8yAw==}
|
||||
playwright-core@1.54.1:
|
||||
resolution: {integrity: sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
playwright@1.53.2:
|
||||
resolution: {integrity: sha512-6K/qQxVFuVQhRQhFsVZ9fGeatxirtrpPgxzBYWyZLEXJzqYwuL4fuNmfOfD5et1tJE4GScKyPNeLhZeRwuTU3A==}
|
||||
playwright@1.54.1:
|
||||
resolution: {integrity: sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
@ -4157,8 +4166,8 @@ packages:
|
||||
resolution: {integrity: sha512-2rad1JDFst/GD1J86RuqN1SIP8O8Xv4UbqNyKaVayXTjgF0D6HpvTnUZ1RQ6tANpZweGmq4v6Ay0uyRNEycFPw==}
|
||||
hasBin: true
|
||||
|
||||
rollup@4.44.2:
|
||||
resolution: {integrity: sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==}
|
||||
rollup@4.45.0:
|
||||
resolution: {integrity: sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -4932,7 +4941,7 @@ snapshots:
|
||||
|
||||
'@assemblyscript/loader@0.17.14': {}
|
||||
|
||||
'@asteasolutions/zod-to-openapi@7.3.0(zod@4.0.5)':
|
||||
'@asteasolutions/zod-to-openapi@8.0.0-beta.4(zod@4.0.5)':
|
||||
dependencies:
|
||||
openapi3-ts: 4.5.0
|
||||
zod: 4.0.5
|
||||
@ -5173,9 +5182,9 @@ snapshots:
|
||||
- bluebird
|
||||
- supports-color
|
||||
|
||||
'@electron/remote@2.1.3(electron@37.2.0)':
|
||||
'@electron/remote@2.1.3(electron@38.0.0-alpha.5)':
|
||||
dependencies:
|
||||
electron: 37.2.0
|
||||
electron: 38.0.0-alpha.5
|
||||
|
||||
'@electron/universal@3.0.0':
|
||||
dependencies:
|
||||
@ -5293,9 +5302,9 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.25.6':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.7.0(eslint@9.30.1)':
|
||||
'@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)':
|
||||
dependencies:
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.1': {}
|
||||
@ -5314,6 +5323,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/core@0.15.1':
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/eslintrc@3.3.1':
|
||||
dependencies:
|
||||
ajv: 6.12.6
|
||||
@ -5328,7 +5341,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@eslint/js@9.30.1': {}
|
||||
'@eslint/js@9.31.0': {}
|
||||
|
||||
'@eslint/object-schema@2.1.6': {}
|
||||
|
||||
@ -5362,28 +5375,28 @@ snapshots:
|
||||
|
||||
'@gar/promisify@1.1.3': {}
|
||||
|
||||
'@ghostery/adblocker-content@2.11.0':
|
||||
'@ghostery/adblocker-content@2.11.1':
|
||||
dependencies:
|
||||
'@ghostery/adblocker-extended-selectors': 2.11.0
|
||||
'@ghostery/adblocker-extended-selectors': 2.11.1
|
||||
|
||||
'@ghostery/adblocker-electron-preload@2.11.0(electron@37.2.0)':
|
||||
'@ghostery/adblocker-electron-preload@2.11.1(electron@38.0.0-alpha.5)':
|
||||
dependencies:
|
||||
'@ghostery/adblocker-content': 2.11.0
|
||||
electron: 37.2.0
|
||||
'@ghostery/adblocker-content': 2.11.1
|
||||
electron: 38.0.0-alpha.5
|
||||
|
||||
'@ghostery/adblocker-electron@2.11.0(electron@37.2.0)':
|
||||
'@ghostery/adblocker-electron@2.11.1(electron@38.0.0-alpha.5)':
|
||||
dependencies:
|
||||
'@ghostery/adblocker': 2.11.0
|
||||
'@ghostery/adblocker-electron-preload': 2.11.0(electron@37.2.0)
|
||||
electron: 37.2.0
|
||||
'@ghostery/adblocker': 2.11.1
|
||||
'@ghostery/adblocker-electron-preload': 2.11.1(electron@38.0.0-alpha.5)
|
||||
electron: 38.0.0-alpha.5
|
||||
tldts-experimental: 7.0.9
|
||||
|
||||
'@ghostery/adblocker-extended-selectors@2.11.0': {}
|
||||
'@ghostery/adblocker-extended-selectors@2.11.1': {}
|
||||
|
||||
'@ghostery/adblocker@2.11.0':
|
||||
'@ghostery/adblocker@2.11.1':
|
||||
dependencies:
|
||||
'@ghostery/adblocker-content': 2.11.0
|
||||
'@ghostery/adblocker-extended-selectors': 2.11.0
|
||||
'@ghostery/adblocker-content': 2.11.1
|
||||
'@ghostery/adblocker-extended-selectors': 2.11.1
|
||||
'@ghostery/url-parser': 1.3.0
|
||||
'@remusao/guess-url-type': 2.1.0
|
||||
'@remusao/small': 2.1.0
|
||||
@ -5402,12 +5415,11 @@ snapshots:
|
||||
dependencies:
|
||||
hono: 4.8.4
|
||||
|
||||
'@hono/zod-openapi@0.19.9(hono@4.8.4)(zod@4.0.5)':
|
||||
'@hono/zod-openapi@1.0.0-beta.1(hono@4.8.4)(zod@4.0.5)':
|
||||
dependencies:
|
||||
'@asteasolutions/zod-to-openapi': 7.3.0(zod@4.0.5)
|
||||
'@asteasolutions/zod-to-openapi': 8.0.0-beta.4(zod@4.0.5)
|
||||
'@hono/zod-validator': 0.7.0(hono@4.8.4)(zod@4.0.5)
|
||||
hono: 4.8.4
|
||||
openapi3-ts: 4.5.0
|
||||
zod: 4.0.5
|
||||
|
||||
'@hono/zod-validator@0.7.0(hono@4.8.4)(zod@4.0.5)':
|
||||
@ -5742,9 +5754,9 @@ snapshots:
|
||||
|
||||
'@pkgr/core@0.2.7': {}
|
||||
|
||||
'@playwright/test@1.53.2':
|
||||
'@playwright/test@1.54.1':
|
||||
dependencies:
|
||||
playwright: 1.53.2
|
||||
playwright: 1.54.1
|
||||
|
||||
'@polka/url@1.0.0-next.28': {}
|
||||
|
||||
@ -5805,64 +5817,64 @@ snapshots:
|
||||
|
||||
'@rolldown/pluginutils@1.0.0-beta.26': {}
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.44.2':
|
||||
'@rollup/rollup-android-arm-eabi@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.44.2':
|
||||
'@rollup/rollup-android-arm64@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.44.2':
|
||||
'@rollup/rollup-darwin-arm64@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.44.2':
|
||||
'@rollup/rollup-darwin-x64@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.44.2':
|
||||
'@rollup/rollup-freebsd-arm64@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.44.2':
|
||||
'@rollup/rollup-freebsd-x64@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.44.2':
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.44.2':
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-arm64-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.44.2':
|
||||
'@rollup/rollup-linux-arm64-musl@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.44.2':
|
||||
'@rollup/rollup-linux-riscv64-musl@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-s390x-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.44.2':
|
||||
'@rollup/rollup-linux-x64-gnu@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.44.2':
|
||||
'@rollup/rollup-linux-x64-musl@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.44.2':
|
||||
'@rollup/rollup-win32-arm64-msvc@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.44.2':
|
||||
'@rollup/rollup-win32-ia32-msvc@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.44.2':
|
||||
'@rollup/rollup-win32-x64-msvc@4.45.0':
|
||||
optional: true
|
||||
|
||||
'@rtsao/scc@1.1.0': {}
|
||||
@ -5895,11 +5907,11 @@ snapshots:
|
||||
dependencies:
|
||||
solid-js: 1.9.7
|
||||
|
||||
'@stylistic/eslint-plugin@5.1.0(eslint@9.30.1)':
|
||||
'@stylistic/eslint-plugin@5.1.0(eslint@9.31.0)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1)
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0)
|
||||
'@typescript-eslint/types': 8.36.0
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
eslint-visitor-keys: 4.2.1
|
||||
espree: 10.4.0
|
||||
estraverse: 5.3.0
|
||||
@ -5960,7 +5972,7 @@ snapshots:
|
||||
|
||||
'@types/electron-localshortcut@3.1.3':
|
||||
dependencies:
|
||||
electron: 37.2.0
|
||||
electron: 37.2.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -6028,15 +6040,15 @@ snapshots:
|
||||
'@types/node': 22.13.5
|
||||
optional: true
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.36.0
|
||||
'@typescript-eslint/type-utils': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/type-utils': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.36.0
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
graphemer: 1.4.0
|
||||
ignore: 7.0.3
|
||||
natural-compare: 1.4.0
|
||||
@ -6045,14 +6057,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3)':
|
||||
'@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.36.0
|
||||
'@typescript-eslint/types': 8.36.0
|
||||
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.36.0
|
||||
debug: 4.4.1
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -6075,12 +6087,12 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.36.0(eslint@9.30.1)(typescript@5.8.3)':
|
||||
'@typescript-eslint/type-utils@8.36.0(eslint@9.31.0)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
debug: 4.4.1
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
@ -6104,13 +6116,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.36.0(eslint@9.30.1)(typescript@5.8.3)':
|
||||
'@typescript-eslint/utils@8.36.0(eslint@9.31.0)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1)
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0)
|
||||
'@typescript-eslint/scope-manager': 8.36.0
|
||||
'@typescript-eslint/types': 8.36.0
|
||||
'@typescript-eslint/typescript-estree': 8.36.0(typescript@5.8.3)
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -6546,12 +6558,11 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
|
||||
butterchurn@3.0.0-beta.4:
|
||||
butterchurn@3.0.0-beta.5:
|
||||
dependencies:
|
||||
'@assemblyscript/loader': 0.17.14
|
||||
'@babel/runtime': 7.27.6
|
||||
ecma-proposal-math-extensions: 0.0.2
|
||||
eel-wasm: 0.0.15
|
||||
eel-wasm: 0.0.16
|
||||
|
||||
bytes@3.0.0: {}
|
||||
|
||||
@ -6807,9 +6818,9 @@ snapshots:
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
custom-electron-prompt@1.5.8(electron@37.2.0):
|
||||
custom-electron-prompt@1.5.8(electron@38.0.0-alpha.5):
|
||||
dependencies:
|
||||
electron: 37.2.0
|
||||
electron: 38.0.0-alpha.5
|
||||
|
||||
data-uri-to-buffer@4.0.1: {}
|
||||
|
||||
@ -7012,7 +7023,7 @@ snapshots:
|
||||
|
||||
ecma-proposal-math-extensions@0.0.2: {}
|
||||
|
||||
eel-wasm@0.0.15: {}
|
||||
eel-wasm@0.0.16: {}
|
||||
|
||||
ejs@3.1.10:
|
||||
dependencies:
|
||||
@ -7141,7 +7152,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
electron@37.2.0:
|
||||
electron@37.2.1:
|
||||
dependencies:
|
||||
'@electron/get': 2.0.3
|
||||
'@types/node': 22.13.5
|
||||
extract-zip: 2.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
electron@38.0.0-alpha.5:
|
||||
dependencies:
|
||||
'@electron/get': 2.0.3
|
||||
'@types/node': 22.13.5
|
||||
@ -7312,9 +7331,9 @@ snapshots:
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
eslint-config-prettier@10.1.5(eslint@9.30.1):
|
||||
eslint-config-prettier@10.1.5(eslint@9.31.0):
|
||||
dependencies:
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
|
||||
eslint-import-context@0.1.8(unrs-resolver@1.7.11):
|
||||
dependencies:
|
||||
@ -7323,10 +7342,10 @@ snapshots:
|
||||
optionalDependencies:
|
||||
unrs-resolver: 1.7.11
|
||||
|
||||
eslint-import-resolver-exports@1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.30.1):
|
||||
eslint-import-resolver-exports@1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.31.0):
|
||||
dependencies:
|
||||
eslint: 9.30.1
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1)
|
||||
eslint: 9.31.0
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0)
|
||||
resolve.exports: 2.0.3
|
||||
|
||||
eslint-import-resolver-node@0.3.9:
|
||||
@ -7337,10 +7356,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@4.4.4(eslint-plugin-import@2.32.0)(eslint@9.30.1):
|
||||
eslint-import-resolver-typescript@4.4.4(eslint-plugin-import@2.32.0)(eslint@9.31.0):
|
||||
dependencies:
|
||||
debug: 4.4.1
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
eslint-import-context: 0.1.8(unrs-resolver@1.7.11)
|
||||
get-tsconfig: 4.10.1
|
||||
is-bun-module: 2.0.0
|
||||
@ -7348,22 +7367,22 @@ snapshots:
|
||||
tinyglobby: 0.2.14
|
||||
unrs-resolver: 1.7.11
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1)
|
||||
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1):
|
||||
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
eslint: 9.30.1
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
eslint: 9.31.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.30.1)
|
||||
eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.31.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1):
|
||||
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.9
|
||||
@ -7372,9 +7391,9 @@ snapshots:
|
||||
array.prototype.flatmap: 1.3.3
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.30.1)
|
||||
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.31.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@ -7386,26 +7405,26 @@ snapshots:
|
||||
string.prototype.trimend: 1.0.9
|
||||
tsconfig-paths: 3.15.0
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-prettier@5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.30.1))(eslint@9.30.1)(prettier@3.5.2):
|
||||
eslint-plugin-prettier@5.5.1(@types/eslint@9.6.1)(eslint-config-prettier@10.1.5(eslint@9.31.0))(eslint@9.31.0)(prettier@3.5.2):
|
||||
dependencies:
|
||||
eslint: 9.30.1
|
||||
eslint: 9.31.0
|
||||
prettier: 3.5.2
|
||||
prettier-linter-helpers: 1.0.0
|
||||
synckit: 0.11.8
|
||||
optionalDependencies:
|
||||
'@types/eslint': 9.6.1
|
||||
eslint-config-prettier: 10.1.5(eslint@9.30.1)
|
||||
eslint-config-prettier: 10.1.5(eslint@9.31.0)
|
||||
|
||||
eslint-plugin-solid@0.14.5(eslint@9.30.1)(typescript@5.8.3):
|
||||
eslint-plugin-solid@0.14.5(eslint@9.31.0)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
eslint: 9.30.1
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
eslint: 9.31.0
|
||||
estraverse: 5.3.0
|
||||
is-html: 2.0.0
|
||||
kebab-case: 1.0.2
|
||||
@ -7424,15 +7443,15 @@ snapshots:
|
||||
|
||||
eslint-visitor-keys@4.2.1: {}
|
||||
|
||||
eslint@9.30.1:
|
||||
eslint@9.31.0:
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1)
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0)
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@eslint/config-array': 0.21.0
|
||||
'@eslint/config-helpers': 0.3.0
|
||||
'@eslint/core': 0.14.0
|
||||
'@eslint/core': 0.15.1
|
||||
'@eslint/eslintrc': 3.3.1
|
||||
'@eslint/js': 9.30.1
|
||||
'@eslint/js': 9.31.0
|
||||
'@eslint/plugin-kit': 0.3.1
|
||||
'@humanfs/node': 0.16.6
|
||||
'@humanwhocodes/module-importer': 1.0.1
|
||||
@ -8858,11 +8877,11 @@ snapshots:
|
||||
dependencies:
|
||||
pngjs: 6.0.0
|
||||
|
||||
playwright-core@1.53.2: {}
|
||||
playwright-core@1.54.1: {}
|
||||
|
||||
playwright@1.53.2:
|
||||
playwright@1.54.1:
|
||||
dependencies:
|
||||
playwright-core: 1.53.2
|
||||
playwright-core: 1.54.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
@ -9094,30 +9113,30 @@ snapshots:
|
||||
'@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.26
|
||||
'@rolldown/binding-win32-x64-msvc': 1.0.0-beta.26
|
||||
|
||||
rollup@4.44.2:
|
||||
rollup@4.45.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.44.2
|
||||
'@rollup/rollup-android-arm64': 4.44.2
|
||||
'@rollup/rollup-darwin-arm64': 4.44.2
|
||||
'@rollup/rollup-darwin-x64': 4.44.2
|
||||
'@rollup/rollup-freebsd-arm64': 4.44.2
|
||||
'@rollup/rollup-freebsd-x64': 4.44.2
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.44.2
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.44.2
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-arm64-musl': 4.44.2
|
||||
'@rollup/rollup-linux-loongarch64-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.44.2
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-x64-gnu': 4.44.2
|
||||
'@rollup/rollup-linux-x64-musl': 4.44.2
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.44.2
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.44.2
|
||||
'@rollup/rollup-win32-x64-msvc': 4.44.2
|
||||
'@rollup/rollup-android-arm-eabi': 4.45.0
|
||||
'@rollup/rollup-android-arm64': 4.45.0
|
||||
'@rollup/rollup-darwin-arm64': 4.45.0
|
||||
'@rollup/rollup-darwin-x64': 4.45.0
|
||||
'@rollup/rollup-freebsd-arm64': 4.45.0
|
||||
'@rollup/rollup-freebsd-x64': 4.45.0
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.45.0
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.45.0
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-arm64-musl': 4.45.0
|
||||
'@rollup/rollup-linux-loongarch64-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.45.0
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-x64-gnu': 4.45.0
|
||||
'@rollup/rollup-linux-x64-musl': 4.45.0
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.45.0
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.45.0
|
||||
'@rollup/rollup-win32-x64-msvc': 4.45.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
run-applescript@7.0.0: {}
|
||||
@ -9623,12 +9642,12 @@ snapshots:
|
||||
possible-typed-array-names: 1.1.0
|
||||
reflect.getprototypeof: 1.0.10
|
||||
|
||||
typescript-eslint@8.36.0(eslint@9.30.1)(typescript@5.8.3):
|
||||
typescript-eslint@8.36.0(eslint@9.31.0)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.30.1)(typescript@5.8.3))(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.30.1)(typescript@5.8.3)
|
||||
eslint: 9.30.1
|
||||
'@typescript-eslint/eslint-plugin': 8.36.0(@typescript-eslint/parser@8.36.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.36.0(eslint@9.31.0)(typescript@5.8.3)
|
||||
eslint: 9.31.0
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -11,9 +11,9 @@ export function getPlugins() {
|
||||
return store.get('plugins') as Record<string, PluginConfig>;
|
||||
}
|
||||
|
||||
export function isEnabled(plugin: string) {
|
||||
export async function isEnabled(plugin: string) {
|
||||
const pluginConfig = deepmerge(
|
||||
allPlugins[plugin].config ?? { enabled: false },
|
||||
(await allPlugins())[plugin].config ?? { enabled: false },
|
||||
(store.get('plugins') as Record<string, PluginConfig>)[plugin] ?? {},
|
||||
);
|
||||
return pluginConfig !== undefined && pluginConfig.enabled;
|
||||
|
||||
@ -11,7 +11,7 @@ export type IStore = InstanceType<
|
||||
>;
|
||||
|
||||
const migrations = {
|
||||
'>=3.4.0'(store: IStore) {
|
||||
'>=3.10.0'(store: IStore) {
|
||||
const lyricGeniusConfig = store.get('plugins.lyrics-genius') as
|
||||
| {
|
||||
enabled?: boolean;
|
||||
@ -23,10 +23,16 @@ const migrations = {
|
||||
const syncedLyricsConfig = store.get('plugins.synced-lyrics') as
|
||||
| SyncedLyricsPluginConfig
|
||||
| undefined;
|
||||
store.set('plugins.synced-lyrics', {
|
||||
...syncedLyricsConfig,
|
||||
enabled: lyricGeniusConfig.enabled,
|
||||
});
|
||||
|
||||
if (
|
||||
!syncedLyricsConfig ||
|
||||
syncedLyricsConfig?.enabled !== lyricGeniusConfig?.enabled
|
||||
) {
|
||||
store.set('plugins.synced-lyrics', {
|
||||
...syncedLyricsConfig,
|
||||
enabled: lyricGeniusConfig.enabled,
|
||||
});
|
||||
}
|
||||
|
||||
store.delete('plugins.lyrics-genius');
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import { languageResources } from 'virtual:i18n';
|
||||
|
||||
export const loadI18n = async () =>
|
||||
await init({
|
||||
resources: languageResources,
|
||||
resources: await languageResources(),
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "فتح محدد الترجمة"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "تم تغيير الترجمة الى {{language}}",
|
||||
"caption-disabled": "الترجمة معطلة",
|
||||
"no-captions": "الترجمة لهاته الأغنية غير متاحة"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "أسهم التنقل \"التالي/السابق\" مدمجة مباشرة في الواجهة، كما في متصفحك",
|
||||
"name": "التنقل"
|
||||
"name": "التنقل",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "العودة إلى الصفحة السابقة"
|
||||
},
|
||||
"forward": {
|
||||
"title": "إذهب إلى الصفحة المقبلة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "إزالة أزرار وروابط تسجيل الدخول بجوجل من الواجهة",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "يسمح بتغيير جودة الفيديو باستخدام زر على صورة الفيديو",
|
||||
"name": "مغير جودة الفيديو"
|
||||
"name": "مغير جودة الفيديو",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "إفتح مغير الجودة"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "إضافة دعم Scrobbling (مثل Last.fm، ListenBrainz)",
|
||||
@ -859,7 +877,8 @@
|
||||
},
|
||||
"name": "تفعيل الفيديو",
|
||||
"templates": {
|
||||
"button-song": "أغنية"
|
||||
"button-song": "أغنية",
|
||||
"button-video": "فيديو"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
@ -1 +1,7 @@
|
||||
{}
|
||||
{
|
||||
"language": {
|
||||
"code": "az",
|
||||
"local-name": "Azərbaycan dili",
|
||||
"name": "Azerbaijani"
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,6 +333,30 @@
|
||||
"description": "Прилага компресия на аудиото (намалява обема на най-силните части от сигнала и увеличава обема на най-тихите части)",
|
||||
"name": "Аудио компресор"
|
||||
},
|
||||
"auth-proxy-adapter": {
|
||||
"description": "Поддръжка за използване на услуги за удостоверяване чрез прокси",
|
||||
"menu": {
|
||||
"disable": "Деактивирай адаптера за удостоверяване чрез прокси",
|
||||
"enable": "Активирай адаптера за удостоверяване чрез прокси",
|
||||
"hostname": {
|
||||
"label": "Име на хост"
|
||||
},
|
||||
"port": {
|
||||
"label": "Порт"
|
||||
}
|
||||
},
|
||||
"name": "Адаптер за удостоверяване чрез прокси",
|
||||
"prompt": {
|
||||
"hostname": {
|
||||
"label": "Въведи име за локалния прокси сървър (необходимо е рестартиране):",
|
||||
"title": "Име на прокси хост"
|
||||
},
|
||||
"port": {
|
||||
"label": "Въведи порт за локалния прокси сървър (необходимо е рестартиране):",
|
||||
"title": "Прокси порт"
|
||||
}
|
||||
}
|
||||
},
|
||||
"blur-nav-bar": {
|
||||
"description": "Прави навигационната лента прозрачна и размазана",
|
||||
"name": "Размазанa навигационна лента"
|
||||
@ -357,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "Отвори избора на надписи"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "Надписите са сменени на {{language}}",
|
||||
"caption-disabled": "Надписите са деактивирани",
|
||||
"no-captions": "Няма налични надписи за тази песен"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -576,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "Навигационни стрелки Напред/Назад, директно интегрирани в интерфейса, както в любимия ви браузър",
|
||||
"name": "Навигация"
|
||||
"name": "Навигация",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "Предишна страница"
|
||||
},
|
||||
"forward": {
|
||||
"title": "Следваща страница"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Премахни бутоните за вход с Google и връзките от интерфейса",
|
||||
@ -601,7 +638,7 @@
|
||||
"name": "Известия"
|
||||
},
|
||||
"performance-improvement": {
|
||||
"description": "Подобри произдовителна като пуснеш опасни скриптове",
|
||||
"description": "Подобри производителността като пуснеш експериментални скриптове",
|
||||
"name": "Производителни подобрения"
|
||||
},
|
||||
"picture-in-picture": {
|
||||
@ -668,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "Позволява промяна на качеството на видеото с бутон върху видеото",
|
||||
"name": "Промяна на качеството на видеото"
|
||||
"name": "Промяна на качеството на видеото",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "Отвори настройките за качество на плейъра"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Добавяне на скробблинг поддръжка (last.fm, Listenbrainz и т.н.)",
|
||||
@ -835,7 +877,8 @@
|
||||
},
|
||||
"name": "Превключване на видео",
|
||||
"templates": {
|
||||
"button-song": "Песен"
|
||||
"button-song": "Песен",
|
||||
"button-video": "Видео"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "Untertitelwähler öffnen"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "Untertitel gewechselt zu {{language}}",
|
||||
"caption-disabled": "Untertitel deaktiviert",
|
||||
"no-captions": "Keine Untertitel für dieses Lied verfügbar"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "Vorwärts/Zurück Navigationspfeile direkt in die Oberfläche integriert - wie in deinem geliebten Browser",
|
||||
"name": "Navigation"
|
||||
"name": "Navigation",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "Zur vorherigen Seite gehen"
|
||||
},
|
||||
"forward": {
|
||||
"title": "Zur nächsten Seite gehen"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Googles Anmelden-Knöpfe und -Links von der Oberfläche entfernen",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "Erlaubt die Videoqualität über einen Knopf auf dem Video",
|
||||
"name": "Videoqualitätsänderer"
|
||||
"name": "Videoqualitätsänderer",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "Videoqualität ändern"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Scrobbling-Unterstützung aktivieren (z.B. für last.fm, Listenbrainz)",
|
||||
@ -859,7 +877,8 @@
|
||||
},
|
||||
"name": "Videoumschalter",
|
||||
"templates": {
|
||||
"button-song": "Lied"
|
||||
"button-song": "Lied",
|
||||
"button-video": "Video"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
7
src/i18n/resources/eu.json
Normal file
7
src/i18n/resources/eu.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"language": {
|
||||
"code": "eu",
|
||||
"local-name": "Euskara",
|
||||
"name": "Basque"
|
||||
}
|
||||
}
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "자막 선택기 열기"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "자막 언어가 {{language}}(으)로 변경되었습니다",
|
||||
"caption-disabled": "자막이 비활성화 되었습니다",
|
||||
"no-captions": "이 곡에는 자막이 없습니다"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "브라우저에서처럼, UI에 직접 통합된 앞으로/뒤로 탐색하는 화살표",
|
||||
"name": "탐색"
|
||||
"name": "탐색",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "이전 페이지로 이동"
|
||||
},
|
||||
"forward": {
|
||||
"title": "다음 페이지로 이동"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "UI에서 Google 로그인 버튼 및 링크 제거하기",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "영상 오버레이의 버튼으로 영상 품질을 변경할 수 있습니다",
|
||||
"name": "영상 품질 체인저"
|
||||
"name": "영상 품질 체인저",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "영상 품질 선택기 열기"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "스크로블링 지원을 추가합니다 (예: last.fm, Listenbrainz)",
|
||||
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "Открыть выбор субтитров"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "Субтитры изменены на {{language}}",
|
||||
"caption-disabled": "Субтитры отключены",
|
||||
"no-captions": "Нет доступных субтитров для этой песни"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "Стрелки навигации \"вперед/назад\" интегрированы в интерфейс, как в вашем любимом браузере",
|
||||
"name": "Навигация"
|
||||
"name": "Навигация",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "Предыдущая страница"
|
||||
},
|
||||
"forward": {
|
||||
"title": "Следующая страница"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Убрать из интерфейса кнопки и ссылки для входа через Google",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "Позволяет изменять качество видео с помощью кнопки на оверлее видео",
|
||||
"name": "Изменение качества видео"
|
||||
"name": "Изменение качества видео",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "Открыть настройки качества плеера"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Добавляет поддержку скробблинга (last.fm, Listenbrainz)",
|
||||
@ -859,7 +877,8 @@
|
||||
},
|
||||
"name": "Переключатель видео",
|
||||
"templates": {
|
||||
"button-song": "Песня"
|
||||
"button-song": "Песня",
|
||||
"button-video": "Видео"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
},
|
||||
"dialog": {
|
||||
"hide-menu-enabled": {
|
||||
"detail": "මෙනුව සැගවී ඇත, නැවත පෙන්වීමට 'Alt' යතුර භාවිතා කරන්න. (හෝ In-App මෙනුවේ 'Escape')",
|
||||
"detail": "මෙනුව සැගවී ඇත, නැවත පෙන්වීමට 'Alt' භාවිතා කරන්න. (මෙනුවේ 'Escape')",
|
||||
"message": "මෙනුව සැගවීම සක්රීය කර ඇත",
|
||||
"title": "මෙනුව සැගවීම සක්රීයයි"
|
||||
},
|
||||
@ -175,7 +175,40 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"enabled": "සක්රිය කරන්න",
|
||||
"label": "ප්ලගීන",
|
||||
"new": "නව"
|
||||
},
|
||||
"view": {
|
||||
"label": "බලන්න",
|
||||
"submenu": {
|
||||
"force-reload": "බලෙන් රීලෝඩ් කරන්න",
|
||||
"reload": "රීලෝඩ් කරන්න",
|
||||
"reset-zoom": "සැබෑ ප්රමාණය",
|
||||
"toggle-fullscreen": "සම්පූර්ණ තිරය ටොගල් කරන්න",
|
||||
"zoom-in": "විශාලනය කරන්න",
|
||||
"zoom-out": "කුඩා කරන්න"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tray": {
|
||||
"next": "ඊළඟ",
|
||||
"play-pause": "වාදනය / විරාමය",
|
||||
"previous": "පෙර",
|
||||
"quit": "පිටවීම",
|
||||
"restart": "නැවත ආරම්භ කරන්න",
|
||||
"show": "තිරය පෙන්වන්න",
|
||||
"tooltip": {
|
||||
"default": "YouTube Music",
|
||||
"with-song-info": "YouTube Music: {{artist}} - {{title}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"adblocker": {
|
||||
"description": "සියලුම දැන්වීම් අවහිර කර කොටුවෙන් පිටත ලුහුබැඳීම"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,10 +30,10 @@
|
||||
"receive-command": "Primljena je komanda kroz protokol: \"{{command}}\""
|
||||
},
|
||||
"theme": {
|
||||
"css-file-not-found": "CSS datoteka \"{{cssFile}}\" ne postoji, ignorisano"
|
||||
"css-file-not-found": "CSS datoteka \"{{cssFile}}\" ne postoji, ignorišem"
|
||||
},
|
||||
"unresponsive": {
|
||||
"details": "Aplikacija ne odgovara!\n{{error}}"
|
||||
"details": "Aplikacija se ne odaziva!\n{{error}}"
|
||||
},
|
||||
"when-ready": {
|
||||
"clearing-cache-after-20s": "Čišćenje keširanih podataka"
|
||||
@ -116,7 +116,7 @@
|
||||
"auto-update": "Automatsko ažuriranje",
|
||||
"hide-menu": {
|
||||
"dialog": {
|
||||
"message": "Meni će biti sakriven posle sledećeg pokretanje, upotrebite [Alt]da ga ponovo prikažete (ili backtick [`] ukoliko koristite meni u aplikaciji)",
|
||||
"message": "Meni će biti sakriven posle sledećeg pokretanje, upotrebite [Alt] da ga ponovo prikažete (ili backtick [`] ukoliko koristite meni u aplikaciji)",
|
||||
"title": "Sakrivanje menija je omogućeno"
|
||||
},
|
||||
"label": "Sakrij meni"
|
||||
@ -283,7 +283,7 @@
|
||||
"description": "Dodaje podršku za 'Amuse now' vidžet (6K Labs) u YouTube Muziku",
|
||||
"name": "Amuse",
|
||||
"response": {
|
||||
"query": "Amuse API server je pokrenut. GET /query da biste dobili informacije o numeri."
|
||||
"query": "Amuse API server je pokrenut. Koristite GET /query da biste dobili informacije o numeri."
|
||||
}
|
||||
},
|
||||
"api-server": {
|
||||
@ -292,7 +292,7 @@
|
||||
"request": {
|
||||
"buttons": {
|
||||
"allow": "Dozvoli",
|
||||
"deny": "Ne dozvoli"
|
||||
"deny": "Odbij"
|
||||
},
|
||||
"message": "Dozvoli {{ID}} ({{origin}}) da pristupa API-ju?",
|
||||
"title": "Zahtev za autorizaciju na API"
|
||||
@ -311,7 +311,7 @@
|
||||
}
|
||||
},
|
||||
"hostname": {
|
||||
"label": "Host"
|
||||
"label": "Ime host-a"
|
||||
},
|
||||
"port": {
|
||||
"label": "Port"
|
||||
@ -320,8 +320,8 @@
|
||||
"name": "API Server [Beta]",
|
||||
"prompt": {
|
||||
"hostname": {
|
||||
"label": "Unesite host (npr. 0.0.0.0) za API server:",
|
||||
"title": "Host"
|
||||
"label": "Unesite ime host-a (npr. 0.0.0.0) za API server:",
|
||||
"title": "Ime host-a"
|
||||
},
|
||||
"port": {
|
||||
"label": "Unesite port za API server:",
|
||||
@ -339,7 +339,7 @@
|
||||
"disable": "Onemogući Proxy adapter",
|
||||
"enable": "Omogući Proxy adapter",
|
||||
"hostname": {
|
||||
"label": "Host"
|
||||
"label": "Ime host-a"
|
||||
},
|
||||
"port": {
|
||||
"label": "Port"
|
||||
@ -348,8 +348,8 @@
|
||||
"name": "Proxy adapter za autentifikaciju",
|
||||
"prompt": {
|
||||
"hostname": {
|
||||
"label": "Unesi host za lokalni proxy server (zahteva ponovno pokretanje):",
|
||||
"title": "Proxy Host"
|
||||
"label": "Unesi ime host-a za lokalni proxy server (zahteva ponovno pokretanje):",
|
||||
"title": "Ime host-a za Proxy"
|
||||
},
|
||||
"port": {
|
||||
"label": "Unesi port za lokalni proxy server (zahteva ponovno pokretanje):",
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "Otvori meni za izbor prevoda"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "Prevod promenjen u {{language}}",
|
||||
"caption-disabled": "Prevod onemogućen",
|
||||
"no-captions": "Za ovu pesmu nisu dostupni prevodi"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -418,7 +423,7 @@
|
||||
},
|
||||
"discord": {
|
||||
"backend": {
|
||||
"already-connected": "Pokušaj da se poveže u momentu aktivne veze",
|
||||
"already-connected": "Pokušano je da se poveže sa aktivnom vezom",
|
||||
"connected": "Spojeno sa Discord-om",
|
||||
"disconnected": "Poništeno povezivanje sa Discord-om"
|
||||
},
|
||||
@ -429,7 +434,8 @@
|
||||
"clear-activity-after-timeout": "Očisti aktivnosti nakon isteka vremena",
|
||||
"connected": "Povezano",
|
||||
"disconnected": "Nije povezano",
|
||||
"hide-github-button": "Sakrij GitHub link dugme",
|
||||
"hide-duration-left": "Sakrij preostalo vreme",
|
||||
"hide-github-button": "Sakrij dugme sa GitHub linkom",
|
||||
"play-on-youtube-music": "Reprodukuj na YouTube Muzici",
|
||||
"set-inactivity-timeout": "Podesi tajmer za neaktivnost"
|
||||
},
|
||||
@ -476,7 +482,7 @@
|
||||
"playlist-has-only-one-song": "Plejlista sadrži samo jednu numeru, preuzima se direktno",
|
||||
"playlist-id-not-found": "Nije pronađen ID plejliste",
|
||||
"playlist-is-empty": "Plejlista je prazna",
|
||||
"playlist-is-mix-or-private": "Greška pri preuzimanju informacija o plejlisti: proverite da li je možda skrivena ili \"Mixed for you\" plejlista\n\n{{error}}",
|
||||
"playlist-is-mix-or-private": "Greška pri preuzimanju informacija o plejlisti: proverite da li je možda skrivena ili \"Za tebe\" plejlista\n\n{{error}}",
|
||||
"preparing-file": "Pripremanje datoteke…",
|
||||
"saving": "Čuvanje…",
|
||||
"trying-to-get-playlist-id": "Pokušaj preuzimanja ID plejliste: {{playlistId}}",
|
||||
@ -508,14 +514,14 @@
|
||||
},
|
||||
"name": "Servis za preuzimanje",
|
||||
"renderer": {
|
||||
"can-not-update-progress": "Nemoguće ažuriranje trenutnog progresa"
|
||||
"can-not-update-progress": "Nemoguće ažuriranje trenutnog napretka"
|
||||
},
|
||||
"templates": {
|
||||
"button": "Preuzimanje"
|
||||
}
|
||||
},
|
||||
"equalizer": {
|
||||
"description": "Dodaje 'equalizer' u muzički plejer",
|
||||
"description": "Dodaje ekvilajzer u muzički plejer",
|
||||
"menu": {
|
||||
"presets": {
|
||||
"label": "Predefinisana podešavanja",
|
||||
@ -524,7 +530,363 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "Equalizer"
|
||||
"name": "Ekvilajzer"
|
||||
},
|
||||
"exponential-volume": {
|
||||
"description": "Postavlja slajder jačine kao eksponencijalan radi lakšeg izbora nižih jačina.",
|
||||
"name": "Eksponencijalna jačina"
|
||||
},
|
||||
"in-app-menu": {
|
||||
"description": "Daje izbornim trakama fensi, tamni ili izgled prema boji albuma",
|
||||
"menu": {
|
||||
"hide-dom-window-controls": "Sakrij kontrole DOM prozora"
|
||||
},
|
||||
"name": "Izborni menu unutar aplikacije"
|
||||
},
|
||||
"lumiastream": {
|
||||
"description": "Dodaje podršku za Lumia Stream",
|
||||
"name": "Lumia Stream [Beta]"
|
||||
},
|
||||
"lyrics-genius": {
|
||||
"description": "Dodaje podršku za tekstove za većinu pesama",
|
||||
"menu": {
|
||||
"romanized-lyrics": "Romanizovani tekstovi"
|
||||
},
|
||||
"name": "Genius tekstovi",
|
||||
"renderer": {
|
||||
"fetched-lyrics": "Dobavljen tekst pesme sa Genius-a"
|
||||
}
|
||||
},
|
||||
"music-together": {
|
||||
"description": "Podeli plejlistu sa drugima. Kada domaćin (host) pusti pesmu, svi ostali će čuti istu pesmu",
|
||||
"dialog": {
|
||||
"enter-host": "Unesi ID host-a"
|
||||
},
|
||||
"internal": {
|
||||
"save": "Sačuvaj",
|
||||
"track-source": "Izvor pesme",
|
||||
"unknown-user": "Nepoznat korisnik"
|
||||
},
|
||||
"menu": {
|
||||
"click-to-copy-id": "Kopiraj ID host-a",
|
||||
"close": "Zatvori 'Music Together'",
|
||||
"connected-users": "Spojeni korisnici",
|
||||
"disconnect": "Prekini vezu sa 'Music Together'",
|
||||
"empty-user": "Nema povezanih korisnika",
|
||||
"host": "'Music Together' domaćin (host)",
|
||||
"join": "Pridruži se 'Music Together'",
|
||||
"permission": {
|
||||
"all": "Dozvoli gostima da kontrolišu plejlistu i reprodukciju",
|
||||
"host-only": "Samo domaćin (host) može da kontroliše plejlistu i reprodukciju",
|
||||
"playlist": "Dozvoli gostima da kontrolišu plejlistu"
|
||||
},
|
||||
"set-permission": "Promeni dozvole za upravljanje",
|
||||
"status": {
|
||||
"disconnected": "Nije povezan",
|
||||
"guest": "Povezan kao gost",
|
||||
"host": "Povezan kao domaćin (host)"
|
||||
}
|
||||
},
|
||||
"name": "Music Together [Beta]",
|
||||
"toast": {
|
||||
"add-song-failed": "Dodavanje pesme nije uspelo",
|
||||
"closed": "'Music Together' je zatvorena",
|
||||
"disconnected": "Veza sa 'Music Together' je prekinuta",
|
||||
"host-failed": "Pokretanje 'Music Together' kao domaćin (host) nije uspelo",
|
||||
"id-copied": "ID domaćina (host) kopiran u privremenu memoriju",
|
||||
"id-copy-failed": "Kopiranje ID domaćina (host) u privremenu memoriju nije uspelo",
|
||||
"join-failed": "Povezivanje na 'Music Together' neuspešno",
|
||||
"joined": "Povezan na 'Music Together'",
|
||||
"permission-changed": "Dozvola 'Music Together' promenjena na \"{{permission}}\"",
|
||||
"remove-song-failed": "Uklanjanje pesme nije uspelo",
|
||||
"user-connected": "{{name}} se pridružio na 'Music Together'",
|
||||
"user-disconnected": "{{name}} je napustio 'Music Together'"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"description": "Strelice za navigaciju napred/nazad su direktno integrisane u interfejs, kao i u tvom omiljenom pregledaču",
|
||||
"name": "Navigacija",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "Vrati se na prethodnu stranicu"
|
||||
},
|
||||
"forward": {
|
||||
"title": "Idi na sledeću stranicu"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Ukloni Google dugmad i linkove za prijavu sa interfejsa",
|
||||
"name": "Bez Google prijave"
|
||||
},
|
||||
"notifications": {
|
||||
"description": "Prikaži obaveštenje kada numera krene sa reprodukcijom (interaktivna obaveštenja su dostupna na Windows-u)",
|
||||
"menu": {
|
||||
"interactive": "Interaktivna obaveštenja",
|
||||
"interactive-settings": {
|
||||
"label": "Podešavanja za interakciju",
|
||||
"submenu": {
|
||||
"hide-button-text": "Sakrij tekst dugmeta",
|
||||
"refresh-on-play-pause": "Osveži prilikom Pokreni/Pauziraj",
|
||||
"tray-controls": "Otvori/Zatvori klikom na sistemsku traku"
|
||||
}
|
||||
},
|
||||
"priority": "Prioritet obaveštenja",
|
||||
"toast-style": "Toast stil obaveštenja",
|
||||
"unpause-notification": "Prikaži obaveštenje prilikom nastavka reprodukcije"
|
||||
},
|
||||
"name": "Obaveštenja"
|
||||
},
|
||||
"performance-improvement": {
|
||||
"description": "Poboljšaj performanse omogućavanjem eksperimentalnih skripti",
|
||||
"name": "Poboljšaj performanse [Beta]"
|
||||
},
|
||||
"picture-in-picture": {
|
||||
"description": "Dozvoljava aplikaciji da se prebaci u režim slike-u-slici",
|
||||
"menu": {
|
||||
"always-on-top": "Uvek na vrhu",
|
||||
"hotkey": {
|
||||
"label": "Prečica",
|
||||
"prompt": {
|
||||
"keybind-options": {
|
||||
"hotkey": "Prečica"
|
||||
},
|
||||
"label": "Izaberi prečicu za prebacivanje u režim slike-u-slici",
|
||||
"title": "Prečica za režim slike-u-slici"
|
||||
}
|
||||
},
|
||||
"save-window-position": "Sačuvaj poziciju prozora",
|
||||
"save-window-size": "Sačuvaj veličinu prozora",
|
||||
"use-native-pip": "Koristi izvorni režim slike-u-slici za pregledače"
|
||||
},
|
||||
"name": "Slika-u-slici",
|
||||
"templates": {
|
||||
"button": "Slika-u-slici"
|
||||
}
|
||||
},
|
||||
"playback-speed": {
|
||||
"description": "Slušaj brzo, slušaj sporo! Dodaje slajder koji kontroliše brzinu pesme",
|
||||
"name": "Brzina reprodukcije",
|
||||
"templates": {
|
||||
"button": "Brzina"
|
||||
}
|
||||
},
|
||||
"precise-volume": {
|
||||
"description": "Precizno kontroliši jačinu zvuka korišćenjem točka na mišu/prečica, sa prilagođenim interfejsom i prilagodivim inkrementalnim koracima jačine",
|
||||
"menu": {
|
||||
"arrows-shortcuts": "Lokalne kontrole tastera sa strelicama",
|
||||
"custom-volume-steps": "Postavi prilagođene korake za promenu jačine",
|
||||
"global-shortcuts": "Globalne prečice"
|
||||
},
|
||||
"name": "Precizna jačina",
|
||||
"prompt": {
|
||||
"global-shortcuts": {
|
||||
"keybind-options": {
|
||||
"decrease": "Smanji jačinu",
|
||||
"increase": "Povećaj jačinu"
|
||||
},
|
||||
"label": "Izaberi globalne prečice na tastaturi za jačinu:",
|
||||
"title": "Globalne prečice na tastaturi za jačinu"
|
||||
},
|
||||
"volume-steps": {
|
||||
"label": "Izaberi korake za povećanje/smanjenje jačine",
|
||||
"title": "Koraci za promenu jačine"
|
||||
}
|
||||
}
|
||||
},
|
||||
"quality-changer": {
|
||||
"backend": {
|
||||
"dialog": {
|
||||
"quality-changer": {
|
||||
"detail": "Trenutni kvalitet: {{quality}}",
|
||||
"message": "Izaberi kvalitet videa:",
|
||||
"title": "Izaberi kvalitet videa"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Dozvoljava promenu kvaliteta videa pomoću dugmeta na video preklapanju",
|
||||
"name": "Promena kvaliteta videa",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "Otvori meni za promenu kvaliteta plejera"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Dodaj podršku za 'scrobbling' (poput last.fm, Listenbrainz)",
|
||||
"dialog": {
|
||||
"lastfm": {
|
||||
"auth-failed": {
|
||||
"message": "Autentifikacija sa Last.fm nije uspela.\nZatvori iskačući prozor do sledećeg ponovnog pokretanja.",
|
||||
"title": "Autentifikacija neuspešna"
|
||||
}
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"lastfm": {
|
||||
"api-settings": "Podešavanja za Last.fm API"
|
||||
},
|
||||
"listenbrainz": {
|
||||
"token": "Unesi korisnički token za ListenBrainz"
|
||||
},
|
||||
"scrobble-alternative-title": "Koristi alternativne naslove",
|
||||
"scrobble-other-media": "'Scrobble'-uj druge medije"
|
||||
},
|
||||
"name": "Scrobbler",
|
||||
"prompt": {
|
||||
"lastfm": {
|
||||
"api-key": "Last.fm API ključ",
|
||||
"api-secret": "Last.fm API tajna (secret)"
|
||||
},
|
||||
"listenbrainz": {
|
||||
"token": {
|
||||
"label": "Unesi svoj ListenBrainz korisnički token:",
|
||||
"title": "ListenBrainz token"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortcuts": {
|
||||
"description": "Dozvoljava postavljanje globalnih prečica na tastaturi za reproduciju (pusti/pauziraj/sledeće/prethodno) i isključivanje OSD za medije tako što će prepisati tastere za medije, uključiti Ctrl/CMD + F za pretragu, isključiti MPRIS podršku za medija tastere na Linux-u, i prilagođene prečice za napredne korisnike",
|
||||
"menu": {
|
||||
"override-media-keys": "Prepiši medija tastere",
|
||||
"set-keybinds": "Podesi globalne kontrole za numere"
|
||||
},
|
||||
"name": "Prečice (& MPRIS)",
|
||||
"prompt": {
|
||||
"keybind": {
|
||||
"keybind-options": {
|
||||
"next": "Sledeće",
|
||||
"play-pause": "Pusti / Pauziraj",
|
||||
"previous": "Prethodno"
|
||||
},
|
||||
"label": "Izaberi globalne prečice za upravljanje numerama:",
|
||||
"title": "Globalne prečice na tastaturi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"skip-disliked-songs": {
|
||||
"description": "Preskače numere koje su označene sa 'Ne sviđa mi se'",
|
||||
"name": "Preskoči pesme označene sa 'Ne sviđa mi se'"
|
||||
},
|
||||
"skip-silences": {
|
||||
"description": "Automatski preskoči delove numera u kojima je tišina",
|
||||
"name": "Preskoči tišine"
|
||||
},
|
||||
"sponsorblock": {
|
||||
"description": "Automatski preskače delove numera koji nisu muzika poput uvod/odjava ili delove muzičkih spotova u kojima se muzika ne pušta",
|
||||
"name": "Blok sponzora"
|
||||
},
|
||||
"synced-lyrics": {
|
||||
"description": "Obezbeđuje sinhronizovane tekstove pesama, korišćenjem dobavljača poput LRClib.",
|
||||
"errors": {
|
||||
"fetch": "⚠️\tDošlo je do greške prilikom dobavljanja teksta pesme.\n\tMolimo vas da pokušate ponovo kasnije.",
|
||||
"not-found": "⚠️ Tekst za ovu pesmu nije pronađen."
|
||||
},
|
||||
"menu": {
|
||||
"default-text-string": {
|
||||
"label": "Podrazumevani karakteri između tekstova pesama",
|
||||
"tooltip": "Izaberi podrazumevane karaktere koji će biti korišćeni za razmake između tekstova pesama"
|
||||
},
|
||||
"line-effect": {
|
||||
"label": "Efekat linije",
|
||||
"submenu": {
|
||||
"fancy": {
|
||||
"label": "Fensi",
|
||||
"tooltip": "Koristi velike (kao iz aplikacije) efekte na trenutnu liniju"
|
||||
},
|
||||
"focus": {
|
||||
"label": "Fokus",
|
||||
"tooltip": "Učini samo trenutnu liniju belom"
|
||||
},
|
||||
"offset": {
|
||||
"label": "Pomeraj (offset)",
|
||||
"tooltip": "Pomeraj (offset) na trenutnoj liniji"
|
||||
},
|
||||
"scale": {
|
||||
"label": "Razmera",
|
||||
"tooltip": "Promeni razmeru trenutne linije"
|
||||
}
|
||||
},
|
||||
"tooltip": "Izaberi efekat koji će biti primenjen na trenutnoj liniji"
|
||||
},
|
||||
"precise-timing": {
|
||||
"label": "Učini da tekst pesme bude savršeno usklađen",
|
||||
"tooltip": "Izračunaj do milisekunde prikaz sledeće linije teksta (može malo uticati na performanse)"
|
||||
},
|
||||
"romanization": {
|
||||
"label": "Romanizuj tekstove pesama",
|
||||
"tooltip": "Ako je tekst pesme na drugom jeziku, pokušaj da ga prikažeš u latiničnoj varijanti."
|
||||
},
|
||||
"show-lyrics-even-if-inexact": {
|
||||
"label": "Prikaži tekst pesme čak iako nije tačan",
|
||||
"tooltip": "Ako numera nije pronađena, ekstenzija će pokušati ponovo sa novim upitom za pretragu.\nRezultat iz drugog pokušaja možda neće biti tačan."
|
||||
},
|
||||
"show-time-codes": {
|
||||
"label": "Prikaži vremenske oznake",
|
||||
"tooltip": "Prikaži vremenske oznake pored teksta pesme"
|
||||
}
|
||||
},
|
||||
"name": "Sinhronizovani tekstovi pesama",
|
||||
"refetch-btn": {
|
||||
"fetching": "Dobavljanje...",
|
||||
"normal": "Ponovo dobavi tekst pesme"
|
||||
},
|
||||
"warnings": {
|
||||
"duration-mismatch": "⚠️ - Tekst pesme možda nije usklađen zbog neuklapanja u dužini trajanja.",
|
||||
"inexact": "⚠️ - Tekst za ovu pesmu možda nije tačan",
|
||||
"instrumental": "⚠️ - Ovo je instrumentalna numera"
|
||||
}
|
||||
},
|
||||
"taskbar-mediacontrol": {
|
||||
"description": "Upravljaj reprodukcijom iz Windows trake sa zadacima",
|
||||
"name": "Upravljanje medijima iz trake sa zadacima"
|
||||
},
|
||||
"touchbar": {
|
||||
"description": "Dodaje 'TouchBar' vidžet za macOS korisnike",
|
||||
"name": "TouchBar"
|
||||
},
|
||||
"tuna-obs": {
|
||||
"description": "Integracija sa OBS-ovom ekstenzijom Tuna",
|
||||
"name": "Tuna OBS"
|
||||
},
|
||||
"unobtrusive-player": {
|
||||
"description": "Onemogućava plejeru da iskače kada reprodukuje numeru",
|
||||
"name": "Nenametljivi plejer"
|
||||
},
|
||||
"video-toggle": {
|
||||
"description": "Dodaje dugme za promenu između režima za video/numeru. Opciono, može da ukloni celu karticu sa videom",
|
||||
"menu": {
|
||||
"align": {
|
||||
"label": "Poravnanje",
|
||||
"submenu": {
|
||||
"left": "Levo",
|
||||
"middle": "Sredina",
|
||||
"right": "Desno"
|
||||
}
|
||||
},
|
||||
"force-hide": "Nasilno ukloni karticu sa videom",
|
||||
"mode": {
|
||||
"label": "Režim",
|
||||
"submenu": {
|
||||
"custom": "Prilagođeno prebacivanje",
|
||||
"disabled": "Onemogućeno",
|
||||
"native": "Izvorno prebacivanje"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "Video prebacivanje",
|
||||
"templates": {
|
||||
"button-song": "Numera",
|
||||
"button-video": "Video"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
"description": "Dodaje vizualizaciju u plejer",
|
||||
"menu": {
|
||||
"visualizer-type": "Tip vizualizacije"
|
||||
},
|
||||
"name": "Vizualizacija"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -859,7 +859,8 @@
|
||||
},
|
||||
"name": "வீடியோ மாற்று",
|
||||
"templates": {
|
||||
"button-song": "பாடல்"
|
||||
"button-song": "பாடல்",
|
||||
"button-video": "காணொளி"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
"details": "Yanıt verilmedi!\n{{error}}"
|
||||
},
|
||||
"when-ready": {
|
||||
"clearing-cache-after-20s": "Uygulama ön belleği temizleme"
|
||||
"clearing-cache-after-20s": "Uygulama ön belleği temizle"
|
||||
},
|
||||
"window": {
|
||||
"tried-to-render-offscreen": "Pencere ekranın dışında oluşturulmaya çalışıldı, windowSize={{windowSize}}, displaySize={{displaySize}}, position={{position}}"
|
||||
@ -209,7 +209,7 @@
|
||||
"plugins": {
|
||||
"ad-speedup": {
|
||||
"description": "Bir reklam oynatılırsa sesi kapatır ve oynatma hızını 16x olarak ayarlar",
|
||||
"name": "Hızlandırma"
|
||||
"name": "Reklam Hızlandırma"
|
||||
},
|
||||
"adblocker": {
|
||||
"description": "Tüm reklamları ve izleyicileri engelle",
|
||||
@ -287,7 +287,7 @@
|
||||
}
|
||||
},
|
||||
"api-server": {
|
||||
"description": "APİ ekle ve oynatıcıyı kontrol et",
|
||||
"description": "Oynatıcıyı kontrol etmek için bir API sunucusu ekle",
|
||||
"dialog": {
|
||||
"request": {
|
||||
"buttons": {
|
||||
@ -321,7 +321,7 @@
|
||||
"prompt": {
|
||||
"hostname": {
|
||||
"label": "API sunucusu için hostname (örneğin 0.0.0.0) girin:",
|
||||
"title": "Hostname"
|
||||
"title": "Hostname(Ana bilgisayar adı)"
|
||||
},
|
||||
"port": {
|
||||
"label": "API sunucusu için port girin:",
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "Altyazı seçiciyi aç"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "Başlık {{language}} olarak değiştirildi",
|
||||
"caption-disabled": "Altyazılar devre dışı",
|
||||
"no-captions": "Bu şarkı için altyazı mevcut değil"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "Favori tarayıcınızdaki gibi doğrudan arayüze entegre edilmiş İleri/Geri gezinme okları",
|
||||
"name": "Navigasyon"
|
||||
"name": "Navigasyon",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "Önceki sayfaya git"
|
||||
},
|
||||
"forward": {
|
||||
"title": "Sonraki sayfaya geç"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "Google giriş düğmelerini ve bağlantılarını arayüzden kaldır",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "Video katmanı üzerindeki bir düğme ile video kalitesinin değiştirilmesine izin verir",
|
||||
"name": "Video Kalitesi Değiştirici"
|
||||
"name": "Video Kalitesi Değiştirici",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "Açık oynatıcı kalite değiştirici"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "Listeleme desteği ekler (lastfm, listenbrainz ve benzeri)",
|
||||
@ -859,7 +877,8 @@
|
||||
},
|
||||
"name": "Video Geçiş",
|
||||
"templates": {
|
||||
"button-song": "Şarkı"
|
||||
"button-song": "Şarkı",
|
||||
"button-video": "Video"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
@ -381,6 +381,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"title": "打開標題選擇器"
|
||||
},
|
||||
"toast": {
|
||||
"caption-changed": "字幕語言更改為{{language}}",
|
||||
"caption-disabled": "停用字幕",
|
||||
"no-captions": "此歌曲無標題"
|
||||
}
|
||||
},
|
||||
"compact-sidebar": {
|
||||
@ -600,7 +605,15 @@
|
||||
},
|
||||
"navigation": {
|
||||
"description": "允許應用程式上方顯示上一頁/下一頁按鈕",
|
||||
"name": "導覽列"
|
||||
"name": "導覽列",
|
||||
"templates": {
|
||||
"back": {
|
||||
"title": "回到上一頁"
|
||||
},
|
||||
"forward": {
|
||||
"title": "前往下一頁"
|
||||
}
|
||||
}
|
||||
},
|
||||
"no-google-login": {
|
||||
"description": "移除 Google 登入按鈕及連結",
|
||||
@ -692,7 +705,12 @@
|
||||
}
|
||||
},
|
||||
"description": "允許在影片內進行畫質更改",
|
||||
"name": "允許變更影片畫質"
|
||||
"name": "允許變更影片畫質",
|
||||
"renderer": {
|
||||
"quality-settings-button": {
|
||||
"label": "開啟畫質調整器"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scrobbler": {
|
||||
"description": "額外新增 scrobbling 支援 (例如:last.fm, Listenbrainz)",
|
||||
@ -859,7 +877,8 @@
|
||||
},
|
||||
"name": "歌曲/影片切換",
|
||||
"templates": {
|
||||
"button-song": "歌曲"
|
||||
"button-song": "歌曲",
|
||||
"button-video": "影片"
|
||||
}
|
||||
},
|
||||
"visualizer": {
|
||||
|
||||
40
src/index.ts
40
src/index.ts
@ -62,10 +62,10 @@ import { defaultAuthProxyConfig } from '@/plugins/auth-proxy-adapter/config';
|
||||
import type { PluginConfig } from '@/types/plugins';
|
||||
|
||||
if (!is.macOS()) {
|
||||
delete allPlugins['touchbar'];
|
||||
delete (await allPlugins())['touchbar'];
|
||||
}
|
||||
if (!is.windows()) {
|
||||
delete allPlugins['taskbar-mediacontrol'];
|
||||
delete (await allPlugins())['taskbar-mediacontrol'];
|
||||
}
|
||||
|
||||
// Catch errors and log them
|
||||
@ -126,6 +126,8 @@ app.commandLine.appendSwitch(
|
||||
'enable-features',
|
||||
'OverlayScrollbar,SharedArrayBuffer,UseOzonePlatform,WaylandWindowDecorations',
|
||||
);
|
||||
// Disable Fluent Scrollbar (for OverlayScrollbar)
|
||||
app.commandLine.appendSwitch('disable-features', 'FluentScrollbar');
|
||||
if (config.get('options.disableHardwareAcceleration')) {
|
||||
if (is.dev()) {
|
||||
console.log('Disabling hardware acceleration');
|
||||
@ -139,13 +141,13 @@ if (is.linux()) {
|
||||
app.setName('com.github.th_ch.youtube_music');
|
||||
|
||||
// Stops chromium from launching its own MPRIS service
|
||||
if (config.plugins.isEnabled('shortcuts')) {
|
||||
if (await config.plugins.isEnabled('shortcuts')) {
|
||||
app.commandLine.appendSwitch('disable-features', 'MediaSessionService');
|
||||
}
|
||||
}
|
||||
|
||||
if (config.get('options.proxy')) {
|
||||
const authProxyEnabled = config.plugins.isEnabled('auth-proxy-adapter');
|
||||
const authProxyEnabled = await config.plugins.isEnabled('auth-proxy-adapter');
|
||||
|
||||
let proxyToUse = '';
|
||||
if (authProxyEnabled) {
|
||||
@ -183,19 +185,23 @@ function onClosed() {
|
||||
mainWindow = null;
|
||||
}
|
||||
|
||||
ipcMain.handle('ytmd:get-main-plugin-names', () => Object.keys(mainPlugins));
|
||||
ipcMain.handle('ytmd:get-main-plugin-names', async () =>
|
||||
Object.keys(await mainPlugins()),
|
||||
);
|
||||
|
||||
const initHook = async (win: BrowserWindow) => {
|
||||
const allPluginStubs = await allPlugins();
|
||||
|
||||
const initHook = (win: BrowserWindow) => {
|
||||
ipcMain.handle(
|
||||
'ytmd:get-config',
|
||||
(_, id: string) =>
|
||||
deepmerge(
|
||||
allPlugins[id].config ?? { enabled: false },
|
||||
allPluginStubs[id].config ?? { enabled: false },
|
||||
config.get(`plugins.${id}`) ?? {},
|
||||
) as PluginConfig,
|
||||
);
|
||||
ipcMain.handle('ytmd:set-config', (_, name: string, obj: object) =>
|
||||
config.setPartial(`plugins.${name}`, obj, allPlugins[name].config),
|
||||
config.setPartial(`plugins.${name}`, obj, allPluginStubs[name].config),
|
||||
);
|
||||
|
||||
config.watch((newValue, oldValue) => {
|
||||
@ -214,7 +220,7 @@ const initHook = (win: BrowserWindow) => {
|
||||
if (!isEqual) {
|
||||
const oldConfig = oldPluginConfigList[id] as PluginConfig;
|
||||
const config = deepmerge(
|
||||
allPlugins[id].config ?? { enabled: false },
|
||||
allPluginStubs[id].config ?? { enabled: false },
|
||||
newPluginConfig ?? {},
|
||||
) as PluginConfig;
|
||||
|
||||
@ -229,7 +235,7 @@ const initHook = (win: BrowserWindow) => {
|
||||
forceUnloadMainPlugin(id, win);
|
||||
}
|
||||
|
||||
if (allPlugins[id]?.restartNeeded) {
|
||||
if (allPluginStubs[id]?.restartNeeded) {
|
||||
showNeedToRestartDialog(id);
|
||||
}
|
||||
}
|
||||
@ -250,8 +256,8 @@ const initHook = (win: BrowserWindow) => {
|
||||
});
|
||||
};
|
||||
|
||||
const showNeedToRestartDialog = (id: string) => {
|
||||
const plugin = allPlugins[id];
|
||||
const showNeedToRestartDialog = async (id: string) => {
|
||||
const plugin = (await allPlugins())[id];
|
||||
|
||||
const dialogOptions: Electron.MessageBoxOptions = {
|
||||
type: 'info',
|
||||
@ -325,7 +331,7 @@ async function createMainWindow() {
|
||||
const windowSize = config.get('window-size');
|
||||
const windowMaximized = config.get('window-maximized');
|
||||
const windowPosition: Electron.Point = config.get('window-position');
|
||||
const useInlineMenu = config.plugins.isEnabled('in-app-menu');
|
||||
const useInlineMenu = await config.plugins.isEnabled('in-app-menu');
|
||||
|
||||
const defaultTitleBarOverlayOptions: Electron.TitleBarOverlay = {
|
||||
color: '#00000000',
|
||||
@ -369,7 +375,7 @@ async function createMainWindow() {
|
||||
},
|
||||
...decorations,
|
||||
});
|
||||
initHook(win);
|
||||
await initHook(win);
|
||||
initTheme(win);
|
||||
|
||||
await loadAllMainPlugins(win);
|
||||
@ -614,12 +620,12 @@ app.on('activate', async () => {
|
||||
}
|
||||
});
|
||||
|
||||
const getDefaultLocale = (locale: string) =>
|
||||
Object.keys(languageResources).includes(locale) ? locale : null;
|
||||
const getDefaultLocale = async (locale: string) =>
|
||||
Object.keys(await languageResources()).includes(locale) ? locale : null;
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
if (!config.get('options.language')) {
|
||||
const locale = getDefaultLocale(app.getLocale());
|
||||
const locale = await getDefaultLocale(app.getLocale());
|
||||
if (locale) {
|
||||
config.set('options.language', locale);
|
||||
}
|
||||
|
||||
@ -20,13 +20,17 @@ const createContext = (
|
||||
id: string,
|
||||
win: BrowserWindow,
|
||||
): BackendContext<PluginConfig> => ({
|
||||
getConfig: () =>
|
||||
getConfig: async () =>
|
||||
deepmerge(
|
||||
allPlugins[id].config ?? { enabled: false },
|
||||
(await allPlugins())[id].config ?? { enabled: false },
|
||||
config.get(`plugins.${id}`) ?? {},
|
||||
) as PluginConfig,
|
||||
setConfig: (newConfig) => {
|
||||
config.setPartial(`plugins.${id}`, newConfig, allPlugins[id].config);
|
||||
setConfig: async (newConfig) => {
|
||||
config.setPartial(
|
||||
`plugins.${id}`,
|
||||
newConfig,
|
||||
(await allPlugins())[id].config,
|
||||
);
|
||||
},
|
||||
|
||||
ipc: {
|
||||
@ -96,7 +100,7 @@ export const forceLoadMainPlugin = async (
|
||||
id: string,
|
||||
win: BrowserWindow,
|
||||
): Promise<void> => {
|
||||
const plugin = mainPlugins[id];
|
||||
const plugin = (await mainPlugins())[id];
|
||||
if (!plugin) return;
|
||||
|
||||
try {
|
||||
@ -133,7 +137,7 @@ export const loadAllMainPlugins = async (win: BrowserWindow) => {
|
||||
const pluginConfigs = config.plugins.getPlugins();
|
||||
const queue: Promise<void>[] = [];
|
||||
|
||||
for (const [plugin, pluginDef] of Object.entries(mainPlugins)) {
|
||||
for (const [plugin, pluginDef] of Object.entries(await mainPlugins())) {
|
||||
const config = deepmerge(pluginDef.config, pluginConfigs[plugin] ?? {});
|
||||
if (config.enabled) {
|
||||
queue.push(forceLoadMainPlugin(plugin, win));
|
||||
|
||||
@ -17,19 +17,23 @@ const createContext = (
|
||||
id: string,
|
||||
win: BrowserWindow,
|
||||
): MenuContext<PluginConfig> => ({
|
||||
getConfig: () =>
|
||||
getConfig: async () =>
|
||||
deepmerge(
|
||||
allPlugins[id].config ?? { enabled: false },
|
||||
(await allPlugins())[id].config ?? { enabled: false },
|
||||
config.get(`plugins.${id}`) ?? {},
|
||||
) as PluginConfig,
|
||||
setConfig: (newConfig) => {
|
||||
config.setPartial(`plugins.${id}`, newConfig, allPlugins[id].config);
|
||||
setConfig: async (newConfig) => {
|
||||
config.setPartial(
|
||||
`plugins.${id}`,
|
||||
newConfig,
|
||||
(await allPlugins())[id].config,
|
||||
);
|
||||
},
|
||||
window: win,
|
||||
refresh: async () => {
|
||||
await setApplicationMenu(win);
|
||||
|
||||
if (config.plugins.isEnabled('in-app-menu')) {
|
||||
if (await config.plugins.isEnabled('in-app-menu')) {
|
||||
win.webContents.send('refresh-in-app-menu');
|
||||
}
|
||||
},
|
||||
@ -37,7 +41,7 @@ const createContext = (
|
||||
|
||||
export const forceLoadMenuPlugin = async (id: string, win: BrowserWindow) => {
|
||||
try {
|
||||
const plugin = allPlugins[id];
|
||||
const plugin = (await allPlugins())[id];
|
||||
if (!plugin) return;
|
||||
|
||||
const menu = plugin.menu?.(createContext(id, win));
|
||||
@ -68,7 +72,7 @@ export const forceLoadMenuPlugin = async (id: string, win: BrowserWindow) => {
|
||||
export const loadAllMenuPlugins = async (win: BrowserWindow) => {
|
||||
const pluginConfigs = config.plugins.getPlugins();
|
||||
|
||||
for (const [pluginId, pluginDef] of Object.entries(allPlugins)) {
|
||||
for (const [pluginId, pluginDef] of Object.entries(await allPlugins())) {
|
||||
const config = deepmerge(
|
||||
pluginDef.config ?? { enabled: false },
|
||||
pluginConfigs[pluginId] ?? {},
|
||||
|
||||
@ -15,13 +15,17 @@ const loadedPluginMap: Record<
|
||||
PluginDef<unknown, unknown, unknown>
|
||||
> = {};
|
||||
const createContext = (id: string): PreloadContext<PluginConfig> => ({
|
||||
getConfig: () =>
|
||||
getConfig: async () =>
|
||||
deepmerge(
|
||||
allPlugins[id].config ?? { enabled: false },
|
||||
(await allPlugins())[id].config ?? { enabled: false },
|
||||
config.get(`plugins.${id}`) ?? {},
|
||||
) as PluginConfig,
|
||||
setConfig: (newConfig) => {
|
||||
config.setPartial(`plugins.${id}`, newConfig, allPlugins[id].config);
|
||||
setConfig: async (newConfig) => {
|
||||
config.setPartial(
|
||||
`plugins.${id}`,
|
||||
newConfig,
|
||||
(await allPlugins())[id].config,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@ -48,7 +52,7 @@ export const forceUnloadPreloadPlugin = async (id: string) => {
|
||||
|
||||
export const forceLoadPreloadPlugin = async (id: string) => {
|
||||
try {
|
||||
const plugin = preloadPlugins[id];
|
||||
const plugin = (await preloadPlugins())[id];
|
||||
if (!plugin) return;
|
||||
|
||||
const hasStarted = await startPlugin(id, plugin, {
|
||||
@ -78,10 +82,10 @@ export const forceLoadPreloadPlugin = async (id: string) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const loadAllPreloadPlugins = () => {
|
||||
export const loadAllPreloadPlugins = async () => {
|
||||
const pluginConfigs = config.plugins.getPlugins();
|
||||
|
||||
for (const [pluginId, pluginDef] of Object.entries(preloadPlugins)) {
|
||||
for (const [pluginId, pluginDef] of Object.entries(await preloadPlugins())) {
|
||||
const config = deepmerge(
|
||||
pluginDef.config ?? { enable: false },
|
||||
pluginConfigs[pluginId] ?? {},
|
||||
|
||||
@ -18,7 +18,7 @@ const loadedPluginMap: Record<
|
||||
export const createContext = <Config extends PluginConfig>(
|
||||
id: string,
|
||||
): RendererContext<Config> => ({
|
||||
getConfig: async () =>
|
||||
getConfig: () =>
|
||||
window.ipcRenderer.invoke('ytmd:get-config', id) as Promise<Config>,
|
||||
setConfig: async (newConfig) => {
|
||||
await window.ipcRenderer.invoke('ytmd:set-config', id, newConfig);
|
||||
@ -47,7 +47,7 @@ export const forceUnloadRendererPlugin = async (id: string) => {
|
||||
delete unregisterStyleMap[id];
|
||||
delete loadedPluginMap[id];
|
||||
|
||||
const plugin = rendererPlugins[id];
|
||||
const plugin = (await rendererPlugins())[id];
|
||||
if (!plugin) return;
|
||||
|
||||
const hasStopped = await stopPlugin(id, plugin, {
|
||||
@ -71,7 +71,7 @@ export const forceUnloadRendererPlugin = async (id: string) => {
|
||||
};
|
||||
|
||||
export const forceLoadRendererPlugin = async (id: string) => {
|
||||
const plugin = rendererPlugins[id];
|
||||
const plugin = (await rendererPlugins())[id];
|
||||
if (!plugin) return;
|
||||
|
||||
const hasEvaled = await startPlugin(id, plugin, {
|
||||
@ -117,7 +117,7 @@ export const forceLoadRendererPlugin = async (id: string) => {
|
||||
export const loadAllRendererPlugins = async () => {
|
||||
const pluginConfigs = window.mainConfig.plugins.getPlugins();
|
||||
|
||||
for (const [pluginId, pluginDef] of Object.entries(rendererPlugins)) {
|
||||
for (const [pluginId, pluginDef] of Object.entries(await rendererPlugins())) {
|
||||
const config = deepmerge(pluginDef.config, pluginConfigs[pluginId] ?? {});
|
||||
|
||||
if (config.enabled) {
|
||||
|
||||
81
src/menu.ts
81
src/menu.ts
@ -29,21 +29,21 @@ import packageJson from '../package.json';
|
||||
export type MenuTemplate = Electron.MenuItemConstructorOptions[];
|
||||
|
||||
// True only if in-app-menu was loaded on launch
|
||||
const inAppMenuActive = config.plugins.isEnabled('in-app-menu');
|
||||
const inAppMenuActive = await config.plugins.isEnabled('in-app-menu');
|
||||
|
||||
const pluginEnabledMenu = (
|
||||
const pluginEnabledMenu = async (
|
||||
plugin: string,
|
||||
label = '',
|
||||
description: string | undefined = undefined,
|
||||
isNew = false,
|
||||
hasSubmenu = false,
|
||||
refreshMenu: (() => void) | undefined = undefined,
|
||||
): Electron.MenuItemConstructorOptions => ({
|
||||
): Promise<Electron.MenuItemConstructorOptions> => ({
|
||||
label: label || plugin,
|
||||
sublabel: isNew ? t('main.menu.plugins.new') : undefined,
|
||||
toolTip: description,
|
||||
type: 'checkbox',
|
||||
checked: config.plugins.isEnabled(plugin),
|
||||
checked: await config.plugins.isEnabled(plugin),
|
||||
click(item: Electron.MenuItem) {
|
||||
if (item.checked) {
|
||||
config.plugins.enable(plugin);
|
||||
@ -71,19 +71,21 @@ export const mainMenuTemplate = async (
|
||||
const { navigationHistory } = win.webContents;
|
||||
await loadAllMenuPlugins(win);
|
||||
|
||||
const menuResult = Object.entries(getAllMenuTemplate()).map(
|
||||
([id, template]) => {
|
||||
const plugin = allPlugins[id];
|
||||
const allPluginsStubs = await allPlugins();
|
||||
|
||||
const menuResult = await Promise.all(
|
||||
Object.entries(getAllMenuTemplate()).map(async ([id, template]) => {
|
||||
const plugin = allPluginsStubs[id];
|
||||
const pluginLabel = plugin?.name?.() ?? id;
|
||||
const pluginDescription = plugin?.description?.() ?? undefined;
|
||||
const isNew = plugin?.addedVersion
|
||||
? satisfies(packageJson.version, plugin.addedVersion)
|
||||
: false;
|
||||
|
||||
if (!config.plugins.isEnabled(id)) {
|
||||
if (!(await config.plugins.isEnabled(id))) {
|
||||
return [
|
||||
id,
|
||||
pluginEnabledMenu(
|
||||
await pluginEnabledMenu(
|
||||
id,
|
||||
pluginLabel,
|
||||
pluginDescription,
|
||||
@ -101,7 +103,7 @@ export const mainMenuTemplate = async (
|
||||
sublabel: isNew ? t('main.menu.plugins.new') : undefined,
|
||||
toolTip: pluginDescription,
|
||||
submenu: [
|
||||
pluginEnabledMenu(
|
||||
await pluginEnabledMenu(
|
||||
id,
|
||||
t('main.menu.plugins.enabled'),
|
||||
undefined,
|
||||
@ -114,39 +116,42 @@ export const mainMenuTemplate = async (
|
||||
],
|
||||
} satisfies Electron.MenuItemConstructorOptions,
|
||||
] as const;
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const availablePlugins = Object.keys(allPlugins);
|
||||
const pluginMenus = availablePlugins
|
||||
.sort((a, b) => {
|
||||
const aPluginLabel = allPlugins[a]?.name?.() ?? a;
|
||||
const bPluginLabel = allPlugins[b]?.name?.() ?? b;
|
||||
const availablePlugins = Object.keys(await allPlugins());
|
||||
const pluginMenus = await Promise.all(
|
||||
availablePlugins
|
||||
.sort((a, b) => {
|
||||
const aPluginLabel = allPluginsStubs[a]?.name?.() ?? a;
|
||||
const bPluginLabel = allPluginsStubs[b]?.name?.() ?? b;
|
||||
|
||||
return aPluginLabel.localeCompare(bPluginLabel);
|
||||
})
|
||||
.map((id) => {
|
||||
const predefinedTemplate = menuResult.find((it) => it[0] === id);
|
||||
if (predefinedTemplate) return predefinedTemplate[1];
|
||||
return aPluginLabel.localeCompare(bPluginLabel);
|
||||
})
|
||||
.map((id) => {
|
||||
const predefinedTemplate = menuResult.find((it) => it[0] === id);
|
||||
if (predefinedTemplate) return predefinedTemplate[1];
|
||||
|
||||
const plugin = allPlugins[id];
|
||||
const pluginLabel = plugin?.name?.() ?? id;
|
||||
const pluginDescription = plugin?.description?.() ?? undefined;
|
||||
const isNew = plugin?.addedVersion
|
||||
? satisfies(packageJson.version, plugin.addedVersion)
|
||||
: false;
|
||||
const plugin = allPluginsStubs[id];
|
||||
const pluginLabel = plugin?.name?.() ?? id;
|
||||
const pluginDescription = plugin?.description?.() ?? undefined;
|
||||
const isNew = plugin?.addedVersion
|
||||
? satisfies(packageJson.version, plugin.addedVersion)
|
||||
: false;
|
||||
|
||||
return pluginEnabledMenu(
|
||||
id,
|
||||
pluginLabel,
|
||||
pluginDescription,
|
||||
isNew,
|
||||
true,
|
||||
innerRefreshMenu,
|
||||
);
|
||||
});
|
||||
return pluginEnabledMenu(
|
||||
id,
|
||||
pluginLabel,
|
||||
pluginDescription,
|
||||
isNew,
|
||||
true,
|
||||
innerRefreshMenu,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
const availableLanguages = Object.keys(languageResources);
|
||||
const langResources = await languageResources();
|
||||
const availableLanguages = Object.keys(langResources);
|
||||
|
||||
return [
|
||||
{
|
||||
@ -445,7 +450,7 @@ export const mainMenuTemplate = async (
|
||||
availableLanguages
|
||||
.map(
|
||||
(lang): Electron.MenuItemConstructorOptions => ({
|
||||
label: `${languageResources[lang].translation.language?.name ?? 'Unknown'} (${languageResources[lang].translation.language?.['local-name'] ?? 'Unknown'})`,
|
||||
label: `${langResources[lang].translation.language?.name ?? 'Unknown'} (${langResources[lang].translation.language?.['local-name'] ?? 'Unknown'})`,
|
||||
type: 'checkbox',
|
||||
checked: (config.get('options.language') ?? 'en') === lang,
|
||||
click() {
|
||||
|
||||
@ -19,7 +19,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
||||
async start(ctx) {
|
||||
const config = await ctx.getConfig();
|
||||
|
||||
await this.init(ctx);
|
||||
this.init(ctx);
|
||||
registerCallback((songInfo) => {
|
||||
this.songInfo = songInfo;
|
||||
});
|
||||
@ -60,8 +60,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
||||
},
|
||||
|
||||
// Custom
|
||||
async init(ctx) {
|
||||
const config = await ctx.getConfig();
|
||||
init(backendCtx) {
|
||||
this.app = new Hono();
|
||||
|
||||
this.app.use('*', cors());
|
||||
@ -74,6 +73,8 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
||||
|
||||
// middlewares
|
||||
this.app.use('/api/*', async (ctx, next) => {
|
||||
const config = await backendCtx.getConfig();
|
||||
|
||||
if (config.authStrategy !== AuthStrategy.NONE) {
|
||||
return await jwt({
|
||||
secret: config.secret,
|
||||
@ -83,6 +84,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
||||
});
|
||||
this.app.use('/api/*', async (ctx, next) => {
|
||||
const result = await JWTPayloadSchema.spa(await ctx.get('jwtPayload'));
|
||||
const config = await backendCtx.getConfig();
|
||||
|
||||
const isAuthorized =
|
||||
config.authStrategy === AuthStrategy.NONE ||
|
||||
@ -98,12 +100,12 @@ export const backend = createBackend<BackendType, APIServerConfig>({
|
||||
// routes
|
||||
registerControl(
|
||||
this.app,
|
||||
ctx,
|
||||
backendCtx,
|
||||
() => this.songInfo,
|
||||
() => this.currentRepeatMode,
|
||||
() => this.volume,
|
||||
);
|
||||
registerAuth(this.app, ctx);
|
||||
registerAuth(this.app, backendCtx);
|
||||
|
||||
// swagger
|
||||
this.app.openAPIRegistry.registerComponent(
|
||||
|
||||
@ -15,7 +15,7 @@ export type BackendType = {
|
||||
currentRepeatMode?: RepeatMode;
|
||||
volume?: number;
|
||||
|
||||
init: (ctx: BackendContext<APIServerConfig>) => Promise<void>;
|
||||
init: (ctx: BackendContext<APIServerConfig>) => void;
|
||||
run: (hostname: string, port: number) => void;
|
||||
end: () => void;
|
||||
};
|
||||
|
||||
@ -7,11 +7,9 @@ import { Innertube, UniversalCache, Utils, YTNodes } from 'youtubei.js';
|
||||
import is from 'electron-is';
|
||||
import filenamify from 'filenamify';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import { createFFmpeg } from '@ffmpeg.wasm/main';
|
||||
import NodeID3, { TagConstants } from 'node-id3';
|
||||
|
||||
import { Window } from 'happy-dom';
|
||||
import { BG, type BgConfig } from 'bgutils-js';
|
||||
import { lazy } from 'lazy-var';
|
||||
|
||||
import {
|
||||
cropMaxWidth,
|
||||
@ -44,11 +42,13 @@ import type {
|
||||
|
||||
type CustomSongInfo = SongInfo & { trackId?: string };
|
||||
|
||||
const ffmpeg = createFFmpeg({
|
||||
log: false,
|
||||
logger() {}, // Console.log,
|
||||
progress() {}, // Console.log,
|
||||
});
|
||||
const ffmpeg = lazy(async () =>
|
||||
(await import('@ffmpeg.wasm/main')).createFFmpeg({
|
||||
log: false,
|
||||
logger() {}, // Console.log,
|
||||
progress() {}, // Console.log,
|
||||
}),
|
||||
);
|
||||
const ffmpegMutex = new Mutex();
|
||||
|
||||
let yt: Innertube;
|
||||
@ -142,7 +142,7 @@ export const onMainLoad = async ({
|
||||
try {
|
||||
const [width, height] = win.getSize();
|
||||
// emulate jsdom using linkedom
|
||||
const window = new Window({
|
||||
const window = new (await import('happy-dom')).Window({
|
||||
width,
|
||||
height,
|
||||
console,
|
||||
@ -505,12 +505,13 @@ async function iterableStreamToProcessedUint8Array(
|
||||
|
||||
return await ffmpegMutex.runExclusive(async () => {
|
||||
try {
|
||||
if (!ffmpeg.isLoaded()) {
|
||||
await ffmpeg.load();
|
||||
const ffmpegInstance = await ffmpeg.get();
|
||||
if (!ffmpegInstance.isLoaded()) {
|
||||
await ffmpegInstance.load();
|
||||
}
|
||||
|
||||
sendFeedback(t('plugins.downloader.backend.feedback.preparing-file'));
|
||||
ffmpeg.FS(
|
||||
ffmpegInstance.FS(
|
||||
'writeFile',
|
||||
safeVideoName,
|
||||
Buffer.concat(
|
||||
@ -525,7 +526,7 @@ async function iterableStreamToProcessedUint8Array(
|
||||
|
||||
sendFeedback(t('plugins.downloader.backend.feedback.converting'));
|
||||
|
||||
ffmpeg.setProgress(({ ratio }) => {
|
||||
ffmpegInstance.setProgress(({ ratio }) => {
|
||||
sendFeedback(
|
||||
t('plugins.downloader.backend.feedback.conversion-progress', {
|
||||
percent: Math.floor(ratio * 100),
|
||||
@ -537,7 +538,7 @@ async function iterableStreamToProcessedUint8Array(
|
||||
|
||||
const safeVideoNameWithExtension = `${safeVideoName}.${extension}`;
|
||||
try {
|
||||
await ffmpeg.run(
|
||||
await ffmpegInstance.run(
|
||||
'-i',
|
||||
safeVideoName,
|
||||
...presetFfmpegArgs,
|
||||
@ -545,15 +546,15 @@ async function iterableStreamToProcessedUint8Array(
|
||||
safeVideoNameWithExtension,
|
||||
);
|
||||
} finally {
|
||||
ffmpeg.FS('unlink', safeVideoName);
|
||||
ffmpegInstance.FS('unlink', safeVideoName);
|
||||
}
|
||||
|
||||
sendFeedback(t('plugins.downloader.backend.feedback.saving'));
|
||||
|
||||
try {
|
||||
return ffmpeg.FS('readFile', safeVideoNameWithExtension);
|
||||
return ffmpegInstance.FS('readFile', safeVideoNameWithExtension);
|
||||
} finally {
|
||||
ffmpeg.FS('unlink', safeVideoNameWithExtension);
|
||||
ffmpegInstance.FS('unlink', safeVideoNameWithExtension);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
sendError(error as Error, safeVideoName);
|
||||
|
||||
@ -13,7 +13,6 @@ import { DownloadButton } from './templates/download';
|
||||
import type { RendererContext } from '@/types/contexts';
|
||||
import type { DownloaderPluginConfig } from './index';
|
||||
|
||||
let menu: HTMLElement | null = null;
|
||||
let download: () => void;
|
||||
|
||||
const [downloadButtonText, setDownloadButtonText] = createSignal<string>('');
|
||||
@ -21,14 +20,10 @@ const [downloadButtonText, setDownloadButtonText] = createSignal<string>('');
|
||||
let buttonContainer: HTMLDivElement | null = null;
|
||||
|
||||
const menuObserver = new MutationObserver(() => {
|
||||
if (!menu) {
|
||||
menu = getSongMenu();
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const menu = getSongMenu();
|
||||
|
||||
if (
|
||||
!menu ||
|
||||
menu.contains(buttonContainer) ||
|
||||
!isMusicOrVideoTrack() ||
|
||||
!buttonContainer
|
||||
|
||||
@ -3,7 +3,10 @@ import keyEventAreEqual from 'keyboardevents-areequal';
|
||||
import { render } from 'solid-js/web';
|
||||
|
||||
import { getSongMenu } from '@/providers/dom-elements';
|
||||
import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check';
|
||||
import {
|
||||
isMusicOrVideoTrack,
|
||||
isPlayerMenu,
|
||||
} from '@/plugins/utils/renderer/check';
|
||||
|
||||
import { t } from '@/i18n';
|
||||
|
||||
@ -152,7 +155,11 @@ export const onPlayerApiReady = async (
|
||||
const observer = new MutationObserver(() => {
|
||||
const menu = getSongMenu();
|
||||
|
||||
if (menu?.contains(pipButtonContainer) || !isMusicOrVideoTrack()) {
|
||||
if (
|
||||
menu?.contains(pipButtonContainer) ||
|
||||
!isMusicOrVideoTrack() ||
|
||||
!isPlayerMenu(menu)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,10 @@ import { getSongMenu } from '@/providers/dom-elements';
|
||||
import { PlaybackSpeedSlider } from './components/slider';
|
||||
import { t } from '@/i18n';
|
||||
|
||||
import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check';
|
||||
import {
|
||||
isMusicOrVideoTrack,
|
||||
isPlayerMenu,
|
||||
} from '@/plugins/utils/renderer/check';
|
||||
|
||||
const MIN_PLAYBACK_SPEED = 0.07;
|
||||
const MAX_PLAYBACK_SPEED = 16;
|
||||
@ -83,7 +86,12 @@ export const onPlayerApiReady = () => {
|
||||
const observer = new MutationObserver(() => {
|
||||
const menu = getSongMenu();
|
||||
|
||||
if (menu && !menu.contains(sliderContainer) && isMusicOrVideoTrack()) {
|
||||
if (
|
||||
menu &&
|
||||
!menu.contains(sliderContainer) &&
|
||||
isMusicOrVideoTrack() &&
|
||||
isPlayerMenu(menu)
|
||||
) {
|
||||
menu.prepend(sliderContainer);
|
||||
}
|
||||
});
|
||||
|
||||
@ -45,7 +45,7 @@ export const onPlayerApiReady = async (
|
||||
}, 2500);
|
||||
|
||||
/** Restore saved volume and setup tooltip */
|
||||
function firstRun() {
|
||||
async function firstRun() {
|
||||
if (typeof options.savedVolume === 'number') {
|
||||
// Set saved volume as tooltip
|
||||
setTooltip(options.savedVolume);
|
||||
@ -66,7 +66,7 @@ export const onPlayerApiReady = async (
|
||||
injectVolumeHud(noVid);
|
||||
if (!noVid) {
|
||||
setupVideoPlayerOnwheel();
|
||||
if (!window.mainConfig.plugins.isEnabled('video-toggle')) {
|
||||
if (!await window.mainConfig.plugins.isEnabled('video-toggle')) {
|
||||
// Video-toggle handles hud positioning on its own
|
||||
const videoMode = () =>
|
||||
api.getPlayerResponse().videoDetails?.musicVideoType !==
|
||||
@ -280,7 +280,7 @@ export const onPlayerApiReady = async (
|
||||
);
|
||||
context.ipc.on('setVolume', (value: number) => setVolume(value));
|
||||
|
||||
firstRun();
|
||||
await firstRun();
|
||||
};
|
||||
|
||||
export const onConfigChange = (config: PreciseVolumePluginConfig) => {
|
||||
|
||||
@ -309,8 +309,8 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
player.volume = Number.parseFloat((newVol / 100).toFixed(2));
|
||||
});
|
||||
|
||||
player.on('volume', (newVolume: number) => {
|
||||
if (config.plugins.isEnabled('precise-volume')) {
|
||||
player.on('volume', async (newVolume: number) => {
|
||||
if (await config.plugins.isEnabled('precise-volume')) {
|
||||
// With precise volume we can set the volume to the exact value.
|
||||
win.webContents.send('setVolume', ~~(newVolume * 100));
|
||||
} else {
|
||||
|
||||
@ -1,20 +1,39 @@
|
||||
export const isMusicOrVideoTrack = () => {
|
||||
let menuUrl = document.querySelector<HTMLAnchorElement>(
|
||||
'tp-yt-paper-listbox [tabindex="0"] #navigation-endpoint',
|
||||
)?.href;
|
||||
|
||||
if (!menuUrl?.includes('watch?')) {
|
||||
menuUrl = undefined;
|
||||
// check for podcast
|
||||
for (const it of document.querySelectorAll(
|
||||
'tp-yt-paper-listbox [tabindex="-1"] #navigation-endpoint',
|
||||
)) {
|
||||
if (it.getAttribute('href')?.includes('podcast/')) {
|
||||
menuUrl = it.getAttribute('href')!;
|
||||
break;
|
||||
}
|
||||
for (const menuSelector of document.querySelectorAll<
|
||||
HTMLAnchorElement & {
|
||||
data: {
|
||||
watchEndpoint: {
|
||||
videoId: string;
|
||||
};
|
||||
addToPlaylistEndpoint: {
|
||||
videoId: string;
|
||||
};
|
||||
clickTrackingParams: string;
|
||||
};
|
||||
}
|
||||
>('tp-yt-paper-listbox #navigation-endpoint')) {
|
||||
if (
|
||||
menuSelector?.data?.addToPlaylistEndpoint?.videoId ||
|
||||
menuSelector?.data?.watchEndpoint?.videoId
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return !!menuUrl;
|
||||
return false;
|
||||
};
|
||||
|
||||
export const isPlayerMenu = (menu?: HTMLElement | null) => {
|
||||
return (
|
||||
menu?.parentElement as
|
||||
| (HTMLElement & {
|
||||
ytEventForwardingBehavior: {
|
||||
forwarder_: {
|
||||
eventSink: HTMLElement;
|
||||
};
|
||||
};
|
||||
})
|
||||
| null
|
||||
)?.ytEventForwardingBehavior?.forwarder_?.eventSink?.matches(
|
||||
'ytmusic-menu-renderer.ytmusic-player-bar',
|
||||
);
|
||||
};
|
||||
|
||||
@ -159,9 +159,9 @@ export default createPlugin({
|
||||
const config = await getConfig();
|
||||
this.config = config;
|
||||
|
||||
const moveVolumeHud = window.mainConfig.plugins.isEnabled(
|
||||
const moveVolumeHud = (await window.mainConfig.plugins.isEnabled(
|
||||
'precise-volume',
|
||||
)
|
||||
))
|
||||
? (preciseVolumeMoveVolumeHud as (_: boolean) => void)
|
||||
: () => {};
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ import { loadI18n, setLanguage } from '@/i18n';
|
||||
|
||||
loadI18n().then(async () => {
|
||||
await setLanguage(config.get('options.language') ?? 'en');
|
||||
loadAllPreloadPlugins();
|
||||
await loadAllPreloadPlugins();
|
||||
});
|
||||
|
||||
ipcRenderer.on('plugin:unload', async (_, id: string) => {
|
||||
|
||||
13
src/virtual-module.d.ts
vendored
13
src/virtual-module.d.ts
vendored
@ -3,18 +3,17 @@ declare module 'virtual:plugins' {
|
||||
|
||||
type Plugin = PluginDef<unknown, unknown, unknown, PluginConfig>;
|
||||
|
||||
export const mainPlugins: Record<string, Plugin>;
|
||||
export const preloadPlugins: Record<string, Plugin>;
|
||||
export const rendererPlugins: Record<string, Plugin>;
|
||||
export const mainPlugins: () => Promise<Record<string, Plugin>>;
|
||||
export const preloadPlugins: () => Promise<Record<string, Plugin>>;
|
||||
export const rendererPlugins: () => Promise<Record<string, Plugin>>;
|
||||
|
||||
export const allPlugins: Record<
|
||||
string,
|
||||
Omit<Plugin, 'backend' | 'preload' | 'renderer'>
|
||||
export const allPlugins: () => Promise<
|
||||
Record<string, Omit<Plugin, 'backend' | 'preload' | 'renderer'>>
|
||||
>;
|
||||
}
|
||||
|
||||
declare module 'virtual:i18n' {
|
||||
import type { LanguageResources } from '@/i18n/resources/@types';
|
||||
|
||||
export const languageResources: LanguageResources;
|
||||
export const languageResources: () => Promise<LanguageResources>;
|
||||
}
|
||||
|
||||
@ -4,9 +4,6 @@ import { fileURLToPath } from 'node:url';
|
||||
import { globSync } from 'glob';
|
||||
import { Project } from 'ts-morph';
|
||||
|
||||
const snakeToCamel = (text: string) =>
|
||||
text.replace(/-(\w)/g, (_, letter: string) => letter.toUpperCase());
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const globalProject = new Project({
|
||||
tsConfigFilePath: resolve(__dirname, '..', 'tsconfig.json'),
|
||||
@ -27,20 +24,20 @@ export const i18nImporter = () => {
|
||||
const src = globalProject.createSourceFile(
|
||||
'vm:i18n',
|
||||
(writer) => {
|
||||
// prettier-ignore
|
||||
writer.writeLine('export const languageResources = async () => {');
|
||||
writer.writeLine(' const entries = await Promise.all([');
|
||||
for (const { name, path } of plugins) {
|
||||
const relativePath = relative(resolve(srcPath, '..'), path).replace(/\\/g, '/');
|
||||
writer.writeLine(`import ${snakeToCamel(name)}Json from "./${relativePath}";`);
|
||||
}
|
||||
const relativePath = relative(resolve(srcPath, '..'), path).replace(
|
||||
/\\/g,
|
||||
'/',
|
||||
);
|
||||
|
||||
writer.blankLine();
|
||||
|
||||
writer.writeLine('export const languageResources = {');
|
||||
for (const { name } of plugins) {
|
||||
writer.writeLine(` "${name}": {`);
|
||||
writer.writeLine(` translation: ${snakeToCamel(name)}Json,`);
|
||||
writer.writeLine(' },');
|
||||
writer.writeLine(
|
||||
` import('./${relativePath}').then((mod) => ({ "${name}": { translation: mod.default } })),`,
|
||||
);
|
||||
}
|
||||
writer.writeLine(' ]);');
|
||||
writer.writeLine(' return Object.assign({}, ...entries);');
|
||||
writer.writeLine('};');
|
||||
writer.blankLine();
|
||||
},
|
||||
|
||||
@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url';
|
||||
import { globSync } from 'glob';
|
||||
import { Project } from 'ts-morph';
|
||||
|
||||
const snakeToCamel = (text: string) =>
|
||||
const kebabToCamel = (text: string) =>
|
||||
text.replace(/-(\w)/g, (_, letter: string) => letter.toUpperCase());
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
@ -43,31 +43,83 @@ export const pluginVirtualModuleGenerator = (
|
||||
const src = globalProject.createSourceFile(
|
||||
'vm:pluginIndexes',
|
||||
(writer) => {
|
||||
// prettier-ignore
|
||||
for (const { name, path } of plugins) {
|
||||
const relativePath = relative(resolve(srcPath, '..'), path).replace(/\\/g, '/');
|
||||
writer.writeLine(`import ${snakeToCamel(name)}Plugin, { pluginStub as ${snakeToCamel(name)}PluginStub } from "./${relativePath}";`);
|
||||
}
|
||||
const relativePath = relative(resolve(srcPath, '..'), path).replace(
|
||||
/\\/g,
|
||||
'/',
|
||||
);
|
||||
if (mode === 'main') {
|
||||
// dynamic import (for main)
|
||||
writer.writeLine(
|
||||
`const ${kebabToCamel(name)}PluginImport = () => import('./${relativePath}');`,
|
||||
);
|
||||
writer.writeLine(
|
||||
`const ${kebabToCamel(name)}Plugin = async () => (await ${kebabToCamel(name)}PluginImport()).default;`,
|
||||
);
|
||||
writer.writeLine(
|
||||
`const ${kebabToCamel(name)}PluginStub = async () => (await ${kebabToCamel(name)}PluginImport()).pluginStub;`,
|
||||
);
|
||||
} else {
|
||||
// static import (preload does not support dynamic import)
|
||||
writer.writeLine(
|
||||
`import ${kebabToCamel(name)}PluginImport, { pluginStub as ${kebabToCamel(name)}PluginStubImport } from "./${relativePath}";`,
|
||||
);
|
||||
writer.writeLine(
|
||||
`const ${kebabToCamel(name)}Plugin = () => Promise.resolve(${kebabToCamel(name)}PluginImport);`,
|
||||
);
|
||||
writer.writeLine(
|
||||
`const ${kebabToCamel(name)}PluginStub = () => Promise.resolve(${kebabToCamel(name)}PluginStubImport);`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
writer.blankLine();
|
||||
|
||||
// Context-specific exports
|
||||
writer.writeLine(`export const ${mode}Plugins = {`);
|
||||
writer.writeLine(`let ${mode}PluginsCache = null;`);
|
||||
writer.writeLine(`export const ${mode}Plugins = async () => {`);
|
||||
writer.writeLine(
|
||||
` if (${mode}PluginsCache) return await ${mode}PluginsCache;`,
|
||||
);
|
||||
writer.writeLine(
|
||||
' const { promise, resolve } = Promise.withResolvers();',
|
||||
);
|
||||
writer.writeLine(' ' + `${mode}PluginsCache = promise;`);
|
||||
writer.writeLine(' const pluginEntries = await Promise.all([');
|
||||
for (const { name } of plugins) {
|
||||
const checkMode = mode === 'main' ? 'backend' : mode;
|
||||
// HACK: To avoid situation like importing renderer plugins in main
|
||||
writer.writeLine(
|
||||
` ...(${snakeToCamel(name)}Plugin['${checkMode}'] ? { "${name}": ${snakeToCamel(name)}Plugin } : {}),`,
|
||||
` ${kebabToCamel(name)}Plugin().then((plg) => plg['${checkMode}'] ? ["${name}", plg] : null),`,
|
||||
);
|
||||
}
|
||||
writer.writeLine(' ]);');
|
||||
writer.writeLine(
|
||||
' resolve(pluginEntries.filter((entry) => entry).reduce((acc, [name, plg]) => { acc[name] = plg; return acc; }, {}));',
|
||||
);
|
||||
writer.writeLine(` return await ${mode}PluginsCache;`);
|
||||
writer.writeLine('};');
|
||||
writer.blankLine();
|
||||
|
||||
// All plugins export (stub only) // Omit<Plugin, 'backend' | 'preload' | 'renderer'>
|
||||
writer.writeLine('export const allPlugins = {');
|
||||
writer.writeLine('let allPluginsCache = null;');
|
||||
writer.writeLine('export const allPlugins = async () => {');
|
||||
writer.writeLine(' if (allPluginsCache) return await allPluginsCache;');
|
||||
writer.writeLine(
|
||||
' const { promise, resolve } = Promise.withResolvers();',
|
||||
);
|
||||
writer.writeLine(' allPluginsCache = promise;');
|
||||
writer.writeLine(' const stubEntries = await Promise.all([');
|
||||
for (const { name } of plugins) {
|
||||
writer.writeLine(` "${name}": ${snakeToCamel(name)}PluginStub,`);
|
||||
writer.writeLine(
|
||||
` ${kebabToCamel(name)}PluginStub().then((stub) => ["${name}", stub]),`,
|
||||
);
|
||||
}
|
||||
writer.writeLine(' ]);');
|
||||
writer.writeLine(
|
||||
' resolve(stubEntries.reduce((acc, [name, plg]) => { acc[name] = plg; return acc; }, {}));',
|
||||
);
|
||||
writer.writeLine(' return await promise;');
|
||||
writer.writeLine('};');
|
||||
writer.blankLine();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user