2017-11-13 01:23:39 -05:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// Room
|
|
|
|
// ============================================================================
|
|
|
|
|
2017-11-22 20:21:01 -05:00
|
|
|
import User from './user';
|
|
|
|
|
2019-12-10 20:46:33 -05:00
|
|
|
import {NEW_API, API_SERVER, WEBKIT_CSS as WEBKIT, IS_FIREFOX} from 'utilities/constants';
|
2017-11-13 01:23:39 -05:00
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
import {ManagedStyle} from 'utilities/dom';
|
2019-04-29 18:14:04 -04:00
|
|
|
import {has, SourcedSet, set_equals} from 'utilities/object';
|
2020-08-17 13:33:30 -04:00
|
|
|
import { getBadgeCategory, fixBadgeData } from './badges';
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
|
2017-11-22 20:21:01 -05:00
|
|
|
export default class Room {
|
2017-11-13 01:23:39 -05:00
|
|
|
constructor(manager, id, login) {
|
|
|
|
this._destroy_timer = null;
|
|
|
|
|
|
|
|
this.refs = new Set;
|
|
|
|
this.style = new ManagedStyle(`room--${login}`);
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
this.emote_sets = new SourcedSet;
|
2018-07-13 14:32:12 -04:00
|
|
|
this.badges = null;
|
2017-11-22 20:21:01 -05:00
|
|
|
this.users = {};
|
|
|
|
this.user_ids = {};
|
2017-11-13 01:23:39 -05:00
|
|
|
|
2018-05-10 19:56:39 -04:00
|
|
|
this.manager = manager;
|
|
|
|
this._id = id;
|
|
|
|
this.login = login;
|
|
|
|
|
|
|
|
if ( id )
|
|
|
|
this.manager.room_ids[id] = this;
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
this.manager.emit(':room-add', this);
|
|
|
|
this.load_data();
|
2017-11-13 01:23:39 -05:00
|
|
|
}
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
destroy() {
|
|
|
|
clearTimeout(this._destroy_timer);
|
|
|
|
this._destroy_timer = null;
|
2017-11-15 21:59:13 -05:00
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
this.destroyed = true;
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
this.manager.emit(':room-remove', this);
|
2017-11-14 04:11:43 -05:00
|
|
|
|
2018-04-11 20:48:02 -04:00
|
|
|
if ( this.users ) {
|
|
|
|
for(const user of Object.values(this.users))
|
|
|
|
if ( user )
|
|
|
|
user.destroy();
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
|
2018-04-11 20:48:02 -04:00
|
|
|
if ( this.user_ids ) {
|
|
|
|
for(const user of Object.values(this.user_ids))
|
|
|
|
if ( user )
|
|
|
|
user.destroy();
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
|
2018-09-24 14:33:06 -04:00
|
|
|
this.refs = null;
|
2018-04-07 19:08:20 -04:00
|
|
|
this.users = null;
|
|
|
|
this.user_ids = null;
|
2017-11-22 20:21:01 -05:00
|
|
|
|
2018-04-11 20:48:02 -04:00
|
|
|
if ( this.style ) {
|
|
|
|
this.style.destroy();
|
|
|
|
this.style = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this.emote_sets ) {
|
|
|
|
for(const set_id of this.emote_sets._cache)
|
|
|
|
this.manager.emotes.unrefSet(set_id);
|
|
|
|
|
|
|
|
this.emote_sets = null;
|
|
|
|
}
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
if ( this._login ) {
|
|
|
|
if ( this.manager.rooms[this._login] === this )
|
|
|
|
this.manager.rooms[this._login] = null;
|
|
|
|
|
2018-03-14 13:58:04 -04:00
|
|
|
this.manager.socket.unsubscribe(this, `room.${this.login}`);
|
2017-11-15 21:59:13 -05:00
|
|
|
}
|
|
|
|
|
2018-04-11 17:05:31 -04:00
|
|
|
if ( this.manager.room_ids[this._id] === this )
|
|
|
|
this.manager.room_ids[this._id] = null;
|
2017-11-15 21:59:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-24 14:33:06 -04:00
|
|
|
merge(other) {
|
|
|
|
if ( ! this.login && other.login )
|
|
|
|
this.login = other.login;
|
|
|
|
|
|
|
|
// We skip a lot of data, assuming that we got valid information from FFZ's API.
|
|
|
|
|
|
|
|
if ( other.refs )
|
|
|
|
for(const ref of other.refs)
|
|
|
|
this.ref(ref);
|
|
|
|
|
|
|
|
if ( other.emote_sets && other.emote_sets._sources ) {
|
|
|
|
for(const [provider, sets] of other.emote_sets._sources.entries()) {
|
|
|
|
for(const set_id of sets)
|
|
|
|
this.addSet(provider, set_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( other.data && ! this.data ) {
|
|
|
|
this.data = other.data;
|
|
|
|
if ( this.data.css )
|
|
|
|
this.style.set('css', this.data.css);
|
|
|
|
else
|
|
|
|
this.style.delete('css');
|
|
|
|
|
|
|
|
this.buildModBadgeCSS();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( other.badges && ! this.badges ) {
|
|
|
|
this.badges = other.badges;
|
|
|
|
this.buildBadgeCSS();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( other.bitsConfig && ! this.bitsConfig ) {
|
|
|
|
this.bitsConfig = other.bitsConfig;
|
|
|
|
this.buildBitsCSS();
|
|
|
|
}
|
|
|
|
|
|
|
|
const handled_users = new Set;
|
|
|
|
|
|
|
|
if ( other.users )
|
|
|
|
for(const user of Object.values(other.users)) {
|
|
|
|
if ( ! user.destroyed && ! handled_users.has(user) ) {
|
|
|
|
this.getUser(user.id, user.login).merge(user);
|
|
|
|
handled_users.add(user);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( other.user_ids )
|
|
|
|
for(const user of Object.values(other.user_ids)) {
|
|
|
|
if ( ! user.destroyed && ! handled_users.has(user) ) {
|
|
|
|
this.getUser(user.id, user.login).merge(user);
|
|
|
|
handled_users.add(user);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
get id() {
|
|
|
|
return this._id;
|
|
|
|
}
|
|
|
|
|
|
|
|
get login() {
|
|
|
|
return this._login;
|
|
|
|
}
|
|
|
|
|
|
|
|
set login(val) {
|
|
|
|
if ( this._login === val )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( this._login ) {
|
2017-11-16 00:25:51 -05:00
|
|
|
const old_room = this.manager.rooms[this._login];
|
2017-11-22 20:21:01 -05:00
|
|
|
if ( old_room === this ) {
|
|
|
|
this.manager.rooms[this._login] = null;
|
2018-03-14 13:58:04 -04:00
|
|
|
this.manager.socket.unsubscribe(this, `room.${this.login}`);
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
2017-11-15 21:59:13 -05:00
|
|
|
}
|
2017-11-13 01:23:39 -05:00
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
this._login = val;
|
|
|
|
if ( ! val )
|
|
|
|
return;
|
|
|
|
|
2017-11-16 00:25:51 -05:00
|
|
|
const old_room = this.manager.rooms[val];
|
|
|
|
if ( old_room && old_room !== this )
|
|
|
|
old_room.login = null;
|
|
|
|
|
2018-09-24 14:33:06 -04:00
|
|
|
// Make sure we didn't have a funky loop thing happen.
|
|
|
|
this._login = val;
|
2017-11-16 00:25:51 -05:00
|
|
|
this.manager.rooms[val] = this;
|
2018-03-14 13:58:04 -04:00
|
|
|
this.manager.socket.subscribe(this, `room.${val}`);
|
2017-11-15 21:59:13 -05:00
|
|
|
this.manager.emit(':room-update-login', this, val);
|
2017-11-13 01:23:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-15 17:19:22 -04:00
|
|
|
getUser(id, login, no_create, no_login, error = false) {
|
2018-04-07 19:08:20 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return null;
|
|
|
|
|
2017-11-22 20:21:01 -05:00
|
|
|
let user;
|
|
|
|
if ( id && typeof id === 'number' )
|
|
|
|
id = `${id}`;
|
|
|
|
|
2019-04-28 17:28:16 -04:00
|
|
|
if ( id && this.user_ids[id] )
|
2017-11-22 20:21:01 -05:00
|
|
|
user = this.user_ids[id];
|
|
|
|
|
2019-04-28 17:28:16 -04:00
|
|
|
else if ( login && this.users[login] && ! no_login )
|
2017-11-22 20:21:01 -05:00
|
|
|
user = this.users[login];
|
|
|
|
|
2018-04-15 17:19:22 -04:00
|
|
|
if ( user && user.destroyed )
|
|
|
|
user = null;
|
|
|
|
|
|
|
|
if ( ! user ) {
|
|
|
|
if ( no_create )
|
|
|
|
return null;
|
2017-11-22 20:21:01 -05:00
|
|
|
|
|
|
|
user = new User(this.manager, this, id, login);
|
2018-04-15 17:19:22 -04:00
|
|
|
}
|
2017-11-22 20:21:01 -05:00
|
|
|
|
|
|
|
if ( id && id !== user.id ) {
|
|
|
|
// If the ID isn't what we expected, something is very wrong here.
|
|
|
|
// Blame name changes.
|
2018-04-15 17:19:22 -04:00
|
|
|
if ( user.id ) {
|
|
|
|
this.manager.log.warn(`Data mismatch for user #${id} -- Stored ID: ${user.id} -- Login: ${login} -- Stored Login: ${user.login}`);
|
|
|
|
if ( error )
|
|
|
|
throw new Error('id mismatch');
|
|
|
|
|
|
|
|
// Remove the old reference if we're going with this.
|
|
|
|
if ( this.user_ids[user.id] === user )
|
|
|
|
this.user_ids[user.id] = null;
|
|
|
|
}
|
2017-11-22 20:21:01 -05:00
|
|
|
|
|
|
|
// Otherwise, we're just here to set the ID.
|
|
|
|
user._id = id;
|
|
|
|
this.user_ids[id] = user;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( login ) {
|
|
|
|
const other = this.users[login];
|
|
|
|
if ( other ) {
|
2018-09-24 14:33:06 -04:00
|
|
|
if ( other !== user && ! no_login ) {
|
2017-11-22 20:21:01 -05:00
|
|
|
// If the other has an ID, something weird happened. Screw it
|
|
|
|
// and just take over.
|
|
|
|
if ( other.id )
|
|
|
|
this.users[login] = user;
|
|
|
|
else {
|
2018-09-24 14:33:06 -04:00
|
|
|
user.merge(other);
|
|
|
|
other.destroy();
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
this.users[login] = user;
|
|
|
|
}
|
|
|
|
|
|
|
|
return user;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
// ========================================================================
|
|
|
|
// FFZ Data
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
async load_data(tries = 0) {
|
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
|
|
|
|
2018-04-12 02:29:43 -04:00
|
|
|
if ( this.manager.experiments.getAssignment('api_load') )
|
|
|
|
try {
|
2018-08-16 23:33:27 -04:00
|
|
|
fetch(`${NEW_API}/v1/room/${this.id ? `id/${this.id}` : this.login}`).catch(() => {});
|
2018-04-12 02:29:43 -04:00
|
|
|
} catch(err) { /* do nothing */ }
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
let response, data;
|
|
|
|
try {
|
2017-11-15 21:59:13 -05:00
|
|
|
response = await fetch(`${API_SERVER}/v1/room/${this.id ? `id/${this.id}` : this.login}`);
|
2017-11-13 01:23:39 -05:00
|
|
|
} catch(err) {
|
|
|
|
tries++;
|
|
|
|
if ( tries < 10 )
|
|
|
|
return setTimeout(() => this.load_data(tries), 500 * tries);
|
|
|
|
|
|
|
|
this.manager.log.error(`Error loading room data for ${this.id}:${this.login}`, err);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! response.ok )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
try {
|
|
|
|
data = await response.json();
|
|
|
|
} catch(err) {
|
|
|
|
this.manager.log.error(`Error parsing room data for ${this.id}:${this.login}`, err);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
const d = data.room,
|
2017-11-16 15:54:58 -05:00
|
|
|
id = `${d.twitch_id}`;
|
2017-11-15 21:59:13 -05:00
|
|
|
|
|
|
|
if ( ! this._id ) {
|
|
|
|
this._id = id;
|
|
|
|
this.manager.room_ids[id] = this;
|
|
|
|
|
|
|
|
} else if ( this._id !== id ) {
|
|
|
|
this.manager.log.warn(`Received data for ${this.id}:${this.login} with the wrong ID: ${id}`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-22 15:39:38 -05:00
|
|
|
if ( ! this.login )
|
|
|
|
this.login = d.id;
|
|
|
|
else if ( this.login !== d.id )
|
|
|
|
this.manager.log.warn(`Login mismatch for room ${this.id}:${this.login}. Got "${d.id}" from FFZ's API.`);
|
|
|
|
|
2017-11-15 21:59:13 -05:00
|
|
|
this.data = d;
|
|
|
|
|
|
|
|
if ( d.set )
|
|
|
|
this.emote_sets.set('main', d.set);
|
|
|
|
else
|
|
|
|
this.emote_sets.delete('main');
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
if ( data.sets )
|
|
|
|
for(const set_id in data.sets)
|
|
|
|
if ( has(data.sets, set_id) )
|
2017-11-16 15:54:58 -05:00
|
|
|
this.manager.emotes.loadSetData(set_id, data.sets[set_id]);
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
|
2018-03-15 03:31:30 -04:00
|
|
|
const badges = data.user_badges;
|
|
|
|
if ( badges )
|
|
|
|
for(const badge_id in badges)
|
|
|
|
if ( has(badges, badge_id) )
|
|
|
|
for(const user of badges[badge_id])
|
|
|
|
this.getUser(undefined, user).addBadge('ffz', badge_id);
|
|
|
|
|
|
|
|
|
|
|
|
if ( data.css )
|
|
|
|
this.style.set('css', data.css);
|
|
|
|
else
|
|
|
|
this.style.delete('css');
|
|
|
|
|
|
|
|
this.buildModBadgeCSS();
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-22 20:21:01 -05:00
|
|
|
// ========================================================================
|
|
|
|
// Emote Sets
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
addSet(provider, set_id, data) {
|
2018-04-07 19:08:20 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
|
|
|
|
2018-04-06 21:12:12 -04:00
|
|
|
let changed = false;
|
2017-11-22 20:21:01 -05:00
|
|
|
if ( ! this.emote_sets.sourceIncludes(provider, set_id) ) {
|
|
|
|
this.emote_sets.push(provider, set_id);
|
|
|
|
this.manager.emotes.refSet(set_id);
|
2018-04-06 21:12:12 -04:00
|
|
|
changed = true;
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( data )
|
|
|
|
this.manager.emotes.loadSetData(set_id, data);
|
2018-04-06 21:12:12 -04:00
|
|
|
|
|
|
|
if ( changed )
|
|
|
|
this.manager.emotes.emit(':update-room-sets', this, provider, set_id, true);
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
removeSet(provider, set_id) {
|
2018-04-07 19:08:20 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
|
|
|
|
2017-11-22 20:21:01 -05:00
|
|
|
if ( this.emote_sets.sourceIncludes(provider, set_id) ) {
|
|
|
|
this.emote_sets.remove(provider, set_id);
|
|
|
|
this.manager.emotes.unrefSet(set_id);
|
2018-04-06 21:12:12 -04:00
|
|
|
this.manager.emotes.emit(':update-room-sets', this, provider, set_id, false);
|
2017-11-22 20:21:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Life Cycle
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
ref(referrer) {
|
2019-05-16 14:46:26 -04:00
|
|
|
if ( ! this.refs )
|
|
|
|
throw new Error('Attempting to use destroyed Room');
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
clearTimeout(this._destroy_timer);
|
|
|
|
this._destroy_timer = null;
|
|
|
|
this.refs.add(referrer);
|
|
|
|
}
|
|
|
|
|
|
|
|
unref(referrer) {
|
2019-05-16 14:46:26 -04:00
|
|
|
if ( ! this.refs )
|
|
|
|
return;
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
this.refs.delete(referrer);
|
2019-05-16 14:46:26 -04:00
|
|
|
if ( ! this.refs.size && ! this._destroy_timer )
|
2017-11-13 01:23:39 -05:00
|
|
|
this._destroy_timer = setTimeout(() => this.destroy(), 5000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Badge Data
|
|
|
|
// ========================================================================
|
|
|
|
|
2019-05-08 22:47:38 -04:00
|
|
|
badgeCount() {
|
|
|
|
return this.badge_count || 0;
|
2019-05-03 19:30:46 -04:00
|
|
|
}
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
updateBadges(badges) {
|
2019-05-08 22:47:38 -04:00
|
|
|
this.badge_count = 0;
|
2019-05-03 19:30:46 -04:00
|
|
|
if ( ! Array.isArray(badges) )
|
2018-01-19 17:17:16 -05:00
|
|
|
this.badges = badges;
|
|
|
|
else {
|
2019-05-08 22:47:38 -04:00
|
|
|
// Rooms can have no badges, so we want to allow that.
|
|
|
|
const b = {};
|
|
|
|
for(const data of badges) {
|
|
|
|
const sid = data.setID,
|
2020-08-17 13:33:30 -04:00
|
|
|
bs = b[sid] = b[sid] || {
|
|
|
|
__cat: getBadgeCategory(sid)
|
|
|
|
};
|
|
|
|
|
|
|
|
fixBadgeData(data);
|
2020-06-30 19:48:46 -04:00
|
|
|
|
2019-05-08 22:47:38 -04:00
|
|
|
bs[data.version] = data;
|
|
|
|
this.badge_count++;
|
2018-01-19 17:17:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
this.badges = b;
|
|
|
|
}
|
|
|
|
|
2017-11-28 02:03:59 -05:00
|
|
|
this.buildBadgeCSS();
|
2017-11-13 01:23:39 -05:00
|
|
|
}
|
|
|
|
|
2018-03-15 03:31:30 -04:00
|
|
|
buildModBadgeCSS() {
|
2018-04-06 21:12:12 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
2018-04-07 19:08:20 -04:00
|
|
|
|
2018-03-15 03:31:30 -04:00
|
|
|
if ( ! this.data || ! this.data.mod_urls || ! this.manager.context.get('chat.badges.custom-mod') )
|
|
|
|
return this.style.delete('mod-badge');
|
|
|
|
|
|
|
|
const style = this.manager.context.get('chat.badges.style'),
|
|
|
|
masked = style > 5 ? `${WEBKIT}mask` : 'background',
|
|
|
|
has_image = style !== 3 && style !== 4;
|
|
|
|
|
|
|
|
if ( ! has_image )
|
|
|
|
return this.style.delete('mod-badge');
|
|
|
|
|
|
|
|
const urls = this.data.mod_urls,
|
|
|
|
image = `url("${urls[1]}")`;
|
|
|
|
|
|
|
|
let image_set;
|
|
|
|
if ( urls[2] || urls[4] )
|
|
|
|
image_set = `${WEBKIT}image-set(${image} 1x${urls[2] ? `, url("${urls[2]}") 2x` : ''}${urls[4] ? `, url("${urls[4]}") 4x` : ''})`
|
|
|
|
|
|
|
|
this.style.set('mod-badge', `[data-room-id="${this.id}"] .ffz-badge[data-badge="moderator"] {
|
|
|
|
${masked}-image: ${image};
|
|
|
|
${image_set ? `${masked}-image: ${image_set};` : ''}
|
|
|
|
}`);
|
|
|
|
}
|
|
|
|
|
2017-11-28 02:03:59 -05:00
|
|
|
buildBadgeCSS() {
|
2018-04-06 21:12:12 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
2018-04-07 19:08:20 -04:00
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
if ( ! this.badges )
|
|
|
|
return this.style.delete('badges');
|
|
|
|
|
2019-12-10 20:46:33 -05:00
|
|
|
const use_media = IS_FIREFOX && this.manager.context.get('chat.badges.media-queries'),
|
2020-08-17 13:33:30 -04:00
|
|
|
can_click = this.manager.context.get('chat.badges.clickable'),
|
2019-12-10 20:46:33 -05:00
|
|
|
out = [],
|
2017-11-13 01:23:39 -05:00
|
|
|
id = this.id;
|
|
|
|
|
2018-01-19 17:17:16 -05:00
|
|
|
for(const key in this.badges)
|
|
|
|
if ( has(this.badges, key) ) {
|
|
|
|
const versions = this.badges[key];
|
|
|
|
for(const version in versions)
|
|
|
|
if ( has(versions, version) ) {
|
|
|
|
const data = versions[version],
|
2019-12-10 20:46:33 -05:00
|
|
|
selector = `[data-room-id="${id}"] .ffz-badge[data-badge="${key}"][data-version="${version}"]`;
|
2018-01-19 17:17:16 -05:00
|
|
|
|
2019-12-10 20:46:33 -05:00
|
|
|
out.push(`${selector} {
|
2020-08-17 13:33:30 -04:00
|
|
|
${can_click && (data.click_action || data.click_url) ? 'cursor:pointer;' : ''}
|
2018-01-19 17:17:16 -05:00
|
|
|
background-color: transparent;
|
|
|
|
filter: none;
|
|
|
|
${WEBKIT}mask-image: none;
|
2018-03-15 03:31:30 -04:00
|
|
|
height: 1.8rem;
|
|
|
|
width: 1.8rem;
|
2018-01-19 17:17:16 -05:00
|
|
|
background-size: 1.8rem;
|
|
|
|
background-image: url("${data.image1x}");
|
|
|
|
background-image: ${WEBKIT}image-set(
|
|
|
|
url("${data.image1x}") 1x,
|
|
|
|
url("${data.image2x}") 2x,
|
|
|
|
url("${data.image4x}") 4x
|
|
|
|
);
|
|
|
|
}`);
|
2019-12-10 20:46:33 -05:00
|
|
|
|
|
|
|
if ( use_media ) {
|
|
|
|
out.push(`@media (min-resolution: 100dpi) and (max-resolution:199dpi) { ${selector} {
|
|
|
|
background-image: url("${data.image2x}");
|
|
|
|
}}`);
|
|
|
|
out.push(`@media (min-resolution: 200dpi) { ${selector} {
|
|
|
|
background-image: url("${data.image4x}");
|
|
|
|
}}`);
|
|
|
|
}
|
2018-01-19 17:17:16 -05:00
|
|
|
}
|
2017-11-13 01:23:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.style.set('badges', out.join('\n'));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Bits Data
|
|
|
|
// ========================================================================
|
|
|
|
|
2019-04-29 18:14:04 -04:00
|
|
|
updateBitsConfig(config, force) {
|
|
|
|
if ( ! force && this.bitsConfig && config ) {
|
|
|
|
const old_keys = new Set(Object.keys(this.bitsConfig)),
|
|
|
|
new_keys = new Set(Object.keys(config));
|
|
|
|
|
|
|
|
if ( set_equals(old_keys, new_keys) )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
this.bitsConfig = config;
|
2017-11-28 02:03:59 -05:00
|
|
|
this.buildBitsCSS();
|
2017-11-13 01:23:39 -05:00
|
|
|
}
|
|
|
|
|
2017-11-28 02:03:59 -05:00
|
|
|
buildBitsCSS() {
|
2018-04-06 21:12:12 -04:00
|
|
|
if ( this.destroyed )
|
|
|
|
return;
|
2018-04-07 19:08:20 -04:00
|
|
|
|
2017-11-13 01:23:39 -05:00
|
|
|
if ( ! this.bitsConfig )
|
|
|
|
return this.style.delete('bits');
|
|
|
|
|
|
|
|
const animated = this.manager.context.get('chat.bits.animated') ? 'animated' : 'static',
|
2020-03-25 19:05:38 -04:00
|
|
|
theme = this.manager.context.get('theme.is-dark') ? 'dark' : 'light',
|
|
|
|
tt_theme = this.manager.context.get('theme.tooltips-dark') ? 'dark' : 'light',
|
2017-11-13 01:23:39 -05:00
|
|
|
out = [];
|
|
|
|
|
|
|
|
for(const key in this.bitsConfig)
|
|
|
|
if ( has(this.bitsConfig, key) ) {
|
|
|
|
const action = this.bitsConfig[key],
|
|
|
|
prefix = action.prefix.toLowerCase(),
|
|
|
|
tiers = action.tiers,
|
|
|
|
l = tiers.length;
|
|
|
|
|
|
|
|
for(let i=0; i < l; i++) {
|
|
|
|
const images = tiers[i].images[theme][animated],
|
2017-11-28 02:03:59 -05:00
|
|
|
tt_images = tiers[i].images[tt_theme][animated];
|
2017-11-13 01:23:39 -05:00
|
|
|
|
|
|
|
out.push(`.ffz-cheer[data-prefix="${prefix}"][data-tier="${i}"] {
|
2020-03-25 19:05:38 -04:00
|
|
|
color: ${tiers[i].color || 'inherit'};
|
2017-11-13 01:23:39 -05:00
|
|
|
background-image: url("${images[1]}");
|
|
|
|
background-image: ${WEBKIT}image-set(
|
|
|
|
url("${images[1]}") 1x,
|
|
|
|
url("${images[2]}") 2x,
|
|
|
|
url("${images[4]}") 4x
|
|
|
|
);
|
|
|
|
}
|
|
|
|
.ffz__tooltip .ffz-cheer[data-prefix="${prefix}"][data-tier="${i}"] {
|
2017-11-28 02:03:59 -05:00
|
|
|
background-image: url("${tt_images[1]}");
|
2017-11-13 01:23:39 -05:00
|
|
|
background-image: ${WEBKIT}image-set(
|
2017-11-28 02:03:59 -05:00
|
|
|
url("${tt_images[1]}") 1x,
|
|
|
|
url("${tt_images[2]}") 2x,
|
|
|
|
url("${tt_images[4]}") 4x
|
2017-11-13 01:23:39 -05:00
|
|
|
);
|
|
|
|
}
|
|
|
|
.ffz-cheer-preview[data-prefix="${prefix}"][data-tier="${i}"] {
|
2017-11-28 02:03:59 -05:00
|
|
|
background-image: url("${tt_images[4]}");
|
2017-11-13 01:23:39 -05:00
|
|
|
}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.style.set('bits', out.join('\n'));
|
|
|
|
}
|
|
|
|
}
|