mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-29 07:45:33 +00:00
Basic settings. Pull in FileSaver as a requirement. Menus can have sub-pages now, so that's cool.
This commit is contained in:
parent
9ece18ec0f
commit
771e290197
15 changed files with 2590 additions and 694 deletions
16
script.min.js
vendored
16
script.min.js
vendored
File diff suppressed because one or more lines are too long
256
src/FileSaver.js
Normal file
256
src/FileSaver.js
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
/* FileSaver.js
|
||||||
|
* A saveAs() FileSaver implementation.
|
||||||
|
* 1.1.20150716
|
||||||
|
*
|
||||||
|
* By Eli Grey, http://eligrey.com
|
||||||
|
* License: X11/MIT
|
||||||
|
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*global self */
|
||||||
|
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
|
||||||
|
|
||||||
|
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
|
||||||
|
|
||||||
|
var saveAs = saveAs || (function(view) {
|
||||||
|
"use strict";
|
||||||
|
// IE <10 is explicitly unsupported
|
||||||
|
if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var
|
||||||
|
doc = view.document
|
||||||
|
// only get URL when necessary in case Blob.js hasn't overridden it yet
|
||||||
|
, get_URL = function() {
|
||||||
|
return view.URL || view.webkitURL || view;
|
||||||
|
}
|
||||||
|
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||||
|
, can_use_save_link = "download" in save_link
|
||||||
|
, click = function(node) {
|
||||||
|
var event = new MouseEvent("click");
|
||||||
|
node.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
, webkit_req_fs = view.webkitRequestFileSystem
|
||||||
|
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
|
||||||
|
, throw_outside = function(ex) {
|
||||||
|
(view.setImmediate || view.setTimeout)(function() {
|
||||||
|
throw ex;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
, force_saveable_type = "application/octet-stream"
|
||||||
|
, fs_min_size = 0
|
||||||
|
// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
|
||||||
|
// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
|
||||||
|
// for the reasoning behind the timeout and revocation flow
|
||||||
|
, arbitrary_revoke_timeout = 500 // in ms
|
||||||
|
, revoke = function(file) {
|
||||||
|
var revoker = function() {
|
||||||
|
if (typeof file === "string") { // file is an object URL
|
||||||
|
get_URL().revokeObjectURL(file);
|
||||||
|
} else { // file is a File
|
||||||
|
file.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (view.chrome) {
|
||||||
|
revoker();
|
||||||
|
} else {
|
||||||
|
setTimeout(revoker, arbitrary_revoke_timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, dispatch = function(filesaver, event_types, event) {
|
||||||
|
event_types = [].concat(event_types);
|
||||||
|
var i = event_types.length;
|
||||||
|
while (i--) {
|
||||||
|
var listener = filesaver["on" + event_types[i]];
|
||||||
|
if (typeof listener === "function") {
|
||||||
|
try {
|
||||||
|
listener.call(filesaver, event || filesaver);
|
||||||
|
} catch (ex) {
|
||||||
|
throw_outside(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, auto_bom = function(blob) {
|
||||||
|
// prepend BOM for UTF-8 XML and text/* types (including HTML)
|
||||||
|
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
|
||||||
|
return new Blob(["\ufeff", blob], {type: blob.type});
|
||||||
|
}
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
, FileSaver = function(blob, name, no_auto_bom) {
|
||||||
|
if (!no_auto_bom) {
|
||||||
|
blob = auto_bom(blob);
|
||||||
|
}
|
||||||
|
// First try a.download, then web filesystem, then object URLs
|
||||||
|
var
|
||||||
|
filesaver = this
|
||||||
|
, type = blob.type
|
||||||
|
, blob_changed = false
|
||||||
|
, object_url
|
||||||
|
, target_view
|
||||||
|
, dispatch_all = function() {
|
||||||
|
dispatch(filesaver, "writestart progress write writeend".split(" "));
|
||||||
|
}
|
||||||
|
// on any filesys errors revert to saving with object URLs
|
||||||
|
, fs_error = function() {
|
||||||
|
// don't create more object URLs than needed
|
||||||
|
if (blob_changed || !object_url) {
|
||||||
|
object_url = get_URL().createObjectURL(blob);
|
||||||
|
}
|
||||||
|
if (target_view) {
|
||||||
|
target_view.location.href = object_url;
|
||||||
|
} else {
|
||||||
|
var new_tab = view.open(object_url, "_blank");
|
||||||
|
if (new_tab == undefined && typeof safari !== "undefined") {
|
||||||
|
//Apple do not allow window.open, see http://bit.ly/1kZffRI
|
||||||
|
view.location.href = object_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch_all();
|
||||||
|
revoke(object_url);
|
||||||
|
}
|
||||||
|
, abortable = function(func) {
|
||||||
|
return function() {
|
||||||
|
if (filesaver.readyState !== filesaver.DONE) {
|
||||||
|
return func.apply(this, arguments);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
, create_if_not_found = {create: true, exclusive: false}
|
||||||
|
, slice
|
||||||
|
;
|
||||||
|
filesaver.readyState = filesaver.INIT;
|
||||||
|
if (!name) {
|
||||||
|
name = "download";
|
||||||
|
}
|
||||||
|
if (can_use_save_link) {
|
||||||
|
object_url = get_URL().createObjectURL(blob);
|
||||||
|
save_link.href = object_url;
|
||||||
|
save_link.download = name;
|
||||||
|
setTimeout(function() {
|
||||||
|
click(save_link);
|
||||||
|
dispatch_all();
|
||||||
|
revoke(object_url);
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Object and web filesystem URLs have a problem saving in Google Chrome when
|
||||||
|
// viewed in a tab, so I force save with application/octet-stream
|
||||||
|
// http://code.google.com/p/chromium/issues/detail?id=91158
|
||||||
|
// Update: Google errantly closed 91158, I submitted it again:
|
||||||
|
// https://code.google.com/p/chromium/issues/detail?id=389642
|
||||||
|
if (view.chrome && type && type !== force_saveable_type) {
|
||||||
|
slice = blob.slice || blob.webkitSlice;
|
||||||
|
blob = slice.call(blob, 0, blob.size, force_saveable_type);
|
||||||
|
blob_changed = true;
|
||||||
|
}
|
||||||
|
// Since I can't be sure that the guessed media type will trigger a download
|
||||||
|
// in WebKit, I append .download to the filename.
|
||||||
|
// https://bugs.webkit.org/show_bug.cgi?id=65440
|
||||||
|
if (webkit_req_fs && name !== "download") {
|
||||||
|
name += ".download";
|
||||||
|
}
|
||||||
|
if (type === force_saveable_type || webkit_req_fs) {
|
||||||
|
target_view = view;
|
||||||
|
}
|
||||||
|
if (!req_fs) {
|
||||||
|
fs_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs_min_size += blob.size;
|
||||||
|
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
|
||||||
|
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
|
||||||
|
var save = function() {
|
||||||
|
dir.getFile(name, create_if_not_found, abortable(function(file) {
|
||||||
|
file.createWriter(abortable(function(writer) {
|
||||||
|
writer.onwriteend = function(event) {
|
||||||
|
target_view.location.href = file.toURL();
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch(filesaver, "writeend", event);
|
||||||
|
revoke(file);
|
||||||
|
};
|
||||||
|
writer.onerror = function() {
|
||||||
|
var error = writer.error;
|
||||||
|
if (error.code !== error.ABORT_ERR) {
|
||||||
|
fs_error();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
"writestart progress write abort".split(" ").forEach(function(event) {
|
||||||
|
writer["on" + event] = filesaver["on" + event];
|
||||||
|
});
|
||||||
|
writer.write(blob);
|
||||||
|
filesaver.abort = function() {
|
||||||
|
writer.abort();
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
};
|
||||||
|
filesaver.readyState = filesaver.WRITING;
|
||||||
|
}), fs_error);
|
||||||
|
}), fs_error);
|
||||||
|
};
|
||||||
|
dir.getFile(name, {create: false}, abortable(function(file) {
|
||||||
|
// delete file if it already exists
|
||||||
|
file.remove();
|
||||||
|
save();
|
||||||
|
}), abortable(function(ex) {
|
||||||
|
if (ex.code === ex.NOT_FOUND_ERR) {
|
||||||
|
save();
|
||||||
|
} else {
|
||||||
|
fs_error();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}), fs_error);
|
||||||
|
}), fs_error);
|
||||||
|
}
|
||||||
|
, FS_proto = FileSaver.prototype
|
||||||
|
, saveAs = function(blob, name, no_auto_bom) {
|
||||||
|
return new FileSaver(blob, name, no_auto_bom);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
// IE 10+ (native saveAs)
|
||||||
|
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
|
||||||
|
return function(blob, name, no_auto_bom) {
|
||||||
|
if (!no_auto_bom) {
|
||||||
|
blob = auto_bom(blob);
|
||||||
|
}
|
||||||
|
return navigator.msSaveOrOpenBlob(blob, name || "download");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
FS_proto.abort = function() {
|
||||||
|
var filesaver = this;
|
||||||
|
filesaver.readyState = filesaver.DONE;
|
||||||
|
dispatch(filesaver, "abort");
|
||||||
|
};
|
||||||
|
FS_proto.readyState = FS_proto.INIT = 0;
|
||||||
|
FS_proto.WRITING = 1;
|
||||||
|
FS_proto.DONE = 2;
|
||||||
|
|
||||||
|
FS_proto.error =
|
||||||
|
FS_proto.onwritestart =
|
||||||
|
FS_proto.onprogress =
|
||||||
|
FS_proto.onwrite =
|
||||||
|
FS_proto.onabort =
|
||||||
|
FS_proto.onerror =
|
||||||
|
FS_proto.onwriteend =
|
||||||
|
null;
|
||||||
|
|
||||||
|
return saveAs;
|
||||||
|
}(
|
||||||
|
typeof self !== "undefined" && self
|
||||||
|
|| typeof window !== "undefined" && window
|
||||||
|
|| this.content
|
||||||
|
));
|
||||||
|
// `self` is undefined in Firefox for Android content script context
|
||||||
|
// while `this` is nsIContentFrameMessageManager
|
||||||
|
// with an attribute `content` that corresponds to the window
|
||||||
|
|
||||||
|
if (typeof module !== "undefined" && module.exports) {
|
||||||
|
module.exports.saveAs = saveAs;
|
||||||
|
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
|
||||||
|
define([], function() {
|
||||||
|
return saveAs;
|
||||||
|
});
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ FFZ.prototype.setup_channel = function() {
|
||||||
view.ffzInit();
|
view.ffzInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
this.log("Hooking the Ember Channel model.");
|
this.log("Hooking the Ember Channel model.");
|
||||||
Channel = App.__container__.resolve('model:channel');
|
Channel = App.__container__.resolve('model:channel');
|
||||||
if ( ! Channel )
|
if ( ! Channel )
|
||||||
|
@ -58,7 +58,7 @@ FFZ.prototype.setup_channel = function() {
|
||||||
|
|
||||||
Channel.reopen({
|
Channel.reopen({
|
||||||
ffz_host_target: undefined,
|
ffz_host_target: undefined,
|
||||||
|
|
||||||
setHostMode: function(e) {
|
setHostMode: function(e) {
|
||||||
if ( f.settings.hosted_channels ) {
|
if ( f.settings.hosted_channels ) {
|
||||||
this.set('ffz_host_target', e.target);
|
this.set('ffz_host_target', e.target);
|
||||||
|
@ -87,13 +87,13 @@ FFZ.prototype.setup_channel = function() {
|
||||||
ffzUpdateInfo: function() {
|
ffzUpdateInfo: function() {
|
||||||
if ( this._ffz_update_timer )
|
if ( this._ffz_update_timer )
|
||||||
clearTimeout(this._ffz_update_timer);
|
clearTimeout(this._ffz_update_timer);
|
||||||
|
|
||||||
if ( ! this.get('content.id') )
|
if ( ! this.get('content.id') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._ffz_update_timer = setTimeout(this.ffzCheckUpdate.bind(this), 60000);
|
this._ffz_update_timer = setTimeout(this.ffzCheckUpdate.bind(this), 60000);
|
||||||
}.observes("content.id"),
|
}.observes("content.id"),
|
||||||
|
|
||||||
ffzCheckUpdate: function() {
|
ffzCheckUpdate: function() {
|
||||||
var t = this,
|
var t = this,
|
||||||
id = t.get('content.id');
|
id = t.get('content.id');
|
||||||
|
@ -115,11 +115,11 @@ FFZ.prototype.setup_channel = function() {
|
||||||
t.set('game', game);
|
t.set('game', game);
|
||||||
t.set('rollbackData.game', game);
|
t.set('rollbackData.game', game);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( data.stream.channel ) {
|
if ( data.stream.channel ) {
|
||||||
if ( data.stream.channel.status )
|
if ( data.stream.channel.status )
|
||||||
t.set('status', data.stream.channel.status);
|
t.set('status', data.stream.channel.status);
|
||||||
|
|
||||||
if ( data.stream.channel.views )
|
if ( data.stream.channel.views )
|
||||||
t.set('views', data.stream.channel.views);
|
t.set('views', data.stream.channel.views);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ FFZ.prototype.setup_channel = function() {
|
||||||
|
|
||||||
}.observes("content.hostModeTarget")
|
}.observes("content.hostModeTarget")
|
||||||
});
|
});
|
||||||
|
|
||||||
Channel.ffzUpdateInfo();
|
Channel.ffzUpdateInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +265,8 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
user = f.get_user(),
|
user = f.get_user(),
|
||||||
room = user && f.rooms && f.rooms[user.login] && f.rooms[user.login].room,
|
room = user && f.rooms && f.rooms[user.login] && f.rooms[user.login].room,
|
||||||
now_hosting = room && room.ffz_host_target,
|
now_hosting = room && room.ffz_host_target,
|
||||||
hosts_left = room && room.ffz_hosts_left,
|
hosts_left = room && room.ffz_hosts_left,
|
||||||
|
|
||||||
el = this.get('element');
|
el = this.get('element');
|
||||||
|
|
||||||
this.set('ffz_host_updating', false);
|
this.set('ffz_host_updating', false);
|
||||||
|
@ -283,13 +283,13 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
btn = document.createElement('span');
|
btn = document.createElement('span');
|
||||||
btn.id = 'ffz-ui-host-button';
|
btn.id = 'ffz-ui-host-button';
|
||||||
btn.className = 'button action tooltip';
|
btn.className = 'button action tooltip';
|
||||||
|
|
||||||
btn.addEventListener('click', this.ffzClickHost.bind(btn, this, false));
|
btn.addEventListener('click', this.ffzClickHost.bind(btn, this, false));
|
||||||
|
|
||||||
var before;
|
var before;
|
||||||
try { before = container.querySelector(':scope > .theatre-button'); }
|
try { before = container.querySelector(':scope > .theatre-button'); }
|
||||||
catch(err) { before = undefined; }
|
catch(err) { before = undefined; }
|
||||||
|
|
||||||
if ( before )
|
if ( before )
|
||||||
container.insertBefore(btn, before);
|
container.insertBefore(btn, before);
|
||||||
else
|
else
|
||||||
|
@ -307,8 +307,8 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
btn.title += ' You have ' + hosts_left + ' host command' + utils.pluralize(hosts_left) + ' remaining this half hour.';
|
btn.title += ' You have ' + hosts_left + ' host command' + utils.pluralize(hosts_left) + ' remaining this half hour.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( hosted_id ) {
|
if ( hosted_id ) {
|
||||||
var container = el && el.querySelector('#hostmode .channel-actions'),
|
var container = el && el.querySelector('#hostmode .channel-actions'),
|
||||||
btn = container && container.querySelector('#ffz-ui-host-button');
|
btn = container && container.querySelector('#ffz-ui-host-button');
|
||||||
|
@ -321,9 +321,9 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
btn = document.createElement('span');
|
btn = document.createElement('span');
|
||||||
btn.id = 'ffz-ui-host-button';
|
btn.id = 'ffz-ui-host-button';
|
||||||
btn.className = 'button action tooltip';
|
btn.className = 'button action tooltip';
|
||||||
|
|
||||||
btn.addEventListener('click', this.ffzClickHost.bind(btn, this, true));
|
btn.addEventListener('click', this.ffzClickHost.bind(btn, this, true));
|
||||||
|
|
||||||
var before;
|
var before;
|
||||||
try { before = container.querySelector(':scope > .theatre-button'); }
|
try { before = container.querySelector(':scope > .theatre-button'); }
|
||||||
catch(err) { before = undefined; }
|
catch(err) { before = undefined; }
|
||||||
|
@ -344,9 +344,9 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
if ( typeof hosts_left === "number" )
|
if ( typeof hosts_left === "number" )
|
||||||
btn.title += ' You have ' + hosts_left + ' host command' + utils.pluralize(hosts_left) + ' remaining this half hour.';
|
btn.title += ' You have ' + hosts_left + ' host command' + utils.pluralize(hosts_left) + ' remaining this half hour.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ffzClickHost: function(controller, is_host) {
|
ffzClickHost: function(controller, is_host) {
|
||||||
var target = controller.get(is_host ? 'controller.hostModeTarget.id' : 'controller.id'),
|
var target = controller.get(is_host ? 'controller.hostModeTarget.id' : 'controller.id'),
|
||||||
user = f.get_user(),
|
user = f.get_user(),
|
||||||
|
@ -454,7 +454,7 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
var container = el && el.querySelector('.stats-and-actions .channel-stats'),
|
var container = el && el.querySelector('.stats-and-actions .channel-stats'),
|
||||||
stat_el = container && container.querySelector('#ffz-ui-player-stats'),
|
stat_el = container && container.querySelector('#ffz-ui-player-stats'),
|
||||||
el = stat_el && stat_el.querySelector('span'),
|
el = stat_el && stat_el.querySelector('span'),
|
||||||
|
|
||||||
player_cont = f.players && f.players[channel_id],
|
player_cont = f.players && f.players[channel_id],
|
||||||
player = player_cont && player_cont.player,
|
player = player_cont && player_cont.player,
|
||||||
stats = player && player.stats;
|
stats = player && player.stats;
|
||||||
|
@ -468,29 +468,29 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
stat_el = document.createElement('span');
|
stat_el = document.createElement('span');
|
||||||
stat_el.id = 'ffz-ui-player-stats';
|
stat_el.id = 'ffz-ui-player-stats';
|
||||||
stat_el.className = 'ffz stat tooltip';
|
stat_el.className = 'ffz stat tooltip';
|
||||||
|
|
||||||
stat_el.innerHTML = constants.GRAPH + " ";
|
stat_el.innerHTML = constants.GRAPH + " ";
|
||||||
el = document.createElement('span');
|
el = document.createElement('span');
|
||||||
stat_el.appendChild(el);
|
stat_el.appendChild(el);
|
||||||
|
|
||||||
var other = container.querySelector('#ffz-uptime-display');
|
var other = container.querySelector('#ffz-uptime-display');
|
||||||
if ( other )
|
if ( other )
|
||||||
container.insertBefore(stat_el, other.nextSibling);
|
container.insertBefore(stat_el, other.nextSibling);
|
||||||
else
|
else
|
||||||
container.appendChild(stat_el);
|
container.appendChild(stat_el);
|
||||||
}
|
}
|
||||||
|
|
||||||
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
||||||
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( hosted_id ) {
|
if ( hosted_id ) {
|
||||||
var container = el && el.querySelector('#hostmode .channel-stats'),
|
var container = el && el.querySelector('#hostmode .channel-stats'),
|
||||||
stat_el = container && container.querySelector('#ffz-ui-player-stats'),
|
stat_el = container && container.querySelector('#ffz-ui-player-stats'),
|
||||||
el = stat_el && stat_el.querySelector('span'),
|
el = stat_el && stat_el.querySelector('span'),
|
||||||
|
|
||||||
player_cont = f.players && f.players[hosted_id],
|
player_cont = f.players && f.players[hosted_id],
|
||||||
player = player_cont && player_cont.player,
|
player = player_cont && player_cont.player,
|
||||||
stats = player && player.stats;
|
stats = player && player.stats;
|
||||||
|
@ -504,22 +504,22 @@ FFZ.prototype._modify_cindex = function(view) {
|
||||||
stat_el = document.createElement('span');
|
stat_el = document.createElement('span');
|
||||||
stat_el.id = 'ffz-ui-player-stats';
|
stat_el.id = 'ffz-ui-player-stats';
|
||||||
stat_el.className = 'ffz stat tooltip';
|
stat_el.className = 'ffz stat tooltip';
|
||||||
|
|
||||||
stat_el.innerHTML = constants.GRAPH + " ";
|
stat_el.innerHTML = constants.GRAPH + " ";
|
||||||
el = document.createElement('span');
|
el = document.createElement('span');
|
||||||
stat_el.appendChild(el);
|
stat_el.appendChild(el);
|
||||||
|
|
||||||
var other = container.querySelector('#ffz-uptime-display');
|
var other = container.querySelector('#ffz-uptime-display');
|
||||||
if ( other )
|
if ( other )
|
||||||
container.insertBefore(stat_el, other.nextSibling);
|
container.insertBefore(stat_el, other.nextSibling);
|
||||||
else
|
else
|
||||||
container.appendChild(stat_el);
|
container.appendChild(stat_el);
|
||||||
}
|
}
|
||||||
|
|
||||||
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
stat_el.title = 'Stream Latency\nFPS: ' + stats.fps + '\nPlayback Rate: ' + stats.playbackRate + ' Kbps';
|
||||||
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
el.textContent = stats.hlsLatencyBroadcaster + 's';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -667,10 +667,10 @@ FFZ.settings_info.hosted_channels = {
|
||||||
var cb = document.querySelector('input.ffz-setting-hosted-channels');
|
var cb = document.querySelector('input.ffz-setting-hosted-channels');
|
||||||
if ( cb )
|
if ( cb )
|
||||||
cb.checked = val;
|
cb.checked = val;
|
||||||
|
|
||||||
if ( ! this._cindex )
|
if ( ! this._cindex )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var chan = this._cindex.get('controller.model'),
|
var chan = this._cindex.get('controller.model'),
|
||||||
room = chan && this.rooms && this.rooms[chan.get('id')],
|
room = chan && this.rooms && this.rooms[chan.get('id')],
|
||||||
target = room && room.room && room.room.get('ffz_host_target');
|
target = room && room.room && room.room.get('ffz_host_target');
|
||||||
|
|
|
@ -12,7 +12,7 @@ FFZ.settings_info.minimal_chat = {
|
||||||
value: false,
|
value: false,
|
||||||
|
|
||||||
category: "Chat Appearance",
|
category: "Chat Appearance",
|
||||||
|
|
||||||
name: "Minimalistic Chat",
|
name: "Minimalistic Chat",
|
||||||
help: "Hide all of the chat user interface, only showing messages and an input box.",
|
help: "Hide all of the chat user interface, only showing messages and an input box.",
|
||||||
|
|
||||||
|
@ -25,22 +25,22 @@ FFZ.settings_info.minimal_chat = {
|
||||||
f._roomv && f._roomv.get('stuckToBottom') && f._roomv._scrollToBottom();
|
f._roomv && f._roomv.get('stuckToBottom') && f._roomv._scrollToBottom();
|
||||||
},0);
|
},0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this._chatv && this._chatv.get('controller.showList') )
|
if ( this._chatv && this._chatv.get('controller.showList') )
|
||||||
this._chatv.set('controller.showList', false);
|
this._chatv.set('controller.showList', false);
|
||||||
|
|
||||||
// Remove the style if we have it.
|
// Remove the style if we have it.
|
||||||
if ( ! val && this._chat_style ) {
|
if ( ! val && this._chat_style ) {
|
||||||
if ( this._inputv ) {
|
if ( this._inputv ) {
|
||||||
if ( this._inputv._ffz_minimal_style )
|
if ( this._inputv._ffz_minimal_style )
|
||||||
this._inputv._ffz_minimal_style.innerHTML = '';
|
this._inputv._ffz_minimal_style.innerHTML = '';
|
||||||
|
|
||||||
this._inputv._ffz_last_height = undefined;
|
this._inputv._ffz_last_height = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.update_css(this._chat_style, "input_height", '');
|
utils.update_css(this._chat_style, "input_height", '');
|
||||||
this._roomv && this._roomv.get('stuckToBottom') && this._roomv._scrollToBottom();
|
this._roomv && this._roomv.get('stuckToBottom') && this._roomv._scrollToBottom();
|
||||||
|
|
||||||
} else if ( this._inputv )
|
} else if ( this._inputv )
|
||||||
this._inputv.ffzResizeInput();
|
this._inputv.ffzResizeInput();
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ FFZ.settings_info.remove_deleted = {
|
||||||
total = msgs.get('length'),
|
total = msgs.get('length'),
|
||||||
i = total,
|
i = total,
|
||||||
alternate;
|
alternate;
|
||||||
|
|
||||||
while(i--) {
|
while(i--) {
|
||||||
var msg = msgs.get(i);
|
var msg = msgs.get(i);
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ FFZ.settings_info.remove_deleted = {
|
||||||
msgs.removeAt(i);
|
msgs.removeAt(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( alternate === undefined )
|
if ( alternate === undefined )
|
||||||
alternate = msg.ffz_alternate;
|
alternate = msg.ffz_alternate;
|
||||||
else {
|
else {
|
||||||
|
@ -186,11 +186,11 @@ FFZ.prototype.setup_chatview = function() {
|
||||||
ffzUpdateChannels: function() {
|
ffzUpdateChannels: function() {
|
||||||
if ( ! f._chatv )
|
if ( ! f._chatv )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
f._chatv.ffzRebuildMenu();
|
f._chatv.ffzRebuildMenu();
|
||||||
if ( f.settings.group_tabs )
|
if ( f.settings.group_tabs )
|
||||||
f._chatv.ffzRebuildTabs();
|
f._chatv.ffzRebuildTabs();
|
||||||
|
|
||||||
}.observes("currentChannelRoom", "connectedPrivateGroupRooms"),
|
}.observes("currentChannelRoom", "connectedPrivateGroupRooms"),
|
||||||
|
|
||||||
removeCurrentChannelRoom: function() {
|
removeCurrentChannelRoom: function() {
|
||||||
|
@ -204,7 +204,7 @@ FFZ.prototype.setup_chatview = function() {
|
||||||
if ( ! f.settings.pinned_rooms || f.settings.pinned_rooms.indexOf(room_id) === -1 ) {
|
if ( ! f.settings.pinned_rooms || f.settings.pinned_rooms.indexOf(room_id) === -1 ) {
|
||||||
if ( room === this.get("currentRoom") )
|
if ( room === this.get("currentRoom") )
|
||||||
this.blurRoom();
|
this.blurRoom();
|
||||||
|
|
||||||
// Don't destroy it if it's the user's room.
|
// Don't destroy it if it's the user's room.
|
||||||
if ( room && user && user.login === room_id )
|
if ( room && user && user.login === room_id )
|
||||||
room.destroy();
|
room.destroy();
|
||||||
|
@ -292,7 +292,7 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
ffzInit: function() {
|
ffzInit: function() {
|
||||||
f._chatv = this;
|
f._chatv = this;
|
||||||
this.$('.textarea-contain').append(f.build_ui_link(this));
|
this.$('.textarea-contain').append(f.build_ui_link(this));
|
||||||
this.$('.chat-messages').find('.html-tooltip').tipsy({live: true, html: true});
|
this.$('.chat-messages').find('.html-tooltip').tipsy({live: true, html: true, gravity: jQuery.fn.tipsy.autoNS});
|
||||||
|
|
||||||
if ( !f.has_bttv && f.settings.group_tabs )
|
if ( !f.has_bttv && f.settings.group_tabs )
|
||||||
this.ffzEnableTabs();
|
this.ffzEnableTabs();
|
||||||
|
@ -330,7 +330,7 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
if ( room )
|
if ( room )
|
||||||
rows.children('.ffz-room-row[data-room="' + room.get('id') + '"]').addClass('active').children('span').text('');
|
rows.children('.ffz-room-row[data-room="' + room.get('id') + '"]').addClass('active').children('span').text('');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this._ffz_group_table ) {
|
if ( this._ffz_group_table ) {
|
||||||
rows = jQuery(this._ffz_group_table);
|
rows = jQuery(this._ffz_group_table);
|
||||||
rows.children('.ffz-room-row').removeClass('active');
|
rows.children('.ffz-room-row').removeClass('active');
|
||||||
|
@ -361,23 +361,23 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Better Menu
|
// Better Menu
|
||||||
|
|
||||||
ffzRebuildMenu: function() {
|
ffzRebuildMenu: function() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var el = this.get('element'),
|
var el = this.get('element'),
|
||||||
room_list = el && el.querySelector('.chat-rooms .tse-content');
|
room_list = el && el.querySelector('.chat-rooms .tse-content');
|
||||||
|
|
||||||
if ( ! room_list )
|
if ( ! room_list )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ! room_list.classList.contains('ffz-room-list') ) {
|
if ( ! room_list.classList.contains('ffz-room-list') ) {
|
||||||
room_list.classList.add('ffz-room-list');
|
room_list.classList.add('ffz-room-list');
|
||||||
|
|
||||||
// Find the Pending Invitations
|
// Find the Pending Invitations
|
||||||
var headers = room_list.querySelectorAll('.list-header'),
|
var headers = room_list.querySelectorAll('.list-header'),
|
||||||
hdr = headers.length ? headers[headers.length-1] : undefined;
|
hdr = headers.length ? headers[headers.length-1] : undefined;
|
||||||
|
|
||||||
if ( hdr ) {
|
if ( hdr ) {
|
||||||
hdr.classList.add('ffz');
|
hdr.classList.add('ffz');
|
||||||
if ( hdr.nextSibling && hdr.nextSibling.classList )
|
if ( hdr.nextSibling && hdr.nextSibling.classList )
|
||||||
|
@ -389,7 +389,7 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
// Channel Table
|
// Channel Table
|
||||||
var t = this,
|
var t = this,
|
||||||
chan_table = this._ffz_chan_table || room_list.querySelector('#ffz-channel-table tbody');
|
chan_table = this._ffz_chan_table || room_list.querySelector('#ffz-channel-table tbody');
|
||||||
|
|
||||||
if ( ! chan_table ) {
|
if ( ! chan_table ) {
|
||||||
var tbl = document.createElement('table');
|
var tbl = document.createElement('table');
|
||||||
tbl.setAttribute('cellspacing', 0);
|
tbl.setAttribute('cellspacing', 0);
|
||||||
|
@ -409,13 +409,13 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
row = this.ffzBuildRow(this, room, true);
|
row = this.ffzBuildRow(this, room, true);
|
||||||
row && chan_table.appendChild(row);
|
row && chan_table.appendChild(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host Target
|
// Host Target
|
||||||
if ( this._ffz_host_room ) {
|
if ( this._ffz_host_room ) {
|
||||||
row = this.ffzBuildRow(this, this._ffz_host_room, false, true);
|
row = this.ffzBuildRow(this, this._ffz_host_room, false, true);
|
||||||
row && chan_table.appendChild(row);
|
row && chan_table.appendChild(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinned Rooms
|
// Pinned Rooms
|
||||||
for(var i=0; i < f.settings.pinned_rooms.length; i++) {
|
for(var i=0; i < f.settings.pinned_rooms.length; i++) {
|
||||||
var room_id = f.settings.pinned_rooms[i];
|
var room_id = f.settings.pinned_rooms[i];
|
||||||
|
@ -424,8 +424,8 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
row && chan_table.appendChild(row);
|
row && chan_table.appendChild(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Group Chat Table
|
// Group Chat Table
|
||||||
var group_table = this._ffz_group_table || room_list.querySelector('#ffz-group-table tbody');
|
var group_table = this._ffz_group_table || room_list.querySelector('#ffz-group-table tbody');
|
||||||
if ( ! group_table ) {
|
if ( ! group_table ) {
|
||||||
|
@ -434,49 +434,49 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
tbl.id = 'ffz-group-table';
|
tbl.id = 'ffz-group-table';
|
||||||
tbl.className = 'ffz';
|
tbl.className = 'ffz';
|
||||||
tbl.innerHTML = '<thead><tr><th colspan="2">Group Chats</th><th class="ffz-row-switch">Pin</th></tr></thead><tbody></tbody>';
|
tbl.innerHTML = '<thead><tr><th colspan="2">Group Chats</th><th class="ffz-row-switch">Pin</th></tr></thead><tbody></tbody>';
|
||||||
|
|
||||||
var before = room_list.querySelector('#ffz-channel-table');
|
var before = room_list.querySelector('#ffz-channel-table');
|
||||||
room_list.insertBefore(tbl, before.nextSibling);
|
room_list.insertBefore(tbl, before.nextSibling);
|
||||||
|
|
||||||
group_table = this._ffz_group_table = tbl.querySelector('tbody');
|
group_table = this._ffz_group_table = tbl.querySelector('tbody');
|
||||||
}
|
}
|
||||||
|
|
||||||
group_table.innerHTML = '';
|
group_table.innerHTML = '';
|
||||||
|
|
||||||
_.each(this.get('controller.connectedPrivateGroupRooms'), function(room) {
|
_.each(this.get('controller.connectedPrivateGroupRooms'), function(room) {
|
||||||
var row = t.ffzBuildRow(t, room);
|
var row = t.ffzBuildRow(t, room);
|
||||||
row && group_table && group_table.appendChild(row);
|
row && group_table && group_table.appendChild(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Change Create Tooltip
|
// Change Create Tooltip
|
||||||
var create_btn = el.querySelector('.button.create');
|
var create_btn = el.querySelector('.button.create');
|
||||||
if ( create_btn )
|
if ( create_btn )
|
||||||
create_btn.title = 'Create a Group Room';
|
create_btn.title = 'Create a Group Room';
|
||||||
},
|
},
|
||||||
|
|
||||||
ffzBuildRow: function(view, room, current_channel, host_channel) {
|
ffzBuildRow: function(view, room, current_channel, host_channel) {
|
||||||
var row = document.createElement('tr'),
|
var row = document.createElement('tr'),
|
||||||
icon = document.createElement('td'),
|
icon = document.createElement('td'),
|
||||||
name_el = document.createElement('td'),
|
name_el = document.createElement('td'),
|
||||||
|
|
||||||
btn,
|
btn,
|
||||||
toggle_pinned = document.createElement('td'),
|
toggle_pinned = document.createElement('td'),
|
||||||
toggle_visible = document.createElement('td'),
|
toggle_visible = document.createElement('td'),
|
||||||
|
|
||||||
group = room.get('isGroupRoom'),
|
group = room.get('isGroupRoom'),
|
||||||
current = room === view.get('controller.currentRoom'),
|
current = room === view.get('controller.currentRoom'),
|
||||||
//unread = format_unread(current ? 0 : room.get('unreadCount')),
|
//unread = format_unread(current ? 0 : room.get('unreadCount')),
|
||||||
|
|
||||||
name = room.get('tmiRoom.displayName') || (group ? room.get('tmiRoom.name') : FFZ.get_capitalization(room.get('id'), function(name) {
|
name = room.get('tmiRoom.displayName') || (group ? room.get('tmiRoom.name') : FFZ.get_capitalization(room.get('id'), function(name) {
|
||||||
f.log("Name for Row: " + name);
|
f.log("Name for Row: " + name);
|
||||||
//unread = format_unread(current ? 0 : room.get('unreadCount'));
|
//unread = format_unread(current ? 0 : room.get('unreadCount'));
|
||||||
name_el.innerHTML = utils.sanitize(name);
|
name_el.innerHTML = utils.sanitize(name);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
name_el.className = 'ffz-room';
|
name_el.className = 'ffz-room';
|
||||||
name_el.innerHTML = utils.sanitize(name);
|
name_el.innerHTML = utils.sanitize(name);
|
||||||
|
|
||||||
if ( current_channel ) {
|
if ( current_channel ) {
|
||||||
icon.innerHTML = constants.CAMERA;
|
icon.innerHTML = constants.CAMERA;
|
||||||
icon.title = name_el.title = "Current Channel";
|
icon.title = name_el.title = "Current Channel";
|
||||||
|
@ -486,12 +486,12 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
icon.title = name_el.title = "Hosted Channel";
|
icon.title = name_el.title = "Hosted Channel";
|
||||||
icon.className = name_el.className = 'tooltip';
|
icon.className = name_el.className = 'tooltip';
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_pinned.className = toggle_visible.className = 'ffz-row-switch';
|
toggle_pinned.className = toggle_visible.className = 'ffz-row-switch';
|
||||||
|
|
||||||
toggle_pinned.innerHTML = '<a class="switch' + (f.settings.pinned_rooms.indexOf(room.get('id')) !== -1 ? ' active' : '') + '"><span></span></a>';
|
toggle_pinned.innerHTML = '<a class="switch' + (f.settings.pinned_rooms.indexOf(room.get('id')) !== -1 ? ' active' : '') + '"><span></span></a>';
|
||||||
toggle_visible.innerHTML = '<a class="switch' + (f.settings.visible_rooms.indexOf(room.get('id')) !== -1 ? ' active' : '') + '"><span></span></a>';
|
toggle_visible.innerHTML = '<a class="switch' + (f.settings.visible_rooms.indexOf(room.get('id')) !== -1 ? ' active' : '') + '"><span></span></a>';
|
||||||
|
|
||||||
row.setAttribute('data-room', room.get('id'));
|
row.setAttribute('data-room', room.get('id'));
|
||||||
|
|
||||||
row.className = 'ffz-room-row';
|
row.className = 'ffz-room-row';
|
||||||
|
@ -499,20 +499,20 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
row.classList.toggle('host-channel', host_channel);
|
row.classList.toggle('host-channel', host_channel);
|
||||||
row.classList.toggle('group-chat', group);
|
row.classList.toggle('group-chat', group);
|
||||||
row.classList.toggle('active', current);
|
row.classList.toggle('active', current);
|
||||||
|
|
||||||
row.appendChild(icon);
|
row.appendChild(icon);
|
||||||
row.appendChild(name_el);
|
row.appendChild(name_el);
|
||||||
|
|
||||||
if ( ! group ) {
|
if ( ! group ) {
|
||||||
row.appendChild(toggle_pinned);
|
row.appendChild(toggle_pinned);
|
||||||
btn = toggle_pinned.querySelector('a.switch');
|
btn = toggle_pinned.querySelector('a.switch');
|
||||||
btn.addEventListener('click', function(e) {
|
btn.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation && e.stopPropagation();
|
e.stopPropagation && e.stopPropagation();
|
||||||
|
|
||||||
var room_id = room.get('id'),
|
var room_id = room.get('id'),
|
||||||
is_pinned = f.settings.pinned_rooms.indexOf(room_id) !== -1;
|
is_pinned = f.settings.pinned_rooms.indexOf(room_id) !== -1;
|
||||||
|
|
||||||
if ( is_pinned )
|
if ( is_pinned )
|
||||||
f._leave_room(room_id);
|
f._leave_room(room_id);
|
||||||
else
|
else
|
||||||
|
@ -527,14 +527,14 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
btn.title = 'Leave Group';
|
btn.title = 'Leave Group';
|
||||||
|
|
||||||
name_el.appendChild(btn);
|
name_el.appendChild(btn);
|
||||||
|
|
||||||
btn.addEventListener('click', function(e) {
|
btn.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation && e.stopPropagation();
|
e.stopPropagation && e.stopPropagation();
|
||||||
|
|
||||||
if ( ! confirm('Are you sure you want to leave the group room "' + name + '"?') )
|
if ( ! confirm('Are you sure you want to leave the group room "' + name + '"?') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
room.get('isGroupRoom') && room.del();
|
room.get('isGroupRoom') && room.del();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -544,12 +544,12 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
btn.addEventListener('click', function(e) {
|
btn.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation && e.stopPropagation();
|
e.stopPropagation && e.stopPropagation();
|
||||||
|
|
||||||
var room_id = room.get('id'),
|
var room_id = room.get('id'),
|
||||||
visible_rooms = f.settings.visible_rooms,
|
visible_rooms = f.settings.visible_rooms,
|
||||||
is_visible = visible_rooms.indexOf(room_id) !== -1;
|
is_visible = visible_rooms.indexOf(room_id) !== -1;
|
||||||
|
|
||||||
if ( is_visible )
|
if ( is_visible )
|
||||||
visible_rooms.removeObject(room_id);
|
visible_rooms.removeObject(room_id);
|
||||||
else
|
else
|
||||||
visible_rooms.push(room_id);
|
visible_rooms.push(room_id);
|
||||||
|
@ -558,13 +558,13 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
this.classList.toggle('active', !is_visible);
|
this.classList.toggle('active', !is_visible);
|
||||||
view.ffzRebuildTabs();
|
view.ffzRebuildTabs();
|
||||||
});
|
});
|
||||||
|
|
||||||
row.addEventListener('click', function() {
|
row.addEventListener('click', function() {
|
||||||
var controller = view.get('controller');
|
var controller = view.get('controller');
|
||||||
controller.focusRoom(room);
|
controller.focusRoom(room);
|
||||||
controller.set('showList', false);
|
controller.set('showList', false);
|
||||||
});
|
});
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -684,7 +684,7 @@ FFZ.prototype._modify_cview = function(view) {
|
||||||
|
|
||||||
ffzTabUnread: function(room_id) {
|
ffzTabUnread: function(room_id) {
|
||||||
// TODO: Update menu.
|
// TODO: Update menu.
|
||||||
|
|
||||||
if ( f.has_bttv || ! f.settings.group_tabs )
|
if ( f.has_bttv || ! f.settings.group_tabs )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -803,7 +803,7 @@ FFZ.prototype.connect_extra_chat = function() {
|
||||||
r = Room && Room.findOne(user.login);
|
r = Room && Room.findOne(user.login);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this.has_bttv )
|
if ( this.has_bttv )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,8 @@ FFZ.settings_info.replace_bad_emotes = {
|
||||||
|
|
||||||
name: "Fix Low Quality Twitch Global Emoticons",
|
name: "Fix Low Quality Twitch Global Emoticons",
|
||||||
help: "Replace emoticons such as DansGame and RedCoat with cleaned up versions that don't have pixels around the edges or white backgrounds for nicer display on dark chat."
|
help: "Replace emoticons such as DansGame and RedCoat with cleaned up versions that don't have pixels around the edges or white backgrounds for nicer display on dark chat."
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
FFZ.settings_info.parse_emoji = {
|
FFZ.settings_info.parse_emoji = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
|
@ -211,7 +212,6 @@ FFZ.settings_info.clickable_emoticons = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FFZ.settings_info.link_info = {
|
FFZ.settings_info.link_info = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true,
|
value: true,
|
||||||
|
@ -333,7 +333,7 @@ FFZ.settings_info.high_contrast_chat = {
|
||||||
'112': "Background + Bold",
|
'112': "Background + Bold",
|
||||||
'111': 'All'
|
'111': 'All'
|
||||||
},
|
},
|
||||||
value: '000',
|
value: '222',
|
||||||
|
|
||||||
category: "Chat Appearance",
|
category: "Chat Appearance",
|
||||||
no_bttv: true,
|
no_bttv: true,
|
||||||
|
@ -343,7 +343,7 @@ FFZ.settings_info.high_contrast_chat = {
|
||||||
|
|
||||||
process_value: function(val) {
|
process_value: function(val) {
|
||||||
if ( val === false )
|
if ( val === false )
|
||||||
return '000';
|
return '222';
|
||||||
else if ( val === true )
|
else if ( val === true )
|
||||||
return '111';
|
return '111';
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -50,6 +50,43 @@ try {
|
||||||
// Settings
|
// Settings
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
|
FFZ.basic_settings.enhanced_moderation_cards = {
|
||||||
|
type: "boolean",
|
||||||
|
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
name: "Enhanced Moderation Cards",
|
||||||
|
help: "Improve moderation cards with hotkeys, additional buttons, chat history, and other information to make moderating easier.",
|
||||||
|
|
||||||
|
get: function() {
|
||||||
|
return this.settings.mod_card_hotkeys &&
|
||||||
|
this.settings.mod_card_info &&
|
||||||
|
this.settings.mod_card_history;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('mod_card_hotkeys', val);
|
||||||
|
this.settings.set('mod_card_info', val);
|
||||||
|
this.settings.set('mod_card_history', val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
FFZ.basic_settings.chat_hover_pause = {
|
||||||
|
type: "boolean",
|
||||||
|
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
name: "Pause Chat Scrolling on Mouse Hover",
|
||||||
|
help: "Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",
|
||||||
|
|
||||||
|
get: 'chat_hover_pause',
|
||||||
|
set: 'chat_hover_pause'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
FFZ.settings_info.chat_hover_pause = {
|
FFZ.settings_info.chat_hover_pause = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false,
|
value: false,
|
||||||
|
@ -58,7 +95,7 @@ FFZ.settings_info.chat_hover_pause = {
|
||||||
|
|
||||||
category: "Chat Moderation",
|
category: "Chat Moderation",
|
||||||
name: "Pause Chat Scrolling on Mouse Hover",
|
name: "Pause Chat Scrolling on Mouse Hover",
|
||||||
help: "Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link mis-clicks.",
|
help: "Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",
|
||||||
|
|
||||||
on_update: function(val) {
|
on_update: function(val) {
|
||||||
if ( ! this._roomv )
|
if ( ! this._roomv )
|
||||||
|
@ -151,7 +188,7 @@ FFZ.settings_info.mod_card_buttons = {
|
||||||
else
|
else
|
||||||
old_val += ' ' + cmd;
|
old_val += ' ' + cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
var new_val = prompt("Moderation Card Additional Buttons\n\nPlease enter a list of additional commands to display buttons for on moderation cards. 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}\"", old_val);
|
var new_val = prompt("Moderation Card Additional Buttons\n\nPlease enter a list of additional commands to display buttons for on moderation cards. 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}\"", old_val);
|
||||||
|
|
||||||
if ( new_val === null || new_val === undefined )
|
if ( new_val === null || new_val === undefined )
|
||||||
|
@ -159,7 +196,7 @@ FFZ.settings_info.mod_card_buttons = {
|
||||||
|
|
||||||
var vals = [];
|
var vals = [];
|
||||||
new_val = new_val.trim();
|
new_val = new_val.trim();
|
||||||
|
|
||||||
while(new_val) {
|
while(new_val) {
|
||||||
if ( new_val.charAt(0) === '"' ) {
|
if ( new_val.charAt(0) === '"' ) {
|
||||||
var end = new_val.indexOf('"', 1);
|
var end = new_val.indexOf('"', 1);
|
||||||
|
@ -170,8 +207,8 @@ FFZ.settings_info.mod_card_buttons = {
|
||||||
if ( segment )
|
if ( segment )
|
||||||
vals.push(segment);
|
vals.push(segment);
|
||||||
|
|
||||||
new_val = new_val.substr(end + 1);
|
new_val = new_val.substr(end + 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var ind = new_val.indexOf(' ');
|
var ind = new_val.indexOf(' ');
|
||||||
if ( ind === -1 ) {
|
if ( ind === -1 ) {
|
||||||
|
@ -274,7 +311,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
|
|
||||||
if ( typeof followers === "number" ) {
|
if ( typeof followers === "number" ) {
|
||||||
out += '<span class="stat tooltip" title="Followers">' + constants.HEART + ' ' + utils.number_commas(followers || 0) + '</span>';
|
out += '<span class="stat tooltip" title="Followers">' + constants.HEART + ' ' + utils.number_commas(followers || 0) + '</span>';
|
||||||
|
|
||||||
} else if ( followers === undefined ) {
|
} else if ( followers === undefined ) {
|
||||||
var t = this;
|
var t = this;
|
||||||
this.set('cardInfo.user.ffz_followers', false);
|
this.set('cardInfo.user.ffz_followers', false);
|
||||||
|
@ -299,7 +336,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
userName: Ember.computed("cardInfo.user.id", "cardInfo.user.display_name", function() {
|
userName: Ember.computed("cardInfo.user.id", "cardInfo.user.display_name", function() {
|
||||||
var user_id = this.get("cardInfo.user.id"),
|
var user_id = this.get("cardInfo.user.id"),
|
||||||
alias = f.aliases[user_id];
|
alias = f.aliases[user_id];
|
||||||
|
|
||||||
return alias || this.get("cardInfo.user.display_name") || user_id.capitalize();
|
return alias || this.get("cardInfo.user.display_name") || user_id.capitalize();
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -313,7 +350,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
var el = this.get('element'),
|
var el = this.get('element'),
|
||||||
controller = this.get('controller'),
|
controller = this.get('controller'),
|
||||||
line,
|
line,
|
||||||
|
|
||||||
user_id = controller.get('cardInfo.user.id'),
|
user_id = controller.get('cardInfo.user.id'),
|
||||||
alias = f.aliases[user_id];
|
alias = f.aliases[user_id];
|
||||||
|
|
||||||
|
@ -340,7 +377,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
after = el.querySelector('h3.name');
|
after = el.querySelector('h3.name');
|
||||||
if ( after ) {
|
if ( after ) {
|
||||||
el.classList.add('ffz-has-info');
|
el.classList.add('ffz-has-info');
|
||||||
info.className = 'info channel-stats';
|
info.className = 'info channel-stats';
|
||||||
after.parentElement.insertBefore(info, after.nextSibling);
|
after.parentElement.insertBefore(info, after.nextSibling);
|
||||||
this.ffzRebuildInfo();
|
this.ffzRebuildInfo();
|
||||||
}
|
}
|
||||||
|
@ -350,16 +387,16 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
if ( f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
|
if ( f.settings.mod_card_buttons && f.settings.mod_card_buttons.length ) {
|
||||||
line = document.createElement('div');
|
line = document.createElement('div');
|
||||||
line.className = 'extra-interface interface clearfix';
|
line.className = 'extra-interface interface clearfix';
|
||||||
|
|
||||||
var cmds = {},
|
var cmds = {},
|
||||||
add_btn_click = function(cmd) {
|
add_btn_click = function(cmd) {
|
||||||
var user_id = controller.get('cardInfo.user.id'),
|
var user_id = controller.get('cardInfo.user.id'),
|
||||||
cont = App.__container__.lookup('controller:chat'),
|
cont = App.__container__.lookup('controller:chat'),
|
||||||
room = cont && cont.get('currentRoom');
|
room = cont && cont.get('currentRoom');
|
||||||
|
|
||||||
room && room.send(cmd.replace(/{user}/g, user_id));
|
room && room.send(cmd.replace(/{user}/g, user_id));
|
||||||
},
|
},
|
||||||
|
|
||||||
add_btn_make = function(cmd) {
|
add_btn_make = function(cmd) {
|
||||||
var btn = document.createElement('button'),
|
var btn = document.createElement('button'),
|
||||||
segment = cmd.split(' ', 1)[0],
|
segment = cmd.split(' ', 1)[0],
|
||||||
|
@ -373,12 +410,12 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
btn.className = 'button';
|
btn.className = 'button';
|
||||||
btn.innerHTML = utils.sanitize(title);
|
btn.innerHTML = utils.sanitize(title);
|
||||||
btn.title = utils.sanitize(cmd.replace(/{user}/g, controller.get('cardInfo.user.id') || '{user}'));
|
btn.title = utils.sanitize(cmd.replace(/{user}/g, controller.get('cardInfo.user.id') || '{user}'));
|
||||||
|
|
||||||
jQuery(btn).tipsy();
|
jQuery(btn).tipsy();
|
||||||
btn.addEventListener('click', add_btn_click.bind(this, cmd));
|
btn.addEventListener('click', add_btn_click.bind(this, cmd));
|
||||||
return btn;
|
return btn;
|
||||||
};
|
};
|
||||||
|
|
||||||
var cmds = {};
|
var cmds = {};
|
||||||
for(var i=0; i < f.settings.mod_card_buttons.length; i++)
|
for(var i=0; i < f.settings.mod_card_buttons.length; i++)
|
||||||
cmds[f.settings.mod_card_buttons[i].split(' ',1)[0]] = (cmds[f.settings.mod_card_buttons[i].split(' ',1)[0]] || 0) + 1;
|
cmds[f.settings.mod_card_buttons[i].split(' ',1)[0]] = (cmds[f.settings.mod_card_buttons[i].split(' ',1)[0]] || 0) + 1;
|
||||||
|
@ -392,7 +429,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
|
|
||||||
line.appendChild(add_btn_make(cmd))
|
line.appendChild(add_btn_make(cmd))
|
||||||
}
|
}
|
||||||
|
|
||||||
el.appendChild(line);
|
el.appendChild(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +468,7 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
// Only do the big stuff if we're mod.
|
// Only do the big stuff if we're mod.
|
||||||
if ( controller.get('cardInfo.isModeratorOrHigher') ) {
|
if ( controller.get('cardInfo.isModeratorOrHigher') ) {
|
||||||
el.classList.add('ffz-is-mod');
|
el.classList.add('ffz-is-mod');
|
||||||
|
|
||||||
// Key Handling
|
// Key Handling
|
||||||
if ( f.settings.mod_card_hotkeys ) {
|
if ( f.settings.mod_card_hotkeys ) {
|
||||||
el.classList.add('no-mousetrap');
|
el.classList.add('no-mousetrap');
|
||||||
|
@ -544,31 +581,31 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
|
|
||||||
msg_btn.title = "Whisper User";
|
msg_btn.title = "Whisper User";
|
||||||
jQuery(msg_btn).tipsy();
|
jQuery(msg_btn).tipsy();
|
||||||
|
|
||||||
|
|
||||||
var real_msg = document.createElement('button');
|
var real_msg = document.createElement('button');
|
||||||
real_msg.className = 'message-button button glyph-only message tooltip';
|
real_msg.className = 'message-button button glyph-only message tooltip';
|
||||||
real_msg.innerHTML = MESSAGE;
|
real_msg.innerHTML = MESSAGE;
|
||||||
real_msg.title = "Message User";
|
real_msg.title = "Message User";
|
||||||
|
|
||||||
real_msg.addEventListener('click', function() {
|
real_msg.addEventListener('click', function() {
|
||||||
window.open('http://www.twitch.tv/message/compose?to=' + controller.get('cardInfo.user.id'));
|
window.open('http://www.twitch.tv/message/compose?to=' + controller.get('cardInfo.user.id'));
|
||||||
})
|
})
|
||||||
|
|
||||||
msg_btn.parentElement.insertBefore(real_msg, msg_btn.nextSibling);
|
msg_btn.parentElement.insertBefore(real_msg, msg_btn.nextSibling);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Alias Button
|
// Alias Button
|
||||||
var alias_btn = document.createElement('button');
|
var alias_btn = document.createElement('button');
|
||||||
alias_btn.className = 'alias button glyph-only tooltip';
|
alias_btn.className = 'alias button glyph-only tooltip';
|
||||||
alias_btn.innerHTML = constants.EDIT;
|
alias_btn.innerHTML = constants.EDIT;
|
||||||
alias_btn.title = "Set Alias";
|
alias_btn.title = "Set Alias";
|
||||||
|
|
||||||
alias_btn.addEventListener('click', function() {
|
alias_btn.addEventListener('click', function() {
|
||||||
var user = controller.get('cardInfo.user.id'),
|
var user = controller.get('cardInfo.user.id'),
|
||||||
alias = f.aliases[user];
|
alias = f.aliases[user];
|
||||||
|
|
||||||
var new_val = prompt("Alias for User: " + user + "\n\nPlease enter an alias for the user. Leave it blank to remove the alias.", alias);
|
var new_val = prompt("Alias for User: " + user + "\n\nPlease enter an alias for the user. Leave it blank to remove the alias.", alias);
|
||||||
if ( new_val === null || new_val === undefined )
|
if ( new_val === null || new_val === undefined )
|
||||||
return;
|
return;
|
||||||
|
@ -579,20 +616,20 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
|
|
||||||
f.aliases[user] = new_val;
|
f.aliases[user] = new_val;
|
||||||
f.save_aliases();
|
f.save_aliases();
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
f._update_alias(user);
|
f._update_alias(user);
|
||||||
|
|
||||||
Ember.propertyDidChange(controller, 'userName');
|
Ember.propertyDidChange(controller, 'userName');
|
||||||
var name = el.querySelector('h3.name'),
|
var name = el.querySelector('h3.name'),
|
||||||
link = name && name.querySelector('a');
|
link = name && name.querySelector('a');
|
||||||
|
|
||||||
if ( link )
|
if ( link )
|
||||||
name = link;
|
name = link;
|
||||||
if ( name )
|
if ( name )
|
||||||
name.classList.toggle('ffz-alias', new_val);
|
name.classList.toggle('ffz-alias', new_val);
|
||||||
});
|
});
|
||||||
|
|
||||||
if ( msg_btn )
|
if ( msg_btn )
|
||||||
msg_btn.parentElement.insertBefore(alias_btn, msg_btn);
|
msg_btn.parentElement.insertBefore(alias_btn, msg_btn);
|
||||||
else {
|
else {
|
||||||
|
@ -676,22 +713,21 @@ FFZ.prototype.setup_mod_card = function() {
|
||||||
|
|
||||||
FFZ.prototype._update_alias = function(user) {
|
FFZ.prototype._update_alias = function(user) {
|
||||||
var alias = this.aliases && this.aliases[user],
|
var alias = this.aliases && this.aliases[user],
|
||||||
display_name = alias,
|
cap_name = FFZ.get_capitalization(user),
|
||||||
|
display_name = alias || cap_name,
|
||||||
el = this._roomv && this._roomv.get('element'),
|
el = this._roomv && this._roomv.get('element'),
|
||||||
lines = el && el.querySelectorAll('.chat-line[data-sender="' + user + '"]');
|
lines = el && el.querySelectorAll('.chat-line[data-sender="' + user + '"]');
|
||||||
|
|
||||||
if ( ! lines )
|
if ( ! lines )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( ! display_name )
|
|
||||||
display_name = FFZ.get_capitalization(user);
|
|
||||||
|
|
||||||
for(var i=0, l = lines.length; i < l; i++) {
|
for(var i=0, l = lines.length; i < l; i++) {
|
||||||
var line = lines[i],
|
var line = lines[i],
|
||||||
el_from = line.querySelector('.from');
|
el_from = line.querySelector('.from');
|
||||||
|
|
||||||
el_from.classList.toggle('ffz-alias', alias);
|
el_from.classList.toggle('ffz-alias', alias);
|
||||||
el_from.textContent = display_name;
|
el_from.textContent = display_name;
|
||||||
|
el_from.title = alias ? cap_name : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,12 @@ FFZ.prototype.setup_bttv = function(delay) {
|
||||||
this._dark_style.parentElement.removeChild(this._dark_style);
|
this._dark_style.parentElement.removeChild(this._dark_style);
|
||||||
this._dark_style = undefined;
|
this._dark_style = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this._layout_style ) {
|
if ( this._layout_style ) {
|
||||||
this._layout_style.parentElement.removeChild(this._layout_style);
|
this._layout_style.parentElement.removeChild(this._layout_style);
|
||||||
this._layout_style = undefined;
|
this._layout_style = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( this._chat_style ) {
|
if ( this._chat_style ) {
|
||||||
utils.update_css(this._chat_style, 'chat_font_size', '');
|
utils.update_css(this._chat_style, 'chat_font_size', '');
|
||||||
utils.update_css(this._chat_style, 'chat_ts_font_size', '');
|
utils.update_css(this._chat_style, 'chat_ts_font_size', '');
|
||||||
|
@ -76,6 +76,7 @@ FFZ.prototype.setup_bttv = function(delay) {
|
||||||
if ( this.settings.following_count ) {
|
if ( this.settings.following_count ) {
|
||||||
this._schedule_following_count();
|
this._schedule_following_count();
|
||||||
this._draw_following_count();
|
this._draw_following_count();
|
||||||
|
this._draw_following_channels();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove Sub Count
|
// Remove Sub Count
|
||||||
|
@ -186,7 +187,7 @@ FFZ.prototype.setup_bttv = function(delay) {
|
||||||
var original_emoticonize = BetterTTV.chat.templates.emoticonize;
|
var original_emoticonize = BetterTTV.chat.templates.emoticonize;
|
||||||
BetterTTV.chat.templates.emoticonize = function(message, emotes) {
|
BetterTTV.chat.templates.emoticonize = function(message, emotes) {
|
||||||
var tokens = original_emoticonize(message, emotes),
|
var tokens = original_emoticonize(message, emotes),
|
||||||
|
|
||||||
room = (received_room || BetterTTV.getChannel()),
|
room = (received_room || BetterTTV.getChannel()),
|
||||||
l_room = room && room.toLowerCase(),
|
l_room = room && room.toLowerCase(),
|
||||||
l_sender = received_sender && received_sender.toLowerCase(),
|
l_sender = received_sender && received_sender.toLowerCase(),
|
||||||
|
|
|
@ -21,7 +21,7 @@ FFZ.get = function() { return FFZ.instance; }
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
var VER = FFZ.version_info = {
|
var VER = FFZ.version_info = {
|
||||||
major: 3, minor: 5, revision: 10,
|
major: 3, minor: 5, revision: 12,
|
||||||
toString: function() {
|
toString: function() {
|
||||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||||
}
|
}
|
||||||
|
|
750
src/settings.js
750
src/settings.js
|
@ -1,5 +1,6 @@
|
||||||
var FFZ = window.FrankerFaceZ,
|
var FFZ = window.FrankerFaceZ,
|
||||||
constants = require("./constants");
|
constants = require("./constants"),
|
||||||
|
FileSaver = require("./FileSaver");
|
||||||
|
|
||||||
|
|
||||||
make_ls = function(key) {
|
make_ls = function(key) {
|
||||||
|
@ -11,9 +12,28 @@ var FFZ = window.FrankerFaceZ,
|
||||||
this.settings.set(key, val);
|
this.settings.set(key, val);
|
||||||
swit.classList.toggle('active', val);
|
swit.classList.toggle('active', val);
|
||||||
},
|
},
|
||||||
|
|
||||||
option_setting = function(select, key) {
|
option_setting = function(select, key) {
|
||||||
this.settings.set(key, JSON.parse(select.options[select.selectedIndex].value));
|
this.settings.set(key, JSON.parse(select.options[select.selectedIndex].value));
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
toggle_basic_setting = function(swit, key) {
|
||||||
|
var getter = FFZ.basic_settings[key].get,
|
||||||
|
val = !(typeof getter === 'function' ? getter.bind(this)() : this.settings.get(getter)),
|
||||||
|
|
||||||
|
setter = FFZ.basic_settings[key].set;
|
||||||
|
|
||||||
|
if ( typeof setter === 'function' )
|
||||||
|
setter.bind(this)(val);
|
||||||
|
else
|
||||||
|
this.settings.set(setter, val);
|
||||||
|
|
||||||
|
swit.classList.toggle('active', val);
|
||||||
|
},
|
||||||
|
|
||||||
|
option_basic_setting = function(select, key) {
|
||||||
|
FFZ.basic_settings[key].set.bind(this)(JSON.parse(select.options[select.selectedIndex].value));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +41,11 @@ var FFZ = window.FrankerFaceZ,
|
||||||
// Initializer
|
// Initializer
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
FFZ.settings_info = {};
|
FFZ.settings_info = {
|
||||||
|
advanced_settings: { value: false, visible: false }
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings = {};
|
||||||
|
|
||||||
FFZ.prototype.load_settings = function() {
|
FFZ.prototype.load_settings = function() {
|
||||||
this.log("Loading settings.");
|
this.log("Loading settings.");
|
||||||
|
@ -61,200 +85,610 @@ FFZ.prototype.load_settings = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Backup and Restore
|
||||||
|
// --------------------
|
||||||
|
|
||||||
|
FFZ.prototype.save_settings_file = function() {
|
||||||
|
var data = {
|
||||||
|
version: 1,
|
||||||
|
script_version: FFZ.version_info + '',
|
||||||
|
aliases: this.aliases,
|
||||||
|
settings: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(var key in FFZ.settings_info) {
|
||||||
|
if ( ! FFZ.settings_info.hasOwnProperty(key) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var info = FFZ.settings_info[key],
|
||||||
|
ls_key = info.storage_key || make_ls(key);
|
||||||
|
|
||||||
|
if ( localStorage.hasOwnProperty(ls_key) )
|
||||||
|
data.settings[key] = this.settings[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var blob = new Blob([JSON.stringify(data, null, 4)], {type: "application/json;charset=utf-8"});
|
||||||
|
FileSaver.saveAs(blob, "ffz-settings.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FFZ.prototype.load_settings_file = function(file) {
|
||||||
|
if ( typeof file === "string" )
|
||||||
|
this._load_settings_file(file);
|
||||||
|
else {
|
||||||
|
var reader = new FileReader(),
|
||||||
|
f = this;
|
||||||
|
|
||||||
|
reader.onload = function(e) { f._load_settings_file(e.target.result); }
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FFZ.prototype._load_settings_file = function(data) {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
} catch(err) {
|
||||||
|
this.error("Error Loading Settings: " + err);
|
||||||
|
return alert("There was an error attempting to read the provided settings data.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log("Loading Settings Data", data);
|
||||||
|
|
||||||
|
var skipped = [],
|
||||||
|
applied = [];
|
||||||
|
|
||||||
|
if ( data.settings ) {
|
||||||
|
for(var key in data.settings) {
|
||||||
|
if ( ! FFZ.settings_info.hasOwnProperty(key) ) {
|
||||||
|
skipped.push(key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = FFZ.settings_info[key],
|
||||||
|
val = data.settings[key];
|
||||||
|
|
||||||
|
if ( info.process_value )
|
||||||
|
val = info.process_value.bind(this)(val);
|
||||||
|
|
||||||
|
if ( val !== this.settings.get(key) )
|
||||||
|
this.settings.set(key, val);
|
||||||
|
|
||||||
|
applied.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------
|
// --------------------
|
||||||
// Menu Page
|
// Menu Page
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
FFZ.menu_pages.settings = {
|
FFZ.menu_pages.settings = {
|
||||||
render: function(view, container) {
|
render: function(view, container) {
|
||||||
var settings = {},
|
// Bottom Bar
|
||||||
categories = [],
|
var menu = document.createElement('ul'),
|
||||||
is_android = navigator.userAgent.indexOf('Android') !== -1;
|
page = document.createElement('div'),
|
||||||
|
|
||||||
for(var key in FFZ.settings_info) {
|
tab_basic = document.createElement('li'),
|
||||||
if ( ! FFZ.settings_info.hasOwnProperty(key) )
|
link_basic = document.createElement('a'),
|
||||||
|
|
||||||
|
tab_adv = document.createElement('li'),
|
||||||
|
link_adv = document.createElement('a'),
|
||||||
|
|
||||||
|
tab_save = document.createElement('li'),
|
||||||
|
link_save = document.createElement('a'),
|
||||||
|
|
||||||
|
height = parseInt(container.style.maxHeight || '0');
|
||||||
|
|
||||||
|
|
||||||
|
// Height Calculation
|
||||||
|
if ( ! height )
|
||||||
|
height = Math.max(200, view.$().height() - 172);
|
||||||
|
|
||||||
|
if ( height && height !== NaN ) {
|
||||||
|
height -= 37;
|
||||||
|
page.style.maxHeight = height + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Menu Building
|
||||||
|
page.className = 'ffz-ui-sub-menu-page';
|
||||||
|
menu.className = 'menu sub-menu clearfix';
|
||||||
|
|
||||||
|
tab_basic.className = 'item';
|
||||||
|
tab_basic.id = 'ffz-settings-page-basic';
|
||||||
|
link_basic.innerHTML = 'Basic';
|
||||||
|
tab_basic.appendChild(link_basic);
|
||||||
|
|
||||||
|
tab_adv.className = 'item';
|
||||||
|
tab_adv.id = 'ffz-settings-page-advanced';
|
||||||
|
link_adv.innerHTML = 'Advanced';
|
||||||
|
tab_adv.appendChild(link_adv);
|
||||||
|
|
||||||
|
tab_save.className = 'item';
|
||||||
|
tab_save.id = 'ffz-settings-page-save';
|
||||||
|
link_save.textContent = 'Backup & Restore';
|
||||||
|
tab_save.appendChild(link_save);
|
||||||
|
|
||||||
|
menu.appendChild(tab_basic);
|
||||||
|
menu.appendChild(tab_adv);
|
||||||
|
menu.appendChild(tab_save);
|
||||||
|
|
||||||
|
var cp = FFZ.menu_pages.settings.change_page;
|
||||||
|
|
||||||
|
link_basic.addEventListener('click', cp.bind(this, view, container, menu, page, 'basic'));
|
||||||
|
link_adv.addEventListener('click', cp.bind(this, view, container, menu, page, 'advanced'));
|
||||||
|
link_save.addEventListener('click', cp.bind(this, view, container, menu, page, 'save'));
|
||||||
|
|
||||||
|
if ( this.settings.advanced_settings )
|
||||||
|
link_adv.click();
|
||||||
|
else
|
||||||
|
link_basic.click();
|
||||||
|
|
||||||
|
container.appendChild(page);
|
||||||
|
container.appendChild(menu);
|
||||||
|
},
|
||||||
|
|
||||||
|
change_page: function(view, container, menu, page, key) {
|
||||||
|
page.innerHTML = '';
|
||||||
|
page.setAttribute('data-page', key);
|
||||||
|
|
||||||
|
var els = menu.querySelectorAll('li.active');
|
||||||
|
for(var i=0, l = els.length; i < l; i++)
|
||||||
|
els[i].classList.remove('active');
|
||||||
|
|
||||||
|
var el = menu.querySelector('#ffz-settings-page-' + key);
|
||||||
|
if ( el )
|
||||||
|
el.classList.add('active');
|
||||||
|
|
||||||
|
FFZ.menu_pages.settings['render_' + key].bind(this)(view, page);
|
||||||
|
|
||||||
|
if ( key === 'advanced' )
|
||||||
|
this.settings.set('advanced_settings', true);
|
||||||
|
else if ( key === 'basic' )
|
||||||
|
this.settings.set('advanced_settings', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
render_save: function(view, container) {
|
||||||
|
var backup_head = document.createElement('div'),
|
||||||
|
restore_head = document.createElement('div'),
|
||||||
|
backup_cont = document.createElement('div'),
|
||||||
|
restore_cont = document.createElement('div'),
|
||||||
|
|
||||||
|
backup_para = document.createElement('p'),
|
||||||
|
backup_link = document.createElement('a'),
|
||||||
|
backup_help = document.createElement('span'),
|
||||||
|
|
||||||
|
restore_para = document.createElement('p'),
|
||||||
|
restore_input = document.createElement('input'),
|
||||||
|
restore_link = document.createElement('a'),
|
||||||
|
restore_help = document.createElement('span'),
|
||||||
|
f = this;
|
||||||
|
|
||||||
|
|
||||||
|
backup_cont.className = 'chat-menu-content';
|
||||||
|
backup_head.className = 'heading';
|
||||||
|
backup_head.innerHTML = 'Backup Settings';
|
||||||
|
backup_cont.appendChild(backup_head);
|
||||||
|
|
||||||
|
backup_para.className = 'clearfix option';
|
||||||
|
|
||||||
|
backup_link.href = '#';
|
||||||
|
backup_link.innerHTML = 'Save to File';
|
||||||
|
backup_link.addEventListener('click', this.save_settings_file.bind(this));
|
||||||
|
|
||||||
|
backup_help.className = 'help';
|
||||||
|
backup_help.innerHTML = 'This generates a JSON file containing all of your settings and prompts you to save it.';
|
||||||
|
|
||||||
|
backup_para.appendChild(backup_link);
|
||||||
|
backup_para.appendChild(backup_help);
|
||||||
|
backup_cont.appendChild(backup_para);
|
||||||
|
|
||||||
|
restore_cont.className = 'chat-menu-content';
|
||||||
|
restore_head.className = 'heading';
|
||||||
|
restore_head.innerHTML = 'Restore Settings';
|
||||||
|
restore_cont.appendChild(restore_head);
|
||||||
|
|
||||||
|
restore_para.className = 'clearfix option';
|
||||||
|
|
||||||
|
restore_input.type = 'file';
|
||||||
|
restore_input.addEventListener('change', function() { f.load_settings_file(this.files[0]); })
|
||||||
|
|
||||||
|
restore_link.href = '#';
|
||||||
|
restore_link.innerHTML = 'Restore from File';
|
||||||
|
restore_link.addEventListener('click', function(e) { e.preventDefault(); restore_input.click(); });
|
||||||
|
|
||||||
|
restore_help.className = 'help';
|
||||||
|
restore_help.innerHTML = 'This loads settings from a previously generated JSON file.';
|
||||||
|
|
||||||
|
restore_para.appendChild(restore_link);
|
||||||
|
restore_para.appendChild(restore_help);
|
||||||
|
restore_cont.appendChild(restore_para);
|
||||||
|
|
||||||
|
container.appendChild(backup_cont);
|
||||||
|
container.appendChild(restore_cont);
|
||||||
|
},
|
||||||
|
|
||||||
|
render_basic: function(view, container) {
|
||||||
|
var settings = {},
|
||||||
|
categories = [],
|
||||||
|
is_android = navigator.userAgent.indexOf('Android') !== -1;
|
||||||
|
|
||||||
|
for(var key in FFZ.basic_settings) {
|
||||||
|
if ( ! FFZ.basic_settings.hasOwnProperty(key) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var info = FFZ.basic_settings[key],
|
||||||
|
cat = info.category || "Miscellaneous",
|
||||||
|
cs = settings[cat];
|
||||||
|
|
||||||
|
if ( info.visible !== undefined && info.visible !== null ) {
|
||||||
|
var visible = info.visible;
|
||||||
|
if ( typeof info.visible == "function" )
|
||||||
|
visible = info.visible.bind(this)();
|
||||||
|
|
||||||
|
if ( ! visible )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var info = FFZ.settings_info[key],
|
|
||||||
cat = info.category || "Miscellaneous",
|
|
||||||
cs = settings[cat];
|
|
||||||
|
|
||||||
if ( info.visible !== undefined && info.visible !== null ) {
|
|
||||||
var visible = info.visible;
|
|
||||||
if ( typeof info.visible == "function" )
|
|
||||||
visible = info.visible.bind(this)();
|
|
||||||
|
|
||||||
if ( ! visible )
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_android && info.no_mobile )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( ! cs ) {
|
|
||||||
categories.push(cat);
|
|
||||||
cs = settings[cat] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
cs.push([key, info]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
categories.sort(function(a,b) {
|
if ( is_android && info.no_mobile )
|
||||||
var a = a.toLowerCase(),
|
continue;
|
||||||
b = b.toLowerCase();
|
|
||||||
|
|
||||||
if ( a === "debugging" )
|
if ( ! cs ) {
|
||||||
a = "zzz" + a;
|
categories.push(cat);
|
||||||
|
cs = settings[cat] = [];
|
||||||
|
}
|
||||||
|
|
||||||
if ( b === "debugging" )
|
cs.push([key, info]);
|
||||||
b = "zzz" + b;
|
}
|
||||||
|
|
||||||
|
categories.sort(function(a,b) {
|
||||||
|
var a = a.toLowerCase(),
|
||||||
|
b = b.toLowerCase();
|
||||||
|
|
||||||
|
if ( a === "debugging" )
|
||||||
|
a = "zzz" + a;
|
||||||
|
|
||||||
|
if ( b === "debugging" )
|
||||||
|
b = "zzz" + b;
|
||||||
|
|
||||||
|
if ( a < b ) return -1;
|
||||||
|
else if ( a > b ) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
var f = this,
|
||||||
|
current_page = this._ffz_basic_settings_page || categories[0];
|
||||||
|
|
||||||
|
for(var ci=0; ci < categories.length; ci++) {
|
||||||
|
var category = categories[ci],
|
||||||
|
cset = settings[category],
|
||||||
|
|
||||||
|
menu = document.createElement('div'),
|
||||||
|
heading = document.createElement('div');
|
||||||
|
|
||||||
|
heading.className = 'heading';
|
||||||
|
menu.className = 'chat-menu-content'; // collapsable';
|
||||||
|
|
||||||
|
menu.setAttribute('data-category', category);
|
||||||
|
//menu.classList.toggle('collapsed', current_page !== category);
|
||||||
|
|
||||||
|
heading.innerHTML = category;
|
||||||
|
menu.appendChild(heading);
|
||||||
|
|
||||||
|
/*menu.addEventListener('click', function() {
|
||||||
|
if ( ! this.classList.contains('collapsed') )
|
||||||
|
return;
|
||||||
|
|
||||||
|
var t = this,
|
||||||
|
old_selection = container.querySelectorAll('.chat-menu-content:not(.collapsed)');
|
||||||
|
for(var i=0; i < old_selection.length; i++)
|
||||||
|
old_selection[i].classList.add('collapsed');
|
||||||
|
|
||||||
|
f._ffz_basic_settings_page = t.getAttribute('data-category');
|
||||||
|
t.classList.remove('collapsed');
|
||||||
|
setTimeout(function(){t.scrollIntoViewIfNeeded()});
|
||||||
|
});*/
|
||||||
|
|
||||||
|
cset.sort(function(a,b) {
|
||||||
|
var a = a[1],
|
||||||
|
b = b[1],
|
||||||
|
|
||||||
|
at = a.type === "boolean" ? 1 : 2,
|
||||||
|
bt = b.type === "boolean" ? 1 : 2,
|
||||||
|
|
||||||
|
an = a.name.toLowerCase(),
|
||||||
|
bn = b.name.toLowerCase();
|
||||||
|
|
||||||
|
if ( at < bt ) return -1;
|
||||||
|
else if ( at > bt ) return 1;
|
||||||
|
|
||||||
|
else if ( an < bn ) return -1;
|
||||||
|
else if ( an > bn ) return 1;
|
||||||
|
|
||||||
if ( a < b ) return -1;
|
|
||||||
else if ( a > b ) return 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
var f = this,
|
for(var i=0; i < cset.length; i++) {
|
||||||
current_page = this._ffz_settings_page || categories[0];
|
var key = cset[i][0],
|
||||||
|
info = cset[i][1],
|
||||||
|
el = document.createElement('p'),
|
||||||
|
val = info.type !== "button" && typeof info.get === 'function' ? info.get.bind(this)() : this.settings.get(info.get);
|
||||||
|
|
||||||
for(var ci=0; ci < categories.length; ci++) {
|
el.className = 'clearfix';
|
||||||
var category = categories[ci],
|
|
||||||
cset = settings[category],
|
|
||||||
|
|
||||||
menu = document.createElement('div'),
|
if ( this.has_bttv && info.no_bttv ) {
|
||||||
heading = document.createElement('div');
|
var label = document.createElement('span'),
|
||||||
|
help = document.createElement('span');
|
||||||
|
label.className = 'switch-label';
|
||||||
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
heading.className = 'heading';
|
help = document.createElement('span');
|
||||||
menu.className = 'chat-menu-content collapsable';
|
help.className = 'help';
|
||||||
|
help.innerHTML = 'Disabled due to incompatibility with BetterTTV.';
|
||||||
menu.setAttribute('data-category', category);
|
|
||||||
menu.classList.toggle('collapsed', current_page !== category);
|
|
||||||
|
|
||||||
heading.innerHTML = category;
|
el.classList.add('disabled');
|
||||||
menu.appendChild(heading);
|
el.appendChild(label);
|
||||||
|
el.appendChild(help);
|
||||||
|
|
||||||
menu.addEventListener('click', function() {
|
} else {
|
||||||
if ( ! this.classList.contains('collapsed') )
|
if ( info.type == "boolean" ) {
|
||||||
return;
|
var swit = document.createElement('a'),
|
||||||
|
label = document.createElement('span');
|
||||||
|
|
||||||
var t = this,
|
swit.className = 'switch';
|
||||||
old_selection = container.querySelectorAll('.chat-menu-content:not(.collapsed)');
|
swit.classList.toggle('active', val);
|
||||||
for(var i=0; i < old_selection.length; i++)
|
swit.innerHTML = "<span></span>";
|
||||||
old_selection[i].classList.add('collapsed');
|
|
||||||
|
|
||||||
f._ffz_settings_page = t.getAttribute('data-category');
|
|
||||||
t.classList.remove('collapsed');
|
|
||||||
setTimeout(function(){t.scrollIntoViewIfNeeded()});
|
|
||||||
});
|
|
||||||
|
|
||||||
cset.sort(function(a,b) {
|
|
||||||
var a = a[1],
|
|
||||||
b = b[1],
|
|
||||||
|
|
||||||
at = a.type === "boolean" ? 1 : 2,
|
|
||||||
bt = b.type === "boolean" ? 1 : 2,
|
|
||||||
|
|
||||||
an = a.name.toLowerCase(),
|
|
||||||
bn = b.name.toLowerCase();
|
|
||||||
|
|
||||||
if ( at < bt ) return -1;
|
|
||||||
else if ( at > bt ) return 1;
|
|
||||||
|
|
||||||
else if ( an < bn ) return -1;
|
|
||||||
else if ( an > bn ) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
for(var i=0; i < cset.length; i++) {
|
|
||||||
var key = cset[i][0],
|
|
||||||
info = cset[i][1],
|
|
||||||
el = document.createElement('p'),
|
|
||||||
val = this.settings.get(key);
|
|
||||||
|
|
||||||
el.className = 'clearfix';
|
|
||||||
|
|
||||||
if ( this.has_bttv && info.no_bttv ) {
|
|
||||||
var label = document.createElement('span'),
|
|
||||||
help = document.createElement('span');
|
|
||||||
label.className = 'switch-label';
|
label.className = 'switch-label';
|
||||||
label.innerHTML = info.name;
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
help = document.createElement('span');
|
el.appendChild(swit);
|
||||||
help.className = 'help';
|
|
||||||
help.innerHTML = 'Disabled due to incompatibility with BetterTTV.';
|
|
||||||
|
|
||||||
el.classList.add('disabled');
|
|
||||||
el.appendChild(label);
|
el.appendChild(label);
|
||||||
el.appendChild(help);
|
|
||||||
|
swit.addEventListener("click", toggle_basic_setting.bind(this, swit, key));
|
||||||
|
|
||||||
|
} else if ( info.type === "select" ) {
|
||||||
|
var select = document.createElement('select'),
|
||||||
|
label = document.createElement('span');
|
||||||
|
|
||||||
|
label.className = 'option-label';
|
||||||
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
|
for(var ok in info.options) {
|
||||||
|
var op = document.createElement('option');
|
||||||
|
op.value = JSON.stringify(ok);
|
||||||
|
if ( val === ok )
|
||||||
|
op.setAttribute('selected', true);
|
||||||
|
op.innerHTML = info.options[ok];
|
||||||
|
select.appendChild(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
select.addEventListener('change', option_basic_setting.bind(this, select, key));
|
||||||
|
|
||||||
|
el.appendChild(label);
|
||||||
|
el.appendChild(select);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if ( info.type == "boolean" ) {
|
el.classList.add("option");
|
||||||
var swit = document.createElement('a'),
|
var link = document.createElement('a');
|
||||||
label = document.createElement('span');
|
link.innerHTML = info.name;
|
||||||
|
link.href = "#";
|
||||||
|
el.appendChild(link);
|
||||||
|
|
||||||
swit.className = 'switch';
|
link.addEventListener("click", info.method.bind(this));
|
||||||
swit.classList.toggle('active', val);
|
|
||||||
swit.innerHTML = "<span></span>";
|
|
||||||
|
|
||||||
label.className = 'switch-label';
|
|
||||||
label.innerHTML = info.name;
|
|
||||||
|
|
||||||
el.appendChild(swit);
|
|
||||||
el.appendChild(label);
|
|
||||||
|
|
||||||
swit.addEventListener("click", toggle_setting.bind(this, swit, key));
|
|
||||||
|
|
||||||
} else if ( info.type === "select" ) {
|
|
||||||
var select = document.createElement('select'),
|
|
||||||
label = document.createElement('span');
|
|
||||||
|
|
||||||
label.className = 'option-label';
|
|
||||||
label.innerHTML = info.name;
|
|
||||||
|
|
||||||
for(var ok in info.options) {
|
|
||||||
var op = document.createElement('option');
|
|
||||||
op.value = JSON.stringify(ok);
|
|
||||||
if ( val === ok )
|
|
||||||
op.setAttribute('selected', true);
|
|
||||||
op.innerHTML = info.options[ok];
|
|
||||||
select.appendChild(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
select.addEventListener('change', option_setting.bind(this, select, key));
|
|
||||||
|
|
||||||
el.appendChild(label);
|
|
||||||
el.appendChild(select);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
el.classList.add("option");
|
|
||||||
var link = document.createElement('a');
|
|
||||||
link.innerHTML = info.name;
|
|
||||||
link.href = "#";
|
|
||||||
el.appendChild(link);
|
|
||||||
|
|
||||||
link.addEventListener("click", info.method.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( info.help ) {
|
|
||||||
var help = document.createElement('span');
|
|
||||||
help.className = 'help';
|
|
||||||
help.innerHTML = info.help;
|
|
||||||
el.appendChild(help);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.appendChild(el);
|
if ( info.help ) {
|
||||||
|
var help = document.createElement('span');
|
||||||
|
help.className = 'help';
|
||||||
|
help.innerHTML = info.help;
|
||||||
|
el.appendChild(help);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.appendChild(menu);
|
menu.appendChild(el);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
container.appendChild(menu);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render_advanced: function(view, container) {
|
||||||
|
var settings = {},
|
||||||
|
categories = [],
|
||||||
|
is_android = navigator.userAgent.indexOf('Android') !== -1;
|
||||||
|
|
||||||
|
for(var key in FFZ.settings_info) {
|
||||||
|
if ( ! FFZ.settings_info.hasOwnProperty(key) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var info = FFZ.settings_info[key],
|
||||||
|
cat = info.category || "Miscellaneous",
|
||||||
|
cs = settings[cat];
|
||||||
|
|
||||||
|
if ( info.visible !== undefined && info.visible !== null ) {
|
||||||
|
var visible = info.visible;
|
||||||
|
if ( typeof info.visible == "function" )
|
||||||
|
visible = info.visible.bind(this)();
|
||||||
|
|
||||||
|
if ( ! visible )
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_android && info.no_mobile )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! cs ) {
|
||||||
|
categories.push(cat);
|
||||||
|
cs = settings[cat] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.push([key, info]);
|
||||||
|
}
|
||||||
|
|
||||||
|
categories.sort(function(a,b) {
|
||||||
|
var a = a.toLowerCase(),
|
||||||
|
b = b.toLowerCase();
|
||||||
|
|
||||||
|
if ( a === "debugging" )
|
||||||
|
a = "zzz" + a;
|
||||||
|
|
||||||
|
if ( b === "debugging" )
|
||||||
|
b = "zzz" + b;
|
||||||
|
|
||||||
|
if ( a < b ) return -1;
|
||||||
|
else if ( a > b ) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
var f = this,
|
||||||
|
current_page = this._ffz_settings_page || categories[0];
|
||||||
|
|
||||||
|
for(var ci=0; ci < categories.length; ci++) {
|
||||||
|
var category = categories[ci],
|
||||||
|
cset = settings[category],
|
||||||
|
|
||||||
|
menu = document.createElement('div'),
|
||||||
|
heading = document.createElement('div');
|
||||||
|
|
||||||
|
heading.className = 'heading';
|
||||||
|
menu.className = 'chat-menu-content collapsable';
|
||||||
|
|
||||||
|
menu.setAttribute('data-category', category);
|
||||||
|
menu.classList.toggle('collapsed', current_page !== category);
|
||||||
|
|
||||||
|
heading.innerHTML = category;
|
||||||
|
menu.appendChild(heading);
|
||||||
|
|
||||||
|
menu.addEventListener('click', function() {
|
||||||
|
if ( ! this.classList.contains('collapsed') )
|
||||||
|
return;
|
||||||
|
|
||||||
|
var t = this,
|
||||||
|
old_selection = container.querySelectorAll('.chat-menu-content:not(.collapsed)');
|
||||||
|
for(var i=0; i < old_selection.length; i++)
|
||||||
|
old_selection[i].classList.add('collapsed');
|
||||||
|
|
||||||
|
f._ffz_settings_page = t.getAttribute('data-category');
|
||||||
|
t.classList.remove('collapsed');
|
||||||
|
setTimeout(function(){t.scrollIntoViewIfNeeded()});
|
||||||
|
});
|
||||||
|
|
||||||
|
cset.sort(function(a,b) {
|
||||||
|
var a = a[1],
|
||||||
|
b = b[1],
|
||||||
|
|
||||||
|
at = a.type === "boolean" ? 1 : 2,
|
||||||
|
bt = b.type === "boolean" ? 1 : 2,
|
||||||
|
|
||||||
|
an = a.name.toLowerCase(),
|
||||||
|
bn = b.name.toLowerCase();
|
||||||
|
|
||||||
|
if ( at < bt ) return -1;
|
||||||
|
else if ( at > bt ) return 1;
|
||||||
|
|
||||||
|
else if ( an < bn ) return -1;
|
||||||
|
else if ( an > bn ) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for(var i=0; i < cset.length; i++) {
|
||||||
|
var key = cset[i][0],
|
||||||
|
info = cset[i][1],
|
||||||
|
el = document.createElement('p'),
|
||||||
|
val = this.settings.get(key);
|
||||||
|
|
||||||
|
el.className = 'clearfix';
|
||||||
|
|
||||||
|
if ( this.has_bttv && info.no_bttv ) {
|
||||||
|
var label = document.createElement('span'),
|
||||||
|
help = document.createElement('span');
|
||||||
|
label.className = 'switch-label';
|
||||||
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
|
help = document.createElement('span');
|
||||||
|
help.className = 'help';
|
||||||
|
help.innerHTML = 'Disabled due to incompatibility with BetterTTV.';
|
||||||
|
|
||||||
|
el.classList.add('disabled');
|
||||||
|
el.appendChild(label);
|
||||||
|
el.appendChild(help);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if ( info.type == "boolean" ) {
|
||||||
|
var swit = document.createElement('a'),
|
||||||
|
label = document.createElement('span');
|
||||||
|
|
||||||
|
swit.className = 'switch';
|
||||||
|
swit.classList.toggle('active', val);
|
||||||
|
swit.innerHTML = "<span></span>";
|
||||||
|
|
||||||
|
label.className = 'switch-label';
|
||||||
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
|
el.appendChild(swit);
|
||||||
|
el.appendChild(label);
|
||||||
|
|
||||||
|
swit.addEventListener("click", toggle_setting.bind(this, swit, key));
|
||||||
|
|
||||||
|
} else if ( info.type === "select" ) {
|
||||||
|
var select = document.createElement('select'),
|
||||||
|
label = document.createElement('span');
|
||||||
|
|
||||||
|
label.className = 'option-label';
|
||||||
|
label.innerHTML = info.name;
|
||||||
|
|
||||||
|
for(var ok in info.options) {
|
||||||
|
var op = document.createElement('option');
|
||||||
|
op.value = JSON.stringify(ok);
|
||||||
|
if ( val === ok )
|
||||||
|
op.setAttribute('selected', true);
|
||||||
|
op.innerHTML = info.options[ok];
|
||||||
|
select.appendChild(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
select.addEventListener('change', option_setting.bind(this, select, key));
|
||||||
|
|
||||||
|
el.appendChild(label);
|
||||||
|
el.appendChild(select);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
el.classList.add("option");
|
||||||
|
var link = document.createElement('a');
|
||||||
|
link.innerHTML = info.name;
|
||||||
|
link.href = "#";
|
||||||
|
el.appendChild(link);
|
||||||
|
|
||||||
|
link.addEventListener("click", info.method.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( info.help ) {
|
||||||
|
var help = document.createElement('span');
|
||||||
|
help.className = 'help';
|
||||||
|
help.innerHTML = info.help;
|
||||||
|
el.appendChild(help);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.appendChild(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
container.appendChild(menu);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
icon: constants.GEAR,
|
icon: constants.GEAR,
|
||||||
sort_order: 99999,
|
sort_order: 99999,
|
||||||
wide: true
|
wide: true,
|
||||||
|
sub_menu: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
103
src/ui/dark.js
103
src/ui/dark.js
|
@ -6,6 +6,107 @@ var FFZ = window.FrankerFaceZ,
|
||||||
// Settings
|
// Settings
|
||||||
// ---------------------
|
// ---------------------
|
||||||
|
|
||||||
|
FFZ.basic_settings.dark_twitch = {
|
||||||
|
type: "boolean",
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
category: "General",
|
||||||
|
name: "Dark Twitch",
|
||||||
|
help: "Apply a dark background to channels and other related pages for easier viewing.",
|
||||||
|
|
||||||
|
get: function() {
|
||||||
|
return this.settings.dark_twitch;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('dark_twitch', val);
|
||||||
|
this.settings.set('dark_no_blue', val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings.separated_chat = {
|
||||||
|
type: "boolean",
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
name: "Separated Lines",
|
||||||
|
help: "Use alternating rows and thin lines to visually separate chat messages for easier reading.",
|
||||||
|
|
||||||
|
get: function() {
|
||||||
|
return this.settings.chat_rows && this.settings.chat_separators !== '0';
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('chat_rows', val);
|
||||||
|
this.settings.set('chat_separators', val ? '2' : '0');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings.minimalistic_chat = {
|
||||||
|
type: "boolean",
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
name: "Minimalistic UI",
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('minimal_chat', val);
|
||||||
|
this.settings.set('chat_padding', val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings.high_contrast = {
|
||||||
|
type: "boolean",
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
name: "High Contrast",
|
||||||
|
help: "Display chat using white and black for maximum contrast. This is suitable for capturing and chroma keying chat to display on stream.",
|
||||||
|
|
||||||
|
get: function() {
|
||||||
|
return this.settings.high_contrast_chat !== '222';
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('high_contrast_chat', val ? '111': '222');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings.keywords = {
|
||||||
|
type: "button",
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
name: "Highlight Keywords",
|
||||||
|
help: "Set additional keywords that will be highlighted in chat.",
|
||||||
|
|
||||||
|
method: function() {
|
||||||
|
FFZ.settings_info.keywords.method.bind(this)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FFZ.basic_settings.banned_words = {
|
||||||
|
type: "button",
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
no_bttv: true,
|
||||||
|
|
||||||
|
name: "Banned Keywords",
|
||||||
|
help: "Set a list of words that will be removed from chat messages, locally.",
|
||||||
|
|
||||||
|
method: function() {
|
||||||
|
FFZ.settings_info.banned_words.method.bind(this)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FFZ.settings_info.twitch_chat_dark = {
|
FFZ.settings_info.twitch_chat_dark = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false,
|
value: false,
|
||||||
|
@ -28,7 +129,7 @@ FFZ.settings_info.dark_twitch = {
|
||||||
var cb = document.querySelector('input.ffz-setting-dark-twitch');
|
var cb = document.querySelector('input.ffz-setting-dark-twitch');
|
||||||
if ( cb )
|
if ( cb )
|
||||||
cb.checked = val;
|
cb.checked = val;
|
||||||
|
|
||||||
if ( this.has_bttv )
|
if ( this.has_bttv )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
var FFZ = window.FrankerFaceZ,
|
var FFZ = window.FrankerFaceZ,
|
||||||
utils = require('../utils'),
|
utils = require('../utils'),
|
||||||
constants = require('../constants');
|
constants = require('../constants'),
|
||||||
|
|
||||||
|
FOLLOW_GRAVITY = function(f, el) {
|
||||||
|
return (f.settings.following_count && el.parentElement.getAttribute('data-name') === 'following' ? 'n' : '') + (f.settings.swap_sidebars ? 'e' : 'w');
|
||||||
|
},
|
||||||
|
|
||||||
|
WIDE_TIP = function(f, el) {
|
||||||
|
return ( ! f.settings.following_count || (el.id !== 'header_following' && el.parentElement.getAttribute('data-name') !== 'following') ) ? '' : 'ffz-wide-tip';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
FFZ.settings_info.following_count = {
|
FFZ.settings_info.following_count = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: true,
|
value: true,
|
||||||
|
|
||||||
no_bttv: true,
|
|
||||||
no_mobile: true,
|
no_mobile: true,
|
||||||
|
|
||||||
category: "Appearance",
|
category: "Appearance",
|
||||||
name: "Sidebar Following Count",
|
name: "Sidebar Following Data",
|
||||||
help: "Display the number of live channels you're following on the sidebar.",
|
help: "Display the number of live channels you're following on the sidebar, and list the channels in a tooltip.",
|
||||||
|
|
||||||
on_update: function(val) {
|
on_update: function(val) {
|
||||||
this._schedule_following_count();
|
this._schedule_following_count();
|
||||||
|
@ -21,10 +27,14 @@ FFZ.settings_info.following_count = {
|
||||||
var Stream = window.App && App.__container__.resolve('model:stream'),
|
var Stream = window.App && App.__container__.resolve('model:stream'),
|
||||||
Live = Stream && Stream.find("live");
|
Live = Stream && Stream.find("live");
|
||||||
|
|
||||||
if ( Live )
|
if ( Live ) {
|
||||||
this._draw_following_count(Live.get('total') || 0);
|
var total = Live.get('total') || 0;
|
||||||
else
|
this._draw_following_count(total);
|
||||||
|
this._draw_following_channels(Live.get('content'), total);;
|
||||||
|
} else {
|
||||||
this._update_following_count();
|
this._update_following_count();
|
||||||
|
this._draw_following_channels();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,6 +47,9 @@ FFZ.prototype.setup_following_count = function(has_ember) {
|
||||||
if ( this.settings.following_count )
|
if ( this.settings.following_count )
|
||||||
this._schedule_following_count();
|
this._schedule_following_count();
|
||||||
|
|
||||||
|
// Tooltips~!
|
||||||
|
this._install_following_tooltips();
|
||||||
|
|
||||||
// If we don't have Ember, no point in trying this stuff.
|
// If we don't have Ember, no point in trying this stuff.
|
||||||
if ( ! has_ember )
|
if ( ! has_ember )
|
||||||
return this._update_following_count();
|
return this._update_following_count();
|
||||||
|
@ -68,7 +81,7 @@ FFZ.prototype.setup_following_count = function(has_ember) {
|
||||||
|
|
||||||
|
|
||||||
FFZ.prototype._schedule_following_count = function() {
|
FFZ.prototype._schedule_following_count = function() {
|
||||||
if ( this.has_bttv || ! this.settings.following_count ) {
|
if ( ! this.settings.following_count ) {
|
||||||
if ( this._following_count_timer ) {
|
if ( this._following_count_timer ) {
|
||||||
clearTimeout(this._following_count_timer);
|
clearTimeout(this._following_count_timer);
|
||||||
this._following_count_timer = undefined;
|
this._following_count_timer = undefined;
|
||||||
|
@ -110,9 +123,21 @@ FFZ.prototype._update_following_count = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FFZ.prototype._draw_following_channels = function(streams, total) {
|
FFZ.prototype._build_following_tooltip = function(el) {
|
||||||
// First, build the data.
|
if ( el.id !== 'header_following' && el.parentElement.getAttribute('data-name') !== 'following' )
|
||||||
var tooltip = 'Following';
|
return el.getAttribute('original-title');
|
||||||
|
|
||||||
|
if ( ! this.settings.following_count )
|
||||||
|
return 'Following';
|
||||||
|
|
||||||
|
var tooltip = (this.has_bttv ? '<span class="stat playing">FrankerFaceZ</span>' : '') + 'Following',
|
||||||
|
bb = el.getBoundingClientRect(),
|
||||||
|
height = document.body.clientHeight - (bb.bottom + 54),
|
||||||
|
max_lines = Math.max(Math.floor(height / 36) - 1, 2),
|
||||||
|
|
||||||
|
streams = this._tooltip_streams,
|
||||||
|
total = this._tooltip_total || (streams && streams.length) || 0;
|
||||||
|
|
||||||
|
|
||||||
if ( streams && streams.length ) {
|
if ( streams && streams.length ) {
|
||||||
var c = 0;
|
var c = 0;
|
||||||
|
@ -122,61 +147,93 @@ FFZ.prototype._draw_following_channels = function(streams, total) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c += 1;
|
c += 1;
|
||||||
if ( c > 5 ) {
|
if ( c > max_lines ) {
|
||||||
var ttl = total || streams.length;
|
tooltip += '<hr><span>And ' + utils.number_commas(total - max_lines) + ' more...</span>';
|
||||||
tooltip += '<hr><span>And ' + utils.number_commas(ttl - 5) + ' more...</span>';
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltip += (i > 0 ? '<br>' : '<hr>') + '<span class="viewers">' + constants.LIVE + ' ' + utils.number_commas(stream.viewers) + '</span><b>' + utils.sanitize(stream.channel.display_name || stream.channel.name) + '</b><br><span class="playing">' + (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing') + '</span>';
|
var up_since = this.settings.stream_uptime && stream.created_at && utils.parse_date(stream.created_at),
|
||||||
}
|
uptime = up_since && Math.floor((Date.now() - up_since.getTime()) / 1000) || 0,
|
||||||
}
|
minutes = Math.floor(uptime / 60) % 60,
|
||||||
|
hours = Math.floor(uptime / 3600);
|
||||||
|
|
||||||
|
tooltip += (i === 0 ? '<hr>' : '') +
|
||||||
|
(uptime > 0 ? '<span class="stat">' + constants.CLOCK + ' ' + (hours > 0 ? hours + 'h' : '') + minutes + 'm</span>' : '') +
|
||||||
|
'<span class="stat">' + constants.LIVE + ' ' + utils.number_commas(stream.viewers) + '</span>' +
|
||||||
|
'<b>' + utils.sanitize(stream.channel.display_name || stream.channel.name) + '</b><br>' +
|
||||||
|
'<span class="playing">' + (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing') + '</span>';
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
tooltip += "<hr>No one you're following is online.";
|
||||||
|
|
||||||
|
|
||||||
|
// Reposition the tooltip.
|
||||||
|
setTimeout(function() {
|
||||||
|
var tip = document.querySelector('.tipsy'),
|
||||||
|
bb = tip.getBoundingClientRect(),
|
||||||
|
|
||||||
|
left = parseInt(tip.style.left || '0'),
|
||||||
|
right = bb.left + tip.scrollWidth;
|
||||||
|
|
||||||
|
if ( bb.left < 5 )
|
||||||
|
tip.style.left = (left - bb.left) + 5 + 'px';
|
||||||
|
else if ( right > document.body.clientWidth - 5 )
|
||||||
|
tip.style.left = (left - (5 + right - document.body.clientWidth)) + 'px';
|
||||||
|
});
|
||||||
|
|
||||||
|
return tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FFZ.prototype._install_following_tooltips = function() {
|
||||||
|
var f = this,
|
||||||
|
data = {
|
||||||
|
html: true,
|
||||||
|
className: function() { return WIDE_TIP(f, this); },
|
||||||
|
title: function() { return f._build_following_tooltip(this); }
|
||||||
|
};
|
||||||
|
|
||||||
// Small
|
// Small
|
||||||
var small_following = jQuery('#small_nav ul.game_filters li[data-name="following"] a');
|
var small_following = jQuery('#small_nav ul.game_filters li[data-name="following"] a');
|
||||||
if ( small_following && small_following.length ) {
|
if ( small_following && small_following.length ) {
|
||||||
var data = small_following.data('tipsy');
|
var td = small_following.data('tipsy');
|
||||||
if ( data && data.options ) {
|
if ( td && td.options ) {
|
||||||
data.options.gravity = function() { return this.parentElement.getAttribute('data-name') === 'following' ? 'nw': 'w'; };
|
td.options = _.extend(td.options, data);
|
||||||
data.options.html = true;
|
td.options.gravity = function() { return FOLLOW_GRAVITY(f, this); };
|
||||||
data.options.className = 'ffz-wide-tip';
|
|
||||||
} else
|
} else
|
||||||
small_following.tipsy({html: true, className: 'ffz-wide-tip', gravity: 'nw'});
|
small_following.tipsy(_.extend({gravity: function() { return FOLLOW_GRAVITY(f, this); }}, data));
|
||||||
|
|
||||||
small_following.attr('title', tooltip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Large
|
// Large
|
||||||
var large_following = jQuery('#large_nav #nav_personal li[data-name="following"] a');
|
var large_following = jQuery('#large_nav #nav_personal li[data-name="following"] a');
|
||||||
if ( large_following && large_following.length ) {
|
if ( large_following && large_following.length ) {
|
||||||
var data = large_following.data('tipsy');
|
var td = large_following.data('tipsy');
|
||||||
if ( data && data.options ) {
|
if ( td && td.options )
|
||||||
data.options.html = true;
|
td.options = _.extend(td.options, data);
|
||||||
data.options.className = 'ffz-wide-tip';
|
else
|
||||||
} else
|
large_following.tipsy(data);
|
||||||
large_following.tipsy({html:true, className: 'ffz-wide-tip'});
|
|
||||||
|
|
||||||
large_following.attr('title', tooltip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Heading
|
// Heading
|
||||||
var head_following = jQuery('#header_actions #header_following');
|
var head_following = jQuery('#header_actions #header_following');
|
||||||
if ( head_following && head_following.length ) {
|
if ( head_following && head_following.length ) {
|
||||||
var data = head_following.data('tipsy');
|
var td = head_following.data('tipsy');
|
||||||
if ( data && data.options ) {
|
if ( td && td.options )
|
||||||
data.options.html = true;
|
td.options = _.extend(td.options, data);
|
||||||
data.options.className = 'ffz-wide-tip';
|
else
|
||||||
} else
|
head_following.tipsy(data);
|
||||||
head_following.tipsy({html: true, className: 'ffz-wide-tip'});
|
|
||||||
|
|
||||||
head_following.attr('title', tooltip);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FFZ.prototype._draw_following_channels = function(streams, total) {
|
||||||
|
this._tooltip_streams = streams;
|
||||||
|
this._tooltip_total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FFZ.prototype._draw_following_count = function(count) {
|
FFZ.prototype._draw_following_count = function(count) {
|
||||||
// Small
|
// Small
|
||||||
var small_following = document.querySelector('#small_nav ul.game_filters li[data-name="following"] a');
|
var small_following = document.querySelector('#small_nav ul.game_filters li[data-name="following"] a');
|
||||||
|
|
|
@ -308,7 +308,7 @@ FFZ.prototype.build_ui_popup = function(view) {
|
||||||
el = document.createElement('li'),
|
el = document.createElement('li'),
|
||||||
link = document.createElement('a');
|
link = document.createElement('a');
|
||||||
|
|
||||||
el.className = 'item';
|
el.className = 'item' + (page.sub_menu ? ' has-sub-menu' : '');
|
||||||
el.id = "ffz-menu-page-" + key;
|
el.id = "ffz-menu-page-" + key;
|
||||||
link.title = page.name;
|
link.title = page.name;
|
||||||
link.innerHTML = page.icon;
|
link.innerHTML = page.icon;
|
||||||
|
|
|
@ -10,6 +10,25 @@ var FFZ = window.FrankerFaceZ,
|
||||||
// Initialization
|
// Initialization
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
|
FFZ.basic_settings.replace_twitch_menu = {
|
||||||
|
type: "boolean",
|
||||||
|
|
||||||
|
category: "Chat",
|
||||||
|
|
||||||
|
name: "Unified Emoticons Menu",
|
||||||
|
help: "Completely replace the default Twitch emoticon menu and display global emoticons in the My Emoticons menu.",
|
||||||
|
|
||||||
|
get: function() {
|
||||||
|
return this.settings.replace_twitch_menu && this.settings.global_emotes_in_menu && this.settings.emoji_in_menu;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(val) {
|
||||||
|
this.settings.set('replace_twitch_menu', val);
|
||||||
|
this.settings.set('global_emotes_in_menu', val);
|
||||||
|
this.settings.set('emoji_in_menu', val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
FFZ.settings_info.replace_twitch_menu = {
|
FFZ.settings_info.replace_twitch_menu = {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
value: false,
|
value: false,
|
||||||
|
|
94
style.css
94
style.css
|
@ -476,6 +476,7 @@ body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + s
|
||||||
margin: 11px 13px;
|
margin: 11px 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-sub-menu-page,
|
||||||
.ffz-ui-menu-page { overflow-y: auto; }
|
.ffz-ui-menu-page { overflow-y: auto; }
|
||||||
|
|
||||||
.ffz-ui-menu-page[data-page="about"],
|
.ffz-ui-menu-page[data-page="about"],
|
||||||
|
@ -540,10 +541,15 @@ body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + s
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-menu-page input,
|
||||||
.ffz-ui-menu-page select {
|
.ffz-ui-menu-page select {
|
||||||
margin: 0 10px 5px;
|
margin: 0 10px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-menu-page input[type="file"] {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
#ffz-chat-menu { pointer-events: none; }
|
#ffz-chat-menu { pointer-events: none; }
|
||||||
|
|
||||||
.ffz-ui-popup ul.menu {
|
.ffz-ui-popup ul.menu {
|
||||||
|
@ -570,15 +576,42 @@ body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + s
|
||||||
background-color: #282828;
|
background-color: #282828;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.sub-menu li.title,
|
||||||
.ffz-ui-menu-page .heading .right,
|
.ffz-ui-menu-page .heading .right,
|
||||||
.ffz-ui-popup ul.menu li.item {
|
.ffz-ui-popup ul.menu li.item {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.sub-menu li.item,
|
||||||
.ffz-ui-popup ul.menu li.title {
|
.ffz-ui-popup ul.menu li.title {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.sub-menu { background-color: #dfdfdf; }
|
||||||
|
|
||||||
|
.app-main.theatre .ffz-ui-popup ul.sub-menu,
|
||||||
|
.chat-container.dark .ffz-ui-popup ul.sub-menu,
|
||||||
|
.chat-container.force-dark .ffz-ui-popup ul.sub-menu,
|
||||||
|
.ember-chat-container.dark .ffz-ui-popup ul.sub-menu,
|
||||||
|
.ember-chat-container.force-dark .ffz-ui-popup ul.sub-menu,
|
||||||
|
.ffz-ui-popup.dark ul.sub-menu {
|
||||||
|
background-color: #181818;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.sub-menu a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-main.theatre .ffz-ui-popup ul.sub-menu a,
|
||||||
|
.chat-container.dark .ffz-ui-popup ul.sub-menu a,
|
||||||
|
.chat-container.force-dark .ffz-ui-popup ul.sub-menu a,
|
||||||
|
.ember-chat-container.dark .ffz-ui-popup ul.sub-menu a,
|
||||||
|
.ember-chat-container.force-dark .ffz-ui-popup ul.sub-menu a,
|
||||||
|
.ffz-ui-popup.dark ul.sub-menu a {
|
||||||
|
color: #d3d3d3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
span.ffz-handle {
|
span.ffz-handle {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -668,6 +701,11 @@ span.ffz-handle:after { left: 8px }
|
||||||
border-top: 1px solid transparent;
|
border-top: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.sub-menu a {
|
||||||
|
border-left: none;
|
||||||
|
border-right: 1px solid rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
.ffz-ui-popup ul.menu li.active {
|
.ffz-ui-popup ul.menu li.active {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
@ -676,6 +714,15 @@ span.ffz-handle:after { left: 8px }
|
||||||
border-top-color: #fff;
|
border-top-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.menu li.active.has-sub-menu {
|
||||||
|
background-color: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ffz-ui-popup ul.menu li.active.has-sub-menu a {
|
||||||
|
border-top-color: #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
.chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
||||||
.chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
.chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
||||||
.ember-chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
.ember-chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active,
|
||||||
|
@ -694,6 +741,24 @@ span.ffz-handle:after { left: 8px }
|
||||||
border-top-color: rgb(16,16,16);
|
border-top-color: rgb(16,16,16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu,
|
||||||
|
.chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu,
|
||||||
|
.ember-chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu,
|
||||||
|
.ember-chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu,
|
||||||
|
.app-main.theatre .chat-container .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu,
|
||||||
|
.ffz-ui-popup.dark ul.menu li.active.has-sub-menu {
|
||||||
|
background-color: #181818;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu a,
|
||||||
|
.chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu a,
|
||||||
|
.ember-chat-container.dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu a,
|
||||||
|
.ember-chat-container.force-dark .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu a,
|
||||||
|
.app-main.theatre .chat-container .chat-interface .ffz-ui-popup ul.menu li.active.has-sub-menu a,
|
||||||
|
.ffz-ui-popup.dark ul.menu li.active.has-sub-menu a {
|
||||||
|
border-top-color: #181818;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-container.dark .chat-interface .ffz-ui-popup a,
|
.chat-container.dark .chat-interface .ffz-ui-popup a,
|
||||||
.chat-container.force-dark .chat-interface .ffz-ui-popup a,
|
.chat-container.force-dark .chat-interface .ffz-ui-popup a,
|
||||||
.ember-chat-container.dark .chat-interface .ffz-ui-popup a,
|
.ember-chat-container.dark .chat-interface .ffz-ui-popup a,
|
||||||
|
@ -735,6 +800,7 @@ span.ffz-handle:after { left: 8px }
|
||||||
.chat-history::-webkit-scrollbar,
|
.chat-history::-webkit-scrollbar,
|
||||||
#ffz-race-popup .table::-webkit-scrollbar,
|
#ffz-race-popup .table::-webkit-scrollbar,
|
||||||
.emoticon-selector-box .all-emotes::-webkit-scrollbar,
|
.emoticon-selector-box .all-emotes::-webkit-scrollbar,
|
||||||
|
.ffz-ui-sub-menu-page::-webkit-scrollbar,
|
||||||
.ffz-ui-menu-page::-webkit-scrollbar {
|
.ffz-ui-menu-page::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
}
|
}
|
||||||
|
@ -742,6 +808,7 @@ span.ffz-handle:after { left: 8px }
|
||||||
.chat-history::-webkit-scrollbar-thumb,
|
.chat-history::-webkit-scrollbar-thumb,
|
||||||
#ffz-race-popup .table::-webkit-scrollbar-thumb,
|
#ffz-race-popup .table::-webkit-scrollbar-thumb,
|
||||||
.emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
|
.emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
|
||||||
|
.ffz-ui-sub-menu-page::-webkit-scrollbar-thumb,
|
||||||
.ffz-ui-menu-page::-webkit-scrollbar-thumb {
|
.ffz-ui-menu-page::-webkit-scrollbar-thumb {
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
background: rgba(0,0,0,0.7);
|
background: rgba(0,0,0,0.7);
|
||||||
|
@ -755,7 +822,10 @@ span.ffz-handle:after { left: 8px }
|
||||||
.app-main.theatre .emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
|
.app-main.theatre .emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
|
||||||
.ember-chat-container.dark .ffz-ui-menu-page::-webkit-scrollbar-thumb,
|
.ember-chat-container.dark .ffz-ui-menu-page::-webkit-scrollbar-thumb,
|
||||||
.chat-container.dark .ffz-ui-menu-page::-webkit-scrollbar-thumb,
|
.chat-container.dark .ffz-ui-menu-page::-webkit-scrollbar-thumb,
|
||||||
.app-main.theatre .ffz-ui-menu-page::-webkit-scrollbar-thumb {
|
.app-main.theatre .ffz-ui-menu-page::-webkit-scrollbar-thumb,
|
||||||
|
.ember-chat-container.dark .ffz-ui-sub-menu-page::-webkit-scrollbar-thumb,
|
||||||
|
.chat-container.dark .ffz-ui-sub-menu-page::-webkit-scrollbar-thumb,
|
||||||
|
.app-main.theatre .ffz-ui-sub-menu-page::-webkit-scrollbar-thumb {
|
||||||
background: rgba(255,255,255,0.6);
|
background: rgba(255,255,255,0.6);
|
||||||
box-shadow: 0 0 1px 1px rgba(0,0,0,0.25);
|
box-shadow: 0 0 1px 1px rgba(0,0,0,0.25);
|
||||||
}
|
}
|
||||||
|
@ -1080,21 +1150,35 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
||||||
/* Emoticon Tooltips */
|
/* Emoticon Tooltips */
|
||||||
|
|
||||||
.ffz-wide-tip .tipsy-inner {
|
.ffz-wide-tip .tipsy-inner {
|
||||||
|
min-width: 300px;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz-wide-tip span.viewers {
|
.ffz-wide-tip span.stat {
|
||||||
float: right;
|
float: right;
|
||||||
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz-wide-tip span.viewers svg {
|
.ffz-wide-tip b { margin-right: 20px; }
|
||||||
|
|
||||||
|
.ffz-wide-tip span.stat svg {
|
||||||
float: left;
|
float: left;
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz-wide-tip svg path { fill: #fff; }
|
.ffz-wide-tip svg path { fill: #fff; }
|
||||||
.ffz-wide-tip span.playing { opacity: 0.7; }
|
.ffz-wide-tip span.playing {
|
||||||
|
opacity: 0.7;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.tipsy .tipsy-inner {
|
.tipsy .tipsy-inner {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
@ -1102,10 +1186,12 @@ body:not(.ffz-chat-purge-icon) .ember-chat .mod-icons .purge { display: none; }
|
||||||
|
|
||||||
/* Menu Page Loader */
|
/* Menu Page Loader */
|
||||||
|
|
||||||
|
.ffz-ui-sub-menu-page:empty,
|
||||||
.ffz-ui-menu-page:empty {
|
.ffz-ui-menu-page:empty {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ffz-ui-sub-menu-page:empty::after,
|
||||||
.ffz-ui-menu-page:empty::after {
|
.ffz-ui-menu-page:empty::after {
|
||||||
content: " ";
|
content: " ";
|
||||||
display: block;
|
display: block;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue