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

3.5.319. More logviewer integration. Notes work now. Clean up colored badges a bit more. Fix for incorrect player height. Modify chat lines the new, improved way. Load user <-> emote set mappings from the API. Fix legacy badges not showing correctly. Remove negative margins from chat lines. Add a line saying a sub is a Twitch Prime sub to the FFZ menu. Dark theme CSS tweaks.

This commit is contained in:
SirStendec 2016-10-07 18:11:05 -04:00
parent d02f87528d
commit 9ddfabb1b1
16 changed files with 723 additions and 581 deletions

View file

@ -1,3 +1,24 @@
<div class="list-header">3.5.319 <time datetime="2016-10-03">(2016-10-07)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Load emote set &lt;-&gt; user mappings from the API.</li>
<li>Added: Logviewer integration now supports notes.</li>
<li>Changed: Simplify CSS for chat lines just a bit. No more negative margins.</li>
<li>Changed: Minor CSS tweaks.</li>
<li>Fixed: Legacy badges got broken when I added colored badges.</li>
</ul>
<div class="list-header">3.5.318 <time datetime="2016-10-03">(2016-10-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Twitch's player is still the wrong height. <em>**sigh**</em> Temporary fix.</li>
</ul>
<div class="list-header">3.5.317 <time datetime="2016-10-03">(2016-10-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: More tweaks to Transparent (Color) badge rendering to make sure all badges are rendered correctly.</li>
<li>&nbsp;</li>
<li>Let's be honest, a release just isn't a release without a pair of immediate bugfixes, am I right?</li>
</ul>
<div class="list-header">3.5.316 <time datetime="2016-10-03">(2016-10-05)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Prime emotes aren't sub emotes, tab-completion. Stop being silly.</li>

View file

@ -492,19 +492,20 @@ FFZ.prototype.render_badges = function(badges) {
for(var key in badges) {
var badge = badges[key],
klass = badge.klass,
css = '';
css = '',
is_colored = !(badge.no_color !== undefined ? badge.no_color : badge.transparent);
if ( badge.image )
if ( setting === 6 )
if ( is_colored && setting === 6 )
css += '-webkit-mask-image:url("' + utils.quote_attr(badge.image) + '");';
else
css += 'background-image:url("' + utils.quote_attr(badge.image) + '");';
if ( badge.srcSet && setting !== 6 )
if ( badge.srcSet && (setting !== 6 || !is_colored) )
css += 'background-image:-webkit-image-set(' + badge.srcSet + ');background-image:image-set(' + badge.srcSet + ');'
if ( badge.color )
if ( setting === 6 )
if ( is_colored && setting === 6 )
css += 'background: linear-gradient(' + badge.color + ',' + badge.color + ');';
else
css += 'background-color:' + badge.color + ';'
@ -521,7 +522,7 @@ FFZ.prototype.render_badges = function(badges) {
if ( badge.invert_invert )
klass += ' invert-invert';
if ( ! badge.no_color && setting === 6 )
if ( is_colored && setting === 6 )
klass += ' colored';
if ( badge.transparent )

View file

@ -222,7 +222,7 @@ FFZ.prototype.setup_layout = function() {
height = size[1],
host_height = size[2];
return "<style>.dynamic-player, .dynamic-player object, .dynamic-player video{width:" + width + "px !important;height:" + height + "px !important} .dynamic-target-player,.dynamic-target-player object, .dynamic-target-player video{width:" + width + "px !important;height:" + host_height + "px !important}</style><style>.dynamic-player .player object, .dynamic-player .player video{width:100% !important; height:100% !important}</style>";
return "<style>.dynamic-player, .dynamic-player object, .dynamic-player video{width:" + width + "px !important;height:" + height + "px !important} .cn-hosted .dynamic-target-player,.cn-hosted .dynamic-target-player object, .cn-hosted .dynamic-target-player video{width:" + width + "px !important;height:" + host_height + "px !important}</style><style>.dynamic-player .player object, .dynamic-player .player video{width:100% !important; height:100% !important}</style>";
}.property("playerSize"),
ffzPortraitWarning: function() {

View file

@ -661,7 +661,12 @@ FFZ.prototype.setup_line = function() {
if ( Line )
this._modify_chat_line(Line);*/
this.log("Hooking the Ember VOD Chat Line component.");
this.update_views('component:vod-chat-line', this._modify_vod_line);
this.update_views('component:chat/message-line', this._modify_chat_subline);
this.update_views('component:chat/whisper-line', this._modify_chat_subline);
/*this.log("Hooking the Ember VOD Chat Line component.");
var VOD = utils.ember_resolve('component:vod-chat-line');
if ( VOD )
this._modify_vod_line(VOD);
@ -681,7 +686,7 @@ FFZ.prototype.setup_line = function() {
if ( WLine )
this._modify_chat_subline(WLine);
else
this.error("Couldn't find the Whisper Line component.");
this.error("Couldn't find the Whisper Line component.");*/
// Store the capitalization of our own name.

View file

@ -660,6 +660,9 @@ FFZ.prototype.modify_moderation_card = function(component) {
this._lv_sock_user = null;
}
if ( f.settings.mod_card_history )
this.ffzRenderHistory();
// Highlight this user's chat messages.
if ( f.settings.highlight_messages_with_mod_card )
utils.update_css(f._chat_style, 'mod-card-highlight', styles['chat-user-bg'].replace(/{user_id}/g, this.get('cardInfo.user.id')));
@ -748,41 +751,79 @@ FFZ.prototype.modify_moderation_card = function(component) {
lvOnMessage: function(cmd, data) {
//f.log("[LV] Socket Message: " + cmd, data)
// Make sure:
// 1) It's a log-add command.
// 2) We have logs loaded already.
// 3) The loaded logs are for this user.
if ( cmd !== 'log-add' || ! this._lv_logs || ! this._lv_logs.data || data.nick !== this._lv_logs.data.user.nick )
return;
if ( cmd === "comment-add" ) {
if ( data.topic !== this.get('cardInfo.user.id') )
return;
// Parse the message. Store the data.
var t,
message = f.lv_parse_message(data);
this._lv_logs.data.before.push(message);
this._lv_logs.data.user[message.is_ban ? 'timeouts' : 'messages'] += 1;
FFZ.mod_card_pages.notes.add_note.call(f, this, this.get('element'), data);
// If we're viewing the chat history, update it.
var el = this.get('element'),
container = el && el.querySelector('.ffz-tab-container'),
history = container && container.querySelector('.chat-history.lv-history');
} else if ( cmd === "comment-update" ) {
var el = this.get('element'),
line = el && el.querySelector('.user-notes .chat-line[data-lv-id="' + data.id + '"]');
if ( history ) {
var was_at_bottom = history.scrollTop >= (history.scrollHeight - history.clientHeight),
last_line = history.querySelector('.chat-line:last-of-type'),
ll_date = last_line && last_line.getAttribute('data-date'),
date = message.date.toLocaleDateString();
if ( ! line )
return;
if ( last_line && ll_date !== date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
var new_line = FFZ.mod_card_pages.notes.build_note.call(f, this, data);
line.outerHTML = new_line.outerHTML;
} else if ( cmd === "comment-delete" ) {
var el = this.get('element'),
line = el && el.querySelector('.user-notes .chat-line[data-lv-id="' + data.id + '"]');
if ( ! line )
return;
// If we're the only message on this date, remove the timestamp line.
var before_line = line.previousElementSibling,
after_line = line.nextElementSibling;
if ( before_line && before_line.classList.contains('timestamp-line') &&
(! after_line || after_line.classList.contains('timestamp-line')) )
before_line.parentElement.removeChild(before_line);
// Remove the line itself.
line.parentElement.removeChild(line);
} else if ( cmd === "log-add" ) {
if ( ! this._lv_logs || ! this._lv_logs.data || data.nick !== this._lv_logs.data.user.nick )
return;
// Parse the message. Store the data.
var t,
message = f.lv_parse_message(data);
this._lv_logs.data.before.push(message);
this._lv_logs.data.user[message.is_ban ? 'timeouts' : 'messages'] += 1;
// If we're viewing the chat history, update it.
var el = this.get('element'),
container = el && el.querySelector('.ffz-tab-container'),
history = container && container.querySelector('.chat-history.lv-history');
if ( history ) {
var was_at_bottom = history.scrollTop >= (history.scrollHeight - history.clientHeight),
last_line = history.querySelector('.chat-line:last-of-type'),
ll_date = last_line && last_line.getAttribute('data-date'),
date = message.date.toLocaleDateString();
if ( last_line.classList.contains('no-messages') ) {
last_line.parentElement.removeChild(last_line);
last_line = null;
ll_date = null;
}
if ( last_line && ll_date !== date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
}
history.appendChild(f._build_mod_card_history(message, this, false,
FFZ.mod_card_pages.history.render_adjacent.bind(f, t, container, message)));
if ( was_at_bottom )
setTimeout(function() { history.scrollTop = history.scrollHeight; })
}
history.appendChild(f._build_mod_card_history(message, this, false,
FFZ.mod_card_pages.history.render_adjacent.bind(f, t, container, message)));
if ( was_at_bottom )
setTimeout(function() { history.scrollTop = history.scrollHeight; })
}
},
@ -862,7 +903,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
// Should we be requesting a token? How about access levels?
if ( f.settings.logviewer_test && ffz_room.has_logs )
if ( ! ffz_room.logviewer_levels )
if ( ! ffz_room.logviewer_levels || (user && user.login && ! ffz_room.logviewer_levels.me.valid ) )
f.lv_get_token().then(function(token) {
if ( ! token )
return;
@ -1009,12 +1050,13 @@ FFZ.prototype.modify_moderation_card = function(component) {
handle_key = function(e) {
var key = e.keyCode || e.which,
is_meta = e.ctrlKey || e.altKey || e.metaKey,
tag = e.target && e.target.tagName,
user_id = controller.get('cardInfo.user.id'),
is_mod = controller.get('cardInfo.isModeratorOrHigher'),
room = utils.ember_lookup('controller:chat').get('currentRoom');
// We don't want modifier keys.'
if ( is_meta )
// We don't want modifier keys. Also don't override input to input elements.
if ( is_meta || tag === 'TEXTAREA' || tag === 'INPUT')
return;
if ( key === keycodes.C )
@ -1244,7 +1286,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
for(var page_id in FFZ.mod_card_pages) {
var page = FFZ.mod_card_pages[page_id];
if ( page && page.title && (page_id !== 'history' || f.settings.mod_card_history) ) {
if ( page && page.title ) {
var tab = utils.createElement('li', 'item', page.title);
if ( page_id === 'default' )
tab.classList.add('active');
@ -1264,16 +1306,8 @@ FFZ.prototype.modify_moderation_card = function(component) {
el.classList.add('ffz-default-tab');
// Message History
if ( f.settings.mod_card_history ) {
var history = utils.createElement('ul', 'interface chat-history live-history');
el.appendChild(history);
var chat_history = ffz_room.user_history && ffz_room.user_history[user_id] || [];
for(var i=0; i < chat_history.length; i++)
history.appendChild(f._build_mod_card_history(chat_history[i], t, false));
setTimeout(function(){history.scrollTop = history.scrollHeight;});
}
if ( f.settings.mod_card_history )
this.ffzRenderHistory();
// Reposition the menu if it's off-screen.
this.ffzReposition();
@ -1336,187 +1370,33 @@ FFZ.prototype.modify_moderation_card = function(component) {
}
}.observes('cardInfo.renderTop', 'cardInfo.renderLeft', 'cardInfo.renderRight', 'cardInfo.renderBottom'),
/*ffzRenderHistory: function() {
ffzRenderHistory: function() {
var t = this,
Chat = utils.ember_lookup('controller:chat'),
room = Chat && Chat.get('currentRoom'),
delete_links = room && room.get('roomProperties.hide_chat_links'),
tmiSession = room.tmiSession || (window.TMI && TMI._sessions && TMI._sessions[0]),
room_id = room.get('id'),
room_id = Chat && Chat.get('currentRoom.id'),
user_id = this.get('cardInfo.user.id'),
ffz_room = room && f.rooms && f.rooms[room_id],
user_history = ffz_room && ffz_room.user_history && ffz_room.user_history[user_id] || [],
ffz_room = f.rooms && f.rooms[room_id],
chat_history = ffz_room && ffz_room.user_history && ffz_room.user_history[user_id] || [],
el = this.get('element'),
history = el && el.querySelector('.ffz-tab-container');
if ( history && ! history.classList.contains('chat-history') ) {
history.parentElement.removeChild(history);
history = null;
}
history = el.querySelector('.chat-history.live-history');
if ( ! history ) {
history = utils.createElement('ul', 'interface clearfix ffz-tab-container chat-history');
history = utils.createElement('ul', 'interface chat-history live-history');
el.appendChild(history);
} else {
history.classList.remove('loading');
} else
history.innerHTML = '';
}
/*if ( user_history.length < 50 ) {
var before = (user_history.length > 0 && user_history[0].date ? user_history[0].date.getTime() : Date.now()) - (f._ws_server_offset || 0);
f.ws_send("user_history", [room_id, user_id, 50 - user_history.length], function(success, data) {
if ( ! success )
return;
for(var i=0; i < chat_history.length; i++)
history.appendChild(f._build_mod_card_history(chat_history[i], t, false));
f.parse_history(data, null, null, room_id, delete_links, tmiSession);
var i = data.length,
was_at_top = history && history.scrollTop >= (history.scrollHeight - history.clientHeight),
first = true;
while(i--) {
var msg = data[i];
if ( ! msg )
continue;
msg.from_server = true;
if ( ! msg.date || msg.date.getTime() >= before )
continue;
if ( first ) {
first = false;
history.insertBefore(f._build_mod_card_history({
date: msg.date,
from: "jtv",
style: "admin",
cachedTokens: ["(Server History Above)"]
}), history.firstElementChild);
}
history.insertBefore(f._build_mod_card_history(msg, t), history.firstElementChild);
}
if ( was_at_top )
setTimeout(function() { history.scrollTop = history.scrollHeight; });
});
}*//*
for(var i=0; i < user_history.length; i++)
history.appendChild(f._build_mod_card_history(user_history[i], t));
// Lazy scroll-to-bottom
history.scrollTop = history.scrollHeight;
},*/
/*ffzAdjacentHistory: function(line) {
var Chat = utils.ember_lookup('controller:chat'),
t = this,
user_id = this.get('cardInfo.user.id'),
room = Chat && Chat.get('currentRoom'),
room_id = room.get('id'),
delete_links = room && room.get('roomProperties.hide_chat_links'),
tmiSession = room.tmiSession || (window.TMI && TMI._sessions && TMI._sessions[0]),
el = this.get('element'),
history = el && el.querySelector('.chat-history'),
logs = el && el.querySelector('.chat-history.adjacent-history'),
when = line.date.getTime(),
scroll_top = logs && logs.scrollTop || history && history.scrollTop || 0;
if ( ! history )
return;
if ( logs ) {
logs.classList.add('loading');
logs.scrollTop = 0;
} else {
history.classList.add('loading');
history.scrollTop = 0;
}
if ( ! f.ws_send("adjacent_history", [room_id, when, 2], function(success, data) {
var was_loading = history.classList.contains('loading');
if ( logs ) {
logs.classList.remove('loading');
logs.scrollTop = scroll_top;
} else {
history.classList.remove('loading');
history.scrollTop = scroll_top;
}
if ( ! success || ! data || ! data.length || ! was_loading )
return;
var had_logs = false,
found_original = false,
back;
if ( logs ) {
had_logs = true;
logs.innerHTML = '';
} else {
logs = utils.createElement('ul', 'interface clearfix chat-history adjacent-history');
back = utils.createElement('button', 'button ffz-no-bg back-button');
back.innerHTML = '&laquo; Back';
back.addEventListener('click', function() {
logs.parentElement.removeChild(logs);
back.parentElement.removeChild(back);
history.classList.remove('hidden');
});
}
f.parse_history(data, null, null, room_id, delete_links, tmiSession, function(msg) {
msg.from_server = true;
var line_time = line.date.getTime() - (line.from_server ? 0 : (f._ws_server_offset || 0)),
is_original = ! found_original && Math.abs(line_time - msg.date.getTime()) < (line.from_server ? 50 : 1000) && line.from === msg.from && line.message === msg.message;
msg.original_sender = user_id === msg.from;
msg.is_original = is_original;
found_original = found_original || is_original;
logs.insertBefore(f._build_mod_card_history(msg, t, true), logs.firstElementChild);
return true;
});
if ( ! had_logs ) {
history.classList.add('hidden');
history.parentElement.insertBefore(logs, history);
history.parentElement.insertBefore(back, logs);
}
if ( found_original )
setTimeout(function(){
el = logs.querySelector('.original-msg');
if ( el )
logs.scrollTop = (el.offsetTop - logs.offsetTop) - (logs.clientHeight - el.clientHeight) / 2;
});
}) )
if ( logs ) {
logs.classList.remove('loading');
logs.scrollTop = scroll_top;
} else {
history.classList.remove('loading');
history.scrollTop = scroll_top;
}
}*/
setTimeout(function(){history.scrollTop = history.scrollHeight});
}
});
}
FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_click) {
FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_click, mod_icons) {
var l_el = document.createElement('li'),
out = [],
f = this;
@ -1529,6 +1409,13 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from, ts_cli
var alias = this.aliases[msg.from],
results = this.format_display_name(msg.tags && msg.tags['display-name'], msg.from);
if ( mod_icons ) {
out.push('<span class="mod-icons">');
if ( typeof mod_icons === "string" )
out.push(mod_icons);
out.push('</span>');
}
if ( show_from ) {
// Badges
out.push('<span class="badges">');
@ -1729,329 +1616,4 @@ FFZ.chat_commands.u = function(room, args) {
}
}
FFZ.chat_commands.u.enabled = function() { return this.settings.short_commands; }
// ----------------
// Moderation Card Pages
// ----------------
FFZ.mod_card_pages = {};
FFZ.mod_card_pages.default = {
title: "<span>C</span>ontrols",
render: function(mod_card, el) { }
}
FFZ.mod_card_pages.history = {
title: "Chat <span>H</span>istory",
render_more: function(mod_card, el, history, ref_id, is_user, is_after) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
btn_more = utils.createElement('li', 'button ffz-load-more' + (is_after ? ' load-after' : ''), '<span class="ffz-chevron"></span> Load More <span class="ffz-chevron"></span>');
if ( is_after )
history.appendChild(btn_more);
else
history.insertBefore(btn_more, history.firstElementChild);
btn_more.addEventListener('click', function() {
history.scrollTop = 0;
history.classList.add('loading');
f.lv_get_logs(room_id, is_user ? user_id : null, ref_id, is_after ? 0 : 10, is_after ? 10 : 0).then(function(data) {
history.removeChild(btn_more);
history.classList.remove('loading');
var messages = is_after ? data.after : data.before,
last_message = history.querySelector('.chat-line:' + (is_after ? 'last' : 'first') + '-of-type'),
last_date = last_message ? last_message.getAttribute('data-date') : (new Date).toLocaleDateString();
if ( last_message.classList.contains('timestamp-line') )
last_message.parentElement.removeChild(last_message);
if ( ! is_after )
messages.reverse();
var original_message = history.querySelector('.original-msg'),
original_sender = original_message && original_message.getAttribute('data-sender');
for(var i=0; i < messages.length; i++) {
var new_message = messages[i],
date = new_message.date.toLocaleDateString(),
date_line = null;
new_message.original_sender = original_sender === new_message.from;
var new_line = f._build_mod_card_history(
new_message, mod_card, !is_user,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, new_message)
);
if ( is_user )
new_line.classList.remove('ffz-mentioned');
new_message.original_sender = null;
if ( last_date !== date ) {
date_line = utils.createElement('li', 'chat-line timestamp-line', is_after ? date : last_date);
date_line.setAttribute('data-date', is_after ? date : last_date);
last_date = date;
if ( is_after )
history.appendChild(date_line);
else
history.insertBefore(date_line, history.firstElementChild);
}
if ( is_after )
history.appendChild(new_line);
else
history.insertBefore(new_line, history.firstElementChild);
}
if ( ! is_after && last_date !== (new Date).toLocaleDateString() ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', last_date);
date_line.setAttribute('data-date', last_date);
history.insertBefore(date_line, history.firstElementChild);
}
// Only add the button back if there are even more messages to load.
if ( messages.length >= 10 )
if ( is_after )
history.appendChild(btn_more);
else
history.insertBefore(btn_more, history.firstElementChild);
var original = history.querySelector('.chat-line[data-lv-id="' + ref_id + '"]');
if ( original )
setTimeout(function() {
history.scrollTop = (original.offsetTop - history.offsetTop) - (history.clientHeight - original.clientHeight) / 2;
});
ref_id = messages[messages.length-1].lv_id;
});
})
},
render_adjacent: function(mod_card, el, message) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
ffz_room = this.rooms[room_id],
old_history = el.querySelector('.chat-history'),
history = el.querySelector('.adjacent-history');
old_history.classList.add('hidden');
if ( history )
history.innerHTML = '';
else {
var btn_hide = utils.createElement('li', 'button ffz-back-button', '<span class="ffz-chevron"></span> Back'),
btn_container = utils.createElement('ul', 'interface chat-history chat-back-button', btn_hide);
btn_hide.addEventListener('click', function() {
el.removeChild(history);
el.removeChild(btn_container);
old_history.classList.remove('hidden');
})
history = utils.createElement('ul', 'interface chat-history adjacent-history');
el.appendChild(btn_container);
el.appendChild(history);
}
history.classList.add('loading');
f.lv_get_logs(room_id, null, message.lv_id, 10, 10).then(function(data) {
history.classList.remove('loading');
// Should we display more?
if ( data.before.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.before[0].lv_id, false, false);
var last_date = (new Date).toLocaleDateString(),
messages = _.union(data.before, [message], data.after);
for(var i=0; i < messages.length; i++) {
var new_message = messages[i],
date = new_message.date.toLocaleDateString();
if ( date !== last_date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
last_date = date;
}
new_message.is_original = new_message.lv_id === message.lv_id;
new_message.original_sender = new_message.from === message.from;
var msg_line = f._build_mod_card_history(new_message, mod_card, true,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, new_message));
if ( new_message.is_original )
msg_line.classList.remove('ffz-mentioned');
history.appendChild(msg_line);
// These objects can be persistent, so clear these.
new_message.is_original = null;
new_message.original_sender = null;
}
if ( data.after.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.after[data.after.length-1].lv_id, false, true);
setTimeout(function() {
var original = history.querySelector('.original-msg');
if ( original )
history.scrollTop = (original.offsetTop - history.offsetTop) - (history.clientHeight - original.clientHeight) / 2;
})
});
},
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
ffz_room = this.rooms[room_id],
history = utils.createElement('ul', 'interface chat-history lv-history');
el.appendChild(history);
// Are we relying on LogViewer here?
if ( ! ffz_room.has_logs || ! mod_card.lv_view ) {
history.innerHTML = '<li class="chat-line admin"><span class="message">You do not have permission to view chat history in this channel.</span></li>';
return;
}
// Start loading!
history.classList.add('loading');
mod_card.lvGetLogs().then(function(data) {
f.log("[LV] Logs: " + user_id + " in " + room_id, data);
history.classList.remove('loading');
// Should we display more?
if ( data.before.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.before[0].lv_id, true, false);
var last_date = (new Date).toLocaleDateString();
for(var i=0; i < data.before.length; i++) {
var message = data.before[i],
date = message.date.toLocaleDateString();
if ( date !== last_date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
last_date = date;
}
var msg_line = f._build_mod_card_history(message, mod_card, false,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, message));
msg_line.classList.remove('ffz-mentioned');
history.appendChild(msg_line);
}
history.scrollTop = history.scrollHeight;
});
}
}
FFZ.mod_card_pages.stats = {
title: "<span>S</span>tatistics",
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
room_id = controller && controller.get('currentRoom.id'),
user_id = mod_card.get('cardInfo.user.id'),
ffz_room = f.rooms && f.rooms[room_id];
var container = utils.createElement('ul', 'interface version-list');
el.appendChild(container);
if ( ffz_room.has_logs && mod_card.lv_view ) {
container.classList.add('loading');
mod_card.lvGetLogs().then(function(data) {
container.classList.remove('loading');
container.innerHTML = '<li>Messages <span>' + utils.number_commas(data.user.messages) + '</span></li><li>Timeouts <span> ' + utils.number_commas(data.user.timeouts) + '</span></li>';
});
var notice = utils.createElement('div', 'interface');
notice.innerHTML = 'Chat Log Source: <a target="_blank" href="https://cbenni.com/' + room_id + '?user=' + user_id + '">CBenni\'s logviewer</a>';
el.appendChild(notice);
}
}
}
FFZ.mod_card_pages.notes = {
title: "<span>N</span>otes",
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
room = controller && controller.get('currentRoom'),
tmiSession = room.tmiSession || (window.TMI && TMI._sessions && TMI._sessions[0]),
room_id = room && room.get('id'),
user_id = mod_card.get('cardInfo.user.id'),
ffz_room = this.rooms[room_id],
history = utils.createElement('ul', 'interface chat-history user-notes');
el.appendChild(history);
if ( ! ffz_room.has_logs || ! mod_card.lv_view_notes ) {
history.innerHTML = '<li class="chat-line admin"><span class="message">You do not have permission to view notes in this channel.</span></li>';
return;
}
history.classList.add('loading');
this.lv_get_token().then(function(token) {
utils.logviewer.get("comments/" + room_id + "?topic=" + user_id, token)
.then(utils.json).then(function(data) {
f.log("[LV] Comments: " + user_id + " in " + room_id, data);
history.classList.remove('loading');
if ( data.length )
for(var i=0; i < data.length; i++) {
var raw = data[i],
msg = {
date: new Date(raw.added * 1000),
from: raw.author,
room: raw.channel,
lv_id: raw.id,
message: raw.text,
tags: {},
color: tmiSession && raw.author ? tmiSession.getColor(raw.author) : "#755000"
};
f.tokenize_chat_line(msg, true, false);
history.appendChild(f._build_mod_card_history(msg, mod_card, true));
}
else
history.appendChild(utils.createElement('li', 'chat-line message-line admin',
'<span class="message">There are no notes on this user.</span>'));
history.appendChild(utils.createElement('li', 'chat-line message-line admin',
'<span clss="message">Create notes for this user at <a target="_blank" href="https://cbenni.com/' + room_id + '?user=' + user_id + '">CBenni\'s logviewer.</a></span>'));
});
});
}
}
FFZ.chat_commands.u.enabled = function() { return this.settings.short_commands; }

View file

@ -301,6 +301,9 @@ FFZ.prototype.load_global_sets = function(callback, tries) {
gs.push(key);
f._load_set_json(key, undefined, set);
}
f._load_set_users(data.users);
}).fail(function(data) {
if ( data.status == 404 )
return typeof callback == "function" && callback(false);
@ -315,11 +318,33 @@ FFZ.prototype.load_global_sets = function(callback, tries) {
}
FFZ.prototype._load_set_users = function(data) {
if ( data )
for(var set_id in data)
if ( data.hasOwnProperty(set_id) ) {
var emote_set = this.emote_sets[set_id],
users = data[set_id];
for(var i=0; i < users.length; i++) {
var user = users[i],
ud = this.users[user] = this.users[user] || {},
sets = ud.sets = ud.sets || [];
if ( sets.indexOf(set_id) === -1 )
sets.push(set_id);
}
this.log('Added "' + (emote_set ? emote_set.title : set_id) + '" emote set to ' + utils.number_commas(users.length) + ' users.');
}
}
FFZ.prototype.load_set = function(set_id, callback, tries) {
var f = this;
jQuery.getJSON(constants.API_SERVER + "v1/set/" + set_id)
.done(function(data) {
f._load_set_json(set_id, callback, data && data.set);
f._load_set_users(data.users);
}).fail(function(data) {
if ( data.status == 404 )

View file

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

View file

@ -1,9 +1,9 @@
.badges .moderator:not(.colored) {
.badges .badge.moderator.version-1:not(.colored) {
background-color: #068c10;
background-image: url('//cdn.frankerfacez.com/script/legacy-mod.png');
}
.badges .moderator.colored {
.badges .badge.moderator.version-1.colored {
background: linear-gradient(#068c10,#068c10);
-webkit-mask-image: url('//cdn.frankerfacez.com/script/legacy-mod.png');
}

View file

@ -1,9 +1,9 @@
.badges .turbo:not(.colored) {
.badges .badge.turbo.version-1:not(.colored) {
background-color: #6441a3;
background-image: url('//cdn.frankerfacez.com/script/legacy-turbo.png');
}
.badges .turbo.colored {
.badges .badge.turbo.version-1.colored {
background: linear-gradient(#6441a3,#6441a3);
-webkit-mask-image: url('//cdn.frankerfacez.com/script/legacy-turbo.png');
}

View file

@ -1,29 +1,29 @@
.badges .staff:not(.colored) {
.badges .badge.staff.version-1:not(.colored) {
background-color: #6441a5;
background-image: url('//cdn.frankerfacez.com/script/legacy-staff.png');
}
.badges .staff.colored {
.badges .badge.staff.version-1.colored {
background: linear-gradient(#6441a5,#6441a5);
-webkit-mask-image: url('//cdn.frankerfacez.com/script/legacy-staff.png');
}
.badges .broadcaster:not(.colored) {
.badges .badge.broadcaster.version-1:not(.colored) {
background-color: #000;
background-image: url('//cdn.frankerfacez.com/script/legacy-broadcaster.png');
}
.badges .broadcaster.colored {
.badges .badge.broadcaster.version-1.colored {
background: linear-gradient(#e71818,#e71818);
-webkit-mask-image: url('//cdn.frankerfacez.com/script/legacy-broadcaster.png');
}
.badges .admin:not(.colored) {
.badges .badge.admin.version-1:not(.colored) {
background-color: #ff0303;
background-image: url('//cdn.frankerfacez.com/script/legacy-admin.png');
}
.badges .admin.colored {
.badges .badge.admin.version-1.colored {
background: linear-gradient(#ff0303,#ff0303);
-webkit-mask-image: url('//cdn.frankerfacez.com/script/legacy-admin.png');
}

View file

@ -5,7 +5,7 @@
.conversation-window .conversation-system-messages,
.conversation-window .conversation-chat-line,
.conversation-window .timestamp-line {
padding: 5px;
padding: 3px 5px;
}

View file

@ -10,10 +10,6 @@
position: absolute;
z-index: -1;
left: 0; right: 0;
top: 2px; bottom: 1px;
}
.chat-history .chat-line:before {
top: 0; bottom: 0;
}

View file

@ -16,6 +16,11 @@ FFZ.prototype.lv_get_token = function() {
now = Date.now() / 1000;
return new Promise(function(succeed, fail) {
// If we're not logged in, we can't get a token.
var user = f.get_user();
if ( ! user || ! user.login )
return fail(null);
// Make sure the token will be valid for at least 5 more minutes.
if ( token.token && token.expires > (now + 300) )
return succeed(token.token);
@ -38,6 +43,9 @@ FFZ.prototype.lv_get_token = function() {
requests[i][succeeded ? 0 : 1](token.token);
}
if ( succeeded && f._lv_ws_open )
f._lv_ws_sock.send('42' + JSON.stringify(["token", token]));
}, true);
});
}
@ -143,6 +151,9 @@ FFZ.prototype.lv_ws_create = function() {
ws.send('2probe');
ws.send('5');
if ( f._lv_token.token )
ws.send('42' + JSON.stringify(["token", f._lv_token.token]));
// Ping every 10 seconds just to be safe.
f._lv_ws_ping_timer = setInterval(function() {
ws.send('2');
@ -246,4 +257,491 @@ FFZ.prototype.lv_ws_maybe_close = function() {
if ( (! this._lv_ws_topics || ! this._lv_ws_topics.length) && this._lv_ws_open )
this._lv_ws_sock.close();
}
// ----------------
// Moderation Card Pages
// ----------------
FFZ.mod_card_pages = {};
FFZ.mod_card_pages.default = {
title: "<span>C</span>ontrols",
render: function(mod_card, el) { }
}
FFZ.mod_card_pages.history = {
title: "Chat <span>H</span>istory",
render_more: function(mod_card, el, history, ref_id, is_user, is_after) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
btn_more = utils.createElement('li', 'button ffz-load-more' + (is_after ? ' load-after' : ''), '<span class="ffz-chevron"></span> Load More <span class="ffz-chevron"></span>');
if ( is_after )
history.appendChild(btn_more);
else
history.insertBefore(btn_more, history.firstElementChild);
btn_more.addEventListener('click', function() {
history.scrollTop = 0;
history.classList.add('loading');
f.lv_get_logs(room_id, is_user ? user_id : null, ref_id, is_after ? 0 : 10, is_after ? 10 : 0).then(function(data) {
history.removeChild(btn_more);
history.classList.remove('loading');
var messages = is_after ? data.after : data.before,
last_message = history.querySelector('.chat-line:' + (is_after ? 'last' : 'first') + '-of-type'),
last_date = last_message ? last_message.getAttribute('data-date') : (new Date).toLocaleDateString();
if ( last_message.classList.contains('timestamp-line') )
last_message.parentElement.removeChild(last_message);
if ( ! is_after )
messages.reverse();
var original_message = history.querySelector('.original-msg'),
original_sender = original_message && original_message.getAttribute('data-sender');
for(var i=0; i < messages.length; i++) {
var new_message = messages[i],
date = new_message.date.toLocaleDateString(),
date_line = null;
new_message.original_sender = original_sender === new_message.from;
var new_line = f._build_mod_card_history(
new_message, mod_card, !is_user,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, new_message)
);
if ( is_user )
new_line.classList.remove('ffz-mentioned');
new_message.original_sender = null;
if ( last_date !== date ) {
date_line = utils.createElement('li', 'chat-line timestamp-line', is_after ? date : last_date);
date_line.setAttribute('data-date', is_after ? date : last_date);
last_date = date;
if ( is_after )
history.appendChild(date_line);
else
history.insertBefore(date_line, history.firstElementChild);
}
if ( is_after )
history.appendChild(new_line);
else
history.insertBefore(new_line, history.firstElementChild);
}
if ( ! is_after && last_date !== (new Date).toLocaleDateString() ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', last_date);
date_line.setAttribute('data-date', last_date);
history.insertBefore(date_line, history.firstElementChild);
}
// Only add the button back if there are even more messages to load.
if ( messages.length >= 10 )
if ( is_after )
history.appendChild(btn_more);
else
history.insertBefore(btn_more, history.firstElementChild);
var original = history.querySelector('.chat-line[data-lv-id="' + ref_id + '"]');
if ( original )
setTimeout(function() {
history.scrollTop = (original.offsetTop - history.offsetTop) - (history.clientHeight - original.clientHeight) / 2;
});
ref_id = messages[messages.length-1].lv_id;
});
})
},
render_adjacent: function(mod_card, el, message) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
ffz_room = this.rooms[room_id],
old_history = el.querySelector('.chat-history'),
history = el.querySelector('.adjacent-history');
old_history.classList.add('hidden');
if ( history )
history.innerHTML = '';
else {
var btn_hide = utils.createElement('li', 'button ffz-back-button', '<span class="ffz-chevron"></span> Back'),
btn_container = utils.createElement('ul', 'interface chat-history chat-back-button', btn_hide);
btn_hide.addEventListener('click', function() {
el.removeChild(history);
el.removeChild(btn_container);
old_history.classList.remove('hidden');
})
history = utils.createElement('ul', 'interface chat-history adjacent-history');
el.appendChild(btn_container);
el.appendChild(history);
}
history.classList.add('loading');
f.lv_get_logs(room_id, null, message.lv_id, 10, 10).then(function(data) {
history.classList.remove('loading');
// Should we display more?
if ( data.before.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.before[0].lv_id, false, false);
var last_date = (new Date).toLocaleDateString(),
messages = _.union(data.before, [message], data.after);
for(var i=0; i < messages.length; i++) {
var new_message = messages[i],
date = new_message.date.toLocaleDateString();
if ( date !== last_date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
last_date = date;
}
new_message.is_original = new_message.lv_id === message.lv_id;
new_message.original_sender = new_message.from === message.from;
var msg_line = f._build_mod_card_history(new_message, mod_card, true,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, new_message));
if ( new_message.is_original )
msg_line.classList.remove('ffz-mentioned');
history.appendChild(msg_line);
// These objects can be persistent, so clear these.
new_message.is_original = null;
new_message.original_sender = null;
}
if ( data.after.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.after[data.after.length-1].lv_id, false, true);
setTimeout(function() {
var original = history.querySelector('.original-msg');
if ( original )
history.scrollTop = (original.offsetTop - history.offsetTop) - (history.clientHeight - original.clientHeight) / 2;
})
});
},
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
user_id = mod_card.get('cardInfo.user.id'),
room_id = controller && controller.get('currentRoom.id'),
ffz_room = this.rooms[room_id],
history = utils.createElement('ul', 'interface chat-history lv-history');
el.appendChild(history);
// Are we relying on LogViewer here?
if ( ! ffz_room.has_logs || ! mod_card.lv_view ) {
history.innerHTML = '<li class="chat-line admin"><span class="message">You do not have permission to view chat history in this channel.</span></li>';
return;
}
// Start loading!
history.classList.add('loading');
mod_card.lvGetLogs().then(function(data) {
history.classList.remove('loading');
// Should we display more?
if ( data.before.length >= 10 )
FFZ.mod_card_pages.history.render_more.call(
f, mod_card, el, history, data.before[0].lv_id, true, false);
var last_date = (new Date).toLocaleDateString();
if ( ! data.before.length )
history.innerHTML = '<li class="message-line chat-line admin no-messages"><span class="message">(There are no logged messages to display.)</span></li>';
for(var i=0; i < data.before.length; i++) {
var message = data.before[i],
date = message.date.toLocaleDateString();
if ( date !== last_date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
last_date = date;
}
var msg_line = f._build_mod_card_history(message, mod_card, false,
FFZ.mod_card_pages.history.render_adjacent.bind(f, mod_card, el, message));
msg_line.classList.remove('ffz-mentioned');
history.appendChild(msg_line);
}
history.scrollTop = history.scrollHeight;
});
}
}
FFZ.mod_card_pages.stats = {
title: "<span>S</span>tatistics",
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
room_id = controller && controller.get('currentRoom.id'),
user_id = mod_card.get('cardInfo.user.id'),
ffz_room = f.rooms && f.rooms[room_id];
var container = utils.createElement('ul', 'interface version-list');
el.appendChild(container);
if ( ffz_room.has_logs && mod_card.lv_view ) {
container.classList.add('loading');
mod_card.lvGetLogs().then(function(data) {
container.classList.remove('loading');
container.innerHTML = '<li>Messages <span>' + utils.number_commas(data.user.messages) + '</span></li><li>Timeouts <span> ' + utils.number_commas(data.user.timeouts) + '</span></li>';
});
var notice = utils.createElement('div', 'interface');
notice.innerHTML = 'Chat Log Source: <a target="_blank" href="https://cbenni.com/' + room_id + '?user=' + user_id + '">CBenni\'s logviewer</a>';
el.appendChild(notice);
}
}
}
FFZ.mod_card_pages.notes = {
title: "<span>N</span>otes",
add_note: function(mod_card, el, note, history, last_line, do_scroll) {
if ( ! history )
history = el.querySelector('.chat-history.user-notes');
if ( ! history )
return;
if ( ! last_line )
last_line = history.querySelector('.chat-line:last-of-type');
var was_at_bottom = do_scroll ? history.scrollTop >= (history.scrollHeight - history.clientHeight) : false,
last_date = last_line ? last_line.getAttribute('data-date') : (new Date).toLocaleDateString();
if ( last_line && last_line.classList.contains('no-messages') ) {
last_line.parentElement.removeChild(last_line);
last_line = null;
}
var output = FFZ.mod_card_pages.notes.build_note.call(this, mod_card, note),
date = output.getAttribute('data-date');
if ( last_date !== date ) {
var date_line = utils.createElement('li', 'chat-line timestamp-line', date);
date_line.setAttribute('data-date', date);
history.appendChild(date_line);
}
history.appendChild(output);
if ( was_at_bottom )
setTimeout(function() { history.scrollTop = history.scrollHeight });
return output;
},
build_note: function(mod_card, note) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
room = controller && controller.get('currentRoom'),
user = this.get_user(),
tmiSession = room.tmiSession || (window.TMI && TMI._sessions && TMI._sessions[0]),
message = {
date: new Date(note.added * 1000),
from: note.author,
room: note.channel,
lv_id: note.id,
message: note.text,
tags: {
'display-name': FFZ.get_capitalization(note.author)
},
color: tmiSession && note.author ? tmiSession.getColor(note.author) : "#755000"
};
this.tokenize_chat_line(message, true, false);
var can_edit = false, // mod_card.lv_write_notes && user && user.login === message.from,
can_delete = false, //mod_card.lv_delete_notes || (user && user.login === message.from),
can_mod = can_edit || can_delete;
var output = this._build_mod_card_history(message, mod_card, true, false, can_mod);
/*if ( can_mod ) {
var mod_icons = output.querySelector('.mod-icons');
if ( can_delete ) {
var btn_delete = utils.createElement('a', 'mod-icon html-tooltip delete-note', 'Delete');
btn_delete.title = 'Delete Note';
mod_icons.appendChild(btn_delete);
btn_delete.addEventListener('click', function(e) {
if ( e.ctrlKey || e.metaKey || e.altKey || btn_delete.classList.contains('loading') )
return;
btn_delete.classList.add('loading');
f.lv_get_token().then(function(token) {
utils.logviewer.del("comments/" + note.channel + "?id=" + note.id, token)
.then(function(resp) {
btn_delete.classList.remove('loading');
if ( resp.ok )
mod_card.lvOnMessage("comment-delete", note);
else
alert("An error occured deleting this note.");
}).catch(function() {
btn_delete.classList.remove('loading');
alert("An error occured deleting this note.");
});
}).catch(function() {
btn_delete.classList.remove('loading');
alert("An error occured deleting this note.");
})
e.preventDefault();
e.stopPropagation();
});
}
/*if ( can_edit ) {
var btn_edit = utils.createElement('a', 'mod-icon html-tooltip edit-note', 'Edit');
btn_edit.title = 'Edit Note';
mod_icons.appendChild(btn_edit);
}*
}*/
return output;
},
render: function(mod_card, el) {
var f = this,
controller = utils.ember_lookup('controller:chat'),
room = controller && controller.get('currentRoom'),
tmiSession = room.tmiSession || (window.TMI && TMI._sessions && TMI._sessions[0]),
room_id = room && room.get('id'),
user_id = mod_card.get('cardInfo.user.id'),
ffz_room = this.rooms[room_id],
history = utils.createElement('ul', 'interface chat-history user-notes');
el.appendChild(history);
if ( ! ffz_room.has_logs || ! mod_card.lv_view_notes ) {
history.innerHTML = '<li class="chat-line admin"><span class="message">You do not have permission to view notes in this channel.</span></li>';
return;
}
history.classList.add('loading');
this.lv_get_token().then(function(token) {
utils.logviewer.get("comments/" + room_id + "?topic=" + user_id, token)
.then(utils.json).then(function(data) {
f.log("[LV] Comments: " + user_id + " in " + room_id, data);
history.classList.remove('loading');
// We want to listen to get new notes for this user.
mod_card._lv_sock_room = room_id;
mod_card._lv_sock_user = user_id;
f.lv_ws_sub(room_id + '-' + user_id);
if ( data.length ) {
var last_line = null;
for(var i=0; i < data.length; i++)
last_line = FFZ.mod_card_pages.notes.add_note.call(f, mod_card, el, data[i], history, last_line, false);
}
else
history.appendChild(utils.createElement('li', 'chat-line message-line admin no-messages',
'<span class="message">There are no notes on this user.</span>'));
});
});
if ( mod_card.lv_write_notes ) {
var textarea = utils.createElement('textarea', 'chat_text_input mousetrap note-text-input'),
note_container = utils.createElement('div', 'interface textarea-contain note-input', textarea),
btn_submit = utils.createElement('button', 'button float-right', 'Add Note'),
btn_container = utils.createElement('div', 'chat-buttons-container clearfix', btn_submit),
submit_note = function() {
if ( note_container.classList.contains('loading') )
return;
var comment = textarea.value.trim();
if ( ! comment.length )
return;
note_container.classList.add('loading');
textarea.disabled = btn_submit.disabled = true;
f.lv_get_token().then(function(token) {
utils.logviewer.post("comments/" + room_id, null, {
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
body: JSON.stringify({
comment: {
topic: user_id,
text: comment
},
token: token
})
}).then(function(resp) {
note_container.classList.remove('loading');
textarea.disabled = btn_submit.disabled = false;
textarea.value = '';
if ( resp.ok )
textarea.placeholder = 'The note was posted successfully. Write another note...';
else
alert("An error occured posting this note.");
}).catch(function() {
note_container.classList.remove('loading');
textarea.disabled = btn_submit.disabled = false;
alert("An error occured posting this note.");
});
}).catch(function() {
note_container.classList.remove('loading');
textarea.disabled = btn_submit.disabled = false;
alert("An error occured posting this note.");
})
};
textarea.placeholder = 'Write a note about ' + user_id + '...';
btn_submit.addEventListener('click', submit_note);
note_container.appendChild(btn_container);
el.appendChild(note_container);
}
}
}

View file

@ -83,6 +83,8 @@ FFZ.prototype.modify_chat_settings_menu = function(component) {
cb.addEventListener("change", function(e) {
f.settings.set("dark_twitch", this.checked);
if ( this.checked )
f.settings.set("dark_no_blue", true);
});
@ -580,7 +582,8 @@ FFZ.menu_pages.channel = {
var last_content = tickets.get("content");
last_content = last_content.length > 0 ? last_content[last_content.length-1] : undefined;
if ( last_content && last_content.purchase_profile && !last_content.purchase_profile.will_renew ) {
var ends_at = utils.parse_date(last_content.access_end || "");
var ends_at = utils.parse_date(last_content.access_end || ""),
provider = last_content.purchase_profile && last_content.purchase_profile.payment_provider,
sub_message = document.createElement("div"),
nonsub_message = document.createElement("div"),
unlock_text = document.createElement("span"),
@ -593,6 +596,10 @@ FFZ.menu_pages.channel = {
unlock_text.className = "unlock-text";
unlock_text.innerHTML = "Subscription expires in " + utils.time_to_string(end_time, true, true);
if ( provider === "samus" )
unlock_text.innerHTML += '<br>(Twitch Prime Free Sub)';
nonsub_message.appendChild(unlock_text);
inner.appendChild(sub_message);
}

View file

@ -521,7 +521,7 @@ module.exports = FFZ.utils = {
},
logviewer: {
del: function(u,t,i) { return logviewer_call('del', u,t,i) },
del: function(u,t,i) { return logviewer_call('delete', u,t,i) },
get: function(u,t,i) { return logviewer_call('get', u,t,i) },
post: function(u,t,i) { return logviewer_call('post', u,t,i) },
put: function(u,t,i) { return logviewer_call('put', u,t,i) },

View file

@ -1139,20 +1139,20 @@ body.ffz-bttv-dark .ffz-ui-popup .ffz-ui-menu-page { border-bottom: none }
.app-main.theatre .chatReplay .chat-messages .chat-line .mod-icons,
.ffz-dark .chatReplay .chat-messages .chat-line .mod-icons {
background-color: rgba(0,0,0,0.8);
background-color: rgba(0,0,0,0.8);
}
.chatReplay .chat-messages .chat-line .mod-icons {
position: absolute;
z-index: 10;
left: 0; top: 2px; bottom: 2px;
padding: 4px 5px 4px 4px;
background: rgba(255,255,255,0.8);
transition: margin-left .08s linear;
position: absolute;
z-index: 10;
left: 0; top: 2px; bottom: 2px;
padding: 4px 5px 4px 4px;
background: rgba(255,255,255,0.8);
transition: margin-left .08s linear;
}
.chatReplay .chat-messages .chat-line:hover .mod-icons {
margin-left: 0;
margin-left: 0;
}
.chatReplay .chat-messages .horizontal-line { margin: 4px 0 }
@ -1388,6 +1388,7 @@ img.channel_background[src="null"] { display: none; }
.ffz-moderation-card ul.menu + .interface { border-top: none }
.ffz-moderation-card .interface:last-child,
.ffz-moderation-card .interface:not(:last-of-type) {
border-bottom: none;
}
@ -1418,6 +1419,11 @@ img.channel_background[src="null"] { display: none; }
.ffz-moderation-card ul.menu span { text-decoration: underline }
.ffz-dark .moderation-card .interface,
.theatre .moderation-card .interface,
.dark .moderation-card .interface,
.force-dark .moderation-card .interface,
.ffz-dark .ffz-moderation-card ul.menu,
.theatre .ffz-moderation-card ul.menu,
.dark .ffz-moderation-card ul.menu,
@ -1519,7 +1525,10 @@ img.channel_background[src="null"] { display: none; }
/* Chat Rows */
.chat-line { overflow: hidden }
.ember-chat .chat-messages .chat-line {
margin: 0;
padding: 3px 20px;
}
.theatre .conversation-window .conversation-chat-line,
.dark .chat-line,
@ -1568,7 +1577,7 @@ body:not(.ffz-bttv) .chat-container:not(.chatReplay) .more-messages-indicator {
/* Emoticon Tooltips */
.ffz-wide-tip hr {
margin: 5px 0;
margin: 5px 0;
}
.ffz-wide-tip .tipsy-inner {
@ -3387,20 +3396,19 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
padding: 5px 10px;
}
.chat-room .show-mod-icons .chat-line:not(.admin) .mod-icons {
.chat-room .show-mod-icons .chat-lines .chat-line:not(.admin) .mod-icons {
display: block !important;
position: absolute;
top: 2px;
bottom: 1px;
padding: 4px 5px 0;
top: 0; bottom: 0;
padding: 3px 5px 0;
left: 0;
z-index: 99;
background-color: rgba(255,255,255,0.8);
}
.theatre .chat-room .show-mod-icons .chat-line:not(.admin) .mod-icons,
.dark .chat-room .show-mod-icons .chat-line:not(.admin) .mod-icons,
.force-dark .chat-room .show-mod-icons .chat-line:not(.admin) .mod-icons {
.theatre .chat-room .show-mod-icons .chat-lines .chat-line:not(.admin) .mod-icons,
.dark .chat-room .show-mod-icons .chat-lines .chat-line:not(.admin) .mod-icons,
.force-dark .chat-room .show-mod-icons .chat-lines .chat-line:not(.admin) .mod-icons {
background-color: rgba(0,0,0,0.8);
}
@ -3556,4 +3564,23 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
min-height: 70px;
}
.ffz-hide-channel-banner .cn-bar__avatar-wrap { width: 4rem; height: 4rem; }
.ffz-hide-channel-banner .cn-bar__avatar-wrap { width: 4rem; height: 4rem; }
/* Mod Card Notes */
.ffz-moderation-card .note-input textarea {
width: 100%;
height: 50px;
resize: none;
margin-bottom: 10px;
}
.ffz-moderation-card .mod-icons .delete-note {
background-image: url("//cdn.frankerfacez.com/script/button_ban.svg");
background-repeat: no-repeat;
}
.ffz-moderation-card .mod-icons .edit-note {
background-image: url("//cdn.frankerfacez.com/script/button_edit.svg");
background-repeat: no-repeat;
}