From 4747050b60b2a6c35253123c8bcd106ed478c677 Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Fri, 19 Mar 2021 21:32:33 +0100 Subject: [PATCH 001/118] Added working lastfm support currently only played songs are added --- config/defaults.js | 6 ++ package.json | 3 + plugins/discord/back.js | 5 +- plugins/last-fm/back.js | 135 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 plugins/last-fm/back.js diff --git a/config/defaults.js b/config/defaults.js index 6238e114..b81d1d2e 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -35,6 +35,12 @@ const defaultConfig = { ffmpegArgs: [], // e.g. ["-b:a", "192k"] for an audio bitrate of 192kb/s downloadFolder: undefined, // Custom download folder (absolute path) }, + "last-fm": { + enabled: false, + api_root: "http://ws.audioscrobbler.com/2.0/", + api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123 + secret: "a5d2a36fdf64819290f6982481eaffa2", + } }, }; diff --git a/package.json b/package.json index f5524a37..df4725e1 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", + "axios": "^0.21.1", "browser-id3-writer": "^4.4.0", "discord-rpc": "^3.2.0", "downloads-folder": "^3.0.1", @@ -76,7 +77,9 @@ "electron-unhandled": "^3.0.2", "electron-updater": "^4.3.6", "filenamify": "^4.2.0", + "md5": "^2.3.0", "node-fetch": "^2.6.1", + "open": "^8.0.3", "ytdl-core": "^4.4.5" }, "devDependencies": { diff --git a/plugins/discord/back.js b/plugins/discord/back.js index 5c53193b..1d7e8e21 100644 --- a/plugins/discord/back.js +++ b/plugins/discord/back.js @@ -45,9 +45,6 @@ module.exports = (win) => { }); // Startup the rpc client - rpc.login({ - clientId, - }) - .catch(console.error); + rpc.login({ clientId }).catch(console.error); }); }; diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js new file mode 100644 index 00000000..9a88d4fb --- /dev/null +++ b/plugins/last-fm/back.js @@ -0,0 +1,135 @@ +const fetch = require('node-fetch'); +const md5 = require('md5'); +const open = require("open"); +const axios = require('axios'); +const { setOptions } = require('../../config/plugins'); +const getSongInfo = require('../../providers/song-info'); + +const createFormData = (params) => { + // creates the body for in the post request + let formData = new URLSearchParams(); + for (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 (key in params) { + queryData.push(`${key}=${params[key]}`) + } + return '?'+queryData.join('&') +} + +const createApiSig = (params, secret) => { + // this function creates the api signature, see: https://www.last.fm/api/authspec + let keys = []; + for (key in params){ + keys.push(key); + } + keys.sort(); + let sig = ''; + for (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 an auth token + data = { + method: 'auth.gettoken', + api_key: api_key, + format: 'json' + } + let 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 user for authentication + config.token = await createToken(config); + setOptions('last-fm', config); + open(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`); + return config +} + +const getAndSetSessionKey = async (config) => { + // get and set the session key + data = { + api_key: config.api_key, + format: 'json', + method: 'auth.getsession', + token: config.token, + } + api_sig = createApiSig(data, config.secret); + 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 addScrobble = async (songInfo, config) => { + // this adds one scrobbled song + if (!config.session_key) + await getAndSetSessionKey(config); + data = { + track: songInfo.title, + artist: songInfo.artist, + api_key: config.api_key, + sk: config.session_key, + format: 'json', + method: 'track.scrobble', + timestamp: ~~((Date.now() - songInfo.elapsedSeconds)/1000), + duration: songInfo.songDuration, + } + data.api_sig = createApiSig(data, config.secret) + axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) + .then(res => res.data.scrobbles) + .catch(res => { + if (res.response.data.error == 9){ + // session key is invalid + config.session_key = undefined; + setOptions('last-fm', config); + authenticate(config); + } + }); +} + +// this will store the timeout that will trigger addScrobble +let scrobbleTimer = undefined; + +const lastfm = async (win, config) => { + const registerCallback = getSongInfo(win); + + if (!config.session_key) { + // not authenticated + config = await getAndSetSessionKey(config); + } + + registerCallback((songInfo)=> { + clearTimeout(scrobbleTimer); + if (!songInfo.isPaused) { + let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration/2), 4*60); + if (scrobbleTime > songInfo.elapsedSeconds) { + // scrobble still needs to happen + timeToWait = (scrobbleTime-songInfo.elapsedSeconds)*1000; + scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config); + } + } + }) +} + +module.exports = lastfm; \ No newline at end of file From 42e3d48cafa1e1d32199d5e0012909e11b5ff8bc Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Fri, 19 Mar 2021 22:00:00 +0100 Subject: [PATCH 002/118] Added now playing to last-fm --- plugins/last-fm/back.js | 60 +++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index 9a88d4fb..49eaaa51 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -15,12 +15,12 @@ const createFormData = (params) => { } const createQueryString = (params, api_sig) => { // creates a querystring - const queryData = [] - params.api_sig = api_sig + const queryData = []; + params.api_sig = api_sig; for (key in params) { - queryData.push(`${key}=${params[key]}`) + queryData.push(`${key}=${params[key]}`); } - return '?'+queryData.join('&') + return '?'+queryData.join('&'); } const createApiSig = (params, secret) => { @@ -34,11 +34,11 @@ const createApiSig = (params, secret) => { for (key of keys) { if (String(key) === 'format') continue - sig += `${key}${params[key]}` + sig += `${key}${params[key]}`; } - sig += secret - sig = md5(sig) - return sig + sig += secret; + sig = md5(sig); + return sig; } const createToken = async ({api_key, api_root, secret}) => { @@ -47,7 +47,7 @@ const createToken = async ({api_key, api_root, secret}) => { method: 'auth.gettoken', api_key: api_key, format: 'json' - } + }; let api_sig = createApiSig(data, secret); let response = await fetch(`${api_root}${createQueryString(data, api_sig)}`); response = await response.json(); @@ -59,7 +59,7 @@ const authenticate = async (config) => { config.token = await createToken(config); setOptions('last-fm', config); open(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`); - return config + return config; } const getAndSetSessionKey = async (config) => { @@ -69,7 +69,7 @@ const getAndSetSessionKey = async (config) => { format: 'json', method: 'auth.getsession', token: config.token, - } + }; api_sig = createApiSig(data, config.secret); res = await fetch(`${config.api_root}${createQueryString(data, api_sig)}`); res = await res.json(); @@ -77,7 +77,7 @@ const getAndSetSessionKey = async (config) => { await authenticate(config); config.session_key = res?.session?.key; setOptions('last-fm', config); - return config + return config; } @@ -94,10 +94,9 @@ const addScrobble = async (songInfo, config) => { method: 'track.scrobble', timestamp: ~~((Date.now() - songInfo.elapsedSeconds)/1000), duration: songInfo.songDuration, - } - data.api_sig = createApiSig(data, config.secret) + }; + data.api_sig = createApiSig(data, config.secret); axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) - .then(res => res.data.scrobbles) .catch(res => { if (res.response.data.error == 9){ // session key is invalid @@ -108,6 +107,32 @@ const addScrobble = async (songInfo, config) => { }); } +const setNowPlaying = async (songInfo, config) => { + // this adds one scrobbled song + if (!config.session_key) + await getAndSetSessionKey(config); + data = { + track: songInfo.title, + artist: songInfo.artist, + api_key: config.api_key, + sk: config.session_key, + format: 'json', + method: 'track.updateNowPlaying', + duration: songInfo.songDuration, + }; + data.api_sig = createApiSig(data, config.secret); + axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) + .catch(res => { + if (res.response.data.error == 9){ + // session key is invalid + config.session_key = undefined; + setOptions('last-fm', config); + authenticate(config); + } + }); +} + + // this will store the timeout that will trigger addScrobble let scrobbleTimer = undefined; @@ -119,9 +144,10 @@ const lastfm = async (win, config) => { config = await getAndSetSessionKey(config); } - registerCallback((songInfo)=> { + registerCallback( songInfo => { clearTimeout(scrobbleTimer); if (!songInfo.isPaused) { + setNowPlaying(songInfo, config); let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration/2), 4*60); if (scrobbleTime > songInfo.elapsedSeconds) { // scrobble still needs to happen @@ -129,7 +155,7 @@ const lastfm = async (win, config) => { scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config); } } - }) + }); } module.exports = lastfm; \ No newline at end of file From 2bb67db888ea1da9f8f05a73dddb7617d85e894b Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Sun, 21 Mar 2021 18:47:16 +0100 Subject: [PATCH 003/118] Fixed backwards compatibility --- plugins/last-fm/back.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index 49eaaa51..ece10a5a 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -5,6 +5,13 @@ const axios = require('axios'); const { setOptions } = require('../../config/plugins'); const getSongInfo = require('../../providers/song-info'); +const defaultSettings = { + enabled: true, + api_root: "http://ws.audioscrobbler.com/2.0/", + api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123 + secret: "a5d2a36fdf64819290f6982481eaffa2", +} + const createFormData = (params) => { // creates the body for in the post request let formData = new URLSearchParams(); @@ -138,7 +145,13 @@ let scrobbleTimer = undefined; const lastfm = async (win, config) => { const registerCallback = getSongInfo(win); - + + if (!config.api_root){ + // settings are not present, creating them with the default values + config = defaultSettings; + setOptions('last-fm', config); + } + if (!config.session_key) { // not authenticated config = await getAndSetSessionKey(config); From 1355b692b927deec4e1fdc641f7bad645ab01667 Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Sun, 21 Mar 2021 22:28:05 +0100 Subject: [PATCH 004/118] Remove the - Topic for more matches --- plugins/last-fm/back.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index ece10a5a..9eea51ec 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -94,7 +94,7 @@ const addScrobble = async (songInfo, config) => { await getAndSetSessionKey(config); data = { track: songInfo.title, - artist: songInfo.artist, + artist: songInfo.artist?.replace(' - Topic', ''), api_key: config.api_key, sk: config.session_key, format: 'json', @@ -120,7 +120,7 @@ const setNowPlaying = async (songInfo, config) => { await getAndSetSessionKey(config); data = { track: songInfo.title, - artist: songInfo.artist, + artist: songInfo.artist?.replace(' - Topic', ''), api_key: config.api_key, sk: config.session_key, format: 'json', From bffbcb229d54f64bf84f77f373bb7bc1f8447426 Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Thu, 25 Mar 2021 20:15:43 +0100 Subject: [PATCH 005/118] Made the suffixes configurable and added VEVO suffix to remove --- config/defaults.js | 1 + plugins/last-fm/back.js | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index b81d1d2e..2f345ab4 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -40,6 +40,7 @@ const defaultConfig = { api_root: "http://ws.audioscrobbler.com/2.0/", api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123 secret: "a5d2a36fdf64819290f6982481eaffa2", + suffixesToRemove: [' - Topic', 'VEVO'] // removes suffixes of the artist name, for better recognition } }, }; diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index 9eea51ec..c1c6a09d 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -10,6 +10,20 @@ const defaultSettings = { api_root: "http://ws.audioscrobbler.com/2.0/", api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123 secret: "a5d2a36fdf64819290f6982481eaffa2", + suffixesToRemove: [' - Topic', 'VEVO'] +} + +const cleanupArtistName = (config, artist) => { + let { suffixesToRemove } = config; + if (suffixesToRemove === undefined){ + suffixesToRemove = defaultSettings.suffixesToRemove; + config.suffixesToRemove = suffixesToRemove; + setOptions('last-fm', config); + } + for (suffix of suffixesToRemove){ + artist = artist.replace(suffix,''); + } + return artist } const createFormData = (params) => { @@ -94,7 +108,7 @@ const addScrobble = async (songInfo, config) => { await getAndSetSessionKey(config); data = { track: songInfo.title, - artist: songInfo.artist?.replace(' - Topic', ''), + artist: songInfo.artist, api_key: config.api_key, sk: config.session_key, format: 'json', @@ -120,7 +134,7 @@ const setNowPlaying = async (songInfo, config) => { await getAndSetSessionKey(config); data = { track: songInfo.title, - artist: songInfo.artist?.replace(' - Topic', ''), + artist: songInfo.artist, api_key: config.api_key, sk: config.session_key, format: 'json', @@ -159,6 +173,7 @@ const lastfm = async (win, config) => { registerCallback( songInfo => { clearTimeout(scrobbleTimer); + songInfo.artist = cleanupArtistName(config, songInfo.artist); if (!songInfo.isPaused) { setNowPlaying(songInfo, config); let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration/2), 4*60); From f253a69656aeafa88bcca224d5fcbdc78cace647 Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Thu, 25 Mar 2021 21:11:55 +0100 Subject: [PATCH 006/118] added comment for the added function --- plugins/last-fm/back.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index c1c6a09d..0d32387f 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -14,6 +14,7 @@ const defaultSettings = { } const cleanupArtistName = (config, artist) => { + // removes the suffixes of the artist name for more recognition by last.fm let { suffixesToRemove } = config; if (suffixesToRemove === undefined){ suffixesToRemove = defaultSettings.suffixesToRemove; From bd82bd224968238f46b4aca6a22da0f569fe7d92 Mon Sep 17 00:00:00 2001 From: Sem Visscher Date: Thu, 25 Mar 2021 21:27:33 +0100 Subject: [PATCH 007/118] added extra comments and corrected existing ones --- plugins/last-fm/back.js | 44 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index 0d32387f..4e238469 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -16,18 +16,18 @@ const defaultSettings = { const cleanupArtistName = (config, artist) => { // removes the suffixes of the artist name for more recognition by last.fm let { suffixesToRemove } = config; - if (suffixesToRemove === undefined){ + if (suffixesToRemove === undefined) { suffixesToRemove = defaultSettings.suffixesToRemove; config.suffixesToRemove = suffixesToRemove; setOptions('last-fm', config); } - for (suffix of suffixesToRemove){ - artist = artist.replace(suffix,''); + for (suffix of suffixesToRemove) { + artist = artist.replace(suffix, ''); } return artist } -const createFormData = (params) => { +const createFormData = params => { // creates the body for in the post request let formData = new URLSearchParams(); for (key in params) { @@ -48,7 +48,7 @@ const createQueryString = (params, api_sig) => { const createApiSig = (params, secret) => { // this function creates the api signature, see: https://www.last.fm/api/authspec let keys = []; - for (key in params){ + for (key in params) { keys.push(key); } keys.sort(); @@ -63,8 +63,8 @@ const createApiSig = (params, secret) => { return sig; } -const createToken = async ({api_key, api_root, secret}) => { - // creates an auth token +const createToken = async ({ api_key, api_root, secret }) => { + // creates and stores the auth token data = { method: 'auth.gettoken', api_key: api_key, @@ -76,16 +76,16 @@ const createToken = async ({api_key, api_root, secret}) => { return response?.token; } -const authenticate = async (config) => { - // asks user for authentication +const authenticate = async config => { + // asks the user for authentication config.token = await createToken(config); setOptions('last-fm', config); open(`https://www.last.fm/api/auth/?api_key=${config.api_key}&token=${config.token}`); return config; } -const getAndSetSessionKey = async (config) => { - // get and set the session key +const getAndSetSessionKey = async config => { + // get and store the session key data = { api_key: config.api_key, format: 'json', @@ -104,7 +104,7 @@ const getAndSetSessionKey = async (config) => { const addScrobble = async (songInfo, config) => { - // this adds one scrobbled song + // this adds one scrobbled song to last.fm if (!config.session_key) await getAndSetSessionKey(config); data = { @@ -114,14 +114,14 @@ const addScrobble = async (songInfo, config) => { sk: config.session_key, format: 'json', method: 'track.scrobble', - timestamp: ~~((Date.now() - songInfo.elapsedSeconds)/1000), + timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000), duration: songInfo.songDuration, }; data.api_sig = createApiSig(data, config.secret); axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) .catch(res => { - if (res.response.data.error == 9){ - // session key is invalid + 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); @@ -130,7 +130,7 @@ const addScrobble = async (songInfo, config) => { } const setNowPlaying = async (songInfo, config) => { - // this adds one scrobbled song + // this sets the now playing status in last.fm if (!config.session_key) await getAndSetSessionKey(config); data = { @@ -145,8 +145,8 @@ const setNowPlaying = async (songInfo, config) => { data.api_sig = createApiSig(data, config.secret); axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) .catch(res => { - if (res.response.data.error == 9){ - // session key is invalid + 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); @@ -161,7 +161,7 @@ let scrobbleTimer = undefined; const lastfm = async (win, config) => { const registerCallback = getSongInfo(win); - if (!config.api_root){ + if (!config.api_root) { // settings are not present, creating them with the default values config = defaultSettings; setOptions('last-fm', config); @@ -173,14 +173,16 @@ const lastfm = async (win, config) => { } registerCallback( songInfo => { + // set remove the old scrobble timer clearTimeout(scrobbleTimer); + // make the artist name a bit cleaner songInfo.artist = cleanupArtistName(config, songInfo.artist); if (!songInfo.isPaused) { setNowPlaying(songInfo, config); - let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration/2), 4*60); + let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60); if (scrobbleTime > songInfo.elapsedSeconds) { // scrobble still needs to happen - timeToWait = (scrobbleTime-songInfo.elapsedSeconds)*1000; + timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000; scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config); } } From 216205200c68c1168b2bfcd256f973ac258a65e3 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 15:30:33 +0300 Subject: [PATCH 008/118] fix in-app-menu navbar opacity + scrollbar color --- plugins/in-app-menu/style.css | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/plugins/in-app-menu/style.css b/plugins/in-app-menu/style.css index 25ae7c4a..19dd59fb 100644 --- a/plugins/in-app-menu/style.css +++ b/plugins/in-app-menu/style.css @@ -8,36 +8,36 @@ .menubar-menu-container { overflow-y: visible !important; } + /* fixes scrollbar positioning relative to nav bar */ #nav-bar-background.ytmusic-app-layout { right: 15px !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; + -webkit-app-region: unset !important; } -/* Move navBar downwards and make it opaque */ -ytmusic-app-layout { - --ytmusic-nav-bar-height: 120px; -} - -ytmusic-search-box.ytmusic-nav-bar { - margin-top: 29px; -} - -.center-content.ytmusic-nav-bar { - background: #030303; -} -yt-page-navigation-progress, -#progress.yt-page-navigation-progress, -ytmusic-item-section-renderer[has-item-section-tabbed-header-renderer_] - #header.ytmusic-item-section-renderer, +/* fix weird positioning in search screen*/ ytmusic-header-renderer.ytmusic-search-page { - top: 90px !important; + position: unset !important; } + +/* Move navBar downwards */ +ytmusic-app-layout > [slot="nav-bar"], +#nav-bar-background.ytmusic-app-layout { + 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; @@ -56,13 +56,13 @@ ytmusic-header-renderer.ytmusic-search-page { background-clip: padding-box; border: 2px solid rgba(0, 0, 0, 0); - background: rgb(49, 0, 0); + background: #3a3a3a; border-radius: 100px; -moz-border-radius: 100px; -webkit-border-radius: 100px; } ::-webkit-scrollbar-thumb:vertical:active { - background: rgb(56, 0, 0); /* Some darker color when you click it */ + background: #4d4c4c; /* Some darker color when you click it */ border-radius: 100px; -moz-border-radius: 100px; -webkit-border-radius: 100px; From 2b3a20c5ffd438eeb6b144ed1ca8c55316b83d36 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 15:47:32 +0300 Subject: [PATCH 009/118] Minimalize tray menu -doesnt include main menu template anymore --- menu.js | 134 ++++++++++++++++++++++++++------------------------------ tray.js | 9 +++- 2 files changed, 69 insertions(+), 74 deletions(-) diff --git a/menu.js b/menu.js index f974c4e4..e41fd9e0 100644 --- a/menu.js +++ b/menu.js @@ -23,18 +23,16 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ }, }); -const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ +const mainMenuTemplate = (win, withRoles = true) => [ { label: "Plugins", submenu: [ ...getAllPlugins().map((plugin) => { - const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js"); - + const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js") if (existsSync(pluginPath)) { if (!config.plugins.isEnabled(plugin)) { return pluginEnabledMenu(win, plugin, "", true); } - const getPluginMenu = require(pluginPath); return { label: plugin, @@ -46,7 +44,7 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ ], }; } - + return pluginEnabledMenu(win, plugin); }), { type: "separator" }, @@ -111,12 +109,12 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ config.set("options.hideMenu", item.checked); }, }, - ] + ] : []), ...(is.windows() || is.macOS() ? // Only works on Win/Mac - // https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows - [ + // https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows + [ { label: "Start at login", type: "checkbox", @@ -125,7 +123,7 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ config.set("options.startAtLogin", item.checked); }, }, - ] + ] : []), { label: "Tray", @@ -192,59 +190,55 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ }, ], }, - ...(!isTray - ? [ - { - label: "View", - submenu: withRoles - ? [ - { role: "reload" }, - { role: "forceReload" }, - { type: "separator" }, - { role: "zoomIn" }, - { role: "zoomOut" }, - { role: "resetZoom" }, - ] - : [ - { - label: "Reload", - click: () => { - win.webContents.reload(); - }, - }, - { - label: "Force Reload", - click: () => { - win.webContents.reloadIgnoringCache(); - }, - }, - { type: "separator" }, - { - label: "Zoom In", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() + 1 - ); - }, - }, - { - label: "Zoom Out", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() - 1 - ); - }, - }, - { - label: "Reset Zoom", - click: () => { - win.webContents.setZoomLevel(0); - }, - }, - ], - }, - ] - : []), + { + label: "View", + submenu: withRoles + ? [ + { role: "reload" }, + { role: "forceReload" }, + { type: "separator" }, + { role: "zoomIn" }, + { role: "zoomOut" }, + { role: "resetZoom" }, + ] + : [ + { + label: "Reload", + click: () => { + win.webContents.reload(); + }, + }, + { + label: "Force Reload", + click: () => { + win.webContents.reloadIgnoringCache(); + }, + }, + { type: "separator" }, + { + label: "Zoom In", + click: () => { + win.webContents.setZoomLevel( + win.webContents.getZoomLevel() + 1 + ); + }, + }, + { + label: "Zoom Out", + click: () => { + win.webContents.setZoomLevel( + win.webContents.getZoomLevel() - 1 + ); + }, + }, + { + label: "Reset Zoom", + click: () => { + win.webContents.setZoomLevel(0); + }, + }, + ], + }, { label: "Navigation", submenu: [ @@ -271,16 +265,12 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [ app.quit(); }, }, - ...(!isTray - ? [ - { - label: "Quit App", - click: () => { - app.quit(); - }, - }, - ] - : []), + { + label: "Quit App", + click: () => { + app.quit(); + }, + }, ], }, ]; diff --git a/tray.js b/tray.js index e871f4bf..7d0331f7 100644 --- a/tray.js +++ b/tray.js @@ -3,7 +3,6 @@ const path = require("path"); const { Menu, nativeImage, Tray } = require("electron"); const config = require("./config"); -const { mainMenuTemplate } = require("./menu"); const getSongControls = require("./providers/song-controls"); // Prevent tray being garbage collected @@ -57,7 +56,13 @@ module.exports.setUpTray = (app, win) => { win.show(); }, }, - ...mainMenuTemplate(win, true, true), + { + label: "Restart App", + click: () => { + app.relaunch(); + app.quit(); + }, + }, { label: "Quit", click: () => { From 80a7d2c255d3238adaf4e712de35194fd2633853 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 15:54:51 +0300 Subject: [PATCH 010/118] remove redundant roles --- menu.js | 115 +++++++++++++++++------------------- plugins/in-app-menu/back.js | 14 ++--- 2 files changed, 60 insertions(+), 69 deletions(-) diff --git a/menu.js b/menu.js index e41fd9e0..893ae015 100644 --- a/menu.js +++ b/menu.js @@ -23,7 +23,7 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ }, }); -const mainMenuTemplate = (win, withRoles = true) => [ +const mainMenuTemplate = (win) => [ { label: "Plugins", submenu: [ @@ -44,7 +44,7 @@ const mainMenuTemplate = (win, withRoles = true) => [ ], }; } - + return pluginEnabledMenu(win, plugin); }), { type: "separator" }, @@ -101,28 +101,28 @@ const mainMenuTemplate = (win, withRoles = true) => [ }, ...(is.windows() || is.linux() ? [ - { - label: "Hide menu", - type: "checkbox", - checked: config.get("options.hideMenu"), - click: (item) => { - config.set("options.hideMenu", item.checked); - }, + { + label: "Hide menu", + type: "checkbox", + checked: config.get("options.hideMenu"), + click: (item) => { + config.set("options.hideMenu", item.checked); }, + }, ] : []), ...(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: "Start at login", + type: "checkbox", + checked: config.get("options.startAtLogin"), + click: (item) => { + config.set("options.startAtLogin", item.checked); }, + }, ] : []), { @@ -192,52 +192,43 @@ const mainMenuTemplate = (win, withRoles = true) => [ }, { label: "View", - submenu: withRoles - ? [ - { role: "reload" }, - { role: "forceReload" }, - { type: "separator" }, - { role: "zoomIn" }, - { role: "zoomOut" }, - { role: "resetZoom" }, - ] - : [ - { - label: "Reload", - click: () => { - win.webContents.reload(); - }, - }, - { - label: "Force Reload", - click: () => { - win.webContents.reloadIgnoringCache(); - }, - }, - { type: "separator" }, - { - label: "Zoom In", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() + 1 - ); - }, - }, - { - label: "Zoom Out", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() - 1 - ); - }, - }, - { - label: "Reset Zoom", - click: () => { - win.webContents.setZoomLevel(0); - }, - }, - ], + submenu: [ + { + label: "Reload", + click: () => { + win.webContents.reload(); + }, + }, + { + label: "Force Reload", + click: () => { + win.webContents.reloadIgnoringCache(); + }, + }, + { type: "separator" }, + { + label: "Zoom In", + click: () => { + win.webContents.setZoomLevel( + win.webContents.getZoomLevel() + 1 + ); + }, + }, + { + label: "Zoom Out", + click: () => { + win.webContents.setZoomLevel( + win.webContents.getZoomLevel() - 1 + ); + }, + }, + { + label: "Reset Zoom", + click: () => { + win.webContents.setZoomLevel(0); + }, + }, + ], }, { label: "Navigation", diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 3c77c377..f5925815 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -16,7 +16,7 @@ const originalBuildMenu = Menu.buildFromTemplate; // This function natively gets called on all submenu so no more reason to use recursion Menu.buildFromTemplate = (template) => { // Fix checkboxes and radio buttons - updateCheckboxesAndRadioButtons(win, template); + updateCheckboxesAndRadioButtons(template); // return as normal return originalBuildMenu(template); @@ -39,21 +39,21 @@ module.exports = (winImport) => { //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { - switchMenuVisibility(win); + switchMenuVisibility(); electronLocalshortcut.register(win, "Esc", () => { - switchMenuVisibility(win); + switchMenuVisibility(); }); } }); }; let visible = true; -function switchMenuVisibility(win) { +function switchMenuVisibility() { visible = !visible; win.webContents.send("updateMenu", visible); } -function checkCheckbox(win, item) { +function checkCheckbox(item) { //check item item.checked = !item.checked; //update menu (closes it) @@ -61,14 +61,14 @@ function checkCheckbox(win, item) { } // Update checkboxes/radio buttons -function updateCheckboxesAndRadioButtons(win, template) { +function updateCheckboxesAndRadioButtons(template) { for (let item of template) { // Change onClick of checkbox+radio if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { let originalOnclick = item.click; item.click = (itemClicked) => { originalOnclick(itemClicked); - checkCheckbox(win, itemClicked); + checkCheckbox(itemClicked); }; item.fixed = true; } From 0c6630d2d922bcfe0b1e3bd6d77e930d7990f38d Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 3 Apr 2021 17:12:28 +0200 Subject: [PATCH 011/118] additional cleanup/refactoring --- package.json | 1 - plugins/last-fm/back.js | 101 +++++++++++++++++----------------------- yarn.lock | 49 ++++++++++++++++++- 3 files changed, 89 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 79a9cbf7..aa3f1b95 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,6 @@ "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", - "axios": "^0.21.1", "async-mutex": "^0.3.1", "browser-id3-writer": "^4.4.0", "discord-rpc": "^3.2.0", diff --git a/plugins/last-fm/back.js b/plugins/last-fm/back.js index 4e238469..a34a0a19 100644 --- a/plugins/last-fm/back.js +++ b/plugins/last-fm/back.js @@ -1,35 +1,24 @@ const fetch = require('node-fetch'); const md5 = require('md5'); const open = require("open"); -const axios = require('axios'); const { setOptions } = require('../../config/plugins'); const getSongInfo = require('../../providers/song-info'); - -const defaultSettings = { - enabled: true, - api_root: "http://ws.audioscrobbler.com/2.0/", - api_key: "04d76faaac8726e60988e14c105d421a", // api key registered by @semvis123 - secret: "a5d2a36fdf64819290f6982481eaffa2", - suffixesToRemove: [' - Topic', 'VEVO'] -} +const defaultConfig = require('../../config/defaults'); const cleanupArtistName = (config, artist) => { // removes the suffixes of the artist name for more recognition by last.fm - let { suffixesToRemove } = config; - if (suffixesToRemove === undefined) { - suffixesToRemove = defaultSettings.suffixesToRemove; - config.suffixesToRemove = suffixesToRemove; - setOptions('last-fm', config); - } + const { suffixesToRemove } = config; + if (suffixesToRemove === undefined) return artist; + for (suffix of suffixesToRemove) { artist = artist.replace(suffix, ''); } - return artist + return artist; } const createFormData = params => { // creates the body for in the post request - let formData = new URLSearchParams(); + const formData = new URLSearchParams(); for (key in params) { formData.append(key, params[key]); } @@ -40,14 +29,14 @@ const createQueryString = (params, api_sig) => { const queryData = []; params.api_sig = api_sig; for (key in params) { - queryData.push(`${key}=${params[key]}`); + 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 - let keys = []; + const keys = []; for (key in params) { keys.push(key); } @@ -65,12 +54,12 @@ const createApiSig = (params, secret) => { const createToken = async ({ api_key, api_root, secret }) => { // creates and stores the auth token - data = { + const data = { method: 'auth.gettoken', api_key: api_key, format: 'json' }; - let api_sig = createApiSig(data, secret); + const api_sig = createApiSig(data, secret); let response = await fetch(`${api_root}${createQueryString(data, api_sig)}`); response = await response.json(); return response?.token; @@ -86,14 +75,14 @@ const authenticate = async config => { const getAndSetSessionKey = async config => { // get and store the session key - data = { + const data = { api_key: config.api_key, format: 'json', method: 'auth.getsession', token: config.token, }; - api_sig = createApiSig(data, config.secret); - res = await fetch(`${config.api_root}${createQueryString(data, api_sig)}`); + 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); @@ -102,23 +91,23 @@ const getAndSetSessionKey = async config => { return config; } - -const addScrobble = async (songInfo, config) => { - // this adds one scrobbled song to last.fm +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); - data = { + + const postData = { track: songInfo.title, + duration: songInfo.songDuration, artist: songInfo.artist, api_key: config.api_key, sk: config.session_key, format: 'json', - method: 'track.scrobble', - timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000), - duration: songInfo.songDuration, + ...data, }; - data.api_sig = createApiSig(data, config.secret); - axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(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 @@ -129,29 +118,21 @@ const addScrobble = async (songInfo, config) => { }); } -const setNowPlaying = async (songInfo, config) => { - // this sets the now playing status in last.fm - if (!config.session_key) - await getAndSetSessionKey(config); - data = { - track: songInfo.title, - artist: songInfo.artist, - api_key: config.api_key, - sk: config.session_key, - format: 'json', - method: 'track.updateNowPlaying', - duration: songInfo.songDuration, +const addScrobble = (songInfo, config) => { + // this adds one scrobbled song to last.fm + const data = { + method: 'track.scrobble', + timestamp: ~~((Date.now() - songInfo.elapsedSeconds) / 1000), }; - data.api_sig = createApiSig(data, config.secret); - axios.post('https://ws.audioscrobbler.com/2.0/', createFormData(data)) - .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); - } - }); + 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); } @@ -161,9 +142,10 @@ let scrobbleTimer = undefined; const lastfm = async (win, config) => { const registerCallback = getSongInfo(win); - if (!config.api_root) { + if (!config.api_root || !config.suffixesToRemove) { // settings are not present, creating them with the default values - config = defaultSettings; + config = defaultConfig.plugins['last-fm']; + config.enabled = true; setOptions('last-fm', config); } @@ -179,10 +161,11 @@ const lastfm = async (win, config) => { songInfo.artist = cleanupArtistName(config, songInfo.artist); if (!songInfo.isPaused) { setNowPlaying(songInfo, config); - let scrobbleTime = Math.min(Math.ceil(songInfo.songDuration / 2), 4 * 60); + // 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 - timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000; + const timeToWait = (scrobbleTime - songInfo.elapsedSeconds) * 1000; scrobbleTimer = setTimeout(addScrobble, timeToWait, songInfo, config); } } diff --git a/yarn.lock b/yarn.lock index f1a14d40..f428bd55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1708,6 +1708,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + dependencies: + follow-redirects "^1.10.0" + babel-eslint@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -2223,6 +2230,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -2587,6 +2599,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2756,6 +2773,11 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -3961,6 +3983,11 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +follow-redirects@^1.10.0: + version "1.13.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" + integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4686,7 +4713,7 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-buffer@^1.1.5: +is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -4747,7 +4774,7 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-docker@^2.0.0: +is-docker@^2.0.0, is-docker@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== @@ -6023,6 +6050,15 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + memory-fs@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" @@ -6519,6 +6555,15 @@ open@^7.3.0: is-docker "^2.0.0" is-wsl "^2.1.1" +open@^8.0.3: + version "8.0.5" + resolved "https://registry.yarnpkg.com/open/-/open-8.0.5.tgz#92ee3faafef4ddbe78006f7881572f3e81430b8f" + integrity sha512-hkPXCz7gijWp2GoWqsQ4O/5p7F6d5pIQ/+9NyeWG1nABJ4zvLi9kJRv1a44kVf5p13wK0WMoiRA+Xey68yOytA== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" From 5524a14c871ccf47a2f4237468eb5cdc0c678b21 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 19:20:56 +0300 Subject: [PATCH 012/118] move advanced options to dedicated submenu + add "Use Proxy" checkbox --- menu.js | 102 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/menu.js b/menu.js index 893ae015..c0843247 100644 --- a/menu.js +++ b/menu.js @@ -47,13 +47,6 @@ const mainMenuTemplate = (win) => [ return pluginEnabledMenu(win, plugin); }), - { type: "separator" }, - { - label: "Advanced options", - click: () => { - config.edit(); - }, - }, ], }, { @@ -67,30 +60,6 @@ const mainMenuTemplate = (win) => [ config.set("options.autoUpdates", item.checked); }, }, - { - 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); - }, - }, { label: "Resume last song when app starts", type: "checkbox", @@ -169,24 +138,63 @@ const mainMenuTemplate = (win) => [ ], }, { type: "separator" }, - { - label: "Toggle DevTools", - // Cannot use "toggleDevTools" role in MacOS - click: () => { - const { webContents } = win; - if (webContents.isDevToolsOpened()) { - webContents.closeDevTools(); - } else { - const devToolsOptions = {}; - webContents.openDevTools(devToolsOptions); - } - }, - }, { label: "Advanced options", - click: () => { - config.edit(); - }, + submenu: [ + { + label: "Use Proxy", + type: "checkbox", + checked: !!config.get("options.proxy"), + click: (item) => { + const value = item.checked? "socks5://127.0.0.1:9999" : ""; + config.set("options.proxy", value); + } + }, + { + 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" }, + { + label: "Toggle DevTools", + // Cannot use "toggleDevTools" role in MacOS + click: () => { + const { webContents } = win; + if (webContents.isDevToolsOpened()) { + webContents.closeDevTools(); + } else { + const devToolsOptions = {}; + webContents.openDevTools(devToolsOptions); + } + }, + }, + { + label: "Edit config.json", + click: () => { + config.edit(); + }, + }, + ] }, ], }, From ec3adff70676f2b9f5fe94f7bd0ed670f6373bb4 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 20:15:48 +0300 Subject: [PATCH 013/118] fix bug when loading window with no connection --- plugins/in-app-menu/back.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index f5925815..c8660ecb 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -36,6 +36,8 @@ module.exports = (winImport) => { done = true; setApplicationMenu(win); + //fix bug when loading window with no internet connection + switchMenuVisibility(); //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { @@ -47,7 +49,7 @@ module.exports = (winImport) => { }); }; -let visible = true; +let visible = false; function switchMenuVisibility() { visible = !visible; win.webContents.send("updateMenu", visible); From 061e4a9e5f0e8d6743f933df14aefa6685bbb8ed Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 21:51:35 +0300 Subject: [PATCH 014/118] add 'electron-prompt' and use it for setting proxy --- menu.js | 36 +++++++++++++++++++++++++++++++++--- package.json | 1 + yarn.lock | 19 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/menu.js b/menu.js index c0843247..3c6efa86 100644 --- a/menu.js +++ b/menu.js @@ -6,11 +6,13 @@ const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); +const prompt = require('electron-prompt'); const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, type: "checkbox", checked: config.plugins.isEnabled(plugin), + hasSubmenu: hasSubmenu || undefined, click: (item) => { if (item.checked) { config.plugins.enable(plugin); @@ -142,12 +144,12 @@ const mainMenuTemplate = (win) => [ label: "Advanced options", submenu: [ { - label: "Use Proxy", + label: "Proxy", type: "checkbox", checked: !!config.get("options.proxy"), + //fixed: true, //skip in-app-menu click() override click: (item) => { - const value = item.checked? "socks5://127.0.0.1:9999" : ""; - config.set("options.proxy", value); + setProxy(item, win); } }, { @@ -307,3 +309,31 @@ module.exports.setApplicationMenu = (win) => { const menu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(menu); }; + +// +const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); +function setProxy(item, win) { + prompt({ + title: 'Set Proxy', + label: 'Enter Proxy Adress:', + value: config.get("options.proxy") || `Example - "socks5://127.0.0.1:9999"`, + inputAttrs: { + type: 'text' + }, + type: 'input', + alwaysOnTop: true, + icon: iconPath + }) + .then((input) => { + if(input !== null) { + console.log(`setting proxy to ${input}`); + config.set("options.proxy", input); + if(input === "") + item.checked = false; + item.checked = (input === "") ? false : true; + } else { //user pressed cancel + item.checked = !item.checked; //reset checkbox + } + }) + .catch(console.error); +} \ No newline at end of file diff --git a/package.json b/package.json index ce144c38..736374c5 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "electron-debug": "^3.2.0", "electron-is": "^3.0.0", "electron-localshortcut": "^3.2.1", + "electron-prompt": "^1.6.2", "electron-store": "^7.0.2", "electron-unhandled": "^3.0.2", "electron-updater": "^4.3.6", diff --git a/yarn.lock b/yarn.lock index c969527e..b029d432 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2908,6 +2908,13 @@ dmg-builder@22.9.1: js-yaml "^3.14.0" sanitize-filename "^1.6.3" +doc-ready@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/doc-ready/-/doc-ready-1.0.4.tgz#37f5391969cff994303fdfef2e5d50357f8164d3" + integrity sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM= + dependencies: + eventie "^1" + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -3086,6 +3093,13 @@ electron-localshortcut@^3.1.0, electron-localshortcut@^3.2.1: keyboardevent-from-electron-accelerator "^2.0.0" keyboardevents-areequal "^0.2.1" +electron-prompt@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/electron-prompt/-/electron-prompt-1.6.2.tgz#e26bd3d359120bd45ce2f9625bdc380deb7ee269" + integrity sha512-gC9ZpMopIgz1kW92J7UfsXarkLdPH2zhr77bnJFlDSduYjRlr9nEPm4ux1vyzJsO72AdOyvuPPIQB0j+gWsncQ== + dependencies: + doc-ready "^1.0.4" + electron-publish@22.9.1: version "22.9.1" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.9.1.tgz#7cc76ac4cc53efd29ee31c1e5facb9724329068e" @@ -3605,6 +3619,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +eventie@^1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/eventie/-/eventie-1.0.6.tgz#d4ffc8b0c2b5e493c2aa1b22cbe918d3aee74437" + integrity sha1-1P/IsMK15JPCqhsiy+kY067nRDc= + events@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" From 317521bba618dadb20304596766a360a9b897462 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 21:53:39 +0300 Subject: [PATCH 015/118] fix memory leak + in-app-menu updates menu only if needed --- index.js | 6 ++++++ plugins/in-app-menu/back.js | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 82bb3320..478d2f86 100644 --- a/index.js +++ b/index.js @@ -152,7 +152,13 @@ function createMainWindow() { return win; } +let createdWindow = false; app.on("browser-window-created", (event, win) => { + //Ensure listeners aren't registered when creating input dialog + if(createdWindow){ + return; + } + createdWindow = true; loadPlugins(win); win.webContents.on("did-fail-load", () => { diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index c8660ecb..fba6eb6d 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -16,7 +16,7 @@ const originalBuildMenu = Menu.buildFromTemplate; // This function natively gets called on all submenu so no more reason to use recursion Menu.buildFromTemplate = (template) => { // Fix checkboxes and radio buttons - updateCheckboxesAndRadioButtons(template); + updateTemplate(template); // return as normal return originalBuildMenu(template); @@ -55,22 +55,26 @@ function switchMenuVisibility() { win.webContents.send("updateMenu", visible); } -function checkCheckbox(item) { - //check item +function updateCheckboxesAndRadioButtons(item, isRadio, hasSubmenu) { + if (!isRadio) { + //fix checkbox item.checked = !item.checked; - //update menu (closes it) + } + //update menu if radio / hasSubmenu + if (isRadio || hasSubmenu) { win.webContents.send("updateMenu", true); + } } // Update checkboxes/radio buttons -function updateCheckboxesAndRadioButtons(template) { +function updateTemplate(template) { for (let item of template) { // Change onClick of checkbox+radio if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { let originalOnclick = item.click; item.click = (itemClicked) => { originalOnclick(itemClicked); - checkCheckbox(itemClicked); + updateCheckboxesAndRadioButtons(itemClicked, item.type==='radio', item.hasSubmenu); }; item.fixed = true; } From 70b03b71e4bfa45df6cb70130bf896dd0ec8d755 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 22:04:40 +0300 Subject: [PATCH 016/118] refactor and stylecheck --- menu.js | 3 --- plugins/in-app-menu/back.js | 13 ++++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/menu.js b/menu.js index 3c6efa86..b51fb516 100644 --- a/menu.js +++ b/menu.js @@ -147,7 +147,6 @@ const mainMenuTemplate = (win) => [ label: "Proxy", type: "checkbox", checked: !!config.get("options.proxy"), - //fixed: true, //skip in-app-menu click() override click: (item) => { setProxy(item, win); } @@ -310,7 +309,6 @@ module.exports.setApplicationMenu = (win) => { Menu.setApplicationMenu(menu); }; -// const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); function setProxy(item, win) { prompt({ @@ -326,7 +324,6 @@ function setProxy(item, win) { }) .then((input) => { if(input !== null) { - console.log(`setting proxy to ${input}`); config.set("options.proxy", input); if(input === "") item.checked = false; diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index fba6eb6d..8a6efdf7 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -9,6 +9,8 @@ const { injectCSS } = require("../utils"); //check that menu doesn't get created twice let done = false; +//tracks menu visibility +let visible = true; // win hook for fixing menu let win; @@ -41,17 +43,22 @@ module.exports = (winImport) => { //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { - switchMenuVisibility(); + visible = false; electronLocalshortcut.register(win, "Esc", () => { switchMenuVisibility(); }); } + // fix bug with menu not applying on start + setMenuVisibility(visible); }); }; -let visible = false; function switchMenuVisibility() { - visible = !visible; + setMenuVisibility(!visible); +} + +function setMenuVisibility(value){ + visible = value; win.webContents.send("updateMenu", visible); } From 1cae35a62b5c4aa687eb66cd9449cb3351947498 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 22:34:12 +0300 Subject: [PATCH 017/118] fix in-app-menu hideMenu on launch --- plugins/in-app-menu/back.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 8a6efdf7..53bb9f8d 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -38,17 +38,15 @@ module.exports = (winImport) => { done = true; setApplicationMenu(win); - //fix bug when loading window with no internet connection - switchMenuVisibility(); //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { - visible = false; + switchMenuVisibility(); electronLocalshortcut.register(win, "Esc", () => { switchMenuVisibility(); }); - } - // fix bug with menu not applying on start + } + // fix bug with menu not applying on start when no internet connection available setMenuVisibility(visible); }); }; From 8b6c60bb178e3bc22c8c917f650153a960ea9ae6 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 22:59:20 +0300 Subject: [PATCH 018/118] fix Connection Error when using in-app-menu --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 478d2f86..bc3db73a 100644 --- a/index.js +++ b/index.js @@ -93,6 +93,7 @@ function createMainWindow() { contextIsolation: false, preload: path.join(__dirname, "preload.js"), nodeIntegrationInSubFrames: true, + nodeIntegration: true, nativeWindowOpen: true, // window.open return Window object(like in regular browsers), not BrowserWindowProxy enableRemoteModule: true, affinity: "main-window", // main window, and addition windows should work in one process From 2e6fffc903953b2f4cd6c5321f36f22677572d37 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sat, 3 Apr 2021 23:46:16 +0300 Subject: [PATCH 019/118] Revert "fix Connection Error when using in-app-menu" This reverts commit 8b6c60bb178e3bc22c8c917f650153a960ea9ae6. --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index bc3db73a..478d2f86 100644 --- a/index.js +++ b/index.js @@ -93,7 +93,6 @@ function createMainWindow() { contextIsolation: false, preload: path.join(__dirname, "preload.js"), nodeIntegrationInSubFrames: true, - nodeIntegration: true, nativeWindowOpen: true, // window.open return Window object(like in regular browsers), not BrowserWindowProxy enableRemoteModule: true, affinity: "main-window", // main window, and addition windows should work in one process From 8291cdfc12d37b4902cc1bd2b32af975ba6d49f3 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 02:37:19 +0300 Subject: [PATCH 020/118] disable dev tools on electron-prompt --- index.js | 4 +++- menu.js | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 478d2f86..baa8c49c 100644 --- a/index.js +++ b/index.js @@ -37,7 +37,9 @@ if (config.get("options.proxy")) { } // Adds debug features like hotkeys for triggering dev tools and reload -require("electron-debug")(); +require("electron-debug")({ + showDevTools: false //disable dev tools on electron-prompt +}); // Prevent window being garbage collected let mainWindow; diff --git a/menu.js b/menu.js index b51fb516..9deef729 100644 --- a/menu.js +++ b/menu.js @@ -148,7 +148,7 @@ const mainMenuTemplate = (win) => [ type: "checkbox", checked: !!config.get("options.proxy"), click: (item) => { - setProxy(item, win); + setProxy(item); } }, { @@ -310,7 +310,7 @@ module.exports.setApplicationMenu = (win) => { }; const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); -function setProxy(item, win) { +function setProxy(item) { prompt({ title: 'Set Proxy', label: 'Enter Proxy Adress:', @@ -325,8 +325,6 @@ function setProxy(item, win) { .then((input) => { if(input !== null) { config.set("options.proxy", input); - if(input === "") - item.checked = false; item.checked = (input === "") ? false : true; } else { //user pressed cancel item.checked = !item.checked; //reset checkbox From 421fe6793022386ef21707e78f56739f5689ecf1 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 02:46:12 +0300 Subject: [PATCH 021/118] ignore proxy if equal to example --- menu.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/menu.js b/menu.js index 9deef729..9dd0b8e2 100644 --- a/menu.js +++ b/menu.js @@ -310,11 +310,12 @@ module.exports.setApplicationMenu = (win) => { }; const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); +const example = `Example: "socks5://127.0.0.1:9999"`; function setProxy(item) { prompt({ title: 'Set Proxy', - label: 'Enter Proxy Adress:', - value: config.get("options.proxy") || `Example - "socks5://127.0.0.1:9999"`, + label: 'Enter Proxy Adress (or leave empty to disable)', + value: config.get("options.proxy") || example, inputAttrs: { type: 'text' }, @@ -323,7 +324,7 @@ function setProxy(item) { icon: iconPath }) .then((input) => { - if(input !== null) { + if(input !== null && input !== example) { config.set("options.proxy", input); item.checked = (input === "") ? false : true; } else { //user pressed cancel From d12d16348aff03d6659a0211976d597c50396331 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 15:06:14 +0300 Subject: [PATCH 022/118] custom dark skin for prompt --- darkPrompt.css | 37 +++++++++++++++++++++++++++++++++++++ menu.js | 5 +++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 darkPrompt.css diff --git a/darkPrompt.css b/darkPrompt.css new file mode 100644 index 00000000..100a6ed5 --- /dev/null +++ b/darkPrompt.css @@ -0,0 +1,37 @@ +body { + background-color: rgba(0, 0, 0, 0.3); + background-image: linear-gradient(315deg, #200000 0%, #13253a 74%); + overflow: hidden; + color:whitesmoke; +} +#container { + background: rgba( 0, 0, 0, 0.7 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 10.0px ); + -webkit-backdrop-filter: blur( 10.0px ); + border-radius: 10px; + border: 1px solid rgba(80, 0, 0, 0.4); + + overflow: hidden; +} + +#data { + background: unset; + color: whitesmoke; + border: 1px solid rgb(54, 54, 54); +} + +#data:focus { + outline: unset; + border: 1px solid rgb(85, 85, 85); +} + + #ok:focus, #cancel:focus { + outline: rgba(30, 0, 0, 0.3) solid 1px; + border: 1px solid rgba(60, 0, 0, 0.4); +} + +#ok, #cancel { + background-color: rgb(0, 0, 0); + color: whitesmoke; +} \ No newline at end of file diff --git a/menu.js b/menu.js index 9dd0b8e2..bbe7204f 100644 --- a/menu.js +++ b/menu.js @@ -314,14 +314,15 @@ const example = `Example: "socks5://127.0.0.1:9999"`; function setProxy(item) { prompt({ title: 'Set Proxy', - label: 'Enter Proxy Adress (or leave empty to disable)', + label: 'Enter Proxy Address (leave empty to disable)', value: config.get("options.proxy") || example, inputAttrs: { type: 'text' }, type: 'input', alwaysOnTop: true, - icon: iconPath + icon: iconPath, + customStylesheet: path.join(__dirname, "darkPrompt.css"), }) .then((input) => { if(input !== null && input !== example) { From 7c8e946871fba05e5cbedcf9fa5e9b7a33117ccf Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 19:58:25 +0300 Subject: [PATCH 023/118] implement custom prompt --- menu.js | 18 ++- package.json | 2 +- prompt/customTitlebar.js | 12 ++ darkPrompt.css => prompt/darkPrompt.css | 11 +- prompt/index.js | 127 ++++++++++++++++++ prompt/page/prompt.css | 72 ++++++++++ prompt/page/prompt.html | 18 +++ prompt/page/prompt.js | 170 ++++++++++++++++++++++++ yarn.lock | 7 - 9 files changed, 424 insertions(+), 13 deletions(-) create mode 100644 prompt/customTitlebar.js rename darkPrompt.css => prompt/darkPrompt.css (88%) create mode 100644 prompt/index.js create mode 100644 prompt/page/prompt.css create mode 100644 prompt/page/prompt.html create mode 100644 prompt/page/prompt.js diff --git a/menu.js b/menu.js index bbe7204f..0312778f 100644 --- a/menu.js +++ b/menu.js @@ -6,7 +6,7 @@ const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); -const prompt = require('electron-prompt'); +const prompt = require('./prompt'); const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, @@ -312,7 +312,7 @@ module.exports.setApplicationMenu = (win) => { const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); const example = `Example: "socks5://127.0.0.1:9999"`; function setProxy(item) { - prompt({ + let options = { title: 'Set Proxy', label: 'Enter Proxy Address (leave empty to disable)', value: config.get("options.proxy") || example, @@ -322,8 +322,18 @@ function setProxy(item) { type: 'input', alwaysOnTop: true, icon: iconPath, - customStylesheet: path.join(__dirname, "darkPrompt.css"), - }) + customStylesheet: path.join(__dirname, "prompt","darkPrompt.css"), + }; + if (config.plugins.isEnabled("in-app-menu")) { + Object.assign(options, { + frame: false, + customScript: path.join(__dirname, "prompt","customTitlebar.js"), + enableRemoteModule: true, + height: 200, + width: 450, + }) + } + prompt(options) .then((input) => { if(input !== null && input !== example) { config.set("options.proxy", input); diff --git a/package.json b/package.json index 736374c5..36591897 100644 --- a/package.json +++ b/package.json @@ -70,11 +70,11 @@ "browser-id3-writer": "^4.4.0", "custom-electron-titlebar": "^3.2.6", "discord-rpc": "^3.2.0", + "doc-ready": "^1.0.4", "downloads-folder": "^3.0.1", "electron-debug": "^3.2.0", "electron-is": "^3.0.0", "electron-localshortcut": "^3.2.1", - "electron-prompt": "^1.6.2", "electron-store": "^7.0.2", "electron-unhandled": "^3.0.2", "electron-updater": "^4.3.6", diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js new file mode 100644 index 00000000..203828d4 --- /dev/null +++ b/prompt/customTitlebar.js @@ -0,0 +1,12 @@ +const customTitlebar = require("custom-electron-titlebar"); + +module.exports = () => { + const bar = new customTitlebar.Titlebar({ + backgroundColor: customTitlebar.Color.fromHex("#050505"), + }); + try { + bar.updateMenu(null); + } catch (e) { + //will always throw type error - null isn't menu, but it works + } +} \ No newline at end of file diff --git a/darkPrompt.css b/prompt/darkPrompt.css similarity index 88% rename from darkPrompt.css rename to prompt/darkPrompt.css index 100a6ed5..3bdc5647 100644 --- a/darkPrompt.css +++ b/prompt/darkPrompt.css @@ -4,6 +4,16 @@ body { overflow: hidden; color:whitesmoke; } + +::-webkit-scrollbar { + width: 0 !important; + display: none; +} + +#label { + text-align: center; +} + #container { background: rgba( 0, 0, 0, 0.7 ); box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); @@ -11,7 +21,6 @@ body { -webkit-backdrop-filter: blur( 10.0px ); border-radius: 10px; border: 1px solid rgba(80, 0, 0, 0.4); - overflow: hidden; } diff --git a/prompt/index.js b/prompt/index.js new file mode 100644 index 00000000..d6664305 --- /dev/null +++ b/prompt/index.js @@ -0,0 +1,127 @@ +const electron = require('electron'); + +const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow; +const ipcMain = electron.ipcMain || electron.remote.ipcMain; +const url = require('url'); +const path = require('path'); + +const DEFAULT_WIDTH = 370; +const DEFAULT_HEIGHT = 160; + +function electronPrompt(options, parentWindow) { + return new Promise((resolve, reject) => { + const id = `${Date.now()}-${Math.random()}`; + + const options_ = Object.assign( + { + width: DEFAULT_WIDTH, + height: DEFAULT_HEIGHT, + minWidth: DEFAULT_WIDTH, + minHeight: DEFAULT_HEIGHT, + resizable: false, + title: 'Prompt', + label: 'Please input a value:', + buttonLabels: null, + alwaysOnTop: false, + value: null, + type: 'input', + selectOptions: null, + icon: null, + useHtmlLabel: false, + customStylesheet: null, + menuBarVisible: false, + skipTaskbar: true, + frame: true, + customScript: null, + enableRemoteModule: false + }, + options || {} + ); + + if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) { + reject(new Error('"selectOptions" must be an object')); + return; + } + + let promptWindow = new BrowserWindow({ + frame: options_.frame, + width: options_.width, + height: options_.height, + minWidth: options_.minWidth, + minHeight: options_.minHeight, + resizable: options_.resizable, + minimizable: false, + fullscreenable: false, + maximizable: false, + parent: parentWindow, + skipTaskbar: options_.skipTaskbar, + alwaysOnTop: options_.alwaysOnTop, + useContentSize: options_.resizable, + modal: Boolean(parentWindow), + title: options_.title, + icon: options_.icon || undefined, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + enableRemoteModule: options_.enableRemoteModule + } + }); + + promptWindow.setMenu(null); + promptWindow.setMenuBarVisibility(options_.menuBarVisible); + + const getOptionsListener = event => { + event.returnValue = JSON.stringify(options_); + }; + + const cleanup = () => { + ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener); + ipcMain.removeListener('prompt-post-data:' + id, postDataListener); + ipcMain.removeListener('prompt-error:' + id, errorListener); + + if (promptWindow) { + promptWindow.close(); + promptWindow = null; + } + }; + + const postDataListener = (event, value) => { + resolve(value); + event.returnValue = null; + cleanup(); + }; + + const unresponsiveListener = () => { + reject(new Error('Window was unresponsive')); + cleanup(); + }; + + const errorListener = (event, message) => { + reject(new Error(message)); + event.returnValue = null; + cleanup(); + }; + + ipcMain.on('prompt-get-options:' + id, getOptionsListener); + ipcMain.on('prompt-post-data:' + id, postDataListener); + ipcMain.on('prompt-error:' + id, errorListener); + promptWindow.on('unresponsive', unresponsiveListener); + + promptWindow.on('closed', () => { + promptWindow = null; + cleanup(); + resolve(null); + }); + + const promptUrl = url.format({ + protocol: 'file', + slashes: true, + pathname: path.join(__dirname, 'page', 'prompt.html'), + hash: id + }); + + promptWindow.loadURL(promptUrl); + }); +} + +module.exports = electronPrompt; diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css new file mode 100644 index 00000000..b9d37777 --- /dev/null +++ b/prompt/page/prompt.css @@ -0,0 +1,72 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif; + line-height: 1.5em; + color: #333; + background-color: #fff; +} + +#container { + align-items: center; + justify-content: center; + display: flex; + height: 100%; + overflow: auto; +} + +#form { + width: 100%; + padding-top: .5em; +} + +#label { + max-width: 100%; + max-height: 100%; + margin-bottom: .8em; + padding: 0 .5em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#data { + border-radius: 2px; + background: #fff; + width: 90%; + padding: .4em .5em; + border: 1px solid black; + min-height: 2em; + margin: 0 0 1.2em; +} + +select#data { + height: 2em; +} + +#data-container { + text-align: center; +} + +#buttons { + text-align: right; + padding: 0 .5em 0 0; +} + +#buttons > button, +#buttons > input[type=submit] { + border-radius: 2px; + border: 0; + margin: 0 0 0 .5em; + font-size: .8em; + line-height: 1em; + padding: .6em 1em +} + +#ok { + background-color: #3879D9; + color: white; +} + +#cancel { + background-color: #DDD; + color: black; +} diff --git a/prompt/page/prompt.html b/prompt/page/prompt.html new file mode 100644 index 00000000..cdbfa544 --- /dev/null +++ b/prompt/page/prompt.html @@ -0,0 +1,18 @@ + + + + + +
+
+
...
+
+
+ + +
+
+
+ + + diff --git a/prompt/page/prompt.js b/prompt/page/prompt.js new file mode 100644 index 00000000..754d0e74 --- /dev/null +++ b/prompt/page/prompt.js @@ -0,0 +1,170 @@ +const fs = require('fs'); +const {ipcRenderer} = require('electron'); +const docReady = require('doc-ready'); + +let promptId = null; +let promptOptions = null; + +function promptError(error) { + if (error instanceof Error) { + error = error.message; + } + + ipcRenderer.sendSync('prompt-error:' + promptId, error); +} + +function promptCancel() { + ipcRenderer.sendSync('prompt-post-data:' + promptId, null); +} + +function promptSubmit() { + const dataElement = document.querySelector('#data'); + let data = null; + + if (promptOptions.type === 'input') { + data = dataElement.value; + } else if (promptOptions.type === 'select') { + if (promptOptions.selectMultiple) { + data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value')); + } else { + data = dataElement.value; + } + } + + ipcRenderer.sendSync('prompt-post-data:' + promptId, data); +} + +function promptCreateInput() { + const dataElement = document.createElement('input'); + dataElement.setAttribute('type', 'text'); + + if (promptOptions.value) { + dataElement.value = promptOptions.value; + } else { + dataElement.value = ''; + } + + if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') { + for (const k in promptOptions.inputAttrs) { + if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { + continue; + } + + dataElement.setAttribute(k, promptOptions.inputAttrs[k]); + } + } + + dataElement.addEventListener('keyup', event => { + if (event.key === 'Escape') { + promptCancel(); + } + }); + + dataElement.addEventListener('keypress', event => { + if (event.key === 'Enter') { + event.preventDefault(); + document.querySelector('#ok').click(); + } + }); + + return dataElement; +} + +function promptCreateSelect() { + const dataElement = document.createElement('select'); + let optionElement; + + for (const k in promptOptions.selectOptions) { + if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) { + continue; + } + + optionElement = document.createElement('option'); + optionElement.setAttribute('value', k); + optionElement.textContent = promptOptions.selectOptions[k]; + if (k === promptOptions.value) { + optionElement.setAttribute('selected', 'selected'); + } + + dataElement.append(optionElement); + } + + return dataElement; +} + +function promptRegister() { + promptId = document.location.hash.replace('#', ''); + + try { + promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId)); + } catch (error) { + return promptError(error); + } + + if (promptOptions.useHtmlLabel) { + document.querySelector('#label').innerHTML = promptOptions.label; + } else { + document.querySelector('#label').textContent = promptOptions.label; + } + + if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { + document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok; + } + + if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { + document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel; + } + + if (promptOptions.customStylesheet) { + try { + const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); + if (customStyleContent) { + const customStyle = document.createElement('style'); + customStyle.setAttribute('rel', 'stylesheet'); + customStyle.append(document.createTextNode(customStyleContent)); + document.head.append(customStyle); + } + } catch (error) { + return promptError(error); + } + } + + document.querySelector('#form').addEventListener('submit', promptSubmit); + document.querySelector('#cancel').addEventListener('click', promptCancel); + + const dataContainerElement = document.querySelector('#data-container'); + + let dataElement; + if (promptOptions.type === 'input') { + dataElement = promptCreateInput(); + } else if (promptOptions.type === 'select') { + dataElement = promptCreateSelect(); + } else { + return promptError(`Unhandled input type '${promptOptions.type}'`); + } + + dataContainerElement.append(dataElement); + dataElement.setAttribute('id', 'data'); + + dataElement.focus(); + if (promptOptions.type === 'input') { + dataElement.select(); + } + + if (promptOptions.customScript) { + try { + const customScript = require(promptOptions.customScript); + customScript(); + } catch (error) { + return promptError(error); + } + } +} + +window.addEventListener('error', error => { + if (promptId) { + promptError('An error has occured on the prompt window: \n' + error); + } +}); + +docReady(promptRegister); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b029d432..f9909214 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3093,13 +3093,6 @@ electron-localshortcut@^3.1.0, electron-localshortcut@^3.2.1: keyboardevent-from-electron-accelerator "^2.0.0" keyboardevents-areequal "^0.2.1" -electron-prompt@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/electron-prompt/-/electron-prompt-1.6.2.tgz#e26bd3d359120bd45ce2f9625bdc380deb7ee269" - integrity sha512-gC9ZpMopIgz1kW92J7UfsXarkLdPH2zhr77bnJFlDSduYjRlr9nEPm4ux1vyzJsO72AdOyvuPPIQB0j+gWsncQ== - dependencies: - doc-ready "^1.0.4" - electron-publish@22.9.1: version "22.9.1" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.9.1.tgz#7cc76ac4cc53efd29ee31c1e5facb9724329068e" From 73b0ddc2cecb08509a17bef4d222e8f5b183599e Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 21:25:41 +0300 Subject: [PATCH 024/118] css tweaks --- prompt/customTitlebar.js | 7 +++++++ prompt/darkPrompt.css | 17 +++++++++-------- prompt/page/prompt.css | 8 +++++++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js index 203828d4..5dc942cf 100644 --- a/prompt/customTitlebar.js +++ b/prompt/customTitlebar.js @@ -3,10 +3,17 @@ const customTitlebar = require("custom-electron-titlebar"); module.exports = () => { const bar = new customTitlebar.Titlebar({ backgroundColor: customTitlebar.Color.fromHex("#050505"), + minimizable: false, + maximizable: false, + unfocusEffect: true, }); try { bar.updateMenu(null); } catch (e) { //will always throw type error - null isn't menu, but it works } + let container = document.querySelector('#container'); + container.style.width = '100%'; + container.style.position = 'fixed'; + container.style.border = 'unset'; } \ No newline at end of file diff --git a/prompt/darkPrompt.css b/prompt/darkPrompt.css index 3bdc5647..311c42b5 100644 --- a/prompt/darkPrompt.css +++ b/prompt/darkPrompt.css @@ -1,15 +1,10 @@ + body { background-color: rgba(0, 0, 0, 0.3); background-image: linear-gradient(315deg, #200000 0%, #13253a 74%); - overflow: hidden; color:whitesmoke; } -::-webkit-scrollbar { - width: 0 !important; - display: none; -} - #label { text-align: center; } @@ -30,14 +25,20 @@ body { border: 1px solid rgb(54, 54, 54); } +#data:hover { + border: 1px solid rgb(85, 85, 85); +} + #data:focus { outline: unset; border: 1px solid rgb(85, 85, 85); } - #ok:focus, #cancel:focus { - outline: rgba(30, 0, 0, 0.3) solid 1px; + #ok:hover, #cancel:hover { + outline: rgba(60, 0, 0, 0.4) solid 2px; + /* border: 1px solid rgba(60, 0, 0, 0.4); + */ } #ok, #cancel { diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css index b9d37777..b18d1fc0 100644 --- a/prompt/page/prompt.css +++ b/prompt/page/prompt.css @@ -3,6 +3,12 @@ body { line-height: 1.5em; color: #333; background-color: #fff; + overflow-y: hidden; +} + +::-webkit-scrollbar { + width: 0 !important; + display: none; } #container { @@ -10,7 +16,7 @@ body { justify-content: center; display: flex; height: 100%; - overflow: auto; + overflow-y: hidden; } #form { From 10e29090d8318555d6ca7860d2ce00d9fcc3ce9e Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 4 Apr 2021 21:52:16 +0300 Subject: [PATCH 025/118] stylecheck --- menu.js | 41 ++++++++----------- prompt/customTitlebar.js | 4 +- prompt/darkPrompt.css | 52 ++++++++++++------------ prompt/page/prompt.css | 88 ++++++++++++++++++++-------------------- 4 files changed, 90 insertions(+), 95 deletions(-) diff --git a/menu.js b/menu.js index 0312778f..18764681 100644 --- a/menu.js +++ b/menu.js @@ -148,7 +148,7 @@ const mainMenuTemplate = (win) => [ type: "checkbox", checked: !!config.get("options.proxy"), click: (item) => { - setProxy(item); + setProxy(item, win); } }, { @@ -311,36 +311,31 @@ module.exports.setApplicationMenu = (win) => { const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); const example = `Example: "socks5://127.0.0.1:9999"`; -function setProxy(item) { +function setProxy(item, win) { let options = { title: 'Set Proxy', - label: 'Enter Proxy Address (leave empty to disable)', + label: 'Enter Proxy Address: (leave empty to disable)', value: config.get("options.proxy") || example, inputAttrs: { type: 'text' }, type: 'input', - alwaysOnTop: true, icon: iconPath, - customStylesheet: path.join(__dirname, "prompt","darkPrompt.css"), + customStylesheet: path.join(__dirname, "prompt", "darkPrompt.css"), + frame: false, + customScript: path.join(__dirname, "prompt", "customTitlebar.js"), + enableRemoteModule: true, + height: 200, + width: 450, }; - if (config.plugins.isEnabled("in-app-menu")) { - Object.assign(options, { - frame: false, - customScript: path.join(__dirname, "prompt","customTitlebar.js"), - enableRemoteModule: true, - height: 200, - width: 450, + prompt(options, win) + .then((input) => { + if (input !== null && input !== example) { + config.set("options.proxy", input); + item.checked = (input === "") ? false : true; + } else { //user pressed cancel + item.checked = !item.checked; //reset checkbox + } }) - } - prompt(options) - .then((input) => { - if(input !== null && input !== example) { - config.set("options.proxy", input); - item.checked = (input === "") ? false : true; - } else { //user pressed cancel - item.checked = !item.checked; //reset checkbox - } - }) - .catch(console.error); + .catch(console.error); } \ No newline at end of file diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js index 5dc942cf..116aa56c 100644 --- a/prompt/customTitlebar.js +++ b/prompt/customTitlebar.js @@ -2,11 +2,11 @@ const customTitlebar = require("custom-electron-titlebar"); module.exports = () => { const bar = new customTitlebar.Titlebar({ - backgroundColor: customTitlebar.Color.fromHex("#050505"), + backgroundColor: customTitlebar.Color.fromHex("#050505"), minimizable: false, maximizable: false, unfocusEffect: true, - }); + }); try { bar.updateMenu(null); } catch (e) { diff --git a/prompt/darkPrompt.css b/prompt/darkPrompt.css index 311c42b5..8b343a25 100644 --- a/prompt/darkPrompt.css +++ b/prompt/darkPrompt.css @@ -1,47 +1,45 @@ - body { - background-color: rgba(0, 0, 0, 0.3); - background-image: linear-gradient(315deg, #200000 0%, #13253a 74%); - color:whitesmoke; + background-color: rgba(0, 0, 0, 0.3); + background-image: linear-gradient(315deg, #200000 0%, #13253a 74%); + color: whitesmoke; } #label { - text-align: center; + text-align: center; } #container { - background: rgba( 0, 0, 0, 0.7 ); - box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); - backdrop-filter: blur( 10.0px ); - -webkit-backdrop-filter: blur( 10.0px ); - border-radius: 10px; - border: 1px solid rgba(80, 0, 0, 0.4); - overflow: hidden; + background: rgba(0, 0, 0, 0.7); + box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-radius: 10px; + border: 1px solid rgba(80, 0, 0, 0.4); + overflow: hidden; } #data { - background: unset; - color: whitesmoke; - border: 1px solid rgb(54, 54, 54); + background: unset; + color: whitesmoke; + border: 1px solid rgb(54, 54, 54); } #data:hover { - border: 1px solid rgb(85, 85, 85); + border: 1px solid rgb(85, 85, 85); } #data:focus { - outline: unset; - border: 1px solid rgb(85, 85, 85); + outline: unset; + border: 1px solid rgb(85, 85, 85); } - #ok:hover, #cancel:hover { - outline: rgba(60, 0, 0, 0.4) solid 2px; - /* - border: 1px solid rgba(60, 0, 0, 0.4); - */ +#ok:hover, +#cancel:hover { + outline: rgba(60, 0, 0, 0.4) solid 2px; } -#ok, #cancel { - background-color: rgb(0, 0, 0); - color: whitesmoke; -} \ No newline at end of file +#ok, +#cancel { + background-color: rgb(0, 0, 0); + color: whitesmoke; +} diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css index b18d1fc0..c3530e57 100644 --- a/prompt/page/prompt.css +++ b/prompt/page/prompt.css @@ -1,78 +1,80 @@ body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif; - line-height: 1.5em; - color: #333; - background-color: #fff; - overflow-y: hidden; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, + sans-serif; + line-height: 1.5em; + color: #333; + background-color: #fff; + overflow-y: hidden; } ::-webkit-scrollbar { - width: 0 !important; - display: none; + width: 0 !important; + display: none; } #container { - align-items: center; - justify-content: center; - display: flex; - height: 100%; - overflow-y: hidden; + align-items: center; + justify-content: center; + display: flex; + height: 100%; + overflow-y: hidden; } #form { - width: 100%; - padding-top: .5em; + width: 100%; + padding-top: 0.5em; } #label { - max-width: 100%; - max-height: 100%; - margin-bottom: .8em; - padding: 0 .5em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + max-width: 100%; + max-height: 100%; + margin-bottom: 0.8em; + padding: 0 0.5em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } #data { - border-radius: 2px; - background: #fff; - width: 90%; - padding: .4em .5em; - border: 1px solid black; - min-height: 2em; - margin: 0 0 1.2em; + border-radius: 2px; + background: #fff; + width: 90%; + padding: 0.4em 0.5em; + border: 1px solid black; + min-height: 2em; + margin: 0 0 1.2em; } select#data { - height: 2em; + height: 2em; } #data-container { - text-align: center; + text-align: center; } #buttons { - text-align: right; - padding: 0 .5em 0 0; + text-align: right; + padding: 0 0.5em 0 0; } #buttons > button, -#buttons > input[type=submit] { - border-radius: 2px; - border: 0; - margin: 0 0 0 .5em; - font-size: .8em; - line-height: 1em; - padding: .6em 1em +#buttons > input[type="submit"] { + border-radius: 2px; + border: 0; + margin: 0 0 0 0.5em; + font-size: 0.8em; + line-height: 1em; + padding: 0.6em 1em; } #ok { - background-color: #3879D9; - color: white; + background-color: #3879d9; + color: white; } #cancel { - background-color: #DDD; - color: black; + background-color: #ddd; + color: black; } From 28d366ab19cdf85fdad4537db9762e40c86d4da6 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 03:04:06 +0300 Subject: [PATCH 026/118] add back-to-front logger This somehow fix "did-fail-load" being called on song start, with in-app-plugin-activated --- index.js | 23 +++++++++++++++++++++-- preload.js | 4 ++++ providers/logger.js | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 providers/logger.js diff --git a/index.js b/index.js index baa8c49c..97f4dcb5 100644 --- a/index.js +++ b/index.js @@ -163,10 +163,29 @@ app.on("browser-window-created", (event, win) => { createdWindow = true; loadPlugins(win); - win.webContents.on("did-fail-load", () => { + win.webContents.on("did-fail-load", ( + event, + errorCode, + errorDescription, + validatedURL, + isMainFrame, + frameProcessId, + frameRoutingId, + ) => { + let log = { + error: "did-fail-load", + event, + errorCode, + errorDescription, + validatedURL, + isMainFrame, + frameProcessId, + frameRoutingId, + }; if (is.dev()) { - console.log("did fail load"); + console.log(log); } + win.webContents.send("log", log); win.webContents.loadFile(path.join(__dirname, "error.html")); }); diff --git a/preload.js b/preload.js index 94f2a72a..33e67306 100644 --- a/preload.js +++ b/preload.js @@ -32,6 +32,10 @@ document.addEventListener("DOMContentLoaded", () => { // inject song-info provider const songInfoProviderPath = path.join(__dirname, "providers", "song-info-front.js") fileExists(songInfoProviderPath, require(songInfoProviderPath)); + + // inject front logger + const loggerPath = path.join(__dirname, "providers", "logger.js") + fileExists(loggerPath, require(loggerPath)); // Add action for reloading global.reload = () => diff --git a/providers/logger.js b/providers/logger.js new file mode 100644 index 00000000..84163c52 --- /dev/null +++ b/providers/logger.js @@ -0,0 +1,14 @@ +const { ipcRenderer } = require("electron"); + +module.exports = () => { + ipcRenderer.on("log", (event, log) => { + let string = log.toString() || log; + if (string) { + console.log(string); + } else { + for (let propery of log) { + console.log(propery.toString() || propery); + } + } + }) +} \ No newline at end of file From 11bd1adbd406160b9ee4215fa0b329b5ecd4391d Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 03:25:45 +0300 Subject: [PATCH 027/118] stylecheck --- index.js | 32 ++++++++++++++++---------------- preload.js | 2 +- providers/logger.js | 18 +++++++++--------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index 97f4dcb5..9e8b7233 100644 --- a/index.js +++ b/index.js @@ -37,8 +37,8 @@ if (config.get("options.proxy")) { } // Adds debug features like hotkeys for triggering dev tools and reload -require("electron-debug")({ - showDevTools: false //disable dev tools on electron-prompt +require("electron-debug")({ + showDevTools: false //disable automatic devTools on new window }); // Prevent window being garbage collected @@ -100,18 +100,18 @@ function createMainWindow() { affinity: "main-window", // main window, and addition windows should work in one process ...(isTesting() ? { - // Only necessary when testing with Spectron - contextIsolation: false, - nodeIntegration: true, - } + // Only necessary when testing with Spectron + contextIsolation: false, + nodeIntegration: true, + } : undefined), }, frame: !is.macOS() && !useInlineMenu, titleBarStyle: useInlineMenu ? "hidden" : is.macOS() - ? "hiddenInset" - : "default", + ? "hiddenInset" + : "default", autoHideMenuBar: config.get("options.hideMenu"), }); if (windowPosition) { @@ -157,20 +157,20 @@ function createMainWindow() { let createdWindow = false; app.on("browser-window-created", (event, win) => { //Ensure listeners aren't registered when creating input dialog - if(createdWindow){ + if (createdWindow) { return; } createdWindow = true; loadPlugins(win); win.webContents.on("did-fail-load", ( - event, - errorCode, - errorDescription, - validatedURL, - isMainFrame, - frameProcessId, - frameRoutingId, + event, + errorCode, + errorDescription, + validatedURL, + isMainFrame, + frameProcessId, + frameRoutingId, ) => { let log = { error: "did-fail-load", diff --git a/preload.js b/preload.js index 33e67306..f25dd6b7 100644 --- a/preload.js +++ b/preload.js @@ -36,7 +36,7 @@ document.addEventListener("DOMContentLoaded", () => { // inject front logger const loggerPath = path.join(__dirname, "providers", "logger.js") fileExists(loggerPath, require(loggerPath)); - + // Add action for reloading global.reload = () => remote.getCurrentWindow().webContents.loadURL(config.get("url")); diff --git a/providers/logger.js b/providers/logger.js index 84163c52..560b696b 100644 --- a/providers/logger.js +++ b/providers/logger.js @@ -2,13 +2,13 @@ const { ipcRenderer } = require("electron"); module.exports = () => { ipcRenderer.on("log", (event, log) => { - let string = log.toString() || log; - if (string) { - console.log(string); - } else { - for (let propery of log) { - console.log(propery.toString() || propery); - } - } - }) + let string = log.toString() || log; + if (string) { + console.log(string); + } else { + for (let propery of log) { + console.log(propery.toString() || propery); + } + } + }) } \ No newline at end of file From 6472002f8a441f21a746b72fc876433698b19190 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 04:04:29 +0300 Subject: [PATCH 028/118] fix hide-menu timing + minify log function --- plugins/in-app-menu/back.js | 35 ++++++++++++++++++++++------------- providers/logger.js | 13 +++++-------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 53bb9f8d..5c17317a 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -8,7 +8,9 @@ const { setApplicationMenu } = require("../../menu"); const { injectCSS } = require("../utils"); //check that menu doesn't get created twice -let done = false; +let calledReadyToShow = false; +//check menu state isn't changed twice +let calledFinishedLoad = false //tracks menu visibility let visible = true; // win hook for fixing menu @@ -32,42 +34,49 @@ module.exports = (winImport) => { win.on("ready-to-show", () => { // (apparently ready-to-show is called twice) - if (done) { + if (calledReadyToShow) { return; } - done = true; + calledReadyToShow = true; setApplicationMenu(win); //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { - switchMenuVisibility(); electronLocalshortcut.register(win, "Esc", () => { switchMenuVisibility(); }); - } - // fix bug with menu not applying on start when no internet connection available - setMenuVisibility(visible); + } }); + + //set menu visibility on load + win.webContents.on("did-finish-load", () => { + if (calledFinishedLoad) { + return; + } + calledFinishedLoad = true; + // fix bug with menu not applying on start when no internet connection available + setMenuVisibility(!config.get("options.hideMenu")); + }) }; function switchMenuVisibility() { setMenuVisibility(!visible); } -function setMenuVisibility(value){ +function setMenuVisibility(value) { visible = value; win.webContents.send("updateMenu", visible); } function updateCheckboxesAndRadioButtons(item, isRadio, hasSubmenu) { if (!isRadio) { - //fix checkbox - item.checked = !item.checked; - } + //fix checkbox + item.checked = !item.checked; + } //update menu if radio / hasSubmenu if (isRadio || hasSubmenu) { - win.webContents.send("updateMenu", true); + win.webContents.send("updateMenu", true); } } @@ -79,7 +88,7 @@ function updateTemplate(template) { let originalOnclick = item.click; item.click = (itemClicked) => { originalOnclick(itemClicked); - updateCheckboxesAndRadioButtons(itemClicked, item.type==='radio', item.hasSubmenu); + updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu); }; item.fixed = true; } diff --git a/providers/logger.js b/providers/logger.js index 560b696b..dc91f87b 100644 --- a/providers/logger.js +++ b/providers/logger.js @@ -3,12 +3,9 @@ const { ipcRenderer } = require("electron"); module.exports = () => { ipcRenderer.on("log", (event, log) => { let string = log.toString() || log; - if (string) { - console.log(string); - } else { - for (let propery of log) { - console.log(propery.toString() || propery); - } - } + if (!string || string === "[object Object]") { + string = JSON.stringify(log); + } + console.log(string); }) -} \ No newline at end of file +}; \ No newline at end of file From 106e461beb5a7cc4a92f8970acd041cd1b09b8f9 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 04:08:55 +0300 Subject: [PATCH 029/118] fix typo --- plugins/in-app-menu/back.js | 4 ---- providers/logger.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 5c17317a..b17ee032 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -51,10 +51,6 @@ module.exports = (winImport) => { //set menu visibility on load win.webContents.on("did-finish-load", () => { - if (calledFinishedLoad) { - return; - } - calledFinishedLoad = true; // fix bug with menu not applying on start when no internet connection available setMenuVisibility(!config.get("options.hideMenu")); }) diff --git a/providers/logger.js b/providers/logger.js index dc91f87b..08a940f3 100644 --- a/providers/logger.js +++ b/providers/logger.js @@ -2,7 +2,7 @@ const { ipcRenderer } = require("electron"); module.exports = () => { ipcRenderer.on("log", (event, log) => { - let string = log.toString() || log; + let string = log || log.toString(); if (!string || string === "[object Object]") { string = JSON.stringify(log); } From 6d44a579a44f4420e6ab60e2c6655f7bcf2e429e Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 04:21:52 +0300 Subject: [PATCH 030/118] move prompt to provide --- menu.js | 19 ++++++++++++------- .../prompt}/customTitlebar.js | 0 {prompt => providers/prompt}/darkPrompt.css | 0 {prompt => providers/prompt}/index.js | 0 {prompt => providers/prompt}/page/prompt.css | 0 {prompt => providers/prompt}/page/prompt.html | 0 {prompt => providers/prompt}/page/prompt.js | 0 7 files changed, 12 insertions(+), 7 deletions(-) rename {prompt => providers/prompt}/customTitlebar.js (100%) rename {prompt => providers/prompt}/darkPrompt.css (100%) rename {prompt => providers/prompt}/index.js (100%) rename {prompt => providers/prompt}/page/prompt.css (100%) rename {prompt => providers/prompt}/page/prompt.html (100%) rename {prompt => providers/prompt}/page/prompt.js (100%) diff --git a/menu.js b/menu.js index 18764681..3754d14c 100644 --- a/menu.js +++ b/menu.js @@ -6,7 +6,7 @@ const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); -const prompt = require('./prompt'); +const prompt = require('./providers/prompt'); const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, @@ -321,13 +321,18 @@ function setProxy(item, win) { }, type: 'input', icon: iconPath, - customStylesheet: path.join(__dirname, "prompt", "darkPrompt.css"), - frame: false, - customScript: path.join(__dirname, "prompt", "customTitlebar.js"), - enableRemoteModule: true, - height: 200, - width: 450, + customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"), }; + //TODO: custom bar on prompt need testing on macOS + if(!is.macOS()) { + Object.assign(options, { + frame: false, + customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"), + enableRemoteModule: true, + height: 200, + width: 450, + }); + } prompt(options, win) .then((input) => { if (input !== null && input !== example) { diff --git a/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js similarity index 100% rename from prompt/customTitlebar.js rename to providers/prompt/customTitlebar.js diff --git a/prompt/darkPrompt.css b/providers/prompt/darkPrompt.css similarity index 100% rename from prompt/darkPrompt.css rename to providers/prompt/darkPrompt.css diff --git a/prompt/index.js b/providers/prompt/index.js similarity index 100% rename from prompt/index.js rename to providers/prompt/index.js diff --git a/prompt/page/prompt.css b/providers/prompt/page/prompt.css similarity index 100% rename from prompt/page/prompt.css rename to providers/prompt/page/prompt.css diff --git a/prompt/page/prompt.html b/providers/prompt/page/prompt.html similarity index 100% rename from prompt/page/prompt.html rename to providers/prompt/page/prompt.html diff --git a/prompt/page/prompt.js b/providers/prompt/page/prompt.js similarity index 100% rename from prompt/page/prompt.js rename to providers/prompt/page/prompt.js From 25d0f50f3da69c2f59b27f5640d54315202e4c0b Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 04:52:22 +0300 Subject: [PATCH 031/118] Create readme.md --- providers/prompt/readme.md | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 providers/prompt/readme.md diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md new file mode 100644 index 00000000..2eb13b74 --- /dev/null +++ b/providers/prompt/readme.md @@ -0,0 +1,76 @@ +# Prompt Documentation + +

prompt-preview

+ +## Usage + +```js +prompt([options, parentBrowserWindow]).then(...).catch(...) +``` + +## Example + +```js +const prompt = require('./providers/prompt'); + +prompt({ + title: 'Prompt example', + label: 'URL:', + value: 'http://example.org', + inputAttrs: { + type: 'url' + }, + type: 'input' +}) +.then((r) => { + if(r === null) { + console.log('user cancelled'); + } else { + console.log('result', r); + } +}) +.catch(console.error); +``` + +### Options object (optional) + +| Key | Explanation | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. | +| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. | +| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. | +| value | (optional, string) The default value for the input field. Defaults to null. | +| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. | +| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' | +| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | +| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | +| width | (optional, integer) The width of the prompt window. Defaults to 370. | +| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. | +| height | (optional, integer) The height of the prompt window. Defaults to 130. | +| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. | +| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. | +| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false | +| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. | +| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. | +| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. | +| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. | +| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. | +| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. | +| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. | + +If not supplied, it uses the defaults listed in the table above. + +### parentBrowserWindow (optional) + +The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null. + +### customScript (optional) + +Create the script with the following template: + +```node +module.exports = () => { + // This function will be called as a preload script + // So you can use front features like `document.querySelector` +}; +``` From a215035d0792891845eeb625ba140fd3dadfb241 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 18:28:27 +0300 Subject: [PATCH 032/118] refactor and css fix --- providers/prompt/customTitlebar.js | 15 +++++---------- providers/prompt/darkPrompt.css | 4 +++- providers/prompt/index.js | 6 +++--- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js index 116aa56c..6c508210 100644 --- a/providers/prompt/customTitlebar.js +++ b/providers/prompt/customTitlebar.js @@ -5,15 +5,10 @@ module.exports = () => { backgroundColor: customTitlebar.Color.fromHex("#050505"), minimizable: false, maximizable: false, - unfocusEffect: true, + menu: null }); - try { - bar.updateMenu(null); - } catch (e) { - //will always throw type error - null isn't menu, but it works - } - let container = document.querySelector('#container'); - container.style.width = '100%'; - container.style.position = 'fixed'; - container.style.border = 'unset'; + let mainStyle = document.querySelector('#container').style; + mainStyle.width = '100%'; + mainStyle.position = 'fixed'; + mainStyle.border = 'unset'; } \ No newline at end of file diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/darkPrompt.css index 8b343a25..49e0f88e 100644 --- a/providers/prompt/darkPrompt.css +++ b/providers/prompt/darkPrompt.css @@ -34,7 +34,9 @@ body { } #ok:hover, -#cancel:hover { +#ok:focus, +#cancel:hover, +#cancel:focus { outline: rgba(60, 0, 0, 0.4) solid 2px; } diff --git a/providers/prompt/index.js b/providers/prompt/index.js index d6664305..0d89ebe9 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -50,9 +50,9 @@ function electronPrompt(options, parentWindow) { minWidth: options_.minWidth, minHeight: options_.minHeight, resizable: options_.resizable, - minimizable: false, - fullscreenable: false, - maximizable: false, + minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop, + fullscreenable: options_.resizable, + maximizable: options_.resizable, parent: parentWindow, skipTaskbar: options_.skipTaskbar, alwaysOnTop: options_.alwaysOnTop, From 724c213af10c4ade43fb15b564fbb12123672ffb Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Mon, 5 Apr 2021 23:18:54 +0300 Subject: [PATCH 033/118] xo --fix --- menu.js | 4 +- package.json | 12 ++- plugins/in-app-menu/back.js | 9 +- providers/prompt/custom-titlebar.js | 14 +++ providers/prompt/customTitlebar.js | 14 --- .../{darkPrompt.css => dark-prompt.css} | 0 providers/prompt/index.js | 30 +++---- providers/prompt/page/prompt.js | 88 +++++++++---------- 8 files changed, 89 insertions(+), 82 deletions(-) create mode 100644 providers/prompt/custom-titlebar.js delete mode 100644 providers/prompt/customTitlebar.js rename providers/prompt/{darkPrompt.css => dark-prompt.css} (100%) diff --git a/menu.js b/menu.js index 3754d14c..c0495d68 100644 --- a/menu.js +++ b/menu.js @@ -321,13 +321,13 @@ function setProxy(item, win) { }, type: 'input', icon: iconPath, - customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"), + customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"), }; //TODO: custom bar on prompt need testing on macOS if(!is.macOS()) { Object.assign(options, { frame: false, - customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"), + customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"), enableRemoteModule: true, height: 200, width: 450, diff --git a/package.json b/package.json index 36591897..144ac53f 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,16 @@ "envs": [ "node", "browser" - ] + ], + "rules": { + "quotes": [ + "error", + "double", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ] + } } } diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index b17ee032..938c5475 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -9,8 +9,6 @@ const { injectCSS } = require("../utils"); //check that menu doesn't get created twice let calledReadyToShow = false; -//check menu state isn't changed twice -let calledFinishedLoad = false //tracks menu visibility let visible = true; // win hook for fixing menu @@ -37,6 +35,7 @@ module.exports = (winImport) => { if (calledReadyToShow) { return; } + calledReadyToShow = true; setApplicationMenu(win); @@ -53,7 +52,7 @@ module.exports = (winImport) => { win.webContents.on("did-finish-load", () => { // fix bug with menu not applying on start when no internet connection available setMenuVisibility(!config.get("options.hideMenu")); - }) + }); }; function switchMenuVisibility() { @@ -81,10 +80,10 @@ function updateTemplate(template) { for (let item of template) { // Change onClick of checkbox+radio if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { - let originalOnclick = item.click; + const originalOnclick = item.click; item.click = (itemClicked) => { originalOnclick(itemClicked); - updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu); + updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu); }; item.fixed = true; } diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js new file mode 100644 index 00000000..c36ce5f5 --- /dev/null +++ b/providers/prompt/custom-titlebar.js @@ -0,0 +1,14 @@ +const customTitlebar = require("custom-electron-titlebar"); + +module.exports = () => { + const bar = new customTitlebar.Titlebar({ + backgroundColor: customTitlebar.Color.fromHex("#050505"), + minimizable: false, + maximizable: false, + menu: null + }); + const mainStyle = document.querySelector("#container").style; + mainStyle.width = "100%"; + mainStyle.position = "fixed"; + mainStyle.border = "unset"; +}; diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js deleted file mode 100644 index 6c508210..00000000 --- a/providers/prompt/customTitlebar.js +++ /dev/null @@ -1,14 +0,0 @@ -const customTitlebar = require("custom-electron-titlebar"); - -module.exports = () => { - const bar = new customTitlebar.Titlebar({ - backgroundColor: customTitlebar.Color.fromHex("#050505"), - minimizable: false, - maximizable: false, - menu: null - }); - let mainStyle = document.querySelector('#container').style; - mainStyle.width = '100%'; - mainStyle.position = 'fixed'; - mainStyle.border = 'unset'; -} \ No newline at end of file diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/dark-prompt.css similarity index 100% rename from providers/prompt/darkPrompt.css rename to providers/prompt/dark-prompt.css diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 0d89ebe9..302eeea0 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -1,9 +1,9 @@ -const electron = require('electron'); +const electron = require("electron"); const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow; const ipcMain = electron.ipcMain || electron.remote.ipcMain; -const url = require('url'); -const path = require('path'); +const url = require("url"); +const path = require("path"); const DEFAULT_WIDTH = 370; const DEFAULT_HEIGHT = 160; @@ -38,7 +38,7 @@ function electronPrompt(options, parentWindow) { options || {} ); - if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) { + if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { reject(new Error('"selectOptions" must be an object')); return; } @@ -75,9 +75,9 @@ function electronPrompt(options, parentWindow) { }; const cleanup = () => { - ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener); - ipcMain.removeListener('prompt-post-data:' + id, postDataListener); - ipcMain.removeListener('prompt-error:' + id, errorListener); + ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener); + ipcMain.removeListener("prompt-post-data:" + id, postDataListener); + ipcMain.removeListener("prompt-error:" + id, errorListener); if (promptWindow) { promptWindow.close(); @@ -92,7 +92,7 @@ function electronPrompt(options, parentWindow) { }; const unresponsiveListener = () => { - reject(new Error('Window was unresponsive')); + reject(new Error("Window was unresponsive")); cleanup(); }; @@ -102,21 +102,21 @@ function electronPrompt(options, parentWindow) { cleanup(); }; - ipcMain.on('prompt-get-options:' + id, getOptionsListener); - ipcMain.on('prompt-post-data:' + id, postDataListener); - ipcMain.on('prompt-error:' + id, errorListener); - promptWindow.on('unresponsive', unresponsiveListener); + ipcMain.on("prompt-get-options:" + id, getOptionsListener); + ipcMain.on("prompt-post-data:" + id, postDataListener); + ipcMain.on("prompt-error:" + id, errorListener); + promptWindow.on("unresponsive", unresponsiveListener); - promptWindow.on('closed', () => { + promptWindow.on("closed", () => { promptWindow = null; cleanup(); resolve(null); }); const promptUrl = url.format({ - protocol: 'file', + protocol: "file", slashes: true, - pathname: path.join(__dirname, 'page', 'prompt.html'), + pathname: path.join(__dirname, "page", "prompt.html"), hash: id }); diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 754d0e74..67acd31d 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -1,6 +1,6 @@ -const fs = require('fs'); -const {ipcRenderer} = require('electron'); -const docReady = require('doc-ready'); +const fs = require("fs"); +const {ipcRenderer} = require("electron"); +const docReady = require("doc-ready"); let promptId = null; let promptOptions = null; @@ -10,41 +10,39 @@ function promptError(error) { error = error.message; } - ipcRenderer.sendSync('prompt-error:' + promptId, error); + ipcRenderer.sendSync("prompt-error:" + promptId, error); } function promptCancel() { - ipcRenderer.sendSync('prompt-post-data:' + promptId, null); + ipcRenderer.sendSync("prompt-post-data:" + promptId, null); } function promptSubmit() { - const dataElement = document.querySelector('#data'); + const dataElement = document.querySelector("#data"); let data = null; - if (promptOptions.type === 'input') { + if (promptOptions.type === "input") { data = dataElement.value; - } else if (promptOptions.type === 'select') { - if (promptOptions.selectMultiple) { - data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value')); - } else { - data = dataElement.value; - } + } else if (promptOptions.type === "select") { + data = promptOptions.selectMultiple ? + dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) : + dataElement.value; } - ipcRenderer.sendSync('prompt-post-data:' + promptId, data); + ipcRenderer.sendSync("prompt-post-data:" + promptId, data); } function promptCreateInput() { - const dataElement = document.createElement('input'); - dataElement.setAttribute('type', 'text'); + const dataElement = document.createElement("input"); + dataElement.setAttribute("type", "text"); if (promptOptions.value) { dataElement.value = promptOptions.value; } else { - dataElement.value = ''; + dataElement.value = ""; } - if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') { + if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") { for (const k in promptOptions.inputAttrs) { if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { continue; @@ -54,16 +52,16 @@ function promptCreateInput() { } } - dataElement.addEventListener('keyup', event => { - if (event.key === 'Escape') { + dataElement.addEventListener("keyup", event => { + if (event.key === "Escape") { promptCancel(); } }); - dataElement.addEventListener('keypress', event => { - if (event.key === 'Enter') { + dataElement.addEventListener("keypress", event => { + if (event.key === "Enter") { event.preventDefault(); - document.querySelector('#ok').click(); + document.querySelector("#ok").click(); } }); @@ -71,7 +69,7 @@ function promptCreateInput() { } function promptCreateSelect() { - const dataElement = document.createElement('select'); + const dataElement = document.createElement("select"); let optionElement; for (const k in promptOptions.selectOptions) { @@ -79,11 +77,11 @@ function promptCreateSelect() { continue; } - optionElement = document.createElement('option'); - optionElement.setAttribute('value', k); + optionElement = document.createElement("option"); + optionElement.setAttribute("value", k); optionElement.textContent = promptOptions.selectOptions[k]; if (k === promptOptions.value) { - optionElement.setAttribute('selected', 'selected'); + optionElement.setAttribute("selected", "selected"); } dataElement.append(optionElement); @@ -93,34 +91,34 @@ function promptCreateSelect() { } function promptRegister() { - promptId = document.location.hash.replace('#', ''); + promptId = document.location.hash.replace("#", ""); try { - promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId)); + promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId)); } catch (error) { return promptError(error); } if (promptOptions.useHtmlLabel) { - document.querySelector('#label').innerHTML = promptOptions.label; + document.querySelector("#label").innerHTML = promptOptions.label; } else { - document.querySelector('#label').textContent = promptOptions.label; + document.querySelector("#label").textContent = promptOptions.label; } if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { - document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok; + document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok; } if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { - document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel; + document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel; } if (promptOptions.customStylesheet) { try { const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); if (customStyleContent) { - const customStyle = document.createElement('style'); - customStyle.setAttribute('rel', 'stylesheet'); + const customStyle = document.createElement("style"); + customStyle.setAttribute("rel", "stylesheet"); customStyle.append(document.createTextNode(customStyleContent)); document.head.append(customStyle); } @@ -129,25 +127,25 @@ function promptRegister() { } } - document.querySelector('#form').addEventListener('submit', promptSubmit); - document.querySelector('#cancel').addEventListener('click', promptCancel); + document.querySelector("#form").addEventListener("submit", promptSubmit); + document.querySelector("#cancel").addEventListener("click", promptCancel); - const dataContainerElement = document.querySelector('#data-container'); + const dataContainerElement = document.querySelector("#data-container"); let dataElement; - if (promptOptions.type === 'input') { + if (promptOptions.type === "input") { dataElement = promptCreateInput(); - } else if (promptOptions.type === 'select') { + } else if (promptOptions.type === "select") { dataElement = promptCreateSelect(); } else { return promptError(`Unhandled input type '${promptOptions.type}'`); } dataContainerElement.append(dataElement); - dataElement.setAttribute('id', 'data'); + dataElement.setAttribute("id", "data"); dataElement.focus(); - if (promptOptions.type === 'input') { + if (promptOptions.type === "input") { dataElement.select(); } @@ -161,10 +159,10 @@ function promptRegister() { } } -window.addEventListener('error', error => { +window.addEventListener("error", error => { if (promptId) { - promptError('An error has occured on the prompt window: \n' + error); + promptError("An error has occured on the prompt window: \n" + error); } }); -docReady(promptRegister); \ No newline at end of file +docReady(promptRegister); From 0e9b15722a02fc1e423fb0d5eec4cd969d397dae Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Tue, 6 Apr 2021 01:30:47 +0300 Subject: [PATCH 034/118] add inline doc --- index.js | 18 ++-- menu.js | 1 + providers/logger.js | 20 ++-- providers/prompt/index.js | 41 +++++--- providers/prompt/page/prompt.js | 168 ++++++++++++++++++-------------- providers/prompt/readme.md | 5 +- 6 files changed, 148 insertions(+), 105 deletions(-) diff --git a/index.js b/index.js index 9e8b7233..7fd88754 100644 --- a/index.js +++ b/index.js @@ -110,8 +110,8 @@ function createMainWindow() { titleBarStyle: useInlineMenu ? "hidden" : is.macOS() - ? "hiddenInset" - : "default", + ? "hiddenInset" + : "default", autoHideMenuBar: config.get("options.hideMenu"), }); if (windowPosition) { @@ -156,7 +156,7 @@ function createMainWindow() { let createdWindow = false; app.on("browser-window-created", (event, win) => { - //Ensure listeners aren't registered when creating input dialog + //Ensures listeners are registered only once if (createdWindow) { return; } @@ -172,7 +172,7 @@ app.on("browser-window-created", (event, win) => { frameProcessId, frameRoutingId, ) => { - let log = { + const log = { error: "did-fail-load", event, errorCode, @@ -183,7 +183,7 @@ app.on("browser-window-created", (event, win) => { frameRoutingId, }; if (is.dev()) { - console.log(log); + console.log(log.toString()); } win.webContents.send("log", log); win.webContents.loadFile(path.join(__dirname, "error.html")); @@ -306,13 +306,11 @@ app.on("ready", () => { } // Optimized for Mac OS X - if (is.macOS()) { - if (!config.get("options.appVisible")) { - app.dock.hide(); - } + if (is.macOS() && !config.get("options.appVisible")) { + app.dock.hide(); } - var forceQuit = false; + let forceQuit = false; app.on("before-quit", () => { forceQuit = true; }); diff --git a/menu.js b/menu.js index c0495d68..21ac1e7a 100644 --- a/menu.js +++ b/menu.js @@ -12,6 +12,7 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, type: "checkbox", checked: config.plugins.isEnabled(plugin), + //Submenu check used in in-app-menu hasSubmenu: hasSubmenu || undefined, click: (item) => { if (item.checked) { diff --git a/providers/logger.js b/providers/logger.js index 08a940f3..730a3dfa 100644 --- a/providers/logger.js +++ b/providers/logger.js @@ -1,11 +1,15 @@ const { ipcRenderer } = require("electron"); +function logToString(log) { + let string = (typeof log === "string") ? log : log.toString(); + if (!string || string.includes("[object Object]")) { + string = JSON.stringify(log); + } + return string; +} + module.exports = () => { - ipcRenderer.on("log", (event, log) => { - let string = log || log.toString(); - if (!string || string === "[object Object]") { - string = JSON.stringify(log); - } - console.log(string); - }) -}; \ No newline at end of file + ipcRenderer.on("log", (event, log) => { + console.log(logToString(log)); + }); +}; diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 302eeea0..bbba8b78 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -10,8 +10,10 @@ const DEFAULT_HEIGHT = 160; function electronPrompt(options, parentWindow) { return new Promise((resolve, reject) => { + //id used to ensure unique listeners per window const id = `${Date.now()}-${Math.random()}`; + //custom options override default const options_ = Object.assign( { width: DEFAULT_WIDTH, @@ -19,12 +21,12 @@ function electronPrompt(options, parentWindow) { minWidth: DEFAULT_WIDTH, minHeight: DEFAULT_HEIGHT, resizable: false, - title: 'Prompt', - label: 'Please input a value:', + title: "Prompt", + label: "Please input a value:", buttonLabels: null, alwaysOnTop: false, value: null, - type: 'input', + type: "input", selectOptions: null, icon: null, useHtmlLabel: false, @@ -70,10 +72,7 @@ function electronPrompt(options, parentWindow) { promptWindow.setMenu(null); promptWindow.setMenuBarVisibility(options_.menuBarVisible); - const getOptionsListener = event => { - event.returnValue = JSON.stringify(options_); - }; - + //called on exit const cleanup = () => { ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener); ipcMain.removeListener("prompt-post-data:" + id, postDataListener); @@ -85,6 +84,12 @@ function electronPrompt(options, parentWindow) { } }; + ///transfer options to front + const getOptionsListener = event => { + event.returnValue = JSON.stringify(options_); + }; + + //get input from front const postDataListener = (event, value) => { resolve(value); event.returnValue = null; @@ -96,12 +101,14 @@ function electronPrompt(options, parentWindow) { cleanup(); }; + //get error from front const errorListener = (event, message) => { reject(new Error(message)); event.returnValue = null; cleanup(); }; + //attach listeners ipcMain.on("prompt-get-options:" + id, getOptionsListener); ipcMain.on("prompt-post-data:" + id, postDataListener); ipcMain.on("prompt-error:" + id, errorListener); @@ -113,13 +120,23 @@ function electronPrompt(options, parentWindow) { resolve(null); }); - const promptUrl = url.format({ - protocol: "file", - slashes: true, - pathname: path.join(__dirname, "page", "prompt.html"), - hash: id + //should never happen + promptWindow.webContents.on("did-fail-load", ( + event, + errorCode, + errorDescription, + validatedURL, + ) => { + const log = { + error: "did-fail-load", + errorCode, + errorDescription, + validatedURL, + }; + reject(new Error("prompt.html did-fail-load, log:\n", + log.toString())); }); + //Finally, load prompt promptWindow.loadURL(promptUrl); }); } diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 67acd31d..b7a54120 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -5,6 +5,93 @@ const docReady = require("doc-ready"); let promptId = null; let promptOptions = null; + +docReady(promptRegister); +//start here +function promptRegister() { + //get custom session id + promptId = document.location.hash.replace("#", ""); + + //get options from back + try { + promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId)); + } catch (error) { + return promptError(error); + } + + //set label + if (promptOptions.useHtmlLabel) { + document.querySelector("#label").innerHTML = promptOptions.label; + } else { + document.querySelector("#label").textContent = promptOptions.label; + } + + //set button label + if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { + document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok; + } + + if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { + document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel; + } + + //inject custom stylesheet from options + if (promptOptions.customStylesheet) { + try { + const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); + if (customStyleContent) { + const customStyle = document.createElement("style"); + customStyle.setAttribute("rel", "stylesheet"); + customStyle.append(document.createTextNode(customStyleContent)); + document.head.append(customStyle); + } + } catch (error) { + return promptError(error); + } + } + + //add button listeners + document.querySelector("#form").addEventListener("submit", promptSubmit); + document.querySelector("#cancel").addEventListener("click", promptCancel); + + + //create input/select + const dataContainerElement = document.querySelector("#data-container"); + let dataElement; + if (promptOptions.type === "input") { + dataElement = promptCreateInput(); + } else if (promptOptions.type === "select") { + dataElement = promptCreateSelect(); + } else { + return promptError(`Unhandled input type '${promptOptions.type}'`); + } + + dataContainerElement.append(dataElement); + dataElement.setAttribute("id", "data"); + + dataElement.focus(); + if (promptOptions.type === "input") { + dataElement.select(); + } + + //load custom script from options + if (promptOptions.customScript) { + try { + const customScript = require(promptOptions.customScript); + customScript(); + } catch (error) { + return promptError(error); + } + } +} + +window.addEventListener("error", error => { + if (promptId) { + promptError("An error has occured on the prompt window: \n" + error); + } +}); + +//send error to back function promptError(error) { if (error instanceof Error) { error = error.message; @@ -13,10 +100,12 @@ function promptError(error) { ipcRenderer.sendSync("prompt-error:" + promptId, error); } +//send to back: input=null function promptCancel() { ipcRenderer.sendSync("prompt-post-data:" + promptId, null); } +//transfer input data to back function promptSubmit() { const dataElement = document.querySelector("#data"); let data = null; @@ -32,6 +121,7 @@ function promptSubmit() { ipcRenderer.sendSync("prompt-post-data:" + promptId, data); } +//creates input box function promptCreateInput() { const dataElement = document.createElement("input"); dataElement.setAttribute("type", "text"); @@ -42,6 +132,7 @@ function promptCreateInput() { dataElement.value = ""; } + //insert custom input attributes if in options if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") { for (const k in promptOptions.inputAttrs) { if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { @@ -52,12 +143,14 @@ function promptCreateInput() { } } + //Cancel/Exit on 'Escape' dataElement.addEventListener("keyup", event => { if (event.key === "Escape") { promptCancel(); } }); + //Confrim on 'Enter' dataElement.addEventListener("keypress", event => { if (event.key === "Enter") { event.preventDefault(); @@ -68,6 +161,7 @@ function promptCreateInput() { return dataElement; } +//create multiple select function promptCreateSelect() { const dataElement = document.createElement("select"); let optionElement; @@ -90,79 +184,5 @@ function promptCreateSelect() { return dataElement; } -function promptRegister() { - promptId = document.location.hash.replace("#", ""); - try { - promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId)); - } catch (error) { - return promptError(error); - } - if (promptOptions.useHtmlLabel) { - document.querySelector("#label").innerHTML = promptOptions.label; - } else { - document.querySelector("#label").textContent = promptOptions.label; - } - - if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { - document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok; - } - - if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { - document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel; - } - - if (promptOptions.customStylesheet) { - try { - const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); - if (customStyleContent) { - const customStyle = document.createElement("style"); - customStyle.setAttribute("rel", "stylesheet"); - customStyle.append(document.createTextNode(customStyleContent)); - document.head.append(customStyle); - } - } catch (error) { - return promptError(error); - } - } - - document.querySelector("#form").addEventListener("submit", promptSubmit); - document.querySelector("#cancel").addEventListener("click", promptCancel); - - const dataContainerElement = document.querySelector("#data-container"); - - let dataElement; - if (promptOptions.type === "input") { - dataElement = promptCreateInput(); - } else if (promptOptions.type === "select") { - dataElement = promptCreateSelect(); - } else { - return promptError(`Unhandled input type '${promptOptions.type}'`); - } - - dataContainerElement.append(dataElement); - dataElement.setAttribute("id", "data"); - - dataElement.focus(); - if (promptOptions.type === "input") { - dataElement.select(); - } - - if (promptOptions.customScript) { - try { - const customScript = require(promptOptions.customScript); - customScript(); - } catch (error) { - return promptError(error); - } - } -} - -window.addEventListener("error", error => { - if (promptId) { - promptError("An error has occured on the prompt window: \n" + error); - } -}); - -docReady(promptRegister); diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md index 2eb13b74..6683aced 100644 --- a/providers/prompt/readme.md +++ b/providers/prompt/readme.md @@ -3,11 +3,14 @@

prompt-preview

## Usage - ```js prompt([options, parentBrowserWindow]).then(...).catch(...) ``` +Promise resolve returns input +If user presses cancel/exit window, input = null; + +On error, Prompise reject returns custom error message ## Example ```js From 17fd499420486cdb4d77ec5d8387df8f692bcbbe Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Tue, 6 Apr 2021 01:51:11 +0300 Subject: [PATCH 035/118] fix typo --- menu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/menu.js b/menu.js index 21ac1e7a..90487970 100644 --- a/menu.js +++ b/menu.js @@ -338,10 +338,10 @@ function setProxy(item, win) { .then((input) => { if (input !== null && input !== example) { config.set("options.proxy", input); - item.checked = (input === "") ? false : true; + item.checked = input !== ""; } else { //user pressed cancel item.checked = !item.checked; //reset checkbox } }) .catch(console.error); -} \ No newline at end of file +} From 980ffb45e927335b66ab950751707e283be48674 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Tue, 6 Apr 2021 21:57:16 +0300 Subject: [PATCH 036/118] Create readme.md refactor and css fix xo --fix add inline doc fix typo --- index.js | 18 +- menu.js | 9 +- package.json | 12 +- plugins/in-app-menu/back.js | 9 +- providers/logger.js | 20 +- providers/prompt/custom-titlebar.js | 14 ++ providers/prompt/customTitlebar.js | 19 -- .../{darkPrompt.css => dark-prompt.css} | 4 +- providers/prompt/index.js | 73 +++--- providers/prompt/page/prompt.js | 232 ++++++++++-------- providers/prompt/readme.md | 79 ++++++ 11 files changed, 306 insertions(+), 183 deletions(-) create mode 100644 providers/prompt/custom-titlebar.js delete mode 100644 providers/prompt/customTitlebar.js rename providers/prompt/{darkPrompt.css => dark-prompt.css} (94%) create mode 100644 providers/prompt/readme.md diff --git a/index.js b/index.js index 9e8b7233..7fd88754 100644 --- a/index.js +++ b/index.js @@ -110,8 +110,8 @@ function createMainWindow() { titleBarStyle: useInlineMenu ? "hidden" : is.macOS() - ? "hiddenInset" - : "default", + ? "hiddenInset" + : "default", autoHideMenuBar: config.get("options.hideMenu"), }); if (windowPosition) { @@ -156,7 +156,7 @@ function createMainWindow() { let createdWindow = false; app.on("browser-window-created", (event, win) => { - //Ensure listeners aren't registered when creating input dialog + //Ensures listeners are registered only once if (createdWindow) { return; } @@ -172,7 +172,7 @@ app.on("browser-window-created", (event, win) => { frameProcessId, frameRoutingId, ) => { - let log = { + const log = { error: "did-fail-load", event, errorCode, @@ -183,7 +183,7 @@ app.on("browser-window-created", (event, win) => { frameRoutingId, }; if (is.dev()) { - console.log(log); + console.log(log.toString()); } win.webContents.send("log", log); win.webContents.loadFile(path.join(__dirname, "error.html")); @@ -306,13 +306,11 @@ app.on("ready", () => { } // Optimized for Mac OS X - if (is.macOS()) { - if (!config.get("options.appVisible")) { - app.dock.hide(); - } + if (is.macOS() && !config.get("options.appVisible")) { + app.dock.hide(); } - var forceQuit = false; + let forceQuit = false; app.on("before-quit", () => { forceQuit = true; }); diff --git a/menu.js b/menu.js index 3754d14c..90487970 100644 --- a/menu.js +++ b/menu.js @@ -12,6 +12,7 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, type: "checkbox", checked: config.plugins.isEnabled(plugin), + //Submenu check used in in-app-menu hasSubmenu: hasSubmenu || undefined, click: (item) => { if (item.checked) { @@ -321,13 +322,13 @@ function setProxy(item, win) { }, type: 'input', icon: iconPath, - customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"), + customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"), }; //TODO: custom bar on prompt need testing on macOS if(!is.macOS()) { Object.assign(options, { frame: false, - customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"), + customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"), enableRemoteModule: true, height: 200, width: 450, @@ -337,10 +338,10 @@ function setProxy(item, win) { .then((input) => { if (input !== null && input !== example) { config.set("options.proxy", input); - item.checked = (input === "") ? false : true; + item.checked = input !== ""; } else { //user pressed cancel item.checked = !item.checked; //reset checkbox } }) .catch(console.error); -} \ No newline at end of file +} diff --git a/package.json b/package.json index 36591897..144ac53f 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,16 @@ "envs": [ "node", "browser" - ] + ], + "rules": { + "quotes": [ + "error", + "double", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ] + } } } diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index b17ee032..938c5475 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -9,8 +9,6 @@ const { injectCSS } = require("../utils"); //check that menu doesn't get created twice let calledReadyToShow = false; -//check menu state isn't changed twice -let calledFinishedLoad = false //tracks menu visibility let visible = true; // win hook for fixing menu @@ -37,6 +35,7 @@ module.exports = (winImport) => { if (calledReadyToShow) { return; } + calledReadyToShow = true; setApplicationMenu(win); @@ -53,7 +52,7 @@ module.exports = (winImport) => { win.webContents.on("did-finish-load", () => { // fix bug with menu not applying on start when no internet connection available setMenuVisibility(!config.get("options.hideMenu")); - }) + }); }; function switchMenuVisibility() { @@ -81,10 +80,10 @@ function updateTemplate(template) { for (let item of template) { // Change onClick of checkbox+radio if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { - let originalOnclick = item.click; + const originalOnclick = item.click; item.click = (itemClicked) => { originalOnclick(itemClicked); - updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu); + updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu); }; item.fixed = true; } diff --git a/providers/logger.js b/providers/logger.js index 08a940f3..730a3dfa 100644 --- a/providers/logger.js +++ b/providers/logger.js @@ -1,11 +1,15 @@ const { ipcRenderer } = require("electron"); +function logToString(log) { + let string = (typeof log === "string") ? log : log.toString(); + if (!string || string.includes("[object Object]")) { + string = JSON.stringify(log); + } + return string; +} + module.exports = () => { - ipcRenderer.on("log", (event, log) => { - let string = log || log.toString(); - if (!string || string === "[object Object]") { - string = JSON.stringify(log); - } - console.log(string); - }) -}; \ No newline at end of file + ipcRenderer.on("log", (event, log) => { + console.log(logToString(log)); + }); +}; diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js new file mode 100644 index 00000000..c36ce5f5 --- /dev/null +++ b/providers/prompt/custom-titlebar.js @@ -0,0 +1,14 @@ +const customTitlebar = require("custom-electron-titlebar"); + +module.exports = () => { + const bar = new customTitlebar.Titlebar({ + backgroundColor: customTitlebar.Color.fromHex("#050505"), + minimizable: false, + maximizable: false, + menu: null + }); + const mainStyle = document.querySelector("#container").style; + mainStyle.width = "100%"; + mainStyle.position = "fixed"; + mainStyle.border = "unset"; +}; diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js deleted file mode 100644 index 116aa56c..00000000 --- a/providers/prompt/customTitlebar.js +++ /dev/null @@ -1,19 +0,0 @@ -const customTitlebar = require("custom-electron-titlebar"); - -module.exports = () => { - const bar = new customTitlebar.Titlebar({ - backgroundColor: customTitlebar.Color.fromHex("#050505"), - minimizable: false, - maximizable: false, - unfocusEffect: true, - }); - try { - bar.updateMenu(null); - } catch (e) { - //will always throw type error - null isn't menu, but it works - } - let container = document.querySelector('#container'); - container.style.width = '100%'; - container.style.position = 'fixed'; - container.style.border = 'unset'; -} \ No newline at end of file diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/dark-prompt.css similarity index 94% rename from providers/prompt/darkPrompt.css rename to providers/prompt/dark-prompt.css index 8b343a25..49e0f88e 100644 --- a/providers/prompt/darkPrompt.css +++ b/providers/prompt/dark-prompt.css @@ -34,7 +34,9 @@ body { } #ok:hover, -#cancel:hover { +#ok:focus, +#cancel:hover, +#cancel:focus { outline: rgba(60, 0, 0, 0.4) solid 2px; } diff --git a/providers/prompt/index.js b/providers/prompt/index.js index d6664305..bbba8b78 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -1,17 +1,19 @@ -const electron = require('electron'); +const electron = require("electron"); const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow; const ipcMain = electron.ipcMain || electron.remote.ipcMain; -const url = require('url'); -const path = require('path'); +const url = require("url"); +const path = require("path"); const DEFAULT_WIDTH = 370; const DEFAULT_HEIGHT = 160; function electronPrompt(options, parentWindow) { return new Promise((resolve, reject) => { + //id used to ensure unique listeners per window const id = `${Date.now()}-${Math.random()}`; + //custom options override default const options_ = Object.assign( { width: DEFAULT_WIDTH, @@ -19,12 +21,12 @@ function electronPrompt(options, parentWindow) { minWidth: DEFAULT_WIDTH, minHeight: DEFAULT_HEIGHT, resizable: false, - title: 'Prompt', - label: 'Please input a value:', + title: "Prompt", + label: "Please input a value:", buttonLabels: null, alwaysOnTop: false, value: null, - type: 'input', + type: "input", selectOptions: null, icon: null, useHtmlLabel: false, @@ -38,7 +40,7 @@ function electronPrompt(options, parentWindow) { options || {} ); - if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) { + if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { reject(new Error('"selectOptions" must be an object')); return; } @@ -50,9 +52,9 @@ function electronPrompt(options, parentWindow) { minWidth: options_.minWidth, minHeight: options_.minHeight, resizable: options_.resizable, - minimizable: false, - fullscreenable: false, - maximizable: false, + minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop, + fullscreenable: options_.resizable, + maximizable: options_.resizable, parent: parentWindow, skipTaskbar: options_.skipTaskbar, alwaysOnTop: options_.alwaysOnTop, @@ -70,14 +72,11 @@ function electronPrompt(options, parentWindow) { promptWindow.setMenu(null); promptWindow.setMenuBarVisibility(options_.menuBarVisible); - const getOptionsListener = event => { - event.returnValue = JSON.stringify(options_); - }; - + //called on exit const cleanup = () => { - ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener); - ipcMain.removeListener('prompt-post-data:' + id, postDataListener); - ipcMain.removeListener('prompt-error:' + id, errorListener); + ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener); + ipcMain.removeListener("prompt-post-data:" + id, postDataListener); + ipcMain.removeListener("prompt-error:" + id, errorListener); if (promptWindow) { promptWindow.close(); @@ -85,6 +84,12 @@ function electronPrompt(options, parentWindow) { } }; + ///transfer options to front + const getOptionsListener = event => { + event.returnValue = JSON.stringify(options_); + }; + + //get input from front const postDataListener = (event, value) => { resolve(value); event.returnValue = null; @@ -92,34 +97,46 @@ function electronPrompt(options, parentWindow) { }; const unresponsiveListener = () => { - reject(new Error('Window was unresponsive')); + reject(new Error("Window was unresponsive")); cleanup(); }; + //get error from front const errorListener = (event, message) => { reject(new Error(message)); event.returnValue = null; cleanup(); }; - ipcMain.on('prompt-get-options:' + id, getOptionsListener); - ipcMain.on('prompt-post-data:' + id, postDataListener); - ipcMain.on('prompt-error:' + id, errorListener); - promptWindow.on('unresponsive', unresponsiveListener); + //attach listeners + ipcMain.on("prompt-get-options:" + id, getOptionsListener); + ipcMain.on("prompt-post-data:" + id, postDataListener); + ipcMain.on("prompt-error:" + id, errorListener); + promptWindow.on("unresponsive", unresponsiveListener); - promptWindow.on('closed', () => { + promptWindow.on("closed", () => { promptWindow = null; cleanup(); resolve(null); }); - const promptUrl = url.format({ - protocol: 'file', - slashes: true, - pathname: path.join(__dirname, 'page', 'prompt.html'), - hash: id + //should never happen + promptWindow.webContents.on("did-fail-load", ( + event, + errorCode, + errorDescription, + validatedURL, + ) => { + const log = { + error: "did-fail-load", + errorCode, + errorDescription, + validatedURL, + }; + reject(new Error("prompt.html did-fail-load, log:\n", + log.toString())); }); + //Finally, load prompt promptWindow.loadURL(promptUrl); }); } diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 754d0e74..b7a54120 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -1,126 +1,47 @@ -const fs = require('fs'); -const {ipcRenderer} = require('electron'); -const docReady = require('doc-ready'); +const fs = require("fs"); +const {ipcRenderer} = require("electron"); +const docReady = require("doc-ready"); let promptId = null; let promptOptions = null; -function promptError(error) { - if (error instanceof Error) { - error = error.message; - } - - ipcRenderer.sendSync('prompt-error:' + promptId, error); -} - -function promptCancel() { - ipcRenderer.sendSync('prompt-post-data:' + promptId, null); -} - -function promptSubmit() { - const dataElement = document.querySelector('#data'); - let data = null; - - if (promptOptions.type === 'input') { - data = dataElement.value; - } else if (promptOptions.type === 'select') { - if (promptOptions.selectMultiple) { - data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value')); - } else { - data = dataElement.value; - } - } - - ipcRenderer.sendSync('prompt-post-data:' + promptId, data); -} - -function promptCreateInput() { - const dataElement = document.createElement('input'); - dataElement.setAttribute('type', 'text'); - - if (promptOptions.value) { - dataElement.value = promptOptions.value; - } else { - dataElement.value = ''; - } - - if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') { - for (const k in promptOptions.inputAttrs) { - if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { - continue; - } - - dataElement.setAttribute(k, promptOptions.inputAttrs[k]); - } - } - - dataElement.addEventListener('keyup', event => { - if (event.key === 'Escape') { - promptCancel(); - } - }); - - dataElement.addEventListener('keypress', event => { - if (event.key === 'Enter') { - event.preventDefault(); - document.querySelector('#ok').click(); - } - }); - - return dataElement; -} - -function promptCreateSelect() { - const dataElement = document.createElement('select'); - let optionElement; - - for (const k in promptOptions.selectOptions) { - if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) { - continue; - } - - optionElement = document.createElement('option'); - optionElement.setAttribute('value', k); - optionElement.textContent = promptOptions.selectOptions[k]; - if (k === promptOptions.value) { - optionElement.setAttribute('selected', 'selected'); - } - - dataElement.append(optionElement); - } - - return dataElement; -} +docReady(promptRegister); +//start here function promptRegister() { - promptId = document.location.hash.replace('#', ''); + //get custom session id + promptId = document.location.hash.replace("#", ""); + //get options from back try { - promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId)); + promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId)); } catch (error) { return promptError(error); } + //set label if (promptOptions.useHtmlLabel) { - document.querySelector('#label').innerHTML = promptOptions.label; + document.querySelector("#label").innerHTML = promptOptions.label; } else { - document.querySelector('#label').textContent = promptOptions.label; + document.querySelector("#label").textContent = promptOptions.label; } + //set button label if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { - document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok; + document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok; } if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { - document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel; + document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel; } + //inject custom stylesheet from options if (promptOptions.customStylesheet) { try { const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); if (customStyleContent) { - const customStyle = document.createElement('style'); - customStyle.setAttribute('rel', 'stylesheet'); + const customStyle = document.createElement("style"); + customStyle.setAttribute("rel", "stylesheet"); customStyle.append(document.createTextNode(customStyleContent)); document.head.append(customStyle); } @@ -129,28 +50,31 @@ function promptRegister() { } } - document.querySelector('#form').addEventListener('submit', promptSubmit); - document.querySelector('#cancel').addEventListener('click', promptCancel); + //add button listeners + document.querySelector("#form").addEventListener("submit", promptSubmit); + document.querySelector("#cancel").addEventListener("click", promptCancel); - const dataContainerElement = document.querySelector('#data-container'); + //create input/select + const dataContainerElement = document.querySelector("#data-container"); let dataElement; - if (promptOptions.type === 'input') { + if (promptOptions.type === "input") { dataElement = promptCreateInput(); - } else if (promptOptions.type === 'select') { + } else if (promptOptions.type === "select") { dataElement = promptCreateSelect(); } else { return promptError(`Unhandled input type '${promptOptions.type}'`); } dataContainerElement.append(dataElement); - dataElement.setAttribute('id', 'data'); + dataElement.setAttribute("id", "data"); dataElement.focus(); - if (promptOptions.type === 'input') { + if (promptOptions.type === "input") { dataElement.select(); } + //load custom script from options if (promptOptions.customScript) { try { const customScript = require(promptOptions.customScript); @@ -161,10 +85,104 @@ function promptRegister() { } } -window.addEventListener('error', error => { +window.addEventListener("error", error => { if (promptId) { - promptError('An error has occured on the prompt window: \n' + error); + promptError("An error has occured on the prompt window: \n" + error); } }); -docReady(promptRegister); \ No newline at end of file +//send error to back +function promptError(error) { + if (error instanceof Error) { + error = error.message; + } + + ipcRenderer.sendSync("prompt-error:" + promptId, error); +} + +//send to back: input=null +function promptCancel() { + ipcRenderer.sendSync("prompt-post-data:" + promptId, null); +} + +//transfer input data to back +function promptSubmit() { + const dataElement = document.querySelector("#data"); + let data = null; + + if (promptOptions.type === "input") { + data = dataElement.value; + } else if (promptOptions.type === "select") { + data = promptOptions.selectMultiple ? + dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) : + dataElement.value; + } + + ipcRenderer.sendSync("prompt-post-data:" + promptId, data); +} + +//creates input box +function promptCreateInput() { + const dataElement = document.createElement("input"); + dataElement.setAttribute("type", "text"); + + if (promptOptions.value) { + dataElement.value = promptOptions.value; + } else { + dataElement.value = ""; + } + + //insert custom input attributes if in options + if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") { + for (const k in promptOptions.inputAttrs) { + if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { + continue; + } + + dataElement.setAttribute(k, promptOptions.inputAttrs[k]); + } + } + + //Cancel/Exit on 'Escape' + dataElement.addEventListener("keyup", event => { + if (event.key === "Escape") { + promptCancel(); + } + }); + + //Confrim on 'Enter' + dataElement.addEventListener("keypress", event => { + if (event.key === "Enter") { + event.preventDefault(); + document.querySelector("#ok").click(); + } + }); + + return dataElement; +} + +//create multiple select +function promptCreateSelect() { + const dataElement = document.createElement("select"); + let optionElement; + + for (const k in promptOptions.selectOptions) { + if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) { + continue; + } + + optionElement = document.createElement("option"); + optionElement.setAttribute("value", k); + optionElement.textContent = promptOptions.selectOptions[k]; + if (k === promptOptions.value) { + optionElement.setAttribute("selected", "selected"); + } + + dataElement.append(optionElement); + } + + return dataElement; +} + + + diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md new file mode 100644 index 00000000..6683aced --- /dev/null +++ b/providers/prompt/readme.md @@ -0,0 +1,79 @@ +# Prompt Documentation + +

prompt-preview

+ +## Usage +```js +prompt([options, parentBrowserWindow]).then(...).catch(...) +``` +Promise resolve returns input + +If user presses cancel/exit window, input = null; + +On error, Prompise reject returns custom error message +## Example + +```js +const prompt = require('./providers/prompt'); + +prompt({ + title: 'Prompt example', + label: 'URL:', + value: 'http://example.org', + inputAttrs: { + type: 'url' + }, + type: 'input' +}) +.then((r) => { + if(r === null) { + console.log('user cancelled'); + } else { + console.log('result', r); + } +}) +.catch(console.error); +``` + +### Options object (optional) + +| Key | Explanation | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. | +| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. | +| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. | +| value | (optional, string) The default value for the input field. Defaults to null. | +| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. | +| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' | +| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | +| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | +| width | (optional, integer) The width of the prompt window. Defaults to 370. | +| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. | +| height | (optional, integer) The height of the prompt window. Defaults to 130. | +| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. | +| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. | +| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false | +| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. | +| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. | +| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. | +| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. | +| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. | +| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. | +| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. | + +If not supplied, it uses the defaults listed in the table above. + +### parentBrowserWindow (optional) + +The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null. + +### customScript (optional) + +Create the script with the following template: + +```node +module.exports = () => { + // This function will be called as a preload script + // So you can use front features like `document.querySelector` +}; +``` From e6efddc63914a4ee46e8746c87ad7f7ebe1730b6 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 8 Apr 2021 16:54:46 +0300 Subject: [PATCH 037/118] add windows interactive notifications --- config/defaults.js | 3 +- package.json | 1 + plugins/notifications/back.js | 29 +++++---- plugins/notifications/interactive.js | 96 ++++++++++++++++++++++++++++ plugins/notifications/menu.js | 13 +++- plugins/notifications/utils.js | 54 +++++++++++++--- yarn.lock | 12 ++++ 7 files changed, 186 insertions(+), 22 deletions(-) create mode 100644 plugins/notifications/interactive.js diff --git a/config/defaults.js b/config/defaults.js index fb87e566..e90b36a5 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -44,7 +44,8 @@ const defaultConfig = { notifications: { enabled: false, urgency: "normal", - unpauseNotification: false + unpauseNotification: false, + interactive: true } }, }; diff --git a/package.json b/package.json index ce144c38..467217db 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "electron-updater": "^4.3.6", "filenamify": "^4.2.0", "node-fetch": "^2.6.1", + "node-notifier": "^9.0.1", "ytdl-core": "^4.4.5", "ytpl": "^2.0.5" }, diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index dedd9379..9e1b3fd1 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -1,18 +1,17 @@ const { Notification } = require("electron"); +const is = require("electron-is"); const getSongInfo = require("../../providers/song-info"); +const { notificationImage } = require("./utils"); + +const { setup, notifyInteractive } = require("./interactive") const notify = (info, options) => { - let notificationImage = "assets/youtube-music.png"; - - if (info.image) { - notificationImage = info.image.resize({ height: 256, width: 256 }); - } // Fill the notification with content const notification = { title: info.title || "Playing", body: info.artist, - icon: notificationImage, + icon: notificationImage(info), silent: true, urgency: options.urgency, }; @@ -25,6 +24,10 @@ const notify = (info, options) => { }; module.exports = (win, options) => { + //setup interactive notifications for windows + if (is.windows()) { + setup(win); + } const registerCallback = getSongInfo(win); let oldNotification; let oldURL = ""; @@ -39,13 +42,17 @@ module.exports = (win, options) => { } return; } - // If url isn't the same as last one - send notification + // If url isn"t the same as last one - send notification if (songInfo.url !== oldURL) { oldURL = songInfo.url; - // Close the old notification - oldNotification?.close(); - // This fixes a weird bug that would cause the notification to be updated instead of showing - setTimeout(()=>{ oldNotification = notify(songInfo, options) }, 10); + if (is.windows() && options.interactive) { + notifyInteractive(songInfo); + } else { + // Close the old notification + oldNotification?.close(); + // This fixes a weird bug that would cause the notification to be updated instead of showing + setTimeout(() => { oldNotification = notify(songInfo, options) }, 10); + } } }); }); diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js new file mode 100644 index 00000000..47b7c57c --- /dev/null +++ b/plugins/notifications/interactive.js @@ -0,0 +1,96 @@ +const is = require("electron-is"); +const { app } = require("electron"); +const { notificationImage, icons } = require("./utils"); +const getSongControls = require('../../providers/song-controls'); +const notifier = require("node-notifier"); + +const appID = "com.github.th-ch.youtube-music"; +const shortcutPath = `("Youtube Music" "${app.getPath("exe")}" "${appID}")`; + +//saving controls here avoid errors +let controls; + +//delete old notification +let toDelete; +function Delete() { + if (toDelete === undefined) { + return; + } + const removeNotif = Object.assign(toDelete, { + remove: toDelete.id + }) + notifier.notify(removeNotif) + + toDelete = undefined; +} + +//Setup on launch +module.exports.setup = (win) => { + //save controls + const { playPause, next, previous } = getSongControls(win); + controls = { playPause, next, previous }; + //setup global listeners + notifier.on("dismissed", () => { Delete(); }); + notifier.on("timeout", () => { Delete(); }); + //try installing shortcut + if (!is.dev()) { + notifier.notify({ + title: "installing shortcut", + id: 1337, + install: shortcutPath + }); + } + + //close all listeners on close + win.on("closed", () => { + notifier.removeAllListeners(); + }); +} + +//New notification +module.exports.notifyInteractive = function sendToaster(songInfo) { + Delete(); + //download image and get path + let imgSrc = notificationImage(songInfo, true); + toDelete = { + appID: !is.dev() ? appID : undefined, //(will break action buttons if not installed to start menu) + title: songInfo.title || "Playing", + message: songInfo.artist, + id: parseInt(Math.random() * 1000000, 10), + icon: imgSrc, + actions: [ + icons.previous, // Previous + songInfo.isPaused ? icons.play : icons.pause, + icons.next // Next + ], + sound: false, + }; + //send notification + notifier.notify( + toDelete, + (err, data) => { + // Will also wait until notification is closed. + if (err) { + console.log(`ERROR = ${err}\n DATA = ${data}`); + } + switch (data) { + case icons.previous.normalize(): + controls.previous(); + return; + case icons.next.normalize(): + controls.next(); + return; + case icons.play.normalize(): + controls.playPause(); + toDelete = undefined; // dont delete notification on play/pause + return; + case icons.pause.normalize(): + controls.playPause(); + songInfo.isPaused = true; + toDelete = undefined; // it gets deleted automatically + sendToaster(songInfo); + } + } + + ); +} diff --git a/plugins/notifications/menu.js b/plugins/notifications/menu.js index a61cac67..bc2eab67 100644 --- a/plugins/notifications/menu.js +++ b/plugins/notifications/menu.js @@ -1,4 +1,5 @@ -const {urgencyLevels, setUrgency, setUnpause} = require("./utils"); +const {urgencyLevels, setUrgency, setUnpause, setInteractive} = require("./utils"); +const is = require("electron-is"); module.exports = (win, options) => [ { @@ -15,5 +16,13 @@ module.exports = (win, options) => [ type: "checkbox", checked: options.unpauseNotification, click: (item) => setUnpause(options, item.checked) - } + }, + ...(is.windows() ? + [{ + label: "Interactive", + type: "checkbox", + checked: options.interactive, + click: (item) => setInteractive(options, item.checked) + }] : + []) ]; diff --git a/plugins/notifications/utils.js b/plugins/notifications/utils.js index c43ecb20..d48f8319 100644 --- a/plugins/notifications/utils.js +++ b/plugins/notifications/utils.js @@ -1,19 +1,57 @@ -const {setOptions} = require("../../config/plugins"); +const { setOptions } = require("../../config/plugins"); +const path = require("path"); +const { app } = require("electron"); +const icon = path.join(__dirname, "assets", "youtube-music.png"); +const fs = require("fs"); + +const tempIcon = path.join(app.getPath("userData"), "tempIcon.png"); module.exports.urgencyLevels = [ - {name: "Low", value: "low"}, - {name: "Normal", value: "normal"}, - {name: "High", value: "critical"}, + { name: "Low", value: "low" }, + { name: "Normal", value: "normal" }, + { name: "High", value: "critical" }, ]; module.exports.setUrgency = (options, level) => { - options.urgency = level - setOption(options) + options.urgency = level; + setOption(options); }; module.exports.setUnpause = (options, value) => { - options.unpauseNotification = value - setOption(options) + options.unpauseNotification = value; + setOption(options); +}; +module.exports.setInteractive = (options, value) => { + options.interactive = value; + setOption(options); +} + +module.exports.notificationImage = function (songInfo, url = false) { + //return local url + if (!!songInfo && url) { + try { + fs.writeFileSync(tempIcon, + songInfo.image + .resize({ height: 256, width: 256 }) + .toPNG() + ); + } catch (err) { + console.log(`Error downloading song icon:\n${err.toString()}`) + return icon; + } + return tempIcon; + } + //else: return image + return songInfo.image + ? songInfo.image.resize({ height: 256, width: 256 }) + : icon }; let setOption = options => { setOptions("notifications", options) }; + +module.exports.icons = { + play: "\u{1405}", // ᐅ + pause: "\u{2016}", // ‖ + next: "\u{1433}", // ᐳ + previous: "\u{1438}" // ᐸ +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index c969527e..188f3193 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6335,6 +6335,18 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" +node-notifier@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-9.0.1.tgz#cea837f4c5e733936c7b9005e6545cea825d1af4" + integrity sha512-fPNFIp2hF/Dq7qLDzSg4vZ0J4e9v60gJR+Qx7RbjbWqzPDdEqeVpEx5CFeDAELIl+A/woaaNn1fQ5nEVerMxJg== + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" + shellwords "^0.1.1" + uuid "^8.3.0" + which "^2.0.2" + noop-logger@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" From 30675e0567525c5161fa6f54f44d32157ade2f43 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 8 Apr 2021 18:56:13 +0300 Subject: [PATCH 038/118] remove appID because of bug: Button would not transmit event --- plugins/notifications/interactive.js | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 47b7c57c..b27f6207 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -1,13 +1,9 @@ const is = require("electron-is"); -const { app } = require("electron"); const { notificationImage, icons } = require("./utils"); const getSongControls = require('../../providers/song-controls'); const notifier = require("node-notifier"); -const appID = "com.github.th-ch.youtube-music"; -const shortcutPath = `("Youtube Music" "${app.getPath("exe")}" "${appID}")`; - -//saving controls here avoid errors +//store song controls let controls; //delete old notification @@ -32,16 +28,8 @@ module.exports.setup = (win) => { //setup global listeners notifier.on("dismissed", () => { Delete(); }); notifier.on("timeout", () => { Delete(); }); - //try installing shortcut - if (!is.dev()) { - notifier.notify({ - title: "installing shortcut", - id: 1337, - install: shortcutPath - }); - } - //close all listeners on close + //remove all listeners on close win.on("closed", () => { notifier.removeAllListeners(); }); @@ -53,7 +41,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { //download image and get path let imgSrc = notificationImage(songInfo, true); toDelete = { - appID: !is.dev() ? appID : undefined, //(will break action buttons if not installed to start menu) + //app id undefined - will break buttons title: songInfo.title || "Playing", message: songInfo.artist, id: parseInt(Math.random() * 1000000, 10), @@ -69,6 +57,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { notifier.notify( toDelete, (err, data) => { + console.log("clicked "+data); // Will also wait until notification is closed. if (err) { console.log(`ERROR = ${err}\n DATA = ${data}`); From d8dc4656e469fa6a4eaf99a714932a476a136c8b Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 01:08:22 +0300 Subject: [PATCH 039/118] stylecheck --- plugins/notifications/interactive.js | 2 -- plugins/notifications/menu.js | 2 +- plugins/notifications/utils.js | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index b27f6207..c41588ae 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -1,4 +1,3 @@ -const is = require("electron-is"); const { notificationImage, icons } = require("./utils"); const getSongControls = require('../../providers/song-controls'); const notifier = require("node-notifier"); @@ -57,7 +56,6 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { notifier.notify( toDelete, (err, data) => { - console.log("clicked "+data); // Will also wait until notification is closed. if (err) { console.log(`ERROR = ${err}\n DATA = ${data}`); diff --git a/plugins/notifications/menu.js b/plugins/notifications/menu.js index bc2eab67..53a79a63 100644 --- a/plugins/notifications/menu.js +++ b/plugins/notifications/menu.js @@ -1,4 +1,4 @@ -const {urgencyLevels, setUrgency, setUnpause, setInteractive} = require("./utils"); +const { urgencyLevels, setUrgency, setUnpause, setInteractive } = require("./utils"); const is = require("electron-is"); module.exports = (win, options) => [ diff --git a/plugins/notifications/utils.js b/plugins/notifications/utils.js index d48f8319..42c406d9 100644 --- a/plugins/notifications/utils.js +++ b/plugins/notifications/utils.js @@ -24,9 +24,9 @@ module.exports.setInteractive = (options, value) => { setOption(options); } -module.exports.notificationImage = function (songInfo, url = false) { - //return local url - if (!!songInfo && url) { +module.exports.notificationImage = function (songInfo, saveIcon = false) { + //return local path to temp icon + if (saveIcon && !!songInfo.image) { try { fs.writeFileSync(tempIcon, songInfo.image From ba6244780c0a566ae366c4a8f46a8703dc57d8c6 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 02:14:11 +0300 Subject: [PATCH 040/118] minify --- plugins/notifications/back.js | 9 +++--- plugins/notifications/interactive.js | 45 +++++++++++++--------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index 9e1b3fd1..31162320 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -3,7 +3,7 @@ const is = require("electron-is"); const getSongInfo = require("../../providers/song-info"); const { notificationImage } = require("./utils"); -const { setup, notifyInteractive } = require("./interactive") +const { setupInteractive, notifyInteractive } = require("./interactive") const notify = (info, options) => { @@ -24,9 +24,10 @@ const notify = (info, options) => { }; module.exports = (win, options) => { + const isInteractive = is.windows() && options.interactive; //setup interactive notifications for windows - if (is.windows()) { - setup(win); + if (isInteractive) { + setupInteractive(win); } const registerCallback = getSongInfo(win); let oldNotification; @@ -45,7 +46,7 @@ module.exports = (win, options) => { // If url isn"t the same as last one - send notification if (songInfo.url !== oldURL) { oldURL = songInfo.url; - if (is.windows() && options.interactive) { + if (isInteractive) { notifyInteractive(songInfo); } else { // Close the old notification diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index c41588ae..06999153 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -2,40 +2,29 @@ const { notificationImage, icons } = require("./utils"); const getSongControls = require('../../providers/song-controls'); const notifier = require("node-notifier"); -//store song controls +//store song controls reference on launch let controls; +module.exports.setupInteractive = (win) => { + //save controls + const { playPause, next, previous } = getSongControls(win); + controls = { playPause, next, previous }; +} //delete old notification let toDelete; function Delete() { - if (toDelete === undefined) { - return; + if (toDelete !== undefined) { + const removeNotif = Object.assign(toDelete, { + remove: toDelete.id + }) + notifier.notify(removeNotif) + + toDelete = undefined; } - const removeNotif = Object.assign(toDelete, { - remove: toDelete.id - }) - notifier.notify(removeNotif) - - toDelete = undefined; -} - -//Setup on launch -module.exports.setup = (win) => { - //save controls - const { playPause, next, previous } = getSongControls(win); - controls = { playPause, next, previous }; - //setup global listeners - notifier.on("dismissed", () => { Delete(); }); - notifier.on("timeout", () => { Delete(); }); - - //remove all listeners on close - win.on("closed", () => { - notifier.removeAllListeners(); - }); } //New notification -module.exports.notifyInteractive = function sendToaster(songInfo) { +module.exports.notifyInteractive = (songInfo) => { Delete(); //download image and get path let imgSrc = notificationImage(songInfo, true); @@ -61,6 +50,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { console.log(`ERROR = ${err}\n DATA = ${data}`); } switch (data) { + //buttons case icons.previous.normalize(): controls.previous(); return; @@ -76,6 +66,11 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { songInfo.isPaused = true; toDelete = undefined; // it gets deleted automatically sendToaster(songInfo); + return; + //Native datatype + case "dismissed": + case "timeout": + Delete(); } } From 80b12076406e5e06a219f5b7824f1f3821b54832 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 02:19:06 +0300 Subject: [PATCH 041/118] fix rare crash due to unfocus effect --- plugins/in-app-menu/front.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js index 3287dc5d..8ee1c9cf 100644 --- a/plugins/in-app-menu/front.js +++ b/plugins/in-app-menu/front.js @@ -6,6 +6,8 @@ module.exports = () => { const bar = new customTitlebar.Titlebar({ backgroundColor: customTitlebar.Color.fromHex("#050505"), itemBackgroundColor: customTitlebar.Color.fromHex("#121212"), + // !important - unfocus effect can sometimes cause crash as of v3.2.6 of custom-electron-titlebar + unfocusEffect: false }); bar.updateTitle(" "); document.title = "Youtube Music"; From 095196785a7ef2649014fa92fd1287d015ad886f Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 02:32:14 +0300 Subject: [PATCH 042/118] add note to notifications.interactive --- config/defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/defaults.js b/config/defaults.js index e90b36a5..f3cd7f04 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -45,7 +45,7 @@ const defaultConfig = { enabled: false, urgency: "normal", unpauseNotification: false, - interactive: true + interactive: true //has effect only on Windows 8+ } }, }; From 9c0a633677aced57ed1c365b93ba1eb63729b053 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 03:15:57 +0300 Subject: [PATCH 043/118] fix unPause option compatibility --- config/defaults.js | 2 +- plugins/notifications/back.js | 2 +- plugins/notifications/interactive.js | 24 +++++++++++++++++++----- plugins/notifications/utils.js | 2 +- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index f3cd7f04..57c001b1 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -45,7 +45,7 @@ const defaultConfig = { enabled: false, urgency: "normal", unpauseNotification: false, - interactive: true //has effect only on Windows 8+ + interactive: false //has effect only on Windows 8+ } }, }; diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index 31162320..38fbbbf8 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -27,7 +27,7 @@ module.exports = (win, options) => { const isInteractive = is.windows() && options.interactive; //setup interactive notifications for windows if (isInteractive) { - setupInteractive(win); + setupInteractive(win, options.unpauseNotification); } const registerCallback = getSongInfo(win); let oldNotification; diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 06999153..b7ff461a 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -4,10 +4,14 @@ const notifier = require("node-notifier"); //store song controls reference on launch let controls; -module.exports.setupInteractive = (win) => { - //save controls +let onPause; + +//Save controls and onPause option +module.exports.setupInteractive = (win, unpauseNotification) => { const { playPause, next, previous } = getSongControls(win); controls = { playPause, next, previous }; + + onPause = unpauseNotification; } //delete old notification @@ -24,10 +28,13 @@ function Delete() { } //New notification -module.exports.notifyInteractive = (songInfo) => { +module.exports.notifyInteractive = function sendToaster(songInfo) { + console.log("called toaster"); Delete(); + console.log("deleted"); //download image and get path let imgSrc = notificationImage(songInfo, true); + console.log("got image"); toDelete = { //app id undefined - will break buttons title: songInfo.title || "Playing", @@ -41,6 +48,7 @@ module.exports.notifyInteractive = (songInfo) => { ], sound: false, }; + console.log("sending notification"); //send notification notifier.notify( toDelete, @@ -59,12 +67,18 @@ module.exports.notifyInteractive = (songInfo) => { return; case icons.play.normalize(): controls.playPause(); - toDelete = undefined; // dont delete notification on play/pause + // dont delete notification on play/pause + toDelete = undefined; + //manually send notification if not sending automatically + if (!onPause) { + songInfo.isPaused = false; + sendToaster(songInfo); + } return; case icons.pause.normalize(): controls.playPause(); songInfo.isPaused = true; - toDelete = undefined; // it gets deleted automatically + toDelete = undefined; sendToaster(songInfo); return; //Native datatype diff --git a/plugins/notifications/utils.js b/plugins/notifications/utils.js index 42c406d9..17b96091 100644 --- a/plugins/notifications/utils.js +++ b/plugins/notifications/utils.js @@ -1,9 +1,9 @@ const { setOptions } = require("../../config/plugins"); const path = require("path"); const { app } = require("electron"); -const icon = path.join(__dirname, "assets", "youtube-music.png"); const fs = require("fs"); +const icon = "assets/youtube-music.png"; const tempIcon = path.join(app.getPath("userData"), "tempIcon.png"); module.exports.urgencyLevels = [ From 18f041f1c63809fb06b7142e82cdea0aaab9409b Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 03:26:46 +0300 Subject: [PATCH 044/118] clarify button purpose --- plugins/notifications/interactive.js | 12 ++++-------- plugins/notifications/menu.js | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index b7ff461a..879c0613 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -29,12 +29,9 @@ function Delete() { //New notification module.exports.notifyInteractive = function sendToaster(songInfo) { - console.log("called toaster"); Delete(); - console.log("deleted"); //download image and get path let imgSrc = notificationImage(songInfo, true); - console.log("got image"); toDelete = { //app id undefined - will break buttons title: songInfo.title || "Playing", @@ -42,20 +39,19 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { id: parseInt(Math.random() * 1000000, 10), icon: imgSrc, actions: [ - icons.previous, // Previous + icons.previous, songInfo.isPaused ? icons.play : icons.pause, - icons.next // Next + icons.next ], sound: false, }; - console.log("sending notification"); //send notification notifier.notify( toDelete, (err, data) => { // Will also wait until notification is closed. if (err) { - console.log(`ERROR = ${err}\n DATA = ${data}`); + console.log(`ERROR = ${err.toString()}\n DATA = ${data}`); } switch (data) { //buttons @@ -68,7 +64,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { case icons.play.normalize(): controls.playPause(); // dont delete notification on play/pause - toDelete = undefined; + toDelete = undefined; //manually send notification if not sending automatically if (!onPause) { songInfo.isPaused = false; diff --git a/plugins/notifications/menu.js b/plugins/notifications/menu.js index 53a79a63..ebc1f718 100644 --- a/plugins/notifications/menu.js +++ b/plugins/notifications/menu.js @@ -19,7 +19,7 @@ module.exports = (win, options) => [ }, ...(is.windows() ? [{ - label: "Interactive", + label: "Interactive Notifications", type: "checkbox", checked: options.interactive, click: (item) => setInteractive(options, item.checked) From e6d77c165e0103fb12fb3148dde472373bc55517 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 18:39:57 +0300 Subject: [PATCH 045/118] Center Icon on ALL notifications Delete notification on windowclosed Refactor notifications.utils.setOption --- plugins/notifications/interactive.js | 4 +++ plugins/notifications/menu.js | 8 ++--- plugins/notifications/utils.js | 49 ++++++++++++++-------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 879c0613..d506463a 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -12,6 +12,10 @@ module.exports.setupInteractive = (win, unpauseNotification) => { controls = { playPause, next, previous }; onPause = unpauseNotification; + + win.webContents.on("closed", () => { + Delete() + }); } //delete old notification diff --git a/plugins/notifications/menu.js b/plugins/notifications/menu.js index ebc1f718..bfb8c809 100644 --- a/plugins/notifications/menu.js +++ b/plugins/notifications/menu.js @@ -1,4 +1,4 @@ -const { urgencyLevels, setUrgency, setUnpause, setInteractive } = require("./utils"); +const { urgencyLevels, setOption } = require("./utils"); const is = require("electron-is"); module.exports = (win, options) => [ @@ -8,21 +8,21 @@ module.exports = (win, options) => [ label: level.name, type: "radio", checked: options.urgency === level.value, - click: () => setUrgency(options, level.value) + click: () => setOption(options, "urgency", level.value) })), }, { label: "Show notification on unpause", type: "checkbox", checked: options.unpauseNotification, - click: (item) => setUnpause(options, item.checked) + click: (item) => setOption(options, "unpauseNotification", item.checked) }, ...(is.windows() ? [{ label: "Interactive Notifications", type: "checkbox", checked: options.interactive, - click: (item) => setInteractive(options, item.checked) + click: (item) => setOption(options, "interactive", item.checked) }] : []) ]; diff --git a/plugins/notifications/utils.js b/plugins/notifications/utils.js index 17b96091..34c73a77 100644 --- a/plugins/notifications/utils.js +++ b/plugins/notifications/utils.js @@ -6,52 +6,51 @@ 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.setUrgency = (options, level) => { - options.urgency = level; - setOption(options); -}; -module.exports.setUnpause = (options, value) => { - options.unpauseNotification = value; - setOption(options); -}; -module.exports.setInteractive = (options, value) => { - options.interactive = value; - setOption(options); -} module.exports.notificationImage = function (songInfo, saveIcon = false) { //return local path to temp icon if (saveIcon && !!songInfo.image) { try { fs.writeFileSync(tempIcon, - songInfo.image - .resize({ height: 256, width: 256 }) + centerNativeImage(songInfo.image) .toPNG() ); } catch (err) { - console.log(`Error downloading song icon:\n${err.toString()}`) + console.log(`Error writing song icon to disk:\n${err.toString()}`) return icon; } return tempIcon; } //else: return image return songInfo.image - ? songInfo.image.resize({ height: 256, width: 256 }) + ? centerNativeImage(songInfo.image) : icon }; -let setOption = options => { - setOptions("notifications", options) -}; +function centerNativeImage(nativeImage) { + const tempImage = nativeImage.resize({ height: 256 }); + const margin = Math.max((tempImage.getSize().width - 256), 0); -module.exports.icons = { - play: "\u{1405}", // ᐅ - pause: "\u{2016}", // ‖ - next: "\u{1433}", // ᐳ - previous: "\u{1438}" // ᐸ -} \ No newline at end of file + return tempImage.crop({ + x: Math.round(margin / 2), + y: 0, + width: 256, height: 256 + }) +} From 46ac0a1ed3df9d58538ff52b7722c44f17b0770b Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 19:10:20 +0300 Subject: [PATCH 046/118] change notification priority to show only on linux --- plugins/notifications/menu.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/notifications/menu.js b/plugins/notifications/menu.js index bfb8c809..3f239909 100644 --- a/plugins/notifications/menu.js +++ b/plugins/notifications/menu.js @@ -2,21 +2,17 @@ const { urgencyLevels, setOption } = require("./utils"); const is = require("electron-is"); module.exports = (win, options) => [ - { - label: "Notification Priority", - submenu: urgencyLevels.map(level => ({ - label: level.name, - type: "radio", - checked: options.urgency === level.value, - click: () => setOption(options, "urgency", level.value) - })), - }, - { - label: "Show notification on unpause", - type: "checkbox", - checked: options.unpauseNotification, - click: (item) => setOption(options, "unpauseNotification", item.checked) - }, + ...(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", @@ -24,5 +20,11 @@ module.exports = (win, options) => [ 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) + }, ]; From 3d41d04818ef355cd912e4e6ec7adad081854733 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 22:28:55 +0300 Subject: [PATCH 047/118] Revert "fix rare crash due to unfocus effect" This reverts commit 80b12076406e5e06a219f5b7824f1f3821b54832. --- plugins/in-app-menu/front.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js index 8ee1c9cf..3287dc5d 100644 --- a/plugins/in-app-menu/front.js +++ b/plugins/in-app-menu/front.js @@ -6,8 +6,6 @@ module.exports = () => { const bar = new customTitlebar.Titlebar({ backgroundColor: customTitlebar.Color.fromHex("#050505"), itemBackgroundColor: customTitlebar.Color.fromHex("#121212"), - // !important - unfocus effect can sometimes cause crash as of v3.2.6 of custom-electron-titlebar - unfocusEffect: false }); bar.updateTitle(" "); document.title = "Youtube Music"; From 09d9f72db289aff51c20fd83538fbb40b3ee652c Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 10 Apr 2021 02:51:38 +0300 Subject: [PATCH 048/118] add unresponsive listener --- index.js | 44 ++++++++++++++++++++----- plugins/in-app-menu/back.js | 10 +----- preload.js | 2 +- providers/{logger.js => frontLogger.js} | 2 +- 4 files changed, 39 insertions(+), 19 deletions(-) rename providers/{logger.js => frontLogger.js} (87%) diff --git a/index.js b/index.js index 7fd88754..addd98ed 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ const path = require("path"); const electron = require("electron"); +const { dialog } = require("electron"); const is = require("electron-is"); const unhandled = require("electron-unhandled"); const { autoUpdater } = require("electron-updater"); @@ -144,7 +145,11 @@ function createMainWindow() { }); } }); - + + win.webContents.on("render-process-gone", (event, webContents, details) => { + showUnresponsiveDialog(win, details); + }); + win.once("ready-to-show", () => { if (config.get("options.appVisible")) { win.show(); @@ -154,13 +159,7 @@ function createMainWindow() { return win; } -let createdWindow = false; -app.on("browser-window-created", (event, win) => { - //Ensures listeners are registered only once - if (createdWindow) { - return; - } - createdWindow = true; +app.once("browser-window-created", (event, win) => { loadPlugins(win); win.webContents.on("did-fail-load", ( @@ -325,3 +324,32 @@ app.on("ready", () => { }); } }); + +function showUnresponsiveDialog(win, details) { + if (!!details) { + console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t")) + } + dialog.showMessageBox(win, { + type: "error", + title: "Window Unresponsive", + message: "The Application is Unresponsive", + details: "We are sorry for the inconveniance! please choose what to do with the application:", + buttons: ["Wait", "Relaunch", "Quit"], + cancelId: 0 + }).then( response => { + switch (response) { + case 1: //if relaunch - relaunch+exit + app.relaunch(); + case 2: + app.exit(); + break; + case 0: + default: + return; + //maybe set a timer and afterwards check responsivness and call function again if failed + } + }); +} + +module.exports.aDialog = showUnresponsiveDialog; + diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 938c5475..8365ac8b 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -7,8 +7,6 @@ const config = require("../../config"); const { setApplicationMenu } = require("../../menu"); const { injectCSS } = require("../utils"); -//check that menu doesn't get created twice -let calledReadyToShow = false; //tracks menu visibility let visible = true; // win hook for fixing menu @@ -30,13 +28,7 @@ module.exports = (winImport) => { // css for custom scrollbar + disable drag area(was causing bugs) injectCSS(win.webContents, path.join(__dirname, "style.css")); - win.on("ready-to-show", () => { - // (apparently ready-to-show is called twice) - if (calledReadyToShow) { - return; - } - - calledReadyToShow = true; + win.once("ready-to-show", () => { setApplicationMenu(win); diff --git a/preload.js b/preload.js index f25dd6b7..5fcb2e07 100644 --- a/preload.js +++ b/preload.js @@ -34,7 +34,7 @@ document.addEventListener("DOMContentLoaded", () => { fileExists(songInfoProviderPath, require(songInfoProviderPath)); // inject front logger - const loggerPath = path.join(__dirname, "providers", "logger.js") + const loggerPath = path.join(__dirname, "providers", "frontLogger.js") fileExists(loggerPath, require(loggerPath)); // Add action for reloading diff --git a/providers/logger.js b/providers/frontLogger.js similarity index 87% rename from providers/logger.js rename to providers/frontLogger.js index 730a3dfa..210e3ff8 100644 --- a/providers/logger.js +++ b/providers/frontLogger.js @@ -3,7 +3,7 @@ const { ipcRenderer } = require("electron"); function logToString(log) { let string = (typeof log === "string") ? log : log.toString(); if (!string || string.includes("[object Object]")) { - string = JSON.stringify(log); + string = JSON.stringify(log, null, "\t"); } return string; } From 193c3823b677042d2a3198d6b2a4849288195842 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 22:44:02 +0300 Subject: [PATCH 049/118] remove downloads-folder and use electron instead --- package.json | 1 - plugins/downloader/utils.js | 4 +- yarn.lock | 195 ++---------------------------------- 3 files changed, 8 insertions(+), 192 deletions(-) diff --git a/package.json b/package.json index ce144c38..eeed056f 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "browser-id3-writer": "^4.4.0", "custom-electron-titlebar": "^3.2.6", "discord-rpc": "^3.2.0", - "downloads-folder": "^3.0.1", "electron-debug": "^3.2.0", "electron-is": "^3.0.0", "electron-localshortcut": "^3.2.1", diff --git a/plugins/downloader/utils.js b/plugins/downloader/utils.js index 3e0727cb..0eab78c5 100644 --- a/plugins/downloader/utils.js +++ b/plugins/downloader/utils.js @@ -1,4 +1,4 @@ -const downloadsFolder = require("downloads-folder"); +const { app } = require("electron"); -module.exports.getFolder = (customFolder) => customFolder || downloadsFolder(); +module.exports.getFolder = (customFolder) => customFolder || app.getPath("downloads"); module.exports.defaultMenuDownloadLabel = "Download playlist"; diff --git a/yarn.lock b/yarn.lock index c969527e..d281cf6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1396,11 +1396,6 @@ ansi-regex@^2.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -1484,11 +1479,6 @@ app-builder-lib@22.9.1: semver "^7.3.2" temp-file "^3.3.7" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - archiver-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" @@ -1518,14 +1508,6 @@ archiver@^5.0.0: tar-stream "^2.1.4" zip-stream "^4.0.4" -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2464,11 +2446,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2715,13 +2692,6 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -2807,11 +2777,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - des.js@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" @@ -2820,11 +2785,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -2964,13 +2924,6 @@ dotenv@^8.2.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== -downloads-folder@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/downloads-folder/-/downloads-folder-3.0.1.tgz#ecb8c0b7aa342d9b2d7eb34de598b8324f6690f1" - integrity sha512-d3JQ+cdTO8b6yXA/Mae4KpuqKldP+QWBCWpC2oELfOIzXDf07qbGlF3Ool2aaQkahp1vrGG0ko5pRaXZvDX4nw== - optionalDependencies: - registry-js "^1.9.0" - duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -3694,11 +3647,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - expect@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" @@ -4045,20 +3993,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - gensync@^1.0.0-beta.1: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -4142,11 +4076,6 @@ gifwrap@^0.9.2: image-q "^1.1.1" omggif "^1.0.10" -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -4369,11 +4298,6 @@ has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -6137,11 +6061,6 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" @@ -6195,7 +6114,7 @@ minimist@1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -6208,7 +6127,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: +mkdirp-classic@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== @@ -6235,11 +6154,6 @@ multimap@^1.1.0: resolved "https://registry.yarnpkg.com/multimap/-/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8" integrity sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw== -nan@^2.14.1: - version "2.14.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" - integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -6257,11 +6171,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -napi-build-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" - integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -6272,13 +6181,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-abi@^2.7.0: - version "2.19.3" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d" - integrity sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg== - dependencies: - semver "^5.4.1" - node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -6335,11 +6237,6 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6399,16 +6296,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npmlog@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -6429,7 +6316,7 @@ obj-props@^1.0.0: resolved "https://registry.yarnpkg.com/obj-props/-/obj-props-1.3.0.tgz#8884ab21c8d8496c4a7f696c78bf82289c51680b" integrity sha512-k2Xkjx5wn6eC3537SWAXHzB6lkI81kS+icMKMkh4nG3w7shWG6MaWOBrNvhWVOszrtL5uxdfymQQfPUxwY+2eg== -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -6957,27 +6844,6 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -prebuild-install@^5.3.5: - version "5.3.6" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291" - integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -7168,7 +7034,7 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@^1.2.7, rc@^1.2.8: +rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -7247,7 +7113,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -7314,14 +7180,6 @@ registry-auth-token@^4.0.0: dependencies: rc "^1.2.8" -registry-js@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/registry-js/-/registry-js-1.13.0.tgz#8c25c83383aad53a295a47f1ac38df6bee0b19c9" - integrity sha512-yFwrYjxVaEopLEXyP5ok7MNKxbi+dKBDLcmDGOO3gb2hISlwBizaQkr0K94xNZn3ovuBMYnTf+D9v+jowmMEng== - dependencies: - nan "^2.14.1" - prebuild-install "^5.3.5" - registry-url@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" @@ -7639,7 +7497,7 @@ serialize-error@^8.0.0: dependencies: type-fest "^0.20.2" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -7706,20 +7564,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -7957,14 +7801,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -8020,13 +7856,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -8792,11 +8621,6 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - which@^1.2.10, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -8811,13 +8635,6 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" From 9f2362d34698338c93e2d06125eb2533393060f8 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 23:15:39 +0300 Subject: [PATCH 050/118] update dependecies --- package.json | 16 +- yarn.lock | 1053 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 697 insertions(+), 372 deletions(-) diff --git a/package.json b/package.json index eeed056f..eb6eeadd 100644 --- a/package.json +++ b/package.json @@ -62,10 +62,10 @@ "npm": "Please use yarn and not npm" }, "dependencies": { - "@cliqz/adblocker-electron": "^1.20.1", + "@cliqz/adblocker-electron": "^1.20.4", "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", - "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", + "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.9.0", "async-mutex": "^0.3.1", "browser-id3-writer": "^4.4.0", "custom-electron-titlebar": "^3.2.6", @@ -73,24 +73,24 @@ "electron-debug": "^3.2.0", "electron-is": "^3.0.0", "electron-localshortcut": "^3.2.1", - "electron-store": "^7.0.2", + "electron-store": "^7.0.3", "electron-unhandled": "^3.0.2", - "electron-updater": "^4.3.6", + "electron-updater": "^4.3.8", "filenamify": "^4.2.0", "node-fetch": "^2.6.1", - "ytdl-core": "^4.4.5", + "ytdl-core": "^4.5.0", "ytpl": "^2.0.5" }, "devDependencies": { - "electron": "^11.2.3", - "electron-builder": "^22.9.1", + "electron": "^11.4.2", + "electron-builder": "^22.10.5", "electron-devtools-installer": "^3.1.1", "electron-icon-maker": "0.0.5", "get-port": "^5.1.1", "jest": "^26.6.3", "rimraf": "^3.0.2", "spectron": "^13.0.0", - "xo": "^0.37.1" + "xo": "^0.38.2" }, "resolutions": { "yargs-parser": "18.1.3" diff --git a/yarn.lock b/yarn.lock index d281cf6c..ede3d065 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,13 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" @@ -14,6 +21,11 @@ dependencies: "@babel/highlight" "^7.12.13" +"@babel/compat-data@^7.13.12": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" + integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== + "@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.13.tgz#b73a87a3a3e7d142a66248bf6ad88b9ceb093425" @@ -35,6 +47,36 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.12.16": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.15.tgz#a6d40917df027487b54312202a06812c4f7792d0" + integrity sha512-6GXmNYeNjS2Uz+uls5jalOemgIhnTMeaXo+yBUA72kC2uX/8VW6XyhVIo2L8/q0goKQA3EVKx0KOQpVKSeWadQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.13" + "@babel/helper-module-transforms" "^7.13.14" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.15" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.15" + "@babel/types" "^7.13.14" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/eslint-parser@^7.12.16": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.13.14.tgz#f80fd23bdd839537221914cb5d17720a5ea6ba3a" + integrity sha512-I0HweR36D73Ibn/FfrRDMKlMqJHFwidIUgYdMpH+aXYuQC+waq59YaJ6t9e9N36axJ82v1jR041wwqDrDXEwRA== + dependencies: + eslint-scope "^5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" + "@babel/generator@^7.12.13": version "7.12.15" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" @@ -44,6 +86,25 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.13.9": + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== + dependencies: + "@babel/types" "^7.13.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-compilation-targets@^7.13.13": + version "7.13.13" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz#2b2972a0926474853f41e4adbc69338f520600e5" + integrity sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ== + dependencies: + "@babel/compat-data" "^7.13.12" + "@babel/helper-validator-option" "^7.12.17" + browserslist "^4.14.5" + semver "^6.3.0" + "@babel/helper-function-name@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" @@ -67,6 +128,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-member-expression-to-functions@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" + integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== + dependencies: + "@babel/types" "^7.13.12" + "@babel/helper-module-imports@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" @@ -74,6 +142,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== + dependencies: + "@babel/types" "^7.13.12" + "@babel/helper-module-transforms@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz#01afb052dcad2044289b7b20beb3fa8bd0265bea" @@ -89,6 +164,20 @@ "@babel/types" "^7.12.13" lodash "^4.17.19" +"@babel/helper-module-transforms@^7.13.14": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef" + integrity sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g== + dependencies: + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.12.11" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.13" + "@babel/types" "^7.13.14" + "@babel/helper-optimise-call-expression@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" @@ -111,6 +200,16 @@ "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" +"@babel/helper-replace-supers@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" + integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.13.12" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.12" + "@babel/helper-simple-access@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz#8478bcc5cacf6aa1672b251c1d2dde5ccd61a6c4" @@ -118,6 +217,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-simple-access@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" + integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== + dependencies: + "@babel/types" "^7.13.12" + "@babel/helper-split-export-declaration@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" @@ -130,6 +236,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + "@babel/helpers@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.13.tgz#3c75e993632e4dadc0274eae219c73eb7645ba47" @@ -139,6 +250,24 @@ "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" +"@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== + dependencies: + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + +"@babel/highlight@^7.10.4": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" + integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/highlight@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" @@ -148,11 +277,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.7.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13": version "7.12.15" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== +"@babel/parser@^7.13.15": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8" + integrity sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ== + "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -253,7 +387,7 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.13", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== @@ -268,7 +402,21 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.12.13", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.15.tgz#c38bf7679334ddd4028e8e1f7b3aa5019f0dada7" + integrity sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.15" + "@babel/types" "^7.13.14" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.12.13", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== @@ -277,46 +425,55 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.14": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d" + integrity sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cliqz/adblocker-content@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.3.tgz#198c8719cd62ef3c67a5c98e7a54336b7812ed86" - integrity sha512-aCBTiIiNgVbmDIQyUcsn0j3n+umvs0DuVlL6dccPE3qfeFxT4whUvMwjxUS2/dIBfJK9A1LywmvVke2eSPw9wg== +"@cliqz/adblocker-content@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.4.tgz#68c0c628acd6da49bb5a6ad9ee0cb540a8d50acd" + integrity sha512-Cp6M6MERCsLwklX6lAmrgOxom0pr4DjxmUGLcmM9MDACOIzk/m7ya1e82bXzEWAU1Jni2Bp91xUUWxg+DLWJgQ== dependencies: - "@cliqz/adblocker-extended-selectors" "^1.20.3" + "@cliqz/adblocker-extended-selectors" "^1.20.4" -"@cliqz/adblocker-electron-preload@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.3.tgz#17dff446ad742cb6e68a4572e7a75cff1fa33f95" - integrity sha512-fWAFEGj+F0VOUKZd2FqWLuguXmGzkRQz5wTCqasvndX4HSe0P8Pd2666pWK9RJW1dLJE7U61mQfTbYqlUFVTMA== +"@cliqz/adblocker-electron-preload@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.4.tgz#b7d6606dfc24e7b3f80109cc6820bd203faaf26e" + integrity sha512-tIEgFJJhEDTYrSUzAL+wbw+BBVwCtuFtckA/scka990DGlXsEmkJ7HxNXvUPwhOQiV4YUwN5bsqxCDA8VDTZNw== dependencies: - "@cliqz/adblocker-content" "^1.20.3" + "@cliqz/adblocker-content" "^1.20.4" -"@cliqz/adblocker-electron@^1.20.1": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.3.tgz#f2b4bf5dddf90f64251c46f89238526dc0037384" - integrity sha512-ZcEl3W7R/aoUA0IPIMtvdn7gVE6O9+rDQ9OllIH/s/gVeElXZsgPEtpPMSuoJWbi9d2mlr8yo3UFvkV3u7c4gw== +"@cliqz/adblocker-electron@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.4.tgz#6d7de52cff013ef3cd0f4a7850ebfc31f6240a46" + integrity sha512-HaHexPnJL1BBvloXuqmSh8WtpPKYHyZ+o6f+9SciySN4dJAX9BIGTk9D/V6eJWLmy6+wY7/Bpcn2Q4nrYXsqBw== dependencies: - "@cliqz/adblocker" "^1.20.3" - "@cliqz/adblocker-electron-preload" "^1.20.3" + "@cliqz/adblocker" "^1.20.4" + "@cliqz/adblocker-electron-preload" "^1.20.4" tldts-experimental "^5.6.21" -"@cliqz/adblocker-extended-selectors@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.3.tgz#a817915948ec4e64c8b878a80a71d911ea0412c8" - integrity sha512-Xsrqg4qgpNVx80UJrAz/nS8jcbgCTIGvir0MrjoXrw0GheqRxsgE540XXP9JA7QlifLNVEOO44DpHvhUmISkQw== +"@cliqz/adblocker-extended-selectors@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.4.tgz#6f5ab8251a0d40cacf3703f5621025e0d85d6348" + integrity sha512-VBP8iv1IdYpwQ0hbbeiXCSW7ppzK05dbPM4DyeCb54mB0CjWj/pMQwEvjMZKLWTkEyPd26oMqnxNQz1UgGaZag== -"@cliqz/adblocker@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.3.tgz#4e8d03ed03c476f7b4388d25f910b1b9e0b15cc9" - integrity sha512-Dqj8fJ399kFsFQ53uW0ajA5jH5VJ5ppawOjtoV2s+7NILj1ydvw40jTrr3l/ObMvxaAGaDUj2Euo4beg3/EtRQ== +"@cliqz/adblocker@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.4.tgz#63f75456b6d63f66dc73b9ac2971ed073bf26722" + integrity sha512-ylwc4fScwgDjh9mKAvBQ+oCNyZWncrPakU17KbMtq+l82LkzJ0ND0wififpeq+nI9JBiQosW+eus5R08THpwCQ== dependencies: - "@cliqz/adblocker-content" "^1.20.3" - "@cliqz/adblocker-extended-selectors" "^1.20.3" + "@cliqz/adblocker-content" "^1.20.4" + "@cliqz/adblocker-extended-selectors" "^1.20.4" "@remusao/guess-url-type" "^1.1.2" "@remusao/small" "^1.1.2" "@remusao/smaz" "^1.7.1" @@ -356,10 +513,21 @@ global-agent "^2.0.2" global-tunnel-ng "^2.7.1" -"@eslint/eslintrc@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" - integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== +"@electron/universal@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.0.4.tgz#231ac246c39d45b80e159bd21c3f9027dcaa10f5" + integrity sha512-ajZoumi4XwqwmZe8YVhu4XGkZBCPyWZsVCQONPTIe9TUlleSN+dic3YpXlaWcilx/HOzTdldTKtabNTeI0gDoA== + dependencies: + "@malept/cross-spawn-promise" "^1.1.0" + asar "^3.0.3" + debug "^4.3.1" + dir-compare "^2.4.0" + fs-extra "^9.0.1" + +"@eslint/eslintrc@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547" + integrity sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -368,7 +536,6 @@ ignore "^4.0.6" import-fresh "^3.2.1" js-yaml "^3.13.1" - lodash "^4.17.20" minimatch "^3.0.4" strip-json-comments "^3.1.1" @@ -864,6 +1031,13 @@ "@babel/runtime" "^7.7.2" regenerator-runtime "^0.13.3" +"@malept/cross-spawn-promise@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" + integrity sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ== + dependencies: + cross-spawn "^7.0.1" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1044,10 +1218,10 @@ resolved "https://registry.yarnpkg.com/@types/firefox-webext-browser/-/firefox-webext-browser-82.0.0.tgz#4d0f5cfebd7321d2cbf0ccfb6032570f0138b958" integrity sha512-zKHePkjMx42KIUUZCPcUiyu1tpfQXH9VR4iDYfns3HvmKVJzt/TAFT+DFVroos8BI9RH78YgF3Hi/wlC6R6cKA== -"@types/fs-extra@^9.0.1": - version "9.0.6" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.6.tgz#488e56b77299899a608b8269719c1d133027a6ab" - integrity sha512-ecNRHw4clCkowNOBJH1e77nvbPxHYnWIXMv1IAoG/9+MYGkgoyr3Ppxr7XYFNL41V422EDhyV4/4SSK8L2mlig== +"@types/fs-extra@^9.0.7": + version "9.0.10" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.10.tgz#8023a72e3d06cf54929ea47ec7634e47f33f4046" + integrity sha512-O9T2LLkRDiTlalOBdjEkcnT0MRdT2+wglCl7pJUJ3mkWkR8hX4K+5bg2raQNJcLv4V8zGuTXe7Ud3wSqkTyuyQ== dependencies: "@types/node" "*" @@ -1142,6 +1316,14 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/plist@^3.0.1": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/plist/-/plist-3.0.2.tgz#61b3727bba0f5c462fe333542534a0c3e19ccb01" + integrity sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw== + dependencies: + "@types/node" "*" + xmlbuilder ">=11.0.1" + "@types/prettier@^2.0.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.0.tgz#a4e8205a4955690eef712a6d0394a1d2e121e721" @@ -1178,6 +1360,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== +"@types/verror@^1.10.3": + version "1.10.4" + resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.4.tgz#805c0612b3a0c124cf99f517364142946b74ba3b" + integrity sha512-OjJdqx6QlbyZw9LShPwRW+Kmiegeg3eWNI41MQQKaG3vjdU2L9SRElntM51HmHBY1cu7izxQJ1lMYioQh3XMBg== + "@types/which@^1.3.2": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf" @@ -1188,7 +1375,7 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== -"@types/yargs@^15.0.0", "@types/yargs@^15.0.5": +"@types/yargs@^15.0.0", "@types/yargs@^15.0.13": version "15.0.13" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.13.tgz#34f7fec8b389d7f3c1fd08026a5763e072d3c6dc" integrity sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ== @@ -1202,13 +1389,13 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^4.11.1": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.0.tgz#13a5a07cf30d0d5781e43480aa2a8d38d308b084" - integrity sha512-DJgdGZW+8CFUTz5C/dnn4ONcUm2h2T0itWD85Ob5/V27Ndie8hUoX5HKyGssvR8sUMkAIlUc/AMK67Lqa3kBIQ== +"@typescript-eslint/eslint-plugin@^4.15.1": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.21.0.tgz#3fce2bfa76d95c00ac4f33dff369cb593aab8878" + integrity sha512-FPUyCPKZbVGexmbCFI3EQHzCZdy2/5f+jv6k2EDljGdXSRc0cKvbndd2nHZkSLqCNOPk0jB6lGzwIkglXcYVsQ== dependencies: - "@typescript-eslint/experimental-utils" "4.15.0" - "@typescript-eslint/scope-manager" "4.15.0" + "@typescript-eslint/experimental-utils" "4.21.0" + "@typescript-eslint/scope-manager" "4.21.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -1216,60 +1403,60 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.0.tgz#b87c36410a9b23f637689427be85007a2ec1a9c6" - integrity sha512-V4vaDWvxA2zgesg4KPgEGiomWEBpJXvY4ZX34Y3qxK8LUm5I87L+qGIOTd9tHZOARXNRt9pLbblSKiYBlGMawg== +"@typescript-eslint/experimental-utils@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.21.0.tgz#0b0bb7c15d379140a660c003bdbafa71ae9134b6" + integrity sha512-cEbgosW/tUFvKmkg3cU7LBoZhvUs+ZPVM9alb25XvR0dal4qHL3SiUqHNrzoWSxaXA9gsifrYrS1xdDV6w/gIA== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.15.0" - "@typescript-eslint/types" "4.15.0" - "@typescript-eslint/typescript-estree" "4.15.0" + "@typescript-eslint/scope-manager" "4.21.0" + "@typescript-eslint/types" "4.21.0" + "@typescript-eslint/typescript-estree" "4.21.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^4.11.1": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.0.tgz#8df94365b4b7161f9e8514fe28aef19954810b6b" - integrity sha512-L6Dtbq8Bc7g2aZwnIBETpmUa9XDKCMzKVwAArnGp5Mn7PRNFjf3mUzq8UeBjL3K8t311hvevnyqXAMSmxO8Gpg== +"@typescript-eslint/parser@^4.15.1": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.21.0.tgz#a227fc2af4001668c3e3f7415d4feee5093894c1" + integrity sha512-eyNf7QmE5O/l1smaQgN0Lj2M/1jOuNg2NrBm1dqqQN0sVngTLyw8tdCbih96ixlhbF1oINoN8fDCyEH9SjLeIA== dependencies: - "@typescript-eslint/scope-manager" "4.15.0" - "@typescript-eslint/types" "4.15.0" - "@typescript-eslint/typescript-estree" "4.15.0" + "@typescript-eslint/scope-manager" "4.21.0" + "@typescript-eslint/types" "4.21.0" + "@typescript-eslint/typescript-estree" "4.21.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.0.tgz#c42703558ea6daaaba51a9c3a86f2902dbab9432" - integrity sha512-CSNBZnCC2jEA/a+pR9Ljh8Y+5TY5qgbPz7ICEk9WCpSEgT6Pi7H2RIjxfrrbUXvotd6ta+i27sssKEH8Azm75g== +"@typescript-eslint/scope-manager@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.21.0.tgz#c81b661c4b8af1ec0c010d847a8f9ab76ab95b4d" + integrity sha512-kfOjF0w1Ix7+a5T1knOw00f7uAP9Gx44+OEsNQi0PvvTPLYeXJlsCJ4tYnDj5PQEYfpcgOH5yBlw7K+UEI9Agw== dependencies: - "@typescript-eslint/types" "4.15.0" - "@typescript-eslint/visitor-keys" "4.15.0" + "@typescript-eslint/types" "4.21.0" + "@typescript-eslint/visitor-keys" "4.21.0" -"@typescript-eslint/types@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.0.tgz#3011ae1ac3299bb9a5ac56bdd297cccf679d3662" - integrity sha512-su4RHkJhS+iFwyqyXHcS8EGPlUVoC+XREfy5daivjLur9JP8GhvTmDipuRpcujtGC4M+GYhUOJCPDE3rC5NJrg== +"@typescript-eslint/types@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.21.0.tgz#abdc3463bda5d31156984fa5bc316789c960edef" + integrity sha512-+OQaupjGVVc8iXbt6M1oZMwyKQNehAfLYJJ3SdvnofK2qcjfor9pEM62rVjBknhowTkh+2HF+/KdRAc/wGBN2w== -"@typescript-eslint/typescript-estree@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.0.tgz#402c86a7d2111c1f7a2513022f22a38a395b7f93" - integrity sha512-jG6xTmcNbi6xzZq0SdWh7wQ9cMb2pqXaUp6bUZOMsIlu5aOlxGxgE/t6L/gPybybQGvdguajXGkZKSndZJpksA== +"@typescript-eslint/typescript-estree@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.21.0.tgz#3817bd91857beeaeff90f69f1f112ea58d350b0a" + integrity sha512-ZD3M7yLaVGVYLw4nkkoGKumb7Rog7QID9YOWobFDMQKNl+vPxqVIW/uDk+MDeGc+OHcoG2nJ2HphwiPNajKw3w== dependencies: - "@typescript-eslint/types" "4.15.0" - "@typescript-eslint/visitor-keys" "4.15.0" + "@typescript-eslint/types" "4.21.0" + "@typescript-eslint/visitor-keys" "4.21.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.15.0": - version "4.15.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.0.tgz#2a07768df30c8a5673f1bce406338a07fdec38ca" - integrity sha512-RnDtJwOwFucWFAMjG3ghCG/ikImFJFEg20DI7mn4pHEx3vC48lIAoyjhffvfHmErRDboUPC7p9Z2il4CLb7qxA== +"@typescript-eslint/visitor-keys@4.21.0": + version "4.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.21.0.tgz#990a9acdc124331f5863c2cf21c88ba65233cd8d" + integrity sha512-dH22dROWGi5Z6p+Igc8bLVLmwy7vEe8r+8c+raPQU0LxgogPUrRAtRGtvBWmlr9waTu3n+QLt/qrS/hWzk1x5w== dependencies: - "@typescript-eslint/types" "4.15.0" + "@typescript-eslint/types" "4.21.0" eslint-visitor-keys "^2.0.0" "@wdio/config@6.12.1": @@ -1310,9 +1497,9 @@ dependencies: "@wdio/logger" "6.10.10" -"YoutubeNonStop@git://github.com/lawfx/YoutubeNonStop.git#v0.8.1": +"YoutubeNonStop@git://github.com/lawfx/YoutubeNonStop.git#v0.9.0": version "0.0.0" - resolved "git://github.com/lawfx/YoutubeNonStop.git#7b70a4028d5d5752bea34e318d499bf5e23e4361" + resolved "git://github.com/lawfx/YoutubeNonStop.git#7b6b97b31bb3fd2078179660db0fd3fcc7062259" abab@^2.0.3: version "2.0.5" @@ -1396,6 +1583,11 @@ ansi-regex@^2.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -1446,37 +1638,38 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -app-builder-bin@3.5.10: - version "3.5.10" - resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.10.tgz#4a7f9999fccc0c435b6284ae1366bc76a17c4a7d" - integrity sha512-Jd+GW68lR0NeetgZDo47PdWBEPdnD+p0jEa7XaxjRC8u6Oo/wgJsfKUkORRgr2NpkD19IFKN50P6JYy04XHFLQ== +app-builder-bin@3.5.12: + version "3.5.12" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.12.tgz#bbe174972cc1f481f73d6d92ad47a8b4c7eb4530" + integrity sha512-lQARM2AielmFoBeIo6LZigAe+58Wwe07ZWkt+wVeDxzyieNmeWjlvz/V5dKzinydwdHd+CNswN86sww46yijjA== -app-builder-lib@22.9.1: - version "22.9.1" - resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.9.1.tgz#ccb8f1a02b628514a5dfab9401fa2a976689415c" - integrity sha512-KfXim/fiNwFW2SKffsjEMdAU7RbbEXn62x5YyXle1b4j9X/wEHW9iwox8De6y0hJdR+/kCC/49lI+VgNwLhV7A== +app-builder-lib@22.10.5: + version "22.10.5" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.10.5.tgz#24a88581c891e5b187a0d569aa44e7c4a0dc8de2" + integrity sha512-/W8nlGamJCtKlQtsMWwU9vb+cX4pTNY+rJWCuc7oXUykVSMS50W7LhQusIjCelNfymUQ1XCu6cXEY/ylqhX12A== dependencies: "7zip-bin" "~5.0.3" "@develar/schema-utils" "~2.6.5" + "@electron/universal" "1.0.4" async-exit-hook "^2.0.1" bluebird-lst "^1.0.9" - builder-util "22.9.1" - builder-util-runtime "8.7.2" + builder-util "22.10.5" + builder-util-runtime "8.7.3" chromium-pickle-js "^0.2.0" - debug "^4.3.0" - ejs "^3.1.5" - electron-publish "22.9.1" - fs-extra "^9.0.1" - hosted-git-info "^3.0.5" + debug "^4.3.2" + ejs "^3.1.6" + electron-publish "22.10.5" + fs-extra "^9.1.0" + hosted-git-info "^3.0.8" is-ci "^2.0.0" - isbinaryfile "^4.0.6" - js-yaml "^3.14.0" + istextorbinary "^5.12.0" + js-yaml "^4.0.0" lazy-val "^1.0.4" minimatch "^3.0.4" - normalize-package-data "^2.5.0" + normalize-package-data "^3.0.0" read-config-file "6.0.0" sanitize-filename "^1.6.3" - semver "^7.3.2" + semver "^7.3.4" temp-file "^3.3.7" archiver-utils@^2.1.0: @@ -1515,6 +1708,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + args@^2.3.0: version "2.6.1" resolved "https://registry.yarnpkg.com/args/-/args-2.6.1.tgz#b2590ed4168cd31b62444199bdc5166bb1920c2f" @@ -1598,6 +1796,18 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== +asar@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/asar/-/asar-3.0.3.tgz#1fef03c2d6d2de0cbad138788e4f7ae03b129c7b" + integrity sha512-k7zd+KoR+n8pl71PvgElcoKHrVNiSXtw7odKbyNpmgKe7EGRF9Pnu3uLOukD37EvavKwVFxOUpqXTIZC5B5Pmw== + dependencies: + chromium-pickle-js "^0.2.0" + commander "^5.0.0" + glob "^7.1.6" + minimatch "^3.0.4" + optionalDependencies: + "@types/glob" "^7.1.1" + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -1690,18 +1900,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" @@ -1768,7 +1966,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base64-js@^1.0.2, base64-js@^1.3.1: +base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -1793,6 +1991,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +binaryextensions@^4.15.0: + version "4.15.0" + resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-4.15.0.tgz#c63a502e0078ff1b0e9b00a9f74d3c2b0f8bd32e" + integrity sha512-MkUl3szxXolQ2scI1PM14WOT951KnaTNJ0eMKg7WzOI4kvSxyNo/Cygx4LOBNhwyINhAuSQpJW1rYD9aBSxGaw== + bl@^4.0.3: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -1834,20 +2037,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570" integrity sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g== -boxen@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" - integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^3.0.0" - cli-boxes "^2.2.0" - string-width "^4.1.0" - term-size "^2.1.0" - type-fest "^0.8.1" - widest-line "^3.1.0" - boxen@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.0.0.tgz#64fe9b16066af815f51057adcc800c3730120854" @@ -1969,6 +2158,17 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" +browserslist@^4.14.5: + version "4.16.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== + dependencies: + caniuse-lite "^1.0.30001181" + colorette "^1.2.1" + electron-to-chromium "^1.3.649" + escalade "^3.1.1" + node-releases "^1.1.70" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -1991,6 +2191,11 @@ buffer-equal@0.0.1: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= +buffer-equal@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2010,7 +2215,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0: +buffer@^5.1.0, buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2018,14 +2223,6 @@ buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -builder-util-runtime@8.7.2: - version "8.7.2" - resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.2.tgz#d93afc71428a12789b437e13850e1fa7da956d72" - integrity sha512-xBqv+8bg6cfnzAQK1k3OGpfaHg+QkPgIgpEkXNhouZ0WiUkyZCftuRc2LYzQrLucFywpa14Xbc6+hTbpq83yRA== - dependencies: - debug "^4.1.1" - sax "^1.2.4" - builder-util-runtime@8.7.3: version "8.7.3" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.7.3.tgz#0aaafa52d25295c939496f62231ca9ff06c30e40" @@ -2034,22 +2231,22 @@ builder-util-runtime@8.7.3: debug "^4.3.2" sax "^1.2.4" -builder-util@22.9.1: - version "22.9.1" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.9.1.tgz#b7087a5cde477f90d718ca5d7fafb6ae261b16af" - integrity sha512-5hN/XOaYu4ZQUS6F+5CXE6jTo+NAnVqAxDuKGSaHWb9bejfv/rluChTLoY3/nJh7RFjkoyVjvFJv7zQDB1QmHw== +builder-util@22.10.5: + version "22.10.5" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-22.10.5.tgz#8d0b04a3be6acc74938679aa90dcb3181b1ae86b" + integrity sha512-/MkLhmyo1gU3xMwXJxccQaRj/9tm5eTd6ZyebTf8SYouY4r3hRser+LxhOm/f8Z9W6oJvfPe0jc9TFsxYfMcsg== dependencies: "7zip-bin" "~5.0.3" "@types/debug" "^4.1.5" - "@types/fs-extra" "^9.0.1" - app-builder-bin "3.5.10" + "@types/fs-extra" "^9.0.7" + app-builder-bin "3.5.12" bluebird-lst "^1.0.9" - builder-util-runtime "8.7.2" + builder-util-runtime "8.7.3" chalk "^4.1.0" - debug "^4.3.0" - fs-extra "^9.0.1" + debug "^4.3.2" + fs-extra "^9.1.0" is-ci "^2.0.0" - js-yaml "^3.14.0" + js-yaml "^4.0.0" source-map-support "^0.5.19" stat-mode "^1.0.0" temp-file "^3.3.7" @@ -2152,6 +2349,11 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== +caniuse-lite@^1.0.30001181: + version "1.0.30001208" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz#a999014a35cebd4f98c405930a057a0d75352eb9" + integrity sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -2184,14 +2386,6 @@ chalk@^2.0.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^4.0.0, chalk@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -2267,16 +2461,19 @@ clean-stack@^2.1.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== - cli-boxes@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cli-truncate@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.1.0.tgz#2b2dfd83c53cfd3572b87fc4d430a808afb04086" + integrity sha512-bAtZo0u82gCfaAGfSNxUdTI9mNyza7D8w4CVCcaOsy7sgwDzvx6ekr6cuWJqY3UGzgnQ1+4wgENup5eIhgxEYA== + dependencies: + slice-ansi "^1.0.0" + string-width "^2.0.0" + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -2358,6 +2555,16 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +colors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" + integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -2365,6 +2572,18 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= + dependencies: + graceful-readlink ">= 1.0.0" + +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2513,6 +2732,13 @@ crc32-stream@^4.0.1: crc-32 "^1.2.0" readable-stream "^3.4.0" +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -2555,7 +2781,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2641,7 +2867,7 @@ debounce-fn@^4.0.0: dependencies: mimic-fn "^3.0.0" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -2834,6 +3060,16 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-compare@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631" + integrity sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA== + dependencies: + buffer-equal "1.0.0" + colors "1.0.3" + commander "2.9.0" + minimatch "3.0.4" + dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -2856,17 +3092,34 @@ discord-rpc@^3.2.0: node-fetch "^2.6.1" ws "^7.3.1" -dmg-builder@22.9.1: - version "22.9.1" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.9.1.tgz#64647224f37ee47fc9bd01947c21cc010a30511f" - integrity sha512-jc+DAirqmQrNT6KbDHdfEp8D1kD0DBTnsLhwUR3MX+hMBun5bT134LQzpdK0GKvd22GqF8L1Cz/NOgaVjscAXQ== +dmg-builder@22.10.5: + version "22.10.5" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.10.5.tgz#65a33c106ead5a350c7de8997c546559bd6e0e7c" + integrity sha512-58FEpfH8PEFqjbUNka4bYr52snRT8+LSXrP4gy6EZWOVICbOlmTOYj988pfoLam5C5iXb3odmyUQqwWOxlsEUw== dependencies: - app-builder-lib "22.9.1" - builder-util "22.9.1" - fs-extra "^9.0.1" + app-builder-lib "22.10.5" + builder-util "22.10.5" + fs-extra "^9.1.0" iconv-lite "^0.6.2" - js-yaml "^3.14.0" + js-yaml "^4.0.0" sanitize-filename "^1.6.3" + optionalDependencies: + dmg-license "^1.0.8" + +dmg-license@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/dmg-license/-/dmg-license-1.0.8.tgz#d52e234815f1a07a59706e5f2a2fea71991cf784" + integrity sha512-47GOb6b4yVzpovXC34heXElpH++ICg9GuWBeOTaokUNLAoAdWpE4VehudYEEtu96j2jXsgQWYf78nW7r+0Y3eg== + dependencies: + "@types/plist" "^3.0.1" + "@types/verror" "^1.10.3" + ajv "^6.10.0" + cli-truncate "^1.1.0" + crc "^3.8.0" + iconv-corefoundation "^1.1.5" + plist "^3.0.1" + smart-buffer "^4.0.2" + verror "^1.10.0" doctrine@1.5.0: version "1.5.0" @@ -2945,32 +3198,40 @@ edge-paths@^2.1.0: "@types/which" "^1.3.2" which "^2.0.2" -ejs@^3.1.5: +editions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/editions/-/editions-6.1.0.tgz#ba6c6cf9f4bb571d9e53ea34e771a602e5a66549" + integrity sha512-h6nWEyIocfgho9J3sTSuhU/WoFOu1hTX75rPBebNrbF38Y9QFDjCDizYXdikHTySW7Y3mSxli8bpDz9RAtc7rA== + dependencies: + errlop "^4.0.0" + version-range "^1.0.0" + +ejs@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== dependencies: jake "^10.6.1" -electron-builder@^22.9.1: - version "22.9.1" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.9.1.tgz#a2962db6f2757bc01d02489f38fafe0809f68f60" - integrity sha512-GXPt8l5Mxwm1QKYopUM6/Tdh9W3695G6Ax+IFyj5pQ51G4SD5L1uq4/RkPSsOgs3rP7jNSV6g6OfDzdtVufPdA== +electron-builder@^22.10.5: + version "22.10.5" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.10.5.tgz#03b156b93e6012609027c3aaa69201a3ad21e454" + integrity sha512-0q/289UUJUhRou6lZKDz/wzK6WprIQ6VXMTmaI+w9qXvSNugPC9UA5s2zXInOkjZOvO/xKnjeyiavrVSHYF3tA== dependencies: - "@types/yargs" "^15.0.5" - app-builder-lib "22.9.1" + "@types/yargs" "^15.0.13" + app-builder-lib "22.10.5" bluebird-lst "^1.0.9" - builder-util "22.9.1" - builder-util-runtime "8.7.2" + builder-util "22.10.5" + builder-util-runtime "8.7.3" chalk "^4.1.0" - dmg-builder "22.9.1" - fs-extra "^9.0.1" + dmg-builder "22.10.5" + fs-extra "^9.1.0" is-ci "^2.0.0" lazy-val "^1.0.4" read-config-file "6.0.0" sanitize-filename "^1.6.3" - update-notifier "^4.1.1" - yargs "^16.0.3" + update-notifier "^5.1.0" + yargs "^16.2.0" electron-chromedriver@^11.0.0: version "11.0.0" @@ -3039,28 +3300,33 @@ electron-localshortcut@^3.1.0, electron-localshortcut@^3.2.1: keyboardevent-from-electron-accelerator "^2.0.0" keyboardevents-areequal "^0.2.1" -electron-publish@22.9.1: - version "22.9.1" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.9.1.tgz#7cc76ac4cc53efd29ee31c1e5facb9724329068e" - integrity sha512-ducLjRJLEeU87FaTCWaUyDjCoLXHkawkltP2zqS/n2PyGke54ZIql0tBuUheht4EpR8AhFbVJ11spSn1gy8r6w== +electron-publish@22.10.5: + version "22.10.5" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.10.5.tgz#9cbe46266b6c79d8c6e99840755682e2262d3543" + integrity sha512-dHyuazv3P3j1Xyv7pdwTwAvxWab2pCb0G0Oa6qWQoCc4b1/mRGY00M7AvYW1cPuUijj9zYAf1HmXfM6MifaMlA== dependencies: - "@types/fs-extra" "^9.0.1" + "@types/fs-extra" "^9.0.7" bluebird-lst "^1.0.9" - builder-util "22.9.1" - builder-util-runtime "8.7.2" + builder-util "22.10.5" + builder-util-runtime "8.7.3" chalk "^4.1.0" - fs-extra "^9.0.1" + fs-extra "^9.1.0" lazy-val "^1.0.4" - mime "^2.4.6" + mime "^2.5.0" -electron-store@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-7.0.2.tgz#e45a54d092ea43e2a953619ed4473893d448dfdf" - integrity sha512-tSUeHF9qdiPirph8JKJvIIcdVb3wYwgHUJCE38SJq4L08Op2z1+u8DSQ42Nvx34TKvb2lkQkByV0tHh6xBxdEQ== +electron-store@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-7.0.3.tgz#56d78284454018ed50ffc7645da49f828ae5ff19" + integrity sha512-wIbw4GHt4djs4dVrlRLCD/SpdpDUiRsQc212jagGA6zJ8xt1iwx3KZIzXY8gmwvgVCOcVxi3iyCXZoBBWwBXpQ== dependencies: conf "^9.0.0" type-fest "^0.20.2" +electron-to-chromium@^1.3.649: + version "1.3.711" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.711.tgz#92c3caf7ffed5e18bf63f66b4b57b4db2409c450" + integrity sha512-XbklBVCDiUeho0PZQCjC25Ha6uBwqqJeyDhPLwLwfWRAo4x+FZFsmu1pPPkXT+B4MQMQoQULfyaMltDopfeiHQ== + electron-unhandled@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/electron-unhandled/-/electron-unhandled-3.0.2.tgz#e14a19c830ccf7b6e755191c8e78d23094d25112" @@ -3071,23 +3337,23 @@ electron-unhandled@^3.0.2: ensure-error "^2.0.0" lodash.debounce "^4.0.8" -electron-updater@^4.3.6: - version "4.3.7" - resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.7.tgz#632434cf1dd856e37f5557a68b55867fae29c39e" - integrity sha512-F7l1ZdslA5Do9kABNhiYKMPzreLulFTv+rsbGUQJ3TnRKrEb3JAi/n/jco3mI8LOEG/pgS5f9ytQ+D+5r/PvQw== +electron-updater@^4.3.8: + version "4.3.8" + resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.3.8.tgz#94f1731682a756385726183e2b04b959cb319456" + integrity sha512-/tB82Ogb2LqaXrUzAD8waJC+TZV52Pr0Znfj7w+i4D+jA2GgrKFI3Pxjp+36y9FcBMQz7kYsMHcB6c5zBJao+A== dependencies: "@types/semver" "^7.3.4" builder-util-runtime "8.7.3" - fs-extra "^9.0.1" - js-yaml "^3.14.1" + fs-extra "^9.1.0" + js-yaml "^4.0.0" lazy-val "^1.0.4" lodash.isequal "^4.5.0" semver "^7.3.4" -electron@^11.2.3: - version "11.2.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-11.2.3.tgz#8ad1d9858436cfca0e2e5ea7fea326794ae58ebb" - integrity sha512-6yxOc42nDAptHKNlUG/vcOh2GI9x2fqp2nQbZO0/3sz2CrwsJkwR3i3oMN9XhVJaqI7GK1vSCJz0verOkWlXcQ== +electron@^11.4.2: + version "11.4.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.4.2.tgz#02005d9f5d77ea6485efeffdb5c5433c769ddda4" + integrity sha512-P0PRLH7cXp8ZdpA9yVPe7jRVM+QeiAtsadqmqS6XY3AYrsH+7bJnVrNuw6p/fcmp+b/UxWaCexobqQpyFJ5Qkw== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -3171,6 +3437,11 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== +errlop@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/errlop/-/errlop-4.1.0.tgz#8e7b8f4f1bf0a6feafce4d14f0c0cf4bf5ef036b" + integrity sha512-vul6gGBuVt0M2TPi1/WrcL86+Hb3Q2Tpu3TME3sbVhZrYf7J1ZMHCodI25RQKCVurh56qTfvgM0p3w5cT4reSQ== + error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -3254,28 +3525,20 @@ escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" -eslint-ast-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz#3d58ba557801cfb1c941d68131ee9f8c34bd1586" - integrity sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA== - dependencies: - lodash.get "^4.4.2" - lodash.zip "^4.2.0" - -eslint-config-prettier@^7.1.0: +eslint-config-prettier@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== -eslint-config-xo-typescript@^0.37.0: - version "0.37.0" - resolved "https://registry.yarnpkg.com/eslint-config-xo-typescript/-/eslint-config-xo-typescript-0.37.0.tgz#fead961a5cf1874b57372c63e5417cb5fd58afb3" - integrity sha512-eFRj4xMhiMExCb+H/wyXC1OwTKJiOQ+Qd9myoZLWdyR0X8PAjtzPRfxSOyh2fkBnZvFCDY0DuqcLkPSDSe4Ybg== +eslint-config-xo-typescript@^0.38.0: + version "0.38.0" + resolved "https://registry.yarnpkg.com/eslint-config-xo-typescript/-/eslint-config-xo-typescript-0.38.0.tgz#2aef017ce9a4b68855b246771557a7eab545b589" + integrity sha512-f5z0gN1r9X84PK1qav6T6YT1zW6KcAqtsMPtmqoKBLt4ACRr6tbAddtFwqkluAEH9JvHjWxuB8vu4KJFcjuzdQ== -eslint-config-xo@^0.34.0: - version "0.34.0" - resolved "https://registry.yarnpkg.com/eslint-config-xo/-/eslint-config-xo-0.34.0.tgz#c158ab361aec62727219ed3b1971c24311cd9ad4" - integrity sha512-lbpHNfVmSrEQsHsyQ44wY8VA5mEI4Jri5Dk1BJUH0jiCw6nTkj16VQeHiuWzIBJ/uf+mF2FzSqLVf3tD1cHhYA== +eslint-config-xo@^0.35.0: + version "0.35.0" + resolved "https://registry.yarnpkg.com/eslint-config-xo/-/eslint-config-xo-0.35.0.tgz#8b5afca244c44129c32386c28602f973ad5cb762" + integrity sha512-+WyZTLWUJlvExFrBU/Ldw8AB/S0d3x+26JQdBWbcqig2ZaWh0zinYcHok+ET4IoPaEcRRf3FE9kjItNVjBwnAg== dependencies: confusing-browser-globals "1.0.10" @@ -3396,33 +3659,33 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^3.3.0: +eslint-plugin-prettier@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ== dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== +eslint-plugin-promise@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" + integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== -eslint-plugin-unicorn@^25.0.1: - version "25.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-25.0.1.tgz#bedcbc9b817042a44f6501584e8266741120f023" - integrity sha512-MEyEWoyou/qhJH6rEER9YHACtCsQT+eewc6Fdxbi2eiTvsGrBR8JZMA6qaeof3oMQeRxOpaERoBKzU7R5c4A/w== +eslint-plugin-unicorn@^28.0.2: + version "28.0.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-28.0.2.tgz#ab9884ebae04590ecd9c1c294330d889a74b7c37" + integrity sha512-k4AoFP7n8/oq6lBXkdc9Flid6vw2B8j7aXFCxgzJCyKvmaKrCUFb1TFPhG9eSJQFZowqmymMPRtl8oo9NKLUbw== dependencies: ci-info "^2.0.0" clean-regexp "^1.0.0" - eslint-ast-utils "^1.1.0" - eslint-template-visitor "^2.2.1" + eslint-template-visitor "^2.2.2" eslint-utils "^2.1.0" - import-modules "^2.0.0" + eslint-visitor-keys "^2.0.0" + import-modules "^2.1.0" lodash "^4.17.20" pluralize "^8.0.0" read-pkg-up "^7.0.1" - regexp-tree "^0.1.21" + regexp-tree "^0.1.22" reserved-words "^0.1.2" safe-regex "^2.1.1" semver "^7.3.4" @@ -3432,7 +3695,7 @@ eslint-rule-docs@^1.1.5: resolved "https://registry.yarnpkg.com/eslint-rule-docs/-/eslint-rule-docs-1.1.220.tgz#1768d8c35788c9ea2d3ed70c57c245c13619aec4" integrity sha512-xu80BM9oOJnVUz4BUyRh7pAui5Q52vJ231grUXSvsJdGDNk4Hga2wX7qLJLFpziF4YXUGweIB/58iZ4nzlRTuw== -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@^5.0.0, eslint-scope@^5.1.0, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -3440,12 +3703,13 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-template-visitor@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.2.2.tgz#46cd2b06eca5c1d97369aadd96e131df88fdd59c" - integrity sha512-SkcLjzKw3JjKTWHacRDeLBa2gxb600zbCKTkXj/V97QnZ9yxkknoPL8vc8PFueqbFXP7mYNTQzjCjcMpTRdRaA== +eslint-template-visitor@^2.2.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/eslint-template-visitor/-/eslint-template-visitor-2.3.2.tgz#b52f96ff311e773a345d79053ccc78275bbc463d" + integrity sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA== dependencies: - babel-eslint "^10.1.0" + "@babel/core" "^7.12.16" + "@babel/eslint-parser" "^7.12.16" eslint-visitor-keys "^2.0.0" esquery "^1.3.1" multimap "^1.1.0" @@ -3457,7 +3721,7 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== @@ -3467,13 +3731,13 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^7.17.0: - version "7.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.19.0.tgz#6719621b196b5fad72e43387981314e5d0dc3f41" - integrity sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg== +eslint@^7.20.0: + version "7.23.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.23.0.tgz#8d029d252f6e8cf45894b4bee08f5493f8e94325" + integrity sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q== dependencies: - "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.3.0" + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.0" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -3484,12 +3748,12 @@ eslint@^7.17.0: eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" espree "^7.3.1" - esquery "^1.2.0" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^6.0.0" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" - globals "^12.1.0" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" @@ -3497,7 +3761,7 @@ eslint@^7.17.0: js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" - lodash "^4.17.20" + lodash "^4.17.21" minimatch "^3.0.4" natural-compare "^1.4.0" optionator "^0.9.1" @@ -3529,7 +3793,7 @@ espurify@^2.0.1: resolved "https://registry.yarnpkg.com/espurify/-/espurify-2.0.1.tgz#c25b3bb613863daa142edcca052370a1a459f41d" integrity sha512-7w/dUrReI/QbJFHRwfomTlkQOXaB1NuCrBRn5Y26HXn5gvh18/19AgLbayVrNxXQfkckvgrJloWyvZDuJ7dhEA== -esquery@^1.2.0, esquery@^1.3.1: +esquery@^1.3.1, esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== @@ -3794,10 +4058,10 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -file-entry-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" - integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" @@ -3963,7 +4227,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.1: +fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -3993,7 +4257,7 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gensync@^1.0.0-beta.1: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -4096,7 +4360,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4121,13 +4385,6 @@ global-agent@^2.0.2: semver "^7.3.2" serialize-error "^7.0.1" -global-dirs@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" - integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== - dependencies: - ini "1.3.7" - global-dirs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" @@ -4165,6 +4422,13 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" +globals@^13.6.0: + version "13.8.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3" + integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q== + dependencies: + type-fest "^0.20.2" + globalthis@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.1.tgz#40116f5d9c071f9e8fb0037654df1ab3a83b7ef9" @@ -4248,6 +4512,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.5.tgz#bc18864a6c9fc7b303f2e2abdb9155ad178fbe29" integrity sha512-kBBSQbz2K0Nyn+31j/w36fUfxkBW9/gfwRWdUY1ULReH3iokVJgddZAFcD1D0xlgTmFxJCbUkUclAlc6/IDJkw== +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + grapheme-splitter@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" @@ -4380,7 +4649,7 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hosted-git-info@^3.0.5, hosted-git-info@^3.0.6: +hosted-git-info@^3.0.6, hosted-git-info@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d" integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw== @@ -4455,6 +4724,14 @@ icon-gen@2.0.0: svg2png "4.1.1" uuid "^3.3.2" +iconv-corefoundation@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iconv-corefoundation/-/iconv-corefoundation-1.1.5.tgz#90596d444a579aeb109f5ca113f6bb665a41be2b" + integrity sha512-hI4m7udfV04OcjleOmDaR4gwXnH4xumxN+ZmywHDiKf2CmAzsT9SVYe7Y4pdnQbyZfXwAQyrElykbE5PrPRfmQ== + dependencies: + cli-truncate "^1.1.0" + node-addon-api "^1.6.3" + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -4515,7 +4792,7 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -import-modules@^2.0.0: +import-modules@^2.0.0, import-modules@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-modules/-/import-modules-2.1.0.tgz#abe7df297cb6c1f19b57246eb8b8bd9664b6d8c2" integrity sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A== @@ -4553,11 +4830,6 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" - integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== - ini@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" @@ -4752,14 +5024,6 @@ is-glob@^4.0.0, is-glob@^4.0.1: dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" - integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== - dependencies: - global-dirs "^2.0.1" - is-path-inside "^3.0.1" - is-installed-globally@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" @@ -4785,11 +5049,6 @@ is-negative-zero@^2.0.1: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== -is-npm@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" - integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== - is-npm@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" @@ -4839,7 +5098,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-path-inside@^3.0.1, is-path-inside@^3.0.2: +is-path-inside@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== @@ -4950,11 +5209,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isbinaryfile@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b" - integrity sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5018,6 +5272,15 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +istextorbinary@^5.12.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-5.12.0.tgz#2f84777838668fdf524c305a2363d6057aaeec84" + integrity sha512-wLDRWD7qpNTYubk04+q3en1+XZGS4vYWK0+SxNSXJLaITMMEK+J3o/TlOMyULeH1qozVZ9uUkKcyMA8odyxz8w== + dependencies: + binaryextensions "^4.15.0" + editions "^6.1.0" + textextensions "^5.11.0" + jake@^10.6.1: version "10.8.2" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" @@ -5427,7 +5690,7 @@ js-types@^1.0.0: resolved "https://registry.yarnpkg.com/js-types/-/js-types-1.0.0.tgz#d242e6494ed572ad3c92809fc8bed7f7687cbf03" integrity sha1-0kLmSU7Vcq08koCfyL7X92h8vwM= -js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.14.1: +js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -5435,6 +5698,13 @@ js-yaml@^3.13.1, js-yaml@^3.14.0, js-yaml@^3.14.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -5529,7 +5799,7 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.1.3: +json5@^2.1.2, json5@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== @@ -5644,7 +5914,7 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -latest-version@^5.0.0, latest-version@^5.1.0: +latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== @@ -5808,11 +6078,6 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5853,6 +6118,11 @@ lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + log-symbols@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" @@ -5957,13 +6227,14 @@ memory-fs@^0.2.0: resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" integrity sha1-8rslNovBIeORwlIN6Slpyu4KApA= -meow@^8.1.0: - version "8.1.2" - resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" - integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== dependencies: "@types/minimist" "^1.2.0" camelcase-keys "^6.2.2" + decamelize "^1.2.0" decamelize-keys "^1.1.0" hard-rejection "^2.1.0" minimist-options "4.1.0" @@ -6041,10 +6312,10 @@ mime@^1.3.4: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.6: - version "2.5.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.0.tgz#2b4af934401779806ee98026bb42e8c1ae1876b1" - integrity sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag== +mime@^2.5.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== mimic-fn@^2.1.0: version "2.1.0" @@ -6093,7 +6364,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -6181,6 +6452,11 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-addon-api@^1.6.3: + version "1.7.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -6237,6 +6513,11 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" +node-releases@^1.1.70: + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== + normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -6812,6 +7093,15 @@ pkginfo@0.4.0: resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.0.tgz#349dbb7ffd38081fcadc0853df687f0c7744cd65" integrity sha1-NJ27f/04CB/K3AhT32h/DHdEzWU= +plist@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.2.tgz#74bbf011124b90421c22d15779cee60060ba95bc" + integrity sha512-MSrkwZBdQ6YapHy87/8hDU8MnIcyxBKjeF+McXnr5A9MtffPewTs7G3hlpodT5TacyfIyFTaJEhh3GGcmasTgQ== + dependencies: + base64-js "^1.5.1" + xmlbuilder "^9.0.7" + xmldom "^0.5.0" + plur@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" @@ -6969,7 +7259,7 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -pupa@^2.0.1, pupa@^2.1.1: +pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== @@ -7163,7 +7453,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.21, regexp-tree@~0.1.1: +regexp-tree@^0.1.22, regexp-tree@~0.1.1: version "0.1.23" resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.23.tgz#8a8ce1cc5e971acef62213a7ecdb1f6e18a1f1b2" integrity sha512-+7HWfb4Bvu8Rs2eQTUIpX9I/PlQkYOuTNbRpKLJlQpSgwSkzFYh+pUj0gtvglnOZLKB6YgnIgRuJ2/IlpL48qw== @@ -7303,7 +7593,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== @@ -7579,6 +7869,13 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -7588,6 +7885,11 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +smart-buffer@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" + integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -7801,6 +8103,14 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string-width@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -7856,6 +8166,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-ansi@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -8014,11 +8331,6 @@ temp-file@^3.3.7: async-exit-hook "^2.0.1" fs-extra "^8.1.0" -term-size@^2.1.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" - integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== - terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -8041,6 +8353,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +textextensions@^5.11.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-5.12.0.tgz#b908120b5c1bd4bb9eba41423d75b176011ab68a" + integrity sha512-IYogUDaP65IXboCiPPC0jTLLBzYlhhw2Y4b0a2trPgbHNGGGEfuHE6tds+yDcCf4mpNDaGISFzwSSezcXt+d6w== + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -8303,10 +8620,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" - integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== +typescript@^4.1.5: + version "4.2.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" + integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== ua-parser-js@^0.7.21: version "0.7.23" @@ -8370,26 +8687,7 @@ unzip-crx-3@^0.2.0: mkdirp "^0.5.1" yaku "^0.16.6" -update-notifier@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" - integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== - dependencies: - boxen "^4.2.0" - chalk "^3.0.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.3.1" - is-npm "^4.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.0.0" - pupa "^2.0.1" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -update-notifier@^5.0.1: +update-notifier@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== @@ -8504,7 +8802,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -verror@1.10.0: +verror@1.10.0, verror@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= @@ -8513,6 +8811,18 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +version-compare@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/version-compare/-/version-compare-1.1.0.tgz#7b3e67e7e6cec5c72d9c9e586f8854e419ade17c" + integrity sha512-zVKtPOJTC9x23lzS4+4D7J+drq80BXVYAmObnr5zqxxFVH7OffJ1lJlAS7LYsQNV56jx/wtbw0UV7XHLrvd6kQ== + +version-range@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/version-range/-/version-range-1.1.0.tgz#1c233064202ee742afc9d56e21da3b2e15260acf" + integrity sha512-R1Ggfg2EXamrnrV3TkZ6yBNgITDbclB3viwSjbZ3+eK0VVNK4ajkYJTnDz5N0bIMYDtK9MUBvXJUnKO5RWWJ6w== + dependencies: + version-compare "^1.0.0" + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -8726,6 +9036,16 @@ xml2js@^0.4.5: sax ">=0.6.0" xmlbuilder "~11.0.0" +xmlbuilder@>=11.0.1: + version "15.1.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" + integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== + +xmlbuilder@^9.0.7: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" @@ -8736,20 +9056,25 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xo@^0.37.1: - version "0.37.1" - resolved "https://registry.yarnpkg.com/xo/-/xo-0.37.1.tgz#0843b6a7c6193fa85ae23d26e44eb1fc5652057b" - integrity sha512-UsD1QkITsojNJmiYaDg20GOuTEuHAYtys6Cz4JVWbral6hbCb+WU8ktt9xCTDrsr2rNPjoxp1oonoz9HkPYGnQ== +xmldom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e" + integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA== + +xo@^0.38.2: + version "0.38.2" + resolved "https://registry.yarnpkg.com/xo/-/xo-0.38.2.tgz#a9e44f85e0655dad64bf08d177c096dd35c0008b" + integrity sha512-bGDGXgyPQyiVYIiqrkbFm4S1IIwlKDrNxgWnz9xWrdT4jdbfDU9fHkW6Mwab7jGms7ymoul+aRZVa3uMhcQlTw== dependencies: - "@typescript-eslint/eslint-plugin" "^4.11.1" - "@typescript-eslint/parser" "^4.11.1" + "@typescript-eslint/eslint-plugin" "^4.15.1" + "@typescript-eslint/parser" "^4.15.1" arrify "^2.0.1" cosmiconfig "^7.0.0" debug "^4.3.1" - eslint "^7.17.0" - eslint-config-prettier "^7.1.0" - eslint-config-xo "^0.34.0" - eslint-config-xo-typescript "^0.37.0" + eslint "^7.20.0" + eslint-config-prettier "^7.2.0" + eslint-config-xo "^0.35.0" + eslint-config-xo-typescript "^0.38.0" eslint-formatter-pretty "^4.0.0" eslint-import-resolver-webpack "^0.13.0" eslint-plugin-ava "^11.0.0" @@ -8757,21 +9082,21 @@ xo@^0.37.1: eslint-plugin-import "^2.22.1" eslint-plugin-no-use-extend-native "^0.5.0" eslint-plugin-node "^11.1.0" - eslint-plugin-prettier "^3.3.0" - eslint-plugin-promise "^4.2.1" - eslint-plugin-unicorn "^25.0.1" + eslint-plugin-prettier "^3.3.1" + eslint-plugin-promise "^4.3.1" + eslint-plugin-unicorn "^28.0.2" find-cache-dir "^3.3.1" find-up "^5.0.0" - fs-extra "^9.0.1" + fs-extra "^9.1.0" get-stdin "^8.0.0" globby "^9.2.0" has-flag "^4.0.0" imurmurhash "^0.1.4" is-path-inside "^3.0.2" json-stable-stringify-without-jsonify "^1.0.1" - json5 "^2.1.3" + json5 "^2.2.0" lodash "^4.17.20" - meow "^8.1.0" + meow "^9.0.0" micromatch "^4.0.2" open-editor "^3.0.0" p-reduce "^2.1.0" @@ -8782,8 +9107,8 @@ xo@^0.37.1: semver "^7.3.4" slash "^3.0.0" to-absolute-glob "^2.0.2" - typescript "^4.1.3" - update-notifier "^5.0.1" + typescript "^4.1.5" + update-notifier "^5.1.0" xtend@^4.0.0: version "4.0.2" @@ -8845,7 +9170,7 @@ yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.0.3: +yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -8890,7 +9215,7 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -ytdl-core@^4.4.5: +ytdl-core@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/ytdl-core/-/ytdl-core-4.5.0.tgz#f07733387c548e5c3a5614c93ef55bde666eeaf4" integrity sha512-e8r6skrakWNixsVlNPBMoRM1HrdW1swE97If9nenDUjF65uogYk4DvxIuqlmqRfBWKe+6aIZwqedNxUU9XLYJA== From 61d83be52e30110b183e107e6b0fdf948d72bfb8 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 9 Apr 2021 23:42:03 +0300 Subject: [PATCH 051/118] taskbar-mediacontrol no longer override win.hide (electron 11.4.2 fixed the bug that required that) --- plugins/taskbar-mediacontrol/back.js | 88 ++++++++++++++-------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index b4d7dd3c..73f35762 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -2,57 +2,55 @@ const getSongControls = require('../../providers/song-controls'); const getSongInfo = require('../../providers/song-info'); const path = require('path'); +let controls; +let CurrentSongInfo; + module.exports = win => { - win.hide = function () { - win.minimize(); - win.setSkipTaskbar(true); - }; - - const show = win.show; - win.show = function () { - win.restore(); - win.focus(); - win.setSkipTaskbar(false); - show.apply(win); - }; - - win.isVisible = function () { - return !win.isMinimized(); - }; - const registerCallback = getSongInfo(win); - const {playPause, next, previous} = getSongControls(win); + const { playPause, next, previous } = getSongControls(win); + controls = { playPause, next, previous } - // If the page is ready, register the callback - win.on('ready-to-show', () => { - registerCallback(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() {previous(win.webContents);} - }, { - tooltip: 'Play/Pause', - // Update icon based on play state - icon: songInfo.isPaused ? get('play.png') : get('pause.png'), - click() {playPause(win.webContents);} - }, { - tooltip: 'Next', - icon: get('forward.png'), - click() {next(win.webContents);} - } - ]); - }); + 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", () => { + if (CurrentSongInfo) { + 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); + return path.join(__dirname, "assets", file); } From 2b6cecc441278c70eff168c53c8c0a0964b7f3db Mon Sep 17 00:00:00 2001 From: Araxeus Date: Mon, 12 Apr 2021 20:56:52 +0300 Subject: [PATCH 052/118] Update ytpl --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index eb6eeadd..f900489c 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "filenamify": "^4.2.0", "node-fetch": "^2.6.1", "ytdl-core": "^4.5.0", - "ytpl": "^2.0.5" + "ytpl": "^2.1.1" }, "devDependencies": { "electron": "^11.4.2", diff --git a/yarn.lock b/yarn.lock index ede3d065..73394a47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6349,7 +6349,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -miniget@^4.0.0, miniget@^4.1.0: +miniget@^4.0.0, miniget@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/miniget/-/miniget-4.2.0.tgz#0004e95536b192d95a7d09f4435d67b9285481d0" integrity sha512-IzTOaNgBw/qEpzkPTE7X2cUVXQfSKbG8w52Emi93zb+Zya2ZFrbmavpixzebuDJD9Ku4ecbaFlC7Y1cEESzQtQ== @@ -9224,12 +9224,12 @@ ytdl-core@^4.5.0: miniget "^4.0.0" sax "^1.1.3" -ytpl@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ytpl/-/ytpl-2.0.5.tgz#c56900bccaf96e289304de647bc861121f61223e" - integrity sha512-8hc+f3pijaogj1yoZTCGImMDS4x0ogFPDsx1PefNQ+2EAhJMm1K4brcYT9zpJhPi9SXh+O103pEIHDw3+dAhxA== +ytpl@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ytpl/-/ytpl-2.1.1.tgz#c3c3e0e198e3fc7be13b52f5651e950b0aae94a0" + integrity sha512-yrU/w1k75f089zUONUm1QjlCv96QWhk/SS6jNEVJXMr8/9zEj4k2EIv81nk5wldJvpb+2rvEfm2zIwRqXRoZ9w== dependencies: - miniget "^4.1.0" + miniget "^4.2.0" zip-stream@^4.0.4: version "4.0.4" From c764d657d74fc5d85d0410ec1115d42e84bdc7df Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 14 Apr 2021 13:42:39 +0300 Subject: [PATCH 053/118] cleanup unresponsiveDialog --- index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/index.js b/index.js index addd98ed..13eaa2db 100644 --- a/index.js +++ b/index.js @@ -341,15 +341,11 @@ function showUnresponsiveDialog(win, details) { case 1: //if relaunch - relaunch+exit app.relaunch(); case 2: - app.exit(); + app.quit(); break; case 0: default: return; - //maybe set a timer and afterwards check responsivness and call function again if failed } }); } - -module.exports.aDialog = showUnresponsiveDialog; - From a2207a2cb391b6b961e841c45f82412790744711 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 14 Apr 2021 13:44:32 +0300 Subject: [PATCH 054/118] remove " - Topic" from artist name --- providers/song-info.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/providers/song-info.js b/providers/song-info.js index 131573c4..74fdda6a 100644 --- a/providers/song-info.js +++ b/providers/song-info.js @@ -46,6 +46,9 @@ const handleData = async (responseText, win) => { let data = JSON.parse(responseText); songInfo.title = data?.videoDetails?.title; songInfo.artist = data?.videoDetails?.author; + if (songInfo.artist.endsWith(" - Topic")) { + songInfo.artist = songInfo.artist.slice(0, -8); + } songInfo.views = data?.videoDetails?.viewCount; songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url; songInfo.songDuration = data?.videoDetails?.lengthSeconds; From bb6ad14111608d3b085a50e1c4a0a6d77ce37252 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 15 Apr 2021 12:40:09 +0300 Subject: [PATCH 055/118] navbar background black fix visual bug --- plugins/in-app-menu/style.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/in-app-menu/style.css b/plugins/in-app-menu/style.css index 19dd59fb..c6339093 100644 --- a/plugins/in-app-menu/style.css +++ b/plugins/in-app-menu/style.css @@ -21,6 +21,16 @@ ytmusic-pivot-bar-item-renderer { -webkit-app-region: unset !important; } +/* navbar background black */ +.center-content.ytmusic-nav-bar { + background: #030303; +} + +/* move up item selectrion renderer by 15 px */ +ytmusic-item-section-renderer[has-item-section-tabbed-header-renderer_] #header.ytmusic-item-section-renderer { + top: 75 !important; +} + /* fix weird positioning in search screen*/ ytmusic-header-renderer.ytmusic-search-page { position: unset !important; From ff6a486daf145c5a56ec5f500f29fdbf1c38391b Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 15 Apr 2021 15:34:05 +0300 Subject: [PATCH 056/118] fix unresponsive dialog response --- index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 13eaa2db..82ba695d 100644 --- a/index.js +++ b/index.js @@ -333,11 +333,11 @@ function showUnresponsiveDialog(win, details) { type: "error", title: "Window Unresponsive", message: "The Application is Unresponsive", - details: "We are sorry for the inconveniance! please choose what to do with the application:", + details: "We are sorry for the inconveniance! please choose what to do:", buttons: ["Wait", "Relaunch", "Quit"], cancelId: 0 - }).then( response => { - switch (response) { + }).then( result => { + switch (result.response) { case 1: //if relaunch - relaunch+exit app.relaunch(); case 2: @@ -345,7 +345,7 @@ function showUnresponsiveDialog(win, details) { break; case 0: default: - return; + break; } }); } From f765fb63f0cd937e5aa7f81ea91c95625fcf944f Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 15 Apr 2021 15:59:41 +0300 Subject: [PATCH 057/118] scrape artistName from playBar --- providers/song-info.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/providers/song-info.js b/providers/song-info.js index 74fdda6a..d2dbc962 100644 --- a/providers/song-info.js +++ b/providers/song-info.js @@ -28,6 +28,18 @@ const getPausedStatus = async (win) => { return !title.includes("-"); }; +const getArtist = async (win) => { + return await win.webContents.executeJavaScript( + ` + var bar = document.getElementsByClassName('subtitle ytmusic-player-bar')[0]; + var artistName = (bar.getElementsByClassName('yt-formatted-string')[0]) || (bar.getElementsByClassName('byline ytmusic-player-bar')[0]); + if (artistName) { + artistName.textContent; + } + ` + ) +} + // Fill songInfo with empty values const songInfo = { title: "", @@ -45,10 +57,7 @@ const songInfo = { const handleData = async (responseText, win) => { let data = JSON.parse(responseText); songInfo.title = data?.videoDetails?.title; - songInfo.artist = data?.videoDetails?.author; - if (songInfo.artist.endsWith(" - Topic")) { - songInfo.artist = songInfo.artist.slice(0, -8); - } + songInfo.artist = await getArtist(win) || data?.videoDetails?.author; songInfo.views = data?.videoDetails?.viewCount; songInfo.imageSrc = data?.videoDetails?.thumbnail?.thumbnails?.pop()?.url; songInfo.songDuration = data?.videoDetails?.lengthSeconds; From 9f848e3e764304ab7e5f1acb1c9c6069b24552fe Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 16 Apr 2021 02:19:07 +0000 Subject: [PATCH 058/118] 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 --- package.json | 2 +- yarn.lock | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index ce144c38..c06d7f5d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "npm": "Please use yarn and not npm" }, "dependencies": { - "@cliqz/adblocker-electron": "^1.20.1", + "@cliqz/adblocker-electron": "^1.20.4", "@ffmpeg/core": "^0.8.5", "@ffmpeg/ffmpeg": "^0.9.7", "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.8.1", diff --git a/yarn.lock b/yarn.lock index c969527e..362d11f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -282,41 +282,41 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@cliqz/adblocker-content@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.3.tgz#198c8719cd62ef3c67a5c98e7a54336b7812ed86" - integrity sha512-aCBTiIiNgVbmDIQyUcsn0j3n+umvs0DuVlL6dccPE3qfeFxT4whUvMwjxUS2/dIBfJK9A1LywmvVke2eSPw9wg== +"@cliqz/adblocker-content@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-content/-/adblocker-content-1.20.4.tgz#68c0c628acd6da49bb5a6ad9ee0cb540a8d50acd" + integrity sha512-Cp6M6MERCsLwklX6lAmrgOxom0pr4DjxmUGLcmM9MDACOIzk/m7ya1e82bXzEWAU1Jni2Bp91xUUWxg+DLWJgQ== dependencies: - "@cliqz/adblocker-extended-selectors" "^1.20.3" + "@cliqz/adblocker-extended-selectors" "^1.20.4" -"@cliqz/adblocker-electron-preload@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.3.tgz#17dff446ad742cb6e68a4572e7a75cff1fa33f95" - integrity sha512-fWAFEGj+F0VOUKZd2FqWLuguXmGzkRQz5wTCqasvndX4HSe0P8Pd2666pWK9RJW1dLJE7U61mQfTbYqlUFVTMA== +"@cliqz/adblocker-electron-preload@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron-preload/-/adblocker-electron-preload-1.20.4.tgz#b7d6606dfc24e7b3f80109cc6820bd203faaf26e" + integrity sha512-tIEgFJJhEDTYrSUzAL+wbw+BBVwCtuFtckA/scka990DGlXsEmkJ7HxNXvUPwhOQiV4YUwN5bsqxCDA8VDTZNw== dependencies: - "@cliqz/adblocker-content" "^1.20.3" + "@cliqz/adblocker-content" "^1.20.4" -"@cliqz/adblocker-electron@^1.20.1": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.3.tgz#f2b4bf5dddf90f64251c46f89238526dc0037384" - integrity sha512-ZcEl3W7R/aoUA0IPIMtvdn7gVE6O9+rDQ9OllIH/s/gVeElXZsgPEtpPMSuoJWbi9d2mlr8yo3UFvkV3u7c4gw== +"@cliqz/adblocker-electron@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-electron/-/adblocker-electron-1.20.4.tgz#6d7de52cff013ef3cd0f4a7850ebfc31f6240a46" + integrity sha512-HaHexPnJL1BBvloXuqmSh8WtpPKYHyZ+o6f+9SciySN4dJAX9BIGTk9D/V6eJWLmy6+wY7/Bpcn2Q4nrYXsqBw== dependencies: - "@cliqz/adblocker" "^1.20.3" - "@cliqz/adblocker-electron-preload" "^1.20.3" + "@cliqz/adblocker" "^1.20.4" + "@cliqz/adblocker-electron-preload" "^1.20.4" tldts-experimental "^5.6.21" -"@cliqz/adblocker-extended-selectors@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.3.tgz#a817915948ec4e64c8b878a80a71d911ea0412c8" - integrity sha512-Xsrqg4qgpNVx80UJrAz/nS8jcbgCTIGvir0MrjoXrw0GheqRxsgE540XXP9JA7QlifLNVEOO44DpHvhUmISkQw== +"@cliqz/adblocker-extended-selectors@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker-extended-selectors/-/adblocker-extended-selectors-1.20.4.tgz#6f5ab8251a0d40cacf3703f5621025e0d85d6348" + integrity sha512-VBP8iv1IdYpwQ0hbbeiXCSW7ppzK05dbPM4DyeCb54mB0CjWj/pMQwEvjMZKLWTkEyPd26oMqnxNQz1UgGaZag== -"@cliqz/adblocker@^1.20.3": - version "1.20.3" - resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.3.tgz#4e8d03ed03c476f7b4388d25f910b1b9e0b15cc9" - integrity sha512-Dqj8fJ399kFsFQ53uW0ajA5jH5VJ5ppawOjtoV2s+7NILj1ydvw40jTrr3l/ObMvxaAGaDUj2Euo4beg3/EtRQ== +"@cliqz/adblocker@^1.20.4": + version "1.20.4" + resolved "https://registry.yarnpkg.com/@cliqz/adblocker/-/adblocker-1.20.4.tgz#63f75456b6d63f66dc73b9ac2971ed073bf26722" + integrity sha512-ylwc4fScwgDjh9mKAvBQ+oCNyZWncrPakU17KbMtq+l82LkzJ0ND0wififpeq+nI9JBiQosW+eus5R08THpwCQ== dependencies: - "@cliqz/adblocker-content" "^1.20.3" - "@cliqz/adblocker-extended-selectors" "^1.20.3" + "@cliqz/adblocker-content" "^1.20.4" + "@cliqz/adblocker-extended-selectors" "^1.20.4" "@remusao/guess-url-type" "^1.1.2" "@remusao/small" "^1.1.2" "@remusao/smaz" "^1.7.1" From 40968d573c1c0dae1ac0c5d81a73ce6a1a14fdef Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 16 Apr 2021 21:52:56 +0300 Subject: [PATCH 059/118] add precise scrollwheel control + precise tooltip --- plugins/precise-volume/front.js | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 plugins/precise-volume/front.js diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js new file mode 100644 index 00000000..abf38955 --- /dev/null +++ b/plugins/precise-volume/front.js @@ -0,0 +1,74 @@ +module.exports = () => { + setupPlaybarOnwheel(); + setupObserver(); + firstTooltip(); +} + +function firstTooltip () { + const videoStream = document.querySelector(".video-stream"); + if (videoStream) { + setTooltip(Math.round(parseFloat(videoStream.volume) * 100)); + } else { + setTimeout(firstTooltip, 500); // try again in 500 milliseconds + } + } + +function setupPlaybarOnwheel() { + //add onwheel event to play bar + document.querySelector("ytmusic-player-bar").onwheel = (event) => { + event.preventDefault(); + //event.deltaY < 0 => wheel up + changeVolume(event.deltaY < 0) + } +} + +let newVolume; + + +function changeVolume(increase) { + //need to change both the slider and the actual volume + const videoStream = document.querySelector(".video-stream"); + const slider = document.querySelector("#volume-slider"); + //get the volume diff to apply + const diff = increase + ? videoStream.volume < 1 ? 0.01 : 0 + : videoStream.volume > 0 ? -0.01 : 0 + //apply on both elements and save the new volume + videoStream.volume += diff; + newVolume = Math.round(parseFloat(videoStream.volume) * 100); + slider.value = newVolume; + //finally change tooltip to new value + setTooltip(newVolume) +} + +//observer sets the tooltip when volume is manually changed +function setupObserver() { + const observer = new MutationObserver((mutations) => { + for (const mutation of mutations) { + //this checks that the new volume was manually set (without the new changeVolume() function) + if (mutation.oldValue !== mutation.target.value + && (!newVolume || Math.abs(newVolume - mutation.target.value) > 4)) { + //if diff>4 -> it was manually set, so update tooltip accordingly + setTooltip(mutation.target.value); + } + } + }); + + //observing only changes in value of volume-slider + observer.observe(document.querySelector("#volume-slider"), { + attributeFilter: ["value"], + attributeOldValue: true, + }); +} + +function setTooltip(newValue) { + newValue += "%"; + //set new volume as tooltip for volume slider and icon + document.querySelector("#volume-slider").title = newValue; + document.querySelector("tp-yt-paper-icon-button.volume.style-scope.ytmusic-player-bar").title = newValue; + + //also for expanding slider (appears when window size is small) + let expandingSlider = document.querySelector("#expanding-menu"); + expandingSlider.querySelector("#expand-volume-slider").title = newValue; + expandingSlider.querySelector("#expand-volume").title = newValue; +} \ No newline at end of file From c0ec1bc5cfc1468e158d759e236288ba50dee320 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 16 Apr 2021 22:37:34 +0300 Subject: [PATCH 060/118] update inline doc --- plugins/precise-volume/front.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index abf38955..603ae8ac 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -4,14 +4,14 @@ module.exports = () => { firstTooltip(); } -function firstTooltip () { +function firstTooltip() { const videoStream = document.querySelector(".video-stream"); if (videoStream) { setTooltip(Math.round(parseFloat(videoStream.volume) * 100)); } else { - setTimeout(firstTooltip, 500); // try again in 500 milliseconds + setTimeout(firstTooltip, 500); // try again in 500 milliseconds } - } +} function setupPlaybarOnwheel() { //add onwheel event to play bar @@ -22,8 +22,8 @@ function setupPlaybarOnwheel() { } } -let newVolume; - +//the last volume set by changeVolume() is stored here +let newVolume; //used to determine if volume-slider was manually moved function changeVolume(increase) { //need to change both the slider and the actual volume @@ -41,20 +41,20 @@ function changeVolume(increase) { setTooltip(newVolume) } -//observer sets the tooltip when volume is manually changed +//update the volume tooltip when volume-slider is manually changed function setupObserver() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { - //this checks that the new volume was manually set (without the new changeVolume() function) + //this checks that volume-slider was manually set if (mutation.oldValue !== mutation.target.value && (!newVolume || Math.abs(newVolume - mutation.target.value) > 4)) { - //if diff>4 -> it was manually set, so update tooltip accordingly + //diff>4 means it was manually set, so update tooltip accordingly setTooltip(mutation.target.value); } } }); - //observing only changes in value of volume-slider + //observing only changes in 'value' of volume-slider observer.observe(document.querySelector("#volume-slider"), { attributeFilter: ["value"], attributeOldValue: true, From 02896cac03c587e5003b51c2c91f20842c66c9c8 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 16 Apr 2021 23:02:16 +0300 Subject: [PATCH 061/118] xo --fix --- plugins/precise-volume/front.js | 121 ++++++++++++++++---------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 603ae8ac..d6aa4073 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,74 +1,75 @@ module.exports = () => { - setupPlaybarOnwheel(); - setupObserver(); - firstTooltip(); + setPlaybarOnwheel(); + setObserver(); + setFirstTooltip(); +}; + +function setFirstTooltip() { + const videoStream = document.querySelector(".video-stream"); + if (videoStream?.volume) { + setTooltip(Math.round(parseFloat(videoStream.volume) * 100)); + } else { + setTimeout(setFirstTooltip, 500); // Try again in 500 milliseconds + } } -function firstTooltip() { - const videoStream = document.querySelector(".video-stream"); - if (videoStream) { - setTooltip(Math.round(parseFloat(videoStream.volume) * 100)); - } else { - setTimeout(firstTooltip, 500); // try again in 500 milliseconds - } +function setPlaybarOnwheel() { + // Add onwheel event to play bar + document.querySelector("ytmusic-player-bar").onwheel = event => { + event.preventDefault(); + // Event.deltaY < 0 => wheel up + changeVolume(event.deltaY < 0); + }; } -function setupPlaybarOnwheel() { - //add onwheel event to play bar - document.querySelector("ytmusic-player-bar").onwheel = (event) => { - event.preventDefault(); - //event.deltaY < 0 => wheel up - changeVolume(event.deltaY < 0) - } -} - -//the last volume set by changeVolume() is stored here -let newVolume; //used to determine if volume-slider was manually moved +// The last volume set by changeVolume() is stored here +let newVolume; // Used to determine if volume-slider was manually moved function changeVolume(increase) { - //need to change both the slider and the actual volume - const videoStream = document.querySelector(".video-stream"); - const slider = document.querySelector("#volume-slider"); - //get the volume diff to apply - const diff = increase - ? videoStream.volume < 1 ? 0.01 : 0 - : videoStream.volume > 0 ? -0.01 : 0 - //apply on both elements and save the new volume - videoStream.volume += diff; - newVolume = Math.round(parseFloat(videoStream.volume) * 100); - slider.value = newVolume; - //finally change tooltip to new value - setTooltip(newVolume) + // Need to change both the slider and the actual volume + const videoStream = document.querySelector(".video-stream"); + const slider = document.querySelector("#volume-slider"); + // Get the volume diff to apply + const diff = increase ? + (videoStream.volume < 1 ? 0.01 : 0) : + (videoStream.volume > 0 ? -0.01 : 0); + // Apply on both elements and save the new volume + videoStream.volume += diff; + newVolume = Math.round(Number.parseFloat(videoStream.volume) * 100); + // Slider value automatically rounds to multiples of 5 + slider.value = newVolume; + // Finally change tooltip to new value + setTooltip(newVolume); } -//update the volume tooltip when volume-slider is manually changed -function setupObserver() { - const observer = new MutationObserver((mutations) => { - for (const mutation of mutations) { - //this checks that volume-slider was manually set - if (mutation.oldValue !== mutation.target.value - && (!newVolume || Math.abs(newVolume - mutation.target.value) > 4)) { - //diff>4 means it was manually set, so update tooltip accordingly - setTooltip(mutation.target.value); - } - } - }); +// Update the volume tooltip when volume-slider is manually changed +function setObserver() { + const observer = new MutationObserver(mutations => { + for (const mutation of mutations) { + // This checks that volume-slider was manually set + if (mutation.oldValue !== mutation.target.value && + (!newVolume || Math.abs(newVolume - mutation.target.value) > 4)) { + // Diff>4 means it was manually set, so update tooltip accordingly + setTooltip(mutation.target.value); + } + } + }); - //observing only changes in 'value' of volume-slider - observer.observe(document.querySelector("#volume-slider"), { - attributeFilter: ["value"], - attributeOldValue: true, - }); + // Observing only changes in 'value' of volume-slider + observer.observe(document.querySelector("#volume-slider"), { + attributeFilter: ["value"], + attributeOldValue: true + }); } function setTooltip(newValue) { - newValue += "%"; - //set new volume as tooltip for volume slider and icon - document.querySelector("#volume-slider").title = newValue; - document.querySelector("tp-yt-paper-icon-button.volume.style-scope.ytmusic-player-bar").title = newValue; + newValue += "%"; + // Set new volume as tooltip for volume slider and icon + document.querySelector("#volume-slider").title = newValue; + document.querySelector("tp-yt-paper-icon-button.volume.style-scope.ytmusic-player-bar").title = newValue; - //also for expanding slider (appears when window size is small) - let expandingSlider = document.querySelector("#expanding-menu"); - expandingSlider.querySelector("#expand-volume-slider").title = newValue; - expandingSlider.querySelector("#expand-volume").title = newValue; -} \ No newline at end of file + // Also for expanding slider (appears when window size is small) + const expandingSlider = document.querySelector("#expanding-menu"); + expandingSlider.querySelector("#expand-volume-slider").title = newValue; + expandingSlider.querySelector("#expand-volume").title = newValue; +} From 06958c424c81f6ac24597b0e0fbb8cb43f08b81f Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 16 Apr 2021 23:30:43 +0300 Subject: [PATCH 062/118] refactor --- plugins/precise-volume/front.js | 53 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index d6aa4073..45292194 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -7,19 +7,19 @@ module.exports = () => { function setFirstTooltip() { const videoStream = document.querySelector(".video-stream"); if (videoStream?.volume) { - setTooltip(Math.round(parseFloat(videoStream.volume) * 100)); + setTooltip(toPercent(videoStream.volume)); } else { setTimeout(setFirstTooltip, 500); // Try again in 500 milliseconds } } function setPlaybarOnwheel() { - // Add onwheel event to play bar - document.querySelector("ytmusic-player-bar").onwheel = event => { - event.preventDefault(); - // Event.deltaY < 0 => wheel up - changeVolume(event.deltaY < 0); - }; + // Add onwheel event to play bar + document.querySelector("ytmusic-player-bar").onwheel = event => { + event.preventDefault(); + // Event.deltaY < 0 => wheel up + changeVolume(event.deltaY < 0); + }; } // The last volume set by changeVolume() is stored here @@ -29,13 +29,14 @@ function changeVolume(increase) { // Need to change both the slider and the actual volume const videoStream = document.querySelector(".video-stream"); const slider = document.querySelector("#volume-slider"); - // Get the volume diff to apply - const diff = increase ? - (videoStream.volume < 1 ? 0.01 : 0) : - (videoStream.volume > 0 ? -0.01 : 0); - // Apply on both elements and save the new volume - videoStream.volume += diff; - newVolume = Math.round(Number.parseFloat(videoStream.volume) * 100); + + // Apply volume change if valid + videoStream.volume = increase ? + Math.min(videoStream.volume + 0.01, 1) : + Math.max(videoStream.volume - 0.01, 0); + + // Save the new volume + newVolume = toPercent(videoStream.volume); // Slider value automatically rounds to multiples of 5 slider.value = newVolume; // Finally change tooltip to new value @@ -62,14 +63,22 @@ function setObserver() { }); } +// 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.style-scope.ytmusic-player-bar", + "#expand-volume-slider", + "#expand-volume" +]; + function setTooltip(newValue) { newValue += "%"; - // Set new volume as tooltip for volume slider and icon - document.querySelector("#volume-slider").title = newValue; - document.querySelector("tp-yt-paper-icon-button.volume.style-scope.ytmusic-player-bar").title = newValue; - - // Also for expanding slider (appears when window size is small) - const expandingSlider = document.querySelector("#expanding-menu"); - expandingSlider.querySelector("#expand-volume-slider").title = newValue; - expandingSlider.querySelector("#expand-volume").title = newValue; + for (target of tooltipTargets) { + document.querySelector(target).title = newValue; + } } + +function toPercent(volume) { + return Math.round(Number.parseFloat(volume) * 100); +} + From b65bc65d7c29cc6c8df2b96529b7f6274b28fee0 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 01:58:33 +0300 Subject: [PATCH 063/118] save volume to settings --- plugins/precise-volume/front.js | 62 ++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 45292194..395cee31 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,31 +1,42 @@ -module.exports = () => { - setPlaybarOnwheel(); - setObserver(); - setFirstTooltip(); +const { setOptions } = require("../../config/plugins"); + +module.exports = (options) => { + setPlaybarOnwheel(options); + setObserver(options); + firstRun(options); }; -function setFirstTooltip() { +function saveVolume(volume, options) { + options.savedVolume = volume; + setOptions("precise-volume", options); +} + +function firstRun(options) { const videoStream = document.querySelector(".video-stream"); - if (videoStream?.volume) { + if (videoStream) { + // Set saved volume if it exists and is valid + if (options.savedVolume && options.savedVolume >= 0 && options.savedVolume <= 100) { + videoStream.volume = options.savedVolume / 100; + document.querySelector("#volume-slider").value = options.savedVolume; + } + + // Set current volume as tooltip setTooltip(toPercent(videoStream.volume)); } else { - setTimeout(setFirstTooltip, 500); // Try again in 500 milliseconds + setTimeout(firstRun, 500, options); // Try again in 500 milliseconds } } -function setPlaybarOnwheel() { - // Add onwheel event to play bar - document.querySelector("ytmusic-player-bar").onwheel = event => { - event.preventDefault(); - // Event.deltaY < 0 => wheel up - changeVolume(event.deltaY < 0); - }; +function setPlaybarOnwheel(options) { + // Add onwheel event to play bar + document.querySelector("ytmusic-player-bar").onwheel = event => { + event.preventDefault(); + // Event.deltaY < 0 => wheel up + changeVolume(event.deltaY < 0, options); + }; } -// The last volume set by changeVolume() is stored here -let newVolume; // Used to determine if volume-slider was manually moved - -function changeVolume(increase) { +function changeVolume(increase, options) { // Need to change both the slider and the actual volume const videoStream = document.querySelector(".video-stream"); const slider = document.querySelector("#volume-slider"); @@ -36,22 +47,23 @@ function changeVolume(increase) { Math.max(videoStream.volume - 0.01, 0); // Save the new volume - newVolume = toPercent(videoStream.volume); + saveVolume(toPercent(videoStream.volume), options); // Slider value automatically rounds to multiples of 5 - slider.value = newVolume; + slider.value = options.savedVolume; // Finally change tooltip to new value - setTooltip(newVolume); + setTooltip(options.savedVolume); } -// Update the volume tooltip when volume-slider is manually changed -function setObserver() { +// Save volume + Update the volume tooltip when volume-slider is manually changed +function setObserver(options) { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { // This checks that volume-slider was manually set if (mutation.oldValue !== mutation.target.value && - (!newVolume || Math.abs(newVolume - mutation.target.value) > 4)) { - // Diff>4 means it was manually set, so update tooltip accordingly + (!options.savedVolume || Math.abs(options.savedVolume - mutation.target.value) > 4)) { + // Diff>4 means it was manually set setTooltip(mutation.target.value); + saveVolume(mutation.target.value, options); } } }); From 5adcc3efadc985bbfa4d6552f0f6592255a5a887 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 02:38:45 +0300 Subject: [PATCH 064/118] fix set volume on first run after not using plugin --- plugins/precise-volume/front.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 395cee31..ce657fb1 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -13,11 +13,17 @@ function saveVolume(volume, options) { function firstRun(options) { const videoStream = document.querySelector(".video-stream"); - if (videoStream) { - // Set saved volume if it exists and is valid - if (options.savedVolume && options.savedVolume >= 0 && options.savedVolume <= 100) { + const slider = document.querySelector("#volume-slider"); + + if (videoStream && slider) { + // Set saved volume if it pass checks + if (options.savedVolume + && options.savedVolume >= 0 && options.savedVolume <= 100 + && Math.abs(slider.value - options.savedVolume) < 5 + // If plugin was disabled and volume changed then diff>4 + ) { videoStream.volume = options.savedVolume / 100; - document.querySelector("#volume-slider").value = options.savedVolume; + slider.value = options.savedVolume; } // Set current volume as tooltip From 94e152bb571ad79c7cb889ea4f6482cd3d5371be Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 04:14:54 +0300 Subject: [PATCH 065/118] add optional arrowkeys controls option --- plugins/precise-volume/front.js | 24 ++++++++++++++++++++++++ plugins/precise-volume/menu.js | 10 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 plugins/precise-volume/menu.js diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index ce657fb1..18b1b45c 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,9 +1,11 @@ const { setOptions } = require("../../config/plugins"); +const { ipcRenderer } = require("electron"); module.exports = (options) => { setPlaybarOnwheel(options); setObserver(options); firstRun(options); + setupArrowShortcuts(options); }; function saveVolume(volume, options) { @@ -42,6 +44,28 @@ function setPlaybarOnwheel(options) { }; } +function setupArrowShortcuts(options) { + //change options from renderer to keep sync + ipcRenderer.on("setArrowsShortcut", (event, value) => { + options.arrowsShortcut = value; + setOptions("precise-volume", options); + }); + + //register shortcuts if enabled + if (options.arrowsShortcut) { + window.addEventListener('keydown', (event) => { + switch (event.code) { + case `ArrowUp`: + changeVolume(true, options); + break; + case `ArrowDown`: + changeVolume(false, options); + break; + } + }, true); + } +} + function changeVolume(increase, options) { // Need to change both the slider and the actual volume const videoStream = document.querySelector(".video-stream"); diff --git a/plugins/precise-volume/menu.js b/plugins/precise-volume/menu.js new file mode 100644 index 00000000..9b870efd --- /dev/null +++ b/plugins/precise-volume/menu.js @@ -0,0 +1,10 @@ +module.exports = (win, options) => [ + { + label: "Arrowkeys controls", + type: "checkbox", + checked: !!options.arrowsShortcut, + click: (item) => { + win.webContents.send("setArrowsShortcut", item.checked); + } + } +]; From 834202411d4c02cb83bfbe52354c5b6aa61b35db Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 04:38:23 +0300 Subject: [PATCH 066/118] enable changing shortcut setting without restart --- plugins/precise-volume/front.js | 40 +++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 18b1b45c..7aa42dc5 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -46,23 +46,39 @@ function setPlaybarOnwheel(options) { function setupArrowShortcuts(options) { //change options from renderer to keep sync - ipcRenderer.on("setArrowsShortcut", (event, value) => { - options.arrowsShortcut = value; + ipcRenderer.on("setArrowsShortcut", (event, isEnabled) => { + options.arrowsShortcut = isEnabled; setOptions("precise-volume", options); + //can setting without restarting app + if (isEnabled) { + addListener(); + } else { + removeListener(); + } }); //register shortcuts if enabled if (options.arrowsShortcut) { - window.addEventListener('keydown', (event) => { - switch (event.code) { - case `ArrowUp`: - changeVolume(true, options); - break; - case `ArrowDown`: - changeVolume(false, options); - break; - } - }, true); + addListener(); + } + + function addListener() { + window.addEventListener('keydown', callback); + } + + function removeListener() { + window.removeEventListener("keydown", callback); + } + + function callback(event) { + switch (event.code) { + case `ArrowUp`: + changeVolume(true, options); + break; + case `ArrowDown`: + changeVolume(false, options); + break; + } } } From 49698ea6693462524a88b07b87e82b06e560dda2 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 05:08:07 +0300 Subject: [PATCH 067/118] fix changing settings when plugin is disabled --- plugins/precise-volume/back.js | 12 ++++++++++++ plugins/precise-volume/menu.js | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 plugins/precise-volume/back.js diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js new file mode 100644 index 00000000..7582f4ce --- /dev/null +++ b/plugins/precise-volume/back.js @@ -0,0 +1,12 @@ +/* +this is used to determine if plugin is actually active +(not if its only enabled in options) +*/ +let enabled = false; +module.exports = (win,options) => { + enabled = true; +}; + +module.exports.enabled = () => { + return enabled; +}; \ No newline at end of file diff --git a/plugins/precise-volume/menu.js b/plugins/precise-volume/menu.js index 9b870efd..a906addf 100644 --- a/plugins/precise-volume/menu.js +++ b/plugins/precise-volume/menu.js @@ -1,10 +1,19 @@ +const { enabled } = require("./back") +const { setOptions } = require("../../config/plugins"); + module.exports = (win, options) => [ { label: "Arrowkeys controls", type: "checkbox", checked: !!options.arrowsShortcut, click: (item) => { - win.webContents.send("setArrowsShortcut", item.checked); + //dynamically change setting if plugin enabled + if (enabled()) { + win.webContents.send("setArrowsShortcut", item.checked); + } else { //fallback to usual method if disabled + options.arrowsShortcut = item.checked; + setOptions("precise-volume", options); + } } } ]; From 12a2517697f1f66396faed8653259ee012585491 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 15:03:19 +0300 Subject: [PATCH 068/118] xo --fix --- plugins/precise-volume/back.js | 10 +++++----- plugins/precise-volume/front.js | 27 +++++++++++++-------------- plugins/precise-volume/menu.js | 18 +++++++++--------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index 7582f4ce..e6b101f9 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -1,12 +1,12 @@ /* -this is used to determine if plugin is actually active +This is used to determine if plugin is actually active (not if its only enabled in options) */ let enabled = false; -module.exports = (win,options) => { - enabled = true; +module.exports = () => { + enabled = true; }; module.exports.enabled = () => { - return enabled; -}; \ No newline at end of file + return enabled; +}; diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 7aa42dc5..d6424df1 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -3,9 +3,9 @@ const { ipcRenderer } = require("electron"); module.exports = (options) => { setPlaybarOnwheel(options); - setObserver(options); - firstRun(options); + setupObserver(options); setupArrowShortcuts(options); + firstRun(options); }; function saveVolume(volume, options) { @@ -45,11 +45,16 @@ function setPlaybarOnwheel(options) { } function setupArrowShortcuts(options) { - //change options from renderer to keep sync + // Register shortcuts if enabled + if (options.arrowsShortcut) { + addListener(); + } + + // Change options from renderer to keep sync ipcRenderer.on("setArrowsShortcut", (event, isEnabled) => { options.arrowsShortcut = isEnabled; setOptions("precise-volume", options); - //can setting without restarting app + // Can setting without restarting app if (isEnabled) { addListener(); } else { @@ -57,11 +62,6 @@ function setupArrowShortcuts(options) { } }); - //register shortcuts if enabled - if (options.arrowsShortcut) { - addListener(); - } - function addListener() { window.addEventListener('keydown', callback); } @@ -101,7 +101,7 @@ function changeVolume(increase, options) { } // Save volume + Update the volume tooltip when volume-slider is manually changed -function setObserver(options) { +function setupObserver(options) { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { // This checks that volume-slider was manually set @@ -129,14 +129,13 @@ const tooltipTargets = [ "#expand-volume" ]; -function setTooltip(newValue) { - newValue += "%"; +function setTooltip(volume) { + const tooltip = volume + "%"; for (target of tooltipTargets) { - document.querySelector(target).title = newValue; + document.querySelector(target).title = tooltip; } } function toPercent(volume) { return Math.round(Number.parseFloat(volume) * 100); } - diff --git a/plugins/precise-volume/menu.js b/plugins/precise-volume/menu.js index a906addf..d4ed37a7 100644 --- a/plugins/precise-volume/menu.js +++ b/plugins/precise-volume/menu.js @@ -1,4 +1,4 @@ -const { enabled } = require("./back") +const { enabled } = require("./back"); const { setOptions } = require("../../config/plugins"); module.exports = (win, options) => [ @@ -7,13 +7,13 @@ module.exports = (win, options) => [ type: "checkbox", checked: !!options.arrowsShortcut, click: (item) => { - //dynamically change setting if plugin enabled - if (enabled()) { - win.webContents.send("setArrowsShortcut", item.checked); - } else { //fallback to usual method if disabled - options.arrowsShortcut = item.checked; - setOptions("precise-volume", options); - } - } + // Dynamically change setting if plugin enabled + if (enabled()) { + win.webContents.send("setArrowsShortcut", item.checked); + } else { // Fallback to usual method if disabled + options.arrowsShortcut = item.checked; + setOptions("precise-volume", options); + } + } } ]; From c48260f10c80346c346b035858a61ac70e559e1b Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 16:42:13 +0300 Subject: [PATCH 069/118] add advanced option to change volume steps --- config/defaults.js | 6 ++++++ plugins/precise-volume/front.js | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index fb87e566..4b484951 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -45,6 +45,12 @@ const defaultConfig = { enabled: false, urgency: "normal", unpauseNotification: false + }, + "precise-volume": { + enabled: false, + steps: 1, //percentage of volume to change + arrowsShortcut: true, //enable ArrowUp + ArrowDown local shortcuts + savedVolume: undefined //plugin save volume between session here } }, }; diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index d6424df1..ed0cf4c5 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -86,11 +86,12 @@ function changeVolume(increase, options) { // Need to change both the slider and the actual volume const videoStream = document.querySelector(".video-stream"); const slider = document.querySelector("#volume-slider"); - + // Apply volume change if valid + const steps = options.steps / 100; videoStream.volume = increase ? - Math.min(videoStream.volume + 0.01, 1) : - Math.max(videoStream.volume - 0.01, 0); + Math.min(videoStream.volume + steps, 1) : + Math.max(videoStream.volume - steps, 0); // Save the new volume saveVolume(toPercent(videoStream.volume), options); From 341a06aae70cf42b913ca73f5a0deb5b3afa3537 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 20:30:06 +0300 Subject: [PATCH 070/118] add prompt with number counter --- menu.js | 2 +- package.json | 1 - providers/prompt/dark-prompt.css | 5 ++ providers/prompt/index.js | 16 ++++- providers/prompt/page/prompt.css | 32 +++++++++ providers/prompt/page/prompt.js | 114 +++++++++++++++++++++++-------- providers/prompt/readme.md | 5 +- yarn.lock | 12 ---- 8 files changed, 140 insertions(+), 47 deletions(-) diff --git a/menu.js b/menu.js index 90487970..588dad7c 100644 --- a/menu.js +++ b/menu.js @@ -335,7 +335,7 @@ function setProxy(item, win) { }); } prompt(options, win) - .then((input) => { + .then(input => { if (input !== null && input !== example) { config.set("options.proxy", input); item.checked = input !== ""; diff --git a/package.json b/package.json index 144ac53f..a856babf 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "browser-id3-writer": "^4.4.0", "custom-electron-titlebar": "^3.2.6", "discord-rpc": "^3.2.0", - "doc-ready": "^1.0.4", "downloads-folder": "^3.0.1", "electron-debug": "^3.2.0", "electron-is": "^3.0.0", diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css index 49e0f88e..74fea61e 100644 --- a/providers/prompt/dark-prompt.css +++ b/providers/prompt/dark-prompt.css @@ -45,3 +45,8 @@ body { background-color: rgb(0, 0, 0); color: whitesmoke; } + +.minus, +.plus { + background:rgb(0, 0, 0); +} \ No newline at end of file diff --git a/providers/prompt/index.js b/providers/prompt/index.js index bbba8b78..1c14cfa2 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -6,7 +6,9 @@ const url = require("url"); const path = require("path"); const DEFAULT_WIDTH = 370; +const DEFAULT_COUNTER_WIDTH = 300; const DEFAULT_HEIGHT = 160; +const DEFAULT_COUNTER_HEIGHT= 150; function electronPrompt(options, parentWindow) { return new Promise((resolve, reject) => { @@ -18,8 +20,6 @@ function electronPrompt(options, parentWindow) { { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT, - minWidth: DEFAULT_WIDTH, - minHeight: DEFAULT_HEIGHT, resizable: false, title: "Prompt", label: "Please input a value:", @@ -40,6 +40,11 @@ function electronPrompt(options, parentWindow) { options || {} ); + options_.minWidth = options.minWidth || options.width || + options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH; + options_.minHeight = options.minHeight || options.height || + options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT; + if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { reject(new Error('"selectOptions" must be an object')); return; @@ -136,6 +141,13 @@ function electronPrompt(options, parentWindow) { reject(new Error("prompt.html did-fail-load, log:\n", + log.toString())); }); + const promptUrl = url.format({ + protocol: 'file', + slashes: true, + pathname: path.join(__dirname, 'page', 'prompt.html'), + hash: id + }); + //Finally, load prompt promptWindow.loadURL(promptUrl); }); diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css index c3530e57..10654b8d 100644 --- a/providers/prompt/page/prompt.css +++ b/providers/prompt/page/prompt.css @@ -78,3 +78,35 @@ select#data { background-color: #ddd; color: black; } + +/* Counter mode css */ + +span { + cursor: pointer; +} +.number { + margin: 100px; +} +.minus, +.plus { + user-select: none; + width: 20px; + height: 20px; + background: #f2f2f2; + border-radius: 4px; + padding: 8px 5px 8px 5px; + border: 1px solid #ddd; + display: inline-block; + vertical-align: middle; + text-align: center; +} +.inputt { + height: 34px; + width: 100px; + text-align: center; + font-size: 26px; + border: 1px solid #ddd; + border-radius: 4px; + display: inline-block; + vertical-align: middle; +} diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index b7a54120..042ba546 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -1,13 +1,13 @@ const fs = require("fs"); const {ipcRenderer} = require("electron"); -const docReady = require("doc-ready"); let promptId = null; let promptOptions = null; +function $(selector) {return document.querySelector(selector)} + +document.addEventListener( 'DOMContentLoaded', promptRegister); -docReady(promptRegister); -//start here function promptRegister() { //get custom session id promptId = document.location.hash.replace("#", ""); @@ -21,18 +21,18 @@ function promptRegister() { //set label if (promptOptions.useHtmlLabel) { - document.querySelector("#label").innerHTML = promptOptions.label; + $("#label").innerHTML = promptOptions.label; } else { - document.querySelector("#label").textContent = promptOptions.label; + $("#label").textContent = promptOptions.label; } //set button label if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { - document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok; + $("#ok").textContent = promptOptions.buttonLabels.ok; } if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { - document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel; + $("#cancel").textContent = promptOptions.buttonLabels.cancel; } //inject custom stylesheet from options @@ -51,26 +51,40 @@ function promptRegister() { } //add button listeners - document.querySelector("#form").addEventListener("submit", promptSubmit); - document.querySelector("#cancel").addEventListener("click", promptCancel); + $("#form").addEventListener("submit", promptSubmit); + $("#cancel").addEventListener("click", promptCancel); //create input/select - const dataContainerElement = document.querySelector("#data-container"); + const dataContainerElement = $("#data-container"); let dataElement; - if (promptOptions.type === "input") { - dataElement = promptCreateInput(); - } else if (promptOptions.type === "select") { - dataElement = promptCreateSelect(); - } else { - return promptError(`Unhandled input type '${promptOptions.type}'`); - } - dataContainerElement.append(dataElement); + switch (promptOptions.type) { + case "counter": + case "input": + dataElement = promptCreateInput(); + break; + case "select": + dataElement = promptCreateSelect(); + break; + default: + return promptError(`Unhandled input type '${promptOptions.type}'`); + } + if (promptOptions.type === "counter") { + dataElement.classList.add("input"); + dataElement.style.width = "unset"; + dataElement.style["text-align"] = "center"; + //dataElement.style["min-height"] = "1.5em"; + dataContainerElement.append(createMinus(dataElement)); + dataContainerElement.append(dataElement); + dataContainerElement.append(createPlus(dataElement)); + } else { + dataContainerElement.append(dataElement); + } dataElement.setAttribute("id", "data"); dataElement.focus(); - if (promptOptions.type === "input") { + if (promptOptions.type === "input" || promptOptions.type === "counter") { dataElement.select(); } @@ -87,7 +101,8 @@ function promptRegister() { window.addEventListener("error", error => { if (promptId) { - promptError("An error has occured on the prompt window: \n" + error); + promptError("An error has occured on the prompt window: \n" + JSON.stringify(error, ["message", "arguments", "type", "name"]) + ); } }); @@ -107,15 +122,23 @@ function promptCancel() { //transfer input data to back function promptSubmit() { - const dataElement = document.querySelector("#data"); + const dataElement = $("#data"); let data = null; - if (promptOptions.type === "input") { - data = dataElement.value; - } else if (promptOptions.type === "select") { - data = promptOptions.selectMultiple ? - dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) : - dataElement.value; + switch (promptOptions.type) { + case "input": + data = dataElement.value; + break; + case "counter": + data = validateCounterInput(dataElement.value); + break; + case "select": + data = promptOptions.selectMultiple ? + dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) : + dataElement.value; + break; + default: //will never happen + return promptError(`Unhandled input type '${promptOptions.type}'`); } ipcRenderer.sendSync("prompt-post-data:" + promptId, data); @@ -127,6 +150,9 @@ function promptCreateInput() { dataElement.setAttribute("type", "text"); if (promptOptions.value) { + if (promptOptions.type === "counter") { + promptOptions.value = validateCounterInput(promptOptions.value); + } dataElement.value = promptOptions.value; } else { dataElement.value = ""; @@ -150,11 +176,11 @@ function promptCreateInput() { } }); - //Confrim on 'Enter' + //Confirm on 'Enter' dataElement.addEventListener("keypress", event => { if (event.key === "Enter") { event.preventDefault(); - document.querySelector("#ok").click(); + $("#ok").click(); } }); @@ -184,5 +210,35 @@ function promptCreateSelect() { return dataElement; } +function createMinus(dataElement) { + const minus = document.createElement("span"); + minus.textContent = "-"; + minus.classList.add("minus"); + minus.onmousedown = () => { + dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); + }; + return minus; +} +function createPlus(dataElement) { + const plus = document.createElement("span"); + plus.textContent = "+"; + plus.classList.add("plus"); + plus.onmousedown = () => { + dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1); + }; + return plus; +} +//validate counter +function validateCounterInput(input) { + const min = promptOptions.counterOptions?.minimum, + max = promptOptions.counterOptions?.maximum; + if (min !== undefined && input < min) { + return min; + } + if (max !== undefined && input > max) { + return max; + } + return input; +} diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md index 6683aced..eff1f907 100644 --- a/providers/prompt/readme.md +++ b/providers/prompt/readme.md @@ -43,8 +43,9 @@ prompt({ | label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. | | buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. | | value | (optional, string) The default value for the input field. Defaults to null. | -| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. | -| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' | +| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. | +| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' +| counterOptions | (optional, object) minimum and maximum of counter in format: `{minimum: %int%, maximum: %int%} ` | | selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | | useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | | width | (optional, integer) The width of the prompt window. Defaults to 370. | diff --git a/yarn.lock b/yarn.lock index f9909214..c969527e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2908,13 +2908,6 @@ dmg-builder@22.9.1: js-yaml "^3.14.0" sanitize-filename "^1.6.3" -doc-ready@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/doc-ready/-/doc-ready-1.0.4.tgz#37f5391969cff994303fdfef2e5d50357f8164d3" - integrity sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM= - dependencies: - eventie "^1" - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -3612,11 +3605,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eventie@^1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/eventie/-/eventie-1.0.6.tgz#d4ffc8b0c2b5e493c2aa1b22cbe918d3aee74437" - integrity sha1-1P/IsMK15JPCqhsiy+kY067nRDc= - events@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" From 3f50ab7cfc8c0efcacd35848baf2cf499f8f4706 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 20:43:48 +0300 Subject: [PATCH 071/118] lint --- providers/prompt/dark-prompt.css | 4 ++-- providers/prompt/page/prompt.css | 14 -------------- providers/prompt/page/prompt.js | 11 +++++------ 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css index 74fea61e..8bf39791 100644 --- a/providers/prompt/dark-prompt.css +++ b/providers/prompt/dark-prompt.css @@ -48,5 +48,5 @@ body { .minus, .plus { - background:rgb(0, 0, 0); -} \ No newline at end of file + background: rgb(0, 0, 0); +} diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css index 10654b8d..3224cf6a 100644 --- a/providers/prompt/page/prompt.css +++ b/providers/prompt/page/prompt.css @@ -80,13 +80,9 @@ select#data { } /* Counter mode css */ - span { cursor: pointer; } -.number { - margin: 100px; -} .minus, .plus { user-select: none; @@ -100,13 +96,3 @@ span { vertical-align: middle; text-align: center; } -.inputt { - height: 34px; - width: 100px; - text-align: center; - font-size: 26px; - border: 1px solid #ddd; - border-radius: 4px; - display: inline-block; - vertical-align: middle; -} diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 042ba546..d3abfeab 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -1,12 +1,12 @@ const fs = require("fs"); -const {ipcRenderer} = require("electron"); +const { ipcRenderer } = require("electron"); let promptId = null; let promptOptions = null; -function $(selector) {return document.querySelector(selector)} +function $(selector) { return document.querySelector(selector) } -document.addEventListener( 'DOMContentLoaded', promptRegister); +document.addEventListener('DOMContentLoaded', promptRegister); function promptRegister() { //get custom session id @@ -71,7 +71,6 @@ function promptRegister() { return promptError(`Unhandled input type '${promptOptions.type}'`); } if (promptOptions.type === "counter") { - dataElement.classList.add("input"); dataElement.style.width = "unset"; dataElement.style["text-align"] = "center"; //dataElement.style["min-height"] = "1.5em"; @@ -215,7 +214,7 @@ function createMinus(dataElement) { minus.textContent = "-"; minus.classList.add("minus"); minus.onmousedown = () => { - dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); + dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); }; return minus; } @@ -233,7 +232,7 @@ function createPlus(dataElement) { //validate counter function validateCounterInput(input) { const min = promptOptions.counterOptions?.minimum, - max = promptOptions.counterOptions?.maximum; + max = promptOptions.counterOptions?.maximum; if (min !== undefined && input < min) { return min; } From 97a9e632317c674bae580f818d474fd21487698d Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 21:17:07 +0300 Subject: [PATCH 072/118] xo --fix --- preload.js | 2 +- providers/{frontLogger.js => front-logger.js} | 0 providers/prompt/index.js | 16 +++--- providers/prompt/page/prompt.js | 51 +++++++++++-------- 4 files changed, 38 insertions(+), 31 deletions(-) rename providers/{frontLogger.js => front-logger.js} (100%) diff --git a/preload.js b/preload.js index 5fcb2e07..74860cec 100644 --- a/preload.js +++ b/preload.js @@ -34,7 +34,7 @@ document.addEventListener("DOMContentLoaded", () => { fileExists(songInfoProviderPath, require(songInfoProviderPath)); // inject front logger - const loggerPath = path.join(__dirname, "providers", "frontLogger.js") + const loggerPath = path.join(__dirname, "providers", "front-logger.js") fileExists(loggerPath, require(loggerPath)); // Add action for reloading diff --git a/providers/frontLogger.js b/providers/front-logger.js similarity index 100% rename from providers/frontLogger.js rename to providers/front-logger.js diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 1c14cfa2..1e29766f 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -8,7 +8,7 @@ const path = require("path"); const DEFAULT_WIDTH = 370; const DEFAULT_COUNTER_WIDTH = 300; const DEFAULT_HEIGHT = 160; -const DEFAULT_COUNTER_HEIGHT= 150; +const DEFAULT_COUNTER_HEIGHT = 150; function electronPrompt(options, parentWindow) { return new Promise((resolve, reject) => { @@ -40,9 +40,9 @@ function electronPrompt(options, parentWindow) { options || {} ); - options_.minWidth = options.minWidth || options.width || + options_.minWidth = options.minWidth || options.width || options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH; - options_.minHeight = options.minHeight || options.height || + options_.minHeight = options.minHeight || options.height || options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT; if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { @@ -130,21 +130,21 @@ function electronPrompt(options, parentWindow) { event, errorCode, errorDescription, - validatedURL, + validatedURL ) => { const log = { error: "did-fail-load", errorCode, errorDescription, - validatedURL, + validatedURL }; - reject(new Error("prompt.html did-fail-load, log:\n", + log.toString())); + reject(new Error("prompt.html did-fail-load, log:\n" + log.toString())); }); const promptUrl = url.format({ - protocol: 'file', + protocol: "file", slashes: true, - pathname: path.join(__dirname, 'page', 'prompt.html'), + pathname: path.join(__dirname, "page", "prompt.html"), hash: id }); diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index d3abfeab..ac79f106 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -4,9 +4,11 @@ const { ipcRenderer } = require("electron"); let promptId = null; let promptOptions = null; -function $(selector) { return document.querySelector(selector) } +function $(selector) { + return document.querySelector(selector); +} -document.addEventListener('DOMContentLoaded', promptRegister); +document.addEventListener("DOMContentLoaded", promptRegister); function promptRegister() { //get custom session id @@ -54,7 +56,6 @@ function promptRegister() { $("#form").addEventListener("submit", promptSubmit); $("#cancel").addEventListener("click", promptCancel); - //create input/select const dataContainerElement = $("#data-container"); let dataElement; @@ -70,19 +71,20 @@ function promptRegister() { default: return promptError(`Unhandled input type '${promptOptions.type}'`); } + if (promptOptions.type === "counter") { dataElement.style.width = "unset"; dataElement.style["text-align"] = "center"; - //dataElement.style["min-height"] = "1.5em"; - dataContainerElement.append(createMinus(dataElement)); + dataContainerElement.append(createMinusButton(dataElement)); dataContainerElement.append(dataElement); - dataContainerElement.append(createPlus(dataElement)); + dataContainerElement.append(createPlusButton(dataElement)); } else { dataContainerElement.append(dataElement); } - dataElement.setAttribute("id", "data"); + dataElement.setAttribute("id", "data"); dataElement.focus(); + if (promptOptions.type === "input" || promptOptions.type === "counter") { dataElement.select(); } @@ -100,7 +102,8 @@ function promptRegister() { window.addEventListener("error", error => { if (promptId) { - promptError("An error has occured on the prompt window: \n" + JSON.stringify(error, ["message", "arguments", "type", "name"]) + promptError("An error has occured on the prompt window: \n" + + JSON.stringify(error, ["message", "arguments", "type", "name"]) ); } }); @@ -209,35 +212,39 @@ function promptCreateSelect() { return dataElement; } -function createMinus(dataElement) { - const minus = document.createElement("span"); - minus.textContent = "-"; - minus.classList.add("minus"); - minus.onmousedown = () => { +function createMinusButton(dataElement) { + const minusBtn = document.createElement("span"); + minusBtn.textContent = "-"; + minusBtn.classList.add("minus"); + minusBtn.onmousedown = () => { dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); }; - return minus; + return minusBtn; } -function createPlus(dataElement) { - const plus = document.createElement("span"); - plus.textContent = "+"; - plus.classList.add("plus"); - plus.onmousedown = () => { +function createPlusButton(dataElement) { + const plusBtn = document.createElement("span"); + plusBtn.textContent = "+"; + plusBtn.classList.add("plus"); + plusBtn.onmousedown = () => { dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1); }; - return plus; + + return plusBtn; } //validate counter function validateCounterInput(input) { - const min = promptOptions.counterOptions?.minimum, - max = promptOptions.counterOptions?.maximum; + const min = promptOptions.counterOptions?.minimum; + const max = promptOptions.counterOptions?.maximum; + if (min !== undefined && input < min) { return min; } + if (max !== undefined && input > max) { return max; } + return input; } From b7b1316e7095565eb0c6370f46dc1fee972df61e Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sat, 17 Apr 2021 22:55:25 +0300 Subject: [PATCH 073/118] add rapidFire option to counter prompt --- providers/prompt/index.js | 16 +++++--- providers/prompt/page/prompt.js | 69 +++++++++++++++++++++++++++------ providers/prompt/readme.md | 2 +- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 1e29766f..009c8c7a 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -18,8 +18,8 @@ function electronPrompt(options, parentWindow) { //custom options override default const options_ = Object.assign( { - width: DEFAULT_WIDTH, - height: DEFAULT_HEIGHT, + width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH, + height:options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT: DEFAULT_HEIGHT, resizable: false, title: "Prompt", label: "Please input a value:", @@ -28,6 +28,7 @@ function electronPrompt(options, parentWindow) { value: null, type: "input", selectOptions: null, + counterOptions: {minimum: null, maximum: null, multiFire: false}, icon: null, useHtmlLabel: false, customStylesheet: null, @@ -40,10 +41,13 @@ function electronPrompt(options, parentWindow) { options || {} ); - options_.minWidth = options.minWidth || options.width || - options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH; - options_.minHeight = options.minHeight || options.height || - options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT; + options_.minWidth = options?.minWidth || options?.width || options_.width; + options_.minHeight = options?.minHeight || options?.height || options_.height; + + if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) { + reject(new Error('"counterOptions" must be an object if specified')); + return; + } if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { reject(new Error('"selectOptions" must be an object')); diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index ac79f106..3cad04ac 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -4,7 +4,7 @@ const { ipcRenderer } = require("electron"); let promptId = null; let promptOptions = null; -function $(selector) { +function $(selector) { return document.querySelector(selector); } @@ -62,6 +62,8 @@ function promptRegister() { switch (promptOptions.type) { case "counter": + dataElement = promptCreateCounter(); + break; case "input": dataElement = promptCreateInput(); break; @@ -73,8 +75,6 @@ function promptRegister() { } if (promptOptions.type === "counter") { - dataElement.style.width = "unset"; - dataElement.style["text-align"] = "center"; dataContainerElement.append(createMinusButton(dataElement)); dataContainerElement.append(dataElement); dataContainerElement.append(createPlusButton(dataElement)); @@ -212,27 +212,74 @@ function promptCreateSelect() { return dataElement; } +let pressed = false; +function multiFire(timer, scaleSpeed, callback, ...args) { + if (!pressed) { + return; + } + if (timer > scaleSpeed) { + timer -= scaleSpeed; + } + callback(...args); + setTimeout(multiFire, timer, timer, scaleSpeed, callback, ...args) +} + function createMinusButton(dataElement) { + function doMinus() { + dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); + } const minusBtn = document.createElement("span"); minusBtn.textContent = "-"; minusBtn.classList.add("minus"); - minusBtn.onmousedown = () => { - dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); - }; + if (promptOptions.counterOptions?.multiFire) { + minusBtn.onmousedown = () => { + pressed = true; + multiFire(500, 100, doMinus); + }; + + } else { + minusBtn.onmousedown = () => { + doMinus(); + }; + } return minusBtn; } function createPlusButton(dataElement) { + function doPlus() { + dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1); + } const plusBtn = document.createElement("span"); plusBtn.textContent = "+"; plusBtn.classList.add("plus"); - plusBtn.onmousedown = () => { - dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1); - }; - + if (promptOptions.counterOptions?.multiFire) { + plusBtn.onmousedown = () => { + pressed = true; + multiFire(500, 100, doPlus); + }; + } else { + plusBtn.onmousedown = () => { + doPlus(); + }; + } return plusBtn; } +function promptCreateCounter() { + if (promptOptions.counterOptions?.multiFire) { + document.onmouseup = () => { + pressed = false; + }; + } + + const dataElement = promptCreateInput(); + + dataElement.style.width = "unset"; + dataElement.style["text-align"] = "center"; + + return dataElement; +} + //validate counter function validateCounterInput(input) { const min = promptOptions.counterOptions?.minimum; @@ -245,6 +292,6 @@ function validateCounterInput(input) { if (max !== undefined && input > max) { return max; } - + return input; } diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md index eff1f907..ec272375 100644 --- a/providers/prompt/readme.md +++ b/providers/prompt/readme.md @@ -45,7 +45,7 @@ prompt({ | value | (optional, string) The default value for the input field. Defaults to null. | | type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. | | inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' -| counterOptions | (optional, object) minimum and maximum of counter in format: `{minimum: %int%, maximum: %int%} ` | +| counterOptions | (optional, object) minimum and maximum of counter, and if continuous input is enabled. format: `{minimum: %int%, maximum: %int%, multiFire: %boolean%`. min+max values defaults to null and multiFire defaults to false. | | selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | | useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | | width | (optional, integer) The width of the prompt window. Defaults to 370. | From 00468c7d0ec1db09786ae3385fc3a0413226e40a Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sun, 18 Apr 2021 00:44:22 +0300 Subject: [PATCH 074/118] use timeout ID to stop callback --- providers/prompt/page/prompt.js | 73 ++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 3cad04ac..b4759e2d 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -212,29 +212,60 @@ function promptCreateSelect() { return dataElement; } -let pressed = false; -function multiFire(timer, scaleSpeed, callback, ...args) { - if (!pressed) { - return; +let nextTimeoutID = null; + +/* Function execute callback in 3 accelerated intervals based on timer. + * Terminated from document.onmouseup() that is registered from promptCreateCounter() + * @param {function} callback: function to execute + * @param {object} timer: { + * * time: First delay in miliseconds. + * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially + * * scaleSpeed: Speed change per tick on first acceleration + * } + * @param {int} stepArgs: argument for callback representing Initial steps per click, default to 1 + * steps starts to increase when speed is too fast to notice + * @param {int} counter: used internally to decrease timer.limit + */ +function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) { + callback(stepsArg); + + const nextTimeout = timer.time + + if (counter > 20) { + counter = 0 - stepsArg; + if (timer.limit > 1) { + timer.limit = timer.limit / 2; + } else { + stepsArg *= 2; + } } - if (timer > scaleSpeed) { - timer -= scaleSpeed; + if (timer.time != timer.limit) { + timer.time = timer.time > timer.limit ? + timer.time - timer.scaleSpeed : + timer.limit; } - callback(...args); - setTimeout(multiFire, timer, timer, scaleSpeed, callback, ...args) + + nextTimeoutID = setTimeout( + multiFire, //callback + nextTimeout, //timer + //multiFire args: + callback, + timer, + stepsArg, + counter + 1 + ) } function createMinusButton(dataElement) { - function doMinus() { - dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1); + function doMinus(steps) { + dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps); } const minusBtn = document.createElement("span"); minusBtn.textContent = "-"; minusBtn.classList.add("minus"); if (promptOptions.counterOptions?.multiFire) { minusBtn.onmousedown = () => { - pressed = true; - multiFire(500, 100, doMinus); + multiFire(doMinus); }; } else { @@ -246,16 +277,15 @@ function createMinusButton(dataElement) { } function createPlusButton(dataElement) { - function doPlus() { - dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1); + function doPlus(steps) { + dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps); } const plusBtn = document.createElement("span"); plusBtn.textContent = "+"; plusBtn.classList.add("plus"); if (promptOptions.counterOptions?.multiFire) { plusBtn.onmousedown = () => { - pressed = true; - multiFire(500, 100, doPlus); + multiFire(doPlus); }; } else { plusBtn.onmousedown = () => { @@ -268,7 +298,10 @@ function createPlusButton(dataElement) { function promptCreateCounter() { if (promptOptions.counterOptions?.multiFire) { document.onmouseup = () => { - pressed = false; + if (!!nextTimeoutID) { + clearTimeout(nextTimeoutID) + nextTimeoutID = null; + } }; } @@ -284,12 +317,12 @@ function promptCreateCounter() { function validateCounterInput(input) { const min = promptOptions.counterOptions?.minimum; const max = promptOptions.counterOptions?.maximum; - - if (min !== undefined && input < min) { + //note that !min/max would proc if min/max are 0 + if (min !== null && min !== undefined && input < min) { return min; } - if (max !== undefined && input > max) { + if (max !== null && max !== undefined && input > max) { return max; } From 72716afcd3fcba96714c360257d95cb77af125a8 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sun, 18 Apr 2021 01:44:18 +0300 Subject: [PATCH 075/118] lint --- menu.js | 6 +++--- providers/prompt/index.js | 8 ++++++-- providers/prompt/page/prompt.js | 18 ++++++++++++------ providers/prompt/readme.md | 6 +++--- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/menu.js b/menu.js index 588dad7c..dddce721 100644 --- a/menu.js +++ b/menu.js @@ -149,7 +149,7 @@ const mainMenuTemplate = (win) => [ type: "checkbox", checked: !!config.get("options.proxy"), click: (item) => { - setProxy(item, win); + setProxy(item, win); } }, { @@ -322,10 +322,10 @@ function setProxy(item, win) { }, type: 'input', icon: iconPath, - customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"), + customStylesheet: "dark", }; //TODO: custom bar on prompt need testing on macOS - if(!is.macOS()) { + if (!is.macOS()) { Object.assign(options, { frame: false, customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"), diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 009c8c7a..95babc9c 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -19,7 +19,7 @@ function electronPrompt(options, parentWindow) { const options_ = Object.assign( { width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH, - height:options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT: DEFAULT_HEIGHT, + height: options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT, resizable: false, title: "Prompt", label: "Please input a value:", @@ -28,7 +28,7 @@ function electronPrompt(options, parentWindow) { value: null, type: "input", selectOptions: null, - counterOptions: {minimum: null, maximum: null, multiFire: false}, + counterOptions: { minimum: null, maximum: null, multiFire: false }, icon: null, useHtmlLabel: false, customStylesheet: null, @@ -44,6 +44,10 @@ function electronPrompt(options, parentWindow) { options_.minWidth = options?.minWidth || options?.width || options_.width; options_.minHeight = options?.minHeight || options?.height || options_.height; + if (options_.customStylesheet === "dark") { + options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css"); + } + if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) { reject(new Error('"counterOptions" must be an object if specified')); return; diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index b4759e2d..7f609b52 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -229,17 +229,18 @@ let nextTimeoutID = null; function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) { callback(stepsArg); - const nextTimeout = timer.time + const nextTimeout = timer.time; if (counter > 20) { counter = 0 - stepsArg; if (timer.limit > 1) { - timer.limit = timer.limit / 2; + timer.limit /= 2; } else { stepsArg *= 2; } } - if (timer.time != timer.limit) { + + if (timer.time !== timer.limit) { timer.time = timer.time > timer.limit ? timer.time - timer.scaleSpeed : timer.limit; @@ -253,26 +254,28 @@ function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, timer, stepsArg, counter + 1 - ) + ); } function createMinusButton(dataElement) { function doMinus(steps) { dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps); } + const minusBtn = document.createElement("span"); minusBtn.textContent = "-"; minusBtn.classList.add("minus"); + if (promptOptions.counterOptions?.multiFire) { minusBtn.onmousedown = () => { multiFire(doMinus); }; - } else { minusBtn.onmousedown = () => { doMinus(); }; } + return minusBtn; } @@ -280,9 +283,11 @@ function createPlusButton(dataElement) { function doPlus(steps) { dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps); } + const plusBtn = document.createElement("span"); plusBtn.textContent = "+"; plusBtn.classList.add("plus"); + if (promptOptions.counterOptions?.multiFire) { plusBtn.onmousedown = () => { multiFire(doPlus); @@ -292,13 +297,14 @@ function createPlusButton(dataElement) { doPlus(); }; } + return plusBtn; } function promptCreateCounter() { if (promptOptions.counterOptions?.multiFire) { document.onmouseup = () => { - if (!!nextTimeoutID) { + if (nextTimeoutID) { clearTimeout(nextTimeoutID) nextTimeoutID = null; } diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md index ec272375..a3775b8d 100644 --- a/providers/prompt/readme.md +++ b/providers/prompt/readme.md @@ -1,6 +1,6 @@ # Prompt Documentation -

prompt-preview

+

Simplest Prompt:
prompt-preview

## Usage ```js @@ -49,13 +49,13 @@ prompt({ | selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | | useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | | width | (optional, integer) The width of the prompt window. Defaults to 370. | -| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. | +| minWidth | (optional, integer) The minimum allowed width for the prompt window. Default to width if specified or default_width(370). | | | height | (optional, integer) The height of the prompt window. Defaults to 130. | | minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. | | resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. | | alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false | | icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. | -| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. | +| customStylesheet | (optional, string) The local path of a CSS file to customize the style of the prompt window, you can use just "dark" to use the premade dark skin. Defaults to null. | | menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. | | skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. | | frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. | From 10dffdbde25363a883e7f75e585745d6b6551fa7 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Mon, 19 Apr 2021 01:45:32 +0300 Subject: [PATCH 076/118] refactor + lint --- plugins/precise-volume/front.js | 141 ++++++++++++++++---------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index ed0cf4c5..33ad5095 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,24 +1,29 @@ const { setOptions } = require("../../config/plugins"); const { ipcRenderer } = require("electron"); +function $(selector){ return document.querySelector(selector); } module.exports = (options) => { setPlaybarOnwheel(options); - setupObserver(options); + setupSliderObserver(options); setupArrowShortcuts(options); firstRun(options); }; +function toPercent(volume) { + return Math.round(Number.parseFloat(volume) * 100); +} + function saveVolume(volume, options) { options.savedVolume = volume; setOptions("precise-volume", options); } function firstRun(options) { - const videoStream = document.querySelector(".video-stream"); - const slider = document.querySelector("#volume-slider"); - + const videoStream = $(".video-stream"); + const slider = $("#volume-slider"); + // Those elements load abit after DOMContentLoaded if (videoStream && slider) { - // Set saved volume if it pass checks + // Set saved volume IF it pass checks if (options.savedVolume && options.savedVolume >= 0 && options.savedVolume <= 100 && Math.abs(slider.value - options.savedVolume) < 5 @@ -27,7 +32,6 @@ function firstRun(options) { videoStream.volume = options.savedVolume / 100; slider.value = options.savedVolume; } - // Set current volume as tooltip setTooltip(toPercent(videoStream.volume)); } else { @@ -37,13 +41,67 @@ function firstRun(options) { function setPlaybarOnwheel(options) { // Add onwheel event to play bar - document.querySelector("ytmusic-player-bar").onwheel = event => { + $("ytmusic-player-bar").onwheel = event => { event.preventDefault(); - // Event.deltaY < 0 => wheel up + // Event.deltaY < 0 means wheel-up changeVolume(event.deltaY < 0, options); }; } +// (increase = false) means volume decrease +function changeVolume(increase, options) { + // Need to change both the actual volume and the slider + const videoStream = $(".video-stream"); + + // Apply volume change if valid + const steps = options.steps / 100; + videoStream.volume = increase ? + Math.min(videoStream.volume + steps, 1) : + Math.max(videoStream.volume - steps, 0); + + // Save the new volume + saveVolume(toPercent(videoStream.volume), options); + // Slider value automatically rounds to multiples of 5 + $("#volume-slider").value = options.savedVolume; + // Finally change tooltip to new value + setTooltip(options.savedVolume); +} + +// 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 && + (!options.savedVolume || 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 + }); +} + +// 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.style-scope.ytmusic-player-bar", + "#expand-volume-slider", + "#expand-volume" +]; + +function setTooltip(volume) { + for (target of tooltipTargets) { + $(target).title = `${volume}%`; + } +} + function setupArrowShortcuts(options) { // Register shortcuts if enabled if (options.arrowsShortcut) { @@ -51,10 +109,10 @@ function setupArrowShortcuts(options) { } // Change options from renderer to keep sync - ipcRenderer.on("setArrowsShortcut", (event, isEnabled) => { + ipcRenderer.on("setArrowsShortcut", (_event, isEnabled) => { options.arrowsShortcut = isEnabled; setOptions("precise-volume", options); - // Can setting without restarting app + // This allows changing setting without restarting app if (isEnabled) { addListener(); } else { @@ -72,71 +130,12 @@ function setupArrowShortcuts(options) { function callback(event) { switch (event.code) { - case `ArrowUp`: + case "ArrowUp": changeVolume(true, options); break; - case `ArrowDown`: + case "ArrowDown": changeVolume(false, options); break; } } } - -function changeVolume(increase, options) { - // Need to change both the slider and the actual volume - const videoStream = document.querySelector(".video-stream"); - const slider = document.querySelector("#volume-slider"); - - // Apply volume change if valid - const steps = options.steps / 100; - videoStream.volume = increase ? - Math.min(videoStream.volume + steps, 1) : - Math.max(videoStream.volume - steps, 0); - - // Save the new volume - saveVolume(toPercent(videoStream.volume), options); - // Slider value automatically rounds to multiples of 5 - slider.value = options.savedVolume; - // Finally change tooltip to new value - setTooltip(options.savedVolume); -} - -// Save volume + Update the volume tooltip when volume-slider is manually changed -function setupObserver(options) { - const observer = new MutationObserver(mutations => { - for (const mutation of mutations) { - // This checks that volume-slider was manually set - if (mutation.oldValue !== mutation.target.value && - (!options.savedVolume || 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 - observer.observe(document.querySelector("#volume-slider"), { - attributeFilter: ["value"], - attributeOldValue: true - }); -} - -// 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.style-scope.ytmusic-player-bar", - "#expand-volume-slider", - "#expand-volume" -]; - -function setTooltip(volume) { - const tooltip = volume + "%"; - for (target of tooltipTargets) { - document.querySelector(target).title = tooltip; - } -} - -function toPercent(volume) { - return Math.round(Number.parseFloat(volume) * 100); -} From 5fa8f3ef6f913f059ed31ae80d7049c0616e4717 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 22 Apr 2021 05:34:43 +0300 Subject: [PATCH 077/118] add option for plugin to have a preload.js --- preload.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/preload.js b/preload.js index 94f2a72a..ab7927fc 100644 --- a/preload.js +++ b/preload.js @@ -1,6 +1,6 @@ const path = require("path"); -const { contextBridge, remote } = require("electron"); +const { remote } = require("electron"); const config = require("./config"); const { fileExists } = require("./plugins/utils"); @@ -8,9 +8,15 @@ const { fileExists } = require("./plugins/utils"); const plugins = config.plugins.getEnabled(); plugins.forEach(([plugin, options]) => { - const pluginPath = path.join(__dirname, "plugins", plugin, "actions.js"); - fileExists(pluginPath, () => { - const actions = require(pluginPath).actions || {}; + const preloadPath = path.join(__dirname, "plugins", plugin, "preload.js"); + fileExists(preloadPath, () => { + const run = require(preloadPath); + run(options); + }); + + const actionPath = path.join(__dirname, "plugins", plugin, "actions.js"); + fileExists(actionPath, () => { + const actions = require(actionPath).actions || {}; // TODO: re-enable once contextIsolation is set to true // contextBridge.exposeInMainWorld(plugin + "Actions", actions); From 021d2a8a54531355f3943e104aa2b3bce36e8d20 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 22 Apr 2021 05:34:54 +0300 Subject: [PATCH 078/118] disable native volume-slider listeners --- plugins/precise-volume/back.js | 9 ++++++++- plugins/precise-volume/front.js | 10 ++++++---- plugins/precise-volume/preload.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 plugins/precise-volume/preload.js diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index e6b101f9..c0767535 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -3,8 +3,15 @@ This is used to determine if plugin is actually active (not if its only enabled in options) */ let enabled = false; -module.exports = () => { + +module.exports = (win) => { enabled = true; + + //did-finish-load is called after DOMContentLoaded. + //thats the reason the timing is controlled from main + win.webContents.once("did-finish-load", () => { + win.webContents.send("restoreAddEventListener"); + }); }; module.exports.enabled = () => { diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 33ad5095..91203655 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,6 +1,7 @@ -const { setOptions } = require("../../config/plugins"); const { ipcRenderer } = require("electron"); -function $(selector){ return document.querySelector(selector); } +const { setOptions } = require("../../config/plugins"); + +function $(selector) { return document.querySelector(selector); } module.exports = (options) => { setPlaybarOnwheel(options); @@ -23,6 +24,7 @@ function firstRun(options) { const slider = $("#volume-slider"); // Those elements load abit after DOMContentLoaded if (videoStream && slider) { + // Set saved volume IF it pass checks if (options.savedVolume && options.savedVolume >= 0 && options.savedVolume <= 100 @@ -52,7 +54,7 @@ function setPlaybarOnwheel(options) { function changeVolume(increase, options) { // Need to change both the actual volume and the slider const videoStream = $(".video-stream"); - + // Apply volume change if valid const steps = options.steps / 100; videoStream.volume = increase ? @@ -98,7 +100,7 @@ const tooltipTargets = [ function setTooltip(volume) { for (target of tooltipTargets) { - $(target).title = `${volume}%`; + $(target).title = `${volume}%`; } } diff --git a/plugins/precise-volume/preload.js b/plugins/precise-volume/preload.js new file mode 100644 index 00000000..75580d3b --- /dev/null +++ b/plugins/precise-volume/preload.js @@ -0,0 +1,28 @@ +const { ipcRenderer } = require("electron"); + +// Override specific listeners of volume-slider by modifying Element.prototype +function overrideAddEventListener(){ + // Events to ignore + const nativeEvents = ["mousewheel", "keydown", "keyup"]; + // Save native addEventListener + Element.prototype._addEventListener = Element.prototype.addEventListener; + + Element.prototype.addEventListener = function(type,listener,useCapture=false) { + if(this.tagName === "TP-YT-PAPER-SLIDER") { //tagName of #volume-slider + for (const eventType of nativeEvents) { + if (eventType === type) { + return; + } + } + } //else + this._addEventListener(type,listener,useCapture); + }; +} + +module.exports = () => { + overrideAddEventListener(); + // Restore the listeners after load to avoid keeping Element.prototype altered + ipcRenderer.once("restoreAddEventListener", () => { //called from Main to make sure page is completly loaded + Element.prototype.addEventListener = Element.prototype._addEventListener; + }); +} From 65f682219971919b7e8bd4f15faca3ca18dea5fc Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 22 Apr 2021 14:44:37 +0300 Subject: [PATCH 079/118] Show volume slider on volume change --- plugins/precise-volume/front.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 91203655..24b9e44b 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,6 +1,6 @@ const { ipcRenderer } = require("electron"); const { setOptions } = require("../../config/plugins"); - + function $(selector) { return document.querySelector(selector); } module.exports = (options) => { @@ -54,7 +54,7 @@ function setPlaybarOnwheel(options) { function changeVolume(increase, options) { // Need to change both the actual volume and the slider const videoStream = $(".video-stream"); - + const slider = $("#volume-slider"); // Apply volume change if valid const steps = options.steps / 100; videoStream.volume = increase ? @@ -64,9 +64,11 @@ function changeVolume(increase, options) { // Save the new volume saveVolume(toPercent(videoStream.volume), options); // Slider value automatically rounds to multiples of 5 - $("#volume-slider").value = options.savedVolume; - // Finally change tooltip to new value + slider.value = options.savedVolume; + // Change tooltips to new value setTooltip(options.savedVolume); + // Show volume slider on volume change + slider.classList.add("on-hover") } // Save volume + Update the volume tooltip when volume-slider is manually changed From 0bc1b5e0d3482ee11a791fe5cb975f87497d89ca Mon Sep 17 00:00:00 2001 From: Araxeus Date: Thu, 22 Apr 2021 16:30:34 +0300 Subject: [PATCH 080/118] lint --- plugins/precise-volume/back.js | 5 +++-- plugins/precise-volume/front.js | 5 ++--- plugins/precise-volume/preload.js | 22 +++++++++++----------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index c0767535..1d53e4eb 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -7,8 +7,9 @@ let enabled = false; module.exports = (win) => { enabled = true; - //did-finish-load is called after DOMContentLoaded. - //thats the reason the timing is controlled from main + // youtube-music register some of the target listeners after DOMContentLoaded + // did-finish-load is called after all elements finished loading, including said listeners + // Thats the reason the timing is controlled from main win.webContents.once("did-finish-load", () => { win.webContents.send("restoreAddEventListener"); }); diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 24b9e44b..762ded10 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -24,7 +24,6 @@ function firstRun(options) { const slider = $("#volume-slider"); // Those elements load abit after DOMContentLoaded if (videoStream && slider) { - // Set saved volume IF it pass checks if (options.savedVolume && options.savedVolume >= 0 && options.savedVolume <= 100 @@ -68,7 +67,7 @@ function changeVolume(increase, options) { // Change tooltips to new value setTooltip(options.savedVolume); // Show volume slider on volume change - slider.classList.add("on-hover") + slider.classList.add("on-hover"); } // Save volume + Update the volume tooltip when volume-slider is manually changed @@ -95,7 +94,7 @@ function setupSliderObserver(options) { // 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.style-scope.ytmusic-player-bar", + "tp-yt-paper-icon-button.volume", "#expand-volume-slider", "#expand-volume" ]; diff --git a/plugins/precise-volume/preload.js b/plugins/precise-volume/preload.js index 75580d3b..bfd6a01c 100644 --- a/plugins/precise-volume/preload.js +++ b/plugins/precise-volume/preload.js @@ -1,28 +1,28 @@ const { ipcRenderer } = require("electron"); // Override specific listeners of volume-slider by modifying Element.prototype -function overrideAddEventListener(){ +function overrideAddEventListener() { // Events to ignore const nativeEvents = ["mousewheel", "keydown", "keyup"]; // Save native addEventListener - Element.prototype._addEventListener = Element.prototype.addEventListener; - - Element.prototype.addEventListener = function(type,listener,useCapture=false) { - if(this.tagName === "TP-YT-PAPER-SLIDER") { //tagName of #volume-slider + Element.prototype._addEventListener = Element.prototype.addEventListener; + // Override addEventListener to Ignore specific events in volume-slider + Element.prototype.addEventListener = function (type, listener, useCapture = false) { + if (this.tagName === "TP-YT-PAPER-SLIDER") { // tagName of #volume-slider for (const eventType of nativeEvents) { if (eventType === type) { return; } } - } //else - this._addEventListener(type,listener,useCapture); + }//else + this._addEventListener(type, listener, useCapture); }; } module.exports = () => { overrideAddEventListener(); - // Restore the listeners after load to avoid keeping Element.prototype altered + // Restore original function after did-finish-load to avoid keeping Element.prototype altered ipcRenderer.once("restoreAddEventListener", () => { //called from Main to make sure page is completly loaded - Element.prototype.addEventListener = Element.prototype._addEventListener; - }); -} + Element.prototype.addEventListener = Element.prototype._addEventListener; + }); +}; From 064facb048f12a7cff8925ffc2c42c4b176aeba6 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 23 Apr 2021 01:20:03 +0300 Subject: [PATCH 081/118] remove slider on-hover after 3 seconds if !focused --- plugins/precise-volume/front.js | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 762ded10..941d847d 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -4,7 +4,7 @@ const { setOptions } = require("../../config/plugins"); function $(selector) { return document.querySelector(selector); } module.exports = (options) => { - setPlaybarOnwheel(options); + setupPlaybar(options); setupSliderObserver(options); setupArrowShortcuts(options); firstRun(options); @@ -40,13 +40,23 @@ function firstRun(options) { } } -function setPlaybarOnwheel(options) { +function setupPlaybar(options) { + const playerbar = $("ytmusic-player-bar"); // Add onwheel event to play bar - $("ytmusic-player-bar").onwheel = event => { + playerbar.onwheel = 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"); + }); } // (increase = false) means volume decrease @@ -67,7 +77,25 @@ function changeVolume(increase, options) { // Change tooltips to new value setTooltip(options.savedVolume); // Show volume slider on volume change + showVolumeSlider(slider); +} + +let volumeHoverTimeoutID; + +function showVolumeSlider(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); } // Save volume + Update the volume tooltip when volume-slider is manually changed @@ -132,6 +160,7 @@ function setupArrowShortcuts(options) { } function callback(event) { + event.preventDefault(); switch (event.code) { case "ArrowUp": changeVolume(true, options); From 7c6ed7bb314ad2a5bd92062a7170a242bfc0dec2 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 23 Apr 2021 04:01:40 +0300 Subject: [PATCH 082/118] `once` instead of `on` --- config/defaults.js | 4 ++-- plugins/notifications/back.js | 2 +- plugins/notifications/interactive.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index 57c001b1..c2465a15 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -43,9 +43,9 @@ const defaultConfig = { }, notifications: { enabled: false, - urgency: "normal", unpauseNotification: false, - interactive: false //has effect only on Windows 8+ + urgency: "normal", //has effect only on Linux + interactive: false //has effect only on Windows } }, }; diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index 38fbbbf8..901bdd1f 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -32,7 +32,7 @@ module.exports = (win, options) => { const registerCallback = getSongInfo(win); let oldNotification; let oldURL = ""; - win.on("ready-to-show", () => { + win.once("ready-to-show", () => { // Register the callback for new song information registerCallback(songInfo => { // on pause - reset url? and skip notification diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index d506463a..61f9fed0 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -13,7 +13,7 @@ module.exports.setupInteractive = (win, unpauseNotification) => { onPause = unpauseNotification; - win.webContents.on("closed", () => { + win.webContents.once("closed", () => { Delete() }); } From a1940461688bb3ab42450e426a26fd8ff4f72edf Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 23 Apr 2021 04:06:54 +0300 Subject: [PATCH 083/118] `win.once()` instead of `win.on` --- plugins/in-app-menu/back.js | 2 +- plugins/taskbar-mediacontrol/back.js | 2 +- plugins/touchbar/back.js | 2 +- plugins/utils.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 8365ac8b..82b0af4f 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -41,7 +41,7 @@ module.exports = (winImport) => { }); //set menu visibility on load - win.webContents.on("did-finish-load", () => { + win.webContents.once("did-finish-load", () => { // fix bug with menu not applying on start when no internet connection available setMenuVisibility(!config.get("options.hideMenu")); }); diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index b4d7dd3c..a8133539 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -24,7 +24,7 @@ module.exports = win => { const {playPause, next, previous} = getSongControls(win); // If the page is ready, register the callback - win.on('ready-to-show', () => { + win.once('ready-to-show', () => { registerCallback(songInfo => { // Wait for song to start before setting thumbar if (songInfo.title === '') { diff --git a/plugins/touchbar/back.js b/plugins/touchbar/back.js index 87240ed0..0fca17a7 100644 --- a/plugins/touchbar/back.js +++ b/plugins/touchbar/back.js @@ -63,7 +63,7 @@ module.exports = (win) => { const { playPause, next, previous, like, dislike } = getSongControls(win); // If the page is ready, register the callback - win.on("ready-to-show", () => { + win.once("ready-to-show", () => { controls = [previous, playPause, next, like, dislike]; // Register the callback diff --git a/plugins/utils.js b/plugins/utils.js index b265692f..ed8c7c0a 100644 --- a/plugins/utils.js +++ b/plugins/utils.js @@ -43,7 +43,7 @@ module.exports.fileExists = (path, callbackIfExists) => { }; module.exports.injectCSS = (webContents, filepath, cb = undefined) => { - webContents.on("did-finish-load", async () => { + webContents.once("did-finish-load", async () => { await webContents.insertCSS(fs.readFileSync(filepath, "utf8")); if (cb) { cb(); From eae4cca1484d610e18c71ea6d191b433bffc6dbe Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Fri, 23 Apr 2021 04:25:48 +0300 Subject: [PATCH 084/118] Update readme.md --- providers/prompt/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md index a3775b8d..613b4676 100644 --- a/providers/prompt/readme.md +++ b/providers/prompt/readme.md @@ -1,6 +1,6 @@ -# Prompt Documentation +# Prompt Component Documentation -

Simplest Prompt:
prompt-preview

+

Simplest Prompt with no stylesheet:
prompt-preview

## Usage ```js From 8b1bbdf3607cec7a9fe9323c69ec20aa8283b447 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Fri, 23 Apr 2021 05:29:03 +0300 Subject: [PATCH 085/118] Add Video Player Mousewheel Volume Control (if hide-video-player plugin is disabled) --- plugins/precise-volume/back.js | 3 +++ plugins/precise-volume/front.js | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index 1d53e4eb..93ebea9f 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -1,3 +1,5 @@ +const { isEnabled } = require("../../config/plugins"); + /* This is used to determine if plugin is actually active (not if its only enabled in options) @@ -12,6 +14,7 @@ module.exports = (win) => { // Thats the reason the timing is controlled from main win.webContents.once("did-finish-load", () => { win.webContents.send("restoreAddEventListener"); + win.webContents.send("setupVideoPlayerVolumeMousewheel", !isEnabled("hide-video-player")); }); }; diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 941d847d..27efbfba 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -8,8 +8,21 @@ module.exports = (options) => { setupSliderObserver(options); setupArrowShortcuts(options); firstRun(options); + ipcRenderer.once("setupVideoPlayerVolumeMousewheel", (_event, toEnable) => { + if (toEnable) + setupVideoPlayerOnwheel(options); + }); }; +function setupVideoPlayerOnwheel(options){ + // Add onwheel event to video player + $("#main-panel").onwheel = event => { + event.preventDefault(); + // Event.deltaY < 0 means wheel-up + changeVolume(event.deltaY < 0, options); + }; +} + function toPercent(volume) { return Math.round(Number.parseFloat(volume) * 100); } From d4fdced538f3124a7ac9e687492057f76ac18851 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sun, 25 Apr 2021 02:22:08 +0300 Subject: [PATCH 086/118] addEventListener insead of .onwheel --- plugins/precise-volume/front.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 27efbfba..de7fd614 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -16,11 +16,11 @@ module.exports = (options) => { function setupVideoPlayerOnwheel(options){ // Add onwheel event to video player - $("#main-panel").onwheel = event => { + $("#main-panel").addEventListener("wheel", event => { event.preventDefault(); // Event.deltaY < 0 means wheel-up changeVolume(event.deltaY < 0, options); - }; + }); } function toPercent(volume) { @@ -56,11 +56,11 @@ function firstRun(options) { function setupPlaybar(options) { const playerbar = $("ytmusic-player-bar"); // Add onwheel event to play bar - playerbar.onwheel = event => { + 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", () => { From 5a77528526851807ab38a9539d20d599267a9ef7 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Mon, 26 Apr 2021 21:01:19 +0300 Subject: [PATCH 087/118] enable global volume shortcuts in advanced config --- config/defaults.js | 5 +++++ plugins/precise-volume/front.js | 33 ++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/config/defaults.js b/config/defaults.js index 4b484951..647c2e4f 100644 --- a/config/defaults.js +++ b/config/defaults.js @@ -50,6 +50,11 @@ const defaultConfig = { enabled: false, steps: 1, //percentage of volume to change arrowsShortcut: true, //enable ArrowUp + ArrowDown local shortcuts + globalShortcuts: { + enabled: false, // enable global shortcuts + volumeUp: "Shift+PageUp", // Keybind default can be changed + volumeDown: "Shift+PageDown" + }, savedVolume: undefined //plugin save volume between session here } }, diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index de7fd614..7e6bfa84 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -1,20 +1,30 @@ -const { ipcRenderer } = require("electron"); +const { ipcRenderer, remote } = require("electron"); + const { setOptions } = require("../../config/plugins"); function $(selector) { return document.querySelector(selector); } module.exports = (options) => { + setupPlaybar(options); + setupSliderObserver(options); - setupArrowShortcuts(options); + + setupLocalArrowShortcuts(options); + + if (options.globalShortcuts?.enabled) { + setupGlobalShortcuts(options); + } + firstRun(options); + // This way the ipc listener gets cleared either way ipcRenderer.once("setupVideoPlayerVolumeMousewheel", (_event, toEnable) => { if (toEnable) setupVideoPlayerOnwheel(options); }); }; -function setupVideoPlayerOnwheel(options){ +function setupVideoPlayerOnwheel(options) { // Add onwheel event to video player $("#main-panel").addEventListener("wheel", event => { event.preventDefault(); @@ -73,13 +83,13 @@ function setupPlaybar(options) { } // (increase = false) means volume decrease -function changeVolume(increase, options) { +function changeVolume(toIncrease, options) { // Need to change both the actual volume and the slider const videoStream = $(".video-stream"); const slider = $("#volume-slider"); // Apply volume change if valid const steps = options.steps / 100; - videoStream.volume = increase ? + videoStream.volume = toIncrease ? Math.min(videoStream.volume + steps, 1) : Math.max(videoStream.volume - steps, 0); @@ -98,7 +108,7 @@ let volumeHoverTimeoutID; function showVolumeSlider(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 + // Reset timeout if previous one hasn't completed if (volumeHoverTimeoutID) { clearTimeout(volumeHoverTimeoutID); } @@ -146,7 +156,16 @@ function setTooltip(volume) { } } -function setupArrowShortcuts(options) { +function setupGlobalShortcuts(options) { + if (options.globalShortcuts.volumeUp) { + remote.globalShortcut.register((options.globalShortcuts.volumeUp), () => changeVolume(true, options)); + } + if (options.globalShortcuts.volumeDown) { + remote.globalShortcut.register((options.globalShortcuts.volumeDown), () => changeVolume(false, options)); + } +} + +function setupLocalArrowShortcuts(options) { // Register shortcuts if enabled if (options.arrowsShortcut) { addListener(); From 98fd6240ba457a71b5d106e8aede535f9316785a Mon Sep 17 00:00:00 2001 From: Araxeus Date: Mon, 26 Apr 2021 21:09:42 +0300 Subject: [PATCH 088/118] update inline doc --- plugins/precise-volume/front.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 7e6bfa84..834c5def 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -17,6 +17,7 @@ module.exports = (options) => { } firstRun(options); + // This way the ipc listener gets cleared either way ipcRenderer.once("setupVideoPlayerVolumeMousewheel", (_event, toEnable) => { if (toEnable) @@ -24,8 +25,8 @@ module.exports = (options) => { }); }; +/** Add onwheel event to video player */ function setupVideoPlayerOnwheel(options) { - // Add onwheel event to video player $("#main-panel").addEventListener("wheel", event => { event.preventDefault(); // Event.deltaY < 0 means wheel-up @@ -42,6 +43,7 @@ function saveVolume(volume, options) { setOptions("precise-volume", options); } +/** Restore saved volume and setup tooltip */ function firstRun(options) { const videoStream = $(".video-stream"); const slider = $("#volume-slider"); @@ -63,9 +65,10 @@ function firstRun(options) { } } +/** Add onwheel event to play bar and also track if play bar is hovered*/ function setupPlaybar(options) { const playerbar = $("ytmusic-player-bar"); - // Add onwheel event to play bar + playerbar.addEventListener("wheel", event => { event.preventDefault(); // Event.deltaY < 0 means wheel-up @@ -82,7 +85,7 @@ function setupPlaybar(options) { }); } -// (increase = false) means volume decrease +/** if (toIncrease = false) then volume decrease */ function changeVolume(toIncrease, options) { // Need to change both the actual volume and the slider const videoStream = $(".video-stream"); @@ -121,7 +124,7 @@ function showVolumeSlider(slider) { }, 3000); } -// Save volume + Update the volume tooltip when volume-slider is manually changed +/** 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) { @@ -166,7 +169,6 @@ function setupGlobalShortcuts(options) { } function setupLocalArrowShortcuts(options) { - // Register shortcuts if enabled if (options.arrowsShortcut) { addListener(); } @@ -175,7 +177,7 @@ function setupLocalArrowShortcuts(options) { ipcRenderer.on("setArrowsShortcut", (_event, isEnabled) => { options.arrowsShortcut = isEnabled; setOptions("precise-volume", options); - // This allows changing setting without restarting app + // This allows changing this setting without restarting app if (isEnabled) { addListener(); } else { From 5dc1179d54d6d0e7431c073e95309370cf8b268c Mon Sep 17 00:00:00 2001 From: Araxeus Date: Tue, 27 Apr 2021 23:48:06 +0300 Subject: [PATCH 089/118] implement keybind prompt --- providers/prompt/dark-prompt.css | 28 ++- providers/prompt/index.js | 34 ++-- providers/prompt/page/counter.js | 140 ++++++++++++++ providers/prompt/page/keybind.js | 305 +++++++++++++++++++++++++++++++ providers/prompt/page/prompt.css | 24 ++- providers/prompt/page/prompt.js | 120 ++++++------ 6 files changed, 578 insertions(+), 73 deletions(-) create mode 100644 providers/prompt/page/counter.js create mode 100644 providers/prompt/page/keybind.js diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css index 8bf39791..768b9e52 100644 --- a/providers/prompt/dark-prompt.css +++ b/providers/prompt/dark-prompt.css @@ -18,7 +18,8 @@ body { overflow: hidden; } -#data { +#data, +.keybindData { background: unset; color: whitesmoke; border: 1px solid rgb(54, 54, 54); @@ -41,12 +42,35 @@ body { } #ok, -#cancel { +#cancel, +.clearButton { background-color: rgb(0, 0, 0); color: whitesmoke; } +/* For Counter Prompt */ .minus, .plus { background: rgb(0, 0, 0); } + +/* For Select Prompt */ +option { + background-color: #07070C; +} + +/* For Keybind Prompt */ +.clearButton:focus { + outline: none; +} +.clearButton:hover { + background-color: rgb(5, 5, 5); +} +.keybindData:hover { + border: 1px solid rgb(56, 0, 0); +} + +.keybindData:focus { + outline: 3px solid #1E0919; + border: 1px solid rgb(56, 0, 0); +} diff --git a/providers/prompt/index.js b/providers/prompt/index.js index 95babc9c..a5c2230c 100644 --- a/providers/prompt/index.js +++ b/providers/prompt/index.js @@ -6,9 +6,10 @@ const url = require("url"); const path = require("path"); const DEFAULT_WIDTH = 370; +const DEFAULT_KEYBIND_WIDTH = 420; const DEFAULT_COUNTER_WIDTH = 300; -const DEFAULT_HEIGHT = 160; -const DEFAULT_COUNTER_HEIGHT = 150; +const DEFAULT_HEIGHT = 150; +const DEFAULT_KEYBIND_HEIGHT = options => (options.length * 40) + 100; function electronPrompt(options, parentWindow) { return new Promise((resolve, reject) => { @@ -18,8 +19,8 @@ function electronPrompt(options, parentWindow) { //custom options override default const options_ = Object.assign( { - width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH, - height: options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT, + width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : options?.type === "keybind" ? DEFAULT_KEYBIND_WIDTH : DEFAULT_WIDTH, + height: options?.type === "keybind" && options?.keybindOptions ? DEFAULT_KEYBIND_HEIGHT(options.keybindOptions) : DEFAULT_HEIGHT, resizable: false, title: "Prompt", label: "Please input a value:", @@ -28,6 +29,7 @@ function electronPrompt(options, parentWindow) { value: null, type: "input", selectOptions: null, + keybindOptions: null, counterOptions: { minimum: null, maximum: null, multiFire: false }, icon: null, useHtmlLabel: false, @@ -41,22 +43,21 @@ function electronPrompt(options, parentWindow) { options || {} ); - options_.minWidth = options?.minWidth || options?.width || options_.width; - options_.minHeight = options?.minHeight || options?.height || options_.height; + if (options_.customStylesheet === "dark") { options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css"); } - if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) { - reject(new Error('"counterOptions" must be an object if specified')); - return; + for (let type of ["counter", "select", "keybind"]) { + if (options_.type === type && (!options_[`${type}Options`] || typeof options_[`${type}Options`] !== "object")) { + reject(new Error(`"${type}Options" must be an object if type = ${type}`)); + return; + } } - if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) { - reject(new Error('"selectOptions" must be an object')); - return; - } + options_.minWidth = options?.minWidth || options?.width || options_.width; + options_.minHeight = options?.minHeight || options?.height || options_.height; let promptWindow = new BrowserWindow({ frame: options_.frame, @@ -104,6 +105,11 @@ function electronPrompt(options, parentWindow) { //get input from front const postDataListener = (event, value) => { + if (options_.type === "keybind" && value) { + for (let i=0; i < value.length ;i++) { + value[i] = JSON.parse(value[i]) + } + } resolve(value); event.returnValue = null; cleanup(); @@ -135,7 +141,7 @@ function electronPrompt(options, parentWindow) { //should never happen promptWindow.webContents.on("did-fail-load", ( - event, + _event, errorCode, errorDescription, validatedURL diff --git a/providers/prompt/page/counter.js b/providers/prompt/page/counter.js new file mode 100644 index 00000000..6f773d97 --- /dev/null +++ b/providers/prompt/page/counter.js @@ -0,0 +1,140 @@ +const { promptCreateInput } = require("./prompt"); + +module.exports = { promptCreateCounter , validateCounterInput } + +let options; + + +function promptCreateCounter(promptOptions, parentElement) { + options = promptOptions; + if (options.counterOptions?.multiFire) { + document.onmouseup = () => { + if (nextTimeoutID) { + clearTimeout(nextTimeoutID) + nextTimeoutID = null; + } + }; + } + + options.value = validateCounterInput(options.value); + + const dataElement = promptCreateInput(); + dataElement.onkeypress = function isNumberKey(e) { + if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete") + return false; + return true; + } + + dataElement.style.width = "unset"; + dataElement.style["text-align"] = "center"; + + parentElement.append(createMinusButton(dataElement)); + parentElement.append(dataElement); + parentElement.append(createPlusButton(dataElement)); + + return dataElement; +} + +let nextTimeoutID = null; + +/** Function execute callback in 3 accelerated intervals based on timer. + * Terminated from document.onmouseup() that is registered from promptCreateCounter() + * @param {function} callback function to execute + * @param {object} timer { + * * time: First delay in miliseconds + * * scaleSpeed: Speed change per tick on first acceleration + * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially + * } + * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1 + * steps starts to increase when speed is too fast to notice + * @param {int} counter used internally to decrease timer.limit + */ +function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) { + callback(stepsArg); + + const nextTimeout = timer.time; + + if (counter > 20) { + counter = 0 - stepsArg; + if (timer.limit > 1) { + timer.limit /= 2; + } else { + stepsArg *= 2; + } + } + + if (timer.time !== timer.limit) { + timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit) + } + + nextTimeoutID = setTimeout( + multiFire, //callback + nextTimeout, //timer + //multiFire args: + callback, + timer, + stepsArg, + counter + 1 + ); +} + +function createMinusButton(dataElement) { + function doMinus(steps) { + dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps); + } + + const minusBtn = document.createElement("span"); + minusBtn.textContent = "-"; + minusBtn.classList.add("minus"); + + if (options.counterOptions?.multiFire) { + minusBtn.onmousedown = () => { + multiFire(doMinus); + }; + } else { + minusBtn.onmousedown = () => { + doMinus(); + }; + } + + return minusBtn; +} + +function createPlusButton(dataElement) { + function doPlus(steps) { + dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps); + } + + const plusBtn = document.createElement("span"); + plusBtn.textContent = "+"; + plusBtn.classList.add("plus"); + + if (options.counterOptions?.multiFire) { + plusBtn.onmousedown = () => { + multiFire(doPlus); + }; + } else { + plusBtn.onmousedown = () => { + doPlus(); + }; + } + + return plusBtn; +} + +//validate counter +function validateCounterInput(input) { + + const min = options.counterOptions?.minimum; + const max = options.counterOptions?.maximum; + //note that !min/max would proc if min/max are 0 + if (min !== null && min !== undefined && input < min) { + return min; + } + + if (max !== null && max !== undefined && input > max) { + return max; + } + + return input; +} diff --git a/providers/prompt/page/keybind.js b/providers/prompt/page/keybind.js new file mode 100644 index 00000000..2406f736 --- /dev/null +++ b/providers/prompt/page/keybind.js @@ -0,0 +1,305 @@ +/* HTML + +
+ + + +
+ +*/ +/* CSS + +div.keybind { + display: grid; + grid-template-columns: max-content max-content max-content; + grid-gap: 5px; +} + +div.keybind button { + width: auto; +} + +div.keybind label { + text-align: right; +} + +div.keybind label:after { + content: ":"; +} + +*/ +const { promptError } = require("./prompt") + +class KeybindGetter { + value = null; + modifiers = null; + key = ""; + label = null; + txt = null; + clearButton = null; + + constructor(options, parentElement) { + if (!options.label || !options.value) { + promptError("keybind option must contain label and value"); + return; + } + + this.value = options.value + this.modifiers = new Set(); + this.key = ""; + + this.label = document.createElement("label"); + this.label.classList.add("keybindLabel"); + + this.txt = document.createElement("input"); + this.txt.setAttribute('readonly', true); + this.txt.classList.add("keybindData"); + + this.clearButton = document.createElement("button"); + this.clearButton.classList.add("clearButton"); + this.clearButton.textContent = "Clear"; + this.clearButton.onclick = (e) => e.preventDefault(); + + parentElement.append(this.label, this.txt, this.clearButton); + + this.setup(options); + if (options.default) { + this.setDefault(options.default) + } + } + + focus() { + this.txt.focus(); + } + + output() { + const output = {value: this.value, accelerator: this.txt.value.replaceAll(" ", "")} + return JSON.stringify(output); + } + + updateText() { + let result = ""; + for (let modifier of this.modifiers) { + result += modifier + " + "; + } + this.txt.value = result + this.key; + } + + setDefault(defaultValue) { + const accelerator = parseAccelerator(defaultValue).split("+"); + for (let key of accelerator) { + if (isModifier(key)) + this.modifiers.add(key); + else + this.key = key; + } + this.updateText(); + } + clear() { + this.modifiers.clear(); + this.key = ""; + this.txt.value = ""; + } + + setup(options) { + this.txt.addEventListener("keydown", (event) => { + event.preventDefault(); + if (event.repeat) { + return + } + let key = event.code || event.key; + if (key in virtualKeyCodes) + key = virtualKeyCodes[event.code]; + else { + console.log('Error, key "' + event.code + '" was not found'); + return; + } + + if (isModifier(key)) { + if (this.modifiers.size < 3) + this.modifiers.add(key); + } else { // is key + this.key = key; + } + this.updateText(); + }); + + this.clearButton.addEventListener("click", () => { + this.clear() + }); + this.label.textContent = options.label + " "; + } +} + +class keybindContainer { + elements = []; + + constructor(options, parentElement) { + parentElement.classList.add("keybind"); + this.elements = options.map(option => new KeybindGetter(option, parentElement)); + document.querySelector("#buttons").style["padding-top"] = "20px"; + } + + focus() { + if (this.elements.length > 0) + this.elements[0].focus(); + } + + submit() { + return this.elements.map(element => element.output()); + } +} + +function parseAccelerator(a) { + let accelerator = a.toString(); + + if (process.platform !== 'darwin') { + accelerator = accelerator.replace(/(Cmd)|(Command)/gi, ''); + } else { + accelerator = accelerator.replace(/(Ctrl)|(Control)/gi, ''); + } + + accelerator = accelerator.replace(/(Or)/gi, ''); + + return accelerator; +} + +function isModifier(key) { + for (let modifier of ["Shift", "Control", "Ctrl", "Command", "Cmd", "Alt", "AltGr", "Super"]) { + if (key === modifier) + return true; + } + return false; +} + +const virtualKeyCodes = { + ShiftLeft: "Shift", + ShiftRight: "Shift", + ControlLeft: "Ctrl", + ControlRight: "Ctrl", + AltLeft: "Alt", + AltRight: "Alt", + MetaLeft: "Super", + MetaRight: "Super", + NumLock: "NumLock", + NumpadDivide: "NumDiv", + NumpadMultiply: "NumMult", + NumpadSubtract: "NumSub", + NumpadAdd: "NumAdd", + NumpadDecimal: "NumDec ", + Numpad0: "Num0", + Numpad1: "Num1", + Numpad2: "Num2", + Numpad3: "Num3", + Numpad4: "Num4", + Numpad5: "Num5", + Numpad6: "Num6", + Numpad7: "Num7", + Numpad8: "Num8", + Numpad9: "Num9", + Digit0: "0", + Digit1: "1", + Digit2: "2", + Digit3: "3", + Digit4: "4", + Digit5: "5", + Digit6: "6", + Digit7: "7", + Digit8: "8", + Digit9: "9", + Minus: "-", + Equal: "=", + KeyQ: "Q", + KeyW: "W", + KeyE: "E", + KeyR: "R", + KeyT: "T", + KeyY: "Y", + KeyU: "U", + KeyI: "I", + KeyO: "O", + KeyP: "P", + KeyA: "A", + KeyS: "S", + KeyD: "D", + KeyF: "F", + KeyG: "G", + KeyH: "H", + KeyJ: "J", + KeyK: "K", + KeyL: "L", + KeyZ: "Z", + KeyX: "X", + KeyC: "C", + KeyV: "V", + KeyB: "B", + KeyN: "N", + KeyM: "M", + BracketLeft: "[", + BracketRight: "]", + Semicolon: ";", + Quote: "'", + Backquote: '"', + Backslash: "\\", + Comma: ",", + Period: "'.'", + Slash: "/", + plus: '+', + Space: "Space", + Tab: "Tab", + Backspace: "Backspace", + Delete: "Delete", + Insert: "Insert", + Return: "Return", + Enter: "Enter", + ArrowUp: "Up", + ArrowDown: "Down", + ArrowLeft: "Left", + ArrowRight: "Right", + Home: "Home", + End: "End", + PageUp: "PageUp", + PageDown: "PageDown", + Escape: "Escape", + AudioVolumeUp: "VolumeUp", + AudioVolumeDown: "VolumeDown", + AudioVolumeMute: "VolumeMute", + MediaTrackNext: "MediaNextTrack", + MediaTrackPrevious: "MediaPreviousTrack", + MediaStop: "MediaStop", + MediaPlayPause: "MediaPlayPause", + ScrollLock: "ScrollLock", + PrintScreen: "PrintScreen", + F1: "F1", + F2: "F2", + F3: "F3", + F4: "F4", + F5: "F5", + F6: "F6", + F7: "F7", + F8: "F8", + F9: "F9", + F10: "F10", + F11: "F11", + F12: "F12", + F13: "F13", + F14: "F14", + F15: "F15", + F16: "F16", + F17: "F17", + F18: "F18", + F19: "F19", + F20: "F20", + F21: "F21", + F22: "F22", + F23: "F23", + F24: "F24", +}; + + + +module.exports = function promptCreateKeybind(options, parentElement) { + return new keybindContainer(options, parentElement); +} diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css index 3224cf6a..6e52379a 100644 --- a/providers/prompt/page/prompt.css +++ b/providers/prompt/page/prompt.css @@ -79,7 +79,7 @@ select#data { color: black; } -/* Counter mode css */ +/* Counter mode */ span { cursor: pointer; } @@ -96,3 +96,25 @@ span { vertical-align: middle; text-align: center; } + +/** Keybind mode */ +div.keybind { + display: grid; + grid-template-columns: max-content max-content max-content; + row-gap: 20px; + column-gap: 10px; + margin: auto 0; + justify-content: center; + } + + div.keybind button { + width: auto; + } + + div.keybind label { + text-align: right; + } + + div.keybind label:after { + content: ":"; + } \ No newline at end of file diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js index 7f609b52..e09816d3 100644 --- a/providers/prompt/page/prompt.js +++ b/providers/prompt/page/prompt.js @@ -1,16 +1,15 @@ const fs = require("fs"); const { ipcRenderer } = require("electron"); - let promptId = null; let promptOptions = null; +let dataElement = null; -function $(selector) { - return document.querySelector(selector); -} +function $(selector) { return document.querySelector(selector); } document.addEventListener("DOMContentLoaded", promptRegister); function promptRegister() { + //get custom session id promptId = document.location.hash.replace("#", ""); @@ -56,13 +55,12 @@ function promptRegister() { $("#form").addEventListener("submit", promptSubmit); $("#cancel").addEventListener("click", promptCancel); - //create input/select + //create input/select/counter/keybind const dataContainerElement = $("#data-container"); - let dataElement; switch (promptOptions.type) { case "counter": - dataElement = promptCreateCounter(); + dataElement = promptCreateCounter(dataContainerElement); break; case "input": dataElement = promptCreateInput(); @@ -70,22 +68,24 @@ function promptRegister() { case "select": dataElement = promptCreateSelect(); break; + case "keybind": + dataElement = require("./keybind")(promptOptions.keybindOptions, dataContainerElement); + break; default: return promptError(`Unhandled input type '${promptOptions.type}'`); } - if (promptOptions.type === "counter") { - dataContainerElement.append(createMinusButton(dataElement)); - dataContainerElement.append(dataElement); - dataContainerElement.append(createPlusButton(dataElement)); - } else { - dataContainerElement.append(dataElement); + if (promptOptions.type != "keybind") { + dataElement.setAttribute("id", "data"); + + if (promptOptions.type !== "counter") { + dataContainerElement.append(dataElement); + } } - dataElement.setAttribute("id", "data"); dataElement.focus(); - if (promptOptions.type === "input" || promptOptions.type === "counter") { + if (promptOptions.type !== "select" && promptOptions.type !== "keybind") { dataElement.select(); } @@ -100,10 +100,10 @@ function promptRegister() { } } -window.addEventListener("error", error => { +window.addEventListener("error", event => { if (promptId) { promptError("An error has occured on the prompt window: \n" + - JSON.stringify(error, ["message", "arguments", "type", "name"]) + `Message: ${event.message}\nURL: ${event.url}\nLine: ${event.lineNo}, Column: ${event.columnNo}\nStack: ${event.error.stack}` ); } }); @@ -111,7 +111,7 @@ window.addEventListener("error", error => { //send error to back function promptError(error) { if (error instanceof Error) { - error = error.message; + error = error.message + "\n" + error.stack; } ipcRenderer.sendSync("prompt-error:" + promptId, error); @@ -124,20 +124,18 @@ function promptCancel() { //transfer input data to back function promptSubmit() { - const dataElement = $("#data"); let data = null; switch (promptOptions.type) { case "input": + case "select": data = dataElement.value; break; case "counter": data = validateCounterInput(dataElement.value); break; - case "select": - data = promptOptions.selectMultiple ? - dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) : - dataElement.value; + case "keybind": + data = dataElement.submit(); break; default: //will never happen return promptError(`Unhandled input type '${promptOptions.type}'`); @@ -152,9 +150,6 @@ function promptCreateInput() { dataElement.setAttribute("type", "text"); if (promptOptions.value) { - if (promptOptions.type === "counter") { - promptOptions.value = validateCounterInput(promptOptions.value); - } dataElement.value = promptOptions.value; } else { dataElement.value = ""; @@ -212,21 +207,50 @@ function promptCreateSelect() { return dataElement; } +function promptCreateCounter(parentElement) { + if (promptOptions.counterOptions?.multiFire) { + document.onmouseup = () => { + if (nextTimeoutID) { + clearTimeout(nextTimeoutID) + nextTimeoutID = null; + } + }; + } + + promptOptions.value = validateCounterInput(promptOptions.value); + + const dataElement = promptCreateInput(); + dataElement.onkeypress = function isNumberKey(e) { + if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete") + return false; + return true; + } + + dataElement.style.width = "unset"; + dataElement.style["text-align"] = "center"; + + parentElement.append(createMinusButton(dataElement)); + parentElement.append(dataElement); + parentElement.append(createPlusButton(dataElement)); + + return dataElement; +} + let nextTimeoutID = null; -/* Function execute callback in 3 accelerated intervals based on timer. +/** Function execute callback in 3 accelerated intervals based on timer. * Terminated from document.onmouseup() that is registered from promptCreateCounter() - * @param {function} callback: function to execute - * @param {object} timer: { - * * time: First delay in miliseconds. - * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially + * @param {function} callback function to execute + * @param {object} timer { + * * time: First delay in miliseconds * * scaleSpeed: Speed change per tick on first acceleration - * } - * @param {int} stepArgs: argument for callback representing Initial steps per click, default to 1 + * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially + * } + * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1 * steps starts to increase when speed is too fast to notice - * @param {int} counter: used internally to decrease timer.limit + * @param {int} counter used internally to decrease timer.limit */ -function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) { +function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) { callback(stepsArg); const nextTimeout = timer.time; @@ -241,9 +265,7 @@ function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, } if (timer.time !== timer.limit) { - timer.time = timer.time > timer.limit ? - timer.time - timer.scaleSpeed : - timer.limit; + timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit) } nextTimeoutID = setTimeout( @@ -301,26 +323,9 @@ function createPlusButton(dataElement) { return plusBtn; } -function promptCreateCounter() { - if (promptOptions.counterOptions?.multiFire) { - document.onmouseup = () => { - if (nextTimeoutID) { - clearTimeout(nextTimeoutID) - nextTimeoutID = null; - } - }; - } - - const dataElement = promptCreateInput(); - - dataElement.style.width = "unset"; - dataElement.style["text-align"] = "center"; - - return dataElement; -} - //validate counter function validateCounterInput(input) { + const min = promptOptions.counterOptions?.minimum; const max = promptOptions.counterOptions?.maximum; //note that !min/max would proc if min/max are 0 @@ -334,3 +339,6 @@ function validateCounterInput(input) { return input; } + +module.exports.promptError = promptError; + From e9d7ddebb2d18fe0d0ef32424cb1f8777a70bbd6 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Tue, 27 Apr 2021 23:51:29 +0300 Subject: [PATCH 090/118] defensive code Co-authored-by: th-ch --- plugins/precise-volume/front.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 834c5def..a1b30fe4 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -91,7 +91,7 @@ function changeVolume(toIncrease, options) { const videoStream = $(".video-stream"); const slider = $("#volume-slider"); // Apply volume change if valid - const steps = options.steps / 100; + const steps = (options.steps || 1) / 100; videoStream.volume = toIncrease ? Math.min(videoStream.volume + steps, 1) : Math.max(videoStream.volume - steps, 0); From 395eac26a3dcc66c461babba4cce42ef2df7823f Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Tue, 27 Apr 2021 23:52:08 +0300 Subject: [PATCH 091/118] switch function name to camelCase Co-authored-by: th-ch --- plugins/notifications/interactive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 61f9fed0..9dbed278 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -20,7 +20,7 @@ module.exports.setupInteractive = (win, unpauseNotification) => { //delete old notification let toDelete; -function Delete() { +function deleteNotification() { if (toDelete !== undefined) { const removeNotif = Object.assign(toDelete, { remove: toDelete.id From 8dc486f18fe02a218b149838dc7ab939ec1b698a Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 02:51:19 +0300 Subject: [PATCH 092/118] remove local prompt --- menu.js | 37 --- providers/prompt/custom-titlebar.js | 14 -- providers/prompt/dark-prompt.css | 76 ------ providers/prompt/index.js | 170 -------------- providers/prompt/page/counter.js | 140 ----------- providers/prompt/page/keybind.js | 305 ------------------------ providers/prompt/page/prompt.css | 120 ---------- providers/prompt/page/prompt.html | 18 -- providers/prompt/page/prompt.js | 344 ---------------------------- providers/prompt/readme.md | 80 ------- 10 files changed, 1304 deletions(-) delete mode 100644 providers/prompt/custom-titlebar.js delete mode 100644 providers/prompt/dark-prompt.css delete mode 100644 providers/prompt/index.js delete mode 100644 providers/prompt/page/counter.js delete mode 100644 providers/prompt/page/keybind.js delete mode 100644 providers/prompt/page/prompt.css delete mode 100644 providers/prompt/page/prompt.html delete mode 100644 providers/prompt/page/prompt.js delete mode 100644 providers/prompt/readme.md diff --git a/menu.js b/menu.js index dddce721..0ab62c7f 100644 --- a/menu.js +++ b/menu.js @@ -6,7 +6,6 @@ const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); -const prompt = require('./providers/prompt'); const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ label: label || plugin, @@ -309,39 +308,3 @@ module.exports.setApplicationMenu = (win) => { const menu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(menu); }; - -const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png"); -const example = `Example: "socks5://127.0.0.1:9999"`; -function setProxy(item, win) { - let options = { - title: 'Set Proxy', - label: 'Enter Proxy Address: (leave empty to disable)', - value: config.get("options.proxy") || example, - inputAttrs: { - type: 'text' - }, - type: 'input', - icon: iconPath, - customStylesheet: "dark", - }; - //TODO: custom bar on prompt need testing on macOS - if (!is.macOS()) { - Object.assign(options, { - frame: false, - customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"), - enableRemoteModule: true, - height: 200, - width: 450, - }); - } - prompt(options, win) - .then(input => { - if (input !== null && input !== example) { - config.set("options.proxy", input); - item.checked = input !== ""; - } else { //user pressed cancel - item.checked = !item.checked; //reset checkbox - } - }) - .catch(console.error); -} diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js deleted file mode 100644 index c36ce5f5..00000000 --- a/providers/prompt/custom-titlebar.js +++ /dev/null @@ -1,14 +0,0 @@ -const customTitlebar = require("custom-electron-titlebar"); - -module.exports = () => { - const bar = new customTitlebar.Titlebar({ - backgroundColor: customTitlebar.Color.fromHex("#050505"), - minimizable: false, - maximizable: false, - menu: null - }); - const mainStyle = document.querySelector("#container").style; - mainStyle.width = "100%"; - mainStyle.position = "fixed"; - mainStyle.border = "unset"; -}; diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css deleted file mode 100644 index 768b9e52..00000000 --- a/providers/prompt/dark-prompt.css +++ /dev/null @@ -1,76 +0,0 @@ -body { - background-color: rgba(0, 0, 0, 0.3); - background-image: linear-gradient(315deg, #200000 0%, #13253a 74%); - color: whitesmoke; -} - -#label { - text-align: center; -} - -#container { - background: rgba(0, 0, 0, 0.7); - box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - border-radius: 10px; - border: 1px solid rgba(80, 0, 0, 0.4); - overflow: hidden; -} - -#data, -.keybindData { - background: unset; - color: whitesmoke; - border: 1px solid rgb(54, 54, 54); -} - -#data:hover { - border: 1px solid rgb(85, 85, 85); -} - -#data:focus { - outline: unset; - border: 1px solid rgb(85, 85, 85); -} - -#ok:hover, -#ok:focus, -#cancel:hover, -#cancel:focus { - outline: rgba(60, 0, 0, 0.4) solid 2px; -} - -#ok, -#cancel, -.clearButton { - background-color: rgb(0, 0, 0); - color: whitesmoke; -} - -/* For Counter Prompt */ -.minus, -.plus { - background: rgb(0, 0, 0); -} - -/* For Select Prompt */ -option { - background-color: #07070C; -} - -/* For Keybind Prompt */ -.clearButton:focus { - outline: none; -} -.clearButton:hover { - background-color: rgb(5, 5, 5); -} -.keybindData:hover { - border: 1px solid rgb(56, 0, 0); -} - -.keybindData:focus { - outline: 3px solid #1E0919; - border: 1px solid rgb(56, 0, 0); -} diff --git a/providers/prompt/index.js b/providers/prompt/index.js deleted file mode 100644 index a5c2230c..00000000 --- a/providers/prompt/index.js +++ /dev/null @@ -1,170 +0,0 @@ -const electron = require("electron"); - -const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow; -const ipcMain = electron.ipcMain || electron.remote.ipcMain; -const url = require("url"); -const path = require("path"); - -const DEFAULT_WIDTH = 370; -const DEFAULT_KEYBIND_WIDTH = 420; -const DEFAULT_COUNTER_WIDTH = 300; -const DEFAULT_HEIGHT = 150; -const DEFAULT_KEYBIND_HEIGHT = options => (options.length * 40) + 100; - -function electronPrompt(options, parentWindow) { - return new Promise((resolve, reject) => { - //id used to ensure unique listeners per window - const id = `${Date.now()}-${Math.random()}`; - - //custom options override default - const options_ = Object.assign( - { - width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : options?.type === "keybind" ? DEFAULT_KEYBIND_WIDTH : DEFAULT_WIDTH, - height: options?.type === "keybind" && options?.keybindOptions ? DEFAULT_KEYBIND_HEIGHT(options.keybindOptions) : DEFAULT_HEIGHT, - resizable: false, - title: "Prompt", - label: "Please input a value:", - buttonLabels: null, - alwaysOnTop: false, - value: null, - type: "input", - selectOptions: null, - keybindOptions: null, - counterOptions: { minimum: null, maximum: null, multiFire: false }, - icon: null, - useHtmlLabel: false, - customStylesheet: null, - menuBarVisible: false, - skipTaskbar: true, - frame: true, - customScript: null, - enableRemoteModule: false - }, - options || {} - ); - - - - if (options_.customStylesheet === "dark") { - options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css"); - } - - for (let type of ["counter", "select", "keybind"]) { - if (options_.type === type && (!options_[`${type}Options`] || typeof options_[`${type}Options`] !== "object")) { - reject(new Error(`"${type}Options" must be an object if type = ${type}`)); - return; - } - } - - options_.minWidth = options?.minWidth || options?.width || options_.width; - options_.minHeight = options?.minHeight || options?.height || options_.height; - - let promptWindow = new BrowserWindow({ - frame: options_.frame, - width: options_.width, - height: options_.height, - minWidth: options_.minWidth, - minHeight: options_.minHeight, - resizable: options_.resizable, - minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop, - fullscreenable: options_.resizable, - maximizable: options_.resizable, - parent: parentWindow, - skipTaskbar: options_.skipTaskbar, - alwaysOnTop: options_.alwaysOnTop, - useContentSize: options_.resizable, - modal: Boolean(parentWindow), - title: options_.title, - icon: options_.icon || undefined, - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - enableRemoteModule: options_.enableRemoteModule - } - }); - - promptWindow.setMenu(null); - promptWindow.setMenuBarVisibility(options_.menuBarVisible); - - //called on exit - const cleanup = () => { - ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener); - ipcMain.removeListener("prompt-post-data:" + id, postDataListener); - ipcMain.removeListener("prompt-error:" + id, errorListener); - - if (promptWindow) { - promptWindow.close(); - promptWindow = null; - } - }; - - ///transfer options to front - const getOptionsListener = event => { - event.returnValue = JSON.stringify(options_); - }; - - //get input from front - const postDataListener = (event, value) => { - if (options_.type === "keybind" && value) { - for (let i=0; i < value.length ;i++) { - value[i] = JSON.parse(value[i]) - } - } - resolve(value); - event.returnValue = null; - cleanup(); - }; - - const unresponsiveListener = () => { - reject(new Error("Window was unresponsive")); - cleanup(); - }; - - //get error from front - const errorListener = (event, message) => { - reject(new Error(message)); - event.returnValue = null; - cleanup(); - }; - - //attach listeners - ipcMain.on("prompt-get-options:" + id, getOptionsListener); - ipcMain.on("prompt-post-data:" + id, postDataListener); - ipcMain.on("prompt-error:" + id, errorListener); - promptWindow.on("unresponsive", unresponsiveListener); - - promptWindow.on("closed", () => { - promptWindow = null; - cleanup(); - resolve(null); - }); - - //should never happen - promptWindow.webContents.on("did-fail-load", ( - _event, - errorCode, - errorDescription, - validatedURL - ) => { - const log = { - error: "did-fail-load", - errorCode, - errorDescription, - validatedURL - }; - reject(new Error("prompt.html did-fail-load, log:\n" + log.toString())); - }); - - const promptUrl = url.format({ - protocol: "file", - slashes: true, - pathname: path.join(__dirname, "page", "prompt.html"), - hash: id - }); - - //Finally, load prompt - promptWindow.loadURL(promptUrl); - }); -} - -module.exports = electronPrompt; diff --git a/providers/prompt/page/counter.js b/providers/prompt/page/counter.js deleted file mode 100644 index 6f773d97..00000000 --- a/providers/prompt/page/counter.js +++ /dev/null @@ -1,140 +0,0 @@ -const { promptCreateInput } = require("./prompt"); - -module.exports = { promptCreateCounter , validateCounterInput } - -let options; - - -function promptCreateCounter(promptOptions, parentElement) { - options = promptOptions; - if (options.counterOptions?.multiFire) { - document.onmouseup = () => { - if (nextTimeoutID) { - clearTimeout(nextTimeoutID) - nextTimeoutID = null; - } - }; - } - - options.value = validateCounterInput(options.value); - - const dataElement = promptCreateInput(); - dataElement.onkeypress = function isNumberKey(e) { - if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete") - return false; - return true; - } - - dataElement.style.width = "unset"; - dataElement.style["text-align"] = "center"; - - parentElement.append(createMinusButton(dataElement)); - parentElement.append(dataElement); - parentElement.append(createPlusButton(dataElement)); - - return dataElement; -} - -let nextTimeoutID = null; - -/** Function execute callback in 3 accelerated intervals based on timer. - * Terminated from document.onmouseup() that is registered from promptCreateCounter() - * @param {function} callback function to execute - * @param {object} timer { - * * time: First delay in miliseconds - * * scaleSpeed: Speed change per tick on first acceleration - * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially - * } - * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1 - * steps starts to increase when speed is too fast to notice - * @param {int} counter used internally to decrease timer.limit - */ -function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) { - callback(stepsArg); - - const nextTimeout = timer.time; - - if (counter > 20) { - counter = 0 - stepsArg; - if (timer.limit > 1) { - timer.limit /= 2; - } else { - stepsArg *= 2; - } - } - - if (timer.time !== timer.limit) { - timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit) - } - - nextTimeoutID = setTimeout( - multiFire, //callback - nextTimeout, //timer - //multiFire args: - callback, - timer, - stepsArg, - counter + 1 - ); -} - -function createMinusButton(dataElement) { - function doMinus(steps) { - dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps); - } - - const minusBtn = document.createElement("span"); - minusBtn.textContent = "-"; - minusBtn.classList.add("minus"); - - if (options.counterOptions?.multiFire) { - minusBtn.onmousedown = () => { - multiFire(doMinus); - }; - } else { - minusBtn.onmousedown = () => { - doMinus(); - }; - } - - return minusBtn; -} - -function createPlusButton(dataElement) { - function doPlus(steps) { - dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps); - } - - const plusBtn = document.createElement("span"); - plusBtn.textContent = "+"; - plusBtn.classList.add("plus"); - - if (options.counterOptions?.multiFire) { - plusBtn.onmousedown = () => { - multiFire(doPlus); - }; - } else { - plusBtn.onmousedown = () => { - doPlus(); - }; - } - - return plusBtn; -} - -//validate counter -function validateCounterInput(input) { - - const min = options.counterOptions?.minimum; - const max = options.counterOptions?.maximum; - //note that !min/max would proc if min/max are 0 - if (min !== null && min !== undefined && input < min) { - return min; - } - - if (max !== null && max !== undefined && input > max) { - return max; - } - - return input; -} diff --git a/providers/prompt/page/keybind.js b/providers/prompt/page/keybind.js deleted file mode 100644 index 2406f736..00000000 --- a/providers/prompt/page/keybind.js +++ /dev/null @@ -1,305 +0,0 @@ -/* HTML - -
- - - -
- -*/ -/* CSS - -div.keybind { - display: grid; - grid-template-columns: max-content max-content max-content; - grid-gap: 5px; -} - -div.keybind button { - width: auto; -} - -div.keybind label { - text-align: right; -} - -div.keybind label:after { - content: ":"; -} - -*/ -const { promptError } = require("./prompt") - -class KeybindGetter { - value = null; - modifiers = null; - key = ""; - label = null; - txt = null; - clearButton = null; - - constructor(options, parentElement) { - if (!options.label || !options.value) { - promptError("keybind option must contain label and value"); - return; - } - - this.value = options.value - this.modifiers = new Set(); - this.key = ""; - - this.label = document.createElement("label"); - this.label.classList.add("keybindLabel"); - - this.txt = document.createElement("input"); - this.txt.setAttribute('readonly', true); - this.txt.classList.add("keybindData"); - - this.clearButton = document.createElement("button"); - this.clearButton.classList.add("clearButton"); - this.clearButton.textContent = "Clear"; - this.clearButton.onclick = (e) => e.preventDefault(); - - parentElement.append(this.label, this.txt, this.clearButton); - - this.setup(options); - if (options.default) { - this.setDefault(options.default) - } - } - - focus() { - this.txt.focus(); - } - - output() { - const output = {value: this.value, accelerator: this.txt.value.replaceAll(" ", "")} - return JSON.stringify(output); - } - - updateText() { - let result = ""; - for (let modifier of this.modifiers) { - result += modifier + " + "; - } - this.txt.value = result + this.key; - } - - setDefault(defaultValue) { - const accelerator = parseAccelerator(defaultValue).split("+"); - for (let key of accelerator) { - if (isModifier(key)) - this.modifiers.add(key); - else - this.key = key; - } - this.updateText(); - } - clear() { - this.modifiers.clear(); - this.key = ""; - this.txt.value = ""; - } - - setup(options) { - this.txt.addEventListener("keydown", (event) => { - event.preventDefault(); - if (event.repeat) { - return - } - let key = event.code || event.key; - if (key in virtualKeyCodes) - key = virtualKeyCodes[event.code]; - else { - console.log('Error, key "' + event.code + '" was not found'); - return; - } - - if (isModifier(key)) { - if (this.modifiers.size < 3) - this.modifiers.add(key); - } else { // is key - this.key = key; - } - this.updateText(); - }); - - this.clearButton.addEventListener("click", () => { - this.clear() - }); - this.label.textContent = options.label + " "; - } -} - -class keybindContainer { - elements = []; - - constructor(options, parentElement) { - parentElement.classList.add("keybind"); - this.elements = options.map(option => new KeybindGetter(option, parentElement)); - document.querySelector("#buttons").style["padding-top"] = "20px"; - } - - focus() { - if (this.elements.length > 0) - this.elements[0].focus(); - } - - submit() { - return this.elements.map(element => element.output()); - } -} - -function parseAccelerator(a) { - let accelerator = a.toString(); - - if (process.platform !== 'darwin') { - accelerator = accelerator.replace(/(Cmd)|(Command)/gi, ''); - } else { - accelerator = accelerator.replace(/(Ctrl)|(Control)/gi, ''); - } - - accelerator = accelerator.replace(/(Or)/gi, ''); - - return accelerator; -} - -function isModifier(key) { - for (let modifier of ["Shift", "Control", "Ctrl", "Command", "Cmd", "Alt", "AltGr", "Super"]) { - if (key === modifier) - return true; - } - return false; -} - -const virtualKeyCodes = { - ShiftLeft: "Shift", - ShiftRight: "Shift", - ControlLeft: "Ctrl", - ControlRight: "Ctrl", - AltLeft: "Alt", - AltRight: "Alt", - MetaLeft: "Super", - MetaRight: "Super", - NumLock: "NumLock", - NumpadDivide: "NumDiv", - NumpadMultiply: "NumMult", - NumpadSubtract: "NumSub", - NumpadAdd: "NumAdd", - NumpadDecimal: "NumDec ", - Numpad0: "Num0", - Numpad1: "Num1", - Numpad2: "Num2", - Numpad3: "Num3", - Numpad4: "Num4", - Numpad5: "Num5", - Numpad6: "Num6", - Numpad7: "Num7", - Numpad8: "Num8", - Numpad9: "Num9", - Digit0: "0", - Digit1: "1", - Digit2: "2", - Digit3: "3", - Digit4: "4", - Digit5: "5", - Digit6: "6", - Digit7: "7", - Digit8: "8", - Digit9: "9", - Minus: "-", - Equal: "=", - KeyQ: "Q", - KeyW: "W", - KeyE: "E", - KeyR: "R", - KeyT: "T", - KeyY: "Y", - KeyU: "U", - KeyI: "I", - KeyO: "O", - KeyP: "P", - KeyA: "A", - KeyS: "S", - KeyD: "D", - KeyF: "F", - KeyG: "G", - KeyH: "H", - KeyJ: "J", - KeyK: "K", - KeyL: "L", - KeyZ: "Z", - KeyX: "X", - KeyC: "C", - KeyV: "V", - KeyB: "B", - KeyN: "N", - KeyM: "M", - BracketLeft: "[", - BracketRight: "]", - Semicolon: ";", - Quote: "'", - Backquote: '"', - Backslash: "\\", - Comma: ",", - Period: "'.'", - Slash: "/", - plus: '+', - Space: "Space", - Tab: "Tab", - Backspace: "Backspace", - Delete: "Delete", - Insert: "Insert", - Return: "Return", - Enter: "Enter", - ArrowUp: "Up", - ArrowDown: "Down", - ArrowLeft: "Left", - ArrowRight: "Right", - Home: "Home", - End: "End", - PageUp: "PageUp", - PageDown: "PageDown", - Escape: "Escape", - AudioVolumeUp: "VolumeUp", - AudioVolumeDown: "VolumeDown", - AudioVolumeMute: "VolumeMute", - MediaTrackNext: "MediaNextTrack", - MediaTrackPrevious: "MediaPreviousTrack", - MediaStop: "MediaStop", - MediaPlayPause: "MediaPlayPause", - ScrollLock: "ScrollLock", - PrintScreen: "PrintScreen", - F1: "F1", - F2: "F2", - F3: "F3", - F4: "F4", - F5: "F5", - F6: "F6", - F7: "F7", - F8: "F8", - F9: "F9", - F10: "F10", - F11: "F11", - F12: "F12", - F13: "F13", - F14: "F14", - F15: "F15", - F16: "F16", - F17: "F17", - F18: "F18", - F19: "F19", - F20: "F20", - F21: "F21", - F22: "F22", - F23: "F23", - F24: "F24", -}; - - - -module.exports = function promptCreateKeybind(options, parentElement) { - return new keybindContainer(options, parentElement); -} diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css deleted file mode 100644 index 6e52379a..00000000 --- a/providers/prompt/page/prompt.css +++ /dev/null @@ -1,120 +0,0 @@ -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, - sans-serif; - line-height: 1.5em; - color: #333; - background-color: #fff; - overflow-y: hidden; -} - -::-webkit-scrollbar { - width: 0 !important; - display: none; -} - -#container { - align-items: center; - justify-content: center; - display: flex; - height: 100%; - overflow-y: hidden; -} - -#form { - width: 100%; - padding-top: 0.5em; -} - -#label { - max-width: 100%; - max-height: 100%; - margin-bottom: 0.8em; - padding: 0 0.5em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#data { - border-radius: 2px; - background: #fff; - width: 90%; - padding: 0.4em 0.5em; - border: 1px solid black; - min-height: 2em; - margin: 0 0 1.2em; -} - -select#data { - height: 2em; -} - -#data-container { - text-align: center; -} - -#buttons { - text-align: right; - padding: 0 0.5em 0 0; -} - -#buttons > button, -#buttons > input[type="submit"] { - border-radius: 2px; - border: 0; - margin: 0 0 0 0.5em; - font-size: 0.8em; - line-height: 1em; - padding: 0.6em 1em; -} - -#ok { - background-color: #3879d9; - color: white; -} - -#cancel { - background-color: #ddd; - color: black; -} - -/* Counter mode */ -span { - cursor: pointer; -} -.minus, -.plus { - user-select: none; - width: 20px; - height: 20px; - background: #f2f2f2; - border-radius: 4px; - padding: 8px 5px 8px 5px; - border: 1px solid #ddd; - display: inline-block; - vertical-align: middle; - text-align: center; -} - -/** Keybind mode */ -div.keybind { - display: grid; - grid-template-columns: max-content max-content max-content; - row-gap: 20px; - column-gap: 10px; - margin: auto 0; - justify-content: center; - } - - div.keybind button { - width: auto; - } - - div.keybind label { - text-align: right; - } - - div.keybind label:after { - content: ":"; - } \ No newline at end of file diff --git a/providers/prompt/page/prompt.html b/providers/prompt/page/prompt.html deleted file mode 100644 index cdbfa544..00000000 --- a/providers/prompt/page/prompt.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - -
-
-
...
-
-
- - -
-
-
- - - diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js deleted file mode 100644 index e09816d3..00000000 --- a/providers/prompt/page/prompt.js +++ /dev/null @@ -1,344 +0,0 @@ -const fs = require("fs"); -const { ipcRenderer } = require("electron"); -let promptId = null; -let promptOptions = null; -let dataElement = null; - -function $(selector) { return document.querySelector(selector); } - -document.addEventListener("DOMContentLoaded", promptRegister); - -function promptRegister() { - - //get custom session id - promptId = document.location.hash.replace("#", ""); - - //get options from back - try { - promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId)); - } catch (error) { - return promptError(error); - } - - //set label - if (promptOptions.useHtmlLabel) { - $("#label").innerHTML = promptOptions.label; - } else { - $("#label").textContent = promptOptions.label; - } - - //set button label - if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { - $("#ok").textContent = promptOptions.buttonLabels.ok; - } - - if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) { - $("#cancel").textContent = promptOptions.buttonLabels.cancel; - } - - //inject custom stylesheet from options - if (promptOptions.customStylesheet) { - try { - const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); - if (customStyleContent) { - const customStyle = document.createElement("style"); - customStyle.setAttribute("rel", "stylesheet"); - customStyle.append(document.createTextNode(customStyleContent)); - document.head.append(customStyle); - } - } catch (error) { - return promptError(error); - } - } - - //add button listeners - $("#form").addEventListener("submit", promptSubmit); - $("#cancel").addEventListener("click", promptCancel); - - //create input/select/counter/keybind - const dataContainerElement = $("#data-container"); - - switch (promptOptions.type) { - case "counter": - dataElement = promptCreateCounter(dataContainerElement); - break; - case "input": - dataElement = promptCreateInput(); - break; - case "select": - dataElement = promptCreateSelect(); - break; - case "keybind": - dataElement = require("./keybind")(promptOptions.keybindOptions, dataContainerElement); - break; - default: - return promptError(`Unhandled input type '${promptOptions.type}'`); - } - - if (promptOptions.type != "keybind") { - dataElement.setAttribute("id", "data"); - - if (promptOptions.type !== "counter") { - dataContainerElement.append(dataElement); - } - } - - dataElement.focus(); - - if (promptOptions.type !== "select" && promptOptions.type !== "keybind") { - dataElement.select(); - } - - //load custom script from options - if (promptOptions.customScript) { - try { - const customScript = require(promptOptions.customScript); - customScript(); - } catch (error) { - return promptError(error); - } - } -} - -window.addEventListener("error", event => { - if (promptId) { - promptError("An error has occured on the prompt window: \n" + - `Message: ${event.message}\nURL: ${event.url}\nLine: ${event.lineNo}, Column: ${event.columnNo}\nStack: ${event.error.stack}` - ); - } -}); - -//send error to back -function promptError(error) { - if (error instanceof Error) { - error = error.message + "\n" + error.stack; - } - - ipcRenderer.sendSync("prompt-error:" + promptId, error); -} - -//send to back: input=null -function promptCancel() { - ipcRenderer.sendSync("prompt-post-data:" + promptId, null); -} - -//transfer input data to back -function promptSubmit() { - let data = null; - - switch (promptOptions.type) { - case "input": - case "select": - data = dataElement.value; - break; - case "counter": - data = validateCounterInput(dataElement.value); - break; - case "keybind": - data = dataElement.submit(); - break; - default: //will never happen - return promptError(`Unhandled input type '${promptOptions.type}'`); - } - - ipcRenderer.sendSync("prompt-post-data:" + promptId, data); -} - -//creates input box -function promptCreateInput() { - const dataElement = document.createElement("input"); - dataElement.setAttribute("type", "text"); - - if (promptOptions.value) { - dataElement.value = promptOptions.value; - } else { - dataElement.value = ""; - } - - //insert custom input attributes if in options - if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") { - for (const k in promptOptions.inputAttrs) { - if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) { - continue; - } - - dataElement.setAttribute(k, promptOptions.inputAttrs[k]); - } - } - - //Cancel/Exit on 'Escape' - dataElement.addEventListener("keyup", event => { - if (event.key === "Escape") { - promptCancel(); - } - }); - - //Confirm on 'Enter' - dataElement.addEventListener("keypress", event => { - if (event.key === "Enter") { - event.preventDefault(); - $("#ok").click(); - } - }); - - return dataElement; -} - -//create multiple select -function promptCreateSelect() { - const dataElement = document.createElement("select"); - let optionElement; - - for (const k in promptOptions.selectOptions) { - if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) { - continue; - } - - optionElement = document.createElement("option"); - optionElement.setAttribute("value", k); - optionElement.textContent = promptOptions.selectOptions[k]; - if (k === promptOptions.value) { - optionElement.setAttribute("selected", "selected"); - } - - dataElement.append(optionElement); - } - - return dataElement; -} - -function promptCreateCounter(parentElement) { - if (promptOptions.counterOptions?.multiFire) { - document.onmouseup = () => { - if (nextTimeoutID) { - clearTimeout(nextTimeoutID) - nextTimeoutID = null; - } - }; - } - - promptOptions.value = validateCounterInput(promptOptions.value); - - const dataElement = promptCreateInput(); - dataElement.onkeypress = function isNumberKey(e) { - if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete") - return false; - return true; - } - - dataElement.style.width = "unset"; - dataElement.style["text-align"] = "center"; - - parentElement.append(createMinusButton(dataElement)); - parentElement.append(dataElement); - parentElement.append(createPlusButton(dataElement)); - - return dataElement; -} - -let nextTimeoutID = null; - -/** Function execute callback in 3 accelerated intervals based on timer. - * Terminated from document.onmouseup() that is registered from promptCreateCounter() - * @param {function} callback function to execute - * @param {object} timer { - * * time: First delay in miliseconds - * * scaleSpeed: Speed change per tick on first acceleration - * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially - * } - * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1 - * steps starts to increase when speed is too fast to notice - * @param {int} counter used internally to decrease timer.limit - */ -function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) { - callback(stepsArg); - - const nextTimeout = timer.time; - - if (counter > 20) { - counter = 0 - stepsArg; - if (timer.limit > 1) { - timer.limit /= 2; - } else { - stepsArg *= 2; - } - } - - if (timer.time !== timer.limit) { - timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit) - } - - nextTimeoutID = setTimeout( - multiFire, //callback - nextTimeout, //timer - //multiFire args: - callback, - timer, - stepsArg, - counter + 1 - ); -} - -function createMinusButton(dataElement) { - function doMinus(steps) { - dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps); - } - - const minusBtn = document.createElement("span"); - minusBtn.textContent = "-"; - minusBtn.classList.add("minus"); - - if (promptOptions.counterOptions?.multiFire) { - minusBtn.onmousedown = () => { - multiFire(doMinus); - }; - } else { - minusBtn.onmousedown = () => { - doMinus(); - }; - } - - return minusBtn; -} - -function createPlusButton(dataElement) { - function doPlus(steps) { - dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps); - } - - const plusBtn = document.createElement("span"); - plusBtn.textContent = "+"; - plusBtn.classList.add("plus"); - - if (promptOptions.counterOptions?.multiFire) { - plusBtn.onmousedown = () => { - multiFire(doPlus); - }; - } else { - plusBtn.onmousedown = () => { - doPlus(); - }; - } - - return plusBtn; -} - -//validate counter -function validateCounterInput(input) { - - const min = promptOptions.counterOptions?.minimum; - const max = promptOptions.counterOptions?.maximum; - //note that !min/max would proc if min/max are 0 - if (min !== null && min !== undefined && input < min) { - return min; - } - - if (max !== null && max !== undefined && input > max) { - return max; - } - - return input; -} - -module.exports.promptError = promptError; - diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md deleted file mode 100644 index 613b4676..00000000 --- a/providers/prompt/readme.md +++ /dev/null @@ -1,80 +0,0 @@ -# Prompt Component Documentation - -

Simplest Prompt with no stylesheet:
prompt-preview

- -## Usage -```js -prompt([options, parentBrowserWindow]).then(...).catch(...) -``` -Promise resolve returns input - -If user presses cancel/exit window, input = null; - -On error, Prompise reject returns custom error message -## Example - -```js -const prompt = require('./providers/prompt'); - -prompt({ - title: 'Prompt example', - label: 'URL:', - value: 'http://example.org', - inputAttrs: { - type: 'url' - }, - type: 'input' -}) -.then((r) => { - if(r === null) { - console.log('user cancelled'); - } else { - console.log('result', r); - } -}) -.catch(console.error); -``` - -### Options object (optional) - -| Key | Explanation | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. | -| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. | -| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. | -| value | (optional, string) The default value for the input field. Defaults to null. | -| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. | -| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ``. Used if the type is 'input' -| counterOptions | (optional, object) minimum and maximum of counter, and if continuous input is enabled. format: `{minimum: %int%, maximum: %int%, multiFire: %boolean%`. min+max values defaults to null and multiFire defaults to false. | -| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. | -| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. | -| width | (optional, integer) The width of the prompt window. Defaults to 370. | -| minWidth | (optional, integer) The minimum allowed width for the prompt window. Default to width if specified or default_width(370). | | -| height | (optional, integer) The height of the prompt window. Defaults to 130. | -| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. | -| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. | -| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false | -| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. | -| customStylesheet | (optional, string) The local path of a CSS file to customize the style of the prompt window, you can use just "dark" to use the premade dark skin. Defaults to null. | -| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. | -| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. | -| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. | -| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. | -| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. | - -If not supplied, it uses the defaults listed in the table above. - -### parentBrowserWindow (optional) - -The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null. - -### customScript (optional) - -Create the script with the following template: - -```node -module.exports = () => { - // This function will be called as a preload script - // So you can use front features like `document.querySelector` -}; -``` From 0adb36cfb87102944b5ded57f745ff6ea75a7cf8 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 03:08:25 +0300 Subject: [PATCH 093/118] leave debug for next PR --- index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/index.js b/index.js index 82ba695d..80ba9efe 100644 --- a/index.js +++ b/index.js @@ -38,9 +38,7 @@ if (config.get("options.proxy")) { } // Adds debug features like hotkeys for triggering dev tools and reload -require("electron-debug")({ - showDevTools: false //disable automatic devTools on new window -}); +require("electron-debug")(); // Prevent window being garbage collected let mainWindow; From 0491babe0aeaf2a8d52fe6c3384fd9602cf4c0bf Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 03:36:00 +0300 Subject: [PATCH 094/118] fix typo --- plugins/notifications/back.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/notifications/back.js b/plugins/notifications/back.js index 901bdd1f..d1ef3114 100644 --- a/plugins/notifications/back.js +++ b/plugins/notifications/back.js @@ -43,7 +43,7 @@ module.exports = (win, options) => { } return; } - // If url isn"t the same as last one - send notification + // If url isn't the same as last one - send notification if (songInfo.url !== oldURL) { oldURL = songInfo.url; if (isInteractive) { From b77643b92899fef607bae690e48a8b0354ee81d3 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 03:54:59 +0300 Subject: [PATCH 095/118] remove proxy from menu --- menu.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/menu.js b/menu.js index 0ab62c7f..957d2b2b 100644 --- a/menu.js +++ b/menu.js @@ -143,14 +143,6 @@ const mainMenuTemplate = (win) => [ { label: "Advanced options", submenu: [ - { - label: "Proxy", - type: "checkbox", - checked: !!config.get("options.proxy"), - click: (item) => { - setProxy(item, win); - } - }, { label: "Disable hardware acceleration", type: "checkbox", From 729714375b5332fc11751b493bcaa970522f303f Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 04:27:50 +0300 Subject: [PATCH 096/118] update camelCase --- plugins/notifications/interactive.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 9dbed278..2afb1c49 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -14,7 +14,7 @@ module.exports.setupInteractive = (win, unpauseNotification) => { onPause = unpauseNotification; win.webContents.once("closed", () => { - Delete() + deleteNotification() }); } @@ -33,7 +33,7 @@ function deleteNotification() { //New notification module.exports.notifyInteractive = function sendToaster(songInfo) { - Delete(); + deleteNotification(); //download image and get path let imgSrc = notificationImage(songInfo, true); toDelete = { @@ -84,7 +84,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { //Native datatype case "dismissed": case "timeout": - Delete(); + deleteNotification(); } } From d2925ee3f957e0901a40609d51da24a204bf04f6 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 04:30:19 +0300 Subject: [PATCH 097/118] make variable names clearer --- plugins/notifications/interactive.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 2afb1c49..21fd6603 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -4,14 +4,14 @@ const notifier = require("node-notifier"); //store song controls reference on launch let controls; -let onPause; +let NotificationOnPause; //Save controls and onPause option module.exports.setupInteractive = (win, unpauseNotification) => { const { playPause, next, previous } = getSongControls(win); controls = { playPause, next, previous }; - onPause = unpauseNotification; + NotificationOnPause = unpauseNotification; win.webContents.once("closed", () => { deleteNotification() @@ -22,6 +22,7 @@ module.exports.setupInteractive = (win, unpauseNotification) => { 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 }) @@ -70,7 +71,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { // dont delete notification on play/pause toDelete = undefined; //manually send notification if not sending automatically - if (!onPause) { + if (!NotificationOnPause) { songInfo.isPaused = false; sendToaster(songInfo); } From 66517af81cf70005eff87a9229ee874178018a4c Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 16:33:12 +0300 Subject: [PATCH 098/118] fix typo --- plugins/notifications/interactive.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/notifications/interactive.js b/plugins/notifications/interactive.js index 21fd6603..cb487cae 100644 --- a/plugins/notifications/interactive.js +++ b/plugins/notifications/interactive.js @@ -4,14 +4,14 @@ const notifier = require("node-notifier"); //store song controls reference on launch let controls; -let NotificationOnPause; +let notificationOnPause; //Save controls and onPause option module.exports.setupInteractive = (win, unpauseNotification) => { const { playPause, next, previous } = getSongControls(win); controls = { playPause, next, previous }; - NotificationOnPause = unpauseNotification; + notificationOnPause = unpauseNotification; win.webContents.once("closed", () => { deleteNotification() @@ -71,7 +71,7 @@ module.exports.notifyInteractive = function sendToaster(songInfo) { // dont delete notification on play/pause toDelete = undefined; //manually send notification if not sending automatically - if (!NotificationOnPause) { + if (!notificationOnPause) { songInfo.isPaused = false; sendToaster(songInfo); } From e272d38ca5e00b19eb70af578c2cdf6c64a08e53 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 16:54:05 +0300 Subject: [PATCH 099/118] fix typo --- plugins/taskbar-mediacontrol/back.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index 73f35762..18397b6c 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -3,7 +3,7 @@ const getSongInfo = require('../../providers/song-info'); const path = require('path'); let controls; -let CurrentSongInfo; +let currentSongInfo; module.exports = win => { const registerCallback = getSongInfo(win); @@ -12,15 +12,15 @@ module.exports = win => { registerCallback(songInfo => { //update currentsonginfo for win.on('show') - CurrentSongInfo = songInfo; + currentSongInfo = songInfo; // update thumbar setThumbar(win, songInfo) }); // need to set thumbar again after win.show win.on("show", () => { - if (CurrentSongInfo) { - setThumbar(win, CurrentSongInfo) + if (currentSongInfo) { + setThumbar(win, currentSongInfo) } }) }; From d0800bb31ca99e99558739457570766071bddafc Mon Sep 17 00:00:00 2001 From: Araxeus Date: Wed, 28 Apr 2021 16:58:14 +0300 Subject: [PATCH 100/118] small refactor --- plugins/taskbar-mediacontrol/back.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index 18397b6c..46cb399e 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -8,26 +8,24 @@ let currentSongInfo; module.exports = win => { const registerCallback = getSongInfo(win); const { playPause, next, previous } = getSongControls(win); - controls = { playPause, next, previous } + controls = { playPause, next, previous }; registerCallback(songInfo => { //update currentsonginfo for win.on('show') currentSongInfo = songInfo; // update thumbar - setThumbar(win, songInfo) + setThumbar(win, songInfo); }); // need to set thumbar again after win.show win.on("show", () => { - if (currentSongInfo) { - setThumbar(win, currentSongInfo) - } + setThumbar(win, currentSongInfo) }) }; function setThumbar(win, songInfo) { // Wait for song to start before setting thumbar - if (!songInfo.title) { + if (!songInfo?.title) { return; } From ba02d372f76f581592c2b291eab86b8d58068670 Mon Sep 17 00:00:00 2001 From: TC Date: Wed, 28 Apr 2021 22:23:31 +0200 Subject: [PATCH 101/118] Update yarn.lock --- yarn.lock | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index b3e533cb..6ca9d0b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1708,13 +1708,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== - dependencies: - follow-redirects "^1.10.0" - babel-eslint@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -3988,11 +3981,6 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== -follow-redirects@^1.10.0: - version "1.13.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" - integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA== - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" From c38035188b0abb845eb12e17f890c9b0e1ac0c6b Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 29 Apr 2021 02:19:11 +0000 Subject: [PATCH 102/118] 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 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 54a75d66..f1b86b9a 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "electron-debug": "^3.2.0", "electron-is": "^3.0.0", "electron-localshortcut": "^3.2.1", - "electron-store": "^7.0.2", + "electron-store": "^7.0.3", "electron-unhandled": "^3.0.2", "electron-updater": "^4.3.6", "filenamify": "^4.2.0", diff --git a/yarn.lock b/yarn.lock index 6ca9d0b3..8538a0f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3115,10 +3115,10 @@ electron-publish@22.9.1: lazy-val "^1.0.4" mime "^2.4.6" -electron-store@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-7.0.2.tgz#e45a54d092ea43e2a953619ed4473893d448dfdf" - integrity sha512-tSUeHF9qdiPirph8JKJvIIcdVb3wYwgHUJCE38SJq4L08Op2z1+u8DSQ42Nvx34TKvb2lkQkByV0tHh6xBxdEQ== +electron-store@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-7.0.3.tgz#56d78284454018ed50ffc7645da49f828ae5ff19" + integrity sha512-wIbw4GHt4djs4dVrlRLCD/SpdpDUiRsQc212jagGA6zJ8xt1iwx3KZIzXY8gmwvgVCOcVxi3iyCXZoBBWwBXpQ== dependencies: conf "^9.0.0" type-fest "^0.20.2" From 8a5c39ee5378409b565709ef67845f478a5b35c6 Mon Sep 17 00:00:00 2001 From: TC Date: Thu, 29 Apr 2021 22:56:33 +0200 Subject: [PATCH 103/118] Fix download URL --- plugins/downloader/front.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/downloader/front.js b/plugins/downloader/front.js index a29c9086..e4930f09 100644 --- a/plugins/downloader/front.js +++ b/plugins/downloader/front.js @@ -44,7 +44,7 @@ global.download = () => { .getAttribute("href"); videoUrl = !videoUrl ? global.songInfo.url || window.location.href - : baseUrl + videoUrl; + : baseUrl + "/" + videoUrl; downloadVideoToMP3( videoUrl, From c11ecd3323e3781eed00875049e269b825499c3f Mon Sep 17 00:00:00 2001 From: TC Date: Thu, 29 Apr 2021 22:57:12 +0200 Subject: [PATCH 104/118] Set max file length to 255 in downloader --- plugins/downloader/youtube-dl.js | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/downloader/youtube-dl.js b/plugins/downloader/youtube-dl.js index 4fb8ac75..1ebe0a06 100644 --- a/plugins/downloader/youtube-dl.js +++ b/plugins/downloader/youtube-dl.js @@ -126,6 +126,7 @@ const toMP3 = async ( : videoName; const filename = filenamify(name + "." + extension, { replacement: "_", + maxLength: 255, }); const filePath = join(folder, subfolder, filename); From dfbda7c10bc1cecb669344f0659a4415628111bb Mon Sep 17 00:00:00 2001 From: TC Date: Thu, 29 Apr 2021 22:57:47 +0200 Subject: [PATCH 105/118] Set metadata in back (to have cover) --- plugins/downloader/back.js | 32 +++++++++++++++++++++++++++++++- plugins/downloader/youtube-dl.js | 31 ++++++------------------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/plugins/downloader/back.js b/plugins/downloader/back.js index 8d15a429..49b5eea5 100644 --- a/plugins/downloader/back.js +++ b/plugins/downloader/back.js @@ -1,6 +1,8 @@ +const { writeFileSync } = require("fs"); const { join } = require("path"); -const { dialog } = require("electron"); +const ID3Writer = require("browser-id3-writer"); +const { dialog, ipcMain } = require("electron"); const getSongInfo = require("../../providers/song-info"); const { injectCSS, listenAction } = require("../utils"); @@ -38,6 +40,34 @@ function handle(win) { console.log("Unknown action: " + action); } }); + + ipcMain.on("add-metadata", (event, filePath, songBuffer, currentMetadata) => { + let fileBuffer = songBuffer; + const songMetadata = { ...metadata, ...currentMetadata }; + + try { + const coverBuffer = songMetadata.image.toPNG(); + const writer = new ID3Writer(songBuffer); + + // Create the metadata tags + writer + .setFrame("TIT2", songMetadata.title) + .setFrame("TPE1", [songMetadata.artist]) + .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; diff --git a/plugins/downloader/youtube-dl.js b/plugins/downloader/youtube-dl.js index 1ebe0a06..1a212aaf 100644 --- a/plugins/downloader/youtube-dl.js +++ b/plugins/downloader/youtube-dl.js @@ -1,9 +1,7 @@ const { randomBytes } = require("crypto"); -const { writeFileSync } = require("fs"); const { join } = require("path"); const Mutex = require("async-mutex").Mutex; -const ID3Writer = require("browser-id3-writer"); const { ipcRenderer } = require("electron"); const is = require("electron-is"); const filenamify = require("filenamify"); @@ -133,29 +131,12 @@ const toMP3 = async ( const fileBuffer = ffmpeg.FS("readFile", safeVideoName + "." + extension); // Add the metadata - try { - const writer = new ID3Writer(fileBuffer); - if (metadata.image) { - const coverBuffer = metadata.image.toPNG(); - - // Create the metadata tags - writer - .setFrame("TIT2", metadata.title) - .setFrame("TPE1", [metadata.artist]) - .setFrame("APIC", { - type: 3, - data: coverBuffer, - description: "", - }); - writer.addTag(); - } - - writeFileSync(filePath, Buffer.from(writer.arrayBuffer)); - } catch (error) { - sendError(error); - } finally { - reinit(); - } + sendFeedback("Adding metadata…"); + ipcRenderer.send("add-metadata", filePath, fileBuffer, { + artist: metadata.artist, + title: metadata.title, + }); + ipcRenderer.once("add-metadata-done", reinit); } catch (e) { sendError(e); } finally { From 0468a23c4f0f9a6bbc10c58560dcc3b2dd46096b Mon Sep 17 00:00:00 2001 From: TC Date: Thu, 29 Apr 2021 23:28:27 +0200 Subject: [PATCH 106/118] Fix getFolder util (main/renderer process) --- plugins/downloader/utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/downloader/utils.js b/plugins/downloader/utils.js index 0eab78c5..e2763541 100644 --- a/plugins/downloader/utils.js +++ b/plugins/downloader/utils.js @@ -1,4 +1,5 @@ -const { app } = require("electron"); +const electron = require("electron"); -module.exports.getFolder = (customFolder) => customFolder || app.getPath("downloads"); +module.exports.getFolder = (customFolder) => + customFolder || (electron.app || electron.remote.app).getPath("downloads"); module.exports.defaultMenuDownloadLabel = "Download playlist"; From 442aafd2c56972614ba1f634c39a803a7f38db39 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sun, 2 May 2021 23:25:20 +0300 Subject: [PATCH 107/118] remove redundant dialog import --- index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.js b/index.js index 80ba9efe..75d85348 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,6 @@ const path = require("path"); const electron = require("electron"); -const { dialog } = require("electron"); const is = require("electron-is"); const unhandled = require("electron-unhandled"); const { autoUpdater } = require("electron-updater"); @@ -327,7 +326,7 @@ function showUnresponsiveDialog(win, details) { if (!!details) { console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t")) } - dialog.showMessageBox(win, { + electron.dialog.showMessageBox(win, { type: "error", title: "Window Unresponsive", message: "The Application is Unresponsive", From 1f69048c866a703c03c755573162ce1dc5d28b17 Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 2 May 2021 23:25:34 +0300 Subject: [PATCH 108/118] minify switch case Co-authored-by: th-ch --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index 80ba9efe..681b5a8e 100644 --- a/index.js +++ b/index.js @@ -341,7 +341,6 @@ function showUnresponsiveDialog(win, details) { case 2: app.quit(); break; - case 0: default: break; } From 02d16ca51084c1343bb0fb273f775971d2b844ee Mon Sep 17 00:00:00 2001 From: Araxeus <78568641+Araxeus@users.noreply.github.com> Date: Sun, 2 May 2021 23:25:46 +0300 Subject: [PATCH 109/118] fix typo Co-authored-by: th-ch --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 681b5a8e..9ee68492 100644 --- a/index.js +++ b/index.js @@ -331,7 +331,7 @@ function showUnresponsiveDialog(win, details) { type: "error", title: "Window Unresponsive", message: "The Application is Unresponsive", - details: "We are sorry for the inconveniance! please choose what to do:", + details: "We are sorry for the inconvenience! please choose what to do:", buttons: ["Wait", "Relaunch", "Quit"], cancelId: 0 }).then( result => { From f65c6c89aea9713d1302f840cbc230fa1ba08ecb Mon Sep 17 00:00:00 2001 From: TC Date: Sun, 2 May 2021 22:30:24 +0200 Subject: [PATCH 110/118] Fix package.json indent, update yarn.lock --- package.json | 2 +- yarn.lock | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/package.json b/package.json index 6d0d90a9..3e439844 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "filenamify": "^4.2.0", "md5": "^2.3.0", "node-fetch": "^2.6.1", - "node-notifier": "^9.0.1", + "node-notifier": "^9.0.1", "open": "^8.0.3", "ytdl-core": "^4.5.0", "ytpl": "^2.1.1" diff --git a/yarn.lock b/yarn.lock index af2b6f94..c986cab0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6549,11 +6549,6 @@ node-notifier@^9.0.1: uuid "^8.3.0" which "^2.0.2" -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - node-releases@^1.1.70: version "1.1.71" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" From 8f766bcbaad8da0ea3ec6f22e56fb9f893f27867 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Sun, 2 May 2021 23:41:16 +0300 Subject: [PATCH 111/118] resolve merge conflict --- plugins/taskbar-mediacontrol/back.js | 86 +++++++++++++--------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js index a8133539..46cb399e 100644 --- a/plugins/taskbar-mediacontrol/back.js +++ b/plugins/taskbar-mediacontrol/back.js @@ -2,57 +2,53 @@ const getSongControls = require('../../providers/song-controls'); const getSongInfo = require('../../providers/song-info'); const path = require('path'); +let controls; +let currentSongInfo; + module.exports = win => { - win.hide = function () { - win.minimize(); - win.setSkipTaskbar(true); - }; - - const show = win.show; - win.show = function () { - win.restore(); - win.focus(); - win.setSkipTaskbar(false); - show.apply(win); - }; - - win.isVisible = function () { - return !win.isMinimized(); - }; - const registerCallback = getSongInfo(win); - const {playPause, next, previous} = getSongControls(win); + const { playPause, next, previous } = getSongControls(win); + controls = { playPause, next, previous }; - // If the page is ready, register the callback - win.once('ready-to-show', () => { - registerCallback(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() {previous(win.webContents);} - }, { - tooltip: 'Play/Pause', - // Update icon based on play state - icon: songInfo.isPaused ? get('play.png') : get('pause.png'), - click() {playPause(win.webContents);} - }, { - tooltip: 'Next', - icon: get('forward.png'), - click() {next(win.webContents);} - } - ]); - }); + 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); + return path.join(__dirname, "assets", file); } From 7dbb5fc86dbba39cbe35e4d16eac86bb8d792f20 Mon Sep 17 00:00:00 2001 From: TC Date: Sun, 2 May 2021 22:41:38 +0200 Subject: [PATCH 112/118] Update electron to 11.4.4 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3e439844..76ddd495 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "ytpl": "^2.1.1" }, "devDependencies": { - "electron": "^11.4.2", + "electron": "^11.4.4", "electron-builder": "^22.10.5", "electron-devtools-installer": "^3.1.1", "electron-icon-maker": "0.0.5", diff --git a/yarn.lock b/yarn.lock index c986cab0..7f6265bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3365,10 +3365,10 @@ electron-updater@^4.3.8: lodash.isequal "^4.5.0" semver "^7.3.4" -electron@^11.4.2: - version "11.4.2" - resolved "https://registry.yarnpkg.com/electron/-/electron-11.4.2.tgz#02005d9f5d77ea6485efeffdb5c5433c769ddda4" - integrity sha512-P0PRLH7cXp8ZdpA9yVPe7jRVM+QeiAtsadqmqS6XY3AYrsH+7bJnVrNuw6p/fcmp+b/UxWaCexobqQpyFJ5Qkw== +electron@^11.4.4: + version "11.4.4" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.4.4.tgz#d6c046dedd9e22df5f6408841c3f8ae1a1d59414" + integrity sha512-m52nF85VADCmL9DpzJfgmkvc9fNiGZPYwptv/4fTYrYhAMiO+hmClGMXncCoSAzoULQjl+f+0b9CY4yd6nRFlQ== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" From c7ff536ed5282d8e35457a1e9668dbb32d33c92b Mon Sep 17 00:00:00 2001 From: TC Date: Mon, 3 May 2021 22:24:19 +0200 Subject: [PATCH 113/118] Bump version to 1.12.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76ddd495..c3049f21 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "youtube-music", "productName": "YouTube Music", - "version": "1.11.0", + "version": "1.12.0", "description": "YouTube Music Desktop App - including custom plugins", "license": "MIT", "repository": "th-ch/youtube-music", From d5b9e3c96029922812933350b655bd89de45ddcb Mon Sep 17 00:00:00 2001 From: Araxeus Date: Tue, 4 May 2021 01:22:47 +0300 Subject: [PATCH 114/118] stringify did-fail-load error directly preload front-logger simplify front-logger --- index.js | 6 +++--- preload.js | 3 +-- providers/front-logger.js | 8 +++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index e28607c1..8c98e2c9 100644 --- a/index.js +++ b/index.js @@ -168,7 +168,7 @@ app.once("browser-window-created", (event, win) => { frameProcessId, frameRoutingId, ) => { - const log = { + const log = JSON.stringify({ error: "did-fail-load", event, errorCode, @@ -177,9 +177,9 @@ app.once("browser-window-created", (event, win) => { isMainFrame, frameProcessId, frameRoutingId, - }; + }, null, "\t"); if (is.dev()) { - console.log(log.toString()); + console.log(log); } win.webContents.send("log", log); win.webContents.loadFile(path.join(__dirname, "error.html")); diff --git a/preload.js b/preload.js index 74860cec..e0ce9ffe 100644 --- a/preload.js +++ b/preload.js @@ -34,8 +34,7 @@ document.addEventListener("DOMContentLoaded", () => { fileExists(songInfoProviderPath, require(songInfoProviderPath)); // inject front logger - const loggerPath = path.join(__dirname, "providers", "front-logger.js") - fileExists(loggerPath, require(loggerPath)); + require("./providers/front-logger")(); // Add action for reloading global.reload = () => diff --git a/providers/front-logger.js b/providers/front-logger.js index 210e3ff8..986cbb6f 100644 --- a/providers/front-logger.js +++ b/providers/front-logger.js @@ -1,11 +1,9 @@ const { ipcRenderer } = require("electron"); function logToString(log) { - let string = (typeof log === "string") ? log : log.toString(); - if (!string || string.includes("[object Object]")) { - string = JSON.stringify(log, null, "\t"); - } - return string; + return (typeof log === "string") ? + log : + JSON.stringify(log, null, "\t"); } module.exports = () => { From fb81e1bdd5fd15dd97706eb0799b45966f7d9db1 Mon Sep 17 00:00:00 2001 From: Araxeus Date: Tue, 4 May 2021 02:04:17 +0300 Subject: [PATCH 115/118] ignore did-fail-load error code `-3` bug with in-app-menu --- index.js | 9 +++++---- providers/front-logger.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 8c98e2c9..81fd45b5 100644 --- a/index.js +++ b/index.js @@ -160,7 +160,7 @@ app.once("browser-window-created", (event, win) => { loadPlugins(win); win.webContents.on("did-fail-load", ( - event, + _event, errorCode, errorDescription, validatedURL, @@ -170,7 +170,6 @@ app.once("browser-window-created", (event, win) => { ) => { const log = JSON.stringify({ error: "did-fail-load", - event, errorCode, errorDescription, validatedURL, @@ -181,8 +180,10 @@ app.once("browser-window-created", (event, win) => { if (is.dev()) { console.log(log); } - win.webContents.send("log", log); - win.webContents.loadFile(path.join(__dirname, "error.html")); + 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) => { diff --git a/providers/front-logger.js b/providers/front-logger.js index 986cbb6f..99da2329 100644 --- a/providers/front-logger.js +++ b/providers/front-logger.js @@ -7,7 +7,7 @@ function logToString(log) { } module.exports = () => { - ipcRenderer.on("log", (event, log) => { + ipcRenderer.on("log", (_event, log) => { console.log(logToString(log)); }); }; From 4cb658dacaa59e88ca41d4983e08ef237f7093c2 Mon Sep 17 00:00:00 2001 From: TC Date: Tue, 4 May 2021 21:29:39 +0200 Subject: [PATCH 116/118] Remove preload.js in plugin uses and use front plugin injection --- plugins/precise-volume/back.js | 1 - plugins/precise-volume/front.js | 27 +++++++++++++++++++++++++++ plugins/precise-volume/preload.js | 28 ---------------------------- preload.js | 6 ------ 4 files changed, 27 insertions(+), 35 deletions(-) delete mode 100644 plugins/precise-volume/preload.js diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index 93ebea9f..9546e077 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -13,7 +13,6 @@ module.exports = (win) => { // did-finish-load is called after all elements finished loading, including said listeners // Thats the reason the timing is controlled from main win.webContents.once("did-finish-load", () => { - win.webContents.send("restoreAddEventListener"); win.webContents.send("setupVideoPlayerVolumeMousewheel", !isEnabled("hide-video-player")); }); }; diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index a1b30fe4..38fd5fc2 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -5,6 +5,7 @@ const { setOptions } = require("../../config/plugins"); function $(selector) { return document.querySelector(selector); } module.exports = (options) => { + overrideAddEventListener(); setupPlaybar(options); @@ -22,9 +23,35 @@ module.exports = (options) => { ipcRenderer.once("setupVideoPlayerVolumeMousewheel", (_event, toEnable) => { if (toEnable) setupVideoPlayerOnwheel(options); + // Restore original function after did-finish-load to avoid keeping Element.prototype altered + Element.prototype.addEventListener = Element.prototype._addEventListener; }); }; +// Override specific listeners of volume-slider by modifying Element.prototype +function overrideAddEventListener() { + // Events to ignore + const nativeEvents = ["mousewheel", "keydown", "keyup"]; + // 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 (this.tagName === "TP-YT-PAPER-SLIDER") { + // tagName of #volume-slider + for (const eventType of nativeEvents) { + if (eventType === type) { + return; + } + } + } //else + this._addEventListener(type, listener, useCapture); + }; +} + /** Add onwheel event to video player */ function setupVideoPlayerOnwheel(options) { $("#main-panel").addEventListener("wheel", event => { diff --git a/plugins/precise-volume/preload.js b/plugins/precise-volume/preload.js deleted file mode 100644 index bfd6a01c..00000000 --- a/plugins/precise-volume/preload.js +++ /dev/null @@ -1,28 +0,0 @@ -const { ipcRenderer } = require("electron"); - -// Override specific listeners of volume-slider by modifying Element.prototype -function overrideAddEventListener() { - // Events to ignore - const nativeEvents = ["mousewheel", "keydown", "keyup"]; - // 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 (this.tagName === "TP-YT-PAPER-SLIDER") { // tagName of #volume-slider - for (const eventType of nativeEvents) { - if (eventType === type) { - return; - } - } - }//else - this._addEventListener(type, listener, useCapture); - }; -} - -module.exports = () => { - overrideAddEventListener(); - // Restore original function after did-finish-load to avoid keeping Element.prototype altered - ipcRenderer.once("restoreAddEventListener", () => { //called from Main to make sure page is completly loaded - Element.prototype.addEventListener = Element.prototype._addEventListener; - }); -}; diff --git a/preload.js b/preload.js index 500bda8d..fae01d96 100644 --- a/preload.js +++ b/preload.js @@ -8,12 +8,6 @@ const { fileExists } = require("./plugins/utils"); const plugins = config.plugins.getEnabled(); plugins.forEach(([plugin, options]) => { - const preloadPath = path.join(__dirname, "plugins", plugin, "preload.js"); - fileExists(preloadPath, () => { - const run = require(preloadPath); - run(options); - }); - const actionPath = path.join(__dirname, "plugins", plugin, "actions.js"); fileExists(actionPath, () => { const actions = require(actionPath).actions || {}; From bf409967b23dec3eb9241c0ca120919129205d52 Mon Sep 17 00:00:00 2001 From: TC Date: Tue, 4 May 2021 21:30:10 +0200 Subject: [PATCH 117/118] Import front logger at top level --- preload.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/preload.js b/preload.js index fae01d96..1b9555e5 100644 --- a/preload.js +++ b/preload.js @@ -4,6 +4,7 @@ const { remote } = require("electron"); const config = require("./config"); const { fileExists } = require("./plugins/utils"); +const setupFrontLogger = require("./providers/front-logger"); const plugins = config.plugins.getEnabled(); @@ -34,7 +35,7 @@ document.addEventListener("DOMContentLoaded", () => { fileExists(songInfoProviderPath, require(songInfoProviderPath)); // inject front logger - require("./providers/front-logger")(); + setupFrontLogger(); // Add action for reloading global.reload = () => From d4811b79012f5fd8f9ff0f9eb4ff55f6b166bd73 Mon Sep 17 00:00:00 2001 From: TC Date: Tue, 4 May 2021 22:31:49 +0200 Subject: [PATCH 118/118] Revert "Remove preload.js in plugin uses and use front plugin injection" This reverts commit 4cb658dacaa59e88ca41d4983e08ef237f7093c2. --- plugins/precise-volume/back.js | 1 + plugins/precise-volume/front.js | 27 --------------------------- plugins/precise-volume/preload.js | 28 ++++++++++++++++++++++++++++ preload.js | 6 ++++++ 4 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 plugins/precise-volume/preload.js diff --git a/plugins/precise-volume/back.js b/plugins/precise-volume/back.js index 9546e077..93ebea9f 100644 --- a/plugins/precise-volume/back.js +++ b/plugins/precise-volume/back.js @@ -13,6 +13,7 @@ module.exports = (win) => { // did-finish-load is called after all elements finished loading, including said listeners // Thats the reason the timing is controlled from main win.webContents.once("did-finish-load", () => { + win.webContents.send("restoreAddEventListener"); win.webContents.send("setupVideoPlayerVolumeMousewheel", !isEnabled("hide-video-player")); }); }; diff --git a/plugins/precise-volume/front.js b/plugins/precise-volume/front.js index 38fd5fc2..a1b30fe4 100644 --- a/plugins/precise-volume/front.js +++ b/plugins/precise-volume/front.js @@ -5,7 +5,6 @@ const { setOptions } = require("../../config/plugins"); function $(selector) { return document.querySelector(selector); } module.exports = (options) => { - overrideAddEventListener(); setupPlaybar(options); @@ -23,35 +22,9 @@ module.exports = (options) => { ipcRenderer.once("setupVideoPlayerVolumeMousewheel", (_event, toEnable) => { if (toEnable) setupVideoPlayerOnwheel(options); - // Restore original function after did-finish-load to avoid keeping Element.prototype altered - Element.prototype.addEventListener = Element.prototype._addEventListener; }); }; -// Override specific listeners of volume-slider by modifying Element.prototype -function overrideAddEventListener() { - // Events to ignore - const nativeEvents = ["mousewheel", "keydown", "keyup"]; - // 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 (this.tagName === "TP-YT-PAPER-SLIDER") { - // tagName of #volume-slider - for (const eventType of nativeEvents) { - if (eventType === type) { - return; - } - } - } //else - this._addEventListener(type, listener, useCapture); - }; -} - /** Add onwheel event to video player */ function setupVideoPlayerOnwheel(options) { $("#main-panel").addEventListener("wheel", event => { diff --git a/plugins/precise-volume/preload.js b/plugins/precise-volume/preload.js new file mode 100644 index 00000000..bfd6a01c --- /dev/null +++ b/plugins/precise-volume/preload.js @@ -0,0 +1,28 @@ +const { ipcRenderer } = require("electron"); + +// Override specific listeners of volume-slider by modifying Element.prototype +function overrideAddEventListener() { + // Events to ignore + const nativeEvents = ["mousewheel", "keydown", "keyup"]; + // 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 (this.tagName === "TP-YT-PAPER-SLIDER") { // tagName of #volume-slider + for (const eventType of nativeEvents) { + if (eventType === type) { + return; + } + } + }//else + this._addEventListener(type, listener, useCapture); + }; +} + +module.exports = () => { + overrideAddEventListener(); + // Restore original function after did-finish-load to avoid keeping Element.prototype altered + ipcRenderer.once("restoreAddEventListener", () => { //called from Main to make sure page is completly loaded + Element.prototype.addEventListener = Element.prototype._addEventListener; + }); +}; diff --git a/preload.js b/preload.js index 1b9555e5..6cdaebdd 100644 --- a/preload.js +++ b/preload.js @@ -9,6 +9,12 @@ const setupFrontLogger = require("./providers/front-logger"); const plugins = config.plugins.getEnabled(); plugins.forEach(([plugin, options]) => { + const preloadPath = path.join(__dirname, "plugins", plugin, "preload.js"); + fileExists(preloadPath, () => { + const run = require(preloadPath); + run(options); + }); + const actionPath = path.join(__dirname, "plugins", plugin, "actions.js"); fileExists(actionPath, () => { const actions = require(actionPath).actions || {};