From 6b796ffa7401c3c8041e333bcd09dfa4e47b03d3 Mon Sep 17 00:00:00 2001 From: Lordmau5 Date: Sat, 24 Aug 2019 00:02:30 +0200 Subject: [PATCH] Fix hosting menu (#635) This feature has been broken ever since **JUNE 2018**. There have been enough changes on Twitch's end to support this more easily now, so that's good. Also fixed some potentially longer standing bug with the hosts map not being cleared when the query is being re-ran, causing some hosts not to show up --- .../modules/directory/following.jsx | 103 +++++++----------- .../modules/directory/index.jsx | 3 +- 2 files changed, 40 insertions(+), 66 deletions(-) diff --git a/src/sites/twitch-twilight/modules/directory/following.jsx b/src/sites/twitch-twilight/modules/directory/following.jsx index b58100aa..86832efe 100644 --- a/src/sites/twitch-twilight/modules/directory/following.jsx +++ b/src/sites/twitch-twilight/modules/directory/following.jsx @@ -9,6 +9,7 @@ import {createElement} from 'utilities/dom'; 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'; @@ -123,8 +124,8 @@ export default class Following extends SiteModule { if ( ! edges || ! edges.length ) return res; - const hosts = {}, - out = []; + this.hosts = new WeakMap(); + const out = []; for(const edge of edges) { if ( ! edge ) @@ -138,7 +139,7 @@ export default class Following extends SiteModule { continue; if ( ! stream.viewersCount ) { - if ( ! do_grouping || ! hosts[hosted.login] ) + if ( ! do_grouping || ! this.hosts[hosted.login] ) out.push(edge); continue; } @@ -150,13 +151,13 @@ export default class Following extends SiteModule { //store.game = stream.game; if ( do_grouping ) { - const host_nodes = hosts[hosted.login]; + const host_nodes = this.hosts[hosted.login]; if ( host_nodes ) { host_nodes.push(node); this.hosts.set(store, host_nodes); } else { - this.hosts.set(store, hosts[hosted.login] = [node]); + this.hosts.set(store, this.hosts[hosted.login] = [node]); out.push(edge); } @@ -224,7 +225,7 @@ export default class Following extends SiteModule { } } - showHostMenu(inst, { channels }, event) { + 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; event.preventDefault(); @@ -234,7 +235,6 @@ export default class Following extends SiteModule { this.hostMenu && this.hostMenu.remove(); - const hostData = this.hosts[inst.props.channelName]; const simplebarContentChildren = []; // Hosted Channel Header @@ -244,16 +244,16 @@ export default class Following extends SiteModule { // Hosted Channel Content simplebarContentChildren.push( this.parent.hijackUserClick(e, hostData.channel, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind + class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--alpha tw-interactive" + href={`/${inst.props.channelLogin}`} + onClick={e => this.parent.hijackUserClick(e, inst.props.channelLogin, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind >
- {inst.props.channelName} + {inst.props.channelDisplayName}

- {inst.props.channelName} + {inst.props.channelDisplayName}

); @@ -264,32 +264,27 @@ export default class Following extends SiteModule {

); // Hosting Channels Content - for (let i = 0; i < hostData.nodes.length; i++) { - const node = hostData.nodes[i]; + for (const channel of channels) { simplebarContentChildren.push( this.parent.hijackUserClick(e, node.login, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind + class="tw-block tw-border-radius-small tw-full-width tw-interactable tw-interactable--alpha tw-interactive" + href={`/${channel.login}`} + onClick={e => this.parent.hijackUserClick(e, channel.login, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind >
- {node.displayName} + {channel.displayName}

- {node.displayName} + {channel.displayName}

); } this.hostMenu = (
-
+
-
-
- {simplebarContentChildren} -
-
+ {simplebarContentChildren}
); @@ -297,64 +292,42 @@ export default class Following extends SiteModule { const root = (document.body.querySelector('#root>div') || document.body); root.appendChild(this.hostMenu); - this.hostMenuPopper = new Popper(document.body, this.hostMenu, { - placement: 'bottom-start', - modifiers: { - flip: { - enabled: false - }, - offset: { - offset: `${event.clientX - 60}, ${event.clientY - 60}` + this.hostMenuPopper = new Popper( + makeReference(event.clientX - 60, event.clientY - 60), + this.hostMenu, + { + placement: 'bottom-start', + modifiers: { + flip: { + enabled: false + } } - }, - }); + } + ); this.hostMenuBuffer = Date.now() + 50; } updateChannelCard(inst) { - const container = this.fine.getChildNode(inst), - card = container && container.querySelector && container.querySelector('.tw-card'); + const card = this.fine.getChildNode(inst); if ( ! card ) return; - 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')); + const login = inst.props.channelLogin, + hosting = inst.props.channelLinkTo && inst.props.channelLinkTo.state.content === 'live_host' && this.hosts && this.hosts[login]; if ( hosting && this.settings.get('directory.following.group-hosts') ) { - const host_data = this.hosts[data.displayName]; + const host_data = this.hosts[login]; - const title_link = card.querySelector('a[data-a-target="live-channel-card-title-link"]'), - thumbnail_link = card.querySelector('a[data-a-target="live-channel-card-thumbnail-link"]'), - card_title = card.querySelector('.live-channel-card__title'), - - text_content = host_data.channels.length !== 1 ? - this.i18n.t('host-menu.multiple', '{count,number} hosting {channel}', { - count: host_data.channels.length, - channel: data.displayName - }) : inst.props.title; - - if ( card_title ) - card_title.textContent = card_title.title = text_content; + const title_link = card.querySelector('a[data-test-selector="preview-card-titles__primary-link"]'), + thumbnail_link = card.querySelector('a[data-a-target="preview-card-image-link"]'); if ( title_link ) title_link.addEventListener('click', this.showHostMenu.bind(this, inst, host_data)); - if ( thumbnail_link ) { - thumbnail_link.title = text_content; + if ( thumbnail_link ) thumbnail_link.addEventListener('click', this.showHostMenu.bind(this, inst, host_data)); - } } } } diff --git a/src/sites/twitch-twilight/modules/directory/index.jsx b/src/sites/twitch-twilight/modules/directory/index.jsx index 877f7438..bcc81462 100644 --- a/src/sites/twitch-twilight/modules/directory/index.jsx +++ b/src/sites/twitch-twilight/modules/directory/index.jsx @@ -259,7 +259,7 @@ export default class Directory extends SiteModule { } cls.prototype.renderTitles = function() { - const nodes = t.following.hosts.get(get('props.currentViewerCount', this)); + const nodes = get(get('props.channelLogin', this), t.following.hosts); if ( this.props.hostedByChannelLogin == null || ! nodes || ! nodes.length ) return old_render_titles.call(this); @@ -355,6 +355,7 @@ export default class Directory extends SiteModule { this.updateUptime(inst, 'props.currentViewerCount.createdAt'); this.updateAvatar(inst); + this.following.updateChannelCard(inst); }