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

The Last Ever v3 Commit (Hopefully)

This commit is contained in:
SirStendec 2017-11-13 01:13:52 -05:00
parent e0bad1dc10
commit c2688646af
16 changed files with 396 additions and 121 deletions

View file

@ -1,3 +1,44 @@
<div class="list-header">3.5.536 <time datetime="2017-11-07">(2017-11-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Enable Transparent (Colored) badges in non-Webkit browsers. Note: The feature may not function correctly in all browsers.</li>
</ul>
<div class="list-header">3.5.535 <time datetime="2017-11-02">(2017-11-02)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Raid notices not rendering in chat.</li>
</ul>
<div class="list-header">3.5.534 <time datetime="2017-10-04">(2017-10-04)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Reset Player button not getting added to player because the menu element was renamed.</li>
</ul>
<div class="list-header">3.5.533 <time datetime="2017-10-01">(2017-10-01)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Experimental new feature, promoted messages.</li>
<li>&nbsp;</li>
<li>Moderators can promote a message to have it appear in Recent Highlights for users that
have the feature enabled. To promote a message, a moderator must use the command
<code>/ffz promote &lt;id&gt;</code> with the appropriate message id. The easiest
way to do this is to add a custom in-line moderation icon with the command
<code>/ffz promote {id}</code></li>
</ul>
<div class="list-header">3.5.532 <time datetime="2017-09-30">(2017-09-30)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: And the tooltip rendering tweaks keep coming</li>
</ul>
<div class="list-header">3.5.531 <time datetime="2017-09-29">(2017-09-29)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Properly calculate tooltip positions when added to an element other than the document root.</li>
</ul>
<div class="list-header">3.5.530 <time datetime="2017-09-29">(2017-09-29)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Make sure the dashboard module is loaded before trying to modify dashboard widgets.</li>
</ul>
<div class="list-header">3.5.529 <time datetime="2017-09-28">(2017-09-28)</time></div> <div class="list-header">3.5.529 <time datetime="2017-09-28">(2017-09-28)</time></div>
<ul class="chat-menu-content menu-side-padding"> <ul class="chat-menu-content menu-side-padding">
<li>Changed: Rewrite tooltip rendering to try making them better positioned.</li> <li>Changed: Rewrite tooltip rendering to try making them better positioned.</li>
@ -26,40 +67,5 @@
<li>Fixed: Take control of Twitch's native dark theme when enabling or disabling FFZ's dark theme.</li> <li>Fixed: Take control of Twitch's native dark theme when enabling or disabling FFZ's dark theme.</li>
</ul> </ul>
<div class="list-header">3.5.524 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Tooltips for global emotes not saying where they're from.</li>
</ul>
<div class="list-header">3.5.523 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Socket server status to the Debug menu.</li>
</ul>
<div class="list-header">3.5.522 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Emote data should be loading properly now with the socket servers under control.</li>
<li>Fixed: Update the emoji parsing regular expression.</li>
</ul>
<div class="list-header">3.5.521 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Hopefully a more resilient way of grabbing emote data.</li>
</ul>
<div class="list-header">3.5.520 <time datetime="2017-09-06">(2017-09-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Issue with sub emoticons not being tab-completable without prefixes and showing as having an unknown source.</li>
</ul>
<div class="list-header">3.5.519 <time datetime="2017-09-05">(2017-09-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>The Emote Data Update</li>
<li>&nbsp;</li>
<li>Changed: Start querying the socket server for emote set associations rather than pre-loading data into the client.</li>
<li>Changed: Use an update badges API for the My Emoticons menu.</li>
<li>Changed: Support multiple sub tiers with the Channel emoticons menu.</li>
</ul>
<div class="list-header" id="ffz-old-news-button"><a href="#">View Older</a></div> <div class="list-header" id="ffz-old-news-button"><a href="#">View Older</a></div>
<div id="ffz-old-news"></div> <div id="ffz-old-news"></div>

View file

@ -1,3 +1,38 @@
<div class="list-header">3.5.524 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Tooltips for global emotes not saying where they're from.</li>
</ul>
<div class="list-header">3.5.523 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Socket server status to the Debug menu.</li>
</ul>
<div class="list-header">3.5.522 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Emote data should be loading properly now with the socket servers under control.</li>
<li>Fixed: Update the emoji parsing regular expression.</li>
</ul>
<div class="list-header">3.5.521 <time datetime="2017-09-15">(2017-09-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Hopefully a more resilient way of grabbing emote data.</li>
</ul>
<div class="list-header">3.5.520 <time datetime="2017-09-06">(2017-09-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Issue with sub emoticons not being tab-completable without prefixes and showing as having an unknown source.</li>
</ul>
<div class="list-header">3.5.519 <time datetime="2017-09-05">(2017-09-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>The Emote Data Update</li>
<li>&nbsp;</li>
<li>Changed: Start querying the socket server for emote set associations rather than pre-loading data into the client.</li>
<li>Changed: Use an update badges API for the My Emoticons menu.</li>
<li>Changed: Support multiple sub tiers with the Channel emoticons menu.</li>
</ul>
<div class="list-header">3.5.518 <time datetime="2017-09-02">(2017-09-02)</time></div> <div class="list-header">3.5.518 <time datetime="2017-09-02">(2017-09-02)</time></div>
<ul class="chat-menu-content menu-side-padding"> <ul class="chat-menu-content menu-side-padding">
<li>Fixed: Bug with rich content attached to chat messages not getting removed when a message is timed out.</li> <li>Fixed: Bug with rich content attached to chat messages not getting removed when a message is timed out.</li>

View file

@ -2,6 +2,8 @@ var FFZ = window.FrankerFaceZ,
constants = require('./constants'), constants = require('./constants'),
utils = require('./utils'), utils = require('./utils'),
WEBKIT = constants.IS_WEBKIT ? '-webkit-' : '',
SPECIAL_BADGES = ['staff', 'admin', 'global_mod'], SPECIAL_BADGES = ['staff', 'admin', 'global_mod'],
OTHER_KNOWN = ['turbo', 'bits', 'premium', 'partner'], OTHER_KNOWN = ['turbo', 'bits', 'premium', 'partner'],
@ -251,8 +253,8 @@ FFZ.settings_info.transparent_badges = {
2: "Circular", 2: "Circular",
3: "Circular (Color Only)", 3: "Circular (Color Only)",
4: "Circular (Color Only, Small)", 4: "Circular (Color Only, Small)",
5: "Transparent" //, 5: "Transparent",
//6: "Transparent (Colored)" 6: "Transparent (Colored)"
}, },
value: 0, value: 0,
@ -295,10 +297,6 @@ FFZ.settings_info.transparent_badges = {
} }
}; };
// This requires -webkit-mask-image which isn't working in non-WebKit browsers.
if ( constants.IS_WEBKIT )
FFZ.settings_info.transparent_badges.options[6] = "Transparent (Colored)";
// -------------------- // --------------------
// Initialization // Initialization
@ -573,15 +571,15 @@ FFZ.prototype.render_badges = function(badges) {
if ( badge.image ) if ( badge.image )
if ( is_colored && setting === 6 ) if ( is_colored && setting === 6 )
css += (constants.IS_WEBKIT ? '-webkit-' : '') + 'mask-image:url("' + utils.quote_attr(badge.image) + '");'; css += WEBKIT + 'mask-image:url("' + utils.quote_attr(badge.image) + '");';
else else
css += 'background-image:url("' + utils.quote_attr(badge.image) + '");'; css += 'background-image:url("' + utils.quote_attr(badge.image) + '");';
if ( badge.srcSet ) if ( badge.srcSet )
if ( is_colored && setting === 6 ) if ( is_colored && setting === 6 )
css += (constants.IS_WEBKIT ? '-webkit-mask-image:-webkit-' : 'mask-image:') + 'image-set(' + badge.srcSet + ');'; css += WEBKIT + 'mask-image:' + WEBKIT + 'image-set(' + badge.srcSet + ');';
else else
css += 'background-image:' + (constants.IS_WEBKIT ? '-webkit-' : '') + 'image-set(' + badge.srcSet + ');'; css += 'background-image:' + WEBKIT + 'image-set(' + badge.srcSet + ');';
if ( badge.color ) if ( badge.color )
if ( is_colored && setting === 6 ) if ( is_colored && setting === 6 )

View file

@ -407,6 +407,27 @@ FFZ.chat_commands.renamegroup.enabled = function(room) {
} }
// -----------------
// Promoted Messages
// -----------------
FFZ.ffz_commands.promote = function(room, args) {
args = args.join(" ").trim();
var f = this;
if ( ! args.length || args.indexOf(' ') !== -1 )
return "You must provide only a single message ID. This is easiest to add as a custom in-line moderation action.";
if ( ! this.ws_send("promote_message", [room.id, args], function(success, data) {
if ( ! success ) {
f.log("Promotion Error: " + JSON.stringify(data));
f.room_message(room, "There was an error promoting the message.");
}
}) )
return "There was an error communicating with the server.";
}
// ----------------- // -----------------
// Mass Moderation // Mass Moderation
// ----------------- // -----------------

View file

@ -26,12 +26,26 @@ FFZ.prototype.setup_dashboard = function() {
if ( location.search === '?standalone' ) if ( location.search === '?standalone' )
utils.toggle_cls('ffz-minimal-dashboard')(true); utils.toggle_cls('ffz-minimal-dashboard')(true);
this.update_views('component:dashboards/live-widget', this.modify_dashboard_widget); this.try_modify_dashboard();
//this.update_views('component:dashboards/live/stream-stats', this.modify_dashboard_stats); //this.update_views('component:dashboards/live/stream-stats', this.modify_dashboard_stats);
//this.update_views('component:dashboards/live/stream-health', this.modify_dashboard_health); //this.update_views('component:dashboards/live/stream-health', this.modify_dashboard_health);
} }
FFZ.prototype.try_modify_dashboard = function() {
if ( this._dashboard_modified )
return;
var loaded = window.features && window.features.includes('dashboard');
if ( ! loaded )
return this.log('Dashboard still not loaded.');
this._dashboard_modified = true;
this.update_views('component:dashboards/live-widget', this.modify_dashboard_widget);
}
FFZ.prototype.modify_dashboard_widget = function(component) { FFZ.prototype.modify_dashboard_widget = function(component) {
var f = this; var f = this;
utils.ember_reopen_view(component, { utils.ember_reopen_view(component, {

View file

@ -659,8 +659,16 @@ FFZ.settings_info.chat_font_family = {
FFZ.settings_info.recent_highlights = { FFZ.settings_info.recent_highlights = {
type: "boolean", type: "select",
value: false, options: {
0: "Disabled",
1: "Moderator Promoted",
2: "Mentioned",
3: "Both"
},
value: 0,
process_value: utils.process_int(0, 0, 3),
category: "Chat Appearance", category: "Chat Appearance",
no_bttv: true, no_bttv: true,
@ -1183,11 +1191,33 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
} }
else if ( msg_type === 'raid' || msg_type === 'unraid' ) else if ( msg_type === 'raid' || msg_type === 'unraid' ) {
// TODO: This. var Intl = utils.ember_lookup('service:intl');
return '';
else if ( Intl ) {
if ( msg_type === 'raid' ) {
var channel = this.ffzGetChannel(),
data = channel.loaded ? channel.data : {display_name: tags['msg-param-login']};
out = '<span class="flex align-items-center">' +
(data.logo ? '<div class="square-3">' +
'<img src="' + utils.quote_attr(data.logo) + '" alt="' + utils.quote_san(data.display_name) + '">' +
'</div>' : '') +
'<div class="mg-l-1">' +
Intl.t('chat.raids.incomingRaid', {
displayName: data.display_name,
viewerCount: tags['msg-param-viewerCount'],
htmlSafe: true
}) +
'</div>' +
'</span>';
} else
out = Intl.t('chat.raids.cancelRaid');
} else
out = utils.sanitize(this.get('systemMsg'));
} else
out = utils.sanitize(this.get('systemMsg')); out = utils.sanitize(this.get('systemMsg'));
return out ? '<div class="system-msg">' + out + '</div>' : ''; return out ? '<div class="system-msg">' + out + '</div>' : '';
@ -1210,11 +1240,51 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
return out; return out;
}, },
ffzUpdateSystemMessage: function() {
var msg = this.buildSystemMessageHTML(),
el = this.$('.system-msg')[0];
if ( el )
el.outerHTML = msg;
else if ( msg ) {
el = this.$('.indicator')[0];
el.outerHTML = '<div class="indicator"></div>' + msg;
}
},
ffzUpdateRichContent: function() { ffzUpdateRichContent: function() {
if ( this.get('msgObject.tags.content') ) if ( this.get('msgObject.tags.content') )
this.$(".ffz-rich-content").html(this.buildRichContentHTML()); this.$(".ffz-rich-content").html(this.buildRichContentHTML());
}, },
ffzGetChannel: function() {
var login = this.get('msgObject.tags.msg-param-login');
if ( ! login )
return {
loaded: true,
errored: true
};
var t = this,
channel_info = this._channel_info = this._channel_info || {};
if ( ! channel_info._started ) {
channel_info._started = true;
utils.api.get('channels/' + login, {}, {version: 3})
.done(function(data) {
channel_info.data = data;
channel_info.loaded = true;
t.isDestroyed || t.ffzUpdateSystemMessage();
}).fail(function(data) {
channel_info.loaded = true;
channel_info.errored = true;
t.isDestroyed || t.ffzUpdateSystemMessage();
});
}
return channel_info;
},
ffzGetContent: function(provider_key, info) { ffzGetContent: function(provider_key, info) {
info = info || this.get('msgObject.tags.content.' + provider_key + '.firstObject') info = info || this.get('msgObject.tags.content.' + provider_key + '.firstObject')
if ( ! info || ! info.data ) if ( ! info || ! info.data )

View file

@ -283,7 +283,7 @@ FFZ.prototype.modify_twitch_player = function(player) {
// Add an option to the menu to recreate the player. // Add an option to the menu to recreate the player.
var t = this, var t = this,
el = this.$('.player-buttons-right #js-settings')[0], el = this.$('.player-buttons-right .pl-flex')[0],
container = el && el.parentElement; container = el && el.parentElement;
if ( el && ! container.querySelector('.ffz-player-reset') ) { if ( el && ! container.querySelector('.ffz-player-reset') ) {

View file

@ -682,7 +682,7 @@ FFZ.prototype.modify_room_component = function(component) {
actions.accommodatePinnedMessage = function(e) { actions.accommodatePinnedMessage = function(e) {
var el = t.get('element'), var el = t.get('element'),
chat = el.querySelector('.js-chat-messages'); chat = el && el.querySelector('.js-chat-messages');
if ( chat ) if ( chat )
chat.dataset.pinned_height = e; chat.dataset.pinned_height = e;
@ -2069,41 +2069,121 @@ FFZ.prototype._modify_room = function(room) {
if ( highlight_unread ) { if ( highlight_unread ) {
// API Stuff // API Stuff
f.api_trigger('room-recent-highlights', highlight_messages); f.api_trigger('room-recent-highlights', highlight_messages);
if ( f.settings.recent_highlights && highlight_messages.length ) { if ( f.settings.recent_highlights > 1 )
var old_highlights = this.get('ffz_recent_highlights') || [], this.ffzAddHighlights(highlight_messages);
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); ffzAddHighlights: function(messages) {
this.incrementProperty('ffz_recent_highlights_unread', highlight_messages.length); if ( f.settings.recent_highlights && messages.length ) {
var old_highlights = this.get('ffz_recent_highlights') || [],
raw_remove = old_highlights.length + messages.length > f.settings.recent_highlight_count ?
Math.max(0, old_highlights.length - f.settings.recent_highlight_count) + messages.length : 0,
if ( el && f._roomv.get('room') === this ) { to_remove = raw_remove % 2,
var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight); trimmed = old_highlights.slice(to_remove, old_highlights.length).concat(messages),
el = f._roomv && f._roomv.get('ffz_recent_el');
while( el.childElementCount && to_remove-- ) this.set('ffz_recent_highlights', trimmed);
el.removeChild(el.firstElementChild); this.incrementProperty('ffz_recent_highlights_unread', messages.length);
for(var i=0; i < highlight_messages.length; i++) if ( el && f._roomv.get('room') === this ) {
el.appendChild(f._build_mod_card_history(highlight_messages[i], null, true)); var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight);
if ( was_at_bottom ) while( el.childElementCount && to_remove-- )
el.scrollTop = el.scrollHeight; el.removeChild(el.firstElementChild);
if ( el.dataset.docked ) { for(var i=0; i < messages.length; i++)
el = f._roomv.get('ffz_recent_count_el'); el.appendChild(f._build_mod_card_history(messages[i], null, true));
if ( el )
el.textContent = utils.format_unread(this.get('ffz_recent_highlights_unread'));
}
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'));
} }
} }
} }
}, },
ffzHighlightMessage: function(msg_id) {
var message = this.ffz_ids && this.ffz_ids[msg_id];
if ( ! f.settings.recent_highlights || ! message )
return;
var highlights = this.get('ffz_recent_highlights') || [],
high_len = highlights.length,
posted = message.date,
insert_before = -1;
for(var i=0; i < high_len; i++) {
var msg = highlights[i];
if ( msg.tags && msg.tags.id === msg_id )
return;
if ( insert_before === -1 && posted <= msg.date )
insert_before = i;
}
var raw_remove = high_len + 1 > f.settings.recent_highlight_count ?
Math.max(0, high_len - f.settings.recent_highlight_count) + 1 : 0,
to_remove = raw_remove % 2,
el = f._roomv && f._roomv.get('ffz_recent_el');
console.log('msg', message);
console.log('count', high_len);
console.log('to_remove', to_remove);
console.log('insert_before', insert_before);
console.log('msgs', highlights.slice(0));
// If we're going to add the element only to remove it, leave.
if ( to_remove && insert_before === 0 )
return;
if ( to_remove ) {
highlights.splice(0, to_remove);
insert_before -= to_remove;
high_len = highlights.length;
}
if ( insert_before === -1 )
highlights.push(message);
else
highlights.splice(insert_before, 0, message);
this.set('ffz_recent_highlights', highlights);
this.incrementProperty('ffz_recent_highlights_unread', 1);
if ( ! el || f._roomv.get('room') !== this )
return;
var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight);
while ( el.childElementCount && to_remove-- )
el.removeChild(el.firstElementChild);
var msg_line = f._build_mod_card_history(message, null, true)
if ( insert_before === -1 )
el.appendChild(msg_line);
else
el.insertBefore(msg_line, el.children[insert_before]);
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) { ffzSchedulePendingFlush: function(now) {
// Instead of just blindly looping every x seconds, we want to calculate the time until // Instead of just blindly looping every x seconds, we want to calculate the time until
// the next message should be displayed, and then set the timeout for that. We'll // the next message should be displayed, and then set the timeout for that. We'll
@ -2786,4 +2866,22 @@ FFZ.prototype._modify_room = function(room) {
this.updateWait(0); this.updateWait(0);
}.observes('slowMode') }.observes('slowMode')
}); });
}
// ---------------
// Socket Stuff
// ---------------
FFZ.ws_commands.promote_message = function(data) {
var channel = data[0],
user = data[1],
msg_id = data[2],
ffz_room = this.rooms && this.rooms[channel],
room = ffz_room && ffz_room.room,
setting = this.settings.recent_highlights;
if ( room && (setting === 1 || setting === 3) )
room.ffzHighlightMessage(msg_id, user);
} }

View file

@ -26,6 +26,7 @@ FFZ.prototype.setup_router = function() {
// If we're coming from a page without app-main, make sure we install the // If we're coming from a page without app-main, make sure we install the
// scroll listener. // scroll listener.
f.fix_scroll(); f.fix_scroll();
f.try_modify_dashboard();
try { try {
document.body.setAttribute('data-current-path', App.get('currentPath')); document.body.setAttribute('data-current-path', App.get('currentPath'));

View file

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

View file

@ -361,7 +361,7 @@ FFZ.prototype._ws_on_hello = function(success, data) {
if ( ! success ) if ( ! success )
return this.log("Error Saying Hello: " + data); return this.log("Error Saying Hello: " + data);
this._ws_on_pong(success, data[1]); this._ws_on_pong(false, success, data[1]);
localStorage.ffzClientId = data[0]; localStorage.ffzClientId = data[0];
this.log("Client ID: " + localStorage.ffzClientId); this.log("Client ID: " + localStorage.ffzClientId);

View file

@ -10,7 +10,7 @@ var FFZ = window.FrankerFaceZ,
HOP = Object.prototype.hasOwnProperty, HOP = Object.prototype.hasOwnProperty,
TOOLTIP_VERSION = 3, TOOLTIP_VERSION = 4,
FAV_MARKER = '<span class="ffz-favorite"></span>', FAV_MARKER = '<span class="ffz-favorite"></span>',
EXPLANATION_WARN = '<hr>This link has been sent to you via a whisper rather than standard chat, and has not been checked or approved of by any moderators or staff members. Please treat this link with caution and do not visit it if you do not trust the sender.', EXPLANATION_WARN = '<hr>This link has been sent to you via a whisper rather than standard chat, and has not been checked or approved of by any moderators or staff members. Please treat this link with caution and do not visit it if you do not trust the sender.',
@ -466,8 +466,6 @@ FFZ.prototype.get_link_info = function(url, no_promises) {
li = this.settings.link_info; li = this.settings.link_info;
console.log('get_link_info', url, info);
if ( ! li || (expires && Date.now() > expires) ) if ( ! li || (expires && Date.now() > expires) )
info = this._link_data[url] = null; info = this._link_data[url] = null;
@ -563,6 +561,12 @@ FFZ.prototype.render_link_tooltip = function(data, el) {
else else
content = '<img class="emoticon ffz-image-hover" src="' + utils.quote_attr(data.image) + '">' + content; content = '<img class="emoticon ffz-image-hover" src="' + utils.quote_attr(data.image) + '">' + content;
if ( content.indexOf('<video') !== -1 )
setTimeout(function() {
var el = document.querySelector('.zipsy video');
el && el.play();
},0);
} else if ( content.length ) } else if ( content.length )
content = content.replace(/<!--MS-->.*<!--ME-->/g, ''); content = content.replace(/<!--MS-->.*<!--ME-->/g, '');
@ -756,6 +760,15 @@ FFZ.prototype.render_tooltip = function(el) {
if ( data instanceof Promise ) { if ( data instanceof Promise ) {
var tt_id = FFZ._sc_followed_tooltip_id++, var tt_id = FFZ._sc_followed_tooltip_id++,
replacer = function(data, tooltip_class) { replacer = function(data, tooltip_class) {
var j_el = jQuery(t),
zipsy = j_el.data('tipsy');
if ( zipsy ) {
if ( zipsy.hoverState === 'in' )
j_el.zipsy('hide').zipsy('show');
return;
}
var el = document.querySelector('.ffz-async-tooltip[data-id="' + tt_id + '"]'), var el = document.querySelector('.ffz-async-tooltip[data-id="' + tt_id + '"]'),
container = el && el.parentElement.parentElement; container = el && el.parentElement.parentElement;
if ( ! el ) if ( ! el )

View file

@ -3,9 +3,9 @@ var FFZ = window.FrankerFaceZ,
constants = require('../constants'), constants = require('../constants'),
FOLLOWING_CONTAINERS = [ FOLLOWING_CONTAINERS = [
'.warp__item a[data-href="following"]', ['.warp__item a[data-href="following"]'],
'#header_actions #header_following', ['#header_actions #header_following'],
'.top-nav__nav-link[data-tt_content="directory_following"]' ['.top-nav__nav-link[data-tt_content="directory_following"]', '.top-nav']
], ],
WIDE_TIP = function(f, el) { WIDE_TIP = function(f, el) {
@ -306,13 +306,14 @@ FFZ.prototype._install_following_tooltips = function() {
}; };
for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) { for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) {
var following = jQuery(FOLLOWING_CONTAINERS[i]); var following = jQuery(FOLLOWING_CONTAINERS[i][0]);
if ( following && following.length ) { if ( following && following.length ) {
var dat = _.extend(data, {prependTo: FOLLOWING_CONTAINERS[i][1] || document.body});
var td = following.data('tipsy'); var td = following.data('tipsy');
if ( td && td.options ) { if ( td && td.options ) {
td.options = _.extend(td.options, data); td.options = _.extend(td.options, dat);
} else } else
following.zipsy(data); following.zipsy(dat);
} }
} }
} }
@ -327,7 +328,7 @@ FFZ.prototype._draw_following_channels = function(streams, total) {
FFZ.prototype._draw_following_count = function(count) { FFZ.prototype._draw_following_count = function(count) {
count = count ? utils.format_unread(count) : ''; count = count ? utils.format_unread(count) : '';
for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) { for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) {
var container = document.querySelector(FOLLOWING_CONTAINERS[i]), var container = document.querySelector(FOLLOWING_CONTAINERS[i][0]),
badge = container && container.querySelector('.ffz-follow-count'); badge = container && container.querySelector('.ffz-follow-count');
if ( ! container ) if ( ! container )
continue; continue;

View file

@ -102,29 +102,41 @@ Zipsy.prototype = {
if ( this.options.className ) if ( this.options.className )
$tip.addClass(maybeCall(this.options.className, el)); $tip.addClass(maybeCall(this.options.className, el));
var prepend_to = maybeCall(this.options.prependTo, el);
if ( typeof prepend_to === 'string' )
prepend_to = document.querySelector(prepend_to);
else if ( typeof prepend_to === 'object' && !(prepend_to instanceof HTMLElement) )
prepend_to = prepend_to[0];
else if ( ! prepend_to )
prepend_to = document.body;
if ( ! prepend_to )
return;
$tip.detach().css({ $tip.detach().css({
top: 0, left: 0, top: 0, left: 0,
width: '', height: '', width: '', height: '',
visibility: 'hidden', visibility: 'hidden',
display: 'block' display: 'block'
}).prependTo(this.options.prependTo).data('tipsy-pointee', el); }).prependTo(prepend_to).data('tipsy-pointee', el);
var pos; var pos;
if ( j_el.parents('svg').length > 0 ) if ( j_el.parents('svg').length > 0 )
pos = jQuery.extend({}, j_el.offset(), el.getBBox()); pos = jQuery.extend({}, j_el.offset(), el.getBBox());
else if ( this.options.prependTo !== document.body ) else {
pos = jQuery.extend(j_el.position(), { var el_box = el.getBoundingClientRect(),
width: j_el.width(), cont_box = prepend_to.getBoundingClientRect();
height: j_el.height()
});
else pos = {
pos = jQuery.extend({}, j_el.offset(), { top: el_box.top - cont_box.top,
width: el.offsetWidth || 0, left: el_box.left - cont_box.left,
height: el.offsetHeight || 0 width: el_box.width,
}); height: el_box.height
}
}
var bbox = $tip[0].getBoundingClientRect(), var bbox = $tip[0].getBoundingClientRect(),
actual_width = Math.ceil(bbox.width), actual_width = Math.ceil(bbox.width),
@ -275,8 +287,8 @@ Zipsy.prototype = {
} }
} }
jQuery.fn.zipsy = function(options) { var JQ_Zipsy = function(options) {
jQuery.fn.zipsy.enable(); JQ_Zipsy.enable();
if ( options === true ) if ( options === true )
return this.data('tipsy'); return this.data('tipsy');
@ -289,12 +301,12 @@ jQuery.fn.zipsy = function(options) {
return this; return this;
} }
options = jQuery.extend({}, jQuery.fn.zipsy.defaults, options); options = jQuery.extend({}, JQ_Zipsy.defaults, options);
function get(el) { function get(el) {
var zipsy = jQuery.data(el, 'tipsy'); var zipsy = jQuery.data(el, 'tipsy');
if ( ! zipsy ) { if ( ! zipsy ) {
zipsy = new Zipsy(el, jQuery.fn.zipsy.elementOptions(el, options)); zipsy = new Zipsy(el, JQ_Zipsy.elementOptions(el, options));
jQuery.data(el, 'tipsy', zipsy); jQuery.data(el, 'tipsy', zipsy);
} }
@ -302,7 +314,7 @@ jQuery.fn.zipsy = function(options) {
} }
function enter() { function enter() {
if ( ! jQuery.fn.zipsy.enabled ) if ( ! JQ_Zipsy.enabled )
return; return;
var zipsy = get(this); var zipsy = get(this);
@ -351,7 +363,7 @@ jQuery.fn.zipsy = function(options) {
return this; return this;
} }
jQuery.fn.zipsy.defaults = { JQ_Zipsy.defaults = {
aria: false, aria: false,
className: null, className: null,
delayIn: 0, delayIn: 0,
@ -371,43 +383,46 @@ jQuery.fn.zipsy.defaults = {
prependTo: document.body prependTo: document.body
}; };
jQuery.fn.zipsy.revalidate = function() { JQ_Zipsy.revalidate = function() {
jQuery('.tipsy').each(function() { jQuery('.tipsy').each(function() {
var t = jQuery.data(this, "tipsy-pointee"); var t = jQuery.data(this, "tipsy-pointee");
(!t || !t[0] || !document.contains(t[0])) && jQuery(this).remove(); (!t || !t[0] || !document.contains(t[0])) && jQuery(this).remove();
}); });
} }
jQuery.fn.zipsy.clear = function() { JQ_Zipsy.clear = function() {
jQuery('.tipsy').remove(); jQuery('.tipsy').remove();
} }
jQuery.fn.zipsy.enable = function() { JQ_Zipsy.enable = function() {
jQuery.fn.zipsy.enabled = true; JQ_Zipsy.enabled = true;
} }
jQuery.fn.zipsy.disable = function() { JQ_Zipsy.disable = function() {
jQuery.fn.zipsy.enabled = false; JQ_Zipsy.enabled = false;
} }
jQuery.fn.zipsy.elementOptions = function(el, options) { JQ_Zipsy.elementOptions = function(el, options) {
return options; return options;
} }
jQuery.fn.zipsy.autoNS = function() { JQ_Zipsy.autoNS = function() {
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n'; return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
} }
jQuery.fn.zipsy.autoWE = function() { JQ_Zipsy.autoWE = function() {
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w'; return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
} }
jQuery.fn.zipsy.autoNWNE = function() { JQ_Zipsy.autoNWNE = function() {
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'ne' : 'nw'; return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'ne' : 'nw';
} }
jQuery.fn.zipsy.autoSWSE = function() { JQ_Zipsy.autoSWSE = function() {
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'se' : 'sw'; return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'se' : 'sw';
} }
jQuery.fn.zipsy.autoBounds = utils.newtip_placement; JQ_Zipsy.autoBounds = utils.newtip_placement;
if ( window.jQuery && jQuery.fn )
jQuery.fn.zipsy = JQ_Zipsy;

View file

@ -1182,7 +1182,7 @@ module.exports = FFZ.utils = {
if ( urls[4] ) if ( urls[4] )
image_set += ', url("' + urls[4] + '") 4x'; image_set += ', url("' + urls[4] + '") 4x';
image_set = (constants.IS_WEBKIT ? '-webkit-' : '') + 'image-set(' + image_set + ')'; image_set = WEBKIT + 'image-set(' + image_set + ')';
} }
return '.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored),' + return '.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement):not(.colored),' +
@ -1194,10 +1194,11 @@ module.exports = FFZ.utils = {
'background-image:' + image_set + ' !important}' + 'background-image:' + image_set + ' !important}' +
'.from-display-preview[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored,' + '.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 {' + '.chat-line[data-room="' + room.id + '"] .badges .moderator:not(.ffz-badge-replacement).colored {' +
'-webkit-mask-repeat:no-repeat;' + WEBKIT + 'mask-repeat:no-repeat;' +
'-webkit-mask-size:initial !important;' + WEBKIT + 'mask-size:initial !important;' +
'-webkit-mask-position:center;' + WEBKIT + 'mask-position:center;' +
'-webkit-mask-image:' + image_set + '}'; WEBKIT + 'mask-image: url("' + urls[1] + '");' +
WEBKIT + 'mask-image:' + image_set + '}';
}, },
badge_css: function(badge, klass) { badge_css: function(badge, klass) {

View file

@ -1975,11 +1975,13 @@ body:not(.ffz-bttv) .chat-container:not(.chatReplay) .more-messages-indicator {
.ffz-rich-tip .profile-stats { .ffz-rich-tip .profile-stats {
display: flex; display: flex;
flex-flow: row; flex-flow: row;
flex-wrap: wrap;
} }
.ffz-rich-tip .profile-stats div { .ffz-rich-tip .profile-stats div {
flex-grow: 1; flex-grow: 1;
font-size: 16px; font-size: 16px;
margin-right: 10px;
} }
.ffz-rich-tip .profile-stats span { .ffz-rich-tip .profile-stats span {