1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00

Emote Menu? Emote Menu.

* Add the emote menu.
* Add an option to replace the emote menu icon with the FFZ icon.
* Add icons to the icon font.
* Add a basic human duration formatting method to i18n.
* Add methods to the emotes module to get sets including the providers.
* Add a method to the emotes module to load an arbitrary set.
* Add a map to the emotes module for identifying providers.
* Add new events for when emote sets change.
* Add support for loading featured channel emotes.
* Add an option to suppress source sets in emote tooltips.
* Add an option to display a sellout line in emote tooltips.
* Remove emote menu from the WIP section of the home page of the menu.
* Fix a typo in rich content.
* Remove a bit of logging from fine.
* Add helper methods for set comparison and basic debouncing to utilities/object.
* Add constants for the emote menu.
* Add methods to show/hide a tooltip to the tooltip data object.
This commit is contained in:
SirStendec 2018-04-06 21:12:12 -04:00
parent 92130ebac4
commit e6e11fe562
23 changed files with 1423 additions and 26 deletions

View file

@ -10,6 +10,8 @@ import {has, timeout, SourcedSet} from 'utilities/object';
import {CLIENT_ID, API_SERVER} from 'utilities/constants';
const EXTRA_INVENTORY = [33563];
const MODIFIERS = {
59847: {
modifier_offset: '0 15px 15px 0',
@ -58,13 +60,21 @@ export default class Emotes extends Module {
this.inject('socket');
this.inject('settings');
this.twitch_inventory_sets = [];
this.twitch_inventory_sets = new Set(EXTRA_INVENTORY);
this.__twitch_emote_to_set = new Map;
this.__twitch_set_to_channel = new Map;
this.default_sets = new SourcedSet;
this.global_sets = new SourcedSet;
this.providers = new Map;
this.providers.set('featured', {
name: 'Featured',
i18n_key: 'emote-menu.featured',
sort_key: 75
})
this.emote_sets = {};
this._set_refs = {};
this._set_timers = {};
@ -98,11 +108,40 @@ export default class Emotes extends Module {
}
}
this.socket.on(':command:follow_sets', this.updateFollowSets, this);
this.loadGlobalSets();
this.loadTwitchInventory();
}
// ========================================================================
// Featured Sets
// ========================================================================
updateFollowSets(data) {
for(const room_login in data)
if ( has(data, room_login) ) {
const room = this.parent.getRoom(null, room_login, true),
new_sets = data[room_login] || [],
emote_sets = room.emote_sets,
providers = emote_sets._sources;
if ( providers && providers.has('featured') )
for(const item of providers.get('featured'))
if ( ! new_sets.includes(item) )
room.removeSet('featured', item);
for(const set_id of new_sets) {
room.addSet('featured', set_id);
if ( ! this.emote_sets[set_id] )
this.loadSet(set_id);
}
}
}
// ========================================================================
// Access
// ========================================================================
@ -124,6 +163,41 @@ export default class Emotes extends Module {
.map(set_id => this.emote_sets[set_id]);
}
_withSources(out, seen, emote_sets) { // eslint-disable-line class-methods-use-this
if ( ! emote_sets._sources )
return;
for(const [provider, data] of emote_sets._sources)
for(const item of data)
if ( ! seen.has(item) ) {
out.push([item, provider]);
seen.add(item);
}
return out;
}
getRoomSetIDsWithSources(user_id, user_login, room_id, room_login) {
const room = this.parent.getRoom(room_id, room_login, true),
room_user = room && room.getUser(user_id, user_login, true);
if ( ! room )
return [];
const out = [], seen = new Set;
this._withSources(out, seen, room.emote_sets);
if ( room_user )
this._withSources(out, seen, room_user);
return out;
}
getRoomSetsWithSources(user_id, user_login, room_id, room_login) {
return this.getRoomSetIDsWithSources(user_id, user_login, room_id, room_login)
.map(([set_id, source]) => [this.emote_sets[set_id], source]);
}
getRoomSetIDs(user_id, user_login, room_id, room_login) {
const room = this.parent.getRoom(room_id, room_login, true),
room_user = room && room.getUser(user_id, user_login, true);
@ -142,6 +216,22 @@ export default class Emotes extends Module {
.map(set_id => this.emote_sets[set_id]);
}
getGlobalSetIDsWithSources(user_id, user_login) {
const user = this.parent.getUser(user_id, user_login, true),
out = [], seen = new Set;
this._withSources(out, seen, this.default_sets);
if ( user )
this._withSources(out, seen, user.emote_sets);
return out;
}
getGlobalSetsWithSources(user_id, user_login) {
return this.getGlobalSetIDsWithSources(user_id, user_login)
.map(([set_id, source]) => [this.emote_sets[set_id], source]);
}
getGlobalSetIDs(user_id, user_login) {
const user = this.parent.getUser(user_id, user_login, true);
if ( ! user )
@ -171,28 +261,30 @@ export default class Emotes extends Module {
// ========================================================================
addDefaultSet(provider, set_id, data) {
const had_set = this.default_sets.includes(set_id);
let changed = false;
if ( ! this.default_sets.sourceIncludes(provider, set_id) ) {
this.default_sets.push(provider, set_id);
this.refSet(set_id);
changed = true;
}
if ( data )
this.loadSetData(set_id, data);
if ( ! had_set )
this.emit(':update-default-sets');
if ( changed )
this.emit(':update-default-sets', provider, set_id, true);
}
removeDefaultSet(provider, set_id) {
const had_set = this.default_sets.includes(set_id);
let changed = false;
if ( this.default_sets.sourceIncludes(provider, set_id) ) {
this.default_sets.remove(provider, set_id);
this.unrefSet(set_id);
changed = true;
}
if ( had_set && ! this.default_sets.includes(set_id) )
this.emit(':update-default-sets');
if ( changed )
this.emit(':update-default-sets', provider, set_id, false);
}
refSet(set_id) {
@ -252,7 +344,41 @@ export default class Emotes extends Module {
}
loadSetUsers(data) {
async loadSet(set_id, suppress_log = false, tries = 0) {
let response, data;
try {
response = await fetch(`${API_SERVER}/v1/set/${set_id}`)
} catch(err) {
tries++;
if ( tries < 10 )
return setTimeout(() => this.loadGlobalSets(tries), 500 * tries);
this.log.error(`Error loading data for set "${set_id}".`, err);
return false;
}
if ( ! response.ok )
return false;
try {
data = await response.json();
} catch(err) {
this.log.error(`Error parsing data for set "${set_id}".`, err);
return false;
}
const set = data.set;
if ( set )
this.loadSetData(set.id, set, suppress_log);
if ( data.users )
this.loadSetUsers(data.users);
return true;
}
loadSetUsers(data, suppress_log = false) {
for(const set_id in data)
if ( has(data, set_id) ) {
const emote_set = this.emote_sets[set_id],
@ -262,7 +388,8 @@ export default class Emotes extends Module {
this.parent.getUser(undefined, login)
.addSet('ffz-global', set_id);
this.log.info(`Added "${emote_set ? emote_set.title : set_id}" emote set to ${users.length} users.`);
if ( ! suppress_log )
this.log.info(`Added "${emote_set ? emote_set.title : set_id}" emote set to ${users.length} users.`);
}
}
@ -283,6 +410,7 @@ export default class Emotes extends Module {
new_ems = data.emotes = {},
css = [];
data.id = set_id;
data.emoticons = undefined;
for(const emote of ems) {
@ -413,7 +541,11 @@ export default class Emotes extends Module {
return;
}
this.twitch_inventory_sets = data.emoticon_sets ? Object.keys(data.emoticon_sets) : [];
const sets = this.twitch_inventory_sets = new Set(EXTRA_INVENTORY);
for(const set in data.emoticon_sets)
if ( has(data.emoticon_sets, set) )
sets.add(parseInt(set, 10));
this.log.info('Twitch Inventory Sets:', this.twitch_inventory_sets);
}