1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00

3.5.511. Misc Twitch fixes. Add setting to disable custom mod badges. Add API event for highlighted messages. Allow API to remove chat messages.

This commit is contained in:
SirStendec 2017-08-16 13:24:55 -04:00
parent 81040f1608
commit aa4f999c29
18 changed files with 689 additions and 453 deletions

View file

@ -1,3 +1,55 @@
<div class="list-header">3.5.511 <time datetime="2017-08-12">(2017-08-12)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Bits rendering after Twitch removed the Ember bits-tags service.</li>
</ul>
<div class="list-header">3.5.510 <time datetime="2017-08-10">(2017-08-10)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: <code>Chat Appearance > Enable Custom Badge Images</code> setting that can be used to disable custom mod badges for channels.</li>
<li>Fixed: Re-sub messages not showing in channels without custom sub badges and with <code>Chat Appearance > Old-Style Subscriber Notices</code> enabled.</li>
</ul>
<div class="list-header">3.5.509 <time datetime="2017-08-07">(2017-08-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>API Changed: Throw the <code>room-recent-highlights</code> event even if the Recent Highlights feature is disabled.</li>
</ul>
<div class="list-header">3.5.508 <time datetime="2017-08-07">(2017-08-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>API Added: <code>room-recent-highlights</code> event for triggering behaviors when new highlighted messages are displayed.</li>
<li>API Changed: Allow extensions to repress chat messages by marking them as removed in the <code>room-message</code> API event.</li>
</ul>
<div class="list-header">3.5.507 <time datetime="2017-08-02">(2017-08-02)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Dark theme for the dashboard.</li>
<li>Fixed: Moderation cards not rendering correctly when you start by opening your own mod card.</li>
</ul>
<div class="list-header">3.5.506 <time datetime="2017-07-26">(2017-07-26)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Setting to hide Trending Emotes in chat.</li>
<li>Fixed: Make Minimal Chat input hide the trending emotes stuff too.</li>
</ul>
<div class="list-header">3.5.505 <time datetime="2017-07-24">(2017-07-24)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Minor dark theme tweaks.</li>
<li>Fixed: A scrollbar would appear at the side of the page at times due to tooltips.</li>
<li>Fixed: Don't escape HTML for legacy sidebar tooltips.</li>
</ul>
<div class="list-header">3.5.504 <time datetime="2017-07-13">(2017-07-13)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Support for the <code>AUTOMOD_SMALLER</code> experiment. In-Line AutoMod is not yet working when you are part of that experiment.</li>
</ul>
<div class="list-header">3.5.503 <time datetime="2017-07-13">(2017-07-13)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Emotes parsing in local messages.</li>
<li>Fixed: Use the <code>user-emotes</code> service in all places since <code>tmiSession</code>'s emote parser has been removed.</li>
</ul>
<div class="list-header">3.5.502 <time datetime="2017-07-13">(2017-07-13)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Dark theme for chat.</li>
@ -11,62 +63,5 @@
<li>Fixed: Dark theme for chat.</li>
</ul>
<div class="list-header">3.5.500 <time datetime="2017-07-12">(2017-07-12)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>This version is half-way between 0 and 1000.</li>
<li>What makes a man turn neutral?</li>
<!-- Were you just born with a heart full of neutrality? -->
<li>&nbsp;</li>
<li>Remember to <a href="http://iadayofaction.org" target="_blank">support the Open Internet</a>!</li>
<li>&nbsp;</li>
<li>Fixed: Pulse dark theme issues.</li>
<li>Fixed: Take part in the net neutrality spinners.</li>
<li>Added: Temporary option to disable net neutrality spinners.</li>
</ul>
<div class="list-header">3.5.499 <time datetime="2017-06-30">(2017-06-30)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Updated subscriber badge not being transparent.</li>
<li>Fixed: Unable to use player controls in theater mode with Hide Whispers in Theater Mode enabled.</li>
</ul>
<div class="list-header">3.5.498 <time datetime="2017-06-30">(2017-06-30)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Dark theme for the Video Manager's Clips page.</li>
<li>Fixed: Twitch's poor design choice regarding whispers in theater mode. Again.</li>
<li>Fixed: Unable to close chatter list after opening it with the chat header turned off.</li>
</ul>
<div class="list-header">3.5.497 <time datetime="2017-06-22">(2017-06-22)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Position of player controls in theater mode.</li>
<li>Fixed: Unnecessary bottom border under the player in theater mode.</li>
</ul>
<div class="list-header">3.5.496 <time datetime="2017-06-22">(2017-06-22)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Input handling.</li>
<li>Fixed: Minimal Chat Header not hiding the chat header.</li>
</ul>
<div class="list-header">3.5.495 <time datetime="2017-06-11">(2017-06-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Game Purchase share messages in chat.</li>
</ul>
<div class="list-header">3.5.494 <time datetime="2017-06-11">(2017-06-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: By default, messages from moderators will no longer be removed if they contain banned words. Configurable via <code>Chat Filtering > Remove Messages from Moderators</code>.</li>
<li>Fixed: Bits UI breaking when you switch chat rooms.</li>
<li>Fixed: Incorrect fullscreen and theater mode states when resetting the player.</li>
</ul>
<div class="list-header">3.5.493 <time datetime="2017-06-06">(2017-06-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Tag Vodcasts in the navigation bar's Following tooltip and the enhanced tooltips for live channels on the social bar.</li>
<li>Fixed: New logviewer messages coming in would erase the name history tab of mod cards and display chat instead.</li>
<li>Fixed: Dark theme tweaks.</li>
</ul>
<div class="list-header" id="ffz-old-news-button"><a href="#">View Older</a></div>
<div id="ffz-old-news"></div>

View file

@ -1211,6 +1211,33 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: rgba(255,255,255,0.2);
}
.ffz-dark .dash-column { border: none }
.ffz-dark .js-dashboard-chat-module > div { border-right: none !important }
.ffz-dark .vod-vertical-nav {
background-color: #191919;
border-color: #474747;
}
.ffz-dark .vod-vertical-nav__list-item .active,
.ffz-dark .vod-vertical-nav__list-item .active:hover,
.ffz-dark .vod-vertical-nav__list-item .active:active,
.ffz-dark .vod-vertical-nav__list-item .active:focus {
background-color: #6441a5;
}
.ffz-dark .vod-vertical-nav__link:hover,
.ffz-dark .vod-vertical-nav__link:active,
.ffz-dark .vod-vertical-nav__link:focus {
background-color: #392e5c;
}
.ffz-dark .dashboard-page div[style*="background"][style*="#f9f8fc"] {
background-color: #191919 !important
}
/* Front Page: Pulse */
@ -1335,6 +1362,11 @@ body.ffz-dark:not([data-page="teams#show"]),
/* Playlist */
.ffz-dark .cn-chat-replay-header {
background: transparent;
border: none;
}
.ffz-dark .cn-chat-replay-header,
.ffz-dark .ember-chat .chat-header {
box-shadow: inset 0 -1px 0 0 rgba(255,255,255,0.2);
@ -1669,6 +1701,14 @@ body.ffz-dark:not([data-page="teams#show"]),
}
.ffz-dark .activity-comments {
border-color: #474747;
}
.ffz-dark .activity-comment:hover {
background-color: rgba(255,255,255,0.2);
}
.ffz-dark .activity-card__comments {
background-color: #121212;
box-shadow:inset 0 1px 0 #474747;

View file

@ -1,3 +1,60 @@
<div class="list-header">3.5.500 <time datetime="2017-07-12">(2017-07-12)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>This version is half-way between 0 and 1000.</li>
<li>What makes a man turn neutral?</li>
<!-- Were you just born with a heart full of neutrality? -->
<li>&nbsp;</li>
<li>Remember to <a href="http://iadayofaction.org" target="_blank">support the Open Internet</a>!</li>
<li>&nbsp;</li>
<li>Fixed: Pulse dark theme issues.</li>
<li>Fixed: Take part in the net neutrality spinners.</li>
<li>Added: Temporary option to disable net neutrality spinners.</li>
</ul>
<div class="list-header">3.5.499 <time datetime="2017-06-30">(2017-06-30)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Updated subscriber badge not being transparent.</li>
<li>Fixed: Unable to use player controls in theater mode with Hide Whispers in Theater Mode enabled.</li>
</ul>
<div class="list-header">3.5.498 <time datetime="2017-06-30">(2017-06-30)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Dark theme for the Video Manager's Clips page.</li>
<li>Fixed: Twitch's poor design choice regarding whispers in theater mode. Again.</li>
<li>Fixed: Unable to close chatter list after opening it with the chat header turned off.</li>
</ul>
<div class="list-header">3.5.497 <time datetime="2017-06-22">(2017-06-22)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Position of player controls in theater mode.</li>
<li>Fixed: Unnecessary bottom border under the player in theater mode.</li>
</ul>
<div class="list-header">3.5.496 <time datetime="2017-06-22">(2017-06-22)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Input handling.</li>
<li>Fixed: Minimal Chat Header not hiding the chat header.</li>
</ul>
<div class="list-header">3.5.495 <time datetime="2017-06-11">(2017-06-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Game Purchase share messages in chat.</li>
</ul>
<div class="list-header">3.5.494 <time datetime="2017-06-11">(2017-06-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: By default, messages from moderators will no longer be removed if they contain banned words. Configurable via <code>Chat Filtering > Remove Messages from Moderators</code>.</li>
<li>Fixed: Bits UI breaking when you switch chat rooms.</li>
<li>Fixed: Incorrect fullscreen and theater mode states when resetting the player.</li>
</ul>
<div class="list-header">3.5.493 <time datetime="2017-06-06">(2017-06-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Tag Vodcasts in the navigation bar's Following tooltip and the enhanced tooltips for live channels on the social bar.</li>
<li>Fixed: New logviewer messages coming in would erase the name history tab of mod cards and display chat instead.</li>
<li>Fixed: Dark theme tweaks.</li>
</ul>
<div class="list-header">3.5.492 <time datetime="2017-06-06">(2017-06-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Player size.</li>

View file

@ -781,7 +781,7 @@ FFZ.prototype.modify_chat_input = function(component) {
in_conversation = ConvoInput && this.parentView instanceof ConvoInput,
room = ! in_conversation && this.get('parentView.room'),
room_id = room && room.get('id'),
tmi = in_conversation ? window.TMI && TMI._sessions && TMI._sessions[0] : room && room.tmiSession,
user_emotes = utils.ember_lookup('service:user-emotes'),
set_name, replacement, url, is_inventory, is_sub_set, fav_list,
emote_set, emote, emote_id, code, sort_factor, is_fav,
@ -796,8 +796,8 @@ FFZ.prototype.modify_chat_input = function(component) {
return {};
if ( tmi ) {
var es = tmi.getEmotes();
if ( user_emotes ) {
var es = user_emotes.allEmotes;
if ( es && es.emoticon_sets ) {
for(var set_id in es.emoticon_sets) {
emote_set = es.emoticon_sets[set_id];

View file

@ -45,6 +45,39 @@ FFZ.basic_settings.delayed_chat = {
};
FFZ.settings_info.custom_badge_images = {
type: "boolean",
value: true,
category: "Chat Appearance",
name: "Enable Custom Badge Images",
help: "Display custom mod badges for channels that have them set.",
on_update: function(val) {
var rs = this._room_style;
if ( ! rs )
return;
for(var room_id in this.rooms) {
var room = this.rooms[room_id];
room && utils.update_css(rs, room_id, (val ? utils.moderator_css(room) : '') + (room.css || ''));
}
}
}
FFZ.settings_info.disable_trending_emotes = {
type: "boolean",
value: false,
category: "Chat Appearance",
name: "Disable Trending Emotes",
help: "Disable the trending emotes section above the chat input box on channels where it exists.",
on_update: utils.toggle_cls('ffz-hide-trending-emotes')
}
FFZ.settings_info.minimal_chat = {
type: "select",
options: {
@ -351,8 +384,9 @@ FFZ.prototype.refresh_chat = function() {
}
FFZ.prototype.setup_chatview = function() {
document.body.classList.toggle("ffz-minimal-chat-head", this.settings.minimal_chat === 1 || this.settings.minimal_chat === 3);
document.body.classList.toggle("ffz-minimal-chat-input", this.settings.minimal_chat === 2 || this.settings.minimal_chat === 3);
utils.toggle_cls('ffz-minimal-chat-head')(this.settings.minimal_chat === 1 || this.settings.minimal_chat === 3);
utils.toggle_cls('ffz-minimal-chat-input')(this.settings.minimal_chat === 2 || this.settings.minimal_chat === 3);
utils.toggle_cls('ffz-hide-trending-emotes')(this.settings.disable_trending_emotes);
this.log("Hooking the Ember Chat controller.");
@ -1292,12 +1326,16 @@ FFZ.prototype.modify_chat_room_manager = function(component) {
// ----------------------
FFZ.prototype.connect_extra_chat = function() {
this.log("App Path: " + App.currentPath);
var user = this.get_user();
if ( user && user.login ) {
// Make sure we're in the user's room.
if ( ! this.rooms[user.login] || this.rooms[user.login].room ) {
var Room = utils.ember_resolve('model:room');
Room && Room.findOne(user.login);
var Room = utils.ember_resolve('model:room'),
room = Room && Room.findOne(user.login);
if ( room && App.currentPath === 'user.chat' )
room.set('isEmbedChat', true);
}
}
@ -1356,8 +1394,10 @@ FFZ.prototype._join_room = function(room_id, no_rebuild) {
// Make sure we're not already there.
if ( ! this.rooms[room_id] || ! this.rooms[room_id].room ) {
// Okay, fine. Get it.
var Room = utils.ember_resolve('model:room');
Room && Room.findOne(room_id);
var Room = utils.ember_resolve('model:room'),
room = Room && Room.findOne(room_id);
if ( room && App.currentPath === 'user.chat' )
room.set('isEmbedChat', true);
}

View file

@ -939,7 +939,7 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
}),
clickedChanged: Ember.observer("hasClickedFlaggedMessage", function() {
if ( f.settings.automod_inline )
if ( ! this.get('isAutoModPromptSmaller') && f.settings.automod_inline )
this.$(".mod-icons").replaceWith(this.buildModIconsHTML());
else
this.ffzRender();
@ -955,7 +955,7 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
}.property('msgObject.is_pinned_cheer'),
ffzUserLevel: function() {
if ( this.get('isStaff') )
if ( this.get('isStaff') || this.get('msgObject.from') === 'AutoMod' )
return 5;
else if ( this.get('isAdmin') )
return 4;
@ -1054,7 +1054,7 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
}
}
if ( f.settings.automod_inline && is_tb ) {
if ( ! this.get('isAutoModPromptSmaller') && f.settings.automod_inline && is_tb ) {
var clicked = this.get('hasClickedFlaggedMessage'),
inactive = clicked ? ' inactive' : '';
@ -1188,14 +1188,26 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
buildAutoModHTML: function() {
if ( this.get('hasClickedFlaggedMessage') )
return '<div class="system-msg">Thank you for your response!</div>';
return ' <span class="system-msg">Thank you for your response!</span>';
return '<p class="inline-warning">' + TB_TOOLTIP + '</p>' +
'<div class="pd-y-1 clearfix">' +
'<a class="button button--small button--alert float-left mg-r-1 tb-button" data-action="no">Deny</a>' +
'<a class="button button--small float-left mg-r-1 tb-button" data-action="yes">Allow</a>' +
'<a class="button button--small button--text float-left tb-button" data-action="not sure">Not Sure</a>' +
'</div>';
if ( ! this.get('isAutoModPromptSmaller') )
return '<p class="inline-warning">' + TB_TOOLTIP + '</p>' +
'<div class="pd-y-1 clearfix">' +
'<a class="button button--small button--alert float-left mg-r-1 tb-button" data-action="no">Deny</a>' +
'<a class="button button--small float-left mg-r-1 tb-button" data-action="yes">Allow</a>' +
'<a class="button button--small button--text float-left tb-button" data-action="not sure">Not Sure</a>' +
'</div>';
var line = f._build_mod_card_history(this.get('msgObject.autoModRejectedMsgObject'), null, true, null, null, false);
line.classList.add('mg-y-05');
return ' <span class="system-msg">Allow will post it to chat.</span>' +
'<div class="float-right">' +
'<a class="button button--text button--small tb-button" data-action="yes">Allow</a>' +
'<a class="button button--text button--small tb-button" data-action="no">Deny</a>' +
'</div>' +
'<div style="clear:both"></div>' +
line.outerHTML;
},
ffzRender: function() {
@ -1210,7 +1222,7 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
this.buildDeletedMessageHTML() : this.buildMessageHTML();
}
if ( ! f.settings.automod_inline && this.get('msgObject.autoModRejected') )
if ( (this.get('isAutoModPromptSmaller') || ! f.settings.automod_inline) && this.get('msgObject.autoModRejected') )
output += this.buildAutoModHTML();
el.innerHTML = output;
@ -1513,11 +1525,10 @@ FFZ.prototype._modify_chat_subline = function(component, is_whisper) {
return;
else if ( (f.settings.clickable_mentions && cl.contains('user-token')) || cl.contains('from') || cl.contains('to') || e.target.parentElement.classList.contains('from') || e.target.parentElement.classList.contains('to') ) {
var target = cl.contains('user-token') ?
e.target.getAttribute('data-user') :
(cl.contains('from') || e.target.parentElement.classList.contains('from')) ?
var target = e.target.getAttribute('data-user') ||
((cl.contains('from') || e.target.parentElement.classList.contains('from')) ?
from :
this.get('msgObject.to');
this.get('msgObject.to'));
if ( ! target )
return;

View file

@ -699,7 +699,9 @@ FFZ.prototype.modify_moderation_card = function(component) {
var chat = utils.ember_lookup('controller:chat'),
room_id = chat && chat.get('currentRoom.id'),
user_id = this.get('cardInfo.user.id');
user_id = this.get('cardInfo.user.id'),
user = f.get_user(),
is_me = user && user.login === user_id;
if (( this._lv_sock_room && this._lv_sock_room !== room_id ) || (this._lv_sock_user && this._lv_sock_user !== user_id) ) {
f.lv_ws_unsub('logs-' + this._lv_sock_room + '-' + this._lv_sock_user);
@ -710,6 +712,8 @@ FFZ.prototype.modify_moderation_card = function(component) {
if ( f.settings.mod_card_history )
this.ffzRenderHistory();
Ember.run.next(this.ffzFixDefaultActions.bind(this));
// Highlight this user's chat messages.
if ( f.settings.highlight_messages_with_mod_card )
utils.update_css(f._chat_style, 'mod-card-highlight', styles['chat-user-bg'].replace(/{user_id}/g, this.get('cardInfo.user.id')));
@ -950,6 +954,334 @@ FFZ.prototype.modify_moderation_card = function(component) {
utils.update_css(f._chat_style, 'mod-card-highlight');
},
ffzFixDefaultActions: function() {
var el = this.get('element'),
t = this,
line,
is_mod = t.get('cardInfo.isModeratorOrHigher'),
ban_reasons,
chat = utils.ember_lookup('controller:chat'),
user = f.get_user(),
room = chat && chat.get('currentRoom'),
room_id = room && room.get('id'),
ffz_room = f.rooms && f.rooms[room_id] || {},
is_broadcaster = user && room_id === user.login,
user_id = this.get('cardInfo.user.id'),
is_me = user && user.login === user_id,
alias = f.aliases[user_id],
handle_key,
ban_reason = function() {
return ban_reasons && ban_reasons.value ? ' ' + ban_reasons.value : "";
},
alias_btn = utils.createElement('button', 'alias button float-left button--icon-only html-tooltip');
alias_btn.innerHTML = '<figure class="icon">' + constants.EDIT + '</figure>';
alias_btn.title = "Set Alias";
alias_btn.addEventListener('click', function() {
var user = t.get('cardInfo.user.id'),
alias = f.aliases[user],
results = f.format_display_name(t.get('cardInfo.user.display_name'), user, true);
utils.prompt(
"Alias for <b" + (results[1] ? ' class="html-tooltip" title="' + utils.quote_attr(results[1]) + '">' : '>') + results[0] + "</b>",
"Please enter an alias for the user. Leave it blank to remove the alias.",
alias,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
new_val = new_val.trim();
if ( ! new_val )
new_val = undefined;
f.aliases[user] = new_val;
f.save_aliases();
// Update UI
f._update_alias(user);
var name = el.querySelector('h4.name');
if ( name ) {
name.classList.toggle('ffz-alias', new_val);
var results = f.format_display_name(t.get('cardInfo.user.display_name'), user_id);
name.innerHTML = results[0];
name.title = results[1] || '';
if ( results[1] )
jQuery(name).tipsy({html: true, gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
}
});
});
if ( is_me === this._ffz_was_me )
return;
this._ffz_was_me = is_me;
if ( is_me ) {
jQuery('.ffz-extra-controls', el).remove();
line = utils.createElement('div', 'extra-interface ffz-extra-me-controls moderation-card__actions clearfix');
line.appendChild(alias_btn);
el.appendChild(line);
return;
} else
jQuery('.ffz-extra-me-controls', el).remove();
// Move the default buttons.
var def_actions = el.querySelector('.moderation-card__actions .clearfix');
if ( def_actions ) {
def_actions = def_actions.parentElement;
var def_line = def_actions.querySelector('.clearfix'),
bad_line = def_actions.querySelector('.moderation-card__controls');
if ( def_line && bad_line ) {
var children = bad_line.querySelectorAll('button');
for(var i=0; i < children.length; i++) {
bad_line.removeChild(children[i]);
def_line.appendChild(children[i]);
}
bad_line.classList.add('hidden');
}
}
// Additional Buttons
if ( is_mod ) {
el.classList.add('ffz-is-mod');
if ( f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
line = utils.createElement('div', 'extra-interface ffz-extra-controls moderation-card__actions clearfix');
var build_cmd = function(user, room, cmd) {
var lines = utils.replace_cmd_variables(cmd, user, room).split(/\s*<LINE>\s*/g),
reason = ban_reason();
if ( reason ) {
for(var i=0; i < lines.length; i++) {
var match = TO_REG.exec(lines[i]);
if ( match ) {
if ( ! match[2] )
lines[i] += ' 600';
if ( ! match[3] )
lines[i] += reason;
break;
} else {
match = BAN_REG.exec(lines[i]);
if ( match ) {
if ( ! match[2] )
lines[i] += reason;
break;
}
}
}
}
return lines;
},
add_btn_click = function(cmd) {
var user = t.get('cardInfo.user'),
chat_controller = utils.ember_lookup('controller:chat'),
room = chat_controller && chat_controller.get('currentRoom');
if ( ! room )
return;
var lines = build_cmd(user, room, cmd);
for(var i=0; i < lines.length; i++)
room.send(lines[i], true);
},
add_btn_make = function(label, cmd) {
var btn = utils.createElement('button', 'button ffz-no-bg', utils.sanitize(label));
jQuery(btn).tipsy({
html: true,
gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n'),
title: function() {
var user = t.get('cardInfo.user'),
chat_controller = utils.ember_lookup('controller:chat'),
room = chat_controller && chat_controller.get('currentRoom');
lines = build_cmd(user, room, cmd),
title = _.map(lines, utils.sanitize).join('<br>');
return "Custom Command" + (lines.length > 1 ? 's' : '') +
"<br>" + title;
}
});
btn.addEventListener('click', add_btn_click.bind(this, cmd));
return btn;
};
for(var i=0; i < f.settings.mod_card_buttons.length; i++) {
var label, cmd, pair = f.settings.mod_card_buttons[i];
if ( ! Array.isArray(pair) ) {
cmd = pair;
label = cmd.split(' ', 1)[0];
} else {
label = pair[0];
cmd = pair[1];
}
utils.CMD_VAR_REGEX.lastIndex = 0;
if ( ! utils.CMD_VAR_REGEX.test(cmd) ) {
var lines = cmd.split(/\s*<LINE>\s*/g);
lines[0] += ' {user}';
cmd = lines.join("<LINE>");
}
line.appendChild(add_btn_make(label, cmd));
}
el.appendChild(line);
}
var btn_click = function(timeout) {
var user_id = t.get('cardInfo.user.id'),
room = utils.ember_lookup('controller:chat').get('currentRoom');
if ( timeout === -1 )
room.send("/unban " + user_id, true);
else
room.send("/timeout " + user_id + " " + timeout + ban_reason(), true);
},
btn_make = function(timeout) {
var btn = utils.createElement('button', 'button ffz-no-bg');
btn.innerHTML = utils.duration_string(timeout);
btn.title = "Timeout User for " + utils.number_commas(timeout) + " Second" + (timeout != 1 ? "s" : "");
if ( f.settings.mod_card_hotkeys && timeout === 600 )
btn.title = "(T)" + btn.title.substr(1);
else if ( f.settings.mod_card_hotkeys && timeout === 1 )
btn.title = "(P)urge - " + btn.title;
jQuery(btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
btn.addEventListener('click', btn_click.bind(this, timeout));
return btn;
};
if ( f.settings.mod_card_durations && f.settings.mod_card_durations.length ) {
// Extra Moderation
line = utils.createElement('div', 'extra-interface ffz-extra-controls moderation-card__actions clearfix');
line.appendChild(btn_make(1));
var s = utils.createElement('span', 'right');
line.appendChild(s);
for(var i=0; i < f.settings.mod_card_durations.length; i++)
s.appendChild(btn_make(f.settings.mod_card_durations[i]));
el.appendChild(line);
// Fix Other Buttons
this.$("button.timeout").remove();
}
if ( f.settings.mod_card_reasons && f.settings.mod_card_reasons.length ) {
// Moderation Reasons
line = utils.createElement('div', 'extra-interface ffz-extra-controls moderation-card__actions clearfix');
ban_reasons = utils.createElement('select', 'ffz-ban-reasons', '<option value="">Select a Ban ' + (f.settings.mod_card_hotkeys ? '(R)' : 'R') + 'eason</option>');
line.appendChild(ban_reasons);
for(var i=0; i < f.settings.mod_card_reasons.length; i++) {
var opt = utils.createElement('option'), r = f.settings.mod_card_reasons[i];
opt.value = r;
opt.textContent = (i+1) + ') ' + r;
ban_reasons.appendChild(opt);
}
el.appendChild(line);
}
var ban_btn = el.querySelector('button.ban');
if ( ban_btn ) {
if ( f.settings.mod_card_hotkeys )
ban_btn.setAttribute('title', '(B)an User');
// Unban Button
var unban_btn = utils.createElement('button', 'unban button button--icon-only light');
unban_btn.innerHTML = '<figure class="icon">' + CHECK + '</figure>';
unban_btn.title = (f.settings.mod_card_hotkeys ? "(U)" : "U") + "nban User";
jQuery(unban_btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
unban_btn.addEventListener("click", btn_click.bind(this, -1));
jQuery(ban_btn).after(unban_btn);
}
}
// Tooltips for ban and ignore.
jQuery("button.ignore, button.ban").tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
// More Fixing Other Buttons
var op_btn = el.querySelector('button.mod');
if ( op_btn ) {
var can_op = is_broadcaster || (user && user.is_admin) || (user && user.is_staff);
if ( ! can_op )
op_btn.parentElement.removeChild(op_btn);
}
// Follow Button
var follow_button = el.querySelector(".follow-button");
if ( follow_button )
jQuery(follow_button).tipsy({title: function() { return follow_button.classList.contains('is-following') ? "Unfollow" : "Follow"}});
// Whisper and Message Buttons
var msg_btn = el.querySelector("button.message-button");
if ( msg_btn ) {
msg_btn.innerHTML = 'W';
msg_btn.classList.remove('button--hollow');
msg_btn.classList.add('button--icon-only');
msg_btn.classList.add('message');
msg_btn.title = "Whisper User";
jQuery(msg_btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
var real_msg = utils.createElement('button', 'message-button button float-left button--icon-only message html-tooltip');
real_msg.innerHTML = '<figure class="icon">' + MESSAGE + '</figure>';
real_msg.title = "Message User";
real_msg.addEventListener('click', function() {
window.open('//www.twitch.tv/message/compose?to=' + t.get('cardInfo.user.id'));
})
msg_btn.parentElement.insertBefore(real_msg, msg_btn.nextSibling);
}
// Add the Alias button
if ( msg_btn )
msg_btn.parentElement.insertBefore(alias_btn, msg_btn);
else {
var follow_btn = el.querySelector(".friend-button");
if ( follow_btn )
follow_btn.parentElement.insertBefore(alias_btn, follow_btn.nextSibling);
}
},
ffz_init: function() {
if ( f.has_bttv_6 )
return;
@ -976,6 +1308,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
is_broadcaster = user && room_id === user.login,
user_id = this.get('cardInfo.user.id'),
is_me = user && user.login === user_id,
alias = f.aliases[user_id],
handle_key,
@ -1004,10 +1337,12 @@ FFZ.prototype.modify_moderation_card = function(component) {
else
t.lvUpdateLevels(ffz_room.logviewer_levels);
// Highlight this user's chat messages.
if ( f.settings.highlight_messages_with_mod_card )
utils.update_css(f._chat_style, 'mod-card-highlight', styles['chat-user-bg'].replace(/{user_id}/g, user_id));
// Action Override
this.set('banAction', function(e) {
var room = utils.ember_lookup('controller:chat').get('currentRoom');
@ -1020,24 +1355,6 @@ FFZ.prototype.modify_moderation_card = function(component) {
});
// Move the default buttons.
var def_actions = el.querySelector('.moderation-card__actions');
if ( def_actions ) {
var def_line = def_actions.querySelector('.clearfix'),
bad_line = def_actions.querySelector('.moderation-card__controls');
if ( def_line && bad_line ) {
var children = bad_line.querySelectorAll('button');
for(var i=0; i < children.length; i++) {
bad_line.removeChild(children[i]);
def_line.appendChild(children[i]);
}
bad_line.classList.add('hidden');
}
}
// Alias Display
if ( alias ) {
var name = el.querySelector('.moderation-card__name a');
@ -1052,9 +1369,11 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
}
// Style it!
el.classList.add('ffz-moderation-card');
// Info-tize it!
if ( f.settings.mod_card_info ) {
var info = utils.createElement('div', 'info channel-stats'),
@ -1066,98 +1385,6 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
}
// Additional Buttons
if ( is_mod && f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
line = utils.createElement('div', 'extra-interface moderation-card__actions clearfix');
var build_cmd = function(user, room, cmd) {
var lines = utils.replace_cmd_variables(cmd, user, room).split(/\s*<LINE>\s*/g),
reason = ban_reason();
if ( reason ) {
for(var i=0; i < lines.length; i++) {
var match = TO_REG.exec(lines[i]);
if ( match ) {
if ( ! match[2] )
lines[i] += ' 600';
if ( ! match[3] )
lines[i] += reason;
break;
} else {
match = BAN_REG.exec(lines[i]);
if ( match ) {
if ( ! match[2] )
lines[i] += reason;
break;
}
}
}
}
return lines;
},
add_btn_click = function(cmd) {
var user = t.get('cardInfo.user'),
chat_controller = utils.ember_lookup('controller:chat'),
room = chat_controller && chat_controller.get('currentRoom');
if ( ! room )
return;
var lines = build_cmd(user, room, cmd);
for(var i=0; i < lines.length; i++)
room.send(lines[i], true);
},
add_btn_make = function(label, cmd) {
var btn = utils.createElement('button', 'button ffz-no-bg', utils.sanitize(label));
jQuery(btn).tipsy({
html: true,
gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n'),
title: function() {
var user = t.get('cardInfo.user'),
chat_controller = utils.ember_lookup('controller:chat'),
room = chat_controller && chat_controller.get('currentRoom');
lines = build_cmd(user, room, cmd),
title = _.map(lines, utils.sanitize).join('<br>');
return "Custom Command" + (lines.length > 1 ? 's' : '') +
"<br>" + title;
}
});
btn.addEventListener('click', add_btn_click.bind(this, cmd));
return btn;
};
for(var i=0; i < f.settings.mod_card_buttons.length; i++) {
var label, cmd, pair = f.settings.mod_card_buttons[i];
if ( ! Array.isArray(pair) ) {
cmd = pair;
label = cmd.split(' ', 1)[0];
} else {
label = pair[0];
cmd = pair[1];
}
utils.CMD_VAR_REGEX.lastIndex = 0;
if ( ! utils.CMD_VAR_REGEX.test(cmd) ) {
var lines = cmd.split(/\s*<LINE>\s*/g);
lines[0] += ' {user}';
cmd = lines.join("<LINE>");
}
line.appendChild(add_btn_make(label, cmd));
}
el.appendChild(line);
}
// Key Handling
el.setAttribute('tabindex', 1);
@ -1226,179 +1453,8 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
// Only do the big stuff if we're mod.
if ( is_mod ) {
el.classList.add('ffz-is-mod');
var btn_click = function(timeout) {
var user_id = t.get('cardInfo.user.id'),
room = utils.ember_lookup('controller:chat').get('currentRoom');
if ( timeout === -1 )
room.send("/unban " + user_id, true);
else
room.send("/timeout " + user_id + " " + timeout + ban_reason(), true);
},
btn_make = function(timeout) {
var btn = utils.createElement('button', 'button ffz-no-bg');
btn.innerHTML = utils.duration_string(timeout);
btn.title = "Timeout User for " + utils.number_commas(timeout) + " Second" + (timeout != 1 ? "s" : "");
if ( f.settings.mod_card_hotkeys && timeout === 600 )
btn.title = "(T)" + btn.title.substr(1);
else if ( f.settings.mod_card_hotkeys && timeout === 1 )
btn.title = "(P)urge - " + btn.title;
jQuery(btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
btn.addEventListener('click', btn_click.bind(this, timeout));
return btn;
};
if ( f.settings.mod_card_durations && f.settings.mod_card_durations.length ) {
// Extra Moderation
line = utils.createElement('div', 'extra-interface moderation-card__actions clearfix');
line.appendChild(btn_make(1));
var s = utils.createElement('span', 'right');
line.appendChild(s);
for(var i=0; i < f.settings.mod_card_durations.length; i++)
s.appendChild(btn_make(f.settings.mod_card_durations[i]));
el.appendChild(line);
// Fix Other Buttons
this.$("button.timeout").remove();
}
if ( f.settings.mod_card_reasons && f.settings.mod_card_reasons.length ) {
// Moderation Reasons
line = utils.createElement('div', 'extra-interface moderation-card__actions clearfix');
ban_reasons = utils.createElement('select', 'ffz-ban-reasons', '<option value="">Select a Ban ' + (f.settings.mod_card_hotkeys ? '(R)' : 'R') + 'eason</option>');
line.appendChild(ban_reasons);
for(var i=0; i < f.settings.mod_card_reasons.length; i++) {
var opt = utils.createElement('option'), r = f.settings.mod_card_reasons[i];
opt.value = r;
opt.textContent = (i+1) + ') ' + r;
ban_reasons.appendChild(opt);
}
el.appendChild(line);
}
var ban_btn = el.querySelector('button.ban');
if ( f.settings.mod_card_hotkeys )
ban_btn.setAttribute('title', '(B)an User');
// Unban Button
var unban_btn = utils.createElement('button', 'unban button button--icon-only light');
unban_btn.innerHTML = '<figure class="icon">' + CHECK + '</figure>';
unban_btn.title = (f.settings.mod_card_hotkeys ? "(U)" : "U") + "nban User";
jQuery(unban_btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
unban_btn.addEventListener("click", btn_click.bind(this, -1));
jQuery(ban_btn).after(unban_btn);
}
// Tooltips for ban and ignore.
jQuery("button.ignore, button.ban").tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
// More Fixing Other Buttons
var op_btn = el.querySelector('button.mod');
if ( op_btn ) {
var can_op = is_broadcaster || (user && user.is_admin) || (user && user.is_staff);
if ( ! can_op )
op_btn.parentElement.removeChild(op_btn);
}
// Follow Button
var follow_button = el.querySelector(".follow-button");
if ( follow_button )
jQuery(follow_button).tipsy({title: function() { return follow_button.classList.contains('is-following') ? "Unfollow" : "Follow"}});
// Whisper and Message Buttons
var msg_btn = el.querySelector("button.message-button");
if ( msg_btn ) {
msg_btn.innerHTML = 'W';
msg_btn.classList.remove('button--hollow');
msg_btn.classList.add('button--icon-only');
msg_btn.classList.add('message');
msg_btn.title = "Whisper User";
jQuery(msg_btn).tipsy({gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
var real_msg = utils.createElement('button', 'message-button button float-left button--icon-only message html-tooltip');
real_msg.innerHTML = '<figure class="icon">' + MESSAGE + '</figure>';
real_msg.title = "Message User";
real_msg.addEventListener('click', function() {
window.open('//www.twitch.tv/message/compose?to=' + t.get('cardInfo.user.id'));
})
msg_btn.parentElement.insertBefore(real_msg, msg_btn.nextSibling);
}
// Alias Button
var alias_btn = utils.createElement('button', 'alias button float-left button--icon-only html-tooltip');
alias_btn.innerHTML = '<figure class="icon">' + constants.EDIT + '</figure>';
alias_btn.title = "Set Alias";
alias_btn.addEventListener('click', function() {
var user = t.get('cardInfo.user.id'),
alias = f.aliases[user],
results = f.format_display_name(t.get('cardInfo.user.display_name'), user, true);
utils.prompt(
"Alias for <b" + (results[1] ? ' class="html-tooltip" title="' + utils.quote_attr(results[1]) + '">' : '>') + results[0] + "</b>",
"Please enter an alias for the user. Leave it blank to remove the alias.",
alias,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
new_val = new_val.trim();
if ( ! new_val )
new_val = undefined;
f.aliases[user] = new_val;
f.save_aliases();
// Update UI
f._update_alias(user);
var name = el.querySelector('h4.name');
if ( name ) {
name.classList.toggle('ffz-alias', new_val);
var results = f.format_display_name(t.get('cardInfo.user.display_name'), user_id);
name.innerHTML = results[0];
name.title = results[1] || '';
if ( results[1] )
jQuery(name).tipsy({html: true, gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'n')});
}
});
});
if ( msg_btn )
msg_btn.parentElement.insertBefore(alias_btn, msg_btn);
else {
var follow_btn = el.querySelector(".friend-button");
if ( follow_btn )
follow_btn.parentElement.insertBefore(alias_btn, follow_btn.nextSibling);
}
// Only do the main controls row if we're not looking at ourselves.
this.ffzFixDefaultActions();
// Tabbed Content
@ -1424,7 +1480,8 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
}
el.insertBefore(tab_container, el.querySelector('.moderation-card__actions'));
el.insertBefore(tab_container, el.firstElementChild.nextSibling);
//el.insertBefore(tab_container, el.querySelector('.moderation-card__actions'));
el.insertBefore(tabs, tab_container);
el.classList.add('ffz-default-tab');
@ -1526,7 +1583,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_click, mod_icons) {
FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_click, mod_icons, show_ts) {
var l_el = utils.createElement('li', 'message-line chat-line clearfix'),
out = [],
f = this,
@ -1534,7 +1591,7 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_cli
is_notice = msg.style === 'admin' || msg.style === 'notification',
style = '', colored = '';
if ( helpers && helpers.getTime )
if ( helpers && helpers.getTime && show_ts !== false )
out.push('<span class="timestamp' + (ts_click ? ' ts-action' : '') + '">' + helpers.getTime(msg.date, true) + '</span>');
var alias = this.aliases[msg.from],
@ -1572,7 +1629,7 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_cli
(alias ? ' ffz-alias' : '') +
(results[1] ? ' html-tooltip' : '') +
(style ? ' has-color' : '') +
'" style="' + style + '"' +
'" data-user="' + utils.quote_attr(msg.from) + '" style="' + style + '"' +
(colors ? ' data-color="' + raw_color + '"' : '') +
(results[1] ? ' title="' + utils.quote_attr(results[1]) + '"' : '') + '>'
+ results[0] + '</span>');

View file

@ -47,39 +47,7 @@ var FFZ = window.FrankerFaceZ,
],
// StrimBagZ Support
is_android = navigator.userAgent.indexOf('Android') !== -1,
moderator_css = function(room) {
if ( ! room.mod_urls )
return "";
var urls = room.mod_urls,
image_set = image = 'url("' + urls[1] + '")';
if ( urls[2] || urls[4] ) {
image_set += ' 1x';
if ( urls[2] )
image_set += ', url("' + urls[2] + '") 2x';
if ( urls[4] )
image_set += ', url("' + urls[4] + '") 4x';
image_set = (constants.IS_WEBKIT ? '-webkit-' : '') + 'image-set(' + image_set + ')';
}
return '.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored),' +
'.chat-line[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored) {' +
'background-repeat:no-repeat;' +
'background-size:initial !important;' +
'background-position:center;' +
'background-image: url("' + urls[1] + '") !important;' +
'background-image:' + image_set + ' !important}' +
'.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored,' +
'.chat-line[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored {' +
'-webkit-mask-repeat:no-repeat;' +
'-webkit-mask-size:initial !important;' +
'-webkit-mask-position:center;' +
'-webkit-mask-image:' + image_set + '}';
};
is_android = navigator.userAgent.indexOf('Android') !== -1;
// --------------------
// Initialization
@ -1372,7 +1340,7 @@ FFZ.prototype._load_room_json = function(room_id, callback, data) {
this.rooms[room_id] = data;*/
if ( model.css || model.mod_urls )
utils.update_css(this._room_style, room_id, moderator_css(model) + (model.css || ""));
utils.update_css(this._room_style, room_id, (this.settings.custom_badge_images ? utils.moderator_css(model) : '') + (model.css || ""));
if ( ! this.emote_sets.hasOwnProperty(model.set) )
this.load_set(model.set, function(success, set) {
@ -2089,36 +2057,40 @@ FFZ.prototype._modify_room = function(room) {
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,
if ( highlight_unread ) {
// API Stuff
f.api_trigger('room-recent-highlights', highlight_messages);
if ( f.settings.recent_highlights && highlight_messages.length ) {
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');
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);
this.set('ffz_recent_highlights', trimmed);
this.incrementProperty('ffz_recent_highlights_unread', highlight_messages.length);
if ( el && f._roomv.get('room') === this ) {
var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight);
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);
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));
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 ( 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'));
}
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'));
}
}
}
},
@ -2338,6 +2310,17 @@ FFZ.prototype._modify_room = function(room) {
if ( room_id === msg.from )
msg.tags.mod = true;
// Are there no emotes?
if ( msg.tags && ! msg.tags.emotes ) {
var user = f.get_user(),
is_me = user && user.login === msg.from;
if ( is_me ) {
var user_emotes = utils.ember_lookup('service:user-emotes');
msg.tags.emotes = tmimotes && user_emotes && tmimotes(user_emotes.tryParseEmotes(msg.message));
}
}
// Tokenization
f.tokenize_chat_line(msg, false, this.get('roomProperties.hide_chat_links'));
@ -2352,7 +2335,7 @@ FFZ.prototype._modify_room = function(room) {
badges = ffz_room && ffz_room.badges || {},
sub_version = badges && badges.subscriber && badges.subscriber.versions;
if ( ! isNaN(msg.ffz_sub_months) ) {
if ( sub_version && ! isNaN(msg.ffz_sub_months) ) {
var months = msg.ffz_sub_months;
msg.tags.badges.subscriber = ( months >= 24 && sub_version[24] ) ? 24 :
(months >= 12 && sub_version[12] ) ? 12 :
@ -2392,6 +2375,12 @@ FFZ.prototype._modify_room = function(room) {
return;
// Message Filtering
f.api_trigger('room-message', msg);
if ( msg.ffz_removed )
return;
// Keep the history.
if ( ! is_whisper && msg.from && msg.from !== 'jtv' && msg.from !== 'twitchnotify' )
this.addUserHistory(msg);
@ -2427,10 +2416,6 @@ FFZ.prototype._modify_room = function(room) {
}
// Message Filtering
f.api_trigger('room-message', msg);
// We're past the last return, so store the message
// now that we know we're keeping it.
if ( msg_id ) {

View file

@ -393,7 +393,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
data.options.title = function(el) {
var old_text = t.get('tooltipText');
if ( ! f.settings.following_count )
return utils.sanitize(old_text);
return old_text; //utils.sanitize(old_text);
var tt_id = FFZ._sc_followed_tooltip_id++;
utils.api.get("streams/" + t.get('stream.id'), null, {version: 5}).then(function(data) {
@ -427,7 +427,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
'</span>';
});
return '<div id="ffz-sc-tooltip-' + tt_id + '">' + utils.sanitize(old_text) + '</div>';
return '<div id="ffz-sc-tooltip-' + tt_id + '">' + old_text + '</div>';
};
}
})

View file

@ -79,8 +79,10 @@ FFZ.prototype.modify_vod_chat_display = function(component) {
if ( room_id && ! f.rooms[room_id] ) {
// Load the room model.
f.log("Loading Room for VOD: " + room_id);
var Room = utils.ember_resolve('model:room');
Room && Room.findOne(room_id);
var Room = utils.ember_resolve('model:room'),
room = Room && Room.findOne(room_id);
if ( room && App.currentPath === 'user.chat' )
room.set('isEmbedChat', true);
}
if ( ! f.has_bttv_6 ) {

View file

@ -76,8 +76,8 @@ FFZ.prototype.setup_emoticons = function() {
this.log("Loading emoji data.");
this.load_emoji_data();
this.log("Watching Twitch emoticon parser to ensure it loads.");
this._twitch_emote_check = setTimeout(this.check_twitch_emotes.bind(this), 10000);
//this.log("Watching Twitch emoticon parser to ensure it loads.");
//this._twitch_emote_check = setTimeout(this.check_twitch_emotes.bind(this), 10000);
this._twitch_inventory_sets = [];
this.refresh_twitch_inventory();
@ -246,7 +246,7 @@ FFZ.prototype._click_emote = function(target, event) {
// Twitch Emoticon Checker
// ------------------------
FFZ.prototype.check_twitch_emotes = function() {
/*FFZ.prototype.check_twitch_emotes = function() {
if ( this._twitch_emote_check ) {
clearTimeout(this._twitch_emote_check);
delete this._twitch_emote_check;
@ -281,7 +281,7 @@ FFZ.prototype.check_twitch_emotes = function() {
// Check again in a bit to see if we've got them.
this._twitch_emote_check = setTimeout(this.check_twitch_emotes.bind(this), 10000);
}
}*/

View file

@ -289,7 +289,7 @@ API.prototype.load_set = function(set_id, emote_set) {
// Avoid spamming the console if and when other extensions
// spend time constantly updating emote sets.
if ( ! already_loaded || constants.DEBUG )
if ( this.log_sets )
this.log("Loaded Emoticon Set #" + set_id + ": " + emote_set.title + " (" + emote_set.count + " emotes)", emote_set);
return emote_set;

View file

@ -61,7 +61,7 @@ FFZ.channel_metadata = {};
// Version
var VER = FFZ.version_info = {
major: 3, minor: 5, revision: 502,
major: 3, minor: 5, revision: 511,
toString: function() {
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
}
@ -605,7 +605,8 @@ FFZ.prototype.init_ember = function(delay) {
this.cache_command_aliases();
this.fix_tooltips();
this.fix_scroll();
this.connect_extra_chat();
setTimeout(this.connect_extra_chat.bind(this), 250);
this.setup_message_event();
this.find_bttv(10);

View file

@ -9,6 +9,10 @@
padding: 3px 5px;
}
.ffz-hide-trending-emotes .chat-room.trending-emotes-enabled .chat-messages .chat-line,
.ffz-minimal-chat-input .chat-room.trending-emotes-enabled .chat-messages .chat-line {
padding-right: 5px;
}
.ember-chat .chat-messages .chat-line.brick--marked { padding-left: 8px }

View file

@ -6,7 +6,7 @@ var FFZ = window.FrankerFaceZ,
emote_helpers,
bits_helpers,
bits_service,
bits_tags,
//bits_tags,
HOP = Object.prototype.hasOwnProperty,
@ -220,7 +220,7 @@ FFZ.prototype.setup_tokenization = function() {
if ( ! bits_service )
bits_service = utils.ember_lookup('service:bits-rendering-config');
bits_tags = utils.ember_lookup('service:bits-tags');
//bits_tags = utils.ember_lookup('service:bits-tags');
try {
this.conv_helpers = conv_helpers = window.require && window.require("web-client/helpers/twitch-conversations/conversation-line-helpers");
@ -705,7 +705,7 @@ FFZ.prototype._tokenize_bits = function(tokens) {
if ( bits_helpers && bits_helpers.tokenizeBits )
try {
return bits_helpers.tokenizeBits(tokens,
bits_tags && bits_tags.get('allTagNames'),
//bits_tags && bits_tags.get('allTagNames'),
bits_service && bits_service.get('regexes'));
} catch(err) { }

View file

@ -100,9 +100,9 @@ FFZ.menu_pages.myemotes = {
has_sets: function(view) {
var user = this.get_user(),
controller = utils.ember_lookup('controller:chat'),
tmi = controller && controller.get('currentRoom.tmiSession'),
user_emotes = utils.ember_lookup('service:user-emotes'),
twitch_sets = (user_emotes && user_emotes.allEmotes || {'emoticon_sets': {}})['emoticon_sets'] || {},
ffz_sets = user && this.users[user.login] && this.users[user.login].sets || [],
twitch_sets = (tmi && tmi.getEmotes() || {'emoticon_sets': {}})['emoticon_sets'],
sk = twitch_sets && Object.keys(twitch_sets);
@ -228,8 +228,8 @@ FFZ.menu_pages.myemotes = {
render_lists: function(view, container, favorites_only) {
var controller = utils.ember_lookup('controller:chat'),
tmi = controller && controller.get('currentRoom.tmiSession'),
twitch_sets = (tmi && tmi.getEmotes() || {'emoticon_sets': {}})['emoticon_sets'],
user_emotes = utils.ember_lookup('service:user-emotes'),
twitch_sets = (user_emotes && user_emotes.allEmotes || {'emoticon_sets': {}})['emoticon_sets'] || {},
user = this.get_user(),
ffz_sets = this.getEmotes(user && user.login, null),

View file

@ -1129,6 +1129,38 @@ module.exports = FFZ.utils = {
'}\n';
},
moderator_css: function(room) {
if ( ! room.mod_urls )
return "";
var urls = room.mod_urls,
image_set = image = 'url("' + urls[1] + '")';
if ( urls[2] || urls[4] ) {
image_set += ' 1x';
if ( urls[2] )
image_set += ', url("' + urls[2] + '") 2x';
if ( urls[4] )
image_set += ', url("' + urls[4] + '") 4x';
image_set = (constants.IS_WEBKIT ? '-webkit-' : '') + 'image-set(' + image_set + ')';
}
return '.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored),' +
'.chat-line[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored) {' +
'background-repeat:no-repeat;' +
'background-size:initial !important;' +
'background-position:center;' +
'background-image: url("' + urls[1] + '") !important;' +
'background-image:' + image_set + ' !important}' +
'.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored,' +
'.chat-line[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored {' +
'-webkit-mask-repeat:no-repeat;' +
'-webkit-mask-size:initial !important;' +
'-webkit-mask-position:center;' +
'-webkit-mask-image:' + image_set + '}';
},
badge_css: function(badge, klass) {
klass = klass || ('ffz-badge-' + (badge.real_id || badge.id));
var urls = badge.urls || {1: badge.image},

View file

@ -1,6 +1,6 @@
/* Fix Tooltip Opacity */
body[data-page^="ember#"] { overflow: hidden }
body[data-page^="ember#"] { overflow: hidden; position: relative }
body > div.tipsy { opacity: 1 !important; }
body > div.tipsy .tipsy-inner { background-color: rgba(0,0,0,0.8); }
body > div.tipsy .tipsy-arrow { opacity: 0.8; }
@ -38,6 +38,10 @@ body > div.tipsy .tipsy-arrow { opacity: 0.8; }
.ffz-hide-thumb-info-on-hover .card-carousel__item:hover .card__boxpin,
.ffz-hide-thumb-info-on-hover .ffz-directory-preview:hover .card__boxpin,
.ffz-minimal-chat-input .trending-emote-feed,
.ffz-minimal-chat-input .trending-emote-interface,
.ffz-hide-trending-emotes .trending-emote-feed,
.ffz-hide-trending-emotes .trending-emote-interface,
.player[data-paused="false"] #js-follow-panel,
body:not(.ffz-theater-basic-stats) .player-userinfo__game,
body:not(.ffz-theater-basic-stats) .player-controls-top,
@ -136,6 +140,14 @@ body:not(.ffz-show-bits-tags) .ember-chat .chat-messages.bits-tags__offset {
top: 0;
}
.ffz-hide-trending-emotes .chat-room.trending-emotes-enabled .chat-messages .chat-line,
.ffz-minimal-chat-input .chat-room.trending-emotes-enabled .chat-messages .chat-line {
padding-right: 20px;
}
.ffz-hide-trending-emotes .chat-room.trending-emotes-enabled .chat-messages { bottom: 111px }
.ffz-hide-trending-emotes .chat-room.trending-emotes-enabled .chat-interface { height: 111px }
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .chat-interface .emoticon-selector-toggle + .ffz-ui-toggle svg,
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .chat-interface .emoticon-selector-toggle + div + .ffz-ui-toggle svg
{
@ -4319,7 +4331,7 @@ body.ffz-sidebar-swap .app-main.theatre #main_col:not(.expandRight) #player[data
right: 0;
transition: height ease-in-out 100ms;
height: 30px;
box-shadow: 0 10px 5px -3px rgba(239,238,241,0.5);
box-shadow: 0 5px 5px -3px rgba(239,238,241,0.5);
}
.ffz-recent-messages.ui-moved {
@ -4387,7 +4399,7 @@ body.ffz-sidebar-swap .app-main.theatre #main_col:not(.expandRight) #player[data
.force-dark .ffz-recent-messages {
background-color: #191919;
border-color: #474747;
box-shadow: 0 10px 5px -3px rgba(25,25,25,0.5);
box-shadow: 0 5px 5px -3px rgba(25,25,25,0.5);
}
@ -4404,7 +4416,7 @@ body.ffz-sidebar-swap .app-main.theatre #main_col:not(.expandRight) #player[data
*/
#ffz-chat-menu.ui-draggable-dragging {
/*#ffz-chat-menu.ui-draggable-dragging {
height: auto !important;
width: auto !important;
background: transparent;
@ -4422,7 +4434,7 @@ body.ffz-sidebar-swap .app-main.theatre #main_col:not(.expandRight) #player[data
padding: 0;
display: block;
max-width: 340px;
}
}*/
.app-main.theatre .player-whispers-padding {
margin-bottom: 0;