mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-30 08:08:32 +00:00
3.5.22 to 3.5.30. I need to commit more. Added basic setting for Stream Uptime, made Uptime seconds configurable. Tooltip for Stream Latency includes resolution. Added Stream Uptime to the directory. Added Reset Settings button. Added customizable in-line moderation icons. Added option to show channel logos in the directory. Added option to swap columns on the dashboard. Split Minimalistic Chat into two configurable sub-options.
This commit is contained in:
parent
4072f3c82a
commit
f62132cc7e
22 changed files with 1067 additions and 306 deletions
27
dark.css
27
dark.css
|
@ -161,6 +161,7 @@
|
|||
.ffz-dark .ember-chat .chat-interface .ffz-ui-popup.emoticon-selector .emoticon-selector-box,
|
||||
.ffz-dark .card,
|
||||
.ffz-dark #flyout .content,
|
||||
.ffz-dark .whatisthis,
|
||||
.ffz-dark .ui-menu,
|
||||
.ffz-dark .dropmenu,
|
||||
.ffz-dark .top-dropdown,
|
||||
|
@ -782,10 +783,17 @@
|
|||
}
|
||||
|
||||
.ffz-dark .whatisthis {
|
||||
background-color: #333;
|
||||
box-shadow: 0 0 0 1px rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.ffz-dark .whatisthis:before {
|
||||
border-top-color: #101010;
|
||||
}
|
||||
|
||||
.ffz-dark .whatisthis:after {
|
||||
border-top-color: #32323e;
|
||||
}
|
||||
|
||||
.ffz-dark #chart_container svg rect[fill="#FFFFFF"] {
|
||||
fill: rgb(32,32,32) !important;
|
||||
}
|
||||
|
@ -843,6 +851,7 @@
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ffz-dark .whatisthis .actions .divider,
|
||||
.ffz-dark .dash-chat-column {
|
||||
border-color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
@ -895,3 +904,19 @@
|
|||
filter: invert(100%);
|
||||
-webkit-filter: invert(100%);
|
||||
}
|
||||
|
||||
/* Playlist */
|
||||
|
||||
.ffz-dark .ember-chat .chat-header {
|
||||
box-shadow: inset 0 -1px 0 0 rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.ffz-dark .playlist-controller,
|
||||
.ffz-dark .playlist-item {
|
||||
border-color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.ffz-dark .playlist-container:not(.playlist-enabled) .playlist-item:hover,
|
||||
.ffz-dark .playlist-container:not(.playlist-enabled) .ui-sortable-helper {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
html,body{overflow:hidden; margin:0; padding:0; background:transparent; height: 100%; position: relative }
|
||||
img {
|
||||
max-width: 186px; max-height: 186px;
|
||||
position: absolute;
|
||||
top: 50%; left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">window.onload=function(){
|
||||
var IMGUR_REGEX = /(?:https?:\/\/)?(?:i\.)?imgur\.com\/(?:gallery\/)?([A-Za-z0-9]+)(?:\.(.*))?/,
|
||||
GYAZO_REGEX = /(?:https?:\/\/)?(?:i\.)?gyazo\.com\/([a-z0-9]+)/,
|
||||
YOUTUBE_REGEX = /^(?:https?:\/\/)?(?:m\.|www\.)?youtu(?:be\.com|\.be)\/(?:v\/|watch\/|.*?(?:embed|watch).*?v=)?([a-zA-Z0-9\-_]+)$/;
|
||||
|
||||
var url = location.search.substr(1),
|
||||
image_url = url;
|
||||
imgur = url.match(IMGUR_REGEX);
|
||||
|
||||
if ( imgur )
|
||||
image_url = 'http://i.imgur.com/' + imgur[1] + 't.' + (imgur[2] || "png");
|
||||
|
||||
else {
|
||||
var yt = url.match(YOUTUBE_REGEX);
|
||||
if ( yt ) {
|
||||
image_url = 'http://img.youtube.com/vi/' + yt[1] + '/1.jpg'
|
||||
} else {
|
||||
var gyazo = url.match(GYAZO_REGEX);
|
||||
if ( gyazo )
|
||||
image_url = 'http://i.gyazo.com/' + gyazo[1] + '.png';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var el = document.createElement('img');
|
||||
el.src = image_url;
|
||||
document.body.appendChild(el);
|
||||
}</script>
|
|
@ -431,7 +431,7 @@ FFZ.prototype._legacy_add_donors = function() {
|
|||
}
|
||||
|
||||
FFZ.prototype._legacy_load_bots = function(tries) {
|
||||
jQuery.ajax(constants.SERVER + "script/bots.txt", {cache: false, context: this})
|
||||
jQuery.ajax(constants.SERVER + "script/bots.txt", {context: this})
|
||||
.done(function(data) {
|
||||
this._legacy_parse_badges(data, 0, 2, "Bot (By: {})");
|
||||
|
||||
|
@ -446,7 +446,7 @@ FFZ.prototype._legacy_load_bots = function(tries) {
|
|||
}
|
||||
|
||||
FFZ.prototype._legacy_load_donors = function(tries) {
|
||||
jQuery.ajax(constants.SERVER + "script/donors.txt", {cache: false, context: this})
|
||||
jQuery.ajax(constants.SERVER + "script/donors.txt", {context: this})
|
||||
.done(function(data) {
|
||||
this._legacy_parse_badges(data, 1, 1);
|
||||
|
||||
|
|
|
@ -361,9 +361,9 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
|
||||
controller.set('ffz_host_updating', true);
|
||||
if ( now_hosting === target )
|
||||
room.send("/unhost");
|
||||
room.send("/unhost", true);
|
||||
else
|
||||
room.send("/host " + target);
|
||||
room.send("/host " + target, true);
|
||||
},
|
||||
|
||||
|
||||
|
@ -480,8 +480,25 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
container.appendChild(stat_el);
|
||||
}
|
||||
|
||||
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
||||
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
||||
var delay = parseFloat(stats.hlsLatencyBroadcaster);
|
||||
|
||||
if ( delay > 180 ) {
|
||||
delay = Math.floor(delay);
|
||||
stat_el.setAttribute('original-title', 'Video Information\nBroadcast ' + utils.time_to_string(delay, true) + ' Ago\n\nVideo: ' + stats.videoResolution + 'p @ ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps')
|
||||
el.textContent = utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old';
|
||||
} else {
|
||||
stat_el.setAttribute('original-title', 'Stream Latency\nVideo: ' + stats.videoResolution + 'p @ ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps');
|
||||
|
||||
delay = stats.hlsLatencyBroadcaster;
|
||||
var pos = delay.lastIndexOf('.');
|
||||
|
||||
if ( pos === -1 )
|
||||
delay = delay + '.00';
|
||||
else if ( delay.length - pos < 3 )
|
||||
delay = delay + '0';
|
||||
|
||||
el.textContent = delay + 's';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -516,8 +533,25 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
container.appendChild(stat_el);
|
||||
}
|
||||
|
||||
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
||||
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
||||
var delay = parseFloat(stats.hlsLatencyBroadcaster);
|
||||
|
||||
if ( delay > 180 ) {
|
||||
delay = Math.floor(delay);
|
||||
stat_el.setAttribute('original-title', 'Video Information\nBroadcast ' + utils.time_to_string(delay, true) + ' Ago\n\nVideo: ' + stats.videoResolution + 'p @ ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps')
|
||||
el.textContent = utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old';
|
||||
} else {
|
||||
stat_el.setAttribute('original-title', 'Stream Latency\nVideo: ' + stats.videoResolution + 'p @ ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps');
|
||||
|
||||
delay = stats.hlsLatencyBroadcaster;
|
||||
var pos = delay.lastIndexOf('.');
|
||||
|
||||
if ( pos === -1 )
|
||||
delay = delay + '.00';
|
||||
else if ( delay.length - pos < 3 )
|
||||
delay = delay + '0';
|
||||
|
||||
el.textContent = delay + 's';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -581,7 +615,7 @@ FFZ.prototype._modify_cindex = function(view) {
|
|||
jQuery(stat).tipsy({html: true});
|
||||
}
|
||||
|
||||
el.innerHTML = utils.time_to_string(uptime);
|
||||
el.innerHTML = utils.time_to_string(uptime, false, false, false, f.settings.stream_uptime === 1 || f.settings.stream_uptime === 3);
|
||||
},
|
||||
|
||||
ffzTeardown: function() {
|
||||
|
@ -698,10 +732,27 @@ FFZ.settings_info.stream_host_button = {
|
|||
|
||||
|
||||
FFZ.settings_info.stream_uptime = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
no_mobile: true,
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
1: "Enabled",
|
||||
2: "Enabled (with Seconds)",
|
||||
3: "Enabled (Channel Only)",
|
||||
4: "Enabled (Channel Only with Seconds)"
|
||||
},
|
||||
|
||||
value: 1,
|
||||
process_value: function(val) {
|
||||
if ( val === false )
|
||||
return 0;
|
||||
if ( val === true )
|
||||
return 2;
|
||||
if ( typeof val === "string" )
|
||||
return parseInt(val || "0") || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
no_mobile: true,
|
||||
category: "Channel Metadata",
|
||||
name: "Stream Uptime",
|
||||
help: 'Display the stream uptime under a channel by the viewer count.',
|
||||
|
@ -726,3 +777,30 @@ FFZ.settings_info.stream_title = {
|
|||
this._cindex.ffzFixTitle();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.basic_settings.channel_info = {
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
1: "Enabled",
|
||||
2: "Enabled (with Seconds)",
|
||||
3: "Enabled (Channel Only)",
|
||||
4: "Enabled (Channel Only with Seconds)"
|
||||
},
|
||||
|
||||
category: "General",
|
||||
name: "Stream Uptime",
|
||||
help: "Display the current stream's uptime under the player.",
|
||||
|
||||
get: function() {
|
||||
return this.settings.stream_uptime;
|
||||
},
|
||||
|
||||
set: function(val) {
|
||||
if ( typeof val === 'string' )
|
||||
val = parseInt(val || "0");
|
||||
|
||||
this.settings.set('stream_uptime', val);
|
||||
}
|
||||
}
|
|
@ -177,7 +177,7 @@ FFZ.prototype._modify_chat_input = function(component) {
|
|||
// Input Control
|
||||
|
||||
ffzOnInput: function() {
|
||||
if ( ! f._chat_style || ! f.settings.minimal_chat || is_android )
|
||||
if ( ! f._chat_style || f.settings.minimal_chat < 2 || is_android )
|
||||
return;
|
||||
|
||||
var now = Date.now(),
|
||||
|
@ -194,17 +194,17 @@ FFZ.prototype._modify_chat_input = function(component) {
|
|||
var el = this.get('element'),
|
||||
t = el && el.querySelector('textarea');
|
||||
|
||||
if ( ! t || ! f._chat_style || ! f.settings.minimal_chat )
|
||||
if ( ! t || ! f._chat_style || f.settings.minimal_chat < 2 )
|
||||
return;
|
||||
|
||||
// Unfortunately, we need to change this with CSS.
|
||||
this._ffz_minimal_style.innerHTML = 'body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain textarea { height: auto !important; }';
|
||||
this._ffz_minimal_style.innerHTML = 'body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textarea { height: auto !important; }';
|
||||
var height = Math.max(32, Math.min(128, t.scrollHeight));
|
||||
this._ffz_minimal_style.innerHTML = 'body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain textarea { height: ' + height + 'px !important; }';
|
||||
this._ffz_minimal_style.innerHTML = 'body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textarea { height: ' + height + 'px !important; }';
|
||||
|
||||
if ( height !== this._ffz_last_height ) {
|
||||
utils.update_css(f._chat_style, "input_height", 'body.ffz-minimal-chat .ember-chat .chat-interface { height: ' + height + 'px !important; }' +
|
||||
'body.ffz-minimal-chat .ember-chat .chat-messages, body.ffz-minimal-chat .ember-chat .chat-interface .emoticon-selector { bottom: ' + height + 'px !important; }');
|
||||
utils.update_css(f._chat_style, "input_height", 'body.ffz-minimal-chat-input .ember-chat .chat-interface { height: ' + height + 'px !important; }' +
|
||||
'body.ffz-minimal-chat-input .ember-chat .chat-messages, body.ffz-minimal-chat-input .ember-chat .chat-interface .emoticon-selector { bottom: ' + height + 'px !important; }');
|
||||
f._roomv && f._roomv.get('stuckToBottom') && f._roomv._scrollToBottom();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,16 +40,35 @@ FFZ.basic_settings.delayed_chat = {
|
|||
|
||||
|
||||
FFZ.settings_info.minimal_chat = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
1: "No Heading",
|
||||
2: "Minimalistic Input",
|
||||
3: "All"
|
||||
},
|
||||
|
||||
value: 0,
|
||||
|
||||
category: "Chat Appearance",
|
||||
|
||||
name: "Minimalistic Chat",
|
||||
help: "Hide all of the chat user interface, only showing messages and an input box.",
|
||||
|
||||
process_value: function(val) {
|
||||
if ( val === false )
|
||||
return 0;
|
||||
else if ( val === true )
|
||||
return 3;
|
||||
else if ( typeof val === "string" )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
on_update: function(val) {
|
||||
document.body.classList.toggle("ffz-minimal-chat", val);
|
||||
document.body.classList.toggle("ffz-minimal-chat-head", val === 1 || val === 3);
|
||||
document.body.classList.toggle("ffz-minimal-chat-input", val > 1);
|
||||
|
||||
if ( this.settings.group_tabs && this._chatv && this._chatv._ffz_tabs ) {
|
||||
var f = this;
|
||||
setTimeout(function() {
|
||||
|
@ -58,11 +77,11 @@ FFZ.settings_info.minimal_chat = {
|
|||
},0);
|
||||
}
|
||||
|
||||
if ( this._chatv && this._chatv.get('controller.showList') )
|
||||
if ( (val === 1 || val === 3) && this._chatv && this._chatv.get('controller.showList') )
|
||||
this._chatv.set('controller.showList', false);
|
||||
|
||||
// Remove the style if we have it.
|
||||
if ( ! val && this._chat_style ) {
|
||||
if ( ! (val > 1) && this._chat_style ) {
|
||||
if ( this._inputv ) {
|
||||
if ( this._inputv._ffz_minimal_style )
|
||||
this._inputv._ffz_minimal_style.innerHTML = '';
|
||||
|
@ -73,7 +92,7 @@ FFZ.settings_info.minimal_chat = {
|
|||
utils.update_css(this._chat_style, "input_height", '');
|
||||
this._roomv && this._roomv.get('stuckToBottom') && this._roomv._scrollToBottom();
|
||||
|
||||
} else if ( this._inputv )
|
||||
} else if ( val > 1 && this._inputv )
|
||||
this._inputv.ffzResizeInput();
|
||||
}
|
||||
};
|
||||
|
@ -247,7 +266,8 @@ FFZ.settings_info.visible_rooms = {
|
|||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_chatview = function() {
|
||||
document.body.classList.toggle("ffz-minimal-chat", this.settings.minimal_chat);
|
||||
document.body.classList.toggle("ffz-minimal-chat-head", this.settings.minimal_chat === 1 || this.settings.minimal_chat === 3);
|
||||
document.body.classList.toggle("ffz-minimal-chat-input", this.settings.minimal_chat === 2 || this.settings.minimal_chat === 3);
|
||||
|
||||
this.log("Hooking the Ember Chat controller.");
|
||||
|
||||
|
|
191
src/ember/directory.js
Normal file
191
src/ember/directory.js
Normal file
|
@ -0,0 +1,191 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
utils = require('../utils'),
|
||||
constants = require('../constants');
|
||||
|
||||
|
||||
// --------------------
|
||||
// Settings
|
||||
// --------------------
|
||||
|
||||
FFZ.settings_info.directory_logos = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Appearance",
|
||||
no_mobile: true,
|
||||
|
||||
name: "Directory Logos",
|
||||
help: "Display channel logos in the Twitch directory."
|
||||
};
|
||||
|
||||
|
||||
// --------------------
|
||||
// Initialization
|
||||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_directory = function() {
|
||||
this.log("Hooking the Ember Directory View.");
|
||||
|
||||
var ChannelView = App.__container__.resolve('view:channel');
|
||||
if ( ChannelView )
|
||||
this._modify_directory_live(ChannelView);
|
||||
|
||||
var HostView = App.__container__.resolve('view:host');
|
||||
if ( HostView )
|
||||
this._modify_directory_host(HostView);
|
||||
|
||||
var VideoView = App.__container__.resolve('view:video');
|
||||
if ( VideoView )
|
||||
this._modify_directory_video(VideoView);
|
||||
|
||||
// TODO: Process existing views.
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._modify_directory_video = function(dir) {
|
||||
var f = this;
|
||||
dir.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
|
||||
f.log("New Video View", this);
|
||||
window.v = this;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
dir.create().destroy();
|
||||
} catch(err) { }
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._modify_directory_live = function(dir) {
|
||||
var f = this;
|
||||
dir.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
|
||||
var el = this.get('element'),
|
||||
meta = el && el.querySelector('.meta'),
|
||||
thumb = el && el.querySelector('.thumb'),
|
||||
cap = thumb && thumb.querySelector('.cap');
|
||||
|
||||
|
||||
if ( f.settings.stream_uptime && f.settings.stream_uptime < 3 && cap ) {
|
||||
var t_el = this._ffz_uptime = document.createElement('div');
|
||||
t_el.className = 'overlay_info length live';
|
||||
|
||||
jQuery(t_el).tipsy({html: true});
|
||||
|
||||
cap.appendChild(t_el);
|
||||
this._ffz_uptime_timer = setInterval(this.ffzUpdateUptime.bind(this), 1000);
|
||||
this.ffzUpdateUptime();
|
||||
}
|
||||
|
||||
if ( f.settings.directory_logos ) {
|
||||
el.classList.add('ffz-directory-logo');
|
||||
|
||||
var link = document.createElement('a'),
|
||||
logo = document.createElement('img'),
|
||||
t = this,
|
||||
target = this.get('context.model.channel.name');
|
||||
|
||||
logo.className = 'profile-photo';
|
||||
logo.src = this.get('context.model.channel.logo') || "http://static-cdn.jtvnw.net/jtv_user_pictures/xarth/404_user_150x150.png";
|
||||
logo.alt = this.get('context.model.channel.display_name');
|
||||
|
||||
link.href = '/' + target;
|
||||
link.addEventListener('click', function(e) {
|
||||
var Channel = App.__container__.resolve('model:channel');
|
||||
if ( ! Channel )
|
||||
return;
|
||||
|
||||
e.preventDefault();
|
||||
t.get('controller').transitionTo('channel.index', Channel.find({id: target}).load());
|
||||
return false;
|
||||
});
|
||||
|
||||
link.appendChild(logo);
|
||||
meta.insertBefore(link, meta.firstChild);
|
||||
}
|
||||
},
|
||||
|
||||
willClearRender: function() {
|
||||
if ( this._ffz_uptime ) {
|
||||
this._ffz_uptime.parentElement.removeChild(this._ffz_uptime);
|
||||
this._ffz_uptime = null;
|
||||
}
|
||||
|
||||
if ( this._ffz_uptime_timer )
|
||||
clearInterval(this._ffz_uptime_timer);
|
||||
|
||||
this._super();
|
||||
},
|
||||
|
||||
|
||||
ffzUpdateUptime: function() {
|
||||
var raw_created = this.get('context.model.created_at'),
|
||||
up_since = raw_created && utils.parse_date(raw_created),
|
||||
uptime = up_since && Math.floor((Date.now() - up_since.getTime()) / 1000) || 0;
|
||||
|
||||
if ( uptime > 0 ) {
|
||||
this._ffz_uptime.innerHTML = constants.CLOCK + utils.time_to_string(uptime, false, false, false, f.settings.stream_uptime === 1);
|
||||
this._ffz_uptime.setAttribute('original-title', 'Stream Uptime <nobr>(since ' + up_since.toLocaleString() + ')</nobr>');;
|
||||
} else {
|
||||
this._ffz_uptime.setAttribute('original-title', '');
|
||||
this._ffz_uptime.innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
dir.create().destroy();
|
||||
} catch(err) { }
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._modify_directory_host = function(dir) {
|
||||
var f = this;
|
||||
dir.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
|
||||
var el = this.get('element'),
|
||||
meta = el && el.querySelector('.meta'),
|
||||
thumb = el && el.querySelector('.thumb'),
|
||||
cap = thumb && thumb.querySelector('.cap');
|
||||
|
||||
|
||||
if ( f.settings.directory_logos ) {
|
||||
el.classList.add('ffz-directory-logo');
|
||||
|
||||
var link = document.createElement('a'),
|
||||
logo = document.createElement('img'),
|
||||
t = this,
|
||||
target = this.get('context.model.target.channel.name');
|
||||
|
||||
logo.className = 'profile-photo';
|
||||
logo.src = this.get('context.model.target.channel.logo') || "http://static-cdn.jtvnw.net/jtv_user_pictures/xarth/404_user_150x150.png";
|
||||
logo.alt = this.get('context.model.target.channel.display_name');
|
||||
|
||||
link.href = '/' + target;
|
||||
link.addEventListener('click', function(e) {
|
||||
var Channel = App.__container__.resolve('model:channel');
|
||||
if ( ! Channel )
|
||||
return;
|
||||
|
||||
e.preventDefault();
|
||||
t.get('controller').transitionTo('channel.index', Channel.find({id: target}).load());
|
||||
return false;
|
||||
});
|
||||
|
||||
link.appendChild(logo);
|
||||
meta.insertBefore(link, meta.firstChild);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
dir.create().destroy();
|
||||
} catch(err) { }
|
||||
}
|
|
@ -26,6 +26,26 @@ FFZ.settings_info.swap_sidebars = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.flip_dashboard = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Appearance",
|
||||
no_mobile: true,
|
||||
no_bttv: true,
|
||||
|
||||
name: "Swap Dashboard Positions",
|
||||
help: "Swap the positions of the left and right columns of the dashboard.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.body.classList.toggle("ffz-flip-dashboard", val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.right_column_width = {
|
||||
type: "button",
|
||||
value: 340,
|
||||
|
@ -102,6 +122,22 @@ FFZ.prototype.setup_layout = function() {
|
|||
|
||||
}.property("windowWidth", "isRightColumnClosed", "isLeftColumnClosed", "rightColumnWidth"),
|
||||
|
||||
playerStyle: function() {
|
||||
var h = this.get('windowHeight'),
|
||||
c = this.get('PLAYER_CONTROLS_HEIGHT'),
|
||||
r = this.get('contentWidth'),
|
||||
|
||||
i = (9 * r / 16) + c,
|
||||
d = h - 120 - 60,
|
||||
c = h - 94 - 185,
|
||||
|
||||
l = Math.floor(r),
|
||||
o = Math.floor(Math.min(i, d)),
|
||||
s = Math.floor(Math.min(i, c));
|
||||
|
||||
return "<style>.dynamic-player, .dynamic-player object, .dynamic-player video{width:" + l + "px !important;height:" + o + "px !important} .dynamic-target-player,.dynamic-target-player object, .dynamic-target-player video{width:" + l + "px !important;height:" + s + "px !important}</style><style>.dynamic-player .player object{width:100% !important; height:100% !important}</style>";
|
||||
}.property("contentWidth", "windowHeight", "PLAYER_CONTROLS_HEIGHT"),
|
||||
|
||||
/*ffzUpdateWidth: _.throttle(function() {
|
||||
var rc = document.querySelector('#right_close');
|
||||
if ( ! rc )
|
||||
|
|
|
@ -27,25 +27,6 @@ FFZ.settings_info.room_status = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.line_purge_icon = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
no_bttv: true,
|
||||
category: "Chat Moderation",
|
||||
|
||||
name: "Purge Icon in Mod Icons",
|
||||
help: "Display a Purge Icon in chat line Mod Icons for quickly purging users.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
document.body.classList.toggle("ffz-chat-purge-icon", val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.replace_bad_emotes = {
|
||||
type: "boolean",
|
||||
value: true,
|
||||
|
@ -297,18 +278,22 @@ FFZ.settings_info.chat_separators = {
|
|||
options: {
|
||||
0: "Disabled",
|
||||
1: "Basic Line (1px solid)",
|
||||
2: "3D Line (2px groove)"
|
||||
2: "3D Line (2px groove)",
|
||||
3: "3D Line (2px groove inset)",
|
||||
4: "Wide Line (2px solid)"
|
||||
},
|
||||
value: '0',
|
||||
value: 0,
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
||||
process_value: function(val) {
|
||||
if ( val === false )
|
||||
return '0';
|
||||
return 0;
|
||||
else if ( val === true )
|
||||
return '1';
|
||||
return 1;
|
||||
else if ( typeof val === "string" )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
|
@ -316,8 +301,10 @@ FFZ.settings_info.chat_separators = {
|
|||
help: "Display thin lines between chat messages for further visual separation.",
|
||||
|
||||
on_update: function(val) {
|
||||
document.body.classList.toggle("ffz-chat-separator", !this.has_bttv && val !== '0');
|
||||
document.body.classList.toggle("ffz-chat-separator-3d", !this.has_bttv && val === '2');
|
||||
document.body.classList.toggle("ffz-chat-separator", !this.has_bttv && val !== 0);
|
||||
document.body.classList.toggle("ffz-chat-separator-3d", !this.has_bttv && val === 2);
|
||||
document.body.classList.toggle("ffz-chat-separator-3d-inset", !this.has_bttv && val === 3);
|
||||
document.body.classList.toggle("ffz-chat-separator-wide", !this.has_bttv && val === 4);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -543,10 +530,11 @@ FFZ.prototype.setup_line = function() {
|
|||
document.body.classList.toggle("ffz-chat-colors-gray", !this.has_bttv && this.settings.fix_color === '-1');
|
||||
|
||||
document.body.classList.toggle('ffz-chat-background', !this.has_bttv && this.settings.chat_rows);
|
||||
document.body.classList.toggle("ffz-chat-separator", !this.has_bttv && this.settings.chat_separators !== '0');
|
||||
document.body.classList.toggle("ffz-chat-separator-3d", !this.has_bttv && this.settings.chat_separators === '2');
|
||||
document.body.classList.toggle("ffz-chat-separator", !this.has_bttv && this.settings.chat_separators !== 0);
|
||||
document.body.classList.toggle("ffz-chat-separator-wide", !this.has_bttv && this.settings.chat_separators === 4);
|
||||
document.body.classList.toggle("ffz-chat-separator-3d", !this.has_bttv && this.settings.chat_separators === 2);
|
||||
document.body.classList.toggle("ffz-chat-separator-3d-inset", !this.has_bttv && this.settings.chat_separators === 3);
|
||||
document.body.classList.toggle("ffz-chat-padding", !this.has_bttv && this.settings.chat_padding);
|
||||
document.body.classList.toggle("ffz-chat-purge-icon", !this.has_bttv && this.settings.line_purge_icon);
|
||||
|
||||
document.body.classList.toggle("ffz-high-contrast-chat-text", !this.has_bttv && this.settings.high_contrast_chat[2] === '1');
|
||||
document.body.classList.toggle("ffz-high-contrast-chat-bold", !this.has_bttv && this.settings.high_contrast_chat[1] === '1');
|
||||
|
@ -645,16 +633,30 @@ FFZ.prototype._modify_line = function(component) {
|
|||
if ( e.target && e.target.classList.contains('mod-icon') ) {
|
||||
jQuery(e.target).trigger('mouseout');
|
||||
|
||||
if ( e.target.classList.contains('purge') ) {
|
||||
/*if ( e.target.classList.contains('purge') ) {
|
||||
var i = this.get('msgObject.from'),
|
||||
room_id = this.get('msgObject.room'),
|
||||
room = room_id && f.rooms[room_id] && f.rooms[room_id].room;
|
||||
|
||||
if ( room ) {
|
||||
room.send("/timeout " + i + " 1");
|
||||
room.send("/timeout " + i + " 1", true);
|
||||
room.clearMessages(i);
|
||||
}
|
||||
return;
|
||||
}*/
|
||||
|
||||
if ( e.target.classList.contains('custom') ) {
|
||||
var room_id = this.get('msgObject.room'),
|
||||
room = room_id && f.rooms[room_id] && f.rooms[room_id].room,
|
||||
|
||||
cmd = e.target.getAttribute('data-cmd');
|
||||
|
||||
if ( room ) {
|
||||
room.send(cmd, true);
|
||||
if ( e.target.classList.contains('is-timeout') )
|
||||
room.clearMessages(this.get('msgObject.from'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,7 +680,7 @@ FFZ.prototype._modify_line = function(component) {
|
|||
return 4;
|
||||
else if ( this.get('isBroadcaster') )
|
||||
return 3;
|
||||
else if ( this.get('isGlobalModerator') )
|
||||
else if ( this.get('isGlobalMod') )
|
||||
return 2;
|
||||
else if ( this.get('isModerator') )
|
||||
return 1;
|
||||
|
@ -712,13 +714,34 @@ FFZ.prototype._modify_line = function(component) {
|
|||
|
||||
if ( ! is_whisper && this_ul < other_ul ) {
|
||||
e.push('<span class="mod-icons float-left">');
|
||||
for(var i=0, l = f.settings.mod_buttons.length; i < l; i++) {
|
||||
var pair = f.settings.mod_buttons[i],
|
||||
prefix = pair[0], btn = pair[1],
|
||||
|
||||
cmd, tip;
|
||||
|
||||
if ( btn === false ) {
|
||||
if ( deleted )
|
||||
e.push('<a class="mod-icon float-left tooltip unban" title="Unban User" href="#">Unban</a>');
|
||||
else
|
||||
e.push('<a class="mod-icon float-left tooltip ban" title="Ban User" href="#">Ban</a>');
|
||||
|
||||
} else if ( btn === 600 )
|
||||
e.push('<a class="mod-icon float-left tooltip timeout" title="Timeout User (10m)" href="#">Timeout</a>');
|
||||
e.push('<a class="mod-icon float-left tooltip purge" title="Purge User (Timeout 1s)" href="#">Purge</a>');
|
||||
|
||||
else {
|
||||
if ( typeof btn === "string" ) {
|
||||
cmd = btn.replace(/{user}/g, user);
|
||||
tip = 'Custom Command\n' + cmd;
|
||||
} else {
|
||||
cmd = "/timeout " + user + " " + btn;
|
||||
tip = "Timeout User (" + utils.duration_string(btn) + ")";
|
||||
}
|
||||
|
||||
e.push('<a class="mod-icon float-left tooltip' + (cmd.substr(0, 9) === '/timeout' ? ' is-timeout' : '') + ' custom" data-cmd="' + utils.quote_attr(cmd) + '" title="' + utils.quote_attr(tip) + '" href="#">' + prefix + '</a>');
|
||||
}
|
||||
}
|
||||
|
||||
e.push('</span>');
|
||||
}
|
||||
|
||||
|
@ -730,7 +753,7 @@ FFZ.prototype._modify_line = function(component) {
|
|||
else if ( this.get('isAdmin') )
|
||||
badges[0] = {klass: 'admin', title: 'Admin'};
|
||||
else if ( this.get('isGlobalMod') )
|
||||
badges[0] = {klass: 'global-moderator', title: 'Global Moderator'};
|
||||
badges[0] = {klass: 'global-mod', title: 'Global Moderator'};
|
||||
else if ( ! is_whisper && this.get('isModerator') )
|
||||
badges[0] = {klass: 'moderator', title: 'Moderator'};
|
||||
|
||||
|
@ -881,7 +904,7 @@ FFZ.get_capitalization = function(name, callback) {
|
|||
|
||||
FFZ.prototype._remove_banned = function(tokens) {
|
||||
var banned_words = this.settings.banned_words,
|
||||
banned_links = this.settings.filter_bad_shorteners ? ['goo.gl', 'j.mp', 'bit.ly'] : null,
|
||||
banned_links = this.settings.filter_bad_shorteners ? ['apo.af', 'goo.gl', 'j.mp', 'bit.ly'] : null,
|
||||
|
||||
has_banned_words = banned_words && banned_words.length;
|
||||
|
||||
|
|
|
@ -12,33 +12,7 @@ var FFZ = window.FrankerFaceZ,
|
|||
},
|
||||
|
||||
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>',
|
||||
CHECK = '<svg class="svg-unban" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path fill-rule="evenodd" clip-rule="evenodd" fill="#888888" d="M6.5,12.75L2,8.25l2-2l2.5,2.5l5.5-5.5l2,2L6.5,12.75z"/></svg>',
|
||||
|
||||
DURATIONS = {},
|
||||
duration_string = function(val) {
|
||||
if ( val === 1 )
|
||||
return 'Purge';
|
||||
|
||||
if ( DURATIONS[val] )
|
||||
return DURATIONS[val];
|
||||
|
||||
var weeks, days, hours, minutes, seconds;
|
||||
|
||||
weeks = Math.floor(val / 604800);
|
||||
seconds = val % 604800;
|
||||
|
||||
days = Math.floor(seconds / 86400);
|
||||
seconds %= 86400;
|
||||
|
||||
hours = Math.floor(seconds / 3600);
|
||||
seconds %= 3600;
|
||||
|
||||
minutes = Math.floor(seconds / 60);
|
||||
seconds %= 60;
|
||||
|
||||
var out = DURATIONS[val] = (weeks ? weeks + 'w' : '') + ((days || (weeks && (hours || minutes || seconds))) ? days + 'd' : '') + ((hours || ((weeks || days) && (minutes || seconds))) ? hours + 'h' : '') + ((minutes || ((weeks || days || hours) && seconds)) ? minutes + 'm' : '') + (seconds ? seconds + 's' : '');
|
||||
return out;
|
||||
};
|
||||
CHECK = '<svg class="svg-unban" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path fill-rule="evenodd" clip-rule="evenodd" fill="#888888" d="M6.5,12.75L2,8.25l2-2l2.5,2.5l5.5-5.5l2,2L6.5,12.75z"/></svg>';
|
||||
|
||||
|
||||
try {
|
||||
|
@ -169,6 +143,127 @@ FFZ.settings_info.mod_card_history = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.mod_buttons = {
|
||||
type: "button",
|
||||
|
||||
// Special Values
|
||||
// false = Ban/Unban
|
||||
// integer = Timeout (that amount of time)
|
||||
value: [['', false, false], ['',600, false]], //, ['', 1, false]],
|
||||
|
||||
category: "Chat Moderation",
|
||||
no_bttv: true,
|
||||
|
||||
name: "Custom In-Line Moderation Icons",
|
||||
help: "Change out the different in-line moderation icons to use any command quickly.",
|
||||
|
||||
method: function() {
|
||||
var old_val = "";
|
||||
for(var i=0; i < this.settings.mod_buttons.length; i++) {
|
||||
var pair = this.settings.mod_buttons[i],
|
||||
prefix = pair[0], cmd = pair[1], had_prefix = pair[2];
|
||||
|
||||
if ( cmd === false )
|
||||
cmd = "<BAN>";
|
||||
else if ( typeof cmd !== "string" )
|
||||
cmd = '' + cmd;
|
||||
|
||||
if ( ! had_prefix )
|
||||
prefix = '';
|
||||
else
|
||||
prefix += '=';
|
||||
|
||||
if ( cmd.substr(cmd.length - 7) === ' {user}' )
|
||||
cmd = cmd.substr(0, cmd.length - 7);
|
||||
|
||||
if ( cmd.indexOf(' ') !== -1 )
|
||||
old_val += ' ' + prefix + '"' + cmd + '"';
|
||||
else
|
||||
old_val += ' ' + prefix + cmd;
|
||||
}
|
||||
|
||||
var new_val = prompt("Custom In-Line Moderation Icons\n\nPlease enter a list of commands to be made available as mod icons within chat lines. Commands are separated by spaces. To include spaces in a command, surround the command with double quotes (\"). Use \"{user}\" to insert the user's username into the command, otherwise it will be appended to the end.\n\nExample: !permit \"!reg add {user}\"\n\nNumeric values will become timeout buttons for that number of seconds. The text \"<BAN>\" is a special value that will act like the normal Ban button in chat.\n\nTo assign a specific letter for use as the icon, specify it at the start of the command followed by an equals sign.\n\nExample: A=\"!reg add\"\n\nDefault: <BAN> 600", old_val);
|
||||
|
||||
if ( new_val === null || new_val === undefined )
|
||||
return;
|
||||
|
||||
var vals = [], prefix = '';
|
||||
new_val = new_val.trim();
|
||||
|
||||
while(new_val) {
|
||||
if ( new_val.charAt(1) === '=' ) {
|
||||
prefix = new_val.charAt(0);
|
||||
new_val = new_val.substr(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( new_val.charAt(0) === '"' ) {
|
||||
var end = new_val.indexOf('"', 1);
|
||||
if ( end === -1 )
|
||||
end = new_val.length;
|
||||
|
||||
var segment = new_val.substr(1, end - 1);
|
||||
if ( segment ) {
|
||||
vals.push([prefix, segment]);
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
new_val = new_val.substr(end + 1);
|
||||
|
||||
} else {
|
||||
var ind = new_val.indexOf(' ');
|
||||
if ( ind === -1 ) {
|
||||
if ( new_val ) {
|
||||
vals.push([prefix, new_val]);
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
new_val = '';
|
||||
|
||||
} else {
|
||||
var segment = new_val.substr(0, ind);
|
||||
if ( segment ) {
|
||||
vals.push([prefix, segment]);
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
new_val = new_val.substr(ind + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var final = [];
|
||||
for(var i=0; i < vals.length; i++) {
|
||||
var had_prefix = false, prefix = vals[i][0], val = vals[i][1];
|
||||
if ( val === "<BAN>" )
|
||||
val = false;
|
||||
|
||||
var num = parseInt(val);
|
||||
if ( num > 0 && num !== NaN )
|
||||
val = num;
|
||||
|
||||
if ( ! prefix ) {
|
||||
var tmp;
|
||||
if ( typeof val === "string" )
|
||||
tmp = /\w/.exec(val);
|
||||
else
|
||||
tmp = utils.duration_string(val);
|
||||
|
||||
prefix = tmp && tmp.length ? tmp[0].toUpperCase() : "C";
|
||||
} else
|
||||
had_prefix = true;
|
||||
|
||||
if ( typeof val === "string" && val.indexOf('{user}') === -1 )
|
||||
val += ' {user}';
|
||||
|
||||
final.push([prefix, val, had_prefix]);
|
||||
}
|
||||
|
||||
this.settings.set('mod_buttons', final);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.mod_card_buttons = {
|
||||
type: "button",
|
||||
value: [],
|
||||
|
@ -351,6 +446,8 @@ FFZ.prototype.setup_mod_card = function() {
|
|||
controller = this.get('controller'),
|
||||
line,
|
||||
|
||||
is_mod = controller.get('cardInfo.isModeratorOrHigher'),
|
||||
|
||||
user_id = controller.get('cardInfo.user.id'),
|
||||
alias = f.aliases[user_id];
|
||||
|
||||
|
@ -384,7 +481,7 @@ FFZ.prototype.setup_mod_card = function() {
|
|||
}
|
||||
|
||||
// Additional Buttons
|
||||
if ( f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
|
||||
if ( is_mod && f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
|
||||
line = document.createElement('div');
|
||||
line.className = 'extra-interface interface clearfix';
|
||||
|
||||
|
@ -394,7 +491,7 @@ FFZ.prototype.setup_mod_card = function() {
|
|||
cont = App.__container__.lookup('controller:chat'),
|
||||
room = cont && cont.get('currentRoom');
|
||||
|
||||
room && room.send(cmd.replace(/{user}/g, user_id));
|
||||
room && room.send(cmd.replace(/{user}/g, user_id), true);
|
||||
},
|
||||
|
||||
add_btn_make = function(cmd) {
|
||||
|
@ -446,16 +543,16 @@ FFZ.prototype.setup_mod_card = function() {
|
|||
room = App.__container__.lookup('controller:chat').get('currentRoom');
|
||||
|
||||
if ( is_mod && key == keycodes.P )
|
||||
room.send("/timeout " + user_id + " 1");
|
||||
room.send("/timeout " + user_id + " 1", true);
|
||||
|
||||
else if ( is_mod && key == keycodes.B )
|
||||
room.send("/ban " + user_id);
|
||||
room.send("/ban " + user_id, true);
|
||||
|
||||
else if ( is_mod && key == keycodes.T )
|
||||
room.send("/timeout " + user_id + " 600");
|
||||
room.send("/timeout " + user_id + " 600", true);
|
||||
|
||||
else if ( is_mod && key == keycodes.U )
|
||||
room.send("/unban " + user_id);
|
||||
room.send("/unban " + user_id, true);
|
||||
|
||||
else if ( key != keycodes.ESC )
|
||||
return;
|
||||
|
@ -466,51 +563,23 @@ FFZ.prototype.setup_mod_card = function() {
|
|||
|
||||
|
||||
// Only do the big stuff if we're mod.
|
||||
if ( controller.get('cardInfo.isModeratorOrHigher') ) {
|
||||
if ( is_mod ) {
|
||||
el.classList.add('ffz-is-mod');
|
||||
|
||||
// Key Handling
|
||||
if ( f.settings.mod_card_hotkeys ) {
|
||||
el.classList.add('no-mousetrap');
|
||||
|
||||
el.addEventListener('keyup', function(e) {
|
||||
var key = e.keyCode || e.which,
|
||||
user_id = controller.get('cardInfo.user.id'),
|
||||
room = App.__container__.lookup('controller:chat').get('currentRoom');
|
||||
|
||||
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.U )
|
||||
room.send("/unban " + user_id);
|
||||
|
||||
else if ( key != keycodes.ESC )
|
||||
return;
|
||||
|
||||
controller.send('close');
|
||||
});
|
||||
}
|
||||
|
||||
var btn_click = function(timeout) {
|
||||
var user_id = controller.get('cardInfo.user.id'),
|
||||
room = App.__container__.lookup('controller:chat').get('currentRoom');
|
||||
|
||||
if ( timeout === -1 )
|
||||
room.send("/unban " + user_id);
|
||||
room.send("/unban " + user_id, true);
|
||||
else
|
||||
room.send("/timeout " + user_id + " " + timeout);
|
||||
room.send("/timeout " + user_id + " " + timeout, true);
|
||||
},
|
||||
|
||||
btn_make = function(timeout) {
|
||||
var btn = document.createElement('button')
|
||||
btn.className = 'button';
|
||||
btn.innerHTML = duration_string(timeout);
|
||||
btn.innerHTML = utils.duration_string(timeout);
|
||||
btn.title = "Timeout User for " + utils.number_commas(timeout) + " Second" + (timeout != 1 ? "s" : "");
|
||||
|
||||
if ( f.settings.mod_card_hotkeys && timeout === 600 )
|
||||
|
@ -746,7 +815,7 @@ FFZ.chat_commands.purge = function(room, args) {
|
|||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/timeout " + name + " 1");
|
||||
room.room.send("/timeout " + name + " 1", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -760,7 +829,7 @@ FFZ.chat_commands.p.enabled = function() { return this.settings.short_commands;
|
|||
FFZ.chat_commands.t = function(room, args) {
|
||||
if ( ! args || ! args.length )
|
||||
return "Timeout Usage: /t username [duration]";
|
||||
room.room.send("/timeout " + args.join(" "));
|
||||
room.room.send("/timeout " + args.join(" "), true);
|
||||
}
|
||||
|
||||
FFZ.chat_commands.t.enabled = function() { return this.settings.short_commands; }
|
||||
|
@ -776,7 +845,7 @@ FFZ.chat_commands.b = function(room, args) {
|
|||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/ban " + name);
|
||||
room.room.send("/ban " + name, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,7 +862,7 @@ FFZ.chat_commands.u = function(room, args) {
|
|||
for(var i=0; i < args.length; i++) {
|
||||
var name = args[i];
|
||||
if ( name )
|
||||
room.room.send("/unban " + name);
|
||||
room.room.send("/unban " + name, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,15 @@ FFZ.settings_info.player_stats = {
|
|||
category: "Channel Metadata",
|
||||
|
||||
name: "Stream Latency",
|
||||
help: "<i>New HTML5 Player Only.</i> Display your current stream latency (how far behind the broadcast you are) under the player, with a few useful statistics in a tooltip.",
|
||||
help: "Display your current stream latency (how far behind the broadcast you are) under the player, with a few useful statistics in a tooltip.",
|
||||
|
||||
on_update: function(val) {
|
||||
for(var key in this.players) {
|
||||
var player = this.players[key];
|
||||
if ( player && player.player && player.player.ffzSetStatsEnabled )
|
||||
player.player.ffzSetStatsEnabled(val || player.player.ffz_stats);
|
||||
}
|
||||
|
||||
if ( ! this._cindex )
|
||||
return;
|
||||
|
||||
|
@ -24,11 +30,35 @@ FFZ.settings_info.player_stats = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.classic_player = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
no_mobile: true,
|
||||
|
||||
category: "Appearance",
|
||||
|
||||
name: "Classic Player",
|
||||
help: "Alter the appearance of the player to resemble the older Twitch player with always visible controls.",
|
||||
|
||||
on_update: function(val) {
|
||||
document.body.classList.toggle('ffz-classic-player', val);
|
||||
var Layout = window.App && App.__container__.lookup('controller:layout');
|
||||
if ( Layout )
|
||||
Layout.set('PLAYER_CONTROLS_HEIGHT', val ? 32 : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ---------------
|
||||
// Initialization
|
||||
// ---------------
|
||||
|
||||
FFZ.prototype.setup_player = function() {
|
||||
document.body.classList.toggle('ffz-classic-player', this.settings.classic_player);
|
||||
var Layout = window.App && App.__container__.lookup('controller:layout');
|
||||
if ( Layout )
|
||||
Layout.set('PLAYER_CONTROLS_HEIGHT', this.settings.classic_player ? 32 : 0);
|
||||
|
||||
this.players = {};
|
||||
|
||||
var Player2 = App && App.__container__.resolve('component:twitch-player2');
|
||||
|
@ -39,6 +69,9 @@ FFZ.prototype.setup_player = function() {
|
|||
this._modify_player(Player2)
|
||||
|
||||
// Modify all existing players.
|
||||
if ( ! window.Ember )
|
||||
return;
|
||||
|
||||
for(var key in Ember.View.views) {
|
||||
if ( ! Ember.View.views.hasOwnProperty(key) )
|
||||
continue;
|
||||
|
@ -49,6 +82,7 @@ FFZ.prototype.setup_player = function() {
|
|||
|
||||
this.log("Manually updating existing Player instance.", view);
|
||||
try {
|
||||
this._modify_player(view);
|
||||
view.ffzInit();
|
||||
if ( view.get('player') )
|
||||
view.ffzPostPlayer();
|
||||
|
@ -65,7 +99,12 @@ FFZ.prototype.setup_player = function() {
|
|||
// ---------------
|
||||
|
||||
FFZ.prototype._modify_player = function(player) {
|
||||
var f = this;
|
||||
var f = this,
|
||||
update_stats = function() {
|
||||
f._cindex && f._cindex.ffzUpdatePlayerStats();
|
||||
};
|
||||
|
||||
|
||||
player.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
|
@ -97,18 +136,17 @@ FFZ.prototype._modify_player = function(player) {
|
|||
ffzInit: function() {
|
||||
var id = this.get('channel.id');
|
||||
f.players[id] = this;
|
||||
|
||||
this._ffz_stat_update = this.ffzStatUpdate.bind(this);
|
||||
},
|
||||
|
||||
ffzTeardown: function() {
|
||||
var id = this.get('channel.id');
|
||||
if ( f.players[id] === this )
|
||||
f.players[id] = undefined;
|
||||
},
|
||||
|
||||
ffzStatUpdate: function() {
|
||||
f._cindex && f._cindex.ffzUpdatePlayerStats();
|
||||
if ( this._ffz_stat_interval ) {
|
||||
clearInterval(this._ffz_stat_interval);
|
||||
this._ffz_stat_interval = null;
|
||||
}
|
||||
},
|
||||
|
||||
ffzPostPlayer: function() {
|
||||
|
@ -116,32 +154,79 @@ FFZ.prototype._modify_player = function(player) {
|
|||
if ( ! player )
|
||||
return;
|
||||
|
||||
// Make it so stats can no longer be disabled.
|
||||
player.ffzSetStatsEnabled = player.setStatsEnabled;
|
||||
player.setStatsEnabled = function() {}
|
||||
// Subscribe to the qualities event.
|
||||
//player.addEventListener('qualitieschange', this.ffzQualitiesUpdated.bind(this));
|
||||
//this.ffzQualitiesUpdated();
|
||||
|
||||
// We can't just request stats straight away...
|
||||
this.ffzWaitForStats();
|
||||
// Only set up the stats hooks if we need stats.
|
||||
if ( ! player.getVideo() )
|
||||
this.ffzInitStats();
|
||||
},
|
||||
|
||||
ffzWaitForStats: function() {
|
||||
ffzInitStats: function() {
|
||||
if ( this.get('ffzStatsInitialized') )
|
||||
return;
|
||||
|
||||
var player = this.get('player');
|
||||
if ( ! player )
|
||||
return;
|
||||
|
||||
if ( player.stats ) {
|
||||
// Add the event listener.
|
||||
player.addEventListener('statschange', this._ffz_stat_update);
|
||||
this.set('ffzStatsInitialized', true);
|
||||
|
||||
// Make it so stats can no longer be disabled if we want them.
|
||||
player.ffzSetStatsEnabled = player.setStatsEnabled;
|
||||
player.ffz_stats = player.getStatsEnabled();
|
||||
|
||||
} else {
|
||||
// Keep going until we've got it.
|
||||
player.ffzSetStatsEnabled(false);
|
||||
var t = this;
|
||||
setTimeout(function() {
|
||||
|
||||
player.setStatsEnabled = function(e, s) {
|
||||
if ( s !== false )
|
||||
player.ffz_stats = e;
|
||||
|
||||
var out = player.ffzSetStatsEnabled(e || f.settings.player_stats);
|
||||
|
||||
if ( ! t._ffz_player_stats_initialized ) {
|
||||
t._ffz_player_stats_initialized = true;
|
||||
player.addEventListener('statschange', update_stats);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
this._ffz_stat_interval = setInterval(function() {
|
||||
if ( f.settings.player_stats || player.ffz_stats ) {
|
||||
player.ffzSetStatsEnabled(false);
|
||||
player.ffzSetStatsEnabled(true);
|
||||
setTimeout(t.ffzWaitForStats.bind(t), 1250);
|
||||
}, 250);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
if ( f.settings.player_stats && ! player.ffz_stats ) {
|
||||
this._ffz_player_stats_initialized = true;
|
||||
player.addEventListener('statschange', update_stats);
|
||||
player.ffzSetStatsEnabled(true);
|
||||
}
|
||||
},
|
||||
|
||||
ffzSetQuality: function(q) {
|
||||
var player = this.get('player');
|
||||
if ( ! player )
|
||||
return;
|
||||
|
||||
this.$(".js-quality-display-contain").attr("data-q", "loading");
|
||||
|
||||
player.setQuality(q);
|
||||
|
||||
var t = this.$(".js-player-alert");
|
||||
t.find(".js-player-alert__message").text();
|
||||
t.attr("data-active", !0);
|
||||
},
|
||||
|
||||
ffzGetQualities: function() {
|
||||
var player = this.get('player');
|
||||
if ( ! player )
|
||||
return [];
|
||||
return player.getQualities();
|
||||
},
|
||||
|
||||
});
|
||||
}
|
|
@ -1180,12 +1180,12 @@ FFZ.prototype._modify_room = function(room) {
|
|||
return this._super(e);
|
||||
},
|
||||
|
||||
send: function(text) {
|
||||
send: function(text, ignore_history) {
|
||||
if ( f.settings.group_tabs && f.settings.whisper_room && this.ffz_whisper_room )
|
||||
return;
|
||||
|
||||
try {
|
||||
if ( text ) {
|
||||
if ( text && ! ignore_history ) {
|
||||
// Command History
|
||||
var mru = this.get('mru_list'),
|
||||
ind = mru.indexOf(text);
|
||||
|
|
|
@ -66,7 +66,10 @@ FFZ.prototype.setup_bttv = function(delay) {
|
|||
document.body.classList.remove("ffz-chat-padding");
|
||||
document.body.classList.remove("ffz-chat-separator");
|
||||
document.body.classList.remove("ffz-chat-separator-3d");
|
||||
document.body.classList.remove("ffz-chat-separator-wide");
|
||||
document.body.classList.remove("ffz-chat-separator-3d-inset");
|
||||
document.body.classList.remove("ffz-sidebar-swap");
|
||||
document.body.classList.remove("ffz-flip-dashboard");
|
||||
document.body.classList.remove("ffz-transparent-badges");
|
||||
document.body.classList.remove("ffz-high-contrast-chat-text");
|
||||
document.body.classList.remove("ffz-high-contrast-chat-bg");
|
||||
|
|
|
@ -17,7 +17,7 @@ FFZ.prototype.check_ff = function(tries) {
|
|||
if ( ! tries )
|
||||
this.log("Checking for Feature Friday data...");
|
||||
|
||||
jQuery.ajax(constants.SERVER + "script/event.json", {cache: false, dataType: "json", context: this})
|
||||
jQuery.ajax(constants.SERVER + "script/event.json", {dataType: "json", context: this})
|
||||
.done(function(data) {
|
||||
return this._load_ff(data);
|
||||
}).fail(function(data) {
|
||||
|
|
6
src/localization.js
Normal file
6
src/localization.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
var FFZ = window.FrankerFaceZ;
|
||||
|
||||
|
||||
FFZ.prototype.tr = function(s) {
|
||||
return s;
|
||||
}
|
18
src/main.js
18
src/main.js
|
@ -21,7 +21,7 @@ FFZ.get = function() { return FFZ.instance; }
|
|||
|
||||
// Version
|
||||
var VER = FFZ.version_info = {
|
||||
major: 3, minor: 5, revision: 21,
|
||||
major: 3, minor: 5, revision: 30,
|
||||
toString: function() {
|
||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ FFZ.prototype.get_user = function() {
|
|||
// -------------------
|
||||
|
||||
// Import these first to set up data structures
|
||||
require('./localization');
|
||||
require('./ui/menu');
|
||||
require('./settings');
|
||||
require('./socket');
|
||||
|
@ -111,11 +112,12 @@ require('./colors');
|
|||
require('./emoticons');
|
||||
require('./badges');
|
||||
require('./tokenize');
|
||||
//require('./filtering');
|
||||
|
||||
|
||||
// Analytics: require('./ember/router');
|
||||
require('./ember/channel');
|
||||
//require('./ember/player');
|
||||
require('./ember/player');
|
||||
require('./ember/room');
|
||||
require('./ember/layout');
|
||||
require('./ember/line');
|
||||
|
@ -124,6 +126,7 @@ require('./ember/viewers');
|
|||
require('./ember/moderation-card');
|
||||
require('./ember/chat-input');
|
||||
//require('./ember/teams');
|
||||
require('./ember/directory');
|
||||
|
||||
require('./debug');
|
||||
|
||||
|
@ -158,7 +161,7 @@ FFZ.prototype.initialize = function(increment, delay) {
|
|||
|
||||
// Check for the player
|
||||
if ( location.hostname === 'player.twitch.tv' ) {
|
||||
//this.init_player(delay);
|
||||
this.init_player(delay);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -211,6 +214,8 @@ FFZ.prototype.init_player = function(delay) {
|
|||
// Literally only make it dark.
|
||||
this.load_settings();
|
||||
this.setup_dark();
|
||||
this.setup_css();
|
||||
this.setup_player();
|
||||
|
||||
var end = (window.performance && performance.now) ? performance.now() : Date.now(),
|
||||
duration = end - start;
|
||||
|
@ -279,7 +284,9 @@ FFZ.prototype.init_dashboard = function(delay) {
|
|||
|
||||
this.setup_tokenization();
|
||||
this.setup_notifications();
|
||||
this.setup_following_count(false);
|
||||
this.setup_css();
|
||||
this.setup_menu();
|
||||
|
||||
this._update_subscribers();
|
||||
|
||||
|
@ -318,7 +325,9 @@ FFZ.prototype.init_ember = function(delay) {
|
|||
//this.setup_router();
|
||||
this.setup_colors();
|
||||
this.setup_tokenization();
|
||||
//this.setup_player();
|
||||
//this.setup_filtering();
|
||||
|
||||
this.setup_player();
|
||||
this.setup_channel();
|
||||
this.setup_room();
|
||||
this.setup_line();
|
||||
|
@ -327,6 +336,7 @@ FFZ.prototype.init_ember = function(delay) {
|
|||
this.setup_viewers();
|
||||
this.setup_mod_card();
|
||||
this.setup_chat_input();
|
||||
this.setup_directory();
|
||||
|
||||
//this.setup_teams();
|
||||
|
||||
|
|
|
@ -89,11 +89,37 @@ FFZ.prototype.load_settings = function() {
|
|||
// Backup and Restore
|
||||
// --------------------
|
||||
|
||||
FFZ.prototype.reset_settings = function() {
|
||||
if ( ! confirm(this.tr('Are you sure you wish to reset FrankerFaceZ?\n\nThis will force the tab to refresh.')) )
|
||||
return;
|
||||
|
||||
|
||||
// Clear Settings
|
||||
for(var key in FFZ.settings_info) {
|
||||
if ( ! FFZ.settings_info.hasOwnProperty(key) )
|
||||
continue;
|
||||
|
||||
this.settings.del(key);
|
||||
}
|
||||
|
||||
// Clear Aliases
|
||||
this.aliases = {};
|
||||
localStorage.ffz_aliases = '{}';
|
||||
|
||||
// TODO: Filters
|
||||
|
||||
|
||||
// Refresh
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype.save_settings_file = function() {
|
||||
var data = {
|
||||
version: 1,
|
||||
script_version: FFZ.version_info + '',
|
||||
aliases: this.aliases,
|
||||
filters: this.filters,
|
||||
settings: {}
|
||||
};
|
||||
|
||||
|
@ -135,8 +161,8 @@ FFZ.prototype._load_settings_file = function(data) {
|
|||
|
||||
this.log("Loading Settings Data", data);
|
||||
|
||||
var skipped = [],
|
||||
applied = [];
|
||||
var skipped = [], applied = [],
|
||||
aliases = 0;
|
||||
|
||||
if ( data.settings ) {
|
||||
for(var key in data.settings) {
|
||||
|
@ -158,9 +184,26 @@ FFZ.prototype._load_settings_file = function(data) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( data.aliases ) {
|
||||
for(var key in data.aliases) {
|
||||
if ( this.aliases[key] === data.aliases[key] )
|
||||
continue;
|
||||
|
||||
this.aliases[key] = data.aliases[key];
|
||||
aliases++;
|
||||
}
|
||||
|
||||
if ( aliases )
|
||||
localStorage.ffz_aliases = JSON.stringify(this.aliases);
|
||||
}
|
||||
|
||||
if ( data.filters ) {
|
||||
// TODO: Load filters!
|
||||
}
|
||||
|
||||
// Do this in a timeout so that any styles have a moment to update.
|
||||
setTimeout(function(){
|
||||
alert('Successfully loaded ' + applied.length + ' settings and skipped ' + skipped.length + ' settings.');
|
||||
alert('Successfully loaded ' + applied.length + ' settings and skipped ' + skipped.length + ' settings. Added ' + aliases + ' user nicknames.');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -257,8 +300,11 @@ FFZ.menu_pages.settings = {
|
|||
render_save: function(view, container) {
|
||||
var backup_head = document.createElement('div'),
|
||||
restore_head = document.createElement('div'),
|
||||
reset_head = document.createElement('div'),
|
||||
|
||||
backup_cont = document.createElement('div'),
|
||||
restore_cont = document.createElement('div'),
|
||||
reset_cont = document.createElement('div'),
|
||||
|
||||
backup_para = document.createElement('p'),
|
||||
backup_link = document.createElement('a'),
|
||||
|
@ -268,6 +314,10 @@ FFZ.menu_pages.settings = {
|
|||
restore_input = document.createElement('input'),
|
||||
restore_link = document.createElement('a'),
|
||||
restore_help = document.createElement('span'),
|
||||
|
||||
reset_para = document.createElement('p'),
|
||||
reset_link = document.createElement('a'),
|
||||
reset_help = document.createElement('span'),
|
||||
f = this;
|
||||
|
||||
|
||||
|
@ -310,8 +360,27 @@ FFZ.menu_pages.settings = {
|
|||
restore_para.appendChild(restore_help);
|
||||
restore_cont.appendChild(restore_para);
|
||||
|
||||
reset_cont.className = 'chat-menu-content';
|
||||
reset_head.className = 'heading';
|
||||
reset_head.innerHTML = this.tr('Reset Settings');
|
||||
reset_cont.appendChild(reset_head);
|
||||
|
||||
reset_para.className = 'clearfix option';
|
||||
|
||||
reset_link.href = '#';
|
||||
reset_link.innerHTML = this.tr('Reset FrankerFaceZ');
|
||||
reset_link.addEventListener('click', this.reset_settings.bind(this));
|
||||
|
||||
reset_help.className = 'help';
|
||||
reset_help.innerHTML = this.tr('This resets all of your FFZ data. That includes chat filters, nicknames for users, and settings.');
|
||||
|
||||
reset_para.appendChild(reset_link);
|
||||
reset_para.appendChild(reset_help);
|
||||
reset_cont.appendChild(reset_para);
|
||||
|
||||
container.appendChild(backup_cont);
|
||||
container.appendChild(restore_cont);
|
||||
container.appendChild(reset_cont);
|
||||
},
|
||||
|
||||
render_basic: function(view, container) {
|
||||
|
@ -797,11 +866,11 @@ FFZ.prototype._setting_del = function(key) {
|
|||
if ( localStorage.hasOwnProperty(ls_key) )
|
||||
localStorage.removeItem(ls_key);
|
||||
|
||||
delete this.settings[key];
|
||||
|
||||
if ( info )
|
||||
val = this.settings[key] = info.hasOwnProperty("value") ? info.value : undefined;
|
||||
|
||||
this.settings[key] = val;
|
||||
|
||||
if ( info.on_update )
|
||||
try {
|
||||
info.on_update.bind(this)(val, true);
|
||||
|
|
|
@ -108,7 +108,7 @@ var FFZ = window.FrankerFaceZ,
|
|||
}
|
||||
|
||||
image_iframe = function(href, extra_class) {
|
||||
return '<iframe class="ffz-image-hover' + (extra_class ? ' ' + extra_class : '') + '" allowtransparency="true" src="' + constants.SERVER + 'script/image-proxy.html?' + utils.quote_attr(href) + '"></iframe>';
|
||||
return '<iframe class="ffz-image-hover' + (extra_class ? ' ' + extra_class : '') + '" allowtransparency="true" src="' + constants.SERVER + 'script/img-proxy.html#' + utils.quote_attr(href) + '"></iframe>';
|
||||
},
|
||||
|
||||
|
||||
|
@ -352,7 +352,7 @@ FFZ.prototype.setup_tokenization = function() {
|
|||
// ---------------------
|
||||
|
||||
FFZ.prototype.load_twitch_emote_data = function(tries) {
|
||||
jQuery.ajax(constants.SERVER + "script/twitch_emotes.json", {cache: false, context: this})
|
||||
jQuery.ajax(constants.SERVER + "script/twitch_emotes.json", {context: this})
|
||||
.done(function(data) {
|
||||
for(var set_id in data) {
|
||||
var set = data[set_id];
|
||||
|
|
|
@ -50,11 +50,11 @@ FFZ.basic_settings.minimalistic_chat = {
|
|||
help: "Hide all of chat except messages and the input box and reduce chat margins.",
|
||||
|
||||
get: function() {
|
||||
return this.settings.minimal_chat && this.settings.chat_padding;
|
||||
return this.settings.minimal_chat === 3 && this.settings.chat_padding;
|
||||
},
|
||||
|
||||
set: function(val) {
|
||||
this.settings.set('minimal_chat', val);
|
||||
this.settings.set('minimal_chat', val ? 3 : 0);
|
||||
this.settings.set('chat_padding', val);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@ var FFZ = window.FrankerFaceZ,
|
|||
constants = require('../constants');
|
||||
|
||||
FFZ.prototype.setup_css = function() {
|
||||
document.body.classList.toggle('ffz-flip-dashboard', this.settings.flip_dashboard);
|
||||
|
||||
this.log("Injecting main FrankerFaceZ CSS.");
|
||||
|
||||
var s = this._main_style = document.createElement('link');
|
||||
|
@ -11,6 +13,7 @@ FFZ.prototype.setup_css = function() {
|
|||
s.setAttribute('href', constants.SERVER + "script/style.css?_=" + (constants.DEBUG ? Date.now() : FFZ.version_info));
|
||||
document.head.appendChild(s);
|
||||
|
||||
if ( window.jQuery && jQuery.noty )
|
||||
jQuery.noty.themes.ffzTheme = {
|
||||
name: "ffzTheme",
|
||||
style: function() {
|
||||
|
|
31
src/utils.js
31
src/utils.js
|
@ -15,6 +15,8 @@ var sanitize_el = document.createElement('span'),
|
|||
R_LT = /</g,
|
||||
R_GT = />/g,
|
||||
|
||||
DURATIONS = {},
|
||||
|
||||
quote_attr = function(msg) {
|
||||
return msg.replace(R_AMP, "&").replace(R_QUOTE, """).replace(R_SQUOTE, "'").replace(R_LT, "<").replace(R_GT, ">");
|
||||
},
|
||||
|
@ -256,7 +258,7 @@ module.exports = {
|
|||
return 'less than a second';
|
||||
},
|
||||
|
||||
time_to_string: function(elapsed, separate_days, days_only, no_hours) {
|
||||
time_to_string: function(elapsed, separate_days, days_only, no_hours, no_seconds) {
|
||||
var seconds = elapsed % 60,
|
||||
minutes = Math.floor(elapsed / 60),
|
||||
hours = Math.floor(minutes / 60),
|
||||
|
@ -273,7 +275,32 @@ module.exports = {
|
|||
days = ( days > 0 ) ? days + " days, " : "";
|
||||
}
|
||||
|
||||
return days + ((!no_hours || days || hours) ? ((hours < 10 ? "0" : "") + hours + ':') : '') + (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||
return days + ((!no_hours || days || hours) ? ((days && hours < 10 ? "0" : "") + hours + ':') : '') + (minutes < 10 ? "0" : "") + minutes + (no_seconds ? "" : (":" + (seconds < 10 ? "0" : "") + seconds));
|
||||
},
|
||||
|
||||
duration_string: function(val) {
|
||||
if ( val === 1 )
|
||||
return 'Purge';
|
||||
|
||||
if ( DURATIONS[val] )
|
||||
return DURATIONS[val];
|
||||
|
||||
var weeks, days, hours, minutes, seconds;
|
||||
|
||||
weeks = Math.floor(val / 604800);
|
||||
seconds = val % 604800;
|
||||
|
||||
days = Math.floor(seconds / 86400);
|
||||
seconds %= 86400;
|
||||
|
||||
hours = Math.floor(seconds / 3600);
|
||||
seconds %= 3600;
|
||||
|
||||
minutes = Math.floor(seconds / 60);
|
||||
seconds %= 60;
|
||||
|
||||
var out = DURATIONS[val] = (weeks ? weeks + 'w' : '') + ((days || (weeks && (hours || minutes || seconds))) ? days + 'd' : '') + ((hours || ((weeks || days) && (minutes || seconds))) ? hours + 'h' : '') + ((minutes || ((weeks || days || hours) && seconds)) ? minutes + 'm' : '') + (seconds ? seconds + 's' : '');
|
||||
return out;
|
||||
},
|
||||
|
||||
format_unread: function(count) {
|
||||
|
|
182
style.css
182
style.css
|
@ -21,20 +21,20 @@ body > div.tipsy .tipsy-arrow { opacity: 0.8; }
|
|||
|
||||
.ffz-hide-recent-past-broadcast .recent-past-broadcast,
|
||||
.ffz-hide-view-count .stat.twitch-channel-views,
|
||||
.ffz-minimal-chat .emoticon-selector-toggle,
|
||||
.ffz-minimal-chat-input .emoticon-selector-toggle,
|
||||
.ffz-menu-replace .emoticon-selector-toggle {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + .ffz-ui-toggle svg,
|
||||
body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + script + .ffz-ui-toggle svg
|
||||
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .emoticon-selector-toggle + .ffz-ui-toggle svg,
|
||||
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .emoticon-selector-toggle + script + .ffz-ui-toggle svg
|
||||
{
|
||||
height: 14px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + .ffz-ui-toggle,
|
||||
body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + script + .ffz-ui-toggle {
|
||||
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .emoticon-selector-toggle + .ffz-ui-toggle,
|
||||
body:not(.ffz-minimal-chat-input):not(.ffz-menu-replace) .emoticon-selector-toggle + script + .ffz-ui-toggle {
|
||||
height: 14px;
|
||||
width: 18px;
|
||||
top: 28px;
|
||||
|
@ -43,6 +43,8 @@ body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + s
|
|||
.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); }
|
||||
|
||||
.streams .stream .content .overlay_info.live svg path,
|
||||
.videos .video .content .overlay_info.live svg path { fill: #ff2020; }
|
||||
|
||||
.ember-chat-container.dark .ffz-ui-toggle svg.svg-emoticons path,
|
||||
.chat-container.dark .ffz-ui-toggle svg.svg-emoticons path,
|
||||
|
@ -974,6 +976,16 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ember-chat .mod-icons .custom {
|
||||
text-indent: 0;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #888 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Chat Rows */
|
||||
|
||||
.ffz-alias { font-style: italic; }
|
||||
|
@ -1045,10 +1057,19 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.ffz-chat-separator-wide .chat-line:before {
|
||||
border-top: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.ffz-chat-separator-3d .chat-line:before {
|
||||
border-top: 1px solid rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
.ffz-chat-separator-3d-inset .chat-line:before {
|
||||
border-bottom-color: rgba(255,255,255,0.5);
|
||||
border-top: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.ffz-chat-separator-3d ul.chat-lines div:first-of-type .chat-line:before {
|
||||
border-top: none;
|
||||
}
|
||||
|
@ -1066,6 +1087,14 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
border-bottom-color: #000;
|
||||
}
|
||||
|
||||
.ffz-chat-separator-wide .app-main.theatre .chat-line:before,
|
||||
.ffz-chat-separator-wide .chat-container.dark .chat-line:before,
|
||||
.ffz-chat-separator-wide .chat-container.force-dark .chat-line:before,
|
||||
.ffz-chat-separator-wide .ember-chat-container.dark .chat-line:before,
|
||||
.ffz-chat-separator-wide .ember-chat-container.force-dark .chat-line:before {
|
||||
border-top-color: #000;
|
||||
}
|
||||
|
||||
.ffz-chat-separator-3d .app-main.theatre .chat-line:before,
|
||||
.ffz-chat-separator-3d .chat-container.dark .chat-line:before,
|
||||
.ffz-chat-separator-3d .chat-container.force-dark .chat-line:before,
|
||||
|
@ -1074,6 +1103,15 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
border-top-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.ffz-chat-separator-3d-inset .app-main.theatre .chat-line:before,
|
||||
.ffz-chat-separator-3d-inset .chat-container.dark .chat-line:before,
|
||||
.ffz-chat-separator-3d-inset .chat-container.force-dark .chat-line:before,
|
||||
.ffz-chat-separator-3d-inset .ember-chat-container.dark .chat-line:before,
|
||||
.ffz-chat-separator-3d-inset .ember-chat-container.force-dark .chat-line:before {
|
||||
border-bottom-color: rgba(255,255,255,0.1);
|
||||
border-top-color: #000;
|
||||
}
|
||||
|
||||
.ffz-chat-background .chat-history .chat-line.ffz-alternate:before,
|
||||
.ffz-chat-background .ember-chat .chat-messages .chat-line.ffz-alternate:before {
|
||||
background-color: rgba(0,0,0, 0.1);
|
||||
|
@ -1213,6 +1251,7 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
|||
display: block;
|
||||
width: 80px;
|
||||
height: 63px;
|
||||
|
||||
background-image: url("//cdn.frankerfacez.com/script/spinner-dark.png");
|
||||
|
||||
margin: 50px auto;
|
||||
|
@ -1514,9 +1553,9 @@ th.ffz-row-switch {
|
|||
|
||||
/* Minimalistic Chat */
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-header,
|
||||
body.ffz-minimal-chat .ember-chat #ffz-group-tabs,
|
||||
body.ffz-minimal-chat .ember-chat .chat-buttons-container {
|
||||
body.ffz-minimal-chat-head .ember-chat > .chat-header,
|
||||
body.ffz-minimal-chat-head .ember-chat #ffz-group-tabs,
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-buttons-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
@ -1525,30 +1564,30 @@ body.ffz-minimal-chat .ember-chat .chat-interface .emoticon-selector {
|
|||
bottom: 33px;
|
||||
}*/
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-interface .emoticon-selector {
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-interface .emoticon-selector {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-interface .emoticon-selector .dropmenu {
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-interface .emoticon-selector .dropmenu {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-room {
|
||||
body.ffz-minimal-chat-head .ember-chat .chat-room {
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-interface {
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-interface {
|
||||
/*height: 33px !important;*/
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain {
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain {
|
||||
top: 0 !important;
|
||||
margin: 0 !important;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain textarea {
|
||||
body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textarea {
|
||||
/*height: 33px !important;*/
|
||||
overflow: hidden;
|
||||
border-bottom: 0 !important;
|
||||
|
@ -1983,3 +2022,118 @@ li[data-name="following"] a {
|
|||
.ffz-yt-thumb {
|
||||
max-height: 90px;
|
||||
}
|
||||
|
||||
/* Classic Player */
|
||||
|
||||
.ffz-classic-player .player .player-video {
|
||||
position: absolute;
|
||||
top: 0; bottom: 32px;
|
||||
left: 0; right: 0;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player.player-isvod .player-video {
|
||||
bottom: 36px;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player .player-controls-bottom {
|
||||
opacity: 1;
|
||||
|
||||
padding-top: 0;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #000;
|
||||
|
||||
background: -webkit-linear-gradient(bottom, #252525, #666);
|
||||
background: linear-gradient(to top, #252525, #666);
|
||||
}
|
||||
|
||||
.ffz-classic-player .app-main.theatre .player .player-video,
|
||||
.ffz-classic-player .player[data-fullscreen="true"] .player-video {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ffz-classic-player .app-main.theatre .player .player-controls-bottom,
|
||||
.ffz-classic-player .player[data-fullscreen="true"] .player-controls-bottom {
|
||||
margin-bottom: -32px;
|
||||
-webkit-transition: margin-bottom .2s ease-out;
|
||||
transition: margin-bottom .2s ease-out;
|
||||
}
|
||||
|
||||
.ffz-classic-player .app-main.theatre .player.player-isvod .player-controls-bottom,
|
||||
.ffz-classic-player .player.player-isvod[data-fullscreen="true"] .player-controls-bottom {
|
||||
margin-bottom: -36px;
|
||||
}
|
||||
|
||||
.ffz-classic-player .app-main.theatre .player-column:hover .player .player-controls-bottom,
|
||||
.ffz-classic-player .app-main.theatre .player-column:focus .player .player-controls-bottom,
|
||||
.ffz-classic-player .player[data-fullscreen="true"][data-controls="true"] .player-controls-bottom {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player .player-button {
|
||||
padding-bottom: 0;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
|
||||
.ffz-classic-player .player .player-slider:before,
|
||||
.ffz-classic-player .player .player-button,
|
||||
.ffz-classic-player .player .player-slider .ui-slider-handle,
|
||||
.ffz-classic-player .player .player-seek .player-seek__time {
|
||||
-webkit-filter: drop-shadow(0px 0px 1px #000);
|
||||
filter: drop-shadow(0px 0px 1px #000);
|
||||
}
|
||||
|
||||
|
||||
.ffz-classic-player .player .player-slider .ui-slider-handle { background-color: #aeaeae; }
|
||||
.ffz-classic-player .player .player-button svg { fill: #aeaeae; }
|
||||
.ffz-classic-player .player .player-seek .player-seek__time { color: #ddd; }
|
||||
|
||||
.ffz-classic-player .player .player-volume__slider-container {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
||||
.ffz-classic-player .player .player-seek {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player .player-seek .player-slider {
|
||||
margin: -1em 0;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player .player-seek .player-seek__time-container {
|
||||
position: absolute;
|
||||
bottom: -12px;
|
||||
left: 210px;
|
||||
}
|
||||
|
||||
.ffz-classic-player .player .player-seek .player-seek__time + .player-seek__time:before {
|
||||
content: "/";
|
||||
padding: 0 5px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Directory Logos */
|
||||
|
||||
.ffz-directory-logo .meta p { width: auto; }
|
||||
|
||||
.ffz-directory-logo .profile-photo {
|
||||
float: left;
|
||||
height: 46px;
|
||||
width: 46px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
/* Flip Dashboard */
|
||||
|
||||
.ffz-flip-dashboard #dash_main #controls_column {
|
||||
float: right;
|
||||
margin-left: 20px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.ffz-flip-dashboard #dash_main .dash-chat-column {
|
||||
right: inherit;
|
||||
left: 0;
|
||||
margin-right: 20px;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue