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

3.5.471. Fixes for the directory. Closes #138. Closes #134. Closes #130. Closes #136. Older: Changes to ITAD popup. Top nav color. Better tool-tips for social bar

This commit is contained in:
SirStendec 2017-04-21 20:02:27 -04:00
parent 996ab7031e
commit e2803a7e1d
23 changed files with 451 additions and 126 deletions

View file

@ -1,3 +1,53 @@
<div class="list-header">3.5.471 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Friend Watching Notifications setting to show notifications when you get a message that a friend is also watching the same channel.</li>
<li>Added: Highlight Users setting to highlight all messages from specific users to tide people over until FFZv4.</li>
<li>Fixed: Changes to Twitch directory breaking channel logo and uptime display.</li>
<li>Fixed: Apply hidden thumbnails setting to more video preview components.</li>
<li>Fixed: Caching of emoji codepoint calculation.</li>
<li>Fixed: Bug with unclickable usernames in moderation card chat history.</li>
<li>Fixed: Don't re-enable gray mode if a user has it specifically disabled and they enable dark mode via the Twitch chat settings menu.</li>
</ul>
<div class="list-header">3.5.470 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: More improved wording for the ITAD popup.</li>
</ul>
<div class="list-header">3.5.469 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Add a bit more nagging when trying to buy from ITAD when a streamer would be supported.</li>
</ul>
<div class="list-header">3.5.468 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Improved the wording for the disclaimer on the ITAD popup.</li>
</ul>
<div class="list-header">3.5.467 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Better tooltips for live followed channels in the social bar.</li>
<li>Fixed: Position of Channel Bar with Minimize Navigation, channel bar on top, and non-minimized channel bar. (Yes, debugging layout things is fun.)</li>
</ul>
<div class="list-header">3.5.466 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Following Data feature not working for top navigation.</li>
<li>Fixed: Open Following to Channels not working for top navigation.</li>
</ul>
<div class="list-header">3.5.465 <time datetime="2017-04-11">(2017-04-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Option to change the color of Twitch's Top Navigation bar.</li>
<li>Fixed: Minimize Navigation not properly hiding the newly modified top navigation bar.</li>
<li>Fixed: Darken a few changes to Twitch's layout.</li>
</ul>
<div class="list-header">3.5.464 <time datetime="2017-04-10">(2017-04-10)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Bug with BetterTTV v7 and tab completion handling.</li>
</ul>
<div class="list-header">3.5.463 <time datetime="2017-04-10">(2017-04-10)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Improved compatibility with BetterTTV v7 (aka the beta)</li>
@ -8,50 +58,5 @@
<li>Fixed: Rendering of <code>system-msg</code> tags that contain template strings or other nonsense that Twitch, for some reason, isn't just putting in the message itself and is making the client reconstruct from tags.</li>
</ul>
<div class="list-header">3.5.461 <time datetime="2017-04-08">(2017-04-08)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Potential infinite loop in new prefix detection code.</li>
</ul>
<div class="list-header">3.5.460 <time datetime="2017-04-07">(2017-04-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Tab completion breaking when encountering an empty emote set.</li>
</ul>
<div class="list-header">3.5.459 <time datetime="2017-04-07">(2017-04-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Improved prefix detection for tab-completion of sub emotes.</li>
<li>Fixed: Darken an input box in the video manager.</li>
<li>API Added: <code>has_prefix</code> for emote sets and <code>prefix_length</code> for emote sets and emotes.</li>
</ul>
<div class="list-header">3.5.458 <time datetime="2017-04-06">(2017-04-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Display a disclaimer on the ITAD popup that purchases made on other websites don't earn Twitch Crates and don't support streamers. Those are both cool things and should be supported.</li>
<li>Fixed: Scrolling over the player could end up scrolling the page when the player is already above 90% volume or below 10% volume.</li>
<li>Fixed: Volume slider not always visible when it should be.</li>
</ul>
<div class="list-header">3.5.457 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Another minor number formatting issue.</li>
</ul>
<div class="list-header">3.5.456 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Disclaimer about IsThereAnyDeal's affiliate links.</li>
</ul>
<div class="list-header">3.5.455 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Minor number formatting issue.</li>
</ul>
<div class="list-header">3.5.454 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: IsThereAnyDeal integration.</li>
<li>Fixed: Dashboard columns not being scrollable.</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

@ -425,6 +425,8 @@ body.ffz-dark:not([data-page="teams#show"]),
color: #a68ed2;
}
.ffz-dark .form__icon svg { fill: rgba(255,255,255,0.2) }
.ffz-dark .button--icon.button--hollow figure svg,
.ffz-dark .button.button--icon-only svg {
fill: #a68ed2;
@ -1680,6 +1682,7 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: #a68ed2;
}
.ffz-dark .offer-list__core:after,
.ffz-dark .offer-item__ci:after {
background-image: linear-gradient(rgba(16,16,16,0) 0,#101010 100%)
}
@ -1735,6 +1738,7 @@ body.ffz-dark:not([data-page="teams#show"]),
.ffz-dark .notification-center-balloon:before,
.ffz-dark .notification-center-balloon:after { display: none }
.ffz-dark .friend-requests__empty,
.ffz-dark .friend-request__content-msg,
.ffz-dark .friend-requests__footer a:hover,
.ffz-dark .notification-center__unread-container,
@ -1754,6 +1758,19 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: rgba(255,255,255,0.2);
}
.ffz-dark .sc-onboarding .sc-onboarding__content,
.ffz-dark .sc-onboarding .sc-onboarding__close {
background-color: #101010;
box-shadow: -0.1rem 0 0 #474747 inset;
}
.ffz-dark .sc-onboarding {
box-shadow: 0 0 0 0.1rem #474747;
}
.ffz-dark .offer-item__ci--wrap { border-color: #474747 }
.ffz-dark .offer-item__background--purple,
.ffz-dark .offer-item--title,
.ffz-dark .notification-center__footer,
.ffz-dark .notification-center__header {
@ -1771,6 +1788,7 @@ body.ffz-dark:not([data-page="teams#show"]),
color: rgba(255,255,255,0.2);
}
.ffz-dark .friend-requests__empty,
.ffz-dark .friend-requests__footer,
.ffz-dark .notification--read,
.ffz-dark .notification {

View file

@ -1,3 +1,48 @@
<div class="list-header">3.5.461 <time datetime="2017-04-08">(2017-04-08)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Potential infinite loop in new prefix detection code.</li>
</ul>
<div class="list-header">3.5.460 <time datetime="2017-04-07">(2017-04-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Tab completion breaking when encountering an empty emote set.</li>
</ul>
<div class="list-header">3.5.459 <time datetime="2017-04-07">(2017-04-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Improved prefix detection for tab-completion of sub emotes.</li>
<li>Fixed: Darken an input box in the video manager.</li>
<li>API Added: <code>has_prefix</code> for emote sets and <code>prefix_length</code> for emote sets and emotes.</li>
</ul>
<div class="list-header">3.5.458 <time datetime="2017-04-06">(2017-04-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Display a disclaimer on the ITAD popup that purchases made on other websites don't earn Twitch Crates and don't support streamers. Those are both cool things and should be supported.</li>
<li>Fixed: Scrolling over the player could end up scrolling the page when the player is already above 90% volume or below 10% volume.</li>
<li>Fixed: Volume slider not always visible when it should be.</li>
</ul>
<div class="list-header">3.5.457 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Another minor number formatting issue.</li>
</ul>
<div class="list-header">3.5.456 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Disclaimer about IsThereAnyDeal's affiliate links.</li>
</ul>
<div class="list-header">3.5.455 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Minor number formatting issue.</li>
</ul>
<div class="list-header">3.5.454 <time datetime="2017-04-05">(2017-04-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: IsThereAnyDeal integration.</li>
<li>Fixed: Dashboard columns not being scrollable.</li>
</ul>
<div class="list-header">3.5.453 <time datetime="2017-04-04">(2017-04-04)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Favoriting emotes from your Twitch Inventory.</li>

View file

@ -89,8 +89,11 @@ FFZ.prototype.setup_channel = function() {
model.set('followers.content.meta.total', info.followers);
}
if ( is_host && f._cindex )
f._cindex.ffzFixHostTitle();
if ( f._cindex )
if ( is_host )
f._cindex.ffzFixHostTitle();
else
f._cindex.ffzFixTitle();
});
},

View file

@ -588,7 +588,7 @@ FFZ.prototype.modify_chat_input = function(component) {
this.set('ffz_updating', false);
} else if ( this.ffz_suggestions_el ) {
this.ffz_suggestions_el.parentElement.removeChild(this.ffz_suggestions_el);
jQuery(this.ffz_suggestions_el).remove();
this.ffz_suggestions_el = null;
}

View file

@ -261,6 +261,7 @@ FFZ.prototype.modify_buy_game_now = function(view) {
t = this,
data = t.get('itad_price'),
el = this.get('element'),
has_support = el && el.parentElement && (el.parentElement.querySelector('.cmrc-channel-box__support') || el.parentElement.querySelector('.cmrc-game-detail-box__support')),
cont = el && el.querySelector('.ffz-price-info');
if ( popup && popup.id === 'ffz-price-popup' || ! data || ! data[1] || ! data[1].list || ! data[1].list.length )
@ -281,7 +282,7 @@ FFZ.prototype.modify_buy_game_now = function(view) {
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>' +
row.innerHTML = '<td><a class="store-link" 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>';
@ -289,16 +290,24 @@ FFZ.prototype.modify_buy_game_now = function(view) {
tbody.appendChild(row);
}
if ( has_support )
jQuery('.store-link', tbody).click(function(e) {
var name = has_support.querySelector('strong').textContent,
link_text = e.target.textContent;
if ( ! confirm("By following this link and purchasing from " + link_text + " you will NOT be supporting " + name + ".\n\nAre you sure you wish to contune?") )
return false;
});
// Add a by-line for IsThereAnyDeal.
var url = data[1].urls && data[1].urls.game || "https://isthereanydeal.com",
by_line = utils.createElement('span', 'ffz-attributiona',
'<hr>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.' +
'<hr>Reminder: Buying games on Twitch directly supports partnered streamers and you can earn <a target="_blank" href="https://blog.twitch.tv/twitch-crates-are-coming-soon-f50fa0cd4cdf">Twitch Crates</a> containing emotes and badges.');
'<hr>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 and do not benefit FrankerFaceZ. You may consider visiting the store directly.' +
'<hr>Reminder: When you buy a game from other services, you miss out on the benefits of purchasing from Twitch directly including: supporting partnered streamers and earning <a target="_blank" href="https://blog.twitch.tv/twitch-crates-are-coming-soon-f50fa0cd4cdf">Twitch Crates</a> containing emotes and badges.');
balloon.appendChild(by_line);
// Now calculate the position and add the balloon to the DOM.
var container = document.querySelector('#main_col'),

View file

@ -255,13 +255,15 @@ FFZ.prototype.setup_directory = function() {
this.log("Hooking the Ember Directory views.");
this.update_views('component:stream-preview', function(x) { this.modify_directory_live(x, false) }, true);
this.update_views('component:creative-preview', function(x) { this.modify_directory_live(x, false) }, true);
this.update_views('component:csgo-channel-preview', function(x) { this.modify_directory_live(x, true) }, true);
this.update_views('component:twitch-carousel/stream-item', function(x) { this.modify_directory_live(x, false, true) }, true);
this.update_views('component:stream/snapshot-card', function(x) { this.modify_directory_live(x, false, true) }, true);
this.update_views('component:stream-preview', this.modify_directory_live, true);
this.update_views('component:creative-preview', this.modify_directory_live, true);
this.update_views('component:csgo-channel-preview', function(x) { this.modify_directory_live(x, 'channel.') }, true);
this.update_views('component:stream/lol-metadata', function(x) { this.modify_directory_live(x, 'content.') }, true);
this.update_views('component:twitch-carousel/stream-item', this.modify_directory_live, true);
this.update_views('component:stream/snapshot-card', this.modify_directory_live, true);
this.update_views('component:host-preview', this.modify_directory_host, true, true);
this.update_views('component:video-preview', this.modify_video_preview, true);
this.update_views('component:video/resumable-wrapper', this.modify_video_preview, true);
this.update_views("component:video/following-uploads", this.modify_following_uploads);
this.update_views('component:game-follow-button', this.modify_game_follow_button);
@ -471,21 +473,16 @@ FFZ.prototype.modify_game_follow_button = function(component) {
}
FFZ.prototype.modify_directory_live = function(component, is_csgo, is_card) {
FFZ.prototype.modify_directory_live = function(component, mode) {
var f = this,
pref = is_csgo ? 'channel.' : 'stream.',
meta_selector = is_card ? '.card__body' : '.meta',
thumb_selector = is_card ? '.card__img' : '.thumb',
cap_selector = is_card ? 'a:not(.card__boxpin)' : '.cap';
pref = mode || 'stream.';
utils.ember_reopen_view(component, {
ffz_init: function() {
var el = this.get('element'),
meta = el && el.querySelector(meta_selector),
thumb = el && el.querySelector(thumb_selector),
cap = thumb && thumb.querySelector(cap_selector),
meta = el && el.querySelector('.card__body'),
thumb = el && el.querySelector('.card__img'),
cap = thumb && thumb.querySelector('a:not(.card__boxpin)'),
uptime_setting = f.settings.stream_uptime,
channel_id = this.get(pref + 'channel.name'),
game = this.get(pref + 'game');
@ -515,7 +512,7 @@ FFZ.prototype.modify_directory_live = function(component, is_csgo, is_card) {
t = this;
logo.className = 'profile-photo';
logo.classList.toggle('is-csgo', is_csgo);
logo.classList.toggle('is-csgo', mode === 'channel.');
logo.src = this.get(pref + 'channel.logo') || constants.NO_LOGO;
logo.alt = f.format_display_name(this.get(pref + 'channel.display_name'), channel_id, true, true)[0];
@ -554,14 +551,9 @@ FFZ.prototype.modify_directory_live = function(component, is_csgo, is_card) {
},
ffzUpdateUptime: function() {
var up_since;
if ( is_card )
up_since = this.get(pref + 'createdAt');
else {
var raw_created = this.get(pref + 'created_at');
up_since = raw_created && utils.parse_date(raw_created);
}
var up_since = this.get(pref + 'created_at');
if ( typeof up_since === "string" )
up_since = utils.parse_date(up_since);
var now = Date.now() - (f._ws_server_offset || 0),
uptime = up_since && Math.floor((now - up_since.getTime()) / 1000) || 0;
@ -569,10 +561,7 @@ FFZ.prototype.modify_directory_live = function(component, is_csgo, is_card) {
if ( uptime > 0 ) {
if ( ! this._ffz_uptime ) {
var el = this.get('element'),
cont = el && el.querySelector(thumb_selector);
if ( ! is_card )
cont = cont && cont.querySelector(cap_selector);
cont = el && el.querySelector('.card__img');
if ( ! cont )
return;
@ -736,10 +725,10 @@ FFZ.prototype.modify_directory_host = function(component) {
ffz_init: function() {
var el = this.get('element'),
meta = el && el.querySelector('.meta'),
thumb = el && el.querySelector('.thumb'),
cap = thumb && thumb.querySelector('.cap'),
title = meta && meta.querySelector('.title a'),
meta = el && el.querySelector('.card__body'), //meta'),
thumb = el && el.querySelector('.card__img'), //thumb'),
cap = thumb && thumb.querySelector('a:not(.card__boxpin)'), //.cap'),
title = meta && meta.querySelector('.card__title a'),
target = this.get('stream.target.channel'),
game = this.get('stream.target.meta_game'),

View file

@ -371,7 +371,7 @@ FFZ.prototype.setup_layout = function() {
'top:' + theatre_chat_top + 'px;' +
'height:' + theatre_chat_height + 'px}' +
'.app-main.theatre #player {' +
'right: 0 !important}' +
'left: 0 !important;right: 0 !important}' +
'body.ffz-minimal-channel-bar:not(.ffz-channel-bar-bottom) .cn-bar-fixed {' +
'top: ' + (video_top - 40) + 'px}' +
'body.ffz-minimal-channel-bar:not(.ffz-channel-bar-bottom) .cn-bar-fixed:hover,' +

View file

@ -11,6 +11,18 @@
// Settings
// ---------------------
FFZ.settings_info.friend_notifications = {
type: "boolean",
value: false,
category: "Chat Filtering",
no_bttv: 6,
name: "Friend Watching Notifications",
help: "Display notifications when you receive a message that a friend has started watching the same channel."
}
FFZ.settings_info.alias_italics = {
type: "boolean",
value: true,
@ -232,6 +244,45 @@ FFZ.settings_info.banned_words = {
};
FFZ.settings_info.key_users = {
type: "button",
value: [],
category: "Chat Filtering",
name: "Highlight Users",
help: "Set a list of users that will have all their messages highlighted in chat.",
method: function(e, from_basic) {
var f = this,
old_val = this.settings.key_users.join("\n"),
input = utils.createElement('textarea');
input.style.marginBottom = "20px";
utils.prompt(
"Highlight Users",
"Please enter a list of usernames of users that you would like to be highlighted in chat.</p><p>Case insensitive. One name per line.",
old_val,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
// Split them up.
var vals = new_val.toLowerCase().trim().split(/\s*\n\s*/g),
i = vals.length;
while(i--)
if ( vals[i].length === 0 )
vals.splice(i,1);
f.settings.set("key_users", vals);
},
600, input);
}
};
FFZ.settings_info.keywords = {
type: "button",
value: [],

View file

@ -1611,9 +1611,9 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_cli
jQuery('img.emoticon', l_el).click(function(e) { f._click_emote(this, e) });
if ( modcard ) {
modcard.get('cardInfo.user.id') !== msg.from && jQuery('span.from', l_el).click(function(e) {
modcard.get('cardInfo.user.id') !== msg.from && jQuery('.from', l_el).click(function(e) {
var el = modcard.get('element');
el && f._roomv && f._roomv.get('room.id') === msg.room && f._roomv.actions.showModCard.call(f._roomv, {
el && f._roomv && f._roomv.get('room.id') === msg.room && f._roomv.actions.showModOverlay.call(f._roomv, {
sender: msg.from,
top: parseInt(el.style.top),
left: parseInt(el.style.left)

View file

@ -1330,6 +1330,18 @@ FFZ.prototype._modify_room = function(room) {
},
addFriendsWatchingMessage: function(msg) {
if ( f.settings.friend_notifications && ! document.hasFocus() )
f.show_notification(
msg.replace(/ *VoHiYo$/g, ''),
document.title,
"ffz_watching_notice",
(this.settings.notification_timeout*1000),
function() {
window.focus();
},
null,
'https://static-cdn.jtvnw.net/emoticons/v1/81274/3.0');
this.addMessage({
style: 'admin' + (f.has_bttv_6 ? '' : ' friend-watching'),
message: msg,

View file

@ -184,6 +184,71 @@ FFZ.settings_info.sidebar_disable_friends = {
};
var TWITCH_NAV_COLOR = "#4b367c",
TWITCH_NAV_RGB = FFZ.Color.RGBA.fromCSS(TWITCH_NAV_COLOR),
TWITCH_NAV_Luv = TWITCH_NAV_RGB.toLUVA();
FFZ.settings_info.top_nav_color = {
type: "button",
value: "#4b367c",
category: "Sidebar",
no_mobile: true,
name: "Top Navigation Color",
help: "Set a custom background color for the top navigation bar.",
on_update: function(val) {
var process = true;
val = val.trim();
if ( val.charAt(0) === '!' ) {
process = false;
val = val.substr(1).trimLeft();
}
var color = val && FFZ.Color.RGBA.fromCSS(val),
color_luv = color && color.toLUVA();
if ( ! val || process && ! color )
return utils.update_css(this._theme_style, 'top-nav-color');
else if ( process && color_luv.l > TWITCH_NAV_Luv.l ) {
color = color_luv._l(TWITCH_NAV_Luv.l).toRGBA();
val = color.toCSS();
}
var out = '.top-nav__menu,.top-nav__drawer-anchor,.top-nav__logo{background-color:' + val + '}';
if ( color.luminance() > 0.2 ) {
out += '.top-nav .notification-center__icon svg,.top-nav .prime-logo-crown.prime-logo-crown--white svg,.top-nav__logo svg path, .top-nav__overflow svg path{fill: #000}' +
'.top-nav__user-card:after{border-top-color:#000}' +
'.top-nav__user-status,.top-nav__nav-link{color: #111}' +
'.top-nav #user_display_name,.top-nav__nav-link:hover{color: #000}';
} else
out += '.top-nav__nav-link{color: #d7d7d7}';
utils.update_css(this._theme_style, 'top-nav-color', out);
},
method: function() {
var f = this;
utils.prompt(
"Top Navigation Color",
"Please enter a custom color for the top navigation bar. This supports any valid CSS color or color name.</p><p><b>Examples:</b> <code>red</code>, <code>orange</code>, <code>#333</code>, <code>rgb(255,127,127)</code></p><p><b>Note:</b> Colors will be darkened by default. To prevent a color being darkened, please start your input with an exclamation mark. Example: <code>!orange</code>",
this.settings.top_nav_color,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
new_val = new_val.trim();
f.settings.set("top_nav_color", new_val);
}
)
}
}
/*FFZ.settings_info.sidebar_start_open = {
type: "boolean",
value: false,
@ -213,6 +278,13 @@ FFZ.settings_info.sidebar_directly_to_followed_channels = {
// --------------------
FFZ.prototype.setup_sidebar = function() {
var s = this._theme_style = utils.createElement('style');
s.id = 'ffz-theme-style';
s.type = 'text/css';
document.head.appendChild(s);
FFZ.settings_info.top_nav_color.on_update.call(this, this.settings.top_nav_color);
// CSS to Hide Stuff
utils.toggle_cls('ffz-hide-promoted-games')(this.settings.sidebar_hide_promoted_games);
utils.toggle_cls('ffz-hide-recommended-channels')(this.settings.sidebar_hide_recommended_channels);
@ -259,8 +331,11 @@ FFZ.prototype.setup_sidebar = function() {
// Navigation Component
this.update_views('component:twitch-navigation', this.modify_navigation);
var f = this;
this.update_views('component:twitch-navigation', function(x) { return f.modify_navigation(x, false) });
this.update_views('component:top-nav', function(x) { return f.modify_navigation(x, true) });
this.update_views('component:recommended-channels', this.modify_recommended_channels);
this.update_views('component:social-column/followed-channel', this.modify_social_followed_channel)
// Navigation Service
/*var NavService = utils.ember_lookup('service:navigation');
@ -296,7 +371,66 @@ FFZ.prototype.modify_recommended_channels = function(component) {
}
FFZ.prototype.modify_navigation = function(component) {
FFZ._sc_followed_tooltip_id = 0;
FFZ.prototype.modify_social_followed_channel = function(component) {
var f = this;
utils.ember_reopen_view(component, {
ffz_init: function() {
var t = this,
el = this.get('element'),
card = jQuery('.sc-card', el),
data = card && card.data('tipsy');
if ( ! data || ! data.options )
return;
data.options.html = true;
data.options.gravity = utils.tooltip_placement(constants.TOOLTIP_DISTANCE, 'w');
data.options.title = function(el) {
var old_text = t.get('tooltipText');
if ( ! f.settings.following_count )
return 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) {
var el = document.querySelector('#ffz-sc-tooltip-' + tt_id);
if ( ! el || ! data || ! data.stream )
return;
var channel = data.stream.channel,
is_spoilered = f.settings.spoiler_games.indexOf(channel.game && channel.game.toLowerCase()) !== -1,
up_since = f.settings.stream_uptime && data.stream.created_at && utils.parse_date(data.stream.created_at),
now = Date.now() - (f._ws_server_offset || 0),
uptime = up_since && (Math.floor((now - up_since.getTime()) / 60000) * 60) || 0;
var cl = el.parentElement.parentElement.classList;
cl.add('ffz-wide-tip');
cl.add('ffz-follow-tip');
el.innerHTML = '<img class="ffz-image-hover" src="' + utils.quote_san(is_spoilered ? 'https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg' : data.stream.preview.large) + '">' +
'<span class="ffz-tt-channel-title">' + utils.sanitize(channel.status) + '</span><hr>' +
(uptime > 0 ? '<span class="stat">' + constants.CLOCK + ' ' + utils.duration_string(uptime) + '</span>' : '') +
'<span class="stat">' + constants.LIVE + ' ' + utils.number_commas(data.stream.viewers) + '</span>' +
'<b>' + utils.sanitize(channel.display_name || channel.name) + '</b><br>' +
'<span class="playing">' +
(channel.game === 'Creative' ?
'Being Creative' :
(channel.game ?
'Playing ' + utils.sanitize(channel.game) :
'Not Playing')) +
'</span>';
});
return '<div id="ffz-sc-tooltip-' + tt_id + '">' + utils.sanitize(old_text) + '</div>';
};
}
})
}
FFZ.prototype.modify_navigation = function(component, is_top_nav) {
var f = this;
utils.ember_reopen_view(component, {
@ -304,11 +438,11 @@ FFZ.prototype.modify_navigation = function(component) {
f._nav = this;
// Fix tooltips now that we've overrode the function.
this._initTooltips();
! is_top_nav && this._initTooltips();
// Override behavior for the Following link.
var el = this.get('element'),
following_link = el && el.querySelector('a[data-href="following"]');
following_link = el && el.querySelector(is_top_nav ? 'a[data-tt_content="directory_following"]' : 'a[data-href="following"]');
if ( following_link ) {
following_link.href = '/directory/following' + (f.settings.sidebar_directly_to_followed_channels ? '/live' : '');

View file

@ -154,6 +154,18 @@
box-shadow: inset 0 0 0 1px lighten(@bg-color, 10%);
}
.button--disabled {
background-color: fade(black, 20%);
color: fade(@fg-color, 25%);
border-color: fade(@fg-color, 35%);
&:hover, &:focus {
background-color: fade(black, 20%);
color: fade(@fg-color, 25%);
border-color: fade(@fg-color, 35%);
}
}
.button--hollow.button--dropmenu {
&:after {

View file

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

View file

@ -141,8 +141,8 @@ FFZ.prototype._get_settings_object = function(skip_default) {
FFZ.prototype.save_settings_file = function() {
var data = this._get_settings_object(),
blob = new Blob(
[JSON.stringify(data, null, 4)], {type: "application/json;charset=utf-8"});
blob = new Blob(
[JSON.stringify(data, null, 4)], {type: "application/json;charset=utf-8"});
FileSaver.saveAs(blob, "ffz-settings.json");
}
@ -844,7 +844,7 @@ FFZ.prototype._setting_set = function(key, val, suppress_log) {
localStorage.setItem(ls_key, jval);
if ( ! suppress_log )
this.log('Changed Setting "' + key + '" to: ' + jval);
this.log('Changed Setting "' + key + '" to: ' + jval);
if ( info.on_update )
try {

View file

@ -1,4 +1,4 @@
.chat-line:not(.admin):not(.notification) span.from,
.chat-line:not(.admin):not(.notification) span.message {
.chat-line:not(.admin):not(.notification) .from,
.chat-line:not(.admin):not(.notification) .message {
color: inherit !important
}

View file

@ -204,14 +204,14 @@ FFZ.prototype.setup_tokenization = function() {
utils.toggle_cls('ffz-clickable-mentions')(this.settings.clickable_mentions);
try {
helpers = window.require && window.require("web-client/helpers/chat/chat-line-helpers");
this.chat_helpers = helpers = window.require && window.require("web-client/helpers/chat/chat-line-helpers");
} catch(err) { }
if ( ! helpers )
return this.log("Unable to get chat helper functions.");
try {
bits_helpers = window.require && window.require("web-client/utilities/bits/tokenize");
this.bits_helpers = bits_helpers = window.require && window.require("web-client/utilities/bits/tokenize");
} catch(err) {
this.error("Unable to get bits tokenizer.", err);
}
@ -223,13 +223,13 @@ FFZ.prototype.setup_tokenization = function() {
bits_tags = utils.ember_lookup('service:bits-tags');
try {
conv_helpers = window.require && window.require("web-client/helpers/twitch-conversations/conversation-line-helpers");
this.conv_helpers = conv_helpers = window.require && window.require("web-client/helpers/twitch-conversations/conversation-line-helpers");
} catch(err) {
this.error("Unable to get conversation helper functions.", err);
}
try {
emote_helpers = window.require && window.require("web-client/utilities/tmi-emotes").default;
this.emote_helpers = emote_helpers = window.require && window.require("web-client/utilities/tmi-emotes").default;
} catch(err) {
this.error("Unable to get tmi-emotes helper function.", err);
}
@ -685,15 +685,20 @@ FFZ.prototype.tokenize_vod_line = function(msgObject, delete_links) {
if ( display && display.length && display !== 'jtv' )
FFZ.capitalization[from_user] = [display.trim(), Date.now()];
var key_user = this.settings.key_users.indexOf(from_user) !== -1;
if ( key_user )
msgObject.set('ffz_has_mention', true);
if ( ! from_me ) {
tokens = this.tokenize_mentions(tokens);
for(var i=0; i < tokens.length; i++) {
var token = tokens[i];
if ( token.type === 'mention' && ! token.isOwnMessage ) {
msgObject.set('ffz_has_mention', true);
break;
if ( ! key_user )
for(var i=0; i < tokens.length; i++) {
var token = tokens[i];
if ( token.type === 'mention' && ! token.isOwnMessage ) {
msgObject.set('ffz_has_mention', true);
break;
}
}
}
}
msgObject.set('cachedTokens', tokens);
@ -790,6 +795,11 @@ FFZ.prototype.tokenize_chat_line = function(msgObject, prevent_notification, del
FFZ.capitalization[from_user] = [display.trim(), Date.now()];
var key_user = this.settings.key_users.indexOf(from_user) !== -1;
if ( key_user )
msgObject.ffz_has_mention = true;
// Mentions!
if ( ! from_me ) {
tokens = this.tokenize_mentions(tokens);
@ -1135,7 +1145,7 @@ FFZ.prototype.render_token = function(render_links, warn_links, render_bits, tok
return '<span class="' + (token.isOwnMessage ? 'mentioning' : 'mentioned') + '">' + utils.sanitize(token.user) + '</span>';
//return `<span class="${token.isOwnMessage ? 'mentioning' : 'mentioned'}">${utils.sanitize(token.user)}</span>`;
else if ( token.deletedLink || token.text )
else if ( token.deletedLink || token.hasOwnProperty('text') )
return utils.sanitize(token.text);
else if ( typeof token !== "string" )

View file

@ -4,11 +4,13 @@ var FFZ = window.FrankerFaceZ,
FOLLOWING_CONTAINERS = [
'.warp__item a[data-href="following"]',
'#header_actions #header_following'
'#header_actions #header_following',
'.top-nav__nav-link[data-tt_content="directory_following"]'
],
WIDE_TIP = function(f, el) {
return (f.settings.following_count && (
(el.classList.contains('top-nav__nav-link') && el.dataset['tt_content'] === 'directory_following') ||
el.id === 'header_following' ||
el.getAttribute('data-href') === 'following' ||
el.parentElement.getAttribute('data-name') === 'following'
@ -175,11 +177,12 @@ FFZ.prototype._update_following_count = function() {
FFZ.prototype._build_following_tooltip = function(el) {
if ( el.id !== 'header_following' && el.getAttribute('data-href') !== 'following' && el.parentElement.getAttribute('data-name') !== 'following' )
var is_top_nav = el.classList.contains('top-nav__nav-link') && el.dataset['tt_content'] === 'directory_following';
if ( ! is_top_nav && el.id !== 'header_following' && el.getAttribute('data-href') !== 'following' && el.parentElement.getAttribute('data-name') !== 'following' )
return el.getAttribute('original-title');
if ( ! this.settings.following_count )
return 'Following';
return is_top_nav ? '' : 'Following';
var tooltip = (this.has_bttv ? '<span class="stat playing">FrankerFaceZ</span>' : '') + 'Following',
bb = el.getBoundingClientRect(),
@ -326,6 +329,9 @@ FFZ.prototype._draw_following_count = function(count) {
} else if ( ! badge ) {
badge = utils.createElement('span', 'ffz-follow-count');
if ( container.classList.contains('top-nav__nav-link') )
badge.className += ' flex flex--horizontalCenter flex--verticalCenter pill';
container.appendChild(badge);
}

View file

@ -859,11 +859,16 @@ FFZ.mod_card_pages.name_history = {
if ( success ) {
for(var i=0; i < data.length; i++) {
var changed_at = data[i][0],
changed = changed_at ? utils.parse_date(changed_at).toLocaleString() : (i === 0 ? 'Initial' : 'Unknown');
var changed_at = data[i][0] && utils.parse_date(data[i][0]),
changed = changed_at ?
(Date.now() - changed_at.getTime()) > 86400000 ?
changed_at.toLocaleDateString() :
changed_at.toLocaleTimeString()
:
i === 0 ? 'Initial' : 'Unknown';
history.appendChild(utils.createElement('li', 'chat-line message-line admin no-messages',
'<span class="timestamp">' + utils.sanitize(changed) + ':</span>' +
'<span class="timestamp html-tooltip" title="' + (changed_at ? utils.quote_san(changed_at.toLocaleString()) : '') + '">' + utils.sanitize(changed) + ':</span>' +
'<span class="message">' + utils.sanitize(data[i][1]) + '</span>'));
}
} else

View file

@ -83,7 +83,7 @@ FFZ.prototype.modify_chat_settings_menu = function(component) {
cb.addEventListener("change", function(e) {
f.settings.set("dark_twitch", this.checked);
if ( this.checked )
if ( this.checked && ! localStorage.hasOwnProperty('ffz_setting_dark_no_blue') )
f.settings.set("dark_no_blue", true);
});

View file

@ -131,7 +131,7 @@ FFZ.prototype.clear_notifications = function() {
}
FFZ.prototype.show_notification = function(message, title, tag, timeout, on_click, on_close) {
FFZ.prototype.show_notification = function(message, title, tag, timeout, on_click, on_close, icon) {
var perm = Notification.permission;
if ( perm === "denied" )
return false;
@ -145,7 +145,7 @@ FFZ.prototype.show_notification = function(message, title, tag, timeout, on_clic
dir: "ltr",
body: message,
tag: tag || "FrankerFaceZ",
icon: "//cdn.frankerfacez.com/icon32.png"
icon: icon || "//cdn.frankerfacez.com/icon32.png"
};
var f = this,
@ -156,6 +156,7 @@ FFZ.prototype.show_notification = function(message, title, tag, timeout, on_clic
n.addEventListener("click", function() {
delete FFZ._notifications[nid];
n.close();
if ( on_click )
on_click.bind(f)();
});

View file

@ -414,9 +414,9 @@ var createElement = function(tag, className, content) {
U200D = String.fromCharCode(0x200D),
EMOJI_CODEPOINTS = {},
emoji_to_codepoint = function(surrogates, sep) {
if ( EMOJI_CODEPOINTS[surrogates] && EMOJI_CODEPOINTS[surrogates][sep] )
return EMOJI_CODEPOINTS[surrogates][sep];
emoji_to_codepoint = function(surrogates) {
if ( EMOJI_CODEPOINTS[surrogates] )
return EMOJI_CODEPOINTS[surrogates];
var input = surrogates.indexOf(U200D) === -1 ? surrogates.replace(UFE0Fg, '') : surrogates,
out = [],

View file

@ -143,6 +143,7 @@ body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .chat-interface .emotic
.ffz-ui-toggle svg.svg-emoticons path { fill: rgba(0,0,0,0.2); }
.ffz-ui-toggle:hover svg.svg-emoticons path { fill: rgba(0,0,0,0.5); }
.card__img .overlay_info.length.live svg path,
.card-carousel__item .card__img .overlay_info.live svg path,
.streams .stream .content .overlay_info.live svg path,
.videos .video .content .overlay_info.live svg path { fill: #ff2020; }
@ -1185,6 +1186,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
/* Menu Scrollbar */
.offer-list__core::-webkit-scrollbar,
.notification-center__content::-webkit-scrollbar,
.balloon__list.scroll-y::-webkit-scrollbar,
.player-menu__menu::-webkit-scrollbar,
@ -1207,6 +1209,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
width: 6px;
}
.offer-list__core::-webkit-scrollbar-thumb,
.notification-center__content::-webkit-scrollbar-thumb,
.balloon__list.scroll-y::-webkit-scrollbar-thumb,
.player-menu__menu::-webkit-scrollbar-thumb,
@ -1230,6 +1233,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
box-shadow: 0 0 1px 1px rgba(255,255,255,0.25);
}
.ffz-dark .offer-list__core::-webkit-scrollbar-thumb,
.ffz-dark .notification-center__content::-webkit-scrollbar-thumb,
.ffz-dark .balloon__list.scroll-y::-webkit-scrollbar-thumb,
.ffz-dark .player-menu__menu::-webkit-scrollbar-thumb,
@ -1249,6 +1253,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
.ffz-dark .conversations-list .conversations-list-inner::-webkit-scrollbar-thumb,
.ffz-dark .conversation-input-bar .emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
.theatre .offer-list__core::-webkit-scrollbar-thumb,
.theatre .search-panel .collection-wrapper::-webkit-scrollbar-thumb,
.theatre .conversations-list .scroll-container::-webkit-scrollbar-thumb,
.theatre .chatters-container::-webkit-scrollbar-thumb,
@ -1262,6 +1267,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
.theatre .ffz-ui-menu-page::-webkit-scrollbar-thumb,
.theatre .ffz-ui-sub-menu-page::-webkit-scrollbar-thumb,
.dark .offer-list__core::-webkit-scrollbar-thumb,
.dark .chatters-container::-webkit-scrollbar-thumb,
.dark .ffz-scrollbar::-webkit-scrollbar-thumb,
.dark .ember-chat .chat-settings::-webkit-scrollbar-thumb,
@ -1604,6 +1610,10 @@ body:not(.ffz-bttv) .chat-container:not(.chatReplay) .more-messages-indicator {
position: relative;
}
.ffz-follow-tip .tipsy-inner {
width: 316px;
}
.ffz-wide-tip span.stat {
float: right;
margin-left: 5px;
@ -2120,6 +2130,8 @@ body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textar
.chat-history .chat-line.admin .from,
.chat-history .chat-line.admin .colon { display: none }
.chat-line .colon, .conversation-chat-line .colon { margin-left: 0 !important }
.chat-history .chat-line.notification .message,
.chat-history .chat-line.admin .message { color: #666; }
@ -2128,7 +2140,7 @@ body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textar
margin-right: 5px;
}
.chat-history .chat-line:not(.original-sender) span.from:hover,
.chat-history .chat-line:not(.original-sender) .from:hover,
.chat-history .timestamp.ts-action:hover {
cursor: pointer;
text-decoration: underline;
@ -2700,11 +2712,15 @@ li[data-name="following"] a {
.ffz-clip-title {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 5px;
}
.ffz-tt-channel-title {
display: block;
}
.ffz-image-hover {
border:none;
max-width: 186px;
@ -2717,6 +2733,12 @@ li[data-name="following"] a {
margin: 5px auto;
}
.ffz-follow-tip .ffz-image-hover {
margin-top: 3px;
max-width: 300px;
max-height: 300px;
}
.ffz-yt-thumb {
max-height: 90px;
}
@ -3243,6 +3265,7 @@ body:not(.ffz-creative-showcase) .ct-spotlight-container { display: none; }
body:not([data-current-path^="directory.csgo"]):not([data-current-path^="directory.game"]):not([data-current-path^="directory.creative"]) .ffz-game-banned { display: none !important }
.ffz-game-spoilered .card__img > img,
.ffz-game-spoilered .card__img a:not(.card__boxpin) img,
.ffz-game-spoilered .thumb .cap img { visibility: hidden }
@ -3391,9 +3414,9 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
/* Button Fix */
.ffz-no-bg.button,
.ffz-no-bg {
background: transparent;
}
.ffz-hidden-badges.badges { margin-left: 5px }
@ -3679,6 +3702,8 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
transition: top ease-in-out 75ms, bottom ease-in-out 75ms;
}
.ffz-sidebar-minimize:not(.ffz-minimal-channel-bar) .has-sc .cn-bar-fixed { top: 10px }
.ffz-minimal-channel-bar .cn-bar-fixed:hover { top: 0 }
.ffz-minimal-channel-bar .has-sc .cn-bar-fixed { top: 10px }
@ -3694,12 +3719,12 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
.ffz-minimal-channel-bar.ffz-channel-bar-bottom .cn-bar-fixed:hover { bottom: 0 }
.ffz-sidebar-minimize .top-nav {
top: -40px;
top: -40px !important;
transition: top ease-in-out 75ms, bottom ease-in-out 75ms;
}
.ffz-sidebar-minimize .app-main.has-sc:not(.theatre) { top: 10px }
.ffz-sidebar-minimize .top-nav:hover { top: 0 }
.ffz-sidebar-minimize .top-nav:hover { top: 0 !important }
.ffz-sidebar-minimize .has-sc .js-player-persistent { margin-top: 40px }
/*.ffz-minimal-channel-title .cn-metabar,