mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-11 18:41:47 +00:00
Compare commits
133 Commits
v2.0.0
...
legacy/htt
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e97699e6c | |||
| a810621762 | |||
| a41db79c35 | |||
| 87786d9aef | |||
| 22f5866050 | |||
| 04894fbcf5 | |||
| c17c624ba4 | |||
| bfe7249df8 | |||
| 13c570efe9 | |||
| b299846f0f | |||
| 59e9289d27 | |||
| 8dc29caa1b | |||
| 7fedf88654 | |||
| 5da0202425 | |||
| 6288d0b171 | |||
| 4248d20e8e | |||
| 0b413492ad | |||
| dc73561c8a | |||
| 949a2f6428 | |||
| bceaa05197 | |||
| 776cdac30d | |||
| 4333891cca | |||
| 8a89bbccf7 | |||
| fa4c69d228 | |||
| c25def8901 | |||
| 284a59b721 | |||
| 5fcba8619a | |||
| f3cd759276 | |||
| 9d3981e361 | |||
| 787326948b | |||
| 779251933c | |||
| 1efe835c69 | |||
| 5702978227 | |||
| fa3d742838 | |||
| c460cc2296 | |||
| 4e4af5e830 | |||
| 9a4e98063b | |||
| 8bfe04bb50 | |||
| 6774d54f5e | |||
| 9705f8489d | |||
| a7229cbe14 | |||
| 7577aba45e | |||
| d78fbe476e | |||
| bfe4b2bba7 | |||
| 7625a3aa52 | |||
| 30c8dcf730 | |||
| 00a3e8d35e | |||
| 4d01cdfa6c | |||
| f924b6c8e3 | |||
| 926d98174c | |||
| 41b3972f54 | |||
| 467f29e363 | |||
| 9cc13c3757 | |||
| f8ccb86156 | |||
| b316aa2301 | |||
| 5c49b28664 | |||
| dedf96afd3 | |||
| 3bb5bc2ca1 | |||
| c79fdd9887 | |||
| d7b821727d | |||
| 21c45faf20 | |||
| 92cab89d17 | |||
| fa160b2e90 | |||
| 308ac38e6b | |||
| a62cafb601 | |||
| bf9e3b5f48 | |||
| 3c6b3aeff0 | |||
| 37181a7b5e | |||
| 0b363d6487 | |||
| e9398adac3 | |||
| 6901713036 | |||
| 1d5b2997bd | |||
| 572a023aaa | |||
| 9187f1e240 | |||
| df13d7d0f3 | |||
| 85228fd7d2 | |||
| 17ba071057 | |||
| d7df4d7d10 | |||
| 7aa970cebc | |||
| f08f003cf4 | |||
| 9f99eded9e | |||
| c512f13009 | |||
| b475f780ff | |||
| 2294102006 | |||
| d69a07d025 | |||
| 4f4995c20c | |||
| b6894dca29 | |||
| 73f14e581d | |||
| 2f2e64af4a | |||
| 5710307ddc | |||
| 52ba2dc9ff | |||
| 926b9fb5e6 | |||
| a6c9b3381a | |||
| 5dc13a4698 | |||
| a69085c591 | |||
| a22f7fed21 | |||
| 8b7045fb1b | |||
| efd1b92514 | |||
| 969f6d7bba | |||
| 4f7c92d6a0 | |||
| 24d4a50574 | |||
| 7693a3ba4a | |||
| 7ca4dc5c85 | |||
| 21ff09b605 | |||
| fbf4b3b8b5 | |||
| 5812eb0147 | |||
| b5dbfaf686 | |||
| 6b7fd5ba63 | |||
| 73a049a7bc | |||
| ef0c30e23a | |||
| 59ed2326d9 | |||
| 07a02c8c82 | |||
| f1050cb676 | |||
| 7131893f1c | |||
| e4dfb2ff33 | |||
| 187fad6834 | |||
| 26df435db0 | |||
| 0bee281d1d | |||
| 26de5802a0 | |||
| c258a4855e | |||
| b7b6d50ba2 | |||
| 0376a30fbb | |||
| ca92031e89 | |||
| 986d2ad5b1 | |||
| d9b8d8c48d | |||
| 0ef34d7c71 | |||
| f87607d25d | |||
| cc0bfae067 | |||
| e7d2d04f5a | |||
| f4319ebc6b | |||
| a1f025e23c | |||
| c002263c3b | |||
| 2d69dfd333 |
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -12,11 +12,13 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have searched the [issue tracker](https://github.com/th-ch/youtube-music/issues) for a bug report that matches the one I want to file, without success.
|
- label: I have searched the [issue tracker](https://github.com/th-ch/youtube-music/issues) for a bug report that matches the one I want to file, without success.
|
||||||
required: true
|
required: true
|
||||||
|
- label: I understand that **th-ch/youtube-music has NO affiliation with Google or YouTube**
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: YouTube Music (Application) Version
|
label: YouTube Music (Application) Version
|
||||||
description: |
|
description: |
|
||||||
What version of YouTube Music Application are you using?
|
What version of the YouTube Music Application are you using?
|
||||||
|
|
||||||
Note: Please check if this issue is reproducible with the latest stable release.
|
Note: Please check if this issue is reproducible with the latest stable release.
|
||||||
placeholder: 2.0.0
|
placeholder: 2.0.0
|
||||||
@ -36,7 +38,7 @@ body:
|
|||||||
- type: input
|
- type: input
|
||||||
attributes:
|
attributes:
|
||||||
label: Operating System Version
|
label: Operating System Version
|
||||||
description: What operating system version are you using? On Windows, click Start button > Settings > System > About. On macOS, click the Apple Menu > About This Mac. On Linux, use lsb_release or uname -a.
|
description: What operating system version are you using? On Windows, click the Start button > Settings > System > About. On macOS, click the Apple Menu > About This Mac. On Linux, use lsb_release or uname -a.
|
||||||
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
|
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
111
.github/workflows/build.yml
vendored
111
.github/workflows/build.yml
vendored
@ -20,59 +20,63 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8
|
||||||
|
run_install: false
|
||||||
|
|
||||||
- name: Setup NodeJS
|
- name: Setup NodeJS
|
||||||
uses: actions/setup-node@v3
|
if: startsWith(matrix.os, 'macOS') != true
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Setup NodeJS for macOS
|
||||||
|
if: startsWith(matrix.os, 'macOS')
|
||||||
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# Only rollup build without release if it is a fork
|
||||||
|
- name: Rollup Build
|
||||||
|
if: github.repository == 'th-ch/youtube-music' && github.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# Build and release if it's the main repository and is not pull-request
|
||||||
|
- name: Build and release on Mac
|
||||||
|
if: startsWith(matrix.os, 'macOS') && (github.repository == 'th-ch/youtube-music' && github.event_name != 'pull_request')
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm release:mac
|
||||||
|
|
||||||
|
- name: Build and release on Linux
|
||||||
|
if: startsWith(matrix.os, 'ubuntu') && (github.repository == 'th-ch/youtube-music' && github.event_name != 'pull_request')
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm release:linux
|
||||||
|
|
||||||
|
- name: Build and release on Windows
|
||||||
|
if: startsWith(matrix.os, 'windows') && (github.repository == 'th-ch/youtube-music' && github.event_name != 'pull_request')
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
pnpm release:win
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
uses: GabrielBB/xvfb-action@v1
|
uses: coactions/setup-xvfb@v1
|
||||||
env:
|
env:
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
with:
|
with:
|
||||||
run: npm run test
|
run: pnpm test:debug
|
||||||
|
|
||||||
# Build and release if it's the main repository
|
|
||||||
- name: Build and release on Mac
|
|
||||||
if: startsWith(matrix.os, 'macOS') && github.repository == 'th-ch/youtube-music'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
npm run release:mac
|
|
||||||
|
|
||||||
- name: Build and release on Linux
|
|
||||||
if: startsWith(matrix.os, 'ubuntu') && github.repository == 'th-ch/youtube-music'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
npm run release:linux
|
|
||||||
|
|
||||||
- name: Build and release on Windows
|
|
||||||
if: startsWith(matrix.os, 'windows') && github.repository == 'th-ch/youtube-music'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
npm run release:win
|
|
||||||
|
|
||||||
# Only build without release if it is a fork
|
|
||||||
- name: Build on Mac
|
|
||||||
if: startsWith(matrix.os, 'macOS') && github.repository != 'th-ch/youtube-music'
|
|
||||||
run: |
|
|
||||||
npm run build:mac
|
|
||||||
|
|
||||||
- name: Build on Linux
|
|
||||||
if: startsWith(matrix.os, 'ubuntu') && github.repository != 'th-ch/youtube-music'
|
|
||||||
run: |
|
|
||||||
npm run build:linux
|
|
||||||
|
|
||||||
- name: Build on Windows
|
|
||||||
if: startsWith(matrix.os, 'windows') && github.repository != 'th-ch/youtube-music'
|
|
||||||
run: |
|
|
||||||
npm run build:win
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -84,14 +88,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v2
|
||||||
|
with:
|
||||||
|
version: 8
|
||||||
|
run_install: false
|
||||||
|
|
||||||
- name: Setup NodeJS
|
- name: Setup NodeJS
|
||||||
uses: actions/setup-node@v3
|
if: startsWith(matrix.os, 'macOS') != true
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'pnpm'
|
||||||
|
|
||||||
|
- name: Setup NodeJS for macOS
|
||||||
|
if: startsWith(matrix.os, 'macOS')
|
||||||
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
run: |
|
run: |
|
||||||
@ -117,7 +134,7 @@ jobs:
|
|||||||
if: ${{ env.VERSION_HASH == '' }}
|
if: ${{ env.VERSION_HASH == '' }}
|
||||||
uses: irongut/EditRelease@v1.2.0
|
uses: irongut/EditRelease@v1.2.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
id: ${{ steps.get_draft_release.outputs.id }}
|
id: ${{ steps.get_draft_release.outputs.id }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
@ -132,7 +149,7 @@ jobs:
|
|||||||
- name: Update changelog
|
- name: Update changelog
|
||||||
if: ${{ env.VERSION_HASH == '' }}
|
if: ${{ env.VERSION_HASH == '' }}
|
||||||
run: |
|
run: |
|
||||||
npm run changelog
|
pnpm changelog
|
||||||
|
|
||||||
- name: Commit changelog
|
- name: Commit changelog
|
||||||
if: ${{ env.VERSION_HASH == '' }}
|
if: ${{ env.VERSION_HASH == '' }}
|
||||||
|
|||||||
20
.github/workflows/winget-cla.yml
vendored
Normal file
20
.github/workflows/winget-cla.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Submit CLA to Winget PR
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
pr_url:
|
||||||
|
description: "Specific PR URL"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment:
|
||||||
|
name: Comment to PR
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Submit CLA to Windows Package Manager Community Repository Pull Request
|
||||||
|
run: gh pr comment $PR_URL --body "@microsoft-github-policy-service agree"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.WINGET_ACC_TOKEN }}
|
||||||
|
PR_URL: ${{ inputs.pr_url }}
|
||||||
2
.github/workflows/winget-submission.yml
vendored
2
.github/workflows/winget-submission.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
uses: vedantmgoyal2009/winget-releaser@v2
|
uses: vedantmgoyal2009/winget-releaser@v2
|
||||||
with:
|
with:
|
||||||
identifier: th-ch.YouTubeMusic
|
identifier: th-ch.YouTubeMusic
|
||||||
installers-regex: '^YouTube-Music-Setup-[\d\.]+\.exe$'
|
installers-regex: '^YouTube-Music-Web-Setup-[\d\.]+\.exe$'
|
||||||
version: ${{ inputs.tag_name || github.event.release.tag_name }}
|
version: ${{ inputs.tag_name || github.event.release.tag_name }}
|
||||||
release-tag: ${{ inputs.tag_name || github.event.release.tag_name }}
|
release-tag: ${{ inputs.tag_name || github.event.release.tag_name }}
|
||||||
token: ${{ secrets.WINGET_ACC_TOKEN }}
|
token: ${{ secrets.WINGET_ACC_TOKEN }}
|
||||||
|
|||||||
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
570
changelog.md
570
changelog.md
@ -2,8 +2,150 @@
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
#### [v2.2.0](https://github.com/th-ch/youtube-music/compare/v2.1.3...v2.2.0)
|
||||||
|
|
||||||
|
- feat(ambient-mode): add config for `ambient-mode` plugin [`#1349`](https://github.com/th-ch/youtube-music/pull/1349)
|
||||||
|
- bump deps [`4248d20`](https://github.com/th-ch/youtube-music/commit/4248d20e8ef926ce7b1d07eb83743755a341d9f6)
|
||||||
|
- Update changelog for v2.1.3 [`dc73561`](https://github.com/th-ch/youtube-music/commit/dc73561c8a8acfc8ba91aff2dc78e4267869f2fd)
|
||||||
|
- Bump version to 2.2.0 [`6288d0b`](https://github.com/th-ch/youtube-music/commit/6288d0b171a65ea015922cdf3af6c7bd9a1f269b)
|
||||||
|
|
||||||
|
#### [v2.1.3](https://github.com/th-ch/youtube-music/compare/v2.1.2...v2.1.3)
|
||||||
|
|
||||||
|
> 23 October 2023
|
||||||
|
|
||||||
|
- fix: fixed bugs in downloader [`#1342`](https://github.com/th-ch/youtube-music/pull/1342)
|
||||||
|
- feat(discord): rename `Listen Along` to `Play on YTM` [`#1341`](https://github.com/th-ch/youtube-music/issues/1341)
|
||||||
|
- chore(deps): bump deps [`4333891`](https://github.com/th-ch/youtube-music/commit/4333891ccabe42aedf756fd48618be715db13262)
|
||||||
|
- Update changelog for v2.1.2 [`fa4c69d`](https://github.com/th-ch/youtube-music/commit/fa4c69d228d4e06a7858e2b22fcdfa075a8ca766)
|
||||||
|
- fix(store): fix listenAlong statement [`bceaa05`](https://github.com/th-ch/youtube-music/commit/bceaa05197d47a4a4bbd22e767d1e4d6ec277514)
|
||||||
|
|
||||||
|
#### [v2.1.2](https://github.com/th-ch/youtube-music/compare/v2.1.1...v2.1.2)
|
||||||
|
|
||||||
|
> 19 October 2023
|
||||||
|
|
||||||
|
- feat(in-app-menu): add an option to hide the window controls [`#1335`](https://github.com/th-ch/youtube-music/pull/1335)
|
||||||
|
- fix: fixed an issue where the album name was missing [`#1334`](https://github.com/th-ch/youtube-music/pull/1334)
|
||||||
|
- chore(deps): update dependency electron to v27.0.1 [`#1331`](https://github.com/th-ch/youtube-music/pull/1331)
|
||||||
|
- fix: fixed an issue where only the first 100 songs in a playlist were downloaded [`#1329`](https://github.com/th-ch/youtube-music/pull/1329)
|
||||||
|
- Updated readme plugins list [`#1326`](https://github.com/th-ch/youtube-music/pull/1326)
|
||||||
|
- QOL: Move source code under the src directory. [`#1318`](https://github.com/th-ch/youtube-music/pull/1318)
|
||||||
|
- feat: migrate from `npm` to `pnpm` [`#1316`](https://github.com/th-ch/youtube-music/pull/1316)
|
||||||
|
- fix: fix unresponsive (fix #1325) [`#1325`](https://github.com/th-ch/youtube-music/issues/1325)
|
||||||
|
- fix(blocker): remove the `app.isPackaged` check (fix #1315) [`#1315`](https://github.com/th-ch/youtube-music/issues/1315)
|
||||||
|
- fix(discord): `Discord RPC fails if a song's title is only one character` (fix #1314) [`#1314`](https://github.com/th-ch/youtube-music/issues/1314)
|
||||||
|
- chore(deps): Bump @rollup/plugin-commonjs, pnpm version, Remove ytpl [`9705f84`](https://github.com/th-ch/youtube-music/commit/9705f8489d7bf262bfd8b15ab84c2d3485f10eae)
|
||||||
|
- chore(deps): Bump rollup, @xhayper/discord-rpc version [`00a3e8d`](https://github.com/th-ch/youtube-music/commit/00a3e8d35ec335e1913be19f30ae09dbe0b7acdd)
|
||||||
|
- chore(deps): update dependency rollup to v4.1.4 [`6774d54`](https://github.com/th-ch/youtube-music/commit/6774d54f5eca432edc2e11743d9d1b1c2fda9ac8)
|
||||||
|
|
||||||
|
#### [v2.1.1](https://github.com/th-ch/youtube-music/compare/v2.1.0...v2.1.1)
|
||||||
|
|
||||||
|
> 14 October 2023
|
||||||
|
|
||||||
|
- hotfix(downloader): can't get an album title (fix #1313) [`#1313`](https://github.com/th-ch/youtube-music/issues/1313)
|
||||||
|
- Update changelog for v2.1.0 [`92cab89`](https://github.com/th-ch/youtube-music/commit/92cab89d17175741e60e65ea61633e23ebdc1f45)
|
||||||
|
- Bump version to 2.1.1 [`3bb5bc2`](https://github.com/th-ch/youtube-music/commit/3bb5bc2ca1856f4e222ee1e01e865f1ab804fdba)
|
||||||
|
- Add "about" menu to show app version [`21c45fa`](https://github.com/th-ch/youtube-music/commit/21c45faf2043cf72a7c14d5cf6c8d848d0448528)
|
||||||
|
|
||||||
|
#### [v2.1.0](https://github.com/th-ch/youtube-music/compare/v2.0.4...v2.1.0)
|
||||||
|
|
||||||
|
> 14 October 2023
|
||||||
|
|
||||||
|
- feat(downloader): Added support for audio format auto-detection [`#1310`](https://github.com/th-ch/youtube-music/pull/1310)
|
||||||
|
- feat(in-app-menu): enable in-app-menu by default (in Windows) [`#1311`](https://github.com/th-ch/youtube-music/pull/1311)
|
||||||
|
- fix: winget publish [`#1307`](https://github.com/th-ch/youtube-music/pull/1307)
|
||||||
|
- hotfix(downloader): fix invalid query selector (fix #1308) [`#1308`](https://github.com/th-ch/youtube-music/issues/1308)
|
||||||
|
- chore(deps): bump dependencies [`3c6b3ae`](https://github.com/th-ch/youtube-music/commit/3c6b3aeff0aae32adb2f2ad9c091b0a9701d3c24)
|
||||||
|
- chore(actions): create winget-cla.yml [`37181a7`](https://github.com/th-ch/youtube-music/commit/37181a7b5e2aa5bed6a36298eac3a66aac2762b8)
|
||||||
|
- Update changelog for v2.0.4 [`e9398ad`](https://github.com/th-ch/youtube-music/commit/e9398adac34a8abb11801e32999a915a8be0ece6)
|
||||||
|
|
||||||
|
#### [v2.0.4](https://github.com/th-ch/youtube-music/compare/v2.0.3...v2.0.4)
|
||||||
|
|
||||||
|
> 12 October 2023
|
||||||
|
|
||||||
|
- hotfix(adblocker): fix `ipcRenderer.sendSync() with ...` [`#1301`](https://github.com/th-ch/youtube-music/pull/1301)
|
||||||
|
- fix(downloader): Korean filename is broken on non-macOS devices [`#1297`](https://github.com/th-ch/youtube-music/pull/1297)
|
||||||
|
- chore(deps): bump deps [`b6894dc`](https://github.com/th-ch/youtube-music/commit/b6894dca2974c63fa2945d3a4995665d11eb2a78)
|
||||||
|
- fix: bump dependencies [`7aa970c`](https://github.com/th-ch/youtube-music/commit/7aa970cebc8e1407ff6937b402ba303e14c73efd)
|
||||||
|
- fix(downloader): private playlist download [`1d5b299`](https://github.com/th-ch/youtube-music/commit/1d5b2997bd0c72c1c007c57b145509e4a8f77fef)
|
||||||
|
|
||||||
|
#### [v2.0.3](https://github.com/th-ch/youtube-music/compare/v2.0.2...v2.0.3)
|
||||||
|
|
||||||
|
> 10 October 2023
|
||||||
|
|
||||||
|
- feat(discord): add `Hide GitHub link Button` [`#1293`](https://github.com/th-ch/youtube-music/pull/1293)
|
||||||
|
- feat(deps): bundle `youtubei.js` (temporary solution) [`#1292`](https://github.com/th-ch/youtube-music/pull/1292)
|
||||||
|
- fix(mpris): fixed an issue where MPRIS information was incorrect [`#1291`](https://github.com/th-ch/youtube-music/pull/1291)
|
||||||
|
- fix(discord): fixed an issue where `timeChanged` was not being applied to Discord activities [`#1290`](https://github.com/th-ch/youtube-music/pull/1290)
|
||||||
|
- Fix: typo in README [`#1286`](https://github.com/th-ch/youtube-music/pull/1286)
|
||||||
|
- fix: chore(deps): update dependency @jellybrick/mpris-service to 2.1.4 (fix #971) [`#971`](https://github.com/th-ch/youtube-music/issues/971)
|
||||||
|
- chore(deps): Bump `@cliqz/adblocker-electron` to 1.26.8 (fix #1269) [`#1269`](https://github.com/th-ch/youtube-music/issues/1269)
|
||||||
|
- fix: missing icons taskbar-mediacontrol [`fbf4b3b`](https://github.com/th-ch/youtube-music/commit/fbf4b3b8b5e39c61975e67efc990c45f62de76d8)
|
||||||
|
- remove: migration scripts [`52ba2dc`](https://github.com/th-ch/youtube-music/commit/52ba2dc9ffd8e235251d1279686f55e33b3fa3bb)
|
||||||
|
- feat: add migration script [`926b9fb`](https://github.com/th-ch/youtube-music/commit/926b9fb5e6db69b69935ec5d7be9a76a84e54ceb)
|
||||||
|
|
||||||
|
#### [v2.0.2](https://github.com/th-ch/youtube-music/compare/v2.0.1...v2.0.2)
|
||||||
|
|
||||||
|
> 8 October 2023
|
||||||
|
|
||||||
|
- fix: discord-rpc [`#1278`](https://github.com/th-ch/youtube-music/pull/1278)
|
||||||
|
- Bump version to 2.0.2 [`b5dbfaf`](https://github.com/th-ch/youtube-music/commit/b5dbfaf68691a546d72f5c1818fd3a44802eb0fa)
|
||||||
|
- Merge pull request #1272 from th-ch/feat/resolves-1265 [`6b7fd5b`](https://github.com/th-ch/youtube-music/commit/6b7fd5ba630888de08004105179c059c6d93e028)
|
||||||
|
- Merge pull request #1279 from th-ch/fix/1274 [`73a049a`](https://github.com/th-ch/youtube-music/commit/73a049a7bc5161f0d53c252cf510f1e2a6f6eeb3)
|
||||||
|
|
||||||
|
#### [v2.0.1](https://github.com/th-ch/youtube-music/compare/v2.0.0...v2.0.1)
|
||||||
|
|
||||||
|
> 8 October 2023
|
||||||
|
|
||||||
|
- Update changelog for v2.0.0 [`2d69dfd`](https://github.com/th-ch/youtube-music/commit/2d69dfd333c3223ecc7de13a0abc98fd99aa3a2b)
|
||||||
|
- hotfix: hotfix for #1267 [`c002263`](https://github.com/th-ch/youtube-music/commit/c002263c3bdd51890b8ffb431283afb60405d8fe)
|
||||||
|
- Bump version to 2.0.1 [`a1f025e`](https://github.com/th-ch/youtube-music/commit/a1f025e23c599fe5eb63b32ea38ee81200d232d6)
|
||||||
|
|
||||||
|
### [v2.0.0](https://github.com/th-ch/youtube-music/compare/v1.20.0...v2.0.0)
|
||||||
|
|
||||||
|
> 7 October 2023
|
||||||
|
|
||||||
|
- Bump version to 2.0.0 [`#1257`](https://github.com/th-ch/youtube-music/pull/1257)
|
||||||
|
- feat(GitHub): add issue template [`#1264`](https://github.com/th-ch/youtube-music/pull/1264)
|
||||||
|
- feat: I guess it's TypeScript [`#1235`](https://github.com/th-ch/youtube-music/pull/1235)
|
||||||
|
- chore(deps): update dependency rollup to v4 [`#44`](https://github.com/th-ch/youtube-music/pull/44)
|
||||||
|
- feat: apply rollup 🚀 [`#20`](https://github.com/th-ch/youtube-music/pull/20)
|
||||||
|
- fix: Fixes the video-toggle being displayed at the wrong position on fullscreen [`#1218`](https://github.com/th-ch/youtube-music/pull/1218)
|
||||||
|
- Change Winget Releaser job to `ubuntu-latest` [`#1225`](https://github.com/th-ch/youtube-music/pull/1225)
|
||||||
|
- Fixes the video-toggle being displayed at the wrong position on fullscreen [`#1218`](https://github.com/th-ch/youtube-music/pull/1218)
|
||||||
|
- Fix Remove upgrade button [`#1206`](https://github.com/th-ch/youtube-music/pull/1206)
|
||||||
|
- Fixed Age Restriction Bypass [`#1221`](https://github.com/th-ch/youtube-music/pull/1221)
|
||||||
|
- fix(tuna): handle `playPaused` [`#1`](https://github.com/th-ch/youtube-music/pull/1)
|
||||||
|
- Add plugin to always use the compact sidebar [`#1190`](https://github.com/th-ch/youtube-music/pull/1190)
|
||||||
|
- Hide login elements [`#1189`](https://github.com/th-ch/youtube-music/pull/1189)
|
||||||
|
- Fix navigation arrows [`#1191`](https://github.com/th-ch/youtube-music/pull/1191)
|
||||||
|
- MacOS better copy paste in readme.md [`#1156`](https://github.com/th-ch/youtube-music/pull/1156)
|
||||||
|
- feat(build-windows): Add support for IA32 (resolves #1110) [`#1110`](https://github.com/th-ch/youtube-music/issues/1110)
|
||||||
|
- fix: fix the downloader to work in a proxy environment (resolve #46) [`#46`](https://github.com/th-ch/youtube-music/issues/46)
|
||||||
|
- fix: fix #34 [`#34`](https://github.com/th-ch/youtube-music/issues/34)
|
||||||
|
- fix: fix #32 [`#32`](https://github.com/th-ch/youtube-music/issues/32)
|
||||||
|
- fix: fix #29 [`#29`](https://github.com/th-ch/youtube-music/issues/29)
|
||||||
|
- fix: fix #30 [`#30`](https://github.com/th-ch/youtube-music/issues/30)
|
||||||
|
- fix: fix #29 [`#29`](https://github.com/th-ch/youtube-music/issues/29)
|
||||||
|
- fix: fix #30 [`#30`](https://github.com/th-ch/youtube-music/issues/30)
|
||||||
|
- hotfix: fix #28 [`#28`](https://github.com/th-ch/youtube-music/issues/28)
|
||||||
|
- fix: resolve #12 [`#12`](https://github.com/th-ch/youtube-music/issues/12)
|
||||||
|
- fix(precise-volume): fix slider ui does not sync [`#15`](https://github.com/th-ch/youtube-music/issues/15)
|
||||||
|
- fix(video-toggle): fix video config not load config [`#16`](https://github.com/th-ch/youtube-music/issues/16)
|
||||||
|
- refactor(in-app-menu): refactor in-app-menu plugin [`#13`](https://github.com/th-ch/youtube-music/issues/13)
|
||||||
|
- feat(disable-autoplay): add `apply once`, resolve #9 [`#9`](https://github.com/th-ch/youtube-music/issues/9)
|
||||||
|
- fix: fix #4 [`#4`](https://github.com/th-ch/youtube-music/issues/4)
|
||||||
|
- fix: fix #7 [`#7`](https://github.com/th-ch/youtube-music/issues/7)
|
||||||
|
- fix: fix #1187 [`#1187`](https://github.com/th-ch/youtube-music/issues/1187)
|
||||||
|
- fix: resolves #978 [`#978`](https://github.com/th-ch/youtube-music/issues/978)
|
||||||
|
- fix: resolves #958 [`#958`](https://github.com/th-ch/youtube-music/issues/958)
|
||||||
|
- Merge pull request #1259 from organization/feat/fork-to-main [`457a8b5`](https://github.com/th-ch/youtube-music/commit/457a8b5018695d82b043cb7fa7264fbcf43f996c)
|
||||||
|
- fix: remove `xo`, migration to `eslint` [`c722896`](https://github.com/th-ch/youtube-music/commit/c722896a73cfbca3bbbab67bfcdfa639474e9030)
|
||||||
|
- fix: rollback changelog [`9048da2`](https://github.com/th-ch/youtube-music/commit/9048da22f98b9091ab606464a6cbdaad8bc185ae)
|
||||||
|
|
||||||
#### [v1.20.0](https://github.com/th-ch/youtube-music/compare/v1.19.0...v1.20.0)
|
#### [v1.20.0](https://github.com/th-ch/youtube-music/compare/v1.19.0...v1.20.0)
|
||||||
|
|
||||||
|
> 18 May 2023
|
||||||
|
|
||||||
- Bump version to 1.20.0 [`#1117`](https://github.com/th-ch/youtube-music/pull/1117)
|
- Bump version to 1.20.0 [`#1117`](https://github.com/th-ch/youtube-music/pull/1117)
|
||||||
- Multiple implementations for the Adblocker plugin [`#1134`](https://github.com/th-ch/youtube-music/pull/1134)
|
- Multiple implementations for the Adblocker plugin [`#1134`](https://github.com/th-ch/youtube-music/pull/1134)
|
||||||
- add xesam:url mpris from songInfo.url [`#1138`](https://github.com/th-ch/youtube-music/pull/1138)
|
- add xesam:url mpris from songInfo.url [`#1138`](https://github.com/th-ch/youtube-music/pull/1138)
|
||||||
@ -23,29 +165,22 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- Allow downloading age restricted videos [`#1086`](https://github.com/th-ch/youtube-music/pull/1086)
|
- Allow downloading age restricted videos [`#1086`](https://github.com/th-ch/youtube-music/pull/1086)
|
||||||
- add starting page option [`#1073`](https://github.com/th-ch/youtube-music/pull/1073)
|
- add starting page option [`#1073`](https://github.com/th-ch/youtube-music/pull/1073)
|
||||||
- [downloader] plugin overhaul [`#1054`](https://github.com/th-ch/youtube-music/pull/1054)
|
- [downloader] plugin overhaul [`#1054`](https://github.com/th-ch/youtube-music/pull/1054)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.25.2 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.25.2 to 1.26.0 [`#1070`](https://github.com/th-ch/youtube-music/pull/1070)
|
||||||
1.26.0 [`#1070`](https://github.com/th-ch/youtube-music/pull/1070)
|
- [in-app-menu] fix css style of the library of uploaded songs [`#1072`](https://github.com/th-ch/youtube-music/pull/1072)
|
||||||
- [in-app-menu] fix css style of the library of uploaded
|
|
||||||
songs [`#1072`](https://github.com/th-ch/youtube-music/pull/1072)
|
|
||||||
- add option to hide the like buttons [`#1077`](https://github.com/th-ch/youtube-music/pull/1077)
|
- add option to hide the like buttons [`#1077`](https://github.com/th-ch/youtube-music/pull/1077)
|
||||||
- Nitpick: Fix name casing in tray icon tooltip [`#1081`](https://github.com/th-ch/youtube-music/pull/1081)
|
- Nitpick: Fix name casing in tray icon tooltip [`#1081`](https://github.com/th-ch/youtube-music/pull/1081)
|
||||||
- [lyrics-genius] Improved reliability of east asian language detection
|
- [lyrics-genius] Improved reliability of east asian language detection #1080 [`#1082`](https://github.com/th-ch/youtube-music/pull/1082)
|
||||||
#1080 [`#1082`](https://github.com/th-ch/youtube-music/pull/1082)
|
|
||||||
- Add dynamic synced plugin config provider [`#1064`](https://github.com/th-ch/youtube-music/pull/1064)
|
- Add dynamic synced plugin config provider [`#1064`](https://github.com/th-ch/youtube-music/pull/1064)
|
||||||
- [captions-selector] fix button showing when there aren't any captions
|
- [captions-selector] fix button showing when there aren't any captions available [`#1063`](https://github.com/th-ch/youtube-music/pull/1063)
|
||||||
available [`#1063`](https://github.com/th-ch/youtube-music/pull/1063)
|
|
||||||
- [in-app-menu] fix items hidden by navbar in library [`#1067`](https://github.com/th-ch/youtube-music/pull/1067)
|
- [in-app-menu] fix items hidden by navbar in library [`#1067`](https://github.com/th-ch/youtube-music/pull/1067)
|
||||||
- Fix Youtube Music logo is draggable [`#1061`](https://github.com/th-ch/youtube-music/pull/1061)
|
- Fix Youtube Music logo is draggable [`#1061`](https://github.com/th-ch/youtube-music/pull/1061)
|
||||||
- fix build action failing on forks, and run it on pull
|
- fix build action failing on forks, and run it on pull requests [`#1069`](https://github.com/th-ch/youtube-music/pull/1069)
|
||||||
requests [`#1069`](https://github.com/th-ch/youtube-music/pull/1069)
|
|
||||||
- try to fix songInfo time&album [`#1032`](https://github.com/th-ch/youtube-music/pull/1032)
|
- try to fix songInfo time&album [`#1032`](https://github.com/th-ch/youtube-music/pull/1032)
|
||||||
- [lyrics] Romanization toggle for Genius plugin [`#1039`](https://github.com/th-ch/youtube-music/pull/1039)
|
- [lyrics] Romanization toggle for Genius plugin [`#1039`](https://github.com/th-ch/youtube-music/pull/1039)
|
||||||
- [Snyk] Upgrade html-to-text from 9.0.3 to 9.0.4 [`#1056`](https://github.com/th-ch/youtube-music/pull/1056)
|
- [Snyk] Upgrade html-to-text from 9.0.3 to 9.0.4 [`#1056`](https://github.com/th-ch/youtube-music/pull/1056)
|
||||||
- [in-app-menu] add toggle menu icon [`#988`](https://github.com/th-ch/youtube-music/pull/988)
|
- [in-app-menu] add toggle menu icon [`#988`](https://github.com/th-ch/youtube-music/pull/988)
|
||||||
- Fix playback speed slider not showing and PiP button showing when it
|
- Fix playback speed slider not showing and PiP button showing when it shouldn't [`#1048`](https://github.com/th-ch/youtube-music/pull/1048)
|
||||||
shouldn't [`#1048`](https://github.com/th-ch/youtube-music/pull/1048)
|
- [lyrics-genius] Fix lyrics not showing up or showing up when they shouldn't [`#1052`](https://github.com/th-ch/youtube-music/pull/1052)
|
||||||
- [lyrics-genius] Fix lyrics not showing up or showing up when they
|
|
||||||
shouldn't [`#1052`](https://github.com/th-ch/youtube-music/pull/1052)
|
|
||||||
- [in-app-menu] disable nav-bar drag when menu is open [`#1055`](https://github.com/th-ch/youtube-music/pull/1055)
|
- [in-app-menu] disable nav-bar drag when menu is open [`#1055`](https://github.com/th-ch/youtube-music/pull/1055)
|
||||||
- [Notifications] [Windows] Native interactive notifications [`#946`](https://github.com/th-ch/youtube-music/pull/946)
|
- [Notifications] [Windows] Native interactive notifications [`#946`](https://github.com/th-ch/youtube-music/pull/946)
|
||||||
- automate winget releases [`#1049`](https://github.com/th-ch/youtube-music/pull/1049)
|
- automate winget releases [`#1049`](https://github.com/th-ch/youtube-music/pull/1049)
|
||||||
@ -73,8 +208,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- fix SnoreToast implementation [`#941`](https://github.com/th-ch/youtube-music/pull/941)
|
- fix SnoreToast implementation [`#941`](https://github.com/th-ch/youtube-music/pull/941)
|
||||||
- Bump json5 from 1.0.1 to 1.0.2 [`#942`](https://github.com/th-ch/youtube-music/pull/942)
|
- Bump json5 from 1.0.1 to 1.0.2 [`#942`](https://github.com/th-ch/youtube-music/pull/942)
|
||||||
- [Snyk] Upgrade custom-electron-titlebar from 4.1.3 to 4.1.5 [`#969`](https://github.com/th-ch/youtube-music/pull/969)
|
- [Snyk] Upgrade custom-electron-titlebar from 4.1.3 to 4.1.5 [`#969`](https://github.com/th-ch/youtube-music/pull/969)
|
||||||
- Fixed video-toggle aligning running before #main-panel
|
- Fixed video-toggle aligning running before #main-panel exists [`#956`](https://github.com/th-ch/youtube-music/pull/956)
|
||||||
exists [`#956`](https://github.com/th-ch/youtube-music/pull/956)
|
|
||||||
- [New plugin] Music visualizers [`#953`](https://github.com/th-ch/youtube-music/pull/953)
|
- [New plugin] Music visualizers [`#953`](https://github.com/th-ch/youtube-music/pull/953)
|
||||||
- fix PiP buttons not showing up [`#964`](https://github.com/th-ch/youtube-music/pull/964)
|
- fix PiP buttons not showing up [`#964`](https://github.com/th-ch/youtube-music/pull/964)
|
||||||
- Use same audio context/source everywhere [`#951`](https://github.com/th-ch/youtube-music/pull/951)
|
- Use same audio context/source everywhere [`#951`](https://github.com/th-ch/youtube-music/pull/951)
|
||||||
@ -86,8 +220,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- fix unescaped url params [`#1050`](https://github.com/th-ch/youtube-music/issues/1050)
|
- fix unescaped url params [`#1050`](https://github.com/th-ch/youtube-music/issues/1050)
|
||||||
- fix playback speed selector [`#1045`](https://github.com/th-ch/youtube-music/issues/1045)
|
- fix playback speed selector [`#1045`](https://github.com/th-ch/youtube-music/issues/1045)
|
||||||
- fix PiP button [`#959`](https://github.com/th-ch/youtube-music/issues/959)
|
- fix PiP button [`#959`](https://github.com/th-ch/youtube-music/issues/959)
|
||||||
- fix security issues in
|
- fix security issues in deps [`9cde19d`](https://github.com/th-ch/youtube-music/commit/9cde19d906081fe1851f90fa44581b2b74c328e3)
|
||||||
deps [`9cde19d`](https://github.com/th-ch/youtube-music/commit/9cde19d906081fe1851f90fa44581b2b74c328e3)
|
|
||||||
- rome lint [`325026e`](https://github.com/th-ch/youtube-music/commit/325026e3eae3daed33a6d66d1ef9f898d6805b28)
|
- rome lint [`325026e`](https://github.com/th-ch/youtube-music/commit/325026e3eae3daed33a6d66d1ef9f898d6805b28)
|
||||||
- lint [`b652a01`](https://github.com/th-ch/youtube-music/commit/b652a011a5a08978db6660aeca6908c47a7cf07a)
|
- lint [`b652a01`](https://github.com/th-ch/youtube-music/commit/b652a011a5a08978db6660aeca6908c47a7cf07a)
|
||||||
|
|
||||||
@ -100,32 +233,25 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- Load plugins as soon as the window is created [`#890`](https://github.com/th-ch/youtube-music/pull/890)
|
- Load plugins as soon as the window is created [`#890`](https://github.com/th-ch/youtube-music/pull/890)
|
||||||
- Bump qs from 6.5.2 to 6.5.3 [`#913`](https://github.com/th-ch/youtube-music/pull/913)
|
- Bump qs from 6.5.2 to 6.5.3 [`#913`](https://github.com/th-ch/youtube-music/pull/913)
|
||||||
- [Snyk] Upgrade custom-electron-titlebar from 4.1.1 to 4.1.2 [`#900`](https://github.com/th-ch/youtube-music/pull/900)
|
- [Snyk] Upgrade custom-electron-titlebar from 4.1.1 to 4.1.2 [`#900`](https://github.com/th-ch/youtube-music/pull/900)
|
||||||
- Add option in skip-silences plugin to only skip at the
|
- Add option in skip-silences plugin to only skip at the beginning [`#931`](https://github.com/th-ch/youtube-music/pull/931)
|
||||||
beginning [`#931`](https://github.com/th-ch/youtube-music/pull/931)
|
|
||||||
- Replace rimraf by del-cli [`#932`](https://github.com/th-ch/youtube-music/pull/932)
|
- Replace rimraf by del-cli [`#932`](https://github.com/th-ch/youtube-music/pull/932)
|
||||||
- docs: Added winget install instructions [`#873`](https://github.com/th-ch/youtube-music/pull/873)
|
- docs: Added winget install instructions [`#873`](https://github.com/th-ch/youtube-music/pull/873)
|
||||||
- [Snyk] Upgrade async-mutex from 0.3.2 to 0.4.0 [`#855`](https://github.com/th-ch/youtube-music/pull/855)
|
- [Snyk] Upgrade async-mutex from 0.3.2 to 0.4.0 [`#855`](https://github.com/th-ch/youtube-music/pull/855)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.25.0 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.25.0 to 1.25.1 [`#856`](https://github.com/th-ch/youtube-music/pull/856)
|
||||||
1.25.1 [`#856`](https://github.com/th-ch/youtube-music/pull/856)
|
|
||||||
- [Snyk] Upgrade custom-electron-titlebar from 4.1.0 to 4.1.1 [`#865`](https://github.com/th-ch/youtube-music/pull/865)
|
- [Snyk] Upgrade custom-electron-titlebar from 4.1.0 to 4.1.1 [`#865`](https://github.com/th-ch/youtube-music/pull/865)
|
||||||
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.11.5 to 0.11.6 [`#876`](https://github.com/th-ch/youtube-music/pull/876)
|
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.11.5 to 0.11.6 [`#876`](https://github.com/th-ch/youtube-music/pull/876)
|
||||||
- Discord Plugin RPC Fix [`#888`](https://github.com/th-ch/youtube-music/pull/888)
|
- Discord Plugin RPC Fix [`#888`](https://github.com/th-ch/youtube-music/pull/888)
|
||||||
- Bump FFMpeg [`#854`](https://github.com/th-ch/youtube-music/pull/854)
|
- Bump FFMpeg [`#854`](https://github.com/th-ch/youtube-music/pull/854)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.8 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.8 to 1.23.9 [`#823`](https://github.com/th-ch/youtube-music/pull/823)
|
||||||
1.23.9 [`#823`](https://github.com/th-ch/youtube-music/pull/823)
|
|
||||||
- [Snyk] Upgrade electron-store from 8.0.2 to 8.1.0 [`#801`](https://github.com/th-ch/youtube-music/pull/801)
|
- [Snyk] Upgrade electron-store from 8.0.2 to 8.1.0 [`#801`](https://github.com/th-ch/youtube-music/pull/801)
|
||||||
- proposal: Adding an option to hide duration before the song
|
- proposal: Adding an option to hide duration before the song ends [`#802`](https://github.com/th-ch/youtube-music/pull/802)
|
||||||
ends [`#802`](https://github.com/th-ch/youtube-music/pull/802)
|
|
||||||
- [Snyk] Security upgrade node-fetch from 2.6.7 to 3.2.10 [`#790`](https://github.com/th-ch/youtube-music/pull/790)
|
- [Snyk] Security upgrade node-fetch from 2.6.7 to 3.2.10 [`#790`](https://github.com/th-ch/youtube-music/pull/790)
|
||||||
- Update README.md with a new theme repo [`#807`](https://github.com/th-ch/youtube-music/pull/807)
|
- Update README.md with a new theme repo [`#807`](https://github.com/th-ch/youtube-music/pull/807)
|
||||||
- Fix likes on touchbar (they were inverted) [`#822`](https://github.com/th-ch/youtube-music/pull/822)
|
- Fix likes on touchbar (they were inverted) [`#822`](https://github.com/th-ch/youtube-music/pull/822)
|
||||||
- Add Scoop install directions for Windows 🪟 [`#839`](https://github.com/th-ch/youtube-music/pull/839)
|
- Add Scoop install directions for Windows 🪟 [`#839`](https://github.com/th-ch/youtube-music/pull/839)
|
||||||
- Bump version and change release type when publishing a new
|
- Bump version and change release type when publishing a new version [`31ab27c`](https://github.com/th-ch/youtube-music/commit/31ab27c39ff6319116a6514d952eed1f02dd45fd)
|
||||||
version [`31ab27c`](https://github.com/th-ch/youtube-music/commit/31ab27c39ff6319116a6514d952eed1f02dd45fd)
|
- Lock node-fetch to v2 for commonJS [`c9f610f`](https://github.com/th-ch/youtube-music/commit/c9f610f7fcfcce1317338364045ab0e1bf4249a4)
|
||||||
- Lock node-fetch to v2 for
|
- fix: upgrade @cliqz/adblocker-electron from 1.25.0 to 1.25.1 [`762ef4e`](https://github.com/th-ch/youtube-music/commit/762ef4eede29b53aae912b3b50a1ca53f6765c53)
|
||||||
commonJS [`c9f610f`](https://github.com/th-ch/youtube-music/commit/c9f610f7fcfcce1317338364045ab0e1bf4249a4)
|
|
||||||
- fix: upgrade @cliqz/adblocker-electron from 1.25.0 to
|
|
||||||
1.25.1 [`762ef4e`](https://github.com/th-ch/youtube-music/commit/762ef4eede29b53aae912b3b50a1ca53f6765c53)
|
|
||||||
|
|
||||||
#### [v1.18.0](https://github.com/th-ch/youtube-music/compare/v1.17.0...v1.18.0)
|
#### [v1.18.0](https://github.com/th-ch/youtube-music/compare/v1.17.0...v1.18.0)
|
||||||
|
|
||||||
@ -138,8 +264,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- [Snyk] Upgrade electron-store from 8.0.1 to 8.0.2 [`#772`](https://github.com/th-ch/youtube-music/pull/772)
|
- [Snyk] Upgrade electron-store from 8.0.1 to 8.0.2 [`#772`](https://github.com/th-ch/youtube-music/pull/772)
|
||||||
- Bump jpeg-js from 0.4.3 to 0.4.4 [`#756`](https://github.com/th-ch/youtube-music/pull/756)
|
- Bump jpeg-js from 0.4.3 to 0.4.4 [`#756`](https://github.com/th-ch/youtube-music/pull/756)
|
||||||
- Support MPRIS loop and volume change [`#749`](https://github.com/th-ch/youtube-music/pull/749)
|
- Support MPRIS loop and volume change [`#749`](https://github.com/th-ch/youtube-music/pull/749)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.7 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.7 to 1.23.8 [`#742`](https://github.com/th-ch/youtube-music/pull/742)
|
||||||
1.23.8 [`#742`](https://github.com/th-ch/youtube-music/pull/742)
|
|
||||||
- Use ; instead of space for play/pause. [`#745`](https://github.com/th-ch/youtube-music/pull/745)
|
- Use ; instead of space for play/pause. [`#745`](https://github.com/th-ch/youtube-music/pull/745)
|
||||||
- Update readme.md [`#750`](https://github.com/th-ch/youtube-music/pull/750)
|
- Update readme.md [`#750`](https://github.com/th-ch/youtube-music/pull/750)
|
||||||
- fix lyrics font size [`#753`](https://github.com/th-ch/youtube-music/pull/753)
|
- fix lyrics font size [`#753`](https://github.com/th-ch/youtube-music/pull/753)
|
||||||
@ -149,8 +274,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- Picture in Picture v2 [`#685`](https://github.com/th-ch/youtube-music/pull/685)
|
- Picture in Picture v2 [`#685`](https://github.com/th-ch/youtube-music/pull/685)
|
||||||
- Add MPRIS volume control [`#776`](https://github.com/th-ch/youtube-music/issues/776)
|
- Add MPRIS volume control [`#776`](https://github.com/th-ch/youtube-music/issues/776)
|
||||||
- Remove jest [`bb6115f`](https://github.com/th-ch/youtube-music/commit/bb6115fec1a18a416edb365a442eb0b0ee330768)
|
- Remove jest [`bb6115f`](https://github.com/th-ch/youtube-music/commit/bb6115fec1a18a416edb365a442eb0b0ee330768)
|
||||||
- migrate from remote to
|
- migrate from remote to ipc [`5bd9768`](https://github.com/th-ch/youtube-music/commit/5bd97685b9e07c656e0b57a9e02819afc70af1b1)
|
||||||
ipc [`5bd9768`](https://github.com/th-ch/youtube-music/commit/5bd97685b9e07c656e0b57a9e02819afc70af1b1)
|
|
||||||
- v3 [`d23bfe9`](https://github.com/th-ch/youtube-music/commit/d23bfe936840b947ca101fd304464f65d36e88cc)
|
- v3 [`d23bfe9`](https://github.com/th-ch/youtube-music/commit/d23bfe936840b947ca101fd304464f65d36e88cc)
|
||||||
|
|
||||||
#### [v1.17.0](https://github.com/th-ch/youtube-music/compare/v1.16.0...v1.17.0)
|
#### [v1.17.0](https://github.com/th-ch/youtube-music/compare/v1.16.0...v1.17.0)
|
||||||
@ -159,8 +283,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
|
|
||||||
- Bump ejs from 3.1.6 to 3.1.7 [`#712`](https://github.com/th-ch/youtube-music/pull/712)
|
- Bump ejs from 3.1.6 to 3.1.7 [`#712`](https://github.com/th-ch/youtube-music/pull/712)
|
||||||
- fix injectCSS `did-finish-load` listener overload [`#693`](https://github.com/th-ch/youtube-music/pull/693)
|
- fix injectCSS `did-finish-load` listener overload [`#693`](https://github.com/th-ch/youtube-music/pull/693)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.6 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.6 to 1.23.7 [`#689`](https://github.com/th-ch/youtube-music/pull/689)
|
||||||
1.23.7 [`#689`](https://github.com/th-ch/youtube-music/pull/689)
|
|
||||||
- [Snyk] Upgrade custom-electron-prompt from 1.4.1 to 1.4.2 [`#686`](https://github.com/th-ch/youtube-music/pull/686)
|
- [Snyk] Upgrade custom-electron-prompt from 1.4.1 to 1.4.2 [`#686`](https://github.com/th-ch/youtube-music/pull/686)
|
||||||
- [Snyk] Upgrade @electron/remote from 2.0.7 to 2.0.8 [`#684`](https://github.com/th-ch/youtube-music/pull/684)
|
- [Snyk] Upgrade @electron/remote from 2.0.7 to 2.0.8 [`#684`](https://github.com/th-ch/youtube-music/pull/684)
|
||||||
- Improve plugin submenu ux [`#699`](https://github.com/th-ch/youtube-music/pull/699)
|
- Improve plugin submenu ux [`#699`](https://github.com/th-ch/youtube-music/pull/699)
|
||||||
@ -173,27 +296,21 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- Add plugin to bypass age restrictions [`#682`](https://github.com/th-ch/youtube-music/pull/682)
|
- Add plugin to bypass age restrictions [`#682`](https://github.com/th-ch/youtube-music/pull/682)
|
||||||
- Add "Picture in picture" plugin [`#674`](https://github.com/th-ch/youtube-music/pull/674)
|
- Add "Picture in picture" plugin [`#674`](https://github.com/th-ch/youtube-music/pull/674)
|
||||||
- Set lyrics metadata from Genius [`#679`](https://github.com/th-ch/youtube-music/pull/679)
|
- Set lyrics metadata from Genius [`#679`](https://github.com/th-ch/youtube-music/pull/679)
|
||||||
- MacOS: bring back the app in dock when using tray + app
|
- MacOS: bring back the app in dock when using tray + app hidden [`#677`](https://github.com/th-ch/youtube-music/pull/677)
|
||||||
hidden [`#677`](https://github.com/th-ch/youtube-music/pull/677)
|
|
||||||
- [Snyk] Upgrade @electron/remote from 2.0.4 to 2.0.5 [`#644`](https://github.com/th-ch/youtube-music/pull/644)
|
- [Snyk] Upgrade @electron/remote from 2.0.4 to 2.0.5 [`#644`](https://github.com/th-ch/youtube-music/pull/644)
|
||||||
- [Snyk] Upgrade ytpl from 2.2.3 to 2.3.0 [`#660`](https://github.com/th-ch/youtube-music/pull/660)
|
- [Snyk] Upgrade ytpl from 2.2.3 to 2.3.0 [`#660`](https://github.com/th-ch/youtube-music/pull/660)
|
||||||
- [Snyk] Upgrade ytdl-core from 4.10.1 to 4.11.0 [`#659`](https://github.com/th-ch/youtube-music/pull/659)
|
- [Snyk] Upgrade ytdl-core from 4.10.1 to 4.11.0 [`#659`](https://github.com/th-ch/youtube-music/pull/659)
|
||||||
- Bump plist from 3.0.2 to 3.0.5 [`#678`](https://github.com/th-ch/youtube-music/pull/678)
|
- Bump plist from 3.0.2 to 3.0.5 [`#678`](https://github.com/th-ch/youtube-music/pull/678)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.4 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.4 to 1.23.5 [`#624`](https://github.com/th-ch/youtube-music/pull/624)
|
||||||
1.23.5 [`#624`](https://github.com/th-ch/youtube-music/pull/624)
|
|
||||||
- [Precise-Volume] fix volumeHud position in miniplayer [`#645`](https://github.com/th-ch/youtube-music/pull/645)
|
- [Precise-Volume] fix volumeHud position in miniplayer [`#645`](https://github.com/th-ch/youtube-music/pull/645)
|
||||||
- add always-on-top option [`#655`](https://github.com/th-ch/youtube-music/pull/655)
|
- add always-on-top option [`#655`](https://github.com/th-ch/youtube-music/pull/655)
|
||||||
- [precise-volume] fix expand-volume-slider not updating its
|
- [precise-volume] fix expand-volume-slider not updating its value [`#670`](https://github.com/th-ch/youtube-music/pull/670)
|
||||||
value [`#670`](https://github.com/th-ch/youtube-music/pull/670)
|
|
||||||
- Fix lyrics genius missing parts [`#671`](https://github.com/th-ch/youtube-music/pull/671)
|
- Fix lyrics genius missing parts [`#671`](https://github.com/th-ch/youtube-music/pull/671)
|
||||||
- feat: option to force show like buttons [`#673`](https://github.com/th-ch/youtube-music/pull/673)
|
- feat: option to force show like buttons [`#673`](https://github.com/th-ch/youtube-music/pull/673)
|
||||||
- fix custom titlebar in prompt options [`#619`](https://github.com/th-ch/youtube-music/pull/619)
|
- fix custom titlebar in prompt options [`#619`](https://github.com/th-ch/youtube-music/pull/619)
|
||||||
- Process lyrics HTML in Genius
|
- Process lyrics HTML in Genius util [`d0532d6`](https://github.com/th-ch/youtube-music/commit/d0532d691e56f955ef0b41f5fe2efe6295dddf9e)
|
||||||
util [`d0532d6`](https://github.com/th-ch/youtube-music/commit/d0532d691e56f955ef0b41f5fe2efe6295dddf9e)
|
- Create first version of picture in picture plugin [`d2265b5`](https://github.com/th-ch/youtube-music/commit/d2265b59d78143cf51fe4dc3d5dee9da66873cc1)
|
||||||
- Create first version of picture in picture
|
- Bump electron-builder to fix Mac build script [`ae8365f`](https://github.com/th-ch/youtube-music/commit/ae8365f721eafda6c502d02eee86d098f2b9e2a1)
|
||||||
plugin [`d2265b5`](https://github.com/th-ch/youtube-music/commit/d2265b59d78143cf51fe4dc3d5dee9da66873cc1)
|
|
||||||
- Bump electron-builder to fix Mac build
|
|
||||||
script [`ae8365f`](https://github.com/th-ch/youtube-music/commit/ae8365f721eafda6c502d02eee86d098f2b9e2a1)
|
|
||||||
|
|
||||||
#### [v1.16.0](https://github.com/th-ch/youtube-music/compare/v1.15.0...v1.16.0)
|
#### [v1.16.0](https://github.com/th-ch/youtube-music/compare/v1.15.0...v1.16.0)
|
||||||
|
|
||||||
@ -202,8 +319,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- update in-app-menu [`#596`](https://github.com/th-ch/youtube-music/pull/596)
|
- update in-app-menu [`#596`](https://github.com/th-ch/youtube-music/pull/596)
|
||||||
- Fix clientID [`#602`](https://github.com/th-ch/youtube-music/pull/602)
|
- Fix clientID [`#602`](https://github.com/th-ch/youtube-music/pull/602)
|
||||||
- Add snoretoast custom compile script [`#600`](https://github.com/th-ch/youtube-music/pull/600)
|
- Add snoretoast custom compile script [`#600`](https://github.com/th-ch/youtube-music/pull/600)
|
||||||
- fix interactive notifications icon + exclude platform specific plugins from
|
- fix interactive notifications icon + exclude platform specific plugins from build [`#591`](https://github.com/th-ch/youtube-music/pull/591)
|
||||||
build [`#591`](https://github.com/th-ch/youtube-music/pull/591)
|
|
||||||
- Add album title to largeImage and change paused icon [`#587`](https://github.com/th-ch/youtube-music/pull/587)
|
- Add album title to largeImage and change paused icon [`#587`](https://github.com/th-ch/youtube-music/pull/587)
|
||||||
- make useragent override optional [`#595`](https://github.com/th-ch/youtube-music/pull/595)
|
- make useragent override optional [`#595`](https://github.com/th-ch/youtube-music/pull/595)
|
||||||
- get album name from DOM [`#588`](https://github.com/th-ch/youtube-music/pull/588)
|
- get album name from DOM [`#588`](https://github.com/th-ch/youtube-music/pull/588)
|
||||||
@ -218,8 +334,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- fix precise-volume hud positioning [`#567`](https://github.com/th-ch/youtube-music/pull/567)
|
- fix precise-volume hud positioning [`#567`](https://github.com/th-ch/youtube-music/pull/567)
|
||||||
- update electron and dependencies [`#565`](https://github.com/th-ch/youtube-music/pull/565)
|
- update electron and dependencies [`#565`](https://github.com/th-ch/youtube-music/pull/565)
|
||||||
- filenamify playlist folder name [`#557`](https://github.com/th-ch/youtube-music/pull/557)
|
- filenamify playlist folder name [`#557`](https://github.com/th-ch/youtube-music/pull/557)
|
||||||
- [Snyk] Security upgrade node-fetch from 2.6.6 to 2.6.7 (3.1.1
|
- [Snyk] Security upgrade node-fetch from 2.6.6 to 2.6.7 (3.1.1 incompatible) [`#554`](https://github.com/th-ch/youtube-music/pull/554)
|
||||||
incompatible) [`#554`](https://github.com/th-ch/youtube-music/pull/554)
|
|
||||||
- fix app starting offscreen [`#548`](https://github.com/th-ch/youtube-music/pull/548)
|
- fix app starting offscreen [`#548`](https://github.com/th-ch/youtube-music/pull/548)
|
||||||
- Release Mac arm64 [`#566`](https://github.com/th-ch/youtube-music/pull/566)
|
- Release Mac arm64 [`#566`](https://github.com/th-ch/youtube-music/pull/566)
|
||||||
- Build command for Apple (m1) silicon macs [`#553`](https://github.com/th-ch/youtube-music/pull/553)
|
- Build command for Apple (m1) silicon macs [`#553`](https://github.com/th-ch/youtube-music/pull/553)
|
||||||
@ -229,24 +344,17 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- allow downloading playlists from popup menu [`#549`](https://github.com/th-ch/youtube-music/pull/549)
|
- allow downloading playlists from popup menu [`#549`](https://github.com/th-ch/youtube-music/pull/549)
|
||||||
- xesam:artist should be a list [`#539`](https://github.com/th-ch/youtube-music/pull/539)
|
- xesam:artist should be a list [`#539`](https://github.com/th-ch/youtube-music/pull/539)
|
||||||
- fix notifications showing thumbnail of last song [`#537`](https://github.com/th-ch/youtube-music/pull/537)
|
- fix notifications showing thumbnail of last song [`#537`](https://github.com/th-ch/youtube-music/pull/537)
|
||||||
-
|
- Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#578`](https://github.com/th-ch/youtube-music/pull/578)
|
||||||
|
- Add automatic changelog [`1d9bfe8`](https://github.com/th-ch/youtube-music/commit/1d9bfe8ac8869cde648164979986964baa52c2f9)
|
||||||
Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#578`](https://github.com/th-ch/youtube-music/pull/578)
|
- update electron to v17.0.0 [`fef7115`](https://github.com/th-ch/youtube-music/commit/fef711549fa9862f8ea23301edde747c5802e352)
|
||||||
|
- update dependencies [`8be07bc`](https://github.com/th-ch/youtube-music/commit/8be07bcb7ad8b727d97c36aa0760aed4e2fc481f)
|
||||||
- Add automatic
|
|
||||||
changelog [`1d9bfe8`](https://github.com/th-ch/youtube-music/commit/1d9bfe8ac8869cde648164979986964baa52c2f9)
|
|
||||||
- update electron to
|
|
||||||
v17.0.0 [`fef7115`](https://github.com/th-ch/youtube-music/commit/fef711549fa9862f8ea23301edde747c5802e352)
|
|
||||||
- update
|
|
||||||
dependencies [`8be07bc`](https://github.com/th-ch/youtube-music/commit/8be07bcb7ad8b727d97c36aa0760aed4e2fc481f)
|
|
||||||
|
|
||||||
#### [v1.15.0](https://github.com/th-ch/youtube-music/compare/v1.14.0...v1.15.0)
|
#### [v1.15.0](https://github.com/th-ch/youtube-music/compare/v1.14.0...v1.15.0)
|
||||||
|
|
||||||
> 30 December 2021
|
> 30 December 2021
|
||||||
|
|
||||||
- Switch from spectron to playwright to fix tests [`#531`](https://github.com/th-ch/youtube-music/pull/531)
|
- Switch from spectron to playwright to fix tests [`#531`](https://github.com/th-ch/youtube-music/pull/531)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.0 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.23.0 to 1.23.1 [`#529`](https://github.com/th-ch/youtube-music/pull/529)
|
||||||
1.23.1 [`#529`](https://github.com/th-ch/youtube-music/pull/529)
|
|
||||||
- fix precise-volume options sync [`#525`](https://github.com/th-ch/youtube-music/pull/525)
|
- fix precise-volume options sync [`#525`](https://github.com/th-ch/youtube-music/pull/525)
|
||||||
- Add album art/thumbnail to discord activity [`#524`](https://github.com/th-ch/youtube-music/pull/524)
|
- Add album art/thumbnail to discord activity [`#524`](https://github.com/th-ch/youtube-music/pull/524)
|
||||||
- fix skip-silences plugin [`#521`](https://github.com/th-ch/youtube-music/pull/521)
|
- fix skip-silences plugin [`#521`](https://github.com/th-ch/youtube-music/pull/521)
|
||||||
@ -256,23 +364,19 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Add "Skip silences" plugin [`#519`](https://github.com/th-ch/youtube-music/pull/519)
|
- Add "Skip silences" plugin [`#519`](https://github.com/th-ch/youtube-music/pull/519)
|
||||||
- Aligned lyric design [`#510`](https://github.com/th-ch/youtube-music/pull/510)
|
- Aligned lyric design [`#510`](https://github.com/th-ch/youtube-music/pull/510)
|
||||||
- Fix mpris bugs - follows #480 [`#509`](https://github.com/th-ch/youtube-music/pull/509)
|
- Fix mpris bugs - follows #480 [`#509`](https://github.com/th-ch/youtube-music/pull/509)
|
||||||
- Various small fixes (discord, video-toggle, precise-volume, playback-speed, shortcuts,
|
- Various small fixes (discord, video-toggle, precise-volume, playback-speed, shortcuts, lyrics) [`#476`](https://github.com/th-ch/youtube-music/pull/476)
|
||||||
lyrics) [`#476`](https://github.com/th-ch/youtube-music/pull/476)
|
|
||||||
- Mpris + obs-tuna fixes [`#480`](https://github.com/th-ch/youtube-music/pull/480)
|
- Mpris + obs-tuna fixes [`#480`](https://github.com/th-ch/youtube-music/pull/480)
|
||||||
- [Snyk] Upgrade node-fetch from 2.6.5 to 2.6.6 [`#498`](https://github.com/th-ch/youtube-music/pull/498)
|
- [Snyk] Upgrade node-fetch from 2.6.5 to 2.6.6 [`#498`](https://github.com/th-ch/youtube-music/pull/498)
|
||||||
- fix interaction between blur navbar & in-app-menu [`#491`](https://github.com/th-ch/youtube-music/pull/491)
|
- fix interaction between blur navbar & in-app-menu [`#491`](https://github.com/th-ch/youtube-music/pull/491)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.7 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.7 to 1.23.0 [`#475`](https://github.com/th-ch/youtube-music/pull/475)
|
||||||
1.23.0 [`#475`](https://github.com/th-ch/youtube-music/pull/475)
|
|
||||||
- New Plugin: Exponential Volume [`#488`](https://github.com/th-ch/youtube-music/pull/488)
|
- New Plugin: Exponential Volume [`#488`](https://github.com/th-ch/youtube-music/pull/488)
|
||||||
- [Snyk] Upgrade electron-updater from 4.6.0 to 4.6.1 [`#474`](https://github.com/th-ch/youtube-music/pull/474)
|
- [Snyk] Upgrade electron-updater from 4.6.0 to 4.6.1 [`#474`](https://github.com/th-ch/youtube-music/pull/474)
|
||||||
- Fix loadeddata/metadata video events rarely not firing (+other small
|
- Fix loadeddata/metadata video events rarely not firing (+other small fixes) [`#477`](https://github.com/th-ch/youtube-music/pull/477)
|
||||||
fixes) [`#477`](https://github.com/th-ch/youtube-music/pull/477)
|
|
||||||
- fix #490 [`#490`](https://github.com/th-ch/youtube-music/issues/490)
|
- fix #490 [`#490`](https://github.com/th-ch/youtube-music/issues/490)
|
||||||
- fix #472 [`#472`](https://github.com/th-ch/youtube-music/issues/472)
|
- fix #472 [`#472`](https://github.com/th-ch/youtube-music/issues/472)
|
||||||
- fix mpris [`ccfe743`](https://github.com/th-ch/youtube-music/commit/ccfe7434bf708ee58156c2952234a049706edfc2)
|
- fix mpris [`ccfe743`](https://github.com/th-ch/youtube-music/commit/ccfe7434bf708ee58156c2952234a049706edfc2)
|
||||||
- lint [`4362101`](https://github.com/th-ch/youtube-music/commit/4362101c0a2ebb7f0536f615cecba8a55ac96702)
|
- lint [`4362101`](https://github.com/th-ch/youtube-music/commit/4362101c0a2ebb7f0536f615cecba8a55ac96702)
|
||||||
- rework songInfo pause
|
- rework songInfo pause listener [`6726e26`](https://github.com/th-ch/youtube-music/commit/6726e2600b3ca3a8d68e3e1b95b50da211fa354d)
|
||||||
listener [`6726e26`](https://github.com/th-ch/youtube-music/commit/6726e2600b3ca3a8d68e3e1b95b50da211fa354d)
|
|
||||||
|
|
||||||
#### [v1.14.0](https://github.com/th-ch/youtube-music/compare/v1.13.0...v1.14.0)
|
#### [v1.14.0](https://github.com/th-ch/youtube-music/compare/v1.13.0...v1.14.0)
|
||||||
|
|
||||||
@ -293,60 +397,50 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Discord plugin: Clean Up Export (follow-up #380) [`#440`](https://github.com/th-ch/youtube-music/pull/440)
|
- Discord plugin: Clean Up Export (follow-up #380) [`#440`](https://github.com/th-ch/youtube-music/pull/440)
|
||||||
- remove upgrade button + makes images unselectable [`#434`](https://github.com/th-ch/youtube-music/pull/434)
|
- remove upgrade button + makes images unselectable [`#434`](https://github.com/th-ch/youtube-music/pull/434)
|
||||||
- new auto confirm when paused [`#433`](https://github.com/th-ch/youtube-music/pull/433)
|
- new auto confirm when paused [`#433`](https://github.com/th-ch/youtube-music/pull/433)
|
||||||
- fix: mpris instance not registering itself and media
|
- fix: mpris instance not registering itself and media controls [`#431`](https://github.com/th-ch/youtube-music/pull/431)
|
||||||
controls [`#431`](https://github.com/th-ch/youtube-music/pull/431)
|
|
||||||
- Audio compressor plugin [`#288`](https://github.com/th-ch/youtube-music/pull/288)
|
- Audio compressor plugin [`#288`](https://github.com/th-ch/youtube-music/pull/288)
|
||||||
- precise-volume plugin fixes & updates [`#275`](https://github.com/th-ch/youtube-music/pull/275)
|
- precise-volume plugin fixes & updates [`#275`](https://github.com/th-ch/youtube-music/pull/275)
|
||||||
- Custom Prompt for changing options [`#243`](https://github.com/th-ch/youtube-music/pull/243)
|
- Custom Prompt for changing options [`#243`](https://github.com/th-ch/youtube-music/pull/243)
|
||||||
- [Snyk] Upgrade async-mutex from 0.3.1 to 0.3.2 [`#412`](https://github.com/th-ch/youtube-music/pull/412)
|
- [Snyk] Upgrade async-mutex from 0.3.1 to 0.3.2 [`#412`](https://github.com/th-ch/youtube-music/pull/412)
|
||||||
- build(deps): bump tmpl from 1.0.4 to 1.0.5 [`#414`](https://github.com/th-ch/youtube-music/pull/414)
|
- build(deps): bump tmpl from 1.0.4 to 1.0.5 [`#414`](https://github.com/th-ch/youtube-music/pull/414)
|
||||||
- [Snyk] Upgrade node-fetch from 2.6.1 to 2.6.2 [`#416`](https://github.com/th-ch/youtube-music/pull/416)
|
- [Snyk] Upgrade node-fetch from 2.6.1 to 2.6.2 [`#416`](https://github.com/th-ch/youtube-music/pull/416)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.5 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.5 to 1.22.6 [`#429`](https://github.com/th-ch/youtube-music/pull/429)
|
||||||
1.22.6 [`#429`](https://github.com/th-ch/youtube-music/pull/429)
|
|
||||||
- build(deps-dev): bump electron from 12.0.8 to 12.1.0 [`#430`](https://github.com/th-ch/youtube-music/pull/430)
|
- build(deps-dev): bump electron from 12.0.8 to 12.1.0 [`#430`](https://github.com/th-ch/youtube-music/pull/430)
|
||||||
- Fix discord clearActivity, menu, listen along option [`#380`](https://github.com/th-ch/youtube-music/pull/380)
|
- Fix discord clearActivity, menu, listen along option [`#380`](https://github.com/th-ch/youtube-music/pull/380)
|
||||||
- Bump dev deps [`41a01ba`](https://github.com/th-ch/youtube-music/commit/41a01ba58a17056ba5143fdbd10d3bae11dd8d52)
|
- Bump dev deps [`41a01ba`](https://github.com/th-ch/youtube-music/commit/41a01ba58a17056ba5143fdbd10d3bae11dd8d52)
|
||||||
- Discord add reconnecting
|
- Discord add reconnecting functionality [`b5fd6b4`](https://github.com/th-ch/youtube-music/commit/b5fd6b4969a318b3738583e7f33eb2c0cf295237)
|
||||||
functionality [`b5fd6b4`](https://github.com/th-ch/youtube-music/commit/b5fd6b4969a318b3738583e7f33eb2c0cf295237)
|
- add custom-electron-prompt [`e4eed2e`](https://github.com/th-ch/youtube-music/commit/e4eed2e51979378e62dab902e425218cae5108dc)
|
||||||
- add
|
|
||||||
custom-electron-prompt [`e4eed2e`](https://github.com/th-ch/youtube-music/commit/e4eed2e51979378e62dab902e425218cae5108dc)
|
|
||||||
|
|
||||||
#### [v1.13.0](https://github.com/th-ch/youtube-music/compare/v1.12.2...v1.13.0)
|
#### [v1.13.0](https://github.com/th-ch/youtube-music/compare/v1.12.2...v1.13.0)
|
||||||
|
|
||||||
> 19 September 2021
|
> 19 September 2021
|
||||||
|
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.4 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.4 to 1.22.5 [`#406`](https://github.com/th-ch/youtube-music/pull/406)
|
||||||
1.22.5 [`#406`](https://github.com/th-ch/youtube-music/pull/406)
|
- Fix incorrect Google alert caused by changing user agent coresponding to current platform [`#384`](https://github.com/th-ch/youtube-music/pull/384)
|
||||||
- Fix incorrect Google alert caused by changing user agent coresponding to current
|
|
||||||
platform [`#384`](https://github.com/th-ch/youtube-music/pull/384)
|
|
||||||
- [Snyk] Upgrade electron-updater from 4.4.3 to 4.4.6 [`#401`](https://github.com/th-ch/youtube-music/pull/401)
|
- [Snyk] Upgrade electron-updater from 4.4.3 to 4.4.6 [`#401`](https://github.com/th-ch/youtube-music/pull/401)
|
||||||
- [Snyk] Upgrade electron-updater from 4.4.0 to 4.4.1 [`#370`](https://github.com/th-ch/youtube-music/pull/370)
|
- [Snyk] Upgrade electron-updater from 4.4.0 to 4.4.1 [`#370`](https://github.com/th-ch/youtube-music/pull/370)
|
||||||
- Bump path-parse from 1.0.6 to 1.0.7 [`#375`](https://github.com/th-ch/youtube-music/pull/375)
|
- Bump path-parse from 1.0.6 to 1.0.7 [`#375`](https://github.com/th-ch/youtube-music/pull/375)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.2 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3 [`#385`](https://github.com/th-ch/youtube-music/pull/385)
|
||||||
1.22.3 [`#385`](https://github.com/th-ch/youtube-music/pull/385)
|
|
||||||
- Bump jszip from 3.5.0 to 3.7.1 [`#388`](https://github.com/th-ch/youtube-music/pull/388)
|
- Bump jszip from 3.5.0 to 3.7.1 [`#388`](https://github.com/th-ch/youtube-music/pull/388)
|
||||||
- List missing plugins [`#382`](https://github.com/th-ch/youtube-music/pull/382)
|
- List missing plugins [`#382`](https://github.com/th-ch/youtube-music/pull/382)
|
||||||
- add tuna plugin for obs [`#397`](https://github.com/th-ch/youtube-music/pull/397)
|
- add tuna plugin for obs [`#397`](https://github.com/th-ch/youtube-music/pull/397)
|
||||||
- Update menu buttons to new format [`#389`](https://github.com/th-ch/youtube-music/pull/389)
|
- Update menu buttons to new format [`#389`](https://github.com/th-ch/youtube-music/pull/389)
|
||||||
- Plugin to fetch lyrics from Genius [`#387`](https://github.com/th-ch/youtube-music/pull/387)
|
- Plugin to fetch lyrics from Genius [`#387`](https://github.com/th-ch/youtube-music/pull/387)
|
||||||
- Add mpris support with cherry picked commit from previous
|
- Add mpris support with cherry picked commit from previous PR https://github.com/th-ch/youtube-music/pull/394 [`#395`](https://github.com/th-ch/youtube-music/pull/395)
|
||||||
PR https://github.com/th-ch/youtube-music/pull/394 [`#395`](https://github.com/th-ch/youtube-music/pull/395)
|
|
||||||
- Add "Listen Along" button, solve #353 [`#383`](https://github.com/th-ch/youtube-music/pull/383)
|
- Add "Listen Along" button, solve #353 [`#383`](https://github.com/th-ch/youtube-music/pull/383)
|
||||||
- Bump node to v14 [`#386`](https://github.com/th-ch/youtube-music/pull/386)
|
- Bump node to v14 [`#386`](https://github.com/th-ch/youtube-music/pull/386)
|
||||||
- [Snyk] Upgrade electron-updater from 4.3.9 to 4.3.10 [`#350`](https://github.com/th-ch/youtube-music/pull/350)
|
- [Snyk] Upgrade electron-updater from 4.3.9 to 4.3.10 [`#350`](https://github.com/th-ch/youtube-music/pull/350)
|
||||||
- [Snyk] Upgrade chokidar from 3.5.1 to 3.5.2 [`#354`](https://github.com/th-ch/youtube-music/pull/354)
|
- [Snyk] Upgrade chokidar from 3.5.1 to 3.5.2 [`#354`](https://github.com/th-ch/youtube-music/pull/354)
|
||||||
- Bump ytdl/ytpl [`c01506d`](https://github.com/th-ch/youtube-music/commit/c01506dc441bfc538471dc2c552c1a8a2800c611)
|
- Bump ytdl/ytpl [`c01506d`](https://github.com/th-ch/youtube-music/commit/c01506dc441bfc538471dc2c552c1a8a2800c611)
|
||||||
- Add mpris support [`e255777`](https://github.com/th-ch/youtube-music/commit/e255777283c7b16611404cbfe260bfcca75a1e40)
|
- Add mpris support [`e255777`](https://github.com/th-ch/youtube-music/commit/e255777283c7b16611404cbfe260bfcca75a1e40)
|
||||||
- Add Genius lyrics
|
- Add Genius lyrics plugin [`acbe0ac`](https://github.com/th-ch/youtube-music/commit/acbe0ac25d568c25fedb514e0e96c66497b0f2d6)
|
||||||
plugin [`acbe0ac`](https://github.com/th-ch/youtube-music/commit/acbe0ac25d568c25fedb514e0e96c66497b0f2d6)
|
|
||||||
|
|
||||||
#### [v1.12.2](https://github.com/th-ch/youtube-music/compare/v1.12.1...v1.12.2)
|
#### [v1.12.2](https://github.com/th-ch/youtube-music/compare/v1.12.1...v1.12.2)
|
||||||
|
|
||||||
> 1 July 2021
|
> 1 July 2021
|
||||||
|
|
||||||
- Fix downloader plugin [`#339`](https://github.com/th-ch/youtube-music/pull/339)
|
- Fix downloader plugin [`#339`](https://github.com/th-ch/youtube-music/pull/339)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.0 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.22.0 to 1.22.1 [`#337`](https://github.com/th-ch/youtube-music/pull/337)
|
||||||
1.22.1 [`#337`](https://github.com/th-ch/youtube-music/pull/337)
|
|
||||||
- Update and simplify in-app-menu [`#249`](https://github.com/th-ch/youtube-music/pull/249)
|
- Update and simplify in-app-menu [`#249`](https://github.com/th-ch/youtube-music/pull/249)
|
||||||
- Bump hosted-git-info from 2.8.8 to 2.8.9 [`#331`](https://github.com/th-ch/youtube-music/pull/331)
|
- Bump hosted-git-info from 2.8.8 to 2.8.9 [`#331`](https://github.com/th-ch/youtube-music/pull/331)
|
||||||
- Bump lodash from 4.17.20 to 4.17.21 [`#330`](https://github.com/th-ch/youtube-music/pull/330)
|
- Bump lodash from 4.17.20 to 4.17.21 [`#330`](https://github.com/th-ch/youtube-music/pull/330)
|
||||||
@ -357,16 +451,12 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- [Snyk] Upgrade @ffmpeg/core from 0.9.0 to 0.10.0 [`#317`](https://github.com/th-ch/youtube-music/pull/317)
|
- [Snyk] Upgrade @ffmpeg/core from 0.9.0 to 0.10.0 [`#317`](https://github.com/th-ch/youtube-music/pull/317)
|
||||||
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0 [`#316`](https://github.com/th-ch/youtube-music/pull/316)
|
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0 [`#316`](https://github.com/th-ch/youtube-music/pull/316)
|
||||||
- [Snyk] Upgrade custom-electron-titlebar from 3.2.6 to 3.2.7 [`#311`](https://github.com/th-ch/youtube-music/pull/311)
|
- [Snyk] Upgrade custom-electron-titlebar from 3.2.6 to 3.2.7 [`#311`](https://github.com/th-ch/youtube-music/pull/311)
|
||||||
- fix hidden webp thumbnail throwing MIME type error in
|
- fix hidden webp thumbnail throwing MIME type error in downloader [`#318`](https://github.com/th-ch/youtube-music/pull/318)
|
||||||
downloader [`#318`](https://github.com/th-ch/youtube-music/pull/318)
|
|
||||||
- Add Sponsorblock plugin [`#308`](https://github.com/th-ch/youtube-music/pull/308)
|
- Add Sponsorblock plugin [`#308`](https://github.com/th-ch/youtube-music/pull/308)
|
||||||
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.7 to 0.9.8 [`#305`](https://github.com/th-ch/youtube-music/pull/305)
|
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.7 to 0.9.8 [`#305`](https://github.com/th-ch/youtube-music/pull/305)
|
||||||
- Bump dependencies to fix
|
- Bump dependencies to fix vulnerabilities [`496836b`](https://github.com/th-ch/youtube-music/commit/496836b33b116e06b8d1361ce1f47ab6c9138cae)
|
||||||
vulnerabilities [`496836b`](https://github.com/th-ch/youtube-music/commit/496836b33b116e06b8d1361ce1f47ab6c9138cae)
|
- update refreshMenu() function [`33855f1`](https://github.com/th-ch/youtube-music/commit/33855f17dd80c099117a3d84bbd9b5021776771c)
|
||||||
- update refreshMenu()
|
- Add SponsorBlock plugin [`ca64a77`](https://github.com/th-ch/youtube-music/commit/ca64a77ed0236fd9cfb4b40e450578a186638dc7)
|
||||||
function [`33855f1`](https://github.com/th-ch/youtube-music/commit/33855f17dd80c099117a3d84bbd9b5021776771c)
|
|
||||||
- Add SponsorBlock
|
|
||||||
plugin [`ca64a77`](https://github.com/th-ch/youtube-music/commit/ca64a77ed0236fd9cfb4b40e450578a186638dc7)
|
|
||||||
|
|
||||||
#### [v1.12.1](https://github.com/th-ch/youtube-music/compare/v1.12.0...v1.12.1)
|
#### [v1.12.1](https://github.com/th-ch/youtube-music/compare/v1.12.0...v1.12.1)
|
||||||
|
|
||||||
@ -374,15 +464,13 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
|
|
||||||
- Bump ws from 7.4.3 to 7.4.6 [`#303`](https://github.com/th-ch/youtube-music/pull/303)
|
- Bump ws from 7.4.3 to 7.4.6 [`#303`](https://github.com/th-ch/youtube-music/pull/303)
|
||||||
- Bump browserslist from 4.16.3 to 4.16.6 [`#301`](https://github.com/th-ch/youtube-music/pull/301)
|
- Bump browserslist from 4.16.3 to 4.16.6 [`#301`](https://github.com/th-ch/youtube-music/pull/301)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.4 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5 [`#300`](https://github.com/th-ch/youtube-music/pull/300)
|
||||||
1.20.5 [`#300`](https://github.com/th-ch/youtube-music/pull/300)
|
|
||||||
- [Snyk] Upgrade ytdl-core from 4.5.0 to 4.7.0 [`#299`](https://github.com/th-ch/youtube-music/pull/299)
|
- [Snyk] Upgrade ytdl-core from 4.5.0 to 4.7.0 [`#299`](https://github.com/th-ch/youtube-music/pull/299)
|
||||||
- [Snyk] Upgrade @ffmpeg/core from 0.8.5 to 0.9.0 [`#298`](https://github.com/th-ch/youtube-music/pull/298)
|
- [Snyk] Upgrade @ffmpeg/core from 0.8.5 to 0.9.0 [`#298`](https://github.com/th-ch/youtube-music/pull/298)
|
||||||
- [Snyk] Upgrade filenamify from 4.2.0 to 4.3.0 [`#293`](https://github.com/th-ch/youtube-music/pull/293)
|
- [Snyk] Upgrade filenamify from 4.2.0 to 4.3.0 [`#293`](https://github.com/th-ch/youtube-music/pull/293)
|
||||||
- [Snyk] Upgrade ytpl from 2.1.1 to 2.2.0 [`#285`](https://github.com/th-ch/youtube-music/pull/285)
|
- [Snyk] Upgrade ytpl from 2.1.1 to 2.2.0 [`#285`](https://github.com/th-ch/youtube-music/pull/285)
|
||||||
- fix song-info callback duplication [`#269`](https://github.com/th-ch/youtube-music/pull/269)
|
- fix song-info callback duplication [`#269`](https://github.com/th-ch/youtube-music/pull/269)
|
||||||
- fix notification showing appID instead of app name on
|
- fix notification showing appID instead of app name on windows [`#270`](https://github.com/th-ch/youtube-music/pull/270)
|
||||||
windows [`#270`](https://github.com/th-ch/youtube-music/pull/270)
|
|
||||||
- Upgrade electron to v12 [`#273`](https://github.com/th-ch/youtube-music/pull/273)
|
- Upgrade electron to v12 [`#273`](https://github.com/th-ch/youtube-music/pull/273)
|
||||||
- fix last-fm overwrite config on each start [`#267`](https://github.com/th-ch/youtube-music/pull/267)
|
- fix last-fm overwrite config on each start [`#267`](https://github.com/th-ch/youtube-music/pull/267)
|
||||||
- Downloader tweaks + taskbar progress bar [`#265`](https://github.com/th-ch/youtube-music/pull/265)
|
- Downloader tweaks + taskbar progress bar [`#265`](https://github.com/th-ch/youtube-music/pull/265)
|
||||||
@ -392,12 +480,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Bump ua-parser-js from 0.7.23 to 0.7.28 [`#260`](https://github.com/th-ch/youtube-music/pull/260)
|
- Bump ua-parser-js from 0.7.23 to 0.7.28 [`#260`](https://github.com/th-ch/youtube-music/pull/260)
|
||||||
- Fix precise volume listener override [`#253`](https://github.com/th-ch/youtube-music/pull/253)
|
- Fix precise volume listener override [`#253`](https://github.com/th-ch/youtube-music/pull/253)
|
||||||
- fix css not inserting on reload [`#255`](https://github.com/th-ch/youtube-music/pull/255)
|
- fix css not inserting on reload [`#255`](https://github.com/th-ch/youtube-music/pull/255)
|
||||||
- playlist download progressBar
|
- playlist download progressBar using `chokidar` [`53bf7c5`](https://github.com/th-ch/youtube-music/commit/53bf7c5068fdc14f5aa469d47b3174d27f40e05c)
|
||||||
using `chokidar` [`53bf7c5`](https://github.com/th-ch/youtube-music/commit/53bf7c5068fdc14f5aa469d47b3174d27f40e05c)
|
- download progress bar on taskbar [`a8ac2c3`](https://github.com/th-ch/youtube-music/commit/a8ac2c3af988f299be85010e7fea541096b7e261)
|
||||||
- download progress bar on
|
- fix: upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5 [`c5f84b5`](https://github.com/th-ch/youtube-music/commit/c5f84b568b0c3480af1abc8ff111771e2170a50e)
|
||||||
taskbar [`a8ac2c3`](https://github.com/th-ch/youtube-music/commit/a8ac2c3af988f299be85010e7fea541096b7e261)
|
|
||||||
- fix: upgrade @cliqz/adblocker-electron from 1.20.4 to
|
|
||||||
1.20.5 [`c5f84b5`](https://github.com/th-ch/youtube-music/commit/c5f84b568b0c3480af1abc8ff111771e2170a50e)
|
|
||||||
|
|
||||||
#### [v1.12.0](https://github.com/th-ch/youtube-music/compare/v1.11.0...v1.12.0)
|
#### [v1.12.0](https://github.com/th-ch/youtube-music/compare/v1.11.0...v1.12.0)
|
||||||
|
|
||||||
@ -407,8 +492,7 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Interactive notifications for windows [`#228`](https://github.com/th-ch/youtube-music/pull/228)
|
- Interactive notifications for windows [`#228`](https://github.com/th-ch/youtube-music/pull/228)
|
||||||
- [Plugin] Precise volume control [`#236`](https://github.com/th-ch/youtube-music/pull/236)
|
- [Plugin] Precise volume control [`#236`](https://github.com/th-ch/youtube-music/pull/236)
|
||||||
- [Snyk] Upgrade electron-store from 7.0.2 to 7.0.3 [`#244`](https://github.com/th-ch/youtube-music/pull/244)
|
- [Snyk] Upgrade electron-store from 7.0.2 to 7.0.3 [`#244`](https://github.com/th-ch/youtube-music/pull/244)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.3 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.3 to 1.20.4 [`#233`](https://github.com/th-ch/youtube-music/pull/233)
|
||||||
1.20.4 [`#233`](https://github.com/th-ch/youtube-music/pull/233)
|
|
||||||
- Dependencies update [`#231`](https://github.com/th-ch/youtube-music/pull/231)
|
- Dependencies update [`#231`](https://github.com/th-ch/youtube-music/pull/231)
|
||||||
- Fix downloader metadata [`#245`](https://github.com/th-ch/youtube-music/pull/245)
|
- Fix downloader metadata [`#245`](https://github.com/th-ch/youtube-music/pull/245)
|
||||||
- Last.fm support [`#196`](https://github.com/th-ch/youtube-music/pull/196)
|
- Last.fm support [`#196`](https://github.com/th-ch/youtube-music/pull/196)
|
||||||
@ -423,53 +507,40 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- [Plugin] styled-bars [`#201`](https://github.com/th-ch/youtube-music/pull/201)
|
- [Plugin] styled-bars [`#201`](https://github.com/th-ch/youtube-music/pull/201)
|
||||||
- Add configurable notification urgency [`#212`](https://github.com/th-ch/youtube-music/pull/212)
|
- Add configurable notification urgency [`#212`](https://github.com/th-ch/youtube-music/pull/212)
|
||||||
- add Download Folder Chooser [`#207`](https://github.com/th-ch/youtube-music/pull/207)
|
- add Download Folder Chooser [`#207`](https://github.com/th-ch/youtube-music/pull/207)
|
||||||
- Improved songinfo provider, by using the data from the '/player'
|
- Improved songinfo provider, by using the data from the '/player' request [`#194`](https://github.com/th-ch/youtube-music/pull/194)
|
||||||
request [`#194`](https://github.com/th-ch/youtube-music/pull/194)
|
|
||||||
- Download plugin directory chooser [`#10`](https://github.com/th-ch/youtube-music/pull/10)
|
- Download plugin directory chooser [`#10`](https://github.com/th-ch/youtube-music/pull/10)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.0 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1 [`#180`](https://github.com/th-ch/youtube-music/pull/180)
|
||||||
1.20.1 [`#180`](https://github.com/th-ch/youtube-music/pull/180)
|
|
||||||
- [Plugin] taskbar-mediacontrol (for Windows) [`#200`](https://github.com/th-ch/youtube-music/pull/200)
|
- [Plugin] taskbar-mediacontrol (for Windows) [`#200`](https://github.com/th-ch/youtube-music/pull/200)
|
||||||
- merge source [`#3`](https://github.com/th-ch/youtube-music/pull/3)
|
- merge source [`#3`](https://github.com/th-ch/youtube-music/pull/3)
|
||||||
- merge source [`#2`](https://github.com/th-ch/youtube-music/pull/2)
|
- merge source [`#2`](https://github.com/th-ch/youtube-music/pull/2)
|
||||||
- Add playlist feature in downloader plugin + custom menus in plugin
|
- Add playlist feature in downloader plugin + custom menus in plugin system [`#203`](https://github.com/th-ch/youtube-music/pull/203)
|
||||||
system [`#203`](https://github.com/th-ch/youtube-music/pull/203)
|
|
||||||
- Added Discord timeout [`#192`](https://github.com/th-ch/youtube-music/pull/192)
|
- Added Discord timeout [`#192`](https://github.com/th-ch/youtube-music/pull/192)
|
||||||
- Override hide(),show(),isVisible from inside
|
- Override hide(),show(),isVisible from inside plugin [`6427b34`](https://github.com/th-ch/youtube-music/commit/6427b3406c8d84c5b7ecbe6a28158d5dc895c3c2)
|
||||||
plugin [`6427b34`](https://github.com/th-ch/youtube-music/commit/6427b3406c8d84c5b7ecbe6a28158d5dc895c3c2)
|
- added back original yarn.lock [`24fea5a`](https://github.com/th-ch/youtube-music/commit/24fea5a24afd4f547628549962d24756cca5e413)
|
||||||
- added back original
|
- remove local prompt [`8dc486f`](https://github.com/th-ch/youtube-music/commit/8dc486f18fe02a218b149838dc7ab939ec1b698a)
|
||||||
yarn.lock [`24fea5a`](https://github.com/th-ch/youtube-music/commit/24fea5a24afd4f547628549962d24756cca5e413)
|
|
||||||
- remove local
|
|
||||||
prompt [`8dc486f`](https://github.com/th-ch/youtube-music/commit/8dc486f18fe02a218b149838dc7ab939ec1b698a)
|
|
||||||
|
|
||||||
#### [v1.11.0](https://github.com/th-ch/youtube-music/compare/v1.10.0...v1.11.0)
|
#### [v1.11.0](https://github.com/th-ch/youtube-music/compare/v1.10.0...v1.11.0)
|
||||||
|
|
||||||
> 9 March 2021
|
> 9 March 2021
|
||||||
|
|
||||||
- [Snyk] Upgrade electron-store from 7.0.1 to 7.0.2 [`#178`](https://github.com/th-ch/youtube-music/pull/178)
|
- [Snyk] Upgrade electron-store from 7.0.1 to 7.0.2 [`#178`](https://github.com/th-ch/youtube-music/pull/178)
|
||||||
- Added function to toggle resuming of last song when app
|
- Added function to toggle resuming of last song when app starts [`#177`](https://github.com/th-ch/youtube-music/pull/177)
|
||||||
starts [`#177`](https://github.com/th-ch/youtube-music/pull/177)
|
|
||||||
- [Snyk] Upgrade discord-rpc from 3.1.4 to 3.2.0 [`#175`](https://github.com/th-ch/youtube-music/pull/175)
|
- [Snyk] Upgrade discord-rpc from 3.1.4 to 3.2.0 [`#175`](https://github.com/th-ch/youtube-music/pull/175)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.19.0 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.19.0 to 1.20.0 [`#154`](https://github.com/th-ch/youtube-music/pull/154)
|
||||||
1.20.0 [`#154`](https://github.com/th-ch/youtube-music/pull/154)
|
- Added metadata to downloader plugin, and updated packages [`dd1bdae`](https://github.com/th-ch/youtube-music/commit/dd1bdae9478ef831ee2a00b29be04c65626933f8)
|
||||||
- Added metadata to downloader plugin, and updated
|
- Fix download/speed menu item [`796a7aa`](https://github.com/th-ch/youtube-music/commit/796a7aaaf1ecaf80b2ef113137f2222499803e29)
|
||||||
packages [`dd1bdae`](https://github.com/th-ch/youtube-music/commit/dd1bdae9478ef831ee2a00b29be04c65626933f8)
|
- fix: upgrade @cliqz/adblocker-electron from 1.19.0 to 1.20.0 [`538ab52`](https://github.com/th-ch/youtube-music/commit/538ab52abd46c2e3c6abb529c5137b5286d29670)
|
||||||
- Fix download/speed menu
|
|
||||||
item [`796a7aa`](https://github.com/th-ch/youtube-music/commit/796a7aaaf1ecaf80b2ef113137f2222499803e29)
|
|
||||||
- fix: upgrade @cliqz/adblocker-electron from 1.19.0 to
|
|
||||||
1.20.0 [`538ab52`](https://github.com/th-ch/youtube-music/commit/538ab52abd46c2e3c6abb529c5137b5286d29670)
|
|
||||||
|
|
||||||
#### [v1.10.0](https://github.com/th-ch/youtube-music/compare/v1.9.0...v1.10.0)
|
#### [v1.10.0](https://github.com/th-ch/youtube-music/compare/v1.9.0...v1.10.0)
|
||||||
|
|
||||||
> 7 February 2021
|
> 7 February 2021
|
||||||
|
|
||||||
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.6 to 0.9.7 [`#146`](https://github.com/th-ch/youtube-music/pull/146)
|
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.6 to 0.9.7 [`#146`](https://github.com/th-ch/youtube-music/pull/146)
|
||||||
- Reuse the same notification, instead of creating a new one each time the song
|
- Reuse the same notification, instead of creating a new one each time the song changes. [`#144`](https://github.com/th-ch/youtube-music/pull/144)
|
||||||
changes. [`#144`](https://github.com/th-ch/youtube-music/pull/144)
|
|
||||||
- [Snyk] Upgrade ytdl-core from 4.2.1 to 4.3.0 [`#136`](https://github.com/th-ch/youtube-music/pull/136)
|
- [Snyk] Upgrade ytdl-core from 4.2.1 to 4.3.0 [`#136`](https://github.com/th-ch/youtube-music/pull/136)
|
||||||
- bring the new commits to this fork [`#1`](https://github.com/th-ch/youtube-music/pull/1)
|
- bring the new commits to this fork [`#1`](https://github.com/th-ch/youtube-music/pull/1)
|
||||||
- GH page [`3bcf409`](https://github.com/th-ch/youtube-music/commit/3bcf409f2b1629333714b187c606891cedb12512)
|
- GH page [`3bcf409`](https://github.com/th-ch/youtube-music/commit/3bcf409f2b1629333714b187c606891cedb12512)
|
||||||
- Add plugin to control playback speed like in YouTube (from 0.25 to
|
- Add plugin to control playback speed like in YouTube (from 0.25 to 2) [`f7f3185`](https://github.com/th-ch/youtube-music/commit/f7f31850d3d9879002dc47326e4f6ec9a52c25a1)
|
||||||
2) [`f7f3185`](https://github.com/th-ch/youtube-music/commit/f7f31850d3d9879002dc47326e4f6ec9a52c25a1)
|
|
||||||
- Update back.js [`1fdf241`](https://github.com/th-ch/youtube-music/commit/1fdf2416ad414035104bfb51b8450d82e566cb13)
|
- Update back.js [`1fdf241`](https://github.com/th-ch/youtube-music/commit/1fdf2416ad414035104bfb51b8450d82e566cb13)
|
||||||
|
|
||||||
#### [v1.9.0](https://github.com/th-ch/youtube-music/compare/v1.8.2...v1.9.0)
|
#### [v1.9.0](https://github.com/th-ch/youtube-music/compare/v1.8.2...v1.9.0)
|
||||||
@ -478,47 +549,35 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
|
|
||||||
- [Snyk] Upgrade electron-debug from 3.1.0 to 3.2.0 [`#121`](https://github.com/th-ch/youtube-music/pull/121)
|
- [Snyk] Upgrade electron-debug from 3.1.0 to 3.2.0 [`#121`](https://github.com/th-ch/youtube-music/pull/121)
|
||||||
- Refactor providers [`#125`](https://github.com/th-ch/youtube-music/pull/125)
|
- Refactor providers [`#125`](https://github.com/th-ch/youtube-music/pull/125)
|
||||||
- Added Discord rich presence and added extra properties to songInfo
|
- Added Discord rich presence and added extra properties to songInfo provider [`#124`](https://github.com/th-ch/youtube-music/pull/124)
|
||||||
provider [`#124`](https://github.com/th-ch/youtube-music/pull/124)
|
|
||||||
- Fix plugins with context isolation [`#127`](https://github.com/th-ch/youtube-music/pull/127)
|
- Fix plugins with context isolation [`#127`](https://github.com/th-ch/youtube-music/pull/127)
|
||||||
- Windows portable exe [`#126`](https://github.com/th-ch/youtube-music/pull/126)
|
- Windows portable exe [`#126`](https://github.com/th-ch/youtube-music/pull/126)
|
||||||
- Split providers in
|
- Split providers in 2 [`0743034`](https://github.com/th-ch/youtube-music/commit/0743034de0443e889ec11d7ea83727ff4fb96599)
|
||||||
2 [`0743034`](https://github.com/th-ch/youtube-music/commit/0743034de0443e889ec11d7ea83727ff4fb96599)
|
- Added Discord rich presence and added extra properties to songinfo provider [`a8ce87f`](https://github.com/th-ch/youtube-music/commit/a8ce87f2ccb4f0fdbd36676883e6a0497bebc263)
|
||||||
- Added Discord rich presence and added extra properties to songinfo
|
- Update discord plugin for new provider + wait for ready [`aec542e`](https://github.com/th-ch/youtube-music/commit/aec542e95e2837f54bf19de675f311444789ea4e)
|
||||||
provider [`a8ce87f`](https://github.com/th-ch/youtube-music/commit/a8ce87f2ccb4f0fdbd36676883e6a0497bebc263)
|
|
||||||
- Update discord plugin for new provider + wait for
|
|
||||||
ready [`aec542e`](https://github.com/th-ch/youtube-music/commit/aec542e95e2837f54bf19de675f311444789ea4e)
|
|
||||||
|
|
||||||
#### [v1.8.2](https://github.com/th-ch/youtube-music/compare/v1.8.1...v1.8.2)
|
#### [v1.8.2](https://github.com/th-ch/youtube-music/compare/v1.8.1...v1.8.2)
|
||||||
|
|
||||||
> 12 January 2021
|
> 12 January 2021
|
||||||
|
|
||||||
- Downloader plugin - custom audio format [`#118`](https://github.com/th-ch/youtube-music/pull/118)
|
- Downloader plugin - custom audio format [`#118`](https://github.com/th-ch/youtube-music/pull/118)
|
||||||
- Globalized the song info and song controls, and updated Touch Bar for
|
- Globalized the song info and song controls, and updated Touch Bar for it. [`#102`](https://github.com/th-ch/youtube-music/pull/102)
|
||||||
it. [`#102`](https://github.com/th-ch/youtube-music/pull/102)
|
|
||||||
- Bump electron to v11 [`#120`](https://github.com/th-ch/youtube-music/pull/120)
|
- Bump electron to v11 [`#120`](https://github.com/th-ch/youtube-music/pull/120)
|
||||||
- Globalized the songinfo and song controls, and changed the pause/play
|
- Globalized the songinfo and song controls, and changed the pause/play button. [`9be3e1a`](https://github.com/th-ch/youtube-music/commit/9be3e1afe91f0aa3419040bba65e7b3b83b469c6)
|
||||||
button. [`9be3e1a`](https://github.com/th-ch/youtube-music/commit/9be3e1afe91f0aa3419040bba65e7b3b83b469c6)
|
- Simplifies the notification plugin to use the globalized song info [`5bffdbd`](https://github.com/th-ch/youtube-music/commit/5bffdbd6285a6816749c467d6e912d14748f9959)
|
||||||
- Simplifies the notification plugin to use the globalized song
|
- Loads providers before plugins [`3a5d9bd`](https://github.com/th-ch/youtube-music/commit/3a5d9bd973bdd67e77f8a7687c1430245a9490bd)
|
||||||
info [`5bffdbd`](https://github.com/th-ch/youtube-music/commit/5bffdbd6285a6816749c467d6e912d14748f9959)
|
|
||||||
- Loads providers before
|
|
||||||
plugins [`3a5d9bd`](https://github.com/th-ch/youtube-music/commit/3a5d9bd973bdd67e77f8a7687c1430245a9490bd)
|
|
||||||
|
|
||||||
#### [v1.8.1](https://github.com/th-ch/youtube-music/compare/v1.8.0...v1.8.1)
|
#### [v1.8.1](https://github.com/th-ch/youtube-music/compare/v1.8.0...v1.8.1)
|
||||||
|
|
||||||
> 8 January 2021
|
> 8 January 2021
|
||||||
|
|
||||||
- [Snyk] Upgrade electron-updater from 4.3.5 to 4.3.6 [`#116`](https://github.com/th-ch/youtube-music/pull/116)
|
- [Snyk] Upgrade electron-updater from 4.3.5 to 4.3.6 [`#116`](https://github.com/th-ch/youtube-music/pull/116)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.18.8 to
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.18.8 to 1.19.0 [`#117`](https://github.com/th-ch/youtube-music/pull/117)
|
||||||
1.19.0 [`#117`](https://github.com/th-ch/youtube-music/pull/117)
|
|
||||||
- [Snyk] Upgrade ytdl-core from 4.1.1 to 4.1.2 [`#109`](https://github.com/th-ch/youtube-music/pull/109)
|
- [Snyk] Upgrade ytdl-core from 4.1.1 to 4.1.2 [`#109`](https://github.com/th-ch/youtube-music/pull/109)
|
||||||
- Bump node-notifier from 8.0.0 to 8.0.1 [`#104`](https://github.com/th-ch/youtube-music/pull/104)
|
- Bump node-notifier from 8.0.0 to 8.0.1 [`#104`](https://github.com/th-ch/youtube-music/pull/104)
|
||||||
- fix: upgrade electron-updater from 4.3.5 to
|
- fix: upgrade electron-updater from 4.3.5 to 4.3.6 [`0bf77e5`](https://github.com/th-ch/youtube-music/commit/0bf77e592a87eb8a5222cf2c1588488a51044422)
|
||||||
4.3.6 [`0bf77e5`](https://github.com/th-ch/youtube-music/commit/0bf77e592a87eb8a5222cf2c1588488a51044422)
|
- fix: upgrade @cliqz/adblocker-electron from 1.18.8 to 1.19.0 [`5c0cc08`](https://github.com/th-ch/youtube-music/commit/5c0cc08d80d60c46e8b27343c6fc302f64fe89e2)
|
||||||
- fix: upgrade @cliqz/adblocker-electron from 1.18.8 to
|
- fix: upgrade ytdl-core from 4.1.1 to 4.1.2 [`e2cc262`](https://github.com/th-ch/youtube-music/commit/e2cc2628aea653739f878ec2cd2e72e2e70018a1)
|
||||||
1.19.0 [`5c0cc08`](https://github.com/th-ch/youtube-music/commit/5c0cc08d80d60c46e8b27343c6fc302f64fe89e2)
|
|
||||||
- fix: upgrade ytdl-core from 4.1.1 to
|
|
||||||
4.1.2 [`e2cc262`](https://github.com/th-ch/youtube-music/commit/e2cc2628aea653739f878ec2cd2e72e2e70018a1)
|
|
||||||
|
|
||||||
#### [v1.8.0](https://github.com/th-ch/youtube-music/compare/v1.7.5...v1.8.0)
|
#### [v1.8.0](https://github.com/th-ch/youtube-music/compare/v1.7.5...v1.8.0)
|
||||||
|
|
||||||
@ -529,12 +588,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6 [`#100`](https://github.com/th-ch/youtube-music/pull/100)
|
- [Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6 [`#100`](https://github.com/th-ch/youtube-music/pull/100)
|
||||||
- [Readme] Web folder for readme assets + new SVG animation [`#96`](https://github.com/th-ch/youtube-music/pull/96)
|
- [Readme] Web folder for readme assets + new SVG animation [`#96`](https://github.com/th-ch/youtube-music/pull/96)
|
||||||
- Add new Linux targets (deb, freebsd, rpm) [`#94`](https://github.com/th-ch/youtube-music/pull/94)
|
- Add new Linux targets (deb, freebsd, rpm) [`#94`](https://github.com/th-ch/youtube-music/pull/94)
|
||||||
- Web folder for readme assets + new svg
|
- Web folder for readme assets + new svg animation [`01fc965`](https://github.com/th-ch/youtube-music/commit/01fc9651705f457da63615ff774f00957f783d3d)
|
||||||
animation [`01fc965`](https://github.com/th-ch/youtube-music/commit/01fc9651705f457da63615ff774f00957f783d3d)
|
- touchbar plugin - fixed code style [`7473677`](https://github.com/th-ch/youtube-music/commit/7473677477071ca5e7b18bda3193e345d7fd549f)
|
||||||
- touchbar plugin - fixed code
|
- added initial touchbar support [`c3e2c13`](https://github.com/th-ch/youtube-music/commit/c3e2c1380810d156d9d6863fffc804242171bec0)
|
||||||
style [`7473677`](https://github.com/th-ch/youtube-music/commit/7473677477071ca5e7b18bda3193e345d7fd549f)
|
|
||||||
- added initial touchbar
|
|
||||||
support [`c3e2c13`](https://github.com/th-ch/youtube-music/commit/c3e2c1380810d156d9d6863fffc804242171bec0)
|
|
||||||
|
|
||||||
#### [v1.7.5](https://github.com/th-ch/youtube-music/compare/v1.7.4...v1.7.5)
|
#### [v1.7.5](https://github.com/th-ch/youtube-music/compare/v1.7.4...v1.7.5)
|
||||||
|
|
||||||
@ -542,12 +598,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
|
|
||||||
- Bump ini from 1.3.5 to 1.3.7 [`#92`](https://github.com/th-ch/youtube-music/pull/92)
|
- Bump ini from 1.3.5 to 1.3.7 [`#92`](https://github.com/th-ch/youtube-music/pull/92)
|
||||||
- Fix adblocking [`#90`](https://github.com/th-ch/youtube-music/pull/90)
|
- Fix adblocking [`#90`](https://github.com/th-ch/youtube-music/pull/90)
|
||||||
- Bump adblocker
|
- Bump adblocker dependency [`49497d0`](https://github.com/th-ch/youtube-music/commit/49497d0efb28ee0be5b16d0f1c3660efafcd289c)
|
||||||
dependency [`49497d0`](https://github.com/th-ch/youtube-music/commit/49497d0efb28ee0be5b16d0f1c3660efafcd289c)
|
- Fix adblocker preloading to inject scripts/styles [`66c5ce4`](https://github.com/th-ch/youtube-music/commit/66c5ce46caa85a7ae4ceb3d63a9e168827015c71)
|
||||||
- Fix adblocker preloading to inject
|
- Add uBlock Origin filters to default sources [`79c7959`](https://github.com/th-ch/youtube-music/commit/79c795927a3be96456a2f45159285c64166a29b8)
|
||||||
scripts/styles [`66c5ce4`](https://github.com/th-ch/youtube-music/commit/66c5ce46caa85a7ae4ceb3d63a9e168827015c71)
|
|
||||||
- Add uBlock Origin filters to default
|
|
||||||
sources [`79c7959`](https://github.com/th-ch/youtube-music/commit/79c795927a3be96456a2f45159285c64166a29b8)
|
|
||||||
|
|
||||||
#### [v1.7.4](https://github.com/th-ch/youtube-music/compare/v1.7.3...v1.7.4)
|
#### [v1.7.4](https://github.com/th-ch/youtube-music/compare/v1.7.3...v1.7.4)
|
||||||
|
|
||||||
@ -557,41 +610,32 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
|
|
||||||
> 8 December 2020
|
> 8 December 2020
|
||||||
|
|
||||||
- Adblocker: add option to disable default
|
- Adblocker: add option to disable default lists [`22c7f70`](https://github.com/th-ch/youtube-music/commit/22c7f70c938566a9db9c4d46a57224cfdee43df0)
|
||||||
lists [`22c7f70`](https://github.com/th-ch/youtube-music/commit/22c7f70c938566a9db9c4d46a57224cfdee43df0)
|
|
||||||
|
|
||||||
#### [v1.7.2](https://github.com/th-ch/youtube-music/compare/v1.7.1...v1.7.2)
|
#### [v1.7.2](https://github.com/th-ch/youtube-music/compare/v1.7.1...v1.7.2)
|
||||||
|
|
||||||
> 6 December 2020
|
> 6 December 2020
|
||||||
|
|
||||||
- Add AUR badge + beautify badges [`#82`](https://github.com/th-ch/youtube-music/pull/82)
|
- Add AUR badge + beautify badges [`#82`](https://github.com/th-ch/youtube-music/pull/82)
|
||||||
- Bugfix: only use cache with no additional
|
- Bugfix: only use cache with no additional blocklists [`467171a`](https://github.com/th-ch/youtube-music/commit/467171a17e648331d63f166c2da2f3134e95b37f)
|
||||||
blocklists [`467171a`](https://github.com/th-ch/youtube-music/commit/467171a17e648331d63f166c2da2f3134e95b37f)
|
- Add AUR tag + beautify tags [`d212206`](https://github.com/th-ch/youtube-music/commit/d21220693b9ffa26e05fe1963376b636b40b9952)
|
||||||
- Add AUR tag + beautify
|
- Readme: add youtube-music logo to badges [`3022fac`](https://github.com/th-ch/youtube-music/commit/3022facbead40ccd81629c37b870ab33ce7fa106)
|
||||||
tags [`d212206`](https://github.com/th-ch/youtube-music/commit/d21220693b9ffa26e05fe1963376b636b40b9952)
|
|
||||||
- Readme: add youtube-music logo to
|
|
||||||
badges [`3022fac`](https://github.com/th-ch/youtube-music/commit/3022facbead40ccd81629c37b870ab33ce7fa106)
|
|
||||||
|
|
||||||
#### [v1.7.1](https://github.com/th-ch/youtube-music/compare/v1.7.0...v1.7.1)
|
#### [v1.7.1](https://github.com/th-ch/youtube-music/compare/v1.7.0...v1.7.1)
|
||||||
|
|
||||||
> 3 December 2020
|
> 3 December 2020
|
||||||
|
|
||||||
- Option to restart the app on config
|
- Option to restart the app on config changes [`fd97576`](https://github.com/th-ch/youtube-music/commit/fd97576611ae80b959ffe7984e88ddc8d28a1ffc)
|
||||||
changes [`fd97576`](https://github.com/th-ch/youtube-music/commit/fd97576611ae80b959ffe7984e88ddc8d28a1ffc)
|
- Bump version to 1.7.1 [`e07cac2`](https://github.com/th-ch/youtube-music/commit/e07cac240691b1c9d6909e457824616182374c3a)
|
||||||
- Bump version to
|
|
||||||
1.7.1 [`e07cac2`](https://github.com/th-ch/youtube-music/commit/e07cac240691b1c9d6909e457824616182374c3a)
|
|
||||||
|
|
||||||
#### [v1.7.0](https://github.com/th-ch/youtube-music/compare/v1.6.5...v1.7.0)
|
#### [v1.7.0](https://github.com/th-ch/youtube-music/compare/v1.6.5...v1.7.0)
|
||||||
|
|
||||||
> 3 December 2020
|
> 3 December 2020
|
||||||
|
|
||||||
- Refactor config, custom plugin options [`#79`](https://github.com/th-ch/youtube-music/pull/79)
|
- Refactor config, custom plugin options [`#79`](https://github.com/th-ch/youtube-music/pull/79)
|
||||||
- Refactor config for simpler use and advanced options in
|
- Refactor config for simpler use and advanced options in plugins [`8ab2da0`](https://github.com/th-ch/youtube-music/commit/8ab2da0482b6211b6b6d43423ec06daed48dac4f)
|
||||||
plugins [`8ab2da0`](https://github.com/th-ch/youtube-music/commit/8ab2da0482b6211b6b6d43423ec06daed48dac4f)
|
- Allow editing config (advanced) [`f4fe5c2`](https://github.com/th-ch/youtube-music/commit/f4fe5c2a58e1ad555c321f27c00d2d78184fc687)
|
||||||
- Allow editing config (
|
- Adblocker - advanced options (caching or not, additional lists) [`b94d0d4`](https://github.com/th-ch/youtube-music/commit/b94d0d4e8bd3a92bbb5e012a63fa782baa774be7)
|
||||||
advanced) [`f4fe5c2`](https://github.com/th-ch/youtube-music/commit/f4fe5c2a58e1ad555c321f27c00d2d78184fc687)
|
|
||||||
- Adblocker - advanced options (caching or not, additional
|
|
||||||
lists) [`b94d0d4`](https://github.com/th-ch/youtube-music/commit/b94d0d4e8bd3a92bbb5e012a63fa782baa774be7)
|
|
||||||
|
|
||||||
#### [v1.6.5](https://github.com/th-ch/youtube-music/compare/v1.6.4...v1.6.5)
|
#### [v1.6.5](https://github.com/th-ch/youtube-music/compare/v1.6.4...v1.6.5)
|
||||||
|
|
||||||
@ -602,12 +646,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Reflect Arch Linux package name change [`#70`](https://github.com/th-ch/youtube-music/pull/70)
|
- Reflect Arch Linux package name change [`#70`](https://github.com/th-ch/youtube-music/pull/70)
|
||||||
- Option to hide menu [`#67`](https://github.com/th-ch/youtube-music/pull/67)
|
- Option to hide menu [`#67`](https://github.com/th-ch/youtube-music/pull/67)
|
||||||
- Add Arch Linux installation instructions [`#68`](https://github.com/th-ch/youtube-music/pull/68)
|
- Add Arch Linux installation instructions [`#68`](https://github.com/th-ch/youtube-music/pull/68)
|
||||||
- Update ytdl-core to
|
- Update ytdl-core to 4.1.1 [`33a11ef`](https://github.com/th-ch/youtube-music/commit/33a11efe9acad234e41ad9044ae9e67fd573b7f4)
|
||||||
4.1.1 [`33a11ef`](https://github.com/th-ch/youtube-music/commit/33a11efe9acad234e41ad9044ae9e67fd573b7f4)
|
- Autoupdate modal: add download/disable updates buttons [`ae5b85d`](https://github.com/th-ch/youtube-music/commit/ae5b85d8d748659f2e23d417560026f24ab8ce9c)
|
||||||
- Autoupdate modal: add download/disable updates
|
- Option to hide menu (win/linux) [`4bac3ac`](https://github.com/th-ch/youtube-music/commit/4bac3ace186c5be2cb9409d2b703f960bd662145)
|
||||||
buttons [`ae5b85d`](https://github.com/th-ch/youtube-music/commit/ae5b85d8d748659f2e23d417560026f24ab8ce9c)
|
|
||||||
- Option to hide menu (
|
|
||||||
win/linux) [`4bac3ac`](https://github.com/th-ch/youtube-music/commit/4bac3ace186c5be2cb9409d2b703f960bd662145)
|
|
||||||
|
|
||||||
#### [v1.6.4](https://github.com/th-ch/youtube-music/compare/v1.6.3...v1.6.4)
|
#### [v1.6.4](https://github.com/th-ch/youtube-music/compare/v1.6.3...v1.6.4)
|
||||||
|
|
||||||
@ -620,12 +661,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Improve CI [`#64`](https://github.com/th-ch/youtube-music/pull/64)
|
- Improve CI [`#64`](https://github.com/th-ch/youtube-music/pull/64)
|
||||||
- Ensure menu is visible on all platforms [`#63`](https://github.com/th-ch/youtube-music/pull/63)
|
- Ensure menu is visible on all platforms [`#63`](https://github.com/th-ch/youtube-music/pull/63)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4 [`#62`](https://github.com/th-ch/youtube-music/pull/62)
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4 [`#62`](https://github.com/th-ch/youtube-music/pull/62)
|
||||||
- fix: upgrade @cliqz/adblocker-electron from 1.18.3 to
|
- fix: upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4 [`2b243f6`](https://github.com/th-ch/youtube-music/commit/2b243f6dcb00d3b6f27fd066c093e7b16bb384e2)
|
||||||
1.18.4 [`2b243f6`](https://github.com/th-ch/youtube-music/commit/2b243f6dcb00d3b6f27fd066c093e7b16bb384e2)
|
- CI: cache yarn directory [`0fd4933`](https://github.com/th-ch/youtube-music/commit/0fd49330d3218ec5f1bc62b72ace28e79d02bc93)
|
||||||
- CI: cache yarn
|
- Run CI on every push/PR [`cf4827d`](https://github.com/th-ch/youtube-music/commit/cf4827d780fee510a27eecf42453b0505c52bcf9)
|
||||||
directory [`0fd4933`](https://github.com/th-ch/youtube-music/commit/0fd49330d3218ec5f1bc62b72ace28e79d02bc93)
|
|
||||||
- Run CI on every
|
|
||||||
push/PR [`cf4827d`](https://github.com/th-ch/youtube-music/commit/cf4827d780fee510a27eecf42453b0505c52bcf9)
|
|
||||||
|
|
||||||
#### [v1.6.2](https://github.com/th-ch/youtube-music/compare/v1.6.0...v1.6.2)
|
#### [v1.6.2](https://github.com/th-ch/youtube-music/compare/v1.6.0...v1.6.2)
|
||||||
|
|
||||||
@ -634,24 +672,18 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Add github action to build/release [`#60`](https://github.com/th-ch/youtube-music/pull/60)
|
- Add github action to build/release [`#60`](https://github.com/th-ch/youtube-music/pull/60)
|
||||||
- Bump to node 12 [`#59`](https://github.com/th-ch/youtube-music/pull/59)
|
- Bump to node 12 [`#59`](https://github.com/th-ch/youtube-music/pull/59)
|
||||||
- Bump to node 12 [`#59`](https://github.com/th-ch/youtube-music/pull/59)
|
- Bump to node 12 [`#59`](https://github.com/th-ch/youtube-music/pull/59)
|
||||||
- Add downloader (video -> mp3) plugin (in music
|
- Add downloader (video -> mp3) plugin (in music menu) [`e197087`](https://github.com/th-ch/youtube-music/commit/e197087a5027af1ca71ecde7bbdf6351137555b9)
|
||||||
menu) [`e197087`](https://github.com/th-ch/youtube-music/commit/e197087a5027af1ca71ecde7bbdf6351137555b9)
|
- Delete AppVeyor/Travis CI integration [`941dd90`](https://github.com/th-ch/youtube-music/commit/941dd90d77a5c46ed5505918374693fcd892af1f)
|
||||||
- Delete AppVeyor/Travis CI
|
- GH action to build/release [`fc4754a`](https://github.com/th-ch/youtube-music/commit/fc4754a1709e6eb70d662f89eafd360aa4a77aa2)
|
||||||
integration [`941dd90`](https://github.com/th-ch/youtube-music/commit/941dd90d77a5c46ed5505918374693fcd892af1f)
|
|
||||||
- GH action to
|
|
||||||
build/release [`fc4754a`](https://github.com/th-ch/youtube-music/commit/fc4754a1709e6eb70d662f89eafd360aa4a77aa2)
|
|
||||||
|
|
||||||
#### [v1.6.0](https://github.com/th-ch/youtube-music/compare/v1.5.0...v1.6.0)
|
#### [v1.6.0](https://github.com/th-ch/youtube-music/compare/v1.5.0...v1.6.0)
|
||||||
|
|
||||||
> 11 November 2020
|
> 11 November 2020
|
||||||
|
|
||||||
- [Snyk] Upgrade electron-store from 6.0.0 to 6.0.1 [`#54`](https://github.com/th-ch/youtube-music/pull/54)
|
- [Snyk] Upgrade electron-store from 6.0.0 to 6.0.1 [`#54`](https://github.com/th-ch/youtube-music/pull/54)
|
||||||
- Add notifications plugin (notify of song on play
|
- Add notifications plugin (notify of song on play event) [`bcff6e5`](https://github.com/th-ch/youtube-music/commit/bcff6e51348645395549c206717225fb16a29cda)
|
||||||
event) [`bcff6e5`](https://github.com/th-ch/youtube-music/commit/bcff6e51348645395549c206717225fb16a29cda)
|
- Plugins/event handlers in each window [`9bc81da`](https://github.com/th-ch/youtube-music/commit/9bc81da6f2c7f5f35769489e179851bdd80a7da8)
|
||||||
- Plugins/event handlers in each
|
- Option to toggle devtools [`3e97e93`](https://github.com/th-ch/youtube-music/commit/3e97e9307cf0991adc5584a603c292b03bc6202d)
|
||||||
window [`9bc81da`](https://github.com/th-ch/youtube-music/commit/9bc81da6f2c7f5f35769489e179851bdd80a7da8)
|
|
||||||
- Option to toggle
|
|
||||||
devtools [`3e97e93`](https://github.com/th-ch/youtube-music/commit/3e97e9307cf0991adc5584a603c292b03bc6202d)
|
|
||||||
|
|
||||||
#### [v1.5.0](https://github.com/th-ch/youtube-music/compare/v1.4.0...v1.5.0)
|
#### [v1.5.0](https://github.com/th-ch/youtube-music/compare/v1.4.0...v1.5.0)
|
||||||
|
|
||||||
@ -665,10 +697,8 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Bump lodash from 4.17.15 to 4.17.19 [`#34`](https://github.com/th-ch/youtube-music/pull/34)
|
- Bump lodash from 4.17.15 to 4.17.19 [`#34`](https://github.com/th-ch/youtube-music/pull/34)
|
||||||
- Option to start at login [`#32`](https://github.com/th-ch/youtube-music/pull/32)
|
- Option to start at login [`#32`](https://github.com/th-ch/youtube-music/pull/32)
|
||||||
- Bump dependencies [`97dce5a`](https://github.com/th-ch/youtube-music/commit/97dce5ad41ba7ff7a12d4e57a6a0acfeccd666d8)
|
- Bump dependencies [`97dce5a`](https://github.com/th-ch/youtube-music/commit/97dce5ad41ba7ff7a12d4e57a6a0acfeccd666d8)
|
||||||
- Bump electron to v10 (+ remove devtron, bump
|
- Bump electron to v10 (+ remove devtron, bump spectron) [`5f0dcbb`](https://github.com/th-ch/youtube-music/commit/5f0dcbb3fc9b2912bba690db232184d32c599150)
|
||||||
spectron) [`5f0dcbb`](https://github.com/th-ch/youtube-music/commit/5f0dcbb3fc9b2912bba690db232184d32c599150)
|
- Navigation plugin: fix arrow style [`8d74a0a`](https://github.com/th-ch/youtube-music/commit/8d74a0a9b52c5b5a04b0986e5fbec9b47a35823e)
|
||||||
- Navigation plugin: fix arrow
|
|
||||||
style [`8d74a0a`](https://github.com/th-ch/youtube-music/commit/8d74a0a9b52c5b5a04b0986e5fbec9b47a35823e)
|
|
||||||
|
|
||||||
#### [v1.4.0](https://github.com/th-ch/youtube-music/compare/v1.3.3...v1.4.0)
|
#### [v1.4.0](https://github.com/th-ch/youtube-music/compare/v1.3.3...v1.4.0)
|
||||||
|
|
||||||
@ -682,33 +712,25 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- [Snyk] Upgrade electron-updater from 4.3.0 to 4.3.1 [`#26`](https://github.com/th-ch/youtube-music/pull/26)
|
- [Snyk] Upgrade electron-updater from 4.3.0 to 4.3.1 [`#26`](https://github.com/th-ch/youtube-music/pull/26)
|
||||||
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2 [`#25`](https://github.com/th-ch/youtube-music/pull/25)
|
- [Snyk] Upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2 [`#25`](https://github.com/th-ch/youtube-music/pull/25)
|
||||||
- [Tests] Add integration tests [`#24`](https://github.com/th-ch/youtube-music/pull/24)
|
- [Tests] Add integration tests [`#24`](https://github.com/th-ch/youtube-music/pull/24)
|
||||||
- Add jest, spectron and getPort util for
|
- Add jest, spectron and getPort util for tests [`736a706`](https://github.com/th-ch/youtube-music/commit/736a70680108620cdecab2da9dd48e10354c713e)
|
||||||
tests [`736a706`](https://github.com/th-ch/youtube-music/commit/736a70680108620cdecab2da9dd48e10354c713e)
|
- fix: upgrade electron-updater from 4.3.1 to 4.3.2 [`8c94510`](https://github.com/th-ch/youtube-music/commit/8c945100e24187885dbbe5bb7830b1da11e4eaa2)
|
||||||
- fix: upgrade electron-updater from 4.3.1 to
|
- Add jest config and test environment to launch app [`bce5b7d`](https://github.com/th-ch/youtube-music/commit/bce5b7d8ebd96886d462a3c999d72e6c69b6f807)
|
||||||
4.3.2 [`8c94510`](https://github.com/th-ch/youtube-music/commit/8c945100e24187885dbbe5bb7830b1da11e4eaa2)
|
|
||||||
- Add jest config and test environment to launch
|
|
||||||
app [`bce5b7d`](https://github.com/th-ch/youtube-music/commit/bce5b7d8ebd96886d462a3c999d72e6c69b6f807)
|
|
||||||
|
|
||||||
#### [v1.3.3](https://github.com/th-ch/youtube-music/compare/v1.3.2...v1.3.3)
|
#### [v1.3.3](https://github.com/th-ch/youtube-music/compare/v1.3.2...v1.3.3)
|
||||||
|
|
||||||
> 29 April 2020
|
> 29 April 2020
|
||||||
|
|
||||||
- Move tray click callback in
|
- Move tray click callback in setUpTray [`4824dda`](https://github.com/th-ch/youtube-music/commit/4824dda5d52565deb5cd6ef4b51d2d742677a154)
|
||||||
setUpTray [`4824dda`](https://github.com/th-ch/youtube-music/commit/4824dda5d52565deb5cd6ef4b51d2d742677a154)
|
- Bump version to 1.3.3 [`37cac19`](https://github.com/th-ch/youtube-music/commit/37cac19d9ccae59b89a68b995eaf7e08c7d24d11)
|
||||||
- Bump version to
|
|
||||||
1.3.3 [`37cac19`](https://github.com/th-ch/youtube-music/commit/37cac19d9ccae59b89a68b995eaf7e08c7d24d11)
|
|
||||||
|
|
||||||
#### [v1.3.2](https://github.com/th-ch/youtube-music/compare/v1.3.1...v1.3.2)
|
#### [v1.3.2](https://github.com/th-ch/youtube-music/compare/v1.3.1...v1.3.2)
|
||||||
|
|
||||||
> 26 April 2020
|
> 26 April 2020
|
||||||
|
|
||||||
- [Snyk] Upgrade electron-updater from 4.2.5 to 4.3.0 [`#22`](https://github.com/th-ch/youtube-music/pull/22)
|
- [Snyk] Upgrade electron-updater from 4.2.5 to 4.3.0 [`#22`](https://github.com/th-ch/youtube-music/pull/22)
|
||||||
- fix: upgrade electron-updater from 4.2.5 to
|
- fix: upgrade electron-updater from 4.2.5 to 4.3.0 [`9821300`](https://github.com/th-ch/youtube-music/commit/98213005d09d00bf013d2217809736bdc334ede6)
|
||||||
4.3.0 [`9821300`](https://github.com/th-ch/youtube-music/commit/98213005d09d00bf013d2217809736bdc334ede6)
|
- Hide the app (no quit) on close if tray enabled [`430687f`](https://github.com/th-ch/youtube-music/commit/430687f4d6d301aaeaeeaa11ae34d971ac3280df)
|
||||||
- Hide the app (no quit) on close if tray
|
- Show/hide window when clicking on tray [`058371a`](https://github.com/th-ch/youtube-music/commit/058371ace8fbd3d9f126454fdc7dbff86df05506)
|
||||||
enabled [`430687f`](https://github.com/th-ch/youtube-music/commit/430687f4d6d301aaeaeeaa11ae34d971ac3280df)
|
|
||||||
- Show/hide window when clicking on
|
|
||||||
tray [`058371a`](https://github.com/th-ch/youtube-music/commit/058371ace8fbd3d9f126454fdc7dbff86df05506)
|
|
||||||
|
|
||||||
#### [v1.3.1](https://github.com/th-ch/youtube-music/compare/v1.2.0...v1.3.1)
|
#### [v1.3.1](https://github.com/th-ch/youtube-music/compare/v1.2.0...v1.3.1)
|
||||||
|
|
||||||
@ -718,10 +740,8 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Upgrade outdated dependencies [`#20`](https://github.com/th-ch/youtube-music/pull/20)
|
- Upgrade outdated dependencies [`#20`](https://github.com/th-ch/youtube-music/pull/20)
|
||||||
- [Plugins] Migrate ad blocker [`#19`](https://github.com/th-ch/youtube-music/pull/19)
|
- [Plugins] Migrate ad blocker [`#19`](https://github.com/th-ch/youtube-music/pull/19)
|
||||||
- Upgrade xo [`297de08`](https://github.com/th-ch/youtube-music/commit/297de08278c2704b3baf65c455bba72f72acc06f)
|
- Upgrade xo [`297de08`](https://github.com/th-ch/youtube-music/commit/297de08278c2704b3baf65c455bba72f72acc06f)
|
||||||
- Bump electron-builder (needed after electron
|
- Bump electron-builder (needed after electron upgrade) [`3d9e59d`](https://github.com/th-ch/youtube-music/commit/3d9e59dc90e0e994e20af55af9134477e68907a5)
|
||||||
upgrade) [`3d9e59d`](https://github.com/th-ch/youtube-music/commit/3d9e59dc90e0e994e20af55af9134477e68907a5)
|
- Migrate from adblock-rs to cliqz [`422c3fc`](https://github.com/th-ch/youtube-music/commit/422c3fc28d83da309a80447dcd5064a4346580e8)
|
||||||
- Migrate from adblock-rs to
|
|
||||||
cliqz [`422c3fc`](https://github.com/th-ch/youtube-music/commit/422c3fc28d83da309a80447dcd5064a4346580e8)
|
|
||||||
|
|
||||||
#### [v1.2.0](https://github.com/th-ch/youtube-music/compare/v1.1.6...v1.2.0)
|
#### [v1.2.0](https://github.com/th-ch/youtube-music/compare/v1.1.6...v1.2.0)
|
||||||
|
|
||||||
@ -732,12 +752,9 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- [Snyk] Upgrade electron-debug from 2.1.0 to 2.2.0 [`#15`](https://github.com/th-ch/youtube-music/pull/15)
|
- [Snyk] Upgrade electron-debug from 2.1.0 to 2.2.0 [`#15`](https://github.com/th-ch/youtube-music/pull/15)
|
||||||
- Fix vulnerability [`#16`](https://github.com/th-ch/youtube-music/pull/16)
|
- Fix vulnerability [`#16`](https://github.com/th-ch/youtube-music/pull/16)
|
||||||
- Plugin: autoconfirm when paused [`#11`](https://github.com/th-ch/youtube-music/pull/11)
|
- Plugin: autoconfirm when paused [`#11`](https://github.com/th-ch/youtube-music/pull/11)
|
||||||
- Migrate to yarn to install packages without package.json (but keep npm
|
- Migrate to yarn to install packages without package.json (but keep npm rebuild) [`9371a48`](https://github.com/th-ch/youtube-music/commit/9371a4827e2312258a4f692c18f964155d57ceb8)
|
||||||
rebuild) [`9371a48`](https://github.com/th-ch/youtube-music/commit/9371a4827e2312258a4f692c18f964155d57ceb8)
|
- Bump electron-store to fix a vulnerability [`7050dfc`](https://github.com/th-ch/youtube-music/commit/7050dfca5c6a545dabc334690572d7f88b37e027)
|
||||||
- Bump electron-store to fix a
|
- Bump electron updater [`f25bb59`](https://github.com/th-ch/youtube-music/commit/f25bb59065d84cde202b5192688847c528c6ef61)
|
||||||
vulnerability [`7050dfc`](https://github.com/th-ch/youtube-music/commit/7050dfca5c6a545dabc334690572d7f88b37e027)
|
|
||||||
- Bump electron
|
|
||||||
updater [`f25bb59`](https://github.com/th-ch/youtube-music/commit/f25bb59065d84cde202b5192688847c528c6ef61)
|
|
||||||
|
|
||||||
#### [v1.1.6](https://github.com/th-ch/youtube-music/compare/v1.1.5...v1.1.6)
|
#### [v1.1.6](https://github.com/th-ch/youtube-music/compare/v1.1.5...v1.1.6)
|
||||||
|
|
||||||
@ -748,78 +765,59 @@ Fix https://github.com/th-ch/youtube-music/pull/578#issuecomment-1035517531 [`#5
|
|||||||
- Bump lodash from 4.17.11 to 4.17.14 [`#5`](https://github.com/th-ch/youtube-music/pull/5)
|
- Bump lodash from 4.17.11 to 4.17.14 [`#5`](https://github.com/th-ch/youtube-music/pull/5)
|
||||||
- npm audit fix [`1a72129`](https://github.com/th-ch/youtube-music/commit/1a72129108935cbe732621d93b877e90d11a4195)
|
- npm audit fix [`1a72129`](https://github.com/th-ch/youtube-music/commit/1a72129108935cbe732621d93b877e90d11a4195)
|
||||||
- Fix Google login [`746b5f1`](https://github.com/th-ch/youtube-music/commit/746b5f13bb08c614df290e69946cfd116a550521)
|
- Fix Google login [`746b5f1`](https://github.com/th-ch/youtube-music/commit/746b5f13bb08c614df290e69946cfd116a550521)
|
||||||
- Bump version to
|
- Bump version to 1.1.6 [`6fd10ea`](https://github.com/th-ch/youtube-music/commit/6fd10ea4a0f63e9a46e7307d811977f4e0f3213f)
|
||||||
1.1.6 [`6fd10ea`](https://github.com/th-ch/youtube-music/commit/6fd10ea4a0f63e9a46e7307d811977f4e0f3213f)
|
|
||||||
|
|
||||||
#### [v1.1.5](https://github.com/th-ch/youtube-music/compare/v1.1.4...v1.1.5)
|
#### [v1.1.5](https://github.com/th-ch/youtube-music/compare/v1.1.4...v1.1.5)
|
||||||
|
|
||||||
> 6 July 2019
|
> 6 July 2019
|
||||||
|
|
||||||
- Fix navigation
|
- Fix navigation plugin [`b10a1bb`](https://github.com/th-ch/youtube-music/commit/b10a1bb32dbea187422a43487527c379a9ddbb26)
|
||||||
plugin [`b10a1bb`](https://github.com/th-ch/youtube-music/commit/b10a1bb32dbea187422a43487527c379a9ddbb26)
|
- Bump version to 1.1.5 [`07c4a42`](https://github.com/th-ch/youtube-music/commit/07c4a429c15f22b173629618518abb97d9ec0100)
|
||||||
- Bump version to
|
|
||||||
1.1.5 [`07c4a42`](https://github.com/th-ch/youtube-music/commit/07c4a429c15f22b173629618518abb97d9ec0100)
|
|
||||||
|
|
||||||
#### [v1.1.4](https://github.com/th-ch/youtube-music/compare/v1.1.3...v1.1.4)
|
#### [v1.1.4](https://github.com/th-ch/youtube-music/compare/v1.1.3...v1.1.4)
|
||||||
|
|
||||||
> 8 June 2019
|
> 8 June 2019
|
||||||
|
|
||||||
- isDev -> is
|
- isDev -> is package [`a85325f`](https://github.com/th-ch/youtube-music/commit/a85325f33dbd40517b6029e500569fc1640af2ef)
|
||||||
package [`a85325f`](https://github.com/th-ch/youtube-music/commit/a85325f33dbd40517b6029e500569fc1640af2ef)
|
- Add titlebar/frame only on MacOS [`b1c4cc9`](https://github.com/th-ch/youtube-music/commit/b1c4cc9c45cc48413118aec8ce54767b1983a3e7)
|
||||||
- Add titlebar/frame only on
|
- Bump version to 1.1.4 [`0420f2e`](https://github.com/th-ch/youtube-music/commit/0420f2e49e295cede0db22dbb1f35ffafd6318ed)
|
||||||
MacOS [`b1c4cc9`](https://github.com/th-ch/youtube-music/commit/b1c4cc9c45cc48413118aec8ce54767b1983a3e7)
|
|
||||||
- Bump version to
|
|
||||||
1.1.4 [`0420f2e`](https://github.com/th-ch/youtube-music/commit/0420f2e49e295cede0db22dbb1f35ffafd6318ed)
|
|
||||||
|
|
||||||
#### [v1.1.3](https://github.com/th-ch/youtube-music/compare/v1.1.2...v1.1.3)
|
#### [v1.1.3](https://github.com/th-ch/youtube-music/compare/v1.1.2...v1.1.3)
|
||||||
|
|
||||||
> 2 June 2019
|
> 2 June 2019
|
||||||
|
|
||||||
- Bump fstream from 1.0.11 to 1.0.12 [`#3`](https://github.com/th-ch/youtube-music/pull/3)
|
- Bump fstream from 1.0.11 to 1.0.12 [`#3`](https://github.com/th-ch/youtube-music/pull/3)
|
||||||
- Version 1.1.3 + npm audit
|
- Version 1.1.3 + npm audit fix [`147ac48`](https://github.com/th-ch/youtube-music/commit/147ac48de6540c836e835fefe47e66e55dbdc9bc)
|
||||||
fix [`147ac48`](https://github.com/th-ch/youtube-music/commit/147ac48de6540c836e835fefe47e66e55dbdc9bc)
|
- Fix case for {en/dis}ablePlugin [`e86d63d`](https://github.com/th-ch/youtube-music/commit/e86d63da8cb083b89c2a26e6514a5b0df8868b13)
|
||||||
- Fix case for
|
- Remove outdated download links [`ec58b5c`](https://github.com/th-ch/youtube-music/commit/ec58b5cbedda8d6f881f0e81f185a1707dbe5fab)
|
||||||
{en/dis}ablePlugin [`e86d63d`](https://github.com/th-ch/youtube-music/commit/e86d63da8cb083b89c2a26e6514a5b0df8868b13)
|
|
||||||
- Remove outdated download
|
|
||||||
links [`ec58b5c`](https://github.com/th-ch/youtube-music/commit/ec58b5cbedda8d6f881f0e81f185a1707dbe5fab)
|
|
||||||
|
|
||||||
#### [v1.1.2](https://github.com/th-ch/youtube-music/compare/v1.1.1...v1.1.2)
|
#### [v1.1.2](https://github.com/th-ch/youtube-music/compare/v1.1.1...v1.1.2)
|
||||||
|
|
||||||
> 1 May 2019
|
> 1 May 2019
|
||||||
|
|
||||||
- Display error/retry in case of
|
- Display error/retry in case of failure [`5a1d7fb`](https://github.com/th-ch/youtube-music/commit/5a1d7fbf230fcd840a3ea654f31602fb5f504852)
|
||||||
failure [`5a1d7fb`](https://github.com/th-ch/youtube-music/commit/5a1d7fbf230fcd840a3ea654f31602fb5f504852)
|
- Bump version to 1.1.2 [`eac2c5c`](https://github.com/th-ch/youtube-music/commit/eac2c5cf14d0a348704f7fbf0ff0bdce02758670)
|
||||||
- Bump version to
|
|
||||||
1.1.2 [`eac2c5c`](https://github.com/th-ch/youtube-music/commit/eac2c5cf14d0a348704f7fbf0ff0bdce02758670)
|
|
||||||
|
|
||||||
#### [v1.1.1](https://github.com/th-ch/youtube-music/compare/v1.1.0...v1.1.1)
|
#### [v1.1.1](https://github.com/th-ch/youtube-music/compare/v1.1.0...v1.1.1)
|
||||||
|
|
||||||
> 28 April 2019
|
> 28 April 2019
|
||||||
|
|
||||||
- Update package
|
- Update package lock [`2d3f77d`](https://github.com/th-ch/youtube-music/commit/2d3f77d96211460bb81a73c8c62b9e5407a7cf30)
|
||||||
lock [`2d3f77d`](https://github.com/th-ch/youtube-music/commit/2d3f77d96211460bb81a73c8c62b9e5407a7cf30)
|
|
||||||
- Add travis config [`5279a45`](https://github.com/th-ch/youtube-music/commit/5279a45f3537170006ba04cd5d59ac8b879d78a5)
|
- Add travis config [`5279a45`](https://github.com/th-ch/youtube-music/commit/5279a45f3537170006ba04cd5d59ac8b879d78a5)
|
||||||
- Add Appveyor
|
- Add Appveyor config [`abc2bb8`](https://github.com/th-ch/youtube-music/commit/abc2bb8a4f749704f2daf376c0d392030f030caf)
|
||||||
config [`abc2bb8`](https://github.com/th-ch/youtube-music/commit/abc2bb8a4f749704f2daf376c0d392030f030caf)
|
|
||||||
|
|
||||||
#### [v1.1.0](https://github.com/th-ch/youtube-music/compare/v1.0.0...v1.1.0)
|
#### [v1.1.0](https://github.com/th-ch/youtube-music/compare/v1.0.0...v1.1.0)
|
||||||
|
|
||||||
> 19 April 2019
|
> 19 April 2019
|
||||||
|
|
||||||
- Build script + check for
|
- Build script + check for updates [`b3c24a5`](https://github.com/th-ch/youtube-music/commit/b3c24a521281c352c37d649e8334b581b2a1de4f)
|
||||||
updates [`b3c24a5`](https://github.com/th-ch/youtube-music/commit/b3c24a521281c352c37d649e8334b581b2a1de4f)
|
- Add download section in readme [`828e8d4`](https://github.com/th-ch/youtube-music/commit/828e8d472ca3d76dea71d95a85f8fa726404b8e7)
|
||||||
- Add download section in
|
- Add release/licence badge in readme [`9d343bf`](https://github.com/th-ch/youtube-music/commit/9d343bf779f2fa830302cc84c484bf4a93a25f36)
|
||||||
readme [`828e8d4`](https://github.com/th-ch/youtube-music/commit/828e8d472ca3d76dea71d95a85f8fa726404b8e7)
|
|
||||||
- Add release/licence badge in
|
|
||||||
readme [`9d343bf`](https://github.com/th-ch/youtube-music/commit/9d343bf779f2fa830302cc84c484bf4a93a25f36)
|
|
||||||
|
|
||||||
#### v1.0.0
|
#### v1.0.0
|
||||||
|
|
||||||
> 19 April 2019
|
> 19 April 2019
|
||||||
|
|
||||||
- Initial commit - app + 4
|
- Initial commit - app + 4 plugins [`8787b5c`](https://github.com/th-ch/youtube-music/commit/8787b5c175d02b52de65f2c559b411d999fa51e4)
|
||||||
plugins [`8787b5c`](https://github.com/th-ch/youtube-music/commit/8787b5c175d02b52de65f2c559b411d999fa51e4)
|
- Fix screenshot shadow + compress image [`c5c128f`](https://github.com/th-ch/youtube-music/commit/c5c128fa0f77c69e9bf12f6ca551315b37c51e84)
|
||||||
- Fix screenshot shadow + compress
|
- Missing quote in readme [`4b446ac`](https://github.com/th-ch/youtube-music/commit/4b446ac7c816c660cf369f3b8b6e420f766ee35f)
|
||||||
image [`c5c128f`](https://github.com/th-ch/youtube-music/commit/c5c128fa0f77c69e9bf12f6ca551315b37c51e84)
|
|
||||||
- Missing quote in
|
|
||||||
readme [`4b446ac`](https://github.com/th-ch/youtube-music/commit/4b446ac7c816c660cf369f3b8b6e420f766ee35f)
|
|
||||||
|
|||||||
9671
package-lock.json
generated
9671
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
141
package.json
141
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "youtube-music",
|
"name": "youtube-music",
|
||||||
"productName": "YouTube Music",
|
"productName": "YouTube Music",
|
||||||
"version": "2.0.0",
|
"version": "2.2.0",
|
||||||
"description": "YouTube Music Desktop App - including custom plugins",
|
"description": "YouTube Music Desktop App - including custom plugins",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -20,24 +20,7 @@
|
|||||||
"license",
|
"license",
|
||||||
"!node_modules",
|
"!node_modules",
|
||||||
"node_modules/custom-electron-prompt/**",
|
"node_modules/custom-electron-prompt/**",
|
||||||
"node_modules/youtubei.js/**",
|
|
||||||
"node_modules/undici/**",
|
|
||||||
"node_modules/@fastify/busboy/**",
|
|
||||||
"node_modules/jintr/**",
|
|
||||||
"node_modules/acorn/**",
|
|
||||||
"node_modules/tslib/**",
|
|
||||||
"node_modules/semver/**",
|
|
||||||
"node_modules/lru-cache/**",
|
|
||||||
"node_modules/detect-libc/**",
|
|
||||||
"node_modules/color/**",
|
|
||||||
"node_modules/color-convert/**",
|
|
||||||
"node_modules/color-string/**",
|
|
||||||
"node_modules/color-name/**",
|
|
||||||
"node_modules/simple-swizzle/**",
|
|
||||||
"node_modules/is-arrayish/**",
|
|
||||||
"node_modules/@cliqz/adblocker-electron-preload/**",
|
"node_modules/@cliqz/adblocker-electron-preload/**",
|
||||||
"node_modules/@cliqz/adblocker-content/**",
|
|
||||||
"node_modules/@cliqz/adblocker-extended-selectors/**",
|
|
||||||
"node_modules/@ffmpeg.wasm/core-mt/**",
|
"node_modules/@ffmpeg.wasm/core-mt/**",
|
||||||
"!node_modules/**/*.map",
|
"!node_modules/**/*.map",
|
||||||
"!node_modules/**/*.ts"
|
"!node_modules/**/*.ts"
|
||||||
@ -59,7 +42,7 @@
|
|||||||
"icon": "assets/generated/icons/win/icon.ico",
|
"icon": "assets/generated/icons/win/icon.ico",
|
||||||
"target": [
|
"target": [
|
||||||
{
|
{
|
||||||
"target": "nsis",
|
"target": "nsis-web",
|
||||||
"arch": [
|
"arch": [
|
||||||
"x64",
|
"x64",
|
||||||
"ia32",
|
"ia32",
|
||||||
@ -76,7 +59,7 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nsis": {
|
"nsisWeb": {
|
||||||
"runAfterFinish": false
|
"runAfterFinish": false
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
@ -104,46 +87,62 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npm run build && playwright test",
|
"test": "playwright test",
|
||||||
"test:debug": "DEBUG=pw:browser* npm run build && playwright test",
|
"test:debug": "cross-env DEBUG=pw:*,-pw:test:protocol playwright test",
|
||||||
"rollup:preload": "rollup -c rollup.preload.config.ts --configPlugin @rollup/plugin-typescript --bundleConfigAsCjs",
|
"rollup:preload": "rollup -c rollup.preload.config.ts --configPlugin @rollup/plugin-typescript --bundleConfigAsCjs",
|
||||||
"rollup:main": "rollup -c rollup.main.config.ts --configPlugin @rollup/plugin-typescript --bundleConfigAsCjs",
|
"rollup:main": "rollup -c rollup.main.config.ts --configPlugin @rollup/plugin-typescript --bundleConfigAsCjs",
|
||||||
"build": "npm run rollup:preload && npm run rollup:main",
|
"build": "yarpm-pnpm run rollup:preload && yarpm-pnpm run rollup:main",
|
||||||
"start": "npm run build && electron ./dist/index.js",
|
"start": "yarpm-pnpm run build && electron ./dist/index.js",
|
||||||
"start:debug": "ELECTRON_ENABLE_LOGGING=1 npm run start",
|
"start:debug": "cross-env ELECTRON_ENABLE_LOGGING=1 yarpm-pnpm run start",
|
||||||
"generate:package": "node utils/generate-package-json.js",
|
|
||||||
"postinstall": "npm run plugins && npm run clean",
|
|
||||||
"clean": "del-cli dist && del-cli pack",
|
"clean": "del-cli dist && del-cli pack",
|
||||||
"dist": "npm run clean && npm run build && electron-builder --win --mac --linux -p never",
|
"dist": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --win --mac --linux -p never",
|
||||||
"dist:linux": "npm run clean && npm run build && electron-builder --linux -p never",
|
"dist:linux": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --linux -p never",
|
||||||
"dist:mac": "npm run clean && npm run build && electron-builder --mac dmg:x64 -p never",
|
"dist:mac": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --mac dmg:x64 -p never",
|
||||||
"dist:mac:arm64": "npm run clean && npm run build && electron-builder --mac dmg:arm64 -p never",
|
"dist:mac:arm64": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --mac dmg:arm64 -p never",
|
||||||
"dist:win": "npm run clean && npm run build && electron-builder --win -p never",
|
"dist:win": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --win -p never",
|
||||||
"dist:win:x64": "npm run clean && npm run build && electron-builder --win nsis:x64 -p never",
|
"dist:win:x64": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --win nsis-web:x64 -p never",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"changelog": "auto-changelog",
|
"changelog": "npx --yes auto-changelog",
|
||||||
"plugins": "npm run plugin:bypass-age-restrictions",
|
"release:linux": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --linux -p always -c.snap.publish=github",
|
||||||
"plugin:bypass-age-restrictions": "del-cli node_modules/simple-youtube-age-restriction-bypass/package.json && npm run generate:package simple-youtube-age-restriction-bypass",
|
"release:mac": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --mac -p always",
|
||||||
"release:linux": "npm run clean && npm run build && electron-builder --linux -p always -c.snap.publish=github",
|
"release:win": "yarpm-pnpm run clean && yarpm-pnpm run build && electron-builder --win -p always",
|
||||||
"release:mac": "npm run clean && npm run build && electron-builder --mac -p always",
|
|
||||||
"release:win": "npm run clean && npm run build && electron-builder --win -p always",
|
|
||||||
"typecheck": "tsc -p tsconfig.json --noEmit"
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0"
|
"node": ">=16.0.0"
|
||||||
},
|
},
|
||||||
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"rollup": "4.2.0",
|
||||||
|
"node-gyp": "10.0.1",
|
||||||
|
"xml2js": "0.6.2",
|
||||||
|
"node-fetch": "3.3.2",
|
||||||
|
"@electron/universal": "1.4.4",
|
||||||
|
"@babel/runtime": "7.23.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"rollup": "4.2.0",
|
||||||
|
"node-gyp": "10.0.1",
|
||||||
|
"xml2js": "0.6.2",
|
||||||
|
"node-fetch": "3.3.2",
|
||||||
|
"@electron/universal": "1.4.4",
|
||||||
|
"@babel/runtime": "7.23.2"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cliqz/adblocker-electron": "1.26.7",
|
"@cliqz/adblocker-electron": "1.26.10",
|
||||||
|
"@cliqz/adblocker-electron-preload": "1.26.10",
|
||||||
"@ffmpeg.wasm/core-mt": "0.12.0",
|
"@ffmpeg.wasm/core-mt": "0.12.0",
|
||||||
"@ffmpeg.wasm/main": "0.12.0",
|
"@ffmpeg.wasm/main": "0.12.0",
|
||||||
"@foobar404/wave": "2.0.4",
|
"@foobar404/wave": "2.0.4",
|
||||||
"@xhayper/discord-rpc": "1.0.23",
|
"@jellybrick/electron-better-web-request": "1.0.4",
|
||||||
|
"@jellybrick/mpris-service": "2.1.4",
|
||||||
|
"@xhayper/discord-rpc": "1.0.24",
|
||||||
"async-mutex": "0.4.0",
|
"async-mutex": "0.4.0",
|
||||||
"butterchurn": "2.6.7",
|
"butterchurn": "3.0.0-beta.4",
|
||||||
"butterchurn-presets": "2.4.7",
|
"butterchurn-presets": "3.0.0-beta.4",
|
||||||
"conf": "10.2.0",
|
"conf": "10.2.0",
|
||||||
"custom-electron-prompt": "1.5.7",
|
"custom-electron-prompt": "1.5.7",
|
||||||
"electron-better-web-request": "1.0.1",
|
|
||||||
"electron-debug": "3.2.0",
|
"electron-debug": "3.2.0",
|
||||||
"electron-is": "3.0.0",
|
"electron-is": "3.0.0",
|
||||||
"electron-localshortcut": "3.2.1",
|
"electron-localshortcut": "3.2.1",
|
||||||
@ -156,57 +155,49 @@
|
|||||||
"html-to-text": "9.0.5",
|
"html-to-text": "9.0.5",
|
||||||
"keyboardevent-from-electron-accelerator": "2.0.0",
|
"keyboardevent-from-electron-accelerator": "2.0.0",
|
||||||
"keyboardevents-areequal": "0.2.2",
|
"keyboardevents-areequal": "0.2.2",
|
||||||
"mpris-service": "2.1.2",
|
|
||||||
"node-id3": "0.2.6",
|
"node-id3": "0.2.6",
|
||||||
"simple-youtube-age-restriction-bypass": "git+https://github.com/MiepHD/Simple-YouTube-Age-Restriction-Bypass.git#v2.5.5",
|
"simple-youtube-age-restriction-bypass": "git+https://github.com/organization/Simple-YouTube-Age-Restriction-Bypass.git#v2.5.8",
|
||||||
"vudio": "2.1.1",
|
"vudio": "2.1.1",
|
||||||
"x11": "2.3.0",
|
"x11": "2.3.0",
|
||||||
"youtubei.js": "6.4.1",
|
"youtubei.js": "7.0.0"
|
||||||
"ytpl": "2.3.0"
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"rollup": "4.0.2",
|
|
||||||
"node-gyp": "9.4.0",
|
|
||||||
"xml2js": "0.6.2",
|
|
||||||
"dbus-next": "0.10.2",
|
|
||||||
"node-fetch": "2.7.0",
|
|
||||||
"@electron/universal": "1.4.2",
|
|
||||||
"electron": "27.0.0-beta.9"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "1.38.1",
|
"@playwright/test": "1.39.0",
|
||||||
"@rollup/plugin-commonjs": "25.0.5",
|
"@rollup/plugin-commonjs": "25.0.7",
|
||||||
"@rollup/plugin-image": "3.0.3",
|
"@rollup/plugin-image": "3.0.3",
|
||||||
"@rollup/plugin-json": "6.0.1",
|
"@rollup/plugin-json": "6.0.1",
|
||||||
"@rollup/plugin-node-resolve": "15.2.2",
|
"@rollup/plugin-node-resolve": "15.2.3",
|
||||||
"@rollup/plugin-terser": "0.4.4",
|
"@rollup/plugin-terser": "0.4.4",
|
||||||
"@rollup/plugin-typescript": "11.1.5",
|
"@rollup/plugin-typescript": "11.1.5",
|
||||||
"@rollup/plugin-wasm": "6.2.2",
|
"@rollup/plugin-wasm": "6.2.2",
|
||||||
"@total-typescript/ts-reset": "0.5.1",
|
"@total-typescript/ts-reset": "0.5.1",
|
||||||
"@types/electron-localshortcut": "3.1.1",
|
"@types/electron-localshortcut": "3.1.2",
|
||||||
"@types/howler": "2.2.9",
|
"@types/howler": "2.2.10",
|
||||||
"@types/html-to-text": "9.0.2",
|
"@types/html-to-text": "9.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "6.7.4",
|
"@typescript-eslint/eslint-plugin": "6.9.1",
|
||||||
"auto-changelog": "2.4.0",
|
"builtin-modules": "^3.3.0",
|
||||||
|
"cross-env": "7.0.3",
|
||||||
"del-cli": "5.1.0",
|
"del-cli": "5.1.0",
|
||||||
"electron": "27.0.0-beta.9",
|
"electron": "27.0.3",
|
||||||
"electron-builder": "24.6.4",
|
"electron-builder": "24.6.4",
|
||||||
"electron-devtools-installer": "3.2.0",
|
"electron-devtools-installer": "3.2.0",
|
||||||
"eslint": "8.51.0",
|
"eslint": "8.52.0",
|
||||||
"eslint-plugin-import": "2.28.1",
|
"eslint-plugin-import": "2.29.0",
|
||||||
"eslint-plugin-prettier": "5.0.0",
|
"eslint-plugin-prettier": "5.0.1",
|
||||||
"node-gyp": "9.4.0",
|
"node-gyp": "10.0.1",
|
||||||
"playwright": "1.38.1",
|
"playwright": "1.39.0",
|
||||||
"rollup": "4.0.2",
|
"rollup": "4.2.0",
|
||||||
"rollup-plugin-copy": "3.5.0",
|
"rollup-plugin-copy": "3.5.0",
|
||||||
"rollup-plugin-import-css": "3.3.4",
|
"rollup-plugin-import-css": "3.3.5",
|
||||||
"rollup-plugin-string": "3.0.0",
|
"rollup-plugin-string": "3.0.0",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.2.2",
|
||||||
|
"yarpm": "1.2.0"
|
||||||
},
|
},
|
||||||
"auto-changelog": {
|
"auto-changelog": {
|
||||||
"hideCredit": true,
|
"hideCredit": true,
|
||||||
"package": true,
|
"package": true,
|
||||||
"unreleased": true,
|
"unreleased": true,
|
||||||
"output": "changelog.md"
|
"output": "changelog.md"
|
||||||
}
|
},
|
||||||
|
"packageManager": "pnpm@8.10.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export default () => {
|
|
||||||
const path = '@cliqz/adblocker-electron-preload'; // prevent require hoisting
|
|
||||||
require(path);
|
|
||||||
};
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { BrowserWindow } from 'electron';
|
|
||||||
|
|
||||||
import style from './style.css';
|
|
||||||
|
|
||||||
import { injectCSS } from '../utils';
|
|
||||||
|
|
||||||
|
|
||||||
export default (win: BrowserWindow) => {
|
|
||||||
injectCSS(win.webContents, style);
|
|
||||||
};
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#song-video canvas.html5-blur-canvas{
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
filter: blur(100px);
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
export default () => {
|
|
||||||
// See https://github.com/zerodytrash/Simple-YouTube-Age-Restriction-Bypass#userscript
|
|
||||||
require('simple-youtube-age-restriction-bypass/dist/Simple-YouTube-Age-Restriction-Bypass.user.js');
|
|
||||||
};
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
import { ipcRenderer, Menu } from 'electron';
|
|
||||||
|
|
||||||
import { createPanel } from './menu/panel';
|
|
||||||
|
|
||||||
import logo from '../../assets/menu.svg';
|
|
||||||
import { isEnabled } from '../../config/plugins';
|
|
||||||
import config from '../../config';
|
|
||||||
|
|
||||||
function $<E extends Element = Element>(selector: string) {
|
|
||||||
return document.querySelector<E>(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isMacOS = navigator.userAgent.includes('Macintosh');
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
let hideMenu = config.get('options.hideMenu');
|
|
||||||
const titleBar = document.createElement('title-bar');
|
|
||||||
const navBar = document.querySelector<HTMLDivElement>('#nav-bar-background');
|
|
||||||
if (isMacOS) titleBar.style.setProperty('--offset-left', '70px');
|
|
||||||
|
|
||||||
logo.classList.add('title-bar-icon');
|
|
||||||
const logoClick = () => {
|
|
||||||
hideMenu = !hideMenu;
|
|
||||||
let visibilityStyle: string;
|
|
||||||
if (hideMenu) {
|
|
||||||
visibilityStyle = 'hidden';
|
|
||||||
} else {
|
|
||||||
visibilityStyle = 'visible';
|
|
||||||
}
|
|
||||||
const menus = document.querySelectorAll<HTMLElement>('menu-button');
|
|
||||||
menus.forEach((menu) => {
|
|
||||||
menu.style.visibility = visibilityStyle;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
logo.onclick = logoClick;
|
|
||||||
|
|
||||||
ipcRenderer.on('toggleMenu', logoClick);
|
|
||||||
|
|
||||||
if (!isMacOS) titleBar.appendChild(logo);
|
|
||||||
document.body.appendChild(titleBar);
|
|
||||||
|
|
||||||
if (navBar) {
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
mutations.forEach(() => {
|
|
||||||
titleBar.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
|
||||||
document.querySelector('html')!.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(navBar, { attributes : true, attributeFilter : ['style'] });
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateMenu = async () => {
|
|
||||||
const children = [...titleBar.children];
|
|
||||||
children.forEach((child) => {
|
|
||||||
if (child !== logo) child.remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
const menu = await ipcRenderer.invoke('get-menu') as Menu | null;
|
|
||||||
if (!menu) return;
|
|
||||||
|
|
||||||
menu.items.forEach((menuItem) => {
|
|
||||||
const menu = document.createElement('menu-button');
|
|
||||||
createPanel(titleBar, menu, menuItem.submenu?.items ?? []);
|
|
||||||
|
|
||||||
menu.append(menuItem.label);
|
|
||||||
titleBar.appendChild(menu);
|
|
||||||
if (hideMenu) {
|
|
||||||
menu.style.visibility = 'hidden';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
updateMenu();
|
|
||||||
|
|
||||||
document.title = 'Youtube Music';
|
|
||||||
|
|
||||||
ipcRenderer.on('refreshMenu', () => {
|
|
||||||
updateMenu();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isEnabled('picture-in-picture')) {
|
|
||||||
ipcRenderer.on('pip-toggle', () => {
|
|
||||||
updateMenu();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increases the right margin of Navbar background when the scrollbar is visible to avoid blocking it (z-index doesn't affect it)
|
|
||||||
document.addEventListener('apiLoaded', () => {
|
|
||||||
const htmlHeadStyle = $('head > div > style');
|
|
||||||
if (htmlHeadStyle) {
|
|
||||||
// HACK: This is a hack to remove the scrollbar width
|
|
||||||
htmlHeadStyle.innerHTML = htmlHeadStyle.innerHTML.replace('html::-webkit-scrollbar {width: var(--ytmusic-scrollbar-width);', 'html::-webkit-scrollbar {');
|
|
||||||
}
|
|
||||||
}, { once: true, passive: true });
|
|
||||||
};
|
|
||||||
5506
pnpm-lock.yaml
generated
Normal file
5506
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
readme.md
45
readme.md
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/th-ch/youtube-music/releases/latest">
|
<a href="https://github.com/th-ch/youtube-music/releases/latest">
|
||||||
<img src="web/youtube-music.svg" width="400" height="100">
|
<img src="web/youtube-music.svg" width="400" height="100" alt="YouTube Music SVG">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -38,7 +38,12 @@ this [wiki page](https://wiki.archlinux.org/index.php/Arch_User_Repository#Insta
|
|||||||
|
|
||||||
### MacOS
|
### MacOS
|
||||||
|
|
||||||
If you get an error "is damaged and can’t be opened." when launching the app, run the following in the Terminal:
|
You can install the app using Homebrew:
|
||||||
|
```bash
|
||||||
|
brew install --cask https://raw.githubusercontent.com/th-ch/youtube-music/master/youtube-music.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
If you install the app manually and get an error "is damaged and can’t be opened." when launching the app, run the following in the Terminal:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
xattr -cr /Applications/YouTube\ Music.app
|
xattr -cr /Applications/YouTube\ Music.app
|
||||||
@ -65,10 +70,24 @@ file).*
|
|||||||
winget install th-ch.YouTubeMusic
|
winget install th-ch.YouTubeMusic
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### How to install without a network connection? (in Windows)
|
||||||
|
|
||||||
|
- Download the `*.nsis.7z` file for _your device architecture_ in [release page](https://github.com/th-ch/youtube-music/releases/latest).
|
||||||
|
- `x64` for 64-bit Windows
|
||||||
|
- `ia32` for 32-bit Windows
|
||||||
|
- `arm64` for ARM64 Windows
|
||||||
|
- Download installer in release page. (`*-Setup.exe`)
|
||||||
|
- Place them in the **same directory**.
|
||||||
|
- Run the installer.
|
||||||
|
|
||||||
## Available plugins:
|
## Available plugins:
|
||||||
|
|
||||||
- **Ad Blocker**: Block all ads and tracking out of the box
|
- **Ad Blocker**: Block all ads and tracking out of the box
|
||||||
|
|
||||||
|
- **Album Color Theme**: Applies a dynamic theme and visual effects based on the album color palette
|
||||||
|
|
||||||
|
- **Ambient Mode**: Applies a lighting effect by casting gentle colors from the video, into your screen’s background.
|
||||||
|
|
||||||
- **Audio Compressor**: Apply compression to audio (lowers the volume of the loudest parts of the signal and raises the
|
- **Audio Compressor**: Apply compression to audio (lowers the volume of the loudest parts of the signal and raises the
|
||||||
volume of the softest parts)
|
volume of the softest parts)
|
||||||
|
|
||||||
@ -94,14 +113,15 @@ winget install th-ch.YouTubeMusic
|
|||||||
slider [exponential](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) so it's easier to
|
slider [exponential](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) so it's easier to
|
||||||
select lower volumes.
|
select lower volumes.
|
||||||
|
|
||||||
- **In-App Menu
|
- **In-App Menu**: [gives bars a fancy, dark look](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
|
||||||
**: [gives bars a fancy, dark look](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
|
|
||||||
|
|
||||||
> (see [this post](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) if you have problem
|
> (see [this post](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) if you have problem
|
||||||
accessing the menu after enabling this plugin and hide-menu option)
|
accessing the menu after enabling this plugin and hide-menu option)
|
||||||
|
|
||||||
- [**Last.fm**](https://www.last.fm/): Scrobbles support
|
- [**Last.fm**](https://www.last.fm/): Scrobbles support
|
||||||
|
|
||||||
|
- **Lumia Stream**: Adds [Lumia Stream](https://lumiastream.com/) support
|
||||||
|
|
||||||
- **Lyrics Genius**: Adds lyrics support for most songs
|
- **Lyrics Genius**: Adds lyrics support for most songs
|
||||||
|
|
||||||
- **Navigation**: Next/Back navigation arrows directly integrated in the interface, like in your favorite browser
|
- **Navigation**: Next/Back navigation arrows directly integrated in the interface, like in your favorite browser
|
||||||
@ -169,8 +189,8 @@ Some predefined themes are available in https://github.com/kerichdev/themes-for-
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/th-ch/youtube-music
|
git clone https://github.com/th-ch/youtube-music
|
||||||
cd youtube-music
|
cd youtube-music
|
||||||
npm
|
pnpm install --frozen-lockfile
|
||||||
npm run start
|
pnpm start
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build your own plugins
|
## Build your own plugins
|
||||||
@ -257,12 +277,13 @@ export default () => {
|
|||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. Clone the repo
|
1. Clone the repo
|
||||||
2. Run `npm i` to install dependencies
|
2. Follow [this guide](https://pnpm.io/installation) to install `pnpm`
|
||||||
3. Run `npm run build:OS`
|
3. Run `pnpm install --frozen-lockfile` to install dependencies
|
||||||
|
4. Run `pnpm build:OS`
|
||||||
|
|
||||||
- `npm run build:win` - Windows
|
- `pnpm dist:win` - Windows
|
||||||
- `npm run build:linux` - Linux
|
- `pnpm dist:linux` - Linux
|
||||||
- `npm run build:mac` - MacOS
|
- `pnpm dist:mac` - MacOS
|
||||||
|
|
||||||
Builds the app for macOS, Linux, and Windows,
|
Builds the app for macOS, Linux, and Windows,
|
||||||
using [electron-builder](https://github.com/electron-userland/electron-builder).
|
using [electron-builder](https://github.com/electron-userland/electron-builder).
|
||||||
@ -270,7 +291,7 @@ using [electron-builder](https://github.com/electron-userland/electron-builder).
|
|||||||
## Tests
|
## Tests
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run test
|
pnpm test
|
||||||
```
|
```
|
||||||
|
|
||||||
Uses [Playwright](https://playwright.dev/) to test the app.
|
Uses [Playwright](https://playwright.dev/) to test the app.
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export default defineConfig({
|
|||||||
nodeResolvePlugin({
|
nodeResolvePlugin({
|
||||||
browser: false,
|
browser: false,
|
||||||
preferBuiltins: true,
|
preferBuiltins: true,
|
||||||
exportConditions: ['node', 'default', 'module', 'import'] ,
|
exportConditions: ['node', 'default', 'module', 'import'],
|
||||||
}),
|
}),
|
||||||
commonjs({
|
commonjs({
|
||||||
ignoreDynamicRequires: true,
|
ignoreDynamicRequires: true,
|
||||||
@ -34,7 +34,7 @@ export default defineConfig({
|
|||||||
css(),
|
css(),
|
||||||
copy({
|
copy({
|
||||||
targets: [
|
targets: [
|
||||||
{ src: 'error.html', dest: 'dist/' },
|
{ src: 'src/error.html', dest: 'dist/' },
|
||||||
{ src: 'assets', dest: 'dist/' },
|
{ src: 'assets', dest: 'dist/' },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -47,19 +47,14 @@ export default defineConfig({
|
|||||||
setTimeout(() => process.exit(0));
|
setTimeout(() => process.exit(0));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name: 'force-close'
|
name: 'force-close',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
input: './index.ts',
|
input: './src/index.ts',
|
||||||
output: {
|
output: {
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
name: '[name].js',
|
name: '[name].js',
|
||||||
dir: './dist',
|
dir: './dist',
|
||||||
},
|
},
|
||||||
external: [
|
external: ['electron', 'custom-electron-prompt', ...builtinModules],
|
||||||
'electron',
|
|
||||||
'custom-electron-prompt',
|
|
||||||
'youtubei.js', // https://github.com/LuanRT/YouTube.js/pull/509
|
|
||||||
...builtinModules,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,18 +41,14 @@ export default defineConfig({
|
|||||||
setTimeout(() => process.exit(0));
|
setTimeout(() => process.exit(0));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name: 'force-close'
|
name: 'force-close',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
input: './preload.ts',
|
input: './src/preload.ts',
|
||||||
output: {
|
output: {
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
name: '[name].js',
|
name: '[name].js',
|
||||||
dir: './dist',
|
dir: './dist',
|
||||||
},
|
},
|
||||||
external: [
|
external: ['electron', 'custom-electron-prompt', ...builtinModules],
|
||||||
'electron',
|
|
||||||
'custom-electron-prompt',
|
|
||||||
...builtinModules,
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
import { blockers } from '../plugins/adblocker/blocker-types';
|
||||||
|
|
||||||
|
import { DefaultPresetList } from '../plugins/downloader/types';
|
||||||
|
|
||||||
export interface WindowSizeConfig {
|
export interface WindowSizeConfig {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
@ -72,12 +76,21 @@ const defaultConfig = {
|
|||||||
'adblocker': {
|
'adblocker': {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
blocker: 'With blocklists',
|
blocker: blockers.InPlayer as string,
|
||||||
additionalBlockLists: [], // Additional list of filters, e.g "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt"
|
additionalBlockLists: [], // Additional list of filters, e.g "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt"
|
||||||
disableDefaultLists: false,
|
disableDefaultLists: false,
|
||||||
},
|
},
|
||||||
'album-color-theme': {},
|
'album-color-theme': {},
|
||||||
'ambient-mode': {},
|
'ambient-mode': {
|
||||||
|
enabled: false,
|
||||||
|
quality: 50,
|
||||||
|
buffer: 30,
|
||||||
|
interpolationTime: 1500,
|
||||||
|
blur: 100,
|
||||||
|
size: 100,
|
||||||
|
opacity: 1,
|
||||||
|
fullscreen: false,
|
||||||
|
},
|
||||||
'audio-compressor': {},
|
'audio-compressor': {},
|
||||||
'blur-nav-bar': {},
|
'blur-nav-bar': {},
|
||||||
'bypass-age-restrictions': {},
|
'bypass-age-restrictions': {},
|
||||||
@ -103,19 +116,27 @@ const defaultConfig = {
|
|||||||
autoReconnect: true, // If enabled, will try to reconnect to discord every 5 seconds after disconnecting or failing to connect
|
autoReconnect: true, // If enabled, will try to reconnect to discord every 5 seconds after disconnecting or failing to connect
|
||||||
activityTimoutEnabled: true, // If enabled, the discord rich presence gets cleared when music paused after the time specified below
|
activityTimoutEnabled: true, // If enabled, the discord rich presence gets cleared when music paused after the time specified below
|
||||||
activityTimoutTime: 10 * 60 * 1000, // 10 minutes
|
activityTimoutTime: 10 * 60 * 1000, // 10 minutes
|
||||||
listenAlong: true, // Add a "listen along" button to rich presence
|
playOnYouTubeMusic: true, // Add a "Play on YouTube Music" button to rich presence
|
||||||
|
hideGitHubButton: false, // Disable the "View App On GitHub" button
|
||||||
hideDurationLeft: false, // Hides the start and end time of the song to rich presence
|
hideDurationLeft: false, // Hides the start and end time of the song to rich presence
|
||||||
},
|
},
|
||||||
'downloader': {
|
'downloader': {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
ffmpegArgs: ['-b:a', '256k'], // E.g. ["-b:a", "192k"] for an audio bitrate of 192kb/s
|
|
||||||
downloadFolder: undefined as string | undefined, // Custom download folder (absolute path)
|
downloadFolder: undefined as string | undefined, // Custom download folder (absolute path)
|
||||||
preset: 'mp3',
|
selectedPreset: 'mp3 (256kbps)', // Selected preset
|
||||||
|
customPresetSetting: DefaultPresetList['mp3 (256kbps)'], // Presets
|
||||||
skipExisting: false,
|
skipExisting: false,
|
||||||
playlistMaxItems: undefined as number | undefined,
|
playlistMaxItems: undefined as number | undefined,
|
||||||
},
|
},
|
||||||
|
'http-api': {},
|
||||||
'exponential-volume': {},
|
'exponential-volume': {},
|
||||||
'in-app-menu': {},
|
'in-app-menu': {
|
||||||
|
/**
|
||||||
|
* true in Windows, false in Linux and macOS (see youtube-music/config/store.ts)
|
||||||
|
*/
|
||||||
|
enabled: false,
|
||||||
|
hideDOMWindowControls: false,
|
||||||
|
},
|
||||||
'last-fm': {
|
'last-fm': {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
token: undefined as string | undefined, // Token used for authentication
|
token: undefined as string | undefined, // Token used for authentication
|
||||||
@ -22,8 +22,20 @@ export function isEnabled(plugin: string) {
|
|||||||
return pluginConfig !== undefined && pluginConfig.enabled;
|
return pluginConfig !== undefined && pluginConfig.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setOptions<T>(plugin: string, options: T) {
|
/**
|
||||||
|
* Set options for a plugin
|
||||||
|
* @param plugin Plugin name
|
||||||
|
* @param options Options to set
|
||||||
|
* @param exclude Options to exclude from the options object
|
||||||
|
*/
|
||||||
|
export function setOptions<T>(plugin: string, options: T, exclude: string[] = ['enabled']) {
|
||||||
const plugins = store.get('plugins') as Record<string, T>;
|
const plugins = store.get('plugins') as Record<string, T>;
|
||||||
|
// HACK: This is a workaround for preventing changed options from being overwritten
|
||||||
|
exclude.forEach((key) => {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(options, key)) {
|
||||||
|
delete options[key as keyof T];
|
||||||
|
}
|
||||||
|
});
|
||||||
store.set('plugins', {
|
store.set('plugins', {
|
||||||
...plugins,
|
...plugins,
|
||||||
[plugin]: {
|
[plugin]: {
|
||||||
@ -33,8 +45,8 @@ export function setOptions<T>(plugin: string, options: T) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setMenuOptions<T>(plugin: string, options: T) {
|
export function setMenuOptions<T>(plugin: string, options: T, exclude: string[] = ['enabled']) {
|
||||||
setOptions(plugin, options);
|
setOptions(plugin, options, exclude);
|
||||||
if (store.get('options.restartOnConfigChanges')) {
|
if (store.get('options.restartOnConfigChanges')) {
|
||||||
restart();
|
restart();
|
||||||
}
|
}
|
||||||
@ -45,11 +57,11 @@ export function getOptions<T>(plugin: string): T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function enable(plugin: string) {
|
export function enable(plugin: string) {
|
||||||
setMenuOptions(plugin, { enabled: true });
|
setMenuOptions(plugin, { enabled: true }, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function disable(plugin: string) {
|
export function disable(plugin: string) {
|
||||||
setMenuOptions(plugin, { enabled: false });
|
setMenuOptions(plugin, { enabled: false }, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -1,8 +1,18 @@
|
|||||||
import Store from 'electron-store';
|
import Store from 'electron-store';
|
||||||
import Conf from 'conf';
|
import Conf from 'conf';
|
||||||
|
import is from 'electron-is';
|
||||||
|
|
||||||
import defaults from './defaults';
|
import defaults from './defaults';
|
||||||
|
|
||||||
|
import { DefaultPresetList, type Preset } from '../plugins/downloader/types';
|
||||||
|
|
||||||
|
const getDefaults = () => {
|
||||||
|
if (is.windows()) {
|
||||||
|
defaults.plugins['in-app-menu'].enabled = true;
|
||||||
|
}
|
||||||
|
return defaults;
|
||||||
|
};
|
||||||
|
|
||||||
const setDefaultPluginOptions = (store: Conf<Record<string, unknown>>, plugin: keyof typeof defaults.plugins) => {
|
const setDefaultPluginOptions = (store: Conf<Record<string, unknown>>, plugin: keyof typeof defaults.plugins) => {
|
||||||
if (!store.get(`plugins.${plugin}`)) {
|
if (!store.get(`plugins.${plugin}`)) {
|
||||||
store.set(`plugins.${plugin}`, defaults.plugins[plugin]);
|
store.set(`plugins.${plugin}`, defaults.plugins[plugin]);
|
||||||
@ -10,6 +20,33 @@ const setDefaultPluginOptions = (store: Conf<Record<string, unknown>>, plugin: k
|
|||||||
};
|
};
|
||||||
|
|
||||||
const migrations = {
|
const migrations = {
|
||||||
|
'>=2.1.3'(store: Conf<Record<string, unknown>>) {
|
||||||
|
const listenAlong = store.get('plugins.discord.listenAlong');
|
||||||
|
if (listenAlong !== undefined) {
|
||||||
|
store.set('plugins.discord.playOnYouTubeMusic', listenAlong);
|
||||||
|
store.delete('plugins.discord.listenAlong');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'>=2.1.0'(store: Conf<Record<string, unknown>>) {
|
||||||
|
const originalPreset = store.get('plugins.downloader.preset') as string | undefined;
|
||||||
|
if (originalPreset) {
|
||||||
|
if (originalPreset !== 'opus') {
|
||||||
|
store.set('plugins.downloader.selectedPreset', 'Custom');
|
||||||
|
store.set('plugins.downloader.customPresetSetting', {
|
||||||
|
extension: 'mp3',
|
||||||
|
ffmpegArgs: store.get('plugins.downloader.ffmpegArgs') as string[] ?? DefaultPresetList['mp3 (256kbps)'].ffmpegArgs,
|
||||||
|
} satisfies Preset);
|
||||||
|
} else {
|
||||||
|
store.set('plugins.downloader.selectedPreset', 'Source');
|
||||||
|
store.set('plugins.downloader.customPresetSetting', {
|
||||||
|
extension: null,
|
||||||
|
ffmpegArgs: store.get('plugins.downloader.ffmpegArgs') as string[] ?? [],
|
||||||
|
} satisfies Preset);
|
||||||
|
}
|
||||||
|
store.delete('plugins.downloader.preset');
|
||||||
|
store.delete('plugins.downloader.ffmpegArgs');
|
||||||
|
}
|
||||||
|
},
|
||||||
'>=1.20.0'(store: Conf<Record<string, unknown>>) {
|
'>=1.20.0'(store: Conf<Record<string, unknown>>) {
|
||||||
setDefaultPluginOptions(store, 'visualizer');
|
setDefaultPluginOptions(store, 'visualizer');
|
||||||
|
|
||||||
@ -118,7 +155,7 @@ const migrations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default new Store({
|
export default new Store({
|
||||||
defaults,
|
defaults: getDefaults(),
|
||||||
clearInvalidConfig: false,
|
clearInvalidConfig: false,
|
||||||
migrations,
|
migrations,
|
||||||
});
|
});
|
||||||
@ -1,16 +1,14 @@
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import { BrowserWindow, app, screen, globalShortcut, session, shell, dialog, ipcMain } from 'electron';
|
import { BrowserWindow, app, screen, globalShortcut, session, shell, dialog, ipcMain } from 'electron';
|
||||||
import enhanceWebRequest from 'electron-better-web-request';
|
import enhanceWebRequest, { BetterSession } from '@jellybrick/electron-better-web-request';
|
||||||
import is from 'electron-is';
|
import is from 'electron-is';
|
||||||
import unhandled from 'electron-unhandled';
|
import unhandled from 'electron-unhandled';
|
||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
import electronDebug from 'electron-debug';
|
import electronDebug from 'electron-debug';
|
||||||
|
|
||||||
import { BetterWebRequest } from 'electron-better-web-request/lib/electron-better-web-request';
|
|
||||||
|
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import { setApplicationMenu } from './menu';
|
import { refreshMenu, setApplicationMenu } from './menu';
|
||||||
import { fileExists, injectCSS, injectCSSAsFile } from './plugins/utils';
|
import { fileExists, injectCSS, injectCSSAsFile } from './plugins/utils';
|
||||||
import { isTesting } from './utils/testing';
|
import { isTesting } from './utils/testing';
|
||||||
import { setUpTray } from './tray';
|
import { setUpTray } from './tray';
|
||||||
@ -26,6 +24,7 @@ import captionsSelector from './plugins/captions-selector/back';
|
|||||||
import crossfade from './plugins/crossfade/back';
|
import crossfade from './plugins/crossfade/back';
|
||||||
import discord from './plugins/discord/back';
|
import discord from './plugins/discord/back';
|
||||||
import downloader from './plugins/downloader/back';
|
import downloader from './plugins/downloader/back';
|
||||||
|
import httpApi from './plugins/http-api/back';
|
||||||
import inAppMenu from './plugins/in-app-menu/back';
|
import inAppMenu from './plugins/in-app-menu/back';
|
||||||
import lastFm from './plugins/last-fm/back';
|
import lastFm from './plugins/last-fm/back';
|
||||||
import lumiaStream from './plugins/lumiastream/back';
|
import lumiaStream from './plugins/lumiastream/back';
|
||||||
@ -111,6 +110,7 @@ const mainPlugins = {
|
|||||||
'crossfade': crossfade,
|
'crossfade': crossfade,
|
||||||
'discord': discord,
|
'discord': discord,
|
||||||
'downloader': downloader,
|
'downloader': downloader,
|
||||||
|
'http-api': httpApi,
|
||||||
'in-app-menu': inAppMenu,
|
'in-app-menu': inAppMenu,
|
||||||
'last-fm': lastFm,
|
'last-fm': lastFm,
|
||||||
'lumiastream': lumiaStream,
|
'lumiastream': lumiaStream,
|
||||||
@ -144,7 +144,7 @@ if (is.windows()) {
|
|||||||
|
|
||||||
ipcMain.handle('get-main-plugin-names', () => Object.keys(mainPlugins));
|
ipcMain.handle('get-main-plugin-names', () => Object.keys(mainPlugins));
|
||||||
|
|
||||||
function loadPlugins(win: BrowserWindow) {
|
async function loadPlugins(win: BrowserWindow) {
|
||||||
injectCSS(win.webContents, youtubeMusicCSS);
|
injectCSS(win.webContents, youtubeMusicCSS);
|
||||||
// Load user CSS
|
// Load user CSS
|
||||||
const themes: string[] = config.get('options.themes');
|
const themes: string[] = config.get('options.themes');
|
||||||
@ -175,7 +175,7 @@ function loadPlugins(win: BrowserWindow) {
|
|||||||
console.log('Loaded plugin - ' + plugin);
|
console.log('Loaded plugin - ' + plugin);
|
||||||
const handler = mainPlugins[plugin as keyof typeof mainPlugins];
|
const handler = mainPlugins[plugin as keyof typeof mainPlugins];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler(win, options as never);
|
await handler(win, options as never);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -184,7 +184,7 @@ function loadPlugins(win: BrowserWindow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMainWindow() {
|
async function createMainWindow() {
|
||||||
const windowSize = config.get('window-size');
|
const windowSize = config.get('window-size');
|
||||||
const windowMaximized = config.get('window-maximized');
|
const windowMaximized = config.get('window-maximized');
|
||||||
const windowPosition: Electron.Point = config.get('window-position');
|
const windowPosition: Electron.Point = config.get('window-position');
|
||||||
@ -223,18 +223,18 @@ function createMainWindow() {
|
|||||||
: 'default'),
|
: 'default'),
|
||||||
autoHideMenuBar: config.get('options.hideMenu'),
|
autoHideMenuBar: config.get('options.hideMenu'),
|
||||||
});
|
});
|
||||||
loadPlugins(win);
|
await loadPlugins(win);
|
||||||
|
|
||||||
if (windowPosition) {
|
if (windowPosition) {
|
||||||
const { x, y } = windowPosition;
|
const { x: windowX, y: windowY } = windowPosition;
|
||||||
const winSize = win.getSize();
|
const winSize = win.getSize();
|
||||||
const displaySize
|
const displaySize
|
||||||
= screen.getDisplayNearestPoint(windowPosition).bounds;
|
= screen.getDisplayNearestPoint(windowPosition).bounds;
|
||||||
if (
|
if (
|
||||||
x + winSize[0] < displaySize.x - 8
|
windowX + winSize[0] < displaySize.x - 8
|
||||||
|| x - winSize[0] > displaySize.x + displaySize.width
|
|| windowX - winSize[0] > displaySize.x + displaySize.width
|
||||||
|| y < displaySize.y - 8
|
|| windowY < displaySize.y - 8
|
||||||
|| y > displaySize.y + displaySize.height
|
|| windowY > displaySize.y + displaySize.height
|
||||||
) {
|
) {
|
||||||
// Window is offscreen
|
// Window is offscreen
|
||||||
if (is.dev()) {
|
if (is.dev()) {
|
||||||
@ -243,7 +243,7 @@ function createMainWindow() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
win.setPosition(x, y);
|
win.setPosition(windowX, windowY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,29 +258,8 @@ function createMainWindow() {
|
|||||||
const urlToLoad = config.get('options.resumeOnStart')
|
const urlToLoad = config.get('options.resumeOnStart')
|
||||||
? config.get('url')
|
? config.get('url')
|
||||||
: config.defaultConfig.url;
|
: config.defaultConfig.url;
|
||||||
win.webContents.loadURL(urlToLoad);
|
|
||||||
win.on('closed', onClosed);
|
win.on('closed', onClosed);
|
||||||
|
|
||||||
const scaleFactor = screen.getAllDisplays().length > 1 ? screen.getPrimaryDisplay().scaleFactor : 1;
|
|
||||||
const size = config.get('window-size');
|
|
||||||
const position = config.get('window-position');
|
|
||||||
|
|
||||||
if (size && size.width && size.height) {
|
|
||||||
const scaledSize = {
|
|
||||||
width: size.width / scaleFactor,
|
|
||||||
height: size.height / scaleFactor,
|
|
||||||
};
|
|
||||||
win.setSize(scaledSize.width, scaledSize.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position && position.x && position.y) {
|
|
||||||
const scaledPosition = {
|
|
||||||
x: position.x / scaleFactor,
|
|
||||||
y: position.y / scaleFactor,
|
|
||||||
};
|
|
||||||
win.setPosition(scaledPosition.x, scaledPosition.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
type PiPOptions = typeof config.defaultConfig.plugins['picture-in-picture'];
|
type PiPOptions = typeof config.defaultConfig.plugins['picture-in-picture'];
|
||||||
const setPiPOptions = config.plugins.isEnabled('picture-in-picture')
|
const setPiPOptions = config.plugins.isEnabled('picture-in-picture')
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
@ -358,6 +337,8 @@ function createMainWindow() {
|
|||||||
|
|
||||||
removeContentSecurityPolicy();
|
removeContentSecurityPolicy();
|
||||||
|
|
||||||
|
win.webContents.loadURL(urlToLoad);
|
||||||
|
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +395,7 @@ app.once('browser-window-created', (event, win) => {
|
|||||||
console.log(log);
|
console.log(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(config.plugins.isEnabled('in-app-menu') && errorCode === -3)) { // -3 is a false positive with in-app-menu
|
if (errorCode !== -3) { // -3 is a false positive
|
||||||
win.webContents.send('log', log);
|
win.webContents.send('log', log);
|
||||||
win.webContents.loadFile(path.join(__dirname, 'error.html'));
|
win.webContents.loadFile(path.join(__dirname, 'error.html'));
|
||||||
}
|
}
|
||||||
@ -434,17 +415,17 @@ app.on('window-all-closed', () => {
|
|||||||
globalShortcut.unregisterAll();
|
globalShortcut.unregisterAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('activate', () => {
|
app.on('activate', async () => {
|
||||||
// On OS X it's common to re-create a window in the app when the
|
// On OS X it's common to re-create a window in the app when the
|
||||||
// dock icon is clicked and there are no other windows open.
|
// dock icon is clicked and there are no other windows open.
|
||||||
if (mainWindow === null) {
|
if (mainWindow === null) {
|
||||||
mainWindow = createMainWindow();
|
mainWindow = await createMainWindow();
|
||||||
} else if (!mainWindow.isVisible()) {
|
} else if (!mainWindow.isVisible()) {
|
||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', async () => {
|
||||||
if (config.get('options.autoResetAppCache')) {
|
if (config.get('options.autoResetAppCache')) {
|
||||||
// Clear cache after 20s
|
// Clear cache after 20s
|
||||||
const clearCacheTimeout = setTimeout(() => {
|
const clearCacheTimeout = setTimeout(() => {
|
||||||
@ -489,8 +470,9 @@ app.on('ready', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mainWindow = createMainWindow();
|
mainWindow = await createMainWindow();
|
||||||
setApplicationMenu(mainWindow);
|
setApplicationMenu(mainWindow);
|
||||||
|
refreshMenu(mainWindow);
|
||||||
setUpTray(app, mainWindow);
|
setUpTray(app, mainWindow);
|
||||||
|
|
||||||
setupProtocolHandler(mainWindow);
|
setupProtocolHandler(mainWindow);
|
||||||
@ -622,8 +604,6 @@ function showUnresponsiveDialog(win: BrowserWindow, details: Electron.RenderProc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: electron-better-web-request's typing is wrong
|
|
||||||
type BetterSession = Omit<Electron.Session, 'webRequest'> & { webRequest: BetterWebRequest & Electron.WebRequest };
|
|
||||||
function removeContentSecurityPolicy(
|
function removeContentSecurityPolicy(
|
||||||
betterSession: BetterSession = session.defaultSession as BetterSession,
|
betterSession: BetterSession = session.defaultSession as BetterSession,
|
||||||
) {
|
) {
|
||||||
@ -643,11 +623,10 @@ function removeContentSecurityPolicy(
|
|||||||
callback({ cancel: false, responseHeaders: details.responseHeaders });
|
callback({ cancel: false, responseHeaders: details.responseHeaders });
|
||||||
});
|
});
|
||||||
|
|
||||||
type ResolverListener = { apply: () => Promise<Record<string, unknown>>; context: unknown };
|
|
||||||
// When multiple listeners are defined, apply them all
|
// When multiple listeners are defined, apply them all
|
||||||
betterSession.webRequest.setResolver('onHeadersReceived', async (listeners: ResolverListener[]) => {
|
betterSession.webRequest.setResolver('onHeadersReceived', async (listeners) => {
|
||||||
return listeners.reduce<Promise<Record<string, unknown>>>(
|
return listeners.reduce(
|
||||||
async (accumulator: Promise<Record<string, unknown>>, listener: ResolverListener) => {
|
async (accumulator, listener) => {
|
||||||
const acc = await accumulator;
|
const acc = await accumulator;
|
||||||
if (acc.cancel) {
|
if (acc.cancel) {
|
||||||
return acc;
|
return acc;
|
||||||
@ -8,11 +8,13 @@ import { startingPages } from './providers/extracted-data';
|
|||||||
import promptOptions from './providers/prompt-options';
|
import promptOptions from './providers/prompt-options';
|
||||||
|
|
||||||
import adblockerMenu from './plugins/adblocker/menu';
|
import adblockerMenu from './plugins/adblocker/menu';
|
||||||
|
import ambientModeMenu from './plugins/ambient-mode/menu';
|
||||||
import captionsSelectorMenu from './plugins/captions-selector/menu';
|
import captionsSelectorMenu from './plugins/captions-selector/menu';
|
||||||
import crossfadeMenu from './plugins/crossfade/menu';
|
import crossfadeMenu from './plugins/crossfade/menu';
|
||||||
import disableAutoplayMenu from './plugins/disable-autoplay/menu';
|
import disableAutoplayMenu from './plugins/disable-autoplay/menu';
|
||||||
import discordMenu from './plugins/discord/menu';
|
import discordMenu from './plugins/discord/menu';
|
||||||
import downloaderMenu from './plugins/downloader/menu';
|
import downloaderMenu from './plugins/downloader/menu';
|
||||||
|
import inAppMenuTitlebarMenu from './plugins/in-app-menu/menu';
|
||||||
import lyricsGeniusMenu from './plugins/lyrics-genius/menu';
|
import lyricsGeniusMenu from './plugins/lyrics-genius/menu';
|
||||||
import notificationsMenu from './plugins/notifications/menu';
|
import notificationsMenu from './plugins/notifications/menu';
|
||||||
import pictureInPictureMenu from './plugins/picture-in-picture/menu';
|
import pictureInPictureMenu from './plugins/picture-in-picture/menu';
|
||||||
@ -31,11 +33,13 @@ const betaPlugins = ['crossfade', 'lumiastream'];
|
|||||||
|
|
||||||
const pluginMenus = {
|
const pluginMenus = {
|
||||||
'adblocker': adblockerMenu,
|
'adblocker': adblockerMenu,
|
||||||
|
'ambient-mode': ambientModeMenu,
|
||||||
'disable-autoplay': disableAutoplayMenu,
|
'disable-autoplay': disableAutoplayMenu,
|
||||||
'captions-selector': captionsSelectorMenu,
|
'captions-selector': captionsSelectorMenu,
|
||||||
'crossfade': crossfadeMenu,
|
'crossfade': crossfadeMenu,
|
||||||
'discord': discordMenu,
|
'discord': discordMenu,
|
||||||
'downloader': downloaderMenu,
|
'downloader': downloaderMenu,
|
||||||
|
'in-app-menu': inAppMenuTitlebarMenu,
|
||||||
'lyrics-genius': lyricsGeniusMenu,
|
'lyrics-genius': lyricsGeniusMenu,
|
||||||
'notifications': notificationsMenu,
|
'notifications': notificationsMenu,
|
||||||
'picture-in-picture': pictureInPictureMenu,
|
'picture-in-picture': pictureInPictureMenu,
|
||||||
@ -62,13 +66,15 @@ const pluginEnabledMenu = (plugin: string, label = '', hasSubmenu = false, refre
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const refreshMenu = (win: BrowserWindow) => {
|
||||||
|
setApplicationMenu(win);
|
||||||
|
if (inAppMenuActive) {
|
||||||
|
win.webContents.send('refreshMenu');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => {
|
export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => {
|
||||||
const refreshMenu = () => {
|
const innerRefreshMenu = () => refreshMenu(win);
|
||||||
setApplicationMenu(win);
|
|
||||||
if (inAppMenuActive) {
|
|
||||||
win.webContents.send('refreshMenu');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -84,15 +90,15 @@ export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => {
|
|||||||
const getPluginMenu = pluginMenus[pluginName as keyof typeof pluginMenus];
|
const getPluginMenu = pluginMenus[pluginName as keyof typeof pluginMenus];
|
||||||
|
|
||||||
if (!config.plugins.isEnabled(pluginName)) {
|
if (!config.plugins.isEnabled(pluginName)) {
|
||||||
return pluginEnabledMenu(pluginName, pluginLabel, true, refreshMenu);
|
return pluginEnabledMenu(pluginName, pluginLabel, true, innerRefreshMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label: pluginLabel,
|
label: pluginLabel,
|
||||||
submenu: [
|
submenu: [
|
||||||
pluginEnabledMenu(pluginName, 'Enabled', true, refreshMenu),
|
pluginEnabledMenu(pluginName, 'Enabled', true, innerRefreshMenu),
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
...getPluginMenu(win, config.plugins.getOptions(pluginName), refreshMenu),
|
...getPluginMenu(win, config.plugins.getOptions(pluginName), innerRefreshMenu),
|
||||||
],
|
],
|
||||||
} satisfies Electron.MenuItemConstructorOptions;
|
} satisfies Electron.MenuItemConstructorOptions;
|
||||||
}
|
}
|
||||||
@ -418,6 +424,12 @@ export const mainMenuTemplate = (win: BrowserWindow): MenuTemplate => {
|
|||||||
{ role: 'quit' },
|
{ role: 'quit' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'About',
|
||||||
|
submenu: [
|
||||||
|
{ role: 'about' },
|
||||||
|
],
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
export const setApplicationMenu = (win: Electron.BrowserWindow) => {
|
export const setApplicationMenu = (win: Electron.BrowserWindow) => {
|
||||||
0
navigation.d.ts → src/navigation.d.ts
vendored
0
navigation.d.ts → src/navigation.d.ts
vendored
@ -8,8 +8,8 @@ import type { ConfigType } from '../../config/dynamic';
|
|||||||
type AdBlockOptions = ConfigType<'adblocker'>;
|
type AdBlockOptions = ConfigType<'adblocker'>;
|
||||||
|
|
||||||
export default async (win: BrowserWindow, options: AdBlockOptions) => {
|
export default async (win: BrowserWindow, options: AdBlockOptions) => {
|
||||||
if (await shouldUseBlocklists()) {
|
if (shouldUseBlocklists()) {
|
||||||
loadAdBlockerEngine(
|
await loadAdBlockerEngine(
|
||||||
win.webContents.session,
|
win.webContents.session,
|
||||||
options.cache,
|
options.cache,
|
||||||
options.additionalBlockLists,
|
options.additionalBlockLists,
|
||||||
4
src/plugins/adblocker/blocker-types.ts
Normal file
4
src/plugins/adblocker/blocker-types.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const blockers = {
|
||||||
|
WithBlocklists: 'With blocklists',
|
||||||
|
InPlayer: 'In player',
|
||||||
|
} as const;
|
||||||
@ -3,7 +3,7 @@ import path from 'node:path';
|
|||||||
import fs, { promises } from 'node:fs';
|
import fs, { promises } from 'node:fs';
|
||||||
|
|
||||||
import { ElectronBlocker } from '@cliqz/adblocker-electron';
|
import { ElectronBlocker } from '@cliqz/adblocker-electron';
|
||||||
import { app } from 'electron';
|
import { app, net } from 'electron';
|
||||||
|
|
||||||
const SOURCES = [
|
const SOURCES = [
|
||||||
'https://raw.githubusercontent.com/kbinani/adblock-youtube-ads/master/signed.txt',
|
'https://raw.githubusercontent.com/kbinani/adblock-youtube-ads/master/signed.txt',
|
||||||
@ -17,19 +17,14 @@ const SOURCES = [
|
|||||||
'https://secure.fanboy.co.nz/fanboy-annoyance_ubo.txt',
|
'https://secure.fanboy.co.nz/fanboy-annoyance_ubo.txt',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const loadAdBlockerEngine = (
|
export const loadAdBlockerEngine = async (
|
||||||
session: Electron.Session | undefined = undefined,
|
session: Electron.Session | undefined = undefined,
|
||||||
cache = true,
|
cache = true,
|
||||||
additionalBlockLists = [],
|
additionalBlockLists = [],
|
||||||
disableDefaultLists: boolean | unknown[] = false,
|
disableDefaultLists: boolean | unknown[] = false,
|
||||||
) => {
|
) => {
|
||||||
// Only use cache if no additional blocklists are passed
|
// Only use cache if no additional blocklists are passed
|
||||||
let cacheDirectory: string;
|
const cacheDirectory = path.join(app.getPath('userData'), 'adblock_cache');
|
||||||
if (app.isPackaged) {
|
|
||||||
cacheDirectory = path.join(app.getPath('userData'), 'adblock_cache');
|
|
||||||
} else {
|
|
||||||
cacheDirectory = path.resolve(__dirname, 'adblock_cache');
|
|
||||||
}
|
|
||||||
if (!fs.existsSync(cacheDirectory)) {
|
if (!fs.existsSync(cacheDirectory)) {
|
||||||
fs.mkdirSync(cacheDirectory);
|
fs.mkdirSync(cacheDirectory);
|
||||||
}
|
}
|
||||||
@ -49,25 +44,24 @@ export const loadAdBlockerEngine = (
|
|||||||
...additionalBlockLists,
|
...additionalBlockLists,
|
||||||
];
|
];
|
||||||
|
|
||||||
ElectronBlocker.fromLists(
|
try {
|
||||||
fetch,
|
const blocker = await ElectronBlocker.fromLists(
|
||||||
lists,
|
(url: string) => net.fetch(url),
|
||||||
{
|
lists,
|
||||||
// When generating the engine for caching, do not load network filters
|
{
|
||||||
// So that enhancing the session works as expected
|
// When generating the engine for caching, do not load network filters
|
||||||
// Allowing to define multiple webRequest listeners
|
// So that enhancing the session works as expected
|
||||||
loadNetworkFilters: session !== undefined,
|
// Allowing to define multiple webRequest listeners
|
||||||
},
|
loadNetworkFilters: session !== undefined,
|
||||||
cachingOptions,
|
},
|
||||||
)
|
cachingOptions,
|
||||||
.then((blocker) => {
|
);
|
||||||
if (session) {
|
if (session) {
|
||||||
blocker.enableBlockingInSession(session);
|
blocker.enableBlockingInSession(session);
|
||||||
} else {
|
}
|
||||||
console.log('Successfully generated adBlocker engine.');
|
} catch (error) {
|
||||||
}
|
console.log('Error loading adBlocker engine', error);
|
||||||
})
|
}
|
||||||
.catch((error) => console.log('Error loading adBlocker engine', error));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default { loadAdBlockerEngine };
|
export default { loadAdBlockerEngine };
|
||||||
@ -1,16 +1,13 @@
|
|||||||
/* eslint-disable @typescript-eslint/await-thenable */
|
/* eslint-disable @typescript-eslint/await-thenable */
|
||||||
/* renderer */
|
/* renderer */
|
||||||
|
|
||||||
|
import { blockers } from './blocker-types';
|
||||||
|
|
||||||
import { PluginConfig } from '../../config/dynamic';
|
import { PluginConfig } from '../../config/dynamic';
|
||||||
|
|
||||||
const config = new PluginConfig('adblocker', { enableFront: true });
|
const config = new PluginConfig('adblocker', { enableFront: true });
|
||||||
|
|
||||||
export const blockers = {
|
export const shouldUseBlocklists = () => config.get('blocker') !== blockers.InPlayer;
|
||||||
WithBlocklists: 'With blocklists',
|
|
||||||
InPlayer: 'In player',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const shouldUseBlocklists = async () => await config.get('blocker') !== blockers.InPlayer;
|
|
||||||
|
|
||||||
export default Object.assign(config, {
|
export default Object.assign(config, {
|
||||||
shouldUseBlocklists,
|
shouldUseBlocklists,
|
||||||
3
src/plugins/adblocker/inject-cliqz-preload.ts
Normal file
3
src/plugins/adblocker/inject-cliqz-preload.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default async () => {
|
||||||
|
await import('@cliqz/adblocker-electron-preload');
|
||||||
|
};
|
||||||
@ -1,4 +1,6 @@
|
|||||||
import config, { blockers } from './config';
|
import config from './config';
|
||||||
|
|
||||||
|
import { blockers } from './blocker-types';
|
||||||
|
|
||||||
import { MenuTemplate } from '../../menu';
|
import { MenuTemplate } from '../../menu';
|
||||||
|
|
||||||
@ -1,13 +1,15 @@
|
|||||||
import config, { blockers } from './config';
|
import config, { shouldUseBlocklists } from './config';
|
||||||
import inject from './inject';
|
import inject from './inject';
|
||||||
import injectCliqzPreload from './inject-cliqz-preload';
|
import injectCliqzPreload from './inject-cliqz-preload';
|
||||||
|
|
||||||
|
import { blockers } from './blocker-types';
|
||||||
|
|
||||||
export default async () => {
|
export default async () => {
|
||||||
if (await config.shouldUseBlocklists()) {
|
if (shouldUseBlocklists()) {
|
||||||
// Preload adblocker to inject scripts/styles
|
// Preload adblocker to inject scripts/styles
|
||||||
injectCliqzPreload();
|
await injectCliqzPreload();
|
||||||
// eslint-disable-next-line @typescript-eslint/await-thenable
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
||||||
} else if ((await config.get('blocker')) === blockers.InPlayer) {
|
} else if ((config.get('blocker')) === blockers.InPlayer) {
|
||||||
inject();
|
inject();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
14
src/plugins/ambient-mode/back.ts
Normal file
14
src/plugins/ambient-mode/back.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { BrowserWindow } from 'electron';
|
||||||
|
|
||||||
|
import config from './config';
|
||||||
|
import style from './style.css';
|
||||||
|
|
||||||
|
import { injectCSS } from '../utils';
|
||||||
|
|
||||||
|
export default (win: BrowserWindow) => {
|
||||||
|
config.subscribeAll((newConfig) => {
|
||||||
|
win.webContents.send('ambient-mode:config-change', newConfig);
|
||||||
|
});
|
||||||
|
|
||||||
|
injectCSS(win.webContents, style);
|
||||||
|
};
|
||||||
4
src/plugins/ambient-mode/config.ts
Normal file
4
src/plugins/ambient-mode/config.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { PluginConfig } from '../../config/dynamic';
|
||||||
|
|
||||||
|
const config = new PluginConfig('ambient-mode');
|
||||||
|
export default config;
|
||||||
@ -1,9 +1,15 @@
|
|||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
import { ConfigType } from '../../config/dynamic';
|
import { ConfigType } from '../../config/dynamic';
|
||||||
|
|
||||||
export default (_: ConfigType<'ambient-mode'>) => {
|
export default (config: ConfigType<'ambient-mode'>) => {
|
||||||
const interpolationTime = 3000; // interpolation time (ms)
|
let interpolationTime = config.interpolationTime; // interpolation time (ms)
|
||||||
const framerate = 30; // frame
|
let buffer = config.buffer; // frame
|
||||||
const qualityRatio = 50; // width size (pixel)
|
let qualityRatio = config.quality; // width size (pixel)
|
||||||
|
let sizeRatio = config.size / 100; // size ratio (percent)
|
||||||
|
let blur = config.blur; // blur (pixel)
|
||||||
|
let opacity = config.opacity; // opacity (percent)
|
||||||
|
let isFullscreen = config.fullscreen; // fullscreen (boolean)
|
||||||
|
|
||||||
let unregister: (() => void) | null = null;
|
let unregister: (() => void) | null = null;
|
||||||
|
|
||||||
@ -37,7 +43,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
|
|||||||
|
|
||||||
context.globalAlpha = 1;
|
context.globalAlpha = 1;
|
||||||
if (lastImageData) {
|
if (lastImageData) {
|
||||||
const frameOffset = (1 / framerate) * (1000 / interpolationTime);
|
const frameOffset = (1 / buffer) * (1000 / interpolationTime);
|
||||||
context.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1
|
context.globalAlpha = 1 - (frameOffset * 2); // because of alpha value must be < 1
|
||||||
context.putImageData(lastImageData, 0, 0);
|
context.putImageData(lastImageData, 0, 0);
|
||||||
context.globalAlpha = frameOffset;
|
context.globalAlpha = frameOffset;
|
||||||
@ -61,8 +67,18 @@ export default (_: ConfigType<'ambient-mode'>) => {
|
|||||||
|
|
||||||
blurCanvas.width = qualityRatio;
|
blurCanvas.width = qualityRatio;
|
||||||
blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio);
|
blurCanvas.height = Math.floor(newHeight / newWidth * qualityRatio);
|
||||||
blurCanvas.style.width = `${newWidth}px`;
|
blurCanvas.style.width = `${newWidth * sizeRatio}px`;
|
||||||
blurCanvas.style.height = `${newHeight}px`;
|
blurCanvas.style.height = `${newHeight * sizeRatio}px`;
|
||||||
|
|
||||||
|
if (isFullscreen) blurCanvas.classList.add('fullscreen');
|
||||||
|
else blurCanvas.classList.remove('fullscreen');
|
||||||
|
|
||||||
|
const leftOffset = newWidth * (sizeRatio - 1) / 2;
|
||||||
|
const topOffset = newHeight * (sizeRatio - 1) / 2;
|
||||||
|
blurCanvas.style.setProperty('--left', `${-1 * leftOffset}px`);
|
||||||
|
blurCanvas.style.setProperty('--top', `${-1 * topOffset}px`);
|
||||||
|
blurCanvas.style.setProperty('--blur', `${blur}px`);
|
||||||
|
blurCanvas.style.setProperty('--opacity', `${opacity}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
const observer = new MutationObserver((mutations) => {
|
||||||
@ -75,10 +91,22 @@ export default (_: ConfigType<'ambient-mode'>) => {
|
|||||||
const resizeObserver = new ResizeObserver(() => {
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
applyVideoAttributes();
|
applyVideoAttributes();
|
||||||
});
|
});
|
||||||
|
const onConfigSync = (_: Electron.IpcRendererEvent, newConfig: ConfigType<'ambient-mode'>) => {
|
||||||
|
if (typeof newConfig.interpolationTime === 'number') interpolationTime = newConfig.interpolationTime;
|
||||||
|
if (typeof newConfig.buffer === 'number') buffer = newConfig.buffer;
|
||||||
|
if (typeof newConfig.quality === 'number') qualityRatio = newConfig.quality;
|
||||||
|
if (typeof newConfig.size === 'number') sizeRatio = newConfig.size / 100;
|
||||||
|
if (typeof newConfig.blur === 'number') blur = newConfig.blur;
|
||||||
|
if (typeof newConfig.opacity === 'number') opacity = newConfig.opacity;
|
||||||
|
if (typeof newConfig.fullscreen === 'boolean') isFullscreen = newConfig.fullscreen;
|
||||||
|
|
||||||
|
applyVideoAttributes();
|
||||||
|
};
|
||||||
|
ipcRenderer.on('ambient-mode:config-change', onConfigSync);
|
||||||
|
|
||||||
/* hooking */
|
/* hooking */
|
||||||
let canvasInterval: NodeJS.Timeout | null = null;
|
let canvasInterval: NodeJS.Timeout | null = null;
|
||||||
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate)));
|
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / buffer)));
|
||||||
applyVideoAttributes();
|
applyVideoAttributes();
|
||||||
observer.observe(songVideo, { attributes: true });
|
observer.observe(songVideo, { attributes: true });
|
||||||
resizeObserver.observe(songVideo);
|
resizeObserver.observe(songVideo);
|
||||||
@ -90,7 +118,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
|
|||||||
};
|
};
|
||||||
const onPlay = () => {
|
const onPlay = () => {
|
||||||
if (canvasInterval) clearInterval(canvasInterval);
|
if (canvasInterval) clearInterval(canvasInterval);
|
||||||
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / framerate)));
|
canvasInterval = setInterval(onSync, Math.max(1, Math.ceil(1000 / buffer)));
|
||||||
};
|
};
|
||||||
songVideo.addEventListener('pause', onPause);
|
songVideo.addEventListener('pause', onPause);
|
||||||
songVideo.addEventListener('play', onPlay);
|
songVideo.addEventListener('play', onPlay);
|
||||||
@ -107,6 +135,7 @@ export default (_: ConfigType<'ambient-mode'>) => {
|
|||||||
|
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
resizeObserver.disconnect();
|
resizeObserver.disconnect();
|
||||||
|
ipcRenderer.off('ambient-mode:config-change', onConfigSync);
|
||||||
window.removeEventListener('resize', applyVideoAttributes);
|
window.removeEventListener('resize', applyVideoAttributes);
|
||||||
|
|
||||||
wrapper.removeChild(blurCanvas);
|
wrapper.removeChild(blurCanvas);
|
||||||
87
src/plugins/ambient-mode/menu.ts
Normal file
87
src/plugins/ambient-mode/menu.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import config from './config';
|
||||||
|
|
||||||
|
import { MenuTemplate } from '../../menu';
|
||||||
|
|
||||||
|
const interpolationTimeList = [0, 500, 1000, 1500, 2000, 3000, 4000, 5000];
|
||||||
|
const qualityList = [10, 25, 50, 100, 200, 500, 1000];
|
||||||
|
const sizeList = [100, 110, 125, 150, 175, 200, 300];
|
||||||
|
const bufferList = [1, 5, 10, 20, 30];
|
||||||
|
const blurAmountList = [0, 5, 10, 25, 50, 100, 150, 200, 500];
|
||||||
|
const opacityList = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
|
||||||
|
|
||||||
|
export default (): MenuTemplate => [
|
||||||
|
{
|
||||||
|
label: 'Smoothness transition',
|
||||||
|
submenu: interpolationTimeList.map((interpolationTime) => ({
|
||||||
|
label: `During ${interpolationTime / 1000}s`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('interpolationTime') === interpolationTime,
|
||||||
|
click() {
|
||||||
|
config.set('interpolationTime', interpolationTime);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Quality',
|
||||||
|
submenu: qualityList.map((quality) => ({
|
||||||
|
label: `${quality} pixels`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('quality') === quality,
|
||||||
|
click() {
|
||||||
|
config.set('quality', quality);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Size',
|
||||||
|
submenu: sizeList.map((size) => ({
|
||||||
|
label: `${size}%`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('size') === size,
|
||||||
|
click() {
|
||||||
|
config.set('size', size);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Buffer',
|
||||||
|
submenu: bufferList.map((buffer) => ({
|
||||||
|
label: `${buffer}`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('buffer') === buffer,
|
||||||
|
click() {
|
||||||
|
config.set('buffer', buffer);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Opacity',
|
||||||
|
submenu: opacityList.map((opacity) => ({
|
||||||
|
label: `${opacity * 100}%`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('opacity') === opacity,
|
||||||
|
click() {
|
||||||
|
config.set('opacity', opacity);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Blur amount',
|
||||||
|
submenu: blurAmountList.map((blur) => ({
|
||||||
|
label: `${blur} pixels`,
|
||||||
|
type: 'radio',
|
||||||
|
checked: config.get('blur') === blur,
|
||||||
|
click() {
|
||||||
|
config.set('blur', blur);
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Using fullscreen',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: config.get('fullscreen'),
|
||||||
|
click(item) {
|
||||||
|
config.set('fullscreen', item.checked);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
26
src/plugins/ambient-mode/style.css
Normal file
26
src/plugins/ambient-mode/style.css
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#song-video canvas.html5-blur-canvas {
|
||||||
|
filter: blur(var(--blur, 100px));
|
||||||
|
opacity: var(--opacity, 1);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#song-video canvas.html5-blur-canvas:not(.fullscreen) {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
left: var(--left, 0px);
|
||||||
|
top: var(--top, 0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#song-video canvas.html5-blur-canvas.fullscreen {
|
||||||
|
position: fixed;
|
||||||
|
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
left: 0 !important;
|
||||||
|
top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#song-video .html5-video-container > video {
|
||||||
|
top: 0 !important;
|
||||||
|
}
|
||||||
4
src/plugins/bypass-age-restrictions/front.ts
Normal file
4
src/plugins/bypass-age-restrictions/front.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export default async () => {
|
||||||
|
// See https://github.com/zerodytrash/Simple-YouTube-Age-Restriction-Bypass#userscript
|
||||||
|
await import('simple-youtube-age-restriction-bypass');
|
||||||
|
};
|
||||||
4
src/plugins/bypass-age-restrictions/simple-youtube-age-restriction-bypass.d.ts
vendored
Normal file
4
src/plugins/bypass-age-restrictions/simple-youtube-age-restriction-bypass.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module 'simple-youtube-age-restriction-bypass' {
|
||||||
|
const nothing: never;
|
||||||
|
export default nothing;
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { app, dialog } from 'electron';
|
import { app, dialog, ipcMain } from 'electron';
|
||||||
import { Client as DiscordClient } from '@xhayper/discord-rpc';
|
import { Client as DiscordClient } from '@xhayper/discord-rpc';
|
||||||
import { dev } from 'electron-is';
|
import { dev } from 'electron-is';
|
||||||
|
|
||||||
import { SetActivity } from '@xhayper/discord-rpc/dist/structures/ClientUser';
|
import { SetActivity } from '@xhayper/discord-rpc/dist/structures/ClientUser';
|
||||||
|
|
||||||
import registerCallback from '../../providers/song-info';
|
import registerCallback, { type SongInfoCallback, type SongInfo } from '../../providers/song-info';
|
||||||
|
|
||||||
import type { ConfigType } from '../../config/dynamic';
|
import type { ConfigType } from '../../config/dynamic';
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ export interface Info {
|
|||||||
rpc: DiscordClient;
|
rpc: DiscordClient;
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
autoReconnect: boolean;
|
autoReconnect: boolean;
|
||||||
lastSongInfo?: import('../../providers/song-info').SongInfo;
|
lastSongInfo?: SongInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const info: Info = {
|
const info: Info = {
|
||||||
@ -44,31 +44,6 @@ const resetInfo = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
info.rpc.on('connected', () => {
|
|
||||||
if (dev()) {
|
|
||||||
console.log('discord connected');
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const cb of refreshCallbacks) {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
info.rpc.on('ready', () => {
|
|
||||||
info.ready = true;
|
|
||||||
if (info.lastSongInfo) {
|
|
||||||
updateActivity(info.lastSongInfo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
info.rpc.on('disconnected', () => {
|
|
||||||
resetInfo();
|
|
||||||
|
|
||||||
if (info.autoReconnect) {
|
|
||||||
connectTimeout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const connectTimeout = () => new Promise((resolve, reject) => setTimeout(() => {
|
const connectTimeout = () => new Promise((resolve, reject) => setTimeout(() => {
|
||||||
if (!info.autoReconnect || info.rpc.isConnected) {
|
if (!info.autoReconnect || info.rpc.isConnected) {
|
||||||
return;
|
return;
|
||||||
@ -117,7 +92,7 @@ export const connect = (showError = false) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let clearActivity: NodeJS.Timeout | undefined;
|
let clearActivity: NodeJS.Timeout | undefined;
|
||||||
let updateActivity: import('../../providers/song-info').SongInfoCallback;
|
let updateActivity: SongInfoCallback;
|
||||||
|
|
||||||
type DiscordOptions = ConfigType<'discord'>;
|
type DiscordOptions = ConfigType<'discord'>;
|
||||||
|
|
||||||
@ -125,6 +100,31 @@ export default (
|
|||||||
win: Electron.BrowserWindow,
|
win: Electron.BrowserWindow,
|
||||||
options: DiscordOptions,
|
options: DiscordOptions,
|
||||||
) => {
|
) => {
|
||||||
|
info.rpc.on('connected', () => {
|
||||||
|
if (dev()) {
|
||||||
|
console.log('discord connected');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const cb of refreshCallbacks) {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
info.rpc.on('ready', () => {
|
||||||
|
info.ready = true;
|
||||||
|
if (info.lastSongInfo) {
|
||||||
|
updateActivity(info.lastSongInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
info.rpc.on('disconnected', () => {
|
||||||
|
resetInfo();
|
||||||
|
|
||||||
|
if (info.autoReconnect) {
|
||||||
|
connectTimeout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
info.autoReconnect = options.autoReconnect;
|
info.autoReconnect = options.autoReconnect;
|
||||||
|
|
||||||
window = win;
|
window = win;
|
||||||
@ -156,14 +156,22 @@ export default (
|
|||||||
// Song information changed, so lets update the rich presence
|
// Song information changed, so lets update the rich presence
|
||||||
// @see https://discord.com/developers/docs/topics/gateway#activity-object
|
// @see https://discord.com/developers/docs/topics/gateway#activity-object
|
||||||
// not all options are transfered through https://github.com/discordjs/RPC/blob/6f83d8d812c87cb7ae22064acd132600407d7d05/src/client.js#L518-530
|
// not all options are transfered through https://github.com/discordjs/RPC/blob/6f83d8d812c87cb7ae22064acd132600407d7d05/src/client.js#L518-530
|
||||||
|
const hangulFillerUnicodeCharacter = '\u3164'; // This is an empty character
|
||||||
|
if (songInfo.title.length < 2) {
|
||||||
|
songInfo.title += hangulFillerUnicodeCharacter.repeat(2 - songInfo.title.length);
|
||||||
|
}
|
||||||
|
if (songInfo.artist.length < 2) {
|
||||||
|
songInfo.artist += hangulFillerUnicodeCharacter.repeat(2 - songInfo.title.length);
|
||||||
|
}
|
||||||
|
|
||||||
const activityInfo: SetActivity = {
|
const activityInfo: SetActivity = {
|
||||||
details: songInfo.title,
|
details: songInfo.title,
|
||||||
state: songInfo.artist,
|
state: songInfo.artist,
|
||||||
largeImageKey: songInfo.imageSrc ?? '',
|
largeImageKey: songInfo.imageSrc ?? '',
|
||||||
largeImageText: songInfo.album ?? '',
|
largeImageText: songInfo.album ?? '',
|
||||||
buttons: [
|
buttons: [
|
||||||
...(options.listenAlong ? [{ label: 'Listen Along', url: songInfo.url ?? '' }] : []),
|
...(options.playOnYouTubeMusic ? [{ label: 'Play on YouTube Music', url: songInfo.url ?? '' }] : []),
|
||||||
{ label: 'View App On GitHub', url: 'https://github.com/th-ch/youtube-music' },
|
...(options.hideGitHubButton ? [] : [{ label: 'View App On GitHub', url: 'https://github.com/th-ch/youtube-music' }]),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -188,8 +196,22 @@ export default (
|
|||||||
|
|
||||||
// If the page is ready, register the callback
|
// If the page is ready, register the callback
|
||||||
win.once('ready-to-show', () => {
|
win.once('ready-to-show', () => {
|
||||||
registerCallback(updateActivity);
|
let lastSongInfo: SongInfo;
|
||||||
|
registerCallback((songInfo) => {
|
||||||
|
lastSongInfo = songInfo;
|
||||||
|
updateActivity(songInfo);
|
||||||
|
});
|
||||||
connect();
|
connect();
|
||||||
|
let lastSent = Date.now();
|
||||||
|
ipcMain.on('timeChanged', (_, t: number) => {
|
||||||
|
const currentTime = Date.now();
|
||||||
|
// if lastSent is more than 5 seconds ago, send the new time
|
||||||
|
if (currentTime - lastSent > 5000) {
|
||||||
|
lastSent = currentTime;
|
||||||
|
lastSongInfo.elapsedSeconds = t;
|
||||||
|
updateActivity(lastSongInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
app.on('window-all-closed', clear);
|
app.on('window-all-closed', clear);
|
||||||
};
|
};
|
||||||
@ -47,11 +47,20 @@ export default (win: Electron.BrowserWindow, options: DiscordOptions, refreshMen
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Listen Along',
|
label: 'Play on YouTube Music',
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
checked: options.listenAlong,
|
checked: options.playOnYouTubeMusic,
|
||||||
click(item: Electron.MenuItem) {
|
click(item: Electron.MenuItem) {
|
||||||
options.listenAlong = item.checked;
|
options.playOnYouTubeMusic = item.checked;
|
||||||
|
setMenuOptions('discord', options);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Hide GitHub link Button',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: options.hideGitHubButton,
|
||||||
|
click(item: Electron.MenuItem) {
|
||||||
|
options.hideGitHubButton = item.checked;
|
||||||
setMenuOptions('discord', options);
|
setMenuOptions('discord', options);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1,28 +1,34 @@
|
|||||||
import { createWriteStream, existsSync, mkdirSync, writeFileSync, } from 'node:fs';
|
import {
|
||||||
|
createWriteStream,
|
||||||
|
existsSync,
|
||||||
|
mkdirSync,
|
||||||
|
writeFileSync,
|
||||||
|
} from 'node:fs';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import { randomBytes } from 'node:crypto';
|
import { randomBytes } from 'node:crypto';
|
||||||
|
|
||||||
import { app, BrowserWindow, dialog, ipcMain, net } from 'electron';
|
import { app, BrowserWindow, dialog, ipcMain, net } from 'electron';
|
||||||
import { ClientType, Innertube, UniversalCache, Utils } from 'youtubei.js';
|
import {
|
||||||
|
ClientType,
|
||||||
|
Innertube,
|
||||||
|
UniversalCache,
|
||||||
|
Utils,
|
||||||
|
YTNodes,
|
||||||
|
} from 'youtubei.js';
|
||||||
import is from 'electron-is';
|
import is from 'electron-is';
|
||||||
import ytpl from 'ytpl';
|
|
||||||
// REPLACE with youtubei getplaylist https://github.com/LuanRT/YouTube.js#getplaylistid
|
|
||||||
import filenamify from 'filenamify';
|
import filenamify from 'filenamify';
|
||||||
import { Mutex } from 'async-mutex';
|
import { Mutex } from 'async-mutex';
|
||||||
import { createFFmpeg } from '@ffmpeg.wasm/main';
|
import { createFFmpeg } from '@ffmpeg.wasm/main';
|
||||||
|
|
||||||
import NodeID3, { TagConstants } from 'node-id3';
|
import NodeID3, { TagConstants } from 'node-id3';
|
||||||
|
|
||||||
import PlayerErrorMessage from 'youtubei.js/dist/src/parser/classes/PlayerErrorMessage';
|
import {
|
||||||
import { FormatOptions } from 'youtubei.js/dist/src/types/FormatUtils';
|
cropMaxWidth,
|
||||||
|
getFolder,
|
||||||
import TrackInfo from 'youtubei.js/dist/src/parser/ytmusic/TrackInfo';
|
sendFeedback as sendFeedback_,
|
||||||
|
setBadge,
|
||||||
import { VideoInfo } from 'youtubei.js/dist/src/parser/youtube';
|
} from './utils';
|
||||||
|
|
||||||
import { cropMaxWidth, getFolder, presets, sendFeedback as sendFeedback_, setBadge } from './utils';
|
|
||||||
|
|
||||||
import config from './config';
|
import config from './config';
|
||||||
|
import { YoutubeFormatList, type Preset, DefaultPresetList } from './types';
|
||||||
|
|
||||||
import style from './style.css';
|
import style from './style.css';
|
||||||
|
|
||||||
@ -32,17 +38,20 @@ import { cleanupName, getImage, SongInfo } from '../../providers/song-info';
|
|||||||
import { injectCSS } from '../utils';
|
import { injectCSS } from '../utils';
|
||||||
import { cache } from '../../providers/decorators';
|
import { cache } from '../../providers/decorators';
|
||||||
|
|
||||||
import type { GetPlayerResponse } from '../../types/get-player-response';
|
import type { FormatOptions } from 'youtubei.js/dist/src/types/FormatUtils';
|
||||||
|
import type PlayerErrorMessage from 'youtubei.js/dist/src/parser/classes/PlayerErrorMessage';
|
||||||
|
import type { Playlist } from 'youtubei.js/dist/src/parser/ytmusic';
|
||||||
|
import type { VideoInfo } from 'youtubei.js/dist/src/parser/youtube';
|
||||||
|
import type TrackInfo from 'youtubei.js/dist/src/parser/ytmusic/TrackInfo';
|
||||||
|
|
||||||
|
import type { GetPlayerResponse } from '../../types/get-player-response';
|
||||||
|
|
||||||
type CustomSongInfo = SongInfo & { trackId?: string };
|
type CustomSongInfo = SongInfo & { trackId?: string };
|
||||||
|
|
||||||
const ffmpeg = createFFmpeg({
|
const ffmpeg = createFFmpeg({
|
||||||
log: false,
|
log: false,
|
||||||
logger() {
|
logger() {}, // Console.log,
|
||||||
}, // Console.log,
|
progress() {}, // Console.log,
|
||||||
progress() {
|
|
||||||
}, // Console.log,
|
|
||||||
});
|
});
|
||||||
const ffmpegMutex = new Mutex();
|
const ffmpegMutex = new Mutex();
|
||||||
|
|
||||||
@ -69,23 +78,31 @@ const sendError = (error: Error, source?: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCookieFromWindow = async (win: BrowserWindow) => {
|
||||||
|
return (
|
||||||
|
await win.webContents.session.cookies.get({
|
||||||
|
url: 'https://music.youtube.com',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.map((it) => it.name + '=' + it.value)
|
||||||
|
.join(';');
|
||||||
|
};
|
||||||
|
|
||||||
export default async (win_: BrowserWindow) => {
|
export default async (win_: BrowserWindow) => {
|
||||||
win = win_;
|
win = win_;
|
||||||
injectCSS(win.webContents, style);
|
injectCSS(win.webContents, style);
|
||||||
|
|
||||||
const cookie = (await win.webContents.session.cookies.get({ url: 'https://music.youtube.com' })).map((it) =>
|
|
||||||
it.name + '=' + it.value + ';'
|
|
||||||
).join('');
|
|
||||||
yt = await Innertube.create({
|
yt = await Innertube.create({
|
||||||
cache: new UniversalCache(false),
|
cache: new UniversalCache(false),
|
||||||
cookie,
|
cookie: await getCookieFromWindow(win),
|
||||||
generate_session_locally: true,
|
generate_session_locally: true,
|
||||||
fetch: async (input: RequestInfo | URL, init?: RequestInit) => {
|
fetch: (async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||||
const url =
|
const url =
|
||||||
typeof input === 'string' ?
|
typeof input === 'string'
|
||||||
new URL(input) :
|
? new URL(input)
|
||||||
input instanceof URL ?
|
: input instanceof URL
|
||||||
input : new URL(input.url);
|
? input
|
||||||
|
: new URL(input.url);
|
||||||
|
|
||||||
if (init?.body && !init.method) {
|
if (init?.body && !init.method) {
|
||||||
init.method = 'POST';
|
init.method = 'POST';
|
||||||
@ -97,7 +114,7 @@ export default async (win_: BrowserWindow) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return net.fetch(request, init);
|
return net.fetch(request, init);
|
||||||
}
|
}) as typeof fetch,
|
||||||
});
|
});
|
||||||
ipcMain.on('download-song', (_, url: string) => downloadSong(url));
|
ipcMain.on('download-song', (_, url: string) => downloadSong(url));
|
||||||
ipcMain.on('video-src-changed', (_, data: GetPlayerResponse) => {
|
ipcMain.on('video-src-changed', (_, data: GetPlayerResponse) => {
|
||||||
@ -112,14 +129,14 @@ export async function downloadSong(
|
|||||||
url: string,
|
url: string,
|
||||||
playlistFolder: string | undefined = undefined,
|
playlistFolder: string | undefined = undefined,
|
||||||
trackId: string | undefined = undefined,
|
trackId: string | undefined = undefined,
|
||||||
increasePlaylistProgress: (value: number) => void = () => {
|
increasePlaylistProgress: (value: number) => void = () => {},
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
let resolvedName;
|
let resolvedName;
|
||||||
try {
|
try {
|
||||||
await downloadSongUnsafe(
|
await downloadSongUnsafe(
|
||||||
|
false,
|
||||||
url,
|
url,
|
||||||
(name: string) => resolvedName = name,
|
(name: string) => (resolvedName = name),
|
||||||
playlistFolder,
|
playlistFolder,
|
||||||
trackId,
|
trackId,
|
||||||
increasePlaylistProgress,
|
increasePlaylistProgress,
|
||||||
@ -129,8 +146,30 @@ export async function downloadSong(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function downloadSongFromId(
|
||||||
|
id: string,
|
||||||
|
playlistFolder: string | undefined = undefined,
|
||||||
|
trackId: string | undefined = undefined,
|
||||||
|
increasePlaylistProgress: (value: number) => void = () => {},
|
||||||
|
) {
|
||||||
|
let resolvedName;
|
||||||
|
try {
|
||||||
|
await downloadSongUnsafe(
|
||||||
|
true,
|
||||||
|
id,
|
||||||
|
(name: string) => (resolvedName = name),
|
||||||
|
playlistFolder,
|
||||||
|
trackId,
|
||||||
|
increasePlaylistProgress,
|
||||||
|
);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
sendError(error as Error, resolvedName || id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function downloadSongUnsafe(
|
async function downloadSongUnsafe(
|
||||||
url: string,
|
isId: boolean,
|
||||||
|
idOrUrl: string,
|
||||||
setName: (name: string) => void,
|
setName: (name: string) => void,
|
||||||
playlistFolder: string | undefined = undefined,
|
playlistFolder: string | undefined = undefined,
|
||||||
trackId: string | undefined = undefined,
|
trackId: string | undefined = undefined,
|
||||||
@ -147,8 +186,13 @@ async function downloadSongUnsafe(
|
|||||||
|
|
||||||
sendFeedback('Downloading...', 2);
|
sendFeedback('Downloading...', 2);
|
||||||
|
|
||||||
const id = getVideoId(url);
|
let id: string | null;
|
||||||
if (typeof id !== 'string') throw new Error('Video not found');
|
if (isId) {
|
||||||
|
id = idOrUrl;
|
||||||
|
} else {
|
||||||
|
id = getVideoId(idOrUrl);
|
||||||
|
if (typeof id !== 'string') throw new Error('Video not found');
|
||||||
|
}
|
||||||
|
|
||||||
let info: TrackInfo | VideoInfo = await yt.music.getInfo(id);
|
let info: TrackInfo | VideoInfo = await yt.music.getInfo(id);
|
||||||
|
|
||||||
@ -163,8 +207,8 @@ async function downloadSongUnsafe(
|
|||||||
|
|
||||||
metadata.trackId = trackId;
|
metadata.trackId = trackId;
|
||||||
|
|
||||||
const dir
|
const dir =
|
||||||
= playlistFolder || config.get('downloadFolder') || app.getPath('downloads');
|
playlistFolder || config.get('downloadFolder') || app.getPath('downloads');
|
||||||
const name = `${metadata.artist ? `${metadata.artist} - ` : ''}${
|
const name = `${metadata.artist ? `${metadata.artist} - ` : ''}${
|
||||||
metadata.title
|
metadata.title
|
||||||
}`;
|
}`;
|
||||||
@ -187,27 +231,22 @@ async function downloadSongUnsafe(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (playabilityStatus.status === 'UNPLAYABLE') {
|
if (playabilityStatus.status === 'UNPLAYABLE') {
|
||||||
const errorScreen = playabilityStatus.error_screen as PlayerErrorMessage | null;
|
const errorScreen =
|
||||||
|
playabilityStatus.error_screen as PlayerErrorMessage | null;
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`[${playabilityStatus.status}] ${errorScreen?.reason.text}: ${errorScreen?.subreason.text}`,
|
`[${playabilityStatus.status}] ${errorScreen?.reason.text}: ${errorScreen?.subreason.text}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const preset = config.get('preset') ?? 'mp3';
|
const selectedPreset = config.get('selectedPreset') ?? 'mp3 (256kbps)';
|
||||||
let presetSetting: { extension: string; ffmpegArgs: string[] } | null = null;
|
let presetSetting: Preset;
|
||||||
if (preset === 'opus') {
|
if (selectedPreset === 'Custom') {
|
||||||
presetSetting = presets[preset];
|
presetSetting =
|
||||||
}
|
config.get('customPresetSetting') ?? DefaultPresetList['Custom'];
|
||||||
|
} else if (selectedPreset === 'Source') {
|
||||||
const filename = filenamify(`${name}.${presetSetting?.extension ?? 'mp3'}`, {
|
presetSetting = DefaultPresetList['Source'];
|
||||||
replacement: '_',
|
} else {
|
||||||
maxLength: 255,
|
presetSetting = DefaultPresetList['mp3 (256kbps)'];
|
||||||
});
|
|
||||||
const filePath = join(dir, filename);
|
|
||||||
|
|
||||||
if (config.get('skipExisting') && existsSync(filePath)) {
|
|
||||||
sendFeedback(null, -1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadOptions: FormatOptions = {
|
const downloadOptions: FormatOptions = {
|
||||||
@ -217,6 +256,30 @@ async function downloadSongUnsafe(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const format = info.chooseFormat(downloadOptions);
|
const format = info.chooseFormat(downloadOptions);
|
||||||
|
|
||||||
|
let targetFileExtension: string;
|
||||||
|
if (!presetSetting?.extension) {
|
||||||
|
targetFileExtension =
|
||||||
|
YoutubeFormatList.find((it) => it.itag === format.itag)?.container ??
|
||||||
|
'mp3';
|
||||||
|
} else {
|
||||||
|
targetFileExtension = presetSetting?.extension ?? 'mp3';
|
||||||
|
}
|
||||||
|
|
||||||
|
let filename = filenamify(`${name}.${targetFileExtension}`, {
|
||||||
|
replacement: '_',
|
||||||
|
maxLength: 255,
|
||||||
|
});
|
||||||
|
if (!is.macOS()) {
|
||||||
|
filename = filename.normalize('NFC');
|
||||||
|
}
|
||||||
|
const filePath = join(dir, filename);
|
||||||
|
|
||||||
|
if (config.get('skipExisting') && existsSync(filePath)) {
|
||||||
|
sendFeedback(null, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const stream = await info.download(downloadOptions);
|
const stream = await info.download(downloadOptions);
|
||||||
|
|
||||||
console.info(
|
console.info(
|
||||||
@ -229,40 +292,25 @@ async function downloadSongUnsafe(
|
|||||||
mkdirSync(dir);
|
mkdirSync(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ffmpegArgs = config.get('ffmpegArgs');
|
const fileBuffer = await iterableStreamToTargetFile(
|
||||||
|
iterableStream,
|
||||||
|
targetFileExtension,
|
||||||
|
metadata,
|
||||||
|
presetSetting?.ffmpegArgs ?? [],
|
||||||
|
format.content_length ?? 0,
|
||||||
|
sendFeedback,
|
||||||
|
increasePlaylistProgress,
|
||||||
|
);
|
||||||
|
|
||||||
if (presetSetting && presetSetting?.extension !== 'mp3') {
|
if (fileBuffer) {
|
||||||
const file = createWriteStream(filePath);
|
if (targetFileExtension !== 'mp3') {
|
||||||
let downloaded = 0;
|
createWriteStream(filePath).write(fileBuffer);
|
||||||
const total: number = format.content_length ?? 1;
|
} else {
|
||||||
|
const buffer = await writeID3(
|
||||||
for await (const chunk of iterableStream) {
|
Buffer.from(fileBuffer),
|
||||||
downloaded += chunk.length;
|
metadata,
|
||||||
const ratio = downloaded / total;
|
sendFeedback,
|
||||||
const progress = Math.floor(ratio * 100);
|
);
|
||||||
sendFeedback(`Download: ${progress}%`, ratio);
|
|
||||||
increasePlaylistProgress(ratio);
|
|
||||||
file.write(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
await ffmpegWriteTags(
|
|
||||||
filePath,
|
|
||||||
metadata,
|
|
||||||
presetSetting.ffmpegArgs,
|
|
||||||
ffmpegArgs,
|
|
||||||
);
|
|
||||||
sendFeedback(null, -1);
|
|
||||||
} else {
|
|
||||||
const fileBuffer = await iterableStreamToMP3(
|
|
||||||
iterableStream,
|
|
||||||
metadata,
|
|
||||||
ffmpegArgs,
|
|
||||||
format.content_length ?? 0,
|
|
||||||
sendFeedback,
|
|
||||||
increasePlaylistProgress,
|
|
||||||
);
|
|
||||||
if (fileBuffer) {
|
|
||||||
const buffer = await writeID3(Buffer.from(fileBuffer), metadata, sendFeedback);
|
|
||||||
if (buffer) {
|
if (buffer) {
|
||||||
writeFileSync(filePath, buffer);
|
writeFileSync(filePath, buffer);
|
||||||
}
|
}
|
||||||
@ -273,14 +321,14 @@ async function downloadSongUnsafe(
|
|||||||
console.info(`Done: "${filePath}"`);
|
console.info(`Done: "${filePath}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function iterableStreamToMP3(
|
async function iterableStreamToTargetFile(
|
||||||
stream: AsyncGenerator<Uint8Array, void>,
|
stream: AsyncGenerator<Uint8Array, void>,
|
||||||
|
extension: string,
|
||||||
metadata: CustomSongInfo,
|
metadata: CustomSongInfo,
|
||||||
ffmpegArgs: string[],
|
presetFfmpegArgs: string[],
|
||||||
contentLength: number,
|
contentLength: number,
|
||||||
sendFeedback: (str: string, value?: number) => void,
|
sendFeedback: (str: string, value?: number) => void,
|
||||||
increasePlaylistProgress: (value: number) => void = () => {
|
increasePlaylistProgress: (value: number) => void = () => {},
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
let downloaded = 0;
|
let downloaded = 0;
|
||||||
@ -316,13 +364,14 @@ async function iterableStreamToMP3(
|
|||||||
increasePlaylistProgress(0.15 + (ratio * 0.85));
|
increasePlaylistProgress(0.15 + (ratio * 0.85));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const safeVideoNameWithExtension = `${safeVideoName}.${extension}`;
|
||||||
try {
|
try {
|
||||||
await ffmpeg.run(
|
await ffmpeg.run(
|
||||||
'-i',
|
'-i',
|
||||||
safeVideoName,
|
safeVideoName,
|
||||||
...ffmpegArgs,
|
...presetFfmpegArgs,
|
||||||
...getFFmpegMetadataArgs(metadata),
|
...getFFmpegMetadataArgs(metadata),
|
||||||
`${safeVideoName}.mp3`,
|
safeVideoNameWithExtension,
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
ffmpeg.FS('unlink', safeVideoName);
|
ffmpeg.FS('unlink', safeVideoName);
|
||||||
@ -331,9 +380,9 @@ async function iterableStreamToMP3(
|
|||||||
sendFeedback('Saving…');
|
sendFeedback('Saving…');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return ffmpeg.FS('readFile', `${safeVideoName}.mp3`);
|
return ffmpeg.FS('readFile', safeVideoNameWithExtension);
|
||||||
} finally {
|
} finally {
|
||||||
ffmpeg.FS('unlink', `${safeVideoName}.mp3`);
|
ffmpeg.FS('unlink', safeVideoNameWithExtension);
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
sendError(error as Error, safeVideoName);
|
sendError(error as Error, safeVideoName);
|
||||||
@ -347,7 +396,11 @@ const getCoverBuffer = cache(async (url: string) => {
|
|||||||
return nativeImage && !nativeImage.isEmpty() ? nativeImage.toPNG() : null;
|
return nativeImage && !nativeImage.isEmpty() ? nativeImage.toPNG() : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
async function writeID3(buffer: Buffer, metadata: CustomSongInfo, sendFeedback: (str: string, value?: number) => void) {
|
async function writeID3(
|
||||||
|
buffer: Buffer,
|
||||||
|
metadata: CustomSongInfo,
|
||||||
|
sendFeedback: (str: string, value?: number) => void,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
sendFeedback('Writing ID3 tags...');
|
sendFeedback('Writing ID3 tags...');
|
||||||
const tags: NodeID3.Tags = {};
|
const tags: NodeID3.Tags = {};
|
||||||
@ -397,13 +450,12 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
|
|||||||
try {
|
try {
|
||||||
givenUrl = new URL(givenUrl ?? '');
|
givenUrl = new URL(givenUrl ?? '');
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
givenUrl = new URL(win.webContents.getURL());
|
||||||
}
|
}
|
||||||
|
|
||||||
const playlistId
|
const playlistId =
|
||||||
= getPlaylistID(givenUrl)
|
getPlaylistID(givenUrl) ||
|
||||||
|| getPlaylistID(new URL(win.webContents.getURL()))
|
getPlaylistID(new URL(playingUrl));
|
||||||
|| getPlaylistID(new URL(playingUrl));
|
|
||||||
|
|
||||||
if (!playlistId) {
|
if (!playlistId) {
|
||||||
sendError(new Error('No playlist ID found'));
|
sendError(new Error('No playlist ID found'));
|
||||||
@ -414,35 +466,56 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
|
|||||||
|
|
||||||
console.log(`trying to get playlist ID: '${playlistId}'`);
|
console.log(`trying to get playlist ID: '${playlistId}'`);
|
||||||
sendFeedback('Getting playlist info…');
|
sendFeedback('Getting playlist info…');
|
||||||
let playlist: ytpl.Result;
|
let playlist: Playlist;
|
||||||
|
const items: YTNodes.MusicResponsiveListItem[] = [];
|
||||||
try {
|
try {
|
||||||
playlist = await ytpl(playlistId, {
|
playlist = await yt.music.getPlaylist(playlistId);
|
||||||
limit: config.get('playlistMaxItems') || Number.POSITIVE_INFINITY,
|
if (playlist?.items) {
|
||||||
});
|
items.push(...playlist.items.as(YTNodes.MusicResponsiveListItem));
|
||||||
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
sendError(
|
sendError(
|
||||||
Error(`Error getting playlist info: make sure it isn't a private or "Mixed for you" playlist\n\n${String(error)}`),
|
Error(
|
||||||
|
`Error getting playlist info: make sure it isn't a private or "Mixed for you" playlist\n\n${String(
|
||||||
|
error,
|
||||||
|
)}`,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playlist.items.length === 0) {
|
if (!playlist || !playlist.items || playlist.items.length === 0) {
|
||||||
sendError(new Error('Playlist is empty'));
|
sendError(new Error('Playlist is empty'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playlist.items.length === 1) {
|
const normalPlaylistTitle = playlist.header?.title?.text;
|
||||||
|
const playlistTitle =
|
||||||
|
normalPlaylistTitle ??
|
||||||
|
playlist.page.contents_memo
|
||||||
|
?.get('MusicResponsiveListItemFlexColumn')
|
||||||
|
?.at(2)
|
||||||
|
?.as(YTNodes.MusicResponsiveListItemFlexColumn)?.title?.text ??
|
||||||
|
'NO_TITLE';
|
||||||
|
const isAlbum = !normalPlaylistTitle;
|
||||||
|
|
||||||
|
while (playlist.has_continuation) {
|
||||||
|
playlist = await playlist.getContinuation();
|
||||||
|
if (playlist?.items) {
|
||||||
|
items.push(...playlist.items.as(YTNodes.MusicResponsiveListItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items.length === 1) {
|
||||||
sendFeedback('Playlist has only one item, downloading it directly');
|
sendFeedback('Playlist has only one item, downloading it directly');
|
||||||
await downloadSong(playlist.items[0].url);
|
await downloadSongFromId(items.at(0)!.id!);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAlbum = playlist.title.startsWith('Album - ');
|
let safePlaylistTitle = filenamify(playlistTitle, { replacement: ' ' });
|
||||||
if (isAlbum) {
|
if (!is.macOS()) {
|
||||||
playlist.title = playlist.title.slice(8);
|
safePlaylistTitle = safePlaylistTitle.normalize('NFC');
|
||||||
}
|
}
|
||||||
|
|
||||||
const safePlaylistTitle = filenamify(playlist.title, { replacement: ' ' });
|
|
||||||
|
|
||||||
const folder = getFolder(config.get('downloadFolder') ?? '');
|
const folder = getFolder(config.get('downloadFolder') ?? '');
|
||||||
const playlistFolder = join(folder, safePlaylistTitle);
|
const playlistFolder = join(folder, safePlaylistTitle);
|
||||||
if (existsSync(playlistFolder)) {
|
if (existsSync(playlistFolder)) {
|
||||||
@ -458,47 +531,51 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
|
|||||||
type: 'info',
|
type: 'info',
|
||||||
buttons: ['OK'],
|
buttons: ['OK'],
|
||||||
title: 'Started Download',
|
title: 'Started Download',
|
||||||
message: `Downloading Playlist "${playlist.title}"`,
|
message: `Downloading Playlist "${playlistTitle}"`,
|
||||||
detail: `(${playlist.items.length} songs)`,
|
detail: `(${items.length} songs)`,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (is.dev()) {
|
if (is.dev()) {
|
||||||
console.log(
|
console.log(
|
||||||
`Downloading playlist "${playlist.title}" - ${playlist.items.length} songs (${playlistId})`,
|
`Downloading playlist "${playlistTitle}" - ${items.length} songs (${playlistId})`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
win.setProgressBar(2); // Starts with indefinite bar
|
win.setProgressBar(2); // Starts with indefinite bar
|
||||||
|
|
||||||
setBadge(playlist.items.length);
|
setBadge(items.length);
|
||||||
|
|
||||||
let counter = 1;
|
let counter = 1;
|
||||||
|
|
||||||
const progressStep = 1 / playlist.items.length;
|
const progressStep = 1 / items.length;
|
||||||
|
|
||||||
const increaseProgress = (itemPercentage: number) => {
|
const increaseProgress = (itemPercentage: number) => {
|
||||||
const currentProgress = (counter - 1) / (playlist.items.length ?? 1);
|
const currentProgress = (counter - 1) / (items.length ?? 1);
|
||||||
const newProgress = currentProgress + (progressStep * itemPercentage);
|
const newProgress = currentProgress + (progressStep * itemPercentage);
|
||||||
win.setProgressBar(newProgress);
|
win.setProgressBar(newProgress);
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const song of playlist.items) {
|
for (const song of items) {
|
||||||
sendFeedback(`Downloading ${counter}/${playlist.items.length}...`);
|
sendFeedback(`Downloading ${counter}/${items.length}...`);
|
||||||
const trackId = isAlbum ? counter : undefined;
|
const trackId = isAlbum ? counter : undefined;
|
||||||
await downloadSong(
|
await downloadSongFromId(
|
||||||
song.url,
|
song.id!,
|
||||||
playlistFolder,
|
playlistFolder,
|
||||||
trackId?.toString(),
|
trackId?.toString(),
|
||||||
increaseProgress,
|
increaseProgress,
|
||||||
).catch((error) =>
|
).catch((error) =>
|
||||||
sendError(
|
sendError(
|
||||||
new Error(`Error downloading "${song.author.name} - ${song.title}":\n ${error}`)
|
new Error(
|
||||||
|
`Error downloading "${
|
||||||
|
song.author!.name
|
||||||
|
} - ${song.title!}":\n ${error}`,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
win.setProgressBar(counter / playlist.items.length);
|
win.setProgressBar(counter / items.length);
|
||||||
setBadge(playlist.items.length - counter);
|
setBadge(items.length - counter);
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
@ -510,29 +587,6 @@ export async function downloadPlaylist(givenUrl?: string | URL) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ffmpegWriteTags(filePath: string, metadata: CustomSongInfo, presetFFmpegArgs: string[] = [], ffmpegArgs: string[] = []) {
|
|
||||||
const releaseFFmpegMutex = await ffmpegMutex.acquire();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!ffmpeg.isLoaded()) {
|
|
||||||
await ffmpeg.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
await ffmpeg.run(
|
|
||||||
'-i',
|
|
||||||
filePath,
|
|
||||||
...getFFmpegMetadataArgs(metadata),
|
|
||||||
...presetFFmpegArgs,
|
|
||||||
...ffmpegArgs,
|
|
||||||
filePath,
|
|
||||||
);
|
|
||||||
} catch (error: unknown) {
|
|
||||||
sendError(error as Error);
|
|
||||||
} finally {
|
|
||||||
releaseFFmpegMutex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFFmpegMetadataArgs(metadata: CustomSongInfo) {
|
function getFFmpegMetadataArgs(metadata: CustomSongInfo) {
|
||||||
if (!metadata) {
|
if (!metadata) {
|
||||||
return [];
|
return [];
|
||||||
@ -549,9 +603,9 @@ function getFFmpegMetadataArgs(metadata: CustomSongInfo) {
|
|||||||
// Playlist radio modifier needs to be cut from playlist ID
|
// Playlist radio modifier needs to be cut from playlist ID
|
||||||
const INVALID_PLAYLIST_MODIFIER = 'RDAMPL';
|
const INVALID_PLAYLIST_MODIFIER = 'RDAMPL';
|
||||||
|
|
||||||
const getPlaylistID = (aURL: URL) => {
|
const getPlaylistID = (aURL?: URL): string | null | undefined => {
|
||||||
const result
|
const result =
|
||||||
= aURL?.searchParams.get('list') || aURL?.searchParams.get('playlist');
|
aURL?.searchParams.get('list') || aURL?.searchParams.get('playlist');
|
||||||
if (result?.startsWith(INVALID_PLAYLIST_MODIFIER)) {
|
if (result?.startsWith(INVALID_PLAYLIST_MODIFIER)) {
|
||||||
return result.slice(INVALID_PLAYLIST_MODIFIER.length);
|
return result.slice(INVALID_PLAYLIST_MODIFIER.length);
|
||||||
}
|
}
|
||||||
@ -560,16 +614,18 @@ const getPlaylistID = (aURL: URL) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getVideoId = (url: URL | string): string | null => {
|
const getVideoId = (url: URL | string): string | null => {
|
||||||
return (new URL(url)).searchParams.get('v');
|
return new URL(url).searchParams.get('v');
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMetadata = (info: TrackInfo): CustomSongInfo => ({
|
const getMetadata = (info: TrackInfo): CustomSongInfo => ({
|
||||||
videoId: info.basic_info.id!,
|
videoId: info.basic_info.id!,
|
||||||
title: cleanupName(info.basic_info.title!),
|
title: cleanupName(info.basic_info.title!),
|
||||||
artist: cleanupName(info.basic_info.author!),
|
artist: cleanupName(info.basic_info.author!),
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-explicit-any
|
album: info.player_overlays?.browser_media_session?.as(
|
||||||
album: (info.player_overlays?.browser_media_session as any)?.album?.text as string | undefined,
|
YTNodes.BrowserMediaSession,
|
||||||
imageSrc: info.basic_info.thumbnail?.find((t) => !t.url.endsWith('.webp'))?.url,
|
).album?.text,
|
||||||
|
imageSrc: info.basic_info.thumbnail?.find((t) => !t.url.endsWith('.webp'))
|
||||||
|
?.url,
|
||||||
views: info.basic_info.view_count!,
|
views: info.basic_info.view_count!,
|
||||||
songDuration: info.basic_info.duration!,
|
songDuration: info.basic_info.duration!,
|
||||||
});
|
});
|
||||||
@ -47,7 +47,7 @@ const menuObserver = new MutationObserver(() => {
|
|||||||
(global as any).download = () => {
|
(global as any).download = () => {
|
||||||
let videoUrl = getSongMenu()
|
let videoUrl = getSongMenu()
|
||||||
// Selector of first button which is always "Start Radio"
|
// Selector of first button which is always "Start Radio"
|
||||||
?.querySelector('ytmusic-menu-navigation-item-renderer[tabindex="0"] #navigation-endpoint')
|
?.querySelector('ytmusic-menu-navigation-item-renderer[tabindex="-1"] #navigation-endpoint')
|
||||||
?.getAttribute('href');
|
?.getAttribute('href');
|
||||||
if (videoUrl) {
|
if (videoUrl) {
|
||||||
if (videoUrl.startsWith('watch?')) {
|
if (videoUrl.startsWith('watch?')) {
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { dialog } from 'electron';
|
import { dialog } from 'electron';
|
||||||
|
|
||||||
import { downloadPlaylist } from './back';
|
import { downloadPlaylist } from './back';
|
||||||
import { defaultMenuDownloadLabel, getFolder, presets } from './utils';
|
import { defaultMenuDownloadLabel, getFolder } from './utils';
|
||||||
|
import { DefaultPresetList } from './types';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
|
|
||||||
import { MenuTemplate } from '../../menu';
|
import { MenuTemplate } from '../../menu';
|
||||||
@ -25,12 +26,12 @@ export default (): MenuTemplate => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Presets',
|
label: 'Presets',
|
||||||
submenu: Object.keys(presets).map((preset) => ({
|
submenu: Object.keys(DefaultPresetList).map((preset) => ({
|
||||||
label: preset,
|
label: preset,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
checked: config.get('preset') === preset,
|
checked: config.get('selectedPreset') === preset,
|
||||||
click() {
|
click() {
|
||||||
config.set('preset', preset);
|
config.set('selectedPreset', preset);
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
116
src/plugins/downloader/types.ts
Normal file
116
src/plugins/downloader/types.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
export interface Preset {
|
||||||
|
extension?: string | null;
|
||||||
|
ffmpegArgs: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Presets for FFmpeg
|
||||||
|
export const DefaultPresetList: Record<string, Preset> = {
|
||||||
|
'mp3 (256kbps)': {
|
||||||
|
extension: 'mp3',
|
||||||
|
ffmpegArgs: ['-b:a', '256k'],
|
||||||
|
},
|
||||||
|
'Source': {
|
||||||
|
extension: undefined,
|
||||||
|
ffmpegArgs: ['-acodec', 'copy'],
|
||||||
|
},
|
||||||
|
'Custom': {
|
||||||
|
extension: null,
|
||||||
|
ffmpegArgs: [],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface YouTubeFormat {
|
||||||
|
itag: number;
|
||||||
|
container: string;
|
||||||
|
content: string;
|
||||||
|
resolution: string;
|
||||||
|
bitrate: string;
|
||||||
|
range: string;
|
||||||
|
vrOr3D: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// converted from https://gist.github.com/sidneys/7095afe4da4ae58694d128b1034e01e2#file-youtube_format_code_itag_list-md
|
||||||
|
export const YoutubeFormatList: YouTubeFormat[] = [
|
||||||
|
{ itag: 5, container: 'flv', content: 'audio/video', resolution: '240p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 6, container: 'flv', content: 'audio/video', resolution: '270p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 17, container: '3gp', content: 'audio/video', resolution: '144p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 18, container: 'mp4', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 22, container: 'mp4', content: 'audio/video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 34, container: 'flv', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 35, container: 'flv', content: 'audio/video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 36, container: '3gp', content: 'audio/video', resolution: '180p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 37, container: 'mp4', content: 'audio/video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 38, container: 'mp4', content: 'audio/video', resolution: '3072p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 43, container: 'webm', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 44, container: 'webm', content: 'audio/video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 45, container: 'webm', content: 'audio/video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 46, container: 'webm', content: 'audio/video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 82, container: 'mp4', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 83, container: 'mp4', content: 'audio/video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 84, container: 'mp4', content: 'audio/video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 85, container: 'mp4', content: 'audio/video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 91, container: 'hls', content: 'audio/video', resolution: '144p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 92, container: 'hls', content: 'audio/video', resolution: '240p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 93, container: 'hls', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 94, container: 'hls', content: 'audio/video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 95, container: 'hls', content: 'audio/video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 96, container: 'hls', content: 'audio/video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '-' },
|
||||||
|
{ itag: 100, container: 'webm', content: 'audio/video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 101, container: 'webm', content: 'audio/video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 102, container: 'webm', content: 'audio/video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '3D' },
|
||||||
|
{ itag: 132, container: 'hls', content: 'audio/video', resolution: '240p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 133, container: 'mp4', content: 'video', resolution: '240p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 134, container: 'mp4', content: 'video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 135, container: 'mp4', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 136, container: 'mp4', content: 'video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 137, container: 'mp4', content: 'video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 138, container: 'mp4', content: 'video', resolution: '2160p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 139, container: 'm4a', content: 'audio', resolution: '-', bitrate: '48k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 140, container: 'm4a', content: 'audio', resolution: '-', bitrate: '128k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 141, container: 'm4a', content: 'audio', resolution: '-', bitrate: '256k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 151, container: 'hls', content: 'audio/video', resolution: '72p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 160, container: 'mp4', content: 'video', resolution: '144p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 167, container: 'webm', content: 'video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 168, container: 'webm', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 169, container: 'webm', content: 'video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 171, container: 'webm', content: 'audio', resolution: '-', bitrate: '128k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 218, container: 'webm', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 219, container: 'webm', content: 'video', resolution: '144p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 242, container: 'webm', content: 'video', resolution: '240p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 243, container: 'webm', content: 'video', resolution: '360p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 244, container: 'webm', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 245, container: 'webm', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 246, container: 'webm', content: 'video', resolution: '480p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 247, container: 'webm', content: 'video', resolution: '720p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 248, container: 'webm', content: 'video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 249, container: 'webm', content: 'audio', resolution: '-', bitrate: '50k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 250, container: 'webm', content: 'audio', resolution: '-', bitrate: '70k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 251, container: 'webm', content: 'audio', resolution: '-', bitrate: '160k', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 264, container: 'mp4', content: 'video', resolution: '1440p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 266, container: 'mp4', content: 'video', resolution: '2160p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 271, container: 'webm', content: 'video', resolution: '1440p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 272, container: 'webm', content: 'video', resolution: '4320p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 278, container: 'webm', content: 'video', resolution: '144p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 298, container: 'mp4', content: 'video', resolution: '720p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 299, container: 'mp4', content: 'video', resolution: '1080p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 302, container: 'webm', content: 'video', resolution: '720p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 303, container: 'webm', content: 'video', resolution: '1080p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 308, container: 'webm', content: 'video', resolution: '1440p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 313, container: 'webm', content: 'video', resolution: '2160p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 315, container: 'webm', content: 'video', resolution: '2160p60', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 330, container: 'webm', content: 'video', resolution: '144p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 331, container: 'webm', content: 'video', resolution: '240p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 332, container: 'webm', content: 'video', resolution: '360p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 333, container: 'webm', content: 'video', resolution: '480p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 334, container: 'webm', content: 'video', resolution: '720p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 335, container: 'webm', content: 'video', resolution: '1080p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 336, container: 'webm', content: 'video', resolution: '1440p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 337, container: 'webm', content: 'video', resolution: '2160p60', bitrate: '-', range: 'hdr', vrOr3D: '' },
|
||||||
|
{ itag: 272, container: 'webm', content: 'video', resolution: '2880p/4320p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 399, container: 'mp4', content: 'video', resolution: '1080p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 400, container: 'mp4', content: 'video', resolution: '1440p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 401, container: 'mp4', content: 'video', resolution: '2160p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 402, container: 'mp4', content: 'video', resolution: '2880p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 571, container: 'mp4', content: 'video', resolution: '3840p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
{ itag: 702, container: 'mp4', content: 'video', resolution: '3840p', bitrate: '-', range: '-', vrOr3D: '' },
|
||||||
|
];
|
||||||
@ -10,7 +10,7 @@ export const sendFeedback = (win: BrowserWindow, message?: unknown) => {
|
|||||||
|
|
||||||
export const cropMaxWidth = (image: Electron.NativeImage) => {
|
export const cropMaxWidth = (image: Electron.NativeImage) => {
|
||||||
const imageSize = image.getSize();
|
const imageSize = image.getSize();
|
||||||
// Standart youtube artwork width with margins from both sides is 280 + 720 + 280
|
// Standart YouTube artwork width with margins from both sides is 280 + 720 + 280
|
||||||
if (imageSize.width === 1280 && imageSize.height === 720) {
|
if (imageSize.width === 1280 && imageSize.height === 720) {
|
||||||
return image.crop({
|
return image.crop({
|
||||||
x: 280,
|
x: 280,
|
||||||
@ -23,15 +23,6 @@ export const cropMaxWidth = (image: Electron.NativeImage) => {
|
|||||||
return image;
|
return image;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Presets for FFmpeg
|
|
||||||
export const presets = {
|
|
||||||
'None (defaults to mp3)': undefined,
|
|
||||||
'opus': {
|
|
||||||
extension: 'opus',
|
|
||||||
ffmpegArgs: ['-acodec', 'libopus'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setBadge = (n: number) => {
|
export const setBadge = (n: number) => {
|
||||||
if (is.linux() || is.macOS()) {
|
if (is.linux() || is.macOS()) {
|
||||||
app.setBadgeCount(n);
|
app.setBadgeCount(n);
|
||||||
112
src/plugins/http-api/back.ts
Normal file
112
src/plugins/http-api/back.ts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import http from 'node:http';
|
||||||
|
|
||||||
|
import { BrowserWindow, ipcMain } from 'electron';
|
||||||
|
import is from 'electron-is';
|
||||||
|
|
||||||
|
import registerCallback, { SongInfo } from '../../providers/song-info';
|
||||||
|
import getSongControls from '../../providers/song-controls';
|
||||||
|
import { isEnabled } from '../../config/plugins';
|
||||||
|
|
||||||
|
const port = 9669; // Choose a port number
|
||||||
|
|
||||||
|
export default (win: BrowserWindow) => {
|
||||||
|
let songInfo: (SongInfo & { loopStatus?: string, volume?: number }) | undefined;
|
||||||
|
|
||||||
|
if (!is.linux() || (is.linux() && !isEnabled('shortcuts'))) {
|
||||||
|
ipcMain.on('apiLoaded', () => {
|
||||||
|
win.webContents.send('setupSeekedListener', 'webinterface');
|
||||||
|
win.webContents.send('setupTimeChangedListener', 'webinterface');
|
||||||
|
win.webContents.send('setupRepeatChangedListener', 'webinterface');
|
||||||
|
win.webContents.send('setupVolumeChangedListener', 'webinterface');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// updations
|
||||||
|
ipcMain.on('seeked', (_, t: number) => {
|
||||||
|
if (songInfo) {
|
||||||
|
songInfo.elapsedSeconds = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('timeChanged', (_, t: number) => {
|
||||||
|
if (songInfo) {
|
||||||
|
songInfo.elapsedSeconds = t;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('repeatChanged', (_, mode: string) => {
|
||||||
|
if (songInfo) {
|
||||||
|
songInfo.loopStatus = mode;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('volumeChanged', (_, newVolume: number) => {
|
||||||
|
if(songInfo) {
|
||||||
|
songInfo.volume = newVolume;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
registerCallback((info) => songInfo = info as SongInfo & { loopStatus?: string, volume?: number });
|
||||||
|
|
||||||
|
const doAction = (action: URLSearchParams) => {
|
||||||
|
//actions
|
||||||
|
const songControls = getSongControls(win);
|
||||||
|
const { playPause, next, previous, volumeMinus10, volumePlus10, shuffle } = songControls;
|
||||||
|
switch (action.get('action')) {
|
||||||
|
case 'play':
|
||||||
|
case 'pause':
|
||||||
|
case 'playpause':
|
||||||
|
if (songInfo) {
|
||||||
|
songInfo.isPaused = !songInfo.isPaused;
|
||||||
|
}
|
||||||
|
playPause();
|
||||||
|
break;
|
||||||
|
case 'next':
|
||||||
|
next();
|
||||||
|
break;
|
||||||
|
case 'previous':
|
||||||
|
previous();
|
||||||
|
break;
|
||||||
|
case 'shuffle':
|
||||||
|
shuffle();
|
||||||
|
break;
|
||||||
|
case 'looptoggle':
|
||||||
|
songControls.switchRepeat(1);
|
||||||
|
break;
|
||||||
|
case 'volumeplus10':
|
||||||
|
volumePlus10();
|
||||||
|
break;
|
||||||
|
case 'volumeminus10':
|
||||||
|
volumeMinus10();
|
||||||
|
break;
|
||||||
|
case 'seek':
|
||||||
|
console.log('seek', action.get('value'));
|
||||||
|
win.webContents.send('seekTo', action.get('value'));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Error(`web-interface: Requested action "${action.get('action')}" not found`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const server = http.createServer((req,res) => {
|
||||||
|
if (req?.url?.slice(0,4) === '/api') {
|
||||||
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
||||||
|
if (url.searchParams.has('action')) {
|
||||||
|
console.log('webinterface: received and trying action ' + url.searchParams.get('action'));
|
||||||
|
try {
|
||||||
|
doAction(url.searchParams);
|
||||||
|
} catch (e) {
|
||||||
|
res.statusCode = 404;
|
||||||
|
res.write(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.setHeader('Content-Type','application/json');
|
||||||
|
res.write(JSON.stringify(songInfo));
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log(`web-interface API Server is running on port ${port}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
3
src/plugins/in-app-menu/assets/close.svg
Normal file
3
src/plugins/in-app-menu/assets/close.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="m4.21 4.387.083-.094a1 1 0 0 1 1.32-.083l.094.083L12 10.585l6.293-6.292a1 1 0 1 1 1.414 1.414L13.415 12l6.292 6.293a1 1 0 0 1 .083 1.32l-.083.094a1 1 0 0 1-1.32.083l-.094-.083L12 13.415l-6.293 6.292a1 1 0 0 1-1.414-1.414L10.585 12 4.293 5.707a1 1 0 0 1-.083-1.32l.083-.094-.083.094Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 392 B |
3
src/plugins/in-app-menu/assets/maximize.svg
Normal file
3
src/plugins/in-app-menu/assets/maximize.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M6 3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3Zm0 2a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 252 B |
|
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 338 B |
3
src/plugins/in-app-menu/assets/minimize.svg
Normal file
3
src/plugins/in-app-menu/assets/minimize.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M3.755 12.5h16.492a.75.75 0 0 0 0-1.5H3.755a.75.75 0 0 0 0 1.5Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 174 B |
3
src/plugins/in-app-menu/assets/unmaximize.svg
Normal file
3
src/plugins/in-app-menu/assets/unmaximize.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#ffffff" d="M7.518 5H6.009a3.25 3.25 0 0 1 3.24-3h8.001A4.75 4.75 0 0 1 22 6.75v8a3.25 3.25 0 0 1-3 3.24v-1.508a1.75 1.75 0 0 0 1.5-1.732v-8a3.25 3.25 0 0 0-3.25-3.25h-8A1.75 1.75 0 0 0 7.518 5ZM5.25 6A3.25 3.25 0 0 0 2 9.25v9.5A3.25 3.25 0 0 0 5.25 22h9.5A3.25 3.25 0 0 0 18 18.75v-9.5A3.25 3.25 0 0 0 14.75 6h-9.5ZM3.5 9.25c0-.966.784-1.75 1.75-1.75h9.5c.967 0 1.75.784 1.75 1.75v9.5a1.75 1.75 0 0 1-1.75 1.75h-9.5a1.75 1.75 0 0 1-1.75-1.75v-9.5Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 546 B |
@ -1,5 +1,3 @@
|
|||||||
import path from 'node:path';
|
|
||||||
|
|
||||||
import { register } from 'electron-localshortcut';
|
import { register } from 'electron-localshortcut';
|
||||||
|
|
||||||
import { BrowserWindow, Menu, MenuItem, ipcMain } from 'electron';
|
import { BrowserWindow, Menu, MenuItem, ipcMain } from 'electron';
|
||||||
@ -25,7 +23,7 @@ export default (win: BrowserWindow) => {
|
|||||||
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const getMenuItemById = (commandId: number): MenuItem | null => {
|
const getMenuItemById = (commandId: number): MenuItem | null => {
|
||||||
const menu = Menu.getApplicationMenu();
|
const menu = Menu.getApplicationMenu();
|
||||||
|
|
||||||
@ -40,7 +38,7 @@ export default (win: BrowserWindow) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,4 +55,13 @@ export default (win: BrowserWindow) => {
|
|||||||
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('window-is-maximized', () => win.isMaximized());
|
||||||
|
|
||||||
|
ipcMain.handle('window-close', () => win.close());
|
||||||
|
ipcMain.handle('window-minimize', () => win.minimize());
|
||||||
|
ipcMain.handle('window-maximize', () => win.maximize());
|
||||||
|
win.on('maximize', () => win.webContents.send('window-maximize'));
|
||||||
|
ipcMain.handle('window-unmaximize', () => win.unmaximize());
|
||||||
|
win.on('unmaximize', () => win.webContents.send('window-unmaximize'));
|
||||||
};
|
};
|
||||||
168
src/plugins/in-app-menu/front.ts
Normal file
168
src/plugins/in-app-menu/front.ts
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import { ipcRenderer, Menu } from 'electron';
|
||||||
|
|
||||||
|
import { createPanel } from './menu/panel';
|
||||||
|
|
||||||
|
import logo from './assets/menu.svg';
|
||||||
|
import close from './assets/close.svg';
|
||||||
|
import minimize from './assets/minimize.svg';
|
||||||
|
import maximize from './assets/maximize.svg';
|
||||||
|
import unmaximize from './assets/unmaximize.svg';
|
||||||
|
|
||||||
|
import { isEnabled } from '../../config/plugins';
|
||||||
|
import config from '../../config';
|
||||||
|
|
||||||
|
function $<E extends Element = Element>(selector: string) {
|
||||||
|
return document.querySelector<E>(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isMacOS = navigator.userAgent.includes('Macintosh');
|
||||||
|
const isNotWindowsOrMacOS = !navigator.userAgent.includes('Windows') && !isMacOS;
|
||||||
|
|
||||||
|
export default async () => {
|
||||||
|
const hideDOMWindowControls = config.get('plugins.in-app-menu.hideDOMWindowControls');
|
||||||
|
let hideMenu = config.get('options.hideMenu');
|
||||||
|
const titleBar = document.createElement('title-bar');
|
||||||
|
const navBar = document.querySelector<HTMLDivElement>('#nav-bar-background');
|
||||||
|
let maximizeButton: HTMLButtonElement;
|
||||||
|
if (isMacOS) titleBar.style.setProperty('--offset-left', '70px');
|
||||||
|
|
||||||
|
logo.classList.add('title-bar-icon');
|
||||||
|
const logoClick = () => {
|
||||||
|
hideMenu = !hideMenu;
|
||||||
|
let visibilityStyle: string;
|
||||||
|
if (hideMenu) {
|
||||||
|
visibilityStyle = 'hidden';
|
||||||
|
} else {
|
||||||
|
visibilityStyle = 'visible';
|
||||||
|
}
|
||||||
|
const menus = document.querySelectorAll<HTMLElement>('menu-button');
|
||||||
|
menus.forEach((menu) => {
|
||||||
|
menu.style.visibility = visibilityStyle;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
logo.onclick = logoClick;
|
||||||
|
|
||||||
|
ipcRenderer.on('toggleMenu', logoClick);
|
||||||
|
|
||||||
|
if (!isMacOS) titleBar.appendChild(logo);
|
||||||
|
document.body.appendChild(titleBar);
|
||||||
|
|
||||||
|
titleBar.appendChild(logo);
|
||||||
|
|
||||||
|
const addWindowControls = async () => {
|
||||||
|
|
||||||
|
// Create window control buttons
|
||||||
|
const minimizeButton = document.createElement('button');
|
||||||
|
minimizeButton.classList.add('window-control');
|
||||||
|
minimizeButton.appendChild(minimize);
|
||||||
|
minimizeButton.onclick = () => ipcRenderer.invoke('window-minimize');
|
||||||
|
|
||||||
|
maximizeButton = document.createElement('button');
|
||||||
|
if (await ipcRenderer.invoke('window-is-maximized')) {
|
||||||
|
maximizeButton.classList.add('window-control');
|
||||||
|
maximizeButton.appendChild(unmaximize);
|
||||||
|
} else {
|
||||||
|
maximizeButton.classList.add('window-control');
|
||||||
|
maximizeButton.appendChild(maximize);
|
||||||
|
}
|
||||||
|
maximizeButton.onclick = async () => {
|
||||||
|
if (await ipcRenderer.invoke('window-is-maximized')) {
|
||||||
|
// change icon to maximize
|
||||||
|
maximizeButton.removeChild(maximizeButton.firstChild!);
|
||||||
|
maximizeButton.appendChild(maximize);
|
||||||
|
|
||||||
|
// call unmaximize
|
||||||
|
await ipcRenderer.invoke('window-unmaximize');
|
||||||
|
} else {
|
||||||
|
// change icon to unmaximize
|
||||||
|
maximizeButton.removeChild(maximizeButton.firstChild!);
|
||||||
|
maximizeButton.appendChild(unmaximize);
|
||||||
|
|
||||||
|
// call maximize
|
||||||
|
await ipcRenderer.invoke('window-maximize');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeButton = document.createElement('button');
|
||||||
|
closeButton.classList.add('window-control');
|
||||||
|
closeButton.appendChild(close);
|
||||||
|
closeButton.onclick = () => ipcRenderer.invoke('window-close');
|
||||||
|
|
||||||
|
// Create a container div for the window control buttons
|
||||||
|
const windowControlsContainer = document.createElement('div');
|
||||||
|
windowControlsContainer.classList.add('window-controls-container');
|
||||||
|
windowControlsContainer.appendChild(minimizeButton);
|
||||||
|
windowControlsContainer.appendChild(maximizeButton);
|
||||||
|
windowControlsContainer.appendChild(closeButton);
|
||||||
|
|
||||||
|
// Add window control buttons to the title bar
|
||||||
|
titleBar.appendChild(windowControlsContainer);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isNotWindowsOrMacOS && !hideDOMWindowControls) await addWindowControls();
|
||||||
|
|
||||||
|
if (navBar) {
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach(() => {
|
||||||
|
titleBar.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
||||||
|
document.querySelector('html')!.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(navBar, { attributes : true, attributeFilter : ['style'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMenu = async () => {
|
||||||
|
const children = [...titleBar.children];
|
||||||
|
children.forEach((child) => {
|
||||||
|
if (child !== logo) child.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
const menu = await ipcRenderer.invoke('get-menu') as Menu | null;
|
||||||
|
if (!menu) return;
|
||||||
|
|
||||||
|
menu.items.forEach((menuItem) => {
|
||||||
|
const menu = document.createElement('menu-button');
|
||||||
|
createPanel(titleBar, menu, menuItem.submenu?.items ?? []);
|
||||||
|
|
||||||
|
menu.append(menuItem.label);
|
||||||
|
titleBar.appendChild(menu);
|
||||||
|
if (hideMenu) {
|
||||||
|
menu.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (isNotWindowsOrMacOS && !hideDOMWindowControls) await addWindowControls();
|
||||||
|
};
|
||||||
|
await updateMenu();
|
||||||
|
|
||||||
|
document.title = 'Youtube Music';
|
||||||
|
|
||||||
|
ipcRenderer.on('refreshMenu', () => updateMenu());
|
||||||
|
ipcRenderer.on('window-maximize', () => {
|
||||||
|
if (isNotWindowsOrMacOS && !hideDOMWindowControls && maximizeButton.firstChild) {
|
||||||
|
maximizeButton.removeChild(maximizeButton.firstChild);
|
||||||
|
maximizeButton.appendChild(unmaximize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ipcRenderer.on('window-unmaximize', () => {
|
||||||
|
if (isNotWindowsOrMacOS && !hideDOMWindowControls && maximizeButton.firstChild) {
|
||||||
|
maximizeButton.removeChild(maximizeButton.firstChild);
|
||||||
|
maximizeButton.appendChild(unmaximize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isEnabled('picture-in-picture')) {
|
||||||
|
ipcRenderer.on('pip-toggle', () => {
|
||||||
|
updateMenu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increases the right margin of Navbar background when the scrollbar is visible to avoid blocking it (z-index doesn't affect it)
|
||||||
|
document.addEventListener('apiLoaded', () => {
|
||||||
|
const htmlHeadStyle = $('head > div > style');
|
||||||
|
if (htmlHeadStyle) {
|
||||||
|
// HACK: This is a hack to remove the scrollbar width
|
||||||
|
htmlHeadStyle.innerHTML = htmlHeadStyle.innerHTML.replace('html::-webkit-scrollbar {width: var(--ytmusic-scrollbar-width);', 'html::-webkit-scrollbar {');
|
||||||
|
}
|
||||||
|
}, { once: true, passive: true });
|
||||||
|
};
|
||||||
22
src/plugins/in-app-menu/menu.ts
Normal file
22
src/plugins/in-app-menu/menu.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { BrowserWindow } from 'electron';
|
||||||
|
|
||||||
|
import is from 'electron-is';
|
||||||
|
|
||||||
|
import { setMenuOptions } from '../../config/plugins';
|
||||||
|
|
||||||
|
import type { MenuTemplate } from '../../menu';
|
||||||
|
import type { ConfigType } from '../../config/dynamic';
|
||||||
|
|
||||||
|
export default (_: BrowserWindow, config: ConfigType<'in-app-menu'>): MenuTemplate => [
|
||||||
|
...(is.linux() ? [
|
||||||
|
{
|
||||||
|
label: 'Hide DOM Window Controls',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: config.hideDOMWindowControls,
|
||||||
|
click(item) {
|
||||||
|
config.hideDOMWindowControls = item.checked;
|
||||||
|
setMenuOptions('in-app-menu', config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] : []) satisfies Electron.MenuItemConstructorOptions[],
|
||||||
|
];
|
||||||
@ -101,6 +101,15 @@ export const createPanel = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
panel.setAttribute('open', 'true');
|
panel.setAttribute('open', 'true');
|
||||||
|
|
||||||
|
// Children are placed below their parent item, which can cause
|
||||||
|
// long lists to squeeze their children at the bottom of the screen
|
||||||
|
// (This needs to be done *after* setAttribute)
|
||||||
|
panel.classList.remove('position-by-bottom');
|
||||||
|
if (options.placement === 'right' && panel.scrollHeight > panel.clientHeight ) {
|
||||||
|
panel.style.setProperty('--y', `${rect.y + rect.height}px`);
|
||||||
|
panel.classList.add('position-by-bottom');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
anchor.addEventListener('click', () => {
|
anchor.addEventListener('click', () => {
|
||||||
@ -80,6 +80,11 @@ menu-panel[open="true"] {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
menu-panel.position-by-bottom {
|
||||||
|
top: unset;
|
||||||
|
bottom: calc(100vh - var(--y, 100%));
|
||||||
|
max-height: calc(var(--y, 0) - var(--menu-bar-height, 36px) - 16px);
|
||||||
|
}
|
||||||
|
|
||||||
menu-item {
|
menu-item {
|
||||||
-webkit-app-region: none;
|
-webkit-app-region: none;
|
||||||
@ -121,6 +126,33 @@ menu-separator {
|
|||||||
margin-left: -4px;
|
margin-left: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Window control container */
|
||||||
|
|
||||||
|
.window-controls-container {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end; /* Align to the right end of the title-bar */
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px; /* Add spacing between the window control buttons */
|
||||||
|
position: absolute; /* Position it absolutely within title-bar */
|
||||||
|
right: 4px; /* Adjust the right position as needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Window control buttons */
|
||||||
|
|
||||||
|
.window-control {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #f1f1f1;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* youtube-music style */
|
/* youtube-music style */
|
||||||
|
|
||||||
ytmusic-app-layout {
|
ytmusic-app-layout {
|
||||||
@ -15,11 +15,24 @@ interface LastFmData {
|
|||||||
timestamp?: number,
|
timestamp?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
const createFormData = (parameters: Record<string, unknown>) => {
|
interface LastFmSongData {
|
||||||
|
track?: string,
|
||||||
|
duration?: number,
|
||||||
|
artist?: string,
|
||||||
|
album?: string,
|
||||||
|
api_key: string,
|
||||||
|
sk?: string,
|
||||||
|
format: string,
|
||||||
|
method: string,
|
||||||
|
timestamp?: number,
|
||||||
|
api_sig?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const createFormData = (parameters: LastFmSongData) => {
|
||||||
// Creates the body for in the post request
|
// Creates the body for in the post request
|
||||||
const formData = new URLSearchParams();
|
const formData = new URLSearchParams();
|
||||||
for (const key in parameters) {
|
for (const key in parameters) {
|
||||||
formData.append(key, String(parameters[key]));
|
formData.append(key, String(parameters[key as keyof LastFmSongData]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
@ -36,7 +49,7 @@ const createQueryString = (parameters: Record<string, unknown>, apiSignature: st
|
|||||||
return '?' + queryData.join('&');
|
return '?' + queryData.join('&');
|
||||||
};
|
};
|
||||||
|
|
||||||
const createApiSig = (parameters: Record<string, unknown>, secret: string) => {
|
const createApiSig = (parameters: LastFmSongData, secret: string) => {
|
||||||
// This function creates the api signature, see: https://www.last.fm/api/authspec
|
// This function creates the api signature, see: https://www.last.fm/api/authspec
|
||||||
const keys = Object.keys(parameters);
|
const keys = Object.keys(parameters);
|
||||||
|
|
||||||
@ -47,7 +60,7 @@ const createApiSig = (parameters: Record<string, unknown>, secret: string) => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sig += `${key}${String(parameters[key])}`;
|
sig += `${key}${parameters[key as keyof LastFmSongData]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
sig += secret;
|
sig += secret;
|
||||||
@ -59,7 +72,7 @@ const createToken = async ({ api_key: apiKey, api_root: apiRoot, secret }: LastF
|
|||||||
// Creates and stores the auth token
|
// Creates and stores the auth token
|
||||||
const data = {
|
const data = {
|
||||||
method: 'auth.gettoken',
|
method: 'auth.gettoken',
|
||||||
apiKey,
|
api_key: apiKey,
|
||||||
format: 'json',
|
format: 'json',
|
||||||
};
|
};
|
||||||
const apiSigature = createApiSig(data, secret);
|
const apiSigature = createApiSig(data, secret);
|
||||||
@ -68,10 +81,9 @@ const createToken = async ({ api_key: apiKey, api_root: apiRoot, secret }: LastF
|
|||||||
return json?.token;
|
return json?.token;
|
||||||
};
|
};
|
||||||
|
|
||||||
const authenticateAndGetToken = async (config: LastFMOptions) => {
|
const authenticate = async (config: LastFMOptions) => {
|
||||||
// Asks the user for authentication
|
// Asks the user for authentication
|
||||||
await shell.openExternal(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`);
|
await shell.openExternal(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`);
|
||||||
return await createToken(config);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAndSetSessionKey = async (config: LastFMOptions) => {
|
const getAndSetSessionKey = async (config: LastFMOptions) => {
|
||||||
@ -86,18 +98,19 @@ const getAndSetSessionKey = async (config: LastFMOptions) => {
|
|||||||
const response = await net.fetch(`${config.api_root}${createQueryString(data, apiSignature)}`);
|
const response = await net.fetch(`${config.api_root}${createQueryString(data, apiSignature)}`);
|
||||||
const json = await response.json() as {
|
const json = await response.json() as {
|
||||||
error?: string,
|
error?: string,
|
||||||
session?: {
|
session?: {
|
||||||
key: string,
|
key: string,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (json.error) {
|
if (json.error) {
|
||||||
config.token = await authenticateAndGetToken(config);
|
config.token = await createToken(config);
|
||||||
|
await authenticate(config);
|
||||||
setOptions('last-fm', config);
|
setOptions('last-fm', config);
|
||||||
}
|
}
|
||||||
if (json.session) {
|
if (json.session) {
|
||||||
config.session_key = json?.session?.key;
|
config.session_key = json.session.key;
|
||||||
setOptions('last-fm', config);
|
|
||||||
}
|
}
|
||||||
|
setOptions('last-fm', config);
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,20 +120,20 @@ const postSongDataToAPI = async (songInfo: SongInfo, config: LastFMOptions, data
|
|||||||
await getAndSetSessionKey(config);
|
await getAndSetSessionKey(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
const postData = {
|
const postData: LastFmSongData = {
|
||||||
track: songInfo.title,
|
track: songInfo.title,
|
||||||
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.api_key,
|
api_key: config.api_key,
|
||||||
api_sig: '',
|
|
||||||
sk: config.session_key,
|
sk: config.session_key,
|
||||||
format: 'json',
|
format: 'json',
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
|
|
||||||
postData.api_sig = createApiSig(postData, config.secret);
|
postData.api_sig = createApiSig(postData, config.secret);
|
||||||
net.fetch('https://ws.audioscrobbler.com/2.0/', { method: 'POST', body: createFormData(postData) })
|
const formData = createFormData(postData);
|
||||||
|
net.fetch('https://ws.audioscrobbler.com/2.0/', { method: 'POST', body: formData })
|
||||||
.catch(async (error: {
|
.catch(async (error: {
|
||||||
response?: {
|
response?: {
|
||||||
data?: {
|
data?: {
|
||||||
@ -131,7 +144,8 @@ const postSongDataToAPI = async (songInfo: SongInfo, config: LastFMOptions, data
|
|||||||
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.session_key = undefined;
|
config.session_key = undefined;
|
||||||
config.token = await authenticateAndGetToken(config);
|
config.token = await createToken(config);
|
||||||
|
await authenticate(config);
|
||||||
setOptions('last-fm', config);
|
setOptions('last-fm', config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user