diff --git a/moz.xpi b/moz.xpi index b9337fd..552d7a9 100644 Binary files a/moz.xpi and b/moz.xpi differ diff --git a/moz.zip b/moz.zip index 7519227..82d0fb0 100644 Binary files a/moz.zip and b/moz.zip differ diff --git a/moz/__test__.js b/moz/__test__.js deleted file mode 100644 index 68ee2d5..0000000 --- a/moz/__test__.js +++ /dev/null @@ -1,2 +0,0 @@ -/* global Update(type:string, details:object) */ -(init = () => Update('SCRIPT', { script: '__test__' }))(); diff --git a/moz/compare.js b/moz/compare.js new file mode 100644 index 0000000..9cb6275 --- /dev/null +++ b/moz/compare.js @@ -0,0 +1,38 @@ +/** GitHub@alexey-bass + * Simply compares two string version values. + * + * Example: + * compareVer('1.1', '1.2') => -1 + * compareVer('1.1', '1.1') => 0 + * compareVer('1.2', '1.1') => 1 + * compareVer('2.23.3', '2.22.3') => 1 + * + * Returns: + * -1 = left is LOWER = right is GREATER + * 0 = they are equal + * 1 = left is GREATER = right is LOWER + * And FALSE if one of input versions are not valid + * + * @function + * @param {String} left Version #1 + * @param {String} right Version #2 + * @return {Integer|Boolean} + * @author Alexey Bass (albass) + * @since 2011-07-14 + */ +function compareVer(left, right) { + if(typeof left + typeof right != 'stringstring') + return false; + + for(let a = left.split('.'), b = right.split('.'), i = 0, l = Math.max(a.length, b.length); i < l; i++) { + if((a[i] && !b[i] && parseInt(a[i]) > 0) || (parseInt(a[i]) > parseInt(b[i]))) + return +1 + /* left is higher */; + else if((b[i] && !a[i] && parseInt(b[i]) > 0) || (parseInt(a[i]) < parseInt(b[i]))) + return -1 + /* right is higher */; + } + + return 0 + /* equal */; +} diff --git a/moz/loading.png b/moz/loading.png deleted file mode 100644 index 749aa93..0000000 Binary files a/moz/loading.png and /dev/null differ diff --git a/moz/manifest.json b/moz/manifest.json index eeaea16..992f9f7 100644 --- a/moz/manifest.json +++ b/moz/manifest.json @@ -4,7 +4,7 @@ "homepage_url": "https://github.com/SpaceK33z/web-to-plex/", "manifest_version": 2, - "version": "4.1.1.6", + "version": "4.1.1.7", "browser_specific_settings": { "gecko": { "id": "mink.cbos@gmail.com", @@ -70,12 +70,6 @@ "all_frames": true }, - // Testing purposes only - { - "matches": ["*://ephellon.github.io/web.to.plex/test/*"], - "js": ["utils.js", "__test__.js"] - }, - // The sites { "matches": ["*://*.movieo.me/*"], diff --git a/moz/movie.poster.jpg b/moz/movie.poster.jpg deleted file mode 100644 index efdc64f..0000000 Binary files a/moz/movie.poster.jpg and /dev/null differ diff --git a/moz/options.css b/moz/options.css index 6f68ef2..bc3ac0b 100644 --- a/moz/options.css +++ b/moz/options.css @@ -81,11 +81,12 @@ a { text-decoration: none !important; } -a[target="_blank"]::after { +[target="_blank"]:not(#version)::after { content: " [\2197]"; font-size: 70%; vertical-align: super; +}ertical-align: super; } hr { @@ -281,6 +282,8 @@ summary, option { } #sidebar summary { + font-size: 12px; + margin-left: -50px; padding-left: 50px; } @@ -297,7 +300,8 @@ summary, option { } #sidebar .checkbox { - display: none; + display: block; + transform: scale(0.75); } display > summary:first-child { @@ -337,18 +341,18 @@ details:last-child > summary { margin: 6px 12px; } -#footer { +footer { bottom: 0; position: fixed; width: 100%; } -[in-use] { +[using], [counter-for] { color: #197bcc; } -[in-use]::after { +[using]::after { content: '\2610'; } @@ -356,6 +360,33 @@ details:last-child > summary { content: '\2611'; } +[special][using]:not([in-use="true"i]) { + color: #666; +} + +[special][in-use="true"i], [special][counter-for] { + color: #cc7b19; +} + +[counter-for] { + border: 1px solid #197bcc; + + margin: 0; + padding: 0 3px; +} + +[counter-for][in-use]::after { + content: '' !important; +} + +[special][counter-for] { + border-color: #cc7b19; +} + +#sidebar [counter-for] { + font-size: 10px; +} + [top] { border-bottom-left-radius: 0 !important; border-bottom-right-radius: 0 !important; @@ -379,6 +410,14 @@ details:last-child > summary { background: #298bdc !important; } +#sidebar .checkbox:not([special]) { + display: none !important; +} + +display summary [using]:not([special]) { + display: none !important; +} + /* bbodine @CodePen - https://codepen.io/bbodine1/pen/novBm */ .checkbox { width: 80px; @@ -480,6 +519,11 @@ span.checkbox { opacity: 0.25 !important; } +.checkbox[disabled] + [using] { + color: #666; + opacity: 0.25; +} + [white] { color: #fff !important; } @@ -490,7 +534,7 @@ span.checkbox { input[type="range"] { appearance: none; - -webkit-appearance: none; + -moz-appearance: none; background: #0004; outline: #0000; @@ -525,10 +569,7 @@ input[type="range"] + output::after { content: ''; } -input[type="range"]::-webkit-slider-thumb { - appearance: none; - -webkit-appearance: none; - +input[type="range"]::-moz-range-thumb { background: #cc7b19; border: 1px solid #cc7b19; border-radius: 100%; @@ -538,34 +579,52 @@ input[type="range"]::-webkit-slider-thumb { width: 32px; } -input[type="range"]::-moz-range-thumb { - background: #cc7b19; - border: 1px solid #cc7b19; - border-radius: 100%; - cursor: pointer; +[disabled], [disabled] * { + cursor: not-allowed !important; + color: #909090EE !important; +} - height: 32px; - width: 32px; +[code], code { + background: #222 !important; + border-radius: 3px !important; + box-shadow: none !important; + box-sizing: border-box !important; + font-family: "System, Monospace, Menlo, Arial", Consolas, "Liberation Mono", Menlo, Courier, monospace !important; + font-size: 12px !important; + line-height: 18px !important; + + margin: 0 !important; + padding: 0.2em 0.4em !important; } #version { - color: #fff; + background: #0000 !important; + border: 1px solid #666 !important; + color: #666 !important; - position: fixed; - right: 4px; - top: calc(100vh - 24px); + position: fixed !important; + right: 12px !important; + top: calc(100vh - 30px) !important; + + transition: border 0.15s, color 0.15s; } -[disabled], [disabled] * { - cursor: not-allowed !important; - color: #909090EE !important; +/* Release is higher than GitHub */ +#version[status="high"] { + border-color: #6cc644 !important; + color: #6cc644 !important; } -[code], code { - border: 1px solid #FFF3; - font-family: monospace, console, consolas, system, arial !important; +/* Release is same as GitHub */ +#version[status="same"] { + border-color: #197bcc !important; + color: #197bcc !important; +} - padding: 0 3px; +/* Release is lower than GitHub */ +#version[status="low"] { + border-color: #f66a0a !important; + color: #f3582c !important; } /* notifications */ @@ -589,6 +648,7 @@ input[type="range"]::-moz-range-thumb { z-index: 999999; } + /* Web to Plex general information notifications */ .notification.info { background: #666 !important; @@ -655,7 +715,7 @@ input[type="range"]::-moz-range-thumb { height: 65px; width: 100%; - -webkit-tap-highlight-color: #0000; + /* -webkit-tap-highlight-color: #0000; */ } .prompt-header { @@ -758,21 +818,9 @@ input[type="range"]::-moz-range-thumb { background: #ffffff4d !important; } - -*::-webkit-scrollbar { - width: 10px; -} - -*::-webkit-scrollbar-thumb { - min-height: 50px; - background: rgba(255, 255, 255, 0.15); - border: 2px solid rgba(0, 0, 0, 0); - border-radius: 8px; - background-clip: padding-box; -} - -*::-webkit-scrollbar-track { - /* background: url(noise.png) fixed, #3f4245 !important; */ +* { + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.15); } *::placeholder { @@ -783,10 +831,6 @@ input[type="range"]::-moz-range-thumb { color: #999; } -*::-webkit-input-placeholder { - color: #999; -} - @keyframes spin { 0% { transform: rotate(0deg) } diff --git a/moz/options.html b/moz/options.html index 9975de1..695ece5 100644 --- a/moz/options.html +++ b/moz/options.html @@ -37,11 +37,11 @@
- Login + Login

Login Settings

- Use your Plex token + Use your Plex token
How to find your Plex token. @@ -109,7 +109,11 @@

Plex Server Options

- Ombi (Movies/TV Shows) + + Ombi (Movies/TV Shows) + + +

Connection Settings

@@ -150,14 +154,18 @@

Login (saved)



- try out ombi +

- Watcher (Movies) + + Watcher (Movies) + + +

Connection Settings

@@ -212,12 +220,16 @@

Login (saved)



- try out watcher +
- Radarr (Movies) + + Radarr (Movies) + + +

Connection Settings

@@ -274,12 +286,16 @@

Login (saved)



- try out radarr +
- CouchPotato (Movies) + + CouchPotato (Movies) + + +

Connection Settings

@@ -332,14 +348,18 @@

Login (saved)



- try out couchpotato +

- Medusa (TV Shows) + + Medusa (TV Shows) + + +

Connection Settings

@@ -401,12 +421,16 @@

Login (saved)



- try out medusa +
- Sonarr (TV Shows) + + Sonarr (TV Shows) + + +

Connection Settings

@@ -463,12 +487,16 @@

Login (saved)



- try out sonarr +
- Sick Beard (TV Shows) + + Sick Beard (TV Shows) + + +

Connection Settings

@@ -534,7 +562,7 @@

Login (saved)



- try out Sick Beard +
@@ -557,7 +585,7 @@

The Button

- Where should the button be (○ only)? + Where should the button be ( only)?
@@ -576,24 +604,28 @@

The Button

- Site Settings + Site Settings + ... +

Experimental Sites

- +

Default Sites

- +
- Connection Settings + Connection Settings + +

Proxy Settings

@@ -611,7 +643,7 @@

Proxy URL & Syntax

- +
Please provide the URL of your proxy.
@@ -627,7 +659,7 @@

Proxy URL & Syntax

Proxy Headers

- +
If your proxy requires special headers, enter that information in here.
@@ -769,7 +801,9 @@

- Advance Settings + Advance Settings + BETA +

API Keys

@@ -802,7 +836,7 @@

Data Compression


Configuration Data (Copy/Paste)

- +
Use this for testing purposes only, as it may contain saved usernames and/or passwords.
@@ -910,9 +944,9 @@

External Links

- +
+ +
@@ -938,12 +972,13 @@

External Links

-
+ ... + diff --git a/moz/options.js b/moz/options.js index 6dd9852..727a5f6 100644 --- a/moz/options.js +++ b/moz/options.js @@ -519,11 +519,12 @@ function performPlexLogin({ event }) { function performPlexTest({ ServerID, event }) { let plexToken = $('#plex_token').value, teststatus = $('#plex_test_status'), - inusestatus = [...$('[in-use="plex_token"]', true)]; + inusestatus = [...$('[using="plex"]', true)]; __save__.disabled = true; __servers__.innerHTML = ''; teststatus.textContent = '?'; + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); getServers(plexToken).then((servers = []) => { @@ -734,10 +735,12 @@ function performOmbiTest({ refreshing = false, event }) { path = $('[data-option="ombiURLRoot"]'), url, headers = { headers: { apikey: options.ombiToken, accept: 'text/html' } }, - enabled = refreshing? $('#using-ombi'): $$('#using-ombi'); + enabled = refreshing? $('#using-ombi'): $$('#using-ombi'), + inusestatus = [...$('[using="ombi"]', true)]; teststatus.textContent = '?'; options.ombiURLRoot = url = path.value = options.ombiURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -770,10 +773,12 @@ function performOmbiTest({ refreshing = false, event }) { teststatus.textContent = '!'; enabled.checked = teststatus.classList = true; enabled.parentElement.removeAttribute('disabled'); + inusestatus.map(e => e.setAttribute('in-use', true)); } else { teststatus.textContent = '!'; enabled.checked = teststatus.classList = false; enabled.parentElement.setAttribute('disabled'); + inusestatus.map(e => e.setAttribute('in-use', false)); throw new Error(`Ombi error [${ status }]`); } @@ -824,12 +829,14 @@ function performWatcherTest({ QualityProfileID = 'Default', refreshing = false, storagepath = __watcher_storagePath__, quality = __watcher_qualityProfile__, url, - enabled = refreshing? $('#using-watcher'): $$('#using-watcher'); + enabled = refreshing? $('#using-watcher'): $$('#using-watcher'), + inusestatus = [...$('[using="watcher"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.value = '[Empty]'; options.watcherURLRoot = url = path.value = options.watcherURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -860,6 +867,7 @@ function performWatcherTest({ QualityProfileID = 'Default', refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Watcher'; @@ -931,12 +939,14 @@ function performRadarrTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __radarr_storagePath__, quality = __radarr_qualityProfile__, url, - enabled = refreshing? $('#using-radarr'): $$('#using-radarr'); + enabled = refreshing? $('#using-radarr'): $$('#using-radarr'), + inusestatus = [...$('[using="radarr"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.radarrURLRoot = url = path.value = options.radarrURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -954,10 +964,10 @@ function performRadarrTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Radarr'; - console.log('Enabling...', enabled, enabled.parentElement); enabled.parentElement.removeAttribute('disabled'); let qualities = []; @@ -1040,12 +1050,14 @@ function performSonarrTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __sonarr_storagePath__, quality = __sonarr_qualityProfile__, url, - enabled = refreshing? $('#using-sonarr'): $$('#using-sonarr'); + enabled = refreshing? $('#using-sonarr'): $$('#using-sonarr'), + inusestatus = [...$('[using="sonarr"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.sonarrURLRoot = url = path.value = options.sonarrURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1062,6 +1074,7 @@ function performSonarrTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Sonarr'; @@ -1147,12 +1160,14 @@ function performMedusaTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __medusa_storagePath__, quality = __medusa_qualityProfile__, url, - enabled = refreshing? $('#using-medusa'): $$('#using-medusa'); + enabled = refreshing? $('#using-medusa'): $$('#using-medusa'), + inusestatus = [...$('[using="medusa"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.medusaURLRoot = url = path.value = options.medusaURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1176,6 +1191,7 @@ function performMedusaTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Medusa'; @@ -1263,12 +1279,14 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals storagepath = __sickBeard_storagePath__, quality = __sickBeard_qualityProfile__, url, - enabled = refreshing? $('#using-sickBeard'): $$('#using-sickBeard'); + enabled = refreshing? $('#using-sickBeard'): $$('#using-sickBeard'), + inusestatus = [...$('[using="sickbeard"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.sickBeardURLRoot = url = path.value = options.sickBeardURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1298,6 +1316,7 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Sick Beard'; @@ -1361,6 +1380,9 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals } function enableCouchPotato() { + let inusestatus = [...$('[using="couchpotato"]', true)]; + + inusestatus.map(e => e.setAttribute('in-use', true)); $('#use-couchpotato').parentElement.removeAttribute('disabled'); } @@ -1975,6 +1997,8 @@ $('[id^="builtin_"]', true) save(`script:${ bid }`, null); } + Recall.CountEnabledSites(); + save(`builtin:${ bid }`, true); }) ); @@ -2074,6 +2098,8 @@ $('[id^="plugin_"]', true) save(`script:${ pid }`, null); } + Recall.CountEnabledSites(); + save(`builtin:${ pid }`, false); }) ); @@ -2146,7 +2172,7 @@ addListener($('#erase_cache'), 'mouseup', event => { }); $('#version') - .innerHTML = `Version ${ manifest.version }`; + .innerHTML = `v${ manifest.version }`; $('[type="range"]', true) .forEach((element, index, array) => { @@ -2161,7 +2187,8 @@ $('[type="range"]', true) $('.checkbox', true) .forEach((element, index, array) => { addListener(element, 'mouseup', event => { - let self = traverse(path(event), element => (element && element.type == 'checkbox'), true); + let self = traverse(path(event), element => (element && element.type == 'checkbox'), true), + isChecked = e => e.setAttribute('in-use', self.checked); if(!self) return; @@ -2190,7 +2217,18 @@ $('.checkbox', true) } break; + case 'extension-branch-type': + [...$('[counter-for="devmode"]', true)].map(isChecked); + Recall.ToggleDeveloprBadge(!self.checked); + break; + default: + let R = RegExp; + + if(/^using-([\w\-]+)/.test(self.id)) + $(`[using="${ R.$1 }"i]`, true).map(isChecked); + else if(/^use/i.test(self.dataset.option)) + $(`[using="${ self.id }"i]`, true).map(isChecked); break; } @@ -2202,13 +2240,11 @@ $('.checkbox', true) $('.test', true) .forEach((element, index, array) => { addListener(element, 'mouseup', async event => { - event.preventDefault(true); + let self = traverse(event.target, element => !!~[...element.classList].indexOf('test')); - let self = traverse(event.target, element => !!~[...element.classList].indexOf('text')); + // await saveOptions(); - await saveOptions(); - - open(self.href, self.target); + open(self.getAttribute('href'), self.getAttribute('target')); }); }); @@ -2273,7 +2309,7 @@ let hold = document.createElement('summary'), $('.bar > article > details', true) .forEach((element, index, array) => { - element.addEventListener('mouseup', event => { + addListener(element, 'mouseup', event => { let self = path(event).filter(e => /^details$/i.test(e.tagName))[0], head = path(event).filter(e => /\bbar\b/i.test(e.classList))[0].querySelector('header'), open = e => {try {e.setAttribute('open', true);} catch(r) {/* not actually an error */}}, @@ -2292,9 +2328,29 @@ $('.bar > article > details', true) disp.setAttribute('_sub-title_', hold.innerText); disp.value = uuid(self); + let checked = {}; + + [...self.children].forEach(child => { + let input = child.querySelector('.checkbox input'); + + if(!input) + return; + + checked[uuid(child)] = input.checked; + }); + swap(self, disp, hold); - $('.bar > article > details[open]', true).forEach(e => e.removeAttribute('open')); + [...self.children].forEach(child => { + let input = child.querySelector('.checkbox input'); + + if(!input) + return; + + input.checked = checked[uuid(child)]; + }); + + [...$('.bar > article > details[open]', true)].forEach(e => e.removeAttribute('open')); open(self); } }) @@ -2361,8 +2417,12 @@ $('[href^="#!/"]', true) let { hash } = window.location; if(hash.length > 1) - switch(hash = hash.slice(1, hash.length).toLowerCase()) { - case 'save': + switch(hash = hash.replace(/^#!\//, '').toLowerCase()) { + /* #!/~COMMAND[:PARAMETER|PARAMETER...] + * #!/~save + * #!/~clear:all + */ + case '~save': setTimeout(async() => { await saveOptions(); @@ -2370,11 +2430,129 @@ if(hash.length > 1) }, 1000); break; + /* #!/SETTING[/SUB-SETTING] + * #!/radarr + * #!/advance-settings/api-keys + */ + case '': + break; + default: terminal.log(`Unknown event "${ hash }"`); break; }; +/* Functions that require some time */ +let Recall = { + '@auto': {}, // run at 100ms, and be recallable + '@0sec': {}, // run at 1ms + '@1sec': {}, // run at 1000ms +}; + +/* Counting sites that are in use */ +Recall['@auto'].CountEnabledSites = () => + [...$('[counter-for="sites"i]', true)].map(e => { + let b = $('[id^="builtin_"]', true), + p = $('[id^="plugin_"]', true), + b_all = b.length, + p_all = p.length, + o = Object.filter(getOptionValues(), k => /^(built|plug)in_/i.test(k)), + bo = Object.filter(o, k => /^built/i.test(k)), + b_on = (Object.values(bo).filter(v => v === true)).length, + po = Object.filter(o, k => /^plug/i.test(k)), + p_on = (Object.values(po).filter(v => v === true)).length; + + e.innerHTML = `${ (b_on + p_on) }/${ (b_all + p_all) }` + }); + +/* Setting the DEV badge */ +Recall['@auto'].ToggleDeveloprBadge = (state = null) => + [...$('[counter-for="devmode"i]', true)].map(e => { + if(state === null) + state = getOptionValues().DeveloperMode; + + if(state) + return e.style.display = 'inline-block'; + e.style.display = 'none'; + }); + +/* Set the version and color */ +Recall['@0sec'].SetVersionInfo = async() => { + let DM = getOptionValues().DeveloperMode; + + function useVer(version) { + let remote = version.tag_name.slice(1, version.tag_name.length), + local = manifest.version, + verEl = $('#version'), + status; + + switch(compareVer(remote, local)) { + case 0: + status = 'same'; + verEl.setAttribute('title', `The installed version is the most recent. No update required`); + break; + + case -1: + status = 'high'; + verEl.setAttribute('title', `The installed version is ahead of GitHub. No update required`); + break; + + case 1: + status = 'low'; + verEl.href += (DM? '': '/latest'); + verEl.setAttribute('title', `The installed version is behind GitHub. Update available`); + break; + } + + verEl.innerHTML = `v${ manifest.version }`; + verEl.setAttribute('status', status); + } + + if(DM) + await fetch('https://api.github.com/repos/SpaceK33z/web-to-plex/releases') + .then(response => response.json()) + .then(versions => useVer(versions[0])); + else + await fetch('https://api.github.com/repos/SpaceK33z/web-to-plex/releases/latest') + .then(response => response.json()) + .then(version => useVer(version)); +}; + +for(let func in Recall) { + if(/^@/.test(func)) { + let f; + + switch(func) { + case '@auto': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + Recall[fn] = f; + setTimeout(f, 100); + } + break; + + case '@0sec': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + setTimeout(f, 1); + } + break; + + case '@1sec': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + setTimeout(f, 1000); + } + break; + } + } else { + /* Do nothing... */ + } +} + /* LZW Compression Algorithm */ function compress(string = '') { let dictionary = {}, @@ -2477,6 +2655,19 @@ String.prototype.toCaps = String.prototype.toCaps || function toCaps(all) { return string; }; +Object.filter = Object.filter || function filter(object, prejudice) { + if(!prejudice) + return object; + + let results = {}; + + for(let key in object) + if(prejudice(key, object[key])) + results[key] = object[key]; + + return results; +}; + function path(element) { if(element.path) return element.path; diff --git a/moz/tv-show.poster.jpg b/moz/tv-show.poster.jpg deleted file mode 100644 index cc96009..0000000 Binary files a/moz/tv-show.poster.jpg and /dev/null differ diff --git a/moz/utils.js b/moz/utils.js index f060631..09104cb 100644 --- a/moz/utils.js +++ b/moz/utils.js @@ -2922,6 +2922,19 @@ String.prototype.toCaps = String.prototype.toCaps || function toCaps(all) { return string; }; +Object.filter = Object.filter || function filter(object, prejudice) { + if(!prejudice) + return object; + + let results = {}; + + for(let key in object) + if(prejudice(key, object[key])) + results[key] = object[key]; + + return results; +}; + (function(parent) { /* SortBy.js */ /** Usage + Example diff --git a/src.crx b/src.crx index d82f450..632fc7a 100644 Binary files a/src.crx and b/src.crx differ diff --git a/src.zip b/src.zip index ba53eb3..3a858d9 100644 Binary files a/src.zip and b/src.zip differ diff --git a/src/manifest.json b/src/manifest.json index 4962f7f..0bfa0e4 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -6,7 +6,7 @@ "homepage_url": "https://github.com/SpaceK33z/web-to-plex/", "manifest_version": 2, - "version": "4.1.1.6", + "version": "4.1.1.7", "icons": { "16": "img/16.png", @@ -66,13 +66,6 @@ "all_frames": true }, - // Testing purposes only - { - "matches": ["*://ephellon.github.io/web.to.plex/test/*"], - "js": ["utils.js", "sites/__test__.js"], - "css": ["sites/common.css", "sites/theme.css"] - }, - // The sites { "matches": ["*://*.movieo.me/*"], diff --git a/src/options/compare.js b/src/options/compare.js new file mode 100644 index 0000000..9cb6275 --- /dev/null +++ b/src/options/compare.js @@ -0,0 +1,38 @@ +/** GitHub@alexey-bass + * Simply compares two string version values. + * + * Example: + * compareVer('1.1', '1.2') => -1 + * compareVer('1.1', '1.1') => 0 + * compareVer('1.2', '1.1') => 1 + * compareVer('2.23.3', '2.22.3') => 1 + * + * Returns: + * -1 = left is LOWER = right is GREATER + * 0 = they are equal + * 1 = left is GREATER = right is LOWER + * And FALSE if one of input versions are not valid + * + * @function + * @param {String} left Version #1 + * @param {String} right Version #2 + * @return {Integer|Boolean} + * @author Alexey Bass (albass) + * @since 2011-07-14 + */ +function compareVer(left, right) { + if(typeof left + typeof right != 'stringstring') + return false; + + for(let a = left.split('.'), b = right.split('.'), i = 0, l = Math.max(a.length, b.length); i < l; i++) { + if((a[i] && !b[i] && parseInt(a[i]) > 0) || (parseInt(a[i]) > parseInt(b[i]))) + return +1 + /* left is higher */; + else if((b[i] && !a[i] && parseInt(b[i]) > 0) || (parseInt(a[i]) < parseInt(b[i]))) + return -1 + /* right is higher */; + } + + return 0 + /* equal */; +} diff --git a/src/options/index.css b/src/options/index.css index d6e1901..270267c 100644 --- a/src/options/index.css +++ b/src/options/index.css @@ -81,7 +81,7 @@ a { text-decoration: none !important; } -a[target="_blank"]::after { +[target="_blank"]:not(#version)::after { content: " [\2197]"; font-size: 70%; @@ -281,6 +281,8 @@ summary, option { } #sidebar summary { + font-size: 12px; + margin-left: -50px; padding-left: 50px; } @@ -297,7 +299,8 @@ summary, option { } #sidebar .checkbox { - display: none; + display: block; + transform: scale(0.75); } display > summary:first-child { @@ -316,12 +319,9 @@ details:last-child > summary { margin-bottom: 0 !important; } -.bar > article > details:not([open]) > summary { - list-style: none; -} - -.bar > article > details[open] > summary { - list-style: disc; +.bar > article > details > summary { + display: list-item; + list-style-type: none; } .bar > article > details[open] > *:not(summary) { @@ -329,39 +329,35 @@ details:last-child > summary { } .bar > article > details > summary::-webkit-details-marker { - display: none; -} - -.bar > article > details > summary::before { - content: '\00b7'; color: #0000; - font-size: 40px; - - position: fixed; - margin-left: -12px; - margin-top: -20px; } .bar > article > details[open] > summary::before { - color: inherit; + content: '\2022'; + color: inherit !important; + font-size: 16px; + + margin-left: 2px; + margin-top: -2px; + position: absolute; } #save { margin: 6px 12px; } -#footer { +footer { bottom: 0; position: fixed; width: 100%; } -[in-use] { +[using], [counter-for] { color: #197bcc; } -[in-use]::after { +[using]::after { content: '\2610'; } @@ -369,6 +365,33 @@ details:last-child > summary { content: '\2611'; } +[special][using]:not([in-use="true"i]) { + color: #666; +} + +[special][in-use="true"i], [special][counter-for] { + color: #cc7b19; +} + +[counter-for] { + border: 1px solid #197bcc; + + margin: 0; + padding: 0 3px; +} + +[counter-for][in-use]::after { + content: '' !important; +} + +[special][counter-for] { + border-color: #cc7b19; +} + +#sidebar [counter-for] { + font-size: 10px; +} + [top] { border-bottom-left-radius: 0 !important; border-bottom-right-radius: 0 !important; @@ -392,6 +415,14 @@ details:last-child > summary { background: #298bdc !important; } +#sidebar .checkbox:not([special]) { + display: none !important; +} + +display summary [using]:not([special]) { + display: none !important; +} + /* bbodine @CodePen - https://codepen.io/bbodine1/pen/novBm */ .checkbox { width: 80px; @@ -493,6 +524,11 @@ span.checkbox { opacity: 0.25 !important; } +.checkbox[disabled] + [using] { + color: #666; + opacity: 0.25; +} + [white] { color: #fff !important; } @@ -551,34 +587,52 @@ input[type="range"]::-webkit-slider-thumb { width: 32px; } -input[type="range"]::-moz-range-thumb { - background: #cc7b19; - border: 1px solid #cc7b19; - border-radius: 100%; - cursor: pointer; +[disabled], [disabled] * { + cursor: not-allowed !important; + color: #909090EE !important; +} - height: 32px; - width: 32px; +[code], code { + background: #222 !important; + border-radius: 3px !important; + box-shadow: none !important; + box-sizing: border-box !important; + font-family: "System, Monospace, Menlo, Arial", Consolas, "Liberation Mono", Menlo, Courier, monospace !important; + font-size: 12px !important; + line-height: 18px !important; + + margin: 0 !important; + padding: 0.2em 0.4em !important; } #version { - color: #fff; + background: #0000 !important; + border: 1px solid #666 !important; + color: #666 !important; - position: fixed; - right: 4px; - top: calc(100vh - 24px); + position: fixed !important; + right: 12px !important; + top: calc(100vh - 30px) !important; + + transition: border 0.15s, color 0.15s; } -[disabled], [disabled] * { - cursor: not-allowed !important; - color: #909090EE !important; +/* Release is higher than GitHub */ +#version[status="high"] { + border-color: #6cc644 !important; + color: #6cc644 !important; } -[code], code { - border: 1px solid #FFF3; - font-family: monospace, console, consolas, system, arial !important; +/* Release is same as GitHub */ +#version[status="same"] { + border-color: #197bcc !important; + color: #197bcc !important; +} - padding: 0 3px; +/* Release is lower than GitHub */ +#version[status="low"] { + border-color: #f66a0a !important; + color: #f3582c !important; } /* notifications */ @@ -792,10 +846,6 @@ input[type="range"]::-moz-range-thumb { color: #999 !important; } -*::-moz-placeholder, *:-moz-placeholder { - color: #999; -} - *::-webkit-input-placeholder { color: #999; } diff --git a/src/options/index.html b/src/options/index.html index c86d627..d2a9f6a 100644 --- a/src/options/index.html +++ b/src/options/index.html @@ -37,11 +37,11 @@
- Login + Login

Login Settings

- Use your Plex token + Use your Plex token
How to find your Plex token. @@ -109,7 +109,11 @@

Plex Server Options

- Ombi (Movies/TV Shows) + + Ombi (Movies/TV Shows) + + +

Connection Settings

@@ -150,14 +154,18 @@

Login (saved)



- try out ombi +

- Watcher (Movies) + + Watcher (Movies) + + +

Connection Settings

@@ -212,12 +220,16 @@

Login (saved)



- try out watcher +
- Radarr (Movies) + + Radarr (Movies) + + +

Connection Settings

@@ -274,12 +286,16 @@

Login (saved)



- try out radarr +
- CouchPotato (Movies) + + CouchPotato (Movies) + + +

Connection Settings

@@ -332,14 +348,18 @@

Login (saved)



- try out couchpotato +

- Medusa (TV Shows) + + Medusa (TV Shows) + + +

Connection Settings

@@ -401,12 +421,16 @@

Login (saved)



- try out medusa +
- Sonarr (TV Shows) + + Sonarr (TV Shows) + + +

Connection Settings

@@ -463,12 +487,16 @@

Login (saved)



- try out sonarr +
- Sick Beard (TV Shows) + + Sick Beard (TV Shows) + + +

Connection Settings

@@ -534,7 +562,7 @@

Login (saved)



- try out Sick Beard +
@@ -576,7 +604,9 @@

The Button

- Site Settings + Site Settings + ... +

Experimental Sites

@@ -593,7 +623,9 @@

Default Sites

- Connection Settings + Connection Settings + +

Proxy Settings

@@ -611,7 +643,7 @@

Proxy URL & Syntax

- +
Please provide the URL of your proxy.
@@ -627,7 +659,7 @@

Proxy URL & Syntax

Proxy Headers

- +
If your proxy requires special headers, enter that information in here.
@@ -769,7 +801,9 @@

- Advance Settings + Advance Settings + BETA +

API Keys

@@ -802,7 +836,7 @@

Data Compression


Configuration Data (Copy/Paste)

- +
Use this for testing purposes only, as it may contain saved usernames and/or passwords.
@@ -910,9 +944,9 @@

External Links

- +
+ +
@@ -938,12 +972,13 @@

External Links

-
+ ... + diff --git a/src/options/index.js b/src/options/index.js index 518275b..9e1f8a2 100644 --- a/src/options/index.js +++ b/src/options/index.js @@ -542,11 +542,12 @@ function performPlexLogin({ event }) { function performPlexTest({ ServerID, event }) { let plexToken = $('#plex_token').value, teststatus = $('#plex_test_status'), - inusestatus = [...$('[in-use="plex_token"]', true)]; + inusestatus = [...$('[using="plex"]', true)]; __save__.disabled = true; __servers__.innerHTML = ''; teststatus.textContent = '?'; + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); getServers(plexToken).then((servers = []) => { @@ -757,10 +758,12 @@ function performOmbiTest({ refreshing = false, event }) { path = $('[data-option="ombiURLRoot"]'), url, headers = { headers: { apikey: options.ombiToken, accept: 'text/html' } }, - enabled = refreshing? $('#using-ombi'): $$('#using-ombi'); + enabled = refreshing? $('#using-ombi'): $$('#using-ombi'), + inusestatus = [...$('[using="ombi"]', true)]; teststatus.textContent = '?'; options.ombiURLRoot = url = path.value = options.ombiURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -793,10 +796,12 @@ function performOmbiTest({ refreshing = false, event }) { teststatus.textContent = '!'; enabled.checked = teststatus.classList = true; enabled.parentElement.removeAttribute('disabled'); + inusestatus.map(e => e.setAttribute('in-use', true)); } else { teststatus.textContent = '!'; enabled.checked = teststatus.classList = false; enabled.parentElement.setAttribute('disabled'); + inusestatus.map(e => e.setAttribute('in-use', false)); throw new Error(`Ombi error [${ status }]`); } @@ -847,12 +852,14 @@ function performWatcherTest({ QualityProfileID = 'Default', refreshing = false, storagepath = __watcher_storagePath__, quality = __watcher_qualityProfile__, url, - enabled = refreshing? $('#using-watcher'): $$('#using-watcher'); + enabled = refreshing? $('#using-watcher'): $$('#using-watcher'), + inusestatus = [...$('[using="watcher"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.value = '[Empty]'; options.watcherURLRoot = url = path.value = options.watcherURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -883,6 +890,7 @@ function performWatcherTest({ QualityProfileID = 'Default', refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Watcher'; @@ -954,12 +962,14 @@ function performRadarrTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __radarr_storagePath__, quality = __radarr_qualityProfile__, url, - enabled = refreshing? $('#using-radarr'): $$('#using-radarr'); + enabled = refreshing? $('#using-radarr'): $$('#using-radarr'), + inusestatus = [...$('[using="radarr"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.radarrURLRoot = url = path.value = options.radarrURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -977,6 +987,7 @@ function performRadarrTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Radarr'; @@ -1062,12 +1073,14 @@ function performSonarrTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __sonarr_storagePath__, quality = __sonarr_qualityProfile__, url, - enabled = refreshing? $('#using-sonarr'): $$('#using-sonarr'); + enabled = refreshing? $('#using-sonarr'): $$('#using-sonarr'), + inusestatus = [...$('[using="sonarr"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.sonarrURLRoot = url = path.value = options.sonarrURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1084,6 +1097,7 @@ function performSonarrTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Sonarr'; @@ -1169,12 +1183,14 @@ function performMedusaTest({ QualityProfileID, StoragePath, refreshing = false, storagepath = __medusa_storagePath__, quality = __medusa_qualityProfile__, url, - enabled = refreshing? $('#using-medusa'): $$('#using-medusa'); + enabled = refreshing? $('#using-medusa'): $$('#using-medusa'), + inusestatus = [...$('[using="medusa"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.medusaURLRoot = url = path.value = options.medusaURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1198,6 +1214,7 @@ function performMedusaTest({ QualityProfileID, StoragePath, refreshing = false, teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus.map(e => e.setAttribute('in-use', enabled.checked)); if(!profiles.length) return teststatus.title = 'Failed to communicate with Medusa'; @@ -1285,12 +1302,14 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals storagepath = __sickBeard_storagePath__, quality = __sickBeard_qualityProfile__, url, - enabled = refreshing? $('#using-sickBeard'): $$('#using-sickBeard'); + enabled = refreshing? $('#using-sickBeard'): $$('#using-sickBeard'), + inusestatus = [...$('[using="sickbeard"]', true)]; quality.innerHTML = ''; teststatus.textContent = '?'; storagepath.textContent = ''; options.sickBeardURLRoot = url = path.value = options.sickBeardURLRoot.replace(/^(\:\d+)/, 'localhost$1').replace(/^(?!^http(s)?:)/, 'http$1://').replace(/\/+$/, ''); + inusestatus.map(e => e.setAttribute('in-use', false)); LoadingAnimation(true); let Get = () => { @@ -1320,6 +1339,7 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals teststatus.textContent = '!'; teststatus.classList = enabled.checked = !!profiles.length; + inusestatus = [...$('[using="sickbeard"]', true)]; if(!profiles.length) return teststatus.title = 'Failed to communicate with Sick Beard'; @@ -1383,6 +1403,9 @@ function performSickBeardTest({ QualityProfileID, StoragePath, refreshing = fals } function enableCouchPotato() { + let inusestatus = [...$('[using="couchpotato"]', true)]; + + inusestatus.map(e => e.setAttribute('in-use', true)); $('#use-couchpotato').parentElement.removeAttribute('disabled'); } @@ -1997,6 +2020,8 @@ $('[id^="builtin_"]', true) save(`script:${ bid }`, null); } + Recall.CountEnabledSites(); + save(`builtin:${ bid }`, true); }) ); @@ -2096,6 +2121,8 @@ $('[id^="plugin_"]', true) save(`script:${ pid }`, null); } + Recall.CountEnabledSites(); + save(`builtin:${ pid }`, false); }) ); @@ -2167,9 +2194,6 @@ addListener($('#erase_cache'), 'mouseup', event => { saveOptions(); }); -$('#version') - .innerHTML = `Version ${ manifest.version }`; - $('[type="range"]', true) .forEach((element, index, array) => { let sibling = element.nextElementSibling, @@ -2183,10 +2207,8 @@ $('[type="range"]', true) $('.checkbox', true) .forEach((element, index, array) => { addListener(element, 'mouseup', event => { - let self = traverse(path(event), element => (element && element.type == 'checkbox'), true); - - if(!self) - return; + let self = traverse(path(event), element => (element && element.type == 'checkbox'), true), + isChecked = e => e.setAttribute('in-use', !self.checked); if('disabled' in self.attributes || traverse(self, element => (element && 'disabled' in element.attributes), true)) return event.preventDefault(true); @@ -2212,7 +2234,18 @@ $('.checkbox', true) } break; + case 'extension-branch-type': + [...$('[counter-for="devmode"]', true)].map(isChecked); + Recall.ToggleDeveloprBadge(!self.checked); + break; + default: + let R = RegExp; + + if(/^using-([\w\-]+)/.test(self.id)) + $(`[using="${ R.$1 }"i]`, true).map(isChecked); + else if(/^use/i.test(self.dataset.option)) + $(`[using="${ self.id }"i]`, true).map(isChecked); break; } @@ -2224,13 +2257,11 @@ $('.checkbox', true) $('.test', true) .forEach((element, index, array) => { addListener(element, 'mouseup', async event => { - event.preventDefault(true); - let self = traverse(event.target, element => !!~[...element.classList].indexOf('test')); - await saveOptions(); + // await saveOptions(); - open(self.href, self.target); + open(self.getAttribute('href'), self.getAttribute('target')); }); }); @@ -2295,7 +2326,7 @@ let hold = document.createElement('summary'), $('.bar > article > details', true) .forEach((element, index, array) => { - element.addEventListener('mouseup', event => { + addListener(element, 'mouseup', event => { let self = path(event).filter(e => /^details$/i.test(e.tagName))[0], head = path(event).filter(e => /\bbar\b/i.test(e.classList))[0].querySelector('header'), open = e => {try {e.setAttribute('open', true);} catch(r) {/* not actually an error */}}, @@ -2314,9 +2345,29 @@ $('.bar > article > details', true) disp.setAttribute('_sub-title_', hold.innerText); disp.value = uuid(self); + let checked = {}; + + [...self.children].forEach(child => { + let input = child.querySelector('.checkbox input'); + + if(!input) + return; + + checked[uuid(child)] = input.checked; + }); + swap(self, disp, hold); - $('.bar > article > details[open]', true).forEach(e => e.removeAttribute('open')); + [...self.children].forEach(child => { + let input = child.querySelector('.checkbox input'); + + if(!input) + return; + + input.checked = checked[uuid(child)]; + }); + + [...$('.bar > article > details[open]', true)].forEach(e => e.removeAttribute('open')); open(self); } }) @@ -2383,8 +2434,12 @@ $('[href^="#!/"]', true) let { hash } = window.location; if(hash.length > 1) - switch(hash = hash.slice(1, hash.length).toLowerCase()) { - case 'save': + switch(hash = hash.replace(/^#!\//, '').toLowerCase()) { + /* #!/~COMMAND[:PARAMETER|PARAMETER...] + * #!/~save + * #!/~clear:all + */ + case '~save': setTimeout(async() => { await saveOptions(); @@ -2392,11 +2447,131 @@ if(hash.length > 1) }, 1000); break; + /* #!/SETTING[/SUB-SETTING] + * #!/radarr + * #!/advance-settings/api-keys + */ + case '': + break; + default: terminal.log(`Unknown event "${ hash }"`); break; }; +/* Functions that require some time */ +let Recall = { + '@auto': {}, // run at 100ms, and be recallable + '@0sec': {}, // run at 1ms + '@1sec': {}, // run at 1000ms +}; + +/* Counting sites that are in use */ +Recall['@auto'].CountEnabledSites = () => + [...$('[counter-for="sites"i]', true)].map(e => { + let b = $('[id^="builtin_"]', true), + p = $('[id^="plugin_"]', true), + b_all = b.length, + p_all = p.length, + o = Object.filter(getOptionValues(), k => /^(built|plug)in_/i.test(k)), + bo = Object.filter(o, k => /^built/i.test(k)), + b_on = (Object.values(bo).filter(v => v === true)).length, + po = Object.filter(o, k => /^plug/i.test(k)), + p_on = (Object.values(po).filter(v => v === true)).length; + + e.innerHTML = `${ (b_on + p_on) }/${ (b_all + p_all) }` + }); + +/* Setting the DEV badge */ +Recall['@auto'].ToggleDeveloprBadge = (state = null) => + [...$('[counter-for="devmode"i]', true)].map(e => { + if(state === null) + state = getOptionValues().DeveloperMode; + + console.log(state); + + if(state) + return e.style.display = 'inline-block'; + e.style.display = 'none'; + }); + +/* Set the version and color */ +Recall['@0sec'].SetVersionInfo = async() => { + let DM = getOptionValues().DeveloperMode; + + function useVer(version) { + let remote = version.tag_name.slice(1, version.tag_name.length), + local = manifest.version, + verEl = $('#version'), + status; + + switch(compareVer(remote, local)) { + case 0: + status = 'same'; + verEl.setAttribute('title', `The installed version is the most recent. No update required`); + break; + + case -1: + status = 'high'; + verEl.setAttribute('title', `The installed version is ahead of GitHub. No update required`); + break; + + case 1: + status = 'low'; + verEl.href += (DM? '': '/latest'); + verEl.setAttribute('title', `The installed version is behind GitHub. Update available`); + break; + } + + verEl.innerHTML = `v${ manifest.version }`; + verEl.setAttribute('status', status); + } + + if(DM) + await fetch('https://api.github.com/repos/SpaceK33z/web-to-plex/releases') + .then(response => response.json()) + .then(versions => useVer(versions[0])); + else + await fetch('https://api.github.com/repos/SpaceK33z/web-to-plex/releases/latest') + .then(response => response.json()) + .then(version => useVer(version)); +}; + +for(let func in Recall) { + if(/^@/.test(func)) { + let f; + + switch(func) { + case '@auto': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + Recall[fn] = f; + setTimeout(f, 100); + } + break; + + case '@0sec': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + setTimeout(f, 1); + } + break; + + case '@1sec': + for(let fn in Recall[func]) { + f = Recall[func][fn]; + + setTimeout(f, 1000); + } + break; + } + } else { + /* Do nothing... */ + } +} + /* LZW Compression Algorithm */ function compress(string = '') { let dictionary = {}, @@ -2499,6 +2674,19 @@ String.prototype.toCaps = String.prototype.toCaps || function toCaps(all) { return string; }; +Object.filter = Object.filter || function filter(object, prejudice) { + if(!prejudice) + return object; + + let results = {}; + + for(let key in object) + if(prejudice(key, object[key])) + results[key] = object[key]; + + return results; +}; + function path(element) { if(element.path) return element.path; diff --git a/src/options/test/blank.html b/src/options/test/blank.html deleted file mode 100644 index 4d9c7fd..0000000 --- a/src/options/test/blank.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/options/test/index.html b/src/options/test/index.html deleted file mode 100644 index 85f58bc..0000000 --- a/src/options/test/index.html +++ /dev/null @@ -1,225 +0,0 @@ - - - - Web to Plex | Testing - - - - - - - - -
-
- - - -
- - -
- - - - - - - - - - - - diff --git a/src/options/test/index.js b/src/options/test/index.js deleted file mode 100644 index 13f13f2..0000000 --- a/src/options/test/index.js +++ /dev/null @@ -1,102 +0,0 @@ -let $ = selector => document.querySelector(selector); - -function modify({ type, title, year, info }) { - let object = { title, year, ...info }; - - $('#example').setAttribute('type', type); - - $('#movie').removeAttribute('active'); - $('#tv-show').removeAttribute('active'); - - $(`#${ type }`).setAttribute('active', true); - - let element; - for(let key in object) - if(element = $(`#${ key }`)) - element.innerHTML = object[key] || ""; - - $('#body').setAttribute('style', `background-image: url("${ type }.poster.jpg")`); - $('#poster').setAttribute('src', `${ type }.poster.jpg`); - - let { imdb, tmdb, tvdb } = object, - ids = { imdb, tmdb, tvdb }; - - for(let id in ids) - $(`#${ id }`).setAttribute('href', ( - ids[id]? - id == 'imdb'? - `https://www.imdb.com/videoembed/${ object[id.toUpperCase()] }/`: - `https://www.youtube.com/embed/${ object[id.toUpperCase()] }`: - 'blank.html' - )); -} - -function as(type) { - open('blank.html', 'frame'); - - return modify({ - "movie": { - 'type': "movie", - 'title': "Being John Malkovich", - 'year': 1999, - 'info': { - 'rating': "R", - 'runtime': "1:53", - 'genre': "Comedy, Drama, Fantasy", - 'release-date': "December 3, 1999 (USA)", - - 'imdb': "tt0120601", - 'IMDB': "vi3568894233", - 'tmdb': 492, - 'TMDB': "HdVvjvW_OEo", - 'tvdb': null, - 'TVDB': null, - }, - }, - - "tv-show": { - 'type': "tv-show", - 'title': "Love, Death & Robots", - 'year': 2019, - 'info': { - 'rating': "TV-MA", - 'runtime': "0:15", - 'genre': "Animation, Comedy, Fantasy, Horror, Science-Fiction", - 'release-date': "May 15, 2019 (USA)", - - 'imdb': "tt9561862", - 'IMDB': "vi1035648281", - 'tmdb': 86831, - 'TMDB': "wUFwunMKa4E", - 'tvdb': 357888, - 'TVDB': "wUFwunMKa4E", - }, - }, - }[type]); -} - -document.querySelectorAll('#movie, #tv-show').forEach(element => { - element.onmouseup = event => { - let self = event.target; - - as(self.id); - }; -}); - -document.querySelectorAll('[target="frame"]').forEach(element => { - let body = document.body, - frame = $('#frame'), - loading = $('#loading'); - - element.onmouseup = event => { - loading.setAttribute('loading', true); - loading.removeAttribute('style'); - } - - frame.onload = frame.onerror = event => { - loading.setAttribute('loading', false); - setTimeout(() => loading.setAttribute('style', 'display:none'), 500); - } -}); - -document.body.onload = event => /#(movie|tv-show)/i.test(location.hash)? as(`${ location.hash.replace('#', '') }`): as('movie'); diff --git a/src/options/test/loading.png b/src/options/test/loading.png deleted file mode 100644 index 749aa93..0000000 Binary files a/src/options/test/loading.png and /dev/null differ diff --git a/src/options/test/movie.poster.jpg b/src/options/test/movie.poster.jpg deleted file mode 100644 index efdc64f..0000000 Binary files a/src/options/test/movie.poster.jpg and /dev/null differ diff --git a/src/options/test/noise.png b/src/options/test/noise.png deleted file mode 100644 index 7eead13..0000000 Binary files a/src/options/test/noise.png and /dev/null differ diff --git a/src/options/test/tv-show.poster.jpg b/src/options/test/tv-show.poster.jpg deleted file mode 100644 index cc96009..0000000 Binary files a/src/options/test/tv-show.poster.jpg and /dev/null differ diff --git a/src/utils.js b/src/utils.js index ac9c885..2e38b2a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -669,7 +669,7 @@ let configuration, init, Update; } catch(error) { console.warn(`Update failed... "${ error }" Attempting to save configuration...`); - return sFrame(extURL(`options/index.html#save`), { + return sFrame(extURL(`options/index.html#!/~save`), { success: async event => { let self = event.target; @@ -2874,6 +2874,19 @@ String.prototype.toCaps = String.prototype.toCaps || function toCaps(all) { return string; }; +Object.filter = Object.filter || function filter(object, prejudice) { + if(!prejudice) + return object; + + let results = {}; + + for(let key in object) + if(prejudice(key, object[key])) + results[key] = object[key]; + + return results; +}; + (function(parent) { /* SortBy.js */ /** Usage + Example