1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00

The "Oh God Why Didn't I Commit Sooner" Edition

v3.5.494.

Added: Chat Filtering > Remove Messages from Moderators
Added: Recent Highlights
Added: Support for room-specific badges from the API.

Fixed: Custom bits badges. Lots of styling. Chat bugs. Dark theme issues. My Emoticons menu not rendering. Reset Player not rendering. Twitch5 extension compatibility. Logviewer messages and Name History. Bits UI breaking when you switch rooms. Player state when you reset the player.

Closes #173
Closes #169
Closes #164
This commit is contained in:
SirStendec 2017-06-11 13:30:37 -04:00
parent e843a3bb19
commit 630d2830ec
30 changed files with 1049 additions and 187 deletions

View file

@ -1,80 +1,62 @@
<div class="list-header">3.5.481 <time datetime="2017-05-09">(2017-05-09)</time></div>
<div class="list-header">3.5.494 <time datetime="2017-06-11">(2017-06-11)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Display the number of Notes a user has on moderation cards, once the data is loaded.</li>
<li>Fixed: Don't display background colors on custom bits badges.</li>
<li>Fixed: Advanced settings search box styling.</li>
<li>Fixed: ITAD button showing in places it shouldn't.</li>
<li>Fixed: Only show the Friend Watching desktop notification for the channel you're watching if you have multiple chats pinned.</li>
<li>Added: By default, messages from moderators will no longer be removed if they contain banned words. Configurable via <code>Chat Filtering > Remove Messages from Moderators</code>.</li>
<li>Fixed: Bits UI breaking when you switch chat rooms.</li>
<li>Fixed: Incorrect fullscreen and theater mode states when resetting the player.</li>
</ul>
<div class="list-header">3.5.480 <time datetime="2017-05-03">(2017-05-03)</time></div>
<div class="list-header">3.5.493 <time datetime="2017-06-06">(2017-06-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Setting for displaying AutoMod actions in the same way as vanilla Twitch.</li>
<li>Changed: More dark mode tweaks for partner-specific pages.</li>
<li>Changed: Tag Vodcasts in the navigation bar's Following tooltip and the enhanced tooltips for live channels on the social bar.</li>
<li>Fixed: New logviewer messages coming in would erase the name history tab of mod cards and display chat instead.</li>
<li>Fixed: Dark theme tweaks.</li>
</ul>
<div class="list-header">3.5.479 <time datetime="2017-05-02">(2017-05-02)</time></div>
<div class="list-header">3.5.492 <time datetime="2017-06-06">(2017-06-06)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: You can now define in-line moderation icons that are usable even when you don't have moderation power over the user.</li>
<li>Fixed: Darken several pages related to subscriptions and bits settings for partners and affiliates.</li>
<li>Fixed: Player size.</li>
</ul>
<div class="list-header">3.5.478 <time datetime="2017-04-28">(2017-04-28)</time></div>
<div class="list-header">3.5.491 <time datetime="2017-06-04">(2017-06-04)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Twitch also broke linkification of channel titles when they removed the selector for the title element.</li>
<li>Fixed: Scrollbars hidden on pages where they shouldn't be.</li>
</ul>
<div class="list-header">3.5.477 <time datetime="2017-04-28">(2017-04-28)</time></div>
<div class="list-header">3.5.490 <time datetime="2017-06-03">(2017-06-03)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Channel Title on Top setting breaking after Twitch removed specific selectors for that part of the page.</li>
<li>Fixed: Don't re-enable gray mode if a user has it specifically disabled and they enable dark mode via the Twitch chat settings menu.</li>
<li>Changed: The Stream Latency display will now warn you when your system clock seems to be set inaccurately.</li>
<li>Fixed: Tooltips can cause scrollbars to appear.</li>
<li>Fixed: Minor CSS tweaks for Recent Highlights.</li>
<li>Fixed: Recent Highlights only showing the first five messages when switching chat rooms.</li>
</ul>
<div class="list-header">3.5.476 <time datetime="2017-04-28">(2017-04-28)</time></div>
<div class="list-header">3.5.489 <time datetime="2017-06-02">(2017-06-02)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Incorrect layout width calculations when the browser's default font size is not as expected.</li>
<li>Fixed: Styles weren't applying properly to the Followed Since display on users' following and followers pages.</li>
<li>Fixed: Recent Highlights colors in light theme and when toggling dark theme.</li>
</ul>
<div class="list-header">3.5.475 <time datetime="2017-04-24">(2017-04-24)</time></div>
<div class="list-header">3.5.488 <time datetime="2017-06-02">(2017-06-02)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: AutoMod stopped working due to internal changes to the Twitch app.</li>
<li>Removed: Excessive debug logging for settings.</li>
<li>The Stop Asking Already Update</li>
<li>&nbsp;</li>
<li>Added: Recent Highlights. (Chat Appearance > Recent Highlights)</li>
<li>Fixed: Dark theme for video comments.</li>
<li>Fixed: Dark theme for channel stats.</li>
</ul>
<div class="list-header">3.5.474 <time datetime="2017-04-23">(2017-04-23)</time></div>
<div class="list-header">3.5.487 <time datetime="2017-05-28">(2017-05-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Stop using <code>localStorage.hasOwnProperty</code> due to a Chrome bug.</li>
<li>Fixed: Revert input handler tweaks for BetterTTV as a race condition can cause Enter to stop working for some users.</li>
</ul>
<div class="list-header">3.5.473 <time datetime="2017-04-23">(2017-04-23)</time></div>
<div class="list-header">3.5.486 <time datetime="2017-05-28">(2017-05-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Excessive debug logging for a settings loading issue.</li>
<li>Fixed: Darken the Twitch Associate agreement.</li>
<li>Fixed: Revert input handler tweaks for BetterTTV as a race condition can cause Enter to stop working for some users.</li>
</ul>
<div class="list-header">3.5.472 <time datetime="2017-04-22">(2017-04-22)</time></div>
<div class="list-header">3.5.485 <time datetime="2017-05-28">(2017-05-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Support for the new Verified badge.</li>
<li>Changed: Add support for badges that have different images when rendered transparently.</li>
<li>Fixed: Add temporary fix for mod card and FFZ menu positioning until Twitch fixes their CSS.</li>
<li>Fixed: Unable to favorite some emoticons added through the API.</li>
<li>Fixed: Fetch Twitch Inventory correctly rather than guessing about which sets are inventory sets.</li>
<li>Fixed: Properly label Twitch Inventory sets in the tab completion UI.</li>
<li>Fixed: Update the favorited status of emotes in the tab completion UI when it is changed.</li>
<li>Fixed: Do not show <code>Channel: undefined</code> for emoticons from unknown sets. They might not be from a channel, and it looks bad.</li>
<li>Fixed: Link colors in the top navigation bar when using a bright color with the dark theme enabled.</li>
</ul>
<div class="list-header">3.5.471 <time datetime="2017-04-21">(2017-04-21)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Friend Watching Notifications setting to show notifications when you get a message that a friend is also watching the same channel.</li>
<li>Added: Highlight Users setting to highlight all messages from specific users to tide people over until FFZv4.</li>
<li>Fixed: Changes to Twitch directory breaking channel logo and uptime display.</li>
<li>Fixed: Apply hidden thumbnails setting to more video preview components.</li>
<li>Fixed: Caching of emoji codepoint calculation.</li>
<li>Fixed: Bug with unclickable usernames in moderation card chat history.</li>
<li>Fixed: Don't re-enable gray mode if a user has it specifically disabled and they enable dark mode via the Twitch chat settings menu.</li>
<li>Changed: Possible fix for Twitch5 infinite loading issues with FFZ on Firefox.</li>
</ul>
<div class="list-header" id="ffz-old-news-button"><a href="#">View Older</a></div>

132
dark.css
View file

@ -534,6 +534,7 @@ body.ffz-dark:not([data-page="teams#show"]),
.ffz-dark .twitch_subwindow_container .card .buttons,
.ffz-dark .kraken-embed .card .buttons,
.ffz-dark .kraken-page .card .buttons,
.ffz-dark .card--bordered,
.ffz-dark .card-vod-edit {
border-color: #474747;
}
@ -619,6 +620,7 @@ body.ffz-dark:not([data-page="teams#show"]),
border-left-color: #6441a5;
}
.ffz-dark .form__label,
.ffz-dark .form__input[type=checkbox] + label,
.ffz-dark .form__input[type=radio] + label,
.ffz-dark label,
@ -946,6 +948,8 @@ body.ffz-dark:not([data-page="teams#show"]),
color: #ccc;
}
.ffz-dark .section ul,
.ffz-dark .section ul li,
.ffz-dark .subdash-feature-section,
.ffz-dark .subdash-feature-header__back,
.ffz-dark .subdash-feature-header,
@ -971,6 +975,14 @@ body.ffz-dark:not([data-page="teams#show"]),
background-color: rgb(16,16,16);
}
.ffz-dark fieldset {
border-color: transparent;
}
.ffz-dark .connect_items .connect-item-details,
.ffz-dark .connect_items .connect-item-details-legal,
.ffz-dark .connect_items,
.ffz-dark .premium_setup_contain #turbo_setup,
.ffz-dark table.simple_table td,
.ffz-dark table.simple_table th,
.ffz-dark .cl-container .section-header,
@ -1619,6 +1631,12 @@ body.ffz-dark:not([data-page="teams#show"]),
border: 1px solid;
}
.ffz-dark .activity-card__reason {
background-color: #141414;
color: #ccc;
box-shadow: none;
}
.ffz-dark .list-load-more,
.ffz-dark .activity-card {
border-color: #474747;
@ -1646,20 +1664,100 @@ body.ffz-dark:not([data-page="teams#show"]),
box-shadow: none; /*inset 0 0 0 1px #474747;*/
}
.ffz-dark .c-background { background: #101010 !important }
.ffz-dark .activity-create--focus {
background-color: #191919;
/*box-shadow: none; inset 0 0 0 1px #474747;*/
border-color: rgba(255,255,255,0.4) !important;
}
.ffz-dark .c-text-alt { color: #999 !important }
.ffz-dark .activity-add-comment__textarea:before {
background: #1d1d1d;
border-left-color: #474747;
border-bottom-color: #474747;
}
.ffz-dark .mod-dashboard__video-title,
.ffz-dark .activity-card { color: #ccc }
.inherit-color { color: inherit !important }
.ffz-dark .tw-button--icon-only figure svg {
fill: #a68cd4;
}
.ffz-dark .mod-comment {
background-color: #191919;
box-shadow: inset 0 0 0 1px #474747;
}
.ffz-dark .mod-comment__timestamp {
color: #a68cd4;
background-color: #222;
}
.ffz-dark .mod-comment__video a:active,
.ffz-dark .mod-comment__video a:focus,
.ffz-dark .mod-comment__video a:hover { background-color: #333 !important }
.ffz-dark .mod-comment:active,
.ffz-dark .mod-comment:focus,
.ffz-dark .mod-comment:hover {
box-shadow: 0 2px 2px 0 rgba(255,255,255,.05), inset 0 0 0 1px #474747;
}
.ffz-dark .c-background-alt-2 {
background-color: #222 !important
}
.ffz-dark .automod-words__item {
border-color: #474747;
background-color: #111;
}
.ffz-dark .automod-words__item--selected {
background-color: #333;
}
.ffz-dark .automod-words__text { color: #ccc }
.ffz-dark .automod-words__fade-mask {
background: none;
}
/* VOD Messages */
.ffz-dark .vod-chat {
color: #ccc;
background-color: #191919;
}
.ffz-dark .vod-chat__header {
box-shadow: inset 0 -1px 0 0 #474747;
}
.ffz-dark .vod-message.vod-message--focused .vod-message__reply,
.ffz-dark .vod-message:hover .vod-message__reply,
.ffz-dark .vod-message__reply {
box-shadow: inset 3px 0 0 0 #474747;
}
.ffz-dark .vod-message__reply-button {
color: #a68cd4;
}
.ffz-dark .vod-chat__input {
background-color: #191919;
box-shadow: inset 0 1px 0 0 #474747;
}
.ffz-dark .vod-message.vod-message--focused,
.ffz-dark .vod-message:hover {
background-color: #333;
}
/* Search Panel */
@ -1791,6 +1889,15 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: rgba(255,255,255,0.2);
}
.ffz-dark .subscription-modal__sub-tabs input:checked+.subscription-modal__sub-tabs-label {
color: #ccc;
box-shadow: 0 -2px 0 #a68ed2 inset, 0 4px 6px -4px #a68cd4;
}
.ffz-dark .subscription-modal__sub-tabs-label {
color: #a68cd4;
}
.ffz-dark .balloon .filter-bar__balloon-link--active {
color: #fff !important;
background-color: #6441a5 !important;
@ -1814,6 +1921,10 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: rgba(255,255,255,0.2);
}
.ffz-dark .dash-widget-watchparty-card:hover {
background-color: rgba(255,255,255,0.1);
}
/* Notification Center */
@ -1918,6 +2029,7 @@ body.ffz-dark:not([data-page="teams#show"]),
background-color: #161616;
}
.ffz-dark .dash-widget-watchparty-card__gripper,
.ffz-dark .playlist-editor-card__gripper {
background-color: #242424;
box-shadow: -8px 0 5px -5px #202020;
@ -1946,6 +2058,8 @@ body.ffz-dark:not([data-page="teams#show"]),
border-color: #474747;
}
.ffz-dark .fp-carousel__title,
.ffz-dark .fp-carousel__desc p,
.ffz-dark .fp-carousel__name,
.ffz-dark .fp-side__header { color: #c3c3c3 }
@ -1972,7 +2086,25 @@ body.ffz-dark:not([data-page="teams#show"]),
fill: #ccc;
}
.ffz-dark .activity--not-included { background-color: #202020; }
.ffz-dark .activity--level-0 { background-color: rgba(100,65,164,.1) }
.ffz-dark .activity--level-1 { background-color: rgba(100,65,164,.25) }
.ffz-dark .activity--level-2 { background-color: rgba(100,65,164,.4) }
.ffz-dark .activity--level-3 { background-color: rgba(100,65,164,.55) }
.ffz-dark .activity--level-4 { background-color: rgba(100,65,164,.7) }
.ffz-dark .activity--level-5 { background-color: rgba(100,65,164,.85) }
.ffz-dark .activity--level-6 { background-color: rgba(100,65,164,1) }
.ffz-dark .inventory-item__image {
background-color: #191919;
border-color: #474747;
}
.ffz-dark .border-r {
border-color: #474747;
}
.ffz-dark .bg--grey {
background-color: #242424;
}

View file

@ -1,3 +1,108 @@
<div class="list-header">3.5.484 <time datetime="2017-05-28">(2017-05-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Display the <code>Reset Player</code> button directly at the bottom of the player since positioning it in the menu would require a mutation observer now that the player UI is powered by React.</li>
<li>Fixed: <code>User (undefined)</code> in tab completion.</li>
<li>Fixed: Bug causing the My Emoticons menu not to render.</li>
<li>Fixed: Minor dark theme tweaks.</li>
</ul>
<div class="list-header">3.5.483 <time datetime="2017-05-24">(2017-05-24)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: Group different tiers of subscriber emotes into a single section of the My Emoticons menu.</li>
<li>Changed: Default to not using in-line mod icons for AutoMod because it confuses people and makes them think FFZ is broken.</li>
<li>Fixed: Darken Clips chat.</li>
<li>Fixed: Darken VOD comments.</li>
<li>Fixed: Dark theme broke for Twitch Pulse.</li>
<li>Fixed: Hide Boxart on Hover setting.</li>
<li>Fixed: Enhanced tooltips when hovering over the social bar.</li>
</ul>
<div class="list-header">3.5.482 <time datetime="2017-05-13">(2017-05-13)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Use data from the FFZ room API's user badges response.</li>
<li>Fixed: Blank lines in chat when users link to clips.</li>
<li>Fixed: API instance <code>error</code> method not accepting an optional object to log.</li>
</ul>
<div class="list-header">3.5.481 <time datetime="2017-05-09">(2017-05-09)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Display the number of Notes a user has on moderation cards, once the data is loaded.</li>
<li>Fixed: Don't display background colors on custom bits badges.</li>
<li>Fixed: Advanced settings search box styling.</li>
<li>Fixed: ITAD button showing in places it shouldn't.</li>
<li>Fixed: Only show the Friend Watching desktop notification for the channel you're watching if you have multiple chats pinned.</li>
</ul>
<div class="list-header">3.5.480 <time datetime="2017-05-03">(2017-05-03)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Setting for displaying AutoMod actions in the same way as vanilla Twitch.</li>
<li>Changed: More dark mode tweaks for partner-specific pages.</li>
</ul>
<div class="list-header">3.5.479 <time datetime="2017-05-02">(2017-05-02)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: You can now define in-line moderation icons that are usable even when you don't have moderation power over the user.</li>
<li>Fixed: Darken several pages related to subscriptions and bits settings for partners and affiliates.</li>
</ul>
<div class="list-header">3.5.478 <time datetime="2017-04-28">(2017-04-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Twitch also broke linkification of channel titles when they removed the selector for the title element.</li>
</ul>
<div class="list-header">3.5.477 <time datetime="2017-04-28">(2017-04-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Channel Title on Top setting breaking after Twitch removed specific selectors for that part of the page.</li>
<li>Fixed: Don't re-enable gray mode if a user has it specifically disabled and they enable dark mode via the Twitch chat settings menu.</li>
</ul>
<div class="list-header">3.5.476 <time datetime="2017-04-28">(2017-04-28)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Incorrect layout width calculations when the browser's default font size is not as expected.</li>
<li>Fixed: Styles weren't applying properly to the Followed Since display on users' following and followers pages.</li>
</ul>
<div class="list-header">3.5.475 <time datetime="2017-04-24">(2017-04-24)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: AutoMod stopped working due to internal changes to the Twitch app.</li>
<li>Removed: Excessive debug logging for settings.</li>
</ul>
<div class="list-header">3.5.474 <time datetime="2017-04-23">(2017-04-23)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Fixed: Stop using <code>localStorage.hasOwnProperty</code> due to a Chrome bug.</li>
</ul>
<div class="list-header">3.5.473 <time datetime="2017-04-23">(2017-04-23)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Excessive debug logging for a settings loading issue.</li>
<li>Fixed: Darken the Twitch Associate agreement.</li>
</ul>
<div class="list-header">3.5.472 <time datetime="2017-04-22">(2017-04-22)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Support for the new Verified badge.</li>
<li>Changed: Add support for badges that have different images when rendered transparently.</li>
<li>Fixed: Add temporary fix for mod card and FFZ menu positioning until Twitch fixes their CSS.</li>
<li>Fixed: Unable to favorite some emoticons added through the API.</li>
<li>Fixed: Fetch Twitch Inventory correctly rather than guessing about which sets are inventory sets.</li>
<li>Fixed: Properly label Twitch Inventory sets in the tab completion UI.</li>
<li>Fixed: Update the favorited status of emotes in the tab completion UI when it is changed.</li>
<li>Fixed: Do not show <code>Channel: undefined</code> for emoticons from unknown sets. They might not be from a channel, and it looks bad.</li>
<li>Fixed: Link colors in the top navigation bar when using a bright color with the dark theme enabled.</li>
</ul>
<div class="list-header">3.5.471 <time datetime="2017-04-21">(2017-04-21)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Friend Watching Notifications setting to show notifications when you get a message that a friend is also watching the same channel.</li>
<li>Added: Highlight Users setting to highlight all messages from specific users to tide people over until FFZv4.</li>
<li>Fixed: Changes to Twitch directory breaking channel logo and uptime display.</li>
<li>Fixed: Apply hidden thumbnails setting to more video preview components.</li>
<li>Fixed: Caching of emoji codepoint calculation.</li>
<li>Fixed: Bug with unclickable usernames in moderation card chat history.</li>
<li>Fixed: Don't re-enable gray mode if a user has it specifically disabled and they enable dark mode via the Twitch chat settings menu.</li>
</ul>
<div class="list-header">3.5.470 <time datetime="2017-04-20">(2017-04-20)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Changed: More improved wording for the ITAD popup.</li>

View file

@ -474,15 +474,17 @@ FFZ.settings_info.chatter_count = {
help: "Display the current number of users connected to chat beneath the channel.",
on_update: function(val) {
if ( this._cindex )
this._cindex.ffzUpdateMetadata('chatters');
if ( ! val || ! this.rooms )
if ( ! this.rooms )
return;
// Refresh the data.
for(var room_id in this.rooms)
this.rooms.hasOwnProperty(room_id) && this.rooms[room_id].room && this.rooms[room_id].room.ffzInitChatterCount();
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room;
r && r.ffzInitChatterCount();
}
if ( this._cindex )
this._cindex.ffzUpdateMetadata('chatters');
}
};

View file

@ -942,7 +942,10 @@ FFZ.prototype.modify_chat_input = function(component) {
return emotes;
}.property(),
_setPartialName: function() { },
_setPartialName: function() {
if ( f.has_bttv )
return this._super();
}.observes('textareaValue'),
ffz_suggestions: function() {
var output = [],
@ -1041,9 +1044,24 @@ FFZ.prototype.modify_chat_input = function(component) {
for(var i=0; i < suggestions.length; i++) {
var suggestion = suggestions[i],
name = suggestion.id,
display_name = suggestion.displayName || (name && name.capitalize()),
username_match = display_name.trim().toLowerCase() === name,
alias = f.aliases[name];
display_name = suggestion.displayName,
username_match;
if ( name === undefined ) {
var dnt = display_name && display_name.trim();
if ( dnt && /^[a-z0-9_]+$/i.test(dnt) )
name = dnt.toLowerCase();
else
continue;
}
if ( ! display_name ) {
display_name = name.capitalize();
username_match = true;
} else
username_match = display_name.trim().toLowerCase() === name;
var alias = f.aliases[name];
if ( user_output[name] && ! user_output[name].is_alias ) {
var token = user_output[name];
@ -1245,6 +1263,9 @@ FFZ.prototype.modify_chat_input = function(component) {
var target = event.target,
cl = target.classList;
if ( f.has_bttv )
this._super();
if ( ! this.get('ffz_suggestions_visible') || cl.contains('suggestion') || cl.contains('suggestions') || target === this.get('chatTextArea') )
return;

View file

@ -180,6 +180,18 @@ FFZ.settings_info.remove_filtered = {
};
FFZ.settings_info.remove_filtered_mod = {
type: "boolean",
value: false,
category: "Chat Filtering",
no_bttv: 6,
name: "Remove Messages from Moderators",
help: "Messages with banned words will only be removed if they are not from a moderator, unless this setting is enabled."
};
FFZ.settings_info.remove_deleted = {
type: "boolean",
value: false,

View file

@ -235,26 +235,19 @@ FFZ.prototype.setup_layout = function() {
}.property("ffzExtraHeight", "windowWidth", "rightColumnWidth", "fullSizePlayerDimensions", "windowHeight"),
contentWidth: function() {
var left_width = this.get('isSocialColumnEnabled') ? LS(
f.settings.socialbar_hide ? 0 :
this.get('isSocialColumnCollapsed') ? 50 : 240
) : LS(
this.get('ffzMinimizeNavigation') ? 10 :
this.get('isLeftColumnClosed') ? 50 : 240
),
var left_width = LS(f.settings.socialbar_hide ? 0 : this.get('isSocialColumnCollapsed') ? 50 : 240),
right_width = ! f.has_bttv && this.get('portraitMode') ? 0 : this.get("isRightColumnClosed") ? 0 : this.get("rightColumnWidth");
return this.get("windowWidth") - left_width - right_width - LS(60);
}.property("windowWidth", 'ffzMinimizeNavigation', "portraitMode", "isRightColumnClosed", "isLeftColumnClosed", "rightColumnWidth", "isSocialColumnCollapsed", "isSocialColumnEnabled"),
}.property("windowWidth", 'ffzMinimizeNavigation', "portraitMode", "isRightColumnClosed", "rightColumnWidth", "isSocialColumnCollapsed"),
ffzExtraHeight: function() {
return (this.get('isSocialColumnEnabled') ? this.get('ffzMinimizeNavigation') ? 10 : 50 : 0) +
return (this.get('ffzMinimizeNavigation') ? 10 : 50) +
(f.settings.channel_bar_collapse ? 10 : 60) + 15 +
(f.settings.channel_title_top === 2 ? 20 : f.settings.channel_title_top > 0 ? 55 : 0) +
(f.settings.channel_title_top ? 70 : 80);
}.property("isSocialColumnEnabled", "ffzMinimizeNavigation"),
}.property("ffzMinimizeNavigation"),
fullSizePlayerDimensions: function() {
var h = this.get('windowHeight'),
@ -321,7 +314,7 @@ FFZ.prototype.setup_layout = function() {
if ( this.get('portraitMode') ) {
var size = this.get('fullSizePlayerDimensions'),
video_below = this.get('portraitVideoBelow'),
top_height = this.get('isSocialColumnEnabled') ? this.get('ffzMinimizeNavigation') ? 10 : 50 : 0,
top_height = this.get('ffzMinimizeNavigation') ? 10 : 50,
video_height = size.height + this.get('ffzExtraHeight'),
chat_height = window_height - video_height,

View file

@ -13,7 +13,7 @@
FFZ.settings_info.automod_inline = {
type: "boolean",
value: true,
value: false,
category: "Chat Moderation",
no_bttv: 6,
@ -597,7 +597,7 @@ FFZ.settings_info.chat_font_family = {
var span = document.createElement('span');
span.style.fontFamily = val;
css = ".pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history,.ember-chat .chat-messages {" + span.style.cssText + "}";
css = ".ffz-recent-messages .chat-line,.pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history,.ember-chat .chat-messages {" + span.style.cssText + "}";
}
utils.update_css(this._chat_style, "chat_font_family", css);
@ -605,6 +605,72 @@ FFZ.settings_info.chat_font_family = {
};
FFZ.settings_info.recent_highlights = {
type: "boolean",
value: false,
category: "Chat Appearance",
no_bttv: true,
name: "Recent Highlights <span>Beta</span>",
help: "Display a Recent Highlights section at the top of chat to make sure you don't miss anything.",
on_update: function(val) {
this._roomv && this._roomv.ffzUpdateRecent();
if ( ! val )
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room;
r.set('ffz_recent_highlights', []);
r.set('ffz_recent_highlights_unread', 0);
}
}
}
FFZ.settings_info.recent_highlight_count = {
type: "button",
value: 50,
category: "Chat Appearance",
no_bttv: true,
name: "Recent Highlights Length",
help: "Set the maximum number of recent highlights to keep at once.",
method: function() {
var f = this;
utils.prompt(
"Recent Highlights Length",
"Please enter a new maximum length for the recent highlights scrollback. Please note that setting this too high may cause your computer to begin lagging as chat messages accumulate.</p><p><b>Default:</b> 50",
this.settings.recent_highlight_count,
function(new_val) {
if ( new_val === null || new_val === undefined )
return;
new_val = parseInt(new_val);
if ( Number.isNaN(new_val) || ! Number.isFinite(new_val) )
new_val = 50;
new_val = Math.max(1, new_val);
f.settings.set("recent_highlight_count", new_val);
});
},
on_update: function(val) {
for(var room_id in this.rooms) {
var r = this.rooms[room_id] && this.rooms[room_id].room,
rh = r && r.get('ffz_recent_highlights');
if ( rh && rh.length > val )
r.set('ffz_recent_highlights', rh.splice(Math.max(0, rh.length - val), rh.length));
}
this._roomv && this._roomv.ffzUpdateRecent();
}
}
FFZ.settings_info.emoji_scale = {
type: "select",
options: {
@ -676,9 +742,9 @@ FFZ.settings_info.chat_font_size = {
var lh = Math.max(20, Math.round((20/12)*val)),
pd = Math.floor((lh - 20) / 2);
css = ".pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history .chat-line,.ember-chat .chat-messages .chat-line { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
css = ".ffz-recent-messages .chat-line,.pinned-cheers .chat-line,.timestamp-line,.conversation-chat-line,.conversation-system-messages,.chat-history .chat-line,.ember-chat .chat-messages .chat-line { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
if ( pd )
css += ".pinned-cheers .chat-line,.ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: " + pd + "px; }";
css += ".ffz-recent-messages .chat-line .mod-icons,.pinned-cheers .chat-line,.ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: " + pd + "px; }";
}
utils.update_css(this._chat_style, "chat_font_size", css);
@ -730,7 +796,7 @@ FFZ.settings_info.chat_ts_size = {
css = "";
else {
var lh = Math.max(20, Math.round((20/12)*val), Math.round((20/12)*this.settings.chat_font_size));
css = ".ember-chat .chat-messages .timestamp { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
css = ".ffz-recent-messages .timestamp,.ember-chat .chat-messages .timestamp { font-size: " + val + "px !important; line-height: " + lh + "px !important; }";
}
utils.update_css(this._chat_style, "chat_ts_font_size", css);

View file

@ -883,7 +883,7 @@ FFZ.prototype.modify_moderation_card = function(component) {
// If we're viewing the chat history, update it.
var el = this.get('element'),
container = el && el.querySelector('.ffz-tab-container'),
history = container && container.querySelector('.chat-history.lv-history');
history = container && container.querySelector('.ffz-tab-container[data-page="history"] .chat-history.lv-history');
if ( history ) {
var was_at_bottom = history.scrollTop >= (history.scrollHeight - history.clientHeight),

View file

@ -30,10 +30,8 @@ FFZ.settings_info.player_stats = {
help: "Display your current stream latency (how far behind the broadcast you are) under the player, with a few useful statistics in a tooltip.",
on_update: function(val) {
if ( ! this._cindex )
return;
this._cindex.ffzUpdateMetadata('player_stats');
if ( this._cindex )
this._cindex.ffzUpdateMetadata('player_stats');
}
};
@ -199,12 +197,19 @@ FFZ.prototype.modify_twitch_player = function(player) {
},
ffzRecreatePlayer: function() {
var player = this.get('player'),
theatre = player && player.getTheatre();
var t = this,
player = this.get('player'),
theatre, fullscreen, had_player = false;
// Tell the player to destroy itself.
if ( player )
if ( player ) {
had_player = true;
fullscreen = player.fullscreen;
theatre = player.theatre;
player.fullscreen = false;
player.theatre = false;
player.destroy();
}
// Break down everything left over from that player.
this.$('#player').html('');
@ -213,7 +218,16 @@ FFZ.prototype.modify_twitch_player = function(player) {
this.set('ffz_post_player', false);
// Now, let Twitch create a new player as usual.
Ember.run.next(this.didInsertElement.bind(this));
Ember.run.next(function() {
t.didInsertElement();
had_player && setTimeout(function() {
var player = t.get('player');
if ( player ) {
//player.fullscreen = fullscreen;
player.theatre = theatre;
}
})
});
},
/*ffzUpdatePlayerPaused: function() {
@ -269,17 +283,18 @@ FFZ.prototype.modify_twitch_player = function(player) {
// Add an option to the menu to recreate the player.
var t = this,
el = this.$('.player-menu .player-menu__item--stats')[0],
el = this.$('.player-buttons-right #js-settings')[0],
container = el && el.parentElement;
if ( el && ! container.querySelector('.js-player-reset') ) {
var btn_link = utils.createElement('a', 'player-text-link js-player-reset', 'Reset Player'),
btn = utils.createElement('p', 'player-menu__item player-menu__item--reset pl-small', btn_link);
if ( el && ! container.querySelector('.ffz-player-reset') ) {
var btn = utils.createElement('button', 'player-button player-button--reset ffz-player-reset');
btn.type = 'button';
btn_link.tabindex = '-1';
btn_link.href = '#';
btn.innerHTML = '<span class="player-tip js-control-tip" data-tip="Double-Click to Reset Player"></span>' +
constants.CLOSE;
btn_link.addEventListener('click', function(e) {
jQuery(btn).on('dblclick', function(e) {
//btn.addEventListener('click', function(e) {
t.ffzRecreatePlayer();
e.preventDefault();
return false;

View file

@ -178,6 +178,28 @@ FFZ.prototype.setup_room = function() {
}
var ChannelSubs = utils.ember_lookup('service:channel-subscriptions');
if ( ChannelSubs ) {
this.log("Hooking the Ember Channel Subscriptions service.");
ChannelSubs.reopen({
populateSubNotificationTokens: function() {
var Chat = utils.ember_lookup('controller:chat'),
tokens = Chat && Chat.get('currentRoom.roomProperties.available_chat_notification_tokens');
return this._super(tokens);
},
_reloadSubNotificationToken: function(e) {
var t = this;
return this.get("api").request("get", "/api/channels/" + e + "/chat_properties").then(function(e) {
var room = f.rooms && f.rooms[e] && f.rooms[e].room;
room && room.set('roomProperties.available_chat_notification_tokens', e.available_chat_notification_tokens);
t.isDestroyed || t.populateSubNotificationTokens(e.available_chat_notification_tokens)
})
},
});
}
this.update_views('component:chat/chat-room', this.modify_room_component);
this.update_views('component:chat/chat-interface', this.modify_chat_interface);
@ -657,7 +679,8 @@ FFZ.HoverPause = {
FFZ.prototype.modify_room_component = function(component) {
var f = this,
PinnedCheers = utils.ember_lookup('service:bits-pinned-cheers');
PinnedCheers = utils.ember_lookup('service:bits-pinned-cheers'),
ChannelSubs = utils.ember_lookup('service:channel-subscriptions');
utils.ember_reopen_view(component, _.extend({
ffz_init: function() {
@ -676,9 +699,18 @@ FFZ.prototype.modify_room_component = function(component) {
this.ffzUpdateStatus();
}
var actions = this._actions || {},
var t = this,
actions = this._actions || {},
orig_show = actions.showModOverlay;
actions.accommodatePinnedMessage = function(e) {
var el = t.get('element'),
chat = el.querySelector('.js-chat-messages');
if ( chat )
chat.dataset.pinned_height = e;
};
actions.showModOverlay = function(e) {
var Channel = utils.ember_resolve('model:deprecated-channel'),
chan = Channel && Channel.find && Channel.find({id: e.sender});
@ -709,6 +741,8 @@ FFZ.prototype.modify_room_component = function(component) {
isModeratorOrHigher: this.get("room.isModeratorOrHigher")
});
}
this.ffzUpdateRecent();
},
ffz_destroy: function() {
@ -719,18 +753,181 @@ FFZ.prototype.modify_room_component = function(component) {
this.ffzRemoveKeyHook();
},
ffzUpdateRecent: function() {
var t = this,
el = this.get('element'),
container = this.get('ffz_recent_el'),
con_count = this.get('ffz_recent_count_el'),
should_show = f.settings.recent_highlights && ! f.has_bttv;
if ( ! el )
return;
if ( ! container ) {
if ( ! should_show )
return;
container = utils.createElement('ul', 'chat-history');
var expander = utils.createElement('div', 'ffz-recent-expando', 'Recent Highlights<span class="pill"></span>'),
big_el = utils.createElement('div', 'ffz-recent-messages', expander),
btn_handle = utils.createElement('span', 'ffz-handle ffz-close-button'),
super_parent = document.body.querySelector('.app-main');
con_count = expander.querySelector('.pill');
container.classList.toggle('dark', f.settings.dark_twitch);
expander.insertBefore(btn_handle, expander.firstChild);
container.dataset.docked = true;
big_el.appendChild(container);
el.appendChild(big_el);
el.classList.add('ffz-has-recent-messages');
this.set('ffz_recent_el', container);
this.set('ffz_recent_count_el', con_count);
expander.addEventListener('mousemove', function(e) {
con_count.textContent = '';
t.set('room.ffz_recent_highlights_unread', 0);
});
btn_handle.addEventListener('click', function(e) {
if ( ! big_el.classList.contains('ui-moved') || ! e.button === 0 )
return;
big_el.style.top = 0;
big_el.style.left = 0;
big_el.classList.remove('ui-moved');
big_el.parentElement.removeChild(big_el);
el.appendChild(big_el);
el.classList.add('ffz-has-recent-messages');
container.dataset.docked = true;
});
var st;
jQuery(big_el).draggable({
handle: expander,
start: function(e) {
st = container.scrollTop;
big_el.classList.add('ui-moved');
container.dataset.docked = false;
el.classList.remove('ffz-has-recent-messages');
},
stop: function(e) {
if ( big_el.parentElement !== super_parent ) {
var rect = big_el.getBoundingClientRect(),
pr = super_parent.getBoundingClientRect();
big_el.parentElement.removeChild(big_el);
super_parent.appendChild(big_el);
big_el.style.top = (rect.top - pr.top) + "px";
big_el.style.left = (rect.left - pr.left) + "px";
}
container.scrollTop = st;
}
});
jQuery(container).on('click', '.chat-line', function(e) {
if ( ! e.target || e.button !== 0 )
return;
var jq = jQuery(e.target),
cl = e.target.classList,
line = cl.contains('chat-line') ? e.target : jq.parents('.chat-line')[0],
room_id = line && line.dataset.room,
room = room_id && f.rooms[room_id] && f.rooms[room_id].room,
from = line && line.dataset.sender,
msg_id = line && line.dataset.id;
if ( cl.contains('deleted-word') ) {
jq.trigger('mouseout');
e.target.outerHTML = e.target.dataset.text;
} else if ( cl.contains('deleted-link') )
return f._deleted_link_click.call(e.target, e);
else if ( cl.contains('badge') ) {
if ( cl.contains('click_action') ) {
var badge = f.badges && f.badges[e.target.getAttribute('data-badge-id')];
if ( badge.click_action )
badge.click_action.call(f, this.get('msgObject'), e);
} else if ( cl.contains('click_url') )
window.open(e.target.dataset.url, "_blank");
else if ( cl.contains('turbo') )
window.open("/products/turbo?ref=chat_badge", "_blank");
else if ( cl.contains('subscriber') )
window.open("/" + room_id + "/subscribe?ref=in_chat_subscriber_link");
} else if ( f._click_emote(e.target, e) )
return;
else if ( (f.settings.clickable_mentions && cl.contains('user-token')) || cl.contains('from') || e.target.parentElement.classList.contains('from') ) {
var target = cl.contains('user-token') ? e.target.dataset.user : from;
if ( ! target )
return;
var bounds = line && line.getBoundingClientRect() || document.body.getBoundingClientRect(),
x = 0, right;
if ( bounds.left > 400 )
right = bounds.left - 40;
f._roomv.actions.showModOverlay.call(f._roomv, {
left: bounds.left,
right: right,
top: bounds.top + bounds.height,
real_top: bounds.top,
sender: target
});
}
});
} else if ( ! should_show ) {
jQuery(container.parentElement).remove();
this.set('ffz_recent_el', null);
this.set('ffz_recent_count_el', null);
el.classList.remove('ffz-has-recent-messages');
return;
}
var was_at_bottom = container.scrollTop >= (container.scrollHeight - container.clientHeight);
container.innerHTML = '';
con_count.textContent = container.dataset.docked ? utils.format_unread(this.get('room.ffz_recent_highlights_unread') || 0) : '';
var messages = this.get('room.ffz_recent_highlights') || [];
for(var i=0; i < messages.length; i++)
container.appendChild(f._build_mod_card_history(messages[i], null, true));
if ( was_at_bottom )
container.scrollTop = container.scrollHeight;
}.observes('room'),
ffzUpdateBits: function() {
var t = this,
channel = this.get('room.channel');
if ( ! channel )
channel = this.get('room.channel'),
bits_room = this.get('bitsRoom');
if ( ! channel || ! bits_room )
return;
PinnedCheers && PinnedCheers.dismissLocalMessage();
if ( ! channel.get('isLoaded') )
channel.load().then(function() { t._initializeBits(channel) })
else
channel.load().then(function() { bits_room.reset(); t._initializeBits(channel) })
else {
bits_room.reset();
this._initializeBits(channel);
}
ChannelSubs && ChannelSubs.populateSubNotificationTokens(this.get('room.roomProperties.available_chat_notification_tokens'));
}.observes('room'),
@ -1130,7 +1327,7 @@ FFZ.prototype._load_room_json = function(room_id, callback, data) {
var model = this.rooms[room_id] = this.rooms[room_id] || {};
for(var key in data)
if ( key !== 'users' && key !== 'room' && data.hasOwnProperty(key) )
if ( key !== 'user_badges' && key !== 'users' && key !== 'room' && data.hasOwnProperty(key) )
model[key] = data[key];
// Merge the user data.
@ -1144,6 +1341,21 @@ FFZ.prototype._load_room_json = function(room_id, callback, data) {
}
}
// Merge badge data
for(var badge_id in data.user_badges) {
var badge = this.badges[badge_id];
if ( ! badge )
continue;
for(var l=data.user_badges[badge_id], i=0, j=l.length; i < j; i++) {
var user_id = l[i],
user = model.users[user_id] = model.users[user_id] || {},
badges = user.badges = user.badges || {};
badges[badge.slot] = {id: badge_id};
}
}
// Preserve the pointer to the Room instance.
/*if ( this.rooms[room_id] )
data.room = this.rooms[room_id].room;
@ -1192,6 +1404,8 @@ FFZ.prototype._modify_room = function(room) {
ffz_banned: false,
mru_list: [],
ffz_recent_highlights: [],
ffz_recent_highlights_unread: 0,
ffzUpdateBadges: function() {
if ( this.get('isGroupRoom') )
@ -1299,7 +1513,7 @@ FFZ.prototype._modify_room = function(room) {
try {
f.add_room(this.id, this);
this.set("ffz_chatters", {});
this.set("ffz_chatters", []);
this.set("ffz_ids", this.get('ffz_ids') || {});
this.set("ffz_last_notices", this.get('ffz_last_notices') || {});
} catch(err) {
@ -1789,7 +2003,10 @@ FFZ.prototype._modify_room = function(room) {
ffzPushMessages: function(messages) {
var new_messages = [],
new_unread = 0;
new_unread = 0,
highlight_messages = [],
highlight_unread = 0;
for(var i=0; i < messages.length; i++) {
var msg = messages[i];
@ -1797,8 +2014,11 @@ FFZ.prototype._modify_room = function(room) {
new_messages.push(msg);
if ( ! (msg.tags && msg.tags.historical) && msg.style !== "admin" && msg.style !== "whisper" ) {
if ( msg.ffz_has_mention )
if ( msg.ffz_has_mention ) {
this.ffz_last_mention = Date.now();
highlight_messages.push(msg);
highlight_unread++;
}
new_unread++;
}
@ -1867,6 +2087,39 @@ FFZ.prototype._modify_room = function(room) {
this.incrementProperty("unreadCount", new_unread);
this.ffz_last_activity = Date.now();
}
if ( f.settings.recent_highlights && highlight_unread ) {
var old_highlights = this.get('ffz_recent_highlights') || [],
raw_remove = old_highlights.length + highlight_messages.length > f.settings.recent_highlight_count ?
Math.max(0, old_highlights.length - f.settings.recent_highlight_count) + highlight_messages.length : 0,
to_remove = raw_remove % 2,
trimmed = old_highlights.slice(to_remove, old_highlights.length).concat(highlight_messages),
el = f._roomv && f._roomv.get('ffz_recent_el');
this.set('ffz_recent_highlights', trimmed);
this.incrementProperty('ffz_recent_highlights_unread', highlight_unread);
if ( el && f._roomv.get('room') === this ) {
var was_at_bottom = el.scrollTop >= (el.scrollHeight - el.clientHeight);
while( el.childElementCount && to_remove-- )
el.removeChild(el.firstElementChild);
for(var i=0; i < highlight_messages.length; i++)
el.appendChild(f._build_mod_card_history(highlight_messages[i], null, true));
if ( was_at_bottom )
el.scrollTop = el.scrollHeight;
if ( el.dataset.docked ) {
el = f._roomv.get('ffz_recent_count_el');
if ( el )
el.textContent = utils.format_unread(this.get('ffz_recent_highlights_unread'));
}
}
}
},
ffzSchedulePendingFlush: function(now) {
@ -2023,7 +2276,7 @@ FFZ.prototype._modify_room = function(room) {
ffzProcessMessage: function(msg) {
if ( msg ) {
var notice_type = msg.tags && msg.tags['msg-id'],
is_resub = notice_type === 'resub',
is_resub = notice_type === 'resub' || notice_type === 'sub',
room_id = this.get('id'),
msg_id = msg.tags && msg.tags.id;
@ -2177,10 +2430,6 @@ FFZ.prototype._modify_room = function(room) {
f.api_trigger('room-message', msg);
// Also update chatters.
if ( ! is_whisper && this.chatters && ! this.chatters[msg.from] && msg.from !== 'twitchnotify' && msg.from !== 'jtv' )
this.ffzUpdateChatters(msg.from);
// We're past the last return, so store the message
// now that we know we're keeping it.
if ( msg_id ) {
@ -2195,8 +2444,8 @@ FFZ.prototype._modify_room = function(room) {
}
// Report this message to the dashboard.
if ( window !== window.parent && parent.postMessage && msg.from && msg.from !== "jtv" && msg.from !== "twitchnotify" )
parent.postMessage({from_ffz: true, command: 'chat_message', data: {from: msg.from, room: msg.room}}, "*"); //location.protocol + "//www.twitch.tv/");
if ( msg.from && msg.from !== "jtv" && msg.from !== "twitchnotify" )
this.ffzSafePM({from_ffz: true, command: 'chat_message', data: {from: msg.from, room: msg.room}}, "*"); //location.protocol + "//www.twitch.tv/");
// Flagging for review.
if ( msg.tags && msg.tags.risk === "high" )
@ -2330,8 +2579,11 @@ FFZ.prototype._modify_room = function(room) {
}.observes('unreadCount'),
ffzInitChatterCount: function() {
if ( ! this.tmiRoom )
if ( ! this.tmiRoom || ! f.settings.chatter_count ) {
this.set("ffz_chatters", []);
this.ffzUpdateChatters();
return;
}
if ( this._ffz_chatter_timer ) {
clearTimeout(this._ffz_chatter_timer);
@ -2340,26 +2592,27 @@ FFZ.prototype._modify_room = function(room) {
var room = this;
this.tmiRoom.list().done(function(data) {
var chatters = {};
var chatters = [];
data = data.data.chatters;
if ( data && data.admins )
for(var i=0; i < data.admins.length; i++)
chatters[data.admins[i]] = true;
chatters.push(data.admins[i]);
if ( data && data.global_mods )
for(var i=0; i < data.global_mods.length; i++)
chatters[data.global_mods[i]] = true;
chatters.push(data.global_mods[i]);
if ( data && data.moderators )
for(var i=0; i < data.moderators.length; i++)
chatters[data.moderators[i]] = true;
chatters.push(data.moderators[i]);
if ( data && data.staff )
for(var i=0; i < data.staff.length; i++)
chatters[data.staff[i]] = true;
chatters.push(data.staff[i]);
if ( data && data.viewers )
for(var i=0; i < data.viewers.length; i++)
chatters[data.viewers[i]] = true;
chatters.push(data.viewers[i]);
room.set("ffz_chatters", chatters);
room.ffzUpdateChatters();
}).always(function() {
room._ffz_chatter_timer = setTimeout(room.ffzInitChatterCount.bind(room), 300000);
});
@ -2367,22 +2620,31 @@ FFZ.prototype._modify_room = function(room) {
ffzUpdateChatters: function(add, remove) {
var chatters = this.get("ffz_chatters") || {};
if ( add )
chatters[add] = true;
if ( remove && chatters[remove] )
delete chatters[remove];
if ( ! f.settings.chatter_count )
return;
var chatters = this.get("ffz_chatters") || [];
if ( add && chatters.indexOf(add) === -1 )
chatters.push(add);
if ( remove ) {
var ind = chatters.indexOf(remove);
if ( ind !== -1 )
chatters.splice(ind, 1);
}
if ( f._cindex )
f._cindex.ffzUpdateMetadata('chatters');
if ( window !== window.parent && parent.postMessage )
parent.postMessage({from_ffz: true, command: 'chatter_count', data: {room: this.get('id'), chatters: Object.keys(this.get('ffz_chatters') || {}).length}}, "*"); //location.protocol + "//www.twitch.tv/");
this.ffzSafePM({from_ffz: true, command: 'chatter_count', data: {room: this.get('id'), chatters: (this.get('ffz_chatters') || []).length}}, "*"); //location.protocol + "//www.twitch.tv/");
},
ffzSafePM: function(message, origin) {
try {
if ( window !== window.parent && parent.postMessage )
return parent.postMessage(message, origin);
} catch(err) { }
},
ffzPatchTMI: function() {
var tmi = this.get('tmiRoom'),

View file

@ -382,7 +382,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
ffz_init: function() {
var t = this,
el = this.get('element'),
card = jQuery('.sc-card', el),
card = jQuery('.js-sc-card', el),
data = card && card.data('tipsy');
if ( ! data || ! data.options )
@ -418,6 +418,7 @@ FFZ.prototype.modify_social_followed_channel = function(component) {
'<span class="stat">' + constants.LIVE + ' ' + utils.number_commas(data.stream.viewers) + '</span>' +
'<b>' + utils.sanitize(channel.display_name || channel.name) + '</b><br>' +
'<span class="playing">' +
(data.stream.stream_type === 'watch_party' ? '<span class="pill is-watch-party">Vodcast</span> ' : '') +
(channel.game === 'Creative' ?
'Being Creative' :
(channel.game ?

View file

@ -104,7 +104,7 @@ API.prototype.log = function(msg, data, to_json, log_json) {
API.prototype.error = function(msg, error, to_json, log_json) {
this.ffz.error('Ext #' + this.id + ' (' + this.name_key + '): ' + msg, data, to_json, log_json);
this.ffz.error('Ext #' + this.id + ' (' + this.name_key + '): ' + msg, error, to_json, log_json);
}

View file

@ -96,6 +96,18 @@ FFZ.prototype.setup_bttv_7 = function(delay) {
}
/* Update the chat input to not use FFZ's input handling.
if ( this._inputv ) {
var t = this._inputv.$("textarea");
t.off("keyup");
t.off("keydown");
t.off("keypress");
t.on("keyup", this._inputv._onKeyUp.bind(this._inputv));
t.on("keydown", this._inputv._onKeyDown.bind(this._inputv));
}//*/
// Hook into BTTV's dark mode.
cl.add('ffz-bttv');
cl.toggle('ffz-bttv-dark', settings.get('darkenedMode'));
@ -105,6 +117,7 @@ FFZ.prototype.setup_bttv_7 = function(delay) {
});
this.update_ui_link();
this._roomv && this._roomv.ffzUpdateRecent();
this.api_trigger('bttv-initialized', 7);
}

View file

@ -41,6 +41,29 @@
.svg-logo_twitch, .clips-nav__logo { fill: white }
.nav-banner {
background-color: lighten(@nav-bg-color, 10%);
}
// Chat
.clip-chat-message {
color: #ccc;
}
.view-clip__main--darker {
background-color: darken(@nav-bg-color, 2%);
}
.view-clip__smallTitle {
color: @fg-color;
& > div {
background-color: @nav-bg-color;
border-bottom: lighten(@nav-bg-color, 10%);
}
}
// Content Meta
.nv-clip-content {

View file

@ -61,7 +61,7 @@ FFZ.channel_metadata = {};
// Version
var VER = FFZ.version_info = {
major: 3, minor: 5, revision: 480,
major: 3, minor: 5, revision: 494,
toString: function() {
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
}

View file

@ -240,7 +240,7 @@ var is_android = navigator.userAgent.indexOf('Android') !== -1,
search_input.placeholder = 'Search for Settings';
search_input.type = 'text';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 51) + 'px';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 53) + 'px';
search_cont.appendChild(search_input);
container.appendChild(filtered_cont);

View file

@ -1,4 +1,5 @@
/* Chat Line Padding */
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin,

View file

@ -5,6 +5,7 @@
border-bottom-color: rgba(255,255,255, 0.5);
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -4,6 +4,7 @@
border-top: 1px solid rgba(255,255,255, 0.5);
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -4,6 +4,7 @@
border-top: 1px solid #aaa;
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-top: 2px }

View file

@ -5,6 +5,7 @@
border-bottom: 1px solid #aaa;
}
.chat-history .chat-line,
.ember-chat .chat-messages .chat-line,
.ember-chat .chat-messages .chat-line.admin { padding-bottom: 2px }

View file

@ -798,7 +798,7 @@ FFZ.prototype.tokenize_chat_line = function(msgObject, prevent_notification, del
// Mentions!
if ( ! from_me ) {
tokens = this.tokenize_mentions(tokens);
var st = this.settings.remove_filtered;
var st = (mod_or_higher && !this.settings.remove_filtered_mod) ? 0 : this.settings.remove_filtered;
for(var i=0; i < tokens.length; i++) {
var token = tokens[i],
@ -1076,14 +1076,16 @@ FFZ.prototype.render_token = function(render_links, warn_links, render_bits, tok
video_info = VIDEO_URL.exec(href);
if ( clip_info ) {
var clips = utils.ember_lookup('service:clips');
clips && clips.getClipInfo(clip_info[1]).then(function(data) {
var clips = utils.ember_lookup('service:store');
clips && clips.findRecord && clips.findRecord('clip', clip_info[1]).then(function(data) {
//clips && clips.getClipInfo(clip_info[1]).then(function(data) {
data &&
success(true, {
image: data.previewImage,
image: data.get('scaledPreviewUrl'),
image_iframe: false,
html: '<span class="ffz-clip-title">' + utils.sanitize(data.title) + '</span>' +
'Channel: ' + utils.sanitize(data.broadcasterDisplayName) +
'<br>Game: ' + utils.sanitize(data.game)
html: '<span class="ffz-clip-title">' + utils.sanitize(data.get('title')) + '</span>' +
'Channel: ' + utils.sanitize(data.get('broadcasterDisplayName')) +
'<br>Game: ' + utils.sanitize(data.get('game'))
});
});

View file

@ -90,30 +90,39 @@ metadata.player_stats = {
stats = player.getVideoInfo();
} catch(err) { }
// Check for server offset.
var delayed = undefined;
if ( this._ws_open ) {
var offset = this._ws_server_offset;
if ( isNaN(offset) || ! isFinite(offset) )
this.ws_ping();
else
delayed = offset > 5000;
}
var delay = stats && Math.round(stats.hls_latency_broadcaster / 10) / 100;
return [stats, delay, delay > 180, player_cont];
return [stats, delay, delay > 180, player_cont, delayed];
},
order: 3,
host_order: 102,
static_label: constants.GRAPH,
label: function(stats, delay, is_old) {
if ( ! this.settings.player_stats || ! stats || ! stats.hls_latency_broadcaster )
label: function(stats, delay, is_old, player_cont, delayed) {
if ( ! this.settings.player_stats || ! delay )
return null;
delayed = delayed ? '(!) ' : '';
if ( is_old )
return utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old'
else {
delay = delay.toString();
var ind = delay.indexOf('.');
return delay + (ind === -1 ? '.00' : (ind >= delay.length - 2 ? '0' : '')) + 's';
}
return delayed + utils.time_to_string(Math.floor(delay), true, delay > 172800) + ' old'
else
return delayed + delay.toFixed(2) + 's';
},
color: function(stats, delay, is_old) {
var setting = this.settings.player_stats;
if ( setting === -1 )
if ( setting === -1 || is_old )
return '';
else if ( delay > (setting * 2) )
@ -127,9 +136,11 @@ metadata.player_stats = {
player_cont.$('.js-stats-toggle').click();
},
tooltip: function(stats, delay, is_old) {
tooltip: function(stats, delay, is_old, player_cont, delayed) {
delayed = delayed ? 'Your local clock seems to be off by roughly ' + (Math.round(this._ws_server_offset / 10) / 100).toFixed(2) + ' seconds, and that could be making this inaccurate.<hr>' : '';
if ( ! stats || ! stats.hls_latency_broadcaster )
return 'Stream Latency';
return delayed + 'Stream Latency';
var bitrate;
if ( stats.playback_bytes_per_second )
@ -137,7 +148,7 @@ metadata.player_stats = {
else
bitrate = Math.round(stats.current_bitrate * 100) / 100;
return (is_old ? 'Video Information<br>' +
return delayed + (is_old ? 'Video Information<br>' +
'Broadcast ' + utils.time_to_string(Math.floor(delay), true) + ' Ago<br><br>' : 'Stream Latency<br>') +
'Video: ' + stats.vid_width + 'x' + stats.vid_height + 'p' + stats.current_fps + '<br>' +
'Playback Rate: ' + utils.number_commas(bitrate) + ' Kbps<br>' +
@ -156,7 +167,7 @@ metadata.chatters = {
if ( ! room || ! this.settings.chatter_count )
return null;
return utils.number_commas(Object.keys(room.room.get('ffz_chatters') || {}).length);
return utils.number_commas((room.room.get('ffz_chatters') || []).length);
},
tooltip: 'Currently in Chat'

View file

@ -133,6 +133,10 @@ FFZ.settings_info.dark_twitch = {
if ( this.has_bttv )
return;
var RH = this._roomv && this._roomv.get('ffz_recent_el');
if ( RH )
RH.classList.toggle('dark', val);
(this.is_clips ? document.querySelector('html') : document.body).classList.toggle("ffz-dark", val);
var Settings = utils.ember_settings();

View file

@ -224,7 +224,9 @@ FFZ.prototype._build_following_tooltip = function(el) {
(uptime > 0 ? '<span class="stat">' + constants.CLOCK + ' ' + utils.duration_string(uptime) + '</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 === 'Creative' ? 'Being Creative' : (stream.channel.game ? 'Playing ' + utils.sanitize(stream.channel.game) : 'Not Playing')) + (tags ? ' | ' + _.pluck(tags, "text").join(" ") : '') + '</span>';
'<span class="playing">' +
(stream.stream_type === 'watch_party' ? '<span class="pill is-watch-party">Vodcast</span> ' : '') +
(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 )

View file

@ -770,7 +770,7 @@ FFZ.mod_card_pages.notes = {
utils.logviewer.get("comments/" + room_id + "?topic=" + user_id, token)
.then(utils.json).then(function(data) {
f.log("[LV] Comments: " + user_id + " in " + room_id, data);
//f.log("[LV] Comments: " + user_id + " in " + room_id, data);
history.classList.remove('loading');
// We want to listen to get new notes for this user.

View file

@ -2,7 +2,8 @@ var FFZ = window.FrankerFaceZ,
constants = require("../constants"),
utils = require("../utils"),
BANNED_SETS = {"00000turbo":true};
BANNED_SETS = {"00000turbo":true},
EXTRA_INVENTORY = ['33563'];
// -------------------
@ -154,6 +155,43 @@ FFZ.menu_pages.myemotes = {
},
render: function(view, container) {
/*var search_cont = utils.createElement('div', 'ffz-filter-container'),
search_input = utils.createElement('input', 'emoticon-selector__filter-input form__input js-filter-input text text--full-width'),
filtered_cont = utils.createElement('div', 'ffz-filter-children ffz-ui-sub-menu-page'),
was_filtered = false;
search_input.placeholder = 'Search for Emotes';
search_input.type = 'text';
filtered_cont.style.maxHeight = (parseInt(container.style.maxHeight) - 53) + 'px';
search_cont.appendChild(search_input);
container.appendChild(filtered_cont);
container.appendChild(search_cont);
search_input.addEventListener('input', function(e) {
var filter = (search_input.value || '').toLowerCase(),
groups = filtered_cont.querySelectorAll('.emoticon-grid');
for(var i=0; i < groups.length; i++) {
var el = groups[i],
emotes = el.querySelectorAll('.emoticon'),
hidden = true;
for(var j=0; j < emotes.length; j++) {
var em = emotes[j],
ehidden = filter.length && em.getAttribute('data-filter').indexOf(filter) === -1;
em.classList.toggle('hidden', ehidden);
hidden = hidden && ehidden;
}
el.classList.toggle('hidden', hidden);
el.classList.toggle('collapsable', ! filter.length);
}
});
container = filtered_cont;*/
FFZ.menu_pages.myemotes.render_lists.call(this, view, container, false);
}
},
@ -199,7 +237,9 @@ FFZ.menu_pages.myemotes = {
gathered_emotes = [];
// Start with Twitch Sets
var gathered_favorites = this.settings.favorite_emotes['twitch-inventory'] || [];
var gathered_favorites = this.settings.favorite_emotes['twitch-inventory'] || [],
gathered_channels = {},
other_channels = [];
for(var set_id in twitch_sets) {
if ( ! twitch_sets.hasOwnProperty(set_id) || ( ! favorites_only && ! this.settings.global_emotes_in_menu && set_id === '0' ) )
@ -213,7 +253,7 @@ FFZ.menu_pages.myemotes = {
if ( ! set.length )
continue;
if ( this._twitch_inventory_sets.indexOf(set_id) !== -1 ) {
if ( this._twitch_inventory_sets.indexOf(set_id) !== -1 || EXTRA_INVENTORY.indexOf(set_id) !== -1 ) {
for(var i=0; i < set.length; i++)
if ( ! favorites_only || gathered_favorites.indexOf(set[i].id) !== -1 )
gathered_emotes.push(set[i]);
@ -228,6 +268,12 @@ FFZ.menu_pages.myemotes = {
if ( favorites_only && (! favorites_list || ! favorites_list.length) )
continue;
if ( menu_id !== 'unknown' ) {
var gathered = gathered_channels[menu_id] = gathered_channels[menu_id] || [];
gathered.push(set_id);
continue;
}
var sort_key = 0,
menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, set_id, set, favorites_only);
@ -240,6 +286,33 @@ FFZ.menu_pages.myemotes = {
sets.push([[sort_key, menu_id], menu]);
}
for(var menu_id in gathered_channels) {
var gathered = [],
stuff = gathered_channels[menu_id];
if ( ! stuff.length )
continue;
for(var i=0; i < stuff.length; i++) {
var set_id = stuff[i],
set = twitch_sets[set_id];
for(var j=0; j < set.length; j++)
gathered.push([set_id, set[j]]);
}
var sort_key = 0,
menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, stuff[0], gathered, favorites_only);
if ( menu_id.indexOf('global') !== -1 )
sort_key = 100;
else if ( menu_id.substr(0,2) === '--' || menu_id === 'turbo' )
sort_key = 75;
if ( menu )
sets.push([[sort_key, menu_id], menu]);
}
// Handle the gathered single emotes.
if ( gathered_emotes.length ) {
var menu = FFZ.menu_pages.myemotes.draw_twitch_set.call(this, view, 'inventory', gathered_emotes, favorites_only);
@ -338,18 +411,22 @@ FFZ.menu_pages.myemotes = {
return true;
},
toggle_section: function(heading, container) {
toggle_section: function(heading, container, set_state) {
var menu = heading.parentElement,
set_id = menu.getAttribute('data-set'),
collapsed_list = this.settings.emote_menu_collapsed,
is_collapsed = collapsed_list.indexOf(set_id) === -1;
has_state = set_state !== undefined,
is_collapsed = has_state ? set_state : collapsed_list.indexOf(set_id) === -1;
if ( ! is_collapsed )
collapsed_list.removeObject(set_id);
else
collapsed_list.push(set_id);
if ( ! has_state ) {
if ( ! is_collapsed )
collapsed_list.removeObject(set_id);
else
collapsed_list.push(set_id);
this.settings.set('emote_menu_collapsed', collapsed_list, true);
}
this.settings.set('emote_menu_collapsed', collapsed_list, true);
menu.classList.toggle('collapsed', !is_collapsed);
if ( is_collapsed )
@ -382,7 +459,7 @@ FFZ.menu_pages.myemotes = {
menu.classList.add('collapsable');
menu.appendChild(heading);
menu.classList.toggle('collapsed', collapsed);
heading.addEventListener('click', function() { FFZ.menu_pages.myemotes.toggle_section.bind(f)(this, emotes); });
heading.addEventListener('click', function() { FFZ.menu_pages.myemotes.toggle_section.bind(f)(this, emotes); });
}
var set = [];
@ -420,6 +497,7 @@ FFZ.menu_pages.myemotes = {
em.classList.toggle('ffz-is-favorite', favorites_only);
em.setAttribute('data-ffz-emoji', emoji.code);
em.setAttribute('data-filter', emoji.name.toLowerCase() + ' :' + emoji.short_name.toLowerCase() + ':');
em.alt = emoji.raw;
em.addEventListener('click', this._add_emote.bind(this, view, emoji.raw, "emoji", emoji.raw));
@ -502,6 +580,11 @@ FFZ.menu_pages.myemotes = {
}
set.sort(function(a,b) {
if ( Array.isArray(a) )
a = a[1];
if ( Array.isArray(b) )
b = b[1];
var an = a.code.toLowerCase(),
bn = b.code.toLowerCase();
@ -514,8 +597,16 @@ FFZ.menu_pages.myemotes = {
for(var i=0; i < set.length; i++) {
var emote = set[i],
code = constants.KNOWN_CODES[emote.code] || emote.code,
is_favorite = favorites.indexOf(emote.id) !== -1;
esid = set_id,
favs = favorites;
if ( Array.isArray(emote) ) {
esid = emote[0];
emote = emote[1];
favs = this.settings.favorite_emotes["twitch-" + esid] || [];
}
var code = constants.KNOWN_CODES[emote.code] || emote.code,
is_favorite = favs.indexOf(emote.id) !== -1;
if ( favorites_only && ! is_favorite )
continue;
@ -525,6 +616,7 @@ FFZ.menu_pages.myemotes = {
em.className = 'emoticon ffz-tooltip ffz-can-favorite';
em.setAttribute('data-emote', emote.id);
em.setAttribute('data-filter', code.toLowerCase());
em.alt = code;
em.classList.toggle('ffz-favorite', is_favorite);
@ -541,13 +633,13 @@ FFZ.menu_pages.myemotes = {
em.style.backgroundImage = img_set;
}
em.addEventListener("click", function(id, c, e) {
em.addEventListener("click", function(id, c, q, e) {
e.preventDefault();
if ( (e.shiftKey || e.shiftLeft) && f.settings.clickable_emoticons )
window.open("https://twitchemotes.com/emote/" + id);
else
this._add_emote(view, c, "twitch-" + set_id, id, e);
}.bind(this, emote.id, code));
this._add_emote(view, c, "twitch-" + q, id, e);
}.bind(this, emote.id, code, esid));
c++;
emotes.appendChild(em);
@ -634,6 +726,7 @@ FFZ.menu_pages.myemotes = {
em.setAttribute('data-ffz-emote', emote.id);
em.setAttribute('data-ffz-set', set.id);
em.setAttribute('data-filter', emote.name.toLowerCase());
em.style.backgroundImage = 'url("' + emote.urls[1] + '")';
em.style.backgroundImage = '-webkit-' + img_set;

View file

@ -1181,6 +1181,7 @@ module.exports = FFZ.utils = {
return (loyalty ? '.ffz-no-loyalty ' : '') + '.from-display-preview[data-room="' + room_id + '"] .badge.' + badge_id + (loyalty ? '' : '.version-' + version) +
(loyalty ? ',.ffz-no-loyalty ' : ',') + '.chat-line[data-room="' + room_id + '"] .badge.' + badge_id + (loyalty ? '' : '.version-' + version) + '{' +
'background-color:transparent;' +
WEBKIT + 'mask-image: none;' +
'background-image:url("' + img_1x + '");' +
'background-image:' + WEBKIT + 'image-set(url("' + img_1x + '") 1x' + (img_2x ? ',url("' + img_2x + '") 2x' : '') + (img_4x ? ',url("' + img_4x + '") 4x' : '') + ')}';
},

157
style.css
View file

@ -1,5 +1,6 @@
/* Fix Tooltip Opacity */
body[data-page^="ember#"] { overflow: hidden }
body > div.tipsy { opacity: 1 !important; }
body > div.tipsy .tipsy-inner { background-color: rgba(0,0,0,0.8); }
body > div.tipsy .tipsy-arrow { opacity: 0.8; }
@ -35,6 +36,7 @@ body > div.tipsy .tipsy-arrow { opacity: 0.8; }
.ffz-hide-thumb-info-on-hover .video.item:hover .card__meta,
.ffz-hide-thumb-info-on-hover .video.item:hover .progress-bar-wrapper,
.ffz-hide-thumb-info-on-hover .card-carousel__item:hover .card__boxpin,
.ffz-hide-thumb-info-on-hover .ffz-directory-preview:hover .card__boxpin,
.player[data-paused="false"] #js-follow-panel,
body:not(.ffz-theater-basic-stats) .player-userinfo__game,
@ -111,7 +113,7 @@ body:not(.ffz-show-bits-tags) .bits-tag--container,
}
.ffz-channel-bar-bottom .subscription-modal__balloon {
top: -220px !important;
top: -400px !important;
}
.cn-hosting--bottom .ffz-channel-options .balloon {
@ -735,6 +737,8 @@ body.ffz-bttv-dark .ffz-ui-toggle.blue.live:hover svg.svg-emoticons path { fill:
margin: 11px 13px;
}
.ffz-player-reset svg { padding: 0 3px }
.player-menu__menu,
.ffz-ui-sub-menu-page,
.ffz-ui-menu-page { overflow-y: auto; }
@ -919,40 +923,48 @@ span.ffz-handle:after {
span.ffz-handle:after { left: 8px }
.ffz-ui-popup.ui-moved span.ffz-handle { width: 24px; cursor: pointer; }
.ui-moved span.ffz-handle { width: 24px; cursor: pointer; }
.ffz-ui-popup.ui-moved span.ffz-handle:before,
.ffz-ui-popup.ui-moved span.ffz-handle:after {
.ui-moved span.ffz-handle:before,
.ui-moved span.ffz-handle:after {
left: 11px;
border-color: #333;
}
.ffz-ui-popup.ui-moved span.ffz-handle:before { transform: rotate(45deg); }
.ffz-ui-popup.ui-moved span.ffz-handle:after { transform: rotate(-45deg); }
.ui-moved span.ffz-handle:before { transform: rotate(45deg); }
.ui-moved span.ffz-handle:after { transform: rotate(-45deg); }
.ffz-dark .ffz-recent-expando span.ffz-handle:before,
.ffz-dark .ffz-recent-expando span.ffz-handle:after,
.app-main.theatre span.ffz-handle:before,
.chat-container.dark span.ffz-handle:before,
.ember-chat-container.dark span.ffz-handle:before,
body.ffz-bttv-dark .ffz-ui-popup span.ffz-handle:before,
body.ffz-bttv-dark span.ffz-handle:before,
.app-main.theatre span.ffz-handle:after,
.chat-container.dark span.ffz-handle:after,
.ember-chat-container.dark span.ffz-handle:after,
body.ffz-bttv-dark .ffz-ui-popup span.ffz-handle:after {
body.ffz-bttv-dark span.ffz-handle:after {
border-color: #666;
}
.app-main.theatre .ffz-ui-popup.ui-moved span.ffz-handle:before,
.chat-container.dark .ffz-ui-popup.ui-moved span.ffz-handle:before,
.ember-chat-container.dark .ffz-ui-popup.ui-moved span.ffz-handle:before,
body.ffz-bttv-dark .ffz-ui-popup.ui-moved span.ffz-handle:before,
.app-main.theatre .ffz-ui-popup.ui-moved span.ffz-handle:after,
.chat-container.dark .ffz-ui-popup.ui-moved span.ffz-handle:after,
.ember-chat-container.dark .ffz-ui-popup.ui-moved span.ffz-handle:after,
body.ffz-bttv-dark .ffz-ui-popup.ui-moved span.ffz-handle:after {
.app-main.theatre .ui-moved span.ffz-handle:before,
.chat-container.dark .ui-moved span.ffz-handle:before,
.ember-chat-container.dark .ui-moved span.ffz-handle:before,
body.ffz-bttv-dark .ui-moved span.ffz-handle:before,
.app-main.theatre .ui-moved span.ffz-handle:after,
.chat-container.dark .ui-moved span.ffz-handle:after,
.ember-chat-container.dark .ui-moved span.ffz-handle:after,
body.ffz-bttv-dark .ui-moved span.ffz-handle:after {
border-color: #d3d3d3;
}
.ffz-recent-expando > span.ffz-handle {
float: left;
margin: -3px 5px -3px -5px;
}
.ffz-ui-popup ul.menu li.title > span.ffz-handle {
float: left;
margin: 5px;
@ -1279,6 +1291,7 @@ body:not(.ffz-bttv) .dropmenu.share { margin-bottom: 0; }
.theatre .conversation-window .conversation-content::-webkit-scrollbar-thumb,
.theatre .conversations-list .conversations-list-inner::-webkit-scrollbar-thumb,
.ffz-dark .chat-history::-webkit-scrollbar-thumb,
.theatre .chat-history::-webkit-scrollbar-thumb,
.theatre .emoticon-selector-box .all-emotes::-webkit-scrollbar-thumb,
.theatre .ffz-ui-menu-page::-webkit-scrollbar-thumb,
@ -1623,8 +1636,10 @@ body:not(.ffz-bttv) .chat-container:not(.chatReplay) .more-messages-indicator {
margin: 10px 0;
}
.ffz-wide-tip hr {
.tipsy-inner hr {
margin: 5px 0;
border-bottom-width: 1px;
border-bottom-style: solid;
}
.ffz-wide-tip .tipsy-inner {
@ -1908,7 +1923,7 @@ th.ffz-row-switch {
}
#ffz-group-tabs .button {
height: 18px;
height: 30px;
padding-bottom: 10px;
margin-bottom: -10px;
margin-right: 4px;
@ -2111,6 +2126,11 @@ body.ffz-minimal-chat-input .ember-chat .chat-interface .textarea-contain textar
overflow-y: auto;
}
.chat-messages .tse-scroll-content,
.chat-history {
will-change: scroll-position, contents;
}
.moderation-card .chat-history.live-history {
max-height: 200px;
}
@ -2487,8 +2507,9 @@ body:not([data-current-path^="user."]) .ffz-sidebar-swap .ember-chat .chat-inter
}
.ffz-no-blue .theme--dark .sc-collapsed-header,
.ffz-no-blue .theme--dark .sc-header { box-shadow: 0 -0.1rem 0 #5c5c5c inset }
.ffz-no-blue .theme--dark .sc-card:hover { box-shadow: -0.1rem 0 0 #414141 inset }
.ffz-no-blue .theme--dark .js-sc-card:hover { box-shadow: -0.1rem 0 0 #414141 inset }
.ffz-no-blue .theme--dark .social-column { box-shadow: -0.1rem 0 0 #2b2b2b inset}
.ffz-no-blue .theme--dark .form__input,
@ -2511,7 +2532,7 @@ body:not([data-current-path^="user."]) .ffz-sidebar-swap .ember-chat .chat-inter
background-color: rgba(25,25,25,.5);
}
.ffz-no-blue .theme--dark .sc-card:hover,
.ffz-no-blue .theme--dark .js-sc-card:hover,
.ffz-no-blue .theme--dark .sc-toggle:hover,
.ffz-no-blue .warp__item a:not(.warp__logo):hover {
background-color: #2b2b2b;
@ -3865,8 +3886,10 @@ div.metadata-box {
.ban-tip { border-bottom: 1px dotted rgba(102,102,102,0.5); }
.ffz-clickable-mentions .ffz-recent-messages .chat-line .user-token,
.ffz-clickable-mentions .pinned-cheers .chat-line .user-token,
.ffz-clickable-mentions .chat-display .chat-line .user-token { font-weight: bold }
.ffz-clickable-mentions .ffz-recent-messages .chat-line .user-token:hover,
.ffz-clickable-mentions .pinned-cheers .chat-line .user-token:hover,
.ffz-clickable-mentions .chat-display .chat-line .user-token:hover {
text-decoration: underline;
@ -4168,6 +4191,100 @@ body.ffz-sidebar-swap .app-main.theatre #main_col:not(.expandRight) #player[data
.itad-balloon table th:not(:first-child),
.itad-balloon table td:not(:first-child) { text-align: right }
.ffz-has-recent-messages .resub-wrap {
padding-top: 30px;
}
.chat-messages[data-pinned_height="30"],
.ffz-has-recent-messages .sticky-message,
.ffz-has-recent-messages .chat-messages {
top: 30px;
}
.chat-messages[data-pinned_height="76"] { top: 76px }
.ffz-has-recent-messages .chat-messages[data-pinned_height="30"] { top: 60px }
.ffz-has-recent-messages .chat-messages[data-pinned_height="76"] { top: 106px }
.ffz-recent-messages {
background-color: #efeef1;
border-bottom: 1px solid #dad8de;
z-index: 1000;
overflow: hidden;
position: absolute !important;
top: 0;
left: 0;
right: 0;
transition: height ease-in-out 100ms;
height: 30px;
box-shadow: 0 10px 5px -3px rgba(239,238,241,0.5);
}
.ffz-recent-messages.ui-moved {
height: auto;
right: auto;
width: 340px;
border: 1px solid #dad8de;
}
.ffz-recent-messages.ui-moved .pill {
display: none;
}
.ffz-recent-messages .ffz-recent-expando {
background-color: #efeef1;
padding: 5px 10px;
border-bottom: 1px solid #dad8de;
color: #333;
cursor: move;
position: relative;
z-index: 1;
}
.ffz-recent-expando .pill {
float: right;
font-size: 100%;
margin-top: 3px;
}
.ffz-recent-messages .chat-history {
top: -150px;
position: relative;
height: 150px;
transition: top ease-in-out 75ms;
}
.ffz-recent-messages:not(.ui-moved):hover {
height: 180px;
}
.ffz-recent-messages.ui-moved .chat-history,
.ffz-recent-messages:not(.ui-moved):hover .chat-history {
top: 0px;
}
.ffz-recent-messages.ui-moved .chat-history {
min-height: 150px;
height: auto;
}
.ffz-dark .ffz-recent-expando,
.theatre .ffz-recent-expando,
.dark .ffz-recent-expando,
.force-dark .ffz-recent-expando {
background-color: #242424;
border-color: #474747;
color: #ccc;
}
.ffz-dark .ffz-recent-messages,
.theatre .ffz-recent-messages,
.dark .ffz-recent-messages,
.force-dark .ffz-recent-messages {
background-color: #191919;
border-color: #474747;
box-shadow: 0 10px 5px -3px rgba(25,25,25,0.5);
}
/*
H O T * G A R B A G E