Compare commits

...

21 Commits

Author SHA1 Message Date
c94b22b82c Bump version to 3.5.3 2024-09-17 21:32:22 +09:00
cab3cb49f0 chore(deps): update dependency electron to v32.1.0 2024-09-17 21:31:29 +09:00
e42084f008 fix(deps): update dependency @floating-ui/dom to v1.6.11 2024-09-17 21:30:11 +09:00
adca273ec3 chore(deps): update dependency typescript to v5.6.2 2024-09-17 21:28:03 +09:00
91dceb3c22 chore(deps): update playwright monorepo to v1.47.1 2024-09-17 21:27:47 +09:00
216e76f4a1 fix(music-together): fix ? operator 2024-09-17 21:09:30 +09:00
178bfa483f fix: openToast to toastService 2024-09-17 21:05:35 +09:00
10ecf5d2fe fix(src/index): fix typo 2024-09-17 20:40:23 +09:00
7099b81296 fix(src/index): ignore eslint error 2024-09-17 20:40:23 +09:00
1f15376b00 chore(deps): update dependency vite to v5.4.6 2024-09-17 20:39:32 +09:00
02b7a39753 chore(deps): update dependency eslint to v8.57.1 2024-09-17 20:38:38 +09:00
6edc84a8bd chore(deps): update dependency rollup to v4.21.3 2024-09-17 20:38:19 +09:00
11a0d39064 fix(song-info-front): fix nullable issue 2024-09-17 20:27:11 +09:00
d5a5ed35b6 fix: fix trustedHTML issue
- (Maybe) fix #2339, caused by YouTube's A/B testing
2024-09-17 20:05:22 +09:00
dbb9e95b32 fix(deps): update dependency i18next to v23.15.1 2024-09-17 18:27:27 +09:00
d4c8a4320d chore(deps): update typescript-eslint monorepo to v8.6.0 2024-09-17 18:27:05 +09:00
68d4f38e41 chore(i18n): Translated using Weblate (Hungarian)
Currently translated at 94.7% (362 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hu/
2024-09-15 22:09:12 +00:00
2204784e89 chore(i18n): Translated using Weblate (Icelandic)
Currently translated at 92.9% (355 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/is/
2024-09-15 22:09:12 +00:00
c3b995b0a8 chore(i18n): Translated using Weblate (Hebrew)
Currently translated at 6.0% (23 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/he/
2024-09-11 22:09:24 +02:00
ed0a344077 chore(i18n): Translated using Weblate (Polish)
Currently translated at 95.2% (364 of 382 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-09-09 22:09:15 +00:00
199d912823 Update changelog for v3.5.2 2024-09-07 12:27:30 +00:00
15 changed files with 473 additions and 301 deletions

View File

@ -2,8 +2,49 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v3.5.2](https://github.com/th-ch/youtube-music/compare/v3.5.1...v3.5.2)
- chore(deps): update typescript-eslint monorepo to v8.4.0 [`#2401`](https://github.com/th-ch/youtube-music/pull/2401)
- chore(deps): update dependency @total-typescript/ts-reset to v0.6.1 [`#2396`](https://github.com/th-ch/youtube-music/pull/2396)
- chore(deps): update dependency electron to v31.5.0 [`#2397`](https://github.com/th-ch/youtube-music/pull/2397)
- chore(deps): update dependency eslint-import-resolver-typescript to v3.6.3 [`#2376`](https://github.com/th-ch/youtube-music/pull/2376)
- chore(deps): update dependency discord-api-types to v0.37.100 [`#2394`](https://github.com/th-ch/youtube-music/pull/2394)
- fix(deps): update dependency electron-updater to v6.3.4 [`#2395`](https://github.com/th-ch/youtube-music/pull/2395)
- chore(deps): update dependency @babel/runtime to v7.25.6 [`#2388`](https://github.com/th-ch/youtube-music/pull/2388)
- chore(deps): update dependency vite-plugin-inspect to v0.8.7 [`#2389`](https://github.com/th-ch/youtube-music/pull/2389)
- chore(deps): update dependency discord-api-types to v0.37.99 [`#2374`](https://github.com/th-ch/youtube-music/pull/2374)
- chore(deps): update dependency vite to v5.4.3 [`#2377`](https://github.com/th-ch/youtube-music/pull/2377)
- fix: incorrect regex when splitting artistName [`#2378`](https://github.com/th-ch/youtube-music/pull/2378)
- chore(deps): update dependency @babel/runtime to v7.25.4 [`#2373`](https://github.com/th-ch/youtube-music/pull/2373)
- synced-lyrics: make the lyrics search more reliable [`#2343`](https://github.com/th-ch/youtube-music/pull/2343)
- fix(deps): update dependency solid-js to v1.8.22 [`#2354`](https://github.com/th-ch/youtube-music/pull/2354)
- chore(deps): update typescript-eslint monorepo to v8.3.0 [`#2350`](https://github.com/th-ch/youtube-music/pull/2350)
- fix(deps): update dependency electron-debug to v4.0.1 [`#2349`](https://github.com/th-ch/youtube-music/pull/2349)
- chore(deps): update dependency electron to v31.4.0 [`#2356`](https://github.com/th-ch/youtube-music/pull/2356)
- fix: hide native-controls on linux when in-app-menu is used [`#2366`](https://github.com/th-ch/youtube-music/pull/2366)
- fix: detect the upgrade btn using the icon [`#2364`](https://github.com/th-ch/youtube-music/pull/2364)
- fix: exclude build-id files from rpm [`#2361`](https://github.com/th-ch/youtube-music/pull/2361)
- fix(deps): update dependency i18next to v23.12.3 [`#2352`](https://github.com/th-ch/youtube-music/pull/2352)
- fix(deps): update dependency @floating-ui/dom to v1.6.10 [`#2340`](https://github.com/th-ch/youtube-music/pull/2340)
- fix(deps): update dependency electron-updater to v6.3.3 [`#2347`](https://github.com/th-ch/youtube-music/pull/2347)
- fix(deps): update dependency solid-js to v1.8.20 [`#2345`](https://github.com/th-ch/youtube-music/pull/2345)
- chore(deps): update dependency vite to v5.4.0 [`#2342`](https://github.com/th-ch/youtube-music/pull/2342)
- chore(deps): update typescript-eslint monorepo to v8.0.1 [`#2335`](https://github.com/th-ch/youtube-music/pull/2335)
- fix(deps): update dependency @floating-ui/dom to v1.6.9 [`#2337`](https://github.com/th-ch/youtube-music/pull/2337)
- chore(deps): update playwright monorepo to v1.46.0 [`#2336`](https://github.com/th-ch/youtube-music/pull/2336)
- chore(README): Translation README to Russian and adding Synced Lyrics to main README [`#2338`](https://github.com/th-ch/youtube-music/pull/2338)
- chore(deps): update dependency rollup to v4.20.0 [`#2326`](https://github.com/th-ch/youtube-music/pull/2326)
- fix(synced-lyric): fix timestamp [`#2323`](https://github.com/th-ch/youtube-music/issues/2323) [`#2379`](https://github.com/th-ch/youtube-music/issues/2379)
- Revert "fix(MPRIS): Prevents player to start with invalid MPRIS interface (#1996)" [`#2225`](https://github.com/th-ch/youtube-music/issues/2225)
- fix(adblocker/inplayer): fix Response.prototype.json [`#2310`](https://github.com/th-ch/youtube-music/issues/2310)
- chore(deps): update dependency eslint-plugin-import to v2.30.0 [`f48e46d`](https://github.com/th-ch/youtube-music/commit/f48e46d29cf09c76c5172fd56d2d0f705616e4e3)
- Revert "chore(deps): update dependency electron-builder to v25" [`089eff3`](https://github.com/th-ch/youtube-music/commit/089eff3152903c8b55ad3e5571b944062a647e27)
- chore(deps): update dependency electron-builder to v25 [`fe4c89c`](https://github.com/th-ch/youtube-music/commit/fe4c89c349bb9f4f54d95c2018943095ccfdab0c)
#### [v3.5.1](https://github.com/th-ch/youtube-music/compare/v3.5.0...v3.5.1) #### [v3.5.1](https://github.com/th-ch/youtube-music/compare/v3.5.0...v3.5.1)
> 1 August 2024
- fix(deps): update dependency youtubei.js to v10.3.0 [`#2306`](https://github.com/th-ch/youtube-music/pull/2306) - fix(deps): update dependency youtubei.js to v10.3.0 [`#2306`](https://github.com/th-ch/youtube-music/pull/2306)
- fix: Window gets stuck offscreen in some instances [`#2303`](https://github.com/th-ch/youtube-music/pull/2303) - fix: Window gets stuck offscreen in some instances [`#2303`](https://github.com/th-ch/youtube-music/pull/2303)
- fix: Incorrect window size on multi-monitor scaled displays [`#2302`](https://github.com/th-ch/youtube-music/pull/2302) - fix: Incorrect window size on multi-monitor scaled displays [`#2302`](https://github.com/th-ch/youtube-music/pull/2302)

View File

@ -1,7 +1,7 @@
{ {
"name": "youtube-music", "name": "youtube-music",
"productName": "YouTube Music", "productName": "YouTube Music",
"version": "3.5.2", "version": "3.5.3",
"description": "YouTube Music Desktop App - including custom plugins", "description": "YouTube Music Desktop App - including custom plugins",
"main": "./dist/main/index.js", "main": "./dist/main/index.js",
"license": "MIT", "license": "MIT",
@ -163,7 +163,7 @@
"@electron/remote": "2.1.2", "@electron/remote": "2.1.2",
"@ffmpeg.wasm/core-mt": "0.12.0", "@ffmpeg.wasm/core-mt": "0.12.0",
"@ffmpeg.wasm/main": "0.12.0", "@ffmpeg.wasm/main": "0.12.0",
"@floating-ui/dom": "1.6.10", "@floating-ui/dom": "1.6.11",
"@foobar404/wave": "2.0.5", "@foobar404/wave": "2.0.5",
"@jellybrick/electron-better-web-request": "1.0.4", "@jellybrick/electron-better-web-request": "1.0.4",
"@jellybrick/mpris-service": "2.1.4", "@jellybrick/mpris-service": "2.1.4",
@ -188,7 +188,7 @@
"filenamify": "6.0.0", "filenamify": "6.0.0",
"howler": "2.2.4", "howler": "2.2.4",
"html-to-text": "9.0.5", "html-to-text": "9.0.5",
"i18next": "23.14.0", "i18next": "23.15.1",
"keyboardevent-from-electron-accelerator": "2.0.0", "keyboardevent-from-electron-accelerator": "2.0.0",
"keyboardevents-areequal": "0.2.2", "keyboardevents-areequal": "0.2.2",
"node-html-parser": "6.1.13", "node-html-parser": "6.1.13",
@ -207,37 +207,38 @@
"youtubei.js": "10.4.0" "youtubei.js": "10.4.0"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "1.47.0", "@playwright/test": "1.47.1",
"@total-typescript/ts-reset": "0.6.1", "@total-typescript/ts-reset": "0.6.1",
"@types/color": "3.0.6", "@types/color": "3.0.6",
"@types/electron-localshortcut": "3.1.3", "@types/electron-localshortcut": "3.1.3",
"@types/howler": "2.2.11", "@types/howler": "2.2.11",
"@types/html-to-text": "9.0.4", "@types/html-to-text": "9.0.4",
"@types/semver": "7.5.8", "@types/semver": "7.5.8",
"@typescript-eslint/eslint-plugin": "8.4.0", "@types/trusted-types": "2.0.7",
"@typescript-eslint/parser": "8.4.0", "@typescript-eslint/eslint-plugin": "8.6.0",
"@typescript-eslint/parser": "8.6.0",
"bufferutil": "4.0.8", "bufferutil": "4.0.8",
"builtin-modules": "4.0.0", "builtin-modules": "4.0.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"del-cli": "5.1.0", "del-cli": "5.1.0",
"discord-api-types": "0.37.100", "discord-api-types": "0.37.100",
"electron": "32.0.2", "electron": "32.1.0",
"electron-builder": "24.13.3", "electron-builder": "24.13.3",
"electron-devtools-installer": "3.2.0", "electron-devtools-installer": "3.2.0",
"electron-vite": "2.3.0", "electron-vite": "2.3.0",
"esbuild": "0.23.1", "esbuild": "0.23.1",
"eslint": "8.57.0", "eslint": "8.57.1",
"eslint-import-resolver-exports": "1.0.0-beta.5", "eslint-import-resolver-exports": "1.0.0-beta.5",
"eslint-import-resolver-typescript": "3.6.3", "eslint-import-resolver-typescript": "3.6.3",
"eslint-plugin-import": "2.30.0", "eslint-plugin-import": "2.30.0",
"eslint-plugin-prettier": "5.2.1", "eslint-plugin-prettier": "5.2.1",
"glob": "11.0.0", "glob": "11.0.0",
"node-gyp": "10.2.0", "node-gyp": "10.2.0",
"playwright": "1.47.0", "playwright": "1.47.1",
"rollup": "4.21.2", "rollup": "4.21.3",
"typescript": "5.5.4", "typescript": "5.6.2",
"utf-8-validate": "6.0.4", "utf-8-validate": "6.0.4",
"vite": "5.4.3", "vite": "5.4.6",
"vite-plugin-inspect": "0.8.7", "vite-plugin-inspect": "0.8.7",
"vite-plugin-resolve": "2.5.2", "vite-plugin-resolve": "2.5.2",
"vite-plugin-solid": "2.10.2", "vite-plugin-solid": "2.10.2",

498
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -2,13 +2,14 @@
"common": { "common": {
"console": { "console": {
"plugins": { "plugins": {
"execute-failed": "נכשל ביצוע תוסף {{pluginName}}::{{contextName}}", "execute-failed": "שגיאה בהרצת התוסף {{pluginName}}::{{contextName}}",
"executed-at-ms": "התוסף {{pluginName}}:{{contextName}} בוצע ב {{ms}}ms", "executed-at-ms": "התוסף {{pluginName}}:{{contextName}} בוצע ב {{ms}}ms",
"initialize-failed": "טעינת התוסף \"{{pluginName}}\" נכשלה", "initialize-failed": "טעינת התוסף \"{{pluginName}}\" נכשלה",
"load-all": "טוען את כל התוספים", "load-all": "טוען את כל התוספים",
"load-failed": "טעינת התוסף \"{{pluginName}}\" נכשלה", "load-failed": "לא ניתן לטעון את התוסף {{pluginName}}",
"loaded": "התוסף \"{{pluginName}}\" נטען", "loaded": "התוסף \"{{pluginName}}\" נטען",
"unload-failed": "הסרת התוסף \"{{pluginName}} נכשלה" "unload-failed": "הסרת התוסף \"{{pluginName}} נכשלה",
"unloaded": "תוסף {{pluginName}} הורד"
} }
} }
}, },
@ -25,14 +26,28 @@
"i18n": { "i18n": {
"loaded": "i18n נטען" "loaded": "i18n נטען"
}, },
"second-instance": {
"receive-command": "התקבלה פקודה מעבר פרוטוקל: {{command}}"
},
"theme": { "theme": {
"css-file-not-found": "קובץ ה-CSS \"{{cssFile}}\" לא קיים. מדלג" "css-file-not-found": "קובץ ה-CSS \"{{cssFile}}\" לא קיים. מדלג"
}, },
"unresponsive": {
"details": "שגיאה ללא תגובה\n{{error}}"
},
"when-ready": { "when-ready": {
"clearing-cache-after-20s": "מוחק קבצי מתמון" "clearing-cache-after-20s": "מוחק קבצי מתמון"
},
"window": {
"tried-to-render-offscreen": "ווינדוס ניסה להציג תוכן מחוץ למסך, גודל חלון={{windowSize}}, גודל מסך={{displaySize}}, מיקום={{position}}"
} }
}, },
"dialog": { "dialog": {
"hide-menu-enabled": {
"detail": "התפריט מוחבא, השתמש \"Alt\" על להציג אותו (או \"Esacpe\" אם משתמשים בתפריט בתוך האפליקציה)",
"message": "הסתרת התפריט מופעלת",
"title": "הסתרת התפריט הופעלה"
},
"need-to-restart": { "need-to-restart": {
"buttons": { "buttons": {
"later": "אחר כך", "later": "אחר כך",

View File

@ -372,6 +372,9 @@
"backend": { "backend": {
"dialog": { "dialog": {
"error": { "error": {
"buttons": {
"ok": "Rendben"
},
"message": "Hoppá! Elnézést, a letöltés sikertelen volt…", "message": "Hoppá! Elnézést, a letöltés sikertelen volt…",
"title": "A letöltés során hiba történt!" "title": "A letöltés során hiba történt!"
}, },
@ -412,6 +415,7 @@
"menu": { "menu": {
"choose-download-folder": "Letöltési mappa kiválasztása", "choose-download-folder": "Letöltési mappa kiválasztása",
"download-finish-settings": { "download-finish-settings": {
"label": "Letöltés befejezéskor",
"prompt": { "prompt": {
"last-percent": "x százalék után", "last-percent": "x százalék után",
"last-seconds": "Utolsó x másodperc" "last-seconds": "Utolsó x másodperc"
@ -425,7 +429,7 @@
} }
}, },
"download-playlist": "Lejátszási lista letöltése", "download-playlist": "Lejátszási lista letöltése",
"presets": "Előbeállítások", "presets": "Sablonok",
"skip-existing": "Meglévő fájlok kihagyása" "skip-existing": "Meglévő fájlok kihagyása"
}, },
"name": "Letöltő", "name": "Letöltő",
@ -666,6 +670,18 @@
"fetch": "⚠️ - Hiba történt a dalszövegek lekérése közben. Kérlek, próbáld újra később.", "fetch": "⚠️ - Hiba történt a dalszövegek lekérése közben. Kérlek, próbáld újra később.",
"not-found": "⚠️ - Nem található dalszöveg ehhez a zenéhez." "not-found": "⚠️ - Nem található dalszöveg ehhez a zenéhez."
}, },
"menu": {
"line-effect": {
"submenu": {
"scale": {
"label": "Mérték"
}
}
},
"precise-timing": {
"label": "Dalszöveg tökéletes szinkronizálása"
}
},
"name": "Szinkronizált dalszövegek", "name": "Szinkronizált dalszövegek",
"refetch-btn": { "refetch-btn": {
"fetching": "Lekérés folyamatban...", "fetching": "Lekérés folyamatban...",

View File

@ -158,6 +158,14 @@
}, },
"remove-upgrade-button": "Fjarlægja uppgræðartakkan", "remove-upgrade-button": "Fjarlægja uppgræðartakkan",
"theme": { "theme": {
"dialog": {
"button": {
"cancel": "Hætta við",
"remove": "Fjarlægja"
},
"remove-theme": "Ertu viss um að þú viljir fjarlægja þetta sérsniðna þema?",
"remove-theme-message": "Þetta mun fjarlægja sérsniðna þema"
},
"label": "Þema", "label": "Þema",
"submenu": { "submenu": {
"import-css-file": "Flytja inn sérsniðna CSS skrá", "import-css-file": "Flytja inn sérsniðna CSS skrá",
@ -199,6 +207,10 @@
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "Ef auglýsing spilar slökknar hún á hljóðinu og stillir spilunarhraðann á 16x",
"name": "Auglýsingahraða"
},
"adblocker": { "adblocker": {
"description": "Lokaðu fyrir allar auglýsingar og rakningar úr kassanum", "description": "Lokaðu fyrir allar auglýsingar og rakningar úr kassanum",
"menu": { "menu": {
@ -402,6 +414,21 @@
"description": "Niðurhalar MP3 / upprunahljóði beint úr viðmótinu", "description": "Niðurhalar MP3 / upprunahljóði beint úr viðmótinu",
"menu": { "menu": {
"choose-download-folder": "Veldu niðurhalsmöppu", "choose-download-folder": "Veldu niðurhalsmöppu",
"download-finish-settings": {
"label": "Sækja þegar lokið",
"prompt": {
"last-percent": "Eftir x sekúndur",
"last-seconds": "Síðustu x sekúndur",
"title": "Stilla hvenær á að hlaða niður"
},
"submenu": {
"advanced": "Ítarlegri",
"enabled": "Virkt",
"mode": "Tímastilling",
"percent": "Hlutfall",
"seconds": "Sekúndur"
}
},
"download-playlist": "Sækja spilunarlista", "download-playlist": "Sækja spilunarlista",
"presets": "Forstillingar", "presets": "Forstillingar",
"skip-existing": "Slepptu núverandi skrám" "skip-existing": "Slepptu núverandi skrám"
@ -641,6 +668,10 @@
"description": "Sleppur sjálfkrafa hlutum sem ekki eru tónlist, eins og inngangur/lok eða hlutar af tónlistarmyndböndum þar sem lag er ekki að spila", "description": "Sleppur sjálfkrafa hlutum sem ekki eru tónlist, eins og inngangur/lok eða hlutar af tónlistarmyndböndum þar sem lag er ekki að spila",
"name": "Styrktarblokk" "name": "Styrktarblokk"
}, },
"synced-lyrics": {
"description": "Veitir samstillta texta við lög, með því að nota veitur eins og LRClib.",
"name": "Samstilltur texti"
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Stjórnaðu spilun frá Windows verkefnastikunni þinni", "description": "Stjórnaðu spilun frá Windows verkefnastikunni þinni",
"name": "Miðlunarstýringarverkefnastikunnar" "name": "Miðlunarstýringarverkefnastikunnar"

View File

@ -668,6 +668,22 @@
"description": "Automatycznie pomija fragmenty niebędące muzyką, takie jak wstęp/zakończenie lub fragmenty teledysków, w których utwór nie jest odtwarzany", "description": "Automatycznie pomija fragmenty niebędące muzyką, takie jak wstęp/zakończenie lub fragmenty teledysków, w których utwór nie jest odtwarzany",
"name": "Pomiń nieistotne fragmenty" "name": "Pomiń nieistotne fragmenty"
}, },
"synced-lyrics": {
"description": "Dodaje zsynchronizowane napisy do utworów używając między innymi LRClib.",
"errors": {
"fetch": "⚠️ - Wystąpił błąd podczas pobierania tekstu utworu. Spróbuj ponownie później.",
"not-found": "⚠️ - Nie znaleziono napisów dla tego utworu."
},
"name": "Napisy zsynchronizowane",
"refetch-btn": {
"fetching": "Pobieranie napisów...",
"normal": "Odśwież napisy"
},
"warnings": {
"duration-mismatch": "⚠️ - Napisy mogą nie być zsynchronizowane z powodu różnicy w czasie trwania.",
"instrumental": "⚠️ - To jest utwór instrumentalny"
}
},
"taskbar-mediacontrol": { "taskbar-mediacontrol": {
"description": "Steruj odtwarzaniem z paska zadań systemu Windows", "description": "Steruj odtwarzaniem z paska zadań systemu Windows",
"name": "Kontroler odtwarzania z paska zadań" "name": "Kontroler odtwarzania z paska zadań"

View File

@ -11,6 +11,7 @@ import {
shell, shell,
dialog, dialog,
ipcMain, ipcMain,
type BrowserWindowConstructorOptions,
} from 'electron'; } from 'electron';
import enhanceWebRequest, { import enhanceWebRequest, {
BetterSession, BetterSession,
@ -56,7 +57,6 @@ import { loadI18n, setLanguage, t } from '@/i18n';
import ErrorHtmlAsset from '@assets/error.html?asset'; import ErrorHtmlAsset from '@assets/error.html?asset';
import type { PluginConfig } from '@/types/plugins'; import type { PluginConfig } from '@/types/plugins';
import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions;
if (!is.macOS()) { if (!is.macOS()) {
delete allPlugins['touchbar']; delete allPlugins['touchbar'];
@ -618,6 +618,7 @@ app.whenReady().then(async () => {
shortcutDetails.target !== appLocation || shortcutDetails.target !== appLocation ||
shortcutDetails.appUserModelId !== appID shortcutDetails.appUserModelId !== appID
) { ) {
// eslint-disable-next-line @typescript-eslint/only-throw-error
throw 'needUpdate'; throw 'needUpdate';
} }
} catch (error) { } catch (error) {

View File

@ -166,13 +166,13 @@ export default createPlugin<
this.profiles = {}; this.profiles = {};
this.connection.onConnections((connection) => { this.connection.onConnections((connection) => {
if (!connection) { if (!connection) {
this.api?.openToast(t('plugins.music-together.toast.disconnected')); this.api?.toastService?.show(t('plugins.music-together.toast.disconnected'));
this.onStop(); this.onStop();
return; return;
} }
if (!connection.open) { if (!connection.open) {
this.api?.openToast(t('plugins.music-together.toast.user-disconnected', { this.api?.toastService?.show(t('plugins.music-together.toast.user-disconnected', {
name: this.profiles[connection.peer]?.name name: this.profiles[connection.peer]?.name
})); }));
this.putProfile(connection.peer, undefined); this.putProfile(connection.peer, undefined);
@ -219,7 +219,7 @@ export default createPlugin<
break; break;
} }
this.api?.openToast(t('plugins.music-together.toast.user-connected', { name: event.payload.profile.name })); this.api?.toastService?.show(t('plugins.music-together.toast.user-connected', { name: event.payload.profile.name }));
this.putProfile(conn.peer, event.payload.profile); this.putProfile(conn.peer, event.payload.profile);
break; break;
} }
@ -307,7 +307,7 @@ export default createPlugin<
if (!connection) return false; if (!connection) return false;
this.connection.onConnections((connection) => { this.connection.onConnections((connection) => {
if (!connection?.open) { if (!connection?.open) {
this.api?.openToast(t('plugins.music-together.toast.disconnected')); this.api?.toastService?.show(t('plugins.music-together.toast.disconnected'));
this.onStop(); this.onStop();
} }
}); });
@ -381,7 +381,7 @@ export default createPlugin<
const permissionLabel = t(`plugins.music-together.menu.permission.${this.permission}`); const permissionLabel = t(`plugins.music-together.menu.permission.${this.permission}`);
this.api?.openToast(t('plugins.music-together.toast.permission-changed', { permission: permissionLabel })); this.api?.toastService?.show(t('plugins.music-together.toast.permission-changed', { permission: permissionLabel }));
break; break;
} }
default: { default: {
@ -593,18 +593,18 @@ export default createPlugin<
onItemClick: (id) => { onItemClick: (id) => {
if (id === 'music-together-close') { if (id === 'music-together-close') {
this.onStop(); this.onStop();
this.api?.openToast(t('plugins.music-together.toast.closed')); this.api?.toastService?.show(t('plugins.music-together.toast.closed'));
hostPopup.dismiss(); hostPopup.dismiss();
} }
if (id === 'music-together-copy-id') { if (id === 'music-together-copy-id') {
navigator.clipboard.writeText(this.connection?.id ?? '') navigator.clipboard.writeText(this.connection?.id ?? '')
.then(() => { .then(() => {
this.api?.openToast(t('plugins.music-together.toast.id-copied')); this.api?.toastService?.show(t('plugins.music-together.toast.id-copied'));
hostPopup.dismiss(); hostPopup.dismiss();
}) })
.catch(() => { .catch(() => {
this.api?.openToast(t('plugins.music-together.toast.id-copy-failed')); this.api?.toastService?.show(t('plugins.music-together.toast.id-copy-failed'));
hostPopup.dismiss(); hostPopup.dismiss();
}); });
} }
@ -620,7 +620,7 @@ export default createPlugin<
settingPopup.setPermission(this.permission); settingPopup.setPermission(this.permission);
const permissionLabel = t(`plugins.music-together.menu.permission.${this.permission}`); const permissionLabel = t(`plugins.music-together.menu.permission.${this.permission}`);
this.api?.openToast(t('plugins.music-together.toast.permission-changed', { permission: permissionLabel })); this.api?.toastService?.show(t('plugins.music-together.toast.permission-changed', { permission: permissionLabel }));
const item = hostPopup.items.find((it) => it?.element.id === id); const item = hostPopup.items.find((it) => it?.element.id === id);
if (item?.type === 'item') { if (item?.type === 'item') {
item.setText(t('plugins.music-together.menu.set-permission')); item.setText(t('plugins.music-together.menu.set-permission'));
@ -632,7 +632,7 @@ export default createPlugin<
onItemClick: (id) => { onItemClick: (id) => {
if (id === 'music-together-disconnect') { if (id === 'music-together-disconnect') {
this.onStop(); this.onStop();
this.api?.openToast(t('plugins.music-together.toast.disconnected')); this.api?.toastService?.show(t('plugins.music-together.toast.disconnected'));
guestPopup.dismiss(); guestPopup.dismiss();
} }
} }
@ -648,14 +648,14 @@ export default createPlugin<
if (result) { if (result) {
navigator.clipboard.writeText(this.connection?.id ?? '') navigator.clipboard.writeText(this.connection?.id ?? '')
.then(() => { .then(() => {
this.api?.openToast(t('plugins.music-together.toast.id-copied')); this.api?.toastService?.show(t('plugins.music-together.toast.id-copied'));
hostPopup.showAtAnchor(setting); hostPopup.showAtAnchor(setting);
}).catch(() => { }).catch(() => {
this.api?.openToast(t('plugins.music-together.toast.id-copy-failed')); this.api?.toastService?.show(t('plugins.music-together.toast.id-copy-failed'));
hostPopup.showAtAnchor(setting); hostPopup.showAtAnchor(setting);
}); });
} else { } else {
this.api?.openToast(t('plugins.music-together.toast.host-failed')); this.api?.toastService?.show(t('plugins.music-together.toast.host-failed'));
} }
} }
@ -666,10 +666,10 @@ export default createPlugin<
this.hideSpinner(); this.hideSpinner();
if (result) { if (result) {
this.api?.openToast(t('plugins.music-together.toast.joined')); this.api?.toastService?.show(t('plugins.music-together.toast.joined'));
guestPopup.showAtAnchor(setting); guestPopup.showAtAnchor(setting);
} else { } else {
this.api?.openToast(t('plugins.music-together.toast.join-failed')); this.api?.toastService?.show(t('plugins.music-together.toast.join-failed'));
} }
} }
} }

View File

@ -2,7 +2,7 @@ import { singleton } from './decorators';
import type { YoutubePlayer } from '@/types/youtube-player'; import type { YoutubePlayer } from '@/types/youtube-player';
import type { GetState } from '@/types/datahost-get-state'; import type { GetState } from '@/types/datahost-get-state';
import type { AlbumDetails, VideoDataChangeValue } from '@/types/player-api-events'; import type { AlbumDetails, PlayerOverlays, VideoDataChangeValue } from '@/types/player-api-events';
import type { SongInfo } from './song-info'; import type { SongInfo } from './song-info';
import type { VideoDataChanged } from '@/types/video-data-changed'; import type { VideoDataChanged } from '@/types/video-data-changed';
@ -208,28 +208,35 @@ export default (api: YoutubePlayer) => {
list: playlistId list: playlistId
} = api.getVideoData(); } = api.getVideoData();
const { playerOverlays } = api.getWatchNextResponse(); const watchNextResponse = api.getWatchNextResponse();
sendSongInfo(<VideoDataChangeValue>{ sendSongInfo({
title, author, videoId, playlistId, title, author, videoId, playlistId,
isUpcoming: false, isUpcoming: false,
lengthSeconds: video.duration, lengthSeconds: video.duration,
loading: true, loading: true,
uhhh: { playerOverlays } ytmdWatchNextResponse: watchNextResponse,
}); } satisfies VideoDataChangeValue);
} }
} }
function sendSongInfo(videoData: VideoDataChangeValue) { function sendSongInfo(videoData: VideoDataChangeValue) {
const data = api.getPlayerResponse(); const data = api.getPlayerResponse();
data.videoDetails.album = ( let playerOverlay: PlayerOverlays | undefined;
Object.entries(videoData).find(
([, value]) => value && Object.hasOwn(value, 'playerOverlays'), if (!videoData.ytmdWatchNextResponse) {
) as [string, AlbumDetails | undefined] playerOverlay = (
)?.[1]?.playerOverlays?.playerOverlayRenderer?.browserMediaSession?.browserMediaSessionRenderer?.album?.runs?.at( Object.entries(videoData).find(
([, value]) => value && Object.hasOwn(value, 'playerOverlays'),
) as [string, AlbumDetails | undefined]
)?.[1]?.playerOverlays;
} else {
playerOverlay = videoData.ytmdWatchNextResponse?.playerOverlays;
}
data.videoDetails.album = playerOverlay?.playerOverlayRenderer?.browserMediaSession?.browserMediaSessionRenderer?.album?.runs?.at(
0, 0,
)?.text; )?.text;
data.videoDetails.elapsedSeconds = 0; data.videoDetails.elapsedSeconds = 0;

View File

@ -23,6 +23,14 @@ let isPluginLoaded = false;
let isApiLoaded = false; let isApiLoaded = false;
let firstDataLoaded = false; let firstDataLoaded = false;
if (window.trustedTypes && window.trustedTypes.createPolicy && !window.trustedTypes.defaultPolicy) {
window.trustedTypes.createPolicy('default', {
createHTML: (input) => input,
createScriptURL: (input) => input,
createScript: (input) => input,
});
}
async function listenForApiLoad() { async function listenForApiLoad() {
if (!isApiLoaded) { if (!isApiLoaded) {
api = document.querySelector('#movie_player'); api = document.querySelector('#movie_player');

2
src/reset.d.ts vendored
View File

@ -6,6 +6,7 @@ import type is from 'electron-is';
import type config from './config'; import type config from './config';
import type { VideoDataChanged } from '@/types/video-data-changed'; import type { VideoDataChanged } from '@/types/video-data-changed';
import type { t } from '@/i18n'; import type { t } from '@/i18n';
import type { trustedTypes } from 'trusted-types';
declare global { declare global {
interface Compressor { interface Compressor {
@ -19,6 +20,7 @@ declare global {
} }
interface Window { interface Window {
trustedTypes?: typeof trustedTypes;
ipcRenderer: typeof electronIpcRenderer; ipcRenderer: typeof electronIpcRenderer;
mainConfig: typeof config; mainConfig: typeof config;
electronIs: typeof is; electronIs: typeof is;

View File

@ -1,3 +1,5 @@
import type { WatchNextResponse } from '@/types/youtube-music-desktop-internal';
export interface AlbumDetails { export interface AlbumDetails {
responseContext: ResponseContext; responseContext: ResponseContext;
contents: Contents; contents: Contents;
@ -252,6 +254,11 @@ export type VideoDataChangeValue = Record<string, unknown> & {
loading: boolean; loading: boolean;
lengthSeconds: number; lengthSeconds: number;
/**
* YouTube Music Desktop internal variable (for album data)
**/
ytmdWatchNextResponse?: WatchNextResponse;
}; };
export interface PlayerAPIEvents { export interface PlayerAPIEvents {

View File

@ -30,11 +30,39 @@ export type QueueAPI = {
continuation?: string; continuation?: string;
autoPlaying?: boolean; autoPlaying?: boolean;
}; };
export type ToastElement = HTMLElement & {
autoFitOnAttach: boolean;
duration: number;
expandSizingTargetForScrollbars: boolean;
horizontalAlign: 'left' | 'right' | 'center';
importPath?: unknown;
label: string;
noAutoFocus: boolean;
noCancelOnEscKey: boolean;
noCancelOnOutsideClick: boolean;
noIronAnnounce: boolean;
restoreFocusOnClose: boolean;
root: ToastElement;
rootPath: string;
sizingTarget: ToastElement;
verticalAlign: 'bottom' | 'top' | 'center';
};
export interface ToastService {
attached: boolean;
displaying: boolean;
messageQueue: string[];
toastElement: ToastElement;
show: (message: string) => void;
}
export type AppElement = HTMLElement & AppAPI; export type AppElement = HTMLElement & AppAPI;
export type AppAPI = { export type AppAPI = {
queue_: QueueAPI; queue: QueueAPI;
playerApi_: YoutubePlayer; playerApi: YoutubePlayer;
openToast: (message: string) => void;
toastService: ToastService;
// TODO: Add more // TODO: Add more
}; };

View File

@ -1,4 +1,5 @@
import type { QueueItem } from '@/types/datahost-get-state'; import type { QueueItem } from '@/types/datahost-get-state';
import type { PlayerOverlays } from '@/types/player-api-events';
export interface QueueResponse { export interface QueueResponse {
items?: QueueItem[]; items?: QueueItem[];
@ -7,15 +8,5 @@ export interface QueueResponse {
} }
export interface WatchNextResponse { export interface WatchNextResponse {
playerOverlays: { playerOverlays?: PlayerOverlays;
playerOverlayRenderer: {
browserMediaSession: {
browserMediaSessionRenderer: {
album: {
runs: { text: string; }[]
}
}
}
}
};
} }