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); }