mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-02 16:08:31 +00:00
3.5.325. Tab complete commands. CSS tweaks. Fix chat lines not updating.
This commit is contained in:
parent
1a52caab6b
commit
6ab4bd64a8
12 changed files with 354 additions and 34 deletions
|
@ -1,3 +1,15 @@
|
|||
<div class="list-header">3.5.325 <time datetime="2016-10-12">(2016-10-12)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Added: Tab-complete commands in chat.</li>
|
||||
<li>Fixed: When the channel title is on top and the page is narrow, don't display the needless separator bar above the channel metadata.</li>
|
||||
<li>Fixed: Issue causing chat lines to stop updating when users are timed out.</li>
|
||||
</ul>
|
||||
|
||||
<div class="list-header">3.5.324 <time datetime="2016-10-12">(2016-10-12)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Fixed: The player wasn't being resized properly with BetterTTV when the chat width was changed.</li>
|
||||
</ul>
|
||||
|
||||
<div class="list-header">3.5.323 <time datetime="2016-10-12">(2016-10-12)</time></div>
|
||||
<ul class="chat-menu-content menu-side-padding">
|
||||
<li>Changed: Refactor how the Debug tab of the About menu works so that it's easier to add more content.</li>
|
||||
|
|
|
@ -55,9 +55,10 @@ FFZ.settings_info.command_aliases = {
|
|||
for(var i=0; i < this.settings.command_aliases.length; i++) {
|
||||
var pair = this.settings.command_aliases[i],
|
||||
name = pair[0],
|
||||
command = pair[1];
|
||||
command = pair[1],
|
||||
label = pair[2];
|
||||
|
||||
old_val.push(name + '=' + command);
|
||||
old_val.push(name + (label ? ' ' + label : '') + '=' + command);
|
||||
}
|
||||
|
||||
utils.prompt(
|
||||
|
@ -67,8 +68,10 @@ FFZ.settings_info.command_aliases = {
|
|||
"Variables, such as arguments you provide running the custom command, can be inserted into the output.<hr>" +
|
||||
|
||||
"All custom commands require names. Names go at the start of each line, and are separated from " +
|
||||
" the actual command by an equals sign. Do not include the leading slash or dot. Those are automatically included.<br>" +
|
||||
"<strong>Example:</strong> <code>boop=/timeout {0} 15 Boop!</code><hr>" +
|
||||
"the actual command by an equals sign. Do not include the leading slash or dot. Those are automatically included. " +
|
||||
"You can also include a description of the arguments after the name but before the equals-sign " +
|
||||
"to include a helpful reminder when using tab-completion with the command.<br>" +
|
||||
"<strong>Example:</strong> <code>boop <user>=/timeout {0} 15 Boop!</code><hr>" +
|
||||
|
||||
"<code>{0}</code>, <code>{1}</code>, <code>{2}</code>, etc. will be replaced with any arguments you've supplied. " +
|
||||
"Follow an argument index with a <code>$</code> to also include all remaining arguments.<br>" +
|
||||
|
@ -89,22 +92,35 @@ FFZ.settings_info.command_aliases = {
|
|||
output = [];
|
||||
|
||||
for(var i=0; i < vals.length; i++) {
|
||||
var cmd = vals[i],
|
||||
name,
|
||||
var cmd = vals[i];
|
||||
if ( cmd.charAt(0) === '.' || cmd.charAt(0) === '/' )
|
||||
cmd = cmd.substr(1);
|
||||
|
||||
var name,
|
||||
label,
|
||||
name_match = /^([^=]+)=/.exec(cmd);
|
||||
|
||||
if ( ! cmd || ! cmd.length )
|
||||
continue;
|
||||
|
||||
if ( name_match ) {
|
||||
name = name_match[1].toLowerCase();
|
||||
var ind = name_match[1].indexOf(' ');
|
||||
if ( ind === -1 ) {
|
||||
name = name_match[1].toLowerCase();
|
||||
label = null;
|
||||
} else {
|
||||
name = name_match[1].substr(0,ind).toLowerCase();
|
||||
label = name_match[1].substr(ind).trim();
|
||||
}
|
||||
|
||||
cmd = cmd.substr(name_match[0].length);
|
||||
}
|
||||
|
||||
output.push([name, cmd]);
|
||||
output.push([name, cmd, label]);
|
||||
}
|
||||
|
||||
f.settings.set("command_aliases", output);
|
||||
|
||||
}, 600, input);
|
||||
}
|
||||
};
|
||||
|
@ -117,14 +133,18 @@ FFZ.prototype.cache_command_aliases = function() {
|
|||
for(var i=0; i < this.settings.command_aliases.length; i++) {
|
||||
var pair = this.settings.command_aliases[i],
|
||||
name = pair[0],
|
||||
command = pair[1];
|
||||
command = pair[1],
|
||||
label = pair[2];
|
||||
|
||||
// Skip taken/invalid names.
|
||||
if ( ! name || ! name.length || aliases[name] || KNOWN_COMMANDS.indexOf(name) !== -1 )
|
||||
continue;
|
||||
|
||||
aliases[name] = command;
|
||||
aliases[name] = [command, label];
|
||||
}
|
||||
|
||||
if ( this._inputv )
|
||||
Ember.propertyDidChange(this._inputv, 'ffz_commands');
|
||||
}
|
||||
|
||||
|
||||
|
@ -243,6 +263,9 @@ FFZ.chat_commands.card = function(room, args) {
|
|||
});
|
||||
}
|
||||
|
||||
FFZ.chat_commands.card.label = '/card <user>';
|
||||
FFZ.chat_commands.card.info = 'Open Moderation Card';
|
||||
|
||||
|
||||
FFZ.chat_commands.rules = function(room, args) {
|
||||
var f = this,
|
||||
|
@ -258,6 +281,8 @@ FFZ.chat_commands.rules = function(room, args) {
|
|||
});
|
||||
}
|
||||
|
||||
FFZ.chat_commands.rules.info = 'Show Chat Room Rules';
|
||||
|
||||
|
||||
FFZ.chat_commands.open_link = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
|
@ -267,6 +292,9 @@ FFZ.chat_commands.open_link = function(room, args) {
|
|||
wnd.opener = null;
|
||||
}
|
||||
|
||||
FFZ.chat_commands.open_link.label = '/open_link <url>';
|
||||
FFZ.chat_commands.open_link.info = 'Open URL in Tab';
|
||||
|
||||
|
||||
FFZ.chat_commands.fetch_link = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
|
@ -318,6 +346,8 @@ FFZ.chat_commands.fetch_link = function(room, args) {
|
|||
});
|
||||
}
|
||||
|
||||
FFZ.chat_commands.fetch_link.label = '/fetch_link <url> <i>[template]</i>';
|
||||
FFZ.chat_commands.fetch_link.info = 'Fetch URL and Display in Chat';
|
||||
|
||||
|
||||
// -----------------
|
||||
|
|
|
@ -4,9 +4,90 @@ var FFZ = window.FrankerFaceZ,
|
|||
|
||||
is_android = navigator.userAgent.indexOf('Android') !== -1,
|
||||
|
||||
MOD_COMMANDS = {
|
||||
ban: {
|
||||
label: '/ban <user> <i>[reason]</i>',
|
||||
info: 'Permanently Ban User'
|
||||
},
|
||||
unban: {
|
||||
label: '/unban <user>',
|
||||
info: 'Unban User'
|
||||
},
|
||||
timeout: {
|
||||
label: '/timeout <user> <i>[duration=600] [reason]</i>',
|
||||
info: 'Temporarily Ban User'
|
||||
},
|
||||
|
||||
clear: {info: 'Clear Chat for All Users'},
|
||||
slow: {
|
||||
label: '/slow <i>[duration=120]</i>',
|
||||
info: 'Enable Slow Mode'
|
||||
},
|
||||
slowoff: {info: 'Disable Slow Mode'},
|
||||
|
||||
r9kbeta: {info: 'Enable R9k Mode'},
|
||||
r9kbetaoff: {info: 'Disable R9k Mode'},
|
||||
|
||||
subscribers: {info: 'Enable Subscribers-Only Mode'},
|
||||
subscribersoff: {info: 'Disable Subscribers-Only Mode'},
|
||||
|
||||
emotesonly: {info: 'Enable Emotes-Only Mode'},
|
||||
emotesonlyoff: {info: 'Disable Emotes-Only Mode'},
|
||||
},
|
||||
|
||||
BROADCASTER_COMMANDS = {
|
||||
mod: {
|
||||
label: '/mod <user>',
|
||||
info: 'Make User a Moderator'
|
||||
},
|
||||
unmod: {
|
||||
label: '/unmod <user>',
|
||||
info: 'Remove User\'s Moderator Status'
|
||||
},
|
||||
|
||||
host: {
|
||||
label: '/host <channel>',
|
||||
info: 'Enter Host Mode with Channel'
|
||||
},
|
||||
|
||||
unhost: {info: 'Exit Host Mode'},
|
||||
|
||||
commercial: {
|
||||
label: '/commercial <i>[length]</i>',
|
||||
info: 'Trigger Commercial(s) for Length'
|
||||
}
|
||||
},
|
||||
|
||||
DEFAULT_COMMANDS = {
|
||||
color: {
|
||||
label: '/color <color>',
|
||||
info: 'Set Username Color'
|
||||
},
|
||||
|
||||
help: {
|
||||
label: '/help <i>[command]</i>',
|
||||
info: 'List Available Chat Commands'
|
||||
},
|
||||
|
||||
me: {
|
||||
label: '/me <message>',
|
||||
info: 'Send a Colored Chat "Action"'
|
||||
},
|
||||
|
||||
w: {
|
||||
label: '/w <user> <message>',
|
||||
info: 'Whisper to User'
|
||||
},
|
||||
|
||||
disconnect: {info: 'Disconnect from Chat'},
|
||||
mods: {info: 'List Chat Moderators'},
|
||||
},
|
||||
|
||||
CHARCODES = {
|
||||
AT_SIGN: 64,
|
||||
COLON: 58
|
||||
COLON: 58,
|
||||
PERIOD: 46,
|
||||
SLASH: 47
|
||||
},
|
||||
|
||||
KEYCODES = {
|
||||
|
@ -117,6 +198,23 @@ FFZ.settings_info.input_complete_emotes = {
|
|||
}
|
||||
|
||||
|
||||
FFZ.settings_info.input_complete_commands = {
|
||||
type: "boolean",
|
||||
value: true,
|
||||
|
||||
category: "Chat Input",
|
||||
no_bttv: true,
|
||||
|
||||
name: "Tab-Complete Commands",
|
||||
help: "Use tab completion to complete commands in chat.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this._inputv )
|
||||
Ember.propertyDidChange(this._inputv, 'ffz_commands');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FFZ.settings_info.input_complete_aliases = {
|
||||
type: "select",
|
||||
options: {
|
||||
|
@ -548,10 +646,94 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
var area = t.get('chatTextArea');
|
||||
move_selection(area, prefix.length);
|
||||
area.focus();
|
||||
|
||||
var text = t.get('textareaValue'),
|
||||
ind = text.indexOf(' '),
|
||||
start = ind !== -1 && text.substr(0, ind);
|
||||
|
||||
if ( (prefix.length-1) === ind && f.settings.input_complete_commands && (start.charAt(0) === '/' || start.charAt(0) === '.') ) {
|
||||
var commands = t.get('ffz_commands'),
|
||||
cmd = commands[start.substr(1)];
|
||||
|
||||
if ( cmd && cmd.label && cmd.label.split(' ',2)[1] === '<user>' ) {
|
||||
t.ffzFetchNameSuggestions();
|
||||
t.set("ffz_suggestions_visible", true);
|
||||
t.ffzSetPartialWord();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
ffz_commands: function() {
|
||||
var commands = _.extend({}, DEFAULT_COMMANDS),
|
||||
in_conversation = ConvoInput && this.parentView instanceof ConvoInput,
|
||||
room = this.get('parentView.context.model'),
|
||||
is_moderator = room && room.get('isModeratorOrHigher'),
|
||||
user = f.get_user(),
|
||||
is_broadcaster = room && user && user.login === room.get('name');
|
||||
|
||||
if ( in_conversation )
|
||||
return {};
|
||||
|
||||
if ( is_moderator )
|
||||
commands = _.extend(commands, MOD_COMMANDS);
|
||||
|
||||
if ( is_broadcaster)
|
||||
commands = _.extend(commands, BROADCASTER_COMMANDS);
|
||||
|
||||
// FFZ Commands
|
||||
|
||||
for(var cmd in FFZ.chat_commands) {
|
||||
var data = FFZ.chat_commands[cmd];
|
||||
if ( commands[cmd] )
|
||||
continue;
|
||||
|
||||
var enabled = data.hasOwnProperty('enabled') ? data.enabled : true;
|
||||
if ( typeof enabled === "function" )
|
||||
try {
|
||||
enabled = data.enabled.call(f, room, [])
|
||||
} catch(err) {
|
||||
f.error('command "' + cmd + '" enabled', err);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
if ( ! enabled )
|
||||
continue;
|
||||
|
||||
commands[cmd] = {
|
||||
label: data.label,
|
||||
info: data.info,
|
||||
alias: false,
|
||||
short: data.short
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Aliases
|
||||
for(var cmd in f._command_aliases) {
|
||||
var data = f._command_aliases[cmd],
|
||||
replacement = data[0],
|
||||
label = data[1];
|
||||
|
||||
if ( ! label ) {
|
||||
var vars = utils.extract_cmd_variables(replacement, true);
|
||||
label = vars.join(' ');
|
||||
} else
|
||||
label = utils.sanitize(label);
|
||||
|
||||
commands[cmd] = {
|
||||
label: '/' + cmd + (label ? ' ' + label : ''),
|
||||
info: replacement,
|
||||
alias: true
|
||||
}
|
||||
}
|
||||
|
||||
return commands;
|
||||
|
||||
}.property('parentView.context.model.isModeratorOrHigher', 'parentView.context.model.name'),
|
||||
|
||||
|
||||
ffz_emoticons: function() {
|
||||
var emotes = {},
|
||||
|
||||
|
@ -653,8 +835,26 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
ffz_suggestions: function() {
|
||||
var output = [],
|
||||
emotes = this.get('ffz_emoticons'),
|
||||
commands = this.get('ffz_commands'),
|
||||
suggestions = this.get('ffz_name_suggestions'); //.mapBy('id').uniq();
|
||||
|
||||
if ( f.settings.input_complete_commands ) {
|
||||
// Include Commands
|
||||
for(var command_name in commands) {
|
||||
var cmd = '/' + command_name,
|
||||
data = commands[command_name];
|
||||
|
||||
output.push({
|
||||
type: "command",
|
||||
match: cmd,
|
||||
alternate_match: command_name.toLowerCase(),
|
||||
content: data.content || cmd,
|
||||
label: data.label || cmd,
|
||||
info: data.alias ? 'Alias: ' + data.info : (data.short ? 'Short ' : '') + 'Command' + (data.info ? ': ' + data.info : '')
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ( f.settings.input_complete_emotes ) {
|
||||
// Include Emoticons
|
||||
for(var emote_name in emotes) {
|
||||
|
@ -794,12 +994,14 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
}.property('ffz_emoticons', 'ffz_name_suggestions'),
|
||||
|
||||
|
||||
ffz_filtered_suggestions: Ember.computed("ffz_suggestions", "ffz_partial_word", function() {
|
||||
ffz_filtered_suggestions: Ember.computed("ffz_suggestions", "ffz_partial_word", "ffz_partial_word_start", function() {
|
||||
var suggestions = this.get('ffz_suggestions'),
|
||||
partial = this.get('ffz_partial_word'),
|
||||
word_start = this.get('ffz_partial_word_start'),
|
||||
part2 = partial.substr(1),
|
||||
char = partial.charAt(0),
|
||||
is_at = char === '@';
|
||||
is_at = char === '@',
|
||||
is_command = char === '.' || char === '/';
|
||||
|
||||
return suggestions.filter(function(item) {
|
||||
var name = item.match || item.content || item.label,
|
||||
|
@ -808,6 +1010,16 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
if ( ! name )
|
||||
return false;
|
||||
|
||||
if ( type === 'command' ) {
|
||||
if ( word_start > 0 )
|
||||
return false;
|
||||
|
||||
if ( is_command )
|
||||
return item.alternate_match.indexOf(part2.toLowerCase()) === 0;
|
||||
|
||||
return name.toLowerCase().indexOf(partial.toLowerCase()) === 0;
|
||||
}
|
||||
|
||||
if ( type === 'user' ) {
|
||||
// Names are case insensitive, and we have to ignore the leading @ of our
|
||||
// partial word when matching.
|
||||
|
@ -946,6 +1158,19 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
|
||||
break;
|
||||
|
||||
case CHARCODES.PERIOD:
|
||||
case CHARCODES.SLASH:
|
||||
// If we get a command, show the menu, but only if we're at the start of a line.
|
||||
if ( ! this.get('ffz_suggestions_visible') && f.settings.input_complete_commands && !(ConvoInput && this.parentView instanceof ConvoInput) ) {
|
||||
var ind = selection_start(this.get('chatTextArea')) - 1;
|
||||
Ember.run.next(function() {
|
||||
if ( ind === -1 )
|
||||
t.ffzShowSuggestions();
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHARCODES.COLON:
|
||||
if ( f.settings.input_emoji ) {
|
||||
var textarea = this.get('chatTextArea'),
|
||||
|
@ -1139,10 +1364,15 @@ FFZ.prototype.modify_chat_input = function(component) {
|
|||
});
|
||||
}
|
||||
|
||||
} else if ( start === '/w' || start === '/ignore' || start === '/unignore' || start === '/mod' || start === '/unmod' || start === '/ban' || start === '/unban' || start === '/timeout' || start === '/purge' ) {
|
||||
t.ffzFetchNameSuggestions();
|
||||
t.set("ffz_suggestions_visible", true);
|
||||
t.ffzSetPartialWord();
|
||||
} else if ( f.settings.input_complete_commands && (start.charAt(0) === '/' || start.charAt(0) === '.') ) {
|
||||
var commands = t.get('ffz_commands'),
|
||||
cmd = commands[start.substr(1)];
|
||||
|
||||
if ( cmd && cmd.label && cmd.label.split(' ',2)[1] === '<user>' ) {
|
||||
t.ffzFetchNameSuggestions();
|
||||
t.set("ffz_suggestions_visible", true);
|
||||
t.ffzSetPartialWord();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1401,6 +1401,8 @@ FFZ.chat_commands.join = function(room, args) {
|
|||
}
|
||||
|
||||
FFZ.chat_commands.join.no_bttv = true;
|
||||
FFZ.chat_commands.join.label = '/join <channel>';
|
||||
FFZ.chat_commands.join.info = 'Add Channel to Pinned Rooms';
|
||||
|
||||
|
||||
FFZ.chat_commands.part = function(room, args) {
|
||||
|
@ -1422,4 +1424,6 @@ FFZ.chat_commands.part = function(room, args) {
|
|||
return "You are not in " + room_id + ".";
|
||||
}
|
||||
|
||||
FFZ.chat_commands.part.no_bttv = true;
|
||||
FFZ.chat_commands.part.no_bttv = true;
|
||||
FFZ.chat_commands.part.label = '/part <channel>';
|
||||
FFZ.chat_commands.part.info = 'Remove Channel from Pinned Rooms';
|
|
@ -222,7 +222,7 @@ FFZ.prototype.setup_layout = function() {
|
|||
height = size[1],
|
||||
host_height = size[2];
|
||||
|
||||
return "<style>body[data-current-path^=\"user.channel.\"] .app-main:not(.theatre) #player,.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,body[data-current-path^=\"user.channel.\"] .app-main:not(.theatre) .cn-hosted #player, .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>";
|
||||
return "<style>.ffz-small-player:not(.ffz-bttv)[data-current-path^=\"user.channel.\"] .app-main:not(.theatre) #player,.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,.ffz-small-player:not(.ffz-bttv)[data-current-path^=\"user.channel.\"] .app-main:not(.theatre) .cn-hosted #player, .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() {
|
||||
|
|
|
@ -712,6 +712,8 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
|
|||
return [{type: 'text', text: 'hi'}];
|
||||
}.property('msgObject.message'),*/
|
||||
|
||||
ffz_modified: true,
|
||||
|
||||
ffzTokenizedMessage: function() {
|
||||
try {
|
||||
return f.tokenize_chat_line(this.get('msgObject'));
|
||||
|
|
|
@ -1567,7 +1567,7 @@ FFZ.prototype._update_alias = function(user) {
|
|||
|
||||
FFZ.chat_commands.purge = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Purge Usage: /p username [ban reason]";
|
||||
return "Usage: /purge <user> [ban reason]";
|
||||
|
||||
var name = args.shift(),
|
||||
reason = args.length ? args.join(" ") : "";
|
||||
|
@ -1575,25 +1575,34 @@ FFZ.chat_commands.purge = function(room, args) {
|
|||
room.room.send("/timeout " + name + " 1 " + reason, true);
|
||||
}
|
||||
|
||||
FFZ.chat_commands.purge.label = '/purge <user> <i>[reason]</i>';
|
||||
FFZ.chat_commands.purge.info = 'Ban User for 1 Second';
|
||||
|
||||
FFZ.chat_commands.p = function(room, args) {
|
||||
return FFZ.chat_commands.purge.call(this, room, args);
|
||||
}
|
||||
|
||||
FFZ.chat_commands.p.enabled = function() { return this.settings.short_commands; }
|
||||
FFZ.chat_commands.p.short = true;
|
||||
FFZ.chat_commands.p.label = '/p <user> <i>[reason]</i>';
|
||||
FFZ.chat_commands.p.info = 'Ban User for 1 Second';
|
||||
|
||||
|
||||
FFZ.chat_commands.t = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Timeout Usage: /t username [duration] [ban reason]";
|
||||
return "Usage: /t <user> [duration=600] [reason]";
|
||||
room.room.send("/timeout " + args.join(" "), true);
|
||||
}
|
||||
|
||||
FFZ.chat_commands.t.enabled = function() { return this.settings.short_commands; }
|
||||
FFZ.chat_commands.t.short = true;
|
||||
FFZ.chat_commands.t.label = '/t <user> <i>[duration=600] [reason]</i>';
|
||||
FFZ.chat_commands.t.info = 'Temporarily Ban User';
|
||||
|
||||
|
||||
FFZ.chat_commands.b = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Ban Usage: /b username [ban reason]";
|
||||
return "Usage: /b <user> [reason]";
|
||||
|
||||
var name = args.shift(),
|
||||
reason = args.length ? args.join(" ") : "";
|
||||
|
@ -1602,11 +1611,14 @@ FFZ.chat_commands.b = function(room, args) {
|
|||
}
|
||||
|
||||
FFZ.chat_commands.b.enabled = function() { return this.settings.short_commands; }
|
||||
FFZ.chat_commands.b.short = true;
|
||||
FFZ.chat_commands.b.label = '/b <user> <i>[reason]</i>';
|
||||
FFZ.chat_commands.b.info = 'Permanently Ban User';
|
||||
|
||||
|
||||
FFZ.chat_commands.u = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Unban Usage: /u username [more usernames separated by spaces]";
|
||||
return "Usage: /u <user> [more usernames separated by spaces]";
|
||||
|
||||
if ( args.length > 10 )
|
||||
return "Please only unban up to 10 users at once.";
|
||||
|
@ -1618,4 +1630,7 @@ FFZ.chat_commands.u = function(room, args) {
|
|||
}
|
||||
}
|
||||
|
||||
FFZ.chat_commands.u.enabled = function() { return this.settings.short_commands; }
|
||||
FFZ.chat_commands.u.enabled = function() { return this.settings.short_commands; }
|
||||
FFZ.chat_commands.u.short = true;
|
||||
FFZ.chat_commands.u.label = '/u <user> <i>[<user> ...]';
|
||||
FFZ.chat_commands.u.info = 'Unban User(s)';
|
|
@ -727,7 +727,7 @@ FFZ.prototype.run_command = function(text, room_id) {
|
|||
try {
|
||||
val = command.enabled.call(this, room, args);
|
||||
} catch(err) {
|
||||
this.error('command "' + cmd + '" enabled: ' + err);
|
||||
this.error('command "' + cmd + '" enabled', err);
|
||||
val = false;
|
||||
}
|
||||
}
|
||||
|
@ -2147,7 +2147,7 @@ FFZ.prototype._modify_room = function(room) {
|
|||
was_handled = true;
|
||||
|
||||
} else {
|
||||
var alias = f._command_aliases[cmd],
|
||||
var alias = f._command_aliases[cmd][0],
|
||||
args = text.substr(1 + cmd.length).trimLeft().split(/\s+/g),
|
||||
output = utils.replace_cmd_variables(alias, null, this, null, args);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ FFZ.prototype.setup_ember_wrapper = function() {
|
|||
}
|
||||
|
||||
|
||||
FFZ.prototype.update_views = function(klass, modifier, if_not_exists, immediate) {
|
||||
FFZ.prototype.update_views = function(klass, modifier, if_not_exists, immediate, no_modify_existing) {
|
||||
var original_klass;
|
||||
if ( typeof klass === 'string' ) {
|
||||
original_klass = klass;
|
||||
|
@ -33,10 +33,10 @@ FFZ.prototype.update_views = function(klass, modifier, if_not_exists, immediate)
|
|||
} else
|
||||
original_klass = klass.toString();
|
||||
|
||||
if ( this._ember_finalized || immediate )
|
||||
this._update_views([[original_klass, klass, modifier]]);
|
||||
if ( this._ember_finalized || immediate || ! this._views_to_update )
|
||||
this._update_views([[original_klass, klass, modifier, no_modify_existing || false]]);
|
||||
else
|
||||
this._views_to_update.push([original_klass, klass, modifier]);
|
||||
this._views_to_update.push([original_klass, klass, modifier, no_modify_existing || false]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -79,10 +79,12 @@ FFZ.prototype._update_views = function(klasses) {
|
|||
updated_instances++;
|
||||
|
||||
try {
|
||||
if ( ! view.ffz_modified )
|
||||
if ( ! view.ffz_modified && ! klasses[i][3] )
|
||||
klasses[i][2].call(this, view);
|
||||
|
||||
(view.ffz_update || view.ffz_init).call(view);
|
||||
var func = view.ffz_update || view.ffz_init;
|
||||
if ( func )
|
||||
func.call(view);
|
||||
|
||||
} catch(err) {
|
||||
this.error("An error occured when updating an existing Ember instance of: " + klasses[i][0], err);
|
||||
|
|
|
@ -34,7 +34,7 @@ FFZ.msg_commands = {};
|
|||
|
||||
// Version
|
||||
var VER = FFZ.version_info = {
|
||||
major: 3, minor: 5, revision: 323,
|
||||
major: 3, minor: 5, revision: 325,
|
||||
toString: function() {
|
||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||
}
|
||||
|
@ -335,6 +335,7 @@ FFZ.prototype.init_normal = function(delay, no_socket) {
|
|||
|
||||
// Initialize all the modules.
|
||||
this.load_settings();
|
||||
this.setup_ember_wrapper();
|
||||
|
||||
// Start this early, for quick loading.
|
||||
this.setup_dark();
|
||||
|
@ -357,6 +358,7 @@ FFZ.prototype.init_normal = function(delay, no_socket) {
|
|||
this.setup_following_count(false);
|
||||
this.setup_menu();
|
||||
|
||||
this.finalize_ember_wrapper();
|
||||
this.setup_message_event();
|
||||
this.fix_tooltips();
|
||||
this.find_bttv(10);
|
||||
|
@ -384,6 +386,7 @@ FFZ.prototype.init_dashboard = function(delay) {
|
|||
|
||||
// Initialize all the modules.
|
||||
this.load_settings();
|
||||
this.setup_ember_wrapper();
|
||||
|
||||
// Start this early, for quick loading.
|
||||
this.setup_dark();
|
||||
|
@ -406,6 +409,8 @@ FFZ.prototype.init_dashboard = function(delay) {
|
|||
this.setup_dash_stats();
|
||||
this.setup_dash_feed();
|
||||
|
||||
this.finalize_ember_wrapper();
|
||||
|
||||
this._update_subscribers();
|
||||
|
||||
// Set up the FFZ message passer.
|
||||
|
|
13
src/utils.js
13
src/utils.js
|
@ -554,6 +554,19 @@ module.exports = FFZ.utils = {
|
|||
|
||||
CMD_VAR_REGEX: CMD_VAR_REGEX,
|
||||
|
||||
extract_cmd_variables: function(command, args_only) {
|
||||
var matches = [];
|
||||
|
||||
CMD_VAR_REGEX.lastIndex = 0;
|
||||
command.replace(CMD_VAR_REGEX, function(match, variable) {
|
||||
if ( args_only && ! /\d+(?:$\d*)?/.test(variable) )
|
||||
return;
|
||||
matches.push('{' + variable + '}');
|
||||
});
|
||||
|
||||
return _.unique(matches);
|
||||
},
|
||||
|
||||
replace_cmd_variables: function(command, user, room, message, args) {
|
||||
user = user || {};
|
||||
room = room || {};
|
||||
|
|
|
@ -311,7 +311,7 @@ body.ffz-bttv-dark .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path { fill:
|
|||
width: auto;
|
||||
|
||||
z-index: 7;
|
||||
padding: 10px;
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.ffz-theater-stats .app-main.theatre .cn-metabar__more {
|
||||
|
@ -3534,6 +3534,13 @@ body.ffz-bttv #ffz-feed-tabs .tabs { margin-bottom: 0 }
|
|||
padding-top: 80px;
|
||||
}
|
||||
|
||||
.ffz-channel-title-top .cn-metabar__more,
|
||||
.app-main.theatre .cn-metabar__more {
|
||||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
.ffz-hide-channel-banner .cn-cover { height: 0 !important }
|
||||
.ffz-minimal-channel-title.ffz-channel-title-top #channel { padding-top: 50px }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue