diff --git a/background.js b/background.js new file mode 100644 index 0000000..8a22f49 --- /dev/null +++ b/background.js @@ -0,0 +1,612 @@ +chrome.alarms.create("refresh", { + "delayInMinutes": 0.1, + "periodInMinutes": 0.1 +}); +chrome.alarms.onAlarm.addListener(alarm => { + refreshToken(true); +}) + +chrome.runtime.onInstalled.addListener(() => { + onStart(); +}); + +chrome.runtime.onStartup.addListener(() => { + onStart(); +}); + +function onStart() { + initValues(); + + chrome.storage.local.set({"lastFollowedChannelsRefresh": 1}); + chrome.storage.local.set({"lastTTVTokenRefresh": 1}); + chrome.storage.local.set({"lastStreamsRefresh": 0}); + chrome.storage.local.set({"callUserInfos": true}); + chrome.storage.local.set({"totalRefreshCount": 0}, () => { + chrome.storage.sync.set({"alreadyNotifiedStreams": []}, () => { + chrome.storage.sync.set({"alreadyNotifiedCategoryChanges": []}, () => { + forceRefresh(); + }); + }); + }); +} + +function initValues() { + chrome.storage.sync.get("viewercount-order", value => { + if (value["viewercount-order"] == null) + chrome.storage.sync.set({"viewercount-order": "descendant"}); + }); + chrome.storage.sync.get("streams-layout", value => { + if (value["streams-layout"] == null) + chrome.storage.sync.set({"streams-layout": "regular"}); + }); + chrome.storage.sync.get("notified-streams", value => { + if (value["notified-streams"] == null) + chrome.storage.sync.set({"notified-streams": []}); + }); + chrome.storage.sync.get("notify-all-streams", value => { + if (value["notify-all-streams"] == null) + chrome.storage.sync.set({"notify-all-streams": true}); + }); + chrome.storage.sync.get("enabled-notifications", value => { + if (value["enabled-notifications"] == null) + chrome.storage.sync.set({"enabled-notifications": []}); + }); +} + +function refreshToken(refreshAll) { + /** + * We validate the ttv token every 1h + * This also allows to get some values from Twitch + */ + chrome.storage.sync.get("ttvToken", ttvToken_result => { + var ttvToken = ttvToken_result.ttvToken; + if (ttvToken != null && ttvToken != "failed" && ttvToken != "none") { + chrome.storage.local.get("lastTTVTokenRefresh", lastTTVTokenRefresh_result => { + if (lastTTVTokenRefresh_result.lastTTVTokenRefresh < (Date.now() - 3600000)) { + validateTTVToken(ttvToken, data => { + if (data == null) { + hardDisconnect(); + } else { + chrome.storage.local.remove("disconnected"); + let ttvUser = { + "client_id": data.client_id, + "expires_in": data.expires_in, + "login": data.login, + "user_id": data.user_id + }; + chrome.storage.local.set({"ttvUser": ttvUser}); + if (refreshAll) + refresh(ttvToken, ttvUser); + } + }); + } else if (refreshAll) { + chrome.storage.local.get("ttvUser", ttvUser_result => { + refresh(ttvToken, ttvUser_result.ttvUser); + }); + } + }); + } + }); +} + + +function getAllTwitchCategories(ttvToken, ttvUserId, clientId, callback, page) { + fetch("https://api.twitch.tv/helix/games/top?first=100" + (page != null ? "&after=" + page : ""), { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken, + "Client-Id": clientId + } + }).then(response => { + response.json().then(data => { + if (data.pagination != null && Object.keys(data.pagination).length !== 0) { + let totalData = []; + Array.prototype.push.apply(totalData, data.data); + getAllTwitchCategories(ttvToken, ttvUserId, clientId, data => { + Array.prototype.push.apply(totalData, data); + callback(totalData); + }, data.pagination.cursor); + } else { + callback(data.data); + } + }) + }, reason => { + // TODO: handle this case + }); +} + +function refresh(ttvToken, ttvUser) { + chrome.storage.local.get("callUserInfos", callUserInfos_result => { + if (callUserInfos_result.callUserInfos) { + chrome.storage.local.set({"callUserInfos": false}); + getUserInfos(ttvToken, ttvUser.client_id, data => { + chrome.storage.local.set({"ttvUser_data": data.data[0]}); + }); + } else { + chrome.storage.local.set({"callUserInfos": true}); + } + }); + + getAllTwitchCategories( + ttvToken, ttvUser.user_id, ttvUser.client_id, data => { + var twitchCategoriesMap = data.map(elm => elm.name); + chrome.storage.local.set({"allTwitchCategories": (twitchCategoriesMap)}, () => {}); + }, + null); + + getLiveFollowedStreams(ttvToken, ttvUser.user_id, ttvUser.client_id, data => { + chrome.storage.local.set({"lastStreamsRefresh": Date.now()}); + chrome.storage.local.set({"ttvStreams_data": data.data}); + + var allStreams = []; + var allCategoryChanges = []; + data.data.forEach(el => { + allStreams.push(el["user_login"]); + allCategoryChanges.push({ + game_name: el["game_name"], + user_login: el["user_login"], + }); + }) + + + chrome.storage.sync.get("notified-streams", notified_streams_result => { + var notified_streams = notified_streams_result["notified-streams"]; + chrome.storage.sync.get("notify-all-streams", notify_result => { + var notify_streams = notify_result["notify-all-streams"]; + chrome.storage.local.get("totalRefreshCount", (totalRefreshCount_result) => { + if (totalRefreshCount_result.totalRefreshCount != 0) { + chrome.storage.sync.get("alreadyNotifiedStreams", (alreadyNotifiedStreams_result) => { + let alreadyNotifiedStreams = alreadyNotifiedStreams_result.alreadyNotifiedStreams; + + //alreadyNotifiedStreams.pop(); + + let notifiedStreams = []; + let newStreams = allStreams; + let stoppedStreams = []; + if (alreadyNotifiedStreams != null) { + newStreams = allStreams.filter(x => !alreadyNotifiedStreams.includes(x)) + stoppedStreams = alreadyNotifiedStreams.filter(x => !allStreams.includes(x)) + notifiedStreams = allStreams.filter(x => !stoppedStreams.includes(x)) + } + + // If "enable all notifications" checkbox isnt checked, we filter out streams + if (!notify_streams) { + newStreams = newStreams.filter(x => notified_streams.includes(x)) + } + + if (newStreams.length > 0) { + newNotification(newStreams); + } + chrome.storage.sync.set({"alreadyNotifiedStreams": notifiedStreams}); + }); + + chrome.storage.sync.get("alreadyNotifiedCategoryChanges", (alreadyNotifiedCategoryChanges_result) => { + let alreadyNotifiedCategoryChanges = alreadyNotifiedCategoryChanges_result.alreadyNotifiedCategoryChanges; + + //alreadyNotifiedCategoryChanges.pop(); + + + let notifiedCategoryChanges = []; + let newCategoryChanges = []; + let stoppedCategoryChanges = []; + if (alreadyNotifiedCategoryChanges != null) { + + for (const element of allCategoryChanges) { + var current_user_login = (element.user_login); + var current_game_name = (element.game_name); + + if (!(alreadyNotifiedCategoryChanges.filter(e => e.user_login === current_user_login).length > 0)) { + //streamer is not in alreadyNotifiedCategoryChanges + //means a new streamer went online + + newCategoryChanges.push({ + game_name: current_game_name, + user_login: current_user_login, + user_just_went_online: true, + }); + } else { + //streamer is in alreadyNotifiedCategoryChanges (already notified) + //means check if game changed + for (const el of alreadyNotifiedCategoryChanges) { + if (el.user_login === current_user_login) { + if (el.game_name !== current_game_name) { + newCategoryChanges.push({ + game_name: current_game_name, + old_game_name: el.game_name, + user_login: current_user_login, + }); + } + } + } + } + } + + + + for (const ell of alreadyNotifiedCategoryChanges) { + if (!(allCategoryChanges.filter(e => e.user_login === ell.user_login).length > 0)) { + //one stream went offline + stoppedCategoryChanges.push({ + game_name: ell.game_name, + user_login: ell.user_login, + }); + } + } + + + + for (const elll of allCategoryChanges) { + if (!(stoppedCategoryChanges.filter(e => e.user_login === elll.user_login).length > 0)) { + notifiedCategoryChanges.push({ + game_name: elll.game_name, + user_login: elll.user_login, + }); + } + } + + } + + if (newCategoryChanges.length > 0) { + newCategoryNotification(newCategoryChanges); + } + chrome.storage.sync.set({"alreadyNotifiedCategoryChanges": notifiedCategoryChanges}); + }); + } else { + chrome.storage.sync.set({"alreadyNotifiedStreams": allStreams}); + chrome.storage.sync.set({"alreadyNotifiedCategoryChanges": allCategoryChanges}); + } + chrome.storage.local.set({"totalRefreshCount": totalRefreshCount_result.totalRefreshCount + 1}); + }); + }); + }); + }); +} + + + +async function currentTabHandlesCategoryChangeNotification(new_category_changes) { + /** + * (c) David Konrad 2018- + * MIT License + * + * Javascript function to convert plain text to unicode variants + * + * Loosely based on the nodejs monotext CLI utility https://github.com/cpsdqs/monotext + * (c) cpsdqs 2016 + * + * For more inspiration see http://unicode.org/charts/ + * + */ + + /* + * supported unicode variants + * + * m: monospace + * b: bold + * i: italic + * c: script (Mathematical Alphanumeric Symbols) + * g: gothic / fraktur + * d: double-struck + * s: sans-serif + * o: circled text + * p: parenthesized latin letters + * q: squared text + * w: fullwidth + */ + + function toUnicodeVariant(str, variant, flags) { + str = str.toUpperCase(); + + const offsets = { + m: [0x1d670, 0x1d7f6], + b: [0x1d400, 0x1d7ce], + i: [0x1d434, 0x00030], + bi: [0x1d468, 0x00030], + c: [0x0001d49c, 0x00030], + bc: [0x1d4d0, 0x00030], + g: [0x1d504, 0x00030], + d: [0x1d538, 0x1d7d8], + bg: [0x1d56c, 0x00030], + s: [0x1d5a0, 0x1d7e2], + bs: [0x1d5d4, 0x1d7ec], + is: [0x1d608, 0x00030], + bis: [0x1d63c, 0x00030], + o: [0x24B6, 0x2460], + on: [0x0001f150, 0x2460], + p: [0x249c, 0x2474], + q: [0x1f130, 0x00030], + qn: [0x0001F170, 0x00030], + w: [0xff21, 0xff10], + u: [0x2090, 0xff10] + } + + const variantOffsets = { + 'monospace': 'm', + 'bold' : 'b', + 'italic' : 'i', + 'bold italic' : 'bi', + 'script': 'c', + 'bold script': 'bc', + 'gothic': 'g', + 'gothic bold': 'bg', + 'doublestruck': 'd', + 'sans': 's', + 'bold sans' : 'bs', + 'italic sans': 'is', + 'bold italic sans': 'bis', + 'parenthesis': 'p', + 'circled': 'o', + 'circled negative': 'on', + 'squared': 'q', + 'squared negative': 'qn', + 'fullwidth': 'w' + } + + // special characters (absolute values) + const special = { + m: { + ' ': 0x2000, + '-': 0x2013 + }, + i: { + 'h': 0x210e + }, + g: { + 'C': 0x212d, + 'H': 0x210c, + 'I': 0x2111, + 'R': 0x211c, + 'Z': 0x2128 + }, + d: { + 'C': 0x2102, + 'H': 0x210D, + 'N': 0x2115, + 'P': 0x2119, + 'Q': 0x211A, + 'R': 0x211D, + 'Z': 0x2124 + }, + o: { + '0': 0x24EA, + '1': 0x2460, + '2': 0x2461, + '3': 0x2462, + '4': 0x2463, + '5': 0x2464, + '6': 0x2465, + '7': 0x2466, + '8': 0x2467, + '9': 0x2468, + }, + on: {}, + p: {}, + q: {}, + qn: {}, + w: {} + } + //support for parenthesized latin letters small cases + //support for full width latin letters small cases + //support for circled negative letters small cases + //support for squared letters small cases + //support for squared letters negative small cases + ;['p', 'w', 'on', 'q', 'qn'].forEach(t => { + for (var i = 97; i <= 122; i++) { + special[t][String.fromCharCode(i)] = offsets[t][0] + (i-97) + } + }) + + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + const numbers = '0123456789' + + const getType = function(variant) { + if (variantOffsets[variant]) return variantOffsets[variant] + if (offsets[variant]) return variant + return 'm' //monospace as default + } + const getFlag = function(flag, flags) { + if (!flags) return false + return flag.split('|').some(f => flags.split(',').indexOf(f) > -1) + } + + const type = getType(variant) + const underline = getFlag('underline|u', flags) + const strike = getFlag('strike|s', flags) + let result = '' + + for (let c of str) { + let index + if (special[type] && special[type][c]) c = String.fromCodePoint(special[type][c]) + if (type && (index = chars.indexOf(c)) > -1) { + result += String.fromCodePoint(index + offsets[type][0]) + } else if (type && (index = numbers.indexOf(c)) > -1) { + result += String.fromCodePoint(index + offsets[type][1]) + } else { + result += c + } + if (underline) result += '\u0332' // add combining underline + if (strike) result += '\u0336' // add combining strike + } + return result + } + + + if (typeof module === 'object' && module && typeof module.exports === 'object') { + module.exports = toUnicodeVariant + } + + + + + var msg = ""; + + chrome.storage.sync.get("enabled-notifications", enabled_notifications_result => { + var enabled_notifications = enabled_notifications_result["enabled-notifications"]; + + if (enabled_notifications) { + for (const enabled_notification of enabled_notifications) { + + for (const new_category_change of new_category_changes) { + if (new_category_change.user_just_went_online) { + if (enabled_notification.login === "ANY STREAMER" || enabled_notification.login === new_category_change.user_login) { + + if (enabled_notification.fromcat === "OFFLINE") { + + if (enabled_notification.tocat === "ANY CATEGORY" || enabled_notification.tocat === new_category_change.game_name) { + //send alert + msg = msg + "[" + toUnicodeVariant(new_category_change.user_login, 'bs') + "] just went online and has changed the category to ["+ toUnicodeVariant(new_category_change.game_name, 'bs') + "]. "; + } + } + } + } else { + + if (enabled_notification.login === "ANY STREAMER" || enabled_notification.login === new_category_change.user_login) { + + if (enabled_notification.fromcat === "ANY CATEGORY" || enabled_notification.fromcat === new_category_change.old_game_name) { + + if (enabled_notification.tocat === "ANY CATEGORY" || enabled_notification.tocat === new_category_change.game_name) { + //send alert + msg = msg + "[" + toUnicodeVariant(new_category_change.user_login, 'bs') + "] has changed the category from [" + toUnicodeVariant(new_category_change.old_game_name, 'bs') + "] to [" + toUnicodeVariant(new_category_change.game_name, 'bs') + "]. "; + } + + } + + } + } + } + + + } + } + + + if (msg !== "") { + alert(msg + "\n\nɴᴏᴛɪꜰɪᴇᴅ ʙʏ ᴛᴡɪᴛᴄʜ ᴄᴀᴛᴇɢᴏʀʏ ᴄʜᴀɴɢᴇ ɴᴏᴛɪꜰɪᴇʀ"); + } + }); +} + +async function currentTabHandlesNotification(streamers) { + var msg = "Message: "; + + for (const streamer of streamers) { + msg = msg + streamer + " went online. "; + } +} + + +function newCategoryNotification(new_category_changes) { + + chrome.tabs.query({active: true, currentWindow: true}).then(([tab]) => { + + chrome.scripting.executeScript( + { + target: {tabId: tab.id}, + //files: ['test.js'], + function: currentTabHandlesCategoryChangeNotification, + args: [new_category_changes], + }); + + + + }).catch(err => setTimeout(function(){ newCategoryNotification(new_category_changes); }, 5000)) +} + +function newNotification(streamers) { + + chrome.tabs.query({active: true, currentWindow: true}).then(([tab]) => { + chrome.scripting.executeScript( + { + target: {tabId: tab.id}, + //files: ['test.js'], + function: currentTabHandlesNotification, + args: [streamers], + }) + }).catch(err => setTimeout(function(){ newNotification(streamers); }, 3000)) +} + +function forceRefresh() { + chrome.storage.local.set({"lastTTVTokenRefresh": 0}, () => { + chrome.storage.local.set({"callUserInfos": true}, () => { + refreshToken(true); + }); + }); +} + +function disconnect() { + chrome.storage.sync.remove("ttvToken"); + chrome.storage.local.remove("ttvStreams_data"); + chrome.storage.local.remove("ttvUser_data"); + chrome.storage.local.remove("ttvUser"); +} + +chrome.runtime.onMessageExternal.addListener( + function(request, sender, sendResponse) { + if (sender.origin === "https://strikr.alwaysdata.net") { + if (request.requestType == "setTtvToken") { + if (request.ttvToken != "none") { + chrome.storage.sync.set({"ttvToken": request.ttvToken}, () => { + forceRefresh(); + }); + sendResponse({status: "success"}); + } else { + chrome.storage.sync.set({"ttvToken": "failed"}); + sendResponse({status: "token_none"}); + } + } else { + console.log("Unknown message type"); + sendResponse({status: "unknown_msg"}); + } + } + } +); + +function validateTTVToken(ttvToken, callback) { + fetch("https://id.twitch.tv/oauth2/validate", { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken + } + }).then(response => { + chrome.storage.local.set({"lastTTVTokenRefresh": Date.now()}); + response.json().then(data => { + callback(data); + }) + }, reason => { + callback(null); + }); +} + +function getLiveFollowedStreams(ttvToken, ttvUserId, clientId, callback) { + fetch("https://api.twitch.tv/helix/streams/followed?user_id=" + ttvUserId, { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken, + "Client-Id": clientId + } + }).then(response => { + response.json().then(data => { + callback(data); + }) + }, reason => { + // TODO: handle this case + console.log(reason); + }); +} + +function getUserInfos(ttvToken, clientId, callback) { + fetch("https://api.twitch.tv/helix/users", { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken, + "Client-Id": clientId + } + }).then(response => { + response.json().then(data => { + callback(data); + }) + }, reason => { + // TODO: handle this case + console.log(reason); + }); +} diff --git a/images/icon.png b/images/icon.png new file mode 100644 index 0000000..3df58da Binary files /dev/null and b/images/icon.png differ diff --git a/images/loading.svg b/images/loading.svg new file mode 100644 index 0000000..a6d4c8a --- /dev/null +++ b/images/loading.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..4c3f778 --- /dev/null +++ b/index.html @@ -0,0 +1,44 @@ + + + + + + + + +
Please wait a few seconds...
+ + \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..aa9cba8 --- /dev/null +++ b/manifest.json @@ -0,0 +1,26 @@ +{ +"update_url": "https://clients2.google.com/service/update2/crx", + + "name": "Twitch Category Change Notifier", + "description": "Know when your favorite streamers are changing categories", + "version": "1.0.1", + "manifest_version": 3, + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1uE11ize3U8cy0zr3m1R8HxA1cDMAMGadNOP2v/HRVa7n3Td1Zm8Aj6wlYodv6emLzXRGF/WhAaKQatX97Hkm8Q2HQZ+CVoyCw7X5oD3VIZo3m+K2mmB9ViPdkQXWzITxZcGuA9KdxamragF9QG62UXEPAeEuajQQvfYlK4jdjNmXhT8lXa2aAJ3/G9x2x8GcRfzwi64K9/r0gV4GEyq0E91QQou4O8mw3eqTNbZ8DjhyhHJJAiEmghlz73st2UUCyCYDZT26J2KoKFa3oVXgkGpLoC/Z0C/i76lLhP6RjKB3WniWCS0HNmn4yPNkgTg+Evv2ogC/NzqEJRz/sMYEQIDAQAB", + "background": { + "service_worker": "background.js" + },"host_permissions": [""], + "permissions": ["storage", "alarms", "scripting", "activeTab", "background"], + "action": { + "default_popup": "popup.html" + }, + "icons": { + "256": "images/icon.png" + }, + "externally_connectable": { + "matches": ["https://strikr.alwaysdata.net/*"] + }, + "web_accessible_resources": [{ + "resources": ["test.js"], + "matches": [""] + }] +} \ No newline at end of file diff --git a/popup.html b/popup.html new file mode 100644 index 0000000..748b0f5 --- /dev/null +++ b/popup.html @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + +
+ +
TTV Category Change Notifier
+ + +
+
+

+

Don't like the current game a streamer is playing?

Waiting for a streamer to finally start playing something?

Missed another watch party because it was unannounced?

+

Login with your Twitch account and create alerts for your individual use case.

+
+ + I am very grateful for PayPal donations, even smol ones. -ttv/Strikr + +
+
+ +
+ +
+ +
+
+
+
+ + \ No newline at end of file diff --git a/scripts/j.js b/scripts/j.js new file mode 100644 index 0000000..200b54e --- /dev/null +++ b/scripts/j.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 { + disconnect(); + }); + }; + + chrome.storage.sync.get("notify-all-streams", notify_result => { + this.document.getElementById("notify-all-streams-checkbox").checked = notify_result["notify-all-streams"]; + }); + this.document.getElementById("notify-all-streams-checkbox").onchange = function(me) { + chrome.storage.sync.set({"notify-all-streams": me.target.checked}); + }; + + this.document.getElementById("searchbox").addEventListener("input", val => { + chrome.storage.local.get("currentTab", currentTab_result => { + switch(currentTab_result.currentTab) { + case "followed-streams-button": + chrome.storage.local.get("ttvStreams_data", ttvStreams_data_result => { + let ttvStreams_data = ttvStreams_data_result.ttvStreams_data; + + let newStreamData = ttvStreams_data.filter(element => { + return element.user_name.toLowerCase().includes(this.document.getElementById("searchbox").value.toLowerCase()); + }) + + populateStreams(newStreamData); + }); + break; + case "streams-notifications-button": + chrome.storage.local.get("followedChannels", followedChannels_result => { + let followedChannels = followedChannels_result.followedChannels; + + let newNotifsData = followedChannels.filter(element => { + return element.name.toLowerCase().includes(this.document.getElementById("searchbox").value.toLowerCase()); + }) + + addNotifChannels(newNotifsData); + }); + break; + } + }); + }); + + populatePage(); +}); + +function disconnect() { + chrome.storage.sync.remove("ttvToken"); + chrome.storage.local.remove("ttvStreams_data", () => { + chrome.storage.local.remove("ttvUser_data", () => { + populatePage(); + }); + }); + chrome.storage.local.remove("ttvUser"); +} + +function populatePage() { + isDisconnected(result => { + if (!result) { + this.document.getElementById("login-twitch").style["display"] = "none"; + this.document.getElementById("user-infos-top").style["display"] = "inline-block"; + this.document.getElementById("disconnected-tip").style["display"] = "none"; + this.document.getElementById("disconnected-stream-tip").style["display"] = "none"; + this.document.getElementById("searchbox").style["display"] = "inline-block"; + this.document.getElementById("informations").style["display"] = "block"; + this.document.getElementById("bottom-bar").style["display"] = "block"; + + + chrome.storage.local.get("ttvUser_data", ttvUser_data_result => { + let ttvUser_data = ttvUser_data_result.ttvUser_data; + + // Populating username + user picture + this.document.getElementById("username-top").innerText = ttvUser_data.display_name; + this.document.getElementById("user-pic-top").src = ttvUser_data.profile_image_url; + }); + + chrome.storage.local.get("ttvStreams_data", ttvStreams_data_result => { + let ttvStreams_data = ttvStreams_data_result.ttvStreams_data; + + }); + } else { + this.document.getElementById("login-twitch").style["display"] = "inline-block"; + this.document.getElementById("user-infos-top").style["display"] = "none"; + this.document.getElementById("disconnected-tip").style["display"] = "inline-block"; + this.document.getElementById("disconnected-stream-tip").style["display"] = "block"; + this.document.getElementById("searchbox").style["display"] = "none"; + this.document.getElementById("informations").style["display"] = "none"; + this.document.getElementById("bottom-bar").style["display"] = "none"; + } + }) + + setTimeout(populatePage, 10000); +} + +function populateStreams(stream_data) { + this.document.getElementById("streams").innerHTML = ""; + stream_data.forEach(element => { + this.document.getElementById("streams").innerHTML += newDiv(element); + }); +} + +function isDisconnected(callback) { + chrome.storage.local.get("disconnected", disconnected_result => { + if (disconnected_result.disconnected != null) { + callback(true); + return; + } + chrome.storage.sync.get("ttvToken", ttvToken_result => { + if (ttvToken_result.ttvToken == null || ttvToken_result.ttvToken == "failed" || ttvToken_result.ttvToken == "none") { + callback(true); + return; + } + callback(false); + }); + }); +} + +function newDiv(stream_info){ + var newStream = + '
' + + '' + + '
' + sanitizeString(stream_info.user_name) + '
' + + '
' + + '
' + sanitizeString(stream_info.title) + '
' + + '
' + sanitizeString(stream_info.game_name) + '
' + + '
' + new Intl.NumberFormat('fr-FR').format(stream_info.viewer_count) + '
' + + '
' + + '
' + getStreamUptime(stream_info.started_at) + '
' + + '
' + stream_info.language + '
' + (stream_info.is_mature ? + '
18+
':'') + + '
' + + '
' + + '
'; + + return newStream; +} + +function sanitizeString(str){ + str = str.replace(/[^a-z0-9áéíóúñü \.,_-]/gim,""); + return str.trim(); +} + +function getStreamUptime(startTime) { + let start = new Date(startTime); + let now = new Date(); + let hours = (((now - start) / 1000) / 60) / 60; + let minutes = (((now - start) / 1000) / 60) % 60; + + return parseInt(hours) + ":" + parseInt(minutes).toString().padStart(2, '0'); +} + +function getFollowedChannels(ttvToken, ttvUserId, clientId, callback, page) { + fetch("https://api.twitch.tv/helix/users/follows?first=100&from_id=" + ttvUserId + (page != null ? "&after=" + page : ""), { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken, + "Client-Id": clientId + } + }).then(response => { + response.json().then(data => { + if (data.pagination != null && Object.keys(data.pagination).length !== 0 && data.total > 100) { + let totalData = []; + Array.prototype.push.apply(totalData, data.data); + getFollowedChannels(ttvToken, ttvUserId, clientId, data => { + Array.prototype.push.apply(totalData, data); + callback(totalData); + }, data.pagination.cursor); + } else { + callback(data.data); + } + }) + }, reason => { + // TODO: handle this case + console.log(reason); + }); +} + +function getAllTwitchCategories(ttvToken, ttvUserId, clientId, callback, page) { + fetch("https://api.twitch.tv/helix/games/top?first=100" + (page != null ? "&after=" + page : ""), { + method: "GET", + headers: { + "Authorization": "Bearer " + ttvToken, + "Client-Id": clientId + } + }).then(response => { + response.json().then(data => { + if (data.pagination != null && Object.keys(data.pagination).length !== 0) { + let totalData = []; + Array.prototype.push.apply(totalData, data.data); + getAllTwitchCategories(ttvToken, ttvUserId, clientId, data => { + Array.prototype.push.apply(totalData, data); + callback(totalData); + }, data.pagination.cursor); + } else { + callback(data.data); + } + }) + }, reason => { + // TODO: handle this case + console.log(reason); + }); +} + +/** + * + * @param {*} data Data to normalize + * @returns Returns alphabetically sorted normalized data array + */ +function normalizeFollowedChannels(data) { + var newData = []; + + data.forEach(element => { + newData.push({ + "id": element.to_id, + "name": element.to_name, + "login": element.to_login, + "date": element.followed_at + }); + }); + + newData.sort(function(a, b) { + return a.name.localeCompare(b.name); + }); + + return newData; +} \ No newline at end of file diff --git a/scripts/tab_notifications.js b/scripts/tab_notifications.js new file mode 100644 index 0000000..9e82b75 --- /dev/null +++ b/scripts/tab_notifications.js @@ -0,0 +1,317 @@ +function openNotificationsTab() { + populateNotifications(); +} + +function populateNotifications() { + isDisconnected(result => { + if (!result) { + chrome.storage.local.get("lastFollowedChannelsRefresh", lastFollowedChannelsRefresh_result => { + if (lastFollowedChannelsRefresh_result.lastFollowedChannelsRefresh < (Date.now() - 1800000)) { + chrome.storage.sync.get("ttvToken", ttvToken_result => { + chrome.storage.local.get("ttvUser", ttvUser_result => { + getFollowedChannels( + ttvToken_result.ttvToken, + ttvUser_result.ttvUser.user_id, + ttvUser_result.ttvUser.client_id, + data => { + chrome.storage.local.set({"lastFollowedChannelsRefresh": Date.now()}); + chrome.storage.local.set({"followedChannels": normalizeFollowedChannels(data)}, () => { + chrome.storage.local.get("followedChannels", followedChannels_result => { + chrome.storage.local.get("allTwitchCategories", allTwitchCategories_result => { + if (!allTwitchCategories_result.allTwitchCategorie || allTwitchCategories_result.allTwitchCategories.length < 50) { + getAllTwitchCategories( + ttvToken_result.ttvToken, ttvUser_result.ttvUser.user_id, + ttvUser_result.ttvUser.client_id, data => { + var twitchCategoriesMap = data.map(elm => elm.name); + chrome.storage.local.set({"allTwitchCategories": (twitchCategoriesMap)}, () => { + chrome.storage.local.get("allTwitchCategories", allTwitchCategories_result => { + addNotifChannels(followedChannels_result.followedChannels, allTwitchCategories_result.allTwitchCategories); + + }); + }); + }, + null); + } else { + addNotifChannels(followedChannels_result.followedChannels, allTwitchCategories_result.allTwitchCategories); + } + }); + }); + }); + }, + null); + }); + }); + } else { + chrome.storage.local.get("followedChannels", followedChannels_result => { + chrome.storage.local.get("allTwitchCategories", allTwitchCategories_result => { + addNotifChannels(followedChannels_result.followedChannels, allTwitchCategories_result.allTwitchCategories); + + }); + }); + } + }); + } else { + + } + }) +} + +function updateAllAlerts() { + $(".loading").show(); + + this.document.getElementsByClassName("all-alerts")[0].innerHTML = ""; + + chrome.storage.sync.get("enabled-notifications", notifieds_result => { + var enabled_notifications = notifieds_result["enabled-notifications"]; + if (enabled_notifications == null || enabled_notifications === false) + enabled_notifications = []; + + + var q_enabled_notifications = enabled_notifications.reduce((unique, o) => { + if(!unique.some(obj => obj.type === o.type && obj.login === o.login && obj.fromcat === o.fromcat && obj.tocat === o.tocat)) { + unique.push(o); + } + return unique; + },[]); + + + var html = ""; + q_enabled_notifications.forEach(function (element, i) { + var text = "I receive an " + (element.type).toString() + " when changes category from " + (element.fromcat).toString() + " to " + (element.tocat).toString()+""; + var single_alert = "
"+text+"
" + html = html + single_alert; + }); + + this.document.getElementsByClassName("all-alerts")[0].innerHTML = html; + + $(".remove-alert").click(function(){ + var type = $(this).parents(".single-alert").children('.type')[0].textContent; + var login = $(this).parents(".single-alert").children('.login')[0].textContent; + var fromcat = $(this).parents(".single-alert").children('.fromcat')[0].textContent; + var tocat = $(this).parents(".single-alert").children('.tocat')[0].textContent; + + removeFromEnabledNotifications(type,login,fromcat,tocat); + }) + + $(".loading").hide(); + }); +} + +function addNotifChannels(followedChannels, allTwitchCategories) { + chrome.storage.sync.get("notified-streams", notifieds_result => { + + updateAllAlerts(); + + this.document.getElementById("alertcreator").innerHTML = ""; + this.document.getElementById("alertcreator").innerHTML = newStreamElement(notifieds_result["notified-streams"], followedChannels, allTwitchCategories); + + tail.select("select", { + search: true, + descriptions: true, + hideSelected: true, + hideDisabled: true, + multiple: false, + }); + + + document.querySelectorAll('.notification').forEach(function(el) { + $(".add-new-alert").click(function(){ + var selects = el.getElementsByTagName('select'); + + var select_type; + var select_login; + var select_fromcat; + var select_tocat; + + + for (var i = 0; i < selects.length; i++) { + var select = selects.item(i); + + if (i === 0) { + select_type = $(select).val(); + } + if (i === 1) { + + select_login = $(select).val(); + } + if (i === 2) { + select_fromcat = $(select).val(); + } + if (i === 3) { + select_tocat = $(select).val(); + } + } + + + addToEnabledNotifications(select_type,select_login,select_fromcat,select_tocat); + }); + }); + }) +} + +function addToEnabledNotifications(type,login,fromcat,tocat) { + + + chrome.storage.sync.get("enabled-notifications", notifieds_result => { + var enabled_notifications = notifieds_result["enabled-notifications"]; + if (enabled_notifications == null || enabled_notifications === false ) + enabled_notifications = []; + + enabled_notifications.push({ + type: type, + login: login, + fromcat: fromcat, + tocat: tocat, + }); + + + var q_enabled_notifications = enabled_notifications.reduce((unique, o) => { + if(!unique.some(obj => obj.type === o.type && obj.login === o.login && obj.fromcat === o.fromcat && obj.tocat === o.tocat)) { + unique.push(o); + } + return unique; + },[]); + + + chrome.storage.sync.set({"enabled-notifications": q_enabled_notifications}); + + chrome.storage.sync.get("enabled-notifications", notifieds_result => { + var enabled_notifications = notifieds_result["enabled-notifications"]; + + updateAllAlerts(); + alert("Done!"); + }); + }); +} + +function removeFromEnabledNotifications(type,login,fromcat,tocat) { + + chrome.storage.sync.get("enabled-notifications", notifieds_result => { + var enabled_notifications = notifieds_result["enabled-notifications"]; + if (enabled_notifications == null || enabled_notifications === false) + enabled_notifications = []; + + + var q_enabled_notifications = enabled_notifications.reduce((unique, o) => { + if(!unique.some(obj => obj.type === o.type && obj.login === o.login && obj.fromcat === o.fromcat && obj.tocat === o.tocat)) { + unique.push(o); + } + return unique; + },[]); + + + + var index = -1; + q_enabled_notifications.forEach(function (element, i) { + console.log(element); + console.log(type+login+fromcat+tocat); + + if (element.type === type && element.login === login && element.fromcat === fromcat && element.tocat === tocat) { + index = i; + } + }); + if (index !== -1) { + var removed = q_enabled_notifications.splice(index, 1); + + chrome.storage.sync.set({"enabled-notifications": q_enabled_notifications}); + + chrome.storage.sync.get("enabled-notifications", notifieds_result => { + var enabled_notifications = notifieds_result["enabled-notifications"]; + updateAllAlerts(); + alert("Done!"); + }); + } + }); +} + + + + +function addToNotified(login) { + chrome.storage.sync.get("notified-streams", notifieds_result => { + var notifieds = notifieds_result["notified-streams"]; + if (notifieds == null) + notifieds = []; + notifieds.push(login); + chrome.storage.sync.set({"notified-streams": notifieds}); + }); +} + +function removeFromNotified(login) { + chrome.storage.sync.get("notified-streams", notifieds_result => { + var notifieds = notifieds_result["notified-streams"]; + if (notifieds == null) + notifieds = []; + if (notifieds.includes(login)) { + notifieds.splice(notifieds.indexOf(login), 1); + chrome.storage.sync.set({"notified-streams": notifieds}); + } + }); +} + +function newStreamElement(notified_streams, followedChannels, allTwitchCategories){ + + var dropdowntwitchCategories = document.createElement("select"); + let any = document.createElement("option"); + any.text = "ANY CATEGORY"; + any.value = "ANY CATEGORY"; + dropdowntwitchCategories.add(any); + let off = document.createElement("option"); + off.text = "OFFLINE"; + off.value = "OFFLINE"; + dropdowntwitchCategories.add(off); + allTwitchCategories.forEach(element => { + let optEle = document.createElement("option"); + optEle.text = element; + optEle.value = element; + dropdowntwitchCategories.add(optEle); + }); + + + + var dropdownfollowedChannels = document.createElement("select"); + let ansy = document.createElement("option"); + ansy.text = "ANY STREAMER"; + ansy.value = "ANY STREAMER"; + dropdownfollowedChannels.add(ansy); + followedChannels.forEach(element => { + let optEle = document.createElement("option"); + optEle.text = element.login; + optEle.value = element.login; + dropdownfollowedChannels.add(optEle); + }); + + + var dropdownNotificationTypes = document.createElement("select"); + var notificationTypes = [{label: "ALERT", value: "alert"},]; + notificationTypes.forEach(element => { + let optEle = document.createElement("option"); + optEle.text = element.label; + optEle.value = element.value; + dropdownNotificationTypes.add(optEle); + }); + + + var newStream = + '
' + + '
' + + '
I receive an '+dropdownNotificationTypes.outerHTML+' when '+dropdownfollowedChannels.outerHTML+' changes category from '+dropdowntwitchCategories.outerHTML+' to '+dropdowntwitchCategories.outerHTML+'' + '
' + + ' ' + + '
' + + '
' + return newStream; +} + +function getFollowedTime(time) { + let date = new Date(time); + return date.toLocaleString("en-US", {month: "long", day: "numeric", year: "numeric"}) + " · " + date.toLocaleTimeString("en-US", {hour12: false}).substring(0, 5); +} + +function hasNotificationsEnabled(notified_streams, login) { + if (notified_streams == null) { + return false; + } + return notified_streams.includes(login); +} \ No newline at end of file diff --git a/scripts/tabs.js b/scripts/tabs.js new file mode 100644 index 0000000..1a6220e --- /dev/null +++ b/scripts/tabs.js @@ -0,0 +1,39 @@ +window.addEventListener("load", function() { + Array.from(document.getElementById("bottom-bar").getElementsByClassName("tab-button")).forEach(element => { + element.onclick = function(click) { + switchTab(element.id); + }; + }); + + + switchTab("streams-notifications-button"); +}); + +function switchTab(tabName) { + removeAllSelected(); + hideAllTabs(); + + + switch(tabName) { + case "streams-notifications-button": + chrome.storage.local.set({"currentTab": tabName}); + this.document.getElementById("streams-notifications-button").classList.add("selected"); + this.document.getElementById("notifications-page").style["display"] = "block"; + openNotificationsTab(); + break; + } +} + +function removeAllSelected() { + var selected = Array.from(document.getElementById("bottom-bar").getElementsByClassName("selected")); + selected.forEach(element => { + element.classList.remove("selected"); + }); +} + +function hideAllTabs() { + var selected = Array.from(document.getElementsByClassName("tab")); + selected.forEach(element => { + element.style["display"] = "none"; + }); +} \ No newline at end of file diff --git a/scripts/tail.js b/scripts/tail.js new file mode 100644 index 0000000..3da4eae --- /dev/null +++ b/scripts/tail.js @@ -0,0 +1,13 @@ +/* + | tail.select - The vanilla solution to make your HTML select fields AWESOME! + | @file ./js/tail.select.js + | @author wolffe + | @author SamBrishes + | @version 0.5.22 + | + | @website https://github.com/wolffe/tail.select.js + | @license X11 / MIT License + | @copyright Copyright © 2020 - 2021 wolffe + | @copyright Copyright © 2014 - 2019 SamBrishes, pytesNET + */ +!function(root,factory){"function"==typeof define&&define.amd?define((function(){return factory(root)})):"object"==typeof module&&module.exports?module.exports=factory(root):(void 0===root.tail&&(root.tail={}),root.tail.select=factory(root),"undefined"!=typeof jQuery&&(jQuery.fn.tailselect=function(o){var r=[],i;return this.each((function(){!1!==(i=tail.select(this,o))&&r.push(i)})),1===r.length?r[0]:0!==r.length&&r}),"undefined"!=typeof MooTools&&Element.implement({tailselect:function(o){return new tail.select(this,o)}}))}(window,(function(root){"use strict";var w=root,d=root.document;function cHAS(el,name){return!!(el&&"classList"in el)&&el.classList.contains(name)}function cADD(el,name){return el&&"classList"in el?el.classList.add(name):void 0}function cREM(el,name){return el&&"classList"in el?el.classList.remove(name):void 0}function trigger(el,event,opt){var ev;if(CustomEvent&&CustomEvent.name)var ev=new CustomEvent(event,opt);else(ev=d.createEvent("CustomEvent")).initCustomEvent(event,!!opt.bubbles,!!opt.cancelable,opt.detail);return el.dispatchEvent(ev)}function clone(obj,rep){if("function"==typeof Object.assign)return Object.assign({},obj,rep||{});var clone=Object.constructor();for(var key in obj)clone[key]=key in rep?rep[key]:obj[key];return clone}function create(tag,classes){var r=d.createElement(tag);return r.className=classes&&classes.join?classes.join(" "):classes||"",r}var select=function(el,config){if((el="string"==typeof el?d.querySelectorAll(el):el)instanceof NodeList||el instanceof HTMLCollection||el instanceof Array){for(var _r=[],l=el.length,i=0;i=0?config.multiLimit:1/0,this.e=el,this.id=++select.count,this.con=clone(select.defaults,config),this.events={},select.inst["tail-"+this.id]=this,this.init().bind()},options;return select.count=0,select.inst={},select.defaults={animate:!0,classNames:null,csvOutput:!1,csvSeparator:",",descriptions:!1,deselect:!1,disabled:!1,height:350,hideDisabled:!1,hideSelected:!1,items:{},locale:"en",linguisticRules:{"е":"ё",a:"ä",o:"ö",u:"ü",ss:"ß"},multiple:!1,multiLimit:1/0,multiPinSelected:!1,multiContainer:!1,multiShowCount:!0,multiShowLimit:!1,multiSelectAll:!1,multiSelectGroup:!0,openAbove:null,placeholder:null,search:!1,searchConfig:["text","value"],searchFocus:!0,searchMarked:!0,searchMinLength:1,searchDisabled:!0,sortItems:!1,sortGroups:!1,sourceBind:!1,sourceHide:!0,startOpen:!1,stayOpen:!1,width:null,cbComplete:void 0,cbEmpty:void 0,cbLoopItem:void 0,cbLoopGroup:void 0},select.strings={en:{all:"All",none:"None",empty:"No Options available",emptySearch:"No Options found",limit:"You can't select more Options",placeholder:"Select an Option...",placeholderMulti:"Select up to :limit Options...",search:"Type in to search...",disabled:"This Field is disabled"},modify:function(locale,id,string){if(!(locale in this))return!1;if(id instanceof Object)for(var key in id)this.modify(locale,key,id[key]);else this[locale][id]="string"==typeof string?string:this[locale][id];return!0},register:function(locale,object){return"string"==typeof locale&&object instanceof Object&&(this[locale]=object,!0)}},select.prototype={_e:function(string,replace,def){if(!(string in this.__))return def||string;var string;if("function"==typeof(string=this.__[string])&&(string=string.call(this,replace)),"object"==typeof replace)for(var key in replace)string=string.replace(key,replace[key]);return string},init:function(){var self=this,classes=["tail-select"],con=this.con,regexp=/^[0-9.]+(?:cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|\%)$/i,c=!0===con.classNames?this.e.className:con.classNames;classes.push(c&&c.push?c.join(" "):c&&c.split?c:"no-classes"),con.hideSelected&&classes.push("hide-selected"),con.hideDisabled&&classes.push("hide-disabled"),0==con.multiLimit&&classes.push("disabled"),con.multiple&&classes.push("multiple"),con.deselect&&classes.push("deselect"),con.disabled&&classes.push("disabled"),this.__=clone(select.strings.en,select.strings[con.locale]||{}),this._init=!0,this._query=!1,this.select=create("DIV",classes),this.label=create("DIV","select-label"),this.dropdown=create("DIV","select-dropdown"),this.search=create("DIV","dropdown-search"),this.csvInput=create("INPUT","select-search"),null!==this.e.getAttribute("tabindex")?this.select.setAttribute("tabindex",this.e.getAttribute("tabindex")):this.select.setAttribute("tabindex",0),con.width&®exp.test(con.width)?this.select.style.width=con.width:con.width&&!isNaN(parseFloat(con.width,10))&&(this.select.style.width=con.width+"px"),this.label.addEventListener("click",(function(event){self.toggle.call(self,self.con.animate)})),this.select.appendChild(this.label),isNaN(parseInt(con.height,10))||(this.dropdown.style.maxHeight=parseInt(con.height,10)+"px"),con.search&&(this.search.innerHTML='',this.search.children[0].placeholder=this._e("search"),this.search.children[0].addEventListener("input",(function(event){self.query.call(self,this.value.length>con.searchMinLength?this.value:void 0)})),this.dropdown.appendChild(this.search)),this.select.appendChild(this.dropdown),this.csvInput.type="hidden",con.csvOutput&&(this.csvInput.name=this.e.name,this.e.removeAttribute("name"),this.select.appendChild(this.csvInput)),con.multiple&&con.multiContainer&&(d.querySelector(con.multiContainer)?(this.container=d.querySelector(con.multiContainer),this.container.className+=" tail-select-container"):!0===con.multiContainer&&(this.container=this.label,this.container.className+=" tail-select-container")),this.options=new options(this.e,this);for(var l=this.e.options.length,i=0;i0&&"UL"==temp.tagName&&temp.children[40==key?0:temp.children.length-1])&&(!cHAS(opt,"dropdown-option")||cHAS(opt,"disabled")););if(opt||40!=key?opt||38!=key||(opt=(tmp=self.dropdown.querySelectorAll(".dropdown-option:not(.disabled)"))[tmp.length-1]):opt=self.dropdown.querySelector(".dropdown-option:not(.disabled)"),opt&&(inner=self.dropdown.querySelector(".dropdown-inner"))){var pos=function(el){for(var _r={top:el.offsetTop,height:el.offsetHeight};(el=el.parentElement)!=inner;)_r.top+=el.offsetTop;return _r}(opt);cADD(opt,"hover"),inner.scrollTop=Math.max(0,pos.top-2*pos.height)}return!0})),d.addEventListener("click",(function(ev){if(!cHAS(self.select,"active")||cHAS(self.select,"idle"))return!1;if(!0===self.con.stayOpen)return!1;for(var targets=[self.e,self.select,self.container],l=targets.length,i=0;i=0)||(u.splice(u.indexOf(item),1),!1)}));self.options.walk.call(self.options,"unselect",u),self.options.walk.call(self.options,"select",s)}})),!0)},callback:function(item,state,_force){var rkey,rgrp,rsel="[data-key='"+item.key.replace(/('|\\)/g,"\\$1")+"'][data-group='"+item.group.replace(/('|\\)/g,"\\$1")+"']";if("rebuild"==state)return this.query();var element=this.dropdown.querySelector(rsel);return element&&["select","disable"].indexOf(state)>=0?cADD(element,"select"==state?"selected":"disabled"):element&&["unselect","enable"].indexOf(state)>=0&&cREM(element,"unselect"==state?"selected":"disabled"),this.update(item),!0===_force||this.trigger("change",item,state)},trigger:function(event){if(this._init)return!1;var obj={bubbles:!1,cancelable:!0,detail:{args:arguments,self:this}};"change"==event&&arguments[2]&&arguments[2].indexOf("select")>=0&&(trigger(this.e,"input",obj),trigger(this.e,"change",obj)),trigger(this.select,"tail::"+event,obj);var args=[],pass;return Array.prototype.map.call(arguments,(function(item,i){i>0&&args.push(item)})),(this.events[event]||[]).forEach((function(item){(pass=[].concat(args)).push(item.args||null),(item.cb||function(){}).apply(obj.detail.self,pass)})),!0},calc:function(){var clone=this.dropdown.cloneNode(!0),height=this.con.height,search=0,inner=this.dropdown.querySelector(".dropdown-inner");(clone=this.dropdown.cloneNode(!0)).style.cssText="height:auto;min-height:auto;max-height:none;opacity:0;display:block;visibility:hidden;",clone.style.maxHeight=this.con.height+"px",clone.className+=" cloned",this.dropdown.parentElement.appendChild(clone),height=height>clone.clientHeight?clone.clientHeight:height,this.con.search&&(search=clone.querySelector(".dropdown-search").clientHeight),this.dropdown.parentElement.removeChild(clone);var pos=this.select.getBoundingClientRect(),bottom=w.innerHeight-(pos.top+pos.height),view=height+search>bottom&&pos.top>bottom;return!0===this.con.openAbove||!1!==this.con.openAbove&&view?(view=!0,height=Math.min(height,pos.top-10),cADD(this.select,"open-top")):(view=!1,height=Math.min(height,bottom-10),cREM(this.select,"open-top")),inner&&(this.dropdown.style.maxHeight=height+"px",inner.style.maxHeight=height-search+"px"),this},query:function(search,conf){var item,tp,ul,li,a1,a2,self=this,con=this.con,g="getAttribute",root=create("DIV","dropdown-inner"),func=search?"finder":"walker",args=search?[search,conf]:[con.sortItems,con.sortGroups];for(this._query="string"==typeof search&&search;item=this.options[func].apply(this.options,args);){if(!ul||ul&&ul[g]("data-group")!==item.group){if(!((tp=(con.cbLoopGroup||this.cbGroup).call(this,item.group,search,root))instanceof Element))break;(ul=tp).setAttribute("data-group",item.group),root.appendChild(ul)}if(null!==(li=(con.cbLoopItem||this.cbItem).call(this,item,ul,search,root))){if(!1===li)break;li.setAttribute("data-key",item.key),li.setAttribute("data-group",item.group),li.addEventListener("click",(function(event){if(!this.hasAttribute("data-key"))return!1;var key=this[g]("data-key"),group=this[g]("data-group")||"#";self.options.toggle.call(self.options,key,group)&&(!1!==self.con.stayOpen||self.con.multiple||self.close.call(self,self.con.animate))})),ul.appendChild(li)}}var count=root.querySelectorAll("*[data-key]").length;0==count&&(this.con.cbEmpty||function(element){var li=create("SPAN","dropdown-empty");li.innerText=this._e("empty"),element.appendChild(li)}).call(this,root,search),count>0&&con.multiple&&con.multiLimit==1/0&&con.multiSelectAll&&(a1=create("BUTTON","tail-all"),a2=create("BUTTON","tail-none"),a1.innerText=this._e("all"),a1.addEventListener("click",(function(event){event.preventDefault();var options=self.dropdown.querySelectorAll(".dropdown-inner .dropdown-option");self.options.walk.call(self.options,"select",options)})),a2.innerText=this._e("none"),a2.addEventListener("click",(function(event){event.preventDefault();var options=self.dropdown.querySelectorAll(".dropdown-inner .dropdown-option");self.options.walk.call(self.options,"unselect",options)})),(li=create("SPAN","dropdown-action")).appendChild(a1),li.appendChild(a2),root.insertBefore(li,root.children[0]));var data=this.dropdown.querySelector(".dropdown-inner");return this.dropdown[(data?"replace":"append")+"Child"](root,data),cHAS(this.select,"active")&&this.calc(),this.updateCSV().updateLabel()},cbGroup:function(group,search){var ul=create("UL","dropdown-optgroup"),self=this,a1,a2;return"#"==group?ul:(ul.innerHTML='
  • '+group+"
  • ",this.con.multiple&&this.con.multiLimit==1/0&&this.con.multiSelectAll&&(a1=create("BUTTON","tail-none"),a2=create("BUTTON","tail-all"),a1.innerText=this._e("none"),a1.addEventListener("click",(function(event){event.preventDefault();var grp=this.parentElement.parentElement.getAttribute("data-group");self.options.all.call(self.options,"unselect",grp)})),a2.innerText=this._e("all"),a2.addEventListener("click",(function(event){event.preventDefault();var grp=this.parentElement.parentElement.getAttribute("data-group");self.options.all.call(self.options,"select",grp)})),ul.children[0].appendChild(a1),ul.children[0].appendChild(a2)),ul)},cbItem:function(item,optgroup,search){var li=create("LI","dropdown-option"+(item.selected?" selected":"")+(item.disabled?" disabled":""));return li.title=item.option.title,search&&search.length>0&&this.con.searchMarked?(search=this.options.applyLinguisticRules(search),li.innerHTML=item.value.replace(new RegExp("("+search+")","i"),"$1")):li.innerText=item.value,this.con.descriptions&&item.description&&(li.innerHTML+=''+item.description+""),li},update:function(item){return this.updateLabel().updateContainer(item).updatePin(item).updateCSV(item)},updateLabel:function(label){if(this.container==this.label&&this.options.selected.length>0)return this.label.querySelector(".label-inner")&&this.label.removeChild(this.label.querySelector(".label-inner")),this.label.querySelector(".label-count")&&this.label.removeChild(this.label.querySelector(".label-count")),this;var c=this.con,len=this.options.selected.length,limit,selected_class;("string"!=typeof label&&(label=c.disabled?"disabled":0==this.dropdown.querySelectorAll("*[data-key]").length?"empty"+(cHAS(this.select,"in-search")?"Search":""):c.multiLimit<=len?"limit":!c.multiple&&this.options.selected.length>0?this.options.selected[0].innerText:"string"==typeof c.placeholder?c.placeholder:"placeholder"+(c.multiple&&c.multiLimit<1/0?"Multi":"")),label=''+(label=this._e(label,{":limit":c.multiLimit},label))+"",limit=c.multiShowLimit&&c.multiLimit<1/0,c.multiple&&c.multiShowCount)&&(label=(label=':c'+label).replace(":c",len+(limit?" / "+c.multiLimit:"")));return this.label.innerHTML=label,this},updateContainer:function(item){if(!this.container||!this.con.multiContainer)return this;var s="[data-group='"+item.group+"'][data-key='"+item.key+"']";if(this.container.querySelector(s))return item.selected||this.container.removeChild(this.container.querySelector(s)),this;if(item.selected){var self=this,hndl=create("DIV","select-handle");hndl.innerText=item.value,hndl.setAttribute("data-key",item.key),hndl.setAttribute("data-group",item.group),hndl.addEventListener("click",(function(event){event.preventDefault(),event.stopPropagation();var key=this.getAttribute("data-key"),grp=this.getAttribute("data-group");self.options.unselect.call(self.options,key,grp)})),this.container.appendChild(hndl)}return this},updatePin:function(item){var inner=this.dropdown.querySelector(".dropdown-inner ul"),option="li[data-key='"+item.key+"'][data-group='"+item.group+"']";if(!this.con.multiPinSelected||!inner||!1!==this._query)return this;if(option=this.dropdown.querySelector(option),item.selected)inner.insertBefore(option,inner.children[0]);else{for(var grp=this.dropdown.querySelector("ul[data-group='"+item.group+"']"),prev=this.options[item.index-1],found=!1;prev&&prev.group==item.group&&!(found=grp.querySelector("li[data-key='"+prev.key+"']"));)prev=this.options[prev.index-1];found&&found.nextElementSibling?grp.insertBefore(option,found.nextElementSibling):grp.appendChild(option)}return this},updateCSV:function(item){if(!this.csvInput||!this.con.csvOutput)return this;for(var selected=[],l=this.options.selected.length,i=0;i=m)return final.call(self);e.height=(h+50>m?m:h+50)+"px",setTimeout(animate,20)}()):(e.cssText="height:"+e.maxHeight+";display:block;overflow:hidden;",final.call(this)),this},close:function(animate){if(!cHAS(this.select,"active")||cHAS(this.select,"idle"))return!1;var final=function(){cREM(this.select,"active"),cREM(this.select,"idle"),this.dropdown.removeAttribute("style"),this.dropdown.querySelector(".dropdown-inner").removeAttribute("style"),this.trigger.call(this,"close")},self=this,e=this.dropdown;return!1!==animate?(cADD(this.select,"idle"),this.dropdown.style.overflow="hidden",function animate(){if(parseInt(e.offsetHeight,10)-50<=0)return final.call(self);e.style.height=parseInt(e.offsetHeight,10)-50+"px",setTimeout(animate,20)}()):final.call(this),this},toggle:function(animate){return cHAS(this.select,"active")?this.close(animate):cHAS(this.select,"idle")?this:this.open(animate)},remove:function(){if(this.e.removeAttribute("data-tail-select"),this.e.hasAttribute("data-select-hidden")&&("0"==this.e.getAttribute("data-select-hidden")&&this.e.style.removeProperty("display"),this.e.removeAttribute("data-select-hidden")),Array.prototype.map.call(this.e.querySelectorAll("[data-select-option='add']"),(function(item){item.parentElement.removeChild(item)})),Array.prototype.map.call(this.e.querySelectorAll("[data-select-optgroup='add']"),(function(item){item.parentElement.removeChild(item)})),this.e.name=this.csvInput.hasAttribute("name")?this.csvInput.name:this.e.name,this.select.parentElement&&this.select.parentElement.removeChild(this.select),this.container)for(var handles=this.container.querySelectorAll(".select-handle"),l=handles.length,i=0;i=con.multiLimit&&(opt.selected=!1),!opt.selected||!con.deselect||opt.hasAttribute("selected")&&0!=con.multiLimit||(opt.selected=!1,opt.parentElement.selectedIndex=-1),opt.hasAttribute("data-description")){var span=create("SPAN");span.innerHTML=opt.getAttribute("data-description"),opt.setAttribute("data-description",span.innerHTML)}return this.items[grp][id]={key:key,value:opt.text,description:opt.getAttribute("data-description")||null,group:grp,option:opt,optgroup:"#"!=grp?this.groups[grp]:void 0,selected:opt.selected,disabled:opt.disabled,hidden:opt.hidden||!1},this.length++,opt.selected&&this.select(this.items[grp][id]),opt.disabled&&this.disable(this.items[grp][id]),!rebuild||this.self.callback(this.items[grp][key],"rebuild")},add:function(key,value,group,selected,disabled,description,rebuild){if(key instanceof Object){for(var k in key)this.add(key[k].key||k,key[k].value,key[k].group,key[k].selected,key[k].disabled,key[k].description,!1);return this.self.query()}if(this.get(key,group))return!1;if("#"!==(group="string"==typeof group?group:"#")&&!(group in this.groups)){var optgroup=create("OPTGROUP");optgroup.label=group,optgroup.setAttribute("data-select-optgroup","add"),this.element.appendChild(optgroup),this.items[group]={},this.groups[group]=optgroup}this.self.con.multiple&&this.selected.length>=this.self.con.multiLimit&&(selected=!1),disabled=!!disabled;var option=d.createElement("OPTION");return option.value=key,option.selected=selected,option.disabled=disabled,option.innerText=value,option.setAttribute("data-select-option","add"),description&&description.length>0&&option.setAttribute("data-description",description),("#"==group?this.element:this.groups[group]).appendChild(option),this.set(option,rebuild)},move:function(item,group,new_group,rebuild){if(!(item=this.get(item,group)))return!1;if("#"!==new_group&&!(new_group in this.groups)){var optgroup=create("OPTGROUP");optgroup.label=new_group,this.element.appendChild(optgroup),this.items[new_group]={},this.groups[new_group]=optgroup,this.groups[new_group].appendChild(item.option)}return delete this.items[item.group][item.key],item.group=new_group,item.optgroup=this.groups[new_group]||void 0,this.items[new_group][item.key]=item,!rebuild||this.self.query()},remove:function(item,group,rebuild){if(!(item=this.get(item,group)))return!1;item.selected&&this.unselect(item),item.disabled&&this.enable(item),item.option.parentElement.removeChild(item.option);var id=/^[0-9]+$/.test(item.key)?"_"+item.key:item.key;return delete this.items[item.group][id],this.length--,0===Object.keys(this.items[item.group]).length&&(delete this.items[item.group],delete this.groups[item.group]),!rebuild||this.self.query()},is:function(state,key,group){var state=this._r(state),item=this.get(key,group);return!item||["select","unselect","disable","enable"].indexOf(state)<0?null:"disable"==state||"enable"==state?"disable"==state?item.disabled:!item.disabled:("select"==state||"unselect"==state)&&("select"==state?item.selected:!item.selected)},handle:function(state,key,group,_force){var item=this.get(key,group),state=this._r(state);if(!item||["select","unselect","disable","enable"].indexOf(state)<0)return null;if("disable"==state||"enable"==state)return item.option in this.disabled||"disable"!=state?item.option in this.disabled&&"enable"==state&&this.disabled.splice(this.disabled.indexOf(item.option),1):this.disabled.push(item.option),item.disabled="disable"==state,item.option.disabled="disable"==state,this.self.callback.call(this.self,item,state);var dis=cHAS(this.self.select,"disabled")||item.disabled||item.option.disabled,lmt=this.self.con.multiple&&this.self.con.multiLimit<=this.selected.length,sgl=!this.self.con.multiple&&this.selected.indexOf(item.option)>0,del=0==this.self.con.multiLimit&&1==this.self.con.deselect,uns=!this.self.con.multiple&&!this.self.con.deselect&&!0!==_force;if("select"==state){if(dis||lmt||del||sgl)return!1;if(!this.self.con.multiple)for(var i in this.selected)this.unselect(this.selected[i],void 0,!0);this.selected.indexOf(item.option)<0&&this.selected.push(item.option)}else if("unselect"==state){if(dis||uns)return!1;this.selected.splice(this.selected.indexOf(item.option),1)}return item.selected="select"==state,item.option.selected="select"==state,item.option[(state.length>6?"remove":"set")+"Attribute"]("selected","selected"),this.self.callback.call(this.self,item,state,_force)},enable:function(key,group){return this.handle("enable",key,group,!1)},disable:function(key,group){return this.handle("disable",key,group,!1)},select:function(key,group){return this.handle("select",key,group,!1)},unselect:function(key,group,_force){return this.handle("unselect",key,group,_force)},toggle:function(item,group){return!!(item=this.get(item,group))&&this.handle(item.selected?"unselect":"select",item,group,!1)},invert:function(state){if(state=this._r(state),["enable","disable"].indexOf(state)>=0)var invert=this.disabled,action="enable"==state?"disable":"enable";else if(["select","unselect"].indexOf(state)>=0)var invert=this.selected,action="select"==state?"unselect":"select";var convert=Array.prototype.filter.call(this,(function(element){return!(element in invert)})),self=this;return[].concat(invert).forEach((function(item){self.handle.call(self,action,item)})),[].concat(convert).forEach((function(item){self.handle.call(self,state,item)})),!0},all:function(state,group){var self=this,list=this;return group in this.items?list=Object.keys(this.items[group]):["unselect","enable"].indexOf(state)>=0&&(list=[].concat("unselect"==state?this.selected:this.disabled)),Array.prototype.forEach.call(list,(function(item){self.handle.call(self,state,item,group,!1)})),!0},walk:function(state,items,args){if(items instanceof Array||items.length)for(var l=items.length,i=0;i0){do{var temp=this.items[this._inGroup][this._inItems.shift()]}while(!0===temp.hidden);return temp}if(this._inGroups.length>0){for(;this._inGroups.length>0;){var group=this._inGroups.shift();if(!(group in this.items))return!1;var keys=Object.keys(this.items[group]);if(keys.length>0)break}return"ASC"==orderi?keys.sort():"DESC"==orderi?keys.sort().reverse():"function"==typeof orderi&&(keys=orderi.call(this,keys)),this._inItems=keys,this._inGroup=group,this.walker(null,null)}return delete this._inLoop,delete this._inItems,delete this._inGroup,delete this._inGroups,!1}var groups=Object.keys(this.groups)||[];return"ASC"==orderg?groups.sort():"DESC"==orderg?groups.sort().reverse():"function"==typeof orderg&&(groups=orderg.call(this,groups)),groups.unshift("#"),this._inLoop=!0,this._inItems=[],this._inGroups=groups,this.walker(orderi,null)}},select})); \ No newline at end of file diff --git a/style/bottombar.css b/style/bottombar.css new file mode 100644 index 0000000..9c79a10 --- /dev/null +++ b/style/bottombar.css @@ -0,0 +1 @@ +#bottom-bar{display:none} diff --git a/style/checkbox.css b/style/checkbox.css new file mode 100644 index 0000000..9dcc4ee --- /dev/null +++ b/style/checkbox.css @@ -0,0 +1 @@ +.switch{position:relative;display:inline-block;width:30px;height:17px}.slider,.slider:before{position:absolute;transition:.4s}.switch input{opacity:0;width:0;height:0}.slider{cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;border-radius:12px}.slider:before{content:"";height:13px;width:13px;left:2px;bottom:2px;background-color:#fff;border-radius:50%}input:checked+.slider{background-color:#62c462}input:focus+.slider{box-shadow:0 0 1px #62c462}input:checked+.slider:before{transform:translateX(13px)} diff --git a/style/mainframe.css b/style/mainframe.css new file mode 100644 index 0000000..2ba5c8f --- /dev/null +++ b/style/mainframe.css @@ -0,0 +1 @@ +#top-bar input,body{background-color:var(--main-light-color)}#login-twitch,#top-bar input{font-family:Roboto,Tahoma,Geneva,Verdana,sans-serif;margin-top:5px;height:25px;display:inline-block}#disconnected-tip,#login-twitch,#top-bar input,.icon{display:inline-block}.stream .right-part .stream-title,.stream .streamer-name{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}#streams,#streams-page,#top-bar,#top-bar input,#user-pic-top,.stream .right-part,.stream .streamer-name{box-sizing:border-box}#top-bar input,.single-alert button{margin-left:5px}*{scrollbar-width:7px;scrollbar-color:var(--scrollbar-thumb-color) var(--main-light-color)}::-webkit-scrollbar{width:7px}::-webkit-scrollbar-track{background:var(--main-light-color)}::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-color);border-radius:10px;border:0 #fff}body{--main-dark-color:#000000;--main-light-color:#000000;--main-border-color:#00000000;--scrollbar-thumb-color:#585858;--stream-element-text:#dbdbdb;--stream-tags-background:#363636;--stream-tags-border:#ffffff00;--color-white:#ffffff;width:360px;height:570px;margin:0;padding:0;font-family:monospace;font-size:82%}.loading{transform:scale(.7)}.icon{background-image:url("chrome-extension://__MSG_@@extension_id__/images/icon.png");background-size:auto 100%;background-repeat:no-repeat}#top-bar{height:35px;width:100%;position:fixed;background-color:var(--main-dark-color);border-bottom:1px solid var(--main-border-color)}#notifications,.single-alert{background-color:#2e3e3d;color:#fff}#top-bar input{border-radius:4px;border:1px solid var(--main-border-color);position:absolute;width:190px;padding-left:5px;caret-color:var(--color-white);color:var(--color-white);font-weight:700}#top-bar input:focus{outline:0}#login-twitch{position:absolute;right:7px}#login-twitch button{height:100%;background:linear-gradient(0deg,#6832b9 9%,#9147ff 100%);border:none;border-radius:4px;color:var(--color-white);font-weight:700;padding-left:9px;padding-right:9px;cursor:pointer;font-family:monospace}#login-twitch button:active{background:linear-gradient(0deg,#6832b9 50%,#9147ff 100%)}#disconnected-tip{color:var(--color-white);margin-top:8px;margin-left:7px;font-size:10px;line-height:2}#disconnected-stream-tip{position:absolute;top:100px;width:100%;text-align:center;color:#878787;font-size:15px}#username-top,.stream .streamer-name{font-size:14px;color:var(--color-white)}#user-infos-top{position:absolute;top:0;right:0;cursor:pointer;height:35px;padding-left:9px;transition:.2s}#user-infos-top:hover{background-color:#363636;transition:.2s}#username-top{position:relative;margin-top:9px;margin-right:6px;font-weight:700;float:right}#user-pic-top{position:relative;width:27px;height:27px;margin-top:4px;margin-right:5px;border-radius:50%;float:right}#streams-page{position:relative;width:100%;height:500px;top:35px;overflow-y:scroll}#streams{width:100%;padding-left:5px;padding-right:5px;padding-top:10px}#streams .stream{position:relative;height:65px;overflow:hidden;background:linear-gradient(270deg,var(--main-light-color) 50%,var(--main-dark-color) 100%);box-shadow:0 0 5px 1px #00000000;margin-bottom:10px;transition:.5s;cursor:pointer}#streams .stream:hover{background:linear-gradient(270deg,var(--main-light-color) 10%,var(--main-dark-color) 100%);transition:.5s}#informations{text-align:center;color:#6a6a6a;font-size:12px;font-weight:700;font-style:italic;padding:0 5px 10px}.stream .stream-pic{width:115px;height:100%}.stream .streamer-name{position:absolute;bottom:0;background-color:rgb(0 0 0 / 80%);padding:2px 7px 3px 3px;max-width:115px}.stream .right-part{position:absolute;width:225px;height:100%;top:0;right:0;padding:2px 2px 2px 3px}.stream .right-part .stream-title{color:var(--stream-element-text);font-weight:700;font-size:13px}.stream .right-part .stream-game{color:var(--stream-element-text);font-size:13px;font-style:italic}.stream .right-part .viewer-count{position:absolute;color:var(--stream-element-text);padding:2px 8px 2px 5px;background-color:var(--stream-tags-background);border:1px solid var(--stream-tags-border);border-radius:15px;right:3px;bottom:3px;font-size:14px;font-weight:700;box-sizing:border-box;transform:scale(.85)}.viewer-count .live-circle{background-color:#eb0400;width:15px;height:15px;border-radius:50%;margin-right:5px;margin-top:1px;float:left}.stream .right-part .stream-tags{position:absolute;bottom:0}.stream .right-part .stream-language,.stream .right-part .stream-mature,.stream .right-part .stream-time{color:var(--stream-element-text);background-color:var(--stream-tags-background);right:3px;bottom:4px;left:1px;font-size:12px;font-weight:700;position:relative;display:inline-block;box-sizing:border-box}.stream .right-part .stream-language,.stream .right-part .stream-time{padding:1px 7px 1px 6px;border:1px solid var(--stream-tags-border);border-radius:15px}.stream .right-part .stream-mature{padding:1px 5px;border:1px solid var(--stream-tags-border);border-radius:15px}#notifications-page{position:relative;width:100%;height:465px;top:35px;box-sizing:border-box;overflow-y:scroll;padding-left:5px}#notifications{width:100%;box-sizing:border-box;text-align:center;padding:5px;margin-top:10px}#notifications .notification{text-align:left}.notification .streamer-name{display:inline-block;font-size:16px;text-align:left;background-color:var(--main-dark-color);padding:3px 9px 4px 5px;box-sizing:border-box;max-width:170px;max-height:25px;text-overflow:ellipsis;overflow:hidden;color:var(--color-white)}.notification .followed-date{padding:1px 7px;font-size:11px}#notifications-page #notify-all-streams{padding:5px 7px;margin:5px 5px 7px;background-color:#2e3e3d;box-shadow:0 0 3px 0 var(--main-dark-color)}#notifications-page #notify-all-streams span{color:var(--color-white);font-size:15px}#notifications-page #notify-all-streams label{float:right}.all-alerts{flex-direction:column;display:flex;gap:10px;margin-top:10px}.single-alert{padding:10px}.single-alert span{font-weight:900;text-transform:uppercase;font-size:130%}.add-alert{margin-top:5px;width:100%;margin-bottom:5px}.separator{display:flex;align-items:center;text-align:center;color:#fff}.separator::after,.separator::before{content:'';flex:1;border-bottom:1px solid #fff}.separator:not(:empty)::before{margin-right:.25em}.separator:not(:empty)::after{margin-left:.25em}#disconnected-stream-tip[style*="display: block;"]+.tab,#searchbox{display:none!important}.enable-notifications.switch{width:60%;margin-bottom:12px;display:block;margin-top:10px}.add-new-alert{width:100%} diff --git a/style/tail.css b/style/tail.css new file mode 100644 index 0000000..b6f9940 --- /dev/null +++ b/style/tail.css @@ -0,0 +1,450 @@ +.tail-select, +.tail-select *, +.tail-select *:before, +.tail-select *:after { + box-sizing: border-box; +} +.tail-select{ + width: 250px; + margin: 1px; + padding: 0; + display: inline-block; + position: relative; + font-size: 14px; + line-height: 22px; + font-family: inherit; +} +.tail-select mark{ + color: white; + background-color: #DC4650; +} +.tail-select button{ + outline: none; +} +.tail-select button.tail-all, .tail-select button.tail-none{ + height: auto; + margin: 0 2px; + padding: 2px 6px; + display: inline-block; + font-size: 10px; + line-height: 14px; + text-shadow: none; + letter-spacing: 0; + text-transform: none; + vertical-align: top; + border-width: 1px; + border-style: solid; + border-color: transparent; + border-radius: 3px; + box-shadow: none; + transition: color 142ms linear, border 142ms linear, background 142ms linear; +} +.tail-select button.tail-all{ + color: rgba(255, 255, 255, 0.35); + border-color: rgba(255, 255, 255, 0.35); + background-color: transparent; +} +.tail-select button.tail-all:hover{ + color: #62C462; + border-color: #62C462; + background-color: transparent; +} +.tail-select button.tail-none{ + color: rgba(255, 255, 255, 0.35); + border-color: rgba(255, 255, 255, 0.35); + background-color: transparent; +} +.tail-select button.tail-none:hover{ + color: #EE5F5B; + border-color: #EE5F5B; + background-color: transparent; +} +.tail-select.disabled button.tail-all{ + color: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.1); + background-color: transparent; +} +.tail-select.disabled button.tail-none{ + color: rgba(255, 255, 255, 0.1); + border-color: rgba(255, 255, 255, 0.1); + background-color: transparent; +} +.tail-select input[type="text"]{ + color: rgba(255, 255, 255, 0.85); + width: 100%; + height: auto; + margin: 0; + padding: 10px 15px; + display: inline-block; + outline: 0; + font-size: 12px; + line-height: 20px; + vertical-align: middle; + background-color: transparent; + border-width: 0; + border-style: solid; + border-color: transparent; + border-radius: 0; + box-shadow: none; +} +.tail-select input[type="text"]:hover{ + color: rgba(255, 255, 255, 0.85); + border-color: transparent; + background-color: transparent; +} +.tail-select input[type="text"]:focus{ + color: #3C82E6; + border-color: transparent; + background-color: transparent; +} +.tail-select.disabled input[type="text"]{ + color: rgba(255, 255, 255, 0.6); + border-color: transparent; + background-color: transparent; +} +.tail-select-container{ + margin: 0; + padding: 3px; + text-align: left; + border-radius: 3px; +} +.tail-select-container .select-handle{ + width: auto; + color: rgba(255, 255, 255, 0.85); + cursor: pointer; + margin: 1px; + padding: 0.2em 0.6em 0.3em; + display: inline-block; + position: relative; + font-size: 11.844px; + text-align: left; + font-weight: bold; + line-height: 16px; + text-shadow: none; + vertical-align: top; + background-color: #000000; + border-width: 0; + border-style: solid; + border-color: transparent; + border-radius: 3px; + transition: background 142ms linear; +} +.tail-select-container .select-handle:hover{ + color: rgba(255, 255, 255, 0.85); + background-color: #DC4650; +} +.tail-select-container.select-label .select-handle{ + margin: 5px 3px; +} +/* @end GENERAL */ + +/* @start LABEL */ +.tail-select .select-label{ + cursor: pointer; + color: rgba(255, 255, 255, 0.7); + width: 100%; + margin: 0; + padding: 5px 30px 5px 10px; + display: block; + z-index: 27; + position: relative; + text-align: left; + background-color: #202428; + border-width: 0px; + border-style: solid; + border-color: #101418; + border-radius: 3px; + box-shadow: 0 0 0 1px #000408, inset 0 0 1px 1px #404448; + transition: background 142ms linear, box-shadow 142ms linear; +} +.tail-select .select-label:after{ + top: 15px; + right: 12px; + width: 0; + height: 0; + margin: 0; + padding: 0; + z-index: 25; + content: ""; + opacity: 0.5; + display: inline-block; + position: absolute; + border-top: 5px dashed; + border-top: 5px solid\9; + border-right: 5px solid transparent; + border-left: 5px solid transparent; + text-shadow: none; + transition: opacity 142ms linear, transform 142ms linear; +} +.tail-select .select-label .label-count, .tail-select .select-label .label-inner{ + width: auto; + margin: 0; + text-align: left; + vertical-align: top; +} +.tail-select .select-label .label-count{ + float: left; + color: rgba(255, 255, 255, 0.7); + margin: 0 5px 0 0; + padding: 0 7px 0 0; + display: inline-block; + font-size: 11.844px; + font-weight: bold; + text-shadow: none; + white-space: nowrap; + vertical-align: top; + border-width: 0px 1px 0 0; + border-style: solid; + border-color: #101418; + border-radius: 0px; +} +.tail-select .select-label .label-inner{ + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.tail-select:hover .select-label, .tail-select.idle .select-label, +.tail-select.active .select-label{ + z-index: 25; + box-shadow: 0 0 0 1px #000408, inset 0 0 1px 1px #3C82E6; +} +.tail-select:hover .select-label:after, .tail-select.idle .select-label:after, +.tail-select.active .select-label:after{ + opacity: 0.85; +} +.tail-select:hover .select-label .label-count, .tail-select.idle .select-label .label-count, +.tail-select.active .select-label .label-count, .tail-select:hover .select-label .label-inner, +.tail-select.idle .select-label .label-inner, .tail-select.active .select-label .label-inner{ + opacity: 1; +} +.tail-select.active .select-label{ + z-index: 27; +} +.tail-select.active .select-label:after{ + opacity: 0.85; + transform: rotate(180deg); +} +.tail-select.disabled .select-label{ + cursor: not-allowed; + box-shadow: 0 0 0 1px #000408, inset 0 0 1px 1px #404448; +} +/* @end LABEL */ + +/* @start DROPDOWN */ +.tail-select .select-dropdown{ + top: 100%; + left: 0; + color: rgba(255, 255, 255, 0.85); + width: 100%; + min-height: 35px; + margin: -1px 0 0 0; + padding: 0; + z-index: 30; + display: none; + overflow: hidden; + position: absolute; + background-color: #202428; + border-width: 0px; + border-style: solid; + border-color: #101418; + border-radius: 0 0 3px 3px; + box-shadow: 0 0 0 1px #000408, inset 0 0 1px 1px #404448; +} +.tail-select .select-dropdown .dropdown-search{ + width: 100%; + margin: 0; + padding: 0; + display: block; + position: relative; + border-width: 0 0 1px 0; + border-style: solid; + border-color: #101418; + box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); +} +.tail-select .select-dropdown .dropdown-inner{ + width: 100%; + margin: 0; + padding: 1px 0; + display: block; + overflow-x: hidden; + overflow-y: auto; +} +.tail-select .select-dropdown .dropdown-empty{ + margin: 0; + padding: 16px 0; + display: block; + font-size: 12px; + text-align: center; + line-height: 18px; +} +.tail-select .select-dropdown .dropdown-action{ + top: 3px; + right: 15px; + width: auto; + margin: 0; + padding: 7px 0; + z-index: 35; + display: inline-block; + position: absolute; + text-align: center; +} +.tail-select .select-dropdown ul, .tail-select .select-dropdown ul li{ + width: 100%; + margin: 0; + padding: 0; + display: block; + position: relative; + list-style: none; + font-size: 14px; + line-height: 20px; + vertical-align: top; +} +.tail-select .select-dropdown ul li{ + color: rgba(255, 255, 255, 0.85); + padding: 5px 10px 5px 35px; + font-size: 12px; + text-align: left; + line-height: 18px; + font-weight: normal; +} +.tail-select .select-dropdown ul li:first-of-type{ + margin-top: 7px; +} +.tail-select .select-dropdown ul li:last-of-type{ + margin-bottom: 7px; +} +.tail-select .select-dropdown ul li.optgroup-title{ + color: rgba(255, 255, 255, 0.55); + cursor: default; + margin: 9px 0 0 0; + padding-left: 10px; + font-size: 14px; + text-shadow: none; +} +.tail-select .select-dropdown ul li.optgroup-title button{ + float: right; + margin-top: -2px; + opacity: 0; +} +.tail-select .select-dropdown ul:hover li button{ + opacity: 1; +} +.tail-select .select-dropdown ul li.dropdown-option{ + cursor: pointer; + color: rgba(255, 255, 255, 0.85); +} +.tail-select .select-dropdown ul li.dropdown-option:before{ + top: 0; + left: 0; + width: 30px; + height: 30px; + margin: 0; + padding: 0; + z-index: 21; + display: inline-block; + content: ""; + opacity: 0; + position: absolute; + vertical-align: top; + background-repeat: no-repeat; + background-position: center center; + transition: opacity 50ms linear; +} +.tail-select .select-dropdown ul li.dropdown-option .option-description{ + color: rgba(255, 255, 255, 0.7); + width: auto; + margin: 0; + padding: 0; + display: block; + font-size: 10px; + text-align: left; + line-height: 14px; + vertical-align: top; +} +.tail-select .select-dropdown ul li.dropdown-option:hover, +.tail-select .select-dropdown ul li.dropdown-option.hover{ + color: rgba(255, 255, 255, 0.85); +} +.tail-select .select-dropdown ul li.dropdown-option:hover .option-description, +.tail-select .select-dropdown ul li.dropdown-option.hover .option-description{ + color: rgba(255, 255, 255, 0.85); +} +.tail-select.open-top .select-dropdown{ + top: auto; + bottom: 100%; + margin: 0 0 -1px 0; + border-radius: 3px 3px 0 0; +} +.tail-select.hide-selected .select-dropdown ul li.selected, +.tail-select.hide-disabled .select-dropdown ul li.disabled{ + display: none; +} +/* State & Icons :: Single */ +.tail-select .select-dropdown ul li.dropdown-option:before{ + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M8%203v3a2%202%200%200%201-2%202H3m18%200h-3a2%202%200%200%201-2-2V3m0%2018v-3a2%202%200%200%201%202-2h3M3%2016h3a2%202%200%200%201%202%202v3%22%3E%3C/path%3E%3C/svg%3E"); +} +.tail-select .select-dropdown ul li.dropdown-option:hover:before, +.tail-select .select-dropdown ul li.dropdown-option.hover:before{ + opacity: 0.5; +} +.tail-select .select-dropdown ul li.dropdown-option.selected{ + color: #3C82E6; + background-color: #202428; +} +.tail-select .select-dropdown ul li.dropdown-option.selected:before{ + opacity: 0.85; + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%2220%206%209%2017%204%2012%22%3E%3C/polyline%3E%3C/svg%3E"); +} +.tail-select .select-dropdown ul li.dropdown-option.selected .option-description{ + color: #3C82E6; +} +.tail-select.deselect .select-dropdown ul li.dropdown-option.selected:hover:before, +.tail-select.deselect .select-dropdown ul li.dropdown-option.selected.hover:before{ + opacity: 0.85; + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cline%20x1%3D%2218%22%20y1%3D%226%22%20x2%3D%226%22%20y2%3D%2218%22%3E%3C/line%3E%3Cline%20x1%3D%226%22%20y1%3D%226%22%20x2%3D%2218%22%20y2%3D%2218%22%3E%3C/line%3E%3C/svg%3E"); +} +.tail-select.deselect .select-dropdown ul li.dropdown-option.selected:hover .option-description, +.tail-select.deselect .select-dropdown ul li.dropdown-option.selected.hover .option-description{ + color: #3C82E6; +} +.tail-select .select-dropdown ul li.dropdown-option{ + transition: all 0.3s ease-in; +} +.tail-select .select-dropdown ul li.dropdown-option:hover, +.tail-select .select-dropdown ul li.dropdown-option.hover{ + transition: all 0.4s ease; + background-color: #171d24; +} +.tail-select.disabled .select-dropdown ul li.dropdown-option, +.tail-select .select-dropdown ul li.dropdown-option.disabled{ + cursor: not-allowed; + color: rgba(255, 255, 255, 0.25); + text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1), 0px -1px 0px rgba(179, 179, 179, 0.1); + background-color: #2a2a2a; +} +.tail-select.disabled .select-dropdown ul li.dropdown-option:before, +.tail-select .select-dropdown ul li.dropdown-option.disabled:before{ + opacity: 0.85; + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M8%203H5a2%202%200%200%200-2%202v3m18%200V5a2%202%200%200%200-2-2h-3m0%2018h3a2%202%200%200%200%202-2v-3M3%2016v3a2%202%200%200%200%202%202h3%22%3E%3C/path%3E%3C/svg%3E"); +} +.tail-select.disabled .select-dropdown ul li.dropdown-option .option-description, +.tail-select .select-dropdown ul li.dropdown-option.disabled .option-description{ + color: rgba(255, 255, 255, 0.25); +} +/* State & Icons :: Multiple */ +.tail-select.multiple .select-dropdown ul li.dropdown-option:before{ + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2210%22%3E%3C/circle%3E%3Cline%20x1%3D%2212%22%20y1%3D%228%22%20x2%3D%2212%22%20y2%3D%2216%22%3E%3C/line%3E%3Cline%20x1%3D%228%22%20y1%3D%2212%22%20x2%3D%2216%22%20y2%3D%2212%22%3E%3C/line%3E%3C/svg%3E"); +} +.tail-select.multiple .select-dropdown ul li.dropdown-option.selected:before{ + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M22%2011.08V12a10%2010%200%201%201-5.93-9.14%22%3E%3C/path%3E%3Cpolyline%20points%3D%2222%204%2012%2014.01%209%2011.01%22%3E%3C/polyline%3E%3C/svg%3E"); +} +.tail-select.multiple .select-dropdown ul li.dropdown-option.selected:hover:before, +.tail-select.multiple .select-dropdown ul li.dropdown-option.selected.hover:before{ + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2210%22%3E%3C/circle%3E%3Cline%20x1%3D%228%22%20y1%3D%2212%22%20x2%3D%2216%22%20y2%3D%2212%22%3E%3C/line%3E%3C/svg%3E"); +} +.tail-select.multiple.disabled .select-dropdown ul li.dropdown-option:before, +.tail-select.multiple .select-dropdown ul li.dropdown-option.disabled:before{ + background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2218%22%20height%3D%2218%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22rgba%28255,%20255,%20255,%200.85%29%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2210%22%3E%3C/circle%3E%3C/svg%3E"); +} +/* @end DROPDOWN */ \ No newline at end of file