mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-29 15:55:33 +00:00
Added "/ffz log" command to upload logs to pastebin. Added extra error handling in Ember-facing code. Added settings menu categories. Added user name color adjustment. Added support for better moderation cards. Added support for extra moderation commands. Fixed menu size limit. Fixed typo in show_message RPC. Fixed CSS for UI button.
This commit is contained in:
parent
fe55f43b8e
commit
b90a25d794
19 changed files with 1788 additions and 676 deletions
4
script.min.js
vendored
4
script.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,11 +1,25 @@
|
|||
var FFZ = window.FrankerFaceZ;
|
||||
|
||||
|
||||
// -----------------
|
||||
// Log Export
|
||||
// -----------------
|
||||
|
||||
FFZ.ffz_commands.log = function(room, args) {
|
||||
this._pastebin(this._log_data.join("\n"), function(url) {
|
||||
if ( ! url )
|
||||
return this.room_message(room, "There was an error uploading the FrankerFaceZ log.");
|
||||
|
||||
this.room_message(room, "Your FrankerFaceZ log has been pasted to: " + url);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// -----------------
|
||||
// Mass Moderation
|
||||
// -----------------
|
||||
|
||||
FFZ.chat_commands.massunmod = function(room, args) {
|
||||
FFZ.ffz_commands.massunmod = function(room, args) {
|
||||
args = args.join(" ").trim();
|
||||
|
||||
if ( ! args.length )
|
||||
|
@ -29,10 +43,10 @@ FFZ.chat_commands.massunmod = function(room, args) {
|
|||
return "Sent unmod command for " + count + " users.";
|
||||
}
|
||||
|
||||
FFZ.chat_commands.massunmod.help = "Usage: /ffz massunmod <list, of, users>\nBroadcaster only. Unmod all the users in the provided list.";
|
||||
FFZ.ffz_commands.massunmod.help = "Usage: /ffz massunmod <list, of, users>\nBroadcaster only. Unmod all the users in the provided list.";
|
||||
|
||||
|
||||
FFZ.chat_commands.massmod = function(room, args) {
|
||||
FFZ.ffz_commands.massmod = function(room, args) {
|
||||
args = args.join(" ").trim();
|
||||
|
||||
if ( ! args.length )
|
||||
|
@ -47,7 +61,6 @@ FFZ.chat_commands.massmod = function(room, args) {
|
|||
if ( args.length > 50 )
|
||||
return "Each user you mod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";
|
||||
|
||||
|
||||
var count = args.length;
|
||||
while(args.length) {
|
||||
var name = args.shift();
|
||||
|
@ -57,4 +70,4 @@ FFZ.chat_commands.massmod = function(room, args) {
|
|||
return "Sent mod command for " + count + " users.";
|
||||
}
|
||||
|
||||
FFZ.chat_commands.massmod.help = "Usage: /ffz massmod <list, of, users>\nBroadcaster only. Mod all the users in the provided list.";
|
||||
FFZ.ffz_commands.massmod.help = "Usage: /ffz massmod <list, of, users>\nBroadcaster only. Mod all the users in the provided list.";
|
|
@ -5,7 +5,7 @@ var FFZ = window.FrankerFaceZ;
|
|||
// Developer Mode Command
|
||||
// -----------------------
|
||||
|
||||
FFZ.chat_commands.developer_mode = function(room, args) {
|
||||
FFZ.ffz_commands.developer_mode = function(room, args) {
|
||||
var enabled, args = args && args.length ? args[0].toLowerCase() : null;
|
||||
if ( args == "y" || args == "yes" || args == "true" || args == "on" )
|
||||
enabled = true;
|
||||
|
@ -19,4 +19,4 @@ FFZ.chat_commands.developer_mode = function(room, args) {
|
|||
return "Developer Mode is now " + (enabled ? "enabled" : "disabled") + ". Please refresh your browser.";
|
||||
}
|
||||
|
||||
FFZ.chat_commands.developer_mode.help = "Usage: /ffz developer_mode <on|off>\nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN.";
|
||||
FFZ.ffz_commands.developer_mode.help = "Usage: /ffz developer_mode <on|off>\nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN.";
|
||||
|
|
|
@ -25,7 +25,11 @@ FFZ.prototype.setup_chatview = function() {
|
|||
continue;
|
||||
|
||||
this.log("Adding UI link manually to Chat view.", view);
|
||||
try {
|
||||
view.$('.textarea-contain').append(this.build_ui_link(view));
|
||||
} catch(err) {
|
||||
this.error("setup: build_ui_link: " + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,16 +44,28 @@ FFZ.prototype._modify_cview = function(view) {
|
|||
view.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
try {
|
||||
this.$() && this.$('.textarea-contain').append(f.build_ui_link(this));
|
||||
} catch(err) {
|
||||
f.error("didInsertElement: build_ui_link: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
willClearRender: function() {
|
||||
this._super();
|
||||
try {
|
||||
this.$(".ffz-ui-toggle").remove();
|
||||
} catch(err) {
|
||||
f.error("willClearRender: remove ui link: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
ffzUpdateLink: Ember.observer('controller.currentRoom', function() {
|
||||
try {
|
||||
f.update_ui_link();
|
||||
} catch(err) {
|
||||
f.error("ffzUpdateLink: update_ui_link: " + err);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
utils = require("../utils"),
|
||||
|
||||
reg_escape = function(str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
|
@ -13,6 +14,7 @@ FFZ.settings_info.capitalize = {
|
|||
type: "boolean",
|
||||
value: true,
|
||||
|
||||
category: "Chat",
|
||||
visible: function() { return ! this.has_bttv },
|
||||
|
||||
name: "Username Capitalization",
|
||||
|
@ -24,6 +26,7 @@ FFZ.settings_info.keywords = {
|
|||
type: "button",
|
||||
value: [],
|
||||
|
||||
category: "Chat",
|
||||
visible: function() { return ! this.has_bttv },
|
||||
|
||||
name: "Highlight Keywords",
|
||||
|
@ -33,7 +36,7 @@ FFZ.settings_info.keywords = {
|
|||
var old_val = this.settings.keywords.join(", "),
|
||||
new_val = prompt("Highlight Keywords\n\nPlease enter a comma-separated list of words that you would like to be highlighted in chat.", old_val);
|
||||
|
||||
if ( ! new_val )
|
||||
if ( new_val === null || new_val === undefined )
|
||||
return;
|
||||
|
||||
// Split them up.
|
||||
|
@ -47,17 +50,40 @@ FFZ.settings_info.keywords = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.fix_color = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Chat",
|
||||
visible: function() { return ! this.has_bttv },
|
||||
|
||||
name: "Adjust Username Colors",
|
||||
help: "Ensure that username colors contrast with the background enough to be readable.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.body.classList.toggle("ffz-chat-colors", val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.chat_rows = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Chat",
|
||||
visible: function() { return ! this.has_bttv },
|
||||
|
||||
name: "Chat Line Backgrounds",
|
||||
help: "Display alternating background colors for lines in chat.",
|
||||
|
||||
on_update: function(val) {
|
||||
document.querySelector(".app-main").classList.toggle("ffz-chat-background", val);
|
||||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.body.classList.toggle("ffz-chat-background", val);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,10 +93,19 @@ FFZ.settings_info.chat_rows = {
|
|||
// ---------------------
|
||||
|
||||
FFZ.prototype.setup_line = function() {
|
||||
// Alternating Background
|
||||
document.querySelector('.app-main').classList.toggle('ffz-chat-background', this.settings.chat_rows);
|
||||
// Chat Enhancements
|
||||
document.body.classList.toggle("ffz-chat-colors", !this.has_bttv && this.settings.fix_color);
|
||||
document.body.classList.toggle('ffz-chat-background', !this.has_bttv && this.settings.chat_rows);
|
||||
|
||||
this._colors = {};
|
||||
this._last_row = {};
|
||||
|
||||
var s = this._fix_color_style = document.createElement('style');
|
||||
s.id = "ffz-style-username-colors";
|
||||
s.type = 'text/css';
|
||||
document.head.appendChild(s);
|
||||
|
||||
|
||||
this.log("Hooking the Ember Line controller.");
|
||||
|
||||
var Line = App.__container__.resolve('controller:line'),
|
||||
|
@ -79,12 +114,21 @@ FFZ.prototype.setup_line = function() {
|
|||
Line.reopen({
|
||||
tokenizedMessage: function() {
|
||||
// Add our own step to the tokenization procedure.
|
||||
var tokens = f._emoticonize(this, this._super()),
|
||||
user = f.get_user();
|
||||
var tokens = this._super();
|
||||
|
||||
try {
|
||||
tokens = f._emoticonize(this, tokens);
|
||||
var user = f.get_user();
|
||||
|
||||
if ( ! user || this.get("model.from") != user.login )
|
||||
tokens = f._mentionize(this, tokens);
|
||||
|
||||
} catch(err) {
|
||||
try {
|
||||
f.error("LineController tokenizedMessage: " + err);
|
||||
} catch(err) { }
|
||||
}
|
||||
|
||||
return tokens;
|
||||
|
||||
}.property("model.message", "isModeratorOrHigher")
|
||||
|
@ -97,32 +141,49 @@ FFZ.prototype.setup_line = function() {
|
|||
Line.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
|
||||
try {
|
||||
var el = this.get('element'),
|
||||
user = this.get('context.model.from'),
|
||||
room = this.get('context.parentController.content.id'),
|
||||
row_type = this.get('context.model.ffzAlternate');
|
||||
color = this.get('context.model.color'),
|
||||
|
||||
row_type = this.get('context.model.ffz_alternate');
|
||||
|
||||
|
||||
// Color Processing
|
||||
if ( color )
|
||||
f._handle_color(color);
|
||||
|
||||
|
||||
// Row Alternation
|
||||
if ( row_type === undefined ) {
|
||||
row_type = f._last_row[room] = f._last_row.hasOwnProperty(room) ? !f._last_row[room] : false;
|
||||
this.set("context.model.ffzAlternate", row_type);
|
||||
this.set("context.model.ffz_alternate", row_type);
|
||||
}
|
||||
|
||||
el.classList.toggle('ffz-alternate', row_type);
|
||||
|
||||
|
||||
// Basic Data
|
||||
el.setAttribute('data-room', room);
|
||||
el.setAttribute('data-sender', user);
|
||||
|
||||
|
||||
// Badge
|
||||
f.render_badge(this);
|
||||
|
||||
|
||||
// Capitalization
|
||||
if ( f.settings.capitalize )
|
||||
f.capitalize(this, user);
|
||||
|
||||
// Check for any mentions.
|
||||
|
||||
// Mention Highlighting
|
||||
var mentioned = el.querySelector('span.mentioned');
|
||||
if ( mentioned ) {
|
||||
el.classList.add("ffz-mentioned");
|
||||
|
||||
if ( ! document.hasFocus() && ! this.get('context.model.ffzNotified') && f.settings.highlight_notifications ) {
|
||||
if ( ! document.hasFocus() && ! this.get('context.model.ffz_notified') && f.settings.highlight_notifications ) {
|
||||
var cap_room = FFZ.get_capitalization(room),
|
||||
cap_user = FFZ.get_capitalization(user),
|
||||
room_name = cap_room,
|
||||
|
@ -147,10 +208,17 @@ FFZ.prototype.setup_line = function() {
|
|||
}
|
||||
|
||||
// Mark that we've checked this message for mentions.
|
||||
this.set('context.model.ffzNotified', true);
|
||||
this.set('context.model.ffz_notified', true);
|
||||
|
||||
} catch(err) {
|
||||
try {
|
||||
f.error("LineView didInsertElement: " + err);
|
||||
} catch(err) { }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Store the capitalization of our own name.
|
||||
var user = this.get_user();
|
||||
if ( user && user.name )
|
||||
|
@ -158,6 +226,69 @@ FFZ.prototype.setup_line = function() {
|
|||
}
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Fix Name Colors
|
||||
// ---------------------
|
||||
|
||||
FFZ.prototype._handle_color = function(color) {
|
||||
if ( ! color || this._colors[color] )
|
||||
return;
|
||||
|
||||
this._colors[color] = true;
|
||||
|
||||
// Parse the color.
|
||||
var raw = parseInt(color.substr(1), 16),
|
||||
rgb = [
|
||||
(raw >> 16),
|
||||
(raw >> 8 & 0x00FF),
|
||||
(raw & 0x0000FF)
|
||||
],
|
||||
|
||||
lum = utils.get_luminance(rgb),
|
||||
|
||||
output = "",
|
||||
rule = 'span[style="color:' + color + '"]',
|
||||
matched = false;
|
||||
|
||||
if ( lum > 0.3 ) {
|
||||
// Color Too Bright. We need a lum of 0.3 or less.
|
||||
matched = true;
|
||||
|
||||
var s = 255,
|
||||
nc = rgb;
|
||||
while(s--) {
|
||||
nc = utils.darken(nc);
|
||||
if ( utils.get_luminance(nc) <= 0.3 )
|
||||
break;
|
||||
}
|
||||
|
||||
output += '.ffz-chat-colors .ember-chat-container:not(.dark) .chat-line ' + rule + ', .ffz-chat-colors .chat-container:not(.dark) .chat-line ' + rule + ' { color: ' + utils.rgb_to_css(nc) + ' !important; }\n';
|
||||
} else
|
||||
output += '.ffz-chat-colors .ember-chat-container:not(.dark) .chat-line ' + rule + ', .ffz-chat-colors .chat-container:not(.dark) .chat-line ' + rule + ' { color: ' + color + ' !important; }\n';
|
||||
|
||||
if ( lum < 0.1 ) {
|
||||
// Color Too Dark. We need a lum of 0.1 or more.
|
||||
matched = true;
|
||||
|
||||
var s = 255,
|
||||
nc = rgb;
|
||||
while(s--) {
|
||||
nc = utils.brighten(nc);
|
||||
if ( utils.get_luminance(nc) >= 0.1 )
|
||||
break;
|
||||
}
|
||||
|
||||
output += '.ffz-chat-colors .theatre .chat-container .chat-line ' + rule + ', .ffz-chat-colors .chat-container.dark .chat-line ' + rule + ', .ffz-chat-colors .ember-chat-container.dark .chat-line ' + rule + ' { color: ' + utils.rgb_to_css(nc) + ' !important; }\n';
|
||||
} else
|
||||
output += '.ffz-chat-colors .theatre .chat-container .chat-line ' + rule + ', .ffz-chat-colors .chat-container.dark .chat-line ' + rule + ', .ffz-chat-colors .ember-chat-container.dark .chat-line ' + rule + ' { color: ' + color + ' !important; }\n';
|
||||
|
||||
|
||||
if ( matched )
|
||||
this._fix_color_style.innerHTML += output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Capitalization
|
||||
// ---------------------
|
||||
|
@ -205,30 +336,13 @@ FFZ.prototype.capitalize = function(view, user) {
|
|||
}
|
||||
|
||||
|
||||
FFZ.chat_commands.capitalization = function(room, args) {
|
||||
var enabled, args = args && args.length ? args[0].toLowerCase() : null;
|
||||
if ( args == "y" || args == "yes" || args == "true" || args == "on" )
|
||||
enabled = true;
|
||||
else if ( args == "n" || args == "no" || args == "false" || args == "off" )
|
||||
enabled = false;
|
||||
|
||||
if ( enabled === undefined )
|
||||
return "Chat Name Capitalization is currently " + (this.settings.capitalize ? "enabled." : "disabled.");
|
||||
|
||||
this.settings.set("capitalize", enabled);
|
||||
return "Chat Name Capitalization is now " + (enabled ? "enabled." : "disabled.");
|
||||
}
|
||||
|
||||
FFZ.chat_commands.capitalization.help = "Usage: /ffz capitalization <on|off>\nEnable or disable Chat Name Capitalization. This setting does not work with BetterTTV.";
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Extra Mentions
|
||||
// ---------------------
|
||||
|
||||
FFZ._regex_cache = {};
|
||||
|
||||
FFZ._get_rex = function(word) {
|
||||
FFZ._get_regex = function(word) {
|
||||
return FFZ._regex_cache[word] = FFZ._regex_cache[word] || RegExp("\\b" + reg_escape(word) + "\\b", "ig");
|
||||
}
|
||||
|
||||
|
@ -266,25 +380,6 @@ FFZ.prototype._mentionize = function(controller, tokens) {
|
|||
}
|
||||
|
||||
|
||||
FFZ.chat_commands.mentionize = function(room, args) {
|
||||
if ( args && args.length ) {
|
||||
var mention_words = args.join(" ").trim().split(/\W*,\W*/);
|
||||
if ( mention_words.length == 1 && mention_words[0] == "disable" )
|
||||
mention_words = [];
|
||||
|
||||
this.settings.set("keywords", mention_words);
|
||||
}
|
||||
|
||||
var mention_words = this.settings.keywords;
|
||||
if ( mention_words.length )
|
||||
return "The following words will be highlighted: " + mention_words.join(", ");
|
||||
else
|
||||
return "There are no words set that will be highlighted.";
|
||||
}
|
||||
|
||||
FFZ.chat_commands.mentionize.help = "Usage: /ffz mentionize <comma, separated, word, list|disable>\nSet a list of words that will also be highlighted in chat.";
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Emoticon Replacement
|
||||
// ---------------------
|
||||
|
|
247
src/ember/moderation-card.js
Normal file
247
src/ember/moderation-card.js
Normal file
|
@ -0,0 +1,247 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
utils = require("../utils"),
|
||||
|
||||
keycodes = {
|
||||
ESC: 27,
|
||||
P: 80,
|
||||
B: 66,
|
||||
T: 84
|
||||
},
|
||||
|
||||
btns = [
|
||||
['5m', 300],
|
||||
['10m', 600],
|
||||
['1hr', 3600],
|
||||
['12hr', 43200],
|
||||
['24hr', 86400]],
|
||||
|
||||
MESSAGE = '<svg class="svg-messages" height="16px" version="1.1" viewBox="0 0 18 18" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M1,15V3h16v12H1z M15.354,5.354l-0.707-0.707L9,10.293L3.354,4.646L2.646,5.354L6.293,9l-3.646,3.646l0.707,0.707L7,9.707l1.646,1.646h0.707L11,9.707l3.646,3.646l0.707-0.707L11.707,9L15.354,5.354z" fill-rule="evenodd"></path></svg>';
|
||||
|
||||
|
||||
// ----------------
|
||||
// Settings
|
||||
// ----------------
|
||||
|
||||
FFZ.settings_info.enhanced_moderation = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
visible: function() { return ! this.has_bttv },
|
||||
category: "Chat",
|
||||
|
||||
name: "Enhanced Moderation",
|
||||
help: "Use /p, /t, /u and /b in chat to moderator, or use hotkeys with moderation cards."
|
||||
};
|
||||
|
||||
|
||||
// ----------------
|
||||
// Initialization
|
||||
// ----------------
|
||||
|
||||
FFZ.prototype.setup_mod_card = function() {
|
||||
this.log("Hooking the Ember Moderation Card view.");
|
||||
var Card = App.__container__.resolve('view:moderation-card'),
|
||||
f = this;
|
||||
|
||||
Card.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
try {
|
||||
if ( ! f.settings.enhanced_moderation )
|
||||
return;
|
||||
|
||||
var el = this.get('element'),
|
||||
controller = this.get('context');
|
||||
|
||||
// Only do the big stuff if we're mod.
|
||||
if ( controller.get('parentController.model.isModeratorOrHigher') ) {
|
||||
el.classList.add('ffz-moderation-card');
|
||||
el.setAttribute('tabindex', 1);
|
||||
|
||||
// Key Handling
|
||||
el.addEventListener('keyup', function(e) {
|
||||
var key = e.keyCode || e.which,
|
||||
user_id = controller.get('model.user.id'),
|
||||
room = controller.get('parentController.model');
|
||||
|
||||
if ( key == keycodes.P )
|
||||
room.send("/timeout " + user_id + " 1");
|
||||
|
||||
else if ( key == keycodes.B )
|
||||
room.send("/ban " + user_id);
|
||||
|
||||
else if ( key == keycodes.T )
|
||||
room.send("/timeout " + user_id + " 600");
|
||||
|
||||
else if ( key != keycodes.ESC )
|
||||
return;
|
||||
|
||||
controller.send('hideModOverlay');
|
||||
});
|
||||
|
||||
|
||||
// Extra Moderation
|
||||
var line = document.createElement('div');
|
||||
line.className = 'interface clearfix';
|
||||
|
||||
var btn_click = function(timeout) {
|
||||
var user_id = controller.get('model.user.id'),
|
||||
room = controller.get('parentController.model');
|
||||
|
||||
if ( timeout === -1 )
|
||||
room.send("/unban " + user_id);
|
||||
else
|
||||
room.send("/timeout " + user_id + " " + timeout);
|
||||
},
|
||||
|
||||
btn_make = function(text, timeout) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'button';
|
||||
btn.innerHTML = text;
|
||||
btn.title = "Timeout User for " + utils.number_commas(timeout) + " Second" + (timeout != 1 ? "s" : "");
|
||||
|
||||
if ( timeout === 600 )
|
||||
btn.title = "(T)" + btn.title.substr(1);
|
||||
else if ( timeout === 1 )
|
||||
btn.title = "(P)urge - " + btn.title;
|
||||
|
||||
jQuery(btn).tipsy();
|
||||
|
||||
btn.addEventListener('click', btn_click.bind(this, timeout));
|
||||
return btn;
|
||||
};
|
||||
|
||||
line.appendChild(btn_make('Purge', 1));
|
||||
|
||||
var s = document.createElement('span');
|
||||
s.className = 'right';
|
||||
line.appendChild(s);
|
||||
|
||||
for(var i=0; i < btns.length; i++)
|
||||
s.appendChild(btn_make(btns[i][0], btns[i][1]));
|
||||
|
||||
el.appendChild(line);
|
||||
|
||||
|
||||
// Unban Button
|
||||
|
||||
var unban_btn = document.createElement('button');
|
||||
unban_btn.className = 'unban button glyph-only light';
|
||||
unban_btn.innerHTML = "✓";
|
||||
unban_btn.title = "(U)nban User";
|
||||
|
||||
jQuery(unban_btn).tipsy();
|
||||
unban_btn.addEventListener("click", btn_click.bind(this, -1));
|
||||
|
||||
var ban_btn = el.querySelector('button.ban');
|
||||
ban_btn.setAttribute('title', '(B)an User');
|
||||
|
||||
jQuery(ban_btn).after(unban_btn);
|
||||
|
||||
|
||||
// Fix Other Buttons
|
||||
this.$("button.timeout").remove();
|
||||
}
|
||||
|
||||
|
||||
// More Fixing Other Buttons
|
||||
var op_btn = el.querySelector('button.mod');
|
||||
if ( op_btn ) {
|
||||
var model = controller.get('parentController.model'),
|
||||
can_op = model.get('isBroadcaster') || model.get('isStaff') || model.get('isAdmin');
|
||||
|
||||
if ( ! can_op )
|
||||
op_btn.parentElement.removeChild(op_btn);
|
||||
}
|
||||
|
||||
|
||||
var msg_btn = el.querySelector(".interface > button");
|
||||
if ( msg_btn && msg_btn.className == "button" ) {
|
||||
msg_btn.innerHTML = MESSAGE;
|
||||
msg_btn.classList.add('glyph-only');
|
||||
msg_btn.classList.add('message');
|
||||
|
||||
msg_btn.title = "Message User";
|
||||
jQuery(msg_btn).tipsy();
|
||||
}
|
||||
|
||||
|
||||
// Focus the Element
|
||||
this.$().draggable({
|
||||
start: function() {
|
||||
el.focus();
|
||||
}});
|
||||
|
||||
el.focus();
|
||||
|
||||
} catch(err) {
|
||||
try {
|
||||
f.error("ModerationCardView didInsertElement: " + err);
|
||||
} catch(err) { }
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
|
||||
// ----------------
|
||||
// Chat Commands
|
||||
// ----------------
|
||||
|
||||
FFZ.chat_commands.purge = FFZ.chat_commands.p = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Purge Usage: /p username [more usernames separated by spaces]";
|
||||
|
||||
if ( args.length > 10 )
|
||||
return "Please only purge up to 10 users at once.";
|
||||
|
||||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/timeout " + name + " 1");
|
||||
}
|
||||
}
|
||||
|
||||
FFZ.chat_commands.p.enabled = function() { return this.settings.enhanced_moderation; }
|
||||
|
||||
|
||||
FFZ.chat_commands.t = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Timeout Usage: /t username [duration]";
|
||||
room.room.send("/timeout " + args.join(" "));
|
||||
}
|
||||
|
||||
FFZ.chat_commands.t.enabled = function() { return this.settings.enhanced_moderation; }
|
||||
|
||||
|
||||
FFZ.chat_commands.b = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Ban Usage: /b username [more usernames separated by spaces]";
|
||||
|
||||
if ( args.length > 10 )
|
||||
return "Please only ban up to 10 users at once.";
|
||||
|
||||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/ban " + name);
|
||||
}
|
||||
}
|
||||
|
||||
FFZ.chat_commands.b.enabled = function() { return this.settings.enhanced_moderation; }
|
||||
|
||||
|
||||
FFZ.chat_commands.u = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Unban Usage: /b username [more usernames separated by spaces]";
|
||||
|
||||
if ( args.length > 10 )
|
||||
return "Please only unban up to 10 users at once.";
|
||||
|
||||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/unban " + name);
|
||||
}
|
||||
}
|
||||
|
||||
FFZ.chat_commands.u.enabled = function() { return this.settings.enhanced_moderation; }
|
|
@ -50,6 +50,7 @@ FFZ.prototype.setup_room = function() {
|
|||
// --------------------
|
||||
|
||||
FFZ.chat_commands = {};
|
||||
FFZ.ffz_commands = {};
|
||||
|
||||
|
||||
FFZ.prototype.room_message = function(room, text) {
|
||||
|
@ -66,6 +67,54 @@ FFZ.prototype.room_message = function(room, text) {
|
|||
|
||||
|
||||
FFZ.prototype.run_command = function(text, room_id) {
|
||||
var room = this.rooms[room_id];
|
||||
if ( ! room || ! room.room )
|
||||
return false;
|
||||
|
||||
if ( ! text )
|
||||
return;
|
||||
|
||||
var args = text.split(" "),
|
||||
cmd = args.shift().substr(1).toLowerCase(),
|
||||
|
||||
command = FFZ.chat_commands[cmd],
|
||||
output;
|
||||
|
||||
if ( ! command )
|
||||
return false;
|
||||
|
||||
if ( command.hasOwnProperty('enabled') ) {
|
||||
var val = command.enabled;
|
||||
if ( typeof val == "function" ) {
|
||||
try {
|
||||
val = command.enabled.bind(this)(room, args);
|
||||
} catch(err) {
|
||||
this.error('command "' + cmd + '" enabled: ' + err);
|
||||
val = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! val )
|
||||
return false;
|
||||
}
|
||||
|
||||
this.log("Received Command: " + cmd, args, true);
|
||||
|
||||
try {
|
||||
output = command.bind(this)(room, args);
|
||||
} catch(err) {
|
||||
this.error('command "' + cmd + '" runner: ' + err);
|
||||
output = "There was an error running the command.";
|
||||
}
|
||||
|
||||
if ( output )
|
||||
this.room_message(room, output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype.run_ffz_command = function(text, room_id) {
|
||||
var room = this.rooms[room_id];
|
||||
if ( ! room || !room.room )
|
||||
return;
|
||||
|
@ -84,7 +133,7 @@ FFZ.prototype.run_command = function(text, room_id) {
|
|||
|
||||
this.log("Received Command: " + cmd, args, true);
|
||||
|
||||
var command = FFZ.chat_commands[cmd], output;
|
||||
var command = FFZ.ffz_commands[cmd], output;
|
||||
if ( command ) {
|
||||
try {
|
||||
output = command.bind(this)(room, args);
|
||||
|
@ -100,9 +149,9 @@ FFZ.prototype.run_command = function(text, room_id) {
|
|||
}
|
||||
|
||||
|
||||
FFZ.chat_commands.help = function(room, args) {
|
||||
FFZ.ffz_commands.help = function(room, args) {
|
||||
if ( args && args.length ) {
|
||||
var command = FFZ.chat_commands[args[0].toLowerCase()];
|
||||
var command = FFZ.ffz_commands[args[0].toLowerCase()];
|
||||
if ( ! command )
|
||||
return 'There is no "' + args[0] + '" command.';
|
||||
|
||||
|
@ -114,13 +163,13 @@ FFZ.chat_commands.help = function(room, args) {
|
|||
}
|
||||
|
||||
var cmds = [];
|
||||
for(var c in FFZ.chat_commands)
|
||||
FFZ.chat_commands.hasOwnProperty(c) && cmds.push(c);
|
||||
for(var c in FFZ.ffz_commands)
|
||||
FFZ.ffz_commands.hasOwnProperty(c) && cmds.push(c);
|
||||
|
||||
return "The available commands are: " + cmds.join(", ");
|
||||
}
|
||||
|
||||
FFZ.chat_commands.help.help = "Usage: /ffz help [command]\nList available commands, or show help for a specific command.";
|
||||
FFZ.ffz_commands.help.help = "Usage: /ffz help [command]\nList available commands, or show help for a specific command.";
|
||||
|
||||
|
||||
// --------------------
|
||||
|
@ -214,12 +263,20 @@ FFZ.prototype._modify_room = function(room) {
|
|||
// Track which rooms the user is currently in.
|
||||
init: function() {
|
||||
this._super();
|
||||
try {
|
||||
f.add_room(this.id, this);
|
||||
} catch(err) {
|
||||
f.error("add_room: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
willDestroy: function() {
|
||||
this._super();
|
||||
try {
|
||||
f.remove_room(this.id);
|
||||
} catch(err) {
|
||||
f.error("remove_room: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
getSuggestions: function() {
|
||||
|
@ -228,18 +285,34 @@ FFZ.prototype._modify_room = function(room) {
|
|||
// filteredSuggestions property of the chat-input component would
|
||||
// be even better, but I was already hooking the room model.
|
||||
var suggestions = this._super();
|
||||
if ( this.settings.capitalize )
|
||||
|
||||
try {
|
||||
if ( f.settings.capitalize )
|
||||
suggestions = _.map(suggestions, FFZ.get_capitalization);
|
||||
} catch(err) {
|
||||
f.error("get_suggestions: " + err);
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
},
|
||||
|
||||
send: function(text) {
|
||||
try {
|
||||
var cmd = text.split(' ', 1)[0].toLowerCase();
|
||||
if ( cmd === "/ffz" ) {
|
||||
this.set("messageToSend", "");
|
||||
f.run_command(text.substr(5), this.get('id'));
|
||||
} else
|
||||
f.run_ffz_command(text.substr(5), this.get('id'));
|
||||
return;
|
||||
|
||||
} else if ( cmd.charAt(0) === "/" && f.run_command(text, this.get('id')) ) {
|
||||
this.set("messageToSend", "");
|
||||
return;
|
||||
}
|
||||
|
||||
} catch(err) {
|
||||
f.error("send: " + err);
|
||||
}
|
||||
|
||||
return this._super(text);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,7 +11,11 @@ FFZ.prototype.setup_router = function() {
|
|||
var f = this;
|
||||
App.__container__.lookup('router:main').reopen({
|
||||
ffzTransition: function() {
|
||||
try {
|
||||
f.track_page();
|
||||
} catch(err) {
|
||||
f.error("ffzTransition: " + err);
|
||||
}
|
||||
}.on('didTransition')
|
||||
});
|
||||
}
|
|
@ -18,8 +18,9 @@ FFZ.prototype._modify_viewers = function(controller) {
|
|||
|
||||
controller.reopen({
|
||||
lines: function() {
|
||||
var viewers = this._super(),
|
||||
categories = [],
|
||||
var viewers = this._super();
|
||||
try {
|
||||
var categories = [],
|
||||
data = {},
|
||||
last_category = null;
|
||||
|
||||
|
@ -86,6 +87,10 @@ FFZ.prototype._modify_viewers = function(controller) {
|
|||
}
|
||||
}
|
||||
|
||||
} catch(err) {
|
||||
f.error("ViewersController lines: " + err);
|
||||
}
|
||||
|
||||
return viewers;
|
||||
}.property("content.chatters")
|
||||
});
|
||||
|
|
|
@ -23,22 +23,27 @@ FFZ.prototype.setup_bttv = function(delay) {
|
|||
this.log("BetterTTV was detected after " + delay + "ms. Hooking.");
|
||||
this.has_bttv = true;
|
||||
|
||||
this.track('setCustomVariable', '3', 'BetterTTV', BetterTTV.info.versionString());
|
||||
// this.track('setCustomVariable', '3', 'BetterTTV', BetterTTV.info.versionString());
|
||||
|
||||
// Disable Dark if it's enabled.
|
||||
document.querySelector(".app-main").classList.remove("ffz-dark");
|
||||
document.body.classList.remove("ffz-dark");
|
||||
if ( this._dark_style ) {
|
||||
this._dark_style.parentElement.removeChild(this._dark_style);
|
||||
delete this._dark_style;
|
||||
}
|
||||
|
||||
// Disable other features too.
|
||||
document.body.classList.remove("ffz-chat-colors");
|
||||
document.body.classList.remove("ffz-chat-background");
|
||||
|
||||
|
||||
// Send Message Behavior
|
||||
var original_send = BetterTTV.chat.helpers.sendMessage, f = this;
|
||||
BetterTTV.chat.helpers.sendMessage = function(message) {
|
||||
var cmd = message.split(' ', 1)[0].toLowerCase();
|
||||
|
||||
if ( cmd === "/ffz" )
|
||||
f.run_command(message.substr(5), BetterTTV.chat.store.currentRoom);
|
||||
f.run_ffz_command(message.substr(5), BetterTTV.chat.store.currentRoom);
|
||||
else
|
||||
return original_send(message);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ FFZ.prototype._feature_friday_ui = function(room_id, parent, view) {
|
|||
btn.innerHTML = "<span>" + message + "</span>";
|
||||
|
||||
// Track the number of users to click this button.
|
||||
btn.addEventListener('click', function() { f.track('trackLink', this.href, 'link'); });
|
||||
// btn.addEventListener('click', function() { f.track('trackLink', this.href, 'link'); });
|
||||
|
||||
btnc.appendChild(btn);
|
||||
parent.appendChild(btnc);
|
||||
|
|
54
src/main.js
54
src/main.js
|
@ -9,6 +9,9 @@ require('./shims');
|
|||
var FFZ = window.FrankerFaceZ = function() {
|
||||
FFZ.instance = this;
|
||||
|
||||
// Logging
|
||||
this._log_data = [];
|
||||
|
||||
// Get things started.
|
||||
this.initialize();
|
||||
}
|
||||
|
@ -19,7 +22,7 @@ FFZ.get = function() { return FFZ.instance; }
|
|||
|
||||
// Version
|
||||
var VER = FFZ.version_info = {
|
||||
major: 3, minor: 0, revision: 0,
|
||||
major: 3, minor: 1, revision: 0,
|
||||
toString: function() {
|
||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||
}
|
||||
|
@ -30,6 +33,8 @@ var VER = FFZ.version_info = {
|
|||
|
||||
FFZ.prototype.log = function(msg, data, to_json) {
|
||||
msg = "FFZ: " + msg + (to_json ? " -- " + JSON.stringify(data) : "");
|
||||
this._log_data.push(msg);
|
||||
|
||||
if ( data !== undefined && console.groupCollapsed && console.dir ) {
|
||||
console.groupCollapsed(msg);
|
||||
if ( navigator.userAgent.indexOf("Firefox/") !== -1 )
|
||||
|
@ -43,6 +48,43 @@ FFZ.prototype.log = function(msg, data, to_json) {
|
|||
}
|
||||
|
||||
|
||||
FFZ.prototype.error = function(msg, data, to_json) {
|
||||
msg = "FFZ Error: " + msg + (to_json ? " -- " + JSON.stringify(data) : "");
|
||||
this._log_data.push(msg);
|
||||
|
||||
if ( data !== undefined && console.groupCollapsed && console.dir ) {
|
||||
console.groupCollapsed(msg);
|
||||
if ( navigator.userAgent.indexOf("Firefox/") !== -1 )
|
||||
console.log(data);
|
||||
else
|
||||
console.dir(data);
|
||||
|
||||
console.groupEnd(msg);
|
||||
} else
|
||||
console.assert(false, msg);
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype.paste_logs = function() {
|
||||
this._pastebin(this._log_data.join("\n"), function(url) {
|
||||
if ( ! url )
|
||||
return console.log("FFZ Error: Unable to upload log to pastebin.");
|
||||
|
||||
console.log("FFZ: Your FrankerFaceZ log has been pasted to: " + url);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._pastebin = function(data, callback) {
|
||||
jQuery.ajax({url: "http://putco.de/", type: "PUT", data: data, context: this})
|
||||
.success(function(e) {
|
||||
callback.bind(this)(e.trim() + ".log");
|
||||
}).fail(function(e) {
|
||||
callback.bind(this)(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// -------------------
|
||||
// User Data
|
||||
// -------------------
|
||||
|
@ -69,14 +111,15 @@ require('./socket');
|
|||
require('./emoticons');
|
||||
require('./badges');
|
||||
|
||||
require('./ember/router');
|
||||
// Analytics: require('./ember/router');
|
||||
require('./ember/room');
|
||||
require('./ember/line');
|
||||
require('./ember/chatview');
|
||||
require('./ember/viewers');
|
||||
require('./ember/moderation-card');
|
||||
//require('./ember/teams');
|
||||
|
||||
require('./tracking');
|
||||
// Analytics: require('./tracking');
|
||||
|
||||
require('./debug');
|
||||
|
||||
|
@ -141,13 +184,14 @@ FFZ.prototype.setup_ember = function(delay) {
|
|||
this.setup_emoticons();
|
||||
this.setup_badges();
|
||||
|
||||
this.setup_piwik();
|
||||
//this.setup_piwik();
|
||||
|
||||
this.setup_router();
|
||||
//this.setup_router();
|
||||
this.setup_room();
|
||||
this.setup_line();
|
||||
this.setup_chatview();
|
||||
this.setup_viewers();
|
||||
this.setup_mod_card();
|
||||
|
||||
//this.setup_teams();
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ FFZ.settings_info.dark_twitch = {
|
|||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.querySelector(".app-main").classList.toggle("ffz-dark", val);
|
||||
document.body.classList.toggle("ffz-dark", val);
|
||||
if ( val )
|
||||
this._load_dark_css();
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ FFZ.prototype.setup_dark = function() {
|
|||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.querySelector(".app-main").classList.toggle("ffz-dark", this.settings.dark_twitch);
|
||||
document.body.classList.toggle("ffz-dark", this.settings.dark_twitch);
|
||||
if ( this.settings.dark_twitch )
|
||||
this._load_dark_css();
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ FFZ.prototype.build_ui_popup = function(view) {
|
|||
|
||||
// Add the menu to the DOM.
|
||||
this._popup = container;
|
||||
sub_container.style.maxHeight = Math.max(300, view.$().height() - 212) + "px";
|
||||
sub_container.style.maxHeight = Math.max(100, view.$().height() - 162) + "px";
|
||||
view.$('.chat-interface').append(container);
|
||||
}
|
||||
|
||||
|
@ -124,14 +124,52 @@ FFZ.prototype._ui_change_page = function(view, menu, container, page) {
|
|||
|
||||
FFZ.menu_pages.settings = {
|
||||
render: function(view, container) {
|
||||
var menu = document.createElement('div');
|
||||
var settings = {},
|
||||
categories = [];
|
||||
for(var key in FFZ.settings_info) {
|
||||
var info = FFZ.settings_info[key],
|
||||
cat = info.category || "Miscellaneous",
|
||||
cs = settings[cat];
|
||||
|
||||
if ( info.visible !== undefined && info.visible !== null ) {
|
||||
var visible = info.visible;
|
||||
if ( typeof info.visible == "function" )
|
||||
visible = info.visible.bind(this)();
|
||||
|
||||
if ( ! visible )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! cs ) {
|
||||
categories.push(cat);
|
||||
cs = settings[cat] = [];
|
||||
}
|
||||
|
||||
cs.push([key, info]);
|
||||
}
|
||||
|
||||
categories.sort(function(a,b) {
|
||||
var a = a.toLowerCase(),
|
||||
b = b.toLowerCase();
|
||||
|
||||
if ( a < b ) return -1;
|
||||
else if ( a > b ) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for(var ci=0; ci < categories.length; ci++) {
|
||||
var category = categories[ci],
|
||||
cset = settings[category],
|
||||
|
||||
menu = document.createElement('div'),
|
||||
heading = document.createElement('div');
|
||||
|
||||
heading.className = 'heading';
|
||||
menu.className = 'chat-menu-content';
|
||||
heading.innerHTML = category;
|
||||
menu.appendChild(heading);
|
||||
|
||||
var settings = [];
|
||||
for(var key in FFZ.settings_info)
|
||||
settings.push([key, FFZ.settings_info[key]]);
|
||||
|
||||
settings.sort(function(a,b) {
|
||||
cset.sort(function(a,b) {
|
||||
var ai = a[1],
|
||||
bi = b[1],
|
||||
|
||||
|
@ -144,21 +182,12 @@ FFZ.menu_pages.settings = {
|
|||
});
|
||||
|
||||
|
||||
for(var i=0; i < settings.length; i++) {
|
||||
var key = settings[i][0],
|
||||
info = settings[i][1],
|
||||
for(var i=0; i < cset.length; i++) {
|
||||
var key = cset[i][0],
|
||||
info = cset[i][1],
|
||||
el = document.createElement('p'),
|
||||
val = this.settings.get(key);
|
||||
|
||||
if ( info.visible !== undefined && info.visible !== null ) {
|
||||
var visible = info.visible;
|
||||
if ( typeof info.visible == "function" )
|
||||
visible = info.visible.bind(this)();
|
||||
|
||||
if ( ! visible )
|
||||
continue;
|
||||
}
|
||||
|
||||
el.className = 'clearfix';
|
||||
|
||||
if ( info.type == "boolean" ) {
|
||||
|
@ -198,6 +227,7 @@ FFZ.menu_pages.settings = {
|
|||
}
|
||||
|
||||
container.appendChild(menu);
|
||||
}
|
||||
},
|
||||
|
||||
name: "Settings",
|
||||
|
@ -236,8 +266,7 @@ FFZ.menu_pages.channel = {
|
|||
var room_id = view.get('controller.currentRoom.id'),
|
||||
room = this.rooms[room_id];
|
||||
|
||||
this.log("Menu for Room: " + room_id, room);
|
||||
this.track('trackEvent', 'Menu', 'Open', room_id);
|
||||
//this.track('trackEvent', 'Menu', 'Open', room_id);
|
||||
|
||||
// Add the header and ad button.
|
||||
/*var btn = document.createElement('a');
|
||||
|
|
|
@ -19,6 +19,7 @@ FFZ.settings_info.highlight_notifications = {
|
|||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Chat",
|
||||
visible: function() { return ! this.has_bttv },
|
||||
|
||||
name: "Highlight Notifications",
|
||||
|
@ -54,7 +55,7 @@ FFZ.settings_info.highlight_notifications = {
|
|||
// ---------------------
|
||||
|
||||
FFZ.ws_commands.message = function(message) {
|
||||
this.show_mesage(message);
|
||||
this.show_message(message);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ FFZ.prototype.setup_races = function() {
|
|||
FFZ.settings_info.srl_races = {
|
||||
type: "boolean",
|
||||
value: true,
|
||||
|
||||
category: "Channel Metadata",
|
||||
name: "SRL Race Information",
|
||||
help: 'Display information about <a href="http://www.speedrunslive.com/" target="_new">SpeedRunsLive</a> races under channels.',
|
||||
on_update: function(val) {
|
||||
|
|
39
src/utils.js
39
src/utils.js
|
@ -11,8 +11,42 @@ var sanitize_cache = {},
|
|||
else if ( num == 3 ) return '3rd';
|
||||
else if ( num == null ) return '---';
|
||||
return num + "th";
|
||||
},
|
||||
|
||||
brighten = function(rgb, amount) {
|
||||
amount = (amount === 0) ? 0 : (amount || 1);
|
||||
amount = Math.round(255 * -(amount / 100));
|
||||
|
||||
var r = Math.max(0, Math.min(255, rgb[0] - amount)),
|
||||
g = Math.max(0, Math.min(255, rgb[1] - amount)),
|
||||
b = Math.max(0, Math.min(255, rgb[2] - amount));
|
||||
|
||||
return [r,g,b];
|
||||
},
|
||||
|
||||
rgb_to_css = function(rgb) {
|
||||
return "rgb(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ")";
|
||||
},
|
||||
|
||||
darken = function(rgb, amount) {
|
||||
amount = (amount === 0) ? 0 : (amount || 1);
|
||||
return brighten(rgb, -amount);
|
||||
},
|
||||
|
||||
get_luminance = function(rgb) {
|
||||
rgb = [rgb[0]/255, rgb[1]/255, rgb[2]/255];
|
||||
for (var i =0; i<rgb.length; i++) {
|
||||
if (rgb[i] <= 0.03928) {
|
||||
rgb[i] = rgb[i] / 12.92;
|
||||
} else {
|
||||
rgb[i] = Math.pow( ((rgb[i]+0.055)/1.055), 2.4 );
|
||||
}
|
||||
}
|
||||
var l = (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]);
|
||||
return l;
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
update_css: function(element, id, css) {
|
||||
var all = element.innerHTML,
|
||||
|
@ -34,6 +68,11 @@ module.exports = {
|
|||
element.innerHTML = all;
|
||||
},
|
||||
|
||||
get_luminance: get_luminance,
|
||||
brighten: brighten,
|
||||
darken: darken,
|
||||
rgb_to_css: rgb_to_css,
|
||||
|
||||
number_commas: function(x) {
|
||||
var parts = x.toString().split(".");
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
|
|
155
style.css
155
style.css
|
@ -16,8 +16,17 @@
|
|||
.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); }
|
||||
|
||||
.chat-container.dark .ffz-ui-toggle svg.svg-emoticons path,.app-main.theatre .ffz-ui-toggle svg.svg-emoticons path,.ffz-ui-toggle.dark svg.svg-emoticons path { fill: #888; }
|
||||
.chat-container.dark .ffz-ui-toggle:hover svg.svg-emoticons path,.app-main.theatre .ffz-ui-toggle:hover svg.svg-emoticons path,.ffz-ui-toggle.dark:hover svg.svg-emoticons path { fill: #777; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle svg.svg-emoticons path,
|
||||
.ffz-ui-toggle.dark svg.svg-emoticons path { fill: #888; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle:hover svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle:hover svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle:hover svg.svg-emoticons path,
|
||||
.ffz-ui-toggle.dark:hover svg.svg-emoticons path { fill: #777; }
|
||||
|
||||
|
||||
.ffz-ui-toggle.no-emotes svg.svg-emoticons path { fill: rgba(80,0,0,0.2); }
|
||||
.ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path { fill: rgba(80,0,0,0.5); }
|
||||
|
@ -28,14 +37,37 @@
|
|||
.ffz-ui-toggle.blue.live svg.svg-emoticons path { fill: rgba(47,88,185,0.5); }
|
||||
.ffz-ui-toggle.blue.live:hover svg.svg-emoticons path { fill: rgba(47,88,185,1); }
|
||||
|
||||
.app-main.theatre .ffz-ui-toggle.no-emotes svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.no-emotes svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.no-emotes svg.svg-emoticons path { fill: #543f3f; }
|
||||
.app-main.theatre .ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.no-emotes:hover svg.svg-emoticons path { fill: #453434; }
|
||||
|
||||
.app-main.theatre .ffz-ui-toggle.live svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.live svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.live svg.svg-emoticons path { fill: #5b4487; }
|
||||
.app-main.theatre .ffz-ui-toggle.live:hover svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.live:hover svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.live:hover svg.svg-emoticons path { fill: #513c78; }
|
||||
.ember-chat-container.dark .ffz-ui-toggle.no-emotes svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.no-emotes svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.no-emotes svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.no-emotes svg.svg-emoticons path { fill: #453434; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.no-emotes:hover svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.no-emotes:hover svg.svg-emoticons path { fill: #543f3f; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle.live svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.live svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.live svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.live svg.svg-emoticons path { fill: #513c78; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle.live:hover svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.live:hover svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.live:hover svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.live:hover svg.svg-emoticons path { fill: #5b4487; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle.blue.live svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.blue.live svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.blue.live svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.blue.live svg.svg-emoticons path { fill: #3c4e78; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path,
|
||||
.app-main.theatre .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path,
|
||||
.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.blue.live:hover svg.svg-emoticons path { fill: #445887; }
|
||||
|
||||
.app-main.theatre .ffz-ui-toggle.blue.live svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.blue.live svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.blue.live svg.svg-emoticons path { fill: #445887; }
|
||||
.app-main.theatre .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path,.chat-container.dark .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path,.ember-chat .chat-interface .textarea-contain .ffz-ui-toggle.dark.blue.live:hover svg.svg-emoticons path { fill: #3c4e78; }
|
||||
|
||||
.ffz-ui-toggle.live {
|
||||
animation: ffzfade 8s linear infinite;
|
||||
|
@ -158,7 +190,9 @@
|
|||
fill: rgba(255,255,255,0.35) !important;
|
||||
}
|
||||
|
||||
.app-main.theatre .follow-button .notify:before, .app-main.theatre .button.drop:after, .app-main.theatre .follow-button .drop.follow:after {
|
||||
.app-main.theatre .follow-button .notify:before,
|
||||
.app-main.theatre .button.drop:after,
|
||||
.app-main.theatre .follow-button .drop.follow:after {
|
||||
border: 5px solid rgba(255,255,255,0.35);
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
|
@ -258,7 +292,8 @@
|
|||
color: inherit;
|
||||
}
|
||||
|
||||
#ffz-race-popup a.twitch, #ffz-race-popup a.hitbox {
|
||||
#ffz-race-popup a.twitch,
|
||||
#ffz-race-popup a.hitbox {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
margin: 0 5px;
|
||||
|
@ -287,12 +322,24 @@
|
|||
|
||||
/* Menu Options */
|
||||
|
||||
@media screen and (max-width: 369px) {
|
||||
.ember-chat-container .ember-chat .chat-interface .emoticon-selector {
|
||||
right: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ffz-ui-menu-page {
|
||||
overflow-y: auto;
|
||||
padding: 0 20px;
|
||||
margin: 0 -20px;
|
||||
}
|
||||
|
||||
.chat-menu.ffz-ui-popup .ffz-ui-menu-page .chat-menu-content .heading {
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid rgba(0,0,0, 0.2);
|
||||
}
|
||||
|
||||
.chat-menu.ffz-ui-popup .ffz-ui-menu-page .chat-menu-content {
|
||||
padding: 10px 0;
|
||||
background-color: transparent;
|
||||
|
@ -341,7 +388,7 @@
|
|||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
border-left: 1px solid rgba(0,0,0,0.2);
|
||||
border-bottom: 1px solid rgba(0,0,0,0.2);
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ffz-ui-popup ul.menu li.active {
|
||||
|
@ -375,13 +422,79 @@
|
|||
background-color: rgba(255,255,255, 0.75);
|
||||
}
|
||||
|
||||
.ffz-chat-background.theatre .chat-container .chat-line .mentioned, .ffz-chat-background .chat-container.dark .chat-line .mentioned {
|
||||
.ffz-chat-background .app-main.theatre .chat-container .chat-line .mentioned,
|
||||
.ffz-chat-background .ember-chat-container.dark .chat-line .mentioned,
|
||||
.ffz-chat-background .chat-container.dark .chat-line .mentioned {
|
||||
color: #8c8c9c;
|
||||
background-color: rgba(16,16,20, 0.75);
|
||||
}
|
||||
|
||||
|
||||
/* Fix Moderation Cards */
|
||||
|
||||
.ember-chat .moderation-card {
|
||||
box-shadow: #808080 0 0 5px;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card button {
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card button:not(.glyph-only):hover,
|
||||
.ember-chat .moderation-card button:not(.glyph-only):focus {
|
||||
color: #fff;
|
||||
background-color: rgba(117,80,186, 1);
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card button.message {
|
||||
height: 30px; width: 28px;
|
||||
}
|
||||
|
||||
.ember-chat .ffz-moderation-card .interface .mod-controls:last-of-type,
|
||||
.ember-chat .moderation-card .interface span.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card:focus {
|
||||
outline: none;
|
||||
box-shadow: #000 0 0 5px;
|
||||
}
|
||||
|
||||
.ember-chat-container.dark .ember-chat .moderation-card:focus,
|
||||
.chat-container.dark .ember-chat .moderation-card:focus,
|
||||
.app-main.theatre .ember-chat .moderation-card:focus {
|
||||
box-shadow: #fff 0 0 5px;
|
||||
}
|
||||
|
||||
.ember-chat-container.dark .ember-chat .moderation-card .interface,
|
||||
.chat-container.dark .ember-chat .moderation-card .interface,
|
||||
.app-main.theatre .ember-chat .moderation-card .interface {
|
||||
background-color: #232329;
|
||||
}
|
||||
|
||||
.ember-chat .ffz-moderation-card .interface:not(:last-of-type) {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card .interface {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card h3.name {
|
||||
display: inline-block;
|
||||
text-shadow: black 0 0 5px;
|
||||
}
|
||||
|
||||
.ember-chat .moderation-card .channel_background {
|
||||
width: 100%;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Chat Rows */
|
||||
|
||||
.ffz-chat-background .more-messages-indicator {
|
||||
/* This looks better when it's full width. */
|
||||
margin: 0 -20px;
|
||||
|
@ -404,10 +517,6 @@
|
|||
background-color: rgba(0,0,0, 0.1);
|
||||
}
|
||||
|
||||
.theatre.ffz-chat-background .ember-chat .chat-messages .chat-line.ffz-alternate, .ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-alternate {
|
||||
background-color: rgba(255,255,255, 0.05);
|
||||
}
|
||||
|
||||
.ffz-chat-background .ember-chat .chat-messages .chat-line.ffz-mentioned {
|
||||
background-color: rgba(255,127,127, 0.2);
|
||||
}
|
||||
|
@ -416,10 +525,20 @@
|
|||
background-color: rgba(255,127,127, 0.4);
|
||||
}
|
||||
|
||||
.theatre.ffz-chat-background .ember-chat .chat-messages .chat-line.ffz-mentioned, .ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned {
|
||||
.ffz-chat-background .app-main.theatre .ember-chat .chat-messages .chat-line.ffz-alternate,
|
||||
.ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-alternate,
|
||||
.ffz-chat-background .ember-chat-container.dark .ember-chat .chat-messages .chat-line.ffz-alternate {
|
||||
background-color: rgba(255,255,255, 0.05);
|
||||
}
|
||||
|
||||
.ffz-chat-background .app-main.theatre .ember-chat .chat-messages .chat-line.ffz-mentioned,
|
||||
.ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned,
|
||||
.ffz-chat-background .ember-chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned {
|
||||
background-color: rgba(255,0,0, 0.2);
|
||||
}
|
||||
|
||||
.theatre.ffz-chat-background .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate, .ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate {
|
||||
.ffz-chat-background .app-main.theatre .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate,
|
||||
.ffz-chat-background .chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate,
|
||||
.ffz-chat-background .ember-chat-container.dark .ember-chat .chat-messages .chat-line.ffz-mentioned.ffz-alternate {
|
||||
background-color: rgba(255,0,0, 0.3);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue