From 4cfd76b89eed45f6e7ff3d65ab448aa8f5f067fc Mon Sep 17 00:00:00 2001 From: SirStendec Date: Tue, 28 Nov 2017 03:01:20 -0500 Subject: [PATCH] Make some changes to how the directory stuff is implemented. There's too much code duplication right now. There's also code leaking from hosts to the main following page. There needs to be a way to detect if a live-channel-card is in the hosts section or not. Communities and Games use the same component, so there's a ton duplicated there. --- .../modules/directory/community.js | 20 ++-- .../modules/directory/following.js | 98 +++++-------------- .../twitch-twilight/modules/directory/game.js | 25 +++-- .../modules/directory/index.js | 23 ----- .../modules/directory/index.off | 77 +++++++++++++++ .../{following_link.js => following_link.off} | 17 ++-- 6 files changed, 129 insertions(+), 131 deletions(-) delete mode 100644 src/sites/twitch-twilight/modules/directory/index.js create mode 100644 src/sites/twitch-twilight/modules/directory/index.off rename src/sites/twitch-twilight/modules/{following_link.js => following_link.off} (98%) diff --git a/src/sites/twitch-twilight/modules/directory/community.js b/src/sites/twitch-twilight/modules/directory/community.js index 544dc566..33d7f816 100644 --- a/src/sites/twitch-twilight/modules/directory/community.js +++ b/src/sites/twitch-twilight/modules/directory/community.js @@ -64,7 +64,7 @@ export default class Community extends SiteModule { for (let i = 0; i < edges.length; i++) { const edge = edges[i]; const node = edge.node; - + const s = node.viewersCount = new Number(node.viewersCount || 0); s.profileImageURL = node.broadcaster.profileImageURL; s.createdAt = node.createdAt; @@ -135,7 +135,7 @@ export default class Community extends SiteModule { const up_since = new Date(inst.props.streamNode.viewersCount.createdAt); const uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; const uptimeText = duration_to_string(uptime, false, false, false, this.settings.get('directory.following.uptime') === 1); - + if (uptime > 0) { if (inst.uptimeElement === undefined) { inst.uptimeElementSpan = e('span', 'tw-stat__value ffz-uptime', `${uptimeText}`); @@ -148,7 +148,7 @@ export default class Community extends SiteModule { ), inst.uptimeElementSpan ]); - + if (card.querySelector('.ffz-uptime') === null) card.appendChild(inst.uptimeElement); } else { inst.uptimeElementSpan.textContent = `${uptimeText}`; @@ -166,11 +166,11 @@ export default class Community extends SiteModule { if (container === null || card === null) return; if (!inst.props.streamNode.viewersCount.createdAt) return; - + // Remove old elements const hiddenBodyCard = card.querySelector('.tw-card-body.hide'); if (hiddenBodyCard !== null) hiddenBodyCard.classList.remove('hide'); - + const ffzChannelData = card.querySelector('.ffz-channel-data'); if (ffzChannelData !== null) ffzChannelData.remove(); @@ -192,7 +192,7 @@ export default class Community extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.streamNode.broadcaster.login}); } }, e('img', { @@ -202,7 +202,7 @@ export default class Community extends SiteModule { })); const cardDivParent = cardDiv.parentElement; - + if (cardDivParent.querySelector('.ffz-channel-data') === null) { cardDiv.classList.add('hide'); @@ -218,7 +218,7 @@ export default class Community extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.streamNode.broadcaster.login}); } }, e('div', 'live-channel-card__boxart bottom-0 absolute', @@ -241,10 +241,10 @@ export default class Community extends SiteModule { const container = this.fine.getHostNode(inst); // We can't get the buttons through querySelector('button ...') so this has to do for now... const buttons = container && container.querySelector && container.querySelector('div > div.align-items-center'); - + const ffzButtons = buttons.querySelector('.ffz-buttons'); if (ffzButtons !== null) ffzButtons.remove(); - + if (buttons.querySelector('.ffz-buttons') === null) { // Block / Unblock Games const blockedGames = this.settings.provider.get('directory.game.blocked-games') || []; diff --git a/src/sites/twitch-twilight/modules/directory/following.js b/src/sites/twitch-twilight/modules/directory/following.js index f9c026e4..536573c1 100644 --- a/src/sites/twitch-twilight/modules/directory/following.js +++ b/src/sites/twitch-twilight/modules/directory/following.js @@ -160,7 +160,7 @@ export default class Following extends SiteModule { } } }`); - + this.apollo.registerModifier('FollowingHosts_CurrentUser', `query { currentUser { followedHosts { @@ -223,7 +223,7 @@ export default class Following extends SiteModule { modifyLiveHosts(res) { // eslint-disable-line class-methods-use-this if (!this.isRouteAcceptable()) return res; - + const hiddenThumbnails = this.settings.provider.get('directory.game.hidden-thumbnails') || []; const blockedGames = this.settings.provider.get('directory.game.blocked-games') || []; @@ -295,8 +295,7 @@ export default class Following extends SiteModule { }); this.ChannelCard.on('mount', inst => this.updateChannelCard(inst), this); - - this.ChannelCard.on('unmount', inst => this.updateUptime(inst), this); + this.ChannelCard.on('unmount', inst => this.parent.clearUptime(inst), this); document.body.addEventListener('click', this.destroyHostMenu.bind(this)); } @@ -309,61 +308,6 @@ export default class Following extends SiteModule { } } - updateUptime(inst) { - const container = this.fine.getHostNode(inst); - const card = container && container.querySelector && container.querySelector('.tw-card .tw-aspect > div'); - - // if (container === null || card === null) { - // if (inst.updateTimer !== undefined) { - // clearInterval(inst.updateTimer); - // inst.updateTimer = undefined; - // return; - // } - // } - - if (this.settings.get('directory.following.uptime') === 0) { - if (inst.updateTimer !== undefined) { - clearInterval(inst.updateTimer); - inst.updateTimer = undefined; - } - - if (inst.uptimeElement !== undefined) { - inst.uptimeElement.remove(); - inst.uptimeElementSpan = inst.uptimeElement = undefined; - } - } else { - if (inst.updateTimer === undefined) { - inst.updateTimer = setInterval( - this.updateUptime.bind(this, inst), - 1000 - ); - } - - const up_since = new Date(inst.props.viewerCount.createdAt); - const uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; - const uptimeText = duration_to_string(uptime, false, false, false, this.settings.get('directory.following.uptime') === 1); - - if (uptime > 0) { - if (inst.uptimeElement === undefined) { - inst.uptimeElementSpan = e('span', 'tw-stat__value ffz-uptime', `${uptimeText}`); - inst.uptimeElement = e('div', { - className: 'c-background-overlay c-text-overlay font-size-6 top-0 right-0 z-default inline-flex absolute mg-05', - style: 'padding-left: 4px; padding-right: 4px;' - }, [ - e('span', 'tw-stat__icon', - e('figure', 'ffz-i-clock') - ), - inst.uptimeElementSpan - ]); - - if (card.querySelector('.ffz-uptime') === null) card.appendChild(inst.uptimeElement); - } else { - inst.uptimeElementSpan.textContent = `${uptimeText}`; - } - } - } - } - showHostMenu(inst, { channels }, event) { if (this.settings.get('directory.following.host-menus') === 0 || this.settings.get('directory.following.host-menus') === 1 && channels.length < 2) return; @@ -393,7 +337,7 @@ export default class Following extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.linkTo.pathname.substring(1)}); } }, e('div', 'align-items-center flex flex-row flex-nowrap mg-x-1 mg-y-05', @@ -483,27 +427,29 @@ export default class Following extends SiteModule { } updateChannelCard(inst) { - this.updateUptime(inst); + this.parent.updateUptime(inst, 'props.viewerCount.createdAt', '.tw-card .tw-aspect > div'); - const container = this.fine.getHostNode(inst); - const card = container && container.querySelector && container.querySelector('.tw-card'); - - if (container === null || card === null) return; + const container = this.fine.getHostNode(inst), + card = container && container.querySelector && container.querySelector('.tw-card'); + + if ( container === null || card === null ) + return; const channelCardTitle = card.querySelector('.live-channel-card__title'); - if (channelCardTitle === null) return; - + if ( channelCardTitle === null ) + return; + // Remove old elements const hiddenBodyCard = card.querySelector('.tw-card-body.hide'); if (hiddenBodyCard !== null) hiddenBodyCard.classList.remove('hide'); - + const ffzChannelData = card.querySelector('.ffz-channel-data'); if (ffzChannelData !== null) ffzChannelData.remove(); - + const channelAvatar = card.querySelector('.channel-avatar'); if (channelAvatar !== null) channelAvatar.remove(); - + if (inst.props.viewerCount.profileImageURL) { const hosting = inst.props.viewerCount.hostData; let channel, displayName; @@ -511,13 +457,13 @@ export default class Following extends SiteModule { channel = inst.props.viewerCount.hostData.channel; displayName = inst.props.viewerCount.hostData.displayName; } - + const avatarSetting = this.settings.get('directory.following.show-channel-avatar'); const cardDiv = card.querySelector('.tw-card-body'); const modifiedDiv = e('div', { innerHTML: cardDiv.innerHTML }); - + let avatarDiv; if (avatarSetting === 1) { avatarDiv = e('a', { @@ -536,7 +482,7 @@ export default class Following extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.streamNode.broadcaster.login}); } }, e('div', 'live-channel-card__boxart bottom-0 absolute', @@ -569,16 +515,16 @@ export default class Following extends SiteModule { 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"]'); - + if (hostObj.channels.length > 1) { const textContent = `${hostObj.channels.length} hosting ${displayName}`; 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); } diff --git a/src/sites/twitch-twilight/modules/directory/game.js b/src/sites/twitch-twilight/modules/directory/game.js index ebfc3d02..d9f3211f 100644 --- a/src/sites/twitch-twilight/modules/directory/game.js +++ b/src/sites/twitch-twilight/modules/directory/game.js @@ -67,7 +67,7 @@ export default class Game extends SiteModule { for (let i = 0; i < edges.length; i++) { const edge = edges[i]; const node = edge.node; - + const s = node.viewersCount = new Number(node.viewersCount || 0); s.profileImageURL = node.broadcaster.profileImageURL; s.createdAt = node.createdAt; @@ -140,7 +140,7 @@ export default class Game extends SiteModule { const up_since = new Date(inst.props.streamNode.viewersCount.createdAt); const uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; const uptimeText = duration_to_string(uptime, false, false, false, this.settings.get('directory.following.uptime') === 1); - + if (uptime > 0) { if (inst.uptimeElement === undefined) { inst.uptimeElementSpan = e('span', 'tw-stat__value ffz-uptime', `${uptimeText}`); @@ -153,7 +153,7 @@ export default class Game extends SiteModule { ), inst.uptimeElementSpan ]); - + if (card.querySelector('.ffz-uptime') === null) card.appendChild(inst.uptimeElement); } else { inst.uptimeElementSpan.textContent = `${uptimeText}`; @@ -167,15 +167,15 @@ export default class Game extends SiteModule { const container = this.fine.getHostNode(inst); const card = container && container.querySelector && container.querySelector('.tw-thumbnail-card'); - + if (container === null || card === null) return; if (!inst.props.streamNode.viewersCount.createdAt || container === null || card === null) return; - + // Remove old elements const hiddenBodyCard = card.querySelector('.tw-card-body.hide'); if (hiddenBodyCard !== null) hiddenBodyCard.classList.remove('hide'); - + const ffzChannelData = card.querySelector('.ffz-channel-data'); if (ffzChannelData !== null) ffzChannelData.remove(); @@ -184,14 +184,13 @@ export default class Game extends SiteModule { const hiddenThumbnails = this.settings.provider.get('directory.game.hidden-thumbnails') || []; const thumbnailBlocked = hiddenThumbnails.includes(inst.props.directoryName); - this.log.warn(inst); if (thumbnailBlocked) { card.classList.add('ffz-thumbnail-hidden'); } else { card.classList.remove('ffz-thumbnail-hidden'); } - + if (inst.props.streamNode.viewersCount.profileImageURL) { const avatarSetting = this.settings.get('directory.following.show-channel-avatar'); if (avatarSetting === 1) { @@ -207,7 +206,7 @@ export default class Game extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.streamNode.broadcaster.login}); } }, e('img', { @@ -217,7 +216,7 @@ export default class Game extends SiteModule { })); const cardDivParent = cardDiv.parentElement; - + if (cardDivParent.querySelector('.ffz-channel-data') === null) { cardDiv.classList.add('hide'); @@ -233,7 +232,7 @@ export default class Game extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: inst.props.streamNode.broadcaster.login}); } }, e('div', 'live-channel-card__boxart bottom-0 absolute', @@ -256,10 +255,10 @@ export default class Game extends SiteModule { const container = this.fine.getHostNode(inst); // We can't get the buttons through querySelector('button ...') so this has to do for now... const buttons = container && container.querySelector && container.querySelector('div > div.align-items-center'); - + const ffzButtons = buttons.querySelector('.ffz-buttons'); if (ffzButtons !== null) ffzButtons.remove(); - + if (buttons.querySelector('.ffz-buttons') === null) { // Block / Unblock Games const blockedGames = this.settings.provider.get('directory.game.blocked-games') || []; diff --git a/src/sites/twitch-twilight/modules/directory/index.js b/src/sites/twitch-twilight/modules/directory/index.js deleted file mode 100644 index 428da086..00000000 --- a/src/sites/twitch-twilight/modules/directory/index.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -// ============================================================================ -// Directory -// ============================================================================ - -import {SiteModule} from 'utilities/module'; - -import Following from './following'; -import Game from './game'; -import Community from './community'; - -export default class Directory extends SiteModule { - constructor(...args) { - super(...args); - - this.should_enable = true; - - this.inject(Following); - this.inject(Game); - this.inject(Community); - } -} \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/directory/index.off b/src/sites/twitch-twilight/modules/directory/index.off new file mode 100644 index 00000000..eccb6f03 --- /dev/null +++ b/src/sites/twitch-twilight/modules/directory/index.off @@ -0,0 +1,77 @@ +'use strict'; + +// ============================================================================ +// Directory +// ============================================================================ + +import {SiteModule} from 'utilities/module'; +import {duration_to_string} from 'utilities/time'; +import {createElement as e} from 'utilities/dom'; +import {get} from 'utilities/object'; + +import Following from './following'; +import Game from './game'; +import Community from './community'; + +export default class Directory extends SiteModule { + constructor(...args) { + super(...args); + + this.should_enable = true; + + this.inject('i18n'); + this.inject('settings'); + this.inject('site.fine'); + + this.inject(Following); + this.inject(Game); + this.inject(Community); + } + + + clearUptime(inst) { // eslint-disable-line class-methods-use-this + if ( inst.ffz_update_timer ) { + clearInterval(inst.ffz_update_timer); + inst.ffz_update_timer = null; + } + + if ( inst.ffz_uptime_el ) { + inst.ffz_uptime_el.parentElement.removeChild(inst.ffz_uptime_el); + inst.ffz_uptime_el = null; + inst.ffz_uptime_span = null; + inst.ffz_uptime_tt = null; + } + } + + + updateUptime(inst, created_path, selector) { + const container = this.fine.getHostNode(inst), + card = container && container.querySelector && container.querySelector(selector), + setting = this.settings.get('directory.following.uptime'), + created_at = get(created_path, inst), + up_since = created_at && new Date(created_at), + uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; + + if ( ! card || setting === 0 || uptime < 1 ) + return this.clearUptime(inst); + + const up_text = duration_to_string(uptime, false, false, false, setting === 1); + + if ( ! inst.ffz_uptime_el ) + card.appendChild(inst.ffz_uptime_el = e('div', + 'video-preview-card__preview-overlay-stat c-background-overlay c-text-overlay font-size-6 top-0 right-0 z-default inline-flex absolute mg-05', + e('div', 'tw-tooltip-wrapper inline-flex', [ + e('div', 'tw-stat', [ + e('span', 'c-text-live tw-stat__icon', e('figure', 'ffz-i-clock')), + inst.ffz_uptime_span = e('span', 'tw-stat__value') + ]), + inst.ffz_uptime_tt = e('div', 'tw-tooltip tw-tooltip--down tw-tooltip--align-center') + ]))); + + if ( ! inst.ffz_update_timer ) + inst.ffz_update_timer = setInterval(this.updateUptime.bind(this, inst, created_path, selector), 1000); + + inst.ffz_uptime_span.textContent = up_text; + inst.ffz_uptime_tt.textContent = up_since.toLocaleString(); + } +} \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/following_link.js b/src/sites/twitch-twilight/modules/following_link.off similarity index 98% rename from src/sites/twitch-twilight/modules/following_link.js rename to src/sites/twitch-twilight/modules/following_link.off index 62077aaa..cb437400 100644 --- a/src/sites/twitch-twilight/modules/following_link.js +++ b/src/sites/twitch-twilight/modules/following_link.off @@ -1,7 +1,7 @@ 'use strict'; // ============================================================================ -// Following Button Modification +// Following Button Modification // ============================================================================ import {SiteModule} from 'utilities/module'; @@ -16,7 +16,6 @@ export default class FollowingText extends SiteModule { this.should_enable = true; - // this.inject('site'); this.inject('settings'); this.inject('site.router'); this.inject('site.apollo'); @@ -71,12 +70,12 @@ export default class FollowingText extends SiteModule { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; - + if (blockedGames.includes(node.stream.game.name)) { filtered += 1; continue; } - + c += 1; if (c > max_lines) { const div = e('div', { @@ -89,7 +88,7 @@ export default class FollowingText extends SiteModule { innerContent.push(div); break; } - + const up_since = new Date(node.stream.createdAt); const uptime = up_since && Math.floor((Date.now() - up_since) / 1000) || 0; const uptimeText = duration_to_string(uptime, false, false, false, true); @@ -100,7 +99,7 @@ export default class FollowingText extends SiteModule { }, [ e('div', { className: 'top-stream-info', - style: 'padding-bottom: 16px;' + style: 'padding-bottom: 16px;' }, [ // Username e('a', { @@ -111,7 +110,7 @@ export default class FollowingText extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('user', { userName: node.login }); } }), @@ -194,7 +193,7 @@ export default class FollowingText extends SiteModule { onclick: event => { event.preventDefault(); event.stopPropagation(); - + this.router.navigate('dir-following'); } }), @@ -205,7 +204,7 @@ export default class FollowingText extends SiteModule { }), tipDiv ]); - + topNavContainer.insertBefore(newFollowing, followingText); followingText.classList.add('hide');