1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-09-16 10:06:54 +00:00

The "Oh God Why Didn't I Commit Sooner" Edition

v3.5.494.

Added: Chat Filtering > Remove Messages from Moderators
Added: Recent Highlights
Added: Support for room-specific badges from the API.

Fixed: Custom bits badges. Lots of styling. Chat bugs. Dark theme issues. My Emoticons menu not rendering. Reset Player not rendering. Twitch5 extension compatibility. Logviewer messages and Name History. Bits UI breaking when you switch rooms. Player state when you reset the player.

Closes #173
Closes #169
Closes #164
This commit is contained in:
SirStendec 2017-06-11 13:30:37 -04:00
parent e843a3bb19
commit 630d2830ec
30 changed files with 1049 additions and 187 deletions

View file

@ -474,15 +474,17 @@ FFZ.settings_info.chatter_count = {
help: "Display the current number of users connected to chat beneath the channel.",
on_update: function(val) {
if ( this._cindex )
this._cindex.ffzUpdateMetadata('chatters');
if ( ! val || ! this.rooms )
if ( ! this.rooms )
return;
// Refresh the data.
for(var room_id in this.rooms)
this.rooms.hasOwnProperty(room_id) && this.rooms[room_id].room && this.rooms[room_id].room.ffzInitChatterCount();
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room;
r && r.ffzInitChatterCount();
}
if ( this._cindex )
this._cindex.ffzUpdateMetadata('chatters');
}
};

View file

@ -942,7 +942,10 @@ FFZ.prototype.modify_chat_input = function(component) {
return emotes;
}.property(),
_setPartialName: function() { },
_setPartialName: function() {
if ( f.has_bttv )
return this._super();
}.observes('textareaValue'),
ffz_suggestions: function() {
var output = [],
@ -1041,9 +1044,24 @@ FFZ.prototype.modify_chat_input = function(component) {
for(var i=0; i < suggestions.length; i++) {
var suggestion = suggestions[i],
name = suggestion.id,
display_name = suggestion.displayName || (name && name.capitalize()),
username_match = display_name.trim().toLowerCase() === name,
alias = f.aliases[name];
display_name = suggestion.displayName,
username_match;
if ( name === undefined ) {
var dnt = display_name && display_name.trim();
if ( dnt && /^[a-z0-9_]+$/i.test(dnt) )
name = dnt.toLowerCase();
else
continue;
}
if ( ! display_name ) {
display_name = name.capitalize();
username_match = true;
} else
username_match = display_name.trim().toLowerCase() === name;
var alias = f.aliases[name];
if ( user_output[name] && ! user_output[name].is_alias ) {
var token = user_output[name];
@ -1245,6 +1263,9 @@ FFZ.prototype.modify_chat_input = function(component) {
var target = event.target,
cl = target.classList;
if ( f.has_bttv )
this._super();
if ( ! this.get('ffz_suggestions_visible') || cl.contains('suggestion') || cl.contains('suggestions') || target === this.get('chatTextArea') )
return;

View file

@ -180,6 +180,18 @@ FFZ.settings_info.remove_filtered = {
};
FFZ.settings_info.remove_filtered_mod = {
type: "boolean",
value: false,
category: "Chat Filtering",
no_bttv: 6,
name: "Remove Messages from Moderators",
help: "Messages with banned words will only be removed if they are not from a moderator, unless this setting is enabled."
};
FFZ.settings_info.remove_deleted = {
type: "boolean",
value: false,

View file

@ -235,26 +235,19 @@ FFZ.prototype.setup_layout = function() {
}.property("ffzExtraHeight", "windowWidth", "rightColumnWidth", "fullSizePlayerDimensions", "windowHeight"),
contentWidth: function() {
var left_width = this.get('isSocialColumnEnabled') ? LS(
f.settings.socialbar_hide ? 0 :
this.get('isSocialColumnCollapsed') ? 50 : 240
) : LS(
this.get('ffzMinimizeNavigation') ? 10 :
this.get('isLeftColumnClosed') ? 50 : 240
),
var left_width = LS(f.settings.socialbar_hide ? 0 : this.get('isSocialColumnCollapsed') ? 50 : 240),
right_width = ! f.has_bttv && this.get('portraitMode') ? 0 : this.get("isRightColumnClosed") ? 0 : this.get("rightColumnWidth");
return this.get("windowWidth") - left_width - right_width - LS(60);
}.property("windowWidth", 'ffzMinimizeNavigation', "portraitMode", "isRightColumnClosed", "isLeftColumnClosed", "rightColumnWidth", "isSocialColumnCollapsed", "isSocialColumnEnabled"),
}.property("windowWidth", 'ffzMinimizeNavigation', "portraitMode", "isRightColumnClosed", "rightColumnWidth", "isSocialColumnCollapsed"),
ffzExtraHeight: function() {
return (this.get('isSocialColumnEnabled') ? this.get('ffzMinimizeNavigation') ? 10 : 50 : 0) +
return (this.get('ffzMinimizeNavigation') ? 10 : 50) +
(f.settings.channel_bar_collapse ? 10 : 60) + 15 +
(f.settings.channel_title_top === 2 ? 20 : f.settings.channel_title_top > 0 ? 55 : 0) +
(f.settings.channel_title_top ? 70 : 80);
}.property("isSocialColumnEnabled", "ffzMinimizeNavigation"),
}.property("ffzMinimizeNavigation"),
fullSizePlayerDimensions: function() {
var h = this.get('windowHeight'),
@ -321,7 +314,7 @@ FFZ.prototype.setup_layout = function() {
if ( this.get('portraitMode') ) {
var size = this.get('fullSizePlayerDimensions'),
video_below = this.get('portraitVideoBelow'),
top_height = this.get('isSocialColumnEnabled') ? this.get('ffzMinimizeNavigation') ? 10 : 50 : 0,
top_height = this.get('ffzMinimizeNavigation') ? 10 : 50,
video_height = size.height + this.get('ffzExtraHeight'),
chat_height = window_height - video_height,

View file

@ -13,7 +13,7 @@
FFZ.settings_info.automod_inline = {
type: "boolean",
value: true,
value: false,
category: "Chat Moderation",
no_bttv: 6,
@ -597,7 +597,7 @@ FFZ.settings_info.chat_font_family = {
var span = document.createElement('span');
span.style.fontFamily = val;
css = ".pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history,.ember-chat .chat-messages {" + span.style.cssText + "}";
css = ".ffz-recent-messages .chat-line,.pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history,.ember-chat .chat-messages {" + span.style.cssText + "}";
}
utils.update_css(this._chat_style, "chat_font_family", css);
@ -605,6 +605,72 @@ FFZ.settings_info.chat_font_family = {
};
FFZ.settings_info.recent_highlights = {
type: "boolean",
value: false,
category: "Chat Appearance",
no_bttv: true,
name: "Recent Highlights <span>Beta</span>",
help: "Display a Recent Highlights section at the top of chat to make sure you don't miss anything.",
on_update: function(val) {
this._roomv && this._roomv.ffzUpdateRecent();
if ( ! val )
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room;
r.set('ffz_recent_highlights', []);
r.set('ffz_recent_highlights_unread', 0);
}
}
}
FFZ.settings_info.recent_highlight_count = {
type: "button",
value: 50,
category: "Chat Appearance",
no_bttv: true,
name: "Recent Highlights Length",
help: "Set the maximum number of recent highlights to keep at once.",
method: function() {
var f = this;
utils.prompt(
"Recent Highlights Length",
"Please enter a new maximum length for the recent highlights scrollback. Please note that setting this too high may cause your computer to begin lagging as chat messages accumulate.</p><p><b>Default:</b> 50",
this.settings.recent_highlight_count,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
new_val = parseInt(new_val);
if ( Number.isNaN(new_val) || ! Number.isFinite(new_val) )
new_val = 50;
new_val = Math.max(1, new_val);
f.settings.set("recent_highlight_count", new_val);
});
},
on_update: function(val) {
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room,
rh = r && r.get('ffz_recent_highlights');
if ( rh && rh.length > val )
r.set('ffz_recent_highlights', rh.splice(Math.max(0, rh.length - val), rh.length));
}
this._roomv && this._roomv.ffzUpdateRecent();
}
}
FFZ.settings_info.emoji_scale = {
type: "select",
options: {
@ -676,9 +742,9 @@ FFZ.settings_info.chat_font_size = {
var lh = Math.max(20, Math.round((20/12)*val)),
pd = Math.floor((lh - 20) / 2);
css = ".pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history .chat-line,.ember-chat .chat-messages .chat-line { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
css = ".ffz-recent-messages .chat-line,.pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history .chat-line,.ember-chat .chat-messages .chat-line { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
if ( pd )
css += ".pinned-cheers .chat-line,.ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: " + pd + "px; }";
css += ".ffz-recent-messages .chat-line .mod-icons,.pinned-cheers .chat-line,.ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: " + pd + "px; }";
}
utils.update_css(this._chat_style, "chat_font_size", css);
@ -730,7 +796,7 @@ FFZ.settings_info.chat_ts_size = {
css = "";
else {
var lh = Math.max(20, Math.round((20/12)*val), Math.round((20/12)*this.settings.chat_font_size));
css = ".ember-chat .chat-messages .timestamp { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
css = ".ffz-recent-messages .timestamp,.ember-chat .chat-messages .timestamp { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
}
utils.update_css(this._chat_style, "chat_ts_font_size", css);

View file

@ -883,7 +883,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
// If we're viewing the chat history, update it.
var el = this.get('element'),
container = el && el.querySelector('.ffz-tab-container'),
history = container && container.querySelector('.chat-history.lv-history');
history = container && container.querySelector('.ffz-tab-container[data-page="history"] .chat-history.lv-history');
if ( history ) {
var was_at_bottom = history.scrollTop >= (history.scrollHeight - history.clientHeight),

View file

@ -30,10 +30,8 @@ FFZ.settings_info.player_stats = {
help: "Display your current stream latency (how far behind the broadcast you are) under the player, with a few useful statistics in a tooltip.",
on_update: function(val) {
if ( ! this._cindex )
return;
this._cindex.ffzUpdateMetadata('player_stats');
if ( this._cindex )
this._cindex.ffzUpdateMetadata('player_stats');
}
};
@ -199,12 +197,19 @@ FFZ.prototype.modify_twitch_player = function(player) {
},
ffzRecreatePlayer: function() {
var player = this.get('player'),
theatre = player && player.getTheatre();
var t = this,
player = this.get('player'),
theatre, fullscreen, had_player = false;
// Tell the player to destroy itself.
if ( player )
if ( player ) {
had_player = true;
fullscreen = player.fullscreen;
theatre = player.theatre;
player.fullscreen = false;
player.theatre = false;
player.destroy();
}
// Break down everything left over from that player.
this.$('#player').html('');
@ -213,7 +218,16 @@ FFZ.prototype.modify_twitch_player = function(player) {
this.set('ffz_post_player', false);
// Now, let Twitch create a new player as usual.
Ember.run.next(this.didInsertElement.bind(this));
Ember.run.next(function() {
t.didInsertElement();
had_player && setTimeout(function() {
var player = t.get('player');
if ( player ) {
//player.fullscreen = fullscreen;
player.theatre = theatre;
}
})
});
},
/*ffzUpdatePlayerPaused: function() {
@ -269,17 +283,18 @@ FFZ.prototype.modify_twitch_player = function(player) {
// Add an option to the menu to recreate the player.
var t = this,
el = this.$('.player-menu .player-menu__item--stats')[0],
el = this.$('.player-buttons-right #js-settings')[0],
container = el && el.parentElement;
if ( el && ! container.querySelector('.js-player-reset') ) {
var btn_link = utils.createElement('a', 'player-text-link js-player-reset', 'Reset Player'),
btn = utils.createElement('p', 'player-menu__item player-menu__item--reset pl-small', btn_link);
if ( el && ! container.querySelector('.ffz-player-reset') ) {
var btn = utils.createElement('button', 'player-button player-button--reset ffz-player-reset');
btn.type = 'button';
btn_link.tabindex = '-1';
btn_link.href = '#';
btn.innerHTML = '<span class="player-tip js-control-tip" data-tip="Double-Click to Reset Player"></span>' +
constants.CLOSE;
btn_link.addEventListener('click', function(e) {
jQuery(btn).on('dblclick', function(e) {
//btn.addEventListener('click', function(e) {
t.ffzRecreatePlayer();
e.preventDefault();
return false;

View file

@ -178,6 +178,28 @@ FFZ.prototype.setup_room = function() {
}
var ChannelSubs = utils.ember_lookup('service:channel-subscriptions');
if ( ChannelSubs ) {
this.log("Hooking the Ember Channel Subscriptions service.");
ChannelSubs.reopen({
populateSubNotificationTokens: function() {
var Chat = utils.ember_lookup('controller:chat'),
tokens = Chat && Chat.get('currentRoom.roomProperties.available_chat_notification_tokens');
return this._super(tokens);
},
_reloadSubNotificationToken: function(e) {
var t = this;
return this.get("api").request("get", "/api/channels/" + e + "/chat_properties").then(function(e) {
var room = f.rooms && f.rooms[e] && f.rooms[e].room;
room && room.set('roomProperties.available_chat_notification_tokens', e.available_chat_notification_tokens);
t.isDestroyed || t.populateSubNotificationTokens(e.available_chat_notification_tokens)
})
},
});
}
this.update_views('component:chat/chat-room', this.modify_room_component);
this.update_views('component:chat/chat-interface', this.modify_chat_interface);
@ -657,7 +679,8 @@ FFZ.HoverPause = {
FFZ.prototype.modify_room_component = function(component) {
var f = this,
PinnedCheers = utils.ember_lookup('service:bits-pinned-cheers');
PinnedCheers = utils.ember_lookup('service:bits-pinned-cheers'),
ChannelSubs = utils.ember_lookup('service:channel-subscriptions');
utils.ember_reopen_view(component, _.extend({
ffz_init: function() {
@ -676,9 +699,18 @@ FFZ.prototype.modify_room_component = function(component) {
this.ffzUpdateStatus();
}
var actions = this._actions || {},
var t = this,
actions = this._actions || {},
orig_show = actions.showModOverlay;
actions.accommodatePinnedMessage = function(e) {
var el = t.get('element'),
chat = el.querySelector('.js-chat-messages');
if ( chat )
chat.dataset.pinned_height = e;
};
actions.showModOverlay = function(e) {
var Channel = utils.ember_resolve('model:deprecated-channel'),
chan = Channel && Channel.find && Channel.find({id: e.sender});
@ -709,6 +741,8 @@ FFZ.prototype.modify_room_component = function(component) {
isModeratorOrHigher: this.get("room.isModeratorOrHigher")
});
}
this.ffzUpdateRecent();
},
ffz_destroy: function() {
@ -719,18 +753,181 @@ FFZ.prototype.modify_room_component = function(component) {
this.ffzRemoveKeyHook();
},
ffzUpdateRecent: function() {
var t = this,
el = this.get('element'),
container = this.get('ffz_recent_el'),
con_count = this.get('ffz_recent_count_el'),
should_show = f.settings.recent_highlights && ! f.has_bttv;
if ( ! el )
return;
if ( ! container ) {
if ( ! should_show )
return;
container = utils.createElement('ul', 'chat-history');
var expander = utils.createElement('div', 'ffz-recent-expando', 'Recent Highlights<span class="pill"></span>'),
big_el = utils.createElement('div', 'ffz-recent-messages', expander),
btn_handle = utils.createElement('span', 'ffz-handle ffz-close-button'),
super_parent = document.body.querySelector('.app-main');
con_count = expander.querySelector('.pill');
container.classList.toggle('dark', f.settings.dark_twitch);
expander.insertBefore(btn_handle, expander.firstChild);
container.dataset.docked = true;
big_el.appendChild(container);
el.appendChild(big_el);
el.classList.add('ffz-has-recent-messages');
this.set('ffz_recent_el', container);
this.set('ffz_recent_count_el', con_count);
expander.addEventListener('mousemove', function(e) {
con_count.textContent = '';
t.set('room.ffz_recent_highlights_unread', 0);
});
btn_handle.addEventListener('click', function(e) {
if ( ! big_el.classList.contains('ui-moved') || ! e.button === 0 )
return;
big_el.style.top = 0;
big_el.style.left = 0;
big_el.classList.remove('ui-moved');
big_el.parentElement.removeChild(big_el);
el.appendChild(big_el);
el.classList.add('ffz-has-recent-messages');
container.dataset.docked = true;
});
var st;
jQuery(big_el).draggable({
handle: expander,
start: function(e) {
st = container.scrollTop;
big_el.classList.add('ui-moved');
container.dataset.docked = false;
el.classList.remove('ffz-has-recent-messages');
},
stop: function(e) {
if ( big_el.parentElement !== super_parent ) {
var rect = big_el.getBoundingClientRect(),
pr = super_parent.getBoundingClientRect();
big_el.parentElement.removeChild(big_el);
super_parent.appendChild(big_el);
big_el.style.top = (rect.top - pr.top) + "px";
big_el.style.left = (rect.left - pr.left) + "px";
}
container.scrollTop = st;
}
});
jQuery(container).on('click', '.chat-line', function(e) {
if ( ! e.target || e.button !== 0 )
return;
var jq = jQuery(e.target),
cl = e.target.classList,
line = cl.contains('chat-line') ? e.target : jq.parents('.chat-line')[0],
room_id = line && line.dataset.room,
room = room_id && f.rooms[room_id] && f.rooms[room_id].room,
from = line && line.dataset.sender,
msg_id = line && line.dataset.id;
if ( cl.contains('deleted-word') ) {
jq.trigger('mouseout');
e.target.outerHTML = e.target.dataset.text;
} else if ( cl.contains('deleted-link') )
return f._deleted_link_click.call(e.target, e);
else if ( cl.contains('badge') ) {
if ( cl.contains('click_action') ) {
var badge = f.badges && f.badges[e.target.getAttribute('data-badge-id')];
if ( badge.click_action )
badge.click_action.call(f, this.get('msgObject'), e);
} else if ( cl.contains('click_url') )
window.open(e.target.dataset.url, "_blank");
else if ( cl.contains('turbo') )
window.open("/products/turbo?ref=chat_badge", "_blank");
else if ( cl.contains('subscriber') )
window.open("/" + room_id + "/subscribe?ref=in_chat_subscriber_link");
} else if ( f._click_emote(e.target, e) )
return;
else if ( (f.settings.clickable_mentions && cl.contains('user-token')) || cl.contains('from') || e.target.parentElement.classList.contains('from') ) {
var target = cl.contains('user-token') ? e.target.dataset.user : from;
if ( ! target )
return;
var bounds = line && line.getBoundingClientRect() || document.body.getBoundingClientRect(),
x = 0, right;
if ( bounds.left > 400 )
right = bounds.left - 40;
f._roomv.actions.showModOverlay.call(f._roomv, {
left: bounds.left,
right: right,
top: bounds.top + bounds.height,
real_top: bounds.top,
sender: target
});
}
});
} else if ( ! should_show ) {
jQuery(container.parentElement).remove();
this.set('ffz_recent_el', null);
this.set('ffz_recent_count_el', null);
el.classList.remove('ffz-has-recent-messages');
return;
}
var was_at_bottom = container.scrollTop >= (container.scrollHeight - container.clientHeight);
container.innerHTML = '';
con_count.textContent = container.dataset.docked ? utils.format_unread(this.get('room.ffz_recent_highlights_unread') || 0) : '';
var messages = this.get('room.ffz_recent_highlights') || [];
for(var i=0; i < messages.length; i++)
container.appendChild(f._build_mod_card_history(messages[i], null, true));
if ( was_at_bottom )
container.scrollTop = container.scrollHeight;
}.observes('room'),
ffzUpdateBits: function() {
var t = this,
channel = this.get('room.channel');
if ( ! channel )
channel = this.get('room.channel'),
bits_room = this.get('bitsRoom');
if ( ! channel || ! bits_room )
return;
PinnedCheers && PinnedCheers.dismissLocalMessage();
if ( ! channel.get('isLoaded') )
channel.load().then(function() { t._initializeBits(channel) })
else
channel.load().then(function() { bits_room.reset(); t._initializeBits(channel) })
else {
bits_room.reset();
this._initializeBits(channel);
}
ChannelSubs && ChannelSubs.populateSubNotificationTokens(this.get('room.roomProperties.available_chat_notification_tokens'));
}.observes('room'),
@ -1130,7 +1327,7 @@ FFZ.prototype._load_room_json = function(room_id, callback, data) {
var model = this.rooms[room_id] = this.rooms[room_id] || {};
for(var key in data)
if ( key !== 'users' && key !== 'room' && data.hasOwnProperty(key) )
if ( key !== 'user_badges' && key !== 'users' && key !== 'room' && data.hasOwnProperty(key) )
model[key] = data[key];
// Merge the user data.
@ -1144,6 +1341,21 @@ FFZ.prototype._load_room_json = function(room_id, callback, data) {
}
}
// Merge badge data
for(var badge_id in data.user_badges) {
var badge = this.badges[badge_id];
if ( ! badge )
continue;
for(var l=data.user_badges[badge_id], i=0, j=l.length; i < j; i++) {
var user_id = l[i],
user = model.users[user_id] = model.users[user_id] || {},
badges = user.badges = user.badges || {};
badges[badge.slot] = {id: badge_id};
}
}
// Preserve the pointer to the Room instance.
/*if ( this.rooms[room_id] )
data.room = this.rooms[room_id].room;
@ -1192,6 +1404,8 @@ FFZ.prototype._modify_room = function(room) {
ffz_banned: false,
mru_list: [],
ffz_recent_highlights: [],
ffz_recent_highlights_unread: 0,
ffzUpdateBadges: function() {
if ( this.get('isGroupRoom') )
@ -1299,7 +1513,7 @@ FFZ.prototype._modify_room = function(room) {
try {
f.add_room(this.id, this);
this.set("ffz_chatters", {});
this.set("ffz_chatters", []);
this.set("ffz_ids", this.get('ffz_ids') || {});
this.set("ffz_last_notices", this.get('ffz_last_notices') || {});
} catch(err) {
@ -1789,7 +2003,10 @@ FFZ.prototype._modify_room = function(room) {
ffzPushMessages: function(messages) {
var new_messages = [],
new_unread = 0;
new_unread = 0,
highlight_messages = [],
highlight_unread = 0;
for(var i=0; i < messages.length; i++) {
var msg = messages[i];
@ -1797,8 +2014,11 @@ FFZ.prototype._modify_room = function(room) {
new_messages.push(msg);
if ( ! (msg.tags && msg.tags.historical) && msg.style !== "admin" && msg.style !== "whisper" ) {
if ( msg.ffz_has_mention )
if ( msg.ffz_has_mention ) {
this.ffz_last_mention = Date.now();
highlight_messages.push(msg);
highlight_unread++;
}
new_unread++;
}
@ -1867,6 +2087,39 @@ FFZ.prototype._modify_room = function(room) {
this.incrementProperty("unreadCount", new_unread);
this.ffz_last_activity = Date.now();
}
if ( f.settings.recent_highlights && highlight_unread ) {
var old_highlights = this.get('ffz_recent_highlights') || [],
raw_remove = old_highlights.length + highlight_messages.length > f.settings.recent_highlight_count ?
Math.max(0, old_highlights.length - f.settings.recent_highlight_count) + highlight_messages.length : 0,
to_remove = raw_remove % 2,
trimmed = old_highlights.slice(to_remove, old_highlights.length).concat(highlight_messages),
el = f._roomv && f._roomv.get('ffz_recent_el');
this.set('ffz_recent_highlights', trimmed);
this.incrementProperty('ffz_recent_highlights_unread', highlight_unread);
if ( el && f._roomv.get('room') === this ) {
var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight);
while( el.childElementCount && to_remove-- )
el.removeChild(el.firstElementChild);
for(var i=0; i < highlight_messages.length; i++)
el.appendChild(f._build_mod_card_history(highlight_messages[i], null, true));
if ( was_at_bottom )
el.scrollTop = el.scrollHeight;
if ( el.dataset.docked ) {
el = f._roomv.get('ffz_recent_count_el');
if ( el )
el.textContent = utils.format_unread(this.get('ffz_recent_highlights_unread'));
}
}
}
},
ffzSchedulePendingFlush: function(now) {
@ -2023,7 +2276,7 @@ FFZ.prototype._modify_room = function(room) {
ffzProcessMessage: function(msg) {
if ( msg ) {
var notice_type = msg.tags && msg.tags['msg-id'],
is_resub = notice_type === 'resub',
is_resub = notice_type === 'resub' || notice_type === 'sub',
room_id = this.get('id'),
msg_id = msg.tags && msg.tags.id;
@ -2177,10 +2430,6 @@ FFZ.prototype._modify_room = function(room) {
f.api_trigger('room-message', msg);
// Also update chatters.
if ( ! is_whisper && this.chatters && ! this.chatters[msg.from] && msg.from !== 'twitchnotify' && msg.from !== 'jtv' )
this.ffzUpdateChatters(msg.from);
// We're past the last return, so store the message
// now that we know we're keeping it.
if ( msg_id ) {
@ -2195,8 +2444,8 @@ FFZ.prototype._modify_room = function(room) {
}
// Report this message to the dashboard.
if ( window !== window.parent && parent.postMessage && msg.from && msg.from !== "jtv" && msg.from !== "twitchnotify" )
parent.postMessage({from_ffz: true, command: 'chat_message', data: {from: msg.from, room: msg.room}}, "*"); //location.protocol + "//www.twitch.tv/");
if ( msg.from && msg.from !== "jtv" && msg.from !== "twitchnotify" )
this.ffzSafePM({from_ffz: true, command: 'chat_message', data: {from: msg.from, room: msg.room}}, "*"); //location.protocol + "//www.twitch.tv/");
// Flagging for review.
if ( msg.tags && msg.tags.risk === "high" )
@ -2330,8 +2579,11 @@ FFZ.prototype._modify_room = function(room) {
}.observes('unreadCount'),
ffzInitChatterCount: function() {
if ( ! this.tmiRoom )
if ( ! this.tmiRoom || ! f.settings.chatter_count ) {
this.set("ffz_chatters", []);
this.ffzUpdateChatters();
return;
}
if ( this._ffz_chatter_timer ) {
clearTimeout(this._ffz_chatter_timer);
@ -2340,26 +2592,27 @@ FFZ.prototype._modify_room = function(room) {
var room = this;
this.tmiRoom.list().done(function(data) {
var chatters = {};
var chatters = [];
data = data.data.chatters;
if ( data && data.admins )
for(var i=0; i < data.admins.length; i++)
chatters[data.admins[i]] = true;
chatters.push(data.admins[i]);
if ( data && data.global_mods )
for(var i=0; i < data.global_mods.length; i++)
chatters[data.global_mods[i]] = true;
chatters.push(data.global_mods[i]);
if ( data && data.moderators )
for(var i=0; i < data.moderators.length; i++)
chatters[data.moderators[i]] = true;
chatters.push(data.moderators[i]);
if ( data && data.staff )
for(var i=0; i < data.staff.length; i++)
chatters[data.staff[i]] = true;
chatters.push(data.staff[i]);
if ( data && data.viewers )
for(var i=0; i < data.viewers.length; i++)
chatters[data.viewers[i]] = true;
chatters.push(data.viewers[i]);
room.set("ffz_chatters", chatters);
room.ffzUpdateChatters();
}).always(function() {
room._ffz_chatter_timer = setTimeout(room.ffzInitChatterCount.bind(room), 300000);
});
@ -2367,22 +2620,31 @@ FFZ.prototype._modify_room = function(room) {
ffzUpdateChatters: function(add, remove) {
var chatters = this.get("ffz_chatters") || {};
if ( add )
chatters[add] = true;
if ( remove && chatters[remove] )
delete chatters[remove];
if ( ! f.settings.chatter_count )
return;
var chatters = this.get("ffz_chatters") || [];
if ( add && chatters.indexOf(add) === -1 )
chatters.push(add);
if ( remove ) {
var ind = chatters.indexOf(remove);
if ( ind !== -1 )
chatters.splice(ind, 1);
}
if ( f._cindex )
f._cindex.ffzUpdateMetadata('chatters');
if ( window !== window.parent && parent.postMessage )
parent.postMessage({from_ffz: true, command: 'chatter_count', data: {room: this.get('id'), chatters: Object.keys(this.get('ffz_chatters') || {}).length}}, "*"); //location.protocol + "//www.twitch.tv/");
this.ffzSafePM({from_ffz: true, command: 'chatter_count', data: {room: this.get('id'), chatters: (this.get('ffz_chatters') || []).length}}, "*"); //location.protocol + "//www.twitch.tv/");
},
ffzSafePM: function(message, origin) {
try {
if ( window !== window.parent && parent.postMessage )
return parent.postMessage(message, origin);
} catch(err) { }
},
ffzPatchTMI: function() {
var tmi = this.get('tmiRoom'),

View file

@ -382,7 +382,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
ffz_init: function() {
var t = this,
el = this.get('element'),
card = jQuery('.sc-card', el),
card = jQuery('.js-sc-card', el),
data = card && card.data('tipsy');
if ( ! data || ! data.options )
@ -418,6 +418,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
'<span class="stat">' + constants.LIVE + ' ' + utils.number_commas(data.stream.viewers) + '</span>' +
'<b>' + utils.sanitize(channel.display_name || channel.name) + '</b><br>' +
'<span class="playing">' +
(data.stream.stream_type === 'watch_party' ? '<span class="pill is-watch-party">Vodcast</span> ' : '') +
(channel.game === 'Creative' ?
'Being Creative' :
(channel.game ?

View file

@ -104,7 +104,7 @@ API.prototype.log = function(msg, data, to_json, log_json) {
API.prototype.error = function(msg, error, to_json, log_json) {
this.ffz.error('Ext #' + this.id + ' (' + this.name_key + '): ' + msg, data, to_json, log_json);
this.ffz.error('Ext #' + this.id + ' (' + this.name_key + '): ' + msg, error, to_json, log_json);
}

View file

@ -96,6 +96,18 @@ FFZ.prototype.setup_bttv_7 = function(delay) {
}
/* Update the chat input to not use FFZ's input handling.
if ( this._inputv ) {
var t = this._inputv.$("textarea");
t.off("keyup");
t.off("keydown");
t.off("keypress");
t.on("keyup", this._inputv._onKeyUp.bind(this._inputv));
t.on("keydown", this._inputv._onKeyDown.bind(this._inputv));
}//*/
// Hook into BTTV's dark mode.
cl.add('ffz-bttv');
cl.toggle('ffz-bttv-dark', settings.get('darkenedMode'));
@ -105,6 +117,7 @@ FFZ.prototype.setup_bttv_7 = function(delay) {
});
this.update_ui_link();
this._roomv && this._roomv.ffzUpdateRecent();
this.api_trigger('bttv-initialized', 7);
}

View file

@ -41,6 +41,29 @@
.svg-logo_twitch, .clips-nav__logo { fill: white }
.nav-banner {
background-color: lighten(@nav-bg-color, 10%);
}
// Chat
.clip-chat-message {
color: #ccc;
}
.view-clip__main--darker {
background-color: darken(@nav-bg-color, 2%);
}
.view-clip__smallTitle {
color: @fg-color;
& > div {
background-color: @nav-bg-color;
border-bottom: lighten(@nav-bg-color, 10%);
}
}
// Content Meta
.nv-clip-content {

View file

@ -61,7 +61,7 @@ FFZ.channel_metadata = {};
// Version
var VER = FFZ.version_info = {
major: 3, minor: 5, revision: 480,
major: 3, minor: 5, revision: 494,
toString: function() {
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
}

View file

@ -240,7 +240,7 @@ var is_android = navigator.userAgent.indexOf('Android') !== -1,
search_input.placeholder = 'Search for Settings';
search_input.type = 'text';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 51) + 'px';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 53) + 'px';
search_cont.appendChild(search_input);
container.appendChild(filtered_cont);

View file

@ -1,4 +1,5 @@
/* Chat Line Padding */
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin,

View file

@ -5,6 +5,7 @@
border-bottom-color: rgba(255,255,255, 0.5);
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -4,6 +4,7 @@
border-top: 1px solid rgba(255,255,255, 0.5);
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -4,6 +4,7 @@
border-top: 1px solid #aaa;
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -5,6 +5,7 @@
border-bottom: 1px solid #aaa;
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-bottom: 2px }

View file

@ -798,7 +798,7 @@ FFZ.prototype.tokenize_chat_line = function(msgObject, prevent_notification, del
// Mentions!
if ( ! from_me ) {
tokens = this.tokenize_mentions(tokens);
var st = this.settings.remove_filtered;
var st = (mod_or_higher && !this.settings.remove_filtered_mod) ? 0 : this.settings.remove_filtered;
for(var i=0; i < tokens.length; i++) {
var token = tokens[i],
@ -1076,14 +1076,16 @@ FFZ.prototype.render_token = function(render_links, warn_links, render_bits, tok
video_info = VIDEO_URL.exec(href);
if ( clip_info ) {
var clips = utils.ember_lookup('service:clips');
clips && clips.getClipInfo(clip_info[1]).then(function(data) {
var clips = utils.ember_lookup('service:store');
clips && clips.findRecord && clips.findRecord('clip', clip_info[1]).then(function(data) {
//clips && clips.getClipInfo(clip_info[1]).then(function(data) {
data &&
success(true, {
image: data.previewImage,
image: data.get('scaledPreviewUrl'),
image_iframe: false,
html: '<span class="ffz-clip-title">' + utils.sanitize(data.title) + '</span>' +
'Channel: ' + utils.sanitize(data.broadcasterDisplayName) +
'<br>Game: ' + utils.sanitize(data.game)
html: '<span class="ffz-clip-title">' + utils.sanitize(data.get('title')) + '</span>' +
'Channel: ' + utils.sanitize(data.get('broadcasterDisplayName')) +
'<br>Game: ' + utils.sanitize(data.get('game'))
});
});

View file

@ -90,30 +90,39 @@ metadata.player_stats = {
stats = player.getVideoInfo();
} catch(err) { }
// Check for server offset.
var delayed = undefined;
if ( this._ws_open ) {
var offset = this._ws_server_offset;
if ( isNaN(offset) || ! isFinite(offset) )
this.ws_ping();
else
delayed = offset > 5000;
}
var delay = stats && Math.round(stats.hls_latency_broadcaster / 10) / 100;
return [stats, delay, delay > 180, player_cont];
return [stats, delay, delay > 180, player_cont, delayed];
},
order: 3,
host_order: 102,
static_label: constants.GRAPH,
label: function(stats, delay, is_old) {
if ( ! this.settings.player_stats || ! stats || ! stats.hls_latency_broadcaster )
label: function(stats, delay, is_old, player_cont, delayed) {
if ( ! this.settings.player_stats || ! delay )
return null;
delayed = delayed ? '(!) ' : '';
if ( is_old )
return utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old'
else {
delay = delay.toString();
var ind = delay.indexOf('.');
return delay + (ind === -1 ? '.00' : (ind >= delay.length - 2 ? '0' : '')) + 's';
}
return delayed + utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old'
else
return delayed + delay.toFixed(2) + 's';
},
color: function(stats, delay, is_old) {
var setting = this.settings.player_stats;
if ( setting === -1 )
if ( setting === -1 || is_old )
return '';
else if ( delay > (setting * 2) )
@ -127,9 +136,11 @@ metadata.player_stats = {
player_cont.$('.js-stats-toggle').click();
},
tooltip: function(stats, delay, is_old) {
tooltip: function(stats, delay, is_old, player_cont, delayed) {
delayed = delayed ? 'Your local clock seems to be off by roughly ' + (Math.round(this._ws_server_offset / 10) / 100).toFixed(2) + ' seconds, and that could be making this inaccurate.<hr>' : '';
if ( ! stats || ! stats.hls_latency_broadcaster )
return 'Stream Latency';
return delayed + 'Stream Latency';
var bitrate;
if ( stats.playback_bytes_per_second )
@ -137,7 +148,7 @@ metadata.player_stats = {
else
bitrate = Math.round(stats.current_bitrate * 100) / 100;
return (is_old ? 'Video Information<br>' +
return delayed + (is_old ? 'Video Information<br>' +
'Broadcast ' + utils.time_to_string(Math.floor(delay), true) + ' Ago<br><br>' : 'Stream Latency<br>') +
'Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p' + stats.current_fps + '<br>' +
'Playback Rate: ' + utils.number_commas(bitrate) + ' Kbps<br>' +
@ -156,7 +167,7 @@ metadata.chatters = {
if ( ! room || ! this.settings.chatter_count )
return null;
return utils.number_commas(Object.keys(room.room.get('ffz_chatters') || {}).length);
return utils.number_commas((room.room.get('ffz_chatters') || []).length);
},
tooltip: 'Currently in Chat'

View file

@ -133,6 +133,10 @@ FFZ.settings_info.dark_twitch = {
if ( this.has_bttv )
return;
var RH = this._roomv && this._roomv.get('ffz_recent_el');
if ( RH )
RH.classList.toggle('dark', val);
(this.is_clips ? document.querySelector('html') : document.body).classList.toggle("ffz-dark", val);
var Settings = utils.ember_settings();

View file

@ -224,7 +224,9 @@ FFZ.prototype._build_following_tooltip = function(el) {
(uptime > 0 ? '<span class="stat">' + constants.CLOCK + ' ' + utils.duration_string(uptime) + '</span>' : '') +
'<span class="stat">' + constants.LIVE + ' ' + utils.number_commas(stream.viewers) + '</span>' +
'<b>' + utils.sanitize(stream.channel.display_name || stream.channel.name) + '</b><br>' +
'<span class="playing">' + (stream.channel.game === 'Creative' ? 'Being Creative' : (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing')) + (tags ? ' | ' + _.pluck(tags, "text").join(" ") : '') + '</span>';
'<span class="playing">' +
(stream.stream_type === 'watch_party' ? '<span class="pill is-watch-party">Vodcast</span> ' : '') +
(stream.channel.game === 'Creative' ? 'Being Creative' : (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing')) + (tags ? ' | ' + _.pluck(tags, "text").join(" ") : '') + '</span>';
}
if ( filtered )

View file

@ -770,7 +770,7 @@ FFZ.mod_card_pages.notes = {
utils.logviewer.get("comments/" + room_id + "?topic=" + user_id, token)
.then(utils.json).then(function(data) {
f.log("[LV] Comments: " + user_id + " in " + room_id, data);
//f.log("[LV] Comments: " + user_id + " in " + room_id, data);
history.classList.remove('loading');
// We want to listen to get new notes for this user.

View file

@ -2,7 +2,8 @@ var FFZ = window.FrankerFaceZ,
constants = require("../constants"),
utils = require("../utils"),
BANNED_SETS = {"00000turbo":true};
BANNED_SETS = {"00000turbo":true},
EXTRA_INVENTORY = ['33563'];
// -------------------
@ -154,6 +155,43 @@ FFZ.menu_pages.myemotes = {
},
render: function(view, container) {
/*var search_cont = utils.createElement('div', 'ffz-filter-container'),
search_input = utils.createElement('input', 'emoticon-selector__filter-input form__input js-filter-input text text--full-width'),
filtered_cont = utils.createElement('div', 'ffz-filter-children ffz-ui-sub-menu-page'),
was_filtered = false;
search_input.placeholder = 'Search for Emotes';
search_input.type = 'text';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 53) + 'px';
search_cont.appendChild(search_input);
container.appendChild(filtered_cont);
container.appendChild(search_cont);
search_input.addEventListener('input', function(e) {
var filter = (search_input.value || '').toLowerCase(),
groups = filtered_cont.querySelectorAll('.emoticon-grid');
for(var i=0; i < groups.length; i++) {
var el = groups[i],
emotes = el.querySelectorAll('.emoticon'),
hidden = true;
for(var j=0; j < emotes.length; j++) {
var em = emotes[j],
ehidden = filter.length && em.getAttribute('data-filter').indexOf(filter) === -1;
em.classList.toggle('hidden', ehidden);
hidden = hidden && ehidden;
}
el.classList.toggle('hidden', hidden);
el.classList.toggle('collapsable', ! filter.length);
}
});
container = filtered_cont;*/
FFZ.menu_pages.myemotes.render_lists.call(this, view, container, false);
}
},
@ -199,7 +237,9 @@ FFZ.menu_pages.myemotes = {
gathered_emotes = [];
// Start with Twitch Sets
var gathered_favorites = this.settings.favorite_emotes['twitch-inventory'] || [];
var gathered_favorites = this.settings.favorite_emotes['twitch-inventory'] || [],
gathered_channels = {},
other_channels = [];
for(var set_id in twitch_sets) {
if ( ! twitch_sets.hasOwnProperty(set_id) || ( ! favorites_only && ! this.settings.global_emotes_in_menu && set_id === '0' ) )
@ -213,7 +253,7 @@ FFZ.menu_pages.myemotes = {
if ( ! set.length )
continue;
if ( this._twitch_inventory_sets.indexOf(set_id) !== -1 ) {
if ( this._twitch_inventory_sets.indexOf(set_id) !== -1 || EXTRA_INVENTORY.indexOf(set_id) !== -1 ) {
for(var i=0; i < set.length; i++)
if ( ! favorites_only || gathered_favorites.indexOf(set[i].id) !== -1 )
gathered_emotes.push(set[i]);
@ -228,6 +268,12 @@ FFZ.menu_pages.myemotes = {
if ( favorites_only && (! favorites_list || ! favorites_list.length) )
continue;
if ( menu_id !== 'unknown' ) {
var gathered = gathered_channels[menu_id] = gathered_channels[menu_id] || [];
gathered.push(set_id);
continue;
}
var sort_key = 0,
menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, set_id, set, favorites_only);
@ -240,6 +286,33 @@ FFZ.menu_pages.myemotes = {
sets.push([[sort_key, menu_id], menu]);
}
for(var menu_id in gathered_channels) {
var gathered = [],
stuff = gathered_channels[menu_id];
if ( ! stuff.length )
continue;
for(var i=0; i < stuff.length; i++) {
var set_id = stuff[i],
set = twitch_sets[set_id];
for(var j=0; j < set.length; j++)
gathered.push([set_id, set[j]]);
}
var sort_key = 0,
menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, stuff[0], gathered, favorites_only);
if ( menu_id.indexOf('global') !== -1 )
sort_key = 100;
else if ( menu_id.substr(0,2) === '--' || menu_id === 'turbo' )
sort_key = 75;
if ( menu )
sets.push([[sort_key, menu_id], menu]);
}
// Handle the gathered single emotes.
if ( gathered_emotes.length ) {
var menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, 'inventory', gathered_emotes, favorites_only);
@ -338,18 +411,22 @@ FFZ.menu_pages.myemotes = {
return true;
},
toggle_section: function(heading, container) {
toggle_section: function(heading, container, set_state) {
var menu = heading.parentElement,
set_id = menu.getAttribute('data-set'),
collapsed_list = this.settings.emote_menu_collapsed,
is_collapsed = collapsed_list.indexOf(set_id) === -1;
has_state = set_state !== undefined,
is_collapsed = has_state ? set_state : collapsed_list.indexOf(set_id) === -1;
if ( ! is_collapsed )
collapsed_list.removeObject(set_id);
else
collapsed_list.push(set_id);
if ( ! has_state ) {
if ( ! is_collapsed )
collapsed_list.removeObject(set_id);
else
collapsed_list.push(set_id);
this.settings.set('emote_menu_collapsed', collapsed_list, true);
}
this.settings.set('emote_menu_collapsed', collapsed_list, true);
menu.classList.toggle('collapsed', !is_collapsed);
if ( is_collapsed )
@ -382,7 +459,7 @@ FFZ.menu_pages.myemotes = {
menu.classList.add('collapsable');
menu.appendChild(heading);
menu.classList.toggle('collapsed', collapsed);
heading.addEventListener('click', function() { FFZ.menu_pages.myemotes.toggle_section.bind(f)(this, emotes); });
heading.addEventListener('click', function() { FFZ.menu_pages.myemotes.toggle_section.bind(f)(this, emotes); });
}
var set = [];
@ -420,6 +497,7 @@ FFZ.menu_pages.myemotes = {
em.classList.toggle('ffz-is-favorite', favorites_only);
em.setAttribute('data-ffz-emoji', emoji.code);
em.setAttribute('data-filter', emoji.name.toLowerCase() + ' :' + emoji.short_name.toLowerCase() + ':');
em.alt = emoji.raw;
em.addEventListener('click', this._add_emote.bind(this, view, emoji.raw, "emoji", emoji.raw));
@ -502,6 +580,11 @@ FFZ.menu_pages.myemotes = {
}
set.sort(function(a,b) {
if ( Array.isArray(a) )
a = a[1];
if ( Array.isArray(b) )
b = b[1];
var an = a.code.toLowerCase(),
bn = b.code.toLowerCase();
@ -514,8 +597,16 @@ FFZ.menu_pages.myemotes = {
for(var i=0; i < set.length; i++) {
var emote = set[i],
code = constants.KNOWN_CODES[emote.code] || emote.code,
is_favorite = favorites.indexOf(emote.id) !== -1;
esid = set_id,
favs = favorites;
if ( Array.isArray(emote) ) {
esid = emote[0];
emote = emote[1];
favs = this.settings.favorite_emotes["twitch-" + esid] || [];
}
var code = constants.KNOWN_CODES[emote.code] || emote.code,
is_favorite = favs.indexOf(emote.id) !== -1;
if ( favorites_only && ! is_favorite )
continue;
@ -525,6 +616,7 @@ FFZ.menu_pages.myemotes = {
em.className = 'emoticon ffz-tooltip ffz-can-favorite';
em.setAttribute('data-emote', emote.id);
em.setAttribute('data-filter', code.toLowerCase());
em.alt = code;
em.classList.toggle('ffz-favorite', is_favorite);
@ -541,13 +633,13 @@ FFZ.menu_pages.myemotes = {
em.style.backgroundImage = img_set;
}
em.addEventListener("click", function(id, c, e) {
em.addEventListener("click", function(id, c, q, e) {
e.preventDefault();
if ( (e.shiftKey || e.shiftLeft) && f.settings.clickable_emoticons )
window.open("https://twitchemotes.com/emote/" + id);
else
this._add_emote(view, c, "twitch-" + set_id, id, e);
}.bind(this, emote.id, code));
this._add_emote(view, c, "twitch-" + q, id, e);
}.bind(this, emote.id, code, esid));
c++;
emotes.appendChild(em);
@ -634,6 +726,7 @@ FFZ.menu_pages.myemotes = {
em.setAttribute('data-ffz-emote', emote.id);
em.setAttribute('data-ffz-set', set.id);
em.setAttribute('data-filter', emote.name.toLowerCase());
em.style.backgroundImage = 'url("' + emote.urls[1] + '")';
em.style.backgroundImage = '-webkit-' + img_set;

View file

@ -1181,6 +1181,7 @@ module.exports = FFZ.utils = {
return (loyalty ? '.ffz-no-loyalty ' : '') + '.from-display-preview[data-room="' + room_id + '"] .badge.' + badge_id + (loyalty ? '' : '.version-' + version) +
(loyalty ? ',.ffz-no-loyalty ' : ',') + '.chat-line[data-room="' + room_id + '"] .badge.' + badge_id + (loyalty ? '' : '.version-' + version) + '{' +
'background-color:transparent;' +
WEBKIT + 'mask-image: none;' +
'background-image:url("' + img_1x + '");' +
'background-image:' + WEBKIT + 'image-set(url("' + img_1x + '") 1x' + (img_2x ? ',url("' + img_2x + '") 2x' : '') + (img_4x ? ',url("' + img_4x + '") 4x' : '') + ')}';
},