1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-10-11 13:41:57 +00:00
* Added: Setting to disable Channel Hosting.
* Added: Setting to hide streams tagged as Promoted from the directory.
* Fixed: Tool-tips not appearing when an element is open in fullscreen.
* Fixed: Bug when destroying a tool-tip instance.
* Fixed: Directory cards not updating with FFZ features on the front page.

* API Added: `Subpump` module for manipulating Twitch PubSub events.
* API Changed: Add-Ons can now define custom settings profile filters.
This commit is contained in:
SirStendec 2020-07-18 15:44:02 -04:00
parent ced61d2bfc
commit 22c60050e0
17 changed files with 356 additions and 96 deletions

View file

@ -0,0 +1,151 @@
'use strict';
// ============================================================================
// Subpump
// It controls Twitch PubSub.
// ============================================================================
import Module from 'utilities/module';
import { FFZEvent } from 'utilities/events';
export class PubSubEvent extends FFZEvent {
constructor(data) {
super(data);
this._obj = undefined;
this._changed = false;
}
markChanged() {
this._changed = true;
}
get topic() {
return this.event.topic;
}
get message() {
if ( this._obj === undefined )
this._obj = JSON.parse(this.event.message);
return this._obj;
}
set message(val) {
this._obj = val;
this._changed = true;
}
}
export default class Subpump extends Module {
constructor(...args) {
super(...args);
this.instance = null;
}
onEnable(tries = 0) {
const instances = window.__Twitch__pubsubInstances;
if ( ! instances ) {
if ( tries > 10 )
this.log.warn('Unable to find PubSub.');
else
new Promise(r => setTimeout(r, 50)).then(() => this.onEnable(tries + 1));
return;
}
for(const [key, val] of Object.entries(instances))
if ( val?._client ) {
if ( this.instance ) {
this.log.warn('Multiple PubSub instances detected. Things might act weird.');
continue;
}
this.instance = val;
this.hookClient(val._client);
}
if ( ! this.instance )
this.log.warn('Unable to find a PubSub instance.');
}
hookClient(client) {
const t = this,
orig_message = client._onMessage;
client._unbindPrimary(client._primarySocket);
client._onMessage = function(e) {
try {
if ( e.type === 'MESSAGE' && e.data?.topic ) {
const raw_topic = e.data.topic,
idx = raw_topic.indexOf('.'),
prefix = idx === -1 ? raw_topic : raw_topic.slice(0, idx),
trail = idx === -1 ? '' : raw_topic.slice(idx + 1);
const event = new PubSubEvent({
prefix,
trail,
event: e.data
});
t.emit(':pubsub-message', event);
if ( event.defaultPrevented )
return;
if ( event._changed )
e.data.message = JSON.stringify(event._obj);
}
} catch(err) {
this.log.error('Error processing PubSub event.', err);
}
return orig_message.call(this, e);
};
client._bindPrimary(client._primarySocket);
const listener = client._listens,
orig_on = listener.on,
orig_off = listener.off;
listener.on = function(topic, fn, ctx) {
const has_topic = !! listener._events?.[topic],
out = orig_on.call(this, topic, fn, ctx);
if ( ! has_topic )
t.emit(':add-topic', topic)
return out;
}
listener.off = function(topic, fn) {
const has_topic = !! listener._events?.[topic],
out = orig_off.call(this, topic, fn);
if ( has_topic && ! listener._events?.[topic] )
t.emit(':remove-topic', topic);
return out;
}
}
inject(topic, message) {
const listens = this.instance?._client?._listens;
if ( ! listens )
throw new Error('No PubSub instance available');
listens._trigger(topic, JSON.stringify(message));
}
get topics() {
const events = this.instance?._client?._listens._events;
if ( ! events )
return [];
return Object.keys(events);
}
}

View file

@ -105,8 +105,8 @@ export class Tooltip {
if ( this.options.manual ) {
// Do nothing~!
} else if ( this.live || this.elements.size > 5 ) {
parent.removeEventListener('mouseover', this._onMouseOver);
parent.removeEventListener('mouseout', this._onMouseOut);
this.parent.removeEventListener('mouseover', this._onMouseOver);
this.parent.removeEventListener('mouseout', this._onMouseOut);
} else
for(const el of this.elements) {
el.removeEventListener('mouseenter', this._onMouseOver);
@ -119,6 +119,7 @@ export class Tooltip {
this.hide(tip);
el[this._accessor] = null;
el._ffz_tooltip = null;
}
this.elements = null;
@ -205,12 +206,18 @@ export class Tooltip {
target = tip.target;
this.elements.add(target);
target._ffz_tooltip = tip;
// Set this early in case content uses it early.
tip._promises = [];
tip.waitForDom = () => tip.element ? Promise.resolve() : new Promise(s => {tip._promises.push(s)});
tip.update = () => tip._update(); // tip.popper && tip.popper.scheduleUpdate();
tip.show = () => this.show(tip);
tip.show = () => {
let tip = target[this._accessor];
if ( ! tip )
tip = target[this._accessor] = {target};
this.show(tip);
};
tip.hide = () => this.hide(tip);
tip.rerender = () => {
if ( tip.visible ) {
@ -385,6 +392,10 @@ export class Tooltip {
if ( this.live && this.elements )
this.elements.delete(tip.target);
if ( tip.target._ffz_tooltip === tip )
tip.target._ffz_tooltip = null;
tip.target[this._accessor] = null;
tip._update = tip.rerender = tip.update = noop;
tip.element = null;
tip.visible = false;