diff --git a/dark.css b/dark.css index eb1d67ed..e2081742 100644 --- a/dark.css +++ b/dark.css @@ -200,10 +200,19 @@ body.ffz-dark:not([data-page="teams#show"]), box-shadow: rgba(255,255,255,0.2) 0 0 0 1px inset; } +.ffz-dark #flyout .content, +.ffz-dark .ffz-ui-popup.emoticon-selector .emoticon-selector-box { border: none } + +.ffz-dark .balloon--up:after { box-shadow: 1px 1px 0 rgba(255,255,255,0.2) } +.ffz-dark .balloon--down:after { box-shadow: -1px -1px 0 rgba(255,255,255,0.2) } +.ffz-dark .balloon--left:after { box-shadow: 1px -1px 0 rgba(255,255,255,0.2) } +.ffz-dark .balloon--right:after { box-shadow: -1px 1px 0 rgba(255,255,255,0.2) } + + .ffz-dark .player-menu__header { color: #c3c3c3 } .ffz-dark .player-menu__section { border-bottom-color: rgba(255,255,255,0.2) } -.ffz-dark .balloon:after { box-shadow: none } +/*.ffz-dark .balloon:after { box-shadow: none }*/ .ffz-dark .st-autocomplete-sidebar .label, .ffz-dark .st-autocomplete-small .label, @@ -287,6 +296,9 @@ body.ffz-dark:not([data-page="teams#show"]), color: #8c8c9c; } +.ffz-dark .balloon .balloon__link { color: #a68ed2 !important } +.ffz-dark .balloon .balloon__link:hover { color: #fff !important } + .ffz-dark .st-autocomplete-sidebar .all p:not(.active), .ffz-dark .st-autocomplete-small .all p:not(.active), .ffz-dark .st-autocomplete .all p:not(.active), diff --git a/src/badges.js b/src/badges.js index 6490abfe..dcdc2fa1 100644 --- a/src/badges.js +++ b/src/badges.js @@ -2,16 +2,36 @@ var FFZ = window.FrankerFaceZ, constants = require('./constants'), utils = require('./utils'), - SPECIAL_BADGES = [ - ['staff', 'staff', 'Staff'], - ['admin', 'admin', 'Admin'], - ['global_mod', 'global-moderator', 'Global Moderator'] - ], + SPECIAL_BADGES = ['staff', 'admin', 'global_mod'], + OTHER_KNOWN = ['turbo', 'warcraft'], - badge_css = function(badge) { - var out = ".badges .ffz-badge-" + badge.id + " { background-color: " + badge.color + '; background-image: url("' + badge.image + '"); ' + (badge.css || "") + '}'; + BTTV_TYPE_REPLACEMENTS = { + 'global-moderator': 'global_mod' + }, + + BADGE_POSITIONS = { + 'broadcaster': 0, + 'staff': 0, + 'admin': 0, + 'global_mod': 0, + 'mod': 1, + 'moderator': 1, + 'subscriber': 10, + }, + + BADGE_NAMES = { + 'global_mod': 'Global Moderator' + }, + + BADGE_KLASSES = { + 'global_mod': 'global-moderator' + }, + + badge_css = function(badge, klass) { + klass = klass || ('ffz-badge-' + badge.id); + var out = ".badges ." + klass + " { background-color: " + badge.color + '; background-image: url("' + badge.image + '"); ' + (badge.css || "") + '}'; if ( badge.alpha_image ) - out += ".badges .badge.alpha.ffz-badge-" + badge.id + ",.ffz-transparent-badges .badges .ffz-badge-" + badge.id + ' { background-image: url("' + badge.alpha_image + '"); }'; + out += ".badges .badge.alpha." + klass + ",.ffz-transparent-badges .badges ." + klass + ' { background-image: url("' + badge.alpha_image + '"); }'; return out; }; @@ -27,7 +47,80 @@ FFZ.settings_info.show_badges = { category: "Chat Appearance", name: "Additional Badges", help: "Show additional badges for bots, FrankerFaceZ donors, and other special users." - }; +}; + + +FFZ.settings_info.hidden_badges = { + type: "button", + value: [], + + category: "Chat Appearance", + name: "Hidden Badges", + help: "Any badges added to this list will not be displayed in chat.", + + on_update: function(val) { + if ( this.has_bttv ) + return; + + var controller = utils.ember_lookup('controller:chat'), + messages = controller && controller.get('currentRoom.messages'); + + if ( ! messages ) + return; + + for(var i=0; i < messages.length; i++) + messages[i]._line && messages[i]._line.ffzUpdateBadges(); + }, + + method: function() { + var f = this, + service = utils.ember_lookup('service:badges'), + badgeCollection = service && service.badgeCollection, + old_val = f.settings.hidden_badges.join(", "), + values = []; + + if ( badgeCollection ) { + if ( badgeCollection.global ) + for(var badge in badgeCollection.global) + if ( badgeCollection.global.hasOwnProperty(badge) && badge !== 'broadcasterName' ) + values.push('' + badge + ''); + + if ( badgeCollection.channel ) + for(var badge in badgeCollection.channel) + if ( badgeCollection.channel.hasOwnProperty(badge) && badge !== 'broadcasterName' ) + values.push('' + badge + ''); + } + + for(var badge_id in f.badges) { + if ( f.badges.hasOwnProperty(badge_id) && f.badges[badge_id].name ) + values.push('ffz-' + f.badges[badge_id].name + ''); + } + + if ( this.has_bttv && window.BetterTTV ) { + try { + for(var badge_id in BetterTTV.chat.store.__badgeTypes) + values.push('bttv-' + badge_id + ''); + + values.push('bot'); + + } catch(err) { + this.error("Unable to load known BetterTTV badges.", err); + } + } + + utils.prompt( + "Hidden Badges", + "Please enter a comma-separated list of badges that you would like to be hidden in chat.

Possible Values: " + _.unique(values).join(", "), + old_val, + function(new_val) { + if ( new_val === null || new_val === undefined ) + return; + + f.settings.set("hidden_badges", _.unique(new_val.trim().toLowerCase().split(/\s*,\s*/))); + }, 600 + ) + } +}; FFZ.settings_info.sub_notice_badges = { @@ -39,10 +132,10 @@ FFZ.settings_info.sub_notice_badges = { help: "Display a subscriber badge on chat messages about new subscribers.", on_update: function(val) { - this.toggle_style('badges-sub-notice', ! val); - this.toggle_style('badges-sub-notice-on', val); - } - }; + this.toggle_style('badges-sub-notice', ! val); + this.toggle_style('badges-sub-notice-on', val); + } +}; FFZ.settings_info.legacy_badges = { @@ -71,11 +164,11 @@ FFZ.settings_info.legacy_badges = { }, on_update: function(val) { - this.toggle_style('badges-legacy', val === 3); - this.toggle_style('badges-legacy-mod', val !== 0); - this.toggle_style('badges-legacy-turbo', val > 1); - } - }; + this.toggle_style('badges-legacy', val === 3); + this.toggle_style('badges-legacy-mod', val !== 0); + this.toggle_style('badges-legacy-turbo', val > 1); + } +}; FFZ.settings_info.transparent_badges = { @@ -108,17 +201,17 @@ FFZ.settings_info.transparent_badges = { }, on_update: function(val) { - if ( this.has_bttv ) - return; + if ( this.has_bttv ) + return; - this.toggle_style('badges-rounded', val === 1); - this.toggle_style('badges-circular', val === 2 || val === 3 || val === 4); - this.toggle_style('badges-blank', val === 3 || val === 4); - this.toggle_style('badges-circular-small', val === 4); - this.toggle_style('badges-transparent', val === 5); - document.body.classList.toggle('ffz-transparent-badges', val === 5); - } - }; + this.toggle_style('badges-rounded', val === 1); + this.toggle_style('badges-circular', val === 2 || val === 3 || val === 4); + this.toggle_style('badges-blank', val === 3 || val === 4); + this.toggle_style('badges-circular-small', val === 4); + this.toggle_style('badges-transparent', val === 5); + document.body.classList.toggle('ffz-transparent-badges', val === 5); + } +}; // -------------------- @@ -187,7 +280,9 @@ FFZ.ws_commands.set_badge = function(data) { // -------------------- FFZ.prototype.get_badges = function(user, room_id, badges, msg) { - var data = this.users[user]; + var data = this.users[user], + hidden_badges = this.settings.hidden_badges; + if ( ! data || ! data.badges || ! this.settings.show_badges ) return badges; @@ -199,6 +294,9 @@ FFZ.prototype.get_badges = function(user, room_id, badges, msg) { full_badge = this.badges[badge.id] || {}, old_badge = badges[slot]; + if ( hidden_badges.indexOf('ffz-' + full_badge.name) !== -1 ) + continue; + if ( full_badge.visible !== undefined ) { var visible = full_badge.visible; if ( typeof visible === "function" ) @@ -223,6 +321,7 @@ FFZ.prototype.get_badges = function(user, room_id, badges, msg) { klass: 'ffz-badge-' + badge.id, title: badge.title || full_badge.title, image: badge.image, + full_image: full_badge.image, color: badge.color, extra_css: badge.extra_css }; @@ -234,30 +333,77 @@ FFZ.prototype.get_badges = function(user, room_id, badges, msg) { FFZ.prototype.get_line_badges = function(msg) { var badges = {}, + hidden_badges = this.settings.hidden_badges, + + last_id = -1, + had_last = false, room = msg.get && msg.get('room') || msg.room, from = msg.get && msg.get('from') || msg.from, tags = msg.get && msg.get('tags') || msg.tags || {}, - labels = msg.labels || []; + badge_tag = tags.badges || {}, - if ( room && from === room ) - badges[0] = {klass: 'broadcaster', title: 'Broadcaster'}; - else { - for(var i=0, l = SPECIAL_BADGES.length; i < l; i++) { - var mb = SPECIAL_BADGES[i]; - if ( tags['user-type'] === mb[0] || labels.indexOf(mb[0]) !== -1 ) { - badges[0] = {klass: mb[1], title: mb[2]} - break; - } - } + service = utils.ember_lookup('service:badges'), + badgeCollection = service && service.badgeCollection, - if ( tags.mod || labels.indexOf('mod') !== -1 ) - badges[1] = {klass: 'moderator', title: 'Moderator'}; - } + globals = badgeCollection && badgeCollection.global || {}, + channel = badgeCollection && badgeCollection.channel || {}; - if ( tags.subscriber || labels.indexOf('subscriber') !== -1 ) - badges[10] = {klass: 'subscriber', title: 'Subscriber'} - if ( tags.turbo || labels.indexOf('turbo') !== -1 ) - badges[15] = {klass: 'turbo', title: 'Turbo'}; + // VoD Chat lines don't have the badges pre-parsed for some reason. + if ( typeof badge_tag === 'string' ) { + var val = badge_tag.split(','); + badge_tag = {}; + for(var i=0; i < val.length; i++) { + var parts = val[i].split('/'); + if ( parts.length === 2 ) + badge_tag[parts[0]] = parts[1]; + } + } + + for(var badge in badge_tag) { + var version = badge_tag[badge]; + if ( ! badge_tag.hasOwnProperty(badge) || ! version ) + continue; + + var versions = channel[badge] || globals[badge], + binfo = versions && versions.versions && versions.versions[version]; + + if ( from === 'sirstendec' && badge === 'turbo' && globals.warcraft ) { + badge = 'warcraft'; + version = 'protoss'; + binfo = { + click_action: 'visit_url', + click_url: 'https://www.youtube.com/watch?v=dpBM2FIHprM', + description: 'My life for Aiur!', + title: 'Protoss', + image_url_1x: 'https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/1.png', + image_url_2x: 'https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/2.png', + image_url_3x: 'https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/4.png' + } + } + + if ( hidden_badges.indexOf(badge) !== -1 ) + continue; + + if ( BADGE_POSITIONS.hasOwnProperty(badge) ) + last_id = BADGE_POSITIONS[badge]; + else { + last_id = had_last ? last_id + 1 : 15; + had_last = true; + } + + var is_known = BADGE_POSITIONS.hasOwnProperty(badge) || OTHER_KNOWN.indexOf(badge) !== -1; + + badges[last_id] = { + klass: (BADGE_KLASSES[badge] || badge) + (is_known ? '' : ' unknown-badge') + ' version-' + version, + title: binfo && binfo.title || BADGE_NAMES[badge] || badge.capitalize(), + click_url: binfo && binfo.click_action === 'visit_url' && binfo.click_url + }; + + if ( ! is_known && binfo ) { + badges[last_id].image = binfo.image_url_1x; + badges[last_id].srcSet = 'url("' + binfo.image_url_1x + '") 1x, url("' + binfo.image_url_2x + '") 2x, url("' + binfo.image_url_3x + '") 4x'; + } + } // FFZ Badges return this.get_badges(from, room, badges, msg); @@ -272,8 +418,8 @@ FFZ.prototype.get_other_badges = function(user_id, room_id, user_type, has_sub, else for(var i=0, l = SPECIAL_BADGES.length; i < l; i++) { var mb = SPECIAL_BADGES[i]; - if ( user_type === mb[0] ) { - badges[0] = {klass: mb[1], title: mb[2]}; + if ( user_type === mb ) { + badges[0] = {klass: BADGE_KLASSES[mb] || mb, title: BADGE_TITLES[mb] || mb.capitalize()}; break; } } @@ -295,15 +441,22 @@ FFZ.prototype.render_badges = function(badges) { var out = []; for(var key in badges) { var badge = badges[key], + klass = badge.klass, css = badge.image ? 'background-image:url("' + utils.quote_attr(badge.image) + '");' : ''; + if ( badge.srcSet ) + css += 'background-image:-webkit-image-set(' + badge.srcSet + ');background-image:image-set(' + badge.srcSet + ');' + if ( badge.color ) css += 'background-color:' + badge.color + ';' if ( badge.extra_css ) css += badge.extra_css; - out.push('

'); + if ( badge.click_url ) + klass += ' click_url'; + + out.push('
'); } return out.join(""); @@ -322,23 +475,38 @@ FFZ.prototype.bttv_badges = function(data) { user = this.users[user_id], badges_out = [], insert_at = -1, + + hidden_badges = this.settings.hidden_badges, alpha = BetterTTV.settings.get('alphaTags'); - if ( ! user || ! user.badges ) - return; if ( ! data.badges ) data.badges = []; // Determine where in the list to insert these badges. + // Also, strip out banned badges while we're at it. for(var i=0; i < data.badges.length; i++) { - var badge = data.badges[i]; - if ( badge.type == "subscriber" || badge.type == "turbo" ) { + var badge = data.badges[i], + space_ind = badge.type.indexOf(' '), + hidden_key = BTTV_TYPE_REPLACEMENTS[badge.type] || (space_ind === -1 ? badge.type : badge.type.substr(0, space_ind)); + + if ( hidden_badges.indexOf(hidden_key) !== -1 ) { + data.badges.splice(i, 1); + continue; + } + + if ( badge.type === "subscriber" || badge.type === "turbo" || badge.type.substr(0, 8) === 'warcraft' ) { insert_at = i; break; } } + // If there's no user, we're done now. + if ( ! user || ! user.badges ) + return; + + + // We have a user. Start replacing badges. for (var slot in user.badges) { if ( ! user.badges.hasOwnProperty(slot) ) continue; @@ -348,9 +516,12 @@ FFZ.prototype.bttv_badges = function(data) { desc = badge.title || full_badge.title, style = ""; + if ( hidden_badges.indexOf('ffz-' + full_badge.name) !== -1 ) + continue; + if ( full_badge.visible !== undefined ) { var visible = full_badge.visible; - if ( typeof visible == "function" ) + if ( typeof visible === "function" ) visible = visible.call(this, null, user_id); if ( ! visible ) @@ -400,6 +571,8 @@ FFZ.prototype.bttv_badges = function(data) { while(badges_out.length) data.badges.insertAt(insert_at, badges_out.shift()[1]); } + + } diff --git a/src/ember/channel.js b/src/ember/channel.js index e5ad0e10..56b0168d 100644 --- a/src/ember/channel.js +++ b/src/ember/channel.js @@ -18,11 +18,6 @@ FFZ.prototype.setup_channel = function() { document.body.classList.toggle("ffz-hide-view-count", !this.settings.channel_views); document.body.classList.toggle('ffz-theater-stats', this.settings.theater_stats); - this.log("Creating channel style element."); - var s = this._channel_style = document.createElement('style'); - s.id = "ffz-channel-css"; - document.head.appendChild(s); - this.log("Hooking the Ember Channel Index view."); var Channel = utils.ember_resolve('view:channel/index'), f = this; diff --git a/src/ember/conversations.js b/src/ember/conversations.js index 81daef62..8d879f7c 100644 --- a/src/ember/conversations.js +++ b/src/ember/conversations.js @@ -138,22 +138,22 @@ FFZ.prototype._modify_conversation_window = function(component) { component.reopen({ headerBadges: Ember.computed("thread.participants", "currentUsername", function() { - var e = this.get("otherUser"), - badges = f.get_other_badges(e.get('username'), null, e.get('userType'), false, e.get('hasTurbo')), - out = []; - - // It wants slightly different output from us. - for(var slot in badges) { - var badge = badges[slot]; - out.push({ - classes: 'badge ' + badge.klass, - title: badge.title - }); - } - - return out; + return []; }), + ffzHeaderBadges: Ember.computed("thread.participants", "currentUsername", function() { + var e = this.get("otherUser"); + return f.get_other_badges(e.get('username'), null, e.get('userType'), false, e.get('hasTurbo')); + }), + + ffzReplaceBadges: function() { + var el = this.get('element'), + badge_el = el && el.querySelector('.badges'), + badges = this.get('ffzHeaderBadges'); + + badge_el.innerHTML = f.render_badges(badges); + }.observes('ffzHeaderBadges'), + didInsertElement: function() { var el = this.get('element'), header = el && el.querySelector('.conversation-header'), @@ -164,6 +164,8 @@ FFZ.prototype._modify_conversation_window = function(component) { is_dark = (Layout && Layout.get('isTheatreMode')) || f.settings.dark_twitch; + this.ffzReplaceBadges(); + if ( header_name && raw_color ) { header_name.style.color = (is_dark ? colors[1] : colors[0]); header_name.classList.add('has-color'); diff --git a/src/ember/line.js b/src/ember/line.js index 436b2f96..10217bb2 100644 --- a/src/ember/line.js +++ b/src/ember/line.js @@ -662,6 +662,10 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) { this.$(".deleted,.message").replaceWith(this.buildMessageHTML()); }), + ffzUpdateBadges: function() { + this.$(".badges").html(f.render_badges(f.get_line_badges(this.get('msgObject')))); + }, + ffzUserLevel: function() { if ( this.get('isStaff') ) return 5; @@ -755,7 +759,7 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) { output += this.buildModIconsHTML(); // Badges - output += '' + f.render_badges(f.get_line_badges(this.get('msgObject'), is_whisper)) + ''; + output += '' + f.render_badges(f.get_line_badges(this.get('msgObject'))) + ''; // Alias Support var alias = f.aliases[user], @@ -915,7 +919,10 @@ FFZ.prototype._modify_chat_subline = function(component) { this.sendAction("timeoutUser", {user:from}); } else if ( cl.contains('badge') ) { - if ( cl.contains('turbo') ) + if ( cl.contains('click_url') ) + window.open(e.target.getAttribute('data-url'), "_blank"); + + else if ( cl.contains('turbo') ) window.open("/products/turbo?ref=chat_badge", "_blank"); else if ( cl.contains('subscriber') ) @@ -1015,7 +1022,19 @@ FFZ.prototype._modify_vod_line = function(component) { }, click: function(e) { - if ( e.target.classList.contains('delete') ) { + var cl = e.target.classList; + + if ( cl.contains('badge') ) { + if ( cl.contains('click_url') ) + window.open(e.target.getAttribute('data-url'), "_blank"); + + else if ( cl.contains('turbo') ) + window.open("/products/turbo?ref=chat_badge", "_blank"); + + else if ( cl.contains('subscriber') ) + this.sendAction("clickSubscriber"); + + } else if ( cl.contains('delete') ) { e.preventDefault(); this.sendAction("timeoutUser", this.get("msgObject.id")); } diff --git a/src/ember/room.js b/src/ember/room.js index 9388cf6b..db74e14b 100644 --- a/src/ember/room.js +++ b/src/ember/room.js @@ -995,7 +995,7 @@ FFZ.prototype._modify_room = function(room) { // If we were banned, set the state and update the UI. if ( is_me ) { t.set('ffz_banned', true); - if ( typeof duration === "number" && duration ) + if ( typeof duration === "number" && duration && isFinite(duration) && !isNaN(duration) ) t.updateWait(duration) else if ( duration ) { t.set('slowWait', 0); @@ -1308,6 +1308,9 @@ FFZ.prototype._modify_room = function(room) { if ( msg.from === 'twitchnotify' && msg.message.indexOf('subscribed to') === -1 && msg.message.indexOf('subscribed') !== -1 ) { if ( ! msg.tags ) msg.tags = {}; + if ( ! msg.tags.badges ) + msg.tags.badges = {}; + msg.tags.badges.subscriber = '1'; msg.tags.subscriber = true; if ( msg.labels && msg.labels.indexOf("subscriber") === -1 ) msg.labels.push("subscriber"); diff --git a/src/main.js b/src/main.js index aec9ce18..9a3e5e62 100644 --- a/src/main.js +++ b/src/main.js @@ -37,7 +37,7 @@ FFZ.msg_commands = {}; // Version var VER = FFZ.version_info = { - major: 3, minor: 5, revision: 196, + major: 3, minor: 5, revision: 203, toString: function() { return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || ""); } diff --git a/src/styles/badges-blank.css b/src/styles/badges-blank.css index 1709f1a8..3fec7ca8 100644 --- a/src/styles/badges-blank.css +++ b/src/styles/badges-blank.css @@ -1,3 +1,3 @@ -.badges .badge:not(.subscriber) { +.badges .badge:not(.subscriber):not(.unknown-badge) { background-size: 0px; } \ No newline at end of file diff --git a/src/styles/badges-circular-small.css b/src/styles/badges-circular-small.css index ec67a3f5..d9eef701 100644 --- a/src/styles/badges-circular-small.css +++ b/src/styles/badges-circular-small.css @@ -1,4 +1,4 @@ -.badges .badge:not(.subscriber) { +.badges .badge:not(.subscriber):not(.unknown-badge) { height: 10px; min-width: 10px; margin: 5px 3px 5px 0; diff --git a/src/styles/badges-circular.css b/src/styles/badges-circular.css index 0cbc892c..166df5f7 100644 --- a/src/styles/badges-circular.css +++ b/src/styles/badges-circular.css @@ -1,4 +1,4 @@ -.badges .badge:not(.subscriber) { +.badges .badge:not(.subscriber):not(.unknown-badge) { border-radius: 9px; background-size: 16px; background-repeat: no-repeat; diff --git a/src/styles/badges-rounded.css b/src/styles/badges-rounded.css index 17c4826c..ba93158f 100644 --- a/src/styles/badges-rounded.css +++ b/src/styles/badges-rounded.css @@ -1,4 +1,4 @@ /* Rounded Badges */ -.badges .badge:not(.subscriber) { +.badges .badge:not(.subscriber):not(.unknown-badge) { border-radius: 2px; } \ No newline at end of file diff --git a/src/tokenize.js b/src/tokenize.js index 0be13ccd..14db7224 100644 --- a/src/tokenize.js +++ b/src/tokenize.js @@ -1139,6 +1139,9 @@ FFZ.prototype.parse_history = function(history, purged, room_id, delete_links, t if ( msg.tags && typeof msg.tags.emotes === "string" ) msg.tags.emotes = utils.uncompressEmotes(msg.tags.emotes); + if ( msg.tags && typeof msg.tags.badges === "string" ) + msg.tags.badges = utils.uncompressBadges(msg.tags.badges); + if ( ! msg.cachedTokens || ! msg.cachedTokens.length ) this.tokenize_chat_line(msg, true, delete_links); diff --git a/src/utils.js b/src/utils.js index f1ab59c4..02098620 100644 --- a/src/utils.js +++ b/src/utils.js @@ -76,6 +76,34 @@ var sanitize_el = document.createElement('span'), return new Date(unix); }, + BADGE_REV = { + 'b': 'broadcaster', + 's': 'staff', + 'a': 'admin', + 'g': 'global_mod', + 'm': 'moderator', + 'u': 'subscriber', + 't': 'turbo' + }, + + uncompressBadges = function(value) { + if ( value === true ) + return {}; + + var output = {}, + badges = value.split(","), + l = badges.length; + + for(var i=0; i < l; i++) { + var parts = badges[i].split('/'); + if ( parts.length !== 2 ) + return {}; + + output[BADGE_REV[parts[0]] || parts[0].substr(1)] = parts[1]; + } + + return output; + }, uncompressEmotes = function(value) { var output = {}, @@ -373,6 +401,7 @@ module.exports = FFZ.utils = { } }, + uncompressBadges: uncompressBadges, uncompressEmotes: uncompressEmotes, emoji_to_codepoint: emoji_to_codepoint, diff --git a/style.css b/style.css index e1b7538d..39434302 100644 --- a/style.css +++ b/style.css @@ -2910,3 +2910,79 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 } /* Chat Pane Overhaul */ .ember-chat.ffz-chat-pane .chat-messages { bottom: 0 } + +/* Hide Outlines */ + +.conversation-header, +.conversations-list-icon, +.toggle-notification-menu { + outline: none !important +} + + +/* Badges */ + +/*.badges .badge { + height: 18px; + min-width: 18px; + display: inline-block; + vertical-align: middle; + float: left; + margin: 1px 3px 1px 0 +} + +.badges .broadcaster { + background: #e71818 url(/images/xarth/badge_broadcaster.svg); + background-size: 100% +} + +.badges .turbo { + cursor: pointer; + background: #6441a5 url(/images/xarth/badge_turbo.svg); + background-size: 100% +} + +.badges .subscriber { + cursor: pointer +} + +.badges .staff { + background: #200f33 url(/images/xarth/badge_staff.svg); + background-size: 100% +} + +.badges .global-moderator { + background: #0c6f20 url(/images/xarth/badge_globalmod.svg); + background-size: 100% +} + +.badges .moderator { + background: #34ae0a url(/images/xarth/badge_mod.svg); + background-size: 100% +} + +.badges .admin { + background: #faaf19 url(/images/xarth/badge_admin.svg); + background-size: 100% +}*/ + +/* Odd Badges */ +.badge.click_url { cursor: pointer } + +.badge.warcraft.version-alliance { + background: url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/1.png") #004094; + background-image: -webkit-image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/4.png") 4x); + background-image: image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/alliance/4.png") 4x); +} + +.badge.warcraft.version-horde { + background: url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/1.png") #ab0016; + background-image: -webkit-image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/4.png") 4x); + background-image: image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/horde/4.png") 4x); +} + +.badge.warcraft.version-protoss { + background: url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/1.png") #5bc7ff; + background-image: -webkit-image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/4.png") 4x); + background-image: image-set(url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/1.png") 1x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/2.png") 2x,url("https://cdn.frankerfacez.com/badges/twitch/warcraft/protoss/4.png") 4x); +} \ No newline at end of file