1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-06 06:10: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 ?