mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-02 16:08:31 +00:00
Add setting to hide live indicator. Fix clicking box-art with channel avatars displayed over thumbnails. Fix width of Chat on Videos with custom chat width. Update hide vodcasts to hide reruns. Fix performance issues and text wrapping in the directory.
This commit is contained in:
parent
8e27f2e6a3
commit
3ca7d1d955
5 changed files with 91 additions and 143 deletions
|
@ -23,6 +23,7 @@ const CLASSES = {
|
||||||
'pinned-cheer': '.pinned-cheer',
|
'pinned-cheer': '.pinned-cheer',
|
||||||
'whispers': '.whispers',
|
'whispers': '.whispers',
|
||||||
|
|
||||||
|
'dir-live-ind': '.live-channel-card:not([data-a-target*="host"]) .stream-type-indicator.stream-type-indicator--live',
|
||||||
'boxart-hover': '.tw-card .tw-full-width:hover a[data-a-target="live-channel-card-game-link"]',
|
'boxart-hover': '.tw-card .tw-full-width:hover a[data-a-target="live-channel-card-game-link"]',
|
||||||
'boxart-hide': '.tw-card a[data-a-target="live-channel-card-game-link"]',
|
'boxart-hide': '.tw-card a[data-a-target="live-channel-card-game-link"]',
|
||||||
'profile-hover-following': '.tw-card .tw-full-width:hover .ffz-channel-avatar',
|
'profile-hover-following': '.tw-card .tw-full-width:hover .ffz-channel-avatar',
|
||||||
|
|
|
@ -10,4 +10,13 @@ body .channel-page__video-player--theatre-mode {
|
||||||
body .video-watch-page__right-column,
|
body .video-watch-page__right-column,
|
||||||
body .channel-page__right-column {
|
body .channel-page__right-column {
|
||||||
width: var(--ffz-chat-width);
|
width: var(--ffz-chat-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
body .video-chat__sync-button {
|
||||||
|
width: calc(var(--ffz-chat-width) - 4rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
body .video-chat {
|
||||||
|
-ms-flex-preferred-size: var(--ffz-chat-width);
|
||||||
|
flex-basis: var(--ffz-chat-width);
|
||||||
}
|
}
|
|
@ -392,114 +392,47 @@ export default class Following extends SiteModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChannelCard(inst) {
|
updateChannelCard(inst) {
|
||||||
this.parent.updateUptime(inst, 'props.viewerCount.createdAt', '.tw-card .tw-aspect > div');
|
|
||||||
|
|
||||||
const container = this.fine.getHostNode(inst),
|
const container = this.fine.getHostNode(inst),
|
||||||
card = container && container.querySelector && container.querySelector('.tw-card');
|
card = container && container.querySelector && container.querySelector('.tw-card');
|
||||||
|
|
||||||
if ( container === null || card === null )
|
if ( ! card )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (inst.props.streamType === 'watch_party')
|
const hosting = inst.props.channelNameLinkTo.state.content === 'live_host' && this.hosts && this.hosts[inst.props.channelName],
|
||||||
|
data = {
|
||||||
|
login: hosting ? this.hosts[inst.props.channelName].channel : inst.props.linkTo.pathname.substr(1),
|
||||||
|
displayName: inst.props.channelName,
|
||||||
|
profileImageURL: inst.props.viewerCount && inst.props.viewerCount.profileImageURL
|
||||||
|
};
|
||||||
|
|
||||||
|
this.parent.updateUptime(inst, 'props.viewerCount.createdAt', '.tw-card .tw-aspect > div');
|
||||||
|
this.parent.addCardAvatar(inst, 'props.viewerCount', '.tw-card', data);
|
||||||
|
|
||||||
|
if (inst.props.streamType === 'rerun')
|
||||||
container.parentElement.classList.toggle('tw-hide', this.settings.get('directory.hide-vodcasts'));
|
container.parentElement.classList.toggle('tw-hide', this.settings.get('directory.hide-vodcasts'));
|
||||||
|
|
||||||
// Remove old elements
|
if ( hosting && this.settings.get('directory.following.group-hosts') ) {
|
||||||
const hiddenBodyCard = card.querySelector('.tw-card-body.tw-hide');
|
const host_data = this.hosts[data.displayName];
|
||||||
if (hiddenBodyCard !== null) hiddenBodyCard.classList.remove('tw-hide');
|
|
||||||
|
|
||||||
const ffzChannelData = card.querySelector('.ffz-channel-data');
|
const title_link = card.querySelector('a[data-a-target="live-channel-card-title-link"]'),
|
||||||
if (ffzChannelData !== null) ffzChannelData.remove();
|
thumbnail_link = card.querySelector('a[data-a-target="live-channel-card-thumbnail-link"]'),
|
||||||
|
card_title = card.querySelector('.live-channel-card__title'),
|
||||||
|
|
||||||
const channelAvatar = card.querySelector('.ffz-channel-avatar');
|
text_content = host_data.channels.length !== 1 ?
|
||||||
if (channelAvatar !== null) channelAvatar.remove();
|
this.i18n.t('host-menu.multiple', '%{count} hosting %{channel}', {
|
||||||
|
count: host_data.channels.length,
|
||||||
|
channel: data.displayName
|
||||||
|
}) : inst.props.title;
|
||||||
|
|
||||||
if (inst.props.viewerCount.profileImageURL) {
|
if ( card_title )
|
||||||
const hosting = inst.props.channelNameLinkTo.state.content === 'live_host' && this.hosts && this.hosts[inst.props.channelName];
|
card_title.textContent = card_title.title = text_content;
|
||||||
let channel, displayName;
|
|
||||||
if (hosting) {
|
|
||||||
channel = this.hosts[inst.props.channelName].channel;
|
|
||||||
displayName = inst.props.channelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const avatarSetting = this.settings.get('directory.show-channel-avatars');
|
if ( title_link )
|
||||||
const cardDiv = card.querySelector('.tw-card-body');
|
title_link.addEventListener('click', this.showHostMenu.bind(this, inst, host_data));
|
||||||
const modifiedDiv = e('div', {
|
|
||||||
innerHTML: cardDiv.innerHTML
|
|
||||||
});
|
|
||||||
|
|
||||||
const broadcasterLogin = inst.props.linkTo.pathname.substring(1);
|
if ( thumbnail_link ) {
|
||||||
modifiedDiv.querySelector('.live-channel-card__channel').onclick = event => {
|
thumbnail_link.title = text_content;
|
||||||
event.preventDefault();
|
thumbnail_link.addEventListener('click', this.showHostMenu.bind(this, inst, host_data));
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
this.router.navigate('user', { userName: broadcasterLogin });
|
|
||||||
};
|
|
||||||
modifiedDiv.querySelector('.live-channel-card__videos').onclick = event => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
this.router.navigate('user-videos', { userName: broadcasterLogin });
|
|
||||||
};
|
|
||||||
|
|
||||||
let avatarDiv;
|
|
||||||
if (avatarSetting === 1) {
|
|
||||||
avatarDiv = e('a', {
|
|
||||||
className: 'ffz-channel-avatar tw-mg-r-05 tw-mg-t-05',
|
|
||||||
href: hosting ? `/${channel}` : inst.props.linkTo.pathname,
|
|
||||||
onclick: event => this.parent.hijackUserClick(event, broadcasterLogin)
|
|
||||||
}, e('img', {
|
|
||||||
title: inst.props.channelName,
|
|
||||||
src: inst.props.viewerCount.profileImageURL
|
|
||||||
}));
|
|
||||||
} else if (avatarSetting === 2 || avatarSetting === 3) {
|
|
||||||
const avatarElement = e('a', {
|
|
||||||
className: 'ffz-channel-avatar',
|
|
||||||
href: hosting ? `/${channel}` : inst.props.linkTo.pathname,
|
|
||||||
onclick: event => this.parent.hijackUserClick(event, broadcasterLogin)
|
|
||||||
}, e('div', 'live-channel-card__boxart tw-bottom-0 tw-absolute',
|
|
||||||
e('figure', 'tw-aspect tw-aspect--align-top',
|
|
||||||
e('img', {
|
|
||||||
title: inst.props.channelName,
|
|
||||||
src: inst.props.viewerCount.profileImageURL
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const divToAppend = card.querySelector('.tw-aspect > div');
|
|
||||||
if (divToAppend.querySelector('.ffz-channel-avatar') === null) divToAppend.appendChild(avatarElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cardDivParent = cardDiv.parentElement;
|
|
||||||
const ffzChannelData = cardDivParent.querySelector('.ffz-channel-data');
|
|
||||||
if (ffzChannelData === null) {
|
|
||||||
cardDiv.classList.add('tw-hide');
|
|
||||||
|
|
||||||
const newCardDiv = e('div', 'ffz-channel-data tw-flex tw-flex-nowrap', [
|
|
||||||
avatarDiv, modifiedDiv
|
|
||||||
]);
|
|
||||||
cardDivParent.appendChild(newCardDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hosting) {
|
|
||||||
const hostObj = this.hosts[displayName];
|
|
||||||
if (this.settings.get('directory.following.group-hosts')) {
|
|
||||||
const titleLink = card.querySelector('.ffz-channel-data a[data-a-target="live-channel-card-title-link"]');
|
|
||||||
const thumbnailLink = card.querySelector('a[data-a-target="live-channel-card-thumbnail-link"]');
|
|
||||||
const channelCardTitle = card.querySelector('.ffz-channel-data .live-channel-card__title');
|
|
||||||
|
|
||||||
const textContent = hostObj.channels.length > 1 ? `${hostObj.channels.length} hosting ${displayName}` : inst.props.title;
|
|
||||||
if (channelCardTitle !== null) {
|
|
||||||
channelCardTitle.textContent
|
|
||||||
= channelCardTitle.title
|
|
||||||
= textContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thumbnailLink !== null) thumbnailLink.title = textContent;
|
|
||||||
|
|
||||||
if (titleLink !== null) titleLink.onclick = this.showHostMenu.bind(this, inst, hostObj);
|
|
||||||
if (thumbnailLink !== null) thumbnailLink.onclick = this.showHostMenu.bind(this, inst, hostObj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,13 +110,24 @@ export default class Directory extends SiteModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.settings.add('directory.hide-live', {
|
||||||
|
default: false,
|
||||||
|
ui: {
|
||||||
|
path: 'Directory > Channels >> Appearance',
|
||||||
|
title: 'Do not show the Live indicator on channels that are live.',
|
||||||
|
component: 'setting-check-box'
|
||||||
|
},
|
||||||
|
|
||||||
|
changed: value => this.css_tweaks.toggleHide('dir-live-ind', value)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
this.settings.add('directory.hide-vodcasts', {
|
this.settings.add('directory.hide-vodcasts', {
|
||||||
default: false,
|
default: false,
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
path: 'Directory > Channels >> Appearance',
|
path: 'Directory > Channels >> Appearance',
|
||||||
title: 'Hide Vodcasts',
|
title: 'Do not show reruns in the directory.',
|
||||||
description: 'Hide vodcasts in the directories.',
|
|
||||||
component: 'setting-check-box'
|
component: 'setting-check-box'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -132,6 +143,7 @@ export default class Directory extends SiteModule {
|
||||||
this.css_tweaks.toggleHide('profile-hover-game', avatars === 2);
|
this.css_tweaks.toggleHide('profile-hover-game', avatars === 2);
|
||||||
this.css_tweaks.toggleHide('profile-hover-following', avatars === 2);
|
this.css_tweaks.toggleHide('profile-hover-following', avatars === 2);
|
||||||
|
|
||||||
|
this.css_tweaks.toggleHide('dir-live-ind', this.settings.get('directory.hide-live'));
|
||||||
this.css_tweaks.toggleHide('boxart-hide', boxart === 0);
|
this.css_tweaks.toggleHide('boxart-hide', boxart === 0);
|
||||||
this.css_tweaks.toggleHide('boxart-hover', boxart === 1);
|
this.css_tweaks.toggleHide('boxart-hover', boxart === 1);
|
||||||
|
|
||||||
|
@ -162,7 +174,7 @@ export default class Directory extends SiteModule {
|
||||||
const hiddenThumbnails = this.settings.provider.get('directory.game.hidden-thumbnails') || [];
|
const hiddenThumbnails = this.settings.provider.get('directory.game.hidden-thumbnails') || [];
|
||||||
const hiddenPreview = 'https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg';
|
const hiddenPreview = 'https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg';
|
||||||
|
|
||||||
if (get('props.streamNode.type', inst) === 'watch_party' || get('props.type', inst) === 'watch_party')
|
if (get('props.streamNode.type', inst) === 'rerun' || get('props.type', inst) === 'rerun')
|
||||||
container.classList.toggle('tw-hide', this.settings.get('directory.hide-vodcasts'));
|
container.classList.toggle('tw-hide', this.settings.get('directory.hide-vodcasts'));
|
||||||
|
|
||||||
const img = container.querySelector && container.querySelector('.tw-card-img img');
|
const img = container.querySelector && container.querySelector('.tw-card-img img');
|
||||||
|
@ -264,59 +276,50 @@ export default class Directory extends SiteModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addCardAvatar(inst, created_path, selector) {
|
addCardAvatar(inst, created_path, selector, data) {
|
||||||
const container = this.fine.getHostNode(inst),
|
const container = this.fine.getHostNode(inst),
|
||||||
card = container && container.querySelector && container.querySelector(selector),
|
card = container && container.querySelector && container.querySelector(selector),
|
||||||
setting = this.settings.get('directory.show-channel-avatars'),
|
setting = this.settings.get('directory.show-channel-avatars');
|
||||||
|
|
||||||
|
if ( ! data )
|
||||||
data = get(created_path, inst);
|
data = get(created_path, inst);
|
||||||
|
|
||||||
if ( ! card )
|
if ( ! card )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Remove old elements
|
// Get the old element.
|
||||||
const hiddenBodyCard = card.querySelector('.tw-card-body.tw-hide');
|
let channel_avatar = card.querySelector('.ffz-channel-avatar');
|
||||||
if (hiddenBodyCard !== null)
|
|
||||||
hiddenBodyCard.classList.remove('tw-hide');
|
|
||||||
|
|
||||||
const ffzChannelData = card.querySelector('.ffz-channel-data');
|
if ( ! data || ! data.profileImageURL || setting === 0 ) {
|
||||||
if (ffzChannelData !== null)
|
if ( channel_avatar !== null )
|
||||||
ffzChannelData.remove();
|
channel_avatar.remove();
|
||||||
|
|
||||||
const channelAvatar = card.querySelector('.ffz-channel-avatar');
|
|
||||||
if (channelAvatar !== null)
|
|
||||||
channelAvatar.remove();
|
|
||||||
|
|
||||||
if ( setting === 0 )
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data) {
|
if ( setting !== inst.ffz_av_setting || data.login !== inst.ffz_av_login || data.profileImageURL !== inst.ffz_av_image ) {
|
||||||
if (setting === 1) {
|
if ( channel_avatar )
|
||||||
const cardDiv = card.querySelector('.tw-card-body');
|
channel_avatar.remove();
|
||||||
const modifiedDiv = e('div', {
|
|
||||||
innerHTML: cardDiv.innerHTML
|
|
||||||
});
|
|
||||||
|
|
||||||
const avatarDiv = e('a', {
|
inst.ffz_av_setting = setting;
|
||||||
className: 'ffz-channel-avatar tw-mg-r-05 tw-mg-t-05',
|
inst.ffz_av_login = data.login;
|
||||||
href: `/${data.login}`,
|
inst.ffz_av_image = data.profileImageURL;
|
||||||
onclick: event => this.hijackUserClick(event, data.login)
|
|
||||||
}, e('img', {
|
|
||||||
title: data.displayName,
|
|
||||||
src: data.profileImageURL
|
|
||||||
}));
|
|
||||||
|
|
||||||
const cardDivParent = cardDiv.parentElement;
|
if ( setting === 1 ) {
|
||||||
|
const body = card.querySelector('.tw-card-body .tw-flex'),
|
||||||
|
avatar = e('a', {
|
||||||
|
className: 'ffz-channel-avatar tw-mg-r-05 tw-mg-t-05',
|
||||||
|
href: `/${data.login}`,
|
||||||
|
title: data.displayName,
|
||||||
|
onclick: event => this.hijackUserClick(event, data.login)
|
||||||
|
}, e('img', {
|
||||||
|
src: data.profileImageURL
|
||||||
|
}));
|
||||||
|
|
||||||
if (cardDivParent.querySelector('.ffz-channel-data') === null) {
|
body.insertBefore(avatar, body.firstElementChild);
|
||||||
cardDiv.classList.add('tw-hide');
|
|
||||||
|
|
||||||
const newCardDiv = e('div', 'ffz-channel-data tw-flex tw-flex-nowrap', [
|
} else if ( setting === 2 || setting === 3 ) {
|
||||||
avatarDiv, modifiedDiv
|
const avatar_el = e('a', {
|
||||||
]);
|
|
||||||
cardDivParent.appendChild(newCardDiv);
|
|
||||||
}
|
|
||||||
} else if (setting === 2 || setting === 3) {
|
|
||||||
const avatarElement = e('a', {
|
|
||||||
className: 'ffz-channel-avatar',
|
className: 'ffz-channel-avatar',
|
||||||
href: `/${data.login}`,
|
href: `/${data.login}`,
|
||||||
onclick: event => this.hijackUserClick(event, data.login)
|
onclick: event => this.hijackUserClick(event, data.login)
|
||||||
|
@ -325,13 +328,12 @@ export default class Directory extends SiteModule {
|
||||||
e('img', {
|
e('img', {
|
||||||
title: data.displayName,
|
title: data.displayName,
|
||||||
src: data.profileImageURL
|
src: data.profileImageURL
|
||||||
})
|
})))
|
||||||
)
|
);
|
||||||
));
|
|
||||||
|
|
||||||
const divToAppend = card.querySelector('figure.tw-aspect');
|
const cont = card.querySelector('figure.tw-aspect > div');
|
||||||
if (divToAppend.querySelector('.ffz-channel-avatar') === null)
|
if ( cont )
|
||||||
divToAppend.appendChild(avatarElement);
|
cont.appendChild(avatar_el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,9 @@ export class Tooltip {
|
||||||
|
|
||||||
arrow.setAttribute('x-arrow', true);
|
arrow.setAttribute('x-arrow', true);
|
||||||
|
|
||||||
|
if ( opts.arrowInner )
|
||||||
|
arrow.appendChild(e('div', opts.arrowInner));
|
||||||
|
|
||||||
if ( tip.add_class ) {
|
if ( tip.add_class ) {
|
||||||
inner.classList.add(tip.add_class);
|
inner.classList.add(tip.add_class);
|
||||||
tip.add_class = undefined;
|
tip.add_class = undefined;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue