mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-09-17 18:26:57 +00:00
3.5.266. Yeah. This is me remembering to commit again, but only because I told someone to make a pull request.
This commit is contained in:
parent
86546ba7d8
commit
8310f89aa0
25 changed files with 717 additions and 592 deletions
|
@ -27,8 +27,9 @@ FFZ.settings_info.fix_color = {
|
|||
2: "HSL Adjustment (Depreciated)",
|
||||
3: "HSV Adjustment (Depreciated)",
|
||||
4: "RGB Adjustment (Depreciated)"
|
||||
//5: "HSL (BTTV-Like)"
|
||||
},
|
||||
value: '1',
|
||||
value: 1,
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
@ -39,16 +40,18 @@ FFZ.settings_info.fix_color = {
|
|||
process_value: function(val) {
|
||||
// Load legacy setting.
|
||||
if ( val === false )
|
||||
return '0';
|
||||
return 0;
|
||||
else if ( val === true )
|
||||
return '1';
|
||||
return 1;
|
||||
else if ( typeof val === "string" )
|
||||
return parseInt(val) || 1;
|
||||
return val;
|
||||
},
|
||||
|
||||
on_update: function(val) {
|
||||
this.toggle_style('chat-colors-gray', !this.has_bttv && val === '-1');
|
||||
this.toggle_style('chat-colors-gray', !this.has_bttv && val === -1);
|
||||
|
||||
if ( ! this.has_bttv && val !== '-1' )
|
||||
if ( ! this.has_bttv && val !== -1 )
|
||||
this._rebuild_colors();
|
||||
}
|
||||
};
|
||||
|
@ -88,7 +91,7 @@ FFZ.settings_info.luv_contrast = {
|
|||
this._rebuild_contrast();
|
||||
this._rebuild_filter_styles();
|
||||
|
||||
if ( ! this.has_bttv && this.settings.fix_color == '1' )
|
||||
if ( ! this.has_bttv && this.settings.fix_color === 1 )
|
||||
this._rebuild_colors();
|
||||
}
|
||||
};
|
||||
|
@ -111,7 +114,7 @@ FFZ.settings_info.color_blind = {
|
|||
help: "Adjust username colors in an attempt to make them more distinct for people with color blindness.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( ! this.has_bttv && this.settings.fix_color !== '-1' )
|
||||
if ( ! this.has_bttv && this.settings.fix_color !== -1 )
|
||||
this._rebuild_colors();
|
||||
}
|
||||
};
|
||||
|
@ -122,7 +125,7 @@ FFZ.settings_info.color_blind = {
|
|||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_colors = function() {
|
||||
this.toggle_style('chat-colors-gray', !this.has_bttv && this.settings.fix_color === '-1');
|
||||
this.toggle_style('chat-colors-gray', !this.has_bttv && this.settings.fix_color === -1);
|
||||
|
||||
this._hex_colors = {};
|
||||
this._rebuild_contrast();
|
||||
|
@ -723,7 +726,7 @@ FFZ.prototype._handle_color = function(color) {
|
|||
|
||||
|
||||
// Color Processing - RGB
|
||||
if ( this.settings.fix_color === '4' ) {
|
||||
if ( this.settings.fix_color === 4 ) {
|
||||
var lum = rgb.luminance();
|
||||
|
||||
if ( lum > 0.3 ) {
|
||||
|
@ -750,8 +753,17 @@ FFZ.prototype._handle_color = function(color) {
|
|||
}
|
||||
|
||||
|
||||
// Color Processing - HSL BTTV-Like
|
||||
/*if ( this.settings.fix_color === 5 ) {
|
||||
var hsl = rgb.toHSLA();
|
||||
|
||||
light_color = hsl._l(Math.min(Math.max(0, .9 * (1 - hsl.l)), 1)).toRGBA();
|
||||
dark_color = hsl._l(Math.min(Math.max(0, 1 - .9 * (1 - hsl.l)), 1)).toRGBA();
|
||||
}*/
|
||||
|
||||
|
||||
// Color Processing - HSL
|
||||
if ( this.settings.fix_color === '2' ) {
|
||||
if ( this.settings.fix_color === 2 ) {
|
||||
var hsl = rgb.toHSLA();
|
||||
|
||||
light_color = hsl._l(Math.min(Math.max(0, 0.7 * hsl.l), 1)).toRGBA();
|
||||
|
@ -760,7 +772,7 @@ FFZ.prototype._handle_color = function(color) {
|
|||
|
||||
|
||||
// Color Processing - HSV
|
||||
if ( this.settings.fix_color === '3' ) {
|
||||
if ( this.settings.fix_color === 3 ) {
|
||||
var hsv = rgb.toHSVA();
|
||||
|
||||
if ( hsv.s === 0 ) {
|
||||
|
@ -775,7 +787,7 @@ FFZ.prototype._handle_color = function(color) {
|
|||
}
|
||||
|
||||
// Color Processing - LUV
|
||||
if ( this.settings.fix_color === '1' ) {
|
||||
if ( this.settings.fix_color === 1 ) {
|
||||
var luv = rgb.toLUVA();
|
||||
|
||||
if ( luv.l > this._luv_required_dark )
|
||||
|
|
|
@ -108,7 +108,7 @@ FFZ.prototype.setup_channel = function() {
|
|||
|
||||
if ( f._cindex )
|
||||
f._cindex.ffzFixTitle();
|
||||
}.observes("content.status", "content.id", "hostModeTarget.status", "hostModeTarget.id"),
|
||||
}.observes("content.status", "content.game", "content.id", "hostModeTarget.status", "hostModeTarget.id", "hostModeTarget.game"),
|
||||
|
||||
ffzHostTarget: function() {
|
||||
var target = this.get('content.hostModeTarget'),
|
||||
|
@ -528,14 +528,20 @@ FFZ.prototype.modify_channel_index = function(view) {
|
|||
je = jQuery(stat_el);
|
||||
|
||||
var delay = Math.round(stats.hls_latency_broadcaster / 10) / 100,
|
||||
dropped = utils.number_commas(stats.dropped_frames || 0),
|
||||
bitrate;
|
||||
|
||||
if ( stats.playback_bytes_per_second )
|
||||
bitrate = Math.round(stats.playback_bytes_per_second * 8 / 10.24) / 100;
|
||||
else
|
||||
bitrate = Math.round(stats.current_bitrate * 100) / 100;
|
||||
|
||||
if ( delay > 180 ) {
|
||||
delay = Math.floor(delay);
|
||||
stat_el.setAttribute('original-title', 'Video Information<br>Broadcast ' + utils.time_to_string(delay, true) + ' Ago<br><br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps')
|
||||
stat_el.setAttribute('original-title', 'Video Information<br>Broadcast ' + utils.time_to_string(delay, true) + ' Ago<br><br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps<br>Dropped Frames: ' + dropped);
|
||||
el.textContent = utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old';
|
||||
} else {
|
||||
stat_el.setAttribute('original-title', 'Stream Latency<br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps');
|
||||
stat_el.setAttribute('original-title', 'Stream Latency<br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps<br>Dropped Frames: ' + dropped);
|
||||
delay = delay.toString();
|
||||
var ind = delay.indexOf('.');
|
||||
if ( ind === -1 )
|
||||
|
@ -597,14 +603,20 @@ FFZ.prototype.modify_channel_index = function(view) {
|
|||
je = jQuery(stat_el);
|
||||
|
||||
var delay = Math.round(stats.hls_latency_broadcaster / 10) / 100,
|
||||
dropped = utils.number_commas(stats.dropped_frames || 0),
|
||||
bitrate;
|
||||
|
||||
if ( stats.playback_bytes_per_second )
|
||||
bitrate = Math.round(stats.playback_bytes_per_second * 8 / 10.24) / 100;
|
||||
else
|
||||
bitrate = Math.round(stats.current_bitrate * 100) / 100;
|
||||
|
||||
if ( delay > 180 ) {
|
||||
delay = Math.floor(delay);
|
||||
stat_el.setAttribute('original-title', 'Video Information<br>Broadcast ' + utils.time_to_string(delay, true) + ' Ago<br><br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps')
|
||||
stat_el.setAttribute('original-title', 'Video Information<br>Broadcast ' + utils.time_to_string(delay, true) + ' Ago<br><br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps<br>Dropped Frames: ' + dropped);
|
||||
el.textContent = utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old';
|
||||
} else {
|
||||
stat_el.setAttribute('original-title', 'Stream Latency<br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps');
|
||||
stat_el.setAttribute('original-title', 'Stream Latency<br>Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p @ ' + stats.current_fps + '<br>Playback Rate: ' + bitrate + ' Kbps<br>Dropped Frames: ' + dropped);
|
||||
delay = delay.toString();
|
||||
var ind = delay.indexOf('.');
|
||||
if ( ind === -1 )
|
||||
|
|
|
@ -10,6 +10,7 @@ var FFZ = window.FrankerFaceZ,
|
|||
FFZ.basic_settings.delayed_chat = {
|
||||
type: "select",
|
||||
options: {
|
||||
"-1": "Default Delay (Room Specific; Non-Mod Only)",
|
||||
0: "No Delay",
|
||||
300: "Minor (Bot Moderation; 0.3s)",
|
||||
1200: "Normal (Human Moderation; 1.2s)",
|
||||
|
@ -137,6 +138,7 @@ FFZ.settings_info.chat_batching = {
|
|||
FFZ.settings_info.chat_delay = {
|
||||
type: "select",
|
||||
options: {
|
||||
"-1": "Default Delay (Room Specific; Non-Mod Only)",
|
||||
0: "No Delay",
|
||||
300: "Minor (Bot Moderation; 0.3s)",
|
||||
1200: "Normal (Human Moderation; 1.2s)",
|
||||
|
@ -147,7 +149,7 @@ FFZ.settings_info.chat_delay = {
|
|||
30000: "Half a Minute (30s)",
|
||||
60000: "Why??? (1m)"
|
||||
},
|
||||
value: 0,
|
||||
value: -1,
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
@ -162,6 +164,12 @@ FFZ.settings_info.chat_delay = {
|
|||
},
|
||||
|
||||
on_update: function (val) {
|
||||
for(var room_id in this.rooms) {
|
||||
var room = this.rooms[room_id].room;
|
||||
if ( room )
|
||||
Ember.propertyDidChange(room, 'ffz_chat_delay');
|
||||
}
|
||||
|
||||
if ( this._roomv )
|
||||
this._roomv.ffzUpdateStatus();
|
||||
}
|
||||
|
|
|
@ -220,19 +220,18 @@ FFZ.prototype.setup_directory = function() {
|
|||
} else
|
||||
this.log("Unable to locate the Ember service:vod-coviews");
|
||||
|
||||
|
||||
this.log("Attempting to modify the Following collection.");
|
||||
this._modify_following();
|
||||
|
||||
this.log("Hooking the Ember Directory views.");
|
||||
|
||||
this.update_views('component:stream-preview', function(x) { this.modify_directory_live(x, false) }, true);
|
||||
this.update_views('component:creative-preview', function(x) { this.modify_directory_live(x, false) }, true);
|
||||
this.update_views('component:csgo-channel-preview', function(x) { this.modify_directory_live(x, true) }, true);
|
||||
this.update_views('component:host-preview', this.modify_directory_host, true);
|
||||
this.update_views('component:host-preview', this.modify_directory_host, true, true);
|
||||
this.update_views('component:video-preview', this.modify_video_preview, true);
|
||||
|
||||
this.update_views('component:game-follow-button', this.modify_game_follow_button);
|
||||
|
||||
this.log("Attempting to modify the Following collection.");
|
||||
this._modify_following();
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,7 +269,7 @@ FFZ.prototype._modify_following = function() {
|
|||
|
||||
// Don't use FFZ's Client ID because loading hosts is a normal part
|
||||
// of the dashboard. We're just manipulating the logic a bit.
|
||||
return Twitch.api.get("/api/users/:login/followed/hosting", t);
|
||||
return this.get("api").request("get", "/api/users/:login/followed/hosting", t);
|
||||
},
|
||||
|
||||
afterSuccess: function(e) {
|
||||
|
|
|
@ -2,7 +2,10 @@ var FFZ = window.FrankerFaceZ,
|
|||
utils = require('../utils'),
|
||||
constants = require('../constants'),
|
||||
|
||||
createElement = utils.createElement;
|
||||
createElement = utils.createElement,
|
||||
|
||||
FOLLOWING_RE = /^\/kraken\/users\/([^/]+)\/follows\/channels/,
|
||||
FOLLOWER_RE = /^\/kraken\/channels\/([^/]+)\/follows/;
|
||||
|
||||
|
||||
// --------------------
|
||||
|
@ -33,200 +36,73 @@ FFZ.prototype.setup_profile_following = function() {
|
|||
this._following_cache = {};
|
||||
this._follower_cache = {};
|
||||
|
||||
/*try {
|
||||
var ChannelSerializer = window.require("web-client/serializers/new-channel"),
|
||||
BaseSerializer = window.require("web-client/serializers/application"),
|
||||
process_channel = function(chan) {
|
||||
var cid = chan.name;
|
||||
return {
|
||||
type: "new-channel",
|
||||
id: cid,
|
||||
attributes: chan,
|
||||
relationships: {
|
||||
following: {
|
||||
links: {
|
||||
related: "/kraken/users/" + cid + "/follows/channels?offset=0&on_site=1"
|
||||
}
|
||||
|
||||
// We want to hook the API to gather this information. It's easier than
|
||||
// modifying the deserialization path.
|
||||
var process_follows = function(channel_id, data, cache) {
|
||||
f.log("Loading Follow Information for: " + channel_id, data);
|
||||
|
||||
var user_cache = cache[channel_id] = cache[channel_id] || {},
|
||||
now = Date.now();
|
||||
|
||||
for(var i=0; i < data.length; i++) {
|
||||
var follow = data[i],
|
||||
user = follow && (follow.user || follow.channel);
|
||||
|
||||
if ( ! user || ! user.name )
|
||||
continue;
|
||||
|
||||
if ( user.display_name )
|
||||
FFZ.capitalization[user.name] = [user.display_name, now];
|
||||
|
||||
user_cache[user.name] = [
|
||||
follow.created_at ? utils.parse_date(follow.created_at) : null,
|
||||
follow.notifications || false];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var ServiceAPI = utils.ember_lookup('service:api');
|
||||
if ( ServiceAPI )
|
||||
ServiceAPI.reopen({
|
||||
request: function(method, url, data, options) {
|
||||
if ( method !== 'get' || url.indexOf('/kraken/') !== 0 )
|
||||
return this._super(method, url, data, options);
|
||||
|
||||
var t = this;
|
||||
return new Promise(function(success, fail) {
|
||||
t._super(method, url, data, options).then(function(result) {
|
||||
if ( result.follows ) {
|
||||
var match = FOLLOWING_RE.exec(url);
|
||||
if ( match )
|
||||
// Following Information
|
||||
process_follows(match[1], result.follows, f._following_cache);
|
||||
|
||||
match = FOLLOWER_RE.exec(url);
|
||||
if ( match )
|
||||
// Follower Information
|
||||
process_follows(match[1], result.follows, f._follower_cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var ser = ChannelSerializer.default = BaseSerializer.default.extend({
|
||||
normalizeFindRecordResponse: function(e, t, a, r) {
|
||||
var l = process_channel(a);
|
||||
return this._super(e, t, {
|
||||
data: l
|
||||
}, r)
|
||||
},
|
||||
|
||||
normalizeResponse: function(e, t, a, r, l) {
|
||||
if ( ! a.follows )
|
||||
return this._super.apply(this, arguments);
|
||||
|
||||
f.log("Normalizing Response", [e, t, a, r, l]);
|
||||
var i = this.extractMeta(e, t, a),
|
||||
o = a.follows.map(function(e) {
|
||||
return process_channel(e.channel);
|
||||
}),
|
||||
d = {
|
||||
data: o,
|
||||
meta: i
|
||||
};
|
||||
|
||||
return this._super(e, t, d, r, l);
|
||||
success(result);
|
||||
}).catch(function(err) {
|
||||
fail(result);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
App.registry.unregister('serializer:new-channel');
|
||||
App.registry.register('serializer:new-channel', ser);
|
||||
|
||||
} catch(err) {
|
||||
this.error("Unable to modify the Ember new-channel serializer", err);
|
||||
}*/
|
||||
else
|
||||
this.error("Unable to locate the Ember service:api");
|
||||
|
||||
|
||||
// First, we need to hook the model. This is what we'll use to grab the following notification state,
|
||||
// rather than making potentially hundreds of API requests.
|
||||
var Following = utils.ember_resolve('model:kraken-channel-following');
|
||||
if ( Following )
|
||||
this._hook_following(Following);
|
||||
|
||||
var Followers = utils.ember_resolve('model:user-followers');
|
||||
if ( Followers )
|
||||
this._hook_followers(Followers);
|
||||
|
||||
// Also try hooking that other model.
|
||||
var Notification = utils.ember_resolve('model:notification');
|
||||
if ( Notification )
|
||||
this._hook_following(Notification, true);
|
||||
|
||||
|
||||
// Find the followed item view
|
||||
var FollowedItem = utils.ember_resolve('component:display-followed-item');
|
||||
if ( ! FollowedItem )
|
||||
return;
|
||||
|
||||
this._modify_display_followed_item(FollowedItem);
|
||||
|
||||
|
||||
// Now, we need to edit the profile Following view itself.
|
||||
var ProfileView = utils.ember_resolve('view:channel/following');
|
||||
if ( ! ProfileView )
|
||||
return;
|
||||
|
||||
ProfileView.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
try {
|
||||
this.ffzInit();
|
||||
} catch(err) {
|
||||
f.error("ProfileView ffzInit: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
ffzInit: function() {
|
||||
// Only process our own profile following page.
|
||||
if ( ! f.settings.enhance_profile_following )
|
||||
return;
|
||||
|
||||
var el = this.get('element'),
|
||||
user = f.get_user(),
|
||||
user_id = this.get('context.model.id');
|
||||
|
||||
el.classList.add('ffz-enhanced-following');
|
||||
el.classList.toggle('ffz-my-following', user && user.login === user_id);
|
||||
el.setAttribute('data-user', user_id);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Add nice Manage Following button to the directory.
|
||||
|
||||
// Now, rebuild any views.
|
||||
try { FollowedItem.create().destroy();
|
||||
} catch(err) { }
|
||||
|
||||
var views = utils.ember_views();
|
||||
|
||||
if ( views ) {
|
||||
for(var key in views) {
|
||||
var view = views[key];
|
||||
if ( view instanceof FollowedItem ) {
|
||||
this.log("Manually updating existing component:display-followed-item.", view);
|
||||
try {
|
||||
if ( ! view.ffzInit )
|
||||
this._modify_display_followed_item(view);
|
||||
view.ffzInit();
|
||||
} catch(err) {
|
||||
this.error("setup: component:display-followed-item ffzInit: " + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Refresh all existing following data.
|
||||
var count = 0,
|
||||
Channel = utils.ember_resolve('model:deprecated-channel');
|
||||
|
||||
if ( Channel && Channel._cache )
|
||||
for(var key in Channel._cache) {
|
||||
var chan = Channel._cache[key];
|
||||
if ( chan instanceof Channel ) {
|
||||
var following = chan.get('following'),
|
||||
followers = chan.get('followers'),
|
||||
|
||||
refresher = function(x) {
|
||||
if ( x.get('isLoading') )
|
||||
setTimeout(refresher.bind(this,x), 25);
|
||||
|
||||
x.clear();
|
||||
x.load();
|
||||
};
|
||||
|
||||
// Make sure this channel's Following collection is modified.
|
||||
this._hook_following(following);
|
||||
this._hook_followers(followers);
|
||||
|
||||
var counted = false;
|
||||
if ( following && (following.get('isLoaded') || following.get('isLoading')) ) {
|
||||
refresher(following);
|
||||
count++;
|
||||
counted = true;
|
||||
}
|
||||
|
||||
if ( followers && (followers.get('isLoaded') || followers.get('isLoading')) ) {
|
||||
refresher(followers);
|
||||
if ( ! counted )
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f.log("Refreshing previously loaded user following data for " + count + " channels.");
|
||||
// Modify followed items.
|
||||
this.update_views('component:display-followed-item', this.modify_display_followed_item);
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._modify_display_followed_item = function(component) {
|
||||
FFZ.prototype.modify_display_followed_item = function(component) {
|
||||
var f = this;
|
||||
component.reopen({
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
try {
|
||||
this.ffzInit();
|
||||
} catch(err) {
|
||||
f.error("component:display-followed-item ffzInit: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
willClearRender: function() {
|
||||
try {
|
||||
this.ffzTeardown();
|
||||
} catch(err) {
|
||||
f.error("component:display-followed-item ffzTeardown: " + err);
|
||||
}
|
||||
},
|
||||
|
||||
utils.ember_reopen_view(component, {
|
||||
ffzParentModel: function() {
|
||||
var x = this.get('parentView');
|
||||
while(x) {
|
||||
|
@ -237,7 +113,7 @@ FFZ.prototype._modify_display_followed_item = function(component) {
|
|||
}
|
||||
}.property('parentView'),
|
||||
|
||||
ffzInit: function() {
|
||||
ffz_init: function() {
|
||||
var el = this.get('element'),
|
||||
channel_id = this.get('ffzParentModel.id'), //.get('parentView.parentView.parentView.model.id'),
|
||||
is_following = document.body.getAttribute('data-current-path').indexOf('.following') !== -1,
|
||||
|
@ -271,7 +147,7 @@ FFZ.prototype._modify_display_followed_item = function(component) {
|
|||
|
||||
if ( age !== undefined ) {
|
||||
t_el.innerHTML = constants.CLOCK + ' ' + (age < 60 ? 'now' : utils.human_time(age, 10));
|
||||
t_el.title = 'Following Since: <nobr>' + data[0].toLocaleString() + '</nobr>';
|
||||
t_el.title = 'Follow' + (is_following ? 'ing' : 'er') + ' Since: <nobr>' + data[0].toLocaleString() + '</nobr>';
|
||||
t_el.style.display = '';
|
||||
} else
|
||||
t_el.style.display = 'none';
|
||||
|
@ -347,91 +223,6 @@ FFZ.prototype._modify_display_followed_item = function(component) {
|
|||
actions.appendChild(notif);
|
||||
|
||||
el.appendChild(actions);
|
||||
},
|
||||
|
||||
ffzTeardown: function() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
FFZ.prototype._hook_following = function(Following) {
|
||||
var f = this;
|
||||
if ( ! Following || Following.ffz_hooked )
|
||||
return;
|
||||
|
||||
Following.reopen({
|
||||
ffz_hooked: true,
|
||||
apiLoad: function(e) {
|
||||
var channel_id = this.get('id'),
|
||||
t = this;
|
||||
|
||||
f._following_cache[channel_id] = f._following_cache[channel_id] || {};
|
||||
|
||||
return new RSVP.Promise(function(success, fail) {
|
||||
t._super(e).then(function(data) {
|
||||
if ( data && data.follows ) {
|
||||
var now = Date.now();
|
||||
for(var i=0; i < data.follows.length; i++) {
|
||||
var follow = data.follows[i];
|
||||
if ( ! follow || ! follow.channel || ! follow.channel.name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( follow.channel.display_name )
|
||||
FFZ.capitalization[follow.channel.name] = [follow.channel.display_name, now];
|
||||
|
||||
f._following_cache[channel_id][follow.channel.name] = [follow.created_at ? utils.parse_date(follow.created_at) : null, follow.notifications || false];
|
||||
}
|
||||
}
|
||||
|
||||
success(data);
|
||||
|
||||
}, function(err) {
|
||||
fail(err);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
FFZ.prototype._hook_followers = function(Followers) {
|
||||
var f = this;
|
||||
if ( ! Followers || Followers.ffz_hooked )
|
||||
return;
|
||||
|
||||
Followers.reopen({
|
||||
ffz_hooked: true,
|
||||
apiLoad: function(e) {
|
||||
var channel_id = this.get('id'),
|
||||
t = this;
|
||||
|
||||
f._follower_cache[channel_id] = f._follower_cache[channel_id] || {};
|
||||
|
||||
return new RSVP.Promise(function(success, fail) {
|
||||
t._super(e).then(function(data) {
|
||||
if ( data && data.follows ) {
|
||||
var now = Date.now();
|
||||
for(var i=0; i < data.follows.length; i++) {
|
||||
var follow = data.follows[i];
|
||||
if ( ! follow || ! follow.user || ! follow.user.name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( follow.user.display_name )
|
||||
FFZ.capitalization[follow.user.name] = [follow.user.display_name, now];
|
||||
|
||||
f._follower_cache[channel_id][follow.user.name] = [follow.created_at ? utils.parse_date(follow.created_at) : null, follow.notifications || false];
|
||||
}
|
||||
}
|
||||
|
||||
success(data);
|
||||
|
||||
}, function(err) {
|
||||
fail(err);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -136,6 +136,31 @@ FFZ.settings_info.right_column_width = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.minimal_channel_title = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Appearance",
|
||||
no_mobile: true,
|
||||
no_bttv: true,
|
||||
|
||||
name: "Minimal Channel Title",
|
||||
help: "Hide the channel's name and current game when viewing a channel to maximize player size.",
|
||||
|
||||
on_update: function(val) {
|
||||
if ( this.has_bttv )
|
||||
return;
|
||||
|
||||
var Layout = utils.ember_lookup('service:layout');
|
||||
if ( ! Layout )
|
||||
return;
|
||||
|
||||
document.body.classList.toggle('ffz-minimal-channel-title', val);
|
||||
Ember.propertyDidChange(Layout, 'windowHeight');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------------
|
||||
// Initialization
|
||||
// --------------------
|
||||
|
@ -145,6 +170,7 @@ FFZ.prototype.setup_layout = function() {
|
|||
return;
|
||||
|
||||
document.body.classList.toggle("ffz-sidebar-swap", this.settings.swap_sidebars);
|
||||
document.body.classList.toggle('ffz-minimal-channel-title', this.settings.minimal_channel_title);
|
||||
|
||||
this.log("Creating layout style element.");
|
||||
var s = this._layout_style = document.createElement('style');
|
||||
|
@ -207,7 +233,7 @@ FFZ.prototype.setup_layout = function() {
|
|||
r = this.get('contentWidth'),
|
||||
|
||||
i = (9 * r / 16) + c,
|
||||
d = h - 120 - 60,
|
||||
d = h - (f.settings.minimal_channel_title ? 75 : 120) - 60,
|
||||
c = h - 94 - 185,
|
||||
|
||||
l = Math.floor(r),
|
||||
|
@ -261,7 +287,7 @@ FFZ.prototype.setup_layout = function() {
|
|||
var size = this.get('playerSize'),
|
||||
video_below = this.get('portraitVideoBelow'),
|
||||
|
||||
video_height = size[1] + 120 + 60,
|
||||
video_height = size[1] + (f.settings.minimal_channel_title ? 75 : 120) + 60,
|
||||
chat_height = window_height - video_height,
|
||||
|
||||
video_top = video_below ? chat_height : 0,
|
||||
|
@ -307,6 +333,7 @@ FFZ.prototype.setup_layout = function() {
|
|||
'#right_col{width:' + width + 'px}' +
|
||||
'body:not(.ffz-sidebar-swap) #main_col:not(.expandRight){' +
|
||||
'margin-right:' + width + 'px}' +
|
||||
'body.ffz-sidebar-swap .theatre #main_col:not(.expandRight),' +
|
||||
'body.ffz-sidebar-swap #main_col:not(.expandRight){' +
|
||||
'margin-left:' + width + 'px}';
|
||||
}
|
||||
|
|
|
@ -679,9 +679,9 @@ FFZ.prototype._modify_chat_line = function(component, is_vod) {
|
|||
Settings = utils.ember_lookup('controller:settings');
|
||||
|
||||
component.reopen({
|
||||
tokenizedMessage: function() {
|
||||
return [];
|
||||
}.property('msgObject.message'),
|
||||
/*tokenizedMessage: function() {
|
||||
return [{type: 'text', text: 'hi'}];
|
||||
}.property('msgObject.message'),*/
|
||||
|
||||
ffzTokenizedMessage: function() {
|
||||
try {
|
||||
|
|
|
@ -1285,7 +1285,7 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from) {
|
|||
if ( alias )
|
||||
out.push('<span class="from ffz-alias html-tooltip' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '" title="' + utils.quote_san(name) + '">' + utils.sanitize(alias) + '</span>');
|
||||
else
|
||||
out.push('<span class="from' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '">' + utils.sanitize(name ) + '</span>');
|
||||
out.push('<span class="from' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '">' + utils.sanitize(name) + '</span>');
|
||||
|
||||
out.push('<span class="colon">:</span> ');
|
||||
}
|
||||
|
@ -1299,7 +1299,7 @@ FFZ.prototype._build_mod_card_history = function(msg, modcard, show_from) {
|
|||
|
||||
|
||||
var message = '<span class="message' + colored + '" style="' + style + (colors ? '" data-color="' + raw_color : '') + '">' +
|
||||
(msg.style === 'action' && ! show_from ? '*' + name + ' ' : '') + this.render_tokens(msg.cachedTokens) + '</span>';
|
||||
(msg.style === 'action' && ! show_from ? '*' + name + ' ' : '') + this.render_tokens(msg.cachedTokens, true, false, msg.tags && msg.tags.bits) + '</span>';
|
||||
|
||||
if ( msg.deleted )
|
||||
out.push('<span class="deleted"><a class="undelete" href="#" data-message="' + utils.quote_attr(message) + '"><message deleted></a></span>');
|
||||
|
|
|
@ -59,6 +59,27 @@ FFZ.settings_info.player_volume_bar = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.player_pause_hosts = {
|
||||
type: "select",
|
||||
options: {
|
||||
0: "Disabled",
|
||||
1: "When Hosting Channel was Paused",
|
||||
2: "Always"
|
||||
},
|
||||
|
||||
value: 1,
|
||||
process_value: function(val) {
|
||||
if ( typeof val === "string" )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
category: "Player",
|
||||
name: "Auto-Pause Hosted Channels",
|
||||
help: "Automatically pause hosted channels if you paused the channel doing the hosting, or just pause all hosts."
|
||||
}
|
||||
|
||||
|
||||
// ---------------
|
||||
// Initialization
|
||||
// ---------------
|
||||
|
@ -72,6 +93,7 @@ FFZ.prototype.setup_player = function() {
|
|||
Layout.set('PLAYER_CONTROLS_HEIGHT', this.settings.classic_player ? 32 : 0);
|
||||
|
||||
this.players = {};
|
||||
this.players_paused = {};
|
||||
|
||||
this.update_views('component:twitch-player2', this.modify_twitch_player);
|
||||
}
|
||||
|
@ -89,7 +111,7 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
f.players[id] = this;
|
||||
|
||||
var player = this.get('player');
|
||||
if ( player )
|
||||
if ( player && !this.get('ffz_post_player') )
|
||||
this.ffzPostPlayer();
|
||||
},
|
||||
|
||||
|
@ -99,10 +121,33 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
f.players[id] = undefined;
|
||||
},
|
||||
|
||||
insertPlayer: function(ffz_reset) {
|
||||
// We want to see if this is a hosted video on a play
|
||||
var should_start_paused = this.get('shouldStartPaused'),
|
||||
hosting_channel = this.get('hostChannel.id');
|
||||
|
||||
// Always start unpaused if the person used the FFZ setting to Reset Player.
|
||||
if ( ffz_reset )
|
||||
this.set('shouldStartPaused', false);
|
||||
|
||||
// Alternatively, depending on the setting...
|
||||
else if (
|
||||
(f.settings.player_pause_hosts === 1 && f.players_paused[hosting_channel]) ||
|
||||
(f.settings.player_pause_hosts === 2 && hosting_channel) )
|
||||
this.set('shouldStartPaused', true);
|
||||
|
||||
this._super();
|
||||
|
||||
// Restore the previous value so it doesn't mess anything up.
|
||||
this.set('shouldStartPaused', should_start_paused);
|
||||
|
||||
}.on('didInsertElement'),
|
||||
|
||||
postPlayerSetup: function() {
|
||||
this._super();
|
||||
try {
|
||||
this.ffzPostPlayer();
|
||||
if ( ! this.get('ffz_post_player') )
|
||||
this.ffzPostPlayer();
|
||||
} catch(err) {
|
||||
f.error("Player2 postPlayerSetup: " + err);
|
||||
}
|
||||
|
@ -122,7 +167,15 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
this.set('player', null);
|
||||
|
||||
// Now, let Twitch create a new player as usual.
|
||||
Ember.run.next(this.insertPlayer.bind(this));
|
||||
Ember.run.next(this.insertPlayer.bind(this, true));
|
||||
},
|
||||
|
||||
ffzUpdatePlayerPaused: function() {
|
||||
var id = this.get('channel.id'),
|
||||
is_paused = this.get('player.paused');
|
||||
|
||||
f.log("Player Pause State for " + id + ": " + is_paused);
|
||||
f.players_paused[id] = is_paused;
|
||||
},
|
||||
|
||||
ffzPostPlayer: function() {
|
||||
|
@ -130,6 +183,12 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
if ( ! player )
|
||||
return;
|
||||
|
||||
this.set('ffz_post_player', true);
|
||||
f.players_paused[this.get('channel.id')] = player.paused;
|
||||
|
||||
player.addEventListener('pause', this.ffzUpdatePlayerPaused.bind(this));
|
||||
player.addEventListener('play', this.ffzUpdatePlayerPaused.bind(this));
|
||||
|
||||
// Make the stats window draggable and fix the button.
|
||||
var stats = this.$('.player .js-playback-stats');
|
||||
stats.draggable({cancel: 'li', containment: 'parent'});
|
||||
|
@ -156,6 +215,7 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
}
|
||||
|
||||
// Check player statistics. If necessary, override getVideoInfo.
|
||||
/*
|
||||
if ( ! Object.keys(player.getVideoInfo()).length && ! player.ffz_stats_hooked ) {
|
||||
f.log("No Video Data. Installing handler.");
|
||||
player.ffz_stats_hooked = true;
|
||||
|
@ -189,10 +249,6 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
toggle_btn.text('Show Video Stats');
|
||||
|
||||
jQuery('.js-stats-close', stats_el).remove();
|
||||
/*off().on('click', function(e) {
|
||||
stats_el.classList.add('hidden');
|
||||
toggle_btn.text('Show Video Stats');
|
||||
});*/
|
||||
|
||||
toggle_btn.off().on('click', function(e) {
|
||||
var visible = stats_el.classList.contains('hidden');
|
||||
|
@ -257,13 +313,6 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
val2 *= 1000;
|
||||
}
|
||||
|
||||
// Only make this change for known bad versions.
|
||||
var version = player.getVersion();
|
||||
if ( version === "0.5.4" ) {
|
||||
val -= (f._ws_server_offset || 0);
|
||||
val2 -= (f._ws_server_offset || 0);
|
||||
}
|
||||
|
||||
if ( val > val2 ) {
|
||||
output.hls_latency_broadcaster = val;
|
||||
output.hls_latency_encoder = val2;
|
||||
|
@ -296,7 +345,7 @@ FFZ.prototype.modify_twitch_player = function(player) {
|
|||
};
|
||||
|
||||
setup_player();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
}
|
|
@ -10,7 +10,7 @@ var FFZ = window.FrankerFaceZ,
|
|||
["sub", "subsOnly", "This room is in subscribers-only mode."],
|
||||
["slow", "slow", function(room) { return "This room is in slow mode. You may send messages every " + utils.number_commas(room && room.get('slow') || 120) + " seconds." }],
|
||||
["ban", "ffz_banned", "You have been banned from talking in this room."],
|
||||
["delay", function() { return this.settings.chat_delay !== 0 }, function() { return "You have enabled artificial chat delay. Messages are displayed after " + (this.settings.chat_delay/1000) + " seconds." }],
|
||||
["delay", function(room) { return room && room.get('ffz_chat_delay') !== 0 }, function(room) { return "Artificial chat delay is enabled. Messages are displayed after " + (room.get('ffz_chat_delay')/1000) + " seconds." }],
|
||||
["batch", function() { return this.settings.chat_batching !== 0 }, function() { return "You have enabled chat message batching. Messages are displayed in " + (this.settings.chat_batching/1000) + " second increments." }]
|
||||
],
|
||||
|
||||
|
@ -158,6 +158,14 @@ FFZ.prototype.modify_room_view = function(view) {
|
|||
calcRecipientEligibility: function(e) {
|
||||
// Because this doesn't work properly with multiple channel rooms
|
||||
// by default, do it ourselves.
|
||||
if ( controller.get('model.isGroupRoom') ) {
|
||||
controller.set('isRecipientBitsIneligible', true);
|
||||
controller.set('isBitsHelperShown', false);
|
||||
controller.set('minimumBits', 0);
|
||||
controller.set('isBitsTooltipActive', false);
|
||||
return;
|
||||
}
|
||||
|
||||
var id = controller.get('model.roomProperties._id'),
|
||||
update = function(data) {
|
||||
if ( controller.isDestroyed || controller.get('model.roomProperties._id') !== id )
|
||||
|
@ -1008,10 +1016,9 @@ FFZ.prototype._modify_room = function(room) {
|
|||
user = f.get_user(),
|
||||
room_id = this.get('id');
|
||||
|
||||
/* ???
|
||||
if ( (Chat && Chat.get('currentChannelRoom') === this) || (user && user.login === room_id) || (f._chatv && f._chatv._ffz_host === room_id) || (f.settings.pinned_rooms && f.settings.pinned_rooms.indexOf(room_id) !== -1) )
|
||||
f.ws_unsub()
|
||||
return this.ffzUnsubscribe(true);*/
|
||||
// Don't destroy the room if it's still relevant.
|
||||
if ( (Chat && Chat.get('currentChannelRoom') === this) || (user && user.login === room_id) || (f._chatv && f._chatv._ffz_host === room_id) || (f.settings.pinned_rooms && f.settings.pinned_rooms.indexOf(room_id) !== -1) )
|
||||
return;
|
||||
|
||||
this.destroy();
|
||||
},
|
||||
|
@ -1336,8 +1343,24 @@ FFZ.prototype._modify_room = function(room) {
|
|||
},
|
||||
|
||||
// Artificial chat delay
|
||||
ffz_chat_delay: function() {
|
||||
var val = f.settings.chat_delay;
|
||||
if ( val !== -1 )
|
||||
return val;
|
||||
|
||||
val = this.get('roomProperties.chat_delay_duration');
|
||||
return ( Number.isNaN(val) || ! Number.isFinite(val) || this.get('isModeratorOrHigher') ) ? 0 : val;
|
||||
|
||||
}.property('roomProperties.chat_delay_duration', 'isModeratorOrHigher'),
|
||||
|
||||
ffz_update_display: function() {
|
||||
if ( f._roomv )
|
||||
f._roomv.ffzUpdateStatus();
|
||||
|
||||
}.observes('roomProperties.chat_delay_duration'),
|
||||
|
||||
pushMessage: function(msg) {
|
||||
if ( f.settings.chat_batching !== 0 || f.settings.chat_delay !== 0 || (this.ffzPending && this.ffzPending.length) ) {
|
||||
if ( f.settings.chat_batching !== 0 || this.get('ffz_chat_delay') !== 0 || (this.ffzPending && this.ffzPending.length) ) {
|
||||
if ( ! this.ffzPending )
|
||||
this.ffzPending = [];
|
||||
|
||||
|
@ -1381,8 +1404,9 @@ FFZ.prototype._modify_room = function(room) {
|
|||
// amount of time from the last batch.
|
||||
now = now || Date.now();
|
||||
var t = this,
|
||||
chat_delay = this.get('ffz_chat_delay'),
|
||||
delay = Math.max(
|
||||
(f.settings.chat_delay !== 0 ? 50 + Math.max(0, (f.settings.chat_delay + (this.ffzPending[0].time||0)) - now) : 0),
|
||||
(chat_delay !== 0 ? 50 + Math.max(0, (chat_delay + (this.ffzPending[0].time||0)) - now) : 0),
|
||||
(f.settings.chat_batching !== 0 ? Math.max(0, f.settings.chat_batching - (now - (this._ffz_last_batch||0))) : 0));
|
||||
|
||||
this._ffz_pending_flush = setTimeout(this.ffzPendingFlush.bind(this), delay);
|
||||
|
@ -1392,7 +1416,8 @@ FFZ.prototype._modify_room = function(room) {
|
|||
ffzPendingFlush: function() {
|
||||
this._ffz_pending_flush = null;
|
||||
|
||||
var now = this._ffz_last_batch = Date.now();
|
||||
var now = this._ffz_last_batch = Date.now(),
|
||||
chat_delay = this.get('ffz_chat_delay');
|
||||
|
||||
for (var i = 0, l = this.ffzPending.length; i < l; i++) {
|
||||
var msg = this.ffzPending[i];
|
||||
|
@ -1404,7 +1429,7 @@ FFZ.prototype._modify_room = function(room) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( f.settings.chat_delay !== 0 && (f.settings.chat_delay + msg.time > now) )
|
||||
if ( chat_delay !== 0 && (chat_delay + msg.time > now) )
|
||||
break;
|
||||
|
||||
msg.pending = false;
|
||||
|
@ -1524,7 +1549,10 @@ FFZ.prototype._modify_room = function(room) {
|
|||
|
||||
new_msg = {
|
||||
from: msg.from,
|
||||
tags: {'display-name': msg.tags && msg.tags['display-name']},
|
||||
tags: {
|
||||
'display-name': msg.tags && msg.tags['display-name'],
|
||||
bits: msg.tags && msg.tags.bits
|
||||
},
|
||||
message: msg.message,
|
||||
cachedTokens: msg.cachedTokens,
|
||||
style: msg.style,
|
||||
|
|
|
@ -54,6 +54,21 @@ FFZ.settings_info.sidebar_hide_recommended_channels = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.sidebar_hide_promoted_games = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Sidebar",
|
||||
no_mobile: true,
|
||||
|
||||
name: "Hide Promoted Games",
|
||||
help: "Hide the Promoted Games section from the sidebar.",
|
||||
|
||||
on_update: utils.toggle_cls('ffz-hide-promoted-games')
|
||||
};
|
||||
|
||||
|
||||
|
||||
FFZ.settings_info.sidebar_hide_recommended_friends = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
@ -131,12 +146,25 @@ FFZ.settings_info.sidebar_start_open = {
|
|||
};
|
||||
|
||||
|
||||
FFZ.settings_info.sidebar_directly_to_followed_channels = {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
|
||||
category: "Sidebar",
|
||||
no_mobile: true,
|
||||
|
||||
name: "Open Following to Channels",
|
||||
help: "When going to your Following directory, view the Live Channels tab by default."
|
||||
};
|
||||
|
||||
|
||||
// --------------------
|
||||
// Initialization
|
||||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_sidebar = function() {
|
||||
// CSS to Hide Stuff
|
||||
utils.toggle_cls('ffz-hide-promoted-games')(this.settings.sidebar_hide_promoted_games);
|
||||
utils.toggle_cls('ffz-hide-recommended-channels')(this.settings.sidebar_hide_recommended_channels);
|
||||
utils.toggle_cls('ffz-hide-recommended-friends')(this.settings.sidebar_hide_recommended_friends);
|
||||
utils.toggle_cls('ffz-hide-friends-collapsed')(this.settings.sidebar_hide_friends_collapsed);
|
||||
|
@ -188,51 +216,54 @@ FFZ.prototype.setup_sidebar = function() {
|
|||
} else
|
||||
this.error("Unable to load the Ember navigation controller.", null);
|
||||
|
||||
/*
|
||||
var NavView = this._modify_navigation(utils.ember_resolve('component:new-navigation')),
|
||||
views = utils.ember_views(),
|
||||
|
||||
el = document.querySelector('nav#js-warp'),
|
||||
view = el && views[el.parentElement.id];
|
||||
|
||||
if ( view ) {
|
||||
try {
|
||||
if ( ! view.ffzInit )
|
||||
this._modify_navigation(view);
|
||||
view.ffzInit();
|
||||
} catch(err) {
|
||||
this.error("Sidebar Setup", err);
|
||||
}
|
||||
}*/
|
||||
if ( this._views_to_update )
|
||||
this.update_views('view:navigation', this.modify_navigation, true);
|
||||
}
|
||||
|
||||
|
||||
/*FFZ.prototype._modify_navigation = function(component) {
|
||||
FFZ.prototype.setup_following_link = function() {
|
||||
var f = this,
|
||||
mutator = {
|
||||
didInsertElement: function() {
|
||||
this.ffzInit();
|
||||
},
|
||||
|
||||
ffzInit: function() {
|
||||
f._nav = this;
|
||||
f.log("Got New Navigation", this);
|
||||
|
||||
var el = this.get("element");
|
||||
|
||||
if ( f.settings.sidebar_start_open ) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if ( component )
|
||||
component.reopen(mutator);
|
||||
else if ( window.App && App.__deprecatedInstance__ ) {
|
||||
component = Ember.Component.extend(mutator);
|
||||
App.__deprecatedInstance__.registry.register('component:new-navigation', component);
|
||||
following_link = document.body.querySelector('#header_following');
|
||||
if ( following_link ) {
|
||||
following_link.href = '/directory/following' + (f.settings.sidebar_directly_to_followed_channels ? '/live' : '');
|
||||
following_link.addEventListener('click', function(e) {
|
||||
following_link.href = '/directory/following' + (f.settings.sidebar_directly_to_followed_channels ? '/live' : '');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return component;
|
||||
}*/
|
||||
|
||||
FFZ.prototype.modify_navigation = function(component) {
|
||||
var f = this;
|
||||
|
||||
utils.ember_reopen_view(component, {
|
||||
ffz_init: function() {
|
||||
f._nav = this;
|
||||
|
||||
// Override behavior for the Following link.
|
||||
var el = this.get('element'),
|
||||
following_link = el && el.querySelector('a[data-href="following"]');
|
||||
|
||||
if ( following_link ) {
|
||||
following_link.href = '/directory/following' + (f.settings.sidebar_directly_to_followed_channels ? '/live' : '');
|
||||
|
||||
following_link.addEventListener('click', function(e) {
|
||||
following_link.href = '/directory/following' + (f.settings.sidebar_directly_to_followed_channels ? '/live' : '');
|
||||
var router = utils.ember_lookup('router:main');
|
||||
if ( ! router || e && (e.button !== 0 || e.ctrlKey || e.metaKey) )
|
||||
return;
|
||||
|
||||
router.transitionTo('directory.following.' + (f.settings.sidebar_directly_to_followed_channels ? 'channels' : 'index'));
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
ffz_destroy: function() {
|
||||
if ( f._nav === this )
|
||||
f._nav = null;
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,5 +1,13 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
utils = require('../utils');
|
||||
utils = require('../utils'),
|
||||
|
||||
VIEWER_CATEGORIES = [
|
||||
['staff', 'Staff'],
|
||||
['admins', 'Admins'],
|
||||
['global_mods', 'Global Moderators'],
|
||||
['moderators', 'Moderators'],
|
||||
['viewers', 'Viewers']
|
||||
];
|
||||
|
||||
|
||||
// --------------------
|
||||
|
@ -21,46 +29,27 @@ FFZ.settings_info.sort_viewers = {
|
|||
// --------------------
|
||||
|
||||
FFZ.prototype.setup_viewers = function() {
|
||||
this.log("Hooking the Ember Viewers controller.");
|
||||
var Viewers = utils.ember_resolve('controller:viewers');
|
||||
if ( Viewers )
|
||||
this._modify_viewers(Viewers);
|
||||
|
||||
/* Disable for now because Twitch reverted this change
|
||||
this.log("Hooking the Ember Viewers view.");
|
||||
var ViewerView = utils.ember_resolve('view:viewers');
|
||||
if ( ViewerView )
|
||||
this._modify_viewer_view(ViewerView);*/
|
||||
this.update_views('component:chat/twitch-chat-viewers', this.modify_viewer_list);
|
||||
}
|
||||
|
||||
|
||||
/*FFZ.prototype._modify_viewer_view = function(view) {
|
||||
view.reopen({
|
||||
setListDimensions: function(e) {
|
||||
// Don't set the stupid scroll thing. Don't use the stupid height thing.
|
||||
this.$(".js-chatters-container").width(e.width).height(e.height);
|
||||
}
|
||||
});
|
||||
}*/
|
||||
|
||||
|
||||
FFZ.prototype._modify_viewers = function(controller) {
|
||||
FFZ.prototype.modify_viewer_list = function(component) {
|
||||
var f = this;
|
||||
|
||||
controller.reopen({
|
||||
utils.ember_reopen_view(component, {
|
||||
lines: function() {
|
||||
var viewers = this._super();
|
||||
if ( ! f.settings.sort_viewers )
|
||||
return viewers;
|
||||
return this._super();
|
||||
|
||||
try {
|
||||
var categories = [],
|
||||
data = {},
|
||||
last_category = null;
|
||||
var viewers = [],
|
||||
has_broadcaster = false,
|
||||
raw_viewers = this.get('model.chatters') || {};
|
||||
|
||||
// Get the broadcaster name.
|
||||
var Channel = utils.ember_lookup('controller:channel'),
|
||||
room_id = this.get('parentController.model.id'),
|
||||
room_id = this.get('model.id'),
|
||||
broadcaster = Channel && Channel.get('model.id');
|
||||
|
||||
// We can get capitalization for the broadcaster from the channel.
|
||||
|
@ -75,57 +64,45 @@ FFZ.prototype._modify_viewers = function(controller) {
|
|||
if ( room_id !== broadcaster )
|
||||
broadcaster = null;
|
||||
|
||||
// Now, break the viewer array down into something we can use.
|
||||
for(var i=0; i < viewers.length; i++) {
|
||||
var entry = viewers[i];
|
||||
if ( entry.category ) {
|
||||
last_category = entry.category;
|
||||
categories.push(last_category);
|
||||
data[last_category] = [];
|
||||
|
||||
} else {
|
||||
var viewer = entry.chatter.toLowerCase();
|
||||
if ( ! viewer )
|
||||
continue;
|
||||
// Iterate over everything~!
|
||||
for(var i=0; i < VIEWER_CATEGORIES.length; i++) {
|
||||
var data = raw_viewers[VIEWER_CATEGORIES[i][0]],
|
||||
label = VIEWER_CATEGORIES[i][1],
|
||||
first_user = true;
|
||||
|
||||
// If the viewer is the broadcaster, give them their own
|
||||
// group. Don't put them with normal mods!
|
||||
if ( viewer == broadcaster ) {
|
||||
categories.unshift("Broadcaster");
|
||||
data["Broadcaster"] = [viewer];
|
||||
|
||||
} else if ( data.hasOwnProperty(last_category) )
|
||||
data[last_category].push(viewer);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, rebuild the viewer list. However, we're going to actually
|
||||
// sort it this time.
|
||||
viewers = [];
|
||||
for(var i=0; i < categories.length; i++) {
|
||||
var category = categories[i],
|
||||
chatters = data[category];
|
||||
|
||||
if ( ! chatters || ! chatters.length )
|
||||
if ( ! data || ! data.length )
|
||||
continue;
|
||||
|
||||
viewers.push({category: category});
|
||||
viewers.push({chatter: ""});
|
||||
for(var x=0; x < data.length; x++) {
|
||||
if ( data[x] === broadcaster ) {
|
||||
has_broadcaster = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Push the chatters, capitalizing them as we go.
|
||||
chatters.sort();
|
||||
while(chatters.length) {
|
||||
var viewer = chatters.shift();
|
||||
viewer = FFZ.get_capitalization(viewer);
|
||||
viewers.push({chatter: viewer});
|
||||
if ( first_user ) {
|
||||
viewers.push({category: i18n(label)});
|
||||
viewers.push({chatter: ""});
|
||||
first_user = false;
|
||||
}
|
||||
|
||||
viewers.push({chatter: FFZ.get_capitalization(data[x])});
|
||||
}
|
||||
}
|
||||
|
||||
if ( has_broadcaster )
|
||||
viewers.splice(0, 0,
|
||||
{category: i18n("Broadcaster")},
|
||||
{chatter: ""},
|
||||
{chatter: FFZ.get_capitalization(broadcaster)});
|
||||
|
||||
return viewers;
|
||||
|
||||
} catch(err) {
|
||||
f.error("ViewersController lines: " + err);
|
||||
return this._super();
|
||||
}
|
||||
|
||||
return viewers;
|
||||
}.property("content.chatters")
|
||||
}.property("model.chatters")
|
||||
});
|
||||
}
|
|
@ -12,7 +12,7 @@ FFZ.prototype.setup_ember_wrapper = function() {
|
|||
}
|
||||
|
||||
|
||||
FFZ.prototype.update_views = function(klass, modifier, if_not_exists) {
|
||||
FFZ.prototype.update_views = function(klass, modifier, if_not_exists, immediate) {
|
||||
var original_klass;
|
||||
if ( typeof klass === 'string' ) {
|
||||
original_klass = klass;
|
||||
|
@ -33,7 +33,7 @@ FFZ.prototype.update_views = function(klass, modifier, if_not_exists) {
|
|||
} else
|
||||
original_klass = klass.toString();
|
||||
|
||||
if ( this._ember_finalized )
|
||||
if ( this._ember_finalized || immediate )
|
||||
this._update_views([[original_klass, klass, modifier]]);
|
||||
else
|
||||
this._views_to_update.push([original_klass, klass, modifier]);
|
||||
|
|
|
@ -210,7 +210,9 @@ FFZ.ws_commands.load_set = function(set_id) {
|
|||
// ---------------------
|
||||
|
||||
FFZ.prototype.load_emoji_data = function(callback, tries) {
|
||||
var f = this;
|
||||
var f = this,
|
||||
puny = window.punycode && punycode.ucs2;
|
||||
|
||||
jQuery.getJSON(constants.SERVER + "emoji/emoji-data.json")
|
||||
.done(function(data) {
|
||||
var new_data = {},
|
||||
|
@ -237,6 +239,8 @@ FFZ.prototype.load_emoji_data = function(callback, tries) {
|
|||
type: "emoticon",
|
||||
imgSrc: true,
|
||||
|
||||
length: puny ? puny.decode(emoji.raw).length : emoji.raw.length,
|
||||
|
||||
tw_src: emoji.tw_src,
|
||||
noto_src: emoji.noto_src,
|
||||
one_src: emoji.one_src,
|
||||
|
|
|
@ -9,11 +9,30 @@ var FFZ = window.FrankerFaceZ,
|
|||
};
|
||||
|
||||
|
||||
// ---------------------
|
||||
// Badware Check
|
||||
// ---------------------
|
||||
|
||||
FFZ.prototype.check_badware = function() {
|
||||
if ( this.embed_in_dash || ! window.jQuery || ! window.jQuery.noty )
|
||||
return;
|
||||
|
||||
// Check for the stolen version of BTTV4FFZ.
|
||||
if ( FFZ.settings_info.bttv_global_emotes && FFZ.settings_info.bttv_global_emotes.category === "BetterTTV" ) {
|
||||
var shown = localStorage.ffz_warning_bttv4ffz_clone;
|
||||
if ( shown !== "true" ) {
|
||||
localStorage.ffz_warning_bttv4ffz_clone = "true";
|
||||
this.show_message("You appear to be using an unofficial version of BTTV4FFZ that was copied without the developer's permission. Please use the official version available at <a href=\"https://lordmau5.com/bttv4ffz/\">https://lordmau5.com/bttv4ffz/</a>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------
|
||||
// API Constructor
|
||||
// ---------------------
|
||||
|
||||
var API = FFZ.API = function(instance, name, icon, version) {
|
||||
var API = FFZ.API = function(instance, name, icon, version, name_key) {
|
||||
this.ffz = instance || FFZ.get();
|
||||
|
||||
// Check for a known API!
|
||||
|
@ -56,7 +75,7 @@ var API = FFZ.API = function(instance, name, icon, version) {
|
|||
this.on_room_callbacks = [];
|
||||
|
||||
this.name = name || ("Extension#" + this.id);
|
||||
this.name_key = this.name.replace(/[^A-Z0-9_\-]/g, '').toLowerCase();
|
||||
this.name_key = name_key || this.name.replace(/[^A-Z0-9_\-]/g, '').toLowerCase();
|
||||
|
||||
this.icon = icon || null;
|
||||
this.version = version || null;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
var FFZ = window.FrankerFaceZ,
|
||||
constants = require('../constants'),
|
||||
utils = require('../utils'),
|
||||
SENDER_REGEX = /(\sdata-sender="[^"]*"(?=>))/;
|
||||
SENDER_REGEX = /(\sdata-sender="[^"]*"(?=>))/,
|
||||
|
||||
HOP = Object.prototype.hasOwnProperty;
|
||||
|
||||
|
||||
// --------------------
|
||||
|
@ -101,10 +103,12 @@ FFZ.prototype.setup_bttv = function(delay) {
|
|||
this.toggle_style('badges-sub-notice-on');
|
||||
|
||||
// Disable other features too.
|
||||
document.body.classList.remove('ffz-transparent-badges');
|
||||
document.body.classList.remove("ffz-sidebar-swap");
|
||||
document.body.classList.remove("ffz-portrait");
|
||||
document.body.classList.remove("ffz-flip-dashboard");
|
||||
var cl = document.body.classList;
|
||||
cl.remove('ffz-transparent-badges');
|
||||
cl.remove("ffz-sidebar-swap");
|
||||
cl.remove("ffz-portrait");
|
||||
cl.remove("ffz-minimal-channel-title");
|
||||
cl.remove("ffz-flip-dashboard");
|
||||
|
||||
// Remove Following Count
|
||||
if ( this.settings.following_count ) {
|
||||
|
@ -293,7 +297,7 @@ FFZ.prototype.setup_bttv = function(delay) {
|
|||
if ( emote_set && emote_set.emoticons )
|
||||
for(var emote_id in emote_set.emoticons) {
|
||||
emote = emote_set.emoticons[emote_id];
|
||||
if ( ! emotes.hasOwnProperty(emote.name) )
|
||||
if ( ! HOP.call(emotes, emote.name) )
|
||||
emotes[emote.name] = emote;
|
||||
}
|
||||
}
|
||||
|
@ -311,7 +315,7 @@ FFZ.prototype.setup_bttv = function(delay) {
|
|||
|
||||
for(var x=0,y=segments.length; x < y; x++) {
|
||||
segment = segments[x];
|
||||
if ( emotes.hasOwnProperty(segment) ) {
|
||||
if ( HOP.call(emotes, segment) ) {
|
||||
emote = emotes[segment];
|
||||
if ( text.length ) {
|
||||
var toks = parse_emoji(text.join(' ') + ' ');
|
||||
|
|
11
src/main.js
11
src/main.js
|
@ -1,6 +1,3 @@
|
|||
// Modify Array and others.
|
||||
// require('./shims');
|
||||
|
||||
// ----------------
|
||||
// The Constructor
|
||||
// ----------------
|
||||
|
@ -37,7 +34,7 @@ FFZ.msg_commands = {};
|
|||
|
||||
// Version
|
||||
var VER = FFZ.version_info = {
|
||||
major: 3, minor: 5, revision: 252,
|
||||
major: 3, minor: 5, revision: 266,
|
||||
toString: function() {
|
||||
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
|
||||
}
|
||||
|
@ -308,6 +305,8 @@ FFZ.prototype.init_normal = function(delay, no_socket) {
|
|||
this.setup_css();
|
||||
this.setup_popups();
|
||||
|
||||
this.setup_following_link();
|
||||
|
||||
if ( ! no_socket ) {
|
||||
this.setup_time();
|
||||
this.ws_create();
|
||||
|
@ -355,6 +354,8 @@ FFZ.prototype.init_dashboard = function(delay) {
|
|||
this.setup_css();
|
||||
this.setup_popups();
|
||||
|
||||
this.setup_following_link();
|
||||
|
||||
this.setup_time();
|
||||
this.ws_create();
|
||||
|
||||
|
@ -460,6 +461,8 @@ FFZ.prototype.init_ember = function(delay) {
|
|||
this.find_bttv(10);
|
||||
this.find_emote_menu(10);
|
||||
|
||||
setTimeout(this.check_badware.bind(this), 10000);
|
||||
|
||||
//this.check_news();
|
||||
this.check_ff();
|
||||
this.refresh_chat();
|
||||
|
|
|
@ -7,13 +7,15 @@ var FFZ = window.FrankerFaceZ,
|
|||
bits_helpers,
|
||||
bits_service,
|
||||
|
||||
HOP = Object.prototype.hasOwnProperty,
|
||||
|
||||
EXPLANATION_WARN = '<hr>This link has been sent to you via a whisper rather than standard chat, and has not been checked or approved of by any moderators or staff members. Please treat this link with caution and do not visit it if you do not trust the sender.',
|
||||
|
||||
reg_escape = function(str) {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
},
|
||||
|
||||
LINK = /(?:https?:\/\/)?(?:[-a-zA-Z0-9@:%_\+~#=]+\.)+[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)/g,
|
||||
LINK = /(?:https?:\/\/)?(?:[-a-zA-Z0-9@:%_\+~#=]+\.)+[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=()]*)/g,
|
||||
|
||||
CLIP_URL = /(?:https?:\/\/)?clips\.twitch\.tv\/(\w+)\/(\w+)/,
|
||||
|
||||
|
@ -101,18 +103,48 @@ FFZ._emote_mirror_swap = function(img) {
|
|||
// Settings
|
||||
// ---------------------
|
||||
|
||||
var ts = new Date(0).toLocaleTimeString().toUpperCase();
|
||||
var ts = new Date(0).toLocaleTimeString().toUpperCase(),
|
||||
default_24 = ts.lastIndexOf('PM') === -1 && ts.lastIndexOf('AM') === -1;
|
||||
|
||||
FFZ.settings_info.twenty_four_timestamps = {
|
||||
type: "boolean",
|
||||
value: ts.lastIndexOf('PM') === -1 && ts.lastIndexOf('AM') === -1,
|
||||
type: "select",
|
||||
options: {
|
||||
0: "12-Hour" + (default_24 ? '' : ' (Default)'),
|
||||
1: "12-Hour Zero-Padded",
|
||||
2: "24-Hour" + (default_24 ? ' (Default)' : ''),
|
||||
3: "24-Hour Zero-Padded"
|
||||
},
|
||||
|
||||
value: default_24 ? 2 : 0,
|
||||
|
||||
process_value: function(val) {
|
||||
if ( val === false )
|
||||
return 0;
|
||||
else if ( val === true )
|
||||
return 2;
|
||||
else if ( typeof val === 'string' )
|
||||
return parseInt(val) || 0;
|
||||
return val;
|
||||
},
|
||||
|
||||
category: "Chat Appearance",
|
||||
no_bttv: true,
|
||||
|
||||
name: "24hr Timestamps",
|
||||
help: "Display timestamps in chat in the 24 hour format rather than 12 hour."
|
||||
};
|
||||
name: "Timestamp Format",
|
||||
help: "Display timestamps in chat in the 24 hour format rather than 12 hour.",
|
||||
|
||||
on_update: function(val) {
|
||||
// Update existing chat lines.
|
||||
var CL = utils.ember_resolve('component:chat/chat-line'),
|
||||
views = (CL && helpers && helpers.getTime) ? utils.ember_views() : {};
|
||||
|
||||
for(var vid in views) {
|
||||
var view = views[vid];
|
||||
if ( view instanceof CL )
|
||||
view.$('.timestamp').text(view.get('timestamp'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
FFZ.settings_info.timestamp_seconds = {
|
||||
|
@ -198,18 +230,22 @@ FFZ.prototype.setup_tokenization = function() {
|
|||
// Timestamp Display
|
||||
helpers.getTime = function(e) {
|
||||
if ( e === undefined || e === null )
|
||||
return '?:??';
|
||||
return '?:??' + (f.settings.timestamp_seconds ? ':??' : '');
|
||||
|
||||
var hours = e.getHours(),
|
||||
minutes = e.getMinutes(),
|
||||
seconds = e.getSeconds();
|
||||
seconds = e.getSeconds(),
|
||||
|
||||
if ( hours > 12 && ! f.settings.twenty_four_timestamps )
|
||||
hours -= 12;
|
||||
else if ( hours === 0 && ! f.settings.twenty_four_timestamps )
|
||||
hours = 12;
|
||||
s = f.settings.twenty_four_timestamps;
|
||||
|
||||
return hours + ':' + (minutes < 10 ? '0' : '') + minutes + (f.settings.timestamp_seconds ? ':' + (seconds < 10 ? '0' : '') + seconds : '');
|
||||
if ( s < 2 ) {
|
||||
if ( hours > 12 )
|
||||
hours -= 12;
|
||||
else if ( hours === 0 )
|
||||
hours = 12;
|
||||
}
|
||||
|
||||
return ((s === 1 || s === 3) && hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes + (f.settings.timestamp_seconds ? ':' + (seconds < 10 ? '0' : '') + seconds : '');
|
||||
};
|
||||
|
||||
|
||||
|
@ -741,6 +777,10 @@ FFZ.prototype.tokenize_feed_body = function(message, emotes, user_id, room_id) {
|
|||
if ( helpers && helpers.linkifyMessage )
|
||||
message = helpers.linkifyMessage(message);
|
||||
|
||||
// We want to tokenize emoji first to make sure that they don't cause issues
|
||||
// with the indices used by emoticonizeMessage.
|
||||
message = this.tokenize_emoji(message);
|
||||
|
||||
if ( helpers && helpers.emoticonizeMessage && this.settings.parse_emoticons )
|
||||
message = helpers.emoticonizeMessage(message, emotes);
|
||||
|
||||
|
@ -771,9 +811,6 @@ FFZ.prototype.tokenize_feed_body = function(message, emotes, user_id, room_id) {
|
|||
if ( this.settings.parse_emoticons && this.settings.parse_emoticons !== 2 )
|
||||
tokens = this.tokenize_emotes(user_id, room_id, tokens)
|
||||
|
||||
if ( this.settings.parse_emoji )
|
||||
tokens = this.tokenize_emoji(tokens);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
|
@ -996,7 +1033,7 @@ FFZ.prototype.tokenize_emotes = function(user, room, tokens, do_report) {
|
|||
if ( emote_set && emote_set.emoticons )
|
||||
for(var emote_id in emote_set.emoticons) {
|
||||
emote = emote_set.emoticons[emote_id];
|
||||
if ( ! emotes.hasOwnProperty(emote.name) )
|
||||
if ( ! HOP.call(emotes, emote.name) )
|
||||
emotes[emote.name] = emote;
|
||||
}
|
||||
}
|
||||
|
@ -1023,7 +1060,7 @@ FFZ.prototype.tokenize_emotes = function(user, room, tokens, do_report) {
|
|||
|
||||
for(var x=0,y=segments.length; x < y; x++) {
|
||||
segment = segments[x];
|
||||
if ( emotes.hasOwnProperty(segment) ) {
|
||||
if ( HOP.call(emotes, segment) ) {
|
||||
emote = emotes[segment];
|
||||
|
||||
if ( text.length ) {
|
||||
|
@ -1095,7 +1132,7 @@ FFZ.prototype.tokenize_emoji = function(tokens) {
|
|||
|
||||
if ( data ) {
|
||||
if ( text && text.length )
|
||||
new_tokens.push({type: "text", text: text});
|
||||
new_tokens.push(text);
|
||||
new_tokens.push(data.token);
|
||||
text = null;
|
||||
} else
|
||||
|
@ -1104,7 +1141,7 @@ FFZ.prototype.tokenize_emoji = function(tokens) {
|
|||
}
|
||||
|
||||
if ( text && text.length )
|
||||
new_tokens.push({type: "text", text: text});
|
||||
new_tokens.push(text);
|
||||
}
|
||||
|
||||
return new_tokens;
|
||||
|
|
|
@ -3,21 +3,10 @@ var FFZ = window.FrankerFaceZ,
|
|||
constants = require('../constants'),
|
||||
|
||||
FOLLOWING_CONTAINERS = [
|
||||
['#small_nav ul.game_filters li[data-name="following"] a', true],
|
||||
['nav a.warp__tipsy[data-href="following"]', true],
|
||||
['#large_nav #nav_personal li[data-name="following"] a', false],
|
||||
['#header_actions #header_following', false]
|
||||
'.warp__item a[data-href="following"]',
|
||||
'#header_actions #header_following'
|
||||
],
|
||||
|
||||
FOLLOW_GRAVITY = function(f, el) {
|
||||
return (f.settings.following_count && (
|
||||
el.getAttribute('data-href') === 'following' ||
|
||||
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' ||
|
||||
|
@ -158,13 +147,14 @@ FFZ.prototype._update_following_count = function() {
|
|||
var Stream = utils.ember_resolve('model:deprecated-stream'),
|
||||
Live = Stream && Stream.find("live"),
|
||||
|
||||
Host = utils.ember_resolve('model:host'),
|
||||
HostLive = Host && Host.find("following"),
|
||||
/*Host = utils.ember_resolve('model:host'),
|
||||
HostLive = Host && Host.find("following"),*/
|
||||
|
||||
current_path = document.body.getAttribute('data-current-path') || '',
|
||||
f = this;
|
||||
|
||||
if ( ! this.is_dashboard && HostLive && document.body.getAttribute('data-current-path').indexOf('directory.following') !== -1 )
|
||||
HostLive.load();
|
||||
/*if ( ! this.is_dashboard && HostLive && current_path.indexOf('directory.following') !== -1 )
|
||||
HostLive.load();*/
|
||||
|
||||
if ( ! this.is_dashboard && Live )
|
||||
Live.load();
|
||||
|
@ -200,17 +190,24 @@ FFZ.prototype._build_following_tooltip = function(el) {
|
|||
|
||||
streams = this._tooltip_streams,
|
||||
total = this._tooltip_total || (streams && streams.length) || 0,
|
||||
c = 0;
|
||||
c = 0,
|
||||
filtered = 0;
|
||||
|
||||
if ( streams && streams.length ) {
|
||||
for(var i=0, l = streams.length; i < l; i++) {
|
||||
var stream = streams[i];
|
||||
if ( ! stream || ! stream.channel || (stream.game && this.settings.banned_games.indexOf(stream.game.toLowerCase()) !== -1) )
|
||||
if ( ! stream || ! stream.channel )
|
||||
continue;
|
||||
|
||||
if ( stream.game && this.settings.banned_games.indexOf(stream.game.toLowerCase()) !== -1 ) {
|
||||
filtered++;
|
||||
continue;
|
||||
}
|
||||
|
||||
c += 1;
|
||||
if ( c > max_lines ) {
|
||||
tooltip += '<hr><span>And ' + utils.number_commas(total - max_lines) + ' more...</span>';
|
||||
tooltip += '<hr><span>And ' + utils.number_commas(total - max_lines) + ' more' + (filtered ? ' (' + filtered + ' hidden)' : '') + '...</span>';
|
||||
filtered = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -225,6 +222,10 @@ FFZ.prototype._build_following_tooltip = function(el) {
|
|||
'<b>' + utils.sanitize(stream.channel.display_name || stream.channel.name) + '</b><br>' +
|
||||
'<span class="playing">' + (stream.channel.game === 'Creative' ? 'Being Creative' : (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing')) + (tags ? ' | ' + _.pluck(tags, "text").join(" ") : '') + '</span>';
|
||||
}
|
||||
|
||||
if ( filtered )
|
||||
tooltip += '<hr><span>(' + filtered + ' hidden)';
|
||||
|
||||
} else {
|
||||
c++; // is a terrible programming language
|
||||
tooltip += "<hr>No one you're following is online.";
|
||||
|
@ -284,23 +285,21 @@ FFZ.prototype._build_following_tooltip = function(el) {
|
|||
|
||||
FFZ.prototype._install_following_tooltips = function() {
|
||||
var f = this,
|
||||
gravity = function() { return FOLLOW_GRAVITY(f, this) },
|
||||
data = {
|
||||
html: true,
|
||||
className: function() { return WIDE_TIP(f, this); },
|
||||
title: function() { return f._build_following_tooltip(this); }
|
||||
title: function() { return f._build_following_tooltip(this); },
|
||||
gravity: utils.tooltip_placement(constants.TOOLTIP_DISTANCE * 2, 'w')
|
||||
};
|
||||
|
||||
for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) {
|
||||
var following = jQuery(FOLLOWING_CONTAINERS[i][0]);
|
||||
var following = jQuery(FOLLOWING_CONTAINERS[i]);
|
||||
if ( following && following.length ) {
|
||||
var td = following.data('tipsy');
|
||||
if ( td && td.options ) {
|
||||
td.options = _.extend(td.options, data);
|
||||
if ( FOLLOWING_CONTAINERS[i][1] )
|
||||
td.options.gravity = gravity;
|
||||
} else
|
||||
following.tipsy(FOLLOWING_CONTAINERS[i][1] ? _.extend({gravity: gravity}, data) : data);
|
||||
following.tipsy(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +314,7 @@ FFZ.prototype._draw_following_channels = function(streams, total) {
|
|||
FFZ.prototype._draw_following_count = function(count) {
|
||||
count = count ? utils.format_unread(count) : '';
|
||||
for(var i=0; i < FOLLOWING_CONTAINERS.length; i++) {
|
||||
var container = document.querySelector(FOLLOWING_CONTAINERS[i][0]),
|
||||
var container = document.querySelector(FOLLOWING_CONTAINERS[i]),
|
||||
badge = container && container.querySelector('.ffz-follow-count');
|
||||
if ( ! container )
|
||||
continue;
|
||||
|
|
|
@ -211,9 +211,18 @@ FFZ.prototype.rebuild_following_ui = function() {
|
|||
cont = document.createElement('span');
|
||||
cont.id = 'ffz-ui-following';
|
||||
|
||||
var before;
|
||||
try { before = container.querySelector(':scope > span'); }
|
||||
catch(err) { before = undefined; }
|
||||
var before = null;
|
||||
try {
|
||||
var before_btn = container.querySelector('.subscribe-button');
|
||||
if ( before_btn )
|
||||
before = before_btn.parentElement.nextSibling;
|
||||
else {
|
||||
before_btn = container.querySelector('.notification-controls');
|
||||
if ( before_btn )
|
||||
before = before_btn.nextSibling;
|
||||
}
|
||||
|
||||
} catch(err) { }
|
||||
|
||||
if ( before )
|
||||
container.insertBefore(cont, before);
|
||||
|
@ -250,9 +259,17 @@ FFZ.prototype.rebuild_following_ui = function() {
|
|||
cont = document.createElement('span');
|
||||
cont.id = 'ffz-ui-following';
|
||||
|
||||
var before;
|
||||
try { before = container.querySelector(':scope > span'); }
|
||||
catch(err) { before = undefined; }
|
||||
var before = null;
|
||||
try {
|
||||
var before_btn = container.querySelector('.subscribe-button');
|
||||
if ( before_btn )
|
||||
before = before_btn.parentElement.nextSibling;
|
||||
else {
|
||||
before_btn = container.querySelector('.notification-controls');
|
||||
if ( before_btn )
|
||||
before = before_btn.nextSibling;
|
||||
}
|
||||
} catch(err) { }
|
||||
|
||||
if ( before )
|
||||
container.insertBefore(cont, before);
|
||||
|
@ -278,21 +295,23 @@ FFZ.prototype.rebuild_following_ui = function() {
|
|||
// UI Construction
|
||||
// ---------------
|
||||
|
||||
FFZ.prototype._build_following_button = function(container, channel_id) {
|
||||
FFZ.prototype._build_following_button = function(cont, channel_id) {
|
||||
if ( ! VALID_CHANNEL.test(channel_id) )
|
||||
return this.log("Ignoring Invalid Channel: " + utils.sanitize(channel_id));
|
||||
|
||||
var btn = document.createElement('a'), f = this,
|
||||
btn_c = document.createElement('div'),
|
||||
noti = document.createElement('a'),
|
||||
noti_c = document.createElement('div'),
|
||||
var f = this,
|
||||
btn = utils.createElement('button', 'follow-button button'),
|
||||
|
||||
noti = utils.createElement('a', 'toggle-notification-menu js-toggle-notification-menu'),
|
||||
noti_c = utils.createElement('div', 'notification-controls v2 hidden', noti),
|
||||
|
||||
display_name,
|
||||
following = false,
|
||||
notifications = false,
|
||||
|
||||
update = function() {
|
||||
btn_c.classList.toggle('is-following', following);
|
||||
btn.classList.toggle('is-following', following);
|
||||
btn.classList.toggle('button--status', following);
|
||||
btn.title = (following ? "Unf" : "F") + "ollow " + utils.sanitize(display_name);
|
||||
btn.innerHTML = (following ? "" : "Follow ") + utils.sanitize(display_name);
|
||||
noti_c.classList.toggle('hidden', !following);
|
||||
|
@ -303,7 +322,7 @@ FFZ.prototype._build_following_button = function(container, channel_id) {
|
|||
if ( ! user || ! user.login ) {
|
||||
following = false;
|
||||
notification = false;
|
||||
btn_c.classList.add('is-initialized');
|
||||
btn.classList.add('is-initialized');
|
||||
return update();
|
||||
}
|
||||
|
||||
|
@ -311,12 +330,12 @@ FFZ.prototype._build_following_button = function(container, channel_id) {
|
|||
.done(function(data) {
|
||||
following = true;
|
||||
notifications = data.notifications;
|
||||
btn_c.classList.add('is-initialized');
|
||||
btn.classList.add('is-initialized');
|
||||
update();
|
||||
}).fail(function(data) {
|
||||
following = false;
|
||||
notifications = false;
|
||||
btn_c.classList.add('is-initialized');
|
||||
btn.classList.add('is-initialized');
|
||||
update();
|
||||
});
|
||||
},
|
||||
|
@ -339,16 +358,9 @@ FFZ.prototype._build_following_button = function(container, channel_id) {
|
|||
update();
|
||||
};
|
||||
|
||||
btn_c.className = 'ember-follow follow-button';
|
||||
btn_c.appendChild(btn);
|
||||
|
||||
// The drop-down button!
|
||||
noti.className = 'toggle-notification-menu js-toggle-notification-menu';
|
||||
noti.href = '#';
|
||||
|
||||
noti_c.className = 'notification-controls v2 hidden';
|
||||
noti_c.appendChild(noti);
|
||||
|
||||
// Event Listeners!
|
||||
btn.addEventListener('click', function(e) {
|
||||
var user = f.get_user();
|
||||
|
@ -399,8 +411,8 @@ FFZ.prototype._build_following_button = function(container, channel_id) {
|
|||
|
||||
setTimeout(check_following, Math.random()*5000);
|
||||
|
||||
container.appendChild(btn_c);
|
||||
container.appendChild(noti_c);
|
||||
cont.appendChild(btn);
|
||||
cont.appendChild(noti_c);
|
||||
}
|
||||
|
||||
|
||||
|
@ -411,11 +423,12 @@ FFZ.prototype._build_following_popup = function(container, channel_id, notificat
|
|||
if ( popup && popup.id == "ffz-following-popup" && popup.getAttribute('data-channel') === channel_id )
|
||||
return null;
|
||||
|
||||
popup = this._popup = document.createElement('div');
|
||||
popup = this._popup = utils.createElement('div', 'dropmenu notify-menu js-notify');
|
||||
popup.id = 'ffz-following-popup';
|
||||
popup.setAttribute('data-channel', channel_id);
|
||||
|
||||
popup.className = (pos >= 300 ? 'right' : 'left') + ' dropmenu notify-menu js-notify';
|
||||
this._popup_allow_parent = true;
|
||||
this._popup_parent = container;
|
||||
|
||||
out = '<div class="header">You are following ' + FFZ.get_capitalization(channel_id) + '</div>';
|
||||
out += '<p class="clearfix">';
|
||||
|
@ -424,6 +437,6 @@ FFZ.prototype._build_following_popup = function(container, channel_id, notificat
|
|||
out += '</p>';
|
||||
|
||||
popup.innerHTML = out;
|
||||
container.appendChild(popup);
|
||||
container.insertBefore(popup, container.firstChild);
|
||||
return popup.querySelector('a.switch');
|
||||
}
|
|
@ -46,7 +46,8 @@ FFZ.prototype.fix_tooltips = function() {
|
|||
|
||||
for(var obj_id in jQuery.cache) {
|
||||
var obj = jQuery.cache[obj_id];
|
||||
if ( obj && obj.data && obj.data.tipsy && obj.data.tipsy.options && typeof obj.data.tipsy.options.gravity !== "function" )
|
||||
if ( obj && obj.data && obj.data.tipsy && obj.data.tipsy.options && typeof obj.data.tipsy.options.gravity !== "function" ) {
|
||||
obj.data.tipsy.options.gravity = utils.tooltip_placement(constants.TOOLTIP_DISTANCE, obj.data.tipsy.options.gravity || 's');
|
||||
}
|
||||
}
|
||||
}
|
17
src/utils.js
17
src/utils.js
|
@ -466,8 +466,19 @@ module.exports = FFZ.utils = {
|
|||
if ( typeof pref === "function" )
|
||||
pref = pref.call(this);
|
||||
|
||||
var dir = {ns: pref[0], ew: (pref.length > 1 ? pref[1] : false)},
|
||||
$this = $(this),
|
||||
var dir = {};
|
||||
|
||||
if ( pref.indexOf('n') !== -1 )
|
||||
dir.ns = 'n';
|
||||
else if ( pref.indexOf('s') !== -1 )
|
||||
dir.ns = 's';
|
||||
|
||||
if ( pref.indexOf('e') !== -1 )
|
||||
dir.ew = 'e';
|
||||
else if ( pref.indexOf('w') !== -1 )
|
||||
dir.ew = 'w';
|
||||
|
||||
var $this = $(this),
|
||||
half_width = $this.width() / 2,
|
||||
half_height = $this.height() / 2,
|
||||
boundTop = $(document).scrollTop() + half_height + (margin*2),
|
||||
|
@ -478,7 +489,7 @@ module.exports = FFZ.utils = {
|
|||
if ($(window).width() + $(document).scrollLeft() - ($this.offset().left + half_width) < margin) dir.ew = 'e';
|
||||
if ($(window).height() + $(document).scrollTop() - ($this.offset().top + half_height) < (2*margin)) dir.ns = 's';
|
||||
|
||||
return dir.ns + (dir.ew ? dir.ew : '');
|
||||
return (dir.ns ? dir.ns : '') + (dir.ew ? dir.ew : '');
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue