Compare commits

...

20 Commits

Author SHA1 Message Date
a33a03f512 Bump version to 3.7.1 2024-12-27 01:44:11 +09:00
f8a53f0d61 fix(api-server): fix swagger 2024-12-27 01:43:03 +09:00
748d77d1c0 fix(downloader): fix #2234 2024-12-27 01:30:09 +09:00
725ad0d630 fix(deps): update dependency node-html-parser to v7 (#2776)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-27 01:15:58 +09:00
bdbab17772 chore(deps): update dependency vite to v6.0.6 (#2774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-27 01:15:18 +09:00
57d2fa372d fix(synced-lyrics): use blur instead of static background color 2024-12-27 01:13:53 +09:00
80471b0ca4 fix: use networkManager.fetch instead of fetch 2024-12-27 01:05:55 +09:00
22fdfe3342 fix(downloader): fix #2769 2024-12-27 00:50:18 +09:00
5ecfa2a1f7 fix: fix #2645, fix #2741 2024-12-26 23:49:19 +09:00
b9beea810e fix(music-together): fix crash 2024-12-26 23:14:42 +09:00
f0e77812e7 fix: fix login CORS issue 2024-12-26 23:13:28 +09:00
6d1237c2a2 chore(i18n): Translated using Weblate (Hindi)
Currently translated at 29.8% (121 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/hi/
2024-12-26 06:04:43 +00:00
b43c92386e chore(i18n): Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pt_BR/
2024-12-26 06:04:42 +00:00
017476a81b chore(i18n): Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/zh_Hant/
2024-12-26 06:04:41 +00:00
9b047d9c54 chore(i18n): Translated using Weblate (Russian)
Currently translated at 100.0% (406 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/ru/
2024-12-26 06:04:40 +00:00
31f009d3c4 chore(i18n): Translated using Weblate (Polish)
Currently translated at 98.7% (401 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-12-26 06:04:40 +00:00
8504f2c086 chore(i18n): Translated using Weblate (Italian)
Currently translated at 99.2% (403 of 406 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/it/
2024-12-26 06:04:39 +00:00
1d6251baea feat(api-server): Add queue api (#2767) 2024-12-25 18:55:24 +09:00
3ea13a2a22 fix(api-server): repeat event listener 2024-12-25 13:08:02 +09:00
1cc153084d Update changelog for v3.7.0 2024-12-25 01:45:32 +00:00
26 changed files with 758 additions and 357 deletions

View File

@ -2,8 +2,166 @@
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.7.0](https://github.com/th-ch/youtube-music/compare/v3.6.2...v3.7.0)
- feat(amuse): song query api (add amuse plugin) [`#2723`](https://github.com/th-ch/youtube-music/pull/2723)
- feat(api-server): add absolute seek endpoint [`#2748`](https://github.com/th-ch/youtube-music/pull/2748)
- feat(api-server): Add repeat mode and seek time API [`#2630`](https://github.com/th-ch/youtube-music/pull/2630)
- feat(synced-lyrics): Better-Lyrics Styling for Synced-Lyrics [`#2554`](https://github.com/th-ch/youtube-music/pull/2554)
- feat(synced-lyrics): multiple lyric sources [`#2383`](https://github.com/th-ch/youtube-music/pull/2383)
- chore(deps): update dependency typescript-eslint to v8.18.2 [`#2763`](https://github.com/th-ch/youtube-music/pull/2763)
- chore(deps): update dependency discord-api-types to v0.37.114 [`#2761`](https://github.com/th-ch/youtube-music/pull/2761)
- chore(deps): update dependency discord-api-types to v0.37.113 [`#2759`](https://github.com/th-ch/youtube-music/pull/2759)
- fix: Set correct window class for X11 and Wayland [`#2758`](https://github.com/th-ch/youtube-music/pull/2758)
- feat: Specify flatpak runtime [`#2755`](https://github.com/th-ch/youtube-music/pull/2755)
- chore(deps): update dependency rollup to v4.29.1 [`#2749`](https://github.com/th-ch/youtube-music/pull/2749)
- chore(deps): update dependency esbuild to v0.24.2 [`#2742`](https://github.com/th-ch/youtube-music/pull/2742)
- fix: Add Flatpak permissions needed for MPRIS and tray icon [`#2754`](https://github.com/th-ch/youtube-music/pull/2754)
- chore(deps): update dependency vite-plugin-inspect to v0.10.6 [`#2756`](https://github.com/th-ch/youtube-music/pull/2756)
- chore(deps): update dependency vite to v6.0.5 [`#2745`](https://github.com/th-ch/youtube-music/pull/2745)
- fix(deps): update dependency i18next to v24.2.0 [`#2744`](https://github.com/th-ch/youtube-music/pull/2744)
- chore(deps): update dependency vite-plugin-inspect to v0.10.4 [`#2743`](https://github.com/th-ch/youtube-music/pull/2743)
- chore(deps): update dependency discord-api-types to v0.37.112 [`#2740`](https://github.com/th-ch/youtube-music/pull/2740)
- fix(discord): Fix Album Art failing on Discord RPC [`#2666`](https://github.com/th-ch/youtube-music/pull/2666)
- feat: Add equalizer plugin with presets (e.g. bass booster) [`#2575`](https://github.com/th-ch/youtube-music/pull/2575)
- chore(deps): update dependency vite to v6.0.4 [`#2738`](https://github.com/th-ch/youtube-music/pull/2738)
- fix: Fixed #1796 [`#2736`](https://github.com/th-ch/youtube-music/pull/2736)
- chore(deps): update dependency electron-devtools-installer to v4 [`#2734`](https://github.com/th-ch/youtube-music/pull/2734)
- Revert "chore(deps): update dependency electron-builder to v25" [`#2732`](https://github.com/th-ch/youtube-music/pull/2732)
- chore(deps): update dependency electron-builder to v25 [`#2490`](https://github.com/th-ch/youtube-music/pull/2490)
- fix(deps): update dependency i18next to v24.1.2 [`#2727`](https://github.com/th-ch/youtube-music/pull/2727)
- chore(deps): update dependency electron-devtools-installer to v3.2.1 [`#2731`](https://github.com/th-ch/youtube-music/pull/2731)
- chore(deps): update dependency typescript-eslint to v8.18.1 [`#2724`](https://github.com/th-ch/youtube-music/pull/2724)
- fix: tab misalignment [`#2713`](https://github.com/th-ch/youtube-music/pull/2713)
- fix(deps): update dependency @hono/zod-validator to v0.4.2 [`#2709`](https://github.com/th-ch/youtube-music/pull/2709)
- chore(deps): update eslint monorepo to v9.17.0 [`#2712`](https://github.com/th-ch/youtube-music/pull/2712)
- fix(deps): update dependency hono to v4.6.14 [`#2716`](https://github.com/th-ch/youtube-music/pull/2716)
- fix: discord rich presence connection status [`#2714`](https://github.com/th-ch/youtube-music/pull/2714)
- fix: Laggy scrolling behaviour in large playlists [`#2708`](https://github.com/th-ch/youtube-music/pull/2708)
- fix(deps): update dependency youtubei.js to v12.2.0 [`#2705`](https://github.com/th-ch/youtube-music/pull/2705)
- fix(deps): update dependency i18next to v24.1.0 [`#2698`](https://github.com/th-ch/youtube-music/pull/2698)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.1 [`#2697`](https://github.com/th-ch/youtube-music/pull/2697)
- fix(deps): update dependency zod to v3.24.1 [`#2694`](https://github.com/th-ch/youtube-music/pull/2694)
- fix(deps): update dependency youtubei.js to v12.1.0 [`#2695`](https://github.com/th-ch/youtube-music/pull/2695)
- chore(deps): update dependency discord-api-types to v0.37.111 [`#2690`](https://github.com/th-ch/youtube-music/pull/2690)
- chore(deps): update dependency typescript-eslint to v8.18.0 [`#2692`](https://github.com/th-ch/youtube-music/pull/2692)
- chore(deps): update playwright monorepo to v1.49.1 [`#2693`](https://github.com/th-ch/youtube-music/pull/2693)
- fix(deps): update dependency hono to v4.6.13 [`#2682`](https://github.com/th-ch/youtube-music/pull/2682)
- chore(deps): update dependency rollup to v4.28.1 [`#2683`](https://github.com/th-ch/youtube-music/pull/2683)
- fix(deps): update dependency conf to v13.1.0 [`#2686`](https://github.com/th-ch/youtube-music/pull/2686)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.12.0 [`#2689`](https://github.com/th-ch/youtube-music/pull/2689)
- fix(deps): update dependency youtubei.js to v12 [`#2681`](https://github.com/th-ch/youtube-music/pull/2681)
- chore(deps): update dependency vite to v6.0.3 [`#2680`](https://github.com/th-ch/youtube-music/pull/2680)
- fix(album-actions): Fixed #2312 [`#2676`](https://github.com/th-ch/youtube-music/pull/2676)
- chore(deps): update dependency eslint-import-resolver-typescript to v3.7.0 [`#2672`](https://github.com/th-ch/youtube-music/pull/2672)
- chore(deps): update dependency node-gyp to v11 [`#2678`](https://github.com/th-ch/youtube-music/pull/2678)
- fix(deps): update dependency i18next to v24.0.5 [`#2669`](https://github.com/th-ch/youtube-music/pull/2669)
- fix(deps): update dependency i18next to v24.0.4 [`#2668`](https://github.com/th-ch/youtube-music/pull/2668)
- chore(deps): update dependency vite to v6.0.2 [`#2662`](https://github.com/th-ch/youtube-music/pull/2662)
- chore(deps): update dependency node-gyp to v10.3.1 [`#2665`](https://github.com/th-ch/youtube-music/pull/2665)
- chore(deps): update dependency typescript-eslint to v8.17.0 [`#2664`](https://github.com/th-ch/youtube-music/pull/2664)
- chore(deps): update dependency vite-plugin-inspect to v0.10.3 [`#2667`](https://github.com/th-ch/youtube-music/pull/2667)
- chore(deps): update dependency rollup to v4.28.0 [`#2661`](https://github.com/th-ch/youtube-music/pull/2661)
- chore(deps): update dependency discord-api-types to v0.37.110 [`#2653`](https://github.com/th-ch/youtube-music/pull/2653)
- fix(deps): update dependency @hono/zod-openapi to v0.18.3 [`#2654`](https://github.com/th-ch/youtube-music/pull/2654)
- chore(deps): update eslint monorepo to v9.16.0 [`#2656`](https://github.com/th-ch/youtube-music/pull/2656)
- chore(deps): update dependency vite-plugin-inspect to v0.10.2 [`#2657`](https://github.com/th-ch/youtube-music/pull/2657)
- fix(youtube-music.css): Fixed #2514 [`#2659`](https://github.com/th-ch/youtube-music/pull/2659)
- fix: Fixed Skip Disliked Song not working [`#2651`](https://github.com/th-ch/youtube-music/pull/2651)
- fix(deps): update dependency @hono/zod-openapi to v0.18.2 [`#2650`](https://github.com/th-ch/youtube-music/pull/2650)
- chore(deps): update dependency vite-plugin-inspect to v0.10.1 [`#2652`](https://github.com/th-ch/youtube-music/pull/2652)
- chore(deps): update dependency electron to v33.2.1 [`#2649`](https://github.com/th-ch/youtube-music/pull/2649)
- chore(deps): update dependency vite-plugin-inspect to v0.10.0 [`#2646`](https://github.com/th-ch/youtube-music/pull/2646)
- chore(deps): update dependency vite to v6 [`#2644`](https://github.com/th-ch/youtube-music/pull/2644)
- fix(deps): update dependency @hono/swagger-ui to v0.5.0 [`#2643`](https://github.com/th-ch/youtube-music/pull/2643)
- chore(deps): update dependency discord-api-types to v0.37.109 [`#2642`](https://github.com/th-ch/youtube-music/pull/2642)
- chore(deps): update dependency vite-plugin-solid to v2.11.0 [`#2641`](https://github.com/th-ch/youtube-music/pull/2641)
- fix(deps): update dependency hono to v4.6.12 [`#2636`](https://github.com/th-ch/youtube-music/pull/2636)
- fix(deps): update dependency i18next to v24.0.2 [`#2637`](https://github.com/th-ch/youtube-music/pull/2637)
- chore(deps): update dependency discord-api-types to v0.37.108 [`#2638`](https://github.com/th-ch/youtube-music/pull/2638)
- chore(deps): update dependency typescript-eslint to v8.16.0 [`#2639`](https://github.com/th-ch/youtube-music/pull/2639)
- chore(deps): update dependency rollup to v4.27.4 [`#2632`](https://github.com/th-ch/youtube-music/pull/2632)
- fix(deps): update dependency i18next to v24 [`#2633`](https://github.com/th-ch/youtube-music/pull/2633)
- chore(deps): update dependency typescript to v5.7.2 [`#2629`](https://github.com/th-ch/youtube-music/pull/2629)
- chore(deps): update dependency discord-api-types to v0.37.107 [`#2627`](https://github.com/th-ch/youtube-music/pull/2627)
- fix(deps): update dependency @hono/zod-openapi to v0.18.0 [`#2626`](https://github.com/th-ch/youtube-music/pull/2626)
- fix(deps): update dependency i18next to v23.16.8 [`#2625`](https://github.com/th-ch/youtube-music/pull/2625)
- chore(deps): update dependency vite-plugin-inspect to v0.8.8 [`#2623`](https://github.com/th-ch/youtube-music/pull/2623)
- fix(deps): update dependency hono to v4.6.11 [`#2624`](https://github.com/th-ch/youtube-music/pull/2624)
- chore(deps): update playwright monorepo to v1.49.0 [`#2617`](https://github.com/th-ch/youtube-music/pull/2617)
- chore(deps): update dependency rollup to v4.27.3 [`#2610`](https://github.com/th-ch/youtube-music/pull/2610)
- chore(deps): update dependency typescript-eslint to v8.15.0 [`#2611`](https://github.com/th-ch/youtube-music/pull/2611)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.11.0 [`#2618`](https://github.com/th-ch/youtube-music/pull/2618)
- chore(deps): update dependency discord-api-types to v0.37.105 [`#2603`](https://github.com/th-ch/youtube-music/pull/2603)
- chore(deps): update dependency rollup to v4.27.2 [`#2604`](https://github.com/th-ch/youtube-music/pull/2604)
- chore(deps): update eslint monorepo to v9.15.0 [`#2607`](https://github.com/th-ch/youtube-music/pull/2607)
- fix(deps): update dependency @hono/zod-openapi to v0.17.1 [`#2608`](https://github.com/th-ch/youtube-music/pull/2608)
- fix(ambient-mode): fix ambient-mode overlapping other elements [`#2609`](https://github.com/th-ch/youtube-music/pull/2609)
- fix: Allow media playback control (MPRIS) for flatpak [`#2606`](https://github.com/th-ch/youtube-music/pull/2606)
- fix(deps): update dependency @hono/node-server to v1.13.7 [`#2598`](https://github.com/th-ch/youtube-music/pull/2598)
- chore(deps): update dependency rollup to v4.26.0 [`#2600`](https://github.com/th-ch/youtube-music/pull/2600)
- fix(deps): update dependency hono to v4.6.10 [`#2601`](https://github.com/th-ch/youtube-music/pull/2601)
- fix(deps): update dependency @hono/node-server to v1.13.6 [`#2594`](https://github.com/th-ch/youtube-music/pull/2594)
- chore(deps): update dependency vite to v5.4.11 [`#2595`](https://github.com/th-ch/youtube-music/pull/2595)
- chore(deps): update dependency typescript-eslint to v8.14.0 [`#2596`](https://github.com/th-ch/youtube-music/pull/2596)
- chore(deps): update dependency electron to v33.2.0 [`#2591`](https://github.com/th-ch/youtube-music/pull/2591)
- fix(deps): update dependency @hono/zod-openapi to v0.17.0 [`#2592`](https://github.com/th-ch/youtube-music/pull/2592)
- fix(deps): update dependency i18next to v23.16.5 [`#2589`](https://github.com/th-ch/youtube-music/pull/2589)
- fix(deps): update dependency @hono/node-server to v1.13.5 [`#2578`](https://github.com/th-ch/youtube-music/pull/2578)
- fix(deps): update dependency hono to v4.6.9 [`#2579`](https://github.com/th-ch/youtube-music/pull/2579)
- chore(deps): update dependency discord-api-types to v0.37.104 [`#2588`](https://github.com/th-ch/youtube-music/pull/2588)
- chore(deps): update dependency typescript-eslint to v8.13.0 [`#2581`](https://github.com/th-ch/youtube-music/pull/2581)
- chore(deps): update dependency rollup to v4.25.0 [`#2580`](https://github.com/th-ch/youtube-music/pull/2580)
- chore(docs): Update screenshot [`#2587`](https://github.com/th-ch/youtube-music/pull/2587)
- chore(docs): Specify full path to xattr for macOS, fixes #2583 [`#2586`](https://github.com/th-ch/youtube-music/pull/2586)
- fix: callback for time-changed event [`#2577`](https://github.com/th-ch/youtube-music/pull/2577)
- chore(deps): update eslint monorepo to v9.14.0 [`#2573`](https://github.com/th-ch/youtube-music/pull/2573)
- chore(deps): update dependency utf-8-validate to v6.0.5 [`#2572`](https://github.com/th-ch/youtube-music/pull/2572)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.1 [`#2571`](https://github.com/th-ch/youtube-music/pull/2571)
- fix(deps): update dependency @hono/node-server to v1.13.4 [`#2570`](https://github.com/th-ch/youtube-music/pull/2570)
- chore(deps): update dependency @stylistic/eslint-plugin-js to v2.10.0 [`#2569`](https://github.com/th-ch/youtube-music/pull/2569)
- fix(deps): update dependency @floating-ui/dom to v1.6.12 [`#2568`](https://github.com/th-ch/youtube-music/pull/2568)
- chore(deps): update dependency rollup to v4.24.3 [`#2565`](https://github.com/th-ch/youtube-music/pull/2565)
- fix(deps): update dependency hono to v4.6.8 [`#2564`](https://github.com/th-ch/youtube-music/pull/2564)
- chore(deps): update dependency typescript-eslint to v8.12.2 [`#2563`](https://github.com/th-ch/youtube-music/pull/2563)
- chore(deps): update dependency typescript-eslint to v8.12.0 [`#2561`](https://github.com/th-ch/youtube-music/pull/2561)
- fix(deps): update dependency youtubei.js to v11 [`#2562`](https://github.com/th-ch/youtube-music/pull/2562)
- chore(deps): update dependency rollup to v4.24.2 [`#2559`](https://github.com/th-ch/youtube-music/pull/2559)
- fix(deps): update dependency @hono/node-server to v1.13.3 [`#2560`](https://github.com/th-ch/youtube-music/pull/2560)
- fix(deps): update dependency i18next to v23.16.4 [`#2550`](https://github.com/th-ch/youtube-music/pull/2550)
- chore(deps): update playwright monorepo to v1.48.2 [`#2551`](https://github.com/th-ch/youtube-music/pull/2551)
- fix(deps): update dependency hono to v4.6.7 [`#2552`](https://github.com/th-ch/youtube-music/pull/2552)
- chore(deps): update dependency @babel/runtime to v7.26.0 [`#2548`](https://github.com/th-ch/youtube-music/pull/2548)
- chore(deps): update dependency @types/color to v4 [`#2547`](https://github.com/th-ch/youtube-music/pull/2547)
- fix(deps): update dependency i18next to v23.16.3 [`#2545`](https://github.com/th-ch/youtube-music/pull/2545)
- fix(deps): update dependency solid-js to v1.9.3 [`#2541`](https://github.com/th-ch/youtube-music/pull/2541)
- chore(deps): update dependency vite to v5.4.10 [`#2542`](https://github.com/th-ch/youtube-music/pull/2542)
- chore(deps): update dependency electron to v33.0.2 [`#2537`](https://github.com/th-ch/youtube-music/pull/2537)
- chore(deps): update dependency @babel/runtime to v7.25.9 [`#2538`](https://github.com/th-ch/youtube-music/pull/2538)
- chore(deps): update dependency discord-api-types to v0.37.103 [`#2532`](https://github.com/th-ch/youtube-music/pull/2532)
- chore(deps): update dependency typescript-eslint to v8.11.0 [`#2534`](https://github.com/th-ch/youtube-music/pull/2534)
- fix(deps): update dependency hono to v4.6.6 [`#2536`](https://github.com/th-ch/youtube-music/pull/2536)
- fix(tuna-obs): Added song url to tuna-obs plugin [`#2524`](https://github.com/th-ch/youtube-music/pull/2524)
- fix(deps): update dependency i18next to v23.16.2 [`#2530`](https://github.com/th-ch/youtube-music/pull/2530)
- fix(deps): update dependency i18next to v23.16.1 [`#2529`](https://github.com/th-ch/youtube-music/pull/2529)
- chore(deps): update eslint monorepo to v9.13.0 [`#2528`](https://github.com/th-ch/youtube-music/pull/2528)
- chore(deps): update dependency typescript-eslint to v8.10.0 [`#2527`](https://github.com/th-ch/youtube-music/pull/2527)
- chore(deps): update playwright monorepo to v1.48.1 [`#2516`](https://github.com/th-ch/youtube-music/pull/2516)
- chore(deps): update dependency electron to v33.0.1 [`#2523`](https://github.com/th-ch/youtube-music/pull/2523)
- fix: disable gpu memory buffer video frames [`#2519`](https://github.com/th-ch/youtube-music/pull/2519)
- fix: use HEAD instead of GET in songInfo.imageSrc validation step [`#2766`](https://github.com/th-ch/youtube-music/issues/2766)
- fix: Fixed #1796 (#2736) [`#1796`](https://github.com/th-ch/youtube-music/issues/1796)
- fix(album-actions): Fixed #2312 (#2676) [`#2312`](https://github.com/th-ch/youtube-music/issues/2312) [`#2312`](https://github.com/th-ch/youtube-music/issues/2312)
- fix(youtube-music.css): Fixed #2514 (#2659) [`#2514`](https://github.com/th-ch/youtube-music/issues/2514)
- chore(docs): Specify full path to xattr for macOS, fixes #2583 (#2586) [`#2583`](https://github.com/th-ch/youtube-music/issues/2583)
- fix: fix pnpm-lock.yaml [`3208bf4`](https://github.com/th-ch/youtube-music/commit/3208bf4a6d47d824875b06bd031299694482f02d)
- Revert "feat: use swc and lightningcss" [`3b50cbc`](https://github.com/th-ch/youtube-music/commit/3b50cbcb6e3163115d52f05075af5d6f25b80660)
- feat: use swc and lightningcss [`ae3a289`](https://github.com/th-ch/youtube-music/commit/ae3a28900576ea388666747bc4794577e1d57e23)
#### [v3.6.2](https://github.com/th-ch/youtube-music/compare/v3.6.1...v3.6.2) #### [v3.6.2](https://github.com/th-ch/youtube-music/compare/v3.6.1...v3.6.2)
> 16 October 2024
- fix(deps): update dependency serve to v14.2.4 [`#2515`](https://github.com/th-ch/youtube-music/pull/2515) - fix(deps): update dependency serve to v14.2.4 [`#2515`](https://github.com/th-ch/youtube-music/pull/2515)
- fix(deps): update dependency hono to v4.6.5 [`#2509`](https://github.com/th-ch/youtube-music/pull/2509) - fix(deps): update dependency hono to v4.6.5 [`#2509`](https://github.com/th-ch/youtube-music/pull/2509)
- chore(deps): update dependency vite to v5.4.9 [`#2500`](https://github.com/th-ch/youtube-music/pull/2500) - chore(deps): update dependency vite to v5.4.9 [`#2500`](https://github.com/th-ch/youtube-music/pull/2500)

View File

@ -2,7 +2,7 @@
"name": "youtube-music", "name": "youtube-music",
"desktopName": "com.github.th_ch.youtube_music", "desktopName": "com.github.th_ch.youtube_music",
"productName": "YouTube Music", "productName": "YouTube Music",
"version": "3.7.0", "version": "3.7.1",
"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",
@ -275,7 +275,7 @@
"jimp": "1.6.0", "jimp": "1.6.0",
"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": "7.0.1",
"node-id3": "0.2.6", "node-id3": "0.2.6",
"peerjs": "1.5.4", "peerjs": "1.5.4",
"semver": "7.6.3", "semver": "7.6.3",
@ -326,7 +326,7 @@
"typescript": "5.7.2", "typescript": "5.7.2",
"typescript-eslint": "8.18.2", "typescript-eslint": "8.18.2",
"utf-8-validate": "6.0.5", "utf-8-validate": "6.0.5",
"vite": "6.0.5", "vite": "6.0.6",
"vite-plugin-inspect": "0.10.6", "vite-plugin-inspect": "0.10.6",
"vite-plugin-resolve": "2.5.2", "vite-plugin-resolve": "2.5.2",
"vite-plugin-solid": "2.11.0", "vite-plugin-solid": "2.11.0",

294
pnpm-lock.yaml generated
View File

@ -151,8 +151,8 @@ importers:
specifier: 0.2.2 specifier: 0.2.2
version: 0.2.2 version: 0.2.2
node-html-parser: node-html-parser:
specifier: 6.1.13 specifier: 7.0.1
version: 6.1.13 version: 7.0.1
node-id3: node-id3:
specifier: 0.2.6 specifier: 0.2.6
version: 0.2.6 version: 0.2.6
@ -255,7 +255,7 @@ importers:
version: 4.0.0 version: 4.0.0
electron-vite: electron-vite:
specifier: 2.3.0 specifier: 2.3.0
version: 2.3.0(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)) version: 2.3.0(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1))
esbuild: esbuild:
specifier: 0.24.2 specifier: 0.24.2
version: 0.24.2 version: 0.24.2
@ -299,17 +299,17 @@ importers:
specifier: 6.0.5 specifier: 6.0.5
version: 6.0.5 version: 6.0.5
vite: vite:
specifier: 6.0.5 specifier: 6.0.6
version: 6.0.5(@types/node@22.9.3)(yaml@2.6.1) version: 6.0.6(@types/node@22.9.3)(yaml@2.6.1)
vite-plugin-inspect: vite-plugin-inspect:
specifier: 0.10.6 specifier: 0.10.6
version: 0.10.6(rollup@4.29.1)(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)) version: 0.10.6(rollup@4.29.1)(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1))
vite-plugin-resolve: vite-plugin-resolve:
specifier: 2.5.2 specifier: 2.5.2
version: 2.5.2 version: 2.5.2
vite-plugin-solid: vite-plugin-solid:
specifier: 2.11.0 specifier: 2.11.0
version: 2.11.0(solid-js@1.9.3)(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)) version: 2.11.0(solid-js@1.9.3)(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1))
ws: ws:
specifier: 8.18.0 specifier: 8.18.0
version: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5) version: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.5)
@ -478,12 +478,6 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [aix] os: [aix]
'@esbuild/aix-ppc64@0.24.0':
resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/aix-ppc64@0.24.2': '@esbuild/aix-ppc64@0.24.2':
resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -496,12 +490,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@esbuild/android-arm64@0.24.0':
resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.24.2': '@esbuild/android-arm64@0.24.2':
resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -514,12 +502,6 @@ packages:
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@esbuild/android-arm@0.24.0':
resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.24.2': '@esbuild/android-arm@0.24.2':
resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -532,12 +514,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [android] os: [android]
'@esbuild/android-x64@0.24.0':
resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.24.2': '@esbuild/android-x64@0.24.2':
resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -550,12 +526,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@esbuild/darwin-arm64@0.24.0':
resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.24.2': '@esbuild/darwin-arm64@0.24.2':
resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -568,12 +538,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@esbuild/darwin-x64@0.24.0':
resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.24.2': '@esbuild/darwin-x64@0.24.2':
resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -586,12 +550,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-arm64@0.24.0':
resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.24.2': '@esbuild/freebsd-arm64@0.24.2':
resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -604,12 +562,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@esbuild/freebsd-x64@0.24.0':
resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.24.2': '@esbuild/freebsd-x64@0.24.2':
resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -622,12 +574,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@esbuild/linux-arm64@0.24.0':
resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.24.2': '@esbuild/linux-arm64@0.24.2':
resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -640,12 +586,6 @@ packages:
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@esbuild/linux-arm@0.24.0':
resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.24.2': '@esbuild/linux-arm@0.24.2':
resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -658,12 +598,6 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
'@esbuild/linux-ia32@0.24.0':
resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.24.2': '@esbuild/linux-ia32@0.24.2':
resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -676,12 +610,6 @@ packages:
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
'@esbuild/linux-loong64@0.24.0':
resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.24.2': '@esbuild/linux-loong64@0.24.2':
resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -694,12 +622,6 @@ packages:
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
'@esbuild/linux-mips64el@0.24.0':
resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.24.2': '@esbuild/linux-mips64el@0.24.2':
resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -712,12 +634,6 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@esbuild/linux-ppc64@0.24.0':
resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.24.2': '@esbuild/linux-ppc64@0.24.2':
resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -730,12 +646,6 @@ packages:
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@esbuild/linux-riscv64@0.24.0':
resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.24.2': '@esbuild/linux-riscv64@0.24.2':
resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -748,12 +658,6 @@ packages:
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@esbuild/linux-s390x@0.24.0':
resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.24.2': '@esbuild/linux-s390x@0.24.2':
resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -766,12 +670,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@esbuild/linux-x64@0.24.0':
resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.24.2': '@esbuild/linux-x64@0.24.2':
resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -790,24 +688,12 @@ packages:
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/netbsd-x64@0.24.0':
resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.24.2': '@esbuild/netbsd-x64@0.24.2':
resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==}
engines: {node: '>=18'} engines: {node: '>=18'}
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
'@esbuild/openbsd-arm64@0.24.0':
resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-arm64@0.24.2': '@esbuild/openbsd-arm64@0.24.2':
resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -820,12 +706,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
'@esbuild/openbsd-x64@0.24.0':
resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.24.2': '@esbuild/openbsd-x64@0.24.2':
resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -838,12 +718,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
'@esbuild/sunos-x64@0.24.0':
resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.24.2': '@esbuild/sunos-x64@0.24.2':
resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -856,12 +730,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@esbuild/win32-arm64@0.24.0':
resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.24.2': '@esbuild/win32-arm64@0.24.2':
resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -874,12 +742,6 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@esbuild/win32-ia32@0.24.0':
resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.24.2': '@esbuild/win32-ia32@0.24.2':
resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -892,12 +754,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@esbuild/win32-x64@0.24.0':
resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.24.2': '@esbuild/win32-x64@0.24.2':
resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -2336,11 +2192,6 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true hasBin: true
esbuild@0.24.0:
resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
engines: {node: '>=18'}
hasBin: true
esbuild@0.24.2: esbuild@0.24.2:
resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -3430,8 +3281,8 @@ packages:
engines: {node: ^18.17.0 || >=20.5.0} engines: {node: ^18.17.0 || >=20.5.0}
hasBin: true hasBin: true
node-html-parser@6.1.13: node-html-parser@7.0.1:
resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} resolution: {integrity: sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA==}
node-id3@0.2.6: node-id3@0.2.6:
resolution: {integrity: sha512-w8GuKXLlPpDjTxLowCt/uYMhRQzED3cg2GdSG1i6RSGKeDzPvxlXeLQuQInKljahPZ0aDnmyX7FX8BbJOM7REg==} resolution: {integrity: sha512-w8GuKXLlPpDjTxLowCt/uYMhRQzED3cg2GdSG1i6RSGKeDzPvxlXeLQuQInKljahPZ0aDnmyX7FX8BbJOM7REg==}
@ -4320,8 +4171,8 @@ packages:
'@testing-library/jest-dom': '@testing-library/jest-dom':
optional: true optional: true
vite@6.0.5: vite@6.0.6:
resolution: {integrity: sha512-akD5IAH/ID5imgue2DYhzsEwCi0/4VKY31uhMLEYJwPP4TiUp8pL5PIK+Wo7H8qT8JY9i+pVfPydcFPYD1EL7g==} resolution: {integrity: sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@ -4727,153 +4578,102 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5': '@esbuild/aix-ppc64@0.21.5':
optional: true optional: true
'@esbuild/aix-ppc64@0.24.0':
optional: true
'@esbuild/aix-ppc64@0.24.2': '@esbuild/aix-ppc64@0.24.2':
optional: true optional: true
'@esbuild/android-arm64@0.21.5': '@esbuild/android-arm64@0.21.5':
optional: true optional: true
'@esbuild/android-arm64@0.24.0':
optional: true
'@esbuild/android-arm64@0.24.2': '@esbuild/android-arm64@0.24.2':
optional: true optional: true
'@esbuild/android-arm@0.21.5': '@esbuild/android-arm@0.21.5':
optional: true optional: true
'@esbuild/android-arm@0.24.0':
optional: true
'@esbuild/android-arm@0.24.2': '@esbuild/android-arm@0.24.2':
optional: true optional: true
'@esbuild/android-x64@0.21.5': '@esbuild/android-x64@0.21.5':
optional: true optional: true
'@esbuild/android-x64@0.24.0':
optional: true
'@esbuild/android-x64@0.24.2': '@esbuild/android-x64@0.24.2':
optional: true optional: true
'@esbuild/darwin-arm64@0.21.5': '@esbuild/darwin-arm64@0.21.5':
optional: true optional: true
'@esbuild/darwin-arm64@0.24.0':
optional: true
'@esbuild/darwin-arm64@0.24.2': '@esbuild/darwin-arm64@0.24.2':
optional: true optional: true
'@esbuild/darwin-x64@0.21.5': '@esbuild/darwin-x64@0.21.5':
optional: true optional: true
'@esbuild/darwin-x64@0.24.0':
optional: true
'@esbuild/darwin-x64@0.24.2': '@esbuild/darwin-x64@0.24.2':
optional: true optional: true
'@esbuild/freebsd-arm64@0.21.5': '@esbuild/freebsd-arm64@0.21.5':
optional: true optional: true
'@esbuild/freebsd-arm64@0.24.0':
optional: true
'@esbuild/freebsd-arm64@0.24.2': '@esbuild/freebsd-arm64@0.24.2':
optional: true optional: true
'@esbuild/freebsd-x64@0.21.5': '@esbuild/freebsd-x64@0.21.5':
optional: true optional: true
'@esbuild/freebsd-x64@0.24.0':
optional: true
'@esbuild/freebsd-x64@0.24.2': '@esbuild/freebsd-x64@0.24.2':
optional: true optional: true
'@esbuild/linux-arm64@0.21.5': '@esbuild/linux-arm64@0.21.5':
optional: true optional: true
'@esbuild/linux-arm64@0.24.0':
optional: true
'@esbuild/linux-arm64@0.24.2': '@esbuild/linux-arm64@0.24.2':
optional: true optional: true
'@esbuild/linux-arm@0.21.5': '@esbuild/linux-arm@0.21.5':
optional: true optional: true
'@esbuild/linux-arm@0.24.0':
optional: true
'@esbuild/linux-arm@0.24.2': '@esbuild/linux-arm@0.24.2':
optional: true optional: true
'@esbuild/linux-ia32@0.21.5': '@esbuild/linux-ia32@0.21.5':
optional: true optional: true
'@esbuild/linux-ia32@0.24.0':
optional: true
'@esbuild/linux-ia32@0.24.2': '@esbuild/linux-ia32@0.24.2':
optional: true optional: true
'@esbuild/linux-loong64@0.21.5': '@esbuild/linux-loong64@0.21.5':
optional: true optional: true
'@esbuild/linux-loong64@0.24.0':
optional: true
'@esbuild/linux-loong64@0.24.2': '@esbuild/linux-loong64@0.24.2':
optional: true optional: true
'@esbuild/linux-mips64el@0.21.5': '@esbuild/linux-mips64el@0.21.5':
optional: true optional: true
'@esbuild/linux-mips64el@0.24.0':
optional: true
'@esbuild/linux-mips64el@0.24.2': '@esbuild/linux-mips64el@0.24.2':
optional: true optional: true
'@esbuild/linux-ppc64@0.21.5': '@esbuild/linux-ppc64@0.21.5':
optional: true optional: true
'@esbuild/linux-ppc64@0.24.0':
optional: true
'@esbuild/linux-ppc64@0.24.2': '@esbuild/linux-ppc64@0.24.2':
optional: true optional: true
'@esbuild/linux-riscv64@0.21.5': '@esbuild/linux-riscv64@0.21.5':
optional: true optional: true
'@esbuild/linux-riscv64@0.24.0':
optional: true
'@esbuild/linux-riscv64@0.24.2': '@esbuild/linux-riscv64@0.24.2':
optional: true optional: true
'@esbuild/linux-s390x@0.21.5': '@esbuild/linux-s390x@0.21.5':
optional: true optional: true
'@esbuild/linux-s390x@0.24.0':
optional: true
'@esbuild/linux-s390x@0.24.2': '@esbuild/linux-s390x@0.24.2':
optional: true optional: true
'@esbuild/linux-x64@0.21.5': '@esbuild/linux-x64@0.21.5':
optional: true optional: true
'@esbuild/linux-x64@0.24.0':
optional: true
'@esbuild/linux-x64@0.24.2': '@esbuild/linux-x64@0.24.2':
optional: true optional: true
@ -4883,60 +4683,39 @@ snapshots:
'@esbuild/netbsd-x64@0.21.5': '@esbuild/netbsd-x64@0.21.5':
optional: true optional: true
'@esbuild/netbsd-x64@0.24.0':
optional: true
'@esbuild/netbsd-x64@0.24.2': '@esbuild/netbsd-x64@0.24.2':
optional: true optional: true
'@esbuild/openbsd-arm64@0.24.0':
optional: true
'@esbuild/openbsd-arm64@0.24.2': '@esbuild/openbsd-arm64@0.24.2':
optional: true optional: true
'@esbuild/openbsd-x64@0.21.5': '@esbuild/openbsd-x64@0.21.5':
optional: true optional: true
'@esbuild/openbsd-x64@0.24.0':
optional: true
'@esbuild/openbsd-x64@0.24.2': '@esbuild/openbsd-x64@0.24.2':
optional: true optional: true
'@esbuild/sunos-x64@0.21.5': '@esbuild/sunos-x64@0.21.5':
optional: true optional: true
'@esbuild/sunos-x64@0.24.0':
optional: true
'@esbuild/sunos-x64@0.24.2': '@esbuild/sunos-x64@0.24.2':
optional: true optional: true
'@esbuild/win32-arm64@0.21.5': '@esbuild/win32-arm64@0.21.5':
optional: true optional: true
'@esbuild/win32-arm64@0.24.0':
optional: true
'@esbuild/win32-arm64@0.24.2': '@esbuild/win32-arm64@0.24.2':
optional: true optional: true
'@esbuild/win32-ia32@0.21.5': '@esbuild/win32-ia32@0.21.5':
optional: true optional: true
'@esbuild/win32-ia32@0.24.0':
optional: true
'@esbuild/win32-ia32@0.24.2': '@esbuild/win32-ia32@0.24.2':
optional: true optional: true
'@esbuild/win32-x64@0.21.5': '@esbuild/win32-x64@0.21.5':
optional: true optional: true
'@esbuild/win32-x64@0.24.0':
optional: true
'@esbuild/win32-x64@0.24.2': '@esbuild/win32-x64@0.24.2':
optional: true optional: true
@ -6587,7 +6366,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
electron-vite@2.3.0(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)): electron-vite@2.3.0(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1)):
dependencies: dependencies:
'@babel/core': 7.26.0 '@babel/core': 7.26.0
'@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0)
@ -6595,7 +6374,7 @@ snapshots:
esbuild: 0.21.5 esbuild: 0.21.5
magic-string: 0.30.13 magic-string: 0.30.13
picocolors: 1.1.1 picocolors: 1.1.1
vite: 6.0.5(@types/node@22.9.3)(yaml@2.6.1) vite: 6.0.6(@types/node@22.9.3)(yaml@2.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -6753,33 +6532,6 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5 '@esbuild/win32-x64': 0.21.5
esbuild@0.24.0:
optionalDependencies:
'@esbuild/aix-ppc64': 0.24.0
'@esbuild/android-arm': 0.24.0
'@esbuild/android-arm64': 0.24.0
'@esbuild/android-x64': 0.24.0
'@esbuild/darwin-arm64': 0.24.0
'@esbuild/darwin-x64': 0.24.0
'@esbuild/freebsd-arm64': 0.24.0
'@esbuild/freebsd-x64': 0.24.0
'@esbuild/linux-arm': 0.24.0
'@esbuild/linux-arm64': 0.24.0
'@esbuild/linux-ia32': 0.24.0
'@esbuild/linux-loong64': 0.24.0
'@esbuild/linux-mips64el': 0.24.0
'@esbuild/linux-ppc64': 0.24.0
'@esbuild/linux-riscv64': 0.24.0
'@esbuild/linux-s390x': 0.24.0
'@esbuild/linux-x64': 0.24.0
'@esbuild/netbsd-x64': 0.24.0
'@esbuild/openbsd-arm64': 0.24.0
'@esbuild/openbsd-x64': 0.24.0
'@esbuild/sunos-x64': 0.24.0
'@esbuild/win32-arm64': 0.24.0
'@esbuild/win32-ia32': 0.24.0
'@esbuild/win32-x64': 0.24.0
esbuild@0.24.2: esbuild@0.24.2:
optionalDependencies: optionalDependencies:
'@esbuild/aix-ppc64': 0.24.2 '@esbuild/aix-ppc64': 0.24.2
@ -7929,7 +7681,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
node-html-parser@6.1.13: node-html-parser@7.0.1:
dependencies: dependencies:
css-select: 5.1.0 css-select: 5.1.0
he: 1.2.0 he: 1.2.0
@ -8859,7 +8611,7 @@ snapshots:
extsprintf: 1.4.1 extsprintf: 1.4.1
optional: true optional: true
vite-plugin-inspect@0.10.6(rollup@4.29.1)(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)): vite-plugin-inspect@0.10.6(rollup@4.29.1)(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1)):
dependencies: dependencies:
'@antfu/utils': 0.7.10 '@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.4(rollup@4.29.1) '@rollup/pluginutils': 5.1.4(rollup@4.29.1)
@ -8870,7 +8622,7 @@ snapshots:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.1.1 picocolors: 1.1.1
sirv: 3.0.0 sirv: 3.0.0
vite: 6.0.5(@types/node@22.9.3)(yaml@2.6.1) vite: 6.0.6(@types/node@22.9.3)(yaml@2.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
@ -8879,7 +8631,7 @@ snapshots:
dependencies: dependencies:
lib-esm: 0.4.2 lib-esm: 0.4.2
vite-plugin-solid@2.11.0(solid-js@1.9.3)(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)): vite-plugin-solid@2.11.0(solid-js@1.9.3)(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1)):
dependencies: dependencies:
'@babel/core': 7.26.0 '@babel/core': 7.26.0
'@types/babel__core': 7.20.5 '@types/babel__core': 7.20.5
@ -8887,14 +8639,14 @@ snapshots:
merge-anything: 5.1.7 merge-anything: 5.1.7
solid-js: 1.9.3 solid-js: 1.9.3
solid-refresh: 0.6.3(solid-js@1.9.3) solid-refresh: 0.6.3(solid-js@1.9.3)
vite: 6.0.5(@types/node@22.9.3)(yaml@2.6.1) vite: 6.0.6(@types/node@22.9.3)(yaml@2.6.1)
vitefu: 1.0.4(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)) vitefu: 1.0.4(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1))
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1): vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1):
dependencies: dependencies:
esbuild: 0.24.0 esbuild: 0.24.2
postcss: 8.4.49 postcss: 8.4.49
rollup: 4.29.1 rollup: 4.29.1
optionalDependencies: optionalDependencies:
@ -8902,9 +8654,9 @@ snapshots:
fsevents: 2.3.3 fsevents: 2.3.3
yaml: 2.6.1 yaml: 2.6.1
vitefu@1.0.4(vite@6.0.5(@types/node@22.9.3)(yaml@2.6.1)): vitefu@1.0.4(vite@6.0.6(@types/node@22.9.3)(yaml@2.6.1)):
optionalDependencies: optionalDependencies:
vite: 6.0.5(@types/node@22.9.3)(yaml@2.6.1) vite: 6.0.6(@types/node@22.9.3)(yaml@2.6.1)
vudio@2.1.1(patch_hash=7iux5msqpgl3octdmwy4uspwoe): {} vudio@2.1.1(patch_hash=7iux5msqpgl3octdmwy4uspwoe): {}

View File

@ -194,10 +194,44 @@
} }
}, },
"tray": { "tray": {
"next": "अगला" "next": "अगला",
"play-pause": "चलाएँ/रोकें",
"previous": "पिछला",
"quit": "निकास",
"restart": "ऐप पुनः प्रारंभ करें",
"show": "ऐप दिखाए",
"tooltip": {
"default": "यूट्यूब म्यूजिक",
"with-song-info": "यूट्यूब म्यूजिक: {{artist}} - {{title}}"
}
} }
}, },
"plugins": { "plugins": {
"ad-speedup": {
"description": "यदि कोई विज्ञापन चलता है तो यह ऑडियो को म्यूट कर देता है और प्लेबैक गति 16x पर सेट कर देता है",
"name": "विज्ञापन की गति बढ़ाना"
},
"adblocker": {
"description": "डिफ़ॉल्ट रूप से सभी विज्ञापनों और ट्रैकिंग को ब्लॉक करें",
"menu": {
"blocker": "ब्लॉकर"
},
"name": "विज्ञापन अवरोधक"
},
"album-actions": {
"description": "प्लेलिस्ट या एल्बम के सभी गानों पर लागू करने के लिए \"अंडिसलाइक,\" \"डिसलाइक,\" \"लाइक,\" और \"अनलाइक\" बटन जोड़ता है",
"name": "एल्बम एक्शन"
},
"album-color-theme": {
"description": "एल्बम रंग पैलेट के आधार पर एक गतिशील थीम और दृश्य प्रभाव लागू करता है",
"menu": {
"color-mix-ratio": {
"submenu": {
"percent": "{{ratio}}%"
}
}
}
},
"video-toggle": { "video-toggle": {
"menu": { "menu": {
"align": { "align": {

View File

@ -279,6 +279,13 @@
}, },
"name": "Modalità Ambiente" "name": "Modalità Ambiente"
}, },
"amuse": {
"description": "Aggiunge il supporto a YouTube Music per il widget Amuse Now Playing di 6K Labs",
"name": "Amuse",
"response": {
"query": "Il server API di Amuse è in funzione. GET /query per ottenere informazioni sui brani."
}
},
"api-server": { "api-server": {
"description": "Aggiunge un server API per controllare il player", "description": "Aggiunge un server API per controllare il player",
"dialog": { "dialog": {
@ -484,6 +491,18 @@
"button": "Scarica" "button": "Scarica"
} }
}, },
"equalizer": {
"description": "Aggiunge un equalizzatore al player",
"menu": {
"presets": {
"label": "Presets",
"list": {
"bass-booster": "Booster dei bassi"
}
}
},
"name": "Equalizzatore"
},
"exponential-volume": { "exponential-volume": {
"description": "Rende esponenziale il cursore del volume, in modo da facilitare la selezione di volumi più bassi.", "description": "Rende esponenziale il cursore del volume, in modo da facilitare la selezione di volumi più bassi.",
"name": "Volume esponenziale" "name": "Volume esponenziale"

View File

@ -279,6 +279,9 @@
}, },
"name": "Tryb otoczenia" "name": "Tryb otoczenia"
}, },
"amuse": {
"name": "Amuse"
},
"api-server": { "api-server": {
"description": "Pozwala na kontrolowanie YouTube Music poprzez podłączenie specjalnego serwera API", "description": "Pozwala na kontrolowanie YouTube Music poprzez podłączenie specjalnego serwera API",
"dialog": { "dialog": {
@ -484,6 +487,18 @@
"button": "Pobierz" "button": "Pobierz"
} }
}, },
"equalizer": {
"description": "Dodaje equalizer do odtwarzacza",
"menu": {
"presets": {
"label": "Presety",
"list": {
"bass-booster": "Wzmacniacz basu"
}
}
},
"name": "Equalizer"
},
"exponential-volume": { "exponential-volume": {
"description": "Sprawia, że suwak głośności jest proporcjonalna, dzięki czemu łatwiej jest wybrać niższą głośność.", "description": "Sprawia, że suwak głośności jest proporcjonalna, dzięki czemu łatwiej jest wybrać niższą głośność.",
"name": "Proporcjonalna głośność" "name": "Proporcjonalna głośność"
@ -725,6 +740,9 @@
"line-effect": { "line-effect": {
"label": "Efekty linijki", "label": "Efekty linijki",
"submenu": { "submenu": {
"fancy": {
"label": "Facy"
},
"focus": { "focus": {
"label": "Fokus", "label": "Fokus",
"tooltip": "Spraw, aby tylko obecna linijka była biała" "tooltip": "Spraw, aby tylko obecna linijka była biała"

View File

@ -279,6 +279,13 @@
}, },
"name": "Modo ambiente" "name": "Modo ambiente"
}, },
"amuse": {
"description": "Adiciona suporte ao YouTube Music ao widget 'Reproduzindo agora' do Amuse da 6K Labs",
"name": "Amuse",
"response": {
"query": "Servidor API do Amuse em execução. GET /query para obter informações da música."
}
},
"api-server": { "api-server": {
"description": "Adiciona um servidor API para controlar o player", "description": "Adiciona um servidor API para controlar o player",
"dialog": { "dialog": {

View File

@ -279,6 +279,13 @@
}, },
"name": "Режим Ambient" "name": "Режим Ambient"
}, },
"amuse": {
"description": "Добавляет поддержку виджета Amuse „сейчас играет“ от 6K Labs",
"name": "Amuse",
"response": {
"query": "Сервер Amuse API запущен. GET /query чтобы получить информацию о треке."
}
},
"api-server": { "api-server": {
"description": "Добавляет API сервер для контроля за плеером", "description": "Добавляет API сервер для контроля за плеером",
"dialog": { "dialog": {
@ -726,8 +733,8 @@
"synced-lyrics": { "synced-lyrics": {
"description": "Предоставляет синхронизированные слова для песен из таких источников, как LRClib.", "description": "Предоставляет синхронизированные слова для песен из таких источников, как LRClib.",
"errors": { "errors": {
"fetch": "⚠️ - Возникла ошибка во время получения слов. Повторите попытку позже.", "fetch": "⚠️\tПроизошла ошибка во время получения слов.\n\tПовторите попытку позже.",
"not-found": "⚠️ - Для этой песни не найдено слов." "not-found": "⚠️ Для этой песни не найдено слов."
}, },
"menu": { "menu": {
"default-text-string": { "default-text-string": {
@ -737,6 +744,10 @@
"line-effect": { "line-effect": {
"label": "Эффект строки", "label": "Эффект строки",
"submenu": { "submenu": {
"fancy": {
"label": "Красивый",
"tooltip": "Использовать большие эффекты строки, как в приложении"
},
"focus": { "focus": {
"label": "Фокусировка", "label": "Фокусировка",
"tooltip": "Делает только текущую строку белой" "tooltip": "Делает только текущую строку белой"

View File

@ -279,6 +279,13 @@
}, },
"name": "微光效果" "name": "微光效果"
}, },
"amuse": {
"description": "加入支援 6K Labs 的 Amuse OBS 外掛以取得 Youtube Music 現正播放資訊",
"name": "Amuse",
"response": {
"query": "Amuse API 伺服器正在運行中,使用 /query 以取得歌曲資訊。"
}
},
"api-server": { "api-server": {
"description": "新增伺服器以使用 API 控制播放器", "description": "新增伺服器以使用 API 控制播放器",
"dialog": { "dialog": {
@ -726,7 +733,7 @@
"synced-lyrics": { "synced-lyrics": {
"description": "使用 LRClib 等管道提供歌詞同步顯示。", "description": "使用 LRClib 等管道提供歌詞同步顯示。",
"errors": { "errors": {
"fetch": "⚠️擷取歌詞時發生錯誤請稍後再試。", "fetch": "⚠️\t擷取歌詞時發生錯誤\n請稍後再試。",
"not-found": "⚠️未找到該首歌曲的歌詞。" "not-found": "⚠️未找到該首歌曲的歌詞。"
}, },
"menu": { "menu": {
@ -737,6 +744,10 @@
"line-effect": { "line-effect": {
"label": "歌詞顯示效果", "label": "歌詞顯示效果",
"submenu": { "submenu": {
"fancy": {
"label": "絢麗",
"tooltip": "使用較為接近原生樣式並且放大當前該行歌詞"
},
"focus": { "focus": {
"label": "高亮", "label": "高亮",
"tooltip": "高亮當前的歌詞" "tooltip": "高亮當前的歌詞"

View File

@ -505,10 +505,11 @@ app.once('browser-window-created', (_event, win) => {
// User agents are from https://developers.whatismybrowser.com/useragents/explore/ // User agents are from https://developers.whatismybrowser.com/useragents/explore/
const originalUserAgent = win.webContents.userAgent; const originalUserAgent = win.webContents.userAgent;
const userAgents = { const userAgents = {
mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1; rv:95.0) Gecko/20100101 Firefox/95.0', mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
windows: windows:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
linux: 'Mozilla/5.0 (Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0', linux:
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.152 Safari/537.36',
}; };
const updatedUserAgent = is.macOS() const updatedUserAgent = is.macOS()
@ -912,10 +913,12 @@ function removeContentSecurityPolicy(
delete details.responseHeaders['content-security-policy']; delete details.responseHeaders['content-security-policy'];
delete details.responseHeaders['Content-Security-Policy']; delete details.responseHeaders['Content-Security-Policy'];
// Only allow cross-origin requests from music.youtube.com if (
delete details.responseHeaders['access-control-allow-origin']; !details.responseHeaders['access-control-allow-origin'] &&
delete details.responseHeaders['Access-Control-Allow-Origin']; !details.responseHeaders['Access-Control-Allow-Origin']
details.responseHeaders['access-control-allow-origin'] = ['https://music.youtube.com']; ) {
details.responseHeaders['access-control-allow-origin'] = ['https://music.youtube.com'];
}
} }
callback({ cancel: false, responseHeaders: details.responseHeaders }); callback({ cancel: false, responseHeaders: details.responseHeaders });

View File

@ -24,9 +24,10 @@ export const backend = createBackend<BackendType, APIServerConfig>({
this.songInfo = songInfo; this.songInfo = songInfo;
}); });
ctx.ipc.on('ytmd:player-api-loaded', () => ctx.ipc.on('ytmd:player-api-loaded', () => {
ctx.ipc.send('ytmd:setup-time-changed-listener'), ctx.ipc.send('ytmd:setup-time-changed-listener');
); ctx.ipc.send('ytmd:setup-repeat-changed-listener');
});
ctx.ipc.on( ctx.ipc.on(
'ytmd:repeat-changed', 'ytmd:repeat-changed',
@ -59,6 +60,12 @@ export const backend = createBackend<BackendType, APIServerConfig>({
this.app.use('*', cors()); this.app.use('*', cors());
// for web remote control
this.app.use('*', async (ctx, next) => {
ctx.header('Access-Control-Request-Private-Network', 'true');
await next();
});
// middlewares // middlewares
this.app.use('/api/*', async (ctx, next) => { this.app.use('/api/*', async (ctx, next) => {
if (config.authStrategy !== AuthStrategy.NONE) { if (config.authStrategy !== AuthStrategy.NONE) {

View File

@ -5,15 +5,19 @@ import { ipcMain } from 'electron';
import getSongControls from '@/providers/song-controls'; import getSongControls from '@/providers/song-controls';
import { import {
AuthHeadersSchema, AddSongToQueueSchema,
type ResponseSongInfo,
SongInfoSchema,
SeekSchema,
GoForwardScheme,
GoBackSchema, GoBackSchema,
SwitchRepeatSchema, GoForwardScheme,
SetVolumeSchema, MoveSongInQueueSchema,
QueueParamsSchema,
SearchSchema,
SeekSchema,
SetFullscreenSchema, SetFullscreenSchema,
SetQueueIndexSchema,
SetVolumeSchema,
SongInfoSchema,
SwitchRepeatSchema,
type ResponseSongInfo,
} from '../scheme'; } from '../scheme';
import type { RepeatMode } from '@/types/datahost-get-state'; import type { RepeatMode } from '@/types/datahost-get-state';
@ -22,6 +26,7 @@ import type { BackendContext } from '@/types/contexts';
import type { APIServerConfig } from '../../config'; import type { APIServerConfig } from '../../config';
import type { HonoApp } from '../types'; import type { HonoApp } from '../types';
import type { QueueResponse } from '@/types/youtube-music-desktop-internal'; import type { QueueResponse } from '@/types/youtube-music-desktop-internal';
import type { Context } from 'hono';
const API_VERSION = 'v1'; const API_VERSION = 'v1';
@ -110,7 +115,6 @@ const routes = {
summary: 'seek', summary: 'seek',
description: 'Seek to a specific time in the current song', description: 'Seek to a specific time in the current song',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'seconds to seek to', description: 'seconds to seek to',
content: { content: {
@ -132,7 +136,6 @@ const routes = {
summary: 'go back', summary: 'go back',
description: 'Move the current song back by a number of seconds', description: 'Move the current song back by a number of seconds',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'seconds to go back', description: 'seconds to go back',
content: { content: {
@ -155,7 +158,6 @@ const routes = {
summary: 'go forward', summary: 'go forward',
description: 'Move the current song forward by a number of seconds', description: 'Move the current song forward by a number of seconds',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'seconds to go forward', description: 'seconds to go forward',
content: { content: {
@ -207,7 +209,6 @@ const routes = {
summary: 'switch repeat', summary: 'switch repeat',
description: 'Switch the repeat mode', description: 'Switch the repeat mode',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'number of times to click the repeat button', description: 'number of times to click the repeat button',
content: { content: {
@ -229,7 +230,6 @@ const routes = {
summary: 'set volume', summary: 'set volume',
description: 'Set the volume of the player', description: 'Set the volume of the player',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'volume to set', description: 'volume to set',
content: { content: {
@ -251,7 +251,6 @@ const routes = {
summary: 'set fullscreen', summary: 'set fullscreen',
description: 'Set the fullscreen state of the player', description: 'Set the fullscreen state of the player',
request: { request: {
headers: AuthHeadersSchema,
body: { body: {
description: 'fullscreen state', description: 'fullscreen state',
content: { content: {
@ -297,7 +296,8 @@ const routes = {
}, },
}, },
}), }),
queueInfo: createRoute({ oldQueueInfo: createRoute({
deprecated: true,
method: 'get', method: 'get',
path: `/api/${API_VERSION}/queue-info`, path: `/api/${API_VERSION}/queue-info`,
summary: 'get current queue info', summary: 'get current queue info',
@ -316,7 +316,8 @@ const routes = {
}, },
}, },
}), }),
songInfo: createRoute({ oldSongInfo: createRoute({
deprecated: true,
method: 'get', method: 'get',
path: `/api/${API_VERSION}/song-info`, path: `/api/${API_VERSION}/song-info`,
summary: 'get current song info', summary: 'get current song info',
@ -335,6 +336,159 @@ const routes = {
}, },
}, },
}), }),
songInfo: createRoute({
method: 'get',
path: `/api/${API_VERSION}/song`,
summary: 'get current song info',
description: 'Get the current song info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: SongInfoSchema,
},
},
},
204: {
description: 'No song info',
},
},
}),
queueInfo: createRoute({
method: 'get',
path: `/api/${API_VERSION}/queue`,
summary: 'get current queue info',
description: 'Get the current queue info',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({}),
},
},
},
204: {
description: 'No queue info',
},
},
}),
addSongToQueue: createRoute({
method: 'post',
path: `/api/${API_VERSION}/queue`,
summary: 'add song to queue',
description: 'Add a song to the queue',
request: {
body: {
description: 'video id of the song to add',
content: {
'application/json': {
schema: AddSongToQueueSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
moveSongInQueue: createRoute({
method: 'patch',
path: `/api/${API_VERSION}/queue/{index}`,
summary: 'move song in queue',
description: 'Move a song in the queue',
request: {
params: QueueParamsSchema,
body: {
description: 'index to move the song to',
content: {
'application/json': {
schema: MoveSongInQueueSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
removeSongFromQueue: createRoute({
method: 'delete',
path: `/api/${API_VERSION}/queue/{index}`,
summary: 'remove song from queue',
description: 'Remove a song from the queue',
request: {
params: QueueParamsSchema,
},
responses: {
204: {
description: 'Success',
},
},
}),
setQueueIndex: createRoute({
method: 'patch',
path: `/api/${API_VERSION}/queue`,
summary: 'set queue index',
description: 'Set the current index of the queue',
request: {
body: {
description: 'index to move the song to',
content: {
'application/json': {
schema: SetQueueIndexSchema,
},
},
},
},
responses: {
204: {
description: 'Success',
},
},
}),
clearQueue: createRoute({
method: 'delete',
path: `/api/${API_VERSION}/queue`,
summary: 'clear queue',
description: 'Clear the queue',
responses: {
204: {
description: 'Success',
},
},
}),
search: createRoute({
method: 'post',
path: `/api/${API_VERSION}/search`,
summary: 'search for a song',
description: 'search for a song',
request: {
body: {
description: 'search query',
content: {
'application/json': {
schema: SearchSchema,
},
},
},
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: z.object({}),
},
},
},
},
}),
}; };
export const register = ( export const register = (
@ -464,7 +618,26 @@ export const register = (
ctx.status(200); ctx.status(200);
return ctx.json({ state: fullscreen }); return ctx.json({ state: fullscreen });
}); });
app.openapi(routes.queueInfo, async (ctx) => {
const songInfo = (ctx: Context) => {
const info = songInfoGetter();
if (!info) {
ctx.status(204);
return ctx.body(null);
}
const body = { ...info };
delete body.image;
ctx.status(200);
return ctx.json(body satisfies ResponseSongInfo);
};
app.openapi(routes.oldSongInfo, songInfo);
app.openapi(routes.songInfo, songInfo);
// Queue
const queueInfo = async (ctx: Context) => {
const queueResponsePromise = new Promise<QueueResponse>((resolve) => { const queueResponsePromise = new Promise<QueueResponse>((resolve) => {
ipcMain.once('ytmd:get-queue-response', (_, queue: QueueResponse) => { ipcMain.once('ytmd:get-queue-response', (_, queue: QueueResponse) => {
return resolve(queue); return resolve(queue);
@ -482,19 +655,50 @@ export const register = (
ctx.status(200); ctx.status(200);
return ctx.json(info); return ctx.json(info);
};
app.openapi(routes.oldQueueInfo, queueInfo);
app.openapi(routes.queueInfo, queueInfo);
app.openapi(routes.addSongToQueue, (ctx) => {
const { videoId } = ctx.req.valid('json');
controller.addSongToQueue(videoId);
ctx.status(204);
return ctx.body(null);
}); });
app.openapi(routes.songInfo, (ctx) => { app.openapi(routes.moveSongInQueue, (ctx) => {
const info = songInfoGetter(); const index = Number(ctx.req.param('index'));
const { toIndex } = ctx.req.valid('json');
controller.moveSongInQueue(index, toIndex);
if (!info) { ctx.status(204);
ctx.status(204); return ctx.body(null);
return ctx.body(null); });
} app.openapi(routes.removeSongFromQueue, (ctx) => {
const index = Number(ctx.req.param('index'));
controller.removeSongFromQueue(index);
const body = { ...info }; ctx.status(204);
delete body.image; return ctx.body(null);
});
app.openapi(routes.setQueueIndex, (ctx) => {
const { index } = ctx.req.valid('json');
controller.setQueueIndex(index);
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.clearQueue, (ctx) => {
controller.clearQueue();
ctx.status(204);
return ctx.body(null);
});
app.openapi(routes.search, async (ctx) => {
const { query } = ctx.req.valid('json');
const response = await controller.search(query);
ctx.status(200); ctx.status(200);
return ctx.json(body satisfies ResponseSongInfo); return ctx.json(response as object);
}); });
}; };

View File

@ -1,11 +1,5 @@
import { z } from '@hono/zod-openapi'; import { z } from '@hono/zod-openapi';
export const AuthHeadersSchema = z.object({
authorization: z.string().openapi({
example: 'Bearer token',
}),
});
export type JWTPayload = z.infer<typeof JWTPayloadSchema>; export type JWTPayload = z.infer<typeof JWTPayloadSchema>;
export const JWTPayloadSchema = z.object({ export const JWTPayloadSchema = z.object({
id: z.string(), id: z.string(),

View File

@ -6,3 +6,5 @@ export * from './go-forward';
export * from './switch-repeat'; export * from './switch-repeat';
export * from './set-volume'; export * from './set-volume';
export * from './set-fullscreen'; export * from './set-fullscreen';
export * from './queue';
export * from './search';

View File

@ -0,0 +1,15 @@
import { z } from '@hono/zod-openapi';
export const QueueParamsSchema = z.object({
index: z.coerce.number().int().nonnegative(),
});
export const AddSongToQueueSchema = z.object({
videoId: z.string(),
});
export const MoveSongInQueueSchema = z.object({
toIndex: z.number(),
});
export const SetQueueIndexSchema = z.object({
index: z.number().int().nonnegative(),
});

View File

@ -0,0 +1,5 @@
import { z } from '@hono/zod-openapi';
export const SearchSchema = z.object({
query: z.string(),
});

View File

@ -63,6 +63,11 @@ let yt: Innertube;
let win: BrowserWindow; let win: BrowserWindow;
let playingUrl: string; let playingUrl: string;
const isYouTubePremium = () =>
win.webContents.executeJavaScript(
'!document.querySelector(\'#endpoint[href="/music_premium"]\')',
) as Promise<boolean>;
const sendError = (error: Error, source?: string) => { const sendError = (error: Error, source?: string) => {
win.setProgressBar(-1); // Close progress bar win.setProgressBar(-1); // Close progress bar
setBadge(0); // Close badge setBadge(0); // Close badge
@ -313,7 +318,7 @@ async function downloadSongUnsafe(
} }
const downloadOptions: FormatOptions = { const downloadOptions: FormatOptions = {
type: 'audio', // Audio, video or video+audio type: (await isYouTubePremium()) ? 'audio' : 'video+audio', // Audio, video or video+audio
quality: 'best', // Best, bestefficiency, 144p, 240p, 480p, 720p and so on. quality: 'best', // Best, bestefficiency, 144p, 240p, 480p, 720p and so on.
format: 'any', // Media container format format: 'any', // Media container format
}; };
@ -585,20 +590,17 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
return; return;
} }
if ( if (!playlist || !playlist.items || playlist.items.length === 0) {
!playlist ||
!playlist.items ||
playlist.items.length === 0 ||
!playlist.header ||
!('title' in playlist.header)
) {
sendError( sendError(
new Error(t('plugins.downloader.backend.feedback.playlist-is-empty')), new Error(t('plugins.downloader.backend.feedback.playlist-is-empty')),
); );
return; return;
} }
const normalPlaylistTitle = playlist.header?.title?.text; const normalPlaylistTitle =
playlist.header && 'title' in playlist.header
? playlist.header?.title?.text
: undefined;
const playlistTitle = const playlistTitle =
normalPlaylistTitle ?? normalPlaylistTitle ??
playlist.page.contents_memo playlist.page.contents_memo

View File

@ -612,7 +612,9 @@ export default createPlugin<
const accountData = renderer.data as RawAccountData; const accountData = renderer.data as RawAccountData;
this.me = { this.me = {
handleId: accountData.channelHandle.runs[0].text, handleId:
accountData.channelHandle.runs[0].text ??
accountData.accountName.runs[0].text,
name: accountData.accountName.runs[0].text, name: accountData.accountName.runs[0].text,
thumbnail: accountData.accountPhoto.thumbnails[0].url, thumbnail: accountData.accountPhoto.thumbnails[0].url,
}; };

View File

@ -6,7 +6,7 @@ import { t } from '@/i18n';
import type { ConnectionEventUnion } from '@/plugins/music-together/connection'; import type { ConnectionEventUnion } from '@/plugins/music-together/connection';
import type { Profile, VideoData } from '../types'; import type { Profile, VideoData } from '../types';
import type { QueueItem } from '@/types/datahost-get-state'; import type { QueueItem } from '@/types/datahost-get-state';
import type { QueueElement } from '@/types/queue'; import type { QueueElement, Store } from '@/types/queue';
const getHeaderPayload = (() => { const getHeaderPayload = (() => {
let payload: { let payload: {
@ -266,7 +266,8 @@ export class Queue {
} }
if (this.originalDispatch) if (this.originalDispatch)
this.queue.queue.store.store.dispatch = this.originalDispatch; this.queue.queue.store.store.dispatch = this
.originalDispatch as Store['dispatch'];
} }
injection() { injection() {
@ -295,7 +296,11 @@ export class Queue {
videoId: it!.videoId, videoId: it!.videoId,
ownerId: this.owner!.id, ownerId: this.owner!.id,
}) satisfies VideoData, }) satisfies VideoData,
event.payload!.items!, (
event.payload! as {
items: QueueItem[];
}
).items,
); );
const index = this._videoList.length + videoList.length - 1; const index = this._videoList.length + videoList.length - 1;
@ -334,7 +339,11 @@ export class Queue {
videoId: it!.videoId, videoId: it!.videoId,
ownerId: this.owner!.id, ownerId: this.owner!.id,
}) satisfies VideoData, }) satisfies VideoData,
event.payload!.items!, (
event.payload! as {
items: QueueItem[];
}
).items,
), ),
}, },
}); });
@ -407,7 +416,13 @@ export class Queue {
}, },
}, },
}; };
this.originalDispatch?.call(fakeContext, event); this.originalDispatch?.call(
fakeContext,
event as {
type: string;
payload?: { items?: QueueItem[] | undefined } | undefined;
},
);
}; };
} }

View File

@ -1,4 +1,5 @@
import type { LyricProvider, LyricResult, SearchSongInfo } from '../types'; import type { LyricProvider, LyricResult, SearchSongInfo } from '../types';
import type { YouTubeMusicAppElement } from '@/types/youtube-music-app-element';
const headers = { const headers = {
'Accept': 'application/json', 'Accept': 'application/json',
@ -102,19 +103,17 @@ export class YTMusic implements LyricProvider {
.padStart(2, '0')}.${remaining.toString().padStart(2, '0')}`; .padStart(2, '0')}.${remaining.toString().padStart(2, '0')}`;
} }
private ENDPOINT = 'https://youtubei.googleapis.com/youtubei/v1/';
// RATE LIMITED (2 req per sec) // RATE LIMITED (2 req per sec)
private PROXIED_ENDPOINT = 'https://ytmbrowseproxy.zvz.be/'; private PROXIED_ENDPOINT = 'https://ytmbrowseproxy.zvz.be/';
private fetchNext(videoId: string) { private fetchNext(videoId: string) {
return fetch(this.ENDPOINT + 'next?prettyPrint=false', { const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
headers,
method: 'POST', if (!app) return null;
body: JSON.stringify({
videoId, return app.networkManager.fetch('/next?prettyPrint=false', {
context: { client }, videoId,
}), }) as Promise<NextData>;
}).then((res) => res.json()) as Promise<NextData>;
} }
private fetchBrowse(browseId: string) { private fetchBrowse(browseId: string) {

View File

@ -190,7 +190,7 @@
position: sticky; position: sticky;
top: var(--top, 0); top: var(--top, 0);
z-index: 100; z-index: 100;
background-color: var(--ytmusic-background); backdrop-filter: blur(5px);
transition: top 325ms ease-in-out; transition: top 325ms ease-in-out;
} }

View File

@ -1,5 +1,5 @@
// This is used for to control the songs // This is used for to control the songs
import { BrowserWindow } from 'electron'; import { BrowserWindow, ipcMain } from 'electron';
// see protocol-handler.ts // see protocol-handler.ts
type ArgsType<T> = T | string[] | undefined; type ArgsType<T> = T | string[] | undefined;
@ -24,6 +24,16 @@ const parseBooleanFromArgsType = (args: ArgsType<boolean>) => {
} }
}; };
const parseStringFromArgsType = (args: ArgsType<string>) => {
if (typeof args === 'string') {
return args;
} else if (Array.isArray(args)) {
return args[0];
} else {
return null;
}
};
export default (win: BrowserWindow) => { export default (win: BrowserWindow) => {
return { return {
// Playback // Playback
@ -80,11 +90,49 @@ export default (win: BrowserWindow) => {
win.webContents.send('ytmd:get-queue'); win.webContents.send('ytmd:get-queue');
}, },
muteUnmute: () => win.webContents.send('ytmd:toggle-mute'), muteUnmute: () => win.webContents.send('ytmd:toggle-mute'),
search: () => { openSearchBox: () => {
win.webContents.sendInputEvent({ win.webContents.sendInputEvent({
type: 'keyDown', type: 'keyDown',
keyCode: '/', keyCode: '/',
}); });
}, },
// Queue
addSongToQueue: (videoId: string) => {
const videoIdValue = parseStringFromArgsType(videoId);
if (videoIdValue === null) return;
win.webContents.send('ytmd:add-to-queue', videoIdValue);
},
moveSongInQueue: (
fromIndex: ArgsType<number>,
toIndex: ArgsType<number>,
) => {
const fromIndexValue = parseNumberFromArgsType(fromIndex);
const toIndexValue = parseNumberFromArgsType(toIndex);
if (fromIndexValue === null || toIndexValue === null) return;
win.webContents.send('ytmd:move-in-queue', fromIndexValue, toIndexValue);
},
removeSongFromQueue: (index: ArgsType<number>) => {
const indexValue = parseNumberFromArgsType(index);
if (indexValue === null) return;
win.webContents.send('ytmd:remove-from-queue', indexValue);
},
setQueueIndex: (index: ArgsType<number>) => {
const indexValue = parseNumberFromArgsType(index);
if (indexValue === null) return;
win.webContents.send('ytmd:set-queue-index', indexValue);
},
clearQueue: () => win.webContents.send('ytmd:clear-queue'),
search: (query: string) =>
new Promise((resolve) => {
ipcMain.once('ytmd:search-results', (_, result) => {
resolve(result as string);
});
win.webContents.send('ytmd:search', query);
}),
}; };
}; };

View File

@ -22,6 +22,8 @@ import type { PluginConfig } from '@/types/plugins';
import type { YoutubePlayer } from '@/types/youtube-player'; import type { YoutubePlayer } from '@/types/youtube-player';
import type { QueueElement } from '@/types/queue'; import type { QueueElement } from '@/types/queue';
import type { QueueResponse } from '@/types/youtube-music-desktop-internal'; import type { QueueResponse } from '@/types/youtube-music-desktop-internal';
import type { YouTubeMusicAppElement } from '@/types/youtube-music-app-element';
import type { SearchBoxElement } from '@/types/search-box-element';
let api: (Element & YoutubePlayer) | null = null; let api: (Element & YoutubePlayer) | null = null;
let isPluginLoaded = false; let isPluginLoaded = false;
@ -41,10 +43,6 @@ async function listenForApiLoad() {
} }
} }
interface YouTubeMusicAppElement extends HTMLElement {
navigate(page: string): void;
}
async function onApiLoaded() { async function onApiLoaded() {
// Workaround for #2459 // Workaround for #2459
document document
@ -159,6 +157,99 @@ async function onApiLoaded() {
} satisfies QueueResponse); } satisfies QueueResponse);
}); });
window.ipcRenderer.on('ytmd:add-to-queue', (_, videoId: string) => {
const queue = document.querySelector<QueueElement>('#queue');
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
if (!app) return;
const store = queue?.queue.store.store;
if (!store) return;
app.networkManager
.fetch('/music/get_queue', {
queueContextParams: store.getState().queue.queueContextParams,
queueInsertPosition: 'INSERT_AT_END',
videoIds: [videoId],
})
.then((result) => {
if (
result &&
typeof result === 'object' &&
'queueDatas' in result &&
Array.isArray(result.queueDatas)
) {
queue?.dispatch({
type: 'ADD_ITEMS',
payload: {
nextQueueItemId: store.getState().queue.nextQueueItemId,
index: store.getState().queue.items.length ?? 0,
items: result.queueDatas
.map((it) =>
typeof it === 'object' && it && 'content' in it
? it.content
: null,
)
.filter(Boolean),
shuffleEnabled: false,
shouldAssignIds: true,
},
});
}
});
});
window.ipcRenderer.on(
'ytmd:move-in-queue',
(_, fromIndex: number, toIndex: number) => {
const queue = document.querySelector<QueueElement>('#queue');
queue?.dispatch({
type: 'MOVE_ITEM',
payload: {
fromIndex,
toIndex,
},
});
},
);
window.ipcRenderer.on('ytmd:remove-from-queue', (_, index: number) => {
const queue = document.querySelector<QueueElement>('#queue');
queue?.dispatch({
type: 'REMOVE_ITEM',
payload: index,
});
});
window.ipcRenderer.on('ytmd:set-queue-index', (_, index: number) => {
const queue = document.querySelector<QueueElement>('#queue');
queue?.dispatch({
type: 'SET_INDEX',
payload: index,
});
});
window.ipcRenderer.on('ytmd:clear-queue', () => {
const queue = document.querySelector<QueueElement>('#queue');
queue?.queue.store.store.dispatch({
type: 'SET_PLAYER_PAGE_INFO',
payload: { open: false },
});
queue?.dispatch({
type: 'CLEAR',
});
});
window.ipcRenderer.on('ytmd:search', async (_, query: string) => {
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
const searchBox =
document.querySelector<SearchBoxElement>('ytmusic-search-box');
if (!app || !searchBox) return;
const result = await app.networkManager.fetch('/search', {
query,
suggestStats: searchBox.getSearchboxStats(),
});
window.ipcRenderer.send('ytmd:search-results', result);
});
const video = document.querySelector('video')!; const video = document.querySelector('video')!;
const audioContext = new AudioContext(); const audioContext = new AudioContext();
const audioSource = audioContext.createMediaElementSource(video); const audioSource = audioContext.createMediaElementSource(video);

View File

@ -2,13 +2,8 @@ import type { YoutubePlayer } from '@/types/youtube-player';
import type { GetState, QueueItem } from '@/types/datahost-get-state'; import type { GetState, QueueItem } from '@/types/datahost-get-state';
type StoreState = GetState; type StoreState = GetState;
type Store = { export type Store = {
dispatch: (obj: { dispatch: (obj: { type: string; payload?: unknown }) => void;
type: string;
payload?: {
items?: QueueItem[];
};
}) => void;
getState: () => StoreState; getState: () => StoreState;
replaceReducer: (param1: unknown) => unknown; replaceReducer: (param1: unknown) => unknown;

View File

@ -0,0 +1,3 @@
export interface SearchBoxElement extends HTMLElement {
getSearchboxStats(): unknown;
}

View File

@ -0,0 +1,6 @@
export interface YouTubeMusicAppElement extends HTMLElement {
navigate(page: string): void;
networkManager: {
fetch: (url: string, data: unknown) => Promise<unknown>;
};
}