1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-09-16 01:56:55 +00:00

3.5.457. Commerce stuff. Favorite any emote. Consolidate emotes from your Twitch Inventory. Dark CSS tweaks. Add emoji size settings. Highlight messages with mentions without having alternating rows enabled.

This commit is contained in:
SirStendec 2017-04-05 19:12:11 -04:00
parent 3d6acd46dd
commit 61ac0b97f6
20 changed files with 830 additions and 160 deletions

View file

@ -90,21 +90,29 @@ FFZ.settings_info.bits_pinned = {
}
FFZ.settings_info.bits_disable_charity = {
FFZ.settings_info.bits_redesign = {
type: "boolean",
value: false,
category: "Chat Filtering",
name: "Disable Cheering with #Charity Notices",
help: "Stop displaying Twitch's notices about Cheering with #Charity."
}
category: "Chat Appearance",
name: "Bits Redesign",
help: "Use the special cheering animations from April 1st, 2017.",
on_update: function() {
var bits = utils.ember_lookup('service:bits-emotes') ||
utils.ember_lookup('service:bits-rendering-config');
if ( bits && bits.ffz_has_css )
bits.ffz_update_css();
}
}
// --------------------
// Initialization
// --------------------
var redesign = function(x) { return x.replace('/actions/cheer/', '/actions/cheer-redesign/') };
FFZ.prototype.setup_bits = function() {
utils.toggle_cls('ffz-show-bits-tags')(this.settings.bits_tags_container);
@ -115,9 +123,19 @@ FFZ.prototype.setup_bits = function() {
PinnedCheers = utils.ember_lookup('service:bits-pinned-cheers'),
image_css = function(images) {
return 'background-image: url("' + images[1] + '");' +
var im_1 = images[1],
im_2 = images[2],
im_4 = images[4];
if ( f.settings.bits_redesign ) {
im_1 = redesign(im_1);
im_2 = redesign(im_2);
im_4 = redesign(im_4);
}
return 'background-image: url("' + im_1 + '");' +
'background-image: ' + (constants.IS_WEBKIT ? ' -webkit-' : '') + 'image-set(' +
'url("' + images[1] + '") 1x, url("' + images[2] + '") 2x, url("' + images[4] + '") 4x);';
'url("' + im_1 + '") 1x, url("' + im_2 + '") 2x, url("' + im_4 + '") 4x);';
},
tier_css = function(ind, prefix, tier) {
@ -184,7 +202,8 @@ FFZ.prototype.setup_bits = function() {
},
ffz_get_preview: function(prefix, amount) {
return this.getImageSrc(amount, prefix, true, !f.settings.bits_animated, 4);
var src = this.getImageSrc(amount, prefix, true, !f.settings.bits_animated, 4);
return f.settings.bits_redesign ? redesign(src) : src;
},
_ffz_image_css: image_css,
@ -249,12 +268,14 @@ FFZ.prototype.setup_bits = function() {
ffz_get_preview: function(prefix, amount) {
var data = this.ffz_get_tier(prefix, amount),
tier = data && data[1];
return tier ? this._constructImageSrc([4], tier, {
background: 'dark',
scale: 4,
state: f.settings.bits_animated ? 'animated' : 'static'
}).src : '';
tier = data && data[1],
src = tier ? this._constructImageSrc([4], tier, {
background: 'dark',
scale: 4,
state: f.settings.bits_animated ? 'animated' : 'static'
}).src : '';
return f.settings.bits_redesign ? redesign(src) : src;
},
_ffz_image_css: image_css,

316
src/ember/commerce.js Normal file
View file

@ -0,0 +1,316 @@
var FFZ = window.FrankerFaceZ,
utils = require('../utils'),
constants = require('../constants');
// --------------------
// Settings
// --------------------
FFZ.settings_info.show_commerce = {
type: "select",
options: {
0: "Never",
1: "When Revenue is Shared",
2: "Always"
},
value: 2,
process_value: utils.process_int(0),
no_mobile: true,
category: "Commerce",
name: "Display Commerce Bar",
help: "Show the commerce bar under channels that allows you to purchase supported games.",
on_update: function(val) {
utils.toggle_cls('ffz-hide-purchase-game')(val === 0);
var views = utils.ember_views(),
ChannelBox = utils.ember_resolve('component:commerce/channel-box');
if ( ! ChannelBox )
return;
for(var key in views)
if ( views[key] instanceof ChannelBox )
try {
views[key].ffzUpdateVisibility();
} catch(err) { }
}
}
FFZ.settings_info.show_itad = {
type: "boolean",
value: true,
no_mobile: true,
category: "Commerce",
name: "Display Competitor Pricing",
help: "Add a button on the commerce bar with pricing from other stores.",
on_update: function(val) {
var views = utils.ember_views(),
BuyGameNow = utils.ember_resolve('component:commerce/buy-game-now');
if ( ! BuyGameNow )
return;
for(var key in views)
if ( views[key] instanceof BuyGameNow )
try {
views[key].ffzRenderPricing();
} catch(err) { }
}
}
// --------------------
// Initialization
// --------------------
FFZ.prototype.setup_commerce = function() {
this._itad_game_to_plain = {};
// Styles
utils.toggle_cls('ffz-hide-purchase-game')(this.settings.show_commerce === 0);
// Ember Modifications
this.update_views('component:commerce/channel-box', this.modify_commerce_box);
this.update_views('component:commerce/buy-game-now', this.modify_buy_game_now);
}
// --------------------
// Modifications
// --------------------
FFZ.prototype.modify_commerce_box = function(view) {
var f = this;
utils.ember_reopen_view(view, {
ffz_init: function() {
this.ffzUpdateVisibility();
},
ffzUpdateVisibility: function() {
var el = this.parentView.get('element'),
real_el = el && el.querySelector('.cmrc-channel-box');
if ( ! real_el )
! this.isDestroyed && setTimeout(this.ffzUpdateVisibility.bind(this), 250);
else
real_el.classList.toggle('hidden', f.settings.show_commerce === 1 && ! this.get('showSupports'));
}.observes('showSupports')
})
}
FFZ.prototype.modify_buy_game_now = function(view) {
var f = this;
utils.ember_reopen_view(view, {
itad_plain: null,
itad_price: null,
twitch_geo: null,
ffz_init: function() {
//f.log("Buy-Game-New Component", this);
this.itad_count = 0;
this.ffzUpdateITADPlain();
var t = this;
Twitch.geo.then(function(data) {
t.set('twitch_geo', data && data.geo);
});
},
ffzTitle: function() {
// Do this because Twitch's ToS say you're not allowed to use data collected from
// the API to show users commercial offers. This extracts the game title from the
// page itself and not from any kind of JS API.
// Granted, they're probably more worried about automated chat spam and people
// sending spam to email addresses recovered from authenticated user profile requests.
var el;
if ( document.body.dataset.currentPath === 'directory.game-details' )
el = document.querySelector('.game-details__page-title');
else
el = document.querySelector('.card__info [data-tt_content="current_game"]');
var output = el ? _.pluck(_.filter(el.childNodes, function(x) { return x.nodeType === document.TEXT_NODE }), 'textContent').join(' ').trim() : null;
if ( ! output && this.itad_count < 50 ) {
var t = this;
setTimeout(function() {
t.itad_count += 1;
Ember.propertyDidChange(this, 'ffzTitle');
}, 250);
}
return output;
}.property(),
didReceiveAttrs: function() {
this._super();
Ember.propertyDidChange(this, 'ffzTitle');
},
ffzUpdateITADPlain: function() {
var title = this.get('ffzTitle'),
old_plain = this.get('itad_plain'),
plain = f._itad_game_to_plain[title] || null;
//f.log("Update ITAD Plain: " + title + " -- [" + plain + "]", this);
// If we already have the value, fetch it now.
if ( ! title || plain ) {
if ( old_plain !== plain )
this.set('itad_plain', plain);
return;
}
if ( old_plain )
this.set('itad_plain', null);
var t = this;
f.ws_send("get_itad_plain", title, function(success, data) {
if ( ! success ) return;
f._itad_game_to_plain[title] = data;
t.ffzUpdateITADPlain();
}, true);
}.observes('ffzTitle'),
ffzUpdateITADPrice: function() {
var t = this,
old_price = this.get('itad_price'),
geo = this.get('twitch_geo'),
plain = this.get('itad_plain');
if ( old_price && old_price[0] === plain )
return;
if ( ! plain || ! geo )
return this.set('itad_price', null);
this.set('itad_price', [plain, null]);
f.ws_send("get_itad_prices", [plain, geo], function(success, data) {
if ( ! success ) return;
t.set('itad_price', [plain, data]);
});
}.observes('itad_plain', 'twitch_geo'),
ffzRenderPricing: function() {
var t = this,
el = this.get('element'),
cont = el && el.querySelector('.ffz-price-info'),
btn_price,
data = this.get('itad_price');
if ( ! f.settings.show_itad || ! data || ! data[1] || ! data[1].list || ! data[1].list.length ) {
if ( cont )
jQuery(cont).remove();
return;
}
if ( ! cont ) {
cont = utils.createElement('div', 'ffz-price-info mg-l-1 balloon-wrapper');
btn_price = utils.createElement('span', 'ffz-price-num button__num-block pd-x-1 mg-1-0');
var btn = utils.createElement('button', 'button itad-button button--dropmenu',
utils.createElement('span', 'ffz-price-label inline-block pd-r-1', 'ITAD'));
btn.appendChild(btn_price);
cont.appendChild(btn);
el.appendChild(cont);
btn.addEventListener('click', function(event) {
t.ffzRenderPopup(event);
});
} else
btn_price = cont.querySelector('.ffz-price-num');
// Determine the cheapest price.
var sales = data[1].list,
cheapest = sales[0].price_new,
currency = data[1].currency,
formatter = new Intl.NumberFormat(undefined, (currency && currency.code) ? {style: 'currency', currency: currency.code, minimumFractionDigits: 2} : {minimumFractionDigits: 2});
btn_price.textContent = formatter.format(cheapest);
}.observes('itad_price'),
ffzRenderPopup: function(e) {
if ( e.button !== 0 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey )
return;
e.preventDefault();
e.stopPropagation();
var popup = f._popup ? f.close_popup() : f._last_popup,
t = this,
data = t.get('itad_price'),
el = this.get('element'),
cont = el && el.querySelector('.ffz-price-info');
if ( popup && popup.id === 'ffz-price-popup' || ! data || ! data[1] || ! data[1].list || ! data[1].list.length )
return;
var balloon = utils.createElement('div', 'itad-balloon balloon balloon--md show', '<table><thead><tr><th>Store</th><th>Price Cut</th><th>Current</th><th>Regular</th></tr></thead><tbody></tbody></table>'),
tbody = balloon.querySelector('tbody');
balloon.id = 'ffz-price-popup';
// Render the table.
var currency = data[1].currency,
formatter = new Intl.NumberFormat(undefined, (currency && currency.code) ? {style: 'currency', currency: currency.code, minimumFractionDigits: 2} : {minimumFractionDigits: 2});
var sales = data[1].list;
for(var i=0; i < sales.length; i++) {
var entry = sales[i],
row = utils.createElement('tr');
row.innerHTML = '<td><a rel="noreferrer" target="_blank" href="' + utils.quote_san(entry.url) + '">' + utils.sanitize(entry.shop.name) + '</a></td>' +
'<td>' + (entry.price_cut < 0 ? '' : '-') + utils.sanitize(entry.price_cut) + '%</td>' +
'<td>' + formatter.format(entry.price_new) + '</td>' +
'<td>' + formatter.format(entry.price_old) + '</td>';
tbody.appendChild(row);
}
// Add a by-line for IsThereAnyDeal.
var url = data[1].urls && data[1].urls.game || "https://isthereanydeal.com",
by_line = utils.createElement('span', 'ffz-attribution', 'Source: <a rel="noreferrer" target="_blank" href="' + utils.quote_san(url) + '">IsThereAnyDeal.com</a><br><br>Any affiliate links in the provided data are the responsibility of IsThereAnyDeal.');
balloon.appendChild(by_line);
// Now calculate the position and add the balloon to the DOM.
var container = document.querySelector('#main_col'),
outer = container.getBoundingClientRect(),
rect = cont.getBoundingClientRect();
var is_up = (rect.top - outer.top) > (outer.bottom - rect.bottom);
balloon.classList.add('balloon--' + (is_up ? 'up' : 'down'));
balloon.classList.toggle('balloon--right', (rect.left - outer.left) > (outer.right - rect.right));
f._popup_allow_parent = true;
f._popup = balloon;
cont.appendChild(balloon);
}
})
}

View file

@ -346,17 +346,30 @@ FFZ.settings_info.image_hover_all_domains = {
FFZ.settings_info.chat_rows = {
type: "boolean",
value: false,
type: "select",
options: {
0: "Disabled",
1: "Alternating",
2: "Red Highlights",
3: "Both"
},
value: 0,
process_value: utils.process_int(0, 0, 3),
category: "Chat Appearance",
no_bttv: true,
name: "Chat Line Backgrounds",
help: "Display alternating background colors for lines in chat.",
help: "Display alternating background colors for lines in chat or make messages with highlighted words red.",
on_update: function(val) {
this.toggle_style('chat-background', !this.has_bttv && val);
if ( this.has_bttv )
val = 0;
this.toggle_style('chat-background', val === 1 || val === 3);
this.toggle_style('chat-mention-bg', val > 1);
this.toggle_style('chat-mention-bg-alt', val === 3);
}
};
@ -527,6 +540,36 @@ FFZ.settings_info.chat_font_family = {
};
FFZ.settings_info.emoji_scale = {
type: "select",
options: {
0: "Scale with Text (Default)",
1: "Old Default (18px)",
2: "Emote Size (28px)"
},
value: 0,
process_value: utils.process_int(0),
category: "Chat Appearance",
no_bttv: true,
name: "Emoji Size",
help: "Make emoji in chat bigger or smaller.",
on_update: function(val) {
var size = 18;
if ( val === 0 )
size = 1.5 * this.settings.chat_font_size;
else if ( val === 2 )
size = 28;
utils.update_css(this._chat_style, 'emoji_size',
size !== 18 ? '.chat-line .emoji{height:' + size + 'px}' : '');
}
}
FFZ.settings_info.chat_font_size = {
type: "button",
value: 12,
@ -567,6 +610,7 @@ FFZ.settings_info.chat_font_size = {
else {
var lh = Math.max(20, Math.round((20/12)*val)),
pd = Math.floor((lh - 20) / 2);
css = ".pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history .chat-line,.ember-chat .chat-messages .chat-line { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
if ( pd )
css += ".pinned-cheers .chat-line,.ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: " + pd + "px; }";
@ -574,6 +618,7 @@ FFZ.settings_info.chat_font_size = {
utils.update_css(this._chat_style, "chat_font_size", css);
FFZ.settings_info.chat_ts_size.on_update.call(this, this.settings.chat_ts_size);
FFZ.settings_info.emoji_scale.on_update.call(this, this.settings.emoji_scale);
}
};
@ -664,7 +709,7 @@ FFZ.prototype.setup_line = function() {
utils.toggle_cls('ffz-baseline-emoticons')(!this.has_bttv && this.settings.emote_alignment === 2);
this.toggle_style('chat-padding', !this.has_bttv && this.settings.chat_padding);
this.toggle_style('chat-background', !this.has_bttv && this.settings.chat_rows);
FFZ.settings_info.chat_rows.on_update.call(this, this.settings.chat_rows);
this.toggle_style('chat-separator', !this.has_bttv && this.settings.chat_separators);
this.toggle_style('chat-separator-3d', !this.has_bttv && this.settings.chat_separators === 2);

View file

@ -2112,9 +2112,6 @@ FFZ.prototype._modify_room = function(room) {
notice_type = msg.tags && msg.tags['msg-id'],
is_whisper = msg.style === 'whisper';
if ( notice_type === 'charity' && f.settings.bits_disable_charity )
return;
// If this message is already in the room, discard the duplicate.
if ( msg_id && this.ffz_ids && this.ffz_ids[msg_id] )
return;