1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-08-03 08:28:31 +00:00
* Added: Option to hide timestamps from Chat on Videos.
* Added: TwitchCon and Overwatch League badges are now sorted into their own categories for controlling badge visibility.
* Fixed: Automatically exit Picture-in-Picture when entering fullscreen mode.
* Fixed: Do not let users enter Picture-in-Picture when already in fullscreen.
* Fixed: Minimal Navigation not actually sliding the top navigation bar out of view.
This commit is contained in:
SirStendec 2020-01-24 19:02:06 -05:00
parent 829ec35808
commit 2d14c359c9
5 changed files with 82 additions and 16 deletions

View file

@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
"version": "4.17.14",
"version": "4.17.15",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"license": "Apache-2.0",
"scripts": {

View file

@ -247,6 +247,8 @@ export default class Badges extends Module {
getSettingsBadges(include_addons) {
const twitch = [],
owl = [],
tcon = [],
game = [],
ffz = [],
addon = [];
@ -258,7 +260,7 @@ export default class Badges extends Module {
let v = badge && (badge[1] || badge[0]);
for(const key in badge)
if ( has(badge, key) ) {
if ( key !== '__cat' && has(badge, key) ) {
const version = badge[key];
if ( ! v )
v = version;
@ -272,8 +274,18 @@ export default class Badges extends Module {
});
}
if ( v )
(badge.__game ? game : twitch).push({
if ( v ) {
let cat;
if ( badge.__cat === 'm-owl' )
cat = owl;
else if ( badge.__cat === 'm-tcon' )
cat = tcon;
else if ( badge.__cat === 'm-game' )
cat = game;
else
cat = twitch;
cat.push({
id: key,
provider: 'twitch',
name: v.title,
@ -282,6 +294,7 @@ export default class Badges extends Module {
versions: vs,
styleImage: `url("${v.image2x}")`
});
}
}
if ( include_addons )
@ -302,6 +315,8 @@ export default class Badges extends Module {
return [
{title: 'Twitch', id: 'm-twitch', badges: twitch},
{title: 'Twitch: TwitchCon', id: 'm-tcon', badges: tcon},
{title: 'Twitch: Overwatch League', id: 'm-owl', badges: owl},
{title: 'Twitch: Game', id: 'm-game', key: 'game', badges: game},
{title: 'FrankerFaceZ', id: 'm-ffz', badges: ffz},
{title: 'Add-on', id: 'm-addon', badges: addon}
@ -408,11 +423,11 @@ export default class Badges extends Module {
is_colored = badge_style !== 5,
has_image = badge_style !== 3 && badge_style !== 4,
twitch_hidden = hidden_badges['m-twitch'],
game_hidden = hidden_badges['m-game'],
ffz_hidden = hidden_badges['m-ffz'],
addon_hidden = hidden_badges['m-addon'],
tb = this.twitch_badges,
out = [],
slotted = {},
twitch_badges = msg.badges || {},
@ -433,9 +448,10 @@ export default class Badges extends Module {
if ( has(twitch_badges, badge_id) ) {
const version = twitch_badges[badge_id],
is_hidden = hidden_badges[badge_id],
is_game = badge_id.endsWith('_1');
bdata = tb && tb[badge_id],
cat = bdata && bdata.__cat || 'm-twitch';
if ( is_hidden || (is_hidden == null && (is_game ? game_hidden : twitch_hidden)))
if ( is_hidden || (is_hidden == null && hidden_badges[cat]) )
continue;
if ( has(BADGE_POSITIONS, badge_id) )
@ -771,7 +787,9 @@ export default class Badges extends Module {
b = {};
for(const data of badges) {
const sid = data.setID,
bs = b[sid] = b[sid] || {__game: /_\d+$/.test(sid) && ! sid.includes('overwatch') };
bs = b[sid] = b[sid] || {
__cat: getBadgeCategory(sid)
};
this.twitch_badge_count++;
bs[data.version] = data;
@ -864,4 +882,16 @@ export default class Badges extends Module {
else
this.style.delete('twitch-badges');
}
}
function getBadgeCategory(key) {
if ( key.startsWith('overwatch-league') )
return 'm-owl';
else if ( key.startsWith('twitchcon') )
return 'm-tcon';
else if ( /_\d+$/.test(key) )
return 'm-game';
return 'm-twitch';
}

View file

@ -4,6 +4,7 @@
height: 5rem !important;
}
position: relative;
height: 1rem !important;
top: -4rem !important;

View file

@ -759,10 +759,22 @@ export default class Player extends Module {
installVisibilityHook() {
if ( ! document.pictureInPictureEnabled ) {
this.log.info('Skipping visibility hook. Picture-in-Picture is not available.');
this.log.info('Skipping visibility hooks. Picture-in-Picture is not available.');
return;
}
document.addEventListener('fullscreenchange', () => {
const fs = document.fullscreenElement,
pip = document.pictureInPictureElement;
if ( fs && pip && (fs === pip || fs.contains(pip)) )
document.exitPictureInPicture();
// Update the UI since we can't enter PiP from Fullscreen
for(const inst of this.Player.instances)
this.addPiPButton(inst);
});
try {
Object.defineProperty(document, 'hidden', {
configurable: true,
@ -796,6 +808,8 @@ export default class Player extends Module {
addPiPButton(inst, tries = 0) {
const outer = inst.props.containerRef || this.fine.getChildNode(inst),
video = inst.props.mediaPlayerInstance?.mediaSinkManager?.video,
is_fs = video && document.fullscreenElement && document.fullscreenElement.contains(video),
container = outer && outer.querySelector('.player-controls__right-control-group'),
has_pip = document.pictureInPictureEnabled && this.settings.get('player.button.pip');
@ -846,12 +860,17 @@ export default class Player extends Module {
}
const pip_active = !!document.pictureInPictureElement,
label = pip_active ?
this.i18n.t('player.pip_button.off', 'Exit Picture-in-Picture') :
this.i18n.t('player.pip_button', 'Picture-in-Picture');
pip_swap = false, //pip_active && document.pictureInPictureElement !== video,
label = is_fs ?
this.i18n.t('player.pip_button.fs', 'Cannot use Picture-in-Picture when Fullscreen')
: pip_swap ?
this.i18n.t('player.pip_button.swap', 'Switch Picture-in-Picture')
: pip_active ?
this.i18n.t('player.pip_button.off', 'Exit Picture-in-Picture')
: this.i18n.t('player.pip_button', 'Picture-in-Picture');
icon.classList.toggle('ffz-i-t-pip-inactive', ! pip_active);
icon.classList.toggle('ffz-i-t-pip-active', pip_active);
icon.classList.toggle('ffz-i-t-pip-inactive', ! pip_active || pip_swap);
icon.classList.toggle('ffz-i-t-pip-active', pip_active && ! pip_swap);
btn.setAttribute('aria-label', label);
tip.textContent = label;
@ -866,6 +885,9 @@ export default class Player extends Module {
if ( e )
e.preventDefault();
if ( document.fullscreenElement && document.fullscreenElement.contains(video) )
return;
if ( ! video._ffz_pip_enter ) {
video.addEventListener('enterpictureinpicture', video._ffz_pip_enter = () => {
this.addPiPButton(inst);
@ -876,9 +898,11 @@ export default class Player extends Module {
});
}
//const is_this = document.pictureInPictureElement === video;
if ( document.pictureInPictureElement )
document.exitPictureInPicture();
else
//if ( ! is_this )
video.requestPictureInPicture();
}

View file

@ -50,6 +50,15 @@ export default class VideoChatHook extends Module {
// Settings
this.settings.add('chat.video-chat.timestamps', {
default: true,
ui: {
path: 'Chat > Chat on Videos >> Appearance',
title: 'Display timestamps alongside chat messages.',
component: 'setting-check-box'
}
});
this.settings.add('chat.video-chat.enabled', {
default: true,
ui: {
@ -64,6 +73,7 @@ export default class VideoChatHook extends Module {
async onEnable() {
this.chat.context.on('changed:chat.video-chat.enabled', this.updateLines, this);
this.chat.context.on('changed:chat.video-chat.timestamps', this.updateLines, this);
this.on('chat:updated-lines', this.updateLines, this);
this.VideoChatController.on('mount', this.chatMounted, this);
@ -275,6 +285,7 @@ export default class VideoChatHook extends Module {
const context = this.props.messageContext,
msg = t.standardizeMessage(context.comment, context.author),
main_message = this.ffzRenderMessage(msg, context),
hide_timestamps = this.props.hideTimestamp || ! t.chat.context.get('chat.video-chat.timestamps'),
bg_css = msg.mentioned && msg.mention_color ? t.site_chat.inverse_colors.process(msg.mention_color) : null;
@ -288,7 +299,7 @@ export default class VideoChatHook extends Module {
class={`tw-align-items-start tw-flex tw-flex-nowrap tw-full-width tw-pd-l-05 tw-pd-y-05 vod-message${msg.is_sub ? ' ffz-notice-line ffz--subscribe-line' : ''}${msg.highlight ? ' ffz-notice-line ffz--points-line' : ''}${highlight ? ' ffz--points-highlight ffz-custom-color' : ''}${msg.mentioned ? ' ffz-mentioned' : ''}${bg_css ? ' ffz-custom-color' : ''}`}
style={{backgroundColor: bg_css}}
>
{this.props.hideTimestamp || (<div data-test-selector="message-timestamp" class="tw-align-right tw-flex tw-flex-shrink-0 vod-message__header">
{hide_timestamps || (<div data-test-selector="message-timestamp" class="tw-align-right tw-flex tw-flex-shrink-0 vod-message__header">
<div class="tw-mg-r-05">
<div class="tw-inline-flex tw-relative tw-tooltip-wrapper">
<button class="tw-block tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive" onClick={this.onTimestampClickHandler}>