Compare commits

...

999 Commits

Author SHA1 Message Date
TC
f44b6f0c33 Bump version to 1.15.0 2021-12-30 19:39:20 +01:00
TC
c45e4e50fc Bump electron to 16.0.5 2021-12-30 19:39:03 +01:00
TC
9839a973f7 nit: re-format package.json 2021-12-30 19:35:53 +01:00
9ea967f03b Merge pull request #531 from th-ch/fix-tests
Switch from spectron to playwright to fix tests
2021-12-30 19:35:00 +01:00
TC
9d6765125b Switch from spectron to playwright to fix tests 2021-12-30 19:26:01 +01:00
TC
8d66735585 Add presets to FFmpeg in menu 2021-12-30 18:46:43 +01:00
14b4c55ce7 Merge pull request #529 from th-ch/snyk-upgrade-27f67e987dd094f8f1db19ad7f90c292
[Snyk] Upgrade @cliqz/adblocker-electron from 1.23.0 to 1.23.1
2021-12-30 17:59:53 +01:00
1d1f4bbcc3 Merge branch 'master' into snyk-upgrade-27f67e987dd094f8f1db19ad7f90c292 2021-12-30 17:59:34 +01:00
bd520c7eff Merge pull request #525 from Araxeus/fix-precise-volume-options-sync
fix precise-volume options sync
2021-12-30 17:57:13 +01:00
73e201bb2c Merge pull request #524 from MulverineX/patch-1
Add album art/thumbnail to discord activity
2021-12-30 15:10:07 +01:00
81b08917ae Merge pull request #521 from Araxeus/fix-skip-silences
fix skip-silences plugin
2021-12-30 15:08:56 +01:00
81c2ab34d9 Merge pull request #520 from th-ch/snyk-upgrade-7535be87da222abdba60d9fa36da34b5
[Snyk] Upgrade electron-updater from 4.6.2 to 4.6.3
2021-12-30 15:06:06 +01:00
TC
33faa2deb3 nit: improve comment for shared Array Buffer 2021-12-30 14:59:11 +01:00
TC
4d4ac56486 Ensure NODE_OPTIONS are unset in dev mode to avoid warning 2021-12-30 14:58:21 +01:00
56ac2b3b06 Merge pull request #515 from Araxeus/fix-useragents
update electron & remote & user agents
2021-12-30 14:57:36 +01:00
c72ea4bad5 fix: upgrade @cliqz/adblocker-electron from 1.23.0 to 1.23.1
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.23.0 to 1.23.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-12-27 20:52:46 +00:00
d60069555e Merge pull request #513 from markbaas/master
fixes mpris bug in snap
2021-12-27 16:12:40 +01:00
ed7025b4a2 fix precise-volume options sync 2021-12-24 02:13:21 +02:00
5fbc0f8122 Add album art/thumbnail to discord activity 2021-12-23 11:36:11 -07:00
02a989ca07 fix unnecessary skips 2021-12-18 21:03:32 +02:00
7c6fe6748e fix: upgrade electron-updater from 4.6.2 to 4.6.3
Snyk has created this PR to upgrade electron-updater from 4.6.2 to 4.6.3.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-12-18 11:02:24 +00:00
8f2ed3039a add comment to useragent fix 2021-12-16 19:29:09 +02:00
baeebd1959 downloader fixes
* --experimental-wasm-bulk-memory
* SharedArrayBuffer
* getFolder from front
* ytdl-core 4.9.2
2021-12-16 19:15:55 +02:00
49edbf723f fix custom-electron-prompt & remote 2021-12-16 18:28:49 +02:00
3764ce9a7c update custom-electron-titlebar 2021-12-16 18:01:11 +02:00
46943520bd Merge branch 'master' into fix-useragents 2021-12-15 19:32:14 +02:00
1048b3f99a Merge pull request #519 from th-ch/skip-silences-plugin
Add "Skip silences" plugin
2021-12-14 23:31:14 +01:00
TC
b1e40271e6 nit: re-order dependencies 2021-12-14 23:17:06 +01:00
TC
11429978c9 Add plugin to skip silences 2021-12-14 23:16:41 +01:00
47ca6e0b1f use session.webRequest.onBeforeSendHeaders for useragent 2021-12-14 19:22:02 +02:00
a273f6f73c fix video toggle button appearing when in song mode 2021-12-14 00:34:32 +02:00
c8ba85be76 use firefox as falllback useragent 2021-12-14 00:34:10 +02:00
6633243628 use @rozzzly/custom-electron-titlebar 2021-12-13 21:10:59 +02:00
2fb47933ac fix useragents 2021-12-13 21:06:52 +02:00
4fd683ed23 update electron & remote module 2021-12-13 20:10:36 +02:00
e1e9748002 always on useragent 2021-12-13 01:11:13 +02:00
dd122666c5 update useragents 2021-12-13 00:56:13 +02:00
5483f0ee36 Merge pull request #510 from MiepHD/master
Aligned lyric design
2021-12-10 21:15:36 +01:00
2c6c80d829 Merge pull request #509 from Araxeus/mpris-urgent-fix
Fix mpris bugs - follows #480
2021-12-10 21:14:31 +01:00
584d3e83c6 fixes mpris bug in snap 2021-12-10 20:52:16 +01:00
58d5256dd2 1vw would fit perfectly 2021-12-05 17:41:59 +01:00
920d61a1c6 Aligned lyric design
I aligned the lyric to the normal lyrics so that the lyric isn't that tiny
2021-12-04 20:53:19 +01:00
c5c2d5b74c Hide cast button which doesn't work 2021-12-03 16:56:51 +02:00
2daee01ff7 Fix bugs from bad merge conflict solving
-fix missing songControls
-use player.seeked directly
-fix 'seeked' event listener
-fix e.target instead of e.detail in apiLoaded event
-fix document.querySelector('video') before apiLoaded
-setup timeChange Listener if linux+shortcuts enabled
2021-12-03 15:55:40 +02:00
d13c9b7ca6 Merge pull request #476 from Araxeus/mix-fixes
Various small fixes (discord, video-toggle, precise-volume, playback-speed, shortcuts, lyrics)
2021-12-02 21:11:28 +01:00
5296a88525 Merge pull request #480 from Araxeus/mpris+tuna-fix
Mpris + obs-tuna fixes
2021-12-02 21:03:03 +01:00
8ce4b5b297 lint 2021-12-01 21:44:48 +02:00
2c39c0efed Merge branch 'master' into mpris+tuna-fix 2021-12-01 20:11:59 +02:00
e917abaec9 fix merge error 2021-12-01 00:08:55 +02:00
bdd0a2e8db Merge branch 'master' into mix-fixes 2021-12-01 00:06:15 +02:00
362003e10e Merge pull request #498 from th-ch/snyk-upgrade-9d2eea8c019b6593f1ef01f7fe8f404b
[Snyk] Upgrade node-fetch from 2.6.5 to 2.6.6
2021-11-30 00:16:34 +01:00
4e4b557413 Merge pull request #491 from Araxeus/fix-blur
fix interaction between blur navbar & in-app-menu
2021-11-30 00:14:49 +01:00
3a068af925 Merge pull request #475 from th-ch/snyk-upgrade-55c8a0f6d6911f431ebf75ad846e8f6c
[Snyk] Upgrade @cliqz/adblocker-electron from 1.22.7 to 1.23.0
2021-11-30 00:12:21 +01:00
44ca812330 Merge pull request #488 from Rubecks/exponential-volume-plugin
New Plugin: Exponential Volume
2021-11-30 00:10:48 +01:00
74a69e1c7a Merge pull request #474 from th-ch/snyk-upgrade-267eeda31c348d529d38d5a6413ef858
[Snyk] Upgrade electron-updater from 4.6.0 to 4.6.1
2021-11-30 00:06:42 +01:00
c3ef16c3dd Merge pull request #477 from Araxeus/fix-loadeddata/metdata-events-rarely-not-firing
Fix loadeddata/metadata video events rarely not firing (+other small fixes)
2021-11-29 23:52:23 +01:00
8c5ac17cdf fix multiple songInfo calls on start 2021-11-23 18:53:04 +02:00
c99b95e611 use config.plugins.isEnabled 2021-11-22 22:52:38 +02:00
4362101c0a lint 2021-11-22 22:08:24 +02:00
7ba205cc6c fix backquotes in keybind prompt 2021-11-22 18:59:29 +02:00
abc1712cf7 fix counter prompt 2021-11-22 18:33:32 +02:00
92452f804f fix song-info-request 2021-11-22 18:20:12 +02:00
c76df84ce3 fix: upgrade node-fetch from 2.6.5 to 2.6.6
Snyk has created this PR to upgrade node-fetch from 2.6.5 to 2.6.6.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-11-22 04:09:33 +00:00
185ebbf417 fix downloader playlist download 2021-11-21 19:44:01 +02:00
6726e2600b rework songInfo pause listener 2021-11-14 23:49:19 +02:00
93e0664f95 fix height & blur of search page item header 2021-11-14 22:02:37 +02:00
bf45ed10aa fix #490 2021-11-14 21:45:34 +02:00
8da78d50c4 Exponential Volume Plugin 2021-11-12 17:58:39 -03:00
b27a959c2b fix video-toggle&precise-volume interaction 2021-11-12 18:42:58 +02:00
cfe719b6bd use native thumbnail without modifiers 2021-11-12 17:46:40 +02:00
071799c435 fix some shortcuts 2021-11-12 16:39:43 +02:00
87ee7ed83d lint video-toggle 2021-11-10 22:35:49 +02:00
08fdd07969 speed up sponsorblock 2021-11-10 20:44:13 +02:00
02d5b78f55 add songInfo.album 2021-11-10 20:11:45 +02:00
5492afe5f6 add catch to fetch 2021-11-10 19:08:19 +02:00
9a7baeac23 fix tuna time update 2021-11-10 18:45:42 +02:00
ccfe7434bf fix mpris 2021-11-10 18:23:55 +02:00
6dbed73e6b fix disable autoplay 2021-11-09 18:52:03 +02:00
895136af0a used youtube's videodatachange event 2021-11-09 17:57:06 +02:00
72b4398024 lint&fix video-toggle plugin 2021-11-09 15:17:26 +02:00
65ce62adc1 use $('video') srcChanged event instead of loadeddata/metadata 2021-11-09 13:29:41 +02:00
eafdd5046d fix lyric text size 2021-11-09 10:42:32 +02:00
bbece751c0 lint playback speed 2021-11-09 10:03:06 +02:00
719c244e32 fix #472 2021-11-09 10:01:33 +02:00
e70b41b256 fix: upgrade @cliqz/adblocker-electron from 1.22.7 to 1.23.0
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.22.7 to 1.23.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-11-09 05:45:20 +00:00
f4b6fd53f3 fix: upgrade electron-updater from 4.6.0 to 4.6.1
Snyk has created this PR to upgrade electron-updater from 4.6.0 to 4.6.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-11-09 05:45:17 +00:00
f40ed04899 Merge pull request #467 from th-ch/snyk-upgrade-cfd310bb818846c87b2239715bd6d1c1
[Snyk] Upgrade custom-electron-prompt from 1.1.0 to 1.2.0
2021-11-07 15:56:27 +01:00
c897323be0 fix: upgrade custom-electron-prompt from 1.1.0 to 1.2.0
Snyk has created this PR to upgrade custom-electron-prompt from 1.1.0 to 1.2.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-11-02 06:46:27 +00:00
TC
d7c4716a6e Re-order plugins in readme 2021-11-01 22:49:34 +01:00
TC
461cac741b nit: add new line at end of file 2021-11-01 22:42:28 +01:00
TC
cee2e066b9 Fix apiLoaded event listener in video-toggle plugin 2021-11-01 22:42:03 +01:00
TC
953d6fe3e4 Migrate old "hide-video-player" plugin to new one 2021-11-01 22:40:26 +01:00
c592a26e42 Merge pull request #448 from Araxeus/new-hide-video-player
Video Toggle Plugin
2021-11-01 22:11:38 +01:00
62bacf76d0 change file names to lower case 2021-11-01 23:10:15 +02:00
fc254db010 Merge pull request #462 from Araxeus/fix-playback-speed-plugin
fix playback speed plugin
2021-11-01 22:10:02 +01:00
0287b69424 fix missing thumbnails
+forced push fix woupsie
2021-11-01 23:04:39 +02:00
ceebd99927 Merge pull request #465 from Araxeus/fix-sponsorblock-v2
Fix sponsorblock skipping when not needed
2021-11-01 21:54:05 +01:00
41285ac9fc fix slider not working on tap 2021-11-01 22:23:26 +02:00
7b9415033f use loadedmetadata instead of loadeddata 2021-11-01 20:03:57 +02:00
b1ffd93bc2 lint in-app-menu 2021-11-01 19:57:28 +02:00
64637a6ac5 Reset segments on song end 2021-11-01 19:57:15 +02:00
b83afa22d9 Merge remote-tracking branch 'upstream/master' into fix-playback-speed-plugin 2021-11-01 18:07:54 +02:00
c68daabeab lint audio-compressor plugin 2021-11-01 18:07:21 +02:00
9ec0830a65 Merge remote-tracking branch 'upstream/master' into new-hide-video-player 2021-11-01 17:59:35 +02:00
48943ee74b lint 2021-11-01 16:06:55 +02:00
29d5b3c7db lint 2021-11-01 16:02:27 +02:00
TC
3de574a2e4 Remove debug log from genius plugin + add a dev log 2021-11-01 12:13:22 +01:00
e765d18ab0 Merge pull request #463 from Araxeus/use-apiLoaded-event-for-time-update
Sponsorblock fix + use new apiLoaded event
2021-11-01 12:03:47 +01:00
4629759eec Merge pull request #458 from Araxeus/use-apiReady-on-audio-compressor-plugin
use apiLoaded event in audio-compressor plugin
2021-11-01 11:47:11 +01:00
a14d27da70 Merge pull request #456 from Araxeus/hide-menu-initial-alert
alert on initial hide-menu enabled
2021-11-01 11:44:27 +01:00
5256ffcf77 Merge pull request #451 from Araxeus/fix-blur-plugin
Blur plugin tweaks and integration with in-app-menu
2021-11-01 11:34:54 +01:00
e2bbc6abbc Merge pull request #449 from Araxeus/fix-resume-on-start
set resume on start url to songInfo.url
2021-11-01 11:30:03 +01:00
6243e6fd48 set max playback speed to 16 ;) 2021-10-30 15:56:12 +03:00
1434849142 simplify playback rate steps 2021-10-30 15:40:45 +03:00
9bd089adb0 add check for lowest playback speed (0.07) 2021-10-30 14:57:16 +03:00
6c1a4c0ac2 playbackSpeed wheel listener 2021-10-30 14:49:03 +03:00
d35fef82fe fix sponsoblock spam updating time 2021-10-30 13:30:38 +03:00
bca22d8e24 update electron to v12.2.2 fixes fetch CERT_HAS_EXPIRED error 2021-10-30 13:17:47 +03:00
754eac6ee0 use apiLoaded 'once'
lint
2021-10-30 12:53:14 +03:00
762566cce6 lint 2021-10-30 12:52:04 +03:00
286bc0113e fix sponsorblock plugin 2021-10-30 12:43:51 +03:00
62e8e673eb use apiLoaded 'once' 2021-10-30 12:17:32 +03:00
68996809f0 add apiLoaded event to disable-autoplay plugin 2021-10-30 12:05:03 +03:00
48a2a13163 fix playback speed plugin 2021-10-30 12:00:29 +03:00
6e94422b15 use apiLoaded event in audio-compressor plugin 2021-10-26 20:57:56 +03:00
713e005aa8 Update readme.md 2021-10-26 20:45:43 +03:00
3f3ab766ce Update readme.md 2021-10-26 20:34:44 +03:00
00e1bbf994 Update readme.md 2021-10-26 20:31:27 +03:00
b45adac847 Update readme.md 2021-10-26 20:03:01 +03:00
3d9b495863 Update readme.md 2021-10-26 19:50:15 +03:00
a70364facf lint 2021-10-26 19:23:10 +03:00
02cb39602f alert on initial hide-menu enabled 2021-10-26 19:07:10 +03:00
12c31725fe fixes scrollbar position relative to navbar depending on player-page-open 2021-10-25 22:45:11 +03:00
e0841060df fix comment typo 2021-10-25 20:20:52 +03:00
b7b55b5c83 Add blur to (library)header + make in-app-menu compatible 2021-10-25 00:43:42 +03:00
43a9093eb7 set resume on start url to songInfo.url 2021-10-24 21:17:45 +03:00
67e43bc0e3 Video Toggle Plugin 2021-10-24 20:09:30 +03:00
TC
a47c906ab2 Add audio compressor plugin to readme 2021-10-24 17:55:37 +02:00
TC
41a01ba58a Bump dev deps 2021-10-24 14:32:35 +02:00
TC
ca2bd011e2 Document quality changer plugin in readme 2021-10-24 14:08:47 +02:00
2106914aff Merge pull request #446 from Araxeus/quality-changer-plugin
quality-changer-plugin
2021-10-24 14:06:08 +02:00
1c11ddbb7d Merge branch 'master' into quality-changer-plugin 2021-10-24 14:03:40 +02:00
TC
fc1211f7a1 Bump version to 1.14.0 2021-10-24 14:02:13 +02:00
TC
18f87c7b0d Add migration for precise-volume plugin (globalShortcuts key) 2021-10-24 14:02:01 +02:00
TC
f9a4bffa55 Fix styling of store migrations 2021-10-24 14:01:29 +02:00
TC
02f4aabead Fix condition on query selector 2021-10-24 14:01:00 +02:00
f97dade168 Merge pull request #443 from Araxeus/songInfo-straight-from-youtube-api
get songInfo from youtube API
2021-10-24 13:42:59 +02:00
8c3a6472f8 Merge branch 'master' into songInfo-straight-from-youtube-api 2021-10-24 13:40:48 +02:00
315f9783f5 Merge pull request #442 from cdaydreamer/master
New plugin: Blur navigation bar
2021-10-24 13:34:45 +02:00
ada78837ce Merge branch 'master' into master 2021-10-24 13:34:15 +02:00
58c6a12e53 Merge pull request #440 from cpiber/discord-clean
Discord plugin: Clean Up Export (follow-up #380)
2021-10-24 13:29:34 +02:00
005c930d58 Merge pull request #434 from Araxeus/remove-upgrade-button
remove upgrade button + makes images unselectable
2021-10-24 13:28:43 +02:00
7c2891b732 Merge branch 'master' into remove-upgrade-button 2021-10-24 13:28:15 +02:00
8b36139dab Merge pull request #433 from Araxeus/new-auto-confirm
new auto confirm when paused
2021-10-24 12:44:19 +02:00
a045d65e58 Merge pull request #431 from itzmanish/fix/mpris
fix: mpris instance not registering itself and media controls
2021-10-24 12:42:31 +02:00
7b064c1e6f Merge pull request #288 from thymue/compressor-plugin
Audio compressor plugin
2021-10-24 12:17:28 +02:00
6a2e3ab6c1 Merge pull request #275 from Araxeus/precise-volume-HUD
precise-volume plugin fixes & updates
2021-10-24 11:40:54 +02:00
362da8c308 Merge pull request #243 from Araxeus/custom-electron-prompt
Custom Prompt for changing options
2021-10-24 11:22:20 +02:00
5658765f54 quality-changer-plugin 2021-10-24 02:24:25 +03:00
38449f003a use apiLoad event 2021-10-23 18:28:38 +03:00
df75e480a6 use apiLoad event 2021-10-23 18:27:35 +03:00
79a95f133b use apiLoad event 2021-10-23 18:22:17 +03:00
9b1a5b8d26 clarify var names in cleanupName() 2021-10-23 17:18:58 +03:00
bb2e1bd616 use youtube native api to change volume 2021-10-23 16:57:44 +03:00
2d518abc19 remove leftover console.log 2021-10-23 16:26:45 +03:00
978aca1f9a use loadeddata instead of loadedmetadata
send event closer to actual initial start time of video
2021-10-23 16:21:42 +03:00
2224786478 lint 2021-10-23 16:19:45 +03:00
51364b63e7 get songInfo from youtube API 2021-10-23 16:13:06 +03:00
c897bedd90 New plugin: Blur navigation bar 2021-10-23 15:38:46 +03:00
831b1ea8e1 access window._lact directly 2021-10-23 15:21:49 +03:00
4d4dacbc71 discord: clean up export (follow-up #380) 2021-10-19 18:40:27 +02:00
1cd4f53657 Merge branch 'master' into custom-electron-prompt 2021-10-19 15:55:00 +03:00
2eda0e4948 Merge branch 'master' into new-auto-confirm 2021-10-19 15:19:58 +03:00
f2e04f9170 Merge pull request #412 from th-ch/snyk-upgrade-3ac551b4f96cf4c26f3157f42a916769
[Snyk] Upgrade async-mutex from 0.3.1 to 0.3.2
2021-10-18 23:34:29 +02:00
c92b3915d9 Merge pull request #414 from th-ch/dependabot/npm_and_yarn/tmpl-1.0.5
build(deps): bump tmpl from 1.0.4 to 1.0.5
2021-10-18 23:31:59 +02:00
6118a17b08 Merge pull request #416 from th-ch/snyk-upgrade-d31d43c15fe12eab06e73b6f8faeda29
[Snyk] Upgrade node-fetch from 2.6.1 to 2.6.2
2021-10-18 23:30:04 +02:00
1490c0f179 Merge pull request #429 from th-ch/snyk-upgrade-129504aaea5df4956b1cd910a6775c4a
[Snyk] Upgrade @cliqz/adblocker-electron from 1.22.5 to 1.22.6
2021-10-18 23:23:27 +02:00
fdf203e70a Merge pull request #430 from th-ch/dependabot/npm_and_yarn/electron-12.1.0
build(deps-dev): bump electron from 12.0.8 to 12.1.0
2021-10-18 23:18:29 +02:00
8114a28964 Merge pull request #380 from cpiber/discord
Fix discord clearActivity, menu, listen along option
2021-10-18 23:10:24 +02:00
663507b3f8 fix: player status when play at start 2021-10-17 11:06:26 +05:30
79d0c7b666 fix: typo 2021-10-17 10:54:05 +05:30
ce4580605d remove upgrade button + makes img unselectable 2021-10-15 15:40:34 +03:00
dda18a72af new auto confirm when paused 2021-10-15 14:38:09 +03:00
f7a1de05c8 defensive coding 2021-10-15 05:41:47 +03:00
361606427a fix: remove unused play pause functions 2021-10-14 10:18:05 +05:30
81fb5118aa fix: don't create play pause method unneccessarily 2021-10-14 10:16:36 +05:30
a76f12c01c feat: add play and pause seperate song controller. 2021-10-13 12:27:13 +05:30
88ee0fb989 fix: mpris was not registering itself before.
Sorry I missed that somehow, because playerctl controls were working.
That was because of chromium was also registering itself for mpris.
2021-10-13 12:26:38 +05:30
3ec49bca74 build(deps-dev): bump electron from 12.0.8 to 12.1.0
Bumps [electron](https://github.com/electron/electron) from 12.0.8 to 12.1.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v12.0.8...v12.1.0)

---
updated-dependencies:
- dependency-name: electron
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-12 22:10:41 +00:00
1908921ae6 fix: upgrade @cliqz/adblocker-electron from 1.22.5 to 1.22.6
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.22.5 to 1.22.6.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-10-11 21:23:58 +00:00
b9dbd8bd4d Allow disable listen along (#426) 2021-10-11 15:02:24 +02:00
587818b91e Add type, clear on close 2021-10-05 10:10:36 +02:00
157ae05f80 fix: upgrade node-fetch from 2.6.1 to 2.6.2
Snyk has created this PR to upgrade node-fetch from 2.6.1 to 2.6.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-09-27 19:13:33 +00:00
f2039e29e7 build(deps): bump tmpl from 1.0.4 to 1.0.5
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-21 21:12:33 +00:00
ea2d33c3cf fix: upgrade async-mutex from 0.3.1 to 0.3.2
Snyk has created this PR to upgrade async-mutex from 0.3.1 to 0.3.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-09-21 03:24:11 +00:00
d775e3d588 Merge pull request #406 from th-ch/snyk-upgrade-3c48abddd3d31d59f08172a32b5dd378
[Snyk] Upgrade @cliqz/adblocker-electron from 1.22.4 to 1.22.5
2021-09-19 16:13:09 +02:00
e7ec15e90f fix: upgrade @cliqz/adblocker-electron from 1.22.4 to 1.22.5
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.22.4 to 1.22.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-09-16 00:27:20 +00:00
TC
403470be69 Bump version 2021-09-15 22:59:06 +02:00
6dc0ba74c4 Merge pull request #384 from konhi/useragent
Fix incorrect Google alert caused by changing user agent coresponding to current platform
2021-09-15 22:54:10 +02:00
TC
6dcfb336c2 Fix missing import in shortcuts plugin 2021-09-15 22:51:58 +02:00
84516b2ac1 Merge pull request #401 from th-ch/snyk-upgrade-4b273faf3969a8ede6309124c5ce3e75
[Snyk] Upgrade electron-updater from 4.4.3 to 4.4.6
2021-09-15 22:50:15 +02:00
57cf2a8cdd fix: upgrade electron-updater from 4.4.3 to 4.4.6
Snyk has created this PR to upgrade electron-updater from 4.4.3 to 4.4.6.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-09-13 01:17:33 +00:00
e3ae97fec4 Merge pull request #370 from th-ch/snyk-upgrade-eeb9d7e7304322861f42850feedf7f74
[Snyk] Upgrade electron-updater from 4.4.0 to 4.4.1
2021-09-12 23:10:47 +02:00
TC
ee76e2cb45 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-eeb9d7e7304322861f42850feedf7f74
* 'master' of github.com:th-ch/youtube-music:
  Bump node to v14
  nit: fix code style for tuna obs (+ typo)
  add tuna plugin for obs
  Add mpris support
  Update menu buttons to new format
  Bump jszip from 3.5.0 to 3.7.1
  Add Genius lyrics plugin
  Apply clean up util to title + enrich prefixes
  Bump node to v14
  fix: upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3
  Add "Listen Along" button
  sort alphabetically
  suggestions from @Araxeus and @cpiber
  Fix broken link
  update descriptions and add images
  List missing plugins
  Bump path-parse from 1.0.6 to 1.0.7
2021-09-12 23:03:23 +02:00
de01bb6e75 Merge pull request #375 from th-ch/dependabot/npm_and_yarn/path-parse-1.0.7
Bump path-parse from 1.0.6 to 1.0.7
2021-09-12 23:02:52 +02:00
TC
42668c3e99 Merge branch 'master' of github.com:th-ch/youtube-music into dependabot/npm_and_yarn/path-parse-1.0.7
* 'master' of github.com:th-ch/youtube-music:
  Bump node to v14
  nit: fix code style for tuna obs (+ typo)
  add tuna plugin for obs
  Add mpris support
  Update menu buttons to new format
  Bump jszip from 3.5.0 to 3.7.1
  Add Genius lyrics plugin
  Apply clean up util to title + enrich prefixes
  Bump node to v14
  fix: upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3
  Add "Listen Along" button
  sort alphabetically
  suggestions from @Araxeus and @cpiber
  Fix broken link
  update descriptions and add images
  List missing plugins
2021-09-12 22:55:08 +02:00
05f3c56e47 Merge pull request #385 from th-ch/snyk-upgrade-f132bed3bdbd1c212a2d1580af9a445a
[Snyk] Upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3
2021-09-12 22:53:39 +02:00
TC
d54977b9ee Bump node to v14 2021-09-12 22:42:31 +02:00
b89fb4dc2f Merge pull request #388 from th-ch/dependabot/npm_and_yarn/jszip-3.7.1
Bump jszip from 3.5.0 to 3.7.1
2021-09-12 22:33:50 +02:00
a0cf77edfb Merge pull request #382 from konhi/patch-1
List missing plugins
2021-09-12 22:20:53 +02:00
TC
069f9855d1 nit: fix code style for tuna obs (+ typo) 2021-09-12 22:17:54 +02:00
e3e0775401 Merge pull request #397 from mesmerx/master
add tuna plugin for obs
2021-09-12 22:16:22 +02:00
d255e5ffe1 Merge pull request #389 from th-ch/fix-menu-buttons
Update menu buttons to new format
2021-09-12 22:13:46 +02:00
fea460a374 Merge pull request #387 from th-ch/lyrics-genius-plugin
Plugin to fetch lyrics from Genius
2021-09-12 22:10:43 +02:00
302d3f693f add tuna plugin for obs 2021-09-08 22:45:49 -03:00
9cc320d74b Merge pull request #395 from itzmanish/feat/mpris-support
Add mpris support with cherry picked commit from previous PR https://github.com/th-ch/youtube-music/pull/394
2021-09-07 00:12:34 +02:00
e255777283 Add mpris support 2021-09-02 16:00:42 +05:30
ef66612cc8 Discord show error dialog on reconnect error 2021-08-27 17:07:23 +02:00
4bed835347 Merge branch 'master' of https://github.com/th-ch/youtube-music into discord 2021-08-27 16:37:50 +02:00
b5fd6b4969 Discord add reconnecting functionality
Clear rpc on disconnect
Add menu button to reconnect
2021-08-27 16:32:55 +02:00
fe0f213919 Merge pull request #383 from konhi/discord
Add "Listen Along" button, solve #353
2021-08-23 01:19:00 +02:00
TC
e888b5c896 Update menu buttons to new format 2021-08-23 01:17:29 +02:00
f27ff52689 Bump jszip from 3.5.0 to 3.7.1
Bumps [jszip](https://github.com/Stuk/jszip) from 3.5.0 to 3.7.1.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.5.0...v3.7.1)

---
updated-dependencies:
- dependency-name: jszip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-22 23:16:24 +00:00
TC
acbe0ac25d Add Genius lyrics plugin 2021-08-23 01:12:53 +02:00
TC
c66ff2bf05 Apply clean up util to title + enrich prefixes 2021-08-23 01:12:53 +02:00
d089487aa8 Merge pull request #386 from th-ch/bump-node-version
Bump node to v14
2021-08-23 01:12:27 +02:00
TC
6bc1d1606f Bump node to v14 2021-08-23 01:05:45 +02:00
9df5d921c7 Chrome -> Firefox, simplified using electron-is
suggestions by @Araxeus
2021-08-20 12:33:46 +02:00
4b1dfa1173 fix: upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.22.2 to 1.22.3.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-08-19 21:20:28 +00:00
f98318e737 Add platform-based user-agent 2021-08-19 16:49:34 +02:00
7fa1278b31 Add "Listen Along" button 2021-08-19 16:16:49 +02:00
878ec1f6c1 sort alphabetically 2021-08-19 15:09:31 +02:00
086048780a suggestions from @Araxeus and @cpiber 2021-08-19 15:04:47 +02:00
65eaaecae5 Merge branch 'master' into custom-electron-prompt 2021-08-19 13:44:42 +03:00
aff0415816 Fix broken link
Oops.
2021-08-19 00:15:25 +02:00
6040fe1cbd update descriptions and add images 2021-08-19 00:08:17 +02:00
36bc9c62b0 Discord timeout 0 clear activity directly 2021-08-18 21:39:40 +02:00
3901457218 Discord add menu button for clearing activity 2021-08-17 10:09:47 +02:00
52f4e9d796 List missing plugins 2021-08-16 18:49:15 +02:00
183bad43f6 Fix discord clearActivity, menu
The callback sends multiple events, in particular two pause when going to the
next song, so the timeout wasn't properly cleared.
Add menu buttons for the two options
2021-08-15 12:25:00 +02:00
09fe80cae7 Bump path-parse from 1.0.6 to 1.0.7
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-12 03:24:48 +00:00
817b48dc9d fix: upgrade electron-updater from 4.4.0 to 4.4.1
Snyk has created this PR to upgrade electron-updater from 4.4.0 to 4.4.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-08-06 21:42:35 +00:00
c6f8c42c45 Merge pull request #350 from th-ch/snyk-upgrade-4809caaf0847354b9b537aa0f8a0999d
[Snyk] Upgrade electron-updater from 4.3.9 to 4.3.10
2021-08-06 23:23:12 +02:00
TC
0535686129 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-4809caaf0847354b9b537aa0f8a0999d
# By TC (1) and snyk-bot (1)
# Via GitHub (1) and TC (1)
* 'master' of github.com:th-ch/youtube-music:
  Bump ytdl/ytpl
  fix: upgrade chokidar from 3.5.1 to 3.5.2
2021-08-06 23:22:44 +02:00
53a77255ca Merge pull request #354 from th-ch/snyk-upgrade-1a48119c8989bb533950b3384b3bce29
[Snyk] Upgrade chokidar from 3.5.1 to 3.5.2
2021-08-06 23:17:51 +02:00
TC
c01506dc44 Bump ytdl/ytpl 2021-08-06 23:12:29 +02:00
a49817fdc3 Merge branch 'master' into custom-electron-prompt 2021-07-20 11:06:08 +03:00
52a4608d76 create options.global if needed 2021-07-20 10:57:32 +03:00
6f5f9386ff fix: upgrade chokidar from 3.5.1 to 3.5.2
Snyk has created this PR to upgrade chokidar from 3.5.1 to 3.5.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-07-07 05:50:15 +00:00
fddd0607e6 fix: upgrade electron-updater from 4.3.9 to 4.3.10
Snyk has created this PR to upgrade electron-updater from 4.3.9 to 4.3.10.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-07-02 06:17:28 +00:00
TC
2cb6f56feb Bump version 2021-07-01 22:43:35 +02:00
TC
46285a5ed0 Bump glob-parent and add lint script (xo) 2021-06-27 21:19:33 +02:00
TC
496836b33b Bump dependencies to fix vulnerabilities 2021-06-27 21:12:28 +02:00
af127879a5 Merge pull request #339 from th-ch/fix-downloader-plugin
Fix downloader plugin
2021-06-27 21:10:35 +02:00
TC
38ef452801 Bump ffmpeg version 2021-06-27 20:46:48 +02:00
TC
a9a5d99676 Do not add network filters in adblocker cache to fix session enhancing 2021-06-27 20:46:48 +02:00
TC
e5ab50cebd Override content security policy to allow FFmpeg worker 2021-06-27 20:46:46 +02:00
TC
49194f8141 nit: re-order dependencies 2021-06-27 20:39:05 +02:00
TC
641ae27efd Update ytdl-core and ytpl 2021-06-27 20:38:08 +02:00
47a5dec465 Merge pull request #337 from th-ch/snyk-upgrade-fe663d0d7c5fc658f327e05ae5966f76
[Snyk] Upgrade @cliqz/adblocker-electron from 1.22.0 to 1.22.1
2021-06-25 23:11:25 +02:00
c93eabb400 Merge pull request #249 from Araxeus/update-in-app-menu
Update and simplify in-app-menu
2021-06-25 23:03:05 +02:00
664be51de2 Merge branch 'master' into custom-electron-prompt 2021-06-25 12:21:40 +03:00
492a47321d Merge branch 'master' into update-in-app-menu 2021-06-25 12:19:39 +03:00
c89f6af8c6 fix: upgrade @cliqz/adblocker-electron from 1.22.0 to 1.22.1
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.22.0 to 1.22.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-25 04:53:24 +00:00
9687c6c8e4 Merge pull request #331 from th-ch/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-06-24 22:06:27 +02:00
ef0a89126a Merge pull request #330 from th-ch/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21
2021-06-24 22:05:46 +02:00
8ce71d628d Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

---
updated-dependencies:
- dependency-name: lodash
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-24 20:04:35 +00:00
ca95d105c8 Merge pull request #328 from th-ch/snyk-upgrade-dacfb8f0b574367961e405e4912a4659
[Snyk] Upgrade ytdl-core from 4.8.0 to 4.8.2
2021-06-24 22:04:32 +02:00
12568c2b09 Merge pull request #324 from th-ch/snyk-upgrade-f650e2139b30a36951a4a00ed1b78d70
[Snyk] Upgrade electron-updater from 4.3.8 to 4.3.9
2021-06-24 22:03:15 +02:00
82abb4d4d3 Merge pull request #323 from th-ch/dependabot/npm_and_yarn/normalize-url-4.5.1
Bump normalize-url from 4.5.0 to 4.5.1
2021-06-24 22:02:52 +02:00
3c0a5dbbe5 Merge pull request #320 from th-ch/dependabot/npm_and_yarn/trim-newlines-3.0.1
Bump trim-newlines from 3.0.0 to 3.0.1
2021-06-24 22:02:33 +02:00
0b98eef06f Merge pull request #317 from th-ch/snyk-upgrade-a785f5d95c7765e2d47737e150a2263d
[Snyk] Upgrade @ffmpeg/core from 0.9.0 to 0.10.0
2021-06-24 22:02:05 +02:00
TC
18e69c9f2a Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-a785f5d95c7765e2d47737e150a2263d
# By Araxeus (2) and snyk-bot (2)
# Via GitHub (3) and Araxeus (1)
* 'master' of github.com:th-ch/youtube-music:
  check if native image is empty before writing id tag
  fix unsupported hidden webp coverart
  fix: upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0
  fix: upgrade custom-electron-titlebar from 3.2.6 to 3.2.7
2021-06-24 22:01:16 +02:00
8f5d06d420 Merge pull request #316 from th-ch/snyk-upgrade-6e93904bf885d198521c6a5d8110bde3
[Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0
2021-06-24 22:00:07 +02:00
8a299461a0 Merge pull request #311 from th-ch/snyk-upgrade-44a5db26689d4091f6a2c3c3c69b869a
[Snyk] Upgrade custom-electron-titlebar from 3.2.6 to 3.2.7
2021-06-24 21:49:53 +02:00
0c58bec921 Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

---
updated-dependencies:
- dependency-name: hosted-git-info
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-19 20:29:37 +00:00
e0cb132686 Merge pull request #318 from Araxeus/fix-hidden-webp-cover-art
fix hidden webp thumbnail throwing MIME type error in downloader
2021-06-19 22:28:59 +02:00
2a192f39f9 fix: upgrade ytdl-core from 4.8.0 to 4.8.2
Snyk has created this PR to upgrade ytdl-core from 4.8.0 to 4.8.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-19 05:30:04 +00:00
b7ebb7d499 fix: upgrade electron-updater from 4.3.8 to 4.3.9
Snyk has created this PR to upgrade electron-updater from 4.3.8 to 4.3.9.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-12 04:23:30 +00:00
fffeac21b7 Bump normalize-url from 4.5.0 to 4.5.1
Bumps [normalize-url](https://github.com/sindresorhus/normalize-url) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/sindresorhus/normalize-url/releases)
- [Commits](https://github.com/sindresorhus/normalize-url/commits)

---
updated-dependencies:
- dependency-name: normalize-url
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-11 04:46:20 +00:00
4387cb485d Bump trim-newlines from 3.0.0 to 3.0.1
Bumps [trim-newlines](https://github.com/sindresorhus/trim-newlines) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/sindresorhus/trim-newlines/releases)
- [Commits](https://github.com/sindresorhus/trim-newlines/commits)

---
updated-dependencies:
- dependency-name: trim-newlines
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-09 18:57:55 +00:00
2a58dc823a check if native image is empty before writing id tag 2021-06-09 20:05:14 +03:00
8eb38271ff fix unsupported hidden webp coverart 2021-06-09 19:53:04 +03:00
1987ad1d4f fix: upgrade @ffmpeg/core from 0.9.0 to 0.10.0
Snyk has created this PR to upgrade @ffmpeg/core from 0.9.0 to 0.10.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-08 04:08:44 +00:00
cc4dae60ef fix: upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0
Snyk has created this PR to upgrade @ffmpeg/ffmpeg from 0.9.8 to 0.10.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-08 04:08:41 +00:00
1943116aa1 fix: upgrade custom-electron-titlebar from 3.2.6 to 3.2.7
Snyk has created this PR to upgrade custom-electron-titlebar from 3.2.6 to 3.2.7.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-06-05 03:53:12 +00:00
3485d26b11 Merge pull request #308 from th-ch/sponsorblock-plugin
Add Sponsorblock plugin
2021-06-04 22:25:26 +02:00
TC
4a60aa9f20 Keep segments when skipping 2021-06-03 22:15:36 +02:00
TC
cda07c9675 Update adblocking 2021-06-03 22:04:49 +02:00
TC
ca64a77ed0 Add SponsorBlock plugin 2021-06-03 21:47:26 +02:00
TC
30e94d1d6f Refactor videoElement getter into a provider with callback 2021-06-03 21:45:28 +02:00
TC
b8c6ebfa53 Set test environment per test file 2021-06-03 21:43:07 +02:00
b26748ded8 Merge pull request #305 from th-ch/snyk-upgrade-15656c519a90f5bc0f5c8742a9fb04e9
[Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.7 to 0.9.8
2021-05-31 22:06:17 +02:00
f186da0834 fix: upgrade @ffmpeg/ffmpeg from 0.9.7 to 0.9.8
Snyk has created this PR to upgrade @ffmpeg/ffmpeg from 0.9.7 to 0.9.8.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-29 04:38:22 +00:00
c52c2d886a Merge pull request #303 from th-ch/dependabot/npm_and_yarn/ws-7.4.6
Bump ws from 7.4.3 to 7.4.6
2021-05-28 23:40:55 +02:00
e5dc1f8a58 Bump ws from 7.4.3 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.4.3 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.3...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-28 21:39:25 +00:00
6dbf4134de Merge pull request #301 from th-ch/dependabot/npm_and_yarn/browserslist-4.16.6
Bump browserslist from 4.16.3 to 4.16.6
2021-05-28 23:38:48 +02:00
e1cc49a74d Merge pull request #300 from th-ch/snyk-upgrade-ce2777733d9dee231391c0a822c24a84
[Snyk] Upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5
2021-05-28 23:35:11 +02:00
TC
4489a400b7 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-ce2777733d9dee231391c0a822c24a84
# By Araxeus (5) and others
# Via GitHub (5) and TC (2)
* 'master' of github.com:th-ch/youtube-music:
  Bump electron to 12.0.8
  fix: upgrade ytdl-core from 4.5.0 to 4.7.0
  fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
  fix notificationOnUnpause option
  fix: upgrade filenamify from 4.2.0 to 4.3.0
  switch to `registerCallback()` on song info
  fix: upgrade ytpl from 2.1.1 to 2.2.0
  lint
  refactor notifications plugin
  setup SongInfo **once**
2021-05-28 23:33:20 +02:00
28aa1c0b22 Merge pull request #299 from th-ch/snyk-upgrade-37e43892f5a34f935e8486a98b3598fb
[Snyk] Upgrade ytdl-core from 4.5.0 to 4.7.0
2021-05-28 23:32:29 +02:00
TC
c540788d20 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-37e43892f5a34f935e8486a98b3598fb
# By Araxeus (5) and others
# Via GitHub (4) and TC (1)
* 'master' of github.com:th-ch/youtube-music:
  Bump electron to 12.0.8
  fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
  fix notificationOnUnpause option
  fix: upgrade filenamify from 4.2.0 to 4.3.0
  switch to `registerCallback()` on song info
  fix: upgrade ytpl from 2.1.1 to 2.2.0
  lint
  refactor notifications plugin
  setup SongInfo **once**
2021-05-28 23:32:05 +02:00
4ab07dc875 Merge pull request #298 from th-ch/snyk-upgrade-d305cdce94133f6db9615e7b16007c87
[Snyk] Upgrade @ffmpeg/core from 0.8.5 to 0.9.0
2021-05-28 23:28:26 +02:00
5033de13ef Merge pull request #293 from th-ch/snyk-upgrade-335ec370c7caa5a759c54a46b2e27cf5
[Snyk] Upgrade filenamify from 4.2.0 to 4.3.0
2021-05-28 23:23:49 +02:00
55a8787a16 Merge pull request #285 from th-ch/snyk-upgrade-7b9c569f5bdd092f76adf7d412b0eea1
[Snyk] Upgrade ytpl from 2.1.1 to 2.2.0
2021-05-28 23:21:51 +02:00
3515bf364d Merge pull request #269 from Araxeus/fix-XHR-duplicate-callback
fix song-info callback duplication
2021-05-28 23:18:10 +02:00
TC
d8f3246e46 Bump electron to 12.0.8 2021-05-28 23:13:07 +02:00
cd613aaba2 Bump browserslist from 4.16.3 to 4.16.6
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.3 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.16.3...4.16.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-27 02:56:37 +00:00
c5f84b568b fix: upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.20.4 to 1.20.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:08 +00:00
14dc78984f fix: upgrade ytdl-core from 4.5.0 to 4.7.0
Snyk has created this PR to upgrade ytdl-core from 4.5.0 to 4.7.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:06 +00:00
fb61dbfa6c fix: upgrade @ffmpeg/core from 0.8.5 to 0.9.0
Snyk has created this PR to upgrade @ffmpeg/core from 0.8.5 to 0.9.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-26 04:36:03 +00:00
33855f17dd update refreshMenu() function 2021-05-23 17:57:54 +03:00
8124623142 fix notificationOnUnpause option 2021-05-22 18:38:36 +03:00
e99c91ce6e get rid of (hopefully) unnecessary watchDOMElement 2021-05-19 21:50:40 +02:00
177ce5721f fix: upgrade filenamify from 4.2.0 to 4.3.0
Snyk has created this PR to upgrade filenamify from 4.2.0 to 4.3.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-19 05:31:34 +00:00
4fb0b1dd08 switch to registerCallback() on song info 2021-05-19 00:22:12 +03:00
177ad2ce7c minify firstRun() 2021-05-18 19:20:09 +03:00
9b88769585 remove leftover console.log 2021-05-18 19:02:56 +03:00
fd044072a1 use front load event instead of webcontents.did-finish-load 2021-05-18 18:53:00 +03:00
bae5155e19 use let and const instead of var 2021-05-17 13:42:27 +02:00
1e2085b990 compressor plugin 2021-05-17 12:33:43 +02:00
bbe5a7d50b fix: upgrade ytpl from 2.1.1 to 2.2.0
Snyk has created this PR to upgrade ytpl from 2.1.1 to 2.2.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-05-17 04:44:57 +00:00
e5473cdfe4 lint 2021-05-17 00:07:28 +03:00
9c7a70e056 use .toFixed(2) on volume decimals 2021-05-16 23:50:59 +03:00
5bc8e86353 Merge pull request #270 from Araxeus/fix-normal-notification-showing-appID
fix notification showing appID instead of app name on windows
2021-05-16 22:46:54 +02:00
5b00465558 Merge pull request #273 from th-ch/upgrade-electron
Upgrade electron to v12
2021-05-16 22:31:07 +02:00
28b70f6459 added timeout when writing volume to config 2021-05-16 22:59:05 +03:00
6961cdee95 override youtube automatically changing the volume 2021-05-16 22:39:38 +03:00
58557505ae show mute icon when volume=0 2021-05-16 22:39:11 +03:00
65178b259f fix video muting when volume < 3 2021-05-16 21:32:40 +03:00
541c7f34b7 restore menuItems roles that were fixed 2021-05-15 17:24:01 +03:00
b2c209837c fix empty string input validation in setProxy 2021-05-14 03:12:27 +03:00
355f61188a use placeholder proxy example 2021-05-13 07:08:17 +03:00
ea672c2423 show volume hud in videoplayer if available 2021-05-13 03:18:24 +03:00
71ba6b8e55 lint 2021-05-12 20:58:43 +03:00
8a07fccf8f setup on page reload 2021-05-12 18:58:29 +03:00
7bc35f4cee add volume hud 2021-05-12 18:31:11 +03:00
002081bcb9 use store migration 2021-05-12 00:47:41 +03:00
TC
0e8e78362b Upgrade electron to v12 2021-05-11 22:56:07 +02:00
cb6a5a478e lint 2021-05-11 16:47:51 +03:00
d615030222 register appID on windows reguardless of shortcut 2021-05-11 00:34:40 +03:00
e43c01da64 lint 2021-05-11 00:20:00 +03:00
cb5ef1d6e5 check that app is installed / unpacked 2021-05-11 00:15:54 +03:00
78a7dcb7e8 lint 2021-05-10 23:46:56 +03:00
8cca9f3eeb create shortcut only if needed 2021-05-10 23:23:17 +03:00
93d4d3c976 writeShortcut on windows 2021-05-10 22:13:45 +03:00
8284b56075 set appID on windows 2021-05-10 20:40:25 +03:00
580caeffb9 destructure keybind output 2021-05-10 16:53:57 +03:00
b266037bb4 lint 2021-05-10 06:05:39 +03:00
cb743de7fd refactor notifications plugin 2021-05-10 05:00:58 +03:00
7cf78c6635 setup SongInfo **once** 2021-05-10 04:15:56 +03:00
0eca30367f lint 2021-05-10 01:56:41 +03:00
36317c953a globalize promptOptions 2021-05-10 01:43:50 +03:00
f910593fb6 use spread operator + async await 2021-05-10 00:40:02 +03:00
7942efa202 Merge pull request #267 from Araxeus/last-fm-config-check-fix
fix last-fm overwrite config on each start
2021-05-09 21:47:07 +02:00
792c2931b0 fix config overwrite on each start 2021-05-09 22:10:20 +03:00
TC
a3778af48a Downloader: rename UrlToJPG to urlToJPG 2021-05-08 22:48:18 +02:00
TC
163dc7e1d1 Downloader: catch error when fetching playlist 2021-05-08 22:41:56 +02:00
0a59122ac2 Merge pull request #265 from Araxeus/ensure-download-from-radio-button
Downloader tweaks + taskbar progress bar
2021-05-08 22:40:24 +02:00
d2a5110f3b querySelector optimization #2 2021-05-08 23:06:18 +03:00
cf4bbf94e4 update radioButton querySelector 2021-05-08 23:02:52 +03:00
d7e42471a4 lint 2021-05-08 23:01:57 +03:00
d634c41e75 Merge pull request #262 from Araxeus/remove-open-dependency
remove `open` dependency from last-fm plugin
2021-05-08 21:58:51 +02:00
6b88397f82 lint 2021-05-08 21:21:07 +03:00
da3c709ff0 remove videoDetails?.media query from XHR
(it never exists in the XHR responce)
2021-05-08 20:46:15 +03:00
ccd320d8ff minimize getArtist() 2021-05-08 20:40:44 +03:00
3831e61d10 differentiate names of different metadata sources 2021-05-08 19:45:33 +03:00
e46e7b74e2 fix sendError() 2021-05-08 19:34:57 +03:00
b3da77a6bc small refactor 2021-05-08 19:24:25 +03:00
96a74f8955 use original metadata only if not already captured from ytpl.getInfo() 2021-05-08 19:19:11 +03:00
3ea17e6f46 refactor 2021-05-08 08:05:38 +03:00
a8ac2c3af9 download progress bar on taskbar
+ Get the best possible artwork
2021-05-08 07:11:54 +03:00
2168cbca30 use image from imageSrc if transfered 2021-05-08 04:04:35 +03:00
cceb45319a debug videoUrl from start Radio button in menu 2021-05-08 04:03:34 +03:00
e985b78241 lint 2021-05-08 01:08:24 +03:00
090ca828c0 Merge branch 'master' into update-in-app-menu 2021-05-08 01:03:14 +03:00
3522925dec remove open dependency 2021-05-08 01:00:23 +03:00
5418ef7ae2 Merge branch 'master' into custom-electron-prompt 2021-05-08 00:21:16 +03:00
5faeddb99b Merge pull request #252 from Araxeus/fix-download-idtag-if-not-playing
Fix downloader metadata if not currently playing
2021-05-07 23:11:10 +02:00
1140c3e2e7 lint 2021-05-07 23:40:14 +03:00
TC
3fb08d27c7 Add start:debug command to enable dev with electron debug 2021-05-07 22:29:21 +02:00
250940d083 Merge pull request #259 from Araxeus/force-pause
fix playPause bugs by directly playPause video element
2021-05-07 22:24:03 +02:00
e00be8f010 lint 2021-05-07 05:43:26 +03:00
8b471c0772 create cleanupArtistName() in song-info 2021-05-07 04:47:24 +03:00
88e738c796 check if yns_pause exists 2021-05-07 04:17:17 +03:00
TC
c76d8c79d8 Bump version to 1.12.1 2021-05-06 22:29:04 +02:00
b396431a8b Merge pull request #260 from th-ch/dependabot/npm_and_yarn/ua-parser-js-0.7.28
Bump ua-parser-js from 0.7.23 to 0.7.28
2021-05-06 22:18:37 +02:00
d1795a82f7 Merge pull request #253 from Araxeus/fix-precise-volume-listener-override
Fix precise volume listener override
2021-05-06 21:45:09 +02:00
9b821a0dfe Bump ua-parser-js from 0.7.23 to 0.7.28
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.23 to 0.7.28.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.23...0.7.28)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 19:41:13 +00:00
bf89842ee8 Merge pull request #255 from Araxeus/fix-css-on-reload
fix css not inserting on reload
2021-05-06 21:40:13 +02:00
d274e80f75 minify 2021-05-06 21:41:08 +03:00
a98b8945fb lint 2021-05-06 21:32:44 +03:00
6b72599f80 directly playPause video element 2021-05-06 21:20:42 +03:00
4b6fe78a1a fix css not inserting on reload 2021-05-06 18:40:56 +03:00
d000c03fca lint 2021-05-06 05:40:31 +03:00
c0a185ba68 refactor addEventListener 2021-05-06 05:18:06 +03:00
ef0813e638 fix preventDefault() being called on *all* keys 2021-05-06 04:58:05 +03:00
25e9f44260 fix listener override condition 2021-05-06 04:56:06 +03:00
2d6e858e8f lint 2021-05-06 04:43:31 +03:00
53bf7c5068 playlist download progressBar using chokidar 2021-05-06 04:41:58 +03:00
13fb686188 started playlist downlaod messageBox 2021-05-06 03:33:49 +03:00
61c5494588 custom metadata on playlist-download 2021-05-06 03:02:06 +03:00
d96fefbc24 fix error thrown when downloading playlist 2021-05-06 02:51:10 +03:00
e18b7c1013 allow unlimited playlist size 2021-05-06 02:28:35 +03:00
f190b51dcc lint 2021-05-06 02:17:48 +03:00
ca41c12f7c use media propery if exist in song-info 2021-05-06 02:05:48 +03:00
844edbe2f4 fix metadata when downloading unplayed song 2021-05-06 01:46:14 +03:00
78974c02e5 save in-app-menu activation state on launch 2021-05-05 21:12:52 +03:00
4508464fd1 update custom-electron-titlebar version 2021-05-05 20:39:08 +03:00
dd6455a559 update in-app-menu 2021-05-05 20:37:29 +03:00
6b147b098a fix prompt width 2021-05-05 03:48:07 +03:00
834f8674a3 massive prompt speed boost with v1.1.0 2021-05-05 03:27:47 +03:00
5cee331abe update prompt version and lint 2021-05-05 02:53:05 +03:00
98c00f7a60 format proxy example 2021-05-05 02:30:08 +03:00
db8d946178 fix electron dependency 2021-05-05 02:08:24 +03:00
b97a86f6dc Update yarn.lock 2021-05-05 01:55:25 +03:00
34a4e6be3d proxy url check 2021-05-05 01:47:53 +03:00
22c5ea5000 lint 2021-05-05 01:25:45 +03:00
79acf6c0ba Volume Steps Prompt
Precise-Volume Global Shortcuts Prompt
2021-05-05 00:42:42 +03:00
ebaa01896f Merge remote-tracking branch 'upstream/master' into custom-electron-prompt 2021-05-04 23:48:27 +03:00
TC
d4811b7901 Revert "Remove preload.js in plugin uses and use front plugin injection"
This reverts commit 4cb658daca.
2021-05-04 22:31:49 +02:00
TC
bf409967b2 Import front logger at top level 2021-05-04 21:30:10 +02:00
TC
4cb658daca Remove preload.js in plugin uses and use front plugin injection 2021-05-04 21:29:39 +02:00
8aeddcf8d8 Merge pull request #224 from Araxeus/menu-fixes
Menu tweaks
2021-05-04 21:24:29 +02:00
fb81e1bdd5 ignore did-fail-load error code -3
bug with in-app-menu
2021-05-04 02:04:17 +03:00
d5b9e3c960 stringify did-fail-load error
directly preload front-logger
simplify front-logger
2021-05-04 01:22:47 +03:00
TC
c7ff536ed5 Bump version to 1.12.0 2021-05-03 22:24:19 +02:00
TC
7dbb5fc86d Update electron to 11.4.4 2021-05-02 22:41:38 +02:00
8f766bcbaa resolve merge conflict 2021-05-02 23:41:16 +03:00
TC
f65c6c89ae Fix package.json indent, update yarn.lock 2021-05-02 22:30:24 +02:00
472462cdcb Merge pull request #228 from Araxeus/interactive-notifications
Interactive notifications for windows
2021-05-02 22:27:36 +02:00
8575996e46 Merge branch 'menu-fixes' of https://github.com/Araxeus/youtube-music into menu-fixes 2021-05-02 23:26:27 +03:00
02d16ca510 fix typo
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2021-05-02 23:25:46 +03:00
1f69048c86 minify switch case
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2021-05-02 23:25:34 +03:00
442aafd2c5 remove redundant dialog import 2021-05-02 23:25:20 +03:00
6082a6549a Merge branch 'master' into interactive-notifications 2021-05-02 22:25:01 +02:00
2567702b44 Merge pull request #236 from Araxeus/precise-volume
[Plugin] Precise volume control
2021-05-02 21:41:17 +02:00
ec981ac547 refactor registerAllShortcuts 2021-04-30 05:09:49 +03:00
d0d4ada7c2 restore original menu lint 2021-04-30 04:33:23 +03:00
54cbe3faa4 lint 2021-04-30 04:29:01 +03:00
49e51de274 update shortcuts config 2021-04-30 04:13:03 +03:00
e456035f29 fix typo 2021-04-30 03:22:36 +03:00
964974c142 add keybind changer v1 2021-04-30 03:04:38 +03:00
b63eb1c8b4 Merge pull request #244 from th-ch/snyk-upgrade-99aee86a0f7b96c0f871bcfabfb6e986
[Snyk] Upgrade electron-store from 7.0.2 to 7.0.3
2021-04-29 23:36:33 +02:00
603bcf7d9d Merge pull request #233 from th-ch/snyk-upgrade-db0717b422c1c3d1fcb50ff90a0b95cd
[Snyk] Upgrade @cliqz/adblocker-electron from 1.20.3 to 1.20.4
2021-04-29 23:34:51 +02:00
TC
0468a23c4f Fix getFolder util (main/renderer process) 2021-04-29 23:28:27 +02:00
f95e29df45 Merge pull request #231 from Araxeus/dependencies-update
Dependencies update
2021-04-29 23:27:21 +02:00
79d95d9477 Merge branch 'master' into dependencies-update 2021-04-29 23:10:52 +02:00
a406ba4ca0 Merge pull request #245 from th-ch/fix-downloader-metadata
Fix downloader metadata
2021-04-29 23:05:17 +02:00
TC
dfbda7c10b Set metadata in back (to have cover) 2021-04-29 22:57:47 +02:00
TC
c11ecd3323 Set max file length to 255 in downloader 2021-04-29 22:57:12 +02:00
TC
8a5c39ee53 Fix download URL 2021-04-29 22:56:33 +02:00
c38035188b fix: upgrade electron-store from 7.0.2 to 7.0.3
Snyk has created this PR to upgrade electron-store from 7.0.2 to 7.0.3.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-04-29 02:19:11 +00:00
TC
ba02d372f7 Update yarn.lock 2021-04-28 22:23:31 +02:00
5312b3694b Merge pull request #196 from semvis123/lastfm
Last.fm support
2021-04-28 22:22:44 +02:00
d0800bb31c small refactor 2021-04-28 16:58:14 +03:00
e272d38ca5 fix typo 2021-04-28 16:54:05 +03:00
66517af81c fix typo 2021-04-28 16:33:12 +03:00
d2925ee3f9 make variable names clearer 2021-04-28 04:30:19 +03:00
729714375b update camelCase 2021-04-28 04:27:50 +03:00
b77643b928 remove proxy from menu 2021-04-28 03:54:59 +03:00
0491babe0a fix typo 2021-04-28 03:36:00 +03:00
0adb36cfb8 leave debug for next PR 2021-04-28 03:08:25 +03:00
8dc486f18f remove local prompt 2021-04-28 02:51:19 +03:00
a229ba9c15 disable reload of plugins on window created 2021-04-28 02:46:13 +03:00
e4eed2e519 add custom-electron-prompt
also use it to set proxy option
2021-04-28 02:41:44 +03:00
395eac26a3 switch function name to camelCase
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2021-04-27 23:52:08 +03:00
e9d7ddebb2 defensive code
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2021-04-27 23:51:29 +03:00
5dc1179d54 implement keybind prompt 2021-04-27 23:48:06 +03:00
8decdf4346 Merge pull request #239 from Araxeus/discord-fix
simple fix for discord plugin
2021-04-27 21:51:07 +02:00
98fd6240ba update inline doc 2021-04-26 21:09:42 +03:00
5a77528526 enable global volume shortcuts in advanced config 2021-04-26 21:01:19 +03:00
d4fdced538 addEventListener insead of .onwheel 2021-04-25 02:22:08 +03:00
8b1bbdf360 Add Video Player Mousewheel Volume Control
(if hide-video-player plugin is disabled)
2021-04-23 05:29:03 +03:00
eae4cca148 Update readme.md 2021-04-23 04:25:48 +03:00
a194046168 win.once() instead of win.on 2021-04-23 04:06:54 +03:00
7c6ed7bb31 once instead of on 2021-04-23 04:01:40 +03:00
20123d8245 revert to original lint format 2021-04-23 03:50:00 +03:00
650945418d simple fix 2021-04-23 03:42:00 +03:00
064facb048 remove slider on-hover after 3 seconds if !focused 2021-04-23 01:20:03 +03:00
0bc1b5e0d3 lint 2021-04-22 16:30:34 +03:00
65f6822199 Show volume slider on volume change 2021-04-22 14:44:37 +03:00
021d2a8a54 disable native volume-slider listeners 2021-04-22 05:34:54 +03:00
5fa8f3ef6f add option for plugin to have a preload.js 2021-04-22 05:34:43 +03:00
10dffdbde2 refactor + lint 2021-04-19 01:45:32 +03:00
72716afcd3 lint 2021-04-18 01:44:18 +03:00
00468c7d0e use timeout ID to stop callback 2021-04-18 00:44:22 +03:00
b7b1316e70 add rapidFire option to counter prompt 2021-04-17 22:55:25 +03:00
97a9e63231 xo --fix 2021-04-17 21:17:07 +03:00
3f50ab7cfc lint 2021-04-17 20:43:48 +03:00
341a06aae7 add prompt with number counter 2021-04-17 20:30:06 +03:00
c48260f10c add advanced option to change volume steps 2021-04-17 16:42:13 +03:00
12a2517697 xo --fix 2021-04-17 15:03:19 +03:00
49698ea669 fix changing settings when plugin is disabled 2021-04-17 05:08:07 +03:00
834202411d enable changing shortcut setting without restart 2021-04-17 04:38:23 +03:00
94e152bb57 add optional arrowkeys controls option 2021-04-17 04:14:54 +03:00
5adcc3efad fix set volume on first run after not using plugin 2021-04-17 02:38:45 +03:00
b65bc65d7c save volume to settings 2021-04-17 02:01:19 +03:00
06958c424c refactor 2021-04-16 23:30:43 +03:00
02896cac03 xo --fix 2021-04-16 23:02:16 +03:00
c0ec1bc5cf update inline doc 2021-04-16 22:37:34 +03:00
40968d573c add precise scrollwheel control + precise tooltip 2021-04-16 21:52:56 +03:00
9f848e3e76 fix: upgrade @cliqz/adblocker-electron from 1.20.3 to 1.20.4
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.20.3 to 1.20.4.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-04-16 02:19:07 +00:00
f765fb63f0 scrape artistName from playBar 2021-04-15 15:59:41 +03:00
ff6a486daf fix unresponsive dialog response 2021-04-15 15:35:22 +03:00
bb6ad14111 navbar background black fix visual bug 2021-04-15 12:40:09 +03:00
a2207a2cb3 remove " - Topic" from artist name 2021-04-14 13:44:32 +03:00
c764d657d7 cleanup unresponsiveDialog 2021-04-14 13:42:39 +03:00
2b6cecc441 Update ytpl 2021-04-12 20:56:52 +03:00
61d83be52e taskbar-mediacontrol no longer override win.hide
(electron 11.4.2 fixed the bug that required that)
2021-04-12 20:19:36 +03:00
9f2362d346 update dependecies 2021-04-12 20:19:35 +03:00
193c3823b6 remove downloads-folder and use electron instead 2021-04-12 20:19:35 +03:00
09d9f72db2 add unresponsive listener 2021-04-10 02:51:38 +03:00
3d41d04818 Revert "fix rare crash due to unfocus effect"
This reverts commit 80b1207640.
2021-04-09 22:28:55 +03:00
46ac0a1ed3 change notification priority to show only on linux 2021-04-09 19:10:20 +03:00
e6d77c165e Center Icon on ALL notifications
Delete notification on windowclosed
Refactor notifications.utils.setOption
2021-04-09 18:39:57 +03:00
18f041f1c6 clarify button purpose 2021-04-09 03:26:46 +03:00
9c0a633677 fix unPause option compatibility 2021-04-09 03:15:57 +03:00
095196785a add note to notifications.interactive 2021-04-09 02:32:14 +03:00
80b1207640 fix rare crash due to unfocus effect 2021-04-09 02:19:06 +03:00
ba6244780c minify 2021-04-09 02:14:11 +03:00
d8dc4656e4 stylecheck 2021-04-09 01:08:22 +03:00
30675e0567 remove appID because of bug:
Button would not transmit event
2021-04-08 18:56:13 +03:00
e6efddc639 add windows interactive notifications 2021-04-08 16:54:46 +03:00
47eace97bd Merge branch 'menu-fixes' of https://github.com/Araxeus/youtube-music into menu-fixes 2021-04-06 21:58:58 +03:00
980ffb45e9 Create readme.md
refactor and css fix

xo --fix

add inline doc

fix typo
2021-04-06 21:57:16 +03:00
17fd499420 fix typo 2021-04-06 01:51:11 +03:00
0e9b15722a add inline doc 2021-04-06 01:30:47 +03:00
724c213af1 xo --fix 2021-04-05 23:18:54 +03:00
a215035d07 refactor and css fix 2021-04-05 18:28:27 +03:00
25d0f50f3d Create readme.md 2021-04-05 04:52:22 +03:00
6d44a579a4 move prompt to provide 2021-04-05 04:21:52 +03:00
106e461beb fix typo 2021-04-05 04:08:55 +03:00
6472002f8a fix hide-menu timing + minify log function 2021-04-05 04:04:29 +03:00
11bd1adbd4 stylecheck 2021-04-05 03:25:45 +03:00
28d366ab19 add back-to-front logger
This somehow fix "did-fail-load" being called on song start, with in-app-plugin-activated
2021-04-05 03:04:06 +03:00
10e29090d8 stylecheck 2021-04-04 21:52:16 +03:00
73b0ddc2ce css tweaks 2021-04-04 21:25:41 +03:00
7c8e946871 implement custom prompt 2021-04-04 19:58:25 +03:00
d12d16348a custom dark skin for prompt 2021-04-04 15:06:14 +03:00
421fe67930 ignore proxy if equal to example 2021-04-04 02:46:12 +03:00
8291cdfc12 disable dev tools on electron-prompt 2021-04-04 02:37:19 +03:00
2e6fffc903 Revert "fix Connection Error when using in-app-menu"
This reverts commit 8b6c60bb17.
2021-04-03 23:46:16 +03:00
8b6c60bb17 fix Connection Error when using in-app-menu 2021-04-03 22:59:20 +03:00
1cae35a62b fix in-app-menu hideMenu on launch 2021-04-03 22:34:12 +03:00
70b03b71e4 refactor and stylecheck 2021-04-03 22:04:40 +03:00
317521bba6 fix memory leak +
in-app-menu updates menu only if needed
2021-04-03 21:53:39 +03:00
061e4a9e5f add 'electron-prompt' and use it for setting proxy 2021-04-03 21:51:35 +03:00
ec3adff706 fix bug when loading window with no connection 2021-04-03 20:15:48 +03:00
5524a14c87 move advanced options to dedicated submenu +
add "Use Proxy" checkbox
2021-04-03 19:20:56 +03:00
e1e8c943f3 Merge branch 'master' into lastfm 2021-04-03 17:21:56 +02:00
0c6630d2d9 additional cleanup/refactoring 2021-04-03 17:12:28 +02:00
80a7d2c255 remove redundant roles 2021-04-03 15:54:51 +03:00
2b3a20c5ff Minimalize tray menu
-doesnt include main menu template anymore
2021-04-03 15:47:32 +03:00
216205200c fix in-app-menu navbar opacity + scrollbar color 2021-04-03 15:30:33 +03:00
TC
61e7124516 Support proxy in advanced options 2021-04-03 12:20:48 +02:00
2ab216effc Merge pull request #215 from th-ch/menu-options
In-app-menu plugin - rename plugin & configure menu builder
2021-04-03 12:10:56 +02:00
TC
1e59301c0e Write metadata in front + pass it along (useful if the song is changed) 2021-04-03 12:04:49 +02:00
TC
d5a2c1cad6 Format front downloader 2021-04-03 12:01:31 +02:00
TC
b5c60ee6a9 Re-format front metadata lib 2021-04-03 11:35:31 +02:00
TC
533b8a8cb7 Metadata: call getImage in front 2021-04-03 11:34:55 +02:00
TC
fecb193ded Re-use default config to get base url in downloader 2021-04-03 11:34:23 +02:00
dc5d257082 Merge pull request #221 from Araxeus/download-song-that-isnt-playing
Allows downloading songs that aren't currently playing
2021-04-03 11:29:20 +02:00
c690473b2e Merge pull request #222 from Keyboardsheep/master
Updated download plugin icon color to match other icons
2021-04-03 10:58:37 +02:00
04fa5eb289 updated download.html svg 2021-04-03 00:10:09 -05:00
d6cd3a0ead updated download.html svg 2021-04-03 00:06:58 -05:00
a23f281734 updated download.html svg 2021-04-03 00:05:36 -05:00
135d58e1f5 updated download.html svg 2021-04-02 23:55:32 -05:00
832ff19e51 allows downloading song that aren't playing 2021-04-03 05:38:21 +03:00
c7bef5ac7b Merge pull request #216 from Araxeus/fix-duplicate-notification
[Notification Plugin] Fix duplicate notification
2021-04-02 23:10:19 +02:00
2254cac15b Merge pull request #213 from th-ch/song-info-front
Pass metadata to front + use metadata URL in downloader
2021-04-02 22:59:57 +02:00
TC
01d574a302 Merge branch 'master' of github.com:th-ch/youtube-music into menu-options
# By Araxeus
# Via GitHub (2) and Araxeus (1)
* 'master' of github.com:th-ch/youtube-music:
  remove 'shortcuts'+'discord' from default plugins
  cleanup styled-bars code
  only refresh if plugin has a menu.js
  update styled-bars to support all changes permantly
  Refresh menu on plugin enable/disable
2021-04-02 22:40:31 +02:00
d67d697847 Merge pull request #217 from Araxeus/Refresh-menu-on-plugin-enable/disable
Refresh menu on plugin enable/disable (show/hide submenu)
2021-04-02 21:43:12 +02:00
8c9e37f8a1 Merge pull request #218 from Araxeus/remove-shortcuts-from-default-plugins
remove 'shortcuts' from default plugins
2021-04-02 21:38:18 +02:00
TC
77393c5324 Replace click callback by override in custom menu 2021-04-02 21:20:50 +02:00
e66db051a9 remove 'shortcuts'+'discord' from default plugins 2021-04-01 21:24:11 +03:00
5670a6d1b4 cleanup styled-bars code 2021-04-01 21:09:31 +03:00
02d45bed74 only refresh if plugin has a menu.js 2021-04-01 19:21:21 +03:00
adc0d145c3 update styled-bars to support
all changes permantly
2021-04-01 19:02:39 +03:00
58481e3133 Refresh menu on plugin enable/disable 2021-04-01 18:10:08 +03:00
a3ec9b7b78 add notification on unpause option 2021-04-01 17:44:40 +03:00
2d534b0293 fix duplicate notification 2021-04-01 15:50:26 +03:00
d73d0cf8ce fix duplicate notification 2021-04-01 15:39:07 +03:00
fbe490c28d Merge remote-tracking branch 'upstream/master' into styled-bars-download-chooser 2021-04-01 02:56:11 +03:00
TC
c09de43154 Rename plugin to in-app-menu + hidden titleBarStyle 2021-03-31 22:37:12 +02:00
TC
be651ebb4b Parameter in menu builder for tray 2021-03-31 22:35:01 +02:00
TC
3fe793cd4d CSS: border radius compatibility 2021-03-31 21:18:31 +02:00
TC
a8cfe399b3 Rename bar var 2021-03-31 21:15:52 +02:00
TC
ff9e39e2ee Re-order dependencies 2021-03-31 21:15:16 +02:00
TC
0d2b61472c Use template builder in custom menu plugin 2021-03-31 21:14:59 +02:00
TC
f9f3482bf1 Pass callback in menu builder 2021-03-31 21:14:55 +02:00
TC
400a2a9bab Add option to menu to render without roles 2021-03-31 20:18:20 +02:00
TC
36864b4c2f Format custom menu plugin 2021-03-31 20:17:12 +02:00
TC
5671b99b7e Format new menu items 2021-03-31 20:15:55 +02:00
76f88686da Merge pull request #201 from Araxeus/styled-bars
[Plugin] styled-bars
2021-03-31 20:07:41 +02:00
ba42a8b269 increase font size for menu and menuItems 2021-03-30 02:18:02 +03:00
ae7def2313 Rename variables and function for clarity 2021-03-30 02:00:35 +03:00
e55176511f Merge pull request #212 from SapuSeven/master
Add configurable notification urgency
2021-03-29 22:42:17 +02:00
TC
640f146373 Use metadata URL in downloader (fallback to current URL) 2021-03-29 22:00:49 +02:00
TC
ebe8755613 Song provider: call callbacks when data is updated 2021-03-29 21:59:45 +02:00
TC
05eee7cb0f Store metadata in front 2021-03-29 21:33:33 +02:00
TC
7ac9fda1eb Send back metadata to front 2021-03-29 21:33:07 +02:00
TC
6987a0a585 Set isPaused default to undefined 2021-03-29 21:32:41 +02:00
1a338fb9e5 Add advanced configuration menu for notifications 2021-03-28 23:33:10 +02:00
8dc18bbe5e Add configurable notification urgency 2021-03-28 23:23:45 +02:00
TC
64c2b32b24 Add url to song info 2021-03-28 22:17:57 +02:00
TC
f01ef5d955 Ensure filename is not empty in downloader plugin 2021-03-28 21:54:21 +02:00
TC
221ee0be05 Order deps in menu file in downloader plugin (+ prettier) 2021-03-28 21:53:50 +02:00
2b8ba02c2a Merge pull request #207 from Araxeus/Download-Plugin-Directory-Chooser
add Download Folder Chooser
2021-03-28 21:51:02 +02:00
TC
b06583afce Bundle imports + prettier 2021-03-28 21:16:33 +02:00
b8b1ae7e88 Merge pull request #194 from semvis123/songprovider-update
Improved songinfo provider, by using the data from the '/player' request
2021-03-28 21:12:03 +02:00
b67b1bed13 refactor for clarity 2021-03-26 20:32:30 +03:00
33fa9f8f50 fix array input + use getFolder() 2021-03-26 17:52:23 +03:00
a7087aaa38 uses getFolder() now 2021-03-26 17:41:12 +03:00
a7170762d4 Merge pull request #10 from Araxeus/Download-Plugin-Directory-Chooser
Download plugin directory chooser
2021-03-26 05:59:45 +03:00
ea3d198723 in tray, delete quit button from submenu
also delete useless nonfunctional view submenu
2021-03-26 05:25:46 +03:00
fe8f048571 add Download Folder Chooser 2021-03-26 04:07:45 +03:00
09d2feb15b Add quit + restart button to main menu ) 2021-03-26 00:24:03 +02:00
33d4c1a60e Refactor into switchMenuVisibility 2021-03-26 00:23:28 +02:00
cbd7a13275 Merge pull request #180 from th-ch/snyk-upgrade-58542eeb4b38266ae86c95a43f335043
[Snyk] Upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1
2021-03-25 22:22:23 +01:00
903b7f8718 lint 2021-03-25 23:16:00 +02:00
TC
88cd1651c3 Clean metadata + apply pngcrush on images in taskbar plugin 2021-03-25 22:15:39 +01:00
13ff5f26a2 Plugin doesn't create a new menu anymore
instead it modifies the original menu
2021-03-25 23:13:54 +02:00
57345a5fd2 Merge pull request #200 from Araxeus/master
[Plugin] taskbar-mediacontrol  (for Windows)
2021-03-25 22:11:49 +01:00
bd82bd2249 added extra comments and corrected existing ones 2021-03-25 21:27:33 +01:00
f253a69656 added comment for the added function 2021-03-25 21:11:55 +01:00
493a5835f8 Merge branch 'master' into lastfm 2021-03-25 20:34:40 +01:00
bffbcb229d Made the suffixes configurable and added VEVO suffix to remove 2021-03-25 20:15:43 +01:00
b5ec431b0a Merge remote-tracking branch 'upstream/master' into styled-bars 2021-03-25 18:39:06 +02:00
259706478f Merge remote-tracking branch 'upstream/master' 2021-03-25 18:33:48 +02:00
c9f172ef21 fix scrollbar clash with nav bar 2021-03-25 16:43:01 +02:00
eb32c98b76 fix tray option radio selection 2021-03-25 07:51:06 +02:00
95c3f04c10 more fixes for plugin options menu 2021-03-25 02:18:23 +02:00
d4daf7231c merge source (#3)
* Added Discord timeout

* Add getOptions in plugin util

* Mutex in ffmpeg conversion (only supports one command at a time)

* Add menu customization in plugin system

* Add ytpl package (playlist info)

* Handle ffmpeg metadata flags when metadata is not present

* Only use artist in file name if present

* Export sendError method

* Handle image not present in metadata util

* Add downloader utils (getFolder and default menu label)

* Pass (optional) existing metadata and subfolder in mp3 converter

* Add listener to download playlist

* Add custom menu in downloader plugin ("download playlist" item)

* nit: fix main CSS style

* Only set the "enable" item in menu if plugin not enabled

* Navigation plugin: inject HTML once CSS is loaded

Co-authored-by: Sem Visscher <semvisscher10@gmail.com>
Co-authored-by: TC <th-ch@users.noreply.github.com>
2021-03-25 01:36:22 +02:00
9a95f435ad merge source (#2)
* Added Discord timeout

* Add getOptions in plugin util

* Mutex in ffmpeg conversion (only supports one command at a time)

* Add menu customization in plugin system

* Add ytpl package (playlist info)

* Handle ffmpeg metadata flags when metadata is not present

* Only use artist in file name if present

* Export sendError method

* Handle image not present in metadata util

* Add downloader utils (getFolder and default menu label)

* Pass (optional) existing metadata and subfolder in mp3 converter

* Add listener to download playlist

* Add custom menu in downloader plugin ("download playlist" item)

* nit: fix main CSS style

* Only set the "enable" item in menu if plugin not enabled

* Navigation plugin: inject HTML once CSS is loaded

Co-authored-by: Sem Visscher <semvisscher10@gmail.com>
Co-authored-by: TC <th-ch@users.noreply.github.com>
2021-03-25 01:02:42 +02:00
5218b80cab preparation for plugin menu update 2021-03-25 01:00:06 +02:00
TC
b1665c880b Navigation plugin: inject HTML once CSS is loaded 2021-03-24 23:06:35 +01:00
6395dfe425 Merge pull request #203 from th-ch/downloader-plugin-playlist
Add playlist feature in downloader plugin + custom menus in plugin system
2021-03-24 22:39:50 +01:00
304ad6e767 Merge pull request #192 from semvis123/master
Added Discord timeout
2021-03-24 22:38:56 +01:00
TC
587a093aff Only set the "enable" item in menu if plugin not enabled 2021-03-24 21:55:53 +01:00
TC
91b49e4a16 nit: fix main CSS style 2021-03-24 21:52:33 +01:00
TC
e72915c5d0 Add custom menu in downloader plugin ("download playlist" item) 2021-03-24 21:52:12 +01:00
TC
bee2da567b Add listener to download playlist 2021-03-24 21:51:11 +01:00
TC
951689c5ea Pass (optional) existing metadata and subfolder in mp3 converter 2021-03-24 21:50:46 +01:00
TC
4146ae60bc Add downloader utils (getFolder and default menu label) 2021-03-24 21:50:31 +01:00
TC
6bcf5efb65 Handle image not present in metadata util 2021-03-24 21:48:12 +01:00
TC
ddf10f1052 Export sendError method 2021-03-24 21:45:59 +01:00
TC
7edca44ed8 Only use artist in file name if present 2021-03-24 21:44:54 +01:00
TC
ebc3f16597 Handle ffmpeg metadata flags when metadata is not present 2021-03-24 21:44:54 +01:00
TC
9dad31775c Add ytpl package (playlist info) 2021-03-24 21:44:54 +01:00
TC
b1089b66c3 Add menu customization in plugin system 2021-03-24 21:44:54 +01:00
TC
84142ab27e Mutex in ffmpeg conversion (only supports one command at a time) 2021-03-24 21:44:48 +01:00
TC
fd518e39ff Add getOptions in plugin util 2021-03-24 21:36:17 +01:00
2fb4cbcf02 move icons to 'assets' folder 2021-03-24 19:38:45 +02:00
d3337c7d3c titlebar dragArea fix + refactor 2021-03-24 00:13:38 +02:00
5fd11bf009 fixed search page header height 2021-03-23 22:15:16 +02:00
92603a1e7f fix search button alignment 2021-03-23 22:09:10 +02:00
7d8afe3476 style check 2021-03-23 22:03:48 +02:00
f9c66ead50 css color fix 2021-03-23 19:47:47 +02:00
a12d5a982f fix library UI bug 2021-03-23 19:29:07 +02:00
c1f176fa21 Fixed MenuItem roles + add restart+quit button 2021-03-23 16:17:50 +02:00
f1dbe4ab6c Allow hide menu options (uses Escape key) 2021-03-23 15:07:31 +02:00
459ebf7070 xo lint --fix 2021-03-23 03:58:19 +02:00
8cf0ec16bb Merge branch 'styled-bars' of https://github.com/Araxeus/youtube-music into styled-bars 2021-03-23 03:51:16 +02:00
87558c67c8 stylecheck 2021-03-23 03:50:59 +02:00
8727a2e299 separate plugins to different branches 2021-03-23 02:51:12 +02:00
b8c5c87cfa Styled Bars [Titlebar + Scrollbar] 2021-03-23 02:46:13 +02:00
ce2970eefa fixed line that xo-lint broke 2021-03-22 13:48:08 +02:00
24fea5a24a added back original yarn.lock
(was deleted by accident)
2021-03-22 04:22:23 +02:00
5285680eed xo lint --fix 2021-03-22 04:17:39 +02:00
17e63194ad fixed typo bug 2021-03-22 04:06:42 +02:00
6427b3406c Override hide(),show(),isVisible from inside plugin
instead of changing source code
2021-03-22 04:01:19 +02:00
df8c77cd3e Wait for song to start before setting thumbar 2021-03-22 03:01:46 +02:00
41796aec06 Tray Break Thumbar Fix
using  win.minimize()
and win.setSkipTaskbar(bool)
instead of win.hide() / win.show()
2021-03-22 01:26:20 +02:00
1355b692b9 Remove the - Topic for more matches 2021-03-21 22:28:05 +01:00
2c13ef40e2 taskbar-mediacontrol plugin
Add UI Control to windows taskbar preview
2021-03-21 20:08:07 +02:00
2bb67db888 Fixed backwards compatibility 2021-03-21 18:47:16 +01:00
204f384d01 fetch highest resolution image instead of lowest resolution 2021-03-21 14:14:26 +01:00
42e3d48caf Added now playing to last-fm 2021-03-19 22:00:00 +01:00
4747050b60 Added working lastfm support
currently only played songs are added
2021-03-19 21:32:33 +01:00
TC
c926db7f13 Increase top margin for MacOS 2021-03-18 22:12:18 +01:00
TC
8cce3f4503 Add view/navigation menu 2021-03-18 22:02:19 +01:00
3464b0383c small readability changes 2021-03-18 17:53:30 +01:00
d852029d25 Improved songinfo provider, by using the data from the '/player' request 2021-03-18 17:48:56 +01:00
ca8d62d4e2 Added Discord timeout 2021-03-17 10:22:19 +01:00
0632920a6f fix: upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.20.0 to 1.20.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-03-10 02:19:11 +00:00
c5bda4f3be Merge pull request #178 from th-ch/snyk-upgrade-da4beb25f2fa1631098996298cd49f89
[Snyk] Upgrade electron-store from 7.0.1 to 7.0.2
2021-03-09 19:50:17 +01:00
3dc92b4939 fix: upgrade electron-store from 7.0.1 to 7.0.2
Snyk has created this PR to upgrade electron-store from 7.0.1 to 7.0.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-03-05 02:19:09 +00:00
TC
150146385f Bump version 2021-03-04 23:09:27 +01:00
TC
f50bd32fa3 Fix resumeOnStart option 2021-03-04 23:09:01 +01:00
0dcf820944 Merge pull request #177 from NNowakowski/resume-last-song-on-start
Added function to toggle resuming of last song when app starts
2021-03-04 22:57:41 +01:00
6fd16684f7 Merge pull request #175 from th-ch/snyk-upgrade-024effb4b0bec6e73345b87366580cf3
[Snyk] Upgrade discord-rpc from 3.1.4 to 3.2.0
2021-03-04 22:54:13 +01:00
TC
eaa957168f Add plugin to disable autoplay 2021-03-04 22:47:53 +01:00
TC
796a7aaaf1 Fix download/speed menu item 2021-03-04 21:29:37 +01:00
9aaae7b2d9 🚀 Added function to toggle resuming of last song when app starts 2021-03-04 14:14:49 +01:00
c00609223b fix: upgrade discord-rpc from 3.1.4 to 3.2.0
Snyk has created this PR to upgrade discord-rpc from 3.1.4 to 3.2.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-03-04 02:19:26 +00:00
5641c3fc87 Merge pull request #154 from th-ch/snyk-upgrade-3f26f6e01fe99104189d358a840963dd
[Snyk] Upgrade @cliqz/adblocker-electron from 1.19.0 to 1.20.0
2021-02-24 23:11:02 +01:00
dd1bdae947 Added metadata to downloader plugin, and updated packages 2021-02-24 22:53:31 +01:00
TC
70973b2281 Clear cache after 20s if option is enabled 2021-02-24 21:08:25 +01:00
TC
5842a6d42f Handle uncaught errors 2021-02-24 20:53:41 +01:00
538ab52abd fix: upgrade @cliqz/adblocker-electron from 1.19.0 to 1.20.0
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.19.0 to 1.20.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-02-12 02:19:15 +00:00
TC
5a1358b310 Bump version 2021-02-07 18:30:01 +01:00
TC
024ed9085c Allow custom shortcuts in plugin 2021-02-07 18:29:35 +01:00
TC
b2c9e445b7 Fix shortcuts 2021-02-07 18:29:08 +01:00
TC
5b8d5d5ee4 Do not run the app after Windows install 2021-02-07 14:43:37 +01:00
TC
a82efaf91b Bump YoutubeNonStop 2021-02-07 14:38:30 +01:00
TC
980090f108 Remember window position 2021-02-07 13:25:01 +01:00
TC
f7f31850d3 Add plugin to control playback speed like in YouTube (from 0.25 to 2) 2021-02-07 11:46:57 +01:00
3415ce3965 Merge pull request #146 from th-ch/snyk-upgrade-aba6333ac62e918200d72118a7613fb6
[Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.6 to 0.9.7
2021-02-06 22:34:21 +01:00
436d9ef3e1 Merge pull request #144 from semvis123/master
Reuse the same notification, instead of creating a new one each time the song changes.
2021-02-06 22:30:35 +01:00
TC
da61621a62 Check updates after 2s 2021-02-06 22:25:23 +01:00
TC
3976d1c862 Add option to reset cache 2021-02-06 22:15:57 +01:00
a9980190d0 fix: upgrade @ffmpeg/ffmpeg from 0.9.6 to 0.9.7
Snyk has created this PR to upgrade @ffmpeg/ffmpeg from 0.9.6 to 0.9.7.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-02-05 02:19:17 +00:00
e75dfcf41c little fixes 2021-02-01 22:00:18 +01:00
1fdf2416ad Update back.js 2021-02-01 21:34:56 +01:00
df627788c9 small formatting changes 2021-02-01 20:23:46 +01:00
c1ee58b47f Reuse the same notifcation, instead of creating a new notification each time. 2021-02-01 20:18:16 +01:00
d6f7c54370 Merge pull request #136 from th-ch/snyk-upgrade-57f12acf80f9a08801a63b7852a10ff8
[Snyk] Upgrade ytdl-core from 4.2.1 to 4.3.0
2021-01-23 12:53:18 +01:00
3a03fb51cd fix: upgrade ytdl-core from 4.2.1 to 4.3.0
Snyk has created this PR to upgrade ytdl-core from 4.2.1 to 4.3.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-01-22 02:21:11 +00:00
TC
e19964edf6 GH page: fix canvas size 2021-01-18 21:58:18 +01:00
TC
3bcf409f2b GH page 2021-01-17 20:32:23 +01:00
TC
37289b9cbe Downloader: 'artist - title' format for filename 2021-01-16 10:19:10 +01:00
TC
227902b7cc Add shortcuts to provider 2021-01-15 23:16:47 +01:00
TC
644950ccc0 Bump version 2021-01-15 09:31:34 +01:00
TC
d848937e6a Rename discord plugin 2021-01-14 23:16:59 +01:00
446aa8becc Merge pull request #121 from th-ch/snyk-upgrade-d29b51f488ba9deb228b72952a3f7b8e
[Snyk] Upgrade electron-debug from 3.1.0 to 3.2.0
2021-01-14 23:12:27 +01:00
TC
d52dbee13c Prettier utils 2021-01-14 23:09:16 +01:00
TC
ed09304ed7 Refactor tray to use provider + play/pause on click 2021-01-14 23:09:04 +01:00
TC
2861473097 Set title/artist metadata in downloader 2021-01-14 23:01:26 +01:00
39dc22973e Merge pull request #1 from th-ch/master
bring the new commits to this fork
2021-01-14 22:24:21 +01:00
25fd48697b Merge pull request #125 from th-ch/refactor-providers
Refactor providers
2021-01-14 21:03:26 +01:00
TC
aec542e95e Update discord plugin for new provider + wait for ready 2021-01-13 22:22:22 +01:00
TC
eae95befe1 Merge branch 'master' of github.com:th-ch/youtube-music into refactor-providers
# By TC (9) and semvis123 (2)
# Via GitHub (4) and semvis123 (1)
* 'master' of github.com:th-ch/youtube-music:
  renamed DiscordRPC to Discord
  Downloader plugin: log audio bitrate
  Disable context isolation (to load ffmpeg wasm)
  Use contextBridge in preload script + update navigation plugin
  Fix downloader plugin with context isolation
  Bump version
  Add portable target to windows builds
  Added Discord rich presence and added extra properties to songinfo provider
  Bump version
  Allow custom audio extensions in downloader
  Defensive: handle null/undefined ffmpeg args
2021-01-13 22:10:10 +01:00
f0200e7b38 Merge pull request #124 from semvis123/master
Added Discord rich presence and added extra properties to songInfo provider
2021-01-13 22:08:10 +01:00
70775f4988 renamed DiscordRPC to Discord 2021-01-13 21:56:53 +01:00
074840ef56 Merge pull request #127 from th-ch/fix-plugins-context-isolation
Fix plugins with context isolation
2021-01-13 21:44:37 +01:00
TC
b54c501eeb Downloader plugin: log audio bitrate 2021-01-13 21:36:16 +01:00
6d587cb432 Merge pull request #126 from th-ch/windows-portable
Windows portable exe
2021-01-13 21:32:53 +01:00
TC
39c8031cd7 Disable context isolation (to load ffmpeg wasm) 2021-01-13 21:28:42 +01:00
TC
9ad1dad6df Use contextBridge in preload script + update navigation plugin 2021-01-12 22:54:04 +01:00
TC
79e8fc2fac Fix downloader plugin with context isolation 2021-01-12 22:52:21 +01:00
TC
67c4422eb8 Bump version 2021-01-12 21:37:02 +01:00
TC
18df1223af Add portable target to windows builds 2021-01-12 21:36:38 +01:00
0fafed7c53 Merge pull request #118 from th-ch/dl-custom-audio-format
Downloader plugin - custom audio format
2021-01-12 21:35:55 +01:00
TC
f7cbf2c221 No autoloading of providers (loaded on demand in plugins) 2021-01-12 21:19:01 +01:00
TC
87d2693e2b Use refactored provider in shortcuts plugin 2021-01-12 21:18:32 +01:00
TC
de1e4196d9 Use refactored provider in notification plugin 2021-01-12 21:18:05 +01:00
TC
9110e79c16 Use refactored providers in touchbar plugin 2021-01-12 21:17:40 +01:00
TC
0743034de0 Split providers in 2 2021-01-12 21:17:08 +01:00
TC
f1ddb92886 nit: prettier 2021-01-12 21:16:29 +01:00
a8ce87f2cc Added Discord rich presence and added extra properties to songinfo provider 2021-01-12 20:16:49 +01:00
86a329a61b fix: upgrade electron-debug from 3.1.0 to 3.2.0
Snyk has created this PR to upgrade electron-debug from 3.1.0 to 3.2.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-01-12 02:24:30 +00:00
77e24f41a5 Merge pull request #102 from semvis123/master
Globalized the song info and song controls, and updated Touch Bar for it.
2021-01-10 22:15:11 +01:00
3a5d9bd973 Loads providers before plugins 2021-01-10 21:37:50 +01:00
69f486d53f moved the song info file and removed the capital letters in folder name 2021-01-10 21:22:01 +01:00
5d89043884 fixed typo, plugins/songInfo/back.js
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2021-01-10 20:31:55 +01:00
2b297c245a Merge pull request #120 from th-ch/bump-electron
Bump electron to v11
2021-01-10 14:37:07 +01:00
TC
945a61fafd Remove warning by setting contextIsolation 2021-01-10 14:10:16 +01:00
TC
1ba166a172 Bump electron to v11 2021-01-10 12:29:12 +01:00
TC
a9a840b6c3 Bump version 2021-01-08 22:41:17 +01:00
TC
6a100c8cb1 Allow custom audio extensions in downloader 2021-01-08 22:29:25 +01:00
TC
b04e2ea130 Defensive: handle null/undefined ffmpeg args 2021-01-08 22:26:44 +01:00
5ac356bf91 Merge pull request #116 from th-ch/snyk-upgrade-041c3272121410c1cb380e1fbc7f9dce
[Snyk] Upgrade electron-updater from 4.3.5 to 4.3.6
2021-01-08 21:29:50 +01:00
35ceb7e83e Merge pull request #117 from th-ch/snyk-upgrade-7528cf91d37d9330a45f611ce738e40e
[Snyk] Upgrade @cliqz/adblocker-electron from 1.18.8 to 1.19.0
2021-01-08 21:28:08 +01:00
5c0cc08d80 fix: upgrade @cliqz/adblocker-electron from 1.18.8 to 1.19.0
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.18.8 to 1.19.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-01-07 02:19:51 +00:00
0bf77e592a fix: upgrade electron-updater from 4.3.5 to 4.3.6
Snyk has created this PR to upgrade electron-updater from 4.3.5 to 4.3.6.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2021-01-05 02:20:56 +00:00
ec3c1578d2 Merge pull request #109 from th-ch/snyk-upgrade-4e8a81615c57edf69b21ad2a68431dfd
[Snyk] Upgrade ytdl-core from 4.1.1 to 4.1.2
2020-12-29 16:35:55 +01:00
e8ed580ecc Merge pull request #104 from th-ch/dependabot/npm_and_yarn/node-notifier-8.0.1
Bump node-notifier from 8.0.0 to 8.0.1
2020-12-29 16:30:59 +01:00
e2cc2628ae fix: upgrade ytdl-core from 4.1.1 to 4.1.2
Snyk has created this PR to upgrade ytdl-core from 4.1.1 to 4.1.2.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-12-25 02:20:03 +00:00
9e31e753f0 Bump node-notifier from 8.0.0 to 8.0.1
Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/v8.0.1/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-22 16:02:44 +00:00
588e0019d6 Changed function style in notifications 2020-12-21 22:11:23 +01:00
5bffdbd628 Simplifies the notification plugin to use the globalized song info 2020-12-21 21:35:02 +01:00
ee239da647 removed unnecessary await keyword 2020-12-21 21:11:00 +01:00
9be3e1afe9 Globalized the songinfo and song controls, and changed the pause/play button.
Globalized the songinfo and song controls, and changed the pause/play button. The songInfo file should eventually get another location, because it isn't really a plugin.
2020-12-21 18:18:34 +01:00
TC
af02b60ce3 Bump version 2020-12-20 20:17:24 +01:00
fbdae0452c Add touchbar plugin to list 2020-12-20 20:16:35 +01:00
d68d73eb4c Merge pull request #101 from semvis123/master
Added Touch Bar plugin
2020-12-20 20:14:49 +01:00
2de27d2e24 Merge pull request #99 from th-ch/snyk-upgrade-d3ff12c0e23681ac817994e603d37491
[Snyk] Upgrade @ffmpeg/core from 0.8.4 to 0.8.5
2020-12-19 22:03:40 +01:00
TC
15591e24d7 Merge branch 'master' of github.com:th-ch/youtube-music into snyk-upgrade-d3ff12c0e23681ac817994e603d37491
# By snyk-bot
# Via GitHub (1) and snyk-bot (1)
* 'master' of github.com:th-ch/youtube-music:
  fix: upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6
2020-12-19 21:50:24 +01:00
715d59e3d4 Merge pull request #100 from th-ch/snyk-upgrade-9aa7c0fdfaaeba26ca66fb92b731a1af
[Snyk] Upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6
2020-12-19 21:32:10 +01:00
f71e0e9da9 Switched like/dislike positions
Switched like/dislike positions to match youtube musics layout
2020-12-16 20:30:01 +01:00
ba3779db07 Updated comment - touchbar plugin 2020-12-16 20:10:05 +01:00
d99aa0242f Added like and dislike buttons 2020-12-16 19:54:44 +01:00
3ea859de09 Added song image 2020-12-16 19:44:26 +01:00
7473677477 touchbar plugin - fixed code style 2020-12-16 15:57:24 +01:00
c3e2c13808 added initial touchbar support 2020-12-16 15:52:01 +01:00
5074ba2f48 fix: upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6
Snyk has created this PR to upgrade @ffmpeg/ffmpeg from 0.9.5 to 0.9.6.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-12-16 02:20:20 +00:00
a8b8f1079f fix: upgrade @ffmpeg/core from 0.8.4 to 0.8.5
Snyk has created this PR to upgrade @ffmpeg/core from 0.8.4 to 0.8.5.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-12-16 02:20:16 +00:00
e52987df92 Merge pull request #96 from th-ch/svg-readme
[Readme] Web folder for readme assets + new SVG animation
2020-12-13 16:40:55 +01:00
TC
01fc965170 Web folder for readme assets + new svg animation 2020-12-13 16:19:33 +01:00
ff71f29206 Merge pull request #94 from th-ch/linux-deb-rpm
Add new Linux targets (deb, freebsd, rpm)
2020-12-13 13:40:07 +01:00
TC
a47c5144ac Additional linux targets 2020-12-12 23:08:05 +01:00
TC
9b979b2273 Bump version 2020-12-12 22:28:38 +01:00
TC
81198192bb Add new linux targets (deb, rpm) 2020-12-12 22:28:30 +01:00
c03a08e76a Merge pull request #92 from th-ch/dependabot/npm_and_yarn/ini-1.3.7
Bump ini from 1.3.5 to 1.3.7
2020-12-12 11:26:49 +01:00
807e21eabf Bump ini from 1.3.5 to 1.3.7
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-11 18:36:02 +00:00
36f9d640df Merge pull request #90 from th-ch/adblocking
Fix adblocking
2020-12-11 19:35:10 +01:00
TC
39f30b143b Bump version to 1.7.4 2020-12-10 18:42:17 +01:00
TC
49497d0efb Bump adblocker dependency 2020-12-10 18:42:00 +01:00
TC
79c795927a Add uBlock Origin filters to default sources 2020-12-10 18:40:31 +01:00
TC
66c5ce46ca Fix adblocker preloading to inject scripts/styles 2020-12-10 18:39:58 +01:00
TC
22c7f70c93 Adblocker: add option to disable default lists 2020-12-08 21:40:03 +01:00
TC
467171a17e Bugfix: only use cache with no additional blocklists 2020-12-06 17:55:51 +01:00
3022facbea Readme: add youtube-music logo to badges 2020-12-05 12:33:26 +01:00
a67bf5ea43 Readme: add link to releases 2020-12-05 12:31:14 +01:00
3a1a3d4241 Merge pull request #82 from hbarsaiyan/master
Add AUR badge + beautify badges
2020-12-05 12:29:26 +01:00
9197f4a0e1 Add link to AUR badge
Co-authored-by: th-ch <th-ch@users.noreply.github.com>
2020-12-05 16:18:54 +05:30
d21220693b Add AUR tag + beautify tags 2020-12-05 08:07:17 +00:00
TC
e07cac2406 Bump version to 1.7.1 2020-12-03 22:30:15 +01:00
TC
fd97576611 Option to restart the app on config changes 2020-12-03 22:29:46 +01:00
6ab01056e0 Merge pull request #79 from th-ch/advanced-config
Refactor config, custom plugin options
2020-12-03 21:48:57 +01:00
TC
4dcbd2e7f0 Add plugin options in migration 2020-12-03 20:43:04 +01:00
TC
b94d0d4e8b Adblocker - advanced options (caching or not, additional lists) 2020-12-03 20:43:04 +01:00
TC
7b20b9339d Download plugin - advanced options (folder, FFmpeg args) 2020-12-03 20:43:04 +01:00
TC
4d4a1f038b Custom plugin options 2020-12-03 20:42:58 +01:00
TC
e5ec79e345 Watch changes in config and update menu 2020-12-03 18:31:01 +01:00
TC
f4fe5c2a58 Allow editing config (advanced) 2020-12-03 18:25:31 +01:00
TC
a5130c1d3f Move migrations into separate const 2020-12-03 18:25:08 +01:00
TC
8ab2da0482 Refactor config for simpler use and advanced options in plugins 2020-12-03 18:16:37 +01:00
TC
1b54b19f3f Add "build:linux" script 2020-12-02 22:22:05 +01:00
TC
be7e6e431f Bump version to 1.6.5 2020-12-02 22:14:43 +01:00
6e42b097f8 Merge pull request #77 from th-ch/disable-hardware-acceleration
Add option to disable hardware acceleration
2020-12-02 22:12:42 +01:00
TC
ef9cd8cd24 Add option to disable hardware acceleration 2020-12-02 22:07:15 +01:00
8f3e165917 Merge pull request #76 from th-ch/downloader-plugin-retry-and-upgrade-dep
Downloader plugin - retry and upgrade dependencies
2020-12-02 21:41:04 +01:00
TC
33a11efe9a Update ytdl-core to 4.1.1 2020-12-02 21:16:39 +01:00
TC
9a97436cd8 Allow up to 3 retries in downloader 2020-12-02 21:16:12 +01:00
f7935c0024 Merge pull request #70 from hbarsaiyan/master
Reflect Arch Linux package name change
2020-11-29 21:17:02 +01:00
2b33d4e857 Reflect Arch Linux package name change
Package name has been changed to youtube-music-bin.
2020-11-29 23:57:07 +05:30
ed16c35a57 Merge pull request #67 from th-ch/hide-menu
Option to hide menu
2020-11-28 18:45:53 +01:00
TC
ae5b85d8d7 Autoupdate modal: add download/disable updates buttons 2020-11-28 18:13:41 +01:00
47b4414eb3 Merge pull request #68 from hbarsaiyan/master
Add Arch Linux installation instructions
2020-11-28 11:09:07 +01:00
e329bb2201 Add Arch Linux installation instructions 2020-11-28 15:22:34 +05:30
TC
155ef9e5f5 Bump version 2020-11-27 21:39:33 +01:00
TC
4bac3ace18 Option to hide menu (win/linux) 2020-11-27 21:39:15 +01:00
1d2b53f6ee Merge pull request #64 from th-ch/ci
Improve CI
2020-11-24 00:32:07 +01:00
TC
0fd49330d3 CI: cache yarn directory 2020-11-24 00:13:01 +01:00
TC
4b0e79345f Fail fast (Can only re-run all jobs, not just one) 2020-11-24 00:13:01 +01:00
0c819e9aa9 Merge pull request #63 from th-ch/menu-visible
Ensure menu is visible on all platforms
2020-11-23 23:41:07 +01:00
20d591c554 Merge pull request #62 from th-ch/snyk-upgrade-407335ffa685010c89f68cbb1a8b27a6
[Snyk] Upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4
2020-11-23 23:29:04 +01:00
TC
002469a98d Bump adblocker 2020-11-23 23:16:54 +01:00
TC
3bc8430201 No CI run on pull_request (already on every push) 2020-11-23 23:11:44 +01:00
TC
db447a5d62 Bump patch version 2020-11-23 23:04:16 +01:00
TC
72527d0522 Disable autoHideMenuBar (so menu bar is always visible) 2020-11-23 22:59:48 +01:00
TC
cf4827d780 Run CI on every push/PR 2020-11-23 22:55:20 +01:00
TC
9b02591767 Test that menu bar is visible 2020-11-23 22:52:00 +01:00
2b243f6dcb fix: upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.18.3 to 1.18.4.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-11-23 02:19:19 +00:00
TC
4d4aadfdfc Re-init download button in case of error 2020-11-22 10:23:20 +01:00
2937db3dde Update plugins list in readme 2020-11-22 10:20:03 +01:00
TC
e1166c06fa Do not cancel CI jobs if one fails 2020-11-22 10:10:31 +01:00
3ee0777628 Merge pull request #60 from th-ch/github-action
Add github action to build/release
2020-11-22 01:01:05 +01:00
3441a6f215 Link build badge to releases 2020-11-22 00:40:47 +01:00
235150a0cc Update build badge (GitHub Actions) 2020-11-22 00:34:49 +01:00
c1427c24d8 Merge pull request #59 from th-ch/node-12
Bump to node 12
2020-11-22 00:33:51 +01:00
TC
941dd90d77 Delete AppVeyor/Travis CI integration 2020-11-22 00:14:28 +01:00
TC
3da76020b1 Bump version (new release through GH actions) 2020-11-22 00:13:46 +01:00
TC
575dc5177d Use xvfb to run tests on linux 2020-11-22 00:04:08 +01:00
TC
27255dc477 Add GH token env var from secret 2020-11-21 23:53:36 +01:00
TC
fc4754a170 GH action to build/release 2020-11-21 23:38:04 +01:00
2e3a177f01 Merge pull request #59 from th-ch/node-12
Bump to node 12
2020-11-21 23:19:39 +01:00
TC
059f756d89 Bump to node 12 2020-11-21 22:54:43 +01:00
TC
e197087a50 Add downloader (video -> mp3) plugin (in music menu) 2020-11-21 22:50:33 +01:00
TC
e0f61f128e Bump version 2020-11-13 22:21:31 +01:00
TC
9ee7598375 Auto-hide menu bar 2020-11-13 22:16:11 +01:00
TC
fc48b920a8 Bump app version to 1.6.0 2020-11-11 12:22:36 +01:00
TC
9bc81da6f2 Plugins/event handlers in each window 2020-11-11 12:16:01 +01:00
TC
2b3363f5dc Bump YoutubeNonStop 2020-11-11 11:36:40 +01:00
TC
bcff6e5134 Add notifications plugin (notify of song on play event) 2020-11-11 11:35:58 +01:00
1dcf76b006 Merge pull request #54 from th-ch/snyk-upgrade-1b704161a30f8a56030e33c24f620f14
[Snyk] Upgrade electron-store from 6.0.0 to 6.0.1
2020-11-04 22:36:53 +01:00
7bdc0f42a2 fix: upgrade electron-store from 6.0.0 to 6.0.1
Snyk has created this PR to upgrade electron-store from 6.0.0 to 6.0.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-10-27 02:19:22 +00:00
TC
023f5b6bc3 Block alert if leaving page when playing (onbeforeunload event) 2020-10-19 22:44:39 +02:00
TC
3e97e9307c Option to toggle devtools 2020-10-18 17:02:12 +02:00
TC
4299ba7865 Update version to 1.5.0 2020-10-04 18:27:07 +02:00
TC
855d8007a7 Add plugin to hide video player 2020-10-04 18:23:30 +02:00
TC
f239ec3232 Force yargs-parser version to fix vulnerability 2020-10-04 18:08:15 +02:00
TC
5f0dcbb3fc Bump electron to v10 (+ remove devtron, bump spectron) 2020-10-04 17:39:18 +02:00
TC
97dce5ad41 Bump dependencies 2020-10-04 17:20:43 +02:00
TC
1b3e4df1b2 Tests: get electron path using require 2020-10-04 17:18:33 +02:00
TC
8d74a0a9b5 Navigation plugin: fix arrow style 2020-10-04 15:06:52 +02:00
fbce109554 Merge pull request #45 from th-ch/dependabot/npm_and_yarn/node-fetch-2.6.1
Bump node-fetch from 2.6.0 to 2.6.1
2020-10-04 14:18:24 +02:00
f4641acdbb Merge pull request #47 from th-ch/snyk-upgrade-468d0cfdab69d8231f03ed7e76703d57
[Snyk] Upgrade @cliqz/adblocker-electron from 1.17.0 to 1.18.0
2020-10-04 14:16:16 +02:00
02ae9f8187 Bump node-fetch from 2.6.0 to 2.6.1
Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-04 12:15:45 +00:00
9f428415bb Merge pull request #40 from th-ch/snyk-upgrade-2d5f77a2ca49e9d611dfcac4a5d0c7e1
[Snyk] Upgrade electron-updater from 4.3.3 to 4.3.4
2020-10-04 14:14:57 +02:00
c7d3741b97 fix: upgrade @cliqz/adblocker-electron from 1.17.0 to 1.18.0
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.17.0 to 1.18.0.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-09-15 02:19:07 +00:00
6404ec0919 fix: upgrade electron-updater from 4.3.3 to 4.3.4
Snyk has created this PR to upgrade electron-updater from 4.3.3 to 4.3.4.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-08-07 02:19:20 +00:00
4cd2d10cad Merge pull request #38 from th-ch/dependabot/npm_and_yarn/elliptic-6.5.3
Bump elliptic from 6.5.2 to 6.5.3
2020-08-03 10:44:10 +02:00
57f5d302d5 Merge pull request #37 from th-ch/snyk-upgrade-414f996ee5dc52155ccdd3d4b64505ac
[Snyk] Upgrade @cliqz/adblocker-electron from 1.16.0 to 1.16.1
2020-08-03 10:42:30 +02:00
168524ba50 Merge pull request #34 from th-ch/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-08-03 10:39:29 +02:00
149362f2a7 Bump elliptic from 6.5.2 to 6.5.3
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-01 20:48:22 +00:00
6c330046b7 fix: upgrade @cliqz/adblocker-electron from 1.16.0 to 1.16.1
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.16.0 to 1.16.1.

See this package in npm:


See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-07-30 02:19:12 +00:00
884a2cc226 Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-19 21:35:20 +00:00
3882118121 Merge pull request #32 from th-ch/start-at-login
Option to start at login
2020-07-13 11:25:32 +02:00
TC
0fd2e7f51c Bump version to 1.4.0 2020-07-12 21:14:41 +02:00
TC
408aa9bb59 Option to start at login 2020-07-12 21:14:41 +02:00
eec6993b95 Merge pull request #31 from th-ch/dependabot/npm_and_yarn/electron-8.2.4
Bump electron from 8.2.1 to 8.2.4
2020-07-12 21:13:56 +02:00
eb8e0a37d6 Bump electron from 8.2.1 to 8.2.4
Bumps [electron](https://github.com/electron/electron) from 8.2.1 to 8.2.4.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.2.1...v8.2.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-07 02:01:10 +00:00
TC
2a915f4fae Fix electron deprecation warnings 2020-07-05 15:57:25 +02:00
TC
26994000d7 readme: yarn run build -> `yarn build 2020-07-05 15:44:26 +02:00
78f143ea10 Merge pull request #30 from th-ch/snyk-upgrade-3427638aafd84464f9f38998c7e3bc6f
[Snyk] Upgrade electron-store from 5.1.1 to 5.2.0
2020-07-05 15:43:02 +02:00
684a369fed fix: upgrade electron-store from 5.1.1 to 5.2.0
Snyk has created this PR to upgrade electron-store from 5.1.1 to 5.2.0.

See this package in NPM:
https://www.npmjs.com/package/electron-store

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-06-28 02:19:06 +00:00
b19470ad0b Merge pull request #29 from th-ch/snyk-upgrade-a4c19e5e6b1b92c533cd6d3ed8538fa2
[Snyk] Upgrade @cliqz/adblocker-electron from 1.14.4 to 1.15.0
2020-06-14 22:40:24 +02:00
6691cbf8c0 Merge pull request #28 from th-ch/snyk-upgrade-54c1400dcbff5fcbde1071153f1be456
[Snyk] Upgrade electron-debug from 3.0.1 to 3.1.0
2020-06-14 22:39:18 +02:00
7ac98cf024 fix: upgrade @cliqz/adblocker-electron from 1.14.4 to 1.15.0
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.14.4 to 1.15.0.

See this package in NPM:
https://www.npmjs.com/package/@cliqz/adblocker-electron

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-06-14 02:19:04 +00:00
3d835fbeaa fix: upgrade electron-debug from 3.0.1 to 3.1.0
Snyk has created this PR to upgrade electron-debug from 3.0.1 to 3.1.0.

See this package in NPM:
https://www.npmjs.com/package/electron-debug

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-06-13 02:19:27 +00:00
d0824f52ea Merge pull request #27 from th-ch/snyk-upgrade-9a04364d99d1aed92239f3dd981f3d67
[Snyk] Upgrade electron-updater from 4.3.1 to 4.3.2
2020-06-05 22:48:14 +02:00
8c945100e2 fix: upgrade electron-updater from 4.3.1 to 4.3.2
Snyk has created this PR to upgrade electron-updater from 4.3.1 to 4.3.2.

See this package in NPM:
https://www.npmjs.com/package/electron-updater

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-06-05 02:19:01 +00:00
68801c8e2b Merge pull request #26 from th-ch/snyk-upgrade-107ef53d6b16bb061dc783179b8991a7
[Snyk] Upgrade electron-updater from 4.3.0 to 4.3.1
2020-05-29 21:32:29 +02:00
a06eece4a0 fix: upgrade electron-updater from 4.3.0 to 4.3.1
Snyk has created this PR to upgrade electron-updater from 4.3.0 to 4.3.1.

See this package in NPM:
https://www.npmjs.com/package/electron-updater

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-05-19 04:19:35 +02:00
873e093ff0 fix: upgrade electron-updater from 4.3.0 to 4.3.1
Snyk has created this PR to upgrade electron-updater from 4.3.0 to 4.3.1.

See this package in NPM:
https://www.npmjs.com/package/electron-updater

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-05-19 04:19:34 +02:00
9c343d58ef Merge pull request #25 from th-ch/snyk-upgrade-86a869f28fc1113ae78c2dcd1eea4b90
[Snyk] Upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2
2020-05-14 22:14:50 +02:00
fed7a1df17 fix: upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2.

See this package in NPM:
https://www.npmjs.com/package/@cliqz/adblocker-electron

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-05-14 04:19:22 +02:00
89d8907bc6 fix: upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2
Snyk has created this PR to upgrade @cliqz/adblocker-electron from 1.14.1 to 1.14.2.

See this package in NPM:
https://www.npmjs.com/package/@cliqz/adblocker-electron

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-05-14 04:19:21 +02:00
08d145b6fc Merge pull request #24 from th-ch/tests
[Tests] Add integration tests
2020-05-03 13:35:41 +02:00
TC
57d3545701 Launch tests in CI 2020-05-03 12:58:28 +02:00
TC
08710558f5 Add tests section to readme 2020-05-03 11:44:23 +02:00
TC
b80007bbd5 Tests: only stop if running (in case of error when launching app) 2020-05-03 11:44:00 +02:00
TC
ab0c93d443 Test script in package.json 2020-05-01 18:59:00 +02:00
TC
e84f045201 Add simple test to ensure app launches properly 2020-05-01 18:58:08 +02:00
TC
692b6b22aa Enable nodeIntegration in test env (required by Spectron) 2020-05-01 18:34:23 +02:00
TC
954a58bcf5 Add util to detect test env 2020-05-01 18:34:01 +02:00
TC
bce5b7d8eb Add jest config and test environment to launch app 2020-05-01 18:33:43 +02:00
TC
736a706801 Add jest, spectron and getPort util for tests 2020-05-01 18:33:02 +02:00
TC
37cac19d9c Bump version to 1.3.3 2020-04-29 22:08:22 +02:00
TC
4824dda5d5 Move tray click callback in setUpTray 2020-04-27 12:25:24 +02:00
TC
3fa3c3ab9e Bump version to 1.3.2 2020-04-26 16:25:56 +02:00
TC
058371ace8 Show/hide window when clicking on tray 2020-04-26 16:25:37 +02:00
TC
430687f4d6 Hide the app (no quit) on close if tray enabled 2020-04-26 16:10:13 +02:00
TC
45f4b3bc28 Use is.macOS shortcut 2020-04-26 15:47:55 +02:00
7c12344d05 Merge pull request #22 from th-ch/snyk-upgrade-2844f3669e30ddb5a4f23b0caf25ece1
[Snyk] Upgrade electron-updater from 4.2.5 to 4.3.0
2020-04-26 14:51:47 +02:00
98213005d0 fix: upgrade electron-updater from 4.2.5 to 4.3.0
Snyk has created this PR to upgrade electron-updater from 4.2.5 to 4.3.0.

See this package in NPM:
https://www.npmjs.com/package/electron-updater

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-04-24 04:19:57 +02:00
db61589735 fix: upgrade electron-updater from 4.2.5 to 4.3.0
Snyk has created this PR to upgrade electron-updater from 4.2.5 to 4.3.0.

See this package in NPM:
https://www.npmjs.com/package/electron-updater

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-04-24 04:19:56 +02:00
TC
26dd7c5f71 Format blocker file + use window session in adblocker 2020-04-12 21:57:13 +02:00
TC
3bbab525c6 Only set user-agent on accounts.google.com (affects preload scripts otherwise) 2020-04-12 21:54:35 +02:00
TC
d42b7bc559 Bump version to 1.3.1 2020-04-12 20:35:44 +02:00
TC
69f88ed840 Force user agent for Google OAuth to work 2020-04-12 19:33:45 +02:00
eb10bf2b34 Merge pull request #21 from th-ch/add-options-and-tray
Add options and tray
2020-04-12 19:32:42 +02:00
TC
e051c4a9a2 Only checked for updates if configured in options 2020-04-12 19:00:06 +02:00
TC
477202bf24 Setup tray (based on options) 2020-04-12 19:00:06 +02:00
TC
876e52bb01 Tray lib 2020-04-12 19:00:06 +02:00
TC
edfd5be6a2 Add youtube-music util to interact with the window 2020-04-12 19:00:06 +02:00
TC
baa4f17276 Add tray icon in assets 2020-04-12 19:00:06 +02:00
TC
1de6f3e2ed Add options to menu, export menu config 2020-04-12 19:00:06 +02:00
TC
1c56e7fea6 Add options in store (tray, app visible, auto-update) 2020-04-12 19:00:06 +02:00
TC
4c46bceb7d Formatting 2020-04-12 19:00:05 +02:00
TC
7098cd7602 Update build command in readme 2020-04-12 16:55:25 +02:00
210418e5d3 Merge pull request #20 from th-ch/upgrade-outdated-dependencies
Upgrade outdated dependencies
2020-04-12 16:29:35 +02:00
TC
297de08278 Upgrade xo 2020-04-12 15:38:43 +02:00
TC
050bdd3c02 Upgrade rimraf 2020-04-12 15:35:59 +02:00
TC
3edc6e9b37 Upgrade electron-store 2020-04-12 15:33:33 +02:00
TC
2e721c942f Upgrade electron-devtools-installer 2020-04-12 15:30:56 +02:00
TC
8d375070ac Upgrade electron-debug 2020-04-12 15:29:36 +02:00
387a6d9f16 Merge pull request #19 from th-ch/migrate-to-adblock-rs
[Plugins] Migrate ad blocker
2020-04-12 15:20:51 +02:00
TC
3999b991fa Bump minor version (for this PR and new features to come) 2020-04-12 15:11:47 +02:00
TC
3d9e59dc90 Bump electron-builder (needed after electron upgrade) 2020-04-12 15:01:03 +02:00
TC
f25eb48f79 Generate the adblocker engine only once (by using built-in caching) 2020-04-12 14:17:38 +02:00
TC
6e45e7b2cb No rust/cargo install in build workers (not needed anymore) 2020-04-12 13:28:49 +02:00
TC
59bba8e590 Disable RDP access to AppVeyor build workers 2020-04-12 13:24:40 +02:00
TC
422c3fc28d Migrate from adblock-rs to cliqz 2020-04-12 13:23:35 +02:00
TC
6fb251f00f Enable RDP to the build worker 2020-04-12 11:43:38 +02:00
TC
1cb876da55 Update travis config 2020-04-12 00:07:51 +02:00
TC
c5021d5ca2 30 min timeout in Travis 2020-04-11 22:43:06 +02:00
TC
359360b058 Use VS 2019 to build on Windows 2020-04-11 21:55:28 +02:00
TC
80da3feb01 Upgrade extract-path and minimist to fix vuln 2020-04-11 21:28:55 +02:00
TC
ff074c10a6 Install rust/cargo for CI builds 2020-04-11 15:47:58 +02:00
TC
098776e31a Bump electron to last version 2020-04-11 14:00:12 +02:00
TC
d702321969 Postinstall scripts per plugin 2020-04-11 13:37:22 +02:00
TC
4748cf92bb Remove electron-rebuild 2020-04-11 13:36:56 +02:00
TC
5e3b7c0db7 Migrate adblock plugin to adblock-rs 2020-04-11 12:43:33 +02:00
TC
4648854a04 Remove adblock, install adblock-rs 2020-04-11 12:42:31 +02:00
0dc28064db Add badge for downloads 2020-03-15 21:45:36 +01:00
a3d5c038ea Merge pull request #13 from th-ch/snyk-upgrade-5770951f6ab79d4e413754bb7cab1225
[Snyk] Upgrade electron-localshortcut from 3.1.0 to 3.2.1
2020-03-15 12:38:57 +01:00
TC
91f7a0d1a5 Upgrade electron-localshortcut from 3.1.0 to 3.2.1 2020-03-15 12:22:41 +01:00
d5a6e50017 Merge pull request #12 from th-ch/snyk-upgrade-ab1b7600d9bb3bfaa5180a93741f304a
[Snyk] Upgrade electron-updater from 4.0.6 to 4.2.2
2020-03-15 12:21:17 +01:00
TC
6d8204f60a Bump appveyor to node 10 (semver requires node >=10) 2020-03-15 12:02:44 +01:00
TC
f25bb59065 Bump electron updater 2020-03-15 12:02:12 +01:00
39c7d56791 Merge pull request #15 from th-ch/snyk-upgrade-d9ce5c80db3f2ceedbda9bf03d7e2e8e
[Snyk] Upgrade electron-debug from 2.1.0 to 2.2.0
2020-03-15 11:56:01 +01:00
1a0369b69d Merge pull request #16 from th-ch/fix-vulnerability
Fix vulnerability
2020-03-15 11:55:19 +01:00
e5b4e01a96 fix: upgrade electron-debug from 2.1.0 to 2.2.0
Snyk has created this PR to upgrade electron-debug from 2.1.0 to 2.2.0.

See this package in NPM:
https://www.npmjs.com/package/electron-debug

See this project in Snyk:
https://app.snyk.io/org/th-ch/project/81809c53-bb7b-46b9-a0d7-806d45d74ac6?utm_source=github&utm_medium=upgrade-pr
2020-03-15 02:28:47 +00:00
TC
0a6587942b Add snyk badge to readme 2020-03-15 00:15:28 +01:00
TC
7050dfca5c Bump electron-store to fix a vulnerability 2020-03-15 00:03:58 +01:00
4a7a94240a Merge pull request #11 from th-ch/autoconfirm-when-paused
Plugin: autoconfirm when paused
2020-03-14 23:43:22 +01:00
TC
479013f9c9 Generate fake package.json for electron-builder to resolve modules 2020-03-14 23:11:11 +01:00
TC
164c3141ca Bump version to 1.2.0 2020-03-14 18:14:54 +01:00
TC
234954a86c Travis: fix MacOS build 2020-03-14 18:03:26 +01:00
TC
8c19757dfc Readme: build with npm 2020-03-14 16:46:43 +01:00
TC
790185893d Build/release with npm on travis 2020-03-14 16:31:07 +01:00
TC
7a816fa4f3 Use node 10 in linux container 2020-03-14 15:22:45 +01:00
TC
d4b5c53dc3 Add env var to allow unresolved deps 2020-03-14 14:51:19 +01:00
TC
e1b83f07a8 Block promo element 2020-03-14 09:32:48 +01:00
TC
b855726973 New plugin: autoconfirm when paused 2020-03-14 09:32:37 +01:00
TC
9371a4827e Migrate to yarn to install packages without package.json (but keep npm rebuild) 2020-03-14 09:32:14 +01:00
TC
81ce939451 Lint readme 2020-03-13 22:17:54 +01:00
TC
6fd10ea4a0 Bump version to 1.1.6 2019-09-11 23:49:31 +02:00
TC
746b5f13bb Fix Google login 2019-09-11 23:46:19 +02:00
474bfd19a2 Merge pull request #7 from th-ch/dependabot/npm_and_yarn/eslint-utils-1.4.2
Bump eslint-utils from 1.3.1 to 1.4.2
2019-09-03 13:41:20 +02:00
71222649a0 Bump eslint-utils from 1.3.1 to 1.4.2
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.3.1 to 1.4.2.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.3.1...v1.4.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-26 22:51:08 +00:00
TC
1a72129108 npm audit fix 2019-07-13 19:51:01 +02:00
3108e16018 Merge pull request #4 from th-ch/dependabot/npm_and_yarn/lodash.mergewith-4.6.2
Bump lodash.mergewith from 4.6.1 to 4.6.2
2019-07-13 19:47:14 +02:00
fae19f4533 Merge pull request #5 from th-ch/dependabot/npm_and_yarn/lodash-4.17.14
Bump lodash from 4.17.11 to 4.17.14
2019-07-13 19:47:01 +02:00
348f1b8189 Bump lodash from 4.17.11 to 4.17.14
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-13 05:20:15 +00:00
ffdc7f66b9 Bump lodash.mergewith from 4.6.1 to 4.6.2
Bumps [lodash.mergewith](https://github.com/lodash/lodash) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-11 10:21:14 +00:00
122 changed files with 15891 additions and 7851 deletions

62
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,62 @@
name: Build YouTube Music
on:
- push
jobs:
build:
name: Build YouTube Music
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- name: Setup NodeJS
uses: actions/setup-node@v1
with:
node-version: "14.x"
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Test
uses: GabrielBB/xvfb-action@v1
with:
run: yarn test
- name: Build on Mac
if: startsWith(matrix.os, 'macOS')
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
yarn run release:mac
- name: Build on Linux
if: startsWith(matrix.os, 'ubuntu')
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
yarn run release:linux
- name: Build on Windows
if: startsWith(matrix.os, 'windows')
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
yarn run release:win

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
engine-strict=true
scripts-prepend-node-path=true

View File

@ -1,43 +0,0 @@
matrix:
include:
- os: osx
osx_image: xcode9.4
language: node_js
node_js: "10"
env:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
- os: linux
services: docker
language: generic
cache:
directories:
- node_modules
- $HOME/.cache/electron
- $HOME/.cache/electron-builder
script:
- |
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
docker run --rm \
$(env | \
grep -Eo '^[^\s=]*(DEBUG|NODE_|ELECTRON_|YARN_|NPM_|CI|CIRCLE|TRAVIS|APPVEYOR_|CSC_|_TOKEN|_KEY|AWS_|STRIP|BUILD_)[^\s=]*' | \
sed '/^$/d;s/^/-e /' | \
paste -sd ' ' \
) \
-v ${PWD}:/project \
-v ~/.cache/electron:/root/.cache/electron \
-v ~/.cache/electron-builder:/root/.cache/electron-builder \
electronuserland/builder \
/bin/bash -c "npm install && npm run release:linux"
else
npm run release:mac
fi
before_cache:
- rm -rf $HOME/.cache/electron-builder
branches:
except:
- "/^v\\d+\\.\\d+\\.\\d+$/"

View File

@ -1,20 +0,0 @@
image: Visual Studio 2017
platform:
- x64
cache:
- node_modules
- '%USERPROFILE%\.electron'
init:
- git config --global core.autocrlf input
install:
- ps: Install-Product node 8 x64
- npm install
build_script:
- npm run release:win
test: off

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

88
config/defaults.js Normal file
View File

@ -0,0 +1,88 @@
const defaultConfig = {
"window-size": {
width: 1100,
height: 550,
},
url: "https://music.youtube.com",
options: {
tray: false,
appVisible: true,
autoUpdates: true,
hideMenu: false,
startAtLogin: false,
disableHardwareAcceleration: false,
restartOnConfigChanges: false,
trayClickPlayPause: false,
autoResetAppCache: false,
resumeOnStart: true,
proxy: "",
},
plugins: {
// Enabled plugins
navigation: {
enabled: true,
},
adblocker: {
enabled: true,
cache: true,
additionalBlockLists: [], // Additional list of filters, e.g "https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt"
},
// Disabled plugins
shortcuts: {
enabled: false,
overrideMediaKeys: false,
},
downloader: {
enabled: false,
ffmpegArgs: [], // e.g. ["-b:a", "192k"] for an audio bitrate of 192kb/s
downloadFolder: undefined, // Custom download folder (absolute path)
preset: "mp3",
},
"last-fm": {
enabled: false,
api_root: "http://ws.audioscrobbler.com/2.0/",
api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123
secret: "a5d2a36fdf64819290f6982481eaffa2",
},
discord: {
enabled: false,
activityTimoutEnabled: true, // if enabled, the discord rich presence gets cleared when music paused after the time specified below
activityTimoutTime: 10 * 60 * 1000, // 10 minutes
listenAlong: true, // add a "listen along" button to rich presence
},
notifications: {
enabled: false,
unpauseNotification: false,
urgency: "normal", //has effect only on Linux
interactive: false //has effect only on Windows
},
"precise-volume": {
enabled: false,
steps: 1, //percentage of volume to change
arrowsShortcut: true, //enable ArrowUp + ArrowDown local shortcuts
globalShortcuts: {
volumeUp: "",
volumeDown: ""
},
savedVolume: undefined //plugin save volume between session here
},
sponsorblock: {
enabled: false,
apiURL: "https://sponsor.ajay.app",
categories: [
"sponsor",
"intro",
"outro",
"interaction",
"selfpromo",
"music_offtopic",
],
},
"video-toggle": {
enabled: false,
forceHide: false,
},
},
};
module.exports = defaultConfig;

23
config/index.js Normal file
View File

@ -0,0 +1,23 @@
const defaultConfig = require("./defaults");
const plugins = require("./plugins");
const store = require("./store");
const set = (key, value) => {
store.set(key, value);
};
const get = (key) => {
return store.get(key);
};
module.exports = {
defaultConfig,
get,
set,
edit: () => store.openInEditor(),
watch: (cb) => {
store.onDidChange("options", cb);
store.onDidChange("plugins", cb);
},
plugins,
};

46
config/plugins.js Normal file
View File

@ -0,0 +1,46 @@
const store = require("./store");
function getEnabled() {
const plugins = store.get("plugins");
const enabledPlugins = Object.entries(plugins).filter(([plugin, options]) =>
isEnabled(plugin)
);
return enabledPlugins;
}
function isEnabled(plugin) {
const pluginConfig = store.get("plugins")[plugin];
return pluginConfig !== undefined && pluginConfig.enabled;
}
function setOptions(plugin, options) {
const plugins = store.get("plugins");
store.set("plugins", {
...plugins,
[plugin]: {
...plugins[plugin],
...options,
},
});
}
function getOptions(plugin) {
return store.get("plugins")[plugin];
}
function enable(plugin) {
setOptions(plugin, { enabled: true });
}
function disable(plugin) {
setOptions(plugin, { enabled: false });
}
module.exports = {
isEnabled,
getEnabled,
enable,
disable,
setOptions,
getOptions,
};

83
config/store.js Normal file
View File

@ -0,0 +1,83 @@
const Store = require("electron-store");
const defaults = require("./defaults");
const migrations = {
">=1.14.0": (store) => {
if (
typeof store.get("plugins.precise-volume.globalShortcuts") !== "object"
) {
store.set("plugins.precise-volume.globalShortcuts", {});
}
if (store.get("plugins.hide-video-player.enabled")) {
store.delete("plugins.hide-video-player");
store.set("plugins.video-toggle.enabled", true);
}
},
">=1.13.0": (store) => {
if (store.get("plugins.discord.listenAlong") === undefined) {
store.set("plugins.discord.listenAlong", true);
}
},
">=1.12.0": (store) => {
const options = store.get("plugins.shortcuts");
let updated = false;
for (const optionType of ["global", "local"]) {
if (Array.isArray(options[optionType])) {
const updatedOptions = {};
for (const optionObject of options[optionType]) {
if (optionObject.action && optionObject.shortcut) {
updatedOptions[optionObject.action] = optionObject.shortcut;
}
}
options[optionType] = updatedOptions;
updated = true;
}
}
if (updated) {
store.set("plugins.shortcuts", options);
}
},
">=1.11.0": (store) => {
if (store.get("options.resumeOnStart") === undefined) {
store.set("options.resumeOnStart", true);
}
},
">=1.7.0": (store) => {
const enabledPlugins = store.get("plugins");
if (!Array.isArray(enabledPlugins)) {
console.warn("Plugins are not in array format, cannot migrate");
return;
}
// Include custom options
const plugins = {
adblocker: {
enabled: true,
cache: true,
additionalBlockLists: [],
},
downloader: {
enabled: false,
ffmpegArgs: [], // e.g. ["-b:a", "192k"] for an audio bitrate of 192kb/s
downloadFolder: undefined, // Custom download folder (absolute path)
},
};
enabledPlugins.forEach((enabledPlugin) => {
plugins[enabledPlugin] = {
...plugins[enabledPlugin],
enabled: true,
};
});
store.set("plugins", plugins);
},
};
module.exports = new Store({
defaults,
clearInvalidConfig: false,
migrations,
});

BIN
docs/favicon/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
docs/favicon/favicon_32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

BIN
docs/favicon/favicon_48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

BIN
docs/favicon/favicon_96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

1
docs/img/adblock.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400"><g transform="translate(183.604 196.396)" stroke="#fff" stroke-width="2.23"><path style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;block-progression:tb;marker:none" d="M-116.99 106.245l31.82 31.82 236.31-236.31-31.82-31.82z" color="#000" font-weight="400" font-family="Sans" overflow="visible" fill="#fff" stroke="none"/><circle r="171.304" cy="4" cx="16" fill="none" stroke-width="44.6"/></g></svg>

After

Width:  |  Height:  |  Size: 552 B

1
docs/img/bg-bottom.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1440" height="347" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#606483" stop-opacity="0" offset="0%"/><stop stop-color="#0B0D19" stop-opacity=".72" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="39.334%" y2="79.282%" id="b"><stop stop-color="#0B0D19" offset="0%"/><stop stop-color="#0B0D19" stop-opacity="0" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M177.486 208.219c78.18 89.285 218.65-81.067 218.65-119.337 0-38.27-86.408-69.295-193-69.295-106.59 0-193 31.024-193 69.295 0 38.27 89.17 30.051 167.35 119.337z" transform="rotate(6 -140.175 3980.948)" fill="url(#a)"/><path d="M252.464 335.471c101.27 115.965 283.227-105.29 283.227-154.996 0-49.705-111.929-90-250-90s-250 40.295-250 90c0 49.706 115.503 39.032 216.773 154.996z" fill="url(#a)" transform="rotate(24 321.92 -247.724)"/><path d="M302.512 242.909c88.025 32.428 156-25.04 156-55.93 0-30.888-69.844-55.928-156-55.928-86.157 0-156 25.04-156 55.929 0 30.888 67.974 23.5 156 55.929z" fill="url(#b)" transform="rotate(24 338.741 -285.505)"/></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
docs/img/bg-top.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1440" height="318" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="38.706%" y1="-187.115%" x2="18.675%" y2="110.984%" id="a"><stop stop-color="#FFF" stop-opacity="0" offset="0%"/><stop stop-color="#c3352e" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="c"><stop stop-color="#606483" stop-opacity="0" offset="0%"/><stop stop-color="#0B0D19" stop-opacity=".72" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="39.334%" y2="79.282%" id="d"><stop stop-color="#0B0D19" stop-opacity=".32" offset="0%"/><stop stop-color="#0B0D19" stop-opacity="0" offset="100%"/></linearGradient><filter id="b"><feTurbulence type="fractalNoise" numOctaves="2" baseFrequency=".3" result="turb"/><feComposite in="turb" operator="arithmetic" k1=".1" k2=".1" k3=".1" k4=".1" result="result1"/><feComposite operator="in" in="result1" in2="SourceGraphic" result="finalFilter"/><feBlend mode="multiply" in="finalFilter" in2="SourceGraphic"/></filter></defs><g fill="none" fill-rule="evenodd"><path d="M88.494 90c67.04 7.177 161.094-24.753 224.996-90H.2c25.3 48.079 42.361 85.083 88.294 90z" transform="translate(1051)" fill="url(#a)" filter="url(#b)"/><path d="M250.464 367.471c101.27 115.965 283.227-105.29 283.227-154.996 0-49.705-111.929-90-250-90s-250 40.295-250 90c0 49.706 115.503 39.032 216.773 154.996z" fill="url(#c)" transform="rotate(143 810.285 354.367)"/><path d="M373.408 256.178c88.026 32.429 156-25.04 156-55.929 0-30.888-69.843-55.929-156-55.929-86.156 0-156 25.04-156 55.93 0 30.888 67.975 23.5 156 55.928z" fill="url(#d)" transform="rotate(136 905.21 332.676)"/></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

1
docs/img/code.svg Normal file
View File

@ -0,0 +1 @@
<svg width="96" height="48" xmlns="http://www.w3.org/2000/svg"><text y="35" x="48" fill="#fff" stroke-width="0" font-size="36" font-family="Monospace" text-anchor="middle" stroke="#fff">&lt;/&gt;</text></svg>

After

Width:  |  Height:  |  Size: 208 B

1
docs/img/download.svg Normal file
View File

@ -0,0 +1 @@
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="style-scope yt-icon" style="width:100%;height:100%" pointer-events="none" display="block" fill="#fff"><g class="style-scope yt-icon"><path d="M25.462 19.105v6.848H4.515v-6.848H.489v8.861c0 1.111.9 2.012 2.016 2.012h24.967c1.115 0 2.016-.9 2.016-2.012v-8.861h-4.026zM14.62 18.426l-5.764-6.965s-.877-.828.074-.828h3.248V9.217.494S12.049 0 12.793 0h4.572c.536 0 .524.416.524.416V10.424h2.998c1.154 0 .285.867.285.867s-4.904 6.51-5.588 7.193c-.492.495-.964-.058-.964-.058z" class="style-scope yt-icon"/></g></svg>

After

Width:  |  Height:  |  Size: 576 B

1
docs/img/footer.svg Normal file
View File

@ -0,0 +1 @@
<svg width="1440" height="582" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#606483" stop-opacity="0" offset="0%"/><stop stop-color="#363636" stop-opacity=".72" offset="100%"/></linearGradient><linearGradient x1="50%" y1="0%" x2="39.334%" y2="79.282%" id="b"><stop stop-color="#363636" offset="0%"/><stop stop-color="#363636" stop-opacity="0" offset="100%"/></linearGradient><radialGradient cx="33.3%" cy="43.394%" fx="33.3%" fy="43.394%" r="57.93%" gradientTransform="matrix(.24796 -.96592 .92535 .25883 -.151 .643)" id="c"><stop stop-color="#c3352e" stop-opacity="0" offset="0%"/><stop stop-color="#c3352e" stop-opacity=".64" offset="51.712%"/><stop stop-color="#c3352e" stop-opacity=".24" offset="100%"/></radialGradient><filter id="d"><feTurbulence type="fractalNoise" numOctaves="2" baseFrequency=".3" result="turb"/><feComposite in="turb" operator="arithmetic" k1=".1" k2=".1" k3=".1" k4=".1" result="result1"/><feComposite operator="in" in="result1" in2="SourceGraphic" result="finalFilter"/><feBlend mode="multiply" in="finalFilter" in2="SourceGraphic"/></filter></defs><g fill="none" fill-rule="evenodd"><path d="M252.464 335.471c101.27 115.965 283.227-105.29 283.227-154.996 0-49.705-111.929-90-250-90s-250 40.295-250 90c0 49.706 115.503 39.032 216.773 154.996z" fill="url(#a)" transform="rotate(24 -272.272 -82.087)"/><path d="M302.512 242.909c88.025 32.428 156-25.04 156-55.93 0-30.888-69.844-55.928-156-55.928-86.157 0-156 25.04-156 55.929 0 30.888 67.974 23.5 156 55.929z" fill="url(#b)" transform="rotate(24 -255.451 -119.868)"/><path d="M103.064 315.218c128.156 12.998 192.38 157.059 218.627 106.632 26.247-50.427-44.059-106.456 60.397-202.707 104.457-96.252-143.2-285.785-172.392-122.551C180.503 259.825-25.091 302.22 103.064 315.218z" transform="translate(1176 -33)" fill="url(#c)" filter="url(#d)"/></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

1
docs/img/plugins.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" fill="#fff"><path d="M45.563 29.174l-22-15A1 1 0 0022 15v30a.999.999 0 001.563.826l22-15a1 1 0 000-1.652zM24 43.107V16.893L43.225 30 24 43.107z"/><path d="M30 0C13.458 0 0 13.458 0 30s13.458 30 30 30 30-13.458 30-30S46.542 0 30 0zm0 58C14.561 58 2 45.439 2 30S14.561 2 30 2s28 12.561 28 28-12.561 28-28 28z"/></svg>

After

Width:  |  Height:  |  Size: 375 B

BIN
docs/img/youtube-music.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 176 176" width="32" height="32"><circle fill="red" cx="88" cy="88" r="88"/><path fill="#FFF" d="M88 46c23.1 0 42 18.8 42 42s-18.8 42-42 42-42-18.8-42-42 18.9-42 42-42m0-4c-25.4 0-46 20.6-46 46s20.6 46 46 46 46-20.6 46-46-20.6-46-46-46z"/><path fill="#FFF" d="M72 111l39-24-39-22z"/></svg>

After

Width:  |  Height:  |  Size: 341 B

490
docs/index.html Normal file
View File

@ -0,0 +1,490 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>YouTube Music Desktop App (Unofficial)</title>
<link
rel="icon"
href="./favicon/favicon.ico"
sizes="16x16"
type="image/x-icon"
/>
<link
rel="icon"
href="./favicon/favicon_32.png"
sizes="32x32"
type="image/png"
/>
<link
rel="icon"
href="./favicon/favicon_48.png"
sizes="48x48"
type="image/png"
/>
<link
rel="icon"
href="./favicon/favicon_96.png"
sizes="96x96"
type="image/png"
/>
<link
rel="icon"
href="./favicon/favicon_144.png"
sizes="144x144"
type="image/png"
/>
<meta name="theme-color" content="#131313" />
<meta
name="description"
content="YouTube Music Unofficial Desktop App with built-in ad blocker and downloader"
/>
<meta
property="og:site_name"
content="YouTube&nbsp;Music&nbsp;Desktop&nbsp;App"
/>
<meta
property="og:url"
class="meta-url"
content="https://th-ch.github.io/youtube-music"
/>
<meta property="og:type" content="website" />
<meta
name="twitter:url"
class="meta-url"
content="https://th-ch.github.io/youtube-music"
/>
<link href="./style/fonts.css" rel="stylesheet" />
<link rel="stylesheet" href="./style/style.css" />
<script src="https://unpkg.com/scrollreveal"></script>
</head>
<body class="has-animations vsc-initialized" style="height: 100%;">
<div class="body-wrap boxed-container">
<header class="site-header text-light">
<div class="container">
<div class="site-header-inner">
<div class="brand header-brand">
<h1 class="m-0">
<a href="https://github.com/th-ch/youtube-music">
<img
class="header-logo-image"
src="./img/youtube-music.svg"
alt="YouTube Music"
/>
</a>
</h1>
</div>
</div>
</div>
</header>
<main>
<section class="hero text-center text-light">
<div class="hero-bg"></div>
<div class="hero-particles-container">
<canvas id="hero-particles"></canvas>
</div>
<div class="container-sm">
<div class="hero-inner">
<div class="hero-copy">
<h1 class="hero-title mt-0">
Custom YouTube Music Desktop App
</h1>
<p class="hero-paragraph">
Open source, cross-platform, unofficial YouTube Music Desktop
App with built-in <strong>ad blocker</strong> and
<strong>downloader</strong>
</p>
<div class="hero-cta">
<a
class="button button-primary button-wide-mobile"
href="https://github.com/th-ch/youtube-music/releases/latest"
>Download</a
>
</div>
</div>
<div class="mockup-container">
<div class="mockup-bg">
<img
src="./img/youtube-music.png"
id="mockup-header-img"
alt="YouTube Music"
/>
</div>
</div>
</div>
</div>
</section>
<section class="features-extended section">
<div class="features-extended-inner section-inner">
<div class="features-extended-wrap">
<div class="container">
<div class="feature-extended">
<div class="feature-extended-image">
<img
class="device-mockup"
src="./img/adblock.svg"
width="100px"
alt="Adblocker"
data-sr-id="0"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
/>
</div>
<div
class="feature-extended-body"
data-sr-id="5"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
>
<h3 class="mt-0 mb-16">Built-in adblocker</h3>
<p class="m-0">Block all ads and tracking out of the box</p>
</div>
</div>
<div class="feature-extended">
<div class="feature-extended-image">
<img
class="device-mockup"
src="./img/download.svg"
alt="Downloader"
data-sr-id="2"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
/>
</div>
<div
class="feature-extended-body"
data-sr-id="6"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
>
<h3 class="mt-0 mb-16">Built-in downloader</h3>
<p class="m-0">
Download (like youtube-dl) to custom formats (mp3, opus,
etc) directly from the interface
</p>
</div>
</div>
<div class="feature-extended">
<div class="feature-extended-image">
<img
class="device-mockup"
src="./img/plugins.svg"
alt="Plugins"
data-sr-id="3"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
/>
</div>
<div
class="feature-extended-body"
data-sr-id="7"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
>
<h3 class="mt-0 mb-16">Many other plugins in one click</h3>
<p class="m-0">
Enhance your user experience with media keys, integrations
(Discord), cosmetic filters, notifications, TouchBar,
auto-unpause and many more! Every plugin can be enabled or
disabled in one click.
</p>
</div>
</div>
<div class="feature-extended">
<div class="feature-extended-image">
<img
class="device-mockup"
src="./img/code.svg"
alt="Code"
data-sr-id="4"
style="
visibility: visible;
width: 200%;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
/>
</div>
<div
class="feature-extended-body"
data-sr-id="8"
style="
visibility: visible;
opacity: 1;
transform: matrix3d(
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
);
transition: opacity 0.6s
cubic-bezier(0.215, 0.61, 0.355, 1) 0s,
transform 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
"
>
<h3 class="mt-0 mb-16">Open source & Cross platform</h3>
<p class="m-0">
Available for Windows (installer and portable), Mac and
Linux (AppImage, deb, etc)
</p>
</div>
</div>
</div>
</div>
</div>
<div class="main-particles-container">
<canvas id="main-particles"></canvas>
</div>
</section>
</main>
<footer class="site-footer">
<div class="footer-particles-container">
<canvas id="footer-particles"></canvas>
</div>
<div class="site-footer-top">
<section class="cta section text-light">
<div class="container-sm">
<div class="cta-inner section-inner">
<div class="cta-header text-center">
<h2 class="section-title mt-0">Download and/or contribute</h2>
<p class="section-paragraph">Pull requests welcome!</p>
<div class="cta-cta">
<a
class="button button-primary button-wide-mobile"
href="https://github.com/th-ch/youtube-music"
>Go to code</a
>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="site-footer-bottom">
<div class="container">
<div class="site-footer-inner">
<div class="brand footer-brand">
<a href="https://github.com/th-ch/youtube-music">
<img src="./img/youtube-music.svg" alt="YouTube Music logo" />
</a>
</div>
<ul class="footer-links list-reset">
<li>
<a href="https://github.com/th-ch/youtube-music">Main page</a>
</li>
<li>
<a href="https://github.com/th-ch/youtube-music/issues"
>Issues</a
>
</li>
<li>
<a href="https://github.com/th-ch/youtube-music/pulls"
>Pull requests</a
>
</li>
</ul>
<ul class="footer-social-links list-reset">
<li>
<a href="https://github.com/th-ch/youtube-music">
<span class="screen-reader-text">GitHub</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 1792 1792"
>
<path
d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5q0 251-146.5 451.5t-378.5 277.5q-27 5-40-7t-13-30q0-3 .5-76.5t.5-134.5q0-97-52-142 57-6 102.5-18t94-39 81-66.5 53-105 20.5-150.5q0-119-79-206 37-91-8-204-28-9-81 11t-92 44l-38 24q-93-26-192-26t-192 26q-16-11-42.5-27t-83.5-38.5-85-13.5q-45 113-8 204-79 87-79 206 0 85 20.5 150t52.5 105 80.5 67 94 39 102.5 18q-39 36-49 103-21 10-45 15t-57 5-65.5-21.5-55.5-62.5q-19-32-48.5-52t-49.5-24l-20-3q-21 0-29 4.5t-5 11.5 9 14 13 12l7 5q22 10 43.5 38t31.5 51l10 23q13 38 44 61.5t67 30 69.5 7 55.5-3.5l23-4q0 38 .5 88.5t.5 54.5q0 18-13 30t-40 7q-232-77-378.5-277.5t-146.5-451.5q0-209 103-385.5t279.5-279.5 385.5-103zm-477 1103q3-7-7-12-10-3-13 2-3 7 7 12 9 6 13-2zm31 34q7-5-2-16-10-9-16-3-7 5 2 16 10 10 16 3zm30 45q9-7 0-19-8-13-17-6-9 5 0 18t17 7zm42 42q8-8-4-19-12-12-20-3-9 8 4 19 12 12 20 3zm57 25q3-11-13-16-15-4-19 7t13 15q15 6 19-6zm63 5q0-13-17-11-16 0-16 11 0 13 17 11 16 0 16-11zm58-10q-2-11-18-9-16 3-14 15t18 8 14-14z"
fill="#fff"
/>
</svg>
</a>
</li>
</ul>
<div class="footer-copyright">© 2021 th-ch</div>
</div>
</div>
</div>
</footer>
</div>
<script src="./js/main.js"></script>
</body>
</html>

262
docs/js/main.js Normal file
View File

@ -0,0 +1,262 @@
// Constants
const element = document.documentElement,
body = document.body,
revealOnScroll = (window.sr = ScrollReveal({ mobile: false }));
// Load animations
element.classList.remove("no-js");
element.classList.add("js");
window.addEventListener("load", function () {
body.classList.add("is-loaded");
});
if (body.classList.contains("has-animations")) {
window.addEventListener("load", function () {
revealOnScroll.reveal(".feature-extended .device-mockup", {
duration: 600,
distance: "100px",
easing: "cubic-bezier(0.215, 0.61, 0.355, 1)",
origin: "bottom",
viewFactor: 0.6,
});
revealOnScroll.reveal(".feature-extended .feature-extended-body", {
duration: 600,
distance: "40px",
easing: "cubic-bezier(0.215, 0.61, 0.355, 1)",
origin: "top",
viewFactor: 0.6,
});
});
}
// Bubble canvas
let bubbleCanvas = function (t) {
let e = this;
e.parentNode = t;
e.setCanvasSize();
window.addEventListener("resize", function () {
e.setCanvasSize();
});
e.mouseX = 0;
e.mouseY = 0;
window.addEventListener("mousemove", function (t) {
(e.mouseX = t.clientX), (e.mouseY = t.clientY);
});
e.randomise();
};
bubbleCanvas.prototype.setCanvasSize = function () {
this.canvasWidth = this.parentNode.clientWidth;
this.canvasHeight = this.parentNode.clientHeight;
};
bubbleCanvas.prototype.generateDecimalBetween = function (start, end) {
return (Math.random() * (start - end) + end).toFixed(2);
};
bubbleCanvas.prototype.update = function () {
let t = this;
t.translateX = t.translateX - t.movementX;
t.translateY = t.translateY - t.movementY;
t.posX += (t.mouseX / (t.staticity / t.magnetism) - t.posX) / t.smoothFactor;
t.posY += (t.mouseY / (t.staticity / t.magnetism) - t.posY) / t.smoothFactor;
if (
t.translateY + t.posY < 0 ||
t.translateX + t.posX < 0 ||
t.translateX + t.posX > t.canvasWidth
) {
t.randomise();
t.translateY = t.canvasHeight;
}
};
bubbleCanvas.prototype.randomise = function () {
this.colors = ["195,53,46", "172,54,46"];
this.velocity = 20;
this.smoothFactor = 50;
this.staticity = 30;
this.magnetism = 0.1 + 4 * Math.random();
this.color = this.colors[Math.floor(Math.random() * this.colors.length)];
this.alpha = this.generateDecimalBetween(5, 10) / 10;
this.size = this.generateDecimalBetween(1, 4);
this.posX = 0;
this.posY = 0;
this.movementX = this.generateDecimalBetween(-2, 2) / this.velocity;
this.movementY = this.generateDecimalBetween(1, 20) / this.velocity;
this.translateX = this.generateDecimalBetween(0, this.canvasWidth);
this.translateY = this.generateDecimalBetween(0, this.canvasHeight);
};
let drawBubbleCanvas = function (t) {
this.canvas = document.getElementById(t);
this.ctx = this.canvas.getContext("2d");
this.dpr = window.devicePixelRatio;
};
drawBubbleCanvas.prototype.start = function (bubbleDensity) {
let t = this;
t.bubbleDensity = bubbleDensity;
t.setCanvasSize();
window.addEventListener("resize", function () {
t.setCanvasSize();
});
t.bubblesList = [];
t.generateBubbles();
t.animate();
};
drawBubbleCanvas.prototype.setCanvasSize = function () {
this.container = this.canvas.parentNode;
this.w = this.container.offsetWidth;
this.h = this.container.offsetHeight;
this.wdpi = this.w * this.dpr;
this.hdpi = this.h * this.dpr;
this.canvas.width = this.wdpi;
this.canvas.height = this.hdpi;
this.canvas.style.width = this.w + "px";
this.canvas.style.height = this.h + "px";
this.ctx.scale(this.dpr, this.dpr);
};
drawBubbleCanvas.prototype.animate = function () {
let t = this;
t.ctx.clearRect(0, 0, t.canvas.clientWidth, t.canvas.clientHeight);
t.bubblesList.forEach(function (e) {
e.update();
t.ctx.translate(e.translateX, e.translateY);
t.ctx.beginPath();
t.ctx.arc(e.posX, e.posY, e.size, 0, 2 * Math.PI);
t.ctx.fillStyle = "rgba(" + e.color + "," + e.alpha + ")";
t.ctx.fill();
t.ctx.setTransform(t.dpr, 0, 0, t.dpr, 0, 0);
});
requestAnimationFrame(this.animate.bind(this));
};
drawBubbleCanvas.prototype.addBubble = function (t) {
return this.bubblesList.push(t);
};
drawBubbleCanvas.prototype.generateBubbles = function () {
let t = this;
for (let e = 0; e < t.bubbleDensity; e++)
t.addBubble(new bubbleCanvas(t.canvas.parentNode));
};
// Night sky with stars canvas
let starCanvas = function (t) {
this.canvas = document.getElementById(t);
this.ctx = this.canvas.getContext("2d");
this.dpr = window.devicePixelRatio;
};
starCanvas.prototype.start = function () {
let w;
let h;
const setCanvasExtents = () => {
w = this.canvas.parentNode.clientWidth;
h = this.canvas.parentNode.clientHeight;
this.canvas.width = w;
this.canvas.height = h;
};
setCanvasExtents();
window.onresize = () => {
setCanvasExtents();
};
const makeStars = (count) => {
const out = [];
for (let i = 0; i < count; i++) {
const s = {
x: Math.random() * w - w / 2,
y: Math.random() * h - h / 2,
z: Math.random() * 1000,
};
out.push(s);
}
return out;
};
let stars = makeStars(10000);
const clear = () => {
this.ctx.fillStyle = "#212121";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
};
const putPixel = (x, y, brightness) => {
const intensity = brightness * 255;
const rgb = "rgb(" + intensity + "," + intensity + "," + intensity + ")";
this.ctx.beginPath();
this.ctx.arc(x, y, 0.9, 0, 2 * Math.PI);
this.ctx.fillStyle = rgb;
this.ctx.fill();
};
const moveStars = (distance) => {
const count = stars.length;
for (var i = 0; i < count; i++) {
const s = stars[i];
s.z -= distance;
while (s.z <= 1) {
s.z += 1000;
}
}
};
let prevTime;
const init = (time) => {
prevTime = time;
requestAnimationFrame(tick);
};
const tick = (time) => {
let elapsed = time - prevTime;
prevTime = time;
moveStars(elapsed * 0.1);
clear();
const cx = w / 2;
const cy = h / 2;
const count = stars.length;
for (var i = 0; i < count; i++) {
const star = stars[i];
const x = cx + star.x / (star.z * 0.001);
const y = cy + star.y / (star.z * 0.001);
if (x < 0 || x >= w || y < 0 || y >= h) {
continue;
}
const d = star.z / 1000.0;
const b = 1 - d * d;
putPixel(x, y, b);
}
requestAnimationFrame(tick);
};
requestAnimationFrame(init);
};
// Start canvas animations
window.addEventListener("load", function () {
// Stars
const headCanvas = new starCanvas("hero-particles");
// Bubbles
const footerCanvas = new drawBubbleCanvas("footer-particles");
const mainCanvas = new drawBubbleCanvas("main-particles");
headCanvas.start();
footerCanvas.start(30);
mainCanvas.start(200);
});

48
docs/style/fonts.css Normal file
View File

@ -0,0 +1,48 @@
/* hebrew */
@font-face {
font-family: 'Heebo';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H0TbFhsqMA6aw.woff2) format('woff2');
unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* latin */
@font-face {
font-family: 'Heebo';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H2TbFhsqMA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* hebrew */
@font-face {
font-family: 'Heebo';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H0TbFhsqMA6aw.woff2) format('woff2');
unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* latin */
@font-face {
font-family: 'Heebo';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H2TbFhsqMA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Oxygen';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/oxygen/v10/2sDcZG1Wl4LcnbuCNWgzZmW5Kb8VZBHR.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Oxygen';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/oxygen/v10/2sDcZG1Wl4LcnbuCNWgzaGW5Kb8VZA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

1561
docs/style/style.css Normal file

File diff suppressed because it is too large Load Diff

404
index.js
View File

@ -1,18 +1,50 @@
"use strict";
const path = require("path");
const electron = require("electron");
const is = require("electron-is");
const electron = require("electron");
const remote = require('@electron/remote/main');
remote.initialize();
const enhanceWebRequest = require("electron-better-web-request").default;
const is = require("electron-is");
const unhandled = require("electron-unhandled");
const { autoUpdater } = require("electron-updater");
const { setApplicationMenu } = require("./menu");
const { getEnabledPlugins, store } = require("./store");
const { fileExists, injectCSS } = require("./plugins/utils");
const config = require("./config");
const { setApplicationMenu } = require("./menu");
const { fileExists, injectCSS } = require("./plugins/utils");
const { isTesting } = require("./utils/testing");
const { setUpTray } = require("./tray");
const { setupSongInfo } = require("./providers/song-info");
// Catch errors and log them
unhandled({
logger: console.error,
showDialog: false,
});
const app = electron.app;
app.commandLine.appendSwitch(
"js-flags",
// WebAssembly flags
"--experimental-wasm-threads"
);
app.commandLine.appendSwitch("enable-features", "SharedArrayBuffer"); // Required for downloader
app.allowRendererProcessReuse = true; // https://github.com/electron/electron/issues/18397
if (config.get("options.disableHardwareAcceleration")) {
if (is.dev()) {
console.log("Disabling hardware acceleration");
}
app.disableHardwareAcceleration();
}
if (config.get("options.proxy")) {
app.commandLine.appendSwitch("proxy-server", config.get("options.proxy"));
}
// Adds debug features like hotkeys for triggering dev tools and reload
require("electron-debug")();
require("electron-debug")({
showDevTools: false //disable automatic devTools on new window
});
// Prevent window being garbage collected
let mainWindow;
@ -31,82 +63,180 @@ function onClosed() {
mainWindow = null;
}
function createMainWindow() {
const windowSize = store.get("window-size");
const windowMaximized = store.get("window-maximized");
const win = new electron.BrowserWindow({
icon : icon,
width : windowSize.width,
height : windowSize.height,
backgroundColor: "#000",
show : false,
webPreferences : {
nodeIntegration: false,
preload : path.join(__dirname, "preload.js")
},
frame : !is.macOS(),
titleBarStyle: is.macOS() ? "hiddenInset": "default"
});
if (windowMaximized) {
win.maximize();
}
win.webContents.loadURL(store.get("url"));
win.on("closed", onClosed);
function loadPlugins(win) {
injectCSS(win.webContents, path.join(__dirname, "youtube-music.css"));
win.webContents.on("did-finish-load", () => {
win.webContents.once("did-finish-load", () => {
if (is.dev()) {
console.log("did finish load");
win.webContents.openDevTools();
}
});
getEnabledPlugins().forEach(plugin => {
config.plugins.getEnabled().forEach(([plugin, options]) => {
console.log("Loaded plugin - " + plugin);
const pluginPath = path.join(__dirname, "plugins", plugin, "back.js");
fileExists(pluginPath, () => {
const handle = require(pluginPath);
handle(win);
handle(win, options);
});
});
}
win.webContents.on("did-fail-load", () => {
if (is.dev()) {
console.log("did fail load");
}
win.webContents.loadFile(path.join(__dirname, "error.html"));
});
function createMainWindow() {
const windowSize = config.get("window-size");
const windowMaximized = config.get("window-maximized");
const windowPosition = config.get("window-position");
const useInlineMenu = config.plugins.isEnabled("in-app-menu");
win.webContents.on("did-navigate-in-page", () => {
const url = win.webContents.getURL();
if (url.startsWith("https://music.youtube.com")) {
store.set("url", url);
}
const win = new electron.BrowserWindow({
icon: icon,
width: windowSize.width,
height: windowSize.height,
backgroundColor: "#000",
show: false,
webPreferences: {
// TODO: re-enable contextIsolation once it can work with ffmepg.wasm
// Possible bundling? https://github.com/ffmpegwasm/ffmpeg.wasm/issues/126
contextIsolation: false,
preload: path.join(__dirname, "preload.js"),
nodeIntegrationInSubFrames: true,
nativeWindowOpen: true, // window.open return Window object(like in regular browsers), not BrowserWindowProxy
affinity: "main-window", // main window, and addition windows should work in one process
...(isTesting()
? {
// Only necessary when testing with Spectron
contextIsolation: false,
nodeIntegration: true,
}
: undefined),
},
frame: !is.macOS() && !useInlineMenu,
titleBarStyle: useInlineMenu
? "hidden"
: is.macOS()
? "hiddenInset"
: "default",
autoHideMenuBar: config.get("options.hideMenu"),
});
remote.enable(win.webContents);
if (windowPosition) {
const { x, y } = windowPosition;
win.setPosition(x, y);
}
if (windowMaximized) {
win.maximize();
}
const urlToLoad = config.get("options.resumeOnStart")
? config.get("url")
: config.defaultConfig.url;
win.webContents.loadURL(urlToLoad);
win.on("closed", onClosed);
win.on("move", () => {
let position = win.getPosition();
store.set("window-position", { x: position[0], y: position[1] });
config.set("window-position", { x: position[0], y: position[1] });
});
win.on("resize", () => {
const windowSize = win.getSize();
store.set("window-maximized", win.isMaximized());
config.set("window-maximized", win.isMaximized());
if (!win.isMaximized()) {
store.set("window-size", { width: windowSize[0], height: windowSize[1] });
config.set("window-size", {
width: windowSize[0],
height: windowSize[1],
});
}
});
win.once("ready-to-show", () => {
win.show();
win.webContents.on("render-process-gone", (event, webContents, details) => {
showUnresponsiveDialog(win, details);
});
win.once("ready-to-show", () => {
if (config.get("options.appVisible")) {
win.show();
}
});
removeContentSecurityPolicy();
return win;
}
app.once("browser-window-created", (event, win) => {
// User agents are from https://developers.whatismybrowser.com/useragents/explore/
const originalUserAgent = win.webContents.userAgent;
const userAgents = {
mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 12.1; rv:95.0) Gecko/20100101 Firefox/95.0",
windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
linux: "Mozilla/5.0 (Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0",
}
const updatedUserAgent =
is.macOS() ? userAgents.mac :
is.windows() ? userAgents.windows :
userAgents.linux;
win.webContents.userAgent = updatedUserAgent;
app.userAgentFallback = updatedUserAgent;
win.webContents.session.webRequest.onBeforeSendHeaders((details, cb) => {
// this will only happen if login failed, and "retry" was pressed
if (win.webContents.getURL().startsWith("https://accounts.google.com") && details.url.startsWith("https://accounts.google.com")){
details.requestHeaders["User-Agent"] = originalUserAgent;
}
cb({ requestHeaders: details.requestHeaders });
});
setupSongInfo(win);
loadPlugins(win);
win.webContents.on("did-fail-load", (
_event,
errorCode,
errorDescription,
validatedURL,
isMainFrame,
frameProcessId,
frameRoutingId,
) => {
const log = JSON.stringify({
error: "did-fail-load",
errorCode,
errorDescription,
validatedURL,
isMainFrame,
frameProcessId,
frameRoutingId,
}, null, "\t");
if (is.dev()) {
console.log(log);
}
if( !(config.plugins.isEnabled("in-app-menu") && errorCode === -3)) { // -3 is a false positive with in-app-menu
win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
}
});
win.webContents.on("will-prevent-unload", (event) => {
event.preventDefault();
});
win.webContents.on(
"new-window",
(e, url, frameName, disposition, options) => {
// hook on new opened window
// at now new window in mainWindow renderer process.
// Also, this will automatically get an option `nodeIntegration=false`(not override to true, like in iframe's) - like in regular browsers
options.webPreferences.affinity = "main-window";
}
);
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
@ -127,30 +257,114 @@ app.on("activate", () => {
});
app.on("ready", () => {
setApplicationMenu();
if (config.get("options.autoResetAppCache")) {
// Clear cache after 20s
const clearCacheTimeout = setTimeout(() => {
if (is.dev()) {
console.log("Clearing app cache.");
}
electron.session.defaultSession.clearCache();
clearTimeout(clearCacheTimeout);
}, 20000);
}
// Register appID on windows
if (is.windows()) {
const appID = "com.github.th-ch.youtube-music";
app.setAppUserModelId(appID);
const appLocation = process.execPath;
const appData = app.getPath("appData");
// check shortcut validity if not in dev mode / running portable app
if (!is.dev() && !appLocation.startsWith(path.join(appData, "..", "Local", "Temp"))) {
const shortcutPath = path.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "YouTube Music.lnk");
try { // check if shortcut is registered and valid
const shortcutDetails = electron.shell.readShortcutLink(shortcutPath); // throw error if doesn't exist yet
if (shortcutDetails.target !== appLocation || shortcutDetails.appUserModelId !== appID) {
throw "needUpdate";
}
} catch (error) { // if not valid -> Register shortcut
electron.shell.writeShortcutLink(
shortcutPath,
error === "needUpdate" ? "update" : "create",
{
target: appLocation,
cwd: appLocation.slice(0, appLocation.lastIndexOf(path.sep)),
description: "YouTube Music Desktop App - including custom plugins",
appUserModelId: appID
}
);
}
}
}
mainWindow = createMainWindow();
if (!is.dev()) {
autoUpdater.checkForUpdatesAndNotify();
setApplicationMenu(mainWindow);
if (config.get("options.restartOnConfigChanges")) {
config.watch(() => {
app.relaunch();
app.exit();
});
}
setUpTray(app, mainWindow);
// Autostart at login
app.setLoginItemSettings({
openAtLogin: config.get("options.startAtLogin"),
});
if (!is.dev() && config.get("options.autoUpdates")) {
const updateTimeout = setTimeout(() => {
autoUpdater.checkForUpdatesAndNotify();
clearTimeout(updateTimeout);
}, 2000);
autoUpdater.on("update-available", () => {
const downloadLink =
"https://github.com/th-ch/youtube-music/releases/latest";
const dialogOpts = {
type : "info",
buttons: ["OK"],
title : "Application Update",
type: "info",
buttons: ["OK", "Download", "Disable updates"],
title: "Application Update",
message: "A new version is available",
detail :
"A new version is available and can be downloaded at https://github.com/th-ch/youtube-music/releases/latest"
detail: `A new version is available and can be downloaded at ${downloadLink}`,
};
electron.dialog.showMessageBox(dialogOpts);
electron.dialog.showMessageBox(dialogOpts).then((dialogOutput) => {
switch (dialogOutput.response) {
// Download
case 1:
electron.shell.openExternal(downloadLink);
break;
// Disable updates
case 2:
config.set("options.autoUpdates", false);
break;
default:
break;
}
});
});
}
// Optimized for Mac OS X
if (process.platform === "darwin") {
var forceQuit = false;
app.on("before-quit", () => {
forceQuit = true;
if (config.get("options.hideMenu") && !config.get("options.hideMenuWarned")) {
electron.dialog.showMessageBox(mainWindow, {
type: 'info', title: 'Hide Menu Enabled',
message: "Menu is hidden, use 'Alt' to show it (or 'Escape' if using in-app-menu)"
});
mainWindow.on("close", event => {
config.set("options.hideMenuWarned", true);
}
// Optimized for Mac OS X
if (is.macOS() && !config.get("options.appVisible")) {
app.dock.hide();
}
let forceQuit = false;
app.on("before-quit", () => {
forceQuit = true;
});
if (is.macOS() || config.get("options.tray")) {
mainWindow.on("close", (event) => {
// Hide the window instead of quitting (quit is available in tray options)
if (!forceQuit) {
event.preventDefault();
mainWindow.hide();
@ -158,3 +372,65 @@ app.on("ready", () => {
});
}
});
function showUnresponsiveDialog(win, details) {
if (!!details) {
console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t"))
}
electron.dialog.showMessageBox(win, {
type: "error",
title: "Window Unresponsive",
message: "The Application is Unresponsive",
details: "We are sorry for the inconvenience! please choose what to do:",
buttons: ["Wait", "Relaunch", "Quit"],
cancelId: 0
}).then( result => {
switch (result.response) {
case 1: //if relaunch - relaunch+exit
app.relaunch();
case 2:
app.quit();
break;
default:
break;
}
});
}
function removeContentSecurityPolicy(
session = electron.session.defaultSession
) {
// Allows defining multiple "onHeadersReceived" listeners
// by enhancing the session.
// Some plugins (e.g. adblocker) also define a "onHeadersReceived" listener
enhanceWebRequest(session);
// Custom listener to tweak the content security policy
session.webRequest.onHeadersReceived(function (details, callback) {
if (
!details.responseHeaders["content-security-policy-report-only"] &&
!details.responseHeaders["content-security-policy"]
)
return callback({ cancel: false });
delete details.responseHeaders["content-security-policy-report-only"];
delete details.responseHeaders["content-security-policy"];
callback({ cancel: false, responseHeaders: details.responseHeaders });
});
// When multiple listeners are defined, apply them all
session.webRequest.setResolver("onHeadersReceived", (listeners) => {
const response = listeners.reduce(
async (accumulator, listener) => {
if (accumulator.cancel) {
return accumulator;
}
const result = await listener.apply();
return { ...accumulator, ...result };
},
{ cancel: false }
);
return response;
});
}

6
jest.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
globals: {
__APP__: undefined, // A different app will be launched in each test environment
},
testTimeout: 30000, // 30s
};

324
menu.js
View File

@ -1,33 +1,279 @@
const { app, Menu } = require("electron");
const { existsSync } = require("fs");
const path = require("path");
const { getAllPlugins } = require("./plugins/utils");
const { isPluginEnabled, enablePlugin, disablePlugin } = require("./store");
const { app, Menu, dialog } = require("electron");
const is = require("electron-is");
module.exports.setApplicationMenu = () => {
const menuTemplate = [
{
label : "Plugins",
submenu: getAllPlugins().map(plugin => {
return {
label : plugin,
type : "checkbox",
checked: isPluginEnabled(plugin),
click : item => {
if (item.checked) {
enablePlugin(plugin);
} else {
disablePlugin(plugin);
}
}
};
})
const { getAllPlugins } = require("./plugins/utils");
const config = require("./config");
const prompt = require("custom-electron-prompt");
const promptOptions = require("./providers/prompt-options");
// true only if in-app-menu was loaded on launch
const inAppMenuActive = config.plugins.isEnabled("in-app-menu");
const pluginEnabledMenu = (plugin, label = "", hasSubmenu = false, refreshMenu = undefined) => ({
label: label || plugin,
type: "checkbox",
checked: config.plugins.isEnabled(plugin),
click: (item) => {
if (item.checked) {
config.plugins.enable(plugin);
} else {
config.plugins.disable(plugin);
}
];
if (hasSubmenu) {
refreshMenu();
}
},
});
const mainMenuTemplate = (win) => {
const refreshMenu = () => {
this.setApplicationMenu(win);
if (inAppMenuActive) {
win.webContents.send("updateMenu", true);
}
}
return [
{
label: "Plugins",
submenu: [
...getAllPlugins().map((plugin) => {
const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js")
if (existsSync(pluginPath)) {
if (!config.plugins.isEnabled(plugin)) {
return pluginEnabledMenu(plugin, "", true, refreshMenu);
}
const getPluginMenu = require(pluginPath);
return {
label: plugin,
submenu: [
pluginEnabledMenu(plugin, "Enabled", true, refreshMenu),
...getPluginMenu(win, config.plugins.getOptions(plugin), refreshMenu),
],
};
}
return pluginEnabledMenu(plugin);
}),
],
},
{
label: "Options",
submenu: [
{
label: "Auto-update",
type: "checkbox",
checked: config.get("options.autoUpdates"),
click: (item) => {
config.set("options.autoUpdates", item.checked);
},
},
{
label: "Resume last song when app starts",
type: "checkbox",
checked: config.get("options.resumeOnStart"),
click: (item) => {
config.set("options.resumeOnStart", item.checked);
},
},
{
label: "Remove upgrade button",
type: "checkbox",
checked: config.get("options.removeUpgradeButton"),
click: (item) => {
config.set("options.removeUpgradeButton", item.checked);
},
},
...(is.windows() || is.linux()
? [
{
label: "Hide menu",
type: "checkbox",
checked: config.get("options.hideMenu"),
click: (item) => {
config.set("options.hideMenu", item.checked);
if (item.checked && !config.get("options.hideMenuWarned")) {
dialog.showMessageBox(win, {
type: 'info', title: 'Hide Menu Enabled',
message: "Menu will be hidden on next launch, use 'Alt' to show it (or 'Escape' if using in-app-menu)"
});
}
},
},
]
: []),
...(is.windows() || is.macOS()
? // Only works on Win/Mac
// https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
[
{
label: "Start at login",
type: "checkbox",
checked: config.get("options.startAtLogin"),
click: (item) => {
config.set("options.startAtLogin", item.checked);
},
},
]
: []),
{
label: "Tray",
submenu: [
{
label: "Disabled",
type: "radio",
checked: !config.get("options.tray"),
click: () => {
config.set("options.tray", false);
config.set("options.appVisible", true);
},
},
{
label: "Enabled + app visible",
type: "radio",
checked:
config.get("options.tray") && config.get("options.appVisible"),
click: () => {
config.set("options.tray", true);
config.set("options.appVisible", true);
},
},
{
label: "Enabled + app hidden",
type: "radio",
checked:
config.get("options.tray") && !config.get("options.appVisible"),
click: () => {
config.set("options.tray", true);
config.set("options.appVisible", false);
},
},
{ type: "separator" },
{
label: "Play/Pause on click",
type: "checkbox",
checked: config.get("options.trayClickPlayPause"),
click: (item) => {
config.set("options.trayClickPlayPause", item.checked);
},
},
],
},
{ type: "separator" },
{
label: "Advanced options",
submenu: [
{
label: "Proxy",
type: "checkbox",
checked: !!config.get("options.proxy"),
click: (item) => {
setProxy(item, win);
},
},
{
label: "Disable hardware acceleration",
type: "checkbox",
checked: config.get("options.disableHardwareAcceleration"),
click: (item) => {
config.set("options.disableHardwareAcceleration", item.checked);
},
},
{
label: "Restart on config changes",
type: "checkbox",
checked: config.get("options.restartOnConfigChanges"),
click: (item) => {
config.set("options.restartOnConfigChanges", item.checked);
},
},
{
label: "Reset App cache when app starts",
type: "checkbox",
checked: config.get("options.autoResetAppCache"),
click: (item) => {
config.set("options.autoResetAppCache", item.checked);
},
},
{ type: "separator" },
is.macOS() ?
{
label: "Toggle DevTools",
// Cannot use "toggleDevTools" role in MacOS
click: () => {
const { webContents } = win;
if (webContents.isDevToolsOpened()) {
webContents.closeDevTools();
} else {
const devToolsOptions = {};
webContents.openDevTools(devToolsOptions);
}
},
} :
{ role: "toggleDevTools" },
{
label: "Edit config.json",
click: () => {
config.edit();
},
},
]
},
],
},
{
label: "View",
submenu: [
{ role: "reload" },
{ role: "forceReload" },
{ type: "separator" },
{ role: "zoomIn" },
{ role: "zoomOut" },
{ role: "resetZoom" },
],
},
{
label: "Navigation",
submenu: [
{
label: "Go back",
click: () => {
if (win.webContents.canGoBack()) {
win.webContents.goBack();
}
},
},
{
label: "Go forward",
click: () => {
if (win.webContents.canGoForward()) {
win.webContents.goForward();
}
},
},
{
label: "Restart App",
click: () => {
app.relaunch();
app.quit();
},
},
{ role: "quit" },
],
},
];
}
module.exports.mainMenuTemplate = mainMenuTemplate;
module.exports.setApplicationMenu = (win) => {
const menuTemplate = [...mainMenuTemplate(win)];
if (process.platform === "darwin") {
const name = app.getName();
const name = app.name;
menuTemplate.unshift({
label : name,
label: name,
submenu: [
{ role: "about" },
{ type: "separator" },
@ -36,9 +282,9 @@ module.exports.setApplicationMenu = () => {
{ role: "unhide" },
{ type: "separator" },
{
label : "Select All",
label: "Select All",
accelerator: "CmdOrCtrl+A",
selector : "selectAll:"
selector: "selectAll:",
},
{ label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" },
{ label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" },
@ -46,11 +292,33 @@ module.exports.setApplicationMenu = () => {
{ type: "separator" },
{ role: "minimize" },
{ role: "close" },
{ role: "quit" }
]
{ role: "quit" },
],
});
}
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
};
async function setProxy(item, win) {
const output = await prompt({
title: 'Set Proxy',
label: 'Enter Proxy Address: (leave empty to disable)',
value: config.get("options.proxy"),
type: 'input',
inputAttrs: {
type: 'url',
placeholder: "Example: 'socks5://127.0.0.1:9999"
},
width: 450,
...promptOptions()
}, win);
if (typeof output === "string") {
config.set("options.proxy", output);
item.checked = output !== "";
} else { //user pressed cancel
item.checked = !item.checked; //reset checkbox
}
}

7321
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,65 +1,132 @@
{
"name" : "youtube-music",
"name": "youtube-music",
"productName": "YouTube Music",
"version" : "1.1.5",
"version": "1.15.0",
"description": "YouTube Music Desktop App - including custom plugins",
"license" : "MIT",
"repository" : "th-ch/youtube-music",
"author" : {
"name" : "th-ch",
"license": "MIT",
"repository": "th-ch/youtube-music",
"author": {
"name": "th-ch",
"email": "th-ch@users.noreply.github.com",
"url" : "https://github.com/th-ch/youtube-music"
"url": "https://github.com/th-ch/youtube-music"
},
"build": {
"appId" : "com.github.th-ch.youtube-music",
"appId": "com.github.th-ch.youtube-music",
"productName": "YouTube Music",
"mac" : {
"mac": {
"identity": null,
"icon" : "assets/generated/icons/mac/icon.icns"
"icon": "assets/generated/icons/mac/icon.icns"
},
"win": {
"icon": "assets/generated/icons/win/icon.ico"
"icon": "assets/generated/icons/win/icon.ico",
"target": [
"nsis",
"portable"
]
},
"nsis": {
"runAfterFinish": false
},
"linux": {
"icon" : "assets/generated/icons/png",
"category": "AudioVideo"
"icon": "assets/generated/icons/png",
"category": "AudioVideo",
"target": [
"AppImage",
"snap",
"freebsd",
"deb",
"rpm"
]
},
"snap": {
"slots": [
{
"mpris": {
"interface": "mpris"
}
}
]
}
},
"scripts": {
"test" : "xo",
"start" : "electron .",
"icon" : "rimraf assets/generated && electron-icon-maker --input=assets/youtube-music.png --output=assets/generated",
"postinstall" : "npm run icon && npm rebuild && node plugins/adblocker/generator.js && electron-rebuild",
"clean" : "rimraf dist",
"build" : "npm run clean && build --win --mac --linux",
"build:mac" : "npm run clean && build --mac",
"build:win" : "npm run clean && build --win",
"release:linux": "npm run clean && build --linux -p always",
"release:mac" : "npm run clean && build --mac -p always",
"release:win" : "npm run clean && build --win -p always"
"test": "jest",
"start": "NODE_OPTIONS= electron .",
"start:debug": "ELECTRON_ENABLE_LOGGING=1 electron .",
"icon": "rimraf assets/generated && electron-icon-maker --input=assets/youtube-music.png --output=assets/generated",
"generate:package": "node utils/generate-package-json.js",
"postinstall": "yarn run icon && yarn run plugins",
"clean": "rimraf dist",
"build": "yarn run clean && electron-builder --win --mac --linux",
"build:linux": "yarn run clean && electron-builder --linux",
"build:mac": "yarn run clean && electron-builder --mac",
"build:win": "yarn run clean && electron-builder --win",
"lint": "xo",
"plugins": "yarn run plugin:adblocker",
"plugin:adblocker": "rimraf plugins/adblocker/ad-blocker-engine.bin && node plugins/adblocker/blocker.js",
"release:linux": "yarn run clean && electron-builder --linux -p always -c.snap.publish=github",
"release:mac": "yarn run clean && electron-builder --mac -p always",
"release:win": "yarn run clean && electron-builder --win -p always"
},
"engines": {
"node": ">=14.0.0",
"npm": "Please use yarn and not npm"
},
"dependencies": {
"ad-block" : "^4.1.3",
"electron-debug" : "^2.0.0",
"electron-is" : "^3.0.0",
"electron-localshortcut": "^3.1.0",
"electron-store" : "^2.0.0",
"electron-updater" : "^4.0.6"
"@cliqz/adblocker-electron": "^1.23.1",
"@electron/remote": "^2.0.1",
"@ffmpeg/core": "^0.10.0",
"@ffmpeg/ffmpeg": "^0.10.0",
"async-mutex": "^0.3.2",
"browser-id3-writer": "^4.4.0",
"chokidar": "^3.5.2",
"custom-electron-prompt": "^1.4.0",
"custom-electron-titlebar": "^3.2.9",
"discord-rpc": "^3.2.0",
"electron-better-web-request": "^1.0.1",
"electron-debug": "^3.2.0",
"electron-is": "^3.0.0",
"electron-localshortcut": "^3.2.1",
"electron-store": "^7.0.3",
"electron-unhandled": "^3.0.2",
"electron-updater": "^4.6.3",
"filenamify": "^4.3.0",
"hark": "^1.2.3",
"md5": "^2.3.0",
"mpris-service": "^2.1.2",
"node-fetch": "^2.6.6",
"node-notifier": "^9.0.1",
"ytdl-core": "^4.9.2",
"ytpl": "^2.2.3"
},
"devDependencies": {
"devtron" : "^1.4.0",
"electron" : "^4.0.8",
"electron-builder" : "^20.40.2",
"electron-devtools-installer": "^2.2.4",
"electron-icon-maker" : "0.0.4",
"electron-rebuild" : "^1.8.4",
"rimraf" : "^2.6.3",
"xo" : "^0.24.0"
"electron": "^16.0.5",
"electron-builder": "^22.10.5",
"electron-devtools-installer": "^3.1.1",
"electron-icon-maker": "0.0.5",
"jest": "^27.3.1",
"playwright": "^1.17.1",
"rimraf": "^3.0.2",
"xo": "^0.45.0"
},
"resolutions": {
"glob-parent": "5.1.2",
"minimist": "1.2.5",
"yargs-parser": "18.1.3"
},
"xo": {
"envs": [
"node",
"browser"
]
],
"rules": {
"quotes": [
"error",
"double",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
]
}
}
}

View File

@ -1 +1 @@
detector.buffer
/ad-blocker-engine.bin

View File

@ -1,3 +1,8 @@
const { blockWindowAds } = require("./blocker");
module.exports = win => blockWindowAds(win.webContents);
const { loadAdBlockerEngine } = require("./blocker");
module.exports = (win, options) =>
loadAdBlockerEngine(
win.webContents.session,
options.cache,
options.additionalBlockLists,
options.disableDefaultLists
);

View File

@ -1,12 +1,60 @@
const { initialize, containsAds } = require("./contains-ads");
const { promises } = require("fs"); // used for caching
const path = require("path");
module.exports.blockWindowAds = webContents => {
initialize();
webContents.session.webRequest.onBeforeRequest(
["*://*./*"],
(details, cb) => {
const shouldBeBlocked = containsAds(details.url);
cb({ cancel: shouldBeBlocked });
}
);
const { ElectronBlocker } = require("@cliqz/adblocker-electron");
const fetch = require("node-fetch");
const SOURCES = [
"https://raw.githubusercontent.com/kbinani/adblock-youtube-ads/master/signed.txt",
// uBlock Origin
"https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters.txt",
"https://raw.githubusercontent.com/uBlockOrigin/uAssets/master/filters/filters-2021.txt",
// Fanboy Annoyances
"https://secure.fanboy.co.nz/fanboy-annoyance_ubo.txt",
];
const loadAdBlockerEngine = (
session = undefined,
cache = true,
additionalBlockLists = [],
disableDefaultLists = false
) => {
// Only use cache if no additional blocklists are passed
const cachingOptions =
cache && additionalBlockLists.length === 0
? {
path: path.resolve(__dirname, "ad-blocker-engine.bin"),
read: promises.readFile,
write: promises.writeFile,
}
: undefined;
const lists = [
...(disableDefaultLists ? [] : SOURCES),
...additionalBlockLists,
];
ElectronBlocker.fromLists(
fetch,
lists,
{
// when generating the engine for caching, do not load network filters
// So that enhancing the session works as expected
// Allowing to define multiple webRequest listeners
loadNetworkFilters: session !== undefined,
},
cachingOptions
)
.then((blocker) => {
if (session) {
blocker.enableBlockingInSession(session);
} else {
console.log("Successfully generated adBlocker engine.");
}
})
.catch((err) => console.log("Error loading adBlocker engine", err));
};
module.exports = { loadAdBlockerEngine };
if (require.main === module) {
loadAdBlockerEngine(); // Generate the engine without enabling it
}

View File

@ -1,24 +0,0 @@
const fs = require("fs");
const path = require("path");
const Blocker = require("ad-block");
const client = new Blocker.AdBlockClient();
const file = path.resolve(__dirname, "detector.buffer");
module.exports.client = client;
module.exports.initialize = () =>
new Promise((resolve, reject) => {
fs.readFile(file, (err, buffer) => {
if (err) {
return reject(err);
}
client.deserialize(buffer);
return resolve();
});
});
const none = Blocker.FilterOptions.noFilterOption;
const isAd = (req, base) => client.matches(req, none, base);
module.exports.containsAds = (req, base) => isAd(req, base);
module.exports.isAd = isAd;

View File

@ -0,0 +1,4 @@
module.exports = () => {
// Preload adblocker to inject scripts/styles
require("@cliqz/adblocker-electron-preload/dist/preload.cjs");
};

View File

@ -1,67 +0,0 @@
// This file generates the detector buffer
const fs = require("fs");
const path = require("path");
const Blocker = require("ad-block");
const https = require("https");
const SOURCES = [
"https://raw.githubusercontent.com/kbinani/adblock-youtube-ads/master/signed.txt"
];
function parseAdblockList(client, adblockList) {
const urls = adblockList.split("\n");
const totalSize = urls.length;
console.log(
"Parsing " + totalSize + " urls (this can take a couple minutes)."
);
urls.map(line => client.parse(line));
console.log("Created buffer.");
}
function writeBuffer(client) {
const output = path.resolve(__dirname, "detector.buffer");
fs.writeFile(output, client.serialize(64), err => {
if (err) {
console.error(err);
return;
}
console.log("Wrote buffer to detector.buffer!");
});
}
function generateDetectorBuffer() {
const client = new Blocker.AdBlockClient();
let nbSourcesFetched = 0;
// fetch updated versions
SOURCES.forEach(source => {
console.log("Downloading " + source);
https
.get(source, resp => {
let data = "";
// A chunk of data has been recieved.
resp.on("data", chunk => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on("end", () => {
parseAdblockList(client, data);
nbSourcesFetched++;
if (nbSourcesFetched === SOURCES.length) {
writeBuffer(client);
}
});
})
.on("error", err => {
console.log("Error: " + err.message);
});
});
}
module.exports = generateDetectorBuffer;
if (require.main === module) {
generateDetectorBuffer();
}

View File

@ -0,0 +1,17 @@
const applyCompressor = () => {
const audioContext = new AudioContext();
const compressor = audioContext.createDynamicsCompressor();
compressor.threshold.value = -50;
compressor.ratio.value = 12;
compressor.knee.value = 40;
compressor.attack.value = 0;
compressor.release.value = 0.25;
const source = audioContext.createMediaElementSource(document.querySelector("video"));
source.connect(compressor);
compressor.connect(audioContext.destination);
};
module.exports = () => document.addEventListener('apiLoaded', applyCompressor, { once: true, passive: true });

View File

@ -0,0 +1,6 @@
const path = require("path");
const { injectCSS } = require("../utils");
module.exports = win => {
injectCSS(win.webContents, path.join(__dirname, "style.css"));
};

View File

@ -0,0 +1,10 @@
#nav-bar-background,
#header.ytmusic-item-section-renderer,
ytmusic-tabs {
background: rgba(0, 0, 0, 0.3) !important;
backdrop-filter: blur(8px) !important;
}
#nav-bar-divider {
display: none !important;
}

View File

@ -0,0 +1,14 @@
module.exports = () => {
document.addEventListener('apiLoaded', apiEvent => {
apiEvent.detail.addEventListener('videodatachange', name => {
if (name === 'dataloaded') {
apiEvent.detail.pauseVideo();
document.querySelector('video').ontimeupdate = e => {
e.target.pause();
}
} else {
document.querySelector('video').ontimeupdate = null;
}
})
}, { once: true, passive: true })
};

148
plugins/discord/back.js Normal file
View File

@ -0,0 +1,148 @@
const Discord = require("discord-rpc");
const { dev } = require("electron-is");
const { dialog, app } = require("electron");
const registerCallback = require("../../providers/song-info");
// Application ID registered by @semvis123
const clientId = "790655993809338398";
/**
* @typedef {Object} Info
* @property {import('discord-rpc').Client} rpc
* @property {boolean} ready
* @property {import('../../providers/song-info').SongInfo} lastSongInfo
*/
/**
* @type {Info}
*/
const info = {
rpc: null,
ready: false,
lastSongInfo: null,
};
/**
* @type {(() => void)[]}
*/
const refreshCallbacks = [];
const resetInfo = () => {
info.rpc = null;
info.ready = false;
clearTimeout(clearActivity);
if (dev()) console.log("discord disconnected");
refreshCallbacks.forEach(cb => cb());
};
let window;
const connect = (showErr = false) => {
if (info.rpc) {
if (dev())
console.log('Attempted to connect with active RPC object');
return;
}
info.rpc = new Discord.Client({
transport: "ipc",
});
info.ready = false;
info.rpc.once("connected", () => {
if (dev()) console.log("discord connected");
refreshCallbacks.forEach(cb => cb());
});
info.rpc.once("ready", () => {
info.ready = true;
if (info.lastSongInfo) updateActivity(info.lastSongInfo)
});
info.rpc.once("disconnected", resetInfo);
// Startup the rpc client
info.rpc.login({ clientId }).catch(err => {
resetInfo();
if (dev()) console.error(err);
if (showErr) dialog.showMessageBox(window, { title: 'Connection failed', message: err.message || String(err), type: 'error' });
});
};
let clearActivity;
/**
* @type {import('../../providers/song-info').songInfoCallback}
*/
let updateActivity;
module.exports = (win, { activityTimoutEnabled, activityTimoutTime, listenAlong }) => {
window = win;
// We get multiple events
// Next song: PAUSE(n), PAUSE(n+1), PLAY(n+1)
// Skip time: PAUSE(N), PLAY(N)
updateActivity = songInfo => {
if (songInfo.title.length === 0 && songInfo.artist.length === 0) {
return;
}
info.lastSongInfo = songInfo;
// stop the clear activity timout
clearTimeout(clearActivity);
// stop early if discord connection is not ready
// do this after clearTimeout to avoid unexpected clears
if (!info.rpc || !info.ready) {
return;
}
// clear directly if timeout is 0
if (songInfo.isPaused && activityTimoutEnabled && activityTimoutTime === 0) {
info.rpc.clearActivity().catch(console.error);
return;
}
// Song information changed, so lets update the rich presence
// @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
const activityInfo = {
type: 2, // Listening, addressed in https://github.com/discordjs/RPC/pull/149
details: songInfo.title,
state: songInfo.artist,
largeImageKey: songInfo.imageSrc,
largeImageText: [
songInfo.uploadDate,
songInfo.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " views",
].join(' || '),
buttons: listenAlong ? [
{ label: "Listen Along", url: songInfo.url },
] : undefined,
};
if (songInfo.isPaused) {
// Add an idle icon to show that the song is paused
activityInfo.smallImageKey = "idle";
activityInfo.smallImageText = "idle/paused";
// Set start the timer so the activity gets cleared after a while if enabled
if (activityTimoutEnabled)
clearActivity = setTimeout(() => info.rpc.clearActivity().catch(console.error), activityTimoutTime ?? 10000);
} else {
// Add the start and end time of the song
const songStartTime = Date.now() - songInfo.elapsedSeconds * 1000;
activityInfo.startTimestamp = songStartTime;
activityInfo.endTimestamp =
songStartTime + songInfo.songDuration * 1000;
}
info.rpc.setActivity(activityInfo).catch(console.error);
};
// If the page is ready, register the callback
win.once("ready-to-show", () => {
registerCallback(updateActivity);
connect();
});
app.on('window-all-closed', module.exports.clear)
};
module.exports.clear = () => {
if (info.rpc) info.rpc.clearActivity();
clearTimeout(clearActivity);
};
module.exports.connect = connect;
module.exports.registerRefresh = (cb) => refreshCallbacks.push(cb);
module.exports.isConnected = () => info.rpc !== null;

47
plugins/discord/menu.js Normal file
View File

@ -0,0 +1,47 @@
const { setOptions } = require("../../config/plugins");
const { edit } = require("../../config");
const { clear, connect, registerRefresh, isConnected } = require("./back");
let hasRegisterred = false;
module.exports = (win, options, refreshMenu) => {
if (!hasRegisterred) {
registerRefresh(refreshMenu);
hasRegisterred = true;
}
return [
{
label: isConnected() ? "Connected" : "Reconnect",
enabled: !isConnected(),
click: connect,
},
{
label: "Clear activity",
click: clear,
},
{
label: "Clear activity after timeout",
type: "checkbox",
checked: options.activityTimoutEnabled,
click: (item) => {
options.activityTimoutEnabled = item.checked;
setOptions('discord', options);
},
},
{
label: "Listen Along",
type: "checkbox",
checked: options.listenAlong,
click: (item) => {
options.listenAlong = item.checked;
setOptions('discord', options);
},
},
{
label: "Set timeout time in config",
// open config.json
click: edit,
},
];
};

View File

@ -0,0 +1,11 @@
const CHANNEL = "downloader";
const ACTIONS = {
ERROR: "error",
METADATA: "metadata",
PROGRESS: "progress",
};
module.exports = {
CHANNEL: CHANNEL,
ACTIONS: ACTIONS,
};

View File

@ -0,0 +1,87 @@
const { writeFileSync } = require("fs");
const { join } = require("path");
const ID3Writer = require("browser-id3-writer");
const { dialog, ipcMain } = require("electron");
const registerCallback = require("../../providers/song-info");
const { injectCSS, listenAction } = require("../utils");
const { cropMaxWidth } = require("./utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { getImage } = require("../../providers/song-info");
const sendError = (win, error) => {
win.setProgressBar(-1); // close progress bar
dialog.showMessageBox({
type: "info",
buttons: ["OK"],
title: "Error in download!",
message: "Argh! Apologies, download failed…",
detail: error.toString(),
});
};
let nowPlayingMetadata = {};
function handle(win) {
injectCSS(win.webContents, join(__dirname, "style.css"));
registerCallback((info) => {
nowPlayingMetadata = info;
});
listenAction(CHANNEL, (event, action, arg) => {
switch (action) {
case ACTIONS.ERROR: // arg = error
sendError(win, arg);
break;
case ACTIONS.METADATA:
event.returnValue = JSON.stringify(nowPlayingMetadata);
break;
case ACTIONS.PROGRESS: // arg = progress
win.setProgressBar(arg);
break;
default:
console.log("Unknown action: " + action);
}
});
ipcMain.on("add-metadata", async (event, filePath, songBuffer, currentMetadata) => {
let fileBuffer = songBuffer;
const songMetadata = currentMetadata.imageSrcYTPL ? // This means metadata come from ytpl.getInfo();
{
...currentMetadata,
image: cropMaxWidth(await getImage(currentMetadata.imageSrcYTPL))
} :
{ ...nowPlayingMetadata, ...currentMetadata };
try {
const coverBuffer = songMetadata.image && !songMetadata.image.isEmpty() ?
songMetadata.image.toPNG() : null;
const writer = new ID3Writer(songBuffer);
// Create the metadata tags
writer
.setFrame("TIT2", songMetadata.title)
.setFrame("TPE1", [songMetadata.artist]);
if (coverBuffer) {
writer.setFrame("APIC", {
type: 3,
data: coverBuffer,
description: ""
});
}
writer.addTag();
fileBuffer = Buffer.from(writer.arrayBuffer);
} catch (error) {
sendError(win, error);
}
writeFileSync(filePath, fileBuffer);
// Notify the youtube-dl file
event.reply("add-metadata-done");
});
}
module.exports = handle;
module.exports.sendError = sendError;

View File

@ -0,0 +1,87 @@
const { contextBridge } = require("electron");
const { defaultConfig } = require("../../config");
const { getSongMenu } = require("../../providers/dom-elements");
const { ElementFromFile, templatePath, triggerAction } = require("../utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { downloadVideoToMP3 } = require("./youtube-dl");
let menu = null;
let progress = null;
const downloadButton = ElementFromFile(
templatePath(__dirname, "download.html")
);
let pluginOptions = {};
const observer = new MutationObserver((mutations, observer) => {
if (!menu) {
menu = getSongMenu();
}
if (menu && !menu.contains(downloadButton)) {
menu.prepend(downloadButton);
progress = document.querySelector("#ytmcustom-download");
}
});
const reinit = () => {
triggerAction(CHANNEL, ACTIONS.PROGRESS, -1); // closes progress bar
if (!progress) {
console.warn("Cannot update progress");
} else {
progress.innerHTML = "Download";
}
};
const baseUrl = defaultConfig.url;
// TODO: re-enable once contextIsolation is set to true
// contextBridge.exposeInMainWorld("downloader", {
// download: () => {
global.download = () => {
triggerAction(CHANNEL, ACTIONS.PROGRESS, 2); // starts with indefinite progress bar
let metadata;
let videoUrl = getSongMenu()
// selector of first button which is always "Start Radio"
?.querySelector('ytmusic-menu-navigation-item-renderer.iron-selected[tabindex="0"] #navigation-endpoint')
?.getAttribute("href");
if (videoUrl) {
videoUrl = baseUrl + "/" + videoUrl;
metadata = null;
} else {
metadata = global.songInfo;
videoUrl = metadata.url || window.location.href;
}
downloadVideoToMP3(
videoUrl,
(feedback, ratio = undefined) => {
if (!progress) {
console.warn("Cannot update progress");
} else {
progress.innerHTML = feedback;
}
if (ratio) {
triggerAction(CHANNEL, ACTIONS.PROGRESS, ratio);
}
},
(error) => {
triggerAction(CHANNEL, ACTIONS.ERROR, error);
reinit();
},
reinit,
pluginOptions,
metadata
);
};
// });
function observeMenu(options) {
pluginOptions = { ...pluginOptions, ...options };
observer.observe(document, {
childList: true,
subtree: true,
});
}
module.exports = observeMenu;

125
plugins/downloader/menu.js Normal file
View File

@ -0,0 +1,125 @@
const { existsSync, mkdirSync } = require("fs");
const { join } = require("path");
const { dialog, ipcMain } = require("electron");
const is = require("electron-is");
const ytpl = require("ytpl");
const chokidar = require('chokidar');
const { setOptions } = require("../../config/plugins");
const { sendError } = require("./back");
const { defaultMenuDownloadLabel, getFolder, presets } = require("./utils");
let downloadLabel = defaultMenuDownloadLabel;
let playingPlaylistId = undefined;
let callbackIsRegistered = false;
module.exports = (win, options) => {
if (!callbackIsRegistered) {
ipcMain.on("video-src-changed", async (_, data) => {
playingPlaylistId = JSON.parse(data)?.videoDetails?.playlistId;
});
callbackIsRegistered = true;
}
return [
{
label: downloadLabel,
click: async () => {
const currentPagePlaylistId = new URL(win.webContents.getURL()).searchParams.get("list");
const playlistId = currentPagePlaylistId || playingPlaylistId;
if (!playlistId) {
sendError(win, new Error("No playlist ID found"));
return;
}
console.log(`trying to get playlist ID: '${playlistId}'`);
let playlist;
try {
playlist = await ytpl(playlistId, {
limit: options.playlistMaxItems || Infinity,
});
} catch (e) {
sendError(win, e);
return;
}
const playlistTitle = playlist.title;
const folder = getFolder(options.downloadFolder);
const playlistFolder = join(folder, playlistTitle);
if (existsSync(playlistFolder)) {
sendError(
win,
new Error(`The folder ${playlistFolder} already exists`)
);
return;
}
mkdirSync(playlistFolder, { recursive: true });
dialog.showMessageBox({
type: "info",
buttons: ["OK"],
title: "Started Download",
message: `Downloading Playlist "${playlistTitle}"`,
detail: `(${playlist.items.length} songs)`,
});
if (is.dev()) {
console.log(
`Downloading playlist "${playlistTitle}" (${playlist.items.length} songs)`
);
}
const steps = 1 / playlist.items.length;
let progress = 0;
win.setProgressBar(2); // starts with indefinite bar
let dirWatcher = chokidar.watch(playlistFolder);
dirWatcher.on('add', () => {
progress += steps;
if (progress >= 0.9999) {
win.setProgressBar(-1); // close progress bar
dirWatcher.close().then(() => dirWatcher = null);
} else {
win.setProgressBar(progress);
}
});
playlist.items.forEach((song) => {
win.webContents.send(
"downloader-download-playlist",
song.url,
playlistTitle,
options
);
});
},
},
{
label: "Choose download folder",
click: () => {
let result = dialog.showOpenDialogSync({
properties: ["openDirectory", "createDirectory"],
defaultPath: getFolder(options.downloadFolder),
});
if (result) {
options.downloadFolder = result[0];
setOptions("downloader", options);
} // else = user pressed cancel
},
},
{
label: "Presets",
submenu: Object.keys(presets).map((preset) => ({
label: preset,
type: "radio",
click: () => {
options.preset = preset;
setOptions("downloader", options);
},
checked: options.preset === preset || presets[preset] === undefined,
})),
},
];
};

View File

@ -0,0 +1,21 @@
.menu-item {
display: var(--ytmusic-menu-item_-_display);
height: var(--ytmusic-menu-item_-_height);
align-items: var(--ytmusic-menu-item_-_align-items);
padding: var(--ytmusic-menu-item_-_padding);
cursor: pointer;
}
.menu-item > .yt-simple-endpoint:hover {
background-color: var(--ytmusic-menu-item-hover-background-color);
}
.menu-icon {
flex: var(--ytmusic-menu-item-icon_-_flex);
margin: var(--ytmusic-menu-item-icon_-_margin);
fill: var(--ytmusic-menu-item-icon_-_fill);
stroke: var(--iron-icon-stroke-color, none);
width: var(--iron-icon-width, 24px);
height: var(--iron-icon-height, 24px);
animation: var(--iron-icon_-_animation);
}

View File

@ -0,0 +1,45 @@
<div
class="style-scope menu-item ytmusic-menu-popup-renderer"
role="option"
tabindex="-1"
aria-disabled="false"
aria-selected="false"
onclick="download()"
>
<div
id="navigation-endpoint"
class="yt-simple-endpoint style-scope ytmusic-menu-navigation-item-renderer"
tabindex="-1"
>
<div
class="icon menu-icon style-scope ytmusic-menu-navigation-item-renderer"
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
focusable="false"
class="style-scope yt-icon"
style="pointer-events: none; display: block; width: 100%; height: 100%"
>
<g class="style-scope yt-icon">
<path
d="M25.462,19.105v6.848H4.515v-6.848H0.489v8.861c0,1.111,0.9,2.012,2.016,2.012h24.967c1.115,0,2.016-0.9,2.016-2.012v-8.861H25.462z"
class="style-scope yt-icon"
fill="#aaaaaa"
/>
<path
d="M14.62,18.426l-5.764-6.965c0,0-0.877-0.828,0.074-0.828s3.248,0,3.248,0s0-0.557,0-1.416c0-2.449,0-6.906,0-8.723c0,0-0.129-0.494,0.615-0.494c0.75,0,4.035,0,4.572,0c0.536,0,0.524,0.416,0.524,0.416c0,1.762,0,6.373,0,8.742c0,0.768,0,1.266,0,1.266s1.842,0,2.998,0c1.154,0,0.285,0.867,0.285,0.867s-4.904,6.51-5.588,7.193C15.092,18.979,14.62,18.426,14.62,18.426z"
class="style-scope yt-icon"
fill="#aaaaaa"
/>
</g>
</svg>
</div>
<div
class="text style-scope ytmusic-menu-navigation-item-renderer"
id="ytmcustom-download"
>
Download
</div>
</div>
</div>

View File

@ -0,0 +1,39 @@
const electron = require("electron");
module.exports.getFolder = customFolder => customFolder || electron.app.getPath("downloads");
module.exports.defaultMenuDownloadLabel = "Download playlist";
const orderedQualityList = ["maxresdefault", "hqdefault", "mqdefault", "sdddefault"];
module.exports.urlToJPG = (imgUrl, videoId) => {
if (!imgUrl || imgUrl.includes(".jpg")) return imgUrl;
//it will almost never get further than hqdefault
for (const quality of orderedQualityList) {
if (imgUrl.includes(quality)) {
return `https://img.youtube.com/vi/${videoId}/${quality}.jpg`;
}
}
return `https://img.youtube.com/vi/${videoId}/default.jpg`;
}
module.exports.cropMaxWidth = (image) => {
const imageSize = image.getSize();
// standart youtube artwork width with margins from both sides is 280 + 720 + 280
if (imageSize.width === 1280 && imageSize.height === 720) {
return image.crop({
x: 280,
y: 0,
width: 720,
height: 720
});
}
return image;
}
// Presets for FFmpeg
module.exports.presets = {
"None (defaults to mp3)": undefined,
opus: {
extension: "opus",
ffmpegArgs: ["-acodec", "libopus"],
},
};

View File

@ -0,0 +1,201 @@
const { randomBytes } = require("crypto");
const { join } = require("path");
const Mutex = require("async-mutex").Mutex;
const { ipcRenderer } = require("electron");
const remote = require('@electron/remote');
const is = require("electron-is");
const filenamify = require("filenamify");
// Browser version of FFmpeg (in renderer process) instead of loading @ffmpeg/ffmpeg
// because --js-flags cannot be passed in the main process when the app is packaged
// See https://github.com/electron/electron/issues/22705
const FFmpeg = require("@ffmpeg/ffmpeg/dist/ffmpeg.min");
const ytdl = require("ytdl-core");
const { triggerAction, triggerActionSync } = require("../utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { presets, urlToJPG } = require("./utils");
const { cleanupName } = require("../../providers/song-info");
const { createFFmpeg } = FFmpeg;
const ffmpeg = createFFmpeg({
log: false,
logger: () => {}, // console.log,
progress: () => {}, // console.log,
});
const ffmpegMutex = new Mutex();
const downloadVideoToMP3 = async (
videoUrl,
sendFeedback,
sendError,
reinit,
options,
metadata = undefined,
subfolder = ""
) => {
sendFeedback("Downloading…");
if (metadata === null) {
const { videoDetails } = await ytdl.getInfo(videoUrl);
const thumbnails = videoDetails?.thumbnails;
metadata = {
artist:
videoDetails?.media?.artist ||
cleanupName(videoDetails?.author?.name) ||
"",
title: videoDetails?.media?.song || videoDetails?.title || "",
imageSrcYTPL: thumbnails ?
urlToJPG(thumbnails[thumbnails.length - 1].url, videoDetails?.videoId)
: ""
}
}
let videoName = "YouTube Music - Unknown title";
let videoReadableStream;
try {
videoReadableStream = ytdl(videoUrl, {
filter: "audioonly",
quality: "highestaudio",
highWaterMark: 32 * 1024 * 1024, // 32 MB
requestOptions: { maxRetries: 3 },
});
} catch (err) {
sendError(err);
return;
}
const chunks = [];
videoReadableStream
.on("data", (chunk) => {
chunks.push(chunk);
})
.on("progress", (_chunkLength, downloaded, total) => {
const ratio = downloaded / total;
const progress = Math.floor(ratio * 100);
sendFeedback("Download: " + progress + "%", ratio);
})
.on("info", (info, format) => {
videoName = info.videoDetails.title.replace("|", "").toString("ascii");
if (is.dev()) {
console.log(
"Downloading video - name:",
videoName,
"- quality:",
format.audioBitrate + "kbits/s"
);
}
})
.on("error", sendError)
.on("end", async () => {
const buffer = Buffer.concat(chunks);
await toMP3(
videoName,
buffer,
sendFeedback,
sendError,
reinit,
options,
metadata,
subfolder
);
});
};
const toMP3 = async (
videoName,
buffer,
sendFeedback,
sendError,
reinit,
options,
existingMetadata = undefined,
subfolder = ""
) => {
const convertOptions = { ...presets[options.preset], ...options };
const safeVideoName = randomBytes(32).toString("hex");
const extension = convertOptions.extension || "mp3";
const releaseFFmpegMutex = await ffmpegMutex.acquire();
try {
if (!ffmpeg.isLoaded()) {
sendFeedback("Loading…", 2); // indefinite progress bar after download
await ffmpeg.load();
}
sendFeedback("Preparing file…");
ffmpeg.FS("writeFile", safeVideoName, buffer);
sendFeedback("Converting…");
const metadata = existingMetadata || getMetadata();
await ffmpeg.run(
"-i",
safeVideoName,
...getFFmpegMetadataArgs(metadata),
...(convertOptions.ffmpegArgs || []),
safeVideoName + "." + extension
);
const folder = options.downloadFolder || remote.app.getPath("downloads");
const name = metadata.title
? `${metadata.artist ? `${metadata.artist} - ` : ""}${metadata.title}`
: videoName;
const filename = filenamify(name + "." + extension, {
replacement: "_",
maxLength: 255,
});
const filePath = join(folder, subfolder, filename);
const fileBuffer = ffmpeg.FS("readFile", safeVideoName + "." + extension);
// Add the metadata
sendFeedback("Adding metadata…");
ipcRenderer.send("add-metadata", filePath, fileBuffer, {
artist: metadata.artist,
title: metadata.title,
imageSrcYTPL: metadata.imageSrcYTPL
});
ipcRenderer.once("add-metadata-done", reinit);
} catch (e) {
sendError(e);
} finally {
releaseFFmpegMutex();
}
};
const getMetadata = () => {
return JSON.parse(triggerActionSync(CHANNEL, ACTIONS.METADATA));
};
const getFFmpegMetadataArgs = (metadata) => {
if (!metadata) {
return;
}
return [
...(metadata.title ? ["-metadata", `title=${metadata.title}`] : []),
...(metadata.artist ? ["-metadata", `artist=${metadata.artist}`] : []),
];
};
module.exports = {
downloadVideoToMP3,
};
ipcRenderer.on(
"downloader-download-playlist",
(_, url, playlistFolder, options) => {
downloadVideoToMP3(
url,
() => {},
(error) => {
triggerAction(CHANNEL, ACTIONS.ERROR, error);
},
() => {},
options,
null,
playlistFolder
);
}
);

View File

@ -0,0 +1,47 @@
// "Youtube Music fix volume ratio 0.4" by Marco Pfeiffer
// https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/
const exponentialVolume = () => {
// manipulation exponent, higher value = lower volume
// 3 is the value used by pulseaudio, which Barteks2x figured out this gist here: https://gist.github.com/Barteks2x/a4e189a36a10c159bb1644ffca21c02a
// 0.05 (or 5%) is the lowest you can select in the UI which with an exponent of 3 becomes 0.000125 or 0.0125%
const EXPONENT = 3;
const storedOriginalVolumes = new WeakMap();
const { get, set } = Object.getOwnPropertyDescriptor(
HTMLMediaElement.prototype,
"volume"
);
Object.defineProperty(HTMLMediaElement.prototype, "volume", {
get() {
const lowVolume = get.call(this);
const calculatedOriginalVolume = lowVolume ** (1 / EXPONENT);
// The calculated value has some accuracy issues which can lead to problems for implementations that expect exact values.
// To avoid this, I'll store the unmodified volume to return it when read here.
// This mostly solves the issue, but the initial read has no stored value and the volume can also change though external influences.
// To avoid ill effects, I check if the stored volume is somewhere in the same range as the calculated volume.
const storedOriginalVolume = storedOriginalVolumes.get(this);
const storedDeviation = Math.abs(
storedOriginalVolume - calculatedOriginalVolume
);
const originalVolume =
storedDeviation < 0.01
? storedOriginalVolume
: calculatedOriginalVolume;
return originalVolume;
},
set(originalVolume) {
const lowVolume = originalVolume ** EXPONENT;
storedOriginalVolumes.set(this, originalVolume);
set.call(this, lowVolume);
},
});
};
module.exports = () =>
document.addEventListener("apiLoaded", exponentialVolume, {
once: true,
passive: true,
});

View File

@ -0,0 +1,33 @@
const path = require("path");
const electronLocalshortcut = require("electron-localshortcut");
const config = require("../../config");
const { injectCSS } = require("../utils");
//tracks menu visibility
let visible = true;
module.exports = (win) => {
// css for custom scrollbar + disable drag area(was causing bugs)
injectCSS(win.webContents, path.join(__dirname, "style.css"));
win.once("ready-to-show", () => {
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
electronLocalshortcut.register(win, "Esc", () => {
setMenuVisibility(!visible);
});
}
});
win.webContents.once("did-finish-load", () => {
// fix bug with menu not applying on start when no internet connection available
setMenuVisibility(!config.get("options.hideMenu"));
});
function setMenuVisibility(value) {
visible = value;
win.webContents.send("updateMenu", visible);
}
};

View File

@ -0,0 +1,33 @@
const { ipcRenderer } = require("electron");
const { Menu } = require("@electron/remote");
const customTitlebar = require("custom-electron-titlebar");
function $(selector) { return document.querySelector(selector); }
module.exports = () => {
const bar = new customTitlebar.Titlebar({
backgroundColor: customTitlebar.Color.fromHex("#050505"),
itemBackgroundColor: customTitlebar.Color.fromHex("#121212"),
});
bar.updateTitle(" ");
document.title = "Youtube Music";
ipcRenderer.on("updateMenu", function (_event, showMenu) {
bar.updateMenu(showMenu ? Menu.getApplicationMenu() : null);
});
// 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', () => {
setNavbarMargin();
const playPageObserver = new MutationObserver(setNavbarMargin);
playPageObserver.observe($('ytmusic-app-layout'), { attributeFilter: ['player-page-open_', 'playerPageOpen_'] })
}, { once: true, passive: true })
};
function setNavbarMargin() {
$('#nav-bar-background').style.right =
$('ytmusic-app-layout').playerPageOpen_ ?
'0px' :
'12px';
}

View File

@ -0,0 +1,73 @@
/* increase font size for menu and menuItems */
.titlebar,
.menubar-menu-container .action-label {
font-size: 14px !important;
}
/* fixes nav-bar-background opacity bug, reposition it, and allows clicking scrollbar through it */
#nav-bar-background {
opacity: 1 !important;
pointer-events: none !important;
position: sticky !important;
top: 0 !important;
height: 75px !important;
}
/* remove window dragging for nav bar (conflict with titlebar drag) */
ytmusic-nav-bar,
.tab-titleiron-icon,
ytmusic-pivot-bar-item-renderer {
-webkit-app-region: unset !important;
}
/* move up item selection renderers */
ytmusic-item-section-renderer.stuck #header.ytmusic-item-section-renderer,
ytmusic-tabs.stuck {
top: calc(var(--ytmusic-nav-bar-height) - 15px) !important;
}
/* fix weird positioning in search screen*/
ytmusic-header-renderer.ytmusic-search-page {
position: unset !important;
}
/* Move navBar downwards */
ytmusic-nav-bar[slot="nav-bar"] {
top: 17px !important;
}
/* fix page progress bar position*/
yt-page-navigation-progress,
#progress.yt-page-navigation-progress {
top: 30px !important;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 12px;
background-color: #030303;
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
}
/* hover effect for both scrollbar area, and scrollbar 'thumb' */
::-webkit-scrollbar:hover {
background-color: rgba(15, 15, 15, 0.699);
}
/* The scrollbar 'thumb' ...that marque oval shape in a scrollbar */
::-webkit-scrollbar-thumb:vertical {
background-clip: padding-box;
border: 2px solid rgba(0, 0, 0, 0);
background: #3a3a3a;
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
}
::-webkit-scrollbar-thumb:vertical:active {
background: #4d4c4c; /* Some darker color when you click it */
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
}

160
plugins/last-fm/back.js Normal file
View File

@ -0,0 +1,160 @@
const fetch = require('node-fetch');
const md5 = require('md5');
const { shell } = require('electron');
const { setOptions } = require('../../config/plugins');
const registerCallback = require('../../providers/song-info');
const defaultConfig = require('../../config/defaults');
const createFormData = params => {
// creates the body for in the post request
const formData = new URLSearchParams();
for (const key in params) {
formData.append(key, params[key]);
}
return formData;
}
const createQueryString = (params, api_sig) => {
// creates a querystring
const queryData = [];
params.api_sig = api_sig;
for (const key in params) {
queryData.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`);
}
return '?'+queryData.join('&');
}
const createApiSig = (params, secret) => {
// this function creates the api signature, see: https://www.last.fm/api/authspec
const keys = [];
for (const key in params) {
keys.push(key);
}
keys.sort();
let sig = '';
for (const key of keys) {
if (String(key) === 'format')
continue
sig += `${key}${params[key]}`;
}
sig += secret;
sig = md5(sig);
return sig;
}
const createToken = async ({ api_key, api_root, secret }) => {
// creates and stores the auth token
const data = {
method: 'auth.gettoken',
api_key: api_key,
format: 'json'
};
const api_sig = createApiSig(data, secret);
let response = await fetch(`${api_root}${createQueryString(data, api_sig)}`);
response = await response.json();
return response?.token;
}
const authenticate = async config => {
// asks the user for authentication
config.token = await createToken(config);
setOptions('last-fm', config);
shell.openExternal(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`);
return config;
}
const getAndSetSessionKey = async config => {
// get and store the session key
const data = {
api_key: config.api_key,
format: 'json',
method: 'auth.getsession',
token: config.token,
};
const api_sig = createApiSig(data, config.secret);
let res = await fetch(`${config.api_root}${createQueryString(data, api_sig)}`);
res = await res.json();
if (res.error)
await authenticate(config);
config.session_key = res?.session?.key;
setOptions('last-fm', config);
return config;
}
const postSongDataToAPI = async (songInfo, config, data) => {
// this sends a post request to the api, and adds the common data
if (!config.session_key)
await getAndSetSessionKey(config);
const postData = {
track: songInfo.title,
duration: songInfo.songDuration,
artist: songInfo.artist,
api_key: config.api_key,
sk: config.session_key,
format: 'json',
...data,
};
postData.api_sig = createApiSig(postData, config.secret);
fetch('https://ws.audioscrobbler.com/2.0/', {method: 'POST', body: createFormData(postData)})
.catch(res => {
if (res.response.data.error == 9) {
// session key is invalid, so remove it from the config and reauthenticate
config.session_key = undefined;
setOptions('last-fm', config);
authenticate(config);
}
});
}
const addScrobble = (songInfo, config) => {
// this adds one scrobbled song to last.fm
const data = {
method: 'track.scrobble',
timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000),
};
postSongDataToAPI(songInfo, config, data);
}
const setNowPlaying = (songInfo, config) => {
// this sets the now playing status in last.fm
const data = {
method: 'track.updateNowPlaying',
};
postSongDataToAPI(songInfo, config, data);
}
// this will store the timeout that will trigger addScrobble
let scrobbleTimer = undefined;
const lastfm = async (_win, config) => {
if (!config.api_root) {
// settings are not present, creating them with the default values
config = defaultConfig.plugins['last-fm'];
config.enabled = true;
setOptions('last-fm', config);
}
if (!config.session_key) {
// not authenticated
config = await getAndSetSessionKey(config);
}
registerCallback( songInfo => {
// set remove the old scrobble timer
clearTimeout(scrobbleTimer);
if (!songInfo.isPaused) {
setNowPlaying(songInfo, config);
// scrobble when the song is half way through, or has passed the 4 minute mark
const scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60);
if (scrobbleTime > songInfo.elapsedSeconds) {
// scrobble still needs to happen
const timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000;
scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config);
}
}
});
}
module.exports = lastfm;

View File

@ -0,0 +1,52 @@
const { join } = require("path");
const { ipcMain } = require("electron");
const is = require("electron-is");
const fetch = require("node-fetch");
const { cleanupName } = require("../../providers/song-info");
const { injectCSS } = require("../utils");
module.exports = async (win) => {
injectCSS(win.webContents, join(__dirname, "style.css"));
ipcMain.on("search-genius-lyrics", async (event, extractedSongInfo) => {
const metadata = JSON.parse(extractedSongInfo);
const queryString = `${cleanupName(metadata.artist)} ${cleanupName(
metadata.title
)}`;
let response = await fetch(
`https://genius.com/api/search/multi?per_page=5&q=${encodeURI(
queryString
)}`
);
if (!response.ok) {
event.returnValue = null;
return;
}
const info = await response.json();
let url = "";
try {
url = info.response.sections.filter(
(section) => section.type === "song"
)[0].hits[0].result.url;
} catch {
event.returnValue = null;
return;
}
if (is.dev()) {
console.log("Fetching lyrics from Genius:", url);
}
response = await fetch(url);
if (!response.ok) {
event.returnValue = null;
return;
}
event.returnValue = await response.text();
});
};

View File

@ -0,0 +1,67 @@
const { ipcRenderer } = require("electron");
const is = require("electron-is");
module.exports = () => {
ipcRenderer.on("update-song-info", (_, extractedSongInfo) => {
const lyricsTab = document.querySelector('tp-yt-paper-tab[tabindex="-1"]');
// Check if disabled
if (!lyricsTab || !lyricsTab.hasAttribute("disabled")) {
return;
}
const html = ipcRenderer.sendSync(
"search-genius-lyrics",
extractedSongInfo
);
if (!html) {
return;
} else if (is.dev()) {
console.log("Fetched lyrics from Genius");
}
const wrapper = document.createElement("div");
wrapper.innerHTML = html;
const lyricsSelector1 = wrapper.querySelector(".lyrics");
const lyricsSelector2 = wrapper.querySelector(
'[class^="Lyrics__Container"]'
);
const lyrics = lyricsSelector1
? lyricsSelector1.innerHTML
: lyricsSelector2
? lyricsSelector2.innerHTML
: null;
if (!lyrics) {
return;
}
lyricsTab.removeAttribute("disabled");
lyricsTab.removeAttribute("aria-disabled");
document.querySelector("tp-yt-paper-tab").onclick = () => {
lyricsTab.removeAttribute("disabled");
lyricsTab.removeAttribute("aria-disabled");
};
lyricsTab.onclick = () => {
const tabContainer = document.querySelector("ytmusic-tab-renderer");
const observer = new MutationObserver((_, observer) => {
const lyricsContainer = document.querySelector(
'[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"] > ytmusic-message-renderer'
);
if (lyricsContainer) {
lyricsContainer.innerHTML = `<div id="contents" class="style-scope ytmusic-section-list-renderer genius-lyrics">
${lyrics}
<yt-formatted-string class="footer style-scope ytmusic-description-shelf-renderer">Source&nbsp;: Genius</yt-formatted-string>
</div>`;
observer.disconnect();
}
});
observer.observe(tabContainer, {
attributes: true,
childList: true,
subtree: true,
});
};
});
};

View File

@ -0,0 +1,12 @@
/* Disable links in Genius lyrics */
.genius-lyrics a {
color: var(--ytmusic-text-primary);
display: inline-block;
pointer-events: none;
text-decoration: none;
}
#contents.genius-lyrics {
font-size: 1vw;
opacity: 0.9;
}

View File

@ -1,24 +1,24 @@
const { triggerAction } = require('../utils');
const { triggerAction } = require("../utils");
const CHANNEL = "navigation";
const ACTIONS = {
NEXT: "next",
BACK: 'back',
}
NEXT: "next",
BACK: "back",
};
function goToNextPage() {
triggerAction(CHANNEL, ACTIONS.NEXT);
triggerAction(CHANNEL, ACTIONS.NEXT);
}
function goToPreviousPage() {
triggerAction(CHANNEL, ACTIONS.BACK);
triggerAction(CHANNEL, ACTIONS.BACK);
}
module.exports = {
CHANNEL: CHANNEL,
ACTIONS: ACTIONS,
global: {
goToNextPage: goToNextPage,
goToPreviousPage: goToPreviousPage,
}
CHANNEL: CHANNEL,
ACTIONS: ACTIONS,
actions: {
goToNextPage: goToNextPage,
goToPreviousPage: goToPreviousPage,
},
};

View File

@ -1,23 +1,26 @@
const path = require("path");
const { injectCSS, listenAction } = require("../utils");
const { ACTIONS, CHANNEL } = require("./actions.js");
const { ACTIONS, CHANNEL } = require("./actions.js");
function handle(win) {
injectCSS(win.webContents, path.join(__dirname, "style.css"));
injectCSS(win.webContents, path.join(__dirname, "style.css"), () => {
win.webContents.send("navigation-css-ready");
});
listenAction(CHANNEL, (event, action) => {
switch (action) {
case ACTIONS.NEXT:
case ACTIONS.NEXT:
if (win.webContents.canGoForward()) {
win.webContents.goForward();
}
break;
case ACTIONS.BACK:
case ACTIONS.BACK:
if (win.webContents.canGoBack()) {
win.webContents.goBack();
}
break;
default:
default:
console.log("Unknown action: " + action);
}
});

View File

@ -1,15 +1,19 @@
const { ipcRenderer } = require("electron");
const { ElementFromFile, templatePath } = require("../utils");
function run() {
const forwardButton = ElementFromFile(
templatePath(__dirname, "forward.html")
);
const backButton = ElementFromFile(templatePath(__dirname, "back.html"));
const menu = document.querySelector("ytmusic-pivot-bar-renderer");
ipcRenderer.on("navigation-css-ready", () => {
const forwardButton = ElementFromFile(
templatePath(__dirname, "forward.html")
);
const backButton = ElementFromFile(templatePath(__dirname, "back.html"));
const menu = document.querySelector("ytmusic-pivot-bar-renderer");
if (menu) {
menu.prepend(backButton, forwardButton);
}
if (menu) {
menu.prepend(backButton, forwardButton);
}
});
}
module.exports = run;

View File

@ -1,17 +1,17 @@
.navigation-item {
font-family : Roboto, Noto Naskh Arabic UI, Arial, sans-serif;
font-size : 20px;
line-height : var(--ytmusic-title-1_-_line-height);
font-weight : 500;
color : #fff;
--yt-endpoint-color : #fff;
--yt-endpoint-hover-color : #fff;
font-family: Roboto, Noto Naskh Arabic UI, Arial, sans-serif;
font-size: 20px;
line-height: var(--ytmusic-title-1_-_line-height);
font-weight: 500;
color: #fff;
--yt-endpoint-color: #fff;
--yt-endpoint-hover-color: #fff;
--yt-endpoint-visited-color: #fff;
display : inline-flex;
align-items : center;
color : rgba(255, 255, 255, 0.5);
cursor : pointer;
margin : 0 var(--ytmusic-pivot-bar-tab-margin);
display: inline-flex;
align-items: center;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
margin: 0 var(--ytmusic-pivot-bar-tab-margin);
}
.navigation-item:hover {
@ -19,18 +19,18 @@
}
.navigation-icon {
display : inline-flex;
-ms-flex-align : center;
-webkit-align-items : center;
align-items : center;
-ms-flex-pack : center;
display: inline-flex;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content : center;
position : relative;
vertical-align : middle;
fill : var(--iron-icon-fill-color, currentcolor);
stroke : none;
width : var(--iron-icon-width, 24px);
height : var(--iron-icon-height, 24px);
animation : var(--iron-icon_-_animation);
justify-content: center;
position: relative;
vertical-align: middle;
fill: var(--iron-icon-fill-color, currentcolor);
stroke: none;
width: var(--iron-icon-width, 24px);
height: var(--iron-icon-height, 24px);
animation: var(--iron-icon_-_animation);
}

View File

@ -4,26 +4,6 @@
role="tab"
onclick="goToPreviousPage()"
>
<div
class="tab-icon style-scope ytmusic-pivot-bar-item-renderer yt-icon-container"
>
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
focusable="false"
class="style-scope yt-icon"
style="pointer-events: none; display: block; width: 100%; height: 100%;"
>
<g class="style-scope yt-icon">
<path
class="st0"
d="M109.3 265.2l218.9 218.9c5.1 5.1 11.8 7.9 19 7.9s14-2.8 19-7.9l16.1-16.1c10.5-10.5 10.5-27.6 0-38.1L198.6 246.1 382.7 62c5.1-5.1 7.9-11.8 7.9-19 0-7.2-2.8-14-7.9-19L366.5 7.9c-5.1-5.1-11.8-7.9-19-7.9-7.2 0-14 2.8-19 7.9L109.3 227c-5.1 5.1-7.9 11.9-7.8 19.1 0 7.2 2.8 14 7.8 19.1z"
class="style-scope yt-icon"
></path>
</g>
</svg>
</div>
<div
class="search-icon style-scope ytmusic-search-box"
role="button"
@ -31,17 +11,19 @@
aria-disabled="false"
title="Go to previous page"
>
<div id="icon" class="style-scope paper-icon-button navigation-icon">
<div
id="icon"
class="tab-icon style-scope paper-icon-button navigation-icon"
>
<svg
viewBox="0 0 492 492"
preserveAspectRatio="xMidYMid meet"
focusable="false"
class="style-scope iron-icon"
style="pointer-events: none; display: block; width: 100%; height: 100%;"
style="pointer-events: none; display: block; width: 100%; height: 100%"
>
<g class="style-scope iron-icon">
<path
class="st0"
d="M109.3 265.2l218.9 218.9c5.1 5.1 11.8 7.9 19 7.9s14-2.8 19-7.9l16.1-16.1c10.5-10.5 10.5-27.6 0-38.1L198.6 246.1 382.7 62c5.1-5.1 7.9-11.8 7.9-19 0-7.2-2.8-14-7.9-19L366.5 7.9c-5.1-5.1-11.8-7.9-19-7.9-7.2 0-14 2.8-19 7.9L109.3 227c-5.1 5.1-7.9 11.9-7.8 19.1 0 7.2 2.8 14 7.8 19.1z"
></path>
</g>

View File

@ -4,26 +4,6 @@
role="tab"
onclick="goToNextPage()"
>
<div class="tab-icon style-scope ytmusic-pivot-bar-item-renderer">
<svg
viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet"
focusable="false"
class="style-scope yt-icon"
style="pointer-events: none; display: block; width: 100%; height: 100%;"
>
<g class="style-scope yt-icon">
<path
d="M382.678,226.804L163.73,7.86C158.666,2.792,151.906,0,144.698,0s-13.968,2.792-19.032,7.86l-16.124,16.12
c-10.492,10.504-10.492,27.576,0,38.064L293.398,245.9l-184.06,184.06c-5.064,5.068-7.86,11.824-7.86,19.028
c0,7.212,2.796,13.968,7.86,19.04l16.124,16.116c5.068,5.068,11.824,7.86,19.032,7.86s13.968-2.792,19.032-7.86L382.678,265
c5.076-5.084,7.864-11.872,7.848-19.088C390.542,238.668,387.754,231.884,382.678,226.804z"
class="style-scope yt-icon"
></path>
</g>
</svg>
</div>
<div
class="search-icon style-scope ytmusic-search-box"
role="button"
@ -31,7 +11,10 @@
aria-disabled="false"
title="Go to next page"
>
<div id="icon" class="style-scope paper-icon-button navigation-icon">
<div
id="icon"
class="tab-icon style-scope paper-icon-button navigation-icon"
>
<svg
viewBox="0 0 492 492"
preserveAspectRatio="xMidYMid meet"
@ -41,7 +24,6 @@
>
<g class="style-scope iron-icon">
<path
class="st0"
d="M382.7,226.8L163.7,7.9c-5.1-5.1-11.8-7.9-19-7.9s-14,2.8-19,7.9L109.5,24c-10.5,10.5-10.5,27.6,0,38.1
l183.9,183.9L109.3,430c-5.1,5.1-7.9,11.8-7.9,19c0,7.2,2.8,14,7.9,19l16.1,16.1c5.1,5.1,11.8,7.9,19,7.9s14-2.8,19-7.9L382.7,265
c5.1-5.1,7.9-11.9,7.8-19.1C390.5,238.7,387.8,231.9,382.7,226.8z"

View File

@ -0,0 +1,46 @@
const { Notification } = require("electron");
const is = require("electron-is");
const registerCallback = require("../../providers/song-info");
const { notificationImage } = require("./utils");
const setupInteractive = require("./interactive")
const notify = (info, options) => {
// Fill the notification with content
const notification = {
title: info.title || "Playing",
body: info.artist,
icon: notificationImage(info),
silent: true,
urgency: options.urgency,
};
// Send the notification
const currentNotification = new Notification(notification);
currentNotification.show()
return currentNotification;
};
const setup = (options) => {
let oldNotification;
let currentUrl;
registerCallback(songInfo => {
if (!songInfo.isPaused && (songInfo.url !== currentUrl || options.unpauseNotification)) {
// Close the old notification
oldNotification?.close();
currentUrl = songInfo.url;
// This fixes a weird bug that would cause the notification to be updated instead of showing
setTimeout(() => { oldNotification = notify(songInfo, options) }, 10);
}
});
}
module.exports = (win, options) => {
// Register the callback for new song information
is.windows() && options.interactive ?
setupInteractive(win, options.unpauseNotification) :
setup(options);
};

View File

@ -0,0 +1,103 @@
const { notificationImage, icons } = require("./utils");
const getSongControls = require('../../providers/song-controls');
const registerCallback = require("../../providers/song-info");
const notifier = require("node-notifier");
//store song controls reference on launch
let controls;
let notificationOnUnpause;
module.exports = (win, unpauseNotification) => {
//Save controls and onPause option
const { playPause, next, previous } = getSongControls(win);
controls = { playPause, next, previous };
notificationOnUnpause = unpauseNotification;
let currentUrl;
// Register songInfoCallback
registerCallback(songInfo => {
if (!songInfo.isPaused && (songInfo.url !== currentUrl || notificationOnUnpause)) {
currentUrl = songInfo.url;
sendToaster(songInfo);
}
});
win.webContents.once("closed", () => {
deleteNotification()
});
}
//delete old notification
let toDelete;
function deleteNotification() {
if (toDelete !== undefined) {
// To remove the notification it has to be done this way
const removeNotif = Object.assign(toDelete, {
remove: toDelete.id
})
notifier.notify(removeNotif)
toDelete = undefined;
}
}
//New notification
function sendToaster(songInfo) {
deleteNotification();
//download image and get path
let imgSrc = notificationImage(songInfo, true);
toDelete = {
//app id undefined - will break buttons
title: songInfo.title || "Playing",
message: songInfo.artist,
id: parseInt(Math.random() * 1000000, 10),
icon: imgSrc,
actions: [
icons.previous,
songInfo.isPaused ? icons.play : icons.pause,
icons.next
],
sound: false,
};
//send notification
notifier.notify(
toDelete,
(err, data) => {
// Will also wait until notification is closed.
if (err) {
console.log(`ERROR = ${err.toString()}\n DATA = ${data}`);
}
switch (data) {
//buttons
case icons.previous.normalize():
controls.previous();
return;
case icons.next.normalize():
controls.next();
return;
case icons.play.normalize():
controls.playPause();
// dont delete notification on play/pause
toDelete = undefined;
//manually send notification if not sending automatically
if (!notificationOnUnpause) {
songInfo.isPaused = false;
sendToaster(songInfo);
}
return;
case icons.pause.normalize():
controls.playPause();
songInfo.isPaused = true;
toDelete = undefined;
sendToaster(songInfo);
return;
//Native datatype
case "dismissed":
case "timeout":
deleteNotification();
}
}
);
}

View File

@ -0,0 +1,30 @@
const { urgencyLevels, setOption } = require("./utils");
const is = require("electron-is");
module.exports = (win, options) => [
...(is.linux() ?
[{
label: "Notification Priority",
submenu: urgencyLevels.map(level => ({
label: level.name,
type: "radio",
checked: options.urgency === level.value,
click: () => setOption(options, "urgency", level.value)
})),
}] :
[]),
...(is.windows() ?
[{
label: "Interactive Notifications",
type: "checkbox",
checked: options.interactive,
click: (item) => setOption(options, "interactive", item.checked)
}] :
[]),
{
label: "Show notification on unpause",
type: "checkbox",
checked: options.unpauseNotification,
click: (item) => setOption(options, "unpauseNotification", item.checked)
},
];

View File

@ -0,0 +1,56 @@
const { setOptions } = require("../../config/plugins");
const path = require("path");
const { app } = require("electron");
const fs = require("fs");
const icon = "assets/youtube-music.png";
const tempIcon = path.join(app.getPath("userData"), "tempIcon.png");
module.exports.icons = {
play: "\u{1405}", // ᐅ
pause: "\u{2016}", // ‖
next: "\u{1433}", //
previous: "\u{1438}" //
}
module.exports.setOption = (options, option, value) => {
options[option] = value;
setOptions("notifications", options)
}
module.exports.urgencyLevels = [
{ name: "Low", value: "low" },
{ name: "Normal", value: "normal" },
{ name: "High", value: "critical" },
];
module.exports.notificationImage = function (songInfo, saveIcon = false) {
//return local path to temp icon
if (saveIcon && !!songInfo.image) {
try {
fs.writeFileSync(tempIcon,
centerNativeImage(songInfo.image)
.toPNG()
);
} catch (err) {
console.log(`Error writing song icon to disk:\n${err.toString()}`)
return icon;
}
return tempIcon;
}
//else: return image
return songInfo.image
? centerNativeImage(songInfo.image)
: icon
};
function centerNativeImage(nativeImage) {
const tempImage = nativeImage.resize({ height: 256 });
const margin = Math.max((tempImage.getSize().width - 256), 0);
return tempImage.crop({
x: Math.round(margin / 2),
y: 0,
width: 256, height: 256
})
}

View File

@ -0,0 +1,93 @@
const { getSongMenu } = require("../../providers/dom-elements");
const { ElementFromFile, templatePath } = require("../utils");
function $(selector) { return document.querySelector(selector); }
const slider = ElementFromFile(templatePath(__dirname, "slider.html"));
const roundToTwo = n => Math.round(n * 1e2) / 1e2;
const MIN_PLAYBACK_SPEED = 0.07;
const MAX_PLAYBACK_SPEED = 16;
let playbackSpeed = 1;
const updatePlayBackSpeed = () => {
$('video').playbackRate = playbackSpeed;
const playbackSpeedElement = $("#playback-speed-value");
if (playbackSpeedElement) {
playbackSpeedElement.innerHTML = playbackSpeed;
}
};
let menu;
let observingSlider = false;
const observePopupContainer = () => {
const observer = new MutationObserver(() => {
if (!menu) {
menu = getSongMenu();
}
if (menu && !menu.contains(slider)) {
menu.prepend(slider);
if (!observingSlider) {
setupSliderListener();
observingSlider = true;
}
}
});
observer.observe($('ytmusic-popup-container'), {
childList: true,
subtree: true,
});
};
const observeVideo = () => {
$('video').addEventListener('ratechange', forcePlaybackRate)
$('video').addEventListener('srcChanged', forcePlaybackRate)
}
const setupWheelListener = () => {
slider.addEventListener('wheel', e => {
e.preventDefault();
if (isNaN(playbackSpeed)) {
playbackSpeed = 1;
}
// e.deltaY < 0 means wheel-up
playbackSpeed = roundToTwo(e.deltaY < 0 ?
Math.min(playbackSpeed + 0.01, MAX_PLAYBACK_SPEED) :
Math.max(playbackSpeed - 0.01, MIN_PLAYBACK_SPEED)
);
updatePlayBackSpeed();
// update slider position
$('#playback-speed-slider').value = playbackSpeed;
})
}
function setupSliderListener() {
$('#playback-speed-slider').addEventListener('immediate-value-changed', e => {
playbackSpeed = e.detail.value || MIN_PLAYBACK_SPEED;
if (isNaN(playbackSpeed)) {
playbackSpeed = 1;
}
updatePlayBackSpeed();
})
}
function forcePlaybackRate(e) {
if (e.target.playbackRate !== playbackSpeed) {
e.target.playbackRate = playbackSpeed
}
}
module.exports = () => {
document.addEventListener('apiLoaded', e => {
observePopupContainer();
observeVideo();
setupWheelListener();
}, { once: true, passive: true })
};

View File

@ -0,0 +1,88 @@
<div
class="style-scope menu-item ytmusic-menu-popup-renderer"
role="option"
tabindex="-1"
aria-disabled="false"
aria-selected="false"
>
<div
id="navigation-endpoint"
class="yt-simple-endpoint style-scope ytmusic-menu-navigation-item-renderer"
tabindex="-1"
>
<tp-yt-paper-slider
id="playback-speed-slider"
class="volume-slider style-scope ytmusic-player-bar on-hover"
style="display: inherit !important"
max="2"
min="0"
step="0.125"
dir="ltr"
title="Playback speed"
aria-label="Playback speed"
role="slider"
tabindex="0"
aria-valuemin="0"
aria-valuemax="2"
aria-valuenow="1"
aria-disabled="false"
value="1"
><!--css-build:shady-->
<div id="sliderContainer" class="style-scope tp-yt-paper-slider">
<div class="bar-container style-scope tp-yt-paper-slider">
<tp-yt-paper-progress
id="sliderBar"
aria-hidden="true"
class="style-scope tp-yt-paper-slider"
role="progressbar"
value="1"
aria-valuenow="1"
aria-valuemin="0"
aria-valuemax="2"
aria-disabled="false"
style="touch-action: none"
><!--css-build:shady-->
<div
id="progressContainer"
class="style-scope tp-yt-paper-progress"
>
<div
id="secondaryProgress"
class="style-scope tp-yt-paper-progress"
hidden="true"
style="transform: scaleX(0)"
></div>
<div
id="primaryProgress"
class="style-scope tp-yt-paper-progress"
style="transform: scaleX(0.5)"
></div>
</div>
</tp-yt-paper-progress>
</div>
<dom-if class="style-scope tp-yt-paper-slider"
><template is="dom-if"></template
></dom-if>
<div
id="sliderKnob"
class="slider-knob style-scope tp-yt-paper-slider"
style="left: 50%; touch-action: none"
>
<div
class="slider-knob-inner style-scope tp-yt-paper-slider"
value="1"
></div>
</div>
</div>
<dom-if class="style-scope tp-yt-paper-slider"
><template is="dom-if"></template></dom-if
></tp-yt-paper-slider>
<div
class="text style-scope ytmusic-menu-navigation-item-renderer"
id="ytmcustom-playback-speed"
>
Speed (<span id="playback-speed-value">1</span>)
</div>
</div>
</div>

View File

@ -0,0 +1,9 @@
/*
This is used to determine if plugin is actually active
(not if its only enabled in options)
*/
let enabled = false;
module.exports = () => enabled = true;
module.exports.enabled = () => enabled;

View File

@ -0,0 +1,236 @@
const { ipcRenderer } = require("electron");
const { globalShortcut } = require('@electron/remote');
const { setOptions } = require("../../config/plugins");
function $(selector) { return document.querySelector(selector); }
let api;
module.exports = (options) => {
document.addEventListener('apiLoaded', e => {
api = e.detail;
firstRun(options);
}, { once: true, passive: true })
};
/** Restore saved volume and setup tooltip */
function firstRun(options) {
if (typeof options.savedVolume === "number") {
// Set saved volume as tooltip
setTooltip(options.savedVolume);
if (api.getVolume() !== options.savedVolume) {
api.setVolume(options.savedVolume);
}
}
setupPlaybar(options);
setupLocalArrowShortcuts(options);
setupGlobalShortcuts(options);
const noVid = $("#main-panel")?.computedStyleMap().get("display").value === "none";
injectVolumeHud(noVid);
if (!noVid) {
setupVideoPlayerOnwheel(options);
}
// Change options from renderer to keep sync
ipcRenderer.on("setOptions", (_event, newOptions = {}) => {
for (option in newOptions) {
options[option] = newOptions[option];
}
setOptions("precise-volume", options);
});
}
function injectVolumeHud(noVid) {
if (noVid) {
const position = "top: 18px; right: 60px; z-index: 999; position: absolute;";
const mainStyle = "font-size: xx-large; padding: 10px; transition: opacity 1s; pointer-events: none;";
$(".center-content.ytmusic-nav-bar").insertAdjacentHTML("beforeend",
`<span id="volumeHud" style="${position + mainStyle}"></span>`)
} else {
const position = `top: 10px; left: 10px; z-index: 999; position: absolute;`;
const mainStyle = "font-size: xxx-large; padding: 10px; transition: opacity 0.6s; webkit-text-stroke: 1px black; font-weight: 600; pointer-events: none;";
$("#song-video").insertAdjacentHTML('afterend',
`<span id="volumeHud" style="${position + mainStyle}"></span>`)
}
}
let hudFadeTimeout;
function showVolumeHud(volume) {
let volumeHud = $("#volumeHud");
if (!volumeHud) return;
volumeHud.textContent = volume + '%';
volumeHud.style.opacity = 1;
if (hudFadeTimeout) {
clearTimeout(hudFadeTimeout);
}
hudFadeTimeout = setTimeout(() => {
volumeHud.style.opacity = 0;
hudFadeTimeout = null;
}, 2000);
}
/** Add onwheel event to video player */
function setupVideoPlayerOnwheel(options) {
$("#main-panel").addEventListener("wheel", event => {
event.preventDefault();
// Event.deltaY < 0 means wheel-up
changeVolume(event.deltaY < 0, options);
});
}
function saveVolume(volume, options) {
options.savedVolume = volume;
writeOptions(options);
}
//without this function it would rewrite config 20 time when volume change by 20
let writeTimeout;
function writeOptions(options) {
if (writeTimeout) clearTimeout(writeTimeout);
writeTimeout = setTimeout(() => {
setOptions("precise-volume", options);
writeTimeout = null;
}, 1000)
}
/** Add onwheel event to play bar and also track if play bar is hovered*/
function setupPlaybar(options) {
const playerbar = $("ytmusic-player-bar");
playerbar.addEventListener("wheel", event => {
event.preventDefault();
// Event.deltaY < 0 means wheel-up
changeVolume(event.deltaY < 0, options);
});
// Keep track of mouse position for showVolumeSlider()
playerbar.addEventListener("mouseenter", () => {
playerbar.classList.add("on-hover");
});
playerbar.addEventListener("mouseleave", () => {
playerbar.classList.remove("on-hover");
});
setupSliderObserver(options);
}
/** Save volume + Update the volume tooltip when volume-slider is manually changed */
function setupSliderObserver(options) {
const sliderObserver = new MutationObserver(mutations => {
for (const mutation of mutations) {
// This checks that volume-slider was manually set
if (mutation.oldValue !== mutation.target.value &&
(typeof options.savedVolume !== "number" || Math.abs(options.savedVolume - mutation.target.value) > 4)) {
// Diff>4 means it was manually set
setTooltip(mutation.target.value);
saveVolume(mutation.target.value, options);
}
}
});
// Observing only changes in 'value' of volume-slider
sliderObserver.observe($("#volume-slider"), {
attributeFilter: ["value"],
attributeOldValue: true
});
}
/** if (toIncrease = false) then volume decrease */
function changeVolume(toIncrease, options) {
// Apply volume change if valid
const steps = Number(options.steps || 1);
api.setVolume(toIncrease ?
Math.min(api.getVolume() + steps, 100) :
Math.max(api.getVolume() - steps, 0));
// Save the new volume
saveVolume(api.getVolume(), options);
// change slider position (important)
updateVolumeSlider(options);
// Change tooltips to new value
setTooltip(options.savedVolume);
// Show volume slider
showVolumeSlider();
// Show volume HUD
showVolumeHud(options.savedVolume);
}
function updateVolumeSlider(options) {
// Slider value automatically rounds to multiples of 5
$("#volume-slider").value = options.savedVolume > 0 && options.savedVolume < 5 ?
5 : options.savedVolume;
}
let volumeHoverTimeoutID;
function showVolumeSlider() {
const slider = $("#volume-slider");
// This class display the volume slider if not in minimized mode
slider.classList.add("on-hover");
// Reset timeout if previous one hasn't completed
if (volumeHoverTimeoutID) {
clearTimeout(volumeHoverTimeoutID);
}
// Timeout to remove volume preview after 3 seconds if playbar isn't hovered
volumeHoverTimeoutID = setTimeout(() => {
volumeHoverTimeoutID = null;
if (!$("ytmusic-player-bar").classList.contains("on-hover")) {
slider.classList.remove("on-hover");
}
}, 3000);
}
// Set new volume as tooltip for volume slider and icon + expanding slider (appears when window size is small)
const tooltipTargets = [
"#volume-slider",
"tp-yt-paper-icon-button.volume",
"#expand-volume-slider",
"#expand-volume"
];
function setTooltip(volume) {
for (target of tooltipTargets) {
$(target).title = `${volume}%`;
}
}
function setupGlobalShortcuts(options) {
if (options.globalShortcuts.volumeUp) {
globalShortcut.register((options.globalShortcuts.volumeUp), () => changeVolume(true, options));
}
if (options.globalShortcuts.volumeDown) {
globalShortcut.register((options.globalShortcuts.volumeDown), () => changeVolume(false, options));
}
}
function setupLocalArrowShortcuts(options) {
if (options.arrowsShortcut) {
window.addEventListener('keydown', (event) => {
switch (event.code) {
case "ArrowUp":
event.preventDefault();
changeVolume(true, options);
break;
case "ArrowDown":
event.preventDefault();
changeVolume(false, options);
break;
}
});
}
}

View File

@ -0,0 +1,82 @@
const { enabled } = require("./back");
const { setOptions } = require("../../config/plugins");
const prompt = require("custom-electron-prompt");
const promptOptions = require("../../providers/prompt-options");
function changeOptions(changedOptions, options, win) {
for (option in changedOptions) {
options[option] = changedOptions[option];
}
// Dynamically change setting if plugin is enabled
if (enabled()) {
win.webContents.send("setOptions", changedOptions);
} else { // Fallback to usual method if disabled
setOptions("precise-volume", options);
}
}
module.exports = (win, options) => [
{
label: "Local Arrowkeys Controls",
type: "checkbox",
checked: !!options.arrowsShortcut,
click: item => {
changeOptions({ arrowsShortcut: item.checked }, options, win);
}
},
{
label: "Global Hotkeys",
type: "checkbox",
checked: !!options.globalShortcuts.volumeUp || !!options.globalShortcuts.volumeDown,
click: item => promptGlobalShortcuts(win, options, item)
},
{
label: "Set Custom Volume Steps",
click: () => promptVolumeSteps(win, options)
}
];
// Helper function for globalShortcuts prompt
const kb = (label_, value_, default_) => { return { value: value_, label: label_, default: default_ || undefined }; };
async function promptVolumeSteps(win, options) {
const output = await prompt({
title: "Volume Steps",
label: "Choose Volume Increase/Decrease Steps",
value: options.steps || 1,
type: "counter",
counterOptions: { minimum: 0, maximum: 100, multiFire: true },
width: 380,
...promptOptions()
}, win)
if (output || output === 0) { // 0 is somewhat valid
changeOptions({ steps: output}, options, win);
}
}
async function promptGlobalShortcuts(win, options, item) {
const output = await prompt({
title: "Global Volume Keybinds",
label: "Choose Global Volume Keybinds:",
type: "keybind",
keybindOptions: [
kb("Increase Volume", "volumeUp", options.globalShortcuts?.volumeUp),
kb("Decrease Volume", "volumeDown", options.globalShortcuts?.volumeDown)
],
...promptOptions()
}, win)
if (output) {
let newGlobalShortcuts = {};
for (const { value, accelerator } of output) {
newGlobalShortcuts[value] = accelerator;
}
changeOptions({ globalShortcuts: newGlobalShortcuts }, options, win);
item.checked = !!options.globalShortcuts.volumeUp || !!options.globalShortcuts.volumeDown;
} else {
// Reset checkbox if prompt was canceled
item.checked = !item.checked;
}
}

View File

@ -0,0 +1,33 @@
const { ipcRenderer } = require("electron");
const is = require("electron-is");
let ignored = {
id: ["volume-slider", "expand-volume-slider"],
types: ["mousewheel", "keydown", "keyup"]
};
function overrideAddEventListener() {
// Save native addEventListener
Element.prototype._addEventListener = Element.prototype.addEventListener;
// Override addEventListener to Ignore specific events in volume-slider
Element.prototype.addEventListener = function (type, listener, useCapture = false) {
if (!(
ignored.id.includes(this.id) &&
ignored.types.includes(type)
)) {
this._addEventListener(type, listener, useCapture);
} else if (is.dev()) {
console.log(`Ignoring event: "${this.id}.${type}()"`);
}
};
}
module.exports = () => {
overrideAddEventListener();
// Restore original function after finished loading to avoid keeping Element.prototype altered
window.addEventListener('load', () => {
Element.prototype.addEventListener = Element.prototype._addEventListener;
Element.prototype._addEventListener = undefined;
ignored = undefined;
}, { once: true });
};

View File

@ -0,0 +1,41 @@
const { ElementFromFile, templatePath } = require("../utils");
const { dialog } = require('@electron/remote');
function $(selector) { return document.querySelector(selector); }
const qualitySettingsButton = ElementFromFile(
templatePath(__dirname, "qualitySettingsTemplate.html")
);
module.exports = () => {
document.addEventListener('apiLoaded', setup, { once: true, passive: true });
}
function setup(event) {
const api = event.detail;
$('.top-row-buttons.ytmusic-player').prepend(qualitySettingsButton);
qualitySettingsButton.onclick = function chooseQuality() {
if (api.getPlayerState() === 2) api.playVideo();
else if (api.getPlayerState() === 1) api.pauseVideo();
const currentIndex = api.getAvailableQualityLevels().indexOf(api.getPlaybackQuality())
dialog.showMessageBox({
type: "question",
buttons: api.getAvailableQualityLabels(),
defaultId: currentIndex,
title: "Choose Video Quality",
message: "Choose Video Quality:",
detail: `Current Quality: ${api.getAvailableQualityLabels()[currentIndex]}`,
cancelId: -1
}).then((promise) => {
if (promise.response === -1) return;
const newQuality = api.getAvailableQualityLevels()[promise.response];
api.setPlaybackQualityRange(newQuality);
api.setPlaybackQuality(newQuality)
})
}
}

View File

@ -0,0 +1,13 @@
<tp-yt-paper-icon-button class="player-quality-button style-scope ytmusic-player" icon="yt-icons:settings"
title="Open player quality changer" aria-label="Open player quality changer" role="button" tabindex="0" aria-disabled="false">
<tp-yt-iron-icon id="icon" class="style-scope tp-yt-paper-icon-button"><svg viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope yt-icon"
style="pointer-events: none; display: block; width: 100%; height: 100%;">
<g class="style-scope yt-icon">
<path
d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.1-1.65c.2-.15.25-.42.13-.64l-2-3.46c-.12-.22-.4-.3-.6-.22l-2.5 1c-.52-.4-1.08-.73-1.7-.98l-.37-2.65c-.06-.24-.27-.42-.5-.42h-4c-.27 0-.48.18-.5.42l-.4 2.65c-.6.25-1.17.6-1.7.98l-2.48-1c-.23-.1-.5 0-.6.22l-2 3.46c-.14.22-.08.5.1.64l2.12 1.65c-.04.32-.07.65-.07.98s.02.66.06.98l-2.1 1.65c-.2.15-.25.42-.13.64l2 3.46c.12.22.4.3.6.22l2.5-1c.52.4 1.08.73 1.7.98l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.6-.25 1.17-.6 1.7-.98l2.48 1c.23.1.5 0 .6-.22l2-3.46c.13-.22.08-.5-.1-.64l-2.12-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"
class="style-scope yt-icon"></path>
</g>
</svg>
</tp-yt-iron-icon>
</tp-yt-paper-icon-button>

View File

@ -1,12 +1,8 @@
const { globalShortcut } = require("electron");
const is = require("electron-is");
const electronLocalshortcut = require("electron-localshortcut");
const {
playPause,
nextTrack,
previousTrack,
startSearch
} = require("./youtube.js");
const getSongControls = require("../../providers/song-controls");
const registerMPRIS = require("./mpris");
function _registerGlobalShortcut(webContents, shortcut, action) {
globalShortcut.register(shortcut, () => {
@ -20,12 +16,47 @@ function _registerLocalShortcut(win, shortcut, action) {
});
}
function registerShortcuts(win) {
_registerGlobalShortcut(win.webContents, "MediaPlayPause", playPause);
_registerGlobalShortcut(win.webContents, "MediaNextTrack", nextTrack);
_registerGlobalShortcut(win.webContents, "MediaPreviousTrack", previousTrack);
_registerLocalShortcut(win, "CommandOrControl+F", startSearch);
_registerLocalShortcut(win, "CommandOrControl+L", startSearch);
function registerShortcuts(win, options) {
const songControls = getSongControls(win);
const { playPause, next, previous, search } = songControls;
if (options.overrideMediaKeys) {
_registerGlobalShortcut(win.webContents, "MediaPlayPause", playPause);
_registerGlobalShortcut(win.webContents, "MediaNextTrack", next);
_registerGlobalShortcut(win.webContents, "MediaPreviousTrack", previous);
}
_registerLocalShortcut(win, "CommandOrControl+F", search);
_registerLocalShortcut(win, "CommandOrControl+L", search);
if (is.linux()) registerMPRIS(win);
const { global, local } = options;
const shortcutOptions = { global, local };
for (const optionType in shortcutOptions) {
registerAllShortcuts(shortcutOptions[optionType], optionType);
}
function registerAllShortcuts(container, type) {
for (const action in container) {
if (!container[action]) {
continue; // Action accelerator is empty
}
console.debug(`Registering ${type} shortcut`, container[action], ":", action);
if (!songControls[action]) {
console.warn("Invalid action", action);
continue;
}
if (type === "global") {
_registerGlobalShortcut(win.webContents, container[action], songControls[action]);
} else { // type === "local"
_registerLocalShortcut(win, local[action], songControls[action]);
}
}
}
}
module.exports = registerShortcuts;

53
plugins/shortcuts/menu.js Normal file
View File

@ -0,0 +1,53 @@
const { setOptions } = require("../../config/plugins");
const prompt = require("custom-electron-prompt");
const promptOptions = require("../../providers/prompt-options");
module.exports = (win, options) => [
{
label: "Set Global Song Controls",
click: () => promptKeybind(options, win)
},
{
label: "Override MediaKeys",
type: "checkbox",
checked: options.overrideMediaKeys,
click: item => setOption(options, "overrideMediaKeys", item.checked)
}
];
function setOption(options, key = null, newValue = null) {
if (key && newValue !== null) {
options[key] = newValue;
}
setOptions("shortcuts", options);
}
// Helper function for keybind prompt
const kb = (label_, value_, default_) => { return { value: value_, label: label_, default: default_ }; };
async function promptKeybind(options, win) {
const output = await prompt({
title: "Global Keybinds",
label: "Choose Global Keybinds for Songs Control:",
type: "keybind",
keybindOptions: [ // If default=undefined then no default is used
kb("Previous", "previous", options.global?.previous),
kb("Play / Pause", "playPause", options.global?.playPause),
kb("Next", "next", options.global?.next)
],
height: 270,
...promptOptions()
}, win);
if (output) {
if (!options.global) {
options.global = {};
}
for (const { value, accelerator } of output) {
options.global[value] = accelerator;
}
setOption(options);
}
// else -> pressed cancel
}

View File

@ -0,0 +1,85 @@
const mpris = require("mpris-service");
const { ipcMain } = require("electron");
const registerCallback = require("../../providers/song-info");
const getSongControls = require("../../providers/song-controls");
function setupMPRIS() {
const player = mpris({
name: "youtube-music",
identity: "YouTube Music",
canRaise: true,
supportedUriSchemes: ["https"],
supportedMimeTypes: ["audio/mpeg"],
supportedInterfaces: ["player"],
desktopEntry: "youtube-music",
});
return player;
}
function registerMPRIS(win) {
const songControls = getSongControls(win);
const { playPause, next, previous } = songControls;
try {
const secToMicro = n => Math.round(Number(n) * 1e6);
const microToSec = n => Math.round(Number(n) / 1e6);
const seekTo = e => win.webContents.send("seekTo", microToSec(e.position));
const seekBy = o => win.webContents.send("seekBy", microToSec(o));
const player = setupMPRIS();
ipcMain.on('seeked', (_, t) => player.seeked(secToMicro(t)));
let currentSeconds = 0;
ipcMain.on('timeChanged', (_, t) => currentSeconds = t);
player.getPosition = () => secToMicro(currentSeconds)
player.on("raise", () => {
win.setSkipTaskbar(false);
win.show();
});
player.on("play", () => {
if (player.playbackStatus !== 'Playing') {
player.playbackStatus = 'Playing';
playPause()
}
});
player.on("pause", () => {
if (player.playbackStatus !== 'Paused') {
player.playbackStatus = 'Paused';
playPause()
}
});
player.on("playpause", playPause);
player.on("next", next);
player.on("previous", previous);
player.on('seek', seekBy);
player.on('position', seekTo);
registerCallback(songInfo => {
if (player) {
const data = {
'mpris:length': secToMicro(songInfo.songDuration),
'mpris:artUrl': songInfo.imageSrc,
'xesam:title': songInfo.title,
'xesam:artist': songInfo.artist,
'mpris:trackid': '/'
};
if (songInfo.album) data['xesam:album'] = songInfo.album;
player.metadata = data;
player.seeked(secToMicro(songInfo.elapsedSeconds))
player.playbackStatus = songInfo.isPaused ? "Paused" : "Playing"
}
})
} catch (e) {
console.warn("Error in MPRIS", e);
}
}
module.exports = registerMPRIS;

View File

@ -1,29 +0,0 @@
function _keyboardInput(webContents, key) {
return webContents.sendInputEvent({
type : "keydown",
keyCode: key
});
}
function playPause(webContents) {
return _keyboardInput(webContents, "Space");
}
function nextTrack(webContents) {
return _keyboardInput(webContents, "j");
}
function previousTrack(webContents) {
return _keyboardInput(webContents, "k");
}
function startSearch(webContents) {
return _keyboardInput(webContents, "/");
}
module.exports = {
playPause : playPause,
nextTrack : nextTrack,
previousTrack: previousTrack,
startSearch : startSearch
};

View File

@ -0,0 +1,37 @@
const hark = require("hark/hark.bundle.js");
module.exports = () => {
let isSilent = false;
document.addEventListener("apiLoaded", (apiEvent) => {
const video = document.querySelector("video");
const speechEvents = hark(video, {
threshold: -100, // dB (-100 = absolute silence, 0 = loudest)
interval: 2, // ms
});
const skipSilence = () => {
if (isSilent && !video.paused) {
video.currentTime += 0.2; // in s
}
};
speechEvents.on("speaking", function () {
isSilent = false;
});
speechEvents.on("stopped_speaking", function () {
if (!(video.paused || video.seeking || video.ended)) {
isSilent = true;
skipSilence();
}
});
video.addEventListener("play", function () {
skipSilence();
});
video.addEventListener("seeked", function () {
skipSilence();
});
});
};

View File

@ -0,0 +1,51 @@
const fetch = require("node-fetch");
const is = require("electron-is");
const { ipcMain } = require("electron");
const defaultConfig = require("../../config/defaults");
const { sortSegments } = require("./segments");
let videoID;
module.exports = (win, options) => {
const { apiURL, categories } = {
...defaultConfig.plugins.sponsorblock,
...options,
};
ipcMain.on("video-src-changed", async (_, data) => {
videoID = JSON.parse(data)?.videoDetails?.videoId;
const segments = await fetchSegments(apiURL, categories);
win.webContents.send("sponsorblock-skip", segments);
});
};
const fetchSegments = async (apiURL, categories) => {
const sponsorBlockURL = `${apiURL}/api/skipSegments?videoID=${videoID}&categories=${JSON.stringify(
categories
)}`;
try {
const resp = await fetch(sponsorBlockURL, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
});
if (resp.status !== 200) {
return [];
}
const segments = await resp.json();
const sortedSegments = sortSegments(
segments.map((submission) => submission.segment)
);
return sortedSegments;
} catch (e) {
if (is.dev()) {
console.log('error on sponsorblock request:', e);
}
return [];
}
};

View File

@ -0,0 +1,31 @@
const { ipcRenderer } = require("electron");
const is = require("electron-is");
let currentSegments = [];
module.exports = () => {
ipcRenderer.on("sponsorblock-skip", (_, segments) => {
currentSegments = segments;
});
document.addEventListener('apiLoaded', () => {
const video = document.querySelector('video');
video.addEventListener('timeupdate', e => {
currentSegments.forEach((segment) => {
if (
e.target.currentTime >= segment[0] &&
e.target.currentTime < segment[1]
) {
e.target.currentTime = segment[1];
if (is.dev()) {
console.log("SponsorBlock: skipping segment", segment);
}
}
});
})
// Reset segments on song end
video.addEventListener('emptied', () => currentSegments = []);
}, { once: true, passive: true })
};

View File

@ -0,0 +1,29 @@
// Segments are an array [ [start, end], … ]
module.exports.sortSegments = (segments) => {
segments.sort((segment1, segment2) =>
segment1[0] === segment2[0]
? segment1[1] - segment2[1]
: segment1[0] - segment2[0]
);
const compiledSegments = [];
let currentSegment;
segments.forEach((segment) => {
if (!currentSegment) {
currentSegment = segment;
return;
}
if (currentSegment[1] < segment[0]) {
compiledSegments.push(currentSegment);
currentSegment = segment;
return;
}
currentSegment[1] = Math.max(currentSegment[1], segment[1]);
});
compiledSegments.push(currentSegment);
return compiledSegments;
};

View File

@ -0,0 +1,34 @@
const { sortSegments } = require("../segments");
test("Segment sorting", () => {
expect(
sortSegments([
[0, 3],
[7, 8],
[5, 6],
])
).toEqual([
[0, 3],
[5, 6],
[7, 8],
]);
expect(
sortSegments([
[0, 5],
[6, 8],
[4, 6],
])
).toEqual([[0, 8]]);
expect(
sortSegments([
[0, 6],
[7, 8],
[4, 6],
])
).toEqual([
[0, 6],
[7, 8],
]);
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

View File

@ -0,0 +1,53 @@
const getSongControls = require('../../providers/song-controls');
const registerCallback = require('../../providers/song-info');
const path = require('path');
let controls;
let currentSongInfo;
module.exports = win => {
const { playPause, next, previous } = getSongControls(win);
controls = { playPause, next, previous };
registerCallback(songInfo => {
//update currentsonginfo for win.on('show')
currentSongInfo = songInfo;
// update thumbar
setThumbar(win, songInfo);
});
// need to set thumbar again after win.show
win.on("show", () => {
setThumbar(win, currentSongInfo)
})
};
function setThumbar(win, songInfo) {
// Wait for song to start before setting thumbar
if (!songInfo?.title) {
return;
}
// Win32 require full rewrite of components
win.setThumbarButtons([
{
tooltip: 'Previous',
icon: get('backward.png'),
click() { controls.previous(win.webContents); }
}, {
tooltip: 'Play/Pause',
// Update icon based on play state
icon: songInfo.isPaused ? get('play.png') : get('pause.png'),
click() { controls.playPause(win.webContents); }
}, {
tooltip: 'Next',
icon: get('forward.png'),
click() { controls.next(win.webContents); }
}
]);
}
// Util
function get(file) {
return path.join(__dirname, "assets", file);
}

86
plugins/touchbar/back.js Normal file
View File

@ -0,0 +1,86 @@
const { TouchBar } = require("electron");
const {
TouchBarButton,
TouchBarLabel,
TouchBarSpacer,
TouchBarSegmentedControl,
TouchBarScrubber,
} = TouchBar;
const registerCallback = require("../../providers/song-info");
const getSongControls = require("../../providers/song-controls");
// Songtitle label
const songTitle = new TouchBarLabel({
label: "",
});
// This will store the song controls once available
let controls = [];
// This will store the song image once available
const songImage = {};
// Pause/play button
const pausePlayButton = new TouchBarButton();
// The song control buttons (control functions are in the same order)
const buttons = new TouchBarSegmentedControl({
mode: "buttons",
segments: [
new TouchBarButton({
label: "⏮",
}),
pausePlayButton,
new TouchBarButton({
label: "⏭",
}),
new TouchBarButton({
label: "👎",
}),
new TouchBarButton({
label: "👍",
}),
],
change: (i) => controls[i](),
});
// This is the touchbar object, this combines everything with proper layout
const touchBar = new TouchBar({
items: [
new TouchBarScrubber({
items: [songImage, songTitle],
continuous: false,
}),
new TouchBarSpacer({
size: "flexible",
}),
buttons,
],
});
module.exports = (win) => {
const { playPause, next, previous, like, dislike } = getSongControls(win);
// If the page is ready, register the callback
win.once("ready-to-show", () => {
controls = [previous, playPause, next, like, dislike];
// Register the callback
registerCallback((songInfo) => {
// Song information changed, so lets update the touchBar
// Set the song title
songTitle.label = songInfo.title;
// Changes the pause button if paused
pausePlayButton.label = songInfo.isPaused ? "▶️" : "⏸";
// Get image source
songImage.icon = songInfo.image
? songInfo.image.resize({ height: 23 })
: null;
win.setTouchBar(touchBar);
});
});
};

52
plugins/tuna-obs/back.js Normal file
View File

@ -0,0 +1,52 @@
const { ipcMain } = require("electron");
const fetch = require('node-fetch');
const registerCallback = require("../../providers/song-info");
const secToMilisec = t => Math.round(Number(t) * 1e3);
const data = {
cover_url: '',
title: '',
artists: [],
status: '',
progress: 0,
duration: 0,
album_url: '',
album: undefined
};
const post = async (data) => {
const port = 1608;
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*'
}
const url = `http://localhost:${port}/`;
fetch(url, { method: 'POST', headers, body: JSON.stringify({ data }) }).catch(e => console.log(`Error: '${e.code || e.errno}' - when trying to access obs-tuna webserver at port ${port}`));
}
module.exports = async (win) => {
ipcMain.on('timeChanged', async (_, t) => {
if (!data.title) return;
data.progress = secToMilisec(t);
post(data);
});
registerCallback((songInfo) => {
if (!songInfo.title && !songInfo.artist) {
return;
}
data.duration = secToMilisec(songInfo.songDuration)
data.progress = secToMilisec(songInfo.elapsedSeconds)
data.cover_url = songInfo.imageSrc;
data.album_url = songInfo.imageSrc;
data.title = songInfo.title;
data.artists = [songInfo.artist];
data.status = songInfo.isPaused ? 'stopped' : 'playing';
data.album = songInfo.album;
post(data);
})
}

View File

@ -4,15 +4,15 @@ const path = require("path");
const { ipcMain, ipcRenderer } = require("electron");
// Creates a DOM element from a HTML string
module.exports.ElementFromHtml = html => {
var template = document.createElement("template");
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
module.exports.ElementFromHtml = (html) => {
var template = document.createElement("template");
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
};
// Creates a DOM element from a HTML file
module.exports.ElementFromFile = filepath => {
module.exports.ElementFromFile = (filepath) => {
return module.exports.ElementFromHtml(fs.readFileSync(filepath, "utf8"));
};
@ -20,8 +20,12 @@ module.exports.templatePath = (pluginPath, name) => {
return path.join(pluginPath, "templates", name);
};
module.exports.triggerAction = (channel, action) => {
return ipcRenderer.send(channel, action);
module.exports.triggerAction = (channel, action, ...args) => {
return ipcRenderer.send(channel, action, ...args);
};
module.exports.triggerActionSync = (channel, action, ...args) => {
return ipcRenderer.sendSync(channel, action, ...args);
};
module.exports.listenAction = (channel, callback) => {
@ -29,7 +33,7 @@ module.exports.listenAction = (channel, callback) => {
};
module.exports.fileExists = (path, callbackIfExists) => {
fs.access(path, fs.F_OK, err => {
fs.access(path, fs.F_OK, (err) => {
if (err) {
return;
}
@ -38,17 +42,20 @@ module.exports.fileExists = (path, callbackIfExists) => {
});
};
module.exports.injectCSS = (webContents, filepath) => {
webContents.on("did-finish-load", () => {
webContents.insertCSS(fs.readFileSync(filepath, "utf8"));
module.exports.injectCSS = (webContents, filepath, cb = undefined) => {
webContents.on("did-finish-load", async () => {
await webContents.insertCSS(fs.readFileSync(filepath, "utf8"));
if (cb) {
cb();
}
});
};
module.exports.getAllPlugins = () => {
const isDirectory = source => fs.lstatSync(source).isDirectory();
const isDirectory = (source) => fs.lstatSync(source).isDirectory();
return fs
.readdirSync(__dirname)
.map(name => path.join(__dirname, name))
.map((name) => path.join(__dirname, name))
.filter(isDirectory)
.map(name => path.basename(name));
.map((name) => path.basename(name));
};

View File

@ -0,0 +1,10 @@
const { injectCSS } = require("../utils");
const path = require("path");
module.exports = (win, options) => {
if (options.forceHide) {
injectCSS(win.webContents, path.join(__dirname, "force-hide.css"));
} else {
injectCSS(win.webContents, path.join(__dirname, "button-switcher.css"));
}
};

View File

@ -0,0 +1,77 @@
#main-panel.ytmusic-player-page {
align-items: unset !important;
}
.video-switch-button {
z-index: 999;
box-sizing: border-box;
padding: 0;
margin-top: 20px;
margin-left: 10px;
background: rgba(33, 33, 33, 0.4);
border-radius: 30px;
overflow: hidden;
width: 240px;
text-align: center;
font-size: 18px;
letter-spacing: 1px;
color: #fff;
padding-right: 120px;
position: absolute;
}
.video-switch-button:before {
content: "Video";
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 120px;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
pointer-events: none;
}
.video-switch-button-checkbox {
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 2;
}
.video-switch-button-label-span {
position: relative;
}
.video-switch-button-checkbox:checked+.video-switch-button-label:before {
transform: translateX(120px);
transition: transform 300ms linear;
}
.video-switch-button-checkbox+.video-switch-button-label {
position: relative;
padding: 15px 0;
display: block;
user-select: none;
pointer-events: none;
}
.video-switch-button-checkbox+.video-switch-button-label:before {
content: "";
background: rgba(60, 60, 60, 0.4);
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
border-radius: 30px;
transform: translateX(0);
transition: transform 300ms;
}

View File

@ -0,0 +1,11 @@
/* Hide the video player */
#main-panel {
display: none !important;
}
/* Make the side-panel full width */
.side-panel.ytmusic-player-page {
max-width: 100% !important;
width: 100% !important;
margin: 0 !important;
}

View File

@ -0,0 +1,116 @@
const { ElementFromFile, templatePath } = require("../utils");
const { setOptions } = require("../../config/plugins");
function $(selector) { return document.querySelector(selector); }
let options, player, video, api;
const switchButtonDiv = ElementFromFile(
templatePath(__dirname, "button_template.html")
);
module.exports = (_options) => {
if (_options.forceHide) return;
options = _options;
document.addEventListener('apiLoaded', setup, { once: true, passive: true });
}
function setup(e) {
api = e.detail;
player = $('ytmusic-player');
video = $('video');
$('ytmusic-player-page').prepend(switchButtonDiv);
$('#song-image.ytmusic-player').style.display = "block";
if (options.hideVideo) {
$('.video-switch-button-checkbox').checked = false;
changeDisplay(false);
forcePlaybackMode();
// fix black video
video.style.height = "auto";
}
// button checked = show video
switchButtonDiv.addEventListener('change', (e) => {
options.hideVideo = !e.target.checked;
changeDisplay(e.target.checked);
setOptions("video-toggle", options);
})
video.addEventListener('srcChanged', videoStarted);
observeThumbnail();
}
function changeDisplay(showVideo) {
player.style.margin = showVideo ? '' : 'auto 0px';
player.setAttribute('playback-mode', showVideo ? 'OMV_PREFERRED' : 'ATV_PREFERRED');
$('#song-video.ytmusic-player').style.display = showVideo ? 'unset' : 'none';
if (showVideo && !video.style.top) {
video.style.top = `${(player.clientHeight - video.clientHeight) / 2}px`;
}
moveVolumeHud(showVideo);
}
function videoStarted() {
if (api.getPlayerResponse().videoDetails.musicVideoType !== 'MUSIC_VIDEO_TYPE_ATV') {
// switch to high res thumbnail
forceThumbnail($('#song-image img'));
// show toggle button
switchButtonDiv.style.display = "initial";
// change display to video mode if video exist & video is hidden & option.hideVideo = false
if (!options.hideVideo && $('#song-video.ytmusic-player').style.display === "none") {
changeDisplay(true);
} else {
moveVolumeHud(!options.hideVideo);
}
} else {
// video doesn't exist -> switch to song mode
changeDisplay(false);
// hide toggle button
switchButtonDiv.style.display = "none";
}
}
// on load, after a delay, the page overrides the playback-mode to 'OMV_PREFERRED' which causes weird aspect ratio in the image container
// this function fix the problem by overriding that override :)
function forcePlaybackMode() {
const playbackModeObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.target.getAttribute('playback-mode') !== "ATV_PREFERRED") {
playbackModeObserver.disconnect();
mutation.target.setAttribute('playback-mode', "ATV_PREFERRED");
}
});
});
playbackModeObserver.observe(player, { attributeFilter: ["playback-mode"] });
}
// if precise volume plugin is enabled, move its hud to be on top of the video
function moveVolumeHud(showVideo) {
const volumeHud = $('#volumeHud');
if (volumeHud)
volumeHud.style.top = showVideo ? `${(player.clientHeight - video.clientHeight) / 2}px` : 0;
}
function observeThumbnail() {
const playbackModeObserver = new MutationObserver(mutations => {
if (!player.videoMode_) return;
mutations.forEach(mutation => {
if (!mutation.target.src.startsWith('data:')) return;
forceThumbnail(mutation.target)
});
});
playbackModeObserver.observe($('#song-image img'), { attributeFilter: ["src"] })
}
function forceThumbnail(img) {
const thumbnails = $('#movie_player').getPlayerResponse()?.videoDetails?.thumbnail?.thumbnails;
if (thumbnails && thumbnails.length > 0) {
img.src = thumbnails[thumbnails.length - 1].url.split("?")[0];
}
}

View File

@ -0,0 +1,13 @@
const { setOptions } = require("../../config/plugins");
module.exports = (win, options) => [
{
label: "Force Remove Video Tab",
type: "checkbox",
checked: options.forceHide,
click: item => {
options.forceHide = item.checked;
setOptions("video-toggle", options);
}
}
];

Some files were not shown because too many files have changed in this diff Show More