From 29765230b1fa83bc06d44d0b3695ceff1d6519f6 Mon Sep 17 00:00:00 2001 From: Timeraa <29104008+Timeraa@users.noreply.github.com> Date: Thu, 1 Nov 2018 19:53:24 +0100 Subject: [PATCH] Basically everything for 1.2 :P --- .gitignore | 5 +- Extension/_locales/de/messages.json | 74 ------ Extension/_locales/en/messages.json | 68 +++-- Extension/_locales/he/messages.json | 74 ------ Extension/_locales/la/messages.json | 74 ------ Extension/_locales/sv/messages.json | 74 ------ Extension/background.js | 30 --- Extension/connect.css | 54 ---- Extension/css/inputs.css | 78 ++++++ Extension/css/options.css | 15 ++ Extension/{ => css}/popup.css | 30 ++- Extension/css/reset.css | 20 ++ Extension/html/popup/options.html | 137 ++++++++++ Extension/{ => html/popup}/popup.html | 18 +- Extension/{ => html/tabs}/installed.html | 10 +- Extension/{ => html/tabs}/updated.html | 10 +- Extension/js/background.js | 62 +++++ Extension/js/options.js | 140 ++++++++++ Extension/js/popup.js | 20 ++ Extension/{ => js}/presences/JKAnime.js | 0 Extension/{ => js}/presences/KissAnime.js | 0 Extension/{ => js}/presences/Netflix.js | 61 +++-- Extension/{ => js}/presences/SoundCloud.js | 0 Extension/{ => js}/presences/Twitch.js | 0 Extension/{ => js}/presences/YouTube.js | 0 Extension/{ => js}/presences/YouTubeMusic.js | 0 Extension/{ => js}/util/jquery-3.3.1.min.js | 0 .../{ => js}/util/socket.io-2.1.1.min.js | 0 Extension/{ => js}/util/socketConnector.js | 0 Extension/manifest.json | 28 +- README.md | 48 ++-- gitassets/UMU.png | Bin 0 -> 32839 bytes src/package-lock.json | 244 +++++++++--------- src/package.json | 2 +- src/util/shortcutHandler.js | 4 + 35 files changed, 778 insertions(+), 602 deletions(-) delete mode 100644 Extension/_locales/de/messages.json delete mode 100644 Extension/_locales/he/messages.json delete mode 100644 Extension/_locales/la/messages.json delete mode 100644 Extension/_locales/sv/messages.json delete mode 100644 Extension/background.js delete mode 100644 Extension/connect.css create mode 100644 Extension/css/inputs.css create mode 100644 Extension/css/options.css rename Extension/{ => css}/popup.css (72%) create mode 100644 Extension/css/reset.css create mode 100644 Extension/html/popup/options.html rename Extension/{ => html/popup}/popup.html (58%) rename Extension/{ => html/tabs}/installed.html (68%) rename Extension/{ => html/tabs}/updated.html (63%) create mode 100644 Extension/js/background.js create mode 100644 Extension/js/options.js create mode 100644 Extension/js/popup.js rename Extension/{ => js}/presences/JKAnime.js (100%) rename Extension/{ => js}/presences/KissAnime.js (100%) rename Extension/{ => js}/presences/Netflix.js (62%) rename Extension/{ => js}/presences/SoundCloud.js (100%) rename Extension/{ => js}/presences/Twitch.js (100%) rename Extension/{ => js}/presences/YouTube.js (100%) rename Extension/{ => js}/presences/YouTubeMusic.js (100%) rename Extension/{ => js}/util/jquery-3.3.1.min.js (100%) rename Extension/{ => js}/util/socket.io-2.1.1.min.js (100%) rename Extension/{ => js}/util/socketConnector.js (100%) create mode 100644 gitassets/UMU.png diff --git a/.gitignore b/.gitignore index b484b50..cb121e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules out -.vscode dist -server \ No newline at end of file +website +server +.vscode \ No newline at end of file diff --git a/Extension/_locales/de/messages.json b/Extension/_locales/de/messages.json deleted file mode 100644 index 9540497..0000000 --- a/Extension/_locales/de/messages.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "appDesc": { - "message": "PreMiD fügt eine Discord-Rich-Presence-Integration, Kontrolle über Multimediatasten und viele weitere Funktionen zu YouTube/YouTube Music, Twitch etc. hinzu." - }, - "connected": { - "message": "Verbunden" - }, - "disconnected": { - "message": "Getrennt" - }, - "installedThanks": { - "message": "Vielen Dank, für das Installieren von PreMiD" - }, - "installedApp": { - "message": "Hast du das Programm bereits installiert?" - }, - "installedNo": { - "message": "Nein? Folge dieser Anleitung:" - }, - "installedStepApp": { - "message": "Lade die neueste Version von $1 herunter" - }, - "installedStepAppMyRepository": { - "message": "meinem GitHub Repository" - }, - "installedWaitInstalled": { - "message": "Offne das Installationsprogramm und warte bis die Installation abgeschlossen ist" - }, - "installedMayWarning": { - "message": "Möglicherweise bekommst du eine Warnung von deiner FireWall und SmartScreen (Es ist kein Virus. Das verspreche ich dir!)" - }, - "installedAppAutostart": { - "message": "Das Programm sollte automatisch starten. Du kannst dies prüfen, indem du auf deine Taskbar (Windows) oder deine Menubar (MacOS) schaust" - }, - "installedYes": { - "message": "Ja? Jetzt bist du bereit!" - }, - "installedStart": { - "message": "Starte, indem du ein Video auf YouTube, deine Lieblingsstreamer auf Twitch oder vielleicht sogar Netflix schaust... Wer weiß? Oder du hörst dir deine Lieblingslieder auf SoundCloud und YouTube Music an." - }, - "installedSupportMe": { - "message": "Unterstütze mich!" - }, - "updatedYTPUpdated": { - "message": "PreMiD wurde aktualisiert!" - }, - "updatedWhatsNew": { - "message": "Was ist neu?" - }, - "updatedWhatChanged": { - "message": "Was hat sich geändert?" - }, - "updatedAdded0": { - "message": "Installieren Tab" - }, - "updatedAdded1": { - "message": "Update Tab" - }, - "updatedChanged0": { - "message": "Kleinere Bugfixes" - }, - "updatedChanged1": { - "message": "Erweiterungs Organisierung" - }, - "updatedAdded2": { - "message": "Sprachunterstützung" - }, - "updatedAdded3": { - "message": "Tab Priorität" - }, - "updatedChanged2": { - "message": "YouTube + YouTube Music neugeschrieben" - } -} \ No newline at end of file diff --git a/Extension/_locales/en/messages.json b/Extension/_locales/en/messages.json index ef16fe8..57594c6 100644 --- a/Extension/_locales/en/messages.json +++ b/Extension/_locales/en/messages.json @@ -36,7 +36,7 @@ "message": "Yes? You are ready to go!" }, "installedStart": { - "message": "Start by watching a video on YouTube, watching your loved streamers on Twitch, maybe even Netflix... Who knows?
Or you just listen to your favourite songs on SoundCloud and YouTube Music." + "message": "Start by watching a video on YouTube, watching your loved streamers on Twitch, Watch your favourite animes on KissAnime or JKAnime, maybe even Netflix... Who knows?
Or you just listen to your favourite songs on SoundCloud and YouTube Music. Settings can be found by clicking the PreMiD icon in your browser." }, "installedSupportMe": { "message": "Support me!" @@ -50,31 +50,55 @@ "updatedWhatChanged": { "message": "What changed?" }, - "updatedAdded0": { - "message": "Install tab page" - }, - "updatedAdded1": { - "message": "Update tab page" - }, - "updatedChanged0": { - "message": "Small bug fixes" - }, - "updatedChanged1": { - "message": "Extension organisation" - }, - "updatedAdded2": { - "message": "Language support" - }, - "updatedAdded3": { - "message": "Tab Priority" - }, - "updatedChanged2": { - "message": "YouTube + YouTube Music rewrite" - }, "playbackPlaying": { "message": "Playing back" }, "playbackPaused": { "message": "Playback paused" + }, + "about": { + "message": "About" + }, + "feedback": { + "message": "Feedback" + }, + "options": { + "message": "Options" + }, + "general": { + "message": "General" + }, + "enabled": { + "message": "Enabled" + }, + "titleMenubar": { + "message": "Title Menubar" + }, + "mediaControls": { + "message": "Media Controls" + }, + "checkForUpdates": { + "message": "Check for updates" + }, + "systemStartup": { + "message": "System startup" + }, + "presences": { + "message": "Presences" + }, + "updatedAdded0": { + "message": "Support for JKAnime & KissAnime" + }, + "updatedAdded1": { + "message": "Extension popup" + }, + "updatedAdded2": { + "message": "Settings Sync (Google Account)" + }, + "updatedChanged0": { + "message": "A lot and I mean a lot of rewrites!" + }, + "updatedChanged1": { + "message": "Huge speed improvements to App" } } diff --git a/Extension/_locales/he/messages.json b/Extension/_locales/he/messages.json deleted file mode 100644 index 940a68e..0000000 --- a/Extension/_locales/he/messages.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "appDesc": { - "message": "YT Presence מוסיף Rich Presence שילוב של מדיה, פיקודים ועוד המון דברים לYouTube/YouTube Music, Twitch ועוד.." - }, - "connected": { - "message": "מחובר" - }, - "disconnected": { - "message": "מנותק" - }, - "installedThanks": { - "message": "תודה שהורדת את YT Presence " - }, - "installedApp": { - "message": "האם התקנת את התוכנה?" - }, - "installedNo": { - "message": "לא? תעקוב אחרי הצעדים הבאים:" - }, - "installedStepApp": { - "message": "הורד את הגרסה החדשה ביותר ב1$" - }, - "installedStepAppMyRepository": { - "message": "מאגר הGitHub שלי" - }, - "installedWaitInstalled": { - "message": "פתח את ההתקנה וחכה על שההתקנה תסתיים" - }, - "installedMayWarning": { - "message": "יש סיכוי שתקבל אזהרה על FireWall וSmartScreen (זה לא וירוס, אני מבטיח)" - }, - "installedAppAutostart": { - "message": "התוכנה אמורה להתחיל אוטומטית, אתה יכול לבדוק את זה בכך שתסתכל על שורת המשימות שלך (Windows) או בתפריט הבר (MacOS)" - }, - "installedYes": { - "message": "כן? אתה מוכן לדרך!" - }, - "installedStart": { - "message": "התחל בכך שתצפה בסרטון ביוטיוב, צפה בסטרימרים האהובים עליך בTwitch, אולי אפילו בNetflix... מי יודע? או שאתה רק רוצה להאזין לשירים האהובים עליך בSoundCloud ובYouTube Music" - }, - "installedSupportMe": { - "message": "עזור לי!" - }, - "updatedYTPUpdated": { - "message": " YT Presence עודכן בהצלחה!" - }, - "updatedWhatsNew": { - "message": "מה חדש?" - }, - "updatedWhatChanged": { - "message": "מה השתנה?" - }, - "updatedAdded0": { - "message": "הורד את לשונית הכרטיסייה" - }, - "updatedAdded1": { - "message": "עדכן את דף הכרטיסייה" - }, - "updatedChanged0": { - "message": "באגים קטנים תוקנו" - }, - "updatedChanged1": { - "message": "ארגון תקינת התוסף" - }, - "updatedAdded2": { - "message": "שפת תמיכה" - }, - "updatedAdded3": { - "message": "" - }, - "updatedChanged2": { - "message": "" - } -} \ No newline at end of file diff --git a/Extension/_locales/la/messages.json b/Extension/_locales/la/messages.json deleted file mode 100644 index 81ba31a..0000000 --- a/Extension/_locales/la/messages.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "appDesc": { - "message": "YT Presence Discord Rich Presence instruens, gubernatio studii et amplius ad YouTube/YouTube Music, Twitch, et cetera addet" - }, - "connected": { - "message": "Connexus" - }, - "disconnected": { - "message": "Discerptim" - }, - "installedThanks": { - "message": "Gratias ago YT Presence instruere" - }, - "installedApp": { - "message": "Iamne usum instruxisti" - }, - "installedNo": { - "message": "Nonne est? Obtempera ii gradi" - }, - "installedStepApp": { - "message": "Instruere suprema forma a $1" - }, - "installedStepAppMyRepository": { - "message": "GitHub logium meum" - }, - "installedWaitInstalled": { - "message": "Aperi instruens et exspecta dum instruxit" - }, - "installedMayWarning": { - "message": "Admonitum super FireWall et SmartScreen accipere potes (Virus non est, promitto)" - }, - "installedAppAutostart": { - "message": "Usus statim incipere debet, id per optutu ad regula initii (Windows et MacOS) tua examinare potes" - }, - "installedYes": { - "message": "Enimne? Incohare potes!" - }, - "installedStart": { - "message": "Incipe per video spectante in YouTube, per streamer amari spectante in Twitch, fortasse etiam Netflix... quis scit? Aut carmina optima in SoundCloud et YouTube Music audis." - }, - "installedSupportMe": { - "message": "Adiuva me!" - }, - "updatedYTPUpdated": { - "message": "YT Presence corrigam est!" - }, - "updatedWhatsNew": { - "message": "Quid nove est?" - }, - "updatedWhatChanged": { - "message": "Quid mutatum est?" - }, - "updatedAdded0": { - "message": "Instruere pars nova" - }, - "updatedAdded1": { - "message": "Corrigere pars" - }, - "updatedChanged0": { - "message": "Parvi errores reparatum est" - }, - "updatedChanged1": { - "message": "Facies dilatationum" - }, - "updatedAdded2": { - "message": "Auxilium linguae" - }, - "updatedAdded3": { - "message": "" - }, - "updatedChanged2": { - "message": "" - } -} \ No newline at end of file diff --git a/Extension/_locales/sv/messages.json b/Extension/_locales/sv/messages.json deleted file mode 100644 index 695ef28..0000000 --- a/Extension/_locales/sv/messages.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "appDesc": { - "message": "YT Presence lägger till Discord Rich Presence Integration, Mediekontroller och mycket mer till YouTube/YouTube Musik, Twitch osv..." - }, - "connected": { - "message": "Ansluten" - }, - "disconnected": { - "message": "Avkopplad" - }, - "installedThanks": { - "message": "Tack för att du har installerat YT Presence" - }, - "installedApp": { - "message": "Har du installerat programmet ännu?" - }, - "installedNo": { - "message": "Nej? Följ dessa steg:" - }, - "installedStepApp": { - "message": "Ladda ner den senaste versionen från $1" - }, - "installedStepAppMyRepository": { - "message": "mitt GitHub-förråd" - }, - "installedWaitInstalled": { - "message": "Öppna installationsprogrammet och vänta tills det installeras" - }, - "installedMayWarning": { - "message": "Du kanske får en varning om brandvägg och Smartscreen (det är inte ett virus jag lovar)" - }, - "installedAppAutostart": { - "message": "Applikationen bör starta automatiskt, du kan kontrollera detta genom att titta på ditt aktivitetsfält (Windows) eller menyraden (Mac OS)" - }, - "installedYes": { - "message": "Ja? Du är redo att gå!" - }, - "installedStart": { - "message": "Börja med att titta på en video på YouTube, titta på dina älskade streamers på Twitch, kanske även Netflix... Vem vet? Eller så lyssnar du bara på dina favoritlåtar på SoundCloud och YouTube Music." - }, - "installedSupportMe": { - "message": "Stöd mig!" - }, - "updatedYTPUpdated": { - "message": "YT Presence har uppdaterats!" - }, - "updatedWhatsNew": { - "message": "Vad är nytt?" - }, - "updatedWhatChanged": { - "message": "Vad har förändrats?" - }, - "updatedAdded0": { - "message": "Installera fliksidan" - }, - "updatedAdded1": { - "message": "Uppdatera fliksidan" - }, - "updatedChanged0": { - "message": "Små buggfixar" - }, - "updatedChanged1": { - "message": "Tillägg organisation" - }, - "updatedAdded2": { - "message": "Språkstöd" - }, - "updatedAdded3": { - "message": "" - }, - "updatedChanged2": { - "message": "" - } -} \ No newline at end of file diff --git a/Extension/background.js b/Extension/background.js deleted file mode 100644 index 738a1fe..0000000 --- a/Extension/background.js +++ /dev/null @@ -1,30 +0,0 @@ -chrome.runtime.onInstalled.addListener(function(details) { - switch(details.reason) { - case "install": { - chrome.tabs.create({url: "installed.html"}) - break; - } - case "update": { - //chrome.tabs.create({url: "updated.html"}) - break; - } - } -}) - -//* Tab Priority -var lastAllowedTab = null -setInterval(() => { - chrome.tabs.getAllInWindow(null, (tabs) => { - var allowedURL = ["www.youtube.com", "music.youtube.com", "twitch.tv", "soundcloud.com", "netflix.com", "kissanime.ac", "jkanime.net"] - - for (var i = 0; i < allowedURL.length; i++) { - var currentTab = tabs.find(tab => tab.highlighted) - if(currentTab.url.indexOf(allowedURL[i]) > -1) { - lastAllowedTab = currentTab.id - } - } - if(lastAllowedTab != null) { - chrome.tabs.sendMessage(lastAllowedTab, {"high": true}) - } - }) -}, 500) \ No newline at end of file diff --git a/Extension/connect.css b/Extension/connect.css deleted file mode 100644 index a920c0f..0000000 --- a/Extension/connect.css +++ /dev/null @@ -1,54 +0,0 @@ -#ytp-connectinfo { - position: fixed; - top: -50px; - right: 0; - z-index: 10000; - min-width: 175px; - border-bottom-left-radius: 5px; - height: 50px; - background-color: rgba(255, 255, 255, 0.5); - user-select: none; - animation-name: slideIn; - animation-duration: 5s; - animation-timing-function: cubic-bezier(0.19, 1, 0.22, 1); - color: black; -} - -#ytp-connectinfo * { - margin: 0; - padding: 0; -} - -#ytp-connectinfo img { - float: left; - margin: 5px; - width: 40px; - height: 40px; -} - -#ytp-connectinfo h1 { - font-size: 20px; - margin-top: 4px; -} - -#ytp-connectinfo h2 { - font-size: 17px; -} - -@keyframes slideIn { - 0% { - top: -50px; - } - - 10% { - top: 0; - } - - 90% { - top: 0; - } - - 100% { - top: -50px; - } -} diff --git a/Extension/css/inputs.css b/Extension/css/inputs.css new file mode 100644 index 0000000..49513cc --- /dev/null +++ b/Extension/css/inputs.css @@ -0,0 +1,78 @@ +/* The switch - the box around the slider */ + +.switch { + position: relative; + display: inline-block; + width: 35px; + height: 15px; +} + +/* Hide default HTML checkbox */ + +.switch input { + display: none; +} + +/* The slider */ + +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgb(255, 75, 75); + -webkit-transition: 0.25s; + transition: 0.25s; +} + +.slider:before { + position: absolute; + content: ""; + height: 17px; + width: 17px; + left: -2.5px; + top: -2.5px; + background-color: white; + -webkit-transition: 0.25s; + transition: 0.25s cubic-bezier(0.215, 0.61, 0.355, 1); + border: 1px solid lightgray; +} + +input:checked + .slider { + background-color: rgb(75, 255, 75); +} + +input:disabled + .slider { + background-color: rgb(255, 75, 75); + cursor: not-allowed; +} + +input:disabled + .slider:before { + background-color: rgb(255, 75, 75); + border: 1px solid rgb(255, 75, 75); + cursor: not-allowed; +} + +input:focus + .slider { + box-shadow: 0 0 1px rgb(75, 255, 75); +} + +input:hover + .slider { + transform: scale(1.1); +} + +input:checked + .slider:before { + transform: translateX(20px); +} + +/* Rounded sliders */ + +.slider.round { + border-radius: 34px; +} + +.slider.round:before { + border-radius: 50%; +} diff --git a/Extension/css/options.css b/Extension/css/options.css new file mode 100644 index 0000000..e8fc5fc --- /dev/null +++ b/Extension/css/options.css @@ -0,0 +1,15 @@ +.right { + float: right; +} + +#content h1 { + margin: 5px; +} + +table { + margin: 5px; +} + +tr td:first-child { + width: 90%; +} diff --git a/Extension/popup.css b/Extension/css/popup.css similarity index 72% rename from Extension/popup.css rename to Extension/css/popup.css index a6ecdfa..35c07b7 100644 --- a/Extension/popup.css +++ b/Extension/css/popup.css @@ -43,10 +43,13 @@ body { border-radius: 5px; color: white; text-align: center; +} + +#panel:not(.open) { cursor: pointer; } -#panel:hover { +#panel:not(.open):hover { transform: scale(1.05); } @@ -68,3 +71,28 @@ body { .github { background-color: #fa503c !important; } + +.open { + position: fixed; + transition: 0.5s all ease-out; + transform: scale(5); + cursor: default; +} + +.open * { + transition: 0.15s all ease-out; + opacity: 0; +} + +.panelContent { + position: relative; + color: white; +} + +.panelContent:not(.open) { + display: none; +} + +.panelContent.open { + display: block; +} diff --git a/Extension/css/reset.css b/Extension/css/reset.css new file mode 100644 index 0000000..17a3677 --- /dev/null +++ b/Extension/css/reset.css @@ -0,0 +1,20 @@ +html, +body { + margin: 0; + padding: 0; + height: 0; + width: 325px; + background-color: #282828; +} + +* { + color: #fff; +} + +#header { + height: 50px; + background-color: #7289da; + color: white; + text-align: center; + line-height: 50px; +} diff --git a/Extension/html/popup/options.html b/Extension/html/popup/options.html new file mode 100644 index 0000000..24df389 --- /dev/null +++ b/Extension/html/popup/options.html @@ -0,0 +1,137 @@ + + + + + + + + + + +
+

+ + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
YouTube + +
YouTube Music + +
Twitch + +
SoundCloud + +
Netflix + +
KissAnime + +
JKAnime + +
+
+ + + + + + \ No newline at end of file diff --git a/Extension/popup.html b/Extension/html/popup/popup.html similarity index 58% rename from Extension/popup.html rename to Extension/html/popup/popup.html index eb2c542..9f36106 100644 --- a/Extension/popup.html +++ b/Extension/html/popup/popup.html @@ -3,32 +3,26 @@ - +
-
- -

About

-
-
- -

Feedback

-

GitHub

-

Options

+

+ + \ No newline at end of file diff --git a/Extension/installed.html b/Extension/html/tabs/installed.html similarity index 68% rename from Extension/installed.html rename to Extension/html/tabs/installed.html index 52975d7..1fc5f4d 100644 --- a/Extension/installed.html +++ b/Extension/html/tabs/installed.html @@ -2,12 +2,12 @@ PreMiD - + @@ -25,12 +25,12 @@

Support me on Patreon! + src="../../images/patreonBTN.png" draggable="false" height="50px" alt="Support me on Patreon!"> - Join my Discord! + Join my Discord! - + \ No newline at end of file diff --git a/Extension/updated.html b/Extension/html/tabs/updated.html similarity index 63% rename from Extension/updated.html rename to Extension/html/tabs/updated.html index ea3052c..43047a7 100644 --- a/Extension/updated.html +++ b/Extension/html/tabs/updated.html @@ -2,12 +2,12 @@ PreMiD - + @@ -21,12 +21,12 @@

Support me on Patreon! + src="../../images/patreonBTN.png" draggable="false" height="50px" alt="Support me on Patreon!"> - Join my Discord! + Join my Discord! - + \ No newline at end of file diff --git a/Extension/js/background.js b/Extension/js/background.js new file mode 100644 index 0000000..0ce66f5 --- /dev/null +++ b/Extension/js/background.js @@ -0,0 +1,62 @@ +chrome.runtime.onInstalled.addListener(function(details) { + switch(details.reason) { + case "install": { + chrome.tabs.create({url: "html/tabs/installed.html"}) + break; + } + case "update": { + chrome.tabs.create({url: "html/tabs/updated.html"}) + break; + } + } +}) + +//* Tab Priority +var lastAllowedTab = null, +allowedURL = [] +setInterval(() => { + chrome.storage.sync.get(['options'], function(result) { + allowedURL = ["www.youtube.com", "music.youtube.com", "twitch.tv", "soundcloud.com", "netflix.com", "kissanime.ac", "kissanime.ru", "jkanime.net"] + var options = result.options + if(!options.enabled) allowedURL = [] + if(!options.youtube) allowedURL.remove("www.youtube.com") + if(!options.youtubeMusic) allowedURL.remove("music.youtube.com") + if(!options.twitch) allowedURL.remove("twitch.tv") + if(!options.soundcloud) allowedURL.remove("soundcloud.com") + if(!options.netflix) allowedURL.remove("netflix.com") + if(!options.kissanime) allowedURL.remove("kissanime.ac") && allowedURL.remove('kissanime.ru') + if(!options.jkanime) allowedURL.remove("jkanime.net") + }) + chrome.tabs.getAllInWindow(null, (tabs) => { + + for (var i = 0; i < allowedURL.length; i++) { + var currentTab = tabs.find(tab => tab.highlighted) + if(currentTab.url.indexOf(allowedURL[i]) > -1) { + lastAllowedTab = currentTab.id + } + } + if(lastAllowedTab != null) { + chrome.tabs.sendMessage(lastAllowedTab, {"high": true}) + } + }) +}, 500) + +Array.prototype.remove = function() { + var what, a = arguments, L = a.length, ax; + while (L && this.length) { + what = a[--L]; + while ((ax = this.indexOf(what)) !== -1) { + this.splice(ax, 1); + } + } + return this; +}; + +//* Create socket connection to application +var socket = io.connect('http://localhost:3020/'); + +setInterval(() => { + chrome.storage.sync.get(['options'], function(result) { + socket.emit('settingsChange', result) + }) +}, 1000) \ No newline at end of file diff --git a/Extension/js/options.js b/Extension/js/options.js new file mode 100644 index 0000000..4487db7 --- /dev/null +++ b/Extension/js/options.js @@ -0,0 +1,140 @@ +let options = undefined + +$('.Ppreferences').html(chrome.i18n.getMessage('options')) +$('.Pgeneral').html(chrome.i18n.getMessage('general')) +$('.Penabled').html(chrome.i18n.getMessage('enabled')) +$('.PmediaControls').html(chrome.i18n.getMessage('mediaControls')) +$('.PcheckForUpdates').html(chrome.i18n.getMessage('checkForUpdates')) +$('.PsystemStartup').html(chrome.i18n.getMessage('systemStartup')) +$('.Ppresences').html(chrome.i18n.getMessage('presences')) + +chrome.runtime.getPlatformInfo(function(info) { + if(info.os == "mac") + $('Title Menubar').insertAfter('#tPresence') + titleMenubarToggle = $('.toggleTitleMenubar') + titleMenubarToggle.change(tMB); +}) + +$(document).ready(function() { + var enabledToggle = $('.togglePresence'), + youtubeToggle = $('.toggleYouTube'), + youtubeMusicToggle = $('.toggleYouTubeMusic'), + twitchToggle = $('.toggleTwitch'), + soundcloudToggle = $('.toggleSoundCloud'), + netflixToggle = $('.toggleNetflix'), + kissanimeToggle = $('.toggleKissAnime'), + jkanimeToggle = $('.toggleJKAnime') + mediaControlsToggle = $('.toggleMediaControls') + checkForUpdatesToggle = $('.toggleCheckUpdates') + systemStartupToggle = $('.toggleSystemStartup') + + enabledToggle.change(tEnabled); + youtubeToggle.change(tYT); + youtubeMusicToggle.change(tYTM); + twitchToggle.change(tT); + soundcloudToggle.change(tSC); + netflixToggle.change(tN); + kissanimeToggle.change(tKA); + jkanimeToggle.change(tJKA); + mediaControlsToggle.change(tMC); + checkForUpdatesToggle.change(tCFU); + systemStartupToggle.change(tSS); + + chrome.storage.sync.get(['options'], function(result) { + options = result.options + if(result.options == undefined) { + chrome.storage.sync.set({options: {enabled: true, youtube: true, youtubeMusic: true, twitch: true, soundcloud: true, netflix: true, kissanime: true, jkanime: true, titleMenubar: true, mediaControls: true, checkForUpdates: true, systemStartup: true}}) + enabledToggle.prop('checked', true) + youtubeToggle.prop('checked', true) + youtubeMusicToggle.prop('checked', true) + twitchToggle.prop('checked', true) + soundcloudToggle.prop('checked', true) + netflixToggle.prop('checked', true) + kissanimeToggle.prop('checked', true) + jkanimeToggle.prop('checked', true) + if(titleMenubarToggle != undefined) + titleMenubarToggle.prop('checked', true) + mediaControlsToggle.prop('checked', true) + checkForUpdatesToggle.prop('checked', true) + systemStartupToggle.prop('checked', true) + } else { + enabledToggle.prop('checked', result.options.enabled) + youtubeToggle.prop('checked', result.options.youtube) + youtubeMusicToggle.prop('checked', result.options.youtubeMusic) + twitchToggle.prop('checked', result.options.twitch) + soundcloudToggle.prop('checked', result.options.soundcloud) + netflixToggle.prop('checked', result.options.netflix) + kissanimeToggle.prop('checked', result.options.kissanime) + jkanimeToggle.prop('checked', result.options.jkanime) + if(titleMenubarToggle != undefined) + titleMenubarToggle.prop('checked', result.options.titleMenubar) + mediaControlsToggle.prop('checked', result.options.mediaControls) + checkForUpdatesToggle.prop('checked', result.options.checkForUpdates) + systemStartupToggle.prop('checked', result.options.systemStartup) + } + }) +}) + +function tEnabled() { + options.enabled = !options.enabled + sync() +} + +function tYT() { + options.youtube = !options.youtube + sync() +} + +function tYTM() { + options.youtubeMusic = !options.youtubeMusic + sync() +} + +function tT() { + options.twitch = !options.twitch + sync() +} + +function tSC() { + options.soundcloud = !options.soundcloud + sync() +} + +function tN() { + options.netflix = !options.netflix + sync() +} + +function tKA() { + options.kissanime = !options.kissanime + sync() +} + +function tJKA() { + options.jkanime = !options.jkanime + sync() +} + +function tMB() { + options.titleMenubar = !options.titleMenubar + sync() +} + +function tMC() { + options.mediaControls = !options.mediaControls + sync() +} + +function tCFU() { + options.checkForUpdates = !options.checkForUpdates + sync() +} + +function tSS() { + options.systemStartup = !options.systemStartup + sync() +} + +function sync() { + chrome.storage.sync.set({options: options}) +} \ No newline at end of file diff --git a/Extension/js/popup.js b/Extension/js/popup.js new file mode 100644 index 0000000..99b1c91 --- /dev/null +++ b/Extension/js/popup.js @@ -0,0 +1,20 @@ +$(document).ready(function() { + $('.Pname').html(chrome.runtime.getManifest().name) + $('.Pversion').html('V' + chrome.runtime.getManifest().version) + $('.Pabout').html(chrome.i18n.getMessage('about')) + $('.Pfeedback').html(chrome.i18n.getMessage('feedback')) + $('.Poptions').html(chrome.i18n.getMessage('options')) + + $('#content #panel').each(function() { + this.addEventListener('click', updateItem) + }) +}) + +function updateItem() { + $(this).addClass('open') + setTimeout(() => { + if($(this).attr("class").split(' ')[0] == "github") { + chrome.tabs.create({url: 'https://github.com/Timeraa/PreMiD'}) + } else window.location.href= $(this).attr("class").split(' ')[0] + ".html"; + }, 350) +} \ No newline at end of file diff --git a/Extension/presences/JKAnime.js b/Extension/js/presences/JKAnime.js similarity index 100% rename from Extension/presences/JKAnime.js rename to Extension/js/presences/JKAnime.js diff --git a/Extension/presences/KissAnime.js b/Extension/js/presences/KissAnime.js similarity index 100% rename from Extension/presences/KissAnime.js rename to Extension/js/presences/KissAnime.js diff --git a/Extension/presences/Netflix.js b/Extension/js/presences/Netflix.js similarity index 62% rename from Extension/presences/Netflix.js rename to Extension/js/presences/Netflix.js index 3ea4777..57a3e72 100644 --- a/Extension/presences/Netflix.js +++ b/Extension/js/presences/Netflix.js @@ -103,28 +103,51 @@ function updateData(playbackChange = false) { var endTime if(musicRunning && $('.VideoContainer div video')[0] != undefined) { - var startTime = Date.now(); - endTime = Math.floor(startTime / 1000) - + var startTime = Math.floor(Date.now()/1000); + endTime = startTime - Math.floor($('.VideoContainer div video')[0].currentTime) + Math.floor($('.VideoContainer div video')[0].duration); - - data = { - nflix: { - url: urlForVideo, - seriesTitle: $('.ellipsize-text').children().html(), - season: $($('.ellipsize-text').children().get(1)).html(), - episodeTitle: $($('.ellipsize-text').children().get(2)).html(), - episodeCurrentTimeSeconds: Math.floor($('.VideoContainer div video')[0].currentTime), - episodeEndTimeSeconds: Math.floor($('.VideoContainer div video')[0].duration), - episodeCurrentTime: startTime, - episodeEndTime: endTime, - playback: $('.VideoContainer div video')[0].paused ? "paused" : "playing" + + var playbackBoolean = !$('.VideoContainer div video')[0].paused + + var smallImageKey = playbackBoolean ? "play" : "pause" + smallImageText = playbackBoolean ? chrome.i18n.getMessage('playbackPlaying') : chrome.i18n.getMessage('playbackPaused') + + if(playbackBoolean) { + data = { + clientID: '499981204045430784', + presenceData: { + details: $('.ellipsize-text').children().html(), + state: $($('.ellipsize-text').children().get(1)).html(), + largeImageKey: 'nflix_lg', + largeImageText: chrome.runtime.getManifest().name + ' V' + chrome.runtime.getManifest().version, + smallImageKey: smallImageKey, + smallImageText: smallImageText, + startTimestamp: startTime, + endTimestamp: endTime + }, + currentSeconds: Math.floor($('.VideoContainer div video')[0].currentTime), + durationSeconds: Math.floor($('.VideoContainer div video')[0].duration), + trayTitle: $('.ellipsize-text').children().html(), + playback: playbackBoolean, + service: 'Netflix' } - } - } else { - data = { - nflix: { - playback: false + } else { + data = { + clientID: '499981204045430784', + presenceData: { + details: $('.ellipsize-text').children().html(), + state: $($('.ellipsize-text').children().get(1)).html(), + largeImageKey: 'nflix_lg', + largeImageText: chrome.runtime.getManifest().name + ' V' + chrome.runtime.getManifest().version, + smallImageKey: smallImageKey, + smallImageText: smallImageText + }, + currentSeconds: Math.floor($('.VideoContainer div video')[0].currentTime), + durationSeconds: Math.floor($('.VideoContainer div video')[0].duration), + trayTitle: $('.ellipsize-text').children().html(), + playback: playbackBoolean, + service: 'Netflix' } } } diff --git a/Extension/presences/SoundCloud.js b/Extension/js/presences/SoundCloud.js similarity index 100% rename from Extension/presences/SoundCloud.js rename to Extension/js/presences/SoundCloud.js diff --git a/Extension/presences/Twitch.js b/Extension/js/presences/Twitch.js similarity index 100% rename from Extension/presences/Twitch.js rename to Extension/js/presences/Twitch.js diff --git a/Extension/presences/YouTube.js b/Extension/js/presences/YouTube.js similarity index 100% rename from Extension/presences/YouTube.js rename to Extension/js/presences/YouTube.js diff --git a/Extension/presences/YouTubeMusic.js b/Extension/js/presences/YouTubeMusic.js similarity index 100% rename from Extension/presences/YouTubeMusic.js rename to Extension/js/presences/YouTubeMusic.js diff --git a/Extension/util/jquery-3.3.1.min.js b/Extension/js/util/jquery-3.3.1.min.js similarity index 100% rename from Extension/util/jquery-3.3.1.min.js rename to Extension/js/util/jquery-3.3.1.min.js diff --git a/Extension/util/socket.io-2.1.1.min.js b/Extension/js/util/socket.io-2.1.1.min.js similarity index 100% rename from Extension/util/socket.io-2.1.1.min.js rename to Extension/js/util/socket.io-2.1.1.min.js diff --git a/Extension/util/socketConnector.js b/Extension/js/util/socketConnector.js similarity index 100% rename from Extension/util/socketConnector.js rename to Extension/js/util/socketConnector.js diff --git a/Extension/manifest.json b/Extension/manifest.json index e065529..6c66bd4 100644 --- a/Extension/manifest.json +++ b/Extension/manifest.json @@ -1,7 +1,7 @@ { "name": "PreMiD", "author": "Timeraa", - "version": "1.1.2", + "version": "1.2", "description": "__MSG_appDesc__", "manifest_version": 2, "default_locale": "en", @@ -9,11 +9,11 @@ "2024": "icon.png" }, "background": { - "scripts": ["background.js"], + "scripts": ["js/util/socket.io-2.1.1.min.js", "js/background.js"], "presistent": false }, "browser_action": { - "default_popup": "popup.html", + "default_popup": "html/popup/popup.html", "default_icon": { "2024": "icon.png" } @@ -21,11 +21,11 @@ "content_scripts": [ { "js": [ - "util/jquery-3.3.1.min.js", - "util/socket.io-2.1.1.min.js", - "util/socketConnector.js" + "js/util/jquery-3.3.1.min.js", + "js/util/socket.io-2.1.1.min.js", + "js/util/socketConnector.js" ], - "css": ["connect.css"], + "css": ["css/connect.css"], "matches": [ "https://www.youtube.com/*", "https://music.youtube.com/*", @@ -38,31 +38,31 @@ ] }, { - "js": ["presences/YouTubeMusic.js"], + "js": ["js/presences/YouTubeMusic.js"], "matches": ["https://music.youtube.com/*"] }, { - "js": ["presences/YouTube.js"], + "js": ["js/presences/YouTube.js"], "matches": ["https://www.youtube.com/*"] }, { - "js": ["presences/Netflix.js"], + "js": ["js/presences/Netflix.js"], "matches": ["https://*.netflix.com/*"] }, { - "js": ["presences/SoundCloud.js"], + "js": ["js/presences/SoundCloud.js"], "matches": ["https://*.soundcloud.com/*"] }, { - "js": ["presences/Twitch.js"], + "js": ["js/presences/Twitch.js"], "matches": ["https://*.twitch.tv/*"] }, { - "js": ["presences/KissAnime.js"], + "js": ["js/presences/KissAnime.js"], "matches": ["https://kissanime.ac/*", "https://kissanime.ru/*"] }, { - "js": ["presences/JKAnime.js"], + "js": ["js/presences/JKAnime.js"], "matches": ["https://jkanime.net/*"] } ], diff --git a/README.md b/README.md index 06f8459..06f5eae 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -## ![version](https://img.shields.io/badge/Version-1.1-brightgreen.svg?style=flat-square) [![Discord](https://img.shields.io/discord/493130730549805057.svg?style=flat-square)](https://discord.gg/Kw7WaYn) +## ![version](https://img.shields.io/badge/Version-1.2-brightgreen.svg?style=flat-square) [![Discord](https://img.shields.io/discord/493130730549805057.svg?style=flat-square)](https://discord.gg/Kw7WaYn) -# PreMiD · Media Rich Presence for Discord +# PreMiD · Discord Rich Presence for your Media! Join my Discord! @@ -12,7 +12,7 @@ ## Summary -**PreMiD** is a simple, configurable utility to allow you to show what you're watching in your Discord **now playing status**. It supports [many different platforms](#support), and will also support multiple users watching the same content simultaneously in an upcoming update. +**PreMiD** is a simple, configurable utility that allows you to show what you're watching/listening in your Discord **now playing status**. It supports [many different platforms](#support), and will support multiple users watching the same content simultaneously in an upcoming update. ## Features @@ -28,6 +28,9 @@ - [Summary](#summary) - [Features](#features) - [Support](#support) + - [Operating Systems](#operating-systems) + - [Browsers](#browsers) + - [Services](#services) - [Installation](#installation) - [Extension](#extension) - Chrome @@ -48,6 +51,18 @@ - Chrome - Opera +### **Services** + +- YouTube +- YouTube Music +- Netflix +- SoundCloud +- Twitch +- JKAnime +- KissAnime + +One missing? Open an [Issue](https://github.com/Timeraa/PreMiD/issues/new?template=feature_request.md)! + # Installation ## Extension @@ -119,12 +134,17 @@

Fruxh

-

Patrons & Donators

+

Patrons \ Donators

Fruxh

Patron

+
+ +

UMU

+

Patron

+

Paz

@@ -132,41 +152,31 @@

Translators

+
+ +

Timeraa

+

Fruxh

-

German

-

Japanese

Restrike

-

German

-

Japanese

-

Korean

-

Latin

-
-
- -

Timeraa

-

German

2dward.

-

Arabic

Ufo

-

Hebrew

VerifyBot

-

Swedish

--- -### PreMiD - (Rich) Presence for Media in Discord | by Timeraa +### PreMiD - Discord Rich Presence for your Media! diff --git a/gitassets/UMU.png b/gitassets/UMU.png new file mode 100644 index 0000000000000000000000000000000000000000..749592b1f8a897e3bdc943135b7aad73eedcda02 GIT binary patch literal 32839 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⋘wIS7{%>^=BE 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 { module.exports.unregister = async () => { console.log(CONSOLEPREFIX + chalk.red("Unregistering keyboard shortcuts...")) + if(require('os').platform() == "darwin") { + app.relaunch() + app.exit(0) + } else globalShortcut.unregisterAll() console.log(CONSOLEPREFIX + chalk.green("Unregistered keyboard shortcuts")) }