mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-06-27 21:05:53 +00:00
4.20.8
* Added: Option to only hide side navigation when the page is in portrait mode. * Added: Option to reveal hidden thumbnails after a short delay. * Changed: Hidden thumbnails are now blurred by default, rather than replaced with a generic live thumbnail. * Fixed: Directory features. * Fixed: Position of theater metadata when in portrait mode.
This commit is contained in:
parent
22fd300b28
commit
0003e6e96d
22 changed files with 272 additions and 547 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "frankerfacez",
|
||||
"author": "Dan Salvato LLC",
|
||||
"version": "4.20.7",
|
||||
"version": "4.20.8",
|
||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
|
|
|
@ -37,11 +37,11 @@ export default class Channel extends Module {
|
|||
}
|
||||
});
|
||||
|
||||
this.SideNav = this.elemental.define(
|
||||
/*this.SideNav = this.elemental.define(
|
||||
'side-nav', '.side-bar-contents .side-nav-section:first-child',
|
||||
null,
|
||||
{childNodes: true, subtree: true}, 1
|
||||
);
|
||||
);*/
|
||||
|
||||
this.ChannelRoot = this.elemental.define(
|
||||
'channel-root', '.channel-root',
|
||||
|
@ -59,9 +59,9 @@ export default class Channel extends Module {
|
|||
onEnable() {
|
||||
this.updateChannelColor();
|
||||
|
||||
this.SideNav.on('mount', this.updateHidden, this);
|
||||
this.SideNav.on('mutate', this.updateHidden, this);
|
||||
this.SideNav.each(el => this.updateHidden(el));
|
||||
//this.SideNav.on('mount', this.updateHidden, this);
|
||||
//this.SideNav.on('mutate', this.updateHidden, this);
|
||||
//this.SideNav.each(el => this.updateHidden(el));
|
||||
|
||||
this.ChannelRoot.on('mount', this.updateRoot, this);
|
||||
this.ChannelRoot.on('mutate', this.updateRoot, this);
|
||||
|
@ -88,7 +88,7 @@ export default class Channel extends Module {
|
|||
}
|
||||
}
|
||||
|
||||
updateHidden(el) { // eslint-disable-line class-methods-use-this
|
||||
/*updateHidden(el) { // eslint-disable-line class-methods-use-this
|
||||
if ( ! el._ffz_raf )
|
||||
el._ffz_raf = requestAnimationFrame(() => {
|
||||
el._ffz_raf = null;
|
||||
|
@ -102,7 +102,7 @@ export default class Channel extends Module {
|
|||
|
||||
}
|
||||
});
|
||||
}
|
||||
}*/
|
||||
|
||||
updateSubscription(login) {
|
||||
if ( this._subbed_login === login )
|
||||
|
|
|
@ -18,7 +18,7 @@ const CLASSES = {
|
|||
'side-friends': '.side-nav .online-friends',
|
||||
'side-closed-friends': '.side-nav--collapsed .online-friends',
|
||||
'side-closed-rec-channels': '.side-nav--collapsed .recommended-channels,.side-nav--collapsed .side-nav-section + .side-nav-section:not(.online-friends)',
|
||||
'side-offline-channels': '.side-nav-card.ffz--offline-side-nav',
|
||||
'side-offline-channels': '.ffz--side-nav-card-offline',
|
||||
'side-rerun-channels': '.side-nav .ffz--side-nav-card-rerun',
|
||||
|
||||
'community-highlights': '.community-highlight-stack__card',
|
||||
|
@ -34,7 +34,7 @@ const CLASSES = {
|
|||
'pinned-cheer': '.pinned-cheer,.pinned-cheer-v2,.channel-leaderboard',
|
||||
'whispers': 'body .whispers-open-threads,.tw-core-button[data-a-target="whisper-box-button"]',
|
||||
|
||||
'dir-live-ind': '.preview-card[data-ffz-type="live"] .tw-channel-status-text-indicator,.live-channel-card:not([data-a-target*="host"]) .stream-type-indicator.stream-type-indicator--live,.stream-thumbnail__card .stream-type-indicator.stream-type-indicator--live,.preview-card .stream-type-indicator.stream-type-indicator--live,.preview-card .preview-card-stat.preview-card-stat--live',
|
||||
'dir-live-ind': '.live-channel-card[data-ffz-type="live"] .tw-channel-status-text-indicator, article[data-ffz-type="live"] .tw-channel-status-text-indicator',
|
||||
'profile-hover': '.preview-card .tw-relative:hover .ffz-channel-avatar',
|
||||
'not-live-bar': 'div[data-test-selector="non-live-video-banner-layout"]',
|
||||
'channel-live-ind': '.channel-header__user .tw-channel-status-text-indicator,.channel-info-content .user-avatar-animated__live',
|
||||
|
@ -111,14 +111,28 @@ export default class CSSTweaks extends Module {
|
|||
});
|
||||
|
||||
this.settings.add('layout.side-nav.show', {
|
||||
default: true,
|
||||
default: 1,
|
||||
requires: ['layout.use-portrait'],
|
||||
process(ctx, val) {
|
||||
if ( val === 2 )
|
||||
return ! ctx.get('layout.use-portrait');
|
||||
|
||||
return val;
|
||||
},
|
||||
|
||||
ui: {
|
||||
sort: -1,
|
||||
path: 'Appearance > Layout >> Side Navigation',
|
||||
title: 'Display Side Navigation',
|
||||
|
||||
component: 'setting-check-box'
|
||||
component: 'setting-select-box',
|
||||
data: [
|
||||
{value: 0, title: 'Never'},
|
||||
{value: 1, title: 'Always'},
|
||||
{value: 2, title: 'Hide in Portrait'}
|
||||
]
|
||||
},
|
||||
|
||||
changed: val => this.toggle('hide-side-nav', !val)
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.ffz-hide-thumbnail h3 {
|
||||
filter: blur(0.5rem);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
.ffz-hide-thumbnail a[data-a-target="preview-card-image-link"] {
|
||||
.tw-aspect {
|
||||
&:before {
|
||||
content: '';
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url("https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
img {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
.ffz-hide-thumbnail:hover {
|
||||
.tw-aspect:before {
|
||||
transition: opacity 0.2s;
|
||||
transition-delay: 1s;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
img {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
img,h3 {
|
||||
transition: opacity 0.2s, filter 0.2s;
|
||||
transition-delay: 1s;
|
||||
filter: blur(0) !important;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
.channel-root__scroll-area--theatre-mode .channel-info-bar {
|
||||
bottom: calc(10rem + var(--ffz-chat-height)) !important;
|
||||
.channel-root__scroll-area--theatre-mode {
|
||||
.channel-info-content > div:first-child {
|
||||
right: 40rem !important;
|
||||
bottom: calc(10rem + var(--ffz-chat-height)) !important;
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
fragment browsePagePopularStreamsWithTagsEdge on StreamEdge {
|
||||
node {
|
||||
createdAt
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
// Directory (Following, for now)
|
||||
// ============================================================================
|
||||
|
||||
import {SiteModule} from 'utilities/module';
|
||||
import {get} from 'utilities/object';
|
||||
|
||||
import BROWSE_POPULAR from './browse_popular.gql';
|
||||
|
||||
export default class BrowsePopular extends SiteModule {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.inject('site.apollo');
|
||||
this.inject('site.fine');
|
||||
this.inject('settings');
|
||||
|
||||
this.apollo.registerModifier('BrowsePage_Popular', BROWSE_POPULAR);
|
||||
this.apollo.registerModifier('BrowsePage_Popular', res => this.modifyStreams(res), false);
|
||||
}
|
||||
|
||||
/*onEnable() {
|
||||
// Popular Directory Channel Cards
|
||||
this.apollo.ensureQuery(
|
||||
'BrowsePage_Popular',
|
||||
'data.streams.edges.0.node.createdAt'
|
||||
);
|
||||
}*/
|
||||
|
||||
modifyStreams(res) { // eslint-disable-line class-methods-use-this
|
||||
const edges = get('data.streams.edges', res);
|
||||
if ( ! edges || ! edges.length )
|
||||
return res;
|
||||
|
||||
res.data.streams.edges = this.parent.processNodes(edges);
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
query FollowedChannels_RENAME2 {
|
||||
currentUser {
|
||||
follows {
|
||||
edges {
|
||||
node {
|
||||
stream {
|
||||
createdAt
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
followedLiveUsers {
|
||||
nodes {
|
||||
stream {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
query FollowingHosts_CurrentUser {
|
||||
currentUser {
|
||||
followedHosts {
|
||||
nodes {
|
||||
profileImageURL(width: 50)
|
||||
hosting {
|
||||
stream {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
query FollowedIndex_CurrentUser {
|
||||
currentUser {
|
||||
followedLiveUsers {
|
||||
nodes {
|
||||
stream {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
followedHosts {
|
||||
nodes {
|
||||
profileImageURL(width: 50)
|
||||
hosting {
|
||||
stream {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
query FollowingLive_CurrentUser {
|
||||
currentUser {
|
||||
followedLiveUsers {
|
||||
edges {
|
||||
node {
|
||||
stream {
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,13 +11,6 @@ import {get} from 'utilities/object';
|
|||
import Popper from 'popper.js';
|
||||
import {makeReference} from 'utilities/tooltip';
|
||||
|
||||
/*import FOLLOWED_INDEX from './followed_index.gql';
|
||||
import FOLLOWED_HOSTS from './followed_hosts.gql';
|
||||
import FOLLOWED_CHANNELS from './followed_channels.gql';
|
||||
import FOLLOWED_LIVE from './followed_live.gql';
|
||||
import SUBSCRIBED_CHANNELS from './sidenav_subscribed.gql';
|
||||
import RECOMMENDED_CHANNELS from './recommended_channels.gql';*/
|
||||
|
||||
export default class Following extends SiteModule {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
@ -66,39 +59,6 @@ export default class Following extends SiteModule {
|
|||
changed: () => this.parent.DirectoryCard.forceUpdate()
|
||||
});
|
||||
|
||||
/*this.apollo.registerModifier('FollowedChannels_RENAME2', FOLLOWED_CHANNELS);
|
||||
this.apollo.registerModifier('SideNav_SubscribedChannels', SUBSCRIBED_CHANNELS);
|
||||
this.apollo.registerModifier('RecommendedChannels', RECOMMENDED_CHANNELS);
|
||||
|
||||
this.apollo.registerModifier('FollowedIndex_CurrentUser', FOLLOWED_INDEX);
|
||||
this.apollo.registerModifier('FollowingLive_CurrentUser', FOLLOWED_LIVE);
|
||||
this.apollo.registerModifier('FollowingHosts_CurrentUser', FOLLOWED_HOSTS);
|
||||
|
||||
this.apollo.registerModifier('FollowedChannels_RENAME2', res => this.modifyLiveUsers(res), false);
|
||||
this.apollo.registerModifier('SideNav_SubscribedChannels', res => this.modifyLiveUsers(res, 'subscribedChannels'), false);
|
||||
this.apollo.registerModifier('RecommendedChannels', res => this.modifyLiveUsers(res, 'recommendations.liveRecommendations'), false);
|
||||
|
||||
this.apollo.registerModifier('FollowingLive_CurrentUser', res => this.modifyLiveUsers(res), false);
|
||||
this.apollo.registerModifier('FollowingHosts_CurrentUser', res => this.modifyLiveHosts(res), false);
|
||||
this.apollo.registerModifier('FollowedIndex_CurrentUser', res => {
|
||||
this.modifyLiveUsers(res);
|
||||
this.modifyLiveHosts(res);
|
||||
}, false);
|
||||
|
||||
this.apollo.registerModifier('Shelves', res => {
|
||||
const shelves = get('data.shelves.edges', res);
|
||||
if ( ! Array.isArray(shelves) )
|
||||
return;
|
||||
|
||||
for(const shelf of shelves) {
|
||||
const edges = get('node.content.edges', shelf);
|
||||
if ( ! Array.isArray(edges) )
|
||||
continue;
|
||||
|
||||
shelf.node.content.edges = this.parent.processNodes(edges);
|
||||
}
|
||||
}, false);*/
|
||||
|
||||
this.hosts = new WeakMap;
|
||||
}
|
||||
|
||||
|
@ -169,51 +129,7 @@ export default class Following extends SiteModule {
|
|||
return res;
|
||||
}
|
||||
|
||||
ensureQueries () {
|
||||
/*this.apollo.ensureQuery(
|
||||
'FollowedChannels_RENAME2',
|
||||
'data.currentUser.followedLiveUsers.nodes.0.stream.createdAt'
|
||||
);
|
||||
|
||||
this.apollo.ensureQuery(
|
||||
'SideNav_SubscribedChannels',
|
||||
'data.currentUser.subscribedChannels.edges.0.node.stream.createdAt'
|
||||
);
|
||||
|
||||
this.apollo.ensureQuery(
|
||||
'RecommendedChannels',
|
||||
'data.currentUser.recommendations.liveRecommendations.nodes.0.createdAt'
|
||||
);*/
|
||||
|
||||
/*if ( this.router.current_name !== 'dir-following' )
|
||||
return;
|
||||
|
||||
const bit = this.router.match[1];
|
||||
|
||||
if ( ! bit )
|
||||
this.apollo.ensureQuery(
|
||||
'FollowedIndex_CurrentUser',
|
||||
n =>
|
||||
get('data.currentUser.followedLiveUsers.nodes.0.stream.createdAt', n) !== undefined ||
|
||||
get('data.currentUser.followedHosts.nodes.0.hosting.stream.createdAt', n) !== undefined
|
||||
);
|
||||
|
||||
/*else if ( bit === 'live' )
|
||||
this.apollo.ensureQuery(
|
||||
'FollowingLive_CurrentUser',
|
||||
'data.currentUser.followedLiveUsers.nodes.0.stream.createdAt'
|
||||
);*/
|
||||
|
||||
/*else if ( bit === 'hosts' )
|
||||
this.apollo.ensureQuery(
|
||||
'FollowingHosts_CurrentUser',
|
||||
'data.currentUser.followedHosts.nodes.0.hosting.stream.createdAt'
|
||||
);*/
|
||||
}
|
||||
|
||||
onEnable() {
|
||||
this.ensureQueries();
|
||||
|
||||
document.body.addEventListener('click', this.destroyHostMenu.bind(this));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
fragment directoryPageGameStreamWithTagsEdge on StreamEdge {
|
||||
node {
|
||||
createdAt
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import {SiteModule} from 'utilities/module';
|
|||
import {createElement} from 'utilities/dom';
|
||||
import { get } from 'utilities/object';
|
||||
|
||||
//import GAME_QUERY from './game.gql';
|
||||
|
||||
export default class Game extends SiteModule {
|
||||
constructor(...args) {
|
||||
|
@ -17,7 +16,6 @@ export default class Game extends SiteModule {
|
|||
this.inject('site.fine');
|
||||
this.inject('site.apollo');
|
||||
|
||||
//this.inject('metadata');
|
||||
this.inject('i18n');
|
||||
this.inject('settings');
|
||||
|
||||
|
@ -26,28 +24,8 @@ export default class Game extends SiteModule {
|
|||
n => n.props && n.props.data && n.getBannerImage && n.getFollowButton,
|
||||
['dir-game-index', 'dir-community', 'dir-game-videos', 'dir-game-clips', 'dir-game-details']
|
||||
);
|
||||
|
||||
/*this.apollo.registerModifier('DirectoryPage_Game', GAME_QUERY);
|
||||
this.apollo.registerModifier('DirectoryPage_Game', res => {
|
||||
/*setTimeout(() =>
|
||||
this.apollo.ensureQuery(
|
||||
'DirectoryPage_Game',
|
||||
'data.game.streams.edges.0.node.createdAt'
|
||||
), 500);* /
|
||||
|
||||
this.modifyStreams(res);
|
||||
}, false);*/
|
||||
}
|
||||
|
||||
/*modifyStreams(res) { // eslint-disable-line class-methods-use-this
|
||||
const edges = get('data.game.streams.edges', res);
|
||||
if ( ! edges || ! edges.length )
|
||||
return res;
|
||||
|
||||
res.data.game.streams.edges = this.parent.processNodes(edges, true);
|
||||
return res;
|
||||
}*/
|
||||
|
||||
onEnable() {
|
||||
this.GameHeader.on('mount', this.updateGameHeader, this);
|
||||
this.GameHeader.on('update', this.updateGameHeader, this);
|
||||
|
@ -149,67 +127,8 @@ export default class Game extends SiteModule {
|
|||
values.splice(idx, 1);
|
||||
|
||||
this.settings.provider.set(setting, values);
|
||||
this.parent.DirectoryCard.forceUpdate();
|
||||
this.parent.updateCards();
|
||||
update_func();
|
||||
}
|
||||
}
|
||||
|
||||
/*unmountGameHeader(inst) { // eslint-disable-line class-methods-use-this
|
||||
const timers = inst._ffz_meta_timers;
|
||||
if ( timers )
|
||||
for(const key in timers)
|
||||
if ( timers[key] )
|
||||
clearTimeout(timers[key]);
|
||||
}
|
||||
|
||||
|
||||
updateGameHeader(inst) {
|
||||
this.updateMetadata(inst);
|
||||
}
|
||||
|
||||
updateMetadata(inst, keys) {
|
||||
const container = this.fine.getChildNode(inst),
|
||||
wrapper = container && container.querySelector && container.querySelector('.side-nav-directory-info__info-wrapper > div + div');
|
||||
|
||||
if ( ! inst._ffz_mounted || ! wrapper )
|
||||
return;
|
||||
|
||||
const metabar = wrapper;
|
||||
|
||||
if ( ! keys )
|
||||
keys = this.metadata.keys;
|
||||
else if ( ! Array.isArray(keys) )
|
||||
keys = [keys];
|
||||
|
||||
const timers = inst._ffz_meta_timers = inst._ffz_meta_timers || {},
|
||||
refresh_func = key => this.updateMetadata(inst, key),
|
||||
data = {
|
||||
directory: inst.props.data.directory,
|
||||
type: inst.props.directoryType,
|
||||
name: inst.props.directoryName,
|
||||
|
||||
_mt: 'directory',
|
||||
_inst: inst
|
||||
}
|
||||
|
||||
for(const key of keys)
|
||||
this.metadata.render(key, data, metabar, timers, refresh_func);
|
||||
}
|
||||
|
||||
generateClickHandler(setting) {
|
||||
return (data, event, update_func) => {
|
||||
const values = this.settings.provider.get(setting, []),
|
||||
game = data.name,
|
||||
idx = values.indexOf(game);
|
||||
|
||||
if ( idx === -1 )
|
||||
values.push(game)
|
||||
else
|
||||
values.splice(idx, 1);
|
||||
|
||||
this.settings.provider.set(setting, values);
|
||||
this.parent.DirectoryCard.forceUpdate();
|
||||
update_func();
|
||||
}
|
||||
}*/
|
||||
}
|
|
@ -9,10 +9,7 @@ import {duration_to_string} from 'utilities/time';
|
|||
import {createElement} from 'utilities/dom';
|
||||
import {get} from 'utilities/object';
|
||||
|
||||
import Following from './following';
|
||||
import Game from './game';
|
||||
//import BrowsePopular from './browse_popular';
|
||||
|
||||
|
||||
export const CARD_CONTEXTS = ((e ={}) => {
|
||||
e[e.SingleGameList = 1] = 'SingleGameList';
|
||||
|
@ -33,24 +30,21 @@ export default class Directory extends SiteModule {
|
|||
|
||||
this.should_enable = true;
|
||||
|
||||
this.inject('site.elemental');
|
||||
this.inject('site.fine');
|
||||
this.inject('site.router');
|
||||
this.inject('site.apollo');
|
||||
this.inject('site.css_tweaks');
|
||||
this.inject('site.web_munch');
|
||||
this.inject('site.twitch_data');
|
||||
|
||||
this.inject('i18n');
|
||||
this.inject('settings');
|
||||
|
||||
this.inject(Following);
|
||||
//this.inject(Following);
|
||||
this.inject(Game);
|
||||
//this.inject(BrowsePopular);
|
||||
|
||||
this.DirectoryCard = this.fine.define(
|
||||
'directory-card',
|
||||
n => n.renderTitles && n.renderIconicImage,
|
||||
DIR_ROUTES
|
||||
this.DirectoryCard = this.elemental.define(
|
||||
'directory-card', '.live-channel-card,article[data-a-target^="followed-vod-"],article[data-a-target^="card-"],div[data-a-target^="video-tower-card-"] article,div[data-a-target^="clips-card-"] article,.shelf-card__impression-wrapper article',
|
||||
DIR_ROUTES, null, 0, 0
|
||||
);
|
||||
|
||||
this.DirectoryShelf = this.fine.define(
|
||||
|
@ -59,23 +53,47 @@ export default class Directory extends SiteModule {
|
|||
DIR_ROUTES
|
||||
);
|
||||
|
||||
this.DirectorySuggestedVideos = this.fine.define(
|
||||
'directory-suggested-videos',
|
||||
n => n.props && n.props.directoryWidth && n.props.data && n.render && n.render.toString().includes('SuggestedVideos'),
|
||||
DIR_ROUTES
|
||||
);
|
||||
|
||||
this.DirectoryLatestVideos = this.fine.define(
|
||||
'directory-latest-videos',
|
||||
n => n.props && n.props.component === 'LatestVideosFromFollowedCarousel',
|
||||
DIR_ROUTES
|
||||
);
|
||||
this.settings.add('directory.hidden.style', {
|
||||
default: 2,
|
||||
|
||||
ui: {
|
||||
path: 'Directory > Channels >> Blocked and Hidden Categories',
|
||||
title: 'Hidden Style',
|
||||
component: 'setting-select-box',
|
||||
|
||||
data: [
|
||||
{value: 0, title: 'Replace Image'},
|
||||
{value: 1, title: 'Replace Image and Blur Title'},
|
||||
{value: 2, title: 'Blur Image'},
|
||||
{value: 3, title: 'Blur Image and Title'}
|
||||
]
|
||||
},
|
||||
|
||||
changed: val => {
|
||||
this.css_tweaks.toggle('dir-no-blur', val < 2);
|
||||
this.css_tweaks.toggle('dir-blur-title', val === 1 || val === 3);
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('directory.hidden.reveal', {
|
||||
default: false,
|
||||
|
||||
ui: {
|
||||
path: 'Directory > Channels >> Blocked and Hidden Categories',
|
||||
title: 'Reveal hidden entries on mouse hover.',
|
||||
component: 'setting-check-box'
|
||||
},
|
||||
|
||||
changed: val => this.css_tweaks.toggle('dir-reveal', val)
|
||||
});
|
||||
|
||||
|
||||
this.settings.add('directory.uptime', {
|
||||
default: 1,
|
||||
|
||||
ui: {
|
||||
path: 'Directory > Channels @{"description": "**Note:** These settings do not currently work due to changes made by Twitch to how the directory works."} >> Appearance',
|
||||
path: 'Directory > Channels >> Appearance',
|
||||
title: 'Stream Uptime',
|
||||
description: 'Display the stream uptime on the channel cards.',
|
||||
component: 'setting-select-box',
|
||||
|
@ -87,11 +105,11 @@ export default class Directory extends SiteModule {
|
|||
]
|
||||
},
|
||||
|
||||
changed: () => this.DirectoryCard.forceUpdate()
|
||||
changed: () => this.updateCards()
|
||||
});
|
||||
|
||||
|
||||
this.settings.add('directory.show-channel-avatars', {
|
||||
/*this.settings.add('directory.show-channel-avatars', {
|
||||
default: true,
|
||||
|
||||
ui: {
|
||||
|
@ -100,8 +118,8 @@ export default class Directory extends SiteModule {
|
|||
component: 'setting-check-box'
|
||||
},
|
||||
|
||||
changed: () => this.DirectoryCard.forceUpdate()
|
||||
});
|
||||
changed: () => this.updateCards()
|
||||
});*/
|
||||
|
||||
|
||||
this.settings.add('directory.hide-live', {
|
||||
|
@ -125,12 +143,7 @@ export default class Directory extends SiteModule {
|
|||
component: 'setting-check-box'
|
||||
},
|
||||
|
||||
changed: () => {
|
||||
//this.DirectoryCard.forceUpdate();
|
||||
|
||||
for(const inst of this.DirectoryCard.instances)
|
||||
this.updateCard(inst);
|
||||
}
|
||||
changed: () => this.updateCards()
|
||||
});
|
||||
|
||||
this.settings.add('directory.hide-recommended', {
|
||||
|
@ -144,7 +157,7 @@ export default class Directory extends SiteModule {
|
|||
changed: () => this.DirectoryShelf.forceUpdate()
|
||||
});
|
||||
|
||||
this.settings.add('directory.hide-viewing-history', {
|
||||
/*this.settings.add('directory.hide-viewing-history', {
|
||||
default: false,
|
||||
ui: {
|
||||
path: 'Directory > Following >> Categories',
|
||||
|
@ -164,22 +177,30 @@ export default class Directory extends SiteModule {
|
|||
},
|
||||
|
||||
changed: () => this.DirectoryLatestVideos.forceUpdate()
|
||||
});
|
||||
});*/
|
||||
|
||||
this.routeClick = this.routeClick.bind(this);
|
||||
}
|
||||
|
||||
|
||||
async onEnable() {
|
||||
onEnable() {
|
||||
this.css_tweaks.toggleHide('profile-hover', this.settings.get('directory.show-channel-avatars') === 2);
|
||||
this.css_tweaks.toggleHide('dir-live-ind', this.settings.get('directory.hide-live'));
|
||||
this.css_tweaks.toggle('dir-reveal', this.settings.get('directory.hidden.reveal'));
|
||||
|
||||
this.on('i18n:update', () => this.DirectoryCard.forceUpdate());
|
||||
const blur = this.settings.get('directory.hidden.style');
|
||||
|
||||
const t = this,
|
||||
React = await this.web_munch.findModule('react');
|
||||
this.css_tweaks.toggle('dir-no-blur', blur < 2);
|
||||
this.css_tweaks.toggle('dir-blur-title', blur === 1 || blur === 3);
|
||||
|
||||
const createElement = React && React.createElement;
|
||||
this.on('i18n:update', () => this.updateCards());
|
||||
|
||||
this.DirectoryCard.on('mount', this.updateCard, this);
|
||||
this.DirectoryCard.on('mutate', this.updateCard, this);
|
||||
this.DirectoryCard.on('unmount', this.clearCard, this);
|
||||
this.DirectoryCard.each(el => this.updateCard(el));
|
||||
|
||||
const t = this;
|
||||
|
||||
this.DirectoryShelf.ready(cls => {
|
||||
const old_render = cls.prototype.render;
|
||||
|
@ -201,44 +222,7 @@ export default class Directory extends SiteModule {
|
|||
this.DirectoryShelf.forceUpdate();
|
||||
});
|
||||
|
||||
this.DirectorySuggestedVideos.ready(cls => {
|
||||
const old_render = cls.prototype.render;
|
||||
cls.prototype.render = function() {
|
||||
try {
|
||||
if ( t.settings.get('directory.hide-viewing-history') )
|
||||
return null;
|
||||
|
||||
} catch(err) {
|
||||
t.log.capture(err);
|
||||
}
|
||||
|
||||
return old_render.call(this);
|
||||
}
|
||||
|
||||
this.DirectorySuggestedVideos.forceUpdate();
|
||||
});
|
||||
|
||||
this.DirectoryLatestVideos.ready(cls => {
|
||||
const old_render = cls.prototype.render;
|
||||
cls.prototype.render = function() {
|
||||
if ( ! this.props || this.props.component !== 'LatestVideosFromFollowedCarousel' )
|
||||
return old_render.call(this);
|
||||
|
||||
try {
|
||||
if ( t.settings.get('directory.hide-latest-videos') )
|
||||
return null;
|
||||
|
||||
} catch(err) {
|
||||
t.log.capture(err);
|
||||
}
|
||||
|
||||
return old_render.call(this);
|
||||
}
|
||||
|
||||
this.DirectoryLatestVideos.forceUpdate();
|
||||
});
|
||||
|
||||
this.DirectoryCard.ready((cls, instances) => {
|
||||
/*this.DirectoryCard.ready((cls, instances) => {
|
||||
//const old_render = cls.prototype.render,
|
||||
const old_render_iconic = cls.prototype.renderIconicImage,
|
||||
old_render_titles = cls.prototype.renderTitles;
|
||||
|
@ -248,7 +232,7 @@ export default class Directory extends SiteModule {
|
|||
return null;
|
||||
|
||||
return old_render.call(this);
|
||||
}*/
|
||||
}*
|
||||
|
||||
cls.prototype.renderIconicImage = function() {
|
||||
if ( this.props.context !== CARD_CONTEXTS.SingleChannelList &&
|
||||
|
@ -308,89 +292,127 @@ export default class Directory extends SiteModule {
|
|||
|
||||
this.DirectoryCard.forceUpdate();
|
||||
|
||||
// Game Directory Channel Cards
|
||||
// TODO: Better query handling.
|
||||
/*this.apollo.ensureQuery(
|
||||
'DirectoryPage_Game',
|
||||
'data.game.streams.edges.0.node.createdAt'
|
||||
);*/
|
||||
|
||||
for(const inst of instances)
|
||||
this.updateCard(inst);
|
||||
});
|
||||
|
||||
this.DirectoryCard.on('update', this.updateCard, this);
|
||||
this.DirectoryCard.on('mount', this.updateCard, this);
|
||||
this.DirectoryCard.on('unmount', this.clearCard, this);
|
||||
|
||||
// TODO: Queries
|
||||
this.DirectoryCard.on('unmount', this.clearCard, this);*/
|
||||
}
|
||||
|
||||
|
||||
updateCard(inst) {
|
||||
const container = this.fine.getChildNode(inst);
|
||||
if ( ! container )
|
||||
|
||||
updateCard(el) {
|
||||
const react = this.fine.getReactInstance(el);
|
||||
if ( ! react )
|
||||
return;
|
||||
|
||||
const props = inst.props,
|
||||
game = props.gameTitle || props.playerMetadataGame || (props.trackingProps && props.trackingProps.categoryName);
|
||||
let props = react.child?.memoizedProps;
|
||||
if ( ! props?.channelLogin )
|
||||
props = react.return?.stateNode?.props;
|
||||
|
||||
container.classList.toggle('ffz-hide-thumbnail', this.settings.provider.get('directory.game.hidden-thumbnails', []).includes(game));
|
||||
container.dataset.ffzType = props.streamType;
|
||||
if ( ! props?.channelLogin )
|
||||
props = react.return?.return?.return?.memoizedProps;
|
||||
|
||||
if ( ! props?.channelLogin )
|
||||
return;
|
||||
|
||||
const game = props.gameTitle || props.trackingProps?.categoryName;
|
||||
|
||||
el.classList.toggle('ffz-hide-thumbnail', this.settings.provider.get('directory.game.hidden-thumbnails', []).includes(game));
|
||||
el.dataset.ffzType = props.streamType;
|
||||
|
||||
const should_hide = (props.streamType === 'rerun' && this.settings.get('directory.hide-vodcasts')) ||
|
||||
(props.context !== CARD_CONTEXTS.SingleGameList && this.settings.provider.get('directory.game.blocked-games', []).includes(game));
|
||||
|
||||
let hide_container = container.closest('.stream-thumbnail,[style*="order:"]');
|
||||
(props.context != null && props.context !== CARD_CONTEXTS.SingleGameList && this.settings.provider.get('directory.game.blocked-games', []).includes(game));
|
||||
|
||||
let hide_container = el.closest('.tw-tower > div');
|
||||
if ( ! hide_container )
|
||||
hide_container = container.closest('.tw-mg-b-2');
|
||||
hide_container = el;
|
||||
|
||||
if ( ! hide_container )
|
||||
hide_container = container;
|
||||
|
||||
if ( hide_container.querySelectorAll('.preview-card').length < 2 )
|
||||
if ( hide_container.querySelectorAll('a[data-a-target="preview-card-image-link"]').length < 2 )
|
||||
hide_container.classList.toggle('tw-hide', should_hide);
|
||||
|
||||
//this.log.info('Card Update', inst.props.channelDisplayName, is_video ? 'Video' : 'Live', is_host ? 'Host' : 'Not-Host', inst);
|
||||
|
||||
this.updateUptime(inst, 'props.currentViewerCount.createdAt');
|
||||
this.updateAvatar(inst);
|
||||
this.following.updateChannelCard(inst);
|
||||
this.updateUptime(el, props);
|
||||
}
|
||||
|
||||
|
||||
clearCard(inst) {
|
||||
this.clearUptime(inst);
|
||||
updateCards() {
|
||||
this.DirectoryCard.each(el => this.updateCard(el));
|
||||
|
||||
this.emit(':update-cards');
|
||||
}
|
||||
|
||||
clearCard(el) {
|
||||
this.clearUptime(el);
|
||||
}
|
||||
|
||||
|
||||
processNodes(edges, is_game_query = false, blocked_games) {
|
||||
const out = [];
|
||||
updateUptime(el, props) {
|
||||
if ( ! document.contains(el) )
|
||||
return this.clearUptime(el);
|
||||
|
||||
if ( ! Array.isArray(blocked_games) )
|
||||
blocked_games = this.settings.provider.get('directory.game.blocked-games', []);
|
||||
const container = el.querySelector('.tw-media-card-image__corners'),
|
||||
setting = this.settings.get('directory.uptime');
|
||||
|
||||
for(const edge of edges) {
|
||||
if ( ! edge )
|
||||
continue;
|
||||
if ( ! container || setting === 0 || props.viewCount || props.animatedImageProps )
|
||||
return this.clearUptime(el);
|
||||
|
||||
const node = edge.node || edge,
|
||||
stream = node.stream || node;
|
||||
let created_at = props.createdAt;
|
||||
|
||||
if ( stream.viewersCount ) {
|
||||
const store = stream.viewersCount = new Number(stream.viewersCount || 0);
|
||||
|
||||
store.createdAt = stream.createdAt;
|
||||
store.title = stream.title;
|
||||
//store.game = stream.game;
|
||||
if ( ! created_at ) {
|
||||
if ( el.ffz_stream_meta === undefined ) {
|
||||
el.ffz_stream_meta = null;
|
||||
this.twitch_data.getStreamMeta(null, props.channelLogin).then(data => {
|
||||
el.ffz_stream_meta = data;
|
||||
this.updateUptime(el, props);
|
||||
});
|
||||
}
|
||||
|
||||
if ( is_game_query || (! stream.game || stream.game && ! blocked_games.includes(stream.game.name)) )
|
||||
out.push(edge);
|
||||
created_at = el.ffz_stream_meta?.createdAt;
|
||||
}
|
||||
|
||||
return out;
|
||||
const up_since = created_at && new Date(created_at),
|
||||
uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0;
|
||||
|
||||
if ( uptime < 1 )
|
||||
return this.clearUptime(el);
|
||||
|
||||
const up_text = duration_to_string(uptime, false, false, false, setting === 1);
|
||||
|
||||
if ( ! el.ffz_uptime_el ) {
|
||||
el.ffz_uptime_el = container.querySelector('.ffz-uptime-element');
|
||||
if ( ! el.ffz_uptime_el )
|
||||
container.appendChild(el.ffz_uptime_el = (<div class="ffz-uptime-element tw-absolute tw-right-0 tw-top-0 tw-mg-1">
|
||||
<div class="tw-relative tw-tooltip-wrapper">
|
||||
<div class="tw-border-radius-small tw-c-background-overlay tw-c-text-overlay tw-flex tw-pd-x-05">
|
||||
<div class="tw-flex tw-c-text-live">
|
||||
<figure class="ffz-i-clock" />
|
||||
</div>
|
||||
{el.ffz_uptime_span = <p />}
|
||||
</div>
|
||||
<div class="tw-tooltip tw-tooltip--down tw-tooltip--align-right">
|
||||
{this.i18n.t('metadata.uptime.tooltip', 'Stream Uptime')}
|
||||
{el.ffz_uptime_tt = <div class="tw-pd-t-05" />}
|
||||
</div>
|
||||
</div>
|
||||
</div>));
|
||||
}
|
||||
|
||||
if ( ! el.ffz_update_timer )
|
||||
el.ffz_update_timer = setInterval(this.updateUptime.bind(this, el, props), 1000);
|
||||
|
||||
el.ffz_uptime_span.textContent = up_text;
|
||||
|
||||
if ( el.ffz_last_created_at !== created_at ) {
|
||||
el.ffz_uptime_tt.textContent = this.i18n.t(
|
||||
'metadata.uptime.since',
|
||||
'(since {since,datetime})',
|
||||
{since: up_since}
|
||||
);
|
||||
|
||||
el.ffz_last_created_at = created_at;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -410,77 +432,7 @@ export default class Directory extends SiteModule {
|
|||
}
|
||||
|
||||
|
||||
updateUptime(inst, created_path) {
|
||||
const container = this.fine.getChildNode(inst),
|
||||
card = container && container.querySelector && container.querySelector('.preview-card-overlay'),
|
||||
setting = this.settings.get('directory.uptime');
|
||||
|
||||
if ( ! card || setting === 0 || ! inst.props || inst.props.viewCount || inst.props.animatedImageProps )
|
||||
return this.clearUptime(inst);
|
||||
|
||||
let created_at = inst.props.createdAt || get(created_path, inst);
|
||||
|
||||
if ( ! created_at ) {
|
||||
if ( inst.ffz_stream_meta === undefined ) {
|
||||
inst.ffz_stream_meta = null;
|
||||
this.twitch_data.getStreamMeta(inst.props.channelId, inst.props.channelLogin).then(data => {
|
||||
inst.ffz_stream_meta = data;
|
||||
this.updateUptime(inst, created_path);
|
||||
});
|
||||
}
|
||||
|
||||
if ( inst.ffz_stream_meta )
|
||||
created_at = inst.ffz_stream_meta.createdAt;
|
||||
}
|
||||
|
||||
if ( ! created_at )
|
||||
return this.clearUptime(inst);
|
||||
|
||||
const up_since = created_at && new Date(created_at),
|
||||
uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0;
|
||||
|
||||
if ( uptime < 1 )
|
||||
return this.clearUptime(inst);
|
||||
|
||||
const up_text = duration_to_string(uptime, false, false, false, setting === 1);
|
||||
|
||||
if ( ! inst.ffz_uptime_el ) {
|
||||
inst.ffz_uptime_el = card.querySelector('.ffz-uptime-element');
|
||||
if ( ! inst.ffz_uptime_el )
|
||||
card.appendChild(inst.ffz_uptime_el = (<div class="ffz-uptime-element tw-absolute tw-right-0 tw-top-0 tw-mg-1">
|
||||
<div class="tw-relative tw-tooltip-wrapper">
|
||||
<div class="preview-card-stat tw-align-items-center tw-border-radi-us-small tw-c-background-overlay tw-c-text-overlay tw-flex tw-font-size-6 tw-justify-content-center">
|
||||
<div class="tw-flex tw-c-text-live">
|
||||
<figure class="ffz-i-clock" />
|
||||
</div>
|
||||
{inst.ffz_uptime_span = <p />}
|
||||
</div>
|
||||
<div class="tw-tooltip tw-tooltip--down tw-tooltip--align-right">
|
||||
{this.i18n.t('metadata.uptime.tooltip', 'Stream Uptime')}
|
||||
{inst.ffz_uptime_tt = <div class="tw-pd-t-05" />}
|
||||
</div>
|
||||
</div>
|
||||
</div>));
|
||||
}
|
||||
|
||||
if ( ! inst.ffz_update_timer )
|
||||
inst.ffz_update_timer = setInterval(this.updateUptime.bind(this, inst, created_path), 1000);
|
||||
|
||||
inst.ffz_uptime_span.textContent = up_text;
|
||||
|
||||
if ( inst.ffz_last_created_at !== created_at ) {
|
||||
inst.ffz_uptime_tt.textContent = this.i18n.t(
|
||||
'metadata.uptime.since',
|
||||
'(since {since,datetime})',
|
||||
{since: up_since}
|
||||
);
|
||||
|
||||
inst.ffz_last_created_at = created_at;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateAvatar(inst) {
|
||||
/*updateAvatar(inst) {
|
||||
const container = this.fine.getChildNode(inst),
|
||||
card = container && container.querySelector && container.querySelector('.preview-card-overlay'),
|
||||
setting = this.settings.get('directory.show-channel-avatars');
|
||||
|
@ -524,7 +476,7 @@ export default class Directory extends SiteModule {
|
|||
</figure>
|
||||
</div>
|
||||
</a>);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
routeClick(event, url) {
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
query RecommendedChannels {
|
||||
recommendedStreams {
|
||||
edges {
|
||||
node {
|
||||
createdAt
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
query {
|
||||
currentUser {
|
||||
subscribedChannels {
|
||||
edges {
|
||||
node {
|
||||
stream {
|
||||
type
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -189,6 +189,11 @@ export default class Layout extends Module {
|
|||
this.css_tweaks.setVariable('portrait-extra-width', `${this.settings.get('layout.portrait-extra-width')}rem`);
|
||||
this.css_tweaks.setVariable('portrait-extra-height', `${this.settings.get('layout.portrait-extra-height')}rem`);
|
||||
|
||||
this.on('site.directory:update-cards', () => {
|
||||
for(const inst of this.SideBarChannels.instances)
|
||||
this.updateCardClass(inst);
|
||||
});
|
||||
|
||||
this.SideBarChannels.ready((cls, instances) => {
|
||||
for(const inst of instances)
|
||||
this.updateCardClass(inst);
|
||||
|
@ -250,10 +255,17 @@ export default class Layout extends Module {
|
|||
updateCardClass(inst) {
|
||||
const node = this.fine.getChildNode(inst);
|
||||
|
||||
if ( node )
|
||||
if ( node ) {
|
||||
node.classList.toggle('ffz--side-nav-card-rerun',
|
||||
inst.props?.tooltipContent?.props?.streamType === 'rerun'
|
||||
);
|
||||
node.classList.toggle('ffz--side-nav-card-offline',
|
||||
inst.props?.offline === true
|
||||
);
|
||||
|
||||
const game = inst.props?.tooltipContent?.props?.gameName || inst.props?.metadataLeft?.props?.activity?.stream?.game?.name || inst.props?.metadataLeft;
|
||||
node.classList.toggle('tw-hide', this.settings.provider.get('directory.game.blocked-games', []).includes(game));
|
||||
}
|
||||
}
|
||||
|
||||
updateNavLinks() {
|
||||
|
|
|
@ -27,20 +27,10 @@
|
|||
}
|
||||
|
||||
|
||||
.ffz-hide-thumbnail {
|
||||
.preview-card-thumbnail__image {
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: url("https://static-cdn.jtvnw.net/ttv-static/404_preview-320x180.jpg") no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.ffz-hide-thumbnail a[data-a-target="preview-card-image-link"] {
|
||||
.tw-aspect {
|
||||
img {
|
||||
display: none;
|
||||
filter: blur(2.5rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ export default class Elemental extends Module {
|
|||
}
|
||||
|
||||
|
||||
define(key, selector, routes, opts = null, limit = 0, timeout = 5000) {
|
||||
define(key, selector, routes, opts = null, limit = 0, timeout = 5000, remove = true) {
|
||||
if ( this._wrappers.has(key) )
|
||||
return this._wrappers.get(key);
|
||||
|
||||
if ( ! selector || typeof selector !== 'string' || ! selector.length )
|
||||
throw new Error('cannot find definition and no selector provided');
|
||||
|
||||
const wrapper = new ElementalWrapper(key, selector, routes, opts, limit, timeout, this);
|
||||
const wrapper = new ElementalWrapper(key, selector, routes, opts, limit, timeout, remove, this);
|
||||
this._wrappers.set(key, wrapper);
|
||||
|
||||
return wrapper;
|
||||
|
@ -46,6 +46,19 @@ export default class Elemental extends Module {
|
|||
this._timer = Date.now();
|
||||
this._updateLiveWatching();
|
||||
this.checkAll();
|
||||
this.cleanAll();
|
||||
}
|
||||
|
||||
|
||||
cleanAll() {
|
||||
if ( this._clean_all )
|
||||
cancelAnimationFrame(this._clean_all);
|
||||
|
||||
this._clean_all = requestAnimationFrame(() => {
|
||||
this._clean_all = null;
|
||||
for(const wrapper of this._wrappers.values())
|
||||
wrapper.clean();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -160,7 +173,7 @@ export default class Elemental extends Module {
|
|||
let elemental_id = 0;
|
||||
|
||||
export class ElementalWrapper extends EventEmitter {
|
||||
constructor(name, selector, routes, opts, limit, timeout, elemental) {
|
||||
constructor(name, selector, routes, opts, limit, timeout, remove, elemental) {
|
||||
super();
|
||||
|
||||
this.id = elemental_id++;
|
||||
|
@ -176,6 +189,7 @@ export class ElementalWrapper extends EventEmitter {
|
|||
this.opts = opts;
|
||||
this.limit = limit;
|
||||
this.timeout = timeout;
|
||||
this.check_removal = remove;
|
||||
|
||||
if ( this.opts && ! this.opts.childList && ! this.opts.attributes && ! this.opts.characterData )
|
||||
this.opts.attributes = true;
|
||||
|
@ -193,6 +207,14 @@ export class ElementalWrapper extends EventEmitter {
|
|||
return this.limit > 0 && this.count >= this.limit;
|
||||
}
|
||||
|
||||
clean() {
|
||||
const instances = Array.from(this.instances);
|
||||
for(const el of instances) {
|
||||
if ( ! document.contains(el) )
|
||||
this.remove(el);
|
||||
}
|
||||
}
|
||||
|
||||
schedule() {
|
||||
if ( ! this._stimer )
|
||||
this._stimer = setTimeout(this._schedule, 0);
|
||||
|
@ -251,15 +273,17 @@ export class ElementalWrapper extends EventEmitter {
|
|||
this.instances.add(el);
|
||||
this.count++;
|
||||
|
||||
const remove_check = new MutationObserver(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if ( ! document.contains(el) )
|
||||
this.remove(el);
|
||||
if ( this.check_removal ) {
|
||||
const remove_check = new MutationObserver(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if ( ! document.contains(el) )
|
||||
this.remove(el);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
remove_check.observe(el.parentNode, {childList: true});
|
||||
el[this.remove_param] = remove_check;
|
||||
remove_check.observe(el.parentNode, {childList: true});
|
||||
el[this.remove_param] = remove_check;
|
||||
}
|
||||
|
||||
if ( this.opts ) {
|
||||
const observer = new MutationObserver(muts => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue