1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-02 16:08:31 +00:00

3.5.58 to 3.5.62. Added enhanced following controls to the profile page. New Conversations options. Tweaked conversation styles.

This commit is contained in:
SirStendec 2015-11-10 21:37:30 -05:00
parent c40b3ba337
commit 4f6dcc9999
15 changed files with 3017 additions and 38 deletions

View file

@ -1036,4 +1036,7 @@
.ffz-dark .conversation-window.has-focus .conversation-input-actions .button,
.ffz-dark .conversation-window.has-focus .conversation-input-actions .follow-button:not(.ember-follow) .follow {
background-color: #6441a5
}
}
.ffz-dark .conversation-window .new-message-divider span { background: transparent; }
.ffz-dark .conversation-window .new-message-divider:after { display: none; }

View file

@ -570,19 +570,7 @@ FFZ.prototype._update_colors = function(darkness_only) {
this._color_old_darkness = is_dark;
var colored_bits = document.querySelectorAll('.chat-line .has-color');
for(var i=0, l=colored_bits.length; i < l; i++) {
var bit = colored_bits[i],
color = bit.getAttribute('data-color'),
colors = color && this._handle_color(color);
if ( ! colors )
continue;
bit.style.color = is_dark ? colors[1] : colors[0];
}
colored_bits = document.querySelectorAll('.conversation-chat-line .has-color');
var colored_bits = document.querySelectorAll('.has-color');
for(var i=0, l=colored_bits.length; i < l; i++) {
var bit = colored_bits[i],
color = bit.getAttribute('data-color'),

View file

@ -77,6 +77,7 @@ module.exports = {
CLOCK: '<svg class="svg-glyph_views ffz-svg svg-clock" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path fill-rule="evenodd" clip-rule="evenodd" fill="#888888" d="M8,15c-3.866,0-7-3.134-7-7s3.134-7,7-7s7,3.134,7,7 S11.866,15,8,15z M8,3C5.238,3,3,5.238,3,8s2.238,5,5,5s5-2.238,5-5S10.762,3,8,3z M7.293,8.707L7,8l1-4l0.902,3.607L11,11 L7.293,8.707z"/></svg>',
GEAR: '<svg class="svg-gear" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M15,7v2h-2.115c-0.125,0.615-0.354,1.215-0.713,1.758l1.484,1.484l-1.414,1.414l-1.484-1.484C10.215,12.531,9.615,12.76,9,12.885V15H7v-2.12c-0.614-0.126-1.21-0.356-1.751-0.714l-1.491,1.49l-1.414-1.414l1.491-1.49C3.477,10.211,3.247,9.613,3.12,9H1V7h2.116C3.24,6.384,3.469,5.785,3.829,5.242L2.343,3.757l1.414-1.414l1.485,1.485C5.785,3.469,6.384,3.24,7,3.115V1h2v2.12c0.613,0.126,1.211,0.356,1.752,0.714l1.49-1.491l1.414,1.414l-1.49,1.492C12.523,5.79,12.754,6.387,12.88,7H15z M8,6C6.896,6,6,6.896,6,8s0.896,2,2,2s2-0.896,2-2S9.104,6,8,6z" fill-rule="evenodd"></path></svg>',
HEART: '<svg class="svg-heart" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M8,13.5L1.5,7V4l2-2h3L8,3.5L9.5,2h3l2,2v3L8,13.5z" fill-rule="evenodd"></path></svg>',
UNHEART: '<svg class="svg-unheart" height="16px" version="1.1" viewbox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M1,9V7h14v2H1z M1,4l2-2h3l2,2l2-2h3l2,2v2H1V4z M8,14l-4.667-4h9.333L8,14z" fill-rule="evenodd"></path></svg>',
EMOTE: '<svg class="svg-emote" height="16px" version="1.1" viewBox="0 0 18 18" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M9,18c-4.971,0-9-4.029-9-9s4.029-9,9-9s9,4.029,9,9S13.971,18,9,18z M14,4.111V4h-0.111C12.627,2.766,10.904,2,9,2C7.095,2,5.373,2.766,4.111,4H4v0.111C2.766,5.373,2,7.096,2,9s0.766,3.627,2,4.889V14l0.05-0.051C5.317,15.217,7.067,16,9,16c1.934,0,3.684-0.783,4.949-2.051L14,14v-0.111c1.234-1.262,2-2.984,2-4.889S15.234,5.373,14,4.111zM11,6h2v4h-2V6z M12.535,12.535C11.631,13.44,10.381,14,9,14s-2.631-0.56-3.536-1.465l0.707-0.707C6.896,12.553,7.896,13,9,13s2.104-0.447,2.828-1.172L12.535,12.535z M5,6h2v4H5V6z" fill-rule="evenodd"></path></svg>',
STAR: '<svg class="svg-star" height="16px" version="1.1" viewbox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M15,6l-4.041,2.694L13,14l-5-3.333L3,14l2.041-5.306L1,6h5.077L8,1l1.924,5H15z" fill-rule="evenodd"></path></svg>',
CLOSE: '<svg class="svg-close_small" height="16px" version="1.1" viewbox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M12.657,4.757L9.414,8l3.243,3.242l-1.415,1.415L8,9.414l-3.243,3.243l-1.414-1.415L6.586,8L3.343,4.757l1.414-1.414L8,6.586l3.242-3.243L12.657,4.757z" fill-rule="evenodd"></path></svg>',

252
src/ember/conversations.js Normal file
View file

@ -0,0 +1,252 @@
var FFZ = window.FrankerFaceZ,
utils = require('../utils'),
constants = require('../constants');
// ---------------
// Settings
// ---------------
FFZ.settings_info.conv_title_clickable = {
type: "boolean",
value: false,
no_mobile: true,
category: "Conversations",
name: "Clickable Header Name",
help: "Make the conversation header a link that takes you to that person's page.",
on_update: function(val) {
document.body.classList.toggle('ffz-conv-title-clickable', val);
}
};
FFZ.settings_info.conv_focus_on_click = {
type: "boolean",
value: false,
no_mobile: true,
category: "Conversations",
name: "Focus Input on Click",
help: "Focus on a conversation's input box when you click it."
};
FFZ.settings_info.top_conversations = {
type: "boolean",
value: false,
no_mobile: true,
category: "Conversations",
name: "Position on Top",
help: "Display the new conversation-style whisper UI at the top of the window instead of the bottom.",
on_update: function(val) {
document.body.classList.toggle('ffz-top-conversations', val);
}
};
FFZ.settings_info.conv_beta_enable = {
type: "boolean",
value: false,
no_mobile: true,
category: "Conversations",
name: "Enable Conversations",
help: "Twitch hasn't enabled them yet, but they're in the code for testing. Try them out!",
on_update: function(val) {
App.__container__.lookup('route:application').controller.set('isConversationsEnabled', val);
}
};
// ---------------
// Initialization
// ---------------
FFZ.prototype.setup_conversations = function() {
document.body.classList.toggle('ffz-top-conversations', this.settings.top_conversations);
document.body.classList.toggle('ffz-conv-title-clickable', this.settings.conv_title_clickable);;
if ( this.settings.conv_beta_enable )
App.__container__.lookup('route:application').controller.set('isConversationsEnabled', true);
this.log("Hooking the Ember Conversation Window component.");
var ConvWindow = App.__container__.resolve('component:conversation-window');
if ( ConvWindow )
this._modify_conversation_window(ConvWindow);
this.log("Hooking the Ember Conversation Line component.");
var ConvLine = App.__container__.resolve('component:conversation-line');
if ( ConvLine )
this._modify_conversation_line(ConvLine);
}
FFZ.prototype._modify_conversation_window = function(component) {
var f = this,
Layout = App.__container__.lookup('controller:layout'),
Settings = App.__container__.lookup('controller:settings');
component.reopen({
onConversationClick: Ember.on('click', function() {
this.markConversationRead();
if ( f.settings.conv_focus_on_click )
this.$(".conversation-input-bar textarea").focus();
}),
headerBadges: Ember.computed("conversation.participants", "currentUsername", function() {
var e = this.get("conversation.participants").rejectBy("username", this.get("currentUsername")).objectAt(0),
badges = {},
ut = e.get("userType");
if ( ut === "staff" )
badges[0] = {classes: 'badge staff', title: 'Staff'};
else if ( ut === 'admin' )
badges[0] = {classes: 'badge admin', title: 'Admin'};
else if ( ut === 'global_mod' )
badges[0] = {classes: 'badge global-moderator', title: 'Global Moderator'};
if ( e.get('hasTurbo') )
badges[15] = {classes: 'badge turbo', title: 'Turbo'}
// FFZ Badges
var data = f.users[e.get('username')];
if ( data && data.badges ) {
for(var slot in data.badges) {
if ( ! data.badges.hasOwnProperty(slot) )
continue;
var badge = data.badges[slot],
full_badge = f.badges[badge.id] || {},
old_badge = badges[slot];
if ( full_badge.visible !== undefined ) {
var visible = full_badge.visible;
if ( typeof visible === "function" )
try {
visible = visible.bind(f)(null, e.get('username'), null, badges);
} catch(err) {
f.error("badge " + badge.id + " visible: " + err);
continue;
}
if ( ! visible )
continue;
}
if ( old_badge ) {
var replaces = badge.hasOwnProperty('replaces') ? badge.replaces : full_badge.replaces;
if ( ! replaces )
continue;
old_badge.klass = 'badge ffz-badge-' + badge.id;
old_badge.title += ', ' + (badge.title || full_badge.title);
continue;
}
badges[slot] = {
classes: 'badge ffz-badge-' + badge.id,
title: badge.title || full_badge.title
}
}
}
var out = [];
for(var slot in badges)
out.push(badges[slot]);
return out;
}),
didInsertElement: function() {
var el = this.get('element'),
header = el && el.querySelector('.conversation-header'),
header_name = header && header.querySelector('.conversation-header-name'),
new_header_name = document.createElement('span'),
raw_color = this.get('otherUser.color'),
colors = raw_color && f._handle_color(raw_color),
is_dark = (Layout && Layout.get('isTheatreMode')) || f.settings.dark_twitch;
if ( header_name ) {
new_header_name.className = 'conversation-header-name';
new_header_name.textContent = header_name.textContent;
header.insertBefore(new_header_name, header_name);
if ( raw_color ) {
header_name.style.color = (is_dark ? colors[1] : colors[0]);
header_name.classList.add('has-color');
header_name.setAttribute('data-color', raw_color);
new_header_name.style.color = (is_dark ? colors[1] : colors[0]);
new_header_name.classList.add('has-color');
new_header_name.setAttribute('data-color', raw_color);
}
}
}
});
}
FFZ.prototype._modify_conversation_line = function(component) {
var f = this,
Layout = App.__container__.lookup('controller:layout'),
Settings = App.__container__.lookup('controller:settings');
component.reopen({
tokenizedMessage: function() {
try {
return f.tokenize_conversation_line(this.get('message'));
} catch(err) {
f.error("convo-line tokenizedMessage: " + err);
return this._super();
}
}.property("message", "currentUsername"),
click: function(e) {
if ( e.target && e.target.classList.contains('deleted-link') )
return f._deleted_link_click.bind(e.target)(e);
if ( f._click_emote(e.target, e) )
return;
return this._super(e);
},
render: function(e) {
var user = this.get('message.from.username'),
raw_color = this.get('message.from.color'),
colors = raw_color && f._handle_color(raw_color),
is_dark = (Layout && Layout.get('isTheatreMode')) || f.settings.dark_twitch;
e.push('<div class="indicator"></div>');
var alias = f.aliases[user],
name = this.get('message.from.displayName') || (user && user.capitalize()) || "unknown user",
style = colors && 'color:' + (is_dark ? colors[1] : colors[0]),
colored = style ? ' has-color' : '';
if ( alias )
e.push('<span class="from ffz-alias tooltip' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '" title="' + utils.sanitize(name) + '">' + utils.sanitize(alias) + '</span>');
else
e.push('<span class="from' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '">' + utils.sanitize(name) + '</span>');
e.push('<span class="colon">:</span> ');
if ( ! this.get('isActionMessage') ) {
style = '';
colored = '';
}
e.push('<span class="message' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '">');
e.push(f.render_tokens(this.get('tokenizedMessage'), true));
e.push('</span>');
}
});
}

View file

@ -45,8 +45,12 @@ FFZ.prototype.setup_directory = function() {
// Initialize existing views.
for(var key in Ember.View.views) {
var view = Ember.View.views[key];
if ( view instanceof ChannelView || view instanceof CreativeChannel || view instanceof CSGOChannel || view instanceof HostView )
view.ffzInit();
try {
if ( (ChannelView && view instanceof ChannelView) || (CreativeChannel && view instanceof CreativeChannel) || (CSGOChannel && view instanceof CSGOChannel) || (HostView && view instanceof HostView) )
view.ffzInit();
} catch(err) {
this.error("Directory Setup: " + err);
}
}
}

318
src/ember/following.js Normal file
View file

@ -0,0 +1,318 @@
var FFZ = window.FrankerFaceZ,
utils = require('../utils'),
constants = require('../constants');
// --------------------
// Settings
// --------------------
FFZ.settings_info.enhance_profile_following = {
type: "boolean",
value: true,
category: "Appearance",
name: "Enhanced Following Control",
help: "Display additional controls on your own profile's Following tab to make management easier."
}
// --------------------
// Initialization
// --------------------
FFZ.prototype.setup_profile_following = function() {
if ( ! window.App )
return;
var f = this;
// Build our is-following cache.
this._following_cache = {};
// First, we need to hook the model. This is what we'll use to grab the following notification state,
// rather than making potentially hundreds of API requests.
var Following = App.__container__.resolve('model:kraken-channel-following');
if ( ! Following )
return;
this._hook_following(Following);
// Also try hooking that other model.
var Notification = App.__container__.resolve('model:notification');
if ( Notification )
this._hook_following(Notification, true);
// Now, we need to edit the profile Following view itself.
var ProfileView = App.__container__.resolve('view:channel/following');
if ( ! ProfileView )
return;
ProfileView.reopen({
didInsertElement: function() {
this._super();
try {
this.ffzInit();
} catch(err) {
f.error("ProfileView ffzInit: " + err);
}
},
willClearRender: function() {
try {
this.ffzTeardown();
} catch(err) {
f.error("ProvileView ffzTeardown: " + err);
}
this._super();
},
ffzInit: function() {
// Only process our own profile following page.
var user = f.get_user();
if ( ! f.settings.enhance_profile_following || ! user || ! user.login === this.get('context.id') )
return;
var el = this.get('element'),
users = el && el.querySelectorAll('.user.item');
el.classList.add('ffz-enhanced-following');
var had_data = true;
if ( users && users.length )
for(var i=0; i < users.length; i++)
had_data = this.ffzProcessUser(users[i]) && had_data;
else
had_data = false;
if ( ! had_data ) {
// Force a refresh.
f.log("Forcing a refresh of user following data.");
var following = this.get('context.following'),
refresher = function() {
if ( following.get('isLoading') )
setTimeout(refresher, 25);
following.clear();
following.load();
}
// We use this weird function to prevent trying to load twice mucking things up.
setTimeout(refresher);
}
// Watch for new ones the bad way.
if ( ! this._ffz_observer ) {
var t = this;
var observer = this._ffz_observer = new MutationObserver(function(mutations) {
for(var i=0; i < mutations.length; i++) {
var mutation = mutations[i];
if ( mutation.type !== "childList" )
continue;
for(var x=0; x < mutation.addedNodes.length; x++) {
var added = mutation.addedNodes[x];
if ( added.nodeType !== added.ELEMENT_NODE || added.tagName !== "DIV" )
continue;
// Is it an ember-view? Check its kids.
if ( added.classList.contains('ember-view') ) {
var users = added.querySelectorAll('.user.item');
if ( users )
for(var y=0; y < users.length; y++)
t.ffzProcessUser(users[y]);
} else if ( added.classList.contains('user') )
t.ffzProcessUser(added);
}
}
});
observer.observe(el, {
childList: true,
subtree: true
});
}
},
ffzTeardown: function() {
if ( this._ffz_observer ) {
this._ffz_observer.disconnect();
this._ffz_observer = null;
}
},
ffzProcessUser: function(user) {
if ( user.classList.contains('ffz-processed') )
return true;
var link = user.querySelector('a'),
link_parts = link && link.href.split("/"),
user_id = link_parts && link_parts[3],
data = f._following_cache[user_id],
t_el = document.createElement('div');
user.classList.add('ffz-processed');
if ( ! data )
return false;
t_el.className = 'overlay_info length';
jQuery(t_el).tipsy({html: true});
var age = data[0] ? Math.floor((Date.now() - data[0].getTime()) / 1000) : 0;
if ( age ) {
t_el.innerHTML = constants.CLOCK + ' ' + utils.human_time(age, 10);
t_el.setAttribute('original-title', 'Following Since: <nobr>' + data[0].toLocaleString() + '</nobr>');
} else
t_el.style.display = 'none';
user.appendChild(t_el);
var actions = document.createElement('div'),
follow = document.createElement('button'),
notif = document.createElement('button'),
update_follow = function() {
data = f._following_cache[user_id];
user.classList.toggle('followed', data);
follow.innerHTML = constants.HEART + constants.UNHEART + '<span> Follow</span>';
if ( t_el ) {
var age = data && data[0] ? Math.floor((Date.now() - data[0].getTime()) / 1000) : undefined;
if ( age !== undefined ) {
t_el.innerHTML = constants.CLOCK + ' ' + (age < 60 ? 'now' : utils.human_time(age, 10));
t_el.setAttribute('original-title', 'Following Since: <nobr>' + data[0].toLocaleString() + '</nobr>');
t_el.style.display = '';
} else {
t_el.style.display = 'none';
}
}
},
update_notif = function() {
data = f._following_cache[user_id];
notif.classList.toggle('notifications-on', data && data[1]);
notif.textContent = 'Notification ' + (data && data[1] ? 'On' : 'Off');
};
actions.className = 'actions';
follow.className = 'button follow';
notif.className = 'button notifications';
update_follow();
update_notif();
follow.addEventListener('click', function() {
var was_following = !!data;
follow.disabled = true;
notif.disabled = true;
follow.textContent = 'Updating';
(was_following ?
Twitch.api.del("users/:login/follows/channels/" + user_id) :
Twitch.api.put("users/:login/follows/channels/" + user_id, {notifications: false}))
.done(function() {
data = f._following_cache[user_id] = was_following ? null : [new Date(), false];
})
.always(function() {
update_follow();
update_notif();
follow.disabled = false;
notif.disabled = false;
})
});
notif.addEventListener('click', function() {
var was_following = data[1];
follow.disabled = true;
notif.disabled = true;
notif.textContent = 'Updating';
Twitch.api.put("users/:login/follows/channels/" + user_id, {notifications: !was_following})
.done(function() {
data[1] = ! was_following;
})
.always(function() {
update_notif();
follow.disabled = false;
notif.disabled = false;
});
});
actions.appendChild(follow);
actions.appendChild(notif);
user.appendChild(actions);
return true;
}
});
// Now, rebuild any views.
try {
ProfileView.create().destroy();
} catch(err) { }
for(var key in Ember.View.views) {
var view = Ember.View.views[key];
if ( ! view || !(view instanceof ProfileView) )
continue;
this.log("Manually updating existing Following View.", view);
try {
var following = view.get('context.following');
this._hook_following(following);
} catch(err) {
this.error("setup: view:channel/following: model hook: " + err);
}
try {
view.ffzInit();
} catch(err) {
this.error("setup: view:channel/following: " + err);
}
}
}
FFZ.prototype._hook_following = function(Following) {
var f = this;
Following.reopen({
apiLoad: function(e) {
var user = f.get_user(),
channel_id = this.get('id'),
t = this;
if ( ! user || user.login !== channel_id )
return this._super(e);
return new RSVP.Promise(function(success, fail) {
t._super(e).then(function(data) {
if ( data && data.follows ) {
var now = Date.now();
for(var i=0; i < data.follows.length; i++) {
var follow = data.follows[i];
if ( ! follow || ! follow.channel || ! follow.channel.name ) {
continue;
}
if ( follow.channel.display_name )
FFZ.capitalization[follow.channel.name] = [follow.channel.display_name, now];
f._following_cache[follow.channel.name] = [follow.created_at ? utils.parse_date(follow.created_at) : null, follow.notifications || false];
}
}
success(data);
}, function(err) {
fail(err);
})
});
}
});
}

View file

@ -549,19 +549,11 @@ FFZ.prototype.setup_line = function() {
this._modify_line(Whisper);
this.log("Hooking the Ember Message Line component.");
var Line = App.__container__.resolve('component:message-line');
if ( Line )
this._modify_line(Line);
this.log("Hooking the Ember Conversation Line component.");
var Conversation = App.__container__.resolve('component:conversation-line');
if ( Conversation )
this._modify_conversation_line(Conversation);
// Store the capitalization of our own name.
var user = this.get_user();
if ( user && user.name )

View file

@ -115,6 +115,8 @@ FFZ.prototype.setup_room = function() {
FFZ.prototype._modify_rview = function(view) {
var f = this;
view.reopen({
alternate: false,
didInsertElement: function() {
this._super();
@ -134,6 +136,10 @@ FFZ.prototype._modify_rview = function(view) {
this._super();
},
ffzUpdateAlternate: function() {
this.get('element').classList.toggle('ffz-alternate', this.get('ffzAlternate'));
}.observes("ffzAlternate"),
ffzInit: function() {
f._roomv = this;
@ -1182,10 +1188,10 @@ FFZ.prototype._modify_room = function(room) {
return;
var is_whisper = msg.style === 'whisper';
if ( f.settings.group_tabs && f.settings.whisper_room ) {
if ( ( is_whisper && ! this.ffz_whisper_room ) || ( ! is_whisper && this.ffz_whisper_room ) )
return;
}
// Ignore whispers if conversations are enabled.
if ( is_whisper && App.__container__.lookup('route:application').controller.get('isConversationsEnabled') )
return;
if ( ! is_whisper )
msg.room = this.get('id');

View file

@ -262,7 +262,7 @@ FFZ.prototype._emote_tooltip = function(emote) {
title = set && set.title || "Global",
source = set && set.source || "FFZ";
emote._tooltip = "Emoticon: " + (emote.hidden ? "???" : emote.name) + "\n" + source + " " + title + (owner ? "\nBy: " + owner.display_name : "");
emote._tooltip = "Emoticon: " + (emote.hidden ? "???" : emote.name) + "<br>" + source + " " + title + (owner ? "<br>By: " + owner.display_name : "");
return emote._tooltip;
}

View file

@ -22,7 +22,7 @@ FFZ.get = function() { return FFZ.instance; }
// Version
var VER = FFZ.version_info = {
major: 3, minor: 5, revision: 57,
major: 3, minor: 5, revision: 62,
toString: function() {
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
}
@ -123,11 +123,13 @@ require('./ember/room');
require('./ember/layout');
require('./ember/line');
require('./ember/chatview');
require('./ember/conversations');
require('./ember/viewers');
require('./ember/moderation-card');
require('./ember/chat-input');
//require('./ember/teams');
require('./ember/directory');
require('./ember/following');
require('./debug');
@ -335,10 +337,12 @@ FFZ.prototype.init_ember = function(delay) {
this.setup_line();
this.setup_layout();
this.setup_chatview();
this.setup_conversations();
this.setup_viewers();
this.setup_mod_card();
this.setup_chat_input();
this.setup_directory();
this.setup_profile_following();
//this.setup_teams();

View file

@ -35,7 +35,7 @@ var FFZ = window.FrankerFaceZ,
set_type = null;
}
return "Emoticon: " + data.code + "\n" + (set_type ? set_type + ": " : "") + set + (owner ? "\nBy: " + owner.display_name : "");
return "Emoticon: " + data.code + "<br>" + (set_type ? set_type + ": " : "") + set + (owner ? "<br>By: " + owner.display_name : "");
},
build_tooltip = function(id) {
@ -603,7 +603,7 @@ FFZ.prototype.render_tokens = function(tokens, render_links) {
var emote_set = f.emote_sets && f.emote_sets[token.ffzEmoteSet],
emote = emote_set && emote_set.emoticons && emote_set.emoticons[token.ffzEmote];
tooltip = emote ? utils.sanitize(f._emote_tooltip(emote)) : token.altText;
tooltip = emote ? f._emote_tooltip(emote) : token.altText;
srcset = emote ? emote.srcSet : token.srcSet;
extra = (emote ? ' data-ffz-emote="' + emote.id + '"' : '') + (emote_set ? ' data-ffz-set="' + emote_set.id + '"' : '');
@ -652,7 +652,7 @@ FFZ.prototype.render_tokens = function(tokens, render_links) {
srcset = build_srcset(id);
}
return '<img class="emoticon tooltip' + (cls||"") + '"' + (extra||"") + ' src="' + utils.quote_attr(src) + '" ' + (srcset ? 'srcset="' + utils.quote_attr(srcset) + '" ' : '') + 'alt="' + utils.quote_attr(token.altText) + '" title="' + utils.quote_attr(tooltip) + '">';
return '<img class="emoticon html-tooltip' + (cls||"") + '"' + (extra||"") + ' src="' + utils.quote_attr(src) + '" ' + (srcset ? 'srcset="' + utils.quote_attr(srcset) + '" ' : '') + 'alt="' + utils.quote_attr(token.altText) + '" title="' + utils.quote_attr(tooltip) + '">';
}
if ( token.isLink ) {

View file

@ -224,6 +224,9 @@ FFZ.prototype.build_ui_popup = function(view) {
container.classList.toggle('dark', dark);
// Stuff
jQuery(inner).find('.html-tooltip').tipsy({live: true, html: true, gravity: jQuery.fn.tipsy.autoNS});
// Menu Container
var sub_container = document.createElement('div');
@ -599,7 +602,7 @@ FFZ.prototype._emotes_for_sets = function(parent, view, sets, header, image, sub
c++;
var s = document.createElement('span');
s.className = 'emoticon tooltip';
s.className = 'emoticon html-tooltip';
s.style.backgroundImage = 'url("' + emote.urls[1] + '")';
if ( srcset ) {

View file

@ -166,7 +166,7 @@ FFZ.menu_pages.myemotes = {
if ( (settings === 1 && ! emoji.tw) || (settings === 2 && ! emoji.noto) )
continue;
em.className = 'emoticon tooltip';
em.className = 'emoticon html-tooltip';
em.title = 'Emoji: ' + emoji.raw + '\nName: ' + emoji.name + (emoji.short_name ? '\nShort Name: :' + emoji.short_name + ':' : '');
em.addEventListener('click', this._add_emote.bind(this, view, emoji.raw));
@ -239,7 +239,7 @@ FFZ.menu_pages.myemotes = {
em = document.createElement('span'),
img_set = 'image-set(url("' + TWITCH_BASE + emote.id + '/1.0") 1x, url("' + TWITCH_BASE + emote.id + '/2.0") 2x, url("' + TWITCH_BASE + emote.id + '/3.0") 4x)';
em.className = 'emoticon tooltip';
em.className = 'emoticon html-tooltip';
if ( this.settings.replace_bad_emotes && constants.EMOTE_REPLACEMENTS[emote.id] ) {
em.style.backgroundImage = 'url("' + constants.EMOTE_REPLACEMENT_BASE + constants.EMOTE_REPLACEMENTS[emote.id] + '")';
@ -316,7 +316,7 @@ FFZ.menu_pages.myemotes = {
img_set += ')';
em.className = 'emoticon tooltip';
em.className = 'emoticon html-tooltip';
em.style.backgroundImage = 'url("' + emote.urls[1] + '")';
em.style.backgroundImage = '-webkit-' + img_set;
em.style.backgroundImage = '-moz-' + img_set;

View file

@ -16,7 +16,7 @@ FFZ.prototype.setup_css = function() {
/*var s = this._main_style = document.createElement('style');
s.textContent = styles.style;
s.id = "ffz-ui-css";
s.id = "ffz-main-css";
document.head.appendChild(s);*/

2408
style.css Normal file

File diff suppressed because it is too large Load diff