diff --git a/package.json b/package.json
index 22f2ce56..39e62d68 100755
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "frankerfacez",
"author": "Dan Salvato LLC",
- "version": "4.36.2",
+ "version": "4.37.0",
"description": "FrankerFaceZ is a Twitch enhancement suite.",
"private": true,
"license": "Apache-2.0",
@@ -12,9 +12,9 @@
"dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --config webpack.web.dev.js",
"dev:prod": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --config webpack.web.dev.prod.js",
"build": "pnpm build:prod",
- "build:stats": "cross-env NODE_ENV=production webpack --config webpack.web.prod.js --json > stats.json",
- "build:prod": "cross-env NODE_ENV=production webpack --config webpack.web.prod.js",
- "build:dev": "pnpm clean && webpack --config webpack.web.dev.js",
+ "build:stats": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack --config webpack.web.prod.js --json > stats.json",
+ "build:prod": "cross-env NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack --config webpack.web.prod.js",
+ "build:dev": "pnpm clean && cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config webpack.web.dev.js",
"font": "pnpm font:edit",
"font:edit": "fontello-cli --cli-config fontello.client.json edit",
"font:save": "fontello-cli --cli-config fontello.client.json save && pnpm font:update",
diff --git a/src/entry.js b/src/entry.js
index ca7b8c21..7b3ae680 100644
--- a/src/entry.js
+++ b/src/entry.js
@@ -2,7 +2,7 @@
'use strict';
(() => {
// Don't run on certain sub-domains.
- if ( /^(?:localhost\.rig|blog|im|chatdepot|tmi|api|brand|dev)\./.test(location.hostname) )
+ if ( /^(?:localhost\.rig|blog|im|chatdepot|tmi|api|brand|dev|gql|passport)\./.test(location.hostname) )
return;
const DEBUG = localStorage.ffzDebugMode == 'true' && document.body.classList.contains('ffz-dev'),
diff --git a/src/modules/chat/actions/components/edit-copy.vue b/src/modules/chat/actions/components/edit-copy.vue
new file mode 100644
index 00000000..1dfbedfd
--- /dev/null
+++ b/src/modules/chat/actions/components/edit-copy.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+ {{ t('setting.actions.variables', 'Available Variables: {vars}', {vars}) }}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/chat/actions/types.jsx b/src/modules/chat/actions/types.jsx
index 4de79288..da02fa29 100644
--- a/src/modules/chat/actions/types.jsx
+++ b/src/modules/chat/actions/types.jsx
@@ -83,6 +83,51 @@ export const edit_overrides = {
}
+// ============================================================================
+// Copy to Clipboard
+// ============================================================================
+
+export const copy_message = {
+ presets: [{
+ appearance: {
+ type: 'icon',
+ icon: 'ffz-i-docs'
+ }
+ }],
+
+ defaults: {
+ format: '{{user.displayName}}: {{message.text}}'
+ },
+
+ editor: () => import(/* webpackChunkName: 'main-menu' */ './components/edit-copy.vue'),
+
+ required_context: ['user', 'message'],
+
+ title: 'Copy Message',
+ description: 'Allows you to quickly copy a chat message to your clipboard.',
+
+ can_self: true,
+
+ tooltip(data) {
+ const msg = this.replaceVariables(data.options.format, data);
+
+ return [
+ (
{ // eslint-disable-line react/jsx-key
+ this.i18n.t('chat.actions.copy_message', 'Copy Message')
+ }
),
+ ({ // eslint-disable-line react/jsx-key
+ msg
+ }
)
+ ];
+ },
+
+ click(event, data) {
+ const msg = this.replaceVariables(data.options.format, data);
+ navigator.clipboard.writeText(msg);
+ }
+}
+
+
// ============================================================================
// Open URL
// ============================================================================
diff --git a/src/sites/shared/player.jsx b/src/sites/shared/player.jsx
index 20425591..f3ec0a95 100644
--- a/src/sites/shared/player.jsx
+++ b/src/sites/shared/player.jsx
@@ -559,6 +559,15 @@ export default class PlayerBase extends Module {
},
changed: val => this.css_tweaks.toggle('player-hide-mouse', val)
});
+
+ this.settings.add('player.single-click-pause', {
+ default: false,
+ ui: {
+ path: 'Player > General >> Playback',
+ title: "Pause/Unpause the player by clicking.",
+ component: 'setting-check-box'
+ }
+ });
}
async onEnable() {
@@ -643,8 +652,6 @@ export default class PlayerBase extends Module {
onShortcut(e) {
- this.log.info('Compressor Hotkey', e);
-
for(const inst of this.Player.instances)
this.compressPlayer(inst, e);
}
@@ -825,10 +832,14 @@ export default class PlayerBase extends Module {
if ( ! this._ffz_click_handler )
this._ffz_click_handler = this.ffzClickHandler.bind(this);
+ if ( ! this._ffz_dblclick_handler )
+ this._ffz_dblclick_handler = this.ffzDblClickHandler.bind(this);
+
if ( ! this._ffz_menu_handler )
this._ffz_menu_handler = this.ffzMenuHandler.bind(this);
on(cont, 'wheel', this._ffz_scroll_handler);
+ on(cont, 'dblclick', this._ffz_dblclick_handler);
on(cont, 'mousedown', this._ffz_click_handler);
on(cont, 'contextmenu', this._ffz_menu_handler);
}
@@ -853,23 +864,60 @@ export default class PlayerBase extends Module {
this._ffz_menu_handler = null;
}
+ if ( this._ffz_dblclick_handler ) {
+ off(cont, 'dblclick', this._ffz_dblclick_handler);
+ this._ffz_dblclick_handler = null;
+ }
+
this._ffz_listeners = false;
}
+ cls.prototype.ffzDelayPause = function() {
+ if ( this._ffz_pause_timer )
+ clearTimeout(this._ffz_pause_timer);
+
+ const player = this.props?.mediaPlayerInstance;
+ if (! player.isPaused())
+ this._ffz_pause_timer = setTimeout(() => {
+ const player = this.props?.mediaPlayerInstance;
+ if (!player.isPaused())
+ player.pause();
+ }, 500);
+ }
+
+ cls.prototype.ffzDblClickHandler = function(event) {
+ if ( ! event )
+ return;
+
+ if ( this._ffz_pause_timer )
+ clearTimeout(this._ffz_pause_timer);
+ }
+
cls.prototype.ffzClickHandler = function(event) {
if ( ! event )
return;
const vol_scroll = t.settings.get('player.volume-scroll'),
gain_scroll = t.settings.get('player.gain.scroll'),
+ click_pause = t.settings.get('player.single-click-pause'),
wants_rmb = wantsRMB(vol_scroll) || wantsRMB(gain_scroll);
+ // Left Click
+ if (click_pause && event.button === 0) {
+ if (! event.target || ! event.target.classList.contains('click-handler'))
+ return;
+
+ this.ffzDelayPause();
+ }
+
+ // Right Click
if ( wants_rmb && event.button === 2 ) {
this.ffz_rmb = true;
this.ffz_scrolled = false;
}
+ // Middle Click
if ( ! t.settings.get('player.mute-click') || event.button !== 1 )
return;
diff --git a/src/sites/twitch-twilight/modules/channel.jsx b/src/sites/twitch-twilight/modules/channel.jsx
index 3751ae8b..af212516 100644
--- a/src/sites/twitch-twilight/modules/channel.jsx
+++ b/src/sites/twitch-twilight/modules/channel.jsx
@@ -79,7 +79,7 @@ export default class Channel extends Module {
changed: () => this.updateLinks()
});
- this.settings.add('channel.hosting.enable', {
+ /*this.settings.add('channel.hosting.enable', {
default: true,
ui: {
path: 'Channel > Behavior >> Hosting',
@@ -87,8 +87,7 @@ export default class Channel extends Module {
component: 'setting-check-box'
},
changed: val => ! val && this.InfoBar.each(el => this.updateBar(el))
- });
-
+ });*/
this.ChannelPanels = this.fine.define(
'channel-panels',
@@ -116,7 +115,7 @@ export default class Channel extends Module {
{childNodes: true, subtree: true}, 1
);
- const strip_host = resp => {
+ /*const strip_host = resp => {
if ( this.settings.get('channel.hosting.enable') )
return;
@@ -130,7 +129,7 @@ export default class Channel extends Module {
};
this.apollo.registerModifier('UseHosting', strip_host, false);
- this.apollo.registerModifier('PlayerTrackingContextQuery', strip_host, false);
+ this.apollo.registerModifier('PlayerTrackingContextQuery', strip_host, false);*/
}
onEnable() {
@@ -162,7 +161,7 @@ export default class Channel extends Module {
this.InfoBar.on('unmount', this.removeBar, this);
this.InfoBar.each(el => this.updateBar(el));
- this.subpump.on(':pubsub-message', this.onPubSub, this);
+ //this.subpump.on(':pubsub-message', this.onPubSub, this);
this.router.on(':route', this.checkNavigation, this);
this.checkNavigation();
@@ -230,7 +229,7 @@ export default class Channel extends Module {
}
}
- setHost(channel_id, channel_login, target_id, target_login) {
+ /*setHost(channel_id, channel_login, target_id, target_login) {
const topic = `stream-chat-room-v1.${channel_id}`;
this.subpump.inject(topic, {
@@ -272,7 +271,7 @@ export default class Channel extends Module {
event.message.data.num_viewers = 0;
event.markChanged();
}
- }
+ }*/
updateSubscription(login) {
@@ -441,8 +440,8 @@ export default class Channel extends Module {
});
}*/
- if ( ! this.settings.get('channel.hosting.enable') && props.hostLogin )
- this.setHost(props.channelID, props.channelLogin, null, null);
+ //if ( ! this.settings.get('channel.hosting.enable') && props.hostLogin )
+ // this.setHost(props.channelID, props.channelLogin, null, null);
this.updateSubscription(props.channelLogin);
this.updateMetadata(el);
@@ -492,10 +491,10 @@ export default class Channel extends Module {
live_since: props.liveSince
},
props,
- hosted: {
+ /*hosted: {
login: props.hostLogin,
display_name: props.hostDisplayName
- },
+ },*/
el,
getViewerCount: () => {
const thing = cont.querySelector('p[data-a-target="animated-channel-viewers-count"]'),
diff --git a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx
index 0da82e64..6e6be4a7 100644
--- a/src/sites/twitch-twilight/modules/chat/emote_menu.jsx
+++ b/src/sites/twitch-twilight/modules/chat/emote_menu.jsx
@@ -188,6 +188,15 @@ export default class EmoteMenu extends Module {
}
});
+ this.settings.add('chat.emote-menu.clear-search', {
+ default: false,
+ ui: {
+ path: 'Chat > Emote Menu >> General',
+ title: 'Reset search when closing the Emote Menu.',
+ component: 'setting-check-box'
+ }
+ });
+
this.settings.add('chat.emote-menu.enabled', {
default: true,
ui: {
@@ -1078,6 +1087,7 @@ export default class EmoteMenu extends Module {
reducedPadding: t.chat.context.get('chat.emote-menu.reduced-padding'),
combineTabs: t.chat.context.get('chat.emote-menu.combine-tabs'),
showSearch: t.chat.context.get('chat.emote-menu.show-search'),
+ clearSearch: t.chat.context.get('chat.emote-menu.clear-search'),
tone: t.settings.provider.get('emoji-tone', null)
}
@@ -1226,6 +1236,7 @@ export default class EmoteMenu extends Module {
t.chat.context.on('changed:chat.emote-menu.show-heading', this.updateSettingState, this);
t.chat.context.on('changed:chat.emote-menu.combine-tabs', this.updateSettingState, this);
t.chat.context.on('changed:chat.emote-menu.show-search', this.updateSettingState, this);
+ t.chat.context.on('changed:chat.emote-menu.clear-search', this.updateSettingState, this);
t.chat.context.on('changed:chat.emote-menu.tall', this.updateSettingState, this);
window.ffz_menu = this;
@@ -1241,6 +1252,7 @@ export default class EmoteMenu extends Module {
t.chat.context.off('changed:chat.emote-menu.reduced-padding', this.updateSettingState, this);
t.chat.context.off('changed:chat.emote-menu.combine-tabs', this.updateSettingState, this);
t.chat.context.off('changed:chat.emote-menu.show-search', this.updateSettingState, this);
+ t.chat.context.off('changed:chat.emote-menu.clear-search', this.updateSettingState, this);
t.chat.context.off('changed:chat.emote-menu.tall', this.updateSettingState, this);
if ( window.ffz_menu === this )
@@ -1256,6 +1268,7 @@ export default class EmoteMenu extends Module {
reducedPadding: t.chat.context.get('chat.emote-menu.reduced-padding'),
combineTabs: t.chat.context.get('chat.emote-menu.combine-tabs'),
showSearch: t.chat.context.get('chat.emote-menu.show-search'),
+ clearSearch: t.chat.context.get('chat.emote-menu.clear-search'),
tall: t.chat.context.get('chat.emote-menu.tall')
});
}
@@ -2309,6 +2322,13 @@ export default class EmoteMenu extends Module {
return;
}
+ if ( ! this.props.visible && old_props.visible ) {
+ if ( this.state.clearSearch ) {
+ this.setState(this.filterState('', this.state));
+ return;
+ }
+ }
+
const cd = this.props.channel_data,
old_cd = old_props.channel_data,
cd_diff = cd?.user !== old_cd?.user || cd?.channel !== old_cd?.channel,
diff --git a/src/sites/twitch-twilight/modules/chat/index.js b/src/sites/twitch-twilight/modules/chat/index.js
index 1b43f35c..62d5f28b 100644
--- a/src/sites/twitch-twilight/modules/chat/index.js
+++ b/src/sites/twitch-twilight/modules/chat/index.js
@@ -201,7 +201,7 @@ export default class ChatHook extends Module {
this.ChatController = this.fine.define(
'chat-controller',
- n => n.hostingHandler && n.onRoomStateUpdated,
+ n => n.parseOutgoingMessage && n.onRoomStateUpdated && n.renderNotifications,
Twilight.CHAT_ROUTES
);
@@ -656,6 +656,15 @@ export default class ChatHook extends Module {
component: 'setting-check-box'
}
});
+
+ this.settings.add('chat.input.show-elevate-your-message', {
+ default: true,
+ ui: {
+ path: 'Chat > Input >> Appearance',
+ title: 'Allow the "Elevate Your Message" button to be displayed.',
+ component: 'setting-check-box'
+ }
+ });
}
get currentChat() {
@@ -941,6 +950,9 @@ export default class ChatHook extends Module {
this.updateMentionCSS();
});
+ this.chat.context.getChanges('chat.input.show-elevate-your-message', val =>
+ this.css_tweaks.toggleHide('elevate-your-message', ! val));
+
this.updateChatCSS();
this.updateColors();
this.updateLineBorders();
@@ -2441,7 +2453,7 @@ export default class ChatHook extends Module {
return old_points.call(i, e);
}
- const old_host = this.onHostingEvent;
+ /*const old_host = this.onHostingEvent;
this.onHostingEvent = function (e, _t) {
t.emit('tmi:host', e, _t);
return old_host.call(i, e, _t);
@@ -2451,7 +2463,7 @@ export default class ChatHook extends Module {
this.onUnhostEvent = function (e, _t) {
t.emit('tmi:unhost', e, _t);
return old_unhost.call(i, e, _t);
- }
+ }*/
const old_add = this.addMessage;
this.addMessage = function(e) {
diff --git a/src/sites/twitch-twilight/modules/css_tweaks/index.js b/src/sites/twitch-twilight/modules/css_tweaks/index.js
index da1cbf50..323eb3bc 100644
--- a/src/sites/twitch-twilight/modules/css_tweaks/index.js
+++ b/src/sites/twitch-twilight/modules/css_tweaks/index.js
@@ -26,6 +26,7 @@ const CLASSES = {
'modview-hide-info': '.modview-player-widget__hide-stream-info',
'community-highlights': '.community-highlight-stack__card',
+ 'elevate-your-message': '.chat-input__input-icons button[aria-label="ElevatedMessage"]',
'prime-offers': '.top-nav__prime',
'discover-luna': '.top-nav__external-link[data-a-target="try-presto-link"]',
@@ -38,7 +39,7 @@ const CLASSES = {
'player-event-bar': '.channel-root .live-event-banner-ui__header',
'player-rerun-bar': '.channel-root__player-container div.tw-c-text-overlay:not([data-a-target="hosting-ui-header"])',
- 'pinned-cheer': '.pinned-cheer,.pinned-cheer-v2,.channel-leaderboard',
+ 'pinned-cheer': '.pinned-cheer,.pinned-cheer-v2,.channel-leaderboard,.channel-leaderboard-marquee',
'whispers': 'body .whispers-open-threads,.tw-core-button[data-a-target="whisper-box-button"],.whispers__pill',
'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',
diff --git a/src/sites/twitch-twilight/modules/dashboard.js b/src/sites/twitch-twilight/modules/dashboard.js
index 9e68298d..2c1cdd95 100644
--- a/src/sites/twitch-twilight/modules/dashboard.js
+++ b/src/sites/twitch-twilight/modules/dashboard.js
@@ -54,7 +54,7 @@ export default class Dashboard extends Module {
this.settings.updateContext({
channel: get('props.channelLogin', inst),
channelID: get('props.channelID', inst),
- hosting: !! inst.props?.hostedChannel?.id
+ //hosting: !! inst.props?.hostedChannel?.id
});
}
@@ -62,7 +62,7 @@ export default class Dashboard extends Module {
this.settings.updateContext({
channel: null,
channelID: null,
- hosting: false
+ //hosting: false
});
}
diff --git a/src/sites/twitch-twilight/modules/directory/following.jsx b/src/sites/twitch-twilight/modules/directory/following.jsx
deleted file mode 100644
index 99ce9efc..00000000
--- a/src/sites/twitch-twilight/modules/directory/following.jsx
+++ /dev/null
@@ -1,249 +0,0 @@
-'use strict';
-
-// ============================================================================
-// Following Page
-// ============================================================================
-
-import {SiteModule} from 'utilities/module';
-import {createElement} from 'utilities/dom';
-import {get} from 'utilities/object';
-
-import {createPopper} from '@popperjs/core';
-import {makeReference} from 'utilities/tooltip';
-
-export default class Following extends SiteModule {
- constructor(...args) {
- super(...args);
-
- this.inject('site.fine');
- this.inject('site.router');
- this.inject('site.apollo');
- this.inject('site.css_tweaks');
-
- this.inject('i18n');
- this.inject('settings');
-
- this.settings.add('directory.following.group-hosts', {
- default: true,
-
- ui: {
- path: 'Directory > Following @{"description": "**Note:** These settings do not currently work due to changes made by Twitch to how the directory works."} >> Hosts',
- title: 'Group Hosts',
- description: 'Only show a given hosted channel once in the directory.',
- component: 'setting-check-box'
- },
-
- changed: () => {
- this.apollo.maybeRefetch('FollowedIndex_CurrentUser');
- this.apollo.maybeRefetch('FollowingHosts_CurrentUser');
- }
- });
-
- this.settings.add('directory.following.host-menus', {
- default: 1,
-
- ui: {
- path: 'Directory > Following >> Hosts',
- title: 'Hosted Channel Menus',
- description: 'Display a menu to select which channel to visit when clicking a hosted channel in the directory.',
-
- component: 'setting-select-box',
-
- data: [
- {value: 0, title: 'Disabled'},
- {value: 1, title: 'When Multiple are Hosting'},
- {value: 2, title: 'Always'}
- ]
- },
-
- changed: () => this.parent.DirectoryCard.forceUpdate()
- });
-
- this.hosts = new WeakMap;
- }
-
- modifyLiveUsers(res, path = 'followedLiveUsers') {
- const followed_live = get(`data.currentUser.${path}`, res);
- if ( ! followed_live )
- return;
-
- if ( followed_live.nodes )
- followed_live.nodes = this.parent.processNodes(followed_live.nodes);
-
- else if ( followed_live.edges )
- followed_live.edges = this.parent.processNodes(followed_live.edges);
-
- return res;
- }
-
- modifyLiveHosts(res) {
- const blocked_games = this.settings.provider.get('directory.game.blocked-games', []),
- do_grouping = this.settings.get('directory.following.group-hosts'),
- edges = get('data.currentUser.followedHosts.nodes', res);
-
- if ( ! edges || ! edges.length )
- return res;
-
- this.hosts = new WeakMap();
- const out = [];
-
- for(const edge of edges) {
- if ( ! edge )
- continue;
-
- const node = edge.node || edge,
- hosted = node.hosting,
- stream = hosted && hosted.stream;
-
- if ( ! stream || stream.game && blocked_games.includes(stream.game.name) )
- continue;
-
- if ( ! stream.viewersCount ) {
- if ( ! do_grouping || ! this.hosts[hosted.login] )
- out.push(edge);
- continue;
- }
-
- const store = stream.viewersCount = new Number(stream.viewersCount || 0);
-
- store.createdAt = stream.createdAt;
- store.title = stream.title;
- //store.game = stream.game;
-
- if ( do_grouping ) {
- 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, this.hosts[hosted.login] = [node]);
- out.push(edge);
- }
-
- } else
- out.push(edge);
- }
-
- res.data.currentUser.followedHosts.nodes = out;
- return res;
- }
-
- onEnable() {
- document.body.addEventListener('click', this.destroyHostMenu.bind(this));
- }
-
- destroyHostMenu(event) {
- if (!event || ! this.hostMenu || event && event.target && event.target.closest('.ffz-channel-selector-outer') === null && Date.now() > this.hostMenuBuffer) {
- this.hostMenuPopper && this.hostMenuPopper.destroy();
- this.hostMenu && this.hostMenu.remove();
- this.hostMenuPopper = this.hostMenu = undefined;
- }
- }
-
- 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();
- event.stopPropagation();
-
- this.hostMenuPopper && this.hostMenuPopper.destroy();
-
- this.hostMenu && this.hostMenu.remove();
-
- const simplebarContentChildren = [];
-
- // Hosted Channel Header
- simplebarContentChildren.push(
- {this.i18n.t('directory.hosted', 'Hosted Channel')}
-
);
-
- // Hosted Channel Content
- simplebarContentChildren.push( this.parent.hijackUserClick(e, inst.props.channelLogin, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
- >
-
-
-

-
-
- {inst.props.channelDisplayName}
-
-
- );
-
- // Hosting Channels Header
- simplebarContentChildren.push(
- {this.i18n.t('directory.hosting', 'Hosting Channels')}
-
);
-
- // Hosting Channels Content
- for (const channel of channels) {
- simplebarContentChildren.push( this.parent.hijackUserClick(e, channel.login, this.destroyHostMenu.bind(this))} // eslint-disable-line react/jsx-no-bind
- >
-
-
-

-
-
- {channel.displayName}
-
-
- );
- }
-
- this.hostMenu = ();
-
- const root = (document.body.querySelector('#root>div') || document.body);
- root.appendChild(this.hostMenu);
-
- this.hostMenuPopper = createPopper(
- makeReference(event.clientX - 60, event.clientY - 60),
- this.hostMenu,
- {
- placement: 'bottom-start',
- modifiers: {
- flip: {
- enabled: false
- }
- }
- }
- );
-
- this.hostMenuBuffer = Date.now() + 50;
- }
-
- updateChannelCard(inst) {
- const card = this.fine.getChildNode(inst);
-
- if ( ! card )
- return;
-
- 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[login];
-
- 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.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 354916bf..9ed24f67 100644
--- a/src/sites/twitch-twilight/modules/directory/index.jsx
+++ b/src/sites/twitch-twilight/modules/directory/index.jsx
@@ -48,7 +48,6 @@ export default class Directory extends SiteModule {
this.inject('i18n');
this.inject('settings');
- //this.inject(Following);
this.inject(Game);
this.DirectoryCard = this.elemental.define(
diff --git a/src/sites/twitch-twilight/modules/host_button/index.js b/src/sites/twitch-twilight/modules/host_button/index.js
deleted file mode 100644
index f854509c..00000000
--- a/src/sites/twitch-twilight/modules/host_button/index.js
+++ /dev/null
@@ -1,379 +0,0 @@
-'use strict';
-
-// ============================================================================
-// Host Button
-// ============================================================================
-
-import Module from 'utilities/module';
-import {get} from 'utilities/object';
-import {createElement} from 'utilities/dom';
-
-const HOST_ERRORS = {
- COMMAND_EXECUTION: {
- key: 'command-execution',
- text: 'There was an error executing the host command. Please try again later.',
- },
- CHAT_CONNECTION: {
- key: 'chat-connection',
- text: 'There was an issue connecting to chat. Please try again later.',
- }
-};
-
-export default class HostButton extends Module {
- constructor(...args) {
- super(...args);
-
- this.should_enable = true;
-
- this.inject('site');
- this.inject('site.fine');
- this.inject('site.chat');
- this.inject('site.twitch_data');
- this.inject('i18n');
- this.inject('metadata');
- this.inject('settings');
-
- this.settings.add('metadata.host-button', {
- default: true,
-
- ui: {
- path: 'Channel > Metadata >> Player',
- title: 'Host Button',
- description: 'Show a host button with the current hosted channel in the tooltip.',
- component: 'setting-check-box'
- },
-
- changed: () => {
- const ffz_user = this.site.getUser(),
- userLogin = ffz_user && ffz_user.login;
-
- if (userLogin)
- this.joinChannel(userLogin);
-
- this.metadata.updateMetadata('host');
- }
- });
- }
-
- isChannelHosted(channelLogin) {
- return this._last_hosted_channel === channelLogin;
- }
-
- sendHostUnhostCommand(channel) {
- if (!this._chat_con) {
- this._host_error = HOST_ERRORS.CHAT_CONNECTION;
- this._host_updating = false;
- return;
- }
-
- const ffz_user = this.site.getUser(),
- userLogin = ffz_user && ffz_user.login;
-
- const commandData = {channel: userLogin, username: channel};
-
- this._host_updating = true;
- this.metadata.updateMetadata('host');
-
- this._host_feedback = setTimeout(() => {
- if (this._last_hosted_channel === null) {
- this._host_error = HOST_ERRORS.COMMAND_EXECUTION;
- this._host_updating = false;
- this.metadata.updateMetadata('host');
- }
- }, 3000);
-
- if (this.isChannelHosted(channel)) {
- this._chat_con.commands.unhost.execute(commandData);
- } else {
- this._chat_con.commands.host.execute(commandData);
- }
- }
-
- joinChannel(channel) {
- if (this._chat_con) {
- if (this.settings.get('metadata.host-button') && !this._chat_con.session.channelstate[`#${channel}`]) {
- this._chat_con.joinChannel(channel);
- }
- }
- }
-
- hookIntoChatConnection(inst) {
- const userLogin = inst.props.currentUserLogin;
-
- if (this._chat_con) {
- this.joinChannel(userLogin);
- return;
- }
-
- this.on('tmi:host', e => {
- if (e.channel.substring(1) !== userLogin) return;
-
- clearTimeout(this._host_feedback);
- this._host_error = false;
- this._last_hosted_channel = e.target;
-
- this._host_updating = false;
- this.metadata.updateMetadata('host');
- });
-
- this.on('tmi:unhost', e => {
- if (e.channel.substring(1) !== userLogin) return;
-
- clearTimeout(this._host_feedback);
- this._host_error = false;
- this._last_hosted_channel = null;
-
- this._host_updating = false;
- this.metadata.updateMetadata('host');
- });
-
- const chatServiceClient = inst.client;
-
- this._chat_con = chatServiceClient;
- if (this.settings.get('metadata.host-button'))
- this.joinChannel(userLogin);
- }
-
- onEnable() {
- this.on('i18n:update', () => this.metadata.updateMetadata('host'));
-
- this.metadata.definitions.host = {
- order: 150,
- border: true,
- button: true,
- fade_in: true,
- modview: true,
-
- disabled: () => this._host_updating || this._host_error,
-
- click: data => {
- if ( data.channel )
- this.sendHostUnhostCommand(data.channel.login);
- },
-
- popup: async (data, tip) => {
- const vue = this.resolve('vue'),
- _host_options_vue = import(/* webpackChunkName: "host-options" */ './host-options.vue'),
- _autoHosts = this.fetchAutoHosts(),
- _autoHostSettings = this.fetchAutoHostSettings();
-
- const [, host_options_vue, autoHosts, autoHostSettings] = await Promise.all([vue.enable(), _host_options_vue, _autoHosts, _autoHostSettings]);
-
- this._auto_host_tip = tip;
- tip.element.classList.remove('tw-pd-1');
- tip.element.classList.add('ffz-balloon--lg');
- vue.component('host-options', host_options_vue.default);
- return this.buildAutoHostMenu(vue, autoHosts, autoHostSettings, data.channel);
- },
-
- label: data => {
- const ffz_user = this.site.getUser();
-
- if ( ! this.settings.get('metadata.host-button') || ! ffz_user || ! data.channel || data.channel.login === ffz_user.login )
- return;
-
- if ( data.channel.video && ! this.isChannelHosted(data.channel.login) )
- return;
-
- if ( this._host_updating )
- return this.i18n.t('metadata.host-button.updating', 'Updating...');
-
- return (this._last_hosted_channel && this.isChannelHosted(data.channel && data.channel.login))
- ? this.i18n.t('metadata.host-button.unhost', 'Unhost')
- : this.i18n.t('metadata.host-button.host', 'Host');
- },
-
- tooltip: () => {
- if (this._host_error) {
- return this.i18n.t(
- `metadata.host-button.tooltip.error.${this._host_error.key}`,
- this._host_error.text);
- } else {
- return this.i18n.t('metadata.host-button.tooltip',
- 'Currently hosting: {channel}',
- {
- channel: this._last_hosted_channel || this.i18n.t('metadata.host-button.tooltip.none', 'None')
- });
- }
- }
- };
-
- this.metadata.updateMetadata('host');
-
- this.chat.ChatService.ready((cls, instances) => {
- for(const inst of instances)
- this.hookIntoChatConnection(inst);
- })
-
- this.chat.ChatService.on('mount', this.hookIntoChatConnection, this);
- }
-
- buildAutoHostMenu(vue, hosts, autoHostSettings, data) {
- this._current_channel_id = data.id;
- this.activeTab = this.activeTab || 'auto-host';
-
- const vueEl = new vue.Vue({
- el: createElement('div'),
- render: h => this.vueHostMenu = h('host-options', {
- hosts,
- autoHostSettings,
- activeTab: this.activeTab,
-
- addedToHosts: this.currentRoomInHosts(),
- addToAutoHosts: () => this.addCurrentRoomToHosts(),
- rearrangeHosts: event => this.rearrangeHosts(event.oldIndex, event.newIndex),
- removeFromHosts: event => this.removeUserFromHosts(event),
- setActiveTab: tab => {
- this.vueHostMenu.data.activeTab = this.activeTab = tab;
- },
- updatePopper: () => {
- if (this._auto_host_tip) this._auto_host_tip.update();
- },
- updateCheckbox: e => {
- const t = e.target;
- let setting = t.dataset.setting,
- state = t.checked;
-
- if ( setting === 'enabled' )
- setting = 'isEnabled';
- else if ( setting === 'teamHost' )
- setting = 'willAutohostTeam';
- else if ( setting === 'strategy' )
- state = state ? 'RANDOM' : 'ORDERED';
- else if ( setting === 'deprioritizeVodcast' ) {
- setting = 'willPrioritizeAutohost';
- }
-
- this.updateAutoHostSetting(setting, state);
- }
- })
- });
-
- return vueEl.$el;
- }
-
- async fetchAutoHosts() {
- const user = this.site.getUser();
- if ( ! user )
- return;
-
- const result = await this.twitch_data.queryApollo(
- await import(/* webpackChunkName: 'host-options' */ './autohost_list.gql'),
- {
- id: user.id
- },
- {
- fetchPolicy: 'network-only'
- }
- );
-
- return this.autoHosts = get('data.user.autohostChannels.nodes', result);
- }
-
- async fetchAutoHostSettings() {
- const user = this.site.getUser();
- if ( ! user )
- return;
-
- const result = await this.twitch_data.queryApollo(
- await import(/* webpackChunkName: 'host-options' */ './autohost_settings.gql'),
- {
- id: user.id
- },
- {
- fetchPolicy: 'network-only'
- }
- );
-
- return this.autoHostSettings = get('data.user.autohostSettings', result);
- }
-
- queueHostUpdate() {
- if (this._host_update_timer) clearTimeout(this._host_update_timer);
-
- this._host_update_timer = setTimeout(() => {
- this._host_update_timer = undefined;
- this.updateAutoHosts(this.autoHosts);
- }, 1000);
- }
-
- rearrangeHosts(oldIndex, newIndex) {
- const host = this.autoHosts.splice(oldIndex, 1)[0];
- this.autoHosts.splice(newIndex, 0, host);
-
- this.queueHostUpdate();
- }
-
- currentRoomInHosts() {
- return this.getAutoHostIDs(this.autoHosts).includes(this._current_channel_id);
- }
-
- addCurrentRoomToHosts() {
- const newHosts = this.autoHosts.slice(0);
- newHosts.push({ id: this._current_channel_id});
-
- this.updateAutoHosts(newHosts);
- }
-
- removeUserFromHosts(event) {
- const id = event.target.closest('.ffz--host-user').dataset.id;
-
- const newHosts = [];
- for (let i = 0; i < this.autoHosts.length; i++) {
- if (this.autoHosts[i].id != id) newHosts.push(this.autoHosts[i]);
- }
-
- this.updateAutoHosts(newHosts);
- }
-
- getAutoHostIDs(hosts) { // eslint-disable-line class-methods-use-this
- const ids = [];
- if (hosts) {
- for (let i = 0; i < hosts.length; i++) {
- ids.push(hosts[i].id);
- }
- }
- return ids;
- }
-
- async updateAutoHosts(newHosts) {
- const user = this.site.getUser();
- if ( ! user )
- return;
-
- const autoHosts = this.getAutoHostIDs(newHosts);
-
- const result = await this.twitch_data.mutate({
- mutation: await import(/* webpackChunkName: 'host-options' */ './autohost_list_mutate.gql'),
- variables: {
- userID: user.id,
- channelIDs: autoHosts
- }
- });
-
- this.autoHosts = get('data.setAutohostChannels.user.autohostChannels.nodes', result);
- if (this.vueHostMenu) {
- this.vueHostMenu.data.hosts = this.autoHosts;
- this.vueHostMenu.data.addedToHosts = this.currentRoomInHosts();
- }
- }
-
- async updateAutoHostSetting(setting, newValue) {
- const user = this.site.getUser();
- if ( ! user )
- return;
-
- const result = await this.twitch_data.mutate({
- mutation: await import(/* webpackChunkName: 'host-options' */ './autohost_settings_mutate.gql'),
- variables: {
- userID: user.id,
- [setting]: newValue
- }
- });
-
- this.autoHostSettings = get('data.updateAutohostSettings.user.autohostSettings', result);
- if (this.vueHostMenu) {
- this.vueHostMenu.data.autoHostSettings = this.autoHostSettings;
- }
- }
-}
\ No newline at end of file
diff --git a/src/sites/twitch-twilight/modules/layout.js b/src/sites/twitch-twilight/modules/layout.js
index 79eade88..6615f71d 100644
--- a/src/sites/twitch-twilight/modules/layout.js
+++ b/src/sites/twitch-twilight/modules/layout.js
@@ -172,7 +172,7 @@ export default class Layout extends Module {
});
this.settings.add('layout.portrait-extra-height', {
- requires: ['context.new_channel', 'context.squad_bar', 'context.hosting', 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
+ requires: ['context.new_channel', 'context.squad_bar', /*'context.hosting',*/ 'context.ui.theatreModeEnabled', 'player.theatre.no-whispers', 'whispers.show', 'layout.minimal-navigation'],
process(ctx) {
let height = 0;
if ( ctx.get('context.ui.theatreModeEnabled') ) {
@@ -192,8 +192,8 @@ export default class Layout extends Module {
height += ctx.get('context.new_channel') ? 1 : 5;
- if ( ctx.get('context.hosting') )
- height += 4;
+ /*if ( ctx.get('context.hosting') )
+ height += 4;*/
}
return height;
diff --git a/src/sites/twitch-twilight/modules/player.jsx b/src/sites/twitch-twilight/modules/player.jsx
index 8e0a323e..1fdf17ec 100644
--- a/src/sites/twitch-twilight/modules/player.jsx
+++ b/src/sites/twitch-twilight/modules/player.jsx
@@ -196,7 +196,7 @@ export default class Player extends PlayerBase {
checkCarousel(inst) {
- if ( this.settings.get('channel.hosting.enable') )
+ /*if ( this.settings.get('channel.hosting.enable') )
return;
if ( inst.props?.playerType === 'channel_home_carousel' ) {
@@ -211,7 +211,7 @@ export default class Player extends PlayerBase {
events = inst.props.playerEvents;
this.stopPlayer(player, events, inst);
- }
+ }*/
}
diff --git a/src/sites/twitch-twilight/styles/main.scss b/src/sites/twitch-twilight/styles/main.scss
index 0f3a0321..bdefc036 100644
--- a/src/sites/twitch-twilight/styles/main.scss
+++ b/src/sites/twitch-twilight/styles/main.scss
@@ -9,7 +9,7 @@
@import 'fixes';
-@import 'host_options';
+//@import 'host_options';
@import 'featured_follow';
@import 'mod_card';
@import 'easteregg';
\ No newline at end of file