Compare commits

...

32 Commits

Author SHA1 Message Date
a6ed8bf3aa release 3.3.1 (HOTFIX) 2024-02-18 21:36:04 +09:00
87acf4cf04 hotfix: in-app-menu position issue 2024-02-18 21:35:41 +09:00
b6fe2afd75 chore: Update README.md 2024-02-18 20:57:38 +09:00
6d9bb8eb1c Update changelog for v3.3.0 2024-02-18 11:40:17 +00:00
192fd0620f release 3.3.0 2024-02-18 20:32:45 +09:00
00d0b31980 fix(scrobbler): remove snake_case 2024-02-18 20:21:19 +09:00
5edb2131d2 fix(in-app-menu): implement auto close 2024-02-18 20:00:52 +09:00
4657aeca45 fix: apply fix from eslint 2024-02-18 11:58:26 +09:00
9f5651a8ba fix: fix upgrade button
fix #1199
2024-02-18 10:50:36 +09:00
570dcfee29 fix: revert fbc02a494a 2024-02-18 10:50:15 +09:00
2c130ce80d chore(mpris): use override keyword 2024-02-18 10:34:29 +09:00
8457115105 fix(mpris): fix mpris invalid position
- fix #1726
2024-02-18 10:26:45 +09:00
fbc02a494a fix(in-app-menu): simplified if-statement 2024-02-18 09:50:20 +09:00
7e2c254ecf fix(in-app-menu): should be disabled by default in linux env 2024-02-18 09:47:05 +09:00
11936a889e fix(deps): update dependency i18next to v23.8.3 (#1751)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-18 07:33:35 +09:00
f33970addd import fixed ./constants (#1748) 2024-02-18 07:33:11 +09:00
2c02b7193d chore(deps): update dependency rollup to v4.12.0 (#1743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-17 10:08:33 +09:00
3f80b598ae chore(deps): bump undici from 5.28.2 to 5.28.3 (#1747)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-17 10:07:19 +09:00
477068ed49 chore(deps): update dependency vite to v5.1.3 (#1742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-16 08:44:31 +09:00
b4083874ac fix: invalid podcast artist name
🤦
2024-02-16 08:41:00 +09:00
c5d0673b2f chore(deps): update dependency vite-plugin-solid to v2.10.1 (#1734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:32:18 +09:00
9ccc44474b chore(deps): update dependency discord-api-types to v0.37.70 (#1740)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:31:50 +09:00
98e341f122 chore(deps): update dependency electron to v28.2.3 (#1736)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:29:11 +09:00
b23eba51dd chore(deps): update pnpm to v8.15.3 (#1739)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:28:47 +09:00
980005a58c chore(deps): update dependency rollup to v4.11.0 (#1738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:28:41 +09:00
aba58b1d34 fix(deps): update dependency solid-js to v1.8.15 (#1735)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 22:28:17 +09:00
bb6a127d22 chore(deps): update dependency vite to v5.1.2 (#1733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-15 20:32:18 +09:00
ac6e30a6b6 chore(i18n): Translated using Weblate (Polish)
Currently translated at 98.2% (334 of 340 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/pl/
2024-02-14 19:01:58 +01:00
3f23282eed chore(deps): update dependency vite-plugin-solid to v2.10.0 (#1732)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-14 20:36:09 +09:00
199a77819c chore(deps): update pnpm to v8.15.2 (#1729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-14 01:16:33 +09:00
89a53b2854 Update Copyright - 2024 (#1730) 2024-02-14 01:06:26 +09:00
c57bf79b08 chore(i18n): Translated using Weblate (Indonesian)
Currently translated at 100.0% (340 of 340 strings)

Translation: th-ch/youtube-music/i18n
Translate-URL: https://hosted.weblate.org/projects/youtube-music/i18n/id/
2024-02-12 23:42:44 +01:00
28 changed files with 816 additions and 265 deletions

View File

@ -33,7 +33,7 @@ Read this in other languages: [🇰🇷](./docs/readme/README-ko.md)
| Player Screen (album color theme & ambient light) | | Player Screen (album color theme & ambient light) |
|:---------------------------------------------------------------------------------------------------------:| |:---------------------------------------------------------------------------------------------------------:|
|![Screenshot2](https://github.com/th-ch/youtube-music/assets/16558115/28ed8f08-c8c4-48ad-811b-7722093e9d81)| |![Screenshot1](https://github.com/th-ch/youtube-music/assets/16558115/53efdf73-b8fa-4d7b-a235-b96b91ea77fc)|
## Translation ## Translation

View File

@ -2,8 +2,106 @@
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.3.0](https://github.com/th-ch/youtube-music/compare/v3.2.2...v3.3.0)
- fix(deps): update dependency i18next to v23.8.3 [`#1751`](https://github.com/th-ch/youtube-music/pull/1751)
- import fixed ./constants [`#1748`](https://github.com/th-ch/youtube-music/pull/1748)
- chore(deps): update dependency rollup to v4.12.0 [`#1743`](https://github.com/th-ch/youtube-music/pull/1743)
- chore(deps): bump undici from 5.28.2 to 5.28.3 [`#1747`](https://github.com/th-ch/youtube-music/pull/1747)
- chore(deps): update dependency vite to v5.1.3 [`#1742`](https://github.com/th-ch/youtube-music/pull/1742)
- chore(deps): update dependency vite-plugin-solid to v2.10.1 [`#1734`](https://github.com/th-ch/youtube-music/pull/1734)
- chore(deps): update dependency discord-api-types to v0.37.70 [`#1740`](https://github.com/th-ch/youtube-music/pull/1740)
- chore(deps): update dependency electron to v28.2.3 [`#1736`](https://github.com/th-ch/youtube-music/pull/1736)
- chore(deps): update pnpm to v8.15.3 [`#1739`](https://github.com/th-ch/youtube-music/pull/1739)
- chore(deps): update dependency rollup to v4.11.0 [`#1738`](https://github.com/th-ch/youtube-music/pull/1738)
- fix(deps): update dependency solid-js to v1.8.15 [`#1735`](https://github.com/th-ch/youtube-music/pull/1735)
- chore(deps): update dependency vite to v5.1.2 [`#1733`](https://github.com/th-ch/youtube-music/pull/1733)
- chore(deps): update dependency vite-plugin-solid to v2.10.0 [`#1732`](https://github.com/th-ch/youtube-music/pull/1732)
- chore(deps): update pnpm to v8.15.2 [`#1729`](https://github.com/th-ch/youtube-music/pull/1729)
- Update Copyright - 2024 [`#1730`](https://github.com/th-ch/youtube-music/pull/1730)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v7 [`#1728`](https://github.com/th-ch/youtube-music/pull/1728)
- fix(deps): update dependency @floating-ui/dom to v1.6.3 [`#1727`](https://github.com/th-ch/youtube-music/pull/1727)
- chore(deps): update dependency electron to v28.2.2 [`#1717`](https://github.com/th-ch/youtube-music/pull/1717)
- chore(deps): update dependency vite to v5.1.1 [`#1718`](https://github.com/th-ch/youtube-music/pull/1718)
- chore(deps): update dependency @types/semver to v7.5.7 [`#1724`](https://github.com/th-ch/youtube-music/pull/1724)
- fix(deps): update dependency @floating-ui/dom to v1.6.2 [`#1725`](https://github.com/th-ch/youtube-music/pull/1725)
- chore(deps): update dependency rollup to v4.10.0 [`#1719`](https://github.com/th-ch/youtube-music/pull/1719)
- fix(deps): update dependency solid-js to v1.8.14 [`#1713`](https://github.com/th-ch/youtube-music/pull/1713)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.21.0 [`#1711`](https://github.com/th-ch/youtube-music/pull/1711)
- fix(deps): update dependency semver to v7.6.0 [`#1712`](https://github.com/th-ch/youtube-music/pull/1712)
- refactor(in-app-menu): refactor `in-app-menu` plugin [`#1710`](https://github.com/th-ch/youtube-music/pull/1710)
- chore(deps): update playwright monorepo to v1.41.2 [`#1706`](https://github.com/th-ch/youtube-music/pull/1706)
- chore(deps): update dependency electron to v29.0.0-beta.5 [`#1707`](https://github.com/th-ch/youtube-music/pull/1707)
- feat(album-color-theme): support album color theme in all pages [`#1685`](https://github.com/th-ch/youtube-music/pull/1685)
- fix(deps): update dependency youtubei.js to v9.0.2 [`#1704`](https://github.com/th-ch/youtube-music/pull/1704)
- fix(deps): update dependency i18next to v23.8.2 [`#1702`](https://github.com/th-ch/youtube-music/pull/1702)
- feat: Support disabling scrobbling for non-music content [`#1665`](https://github.com/th-ch/youtube-music/pull/1665)
- fix(deps): update dependency youtubei.js to v9 [`#1682`](https://github.com/th-ch/youtube-music/pull/1682)
- chore(deps): update dependency electron to v29.0.0-beta.4 [`#1698`](https://github.com/th-ch/youtube-music/pull/1698)
- fix(deps): update dependency i18next to v23.8.1 [`#1694`](https://github.com/th-ch/youtube-music/pull/1694)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.20.0 [`#1700`](https://github.com/th-ch/youtube-music/pull/1700)
- chore(deps): update pnpm to v8.15.1 [`#1699`](https://github.com/th-ch/youtube-music/pull/1699)
- chore(deps): update dependency esbuild to v0.20.0 [`#1691`](https://github.com/th-ch/youtube-music/pull/1691)
- chore(deps): update pnpm to v8.15.0 [`#1692`](https://github.com/th-ch/youtube-music/pull/1692)
- fix(deps): update dependency i18next to v23.7.20 [`#1684`](https://github.com/th-ch/youtube-music/pull/1684)
- chore(deps): update dependency electron to v29.0.0-beta.3 [`#1683`](https://github.com/th-ch/youtube-music/pull/1683)
- chore(deps): update dependency electron to v29.0.0-beta.2 [`#1681`](https://github.com/th-ch/youtube-music/pull/1681)
- chore(deps): update dependency rollup to v4.9.6 [`#1663`](https://github.com/th-ch/youtube-music/pull/1663)
- chore(deps): update dependency electron to v29.0.0-beta.1 [`#1670`](https://github.com/th-ch/youtube-music/pull/1670)
- fix(deps): update dependency i18next to v23.7.19 [`#1680`](https://github.com/th-ch/youtube-music/pull/1680)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.19.1 [`#1669`](https://github.com/th-ch/youtube-music/pull/1669)
- chore(deps): update pnpm to v8.14.3 [`#1668`](https://github.com/th-ch/youtube-music/pull/1668)
- chore(deps): update dependency vite-plugin-inspect to v0.8.3 [`#1672`](https://github.com/th-ch/youtube-music/pull/1672)
- chore(deps): update dependency esbuild to v0.19.12 [`#1673`](https://github.com/th-ch/youtube-music/pull/1673)
- fix(deps): update dependency @electron/remote to v2.1.2 [`#1676`](https://github.com/th-ch/youtube-music/pull/1676)
- chore: Update issue templates [`#1661`](https://github.com/th-ch/youtube-music/pull/1661)
- chore(deps): update playwright monorepo to v1.41.1 [`#1660`](https://github.com/th-ch/youtube-music/pull/1660)
- fix(deps): update dependency i18next to v23.7.18 [`#1662`](https://github.com/th-ch/youtube-music/pull/1662)
- chore(deps): update actions/dependency-review-action action to v4 [`#1654`](https://github.com/th-ch/youtube-music/pull/1654)
- chore(deps): update dependency electron to v29.0.0-alpha.11 [`#1656`](https://github.com/th-ch/youtube-music/pull/1656)
- chore(deps): update dependency vite to v5.0.12 [security] [`#1659`](https://github.com/th-ch/youtube-music/pull/1659)
- fix(deps): update dependency async-mutex to v0.4.1 [`#1653`](https://github.com/th-ch/youtube-music/pull/1653)
- chore(deps): update playwright monorepo to v1.41.0 [`#1651`](https://github.com/th-ch/youtube-music/pull/1651)
- feat: Better Scrobbler Plugin [`#1640`](https://github.com/th-ch/youtube-music/pull/1640)
- chore(deps): update dependency electron to v29.0.0-alpha.10 [`#1645`](https://github.com/th-ch/youtube-music/pull/1645)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.19.0 [`#1643`](https://github.com/th-ch/youtube-music/pull/1643)
- chore(README): Fix plugins names and add plugins in/to Readme (in menu too) [`#1624`](https://github.com/th-ch/youtube-music/pull/1624)
- fix(album-actions): Fixed album actions [`#1639`](https://github.com/th-ch/youtube-music/pull/1639)
- chore(deps): update playwright monorepo to v1.41.0-beta-1705101589000 [`#1638`](https://github.com/th-ch/youtube-music/pull/1638)
- fix(#1543): fix song control doesn't work [`#1637`](https://github.com/th-ch/youtube-music/pull/1637)
- chore(deps): update playwright monorepo to v1.41.0-beta-1705092460000 [`#1635`](https://github.com/th-ch/youtube-music/pull/1635)
- chore(deps): update dependency rollup to v4.9.5 [`#1629`](https://github.com/th-ch/youtube-music/pull/1629)
- chore(deps): update dependency electron to v29.0.0-alpha.9 [`#1627`](https://github.com/th-ch/youtube-music/pull/1627)
- chore(deps): update dependency electron to v29.0.0-alpha.8 [`#1608`](https://github.com/th-ch/youtube-music/pull/1608)
- fix(deps): update dependency @cliqz/adblocker-electron to v1.26.15 [`#1615`](https://github.com/th-ch/youtube-music/pull/1615)
- chore(deps): update dependency rollup to v4.9.4 [`#1591`](https://github.com/th-ch/youtube-music/pull/1591)
- fix(deps): update dependency @cliqz/adblocker-electron-preload to v1.26.15 [`#1616`](https://github.com/th-ch/youtube-music/pull/1616)
- chore(deps): update pnpm to v8.14.1 [`#1619`](https://github.com/th-ch/youtube-music/pull/1619)
- chore(deps): update dependency eslint-plugin-prettier to v5.1.3 [`#1618`](https://github.com/th-ch/youtube-music/pull/1618)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.18.1 [`#1612`](https://github.com/th-ch/youtube-music/pull/1612)
- fix(deps): update dependency youtubei.js to v8.2.0 [`#1614`](https://github.com/th-ch/youtube-music/pull/1614)
- chore(deps): update dependency electron-vite to v2.0.0 [`#1609`](https://github.com/th-ch/youtube-music/pull/1609)
- chore(deps): update dependency @typescript-eslint/eslint-plugin to v6.18.0 [`#1603`](https://github.com/th-ch/youtube-music/pull/1603)
- chore(deps): update dependency electron-vite to v2.0.0-beta.4 [`#1602`](https://github.com/th-ch/youtube-music/pull/1602)
- fix: fix upgrade button [`#1199`](https://github.com/th-ch/youtube-music/issues/1199)
- fix(mpris): fix mpris invalid position [`#1726`](https://github.com/th-ch/youtube-music/issues/1726)
- fix: discord RPC (fix #1664) [`#1664`](https://github.com/th-ch/youtube-music/issues/1664)
- fix: remove sign-in button (fix #1199) [`#1199`](https://github.com/th-ch/youtube-music/issues/1199)
- Fix #1617 [`#1617`](https://github.com/th-ch/youtube-music/issues/1617)
- fix(crossfade): fix #1633 [`#1633`](https://github.com/th-ch/youtube-music/issues/1633)
- fix: fix #1621 [`#1621`](https://github.com/th-ch/youtube-music/issues/1621)
- fix(tuna-obs): partially fix #1596 [`#1596`](https://github.com/th-ch/youtube-music/issues/1596)
- fix(discord): fix hide duration button [`#1644`](https://github.com/th-ch/youtube-music/issues/1644)
- fix(in-app-menu): fix invalid `margin-top` [`#1597`](https://github.com/th-ch/youtube-music/issues/1597)
- fix(README): fix `plugins` path [`#1598`](https://github.com/th-ch/youtube-music/issues/1598)
- chore(i18n): Translated using Weblate (Vietnamese) [`0528637`](https://github.com/th-ch/youtube-music/commit/05286371353e8b4c36a5b9fe9011ae5dfdc7ee82)
- chore: update pnpm-lock [`fd8d59b`](https://github.com/th-ch/youtube-music/commit/fd8d59bada56dab4e156d22394fe0c5efec5abc4)
- fix(in-app-menu): fix app crash in production [`febc63e`](https://github.com/th-ch/youtube-music/commit/febc63edef375bd82db48b7fb460ec5a601ab872)
#### [v3.2.2](https://github.com/th-ch/youtube-music/compare/v3.2.1...v3.2.2) #### [v3.2.2](https://github.com/th-ch/youtube-music/compare/v3.2.1...v3.2.2)
> 5 January 2024
- feat(tray): Add song info and paused icon [`#1592`](https://github.com/th-ch/youtube-music/pull/1592) - feat(tray): Add song info and paused icon [`#1592`](https://github.com/th-ch/youtube-music/pull/1592)
- fix(skip-silences): fix audio distorted [`#1141`](https://github.com/th-ch/youtube-music/issues/1141) - fix(skip-silences): fix audio distorted [`#1141`](https://github.com/th-ch/youtube-music/issues/1141)
- chore(deps): update dependency rollup to v4.9.3 [`0c3c380`](https://github.com/th-ch/youtube-music/commit/0c3c3805918adf2a185a7f1dc67ea3af8135863d) - chore(deps): update dependency rollup to v4.9.3 [`0c3c380`](https://github.com/th-ch/youtube-music/commit/0c3c3805918adf2a185a7f1dc67ea3af8135863d)

View File

@ -478,7 +478,7 @@
</a> </a>
</li> </li>
</ul> </ul>
<div class="footer-copyright">© 2021 th-ch</div> <div class="footer-copyright">© 2024 th-ch</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
{ {
"name": "youtube-music", "name": "youtube-music",
"productName": "YouTube Music", "productName": "YouTube Music",
"version": "3.2.2", "version": "3.3.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",
@ -166,7 +166,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.8.2", "i18next": "23.8.3",
"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.12", "node-html-parser": "6.1.12",
@ -176,7 +176,7 @@
"serve": "14.2.1", "serve": "14.2.1",
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9", "simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
"solid-floating-ui": "0.3.1", "solid-floating-ui": "0.3.1",
"solid-js": "1.8.14", "solid-js": "1.8.15",
"solid-styled-components": "0.28.5", "solid-styled-components": "0.28.5",
"solid-transition-group": "0.2.3", "solid-transition-group": "0.2.3",
"ts-morph": "21.0.1", "ts-morph": "21.0.1",
@ -197,8 +197,8 @@
"builtin-modules": "3.3.0", "builtin-modules": "3.3.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.69", "discord-api-types": "0.37.70",
"electron": "28.2.2", "electron": "28.2.3",
"electron-builder": "24.9.1", "electron-builder": "24.9.1",
"electron-devtools-installer": "3.2.0", "electron-devtools-installer": "3.2.0",
"electron-vite": "2.0.0", "electron-vite": "2.0.0",
@ -211,13 +211,13 @@
"glob": "10.3.10", "glob": "10.3.10",
"node-gyp": "10.0.1", "node-gyp": "10.0.1",
"playwright": "1.41.2", "playwright": "1.41.2",
"rollup": "4.10.0", "rollup": "4.12.0",
"typescript": "5.3.3", "typescript": "5.3.3",
"utf-8-validate": "6.0.3", "utf-8-validate": "6.0.3",
"vite": "5.1.1", "vite": "5.1.3",
"vite-plugin-inspect": "0.8.3", "vite-plugin-inspect": "0.8.3",
"vite-plugin-resolve": "2.5.1", "vite-plugin-resolve": "2.5.1",
"vite-plugin-solid": "2.9.1", "vite-plugin-solid": "2.10.1",
"ws": "8.16.0" "ws": "8.16.0"
}, },
"auto-changelog": { "auto-changelog": {
@ -226,5 +226,5 @@
"unreleased": true, "unreleased": true,
"output": "changelog.md" "output": "changelog.md"
}, },
"packageManager": "pnpm@8.15.1" "packageManager": "pnpm@8.15.3"
} }

240
pnpm-lock.yaml generated
View File

@ -23,16 +23,16 @@ patchedDependencies:
dependencies: dependencies:
'@cliqz/adblocker-electron': '@cliqz/adblocker-electron':
specifier: 1.26.15 specifier: 1.26.15
version: 1.26.15(electron@28.2.2) version: 1.26.15(electron@28.2.3)
'@cliqz/adblocker-electron-preload': '@cliqz/adblocker-electron-preload':
specifier: 1.26.15 specifier: 1.26.15
version: 1.26.15(electron@28.2.2) version: 1.26.15(electron@28.2.3)
'@electron-toolkit/tsconfig': '@electron-toolkit/tsconfig':
specifier: 1.0.1 specifier: 1.0.1
version: 1.0.1(@types/node@20.11.0) version: 1.0.1(@types/node@20.11.0)
'@electron/remote': '@electron/remote':
specifier: 2.1.2 specifier: 2.1.2
version: 2.1.2(electron@28.2.2) version: 2.1.2(electron@28.2.3)
'@ffmpeg.wasm/core-mt': '@ffmpeg.wasm/core-mt':
specifier: 0.12.0 specifier: 0.12.0
version: 0.12.0 version: 0.12.0
@ -71,7 +71,7 @@ dependencies:
version: 10.2.0 version: 10.2.0
custom-electron-prompt: custom-electron-prompt:
specifier: 1.5.7 specifier: 1.5.7
version: 1.5.7(electron@28.2.2) version: 1.5.7(electron@28.2.3)
dbus-next: dbus-next:
specifier: 0.10.2 specifier: 0.10.2
version: 0.10.2 version: 0.10.2
@ -112,8 +112,8 @@ dependencies:
specifier: 9.0.5 specifier: 9.0.5
version: 9.0.5 version: 9.0.5
i18next: i18next:
specifier: 23.8.2 specifier: 23.8.3
version: 23.8.2 version: 23.8.3
keyboardevent-from-electron-accelerator: keyboardevent-from-electron-accelerator:
specifier: 2.0.0 specifier: 2.0.0
version: 2.0.0 version: 2.0.0
@ -140,16 +140,16 @@ dependencies:
version: github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6 version: github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6
solid-floating-ui: solid-floating-ui:
specifier: 0.3.1 specifier: 0.3.1
version: 0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.14) version: 0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.15)
solid-js: solid-js:
specifier: 1.8.14 specifier: 1.8.15
version: 1.8.14 version: 1.8.15
solid-styled-components: solid-styled-components:
specifier: 0.28.5 specifier: 0.28.5
version: 0.28.5(solid-js@1.8.14) version: 0.28.5(solid-js@1.8.15)
solid-transition-group: solid-transition-group:
specifier: 0.2.3 specifier: 0.2.3
version: 0.2.3(solid-js@1.8.14) version: 0.2.3(solid-js@1.8.15)
ts-morph: ts-morph:
specifier: 21.0.1 specifier: 21.0.1
version: 21.0.1 version: 21.0.1
@ -201,11 +201,11 @@ devDependencies:
specifier: 5.1.0 specifier: 5.1.0
version: 5.1.0 version: 5.1.0
discord-api-types: discord-api-types:
specifier: 0.37.69 specifier: 0.37.70
version: 0.37.69 version: 0.37.70
electron: electron:
specifier: 28.2.2 specifier: 28.2.3
version: 28.2.2 version: 28.2.3
electron-builder: electron-builder:
specifier: 24.9.1 specifier: 24.9.1
version: 24.9.1 version: 24.9.1
@ -214,7 +214,7 @@ devDependencies:
version: 3.2.0 version: 3.2.0
electron-vite: electron-vite:
specifier: 2.0.0 specifier: 2.0.0
version: 2.0.0(vite@5.1.1) version: 2.0.0(vite@5.1.3)
esbuild: esbuild:
specifier: 0.20.0 specifier: 0.20.0
version: 0.20.0 version: 0.20.0
@ -243,8 +243,8 @@ devDependencies:
specifier: 1.41.2 specifier: 1.41.2
version: 1.41.2 version: 1.41.2
rollup: rollup:
specifier: 4.10.0 specifier: 4.12.0
version: 4.10.0 version: 4.12.0
typescript: typescript:
specifier: 5.3.3 specifier: 5.3.3
version: 5.3.3 version: 5.3.3
@ -252,17 +252,17 @@ devDependencies:
specifier: 6.0.3 specifier: 6.0.3
version: 6.0.3 version: 6.0.3
vite: vite:
specifier: 5.1.1 specifier: 5.1.3
version: 5.1.1(@types/node@20.11.0) version: 5.1.3(@types/node@20.11.0)
vite-plugin-inspect: vite-plugin-inspect:
specifier: 0.8.3 specifier: 0.8.3
version: 0.8.3(rollup@4.10.0)(vite@5.1.1) version: 0.8.3(rollup@4.12.0)(vite@5.1.3)
vite-plugin-resolve: vite-plugin-resolve:
specifier: 2.5.1 specifier: 2.5.1
version: 2.5.1 version: 2.5.1
vite-plugin-solid: vite-plugin-solid:
specifier: 2.9.1 specifier: 2.10.1
version: 2.9.1(solid-js@1.8.14)(vite@5.1.1) version: 2.10.1(solid-js@1.8.15)(vite@5.1.3)
ws: ws:
specifier: 8.16.0 specifier: 8.16.0
version: 8.16.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) version: 8.16.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
@ -578,23 +578,23 @@ packages:
'@cliqz/adblocker-extended-selectors': 1.26.15 '@cliqz/adblocker-extended-selectors': 1.26.15
dev: false dev: false
/@cliqz/adblocker-electron-preload@1.26.15(electron@28.2.2): /@cliqz/adblocker-electron-preload@1.26.15(electron@28.2.3):
resolution: {integrity: sha512-nGfY84iQitDkiz9JTPdATIGuesPo8xcNJiVjWJ4eVtncNBnVvpGSOBI7HlOAPxKsJMDA42vMujm8dIVavTtnBg==} resolution: {integrity: sha512-nGfY84iQitDkiz9JTPdATIGuesPo8xcNJiVjWJ4eVtncNBnVvpGSOBI7HlOAPxKsJMDA42vMujm8dIVavTtnBg==}
peerDependencies: peerDependencies:
electron: '>11' electron: '>11'
dependencies: dependencies:
'@cliqz/adblocker-content': 1.26.15 '@cliqz/adblocker-content': 1.26.15
electron: 28.2.2 electron: 28.2.3
dev: false dev: false
/@cliqz/adblocker-electron@1.26.15(electron@28.2.2): /@cliqz/adblocker-electron@1.26.15(electron@28.2.3):
resolution: {integrity: sha512-pOidIXaKoX7R/i/klVOEj/CVkXvXFPKkDp4UTlSOC5Xn7mRtLia8hNJAuLiL3VsJR18PFhBTaPPipd2aVR2+yA==} resolution: {integrity: sha512-pOidIXaKoX7R/i/klVOEj/CVkXvXFPKkDp4UTlSOC5Xn7mRtLia8hNJAuLiL3VsJR18PFhBTaPPipd2aVR2+yA==}
peerDependencies: peerDependencies:
electron: '>11' electron: '>11'
dependencies: dependencies:
'@cliqz/adblocker': 1.26.15 '@cliqz/adblocker': 1.26.15
'@cliqz/adblocker-electron-preload': 1.26.15(electron@28.2.2) '@cliqz/adblocker-electron-preload': 1.26.15(electron@28.2.3)
electron: 28.2.2 electron: 28.2.3
tldts-experimental: 6.1.2 tldts-experimental: 6.1.2
dev: false dev: false
@ -683,12 +683,12 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@electron/remote@2.1.2(electron@28.2.2): /@electron/remote@2.1.2(electron@28.2.3):
resolution: {integrity: sha512-EPwNx+nhdrTBxyCqXt/pftoQg/ybtWDW3DUWHafejvnB1ZGGfMpv6e15D8KeempocjXe78T7WreyGGb3mlZxdA==} resolution: {integrity: sha512-EPwNx+nhdrTBxyCqXt/pftoQg/ybtWDW3DUWHafejvnB1ZGGfMpv6e15D8KeempocjXe78T7WreyGGb3mlZxdA==}
peerDependencies: peerDependencies:
electron: '>= 13.0.0' electron: '>= 13.0.0'
dependencies: dependencies:
electron: 28.2.2 electron: 28.2.3
dev: false dev: false
/@electron/universal@2.0.1: /@electron/universal@2.0.1:
@ -1391,7 +1391,7 @@ packages:
resolution: {integrity: sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q==} resolution: {integrity: sha512-yvwa+aCyYI/UjeD39BnpMypG8N06l86wIDW1/PAc6ihBRnodIfZDwccxQN3n1t74wduzaz74m4ZMHZnB06567Q==}
dev: false dev: false
/@rollup/pluginutils@5.1.0(rollup@4.10.0): /@rollup/pluginutils@5.1.0(rollup@4.12.0):
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
peerDependencies: peerDependencies:
@ -1403,107 +1403,107 @@ packages:
'@types/estree': 1.0.5 '@types/estree': 1.0.5
estree-walker: 2.0.2 estree-walker: 2.0.2
picomatch: 2.3.1 picomatch: 2.3.1
rollup: 4.10.0 rollup: 4.12.0
dev: true dev: true
/@rollup/rollup-android-arm-eabi@4.10.0: /@rollup/rollup-android-arm-eabi@4.12.0:
resolution: {integrity: sha512-/MeDQmcD96nVoRumKUljsYOLqfv1YFJps+0pTrb2Z9Nl/w5qNUysMaWQsrd1mvAlNT4yza1iVyIu4Q4AgF6V3A==} resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-android-arm64@4.10.0: /@rollup/rollup-android-arm64@4.12.0:
resolution: {integrity: sha512-lvu0jK97mZDJdpZKDnZI93I0Om8lSDaiPx3OiCk0RXn3E8CMPJNS/wxjAvSJJzhhZpfjXsjLWL8LnS6qET4VNQ==} resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-darwin-arm64@4.10.0: /@rollup/rollup-darwin-arm64@4.12.0:
resolution: {integrity: sha512-uFpayx8I8tyOvDkD7X6n0PriDRWxcqEjqgtlxnUA/G9oS93ur9aZ8c8BEpzFmsed1TH5WZNG5IONB8IiW90TQg==} resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-darwin-x64@4.10.0: /@rollup/rollup-darwin-x64@4.12.0:
resolution: {integrity: sha512-nIdCX03qFKoR/MwQegQBK+qZoSpO3LESurVAC6s6jazLA1Mpmgzo3Nj3H1vydXp/JM29bkCiuF7tDuToj4+U9Q==} resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm-gnueabihf@4.10.0: /@rollup/rollup-linux-arm-gnueabihf@4.12.0:
resolution: {integrity: sha512-Fz7a+y5sYhYZMQFRkOyCs4PLhICAnxRX/GnWYReaAoruUzuRtcf+Qnw+T0CoAWbHCuz2gBUwmWnUgQ67fb3FYw==} resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm64-gnu@4.10.0: /@rollup/rollup-linux-arm64-gnu@4.12.0:
resolution: {integrity: sha512-yPtF9jIix88orwfTi0lJiqINnlWo6p93MtZEoaehZnmCzEmLL0eqjA3eGVeyQhMtxdV+Mlsgfwhh0+M/k1/V7Q==} resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm64-musl@4.10.0: /@rollup/rollup-linux-arm64-musl@4.12.0:
resolution: {integrity: sha512-9GW9yA30ib+vfFiwjX+N7PnjTnCMiUffhWj4vkG4ukYv1kJ4T9gHNg8zw+ChsOccM27G9yXrEtMScf1LaCuoWQ==} resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-riscv64-gnu@4.10.0: /@rollup/rollup-linux-riscv64-gnu@4.12.0:
resolution: {integrity: sha512-X1ES+V4bMq2ws5fF4zHornxebNxMXye0ZZjUrzOrf7UMx1d6wMQtfcchZ8SqUnQPPHdOyOLW6fTcUiFgHFadRA==} resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-x64-gnu@4.10.0: /@rollup/rollup-linux-x64-gnu@4.12.0:
resolution: {integrity: sha512-w/5OpT2EnI/Xvypw4FIhV34jmNqU5PZjZue2l2Y3ty1Ootm3SqhI+AmfhlUYGBTd9JnpneZCDnt3uNOiOBkMyw==} resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-x64-musl@4.10.0: /@rollup/rollup-linux-x64-musl@4.12.0:
resolution: {integrity: sha512-q/meftEe3QlwQiGYxD9rWwB21DoKQ9Q8wA40of/of6yGHhZuGfZO0c3WYkN9dNlopHlNT3mf5BPsUSxoPuVQaw==} resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-arm64-msvc@4.10.0: /@rollup/rollup-win32-arm64-msvc@4.12.0:
resolution: {integrity: sha512-NrR6667wlUfP0BHaEIKgYM/2va+Oj+RjZSASbBMnszM9k+1AmliRjHc3lJIiOehtSSjqYiO7R6KLNrWOX+YNSQ==} resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-ia32-msvc@4.10.0: /@rollup/rollup-win32-ia32-msvc@4.12.0:
resolution: {integrity: sha512-FV0Tpt84LPYDduIDcXvEC7HKtyXxdvhdAOvOeWMWbQNulxViH2O07QXkT/FffX4FqEI02jEbCJbr+YcuKdyyMg==} resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-x64-msvc@4.10.0: /@rollup/rollup-win32-x64-msvc@4.12.0:
resolution: {integrity: sha512-OZoJd+o5TaTSQeFFQ6WjFCiltiYVjIdsXxwu/XZ8qRpsvMQr4UsVrE5UyT9RIvsnuF47DqkJKhhVZ2Q9YW9IpQ==} resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
@ -1521,29 +1521,29 @@ packages:
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
engines: {node: '>=10'} engines: {node: '>=10'}
/@solid-primitives/refs@1.0.6(solid-js@1.8.14): /@solid-primitives/refs@1.0.6(solid-js@1.8.15):
resolution: {integrity: sha512-ruh4YdVMxThEVnvqbpeLXKojW442vpFU8q7dSKtElGOTa31aKOAkRb9BTbdaTwVjN4BEq79fiiYIXozJNl4dSw==} resolution: {integrity: sha512-ruh4YdVMxThEVnvqbpeLXKojW442vpFU8q7dSKtElGOTa31aKOAkRb9BTbdaTwVjN4BEq79fiiYIXozJNl4dSw==}
peerDependencies: peerDependencies:
solid-js: ^1.6.12 solid-js: ^1.6.12
dependencies: dependencies:
'@solid-primitives/utils': 6.2.2(solid-js@1.8.14) '@solid-primitives/utils': 6.2.2(solid-js@1.8.15)
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/@solid-primitives/transition-group@1.0.4(solid-js@1.8.14): /@solid-primitives/transition-group@1.0.4(solid-js@1.8.15):
resolution: {integrity: sha512-9nPg6HYAmEi7riH0C2bSCVw/2asgGSzHuN0yFFYyK9JgmXqJgyeyA+6thZbj7GgUQMRhtBxpH8yG7N2nEh8ttA==} resolution: {integrity: sha512-9nPg6HYAmEi7riH0C2bSCVw/2asgGSzHuN0yFFYyK9JgmXqJgyeyA+6thZbj7GgUQMRhtBxpH8yG7N2nEh8ttA==}
peerDependencies: peerDependencies:
solid-js: ^1.6.12 solid-js: ^1.6.12
dependencies: dependencies:
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/@solid-primitives/utils@6.2.2(solid-js@1.8.14): /@solid-primitives/utils@6.2.2(solid-js@1.8.15):
resolution: {integrity: sha512-11ypVbp987XxETeRqY5Y3OmmTpm8/jZqJXRvo6AyqBthzkvvjEdReuUMU2yVb+pwWGxfZpWHZ6EUCcGXUMhfwg==} resolution: {integrity: sha512-11ypVbp987XxETeRqY5Y3OmmTpm8/jZqJXRvo6AyqBthzkvvjEdReuUMU2yVb+pwWGxfZpWHZ6EUCcGXUMhfwg==}
peerDependencies: peerDependencies:
solid-js: ^1.6.12 solid-js: ^1.6.12
dependencies: dependencies:
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/@szmarczak/http-timer@4.0.6: /@szmarczak/http-timer@4.0.6:
@ -1639,7 +1639,7 @@ packages:
/@types/electron-localshortcut@3.1.3: /@types/electron-localshortcut@3.1.3:
resolution: {integrity: sha512-D+CRdDTRZ4/9UmcSaZ5qvW4uq2VyyVmqsH9cdNReB4CL6MSIgyhr9w2PKeNEb0J/ZS7db7irJM/+ZiA5uSQsLw==} resolution: {integrity: sha512-D+CRdDTRZ4/9UmcSaZ5qvW4uq2VyyVmqsH9cdNReB4CL6MSIgyhr9w2PKeNEb0J/ZS7db7irJM/+ZiA5uSQsLw==}
dependencies: dependencies:
electron: 28.2.2 electron: 28.2.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@ -2763,12 +2763,12 @@ packages:
/csstype@3.1.3: /csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
/custom-electron-prompt@1.5.7(electron@28.2.2): /custom-electron-prompt@1.5.7(electron@28.2.3):
resolution: {integrity: sha512-ptRPJr6CpT06GWLMtg3GD2Lr7gWfXdWI+hR1S39eq+m/mUa2E118YmX6mPCbHdg5QB/W9UVhSpRqBM8FUh1G8w==} resolution: {integrity: sha512-ptRPJr6CpT06GWLMtg3GD2Lr7gWfXdWI+hR1S39eq+m/mUa2E118YmX6mPCbHdg5QB/W9UVhSpRqBM8FUh1G8w==}
peerDependencies: peerDependencies:
electron: '>=10.0.0' electron: '>=10.0.0'
dependencies: dependencies:
electron: 28.2.2 electron: 28.2.3
dev: false dev: false
/data-uri-to-buffer@4.0.1: /data-uri-to-buffer@4.0.1:
@ -2990,8 +2990,8 @@ packages:
path-type: 4.0.0 path-type: 4.0.0
dev: true dev: true
/discord-api-types@0.37.69: /discord-api-types@0.37.70:
resolution: {integrity: sha512-c0rHc5YGNIXQkI+V7QwP8y77wxo74ITNeZmMwxtKC/l01aIF/gKBG/U2MKhUt2iaeRH9XwAt9PT3AI9JQVvKVA==} resolution: {integrity: sha512-8EtfZR0KwOK+yP5q/llWILdUAPmGmF1LmcVUYf7+gtGigz2pu6WR38ZN+IWtMzohY1Ujl2u3KOdbFvrEz9EC8w==}
dev: true dev: true
/dmg-builder@24.9.1: /dmg-builder@24.9.1:
@ -3229,7 +3229,7 @@ packages:
- supports-color - supports-color
dev: false dev: false
/electron-vite@2.0.0(vite@5.1.1): /electron-vite@2.0.0(vite@5.1.3):
resolution: {integrity: sha512-EQiuPVSwJQRPGbZiVrCsCFMDVfNyNtSpDiyUV4fNwPKNadTjBfYMOudnLUpSeBTocKUZYf58SXSzSCAkNg0GTQ==} resolution: {integrity: sha512-EQiuPVSwJQRPGbZiVrCsCFMDVfNyNtSpDiyUV4fNwPKNadTjBfYMOudnLUpSeBTocKUZYf58SXSzSCAkNg0GTQ==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true hasBin: true
@ -3246,13 +3246,13 @@ packages:
esbuild: 0.19.12 esbuild: 0.19.12
magic-string: 0.30.5 magic-string: 0.30.5
picocolors: 1.0.0 picocolors: 1.0.0
vite: 5.1.1(@types/node@20.11.0) vite: 5.1.3(@types/node@20.11.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/electron@28.2.2: /electron@28.2.3:
resolution: {integrity: sha512-8UcvIGFcjplHdjPFNAHVFg5bS0atDyT3Zx21WwuE4iLfxcAMsyMEOgrQX3im5LibA8srwsUZs7Cx0JAUfcQRpw==} resolution: {integrity: sha512-he9nGphZo03ejDjYBXpmFVw0KBKogXvR2tYxE4dyYvnfw42uaFIBFrwGeenvqoEOfheJfcI0u4rFG6h3QxDwnA==}
engines: {node: '>= 12.20.55'} engines: {node: '>= 12.20.55'}
hasBin: true hasBin: true
requiresBuild: true requiresBuild: true
@ -4327,8 +4327,8 @@ packages:
engines: {node: '>=10.17.0'} engines: {node: '>=10.17.0'}
dev: false dev: false
/i18next@23.8.2: /i18next@23.8.3:
resolution: {integrity: sha512-Z84zyEangrlERm0ZugVy4bIt485e/H8VecGUZkZWrH7BDePG6jT73QdL9EA1tRTTVVMpry/MgWIP1FjEn0DRXA==} resolution: {integrity: sha512-IQn6Tfn+XkIRHjC/z3uQSGLhsRC6Y14kgyrsgoPqnFD9MqbNt2B9MF3Ch4p114pEVPQ2qktE2nd0aYr7UxRLKA==}
dependencies: dependencies:
'@babel/runtime': 7.23.8 '@babel/runtime': 7.23.8
dev: false dev: false
@ -5788,26 +5788,26 @@ packages:
sprintf-js: 1.1.3 sprintf-js: 1.1.3
optional: true optional: true
/rollup@4.10.0: /rollup@4.12.0:
resolution: {integrity: sha512-t2v9G2AKxcQ8yrG+WGxctBes1AomT0M4ND7jTFBCVPXQ/WFTvNSefIrNSmLKhIKBrvN8SG+CZslimJcT3W2u2g==} resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
'@types/estree': 1.0.5 '@types/estree': 1.0.5
optionalDependencies: optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.10.0 '@rollup/rollup-android-arm-eabi': 4.12.0
'@rollup/rollup-android-arm64': 4.10.0 '@rollup/rollup-android-arm64': 4.12.0
'@rollup/rollup-darwin-arm64': 4.10.0 '@rollup/rollup-darwin-arm64': 4.12.0
'@rollup/rollup-darwin-x64': 4.10.0 '@rollup/rollup-darwin-x64': 4.12.0
'@rollup/rollup-linux-arm-gnueabihf': 4.10.0 '@rollup/rollup-linux-arm-gnueabihf': 4.12.0
'@rollup/rollup-linux-arm64-gnu': 4.10.0 '@rollup/rollup-linux-arm64-gnu': 4.12.0
'@rollup/rollup-linux-arm64-musl': 4.10.0 '@rollup/rollup-linux-arm64-musl': 4.12.0
'@rollup/rollup-linux-riscv64-gnu': 4.10.0 '@rollup/rollup-linux-riscv64-gnu': 4.12.0
'@rollup/rollup-linux-x64-gnu': 4.10.0 '@rollup/rollup-linux-x64-gnu': 4.12.0
'@rollup/rollup-linux-x64-musl': 4.10.0 '@rollup/rollup-linux-x64-musl': 4.12.0
'@rollup/rollup-win32-arm64-msvc': 4.10.0 '@rollup/rollup-win32-arm64-msvc': 4.12.0
'@rollup/rollup-win32-ia32-msvc': 4.10.0 '@rollup/rollup-win32-ia32-msvc': 4.12.0
'@rollup/rollup-win32-x64-msvc': 4.10.0 '@rollup/rollup-win32-x64-msvc': 4.12.0
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
@ -6060,7 +6060,7 @@ packages:
ip: 2.0.0 ip: 2.0.0
smart-buffer: 4.2.0 smart-buffer: 4.2.0
/solid-floating-ui@0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.14): /solid-floating-ui@0.3.1(@floating-ui/dom@1.6.3)(solid-js@1.8.15):
resolution: {integrity: sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q==} resolution: {integrity: sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
@ -6068,17 +6068,17 @@ packages:
solid-js: ^1.8 solid-js: ^1.8
dependencies: dependencies:
'@floating-ui/dom': 1.6.3 '@floating-ui/dom': 1.6.3
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/solid-js@1.8.14: /solid-js@1.8.15:
resolution: {integrity: sha512-kDfgHBm+ROVLDVuqaXh/jYz0ZVJ29TYfVsKsgDPtNcjoyaPtOvDX2l0tVnthjLdEXr7vDTYeqEYFfMkZakDsOQ==} resolution: {integrity: sha512-d0QP/efr3UVcwGgWVPveQQ0IHOH6iU7yUhc2piy8arNG8wxKmvUy1kFxyF8owpmfCWGB87usDKMaVnsNYZm+Vw==}
dependencies: dependencies:
csstype: 3.1.3 csstype: 3.1.3
seroval: 1.0.4 seroval: 1.0.4
seroval-plugins: 1.0.4(seroval@1.0.4) seroval-plugins: 1.0.4(seroval@1.0.4)
/solid-refresh@0.6.3(solid-js@1.8.14): /solid-refresh@0.6.3(solid-js@1.8.15):
resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==}
peerDependencies: peerDependencies:
solid-js: ^1.3 solid-js: ^1.3
@ -6086,28 +6086,28 @@ packages:
'@babel/generator': 7.23.6 '@babel/generator': 7.23.6
'@babel/helper-module-imports': 7.22.15 '@babel/helper-module-imports': 7.22.15
'@babel/types': 7.23.6 '@babel/types': 7.23.6
solid-js: 1.8.14 solid-js: 1.8.15
dev: true dev: true
/solid-styled-components@0.28.5(solid-js@1.8.14): /solid-styled-components@0.28.5(solid-js@1.8.15):
resolution: {integrity: sha512-vwTcdp76wZNnESIzB6rRZ3U55NgcSAQXCiiRIiEFhxTFqT0bEh/warNT1qaRZu4OkAzrBkViOngF35ktI8sc4A==} resolution: {integrity: sha512-vwTcdp76wZNnESIzB6rRZ3U55NgcSAQXCiiRIiEFhxTFqT0bEh/warNT1qaRZu4OkAzrBkViOngF35ktI8sc4A==}
peerDependencies: peerDependencies:
solid-js: ^1.4.4 solid-js: ^1.4.4
dependencies: dependencies:
csstype: 3.1.3 csstype: 3.1.3
goober: 2.1.14(csstype@3.1.3) goober: 2.1.14(csstype@3.1.3)
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/solid-transition-group@0.2.3(solid-js@1.8.14): /solid-transition-group@0.2.3(solid-js@1.8.15):
resolution: {integrity: sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==} resolution: {integrity: sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==}
engines: {node: '>=18.0.0', pnpm: '>=8.6.0'} engines: {node: '>=18.0.0', pnpm: '>=8.6.0'}
peerDependencies: peerDependencies:
solid-js: ^1.6.12 solid-js: ^1.6.12
dependencies: dependencies:
'@solid-primitives/refs': 1.0.6(solid-js@1.8.14) '@solid-primitives/refs': 1.0.6(solid-js@1.8.15)
'@solid-primitives/transition-group': 1.0.4(solid-js@1.8.14) '@solid-primitives/transition-group': 1.0.4(solid-js@1.8.15)
solid-js: 1.8.14 solid-js: 1.8.15
dev: false dev: false
/source-map-js@1.0.2: /source-map-js@1.0.2:
@ -6498,8 +6498,8 @@ packages:
/undici-types@5.26.5: /undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
/undici@5.28.2: /undici@5.28.3:
resolution: {integrity: sha512-wh1pHJHnUeQV5Xa8/kyQhO7WFa8M34l026L5P/+2TYiakvGy5Rdc8jWZVyG7ieht/0WgJLEd3kcU5gKx+6GC8w==} resolution: {integrity: sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==}
engines: {node: '>=14.0'} engines: {node: '>=14.0'}
dependencies: dependencies:
'@fastify/busboy': 2.1.0 '@fastify/busboy': 2.1.0
@ -6616,7 +6616,7 @@ packages:
dev: true dev: true
optional: true optional: true
/vite-plugin-inspect@0.8.3(rollup@4.10.0)(vite@5.1.1): /vite-plugin-inspect@0.8.3(rollup@4.12.0)(vite@5.1.3):
resolution: {integrity: sha512-SBVzOIdP/kwe6hjkt7LSW4D0+REqqe58AumcnCfRNw4Kt3mbS9pEBkch+nupu2PBxv2tQi69EQHQ1ZA1vgB/Og==} resolution: {integrity: sha512-SBVzOIdP/kwe6hjkt7LSW4D0+REqqe58AumcnCfRNw4Kt3mbS9pEBkch+nupu2PBxv2tQi69EQHQ1ZA1vgB/Og==}
engines: {node: '>=14'} engines: {node: '>=14'}
peerDependencies: peerDependencies:
@ -6627,7 +6627,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@antfu/utils': 0.7.7 '@antfu/utils': 0.7.7
'@rollup/pluginutils': 5.1.0(rollup@4.10.0) '@rollup/pluginutils': 5.1.0(rollup@4.12.0)
debug: 4.3.4 debug: 4.3.4
error-stack-parser-es: 0.1.1 error-stack-parser-es: 0.1.1
fs-extra: 11.2.0 fs-extra: 11.2.0
@ -6635,7 +6635,7 @@ packages:
perfect-debounce: 1.0.0 perfect-debounce: 1.0.0
picocolors: 1.0.0 picocolors: 1.0.0
sirv: 2.0.4 sirv: 2.0.4
vite: 5.1.1(@types/node@20.11.0) vite: 5.1.3(@types/node@20.11.0)
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
- supports-color - supports-color
@ -6647,8 +6647,8 @@ packages:
lib-esm: 0.4.2 lib-esm: 0.4.2
dev: true dev: true
/vite-plugin-solid@2.9.1(solid-js@1.8.14)(vite@5.1.1): /vite-plugin-solid@2.10.1(solid-js@1.8.15)(vite@5.1.3):
resolution: {integrity: sha512-RC4hj+lbvljw57BbMGDApvEOPEh14lwrr/GeXRLNQLcR1qnOdzOwwTSFy13Gj/6FNIZpBEl0bWPU+VYFawrqUw==} resolution: {integrity: sha512-kfVdNLWaJqaJVL52U6iCCKNW/nXE7bS1VVGOWPGllOkJfcNILymVSY0LCBLSnyy0iYnRtrXpiHm14rMuzeC7CA==}
peerDependencies: peerDependencies:
'@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.*
solid-js: ^1.7.2 solid-js: ^1.7.2
@ -6661,16 +6661,16 @@ packages:
'@types/babel__core': 7.20.5 '@types/babel__core': 7.20.5
babel-preset-solid: 1.8.12(@babel/core@7.23.7) babel-preset-solid: 1.8.12(@babel/core@7.23.7)
merge-anything: 5.1.7 merge-anything: 5.1.7
solid-js: 1.8.14 solid-js: 1.8.15
solid-refresh: 0.6.3(solid-js@1.8.14) solid-refresh: 0.6.3(solid-js@1.8.15)
vite: 5.1.1(@types/node@20.11.0) vite: 5.1.3(@types/node@20.11.0)
vitefu: 0.2.5(vite@5.1.1) vitefu: 0.2.5(vite@5.1.3)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/vite@5.1.1(@types/node@20.11.0): /vite@5.1.3(@types/node@20.11.0):
resolution: {integrity: sha512-wclpAgY3F1tR7t9LL5CcHC41YPkQIpKUGeIuT8MdNwNZr6OqOTLs7JX5vIHAtzqLWXts0T+GDrh9pN2arneKqg==} resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@ -6700,12 +6700,12 @@ packages:
'@types/node': 20.11.0 '@types/node': 20.11.0
esbuild: 0.19.12 esbuild: 0.19.12
postcss: 8.4.35 postcss: 8.4.35
rollup: 4.10.0 rollup: 4.12.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
/vitefu@0.2.5(vite@5.1.1): /vitefu@0.2.5(vite@5.1.3):
resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==}
peerDependencies: peerDependencies:
vite: ^3.0.0 || ^4.0.0 || ^5.0.0 vite: ^3.0.0 || ^4.0.0 || ^5.0.0
@ -6713,7 +6713,7 @@ packages:
vite: vite:
optional: true optional: true
dependencies: dependencies:
vite: 5.1.1(@types/node@20.11.0) vite: 5.1.3(@types/node@20.11.0)
dev: true dev: true
/vudio@2.1.1(patch_hash=7iux5msqpgl3octdmwy4uspwoe): /vudio@2.1.1(patch_hash=7iux5msqpgl3octdmwy4uspwoe):
@ -6896,7 +6896,7 @@ packages:
dependencies: dependencies:
jintr: 1.1.0 jintr: 1.1.0
tslib: 2.6.2 tslib: 2.6.2
undici: 5.28.2 undici: 5.28.3
dev: false dev: false
github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6: github.com/organization/Simple-YouTube-Age-Restriction-Bypass/4e2db89ccb2fb880c5110add9ff3f1dfb78d0ff6:

View File

@ -16,24 +16,42 @@ const migrations = {
secret?: string; secret?: string;
}; };
if (lastfmConfig) { if (lastfmConfig) {
const scrobblerConfig = store.get( let scrobblerConfig = store.get(
'plugins.scrobbler', 'plugins.scrobbler',
) as { ) as {
enabled?: boolean; enabled?: boolean;
scrobblers: { scrobblers?: {
lastfm: { lastfm?: {
enabled?: boolean; enabled?: boolean;
token?: string; token?: string;
session_key?: string; sessionKey?: string;
api_root?: string; apiRoot?: string;
api_key?: string; apiKey?: string;
secret?: string; secret?: string;
}; };
}; };
}; } | undefined;
scrobblerConfig.enabled = lastfmConfig.enabled; if (!scrobblerConfig) {
scrobblerConfig.scrobblers.lastfm = lastfmConfig; scrobblerConfig = {
enabled: lastfmConfig.enabled,
};
}
if (!scrobblerConfig.scrobblers) {
scrobblerConfig.scrobblers = {
lastfm: {},
};
}
scrobblerConfig.scrobblers.lastfm = {
enabled: lastfmConfig.enabled,
token: lastfmConfig.token,
sessionKey: lastfmConfig.session_key,
apiRoot: lastfmConfig.api_root,
apiKey: lastfmConfig.api_key,
secret: lastfmConfig.secret,
};
store.set('plugins.scrobbler', scrobblerConfig); store.set('plugins.scrobbler', scrobblerConfig);
} }
}, },

View File

@ -98,7 +98,7 @@
"submenu": { "submenu": {
"auto-reset-app-cache": "Mengatur ulang cache aplikasi saat aplikasi dimulai", "auto-reset-app-cache": "Mengatur ulang cache aplikasi saat aplikasi dimulai",
"disable-hardware-acceleration": "Menonaktifkan akselerasi perangkat keras", "disable-hardware-acceleration": "Menonaktifkan akselerasi perangkat keras",
"edit-config-json": "Edit config.json", "edit-config-json": "Ubah config.json",
"override-user-agent": "Mengesampingkan User-Agent", "override-user-agent": "Mengesampingkan User-Agent",
"restart-on-config-changes": "Mulai ulang pada perubahan konfigurasi", "restart-on-config-changes": "Mulai ulang pada perubahan konfigurasi",
"set-proxy": { "set-proxy": {
@ -194,7 +194,7 @@
"show": "Tampilkan jendela", "show": "Tampilkan jendela",
"tooltip": { "tooltip": {
"default": "YouTube Musik", "default": "YouTube Musik",
"with-song-info": "YouTube Music: {{artist}} - {{Judul}}" "with-song-info": "YouTube Music: {{artist}} - {{title}}"
} }
} }
}, },
@ -207,7 +207,7 @@
"name": "Pemblokir Iklan" "name": "Pemblokir Iklan"
}, },
"album-actions": { "album-actions": {
"description": "Menambahkan tombol Tidak Suka, Tidak Suka, Suka, dan Tidak Suka untuk menerapkannya ke semua lagu dalam daftar putar atau album", "description": "Tambah tombol Suka, Batal Suka, Tidak Suka dan Batal Tidak Suka untuk diterapkan ke semua lagu dalam daftar putar atau album",
"name": "Tindakan Album" "name": "Tindakan Album"
}, },
"album-color-theme": { "album-color-theme": {
@ -398,7 +398,285 @@
"video-id-not-found": "Video tidak ditemukan", "video-id-not-found": "Video tidak ditemukan",
"writing-id3": "Menulis tanda ID3…" "writing-id3": "Menulis tanda ID3…"
} }
},
"description": "Unduh MP3 / sumber suara secara langsung via antarmuka",
"menu": {
"choose-download-folder": "Pilih folder unduhan",
"download-playlist": "Unduh daftar putar",
"presets": "Prasetel",
"skip-existing": "Lewati berkas yang sudah ada"
},
"name": "Pengunduh",
"renderer": {
"can-not-update-progress": "Tidak dapat memperbarui proses"
},
"templates": {
"button": "Unduh"
} }
},
"exponential-volume": {
"description": "Buat penggeser volume menjadi eksponen sehingga memudahkan memilih volume yang lebih rendah.",
"name": "Volume Eksponen"
},
"in-app-menu": {
"description": "Buat bilah-menu terlihat indah, gelap atau serupa dengan album",
"menu": {
"hide-dom-window-controls": "Sembunyikan DOM pengendali jendela"
},
"name": "Menu di Aplikasi"
},
"lumiastream": {
"description": "Tambah dukungan Lumia Stream",
"name": "Lumia Stream [Beta]"
},
"lyrics-genius": {
"description": "Tambah dukungan lirik untuk kebanyakan lagu",
"menu": {
"romanized-lyrics": "Romanisasi Lirik"
},
"name": "Lirik Genius",
"renderer": {
"fetched-lyrics": "Lirik yang diambil untuk Genius"
}
},
"music-together": {
"description": "Bagikan daftar putar dengan yang lain. Saat host memainkan lagu, semua orang akan mendengarkan lagu yang sama",
"dialog": {
"enter-host": "Masukkan ID Host"
},
"internal": {
"save": "Simpan",
"track-source": "Sumber Trek",
"unknown-user": "Pengguna Tidak Diketahui"
},
"menu": {
"click-to-copy-id": "Salin ID Host",
"close": "Tutup Musik Bersama",
"connected-users": "Pengguna Terhubung",
"disconnect": "Putuskan Musik Bersama",
"empty-user": "Tidak ada pengguna terhubung",
"host": "Host Musik Bersama",
"join": "Gabung Musik Bersama",
"permission": {
"all": "Izinkan tamu untuk mengendalikan daftar putar dan pemutar",
"host-only": "Hanya host yang dapat mengendalikan daftar putar dan pemutar",
"playlist": "Izinkan tamu untuk mengendalikan daftar putar"
},
"set-permission": "Ubah Pengendali Izin",
"status": {
"disconnected": "Terputus",
"guest": "Terhubung sebagai Tamu",
"host": "Terhubung sebagai Host"
}
},
"name": "Musik Bersama [Beta]",
"toast": {
"add-song-failed": "Gagal untuk menambahkan lagu",
"closed": "Musik Bersama ditutup",
"disconnected": "Musik Bersama terputus",
"host-failed": "Gagal untuk memulai Musik Bersama",
"id-copied": "ID Host tersalin ke papan klip",
"id-copy-failed": "Gagal menyalin ID Host ke papan klip",
"join-failed": "Gagal untuk bergabung ke Musik Bersama",
"joined": "Bergabung ke Musik Bersama",
"permission-changed": "Perizinan Musik Bersama diubah ke \"{{permission}}\"",
"remove-song-failed": "Gagal menghapus lagu",
"user-connected": "{{name}} bergabung ke Musik Bersama",
"user-disconnected": "{{name}} meninggalkan Musik Bersama"
}
},
"navigation": {
"description": "panah navigasi Selanjutnya/Sebelumnya terintegrasi pada antarmuka, layaknya peramban kesukaan Anda",
"name": "Navigasi"
},
"no-google-login": {
"description": "Hapus tombol dan tautan masuk Google dari antarmuka",
"name": "Tanpa Google Login"
},
"notifications": {
"description": "Tampilkan pemberitahuan saat lagu dimainkan (pemberitahuan interaktif tersedia di Windows)",
"menu": {
"interactive": "Pemberitahuan Interaktif",
"interactive-settings": {
"label": "Pengaturan Interaktif",
"submenu": {
"hide-button-text": "Sembunyikan teks tombol",
"refresh-on-play-pause": "Segarkan saat Putar/Jeda",
"tray-controls": "Buka/Tutup saat baki ditekan"
}
},
"priority": "Prioritas Pemberitahuan",
"toast-style": "Gaya Toast",
"unpause-notification": "Tampilkan pemberitahuan saat tidak dijeda"
},
"name": "Pemberitahuan"
},
"picture-in-picture": {
"description": "Izinkan untuk memindahkan aplikasi ke mode gambar-dalam-gambar",
"menu": {
"always-on-top": "Selalu di atas",
"hotkey": {
"label": "Pintasan",
"prompt": {
"keybind-options": {
"hotkey": "Pintasan"
},
"label": "Pilih pintasan untuk beralih ke gambar-dalam-gambar",
"title": "Pintasan gambar-dalam-gambar"
}
},
"save-window-position": "Simpan posisi jendela",
"save-window-size": "Simpan ukuran jendela",
"use-native-pip": "Gunakan PiP bawaan peramban"
},
"name": "Gambar-dalam-gambar",
"templates": {
"button": "Gambar-dalam-gambar"
}
},
"playback-speed": {
"description": "Dengarkan cepat, dengarkan perlahan! Tambahkan penggeser untuk mengendalikan kecepatan lagu",
"name": "Kecepatan Pemutar",
"templates": {
"button": "Kecepatan"
}
},
"precise-volume": {
"description": "Kendalikan volume secara presisi menggunakan roda tetikus/pintasan, dengan HUD kustom dan langkah volume yang dapat diatur",
"menu": {
"arrows-shortcuts": "Kendali Tombol Panah Lokal",
"custom-volume-steps": "Atur Langkah Volume Kustom",
"global-shortcuts": "Pintasan Global"
},
"name": "Volume Presisi",
"prompt": {
"global-shortcuts": {
"keybind-options": {
"decrease": "Kurangi Volume",
"increase": "Tingkatkan Volume"
},
"label": "Pilih Pintasan Volume Global:",
"title": "Pintasan Volume Global"
},
"volume-steps": {
"label": "Pilih Langkah Peningkatan/Pengurangan Volume",
"title": "Langkah Volume"
}
}
},
"quality-changer": {
"backend": {
"dialog": {
"quality-changer": {
"detail": "Kualitas Terkini: {{quality}}",
"message": "Pilih Kualitas Video:",
"title": "Pilih Kualitas Video"
}
}
},
"description": "Izinkan untuk mengubah kualitas video dengan tombol pada hamparan video",
"name": "Pengubah Kualitas Video"
},
"scrobbler": {
"description": "Tambahkan dukungan scrobbling (mis. last.fm, Listenbrainz)",
"menu": {
"lastfm": {
"api-settings": "Pengaturan API Last.fm"
},
"listenbrainz": {
"token": "Masukkan token pengguna ListenBrainz"
},
"scrobble-other-media": "Scrobble media lain"
},
"name": "Scrobbler",
"prompt": {
"lastfm": {
"api-key": "Kunci API Last.fm",
"api-secret": "Secret API Last.fm"
},
"listenbrainz": {
"token": {
"label": "Masukkan token pengguna ListenBrainz Anda:",
"title": "Token ListenBrainz"
}
}
}
},
"shortcuts": {
"description": "Izinkan pengaturan pintasan global untuk pemutar (main/jeda/selanjutnya/sebelumnya) dan mematikan OSD media dengan mengesampingkan tombol media, mengaktifkan Ctrl/CMD + F untuk pencarian, mengaktifkan dukungan MPRIS Linux untuk tombol media, dan tombol pintasan kustom untuk pengguna lanjutan",
"menu": {
"override-media-keys": "Timpa Tombol Media",
"set-keybinds": "Atur Pengendali Lagu Global"
},
"name": "Pintasan (& MPRIS)",
"prompt": {
"keybind": {
"keybind-options": {
"next": "Selanjutnya",
"play-pause": "Main / Jeda",
"previous": "Sebelumnya"
},
"label": "Pilih Pintasan Global untuk Pengendali Lagu:",
"title": "Pintasan Global"
}
}
},
"skip-disliked-songs": {
"description": "Lewati lagu yang tidak disukai",
"name": "Lewati Lagu yang Tidak Disukai"
},
"skip-silences": {
"description": "Otomatis lewati bagian hening dari lagu",
"name": "Lewati Keheningan"
},
"sponsorblock": {
"description": "Otomatis Melewati bagian yang bukan musik seperti intro/outro atau bagian dari video musik di mana lagu tidak dimainkan",
"name": "SponsorBlock"
},
"taskbar-mediacontrol": {
"description": "Kendalikan pemutaran dari bilah alat Windows",
"name": "Pengendali Media di Bilah Alat"
},
"touchbar": {
"description": "Tambahkan widget TouchBar untuk pengguna macOS",
"name": "TouchBar"
},
"tuna-obs": {
"description": "Integrasi dengan plugin Tuna OBS",
"name": "Tuna OBS"
},
"video-toggle": {
"description": "Tambahkan tombol untuk beralih antara mode Lagu/Video. secara opsional juga dapat menghapus keseluruhan tab video",
"menu": {
"align": {
"label": "Perataan",
"submenu": {
"left": "Kiri",
"middle": "Tengah",
"right": "Kanan"
}
},
"force-hide": "Paksa hapus tab video",
"mode": {
"label": "Mode",
"submenu": {
"custom": "Peralih kustom",
"disabled": "Mati",
"native": "Peralih bawaan"
}
}
},
"name": "Peralih Video",
"templates": {
"button": "Lagu"
}
},
"visualizer": {
"description": "Tambahkan visualisator ke pemutar",
"menu": {
"visualizer-type": "Tipe Visualisator"
},
"name": "Visualisator"
} }
} }
} }

View File

@ -212,6 +212,13 @@
}, },
"album-color-theme": { "album-color-theme": {
"description": "Stosuje dynamiczny motyw i efekty wizualne w oparciu o paletę kolorów albumu", "description": "Stosuje dynamiczny motyw i efekty wizualne w oparciu o paletę kolorów albumu",
"menu": {
"color-mix-ratio": {
"submenu": {
"percent": "{{ratio}}%"
}
}
},
"name": "Motyw kolorów albumu" "name": "Motyw kolorów albumu"
}, },
"ambient-mode": { "ambient-mode": {
@ -569,6 +576,24 @@
"description": "Umożliwia zmianę jakości wideo za pomocą przycisku na nakładce wideo", "description": "Umożliwia zmianę jakości wideo za pomocą przycisku na nakładce wideo",
"name": "Zmieniacz jakości wideo" "name": "Zmieniacz jakości wideo"
}, },
"scrobbler": {
"menu": {
"listenbrainz": {
"token": "Podaj token użytkownika ListenBrainz"
}
},
"prompt": {
"lastfm": {
"api-key": "klucz API Last.fm"
},
"listenbrainz": {
"token": {
"label": "Podaj swój token użytkownika ListenBrainz:",
"title": "Token ListenBrainz"
}
}
}
},
"shortcuts": { "shortcuts": {
"description": "Umożliwia ustawienie globalnych skrótów klawiszowych do odtwarzania (odtwarzanie/pauza/następny/poprzedni) + wyłączanie OSD multimediów poprzez zastąpienie klawiszy multimediów, włączając kombinację klawiszy Ctrl/CMD + F w celu wyszukiwania, obsługę Linux MPRIS dla klawiszy multimediów oraz niestandardowe skróty klawiszowe dla zaawansowanych użytkowników", "description": "Umożliwia ustawienie globalnych skrótów klawiszowych do odtwarzania (odtwarzanie/pauza/następny/poprzedni) + wyłączanie OSD multimediów poprzez zastąpienie klawiszy multimediów, włączając kombinację klawiszy Ctrl/CMD + F w celu wyszukiwania, obsługę Linux MPRIS dla klawiszy multimediów oraz niestandardowe skróty klawiszowe dla zaawansowanych użytkowników",
"menu": { "menu": {

View File

@ -586,7 +586,7 @@ app.whenReady().then(async () => {
); );
try { try {
// Check if shortcut is registered and valid // Check if shortcut is registered and valid
const shortcutDetails = shell.readShortcutLink(shortcutPath); // Throw error if doesn't exist yet const shortcutDetails = shell.readShortcutLink(shortcutPath); // Throw error if it doesn't exist yet
if ( if (
shortcutDetails.target !== appLocation || shortcutDetails.target !== appLocation ||
shortcutDetails.appUserModelId !== appID shortcutDetails.appUserModelId !== appID

View File

@ -30,7 +30,7 @@ import {
import { fetchFromGenius } from '@/plugins/lyrics-genius/main'; import { fetchFromGenius } from '@/plugins/lyrics-genius/main';
import { isEnabled } from '@/config/plugins'; import { isEnabled } from '@/config/plugins';
import { cleanupName, getImage, SongInfo } from '@/providers/song-info'; import { cleanupName, getImage, MediaType, type SongInfo } from '@/providers/song-info';
import { getNetFetchAsFetch } from '@/plugins/utils/main'; import { getNetFetchAsFetch } from '@/plugins/utils/main';
import { cache } from '@/providers/decorators'; import { cache } from '@/providers/decorators';
@ -686,6 +686,7 @@ const getMetadata = (info: TrackInfo): CustomSongInfo => ({
?.url, ?.url,
views: info.basic_info.view_count!, views: info.basic_info.view_count!,
songDuration: info.basic_info.duration!, songDuration: info.basic_info.duration!,
mediaType: MediaType.Audio,
}); });
// This is used to bypass age restrictions // This is used to bypass age restrictions

View File

@ -4,8 +4,24 @@ export interface InAppMenuConfig {
} }
export const defaultInAppMenuConfig: InAppMenuConfig = { export const defaultInAppMenuConfig: InAppMenuConfig = {
enabled: enabled:
(typeof window !== 'undefined' && (
!window.navigator?.userAgent?.includes('mac')) || (
(typeof global !== 'undefined' && global.process?.platform !== 'darwin'), typeof window !== 'undefined' &&
!window.navigator?.userAgent?.includes('mac')
) ||
(
typeof global !== 'undefined' &&
global.process?.platform !== 'darwin'
)
) && (
(
typeof window !== 'undefined' &&
!window.navigator?.userAgent?.includes('linux')
) ||
(
typeof global !== 'undefined' &&
global.process?.platform !== 'linux'
)
),
hideDOMWindowControls: false, hideDOMWindowControls: false,
}; };

View File

@ -2,7 +2,7 @@ import is from 'electron-is';
import { t } from '@/i18n'; import { t } from '@/i18n';
import type { InAppMenuConfig } from './index'; import type { InAppMenuConfig } from './constants';
import type { MenuContext } from '@/types/contexts'; import type { MenuContext } from '@/types/contexts';
import type { MenuTemplate } from '@/menu'; import type { MenuTemplate } from '@/menu';

View File

@ -1,5 +1,6 @@
import { JSX, splitProps } from 'solid-js'; import { JSX, splitProps } from 'solid-js';
import { css } from 'solid-styled-components'; import { css } from 'solid-styled-components';
import { cache } from '@/providers/decorators'; import { cache } from '@/providers/decorators';
const menuStyle = cache(() => css` const menuStyle = cache(() => css`

View File

@ -4,6 +4,7 @@ import { css } from 'solid-styled-components';
import { Transition } from 'solid-transition-group'; import { Transition } from 'solid-transition-group';
import { autoUpdate, flip, offset, OffsetOptions, size } from '@floating-ui/dom'; import { autoUpdate, flip, offset, OffsetOptions, size } from '@floating-ui/dom';
import { useFloating } from 'solid-floating-ui'; import { useFloating } from 'solid-floating-ui';
import { cache } from '@/providers/decorators'; import { cache } from '@/providers/decorators';
const panelStyle = cache(() => css` const panelStyle = cache(() => css`
@ -131,6 +132,7 @@ export const Panel = (props: PanelProps) => {
<Show when={local.open}> <Show when={local.open}>
<ul <ul
{...leftProps} {...leftProps}
data-ytmd-sub-panel={true}
ref={setPanel} ref={setPanel}
class={panelStyle()} class={panelStyle()}
style={{ style={{

View File

@ -9,9 +9,10 @@ import { PanelItem } from './PanelItem';
import { IconButton } from './IconButton'; import { IconButton } from './IconButton';
import { WindowController } from './WindowController'; import { WindowController } from './WindowController';
import { cache } from '@/providers/decorators';
import type { RendererContext } from '@/types/contexts'; import type { RendererContext } from '@/types/contexts';
import type { InAppMenuConfig } from '../constants'; import type { InAppMenuConfig } from '../constants';
import { cache } from '@/providers/decorators';
const titleStyle = cache(() => css` const titleStyle = cache(() => css`
-webkit-app-region: drag; -webkit-app-region: drag;
@ -243,6 +244,19 @@ export const TitleBar = (props: TitleBarProps) => {
props.ipc.on('window-maximize', refetchMaximize); props.ipc.on('window-maximize', refetchMaximize);
props.ipc.on('window-unmaximize', refetchMaximize); props.ipc.on('window-unmaximize', refetchMaximize);
// close menu when the outside of the panel or sub-panel is clicked
document.body.addEventListener('click', (e) => {
if (
e.target instanceof HTMLElement &&
!(
e.target.closest('nav[data-ytmd-main-panel]') ||
e.target.closest('ul[data-ytmd-sub-panel]')
)
) {
setOpenTarget(null);
}
});
}); });
createEffect(() => { createEffect(() => {
@ -252,7 +266,7 @@ export const TitleBar = (props: TitleBarProps) => {
}); });
return ( return (
<nav class={titleStyle()} data-macos={props.isMacOS}> <nav data-ytmd-main-panel={true} class={titleStyle()} data-macos={props.isMacOS}>
<IconButton <IconButton
onClick={() => setCollapsed(!collapsed())} onClick={() => setCollapsed(!collapsed())}
style={{ style={{

View File

@ -38,7 +38,7 @@ export const fetchFromGenius = async (metadata: SongInfo) => {
const songArtist = `${cleanupName(metadata.artist)}`; const songArtist = `${cleanupName(metadata.artist)}`;
let lyrics: string | null; let lyrics: string | null;
/* Uses Regex to test the title and artist first for said characters if romanization is enabled. Otherwise normal /* Uses Regex to test the title and artist first for said characters if romanization is enabled. Otherwise, normal
Genius Lyrics behavior is observed. Genius Lyrics behavior is observed.
*/ */
let hasAsianChars = false; let hasAsianChars = false;

View File

@ -74,7 +74,7 @@ export class Connection {
return conn; return conn;
} }
async disconnect() { disconnect() {
if (this._mode === 'disconnected') throw new Error('Already disconnected'); if (this._mode === 'disconnected') throw new Error('Already disconnected');
this._mode = 'disconnected'; this._mode = 'disconnected';

View File

@ -11,7 +11,7 @@ export interface ScrobblerPluginConfig {
* *
* @default true * @default true
*/ */
scrobble_other_media: boolean, scrobbleOtherMedia: boolean,
scrobblers: { scrobblers: {
lastfm: { lastfm: {
/** /**
@ -27,19 +27,19 @@ export interface ScrobblerPluginConfig {
/** /**
* Session key used for scrobbling * Session key used for scrobbling
*/ */
session_key: string | undefined, sessionKey: string | undefined,
/** /**
* Root of the Last.fm API * Root of the Last.fm API
* *
* @default 'http://ws.audioscrobbler.com/2.0/' * @default 'http://ws.audioscrobbler.com/2.0/'
*/ */
api_root: string, apiRoot: string,
/** /**
* Last.fm api key registered by @semvis123 * Last.fm api key registered by @semvis123
* *
* @default '04d76faaac8726e60988e14c105d421a' * @default '04d76faaac8726e60988e14c105d421a'
*/ */
api_key: string, apiKey: string,
/** /**
* Last.fm api secret registered by @semvis123 * Last.fm api secret registered by @semvis123
* *
@ -63,27 +63,27 @@ export interface ScrobblerPluginConfig {
* *
* @default 'https://api.listenbrainz.org/1/' * @default 'https://api.listenbrainz.org/1/'
*/ */
api_root: string, apiRoot: string,
}, },
} }
} }
export const defaultConfig: ScrobblerPluginConfig = { export const defaultConfig: ScrobblerPluginConfig = {
enabled: false, enabled: false,
scrobble_other_media: true, scrobbleOtherMedia: true,
scrobblers: { scrobblers: {
lastfm: { lastfm: {
enabled: false, enabled: false,
token: undefined, token: undefined,
session_key: undefined, sessionKey: undefined,
api_root: 'http://ws.audioscrobbler.com/2.0/', apiRoot: 'https://ws.audioscrobbler.com/2.0/',
api_key: '04d76faaac8726e60988e14c105d421a', apiKey: '04d76faaac8726e60988e14c105d421a',
secret: 'a5d2a36fdf64819290f6982481eaffa2', secret: 'a5d2a36fdf64819290f6982481eaffa2',
}, },
listenbrainz: { listenbrainz: {
enabled: false, enabled: false,
token: undefined, token: undefined,
api_root: 'https://api.listenbrainz.org/1/', apiRoot: 'https://api.listenbrainz.org/1/',
}, },
}, },
}; };

View File

@ -1,4 +1,4 @@
import registerCallback, { type SongInfo } from '@/providers/song-info'; import registerCallback, { MediaType, type SongInfo } from '@/providers/song-info';
import { createBackend } from '@/utils'; import { createBackend } from '@/utils';
import { ScrobblerPluginConfig } from './index'; import { ScrobblerPluginConfig } from './index';
@ -52,7 +52,7 @@ export const backend = createBackend<{
if (!songInfo.isPaused) { if (!songInfo.isPaused) {
const configNonnull = this.config!; const configNonnull = this.config!;
// Scrobblers normally have no trouble working with official music videos // Scrobblers normally have no trouble working with official music videos
if (!configNonnull.scrobble_other_media && (songInfo.mediaType !== 'AUDIO' && songInfo.mediaType !== 'ORIGINAL_MUSIC_VIDEO')) { if (!configNonnull.scrobble_other_media && (songInfo.mediaType !== MediaType.Audio && songInfo.mediaType !== MediaType.OriginalMusicVideo)) {
return; return;
} }

View File

@ -29,20 +29,20 @@ interface LastFmSongData {
export class LastFmScrobbler extends ScrobblerBase { export class LastFmScrobbler extends ScrobblerBase {
isSessionCreated(config: ScrobblerPluginConfig): boolean { isSessionCreated(config: ScrobblerPluginConfig): boolean {
return !!config.scrobblers.lastfm.session_key; return !!config.scrobblers.lastfm.sessionKey;
} }
async createSession(config: ScrobblerPluginConfig, setConfig: SetConfType): Promise<ScrobblerPluginConfig> { async createSession(config: ScrobblerPluginConfig, setConfig: SetConfType): Promise<ScrobblerPluginConfig> {
// Get and store the session key // Get and store the session key
const data = { const data = {
api_key: config.scrobblers.lastfm.api_key, api_key: config.scrobblers.lastfm.apiKey,
format: 'json', format: 'json',
method: 'auth.getsession', method: 'auth.getsession',
token: config.scrobblers.lastfm.token, token: config.scrobblers.lastfm.token,
}; };
const apiSignature = createApiSig(data, config.scrobblers.lastfm.secret); const apiSignature = createApiSig(data, config.scrobblers.lastfm.secret);
const response = await net.fetch( const response = await net.fetch(
`${config.scrobblers.lastfm.api_root}${createQueryString(data, apiSignature)}`, `${config.scrobblers.lastfm.apiRoot}${createQueryString(data, apiSignature)}`,
); );
const json = (await response.json()) as { const json = (await response.json()) as {
error?: string; error?: string;
@ -56,14 +56,14 @@ export class LastFmScrobbler extends ScrobblerBase {
setConfig(config); setConfig(config);
} }
if (json.session) { if (json.session) {
config.scrobblers.lastfm.session_key = json.session.key; config.scrobblers.lastfm.sessionKey = json.session.key;
} }
setConfig(config); setConfig(config);
return config; return config;
} }
setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void { setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void {
if (!config.scrobblers.lastfm.session_key) { if (!config.scrobblers.lastfm.sessionKey) {
return; return;
} }
@ -75,7 +75,7 @@ export class LastFmScrobbler extends ScrobblerBase {
} }
addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void { addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, setConfig: SetConfType): void {
if (!config.scrobblers.lastfm.session_key) { if (!config.scrobblers.lastfm.sessionKey) {
return; return;
} }
@ -94,7 +94,7 @@ export class LastFmScrobbler extends ScrobblerBase {
setConfig: SetConfType, setConfig: SetConfType,
): Promise<void> { ): Promise<void> {
// This sends a post request to the api, and adds the common data // This sends a post request to the api, and adds the common data
if (!config.scrobblers.lastfm.session_key) { if (!config.scrobblers.lastfm.sessionKey) {
await this.createSession(config, setConfig); await this.createSession(config, setConfig);
} }
@ -103,8 +103,8 @@ export class LastFmScrobbler extends ScrobblerBase {
duration: songInfo.songDuration, duration: songInfo.songDuration,
artist: songInfo.artist, artist: songInfo.artist,
...(songInfo.album ? { album: songInfo.album } : undefined), // Will be undefined if current song is a video ...(songInfo.album ? { album: songInfo.album } : undefined), // Will be undefined if current song is a video
api_key: config.scrobblers.lastfm.api_key, api_key: config.scrobblers.lastfm.apiKey,
sk: config.scrobblers.lastfm.session_key, sk: config.scrobblers.lastfm.sessionKey,
format: 'json', format: 'json',
...data, ...data,
}; };
@ -126,7 +126,7 @@ export class LastFmScrobbler extends ScrobblerBase {
}) => { }) => {
if (error?.response?.data?.error === 9) { if (error?.response?.data?.error === 9) {
// Session key is invalid, so remove it from the config and reauthenticate // Session key is invalid, so remove it from the config and reauthenticate
config.scrobblers.lastfm.session_key = undefined; config.scrobblers.lastfm.sessionKey = undefined;
config.scrobblers.lastfm.token = await createToken(config); config.scrobblers.lastfm.token = await createToken(config);
await authenticate(config); await authenticate(config);
setConfig(config); setConfig(config);
@ -188,8 +188,8 @@ const createApiSig = (parameters: LastFmSongData, secret: string) => {
const createToken = async ({ const createToken = async ({
scrobblers: { scrobblers: {
lastfm: { lastfm: {
api_key: apiKey, apiKey,
api_root: apiRoot, apiRoot,
secret, secret,
} }
} }
@ -211,6 +211,6 @@ const createToken = async ({
const authenticate = async (config: ScrobblerPluginConfig) => { const authenticate = async (config: ScrobblerPluginConfig) => {
// Asks the user for authentication // Asks the user for authentication
await shell.openExternal( await shell.openExternal(
`https://www.last.fm/api/auth/?api_key=${config.scrobblers.lastfm.api_key}&token=${config.scrobblers.lastfm.token}`, `https://www.last.fm/api/auth/?api_key=${config.scrobblers.lastfm.apiKey}&token=${config.scrobblers.lastfm.token}`,
); );
}; };

View File

@ -36,7 +36,7 @@ export class ListenbrainzScrobbler extends ScrobblerBase {
} }
setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void { setNowPlaying(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void {
if (!config.scrobblers.listenbrainz.api_root || !config.scrobblers.listenbrainz.token) { if (!config.scrobblers.listenbrainz.apiRoot || !config.scrobblers.listenbrainz.token) {
return; return;
} }
@ -45,7 +45,7 @@ export class ListenbrainzScrobbler extends ScrobblerBase {
} }
addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void { addScrobble(songInfo: SongInfo, config: ScrobblerPluginConfig, _setConfig: SetConfType): void {
if (!config.scrobblers.listenbrainz.api_root || !config.scrobblers.listenbrainz.token) { if (!config.scrobblers.listenbrainz.apiRoot || !config.scrobblers.listenbrainz.token) {
return; return;
} }
@ -80,7 +80,7 @@ function createRequestBody(listenType: string, songInfo: SongInfo): Listenbrainz
} }
function submitListen(body: ListenbrainzRequestBody, config: ScrobblerPluginConfig) { function submitListen(body: ListenbrainzRequestBody, config: ScrobblerPluginConfig) {
net.fetch(config.scrobblers.listenbrainz.api_root + 'submit-listens', net.fetch(config.scrobblers.listenbrainz.apiRoot + 'submit-listens',
{ {
method: 'POST', method: 'POST',
body: JSON.stringify(body), body: JSON.stringify(body),

View File

@ -56,7 +56,7 @@ declare module '@jellybrick/mpris-service' {
playbackStatus: string; playbackStatus: string;
loopStatus: string; loopStatus: string;
shuffle: boolean; shuffle: boolean;
metadata: object; metadata: Track;
volume: number; volume: number;
canControl: boolean; canControl: boolean;
canPause: boolean; canPause: boolean;

View File

@ -1,37 +1,98 @@
import { BrowserWindow, ipcMain } from 'electron'; import { BrowserWindow, ipcMain } from 'electron';
import mpris, { Track } from '@jellybrick/mpris-service'; import MprisPlayer, { Track } from '@jellybrick/mpris-service';
import registerCallback from '@/providers/song-info'; import registerCallback, { type SongInfo } from '@/providers/song-info';
import getSongControls from '@/providers/song-controls'; import getSongControls from '@/providers/song-controls';
import config from '@/config'; import config from '@/config';
import { LoggerPrefix } from '@/utils';
class YTPlayer extends MprisPlayer {
/**
* @type {number} The current position in microseconds
* @private
*/
private currentPosition: number;
constructor(opts: {
name: string;
identity: string;
supportedMimeTypes?: string[];
supportedInterfaces?: string[];
}) {
super(opts);
this.currentPosition = 0;
}
setPosition(t: number) {
this.currentPosition = t;
}
override getPosition(): number {
return this.currentPosition;
}
setLoopStatus(status: string) {
this.loopStatus = status;
}
isPlaying(): boolean {
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_PLAYING;
}
isPaused(): boolean {
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_PAUSED;
}
isStopped(): boolean {
return this.playbackStatus === YTPlayer.PLAYBACK_STATUS_STOPPED;
}
setPlaybackStatus(status: string) {
this.playbackStatus = status;
}
}
function setupMPRIS() { function setupMPRIS() {
const instance = new mpris({ const instance = new YTPlayer({
name: 'youtube-music', name: 'youtube-music',
identity: 'YouTube Music', identity: 'YouTube Music',
supportedMimeTypes: ['audio/mpeg'], supportedMimeTypes: ['audio/mpeg'],
supportedInterfaces: ['player'], supportedInterfaces: ['player'],
}); });
instance.canRaise = true; instance.canRaise = true;
instance.supportedUriSchemes = ['https']; instance.supportedUriSchemes = ['http', 'https'];
instance.desktopEntry = 'youtube-music'; instance.desktopEntry = 'youtube-music';
return instance; return instance;
} }
function registerMPRIS(win: BrowserWindow) { function registerMPRIS(win: BrowserWindow) {
const songControls = getSongControls(win); const songControls = getSongControls(win);
const { playPause, next, previous, volumeMinus10, volumePlus10, shuffle } = const {
songControls; playPause,
next,
previous,
volumeMinus10,
volumePlus10,
shuffle,
switchRepeat,
} = songControls;
try { try {
// TODO: "Typing" for this arguments let currentSongInfo: SongInfo | null = null;
const secToMicro = (n: unknown) => Math.round(Number(n) * 1e6); const secToMicro = (n: number) => Math.round(Number(n) * 1e6);
const microToSec = (n: unknown) => Math.round(Number(n) / 1e6); const microToSec = (n: number) => Math.round(Number(n) / 1e6);
const seekTo = (e: { position: unknown }) => const seekTo = (event: {
win.webContents.send('ytmd:seek-to', microToSec(e.position)); trackId: string;
const seekBy = (o: unknown) => position: number;
win.webContents.send('ytmd:seek-by', microToSec(o)); }) => {
if (event.trackId === currentSongInfo?.videoId) {
win.webContents.send('ytmd:seek-to', microToSec(event.position ?? 0));
}
};
const seekBy = (offset: number) =>
win.webContents.send('ytmd:seek-by', microToSec(offset));
const player = setupMPRIS(); const player = setupMPRIS();
@ -44,21 +105,22 @@ function registerMPRIS(win: BrowserWindow) {
ipcMain.on('ytmd:seeked', (_, t: number) => player.seeked(secToMicro(t))); ipcMain.on('ytmd:seeked', (_, t: number) => player.seeked(secToMicro(t)));
let currentSeconds = 0; ipcMain.on('ytmd:time-changed', (_, t: number) => {
ipcMain.on('ytmd:time-changed', (_, t: number) => (currentSeconds = t)); player.setPosition(secToMicro(t));
});
ipcMain.on('ytmd:repeat-changed', (_, mode: string) => { ipcMain.on('ytmd:repeat-changed', (_, mode: string) => {
switch (mode) { switch (mode) {
case 'NONE': { case 'NONE': {
player.loopStatus = mpris.LOOP_STATUS_NONE; player.setLoopStatus(YTPlayer.LOOP_STATUS_NONE);
break; break;
} }
case 'ONE': { case 'ONE': {
player.loopStatus = mpris.LOOP_STATUS_TRACK; player.setLoopStatus(YTPlayer.LOOP_STATUS_TRACK);
break; break;
} }
case 'ALL': { case 'ALL': {
player.loopStatus = mpris.LOOP_STATUS_PLAYLIST; player.setLoopStatus(YTPlayer.LOOP_STATUS_PLAYLIST);
// No default // No default
break; break;
} }
@ -67,18 +129,17 @@ function registerMPRIS(win: BrowserWindow) {
player.on('loopStatus', (status: string) => { player.on('loopStatus', (status: string) => {
// SwitchRepeat cycles between states in that order // SwitchRepeat cycles between states in that order
const switches = [ const switches = [
mpris.LOOP_STATUS_NONE, YTPlayer.LOOP_STATUS_NONE,
mpris.LOOP_STATUS_PLAYLIST, YTPlayer.LOOP_STATUS_PLAYLIST,
mpris.LOOP_STATUS_TRACK, YTPlayer.LOOP_STATUS_TRACK,
]; ];
const currentIndex = switches.indexOf(player.loopStatus); const currentIndex = switches.indexOf(player.loopStatus);
const targetIndex = switches.indexOf(status); const targetIndex = switches.indexOf(status);
// Get a delta in the range [0,2] // Get a delta in the range [0,2]
const delta = (targetIndex - currentIndex + 3) % 3; const delta = (targetIndex - currentIndex + 3) % 3;
songControls.switchRepeat(delta); switchRepeat(delta);
}); });
player.getPosition = () => secToMicro(currentSeconds);
player.on('raise', () => { player.on('raise', () => {
win.setSkipTaskbar(false); win.setSkipTaskbar(false);
@ -86,22 +147,23 @@ function registerMPRIS(win: BrowserWindow) {
}); });
player.on('play', () => { player.on('play', () => {
if (player.playbackStatus !== mpris.PLAYBACK_STATUS_PLAYING) { if (!player.isPlaying()) {
player.playbackStatus = mpris.PLAYBACK_STATUS_PLAYING; player.setPlaybackStatus(YTPlayer.PLAYBACK_STATUS_PLAYING);
playPause(); playPause();
} }
}); });
player.on('pause', () => { player.on('pause', () => {
if (player.playbackStatus !== mpris.PLAYBACK_STATUS_PAUSED) { if (player.playbackStatus !== YTPlayer.PLAYBACK_STATUS_PAUSED) {
player.playbackStatus = mpris.PLAYBACK_STATUS_PAUSED; player.setPlaybackStatus(YTPlayer.PLAYBACK_STATUS_PAUSED);
playPause(); playPause();
} }
}); });
player.on('playpause', () => { player.on('playpause', () => {
player.playbackStatus = player.setPlaybackStatus(
player.playbackStatus === mpris.PLAYBACK_STATUS_PLAYING player.isPlaying()
? mpris.PLAYBACK_STATUS_PAUSED ? YTPlayer.PLAYBACK_STATUS_PAUSED
: mpris.PLAYBACK_STATUS_PLAYING; : YTPlayer.PLAYBACK_STATUS_PLAYING
);
playPause(); playPause();
}); });
@ -170,21 +232,32 @@ function registerMPRIS(win: BrowserWindow) {
'xesam:title': songInfo.title, 'xesam:title': songInfo.title,
'xesam:url': songInfo.url, 'xesam:url': songInfo.url,
'xesam:artist': [songInfo.artist], 'xesam:artist': [songInfo.artist],
'mpris:trackid': '/', 'mpris:trackid': songInfo.videoId,
}; };
if (songInfo.album) { if (songInfo.album) {
data['xesam:album'] = songInfo.album; data['xesam:album'] = songInfo.album;
} }
currentSongInfo = songInfo;
player.metadata = data; player.metadata = data;
player.seeked(secToMicro(songInfo.elapsedSeconds));
player.playbackStatus = songInfo.isPaused const currentElapsedMicroSeconds = secToMicro(songInfo.elapsedSeconds ?? 0);
? mpris.PLAYBACK_STATUS_PAUSED player.setPosition(currentElapsedMicroSeconds);
: mpris.PLAYBACK_STATUS_PLAYING; player.seeked(currentElapsedMicroSeconds);
player.setPlaybackStatus(
songInfo.isPaused ?
YTPlayer.PLAYBACK_STATUS_PAUSED :
YTPlayer.PLAYBACK_STATUS_PLAYING
);
} }
}); });
} catch (error) { } catch (error) {
console.warn('Error in MPRIS', error); console.error(
LoggerPrefix,
'Error in MPRIS'
);
console.trace(error);
} }
} }

View File

@ -1,18 +1,37 @@
import { t } from '@/i18n'; import { t } from '@/i18n';
import { createPlugin } from '@/utils'; import { createPlugin } from '@/utils';
export default createPlugin({ export default createPlugin<
unknown,
unknown,
{
observer?: MutationObserver;
waitForElem(selector: string): Promise<HTMLElement>;
start(): void;
stop(): void;
}
>({
name: () => t('plugins.skip-disliked-songs.name'), name: () => t('plugins.skip-disliked-songs.name'),
description: () => t('plugins.skip-disliked-songs.description'), description: () => t('plugins.skip-disliked-songs.description'),
restartNeeded: false, restartNeeded: false,
renderer: { renderer: {
observer: null as MutationObserver | null, waitForElem(selector: string) {
return new Promise<HTMLElement>((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector<HTMLElement>(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
},
start() { start() {
this.waitForElem('#like-button-renderer').then((likeBtn) => { this.waitForElem('#like-button-renderer').then((likeBtn) => {
this.observer = new MutationObserver(() => { this.observer = new MutationObserver(() => {
if (likeBtn?.getAttribute('like-status') == 'DISLIKE') { if (likeBtn?.getAttribute('like-status') == 'DISLIKE') {
document document
.querySelector('tp-yt-paper-icon-button.next-button') .querySelector<HTMLButtonElement>('tp-yt-paper-icon-button.next-button')
?.click(); ?.click();
} }
}); });
@ -26,16 +45,5 @@ export default createPlugin({
stop() { stop() {
this.observer?.disconnect(); this.observer?.disconnect();
}, },
waitForElem(selector) {
return new Promise((resolve) => {
const interval = setInterval(() => {
const elem = document.querySelector(selector);
if (!elem) return;
clearInterval(interval);
resolve(elem);
});
});
},
}, },
}); });

View File

@ -3,33 +3,37 @@ import { BrowserWindow, ipcMain } from 'electron';
export default (win: BrowserWindow) => { export default (win: BrowserWindow) => {
const commands = { const commands = {
// Playback // Playback
previous: () => win.webContents.send('ytmd:previous-video'), previous: () => win.webContents.send('ytmd:previous-video'),
next: () => win.webContents.send('ytmd:next-video'), next: () => win.webContents.send('ytmd:next-video'),
playPause: () => win.webContents.send('ytmd:toggle-play'), playPause: () => win.webContents.send('ytmd:toggle-play'),
like: () => win.webContents.send('ytmd:update-like', 'LIKE'), like: () => win.webContents.send('ytmd:update-like', 'LIKE'),
dislike: () => win.webContents.send('ytmd:update-like', 'DISLIKE'), dislike: () => win.webContents.send('ytmd:update-like', 'DISLIKE'),
go10sBack: () => win.webContents.send('ytmd:seek-by', -10), go10sBack: () => win.webContents.send('ytmd:seek-by', -10),
go10sForward: () => win.webContents.send('ytmd:seek-by', 10), go10sForward: () => win.webContents.send('ytmd:seek-by', 10),
go1sBack: () => win.webContents.send('ytmd:seek-by', -1), go1sBack: () => win.webContents.send('ytmd:seek-by', -1),
go1sForward: () => win.webContents.send('ytmd:seek-by', 1), go1sForward: () => win.webContents.send('ytmd:seek-by', 1),
shuffle: () => win.webContents.send('ytmd:shuffle'), shuffle: () => win.webContents.send('ytmd:shuffle'),
switchRepeat: (n = 1) => win.webContents.send('ytmd:switch-repeat', n), switchRepeat: (n = 1) => win.webContents.send('ytmd:switch-repeat', n),
// General // General
volumeMinus10: () => { volumeMinus10: () => {
ipcMain.once('ytmd:get-volume-return', (_, volume) => { ipcMain.once('ytmd:get-volume-return', (_, volume) => {
win.webContents.send('ytmd:update-volume', volume - 10); win.webContents.send('ytmd:update-volume', volume - 10);
}); });
win.webContents.send('ytmd:get-volume'); win.webContents.send('ytmd:get-volume');
}, },
volumePlus10: () => { volumePlus10: () => {
ipcMain.once('ytmd:get-volume-return', (_, volume) => { ipcMain.once('ytmd:get-volume-return', (_, volume) => {
win.webContents.send('ytmd:update-volume', volume + 10); win.webContents.send('ytmd:update-volume', volume + 10);
}); });
win.webContents.send('ytmd:get-volume'); win.webContents.send('ytmd:get-volume');
}, },
fullscreen: () => win.webContents.send('ytmd:toggle-fullscreen'), fullscreen: () => win.webContents.send('ytmd:toggle-fullscreen'),
muteUnmute: () => win.webContents.send('ytmd:toggle-mute'), muteUnmute: () => win.webContents.send('ytmd:toggle-mute'),
search: () => win.webContents.sendInputEvent({
type: 'keyDown',
keyCode: '/',
}),
}; };
return { return {
...commands, ...commands,

View File

@ -29,8 +29,9 @@ export const setupTimeChangedListener = singleton(() => {
const progressObserver = new MutationObserver((mutations) => { const progressObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) { for (const mutation of mutations) {
const target = mutation.target as Node & { value: string }; const target = mutation.target as Node & { value: string };
window.ipcRenderer.send('ytmd:time-changed', target.value); const numberValue = Number(target.value);
songInfo.elapsedSeconds = Number(target.value); window.ipcRenderer.send('ytmd:time-changed', numberValue);
songInfo.elapsedSeconds = numberValue;
} }
}); });
const progressBar = document.querySelector('#progress-bar'); const progressBar = document.querySelector('#progress-bar');

View File

@ -7,7 +7,7 @@ import config from '@/config';
import type { GetPlayerResponse } from '@/types/get-player-response'; import type { GetPlayerResponse } from '@/types/get-player-response';
enum MediaType { export enum MediaType {
/** /**
* Audio uploaded by the original artist * Audio uploaded by the original artist
*/ */
@ -125,6 +125,18 @@ const handleData = async (
break; break;
default: default:
songInfo.mediaType = MediaType.OtherVideo; songInfo.mediaType = MediaType.OtherVideo;
// HACK: This is a workaround for "podcast" types where "musicVideoType" doesn't exist. Google :facepalm:
if (
!config.get('options.usePodcastParticipantAsArtist') &&
(
data.responseContext.serviceTrackingParams
?.at(0)
?.params
?.find((it) => it.key === 'ipcc')?.value ?? '1'
) != '0'
) {
songInfo.artist = cleanupName(data.microformat.microformatDataRenderer.pageOwnerDetails.name);
}
break; break;
} }

View File

@ -133,7 +133,7 @@ async function onApiLoaded() {
// Remove upgrade button // Remove upgrade button
if (window.mainConfig.get('options.removeUpgradeButton')) { if (window.mainConfig.get('options.removeUpgradeButton')) {
const styles = document.createElement('style'); const styles = document.createElement('style');
styles.innerHTML = `ytmusic-guide-signin-promo-renderer { styles.innerHTML = `ytmusic-guide-section-renderer #items ytmusic-guide-entry-renderer:last-child {
display: none; display: none;
}`; }`;
document.head.appendChild(styles); document.head.appendChild(styles);