mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-10 08:10:52 +00:00
4.24.0
* Changed: The settings for Animated Emotes and chat user color correction now default to enabled or disabled based on your vanilla Twitch settings. * Changed: Strip automatic error reporting from builds till it can be fixed. * Fixed: Native viewer count and uptime not hiding correctly when a stream goes live. * API Added: Settings can now depend on `localStorage` values by using `ls.{name}` keys for JSON or `ls.raw.{name}` for raw strings. * Maintenance: Update dependencies.
This commit is contained in:
parent
ce38c3c251
commit
2340992977
17 changed files with 2689 additions and 1438 deletions
3639
package-lock.json
generated
3639
package-lock.json
generated
File diff suppressed because it is too large
Load diff
72
package.json
72
package.json
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.23.2",
|
"version": "4.24.0",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
@ -25,40 +25,40 @@
|
||||||
"font:update": "node bin/update_fonts"
|
"font:update": "node bin/update_fonts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.10.4",
|
"@babel/core": "^7.14.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.12.13",
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.10.4",
|
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
|
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.10.4",
|
"@babel/plugin-transform-react-jsx": "^7.14.5",
|
||||||
"@ffz/fontello-cli": "^1.0.4",
|
"@ffz/fontello-cli": "^1.0.4",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.2.2",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^5.1.1",
|
"copy-webpack-plugin": "^5.1.2",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^3.1.0",
|
"css-loader": "^3.6.0",
|
||||||
"eslint": "^7.3.1",
|
"eslint": "^7.28.0",
|
||||||
"eslint-plugin-react": "^7.20.3",
|
"eslint-plugin-react": "^7.24.0",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"extract-loader": "^2.0.1",
|
"extract-loader": "^2.0.1",
|
||||||
"file-loader": "^4.1.0",
|
"file-loader": "^4.3.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"jszip": "^3.6.0",
|
"jszip": "^3.6.0",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
"sass-loader": "^7.1.0",
|
|
||||||
"raw-loader": "^3.1.0",
|
"raw-loader": "^3.1.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"semver": "^7.3.2",
|
"sass-loader": "^7.1.0",
|
||||||
"terser-webpack-plugin": "^3.0.6",
|
"semver": "^7.3.5",
|
||||||
"vue": "^2.6.11",
|
"terser-webpack-plugin": "^3.1.0",
|
||||||
"vue-loader": "^15.8.3",
|
"vue": "^2.6.14",
|
||||||
|
"vue-loader": "^15.9.7",
|
||||||
"vue-observe-visibility": "^0.4.6",
|
"vue-observe-visibility": "^0.4.6",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.6.14",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.11.2",
|
||||||
"webpack-manifest-plugin": "^2.2.0",
|
"webpack-manifest-plugin": "^2.2.0",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^4.2.2"
|
||||||
},
|
},
|
||||||
|
@ -71,27 +71,27 @@
|
||||||
"chartjs": "^0.3.24",
|
"chartjs": "^0.3.24",
|
||||||
"chartjs-plugin-waterfall": "^1.0.3",
|
"chartjs-plugin-waterfall": "^1.0.3",
|
||||||
"chartjs-plugin-zoom": "^0.7.7",
|
"chartjs-plugin-zoom": "^0.7.7",
|
||||||
"crypto-js": "^3.1.9-1",
|
"crypto-js": "^3.3.0",
|
||||||
"dayjs": "^1.8.29",
|
"dayjs": "^1.10.5",
|
||||||
"displacejs": "^1.4.1",
|
"displacejs": "^1.4.1",
|
||||||
"emoji-regex": "^9.0.0",
|
"emoji-regex": "^9.2.2",
|
||||||
"file-saver": "^2.0.1",
|
"file-saver": "^2.0.5",
|
||||||
"graphql": "^15.2.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-tag": "^2.10.3",
|
"graphql-tag": "^2.12.4",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"markdown-it": "^11.0.0",
|
"markdown-it": "^11.0.1",
|
||||||
"markdown-it-link-attributes": "^3.0.0",
|
"markdown-it-link-attributes": "^3.0.0",
|
||||||
"mnemonist": "^0.38.0",
|
"mnemonist": "^0.38.3",
|
||||||
"path-to-regexp": "^3.0.0",
|
"path-to-regexp": "^3.2.0",
|
||||||
"popper.js": "^1.14.3",
|
"popper.js": "^1.16.1",
|
||||||
"raven-js": "^3.24.2",
|
"raven-js": "^3.24.2",
|
||||||
"react": "^16.13.1",
|
"react": "^16.14.0",
|
||||||
"safe-regex": "^2.1.1",
|
"safe-regex": "^2.1.1",
|
||||||
"sortablejs": "^1.10.2",
|
"sortablejs": "^1.13.0",
|
||||||
"sourcemapped-stacktrace": "^1.1.11",
|
"sourcemapped-stacktrace": "^1.1.11",
|
||||||
"text-diff": "^1.0.1",
|
"text-diff": "^1.0.1",
|
||||||
"vue-clickaway": "^2.2.2",
|
"vue-clickaway": "^2.2.2",
|
||||||
"vue-color": "^2.7.1",
|
"vue-color": "^2.8.1",
|
||||||
"vuedraggable": "^2.23.2"
|
"vuedraggable": "^2.24.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import RavenLogger from './raven';
|
|
||||||
|
|
||||||
import Logger from 'utilities/logging';
|
import Logger from 'utilities/logging';
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
|
||||||
|
@ -23,12 +21,10 @@ class FFZBridge extends Module {
|
||||||
this.__modules.core = this;
|
this.__modules.core = this;
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// Error Reporting and Logging
|
// Logging
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
this.inject('raven', RavenLogger);
|
this.log = new Logger(null, null, null);
|
||||||
|
|
||||||
this.log = new Logger(null, null, null, this.raven);
|
|
||||||
this.log.label = 'FFZBridge';
|
this.log.label = 'FFZBridge';
|
||||||
this.log.init = true;
|
this.log.init = true;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import RavenLogger from './raven';
|
//import RavenLogger from './raven';
|
||||||
|
|
||||||
import Logger from 'utilities/logging';
|
import Logger from 'utilities/logging';
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
@ -35,9 +35,9 @@ class FrankerFaceZ extends Module {
|
||||||
// Error Reporting and Logging
|
// Error Reporting and Logging
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
this.inject('raven', RavenLogger);
|
//this.inject('raven', RavenLogger);
|
||||||
|
|
||||||
this.log = new Logger(null, null, null, this.raven);
|
this.log = new Logger(null, null, null); //, this.raven);
|
||||||
this.log.label = 'FFZClips';
|
this.log.label = 'FFZClips';
|
||||||
this.log.init = true;
|
this.log.init = true;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import RavenLogger from './raven';
|
//import RavenLogger from './raven';
|
||||||
|
|
||||||
import Logger from 'utilities/logging';
|
import Logger from 'utilities/logging';
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
@ -40,9 +40,9 @@ class FrankerFaceZ extends Module {
|
||||||
// Error Reporting and Logging
|
// Error Reporting and Logging
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
this.inject('raven', RavenLogger);
|
//this.inject('raven', RavenLogger);
|
||||||
|
|
||||||
this.log = new Logger(null, null, null, this.raven);
|
this.log = new Logger(null, null, null); //, this.raven);
|
||||||
this.log.init = true;
|
this.log.init = true;
|
||||||
|
|
||||||
this.core_log = this.log.get('core');
|
this.core_log = this.log.get('core');
|
||||||
|
|
|
@ -1014,12 +1014,23 @@ export default class Chat extends Module {
|
||||||
|
|
||||||
|
|
||||||
this.settings.add('chat.adjustment-mode', {
|
this.settings.add('chat.adjustment-mode', {
|
||||||
default: 1,
|
default: null,
|
||||||
|
process(ctx, val) {
|
||||||
|
if ( val == null )
|
||||||
|
return (ctx.get('ls.useHighContrastColors') ?? true) ? 1 : 0;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
},
|
||||||
|
requires: ['ls.useHighContrastColors'],
|
||||||
ui: {
|
ui: {
|
||||||
path: 'Chat > Appearance >> Colors',
|
path: 'Chat > Appearance >> Colors',
|
||||||
title: 'Adjustment',
|
title: 'Adjustment',
|
||||||
description: 'Alter user colors to ensure that they remain readable.',
|
description: 'Alter user colors to ensure that they remain readable.',
|
||||||
|
|
||||||
|
default(ctx) {
|
||||||
|
return (ctx.get('ls.useHighContrastColors') ?? true) ? 1 : 0;
|
||||||
|
},
|
||||||
|
|
||||||
component: 'setting-select-box',
|
component: 'setting-select-box',
|
||||||
|
|
||||||
data: [
|
data: [
|
||||||
|
@ -1079,12 +1090,22 @@ export default class Chat extends Module {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.settings.add('chat.emotes.animated', {
|
this.settings.add('chat.emotes.animated', {
|
||||||
default: 1,
|
default: null,
|
||||||
|
requires: ['ls.emoteAnimationsEnabled'],
|
||||||
|
process(ctx, val) {
|
||||||
|
if ( val == null )
|
||||||
|
return (ctx.get('ls.emoteAnimationsEnabled') ?? true) ? 1 : 0;
|
||||||
|
return val;
|
||||||
|
},
|
||||||
ui: {
|
ui: {
|
||||||
path: 'Chat > Appearance >> Emotes',
|
path: 'Chat > Appearance >> Emotes',
|
||||||
sort: -50,
|
sort: -50,
|
||||||
title: 'Animated Emotes',
|
title: 'Animated Emotes',
|
||||||
|
|
||||||
|
default(ctx) {
|
||||||
|
return (ctx.get('ls.emoteAnimationsEnabled') ?? true) ? 1 : 0;
|
||||||
|
},
|
||||||
|
|
||||||
getExtraTerms: () => GIF_TERMS,
|
getExtraTerms: () => GIF_TERMS,
|
||||||
|
|
||||||
description: 'This controls whether or not animated emotes are allowed to play in chat. When this is `Disabled`, emotes will appear as static images. Setting this to `Enable on Hover` may cause performance issues.',
|
description: 'This controls whether or not animated emotes are allowed to play in chat. When this is `Disabled`, emotes will appear as static images. Setting this to `Enable on Hover` may cause performance issues.',
|
||||||
|
|
|
@ -1333,10 +1333,15 @@ export const AddonEmotes = {
|
||||||
|
|
||||||
if ( emote_set ) {
|
if ( emote_set ) {
|
||||||
const type = emote_set.type;
|
const type = emote_set.type;
|
||||||
if ( type === EmoteTypes.Global )
|
if ( type === EmoteTypes.Global ) {
|
||||||
source = this.i18n.t('emote.global', 'Twitch Global');
|
if ( emote_set.owner?.login ) {
|
||||||
|
source = this.i18n.t('tooltip.channel', 'Channel: {source}', {
|
||||||
|
source: emote_set.owner.displayName || emote_set.owner.login
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
source = this.i18n.t('emote.global', 'Twitch Global');
|
||||||
|
|
||||||
else if ( type === EmoteTypes.BitsTier ) {
|
} else if ( type === EmoteTypes.BitsTier ) {
|
||||||
source = this.i18n.t('emote.bits', 'Twitch Bits Reward');
|
source = this.i18n.t('emote.bits', 'Twitch Bits Reward');
|
||||||
if ( emote_set.owner?.login )
|
if ( emote_set.owner?.login )
|
||||||
source = this.i18n.t('emote.bits-owner', '{source}\nChannel: {channel}', {
|
source = this.i18n.t('emote.bits-owner', '{source}\nChannel: {channel}', {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import RavenLogger from './raven';
|
//import RavenLogger from './raven';
|
||||||
|
|
||||||
import Logger from 'utilities/logging';
|
import Logger from 'utilities/logging';
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
|
@ -32,9 +32,9 @@ class FrankerFaceZ extends Module {
|
||||||
// Error Reporting and Logging
|
// Error Reporting and Logging
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
||||||
this.inject('raven', RavenLogger);
|
//this.inject('raven', RavenLogger);
|
||||||
|
|
||||||
this.log = new Logger(null, null, null, this.raven);
|
this.log = new Logger(null, null, null); //, this.raven);
|
||||||
this.log.label = 'FFZPlayer';
|
this.log.label = 'FFZPlayer';
|
||||||
this.log.init = true;
|
this.log.init = true;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ export default class SettingsContext extends EventEmitter {
|
||||||
if ( context )
|
if ( context )
|
||||||
this._updateContext(context, undefined, undefined, new Set);*/
|
this._updateContext(context, undefined, undefined, new Set);*/
|
||||||
|
|
||||||
|
this.__ls_listening = false;
|
||||||
|
this.__ls_wanted = new Map;
|
||||||
|
|
||||||
this.__cache = new Map;
|
this.__cache = new Map;
|
||||||
this.__meta = new Map;
|
this.__meta = new Map;
|
||||||
this.__profiles = [];
|
this.__profiles = [];
|
||||||
|
@ -98,6 +101,34 @@ export default class SettingsContext extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Local Storage Handling
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
_watchLS() {
|
||||||
|
if ( this.__ls_watched )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.__ls_watched = true;
|
||||||
|
this.manager.on(':ls-update', this._onLSUpdate, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_unwatchLS() {
|
||||||
|
if ( ! this.__ls_watched )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.__ls_watched = false;
|
||||||
|
this.manager.off(':ls-update', this._onLSUpdate, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onLSUpdate(key) {
|
||||||
|
const keys = this.__ls_wanted.get(`ls.${key}`);
|
||||||
|
if ( keys )
|
||||||
|
for(const key of keys)
|
||||||
|
this._update(key, key, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// State Construction
|
// State Construction
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
@ -340,7 +371,7 @@ export default class SettingsContext extends EventEmitter {
|
||||||
const definition = this.manager.definitions.get(key);
|
const definition = this.manager.definitions.get(key);
|
||||||
if ( definition && definition.required_by )
|
if ( definition && definition.required_by )
|
||||||
for(const req_key of definition.required_by)
|
for(const req_key of definition.required_by)
|
||||||
if ( ! req_key.startsWith('context.') )
|
if ( ! req_key.startsWith('context.') && ! req_key.startsWith('ls.') )
|
||||||
this._update(req_key, initial, Array.from(visited));
|
this._update(req_key, initial, Array.from(visited));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +413,15 @@ export default class SettingsContext extends EventEmitter {
|
||||||
|
|
||||||
if ( definition.requires )
|
if ( definition.requires )
|
||||||
for(const req_key of definition.requires)
|
for(const req_key of definition.requires)
|
||||||
if ( ! req_key.startsWith('context.') && ! this.__cache.has(req_key) )
|
if ( req_key.startsWith('ls.') ) {
|
||||||
|
this._watchLS();
|
||||||
|
let keys = this.__ls_wanted.get(req_key);
|
||||||
|
if ( ! keys )
|
||||||
|
this.__ls_wanted.set(req_key, keys = new Set);
|
||||||
|
|
||||||
|
keys.add(key);
|
||||||
|
|
||||||
|
} else if ( ! req_key.startsWith('context.') && ! this.__cache.has(req_key) )
|
||||||
this._get(req_key, initial, Array.from(visited));
|
this._get(req_key, initial, Array.from(visited));
|
||||||
|
|
||||||
if ( definition.process )
|
if ( definition.process )
|
||||||
|
@ -432,6 +471,9 @@ export default class SettingsContext extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key) {
|
get(key) {
|
||||||
|
if ( key.startsWith('ls.') )
|
||||||
|
return this.manager.getLS(key.slice(3));
|
||||||
|
|
||||||
if ( key.startsWith('context.') )
|
if ( key.startsWith('context.') )
|
||||||
//return this.__context[key.slice(8)];
|
//return this.__context[key.slice(8)];
|
||||||
return getter(key.slice(8), this.__context);
|
return getter(key.slice(8), this.__context);
|
||||||
|
@ -453,6 +495,9 @@ export default class SettingsContext extends EventEmitter {
|
||||||
|
|
||||||
|
|
||||||
uses(key) {
|
uses(key) {
|
||||||
|
if ( key.startsWith('ls.') )
|
||||||
|
return null;
|
||||||
|
|
||||||
if ( key.startsWith('context.') )
|
if ( key.startsWith('context.') )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,12 @@ export default class SettingsManager extends Module {
|
||||||
}
|
}
|
||||||
} catch(err) { /* no-op */ }
|
} catch(err) { /* no-op */ }
|
||||||
|
|
||||||
|
// Local Storage
|
||||||
|
this.__ls_scheduled = new Set;
|
||||||
|
this.__ls_cache = new Map;
|
||||||
|
this.__ls_hooked = false;
|
||||||
|
this._updateLS = this._updateLS.bind(this);
|
||||||
|
|
||||||
// State
|
// State
|
||||||
this.__contexts = [];
|
this.__contexts = [];
|
||||||
this.__profiles = [];
|
this.__profiles = [];
|
||||||
|
@ -277,6 +283,107 @@ export default class SettingsManager extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// LocalStorage Management
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
_updateLSKey(key) {
|
||||||
|
if ( this.__ls_cache.has(key) || this.__ls_cache.has(`raw.${key}`) ) {
|
||||||
|
this.__ls_scheduled.add(key);
|
||||||
|
if ( ! this.__ls_timer )
|
||||||
|
this.__ls_timer = setTimeout(this._updateLS, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_hookLS() {
|
||||||
|
if ( this.__ls_hooked )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.__ls_hooked = true;
|
||||||
|
const original = localStorage.setItem,
|
||||||
|
t = this;
|
||||||
|
|
||||||
|
localStorage.setItem = function(key, ...args) {
|
||||||
|
// Guard this because we never want to break
|
||||||
|
// localStorage, even if something really
|
||||||
|
// weird happens.
|
||||||
|
try {
|
||||||
|
t._updateLSKey(key);
|
||||||
|
} catch(err) { /* no-op */ }
|
||||||
|
|
||||||
|
return original.call(this, key, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handleLSEvent = this._handleLSEvent.bind(this);
|
||||||
|
window.addEventListener('storage', this._handleLSEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleLSEvent(event) {
|
||||||
|
if ( event.storageArea === localStorage )
|
||||||
|
this._updateLSKey(event.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateLS() {
|
||||||
|
clearTimeout(this.__ls_timer);
|
||||||
|
this.__ls_timer = null;
|
||||||
|
const keys = this.__ls_scheduled;
|
||||||
|
this.__ls_scheduled = new Set;
|
||||||
|
|
||||||
|
for(const key of keys) {
|
||||||
|
const has_value = this.__ls_cache.has(key),
|
||||||
|
raw_key = `raw.${key}`,
|
||||||
|
has_raw = this.__ls_cache.has(raw_key);
|
||||||
|
|
||||||
|
if ( ! has_raw && ! has_value )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const raw = localStorage.getItem(key);
|
||||||
|
|
||||||
|
if ( has_raw ) {
|
||||||
|
this.__ls_cache.set(raw_key, raw);
|
||||||
|
this.emit(':ls-update', raw_key, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( has_value ) {
|
||||||
|
let value;
|
||||||
|
if ( raw )
|
||||||
|
try {
|
||||||
|
value = JSON.parse(raw);
|
||||||
|
} catch(err) {
|
||||||
|
this.log.warn(`Unable to parse localStorage value as JSON for "${key}"`, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__ls_cache.set(key, value);
|
||||||
|
this.emit(':ls-update', key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getLS(key) {
|
||||||
|
if ( this.__ls_cache.has(key) )
|
||||||
|
return this.__ls_cache.get(key);
|
||||||
|
|
||||||
|
if ( ! this.__ls_hooked )
|
||||||
|
this._hookLS();
|
||||||
|
|
||||||
|
const is_raw = key.startsWith('raw.'),
|
||||||
|
raw = localStorage.getItem(is_raw ? key.slice(4) : key);
|
||||||
|
|
||||||
|
let value;
|
||||||
|
if ( is_raw )
|
||||||
|
value = raw;
|
||||||
|
else
|
||||||
|
try {
|
||||||
|
value = JSON.parse(raw);
|
||||||
|
} catch(err) {
|
||||||
|
this.log.warn(`Unable to parse localStorage value as JSON for "${key}"`, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__ls_cache.set(key, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
// Backup and Restore
|
// Backup and Restore
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
|
|
@ -583,6 +583,7 @@ export default class Input extends Module {
|
||||||
return {emotes: [], length: 0};
|
return {emotes: [], length: 0};
|
||||||
|
|
||||||
const out = [],
|
const out = [],
|
||||||
|
anim = this.chat.context.get('chat.emotes.animated') > 0,
|
||||||
hidden_sets = this.settings.provider.get('emote-menu.hidden-sets'),
|
hidden_sets = this.settings.provider.get('emote-menu.hidden-sets'),
|
||||||
has_hidden = Array.isArray(hidden_sets) && hidden_sets.length > 0,
|
has_hidden = Array.isArray(hidden_sets) && hidden_sets.length > 0,
|
||||||
hidden_emotes = this.emotes.getHidden('twitch'),
|
hidden_emotes = this.emotes.getHidden('twitch'),
|
||||||
|
@ -624,14 +625,12 @@ export default class Input extends Module {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const replacement = REPLACEMENTS[id];
|
const replacement = REPLACEMENTS[id];
|
||||||
let srcSet, animSrcSet;
|
let srcSet;
|
||||||
|
|
||||||
if ( replacement && this.chat.context.get('chat.fix-bad-emotes') ) {
|
if ( replacement && this.chat.context.get('chat.fix-bad-emotes') ) {
|
||||||
srcSet = `${REPLACEMENT_BASE}${replacement} 1x`;
|
srcSet = `${REPLACEMENT_BASE}${replacement} 1x`;
|
||||||
} else {
|
} else
|
||||||
srcSet = getTwitchEmoteSrcSet(id, false);
|
srcSet = getTwitchEmoteSrcSet(id, anim);
|
||||||
animSrcSet = getTwitchEmoteSrcSet(id, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
out.push({
|
out.push({
|
||||||
id,
|
id,
|
||||||
|
@ -641,7 +640,6 @@ export default class Input extends Module {
|
||||||
token,
|
token,
|
||||||
tokenLower: token.toLowerCase(),
|
tokenLower: token.toLowerCase(),
|
||||||
srcSet,
|
srcSet,
|
||||||
animSrcSet,
|
|
||||||
favorite: favorites.includes(id)
|
favorite: favorites.includes(id)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,4 @@
|
||||||
.live-time {
|
.live-time {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > :first-child > :last-child {
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
.ffz--meta-tray {
|
.ffz--meta-tray {
|
||||||
& > :first-child > :first-child:not(.tw-core-button) {
|
.tw-svg svg[type="color-text-accessible-red"],
|
||||||
|
p[data-a-target="animated-channel-viewers-count"] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,6 @@ export const NEW_API = '//api2.frankerfacez.com';
|
||||||
//export const SENTRY_ID = 'https://07ded545d3224ca59825daee02dc7745@catbag.frankerfacez.com:444/2';
|
//export const SENTRY_ID = 'https://07ded545d3224ca59825daee02dc7745@catbag.frankerfacez.com:444/2';
|
||||||
export const SENTRY_ID = 'https://74b46b3894114f399d51949c6d237489@sentry.frankerfacez.com/2';
|
export const SENTRY_ID = 'https://74b46b3894114f399d51949c6d237489@sentry.frankerfacez.com/2';
|
||||||
|
|
||||||
|
|
||||||
export const LV_SERVER = 'https://cbenni.com/api';
|
export const LV_SERVER = 'https://cbenni.com/api';
|
||||||
export const LV_SOCKET_SERVER = 'wss://cbenni.com/socket.io/';
|
export const LV_SOCKET_SERVER = 'wss://cbenni.com/socket.io/';
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
const merge = require('webpack-merge');
|
|
||||||
const common = require('./webpack.common.js');
|
|
||||||
|
|
||||||
/* global module __dirname */
|
|
||||||
|
|
||||||
module.exports = merge(common, {
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
site: path.resolve(__dirname, 'src/sites/twitch-clips/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,97 +0,0 @@
|
||||||
/* eslint-disable */
|
|
||||||
const path = require('path');
|
|
||||||
const merge = require('webpack-merge');
|
|
||||||
const common = require('./webpack.clips.common.js');
|
|
||||||
|
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
|
||||||
const webpack = require('webpack');
|
|
||||||
|
|
||||||
/* global module */
|
|
||||||
|
|
||||||
module.exports = merge(common, {
|
|
||||||
mode: 'development',
|
|
||||||
devtool: 'inline-source-map',
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new CopyPlugin([
|
|
||||||
{
|
|
||||||
from: './src/entry.js',
|
|
||||||
to: 'script.js'
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
__git_commit__: null
|
|
||||||
})
|
|
||||||
],
|
|
||||||
|
|
||||||
devServer: {
|
|
||||||
https: true,
|
|
||||||
port: 8000,
|
|
||||||
compress: true,
|
|
||||||
inline: false,
|
|
||||||
|
|
||||||
allowedHosts: [
|
|
||||||
'.twitch.tv',
|
|
||||||
'.frankerfacez.com'
|
|
||||||
],
|
|
||||||
|
|
||||||
contentBase: path.join(__dirname, 'dev_cdn'),
|
|
||||||
publicPath: '/script/clips/',
|
|
||||||
|
|
||||||
proxy: {
|
|
||||||
'**': {
|
|
||||||
target: 'https://cdn.frankerfacez.com/',
|
|
||||||
changeOrigin: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
before(app) {
|
|
||||||
// Because the headers config option is broken.
|
|
||||||
app.get('/*', (req, res, next) => {
|
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/update_font', (req, res) => {
|
|
||||||
const proc = exec('npm run font:save');
|
|
||||||
|
|
||||||
proc.stdout.on('data', data => {
|
|
||||||
console.log('FONT>>', data);
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.stderr.on('data', data => {
|
|
||||||
console.error('FONT>>', data);
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.on('close', code => {
|
|
||||||
console.log('FONT>> Exited with code', code);
|
|
||||||
res.redirect(req.headers.referer);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/script/script.js', (req, res, next) => {
|
|
||||||
req.url = req.url.replace(/^\/script/, '/script/clips');
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/script/bridge.js', (req, res, next) => {
|
|
||||||
req.url = req.url.replace(/^\/script/, '/script/clips');
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/dev_server', (req, res) => {
|
|
||||||
res.json({
|
|
||||||
path: process.cwd(),
|
|
||||||
version: 2
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
output: {
|
|
||||||
publicPath: '//localhost:8000/script/clips/',
|
|
||||||
filename: '[name].js',
|
|
||||||
jsonpFunction: 'ffzWebpackJsonp',
|
|
||||||
crossOriginLoading: 'anonymous'
|
|
||||||
}
|
|
||||||
})
|
|
|
@ -1,69 +0,0 @@
|
||||||
const webpack = require('webpack');
|
|
||||||
const merge = require('webpack-merge');
|
|
||||||
const common = require('./webpack.clips.common.js');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
|
||||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
|
||||||
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
|
|
||||||
|
|
||||||
const Terser = require('terser');
|
|
||||||
|
|
||||||
// Get Git info
|
|
||||||
|
|
||||||
const commit_hash = require('child_process').execSync('git rev-parse HEAD').toString().trim();
|
|
||||||
|
|
||||||
/* global module Buffer __dirname */
|
|
||||||
|
|
||||||
module.exports = merge(common, {
|
|
||||||
mode: 'production',
|
|
||||||
devtool: 'source-map',
|
|
||||||
|
|
||||||
optimization: {
|
|
||||||
concatenateModules: false,
|
|
||||||
minimizer: [
|
|
||||||
new TerserPlugin({
|
|
||||||
sourceMap: true,
|
|
||||||
terserOptions: {
|
|
||||||
keep_classnames: true,
|
|
||||||
keep_fnames: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
new CleanWebpackPlugin(),
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
__git_commit__: JSON.stringify(commit_hash)
|
|
||||||
}),
|
|
||||||
new CopyPlugin([
|
|
||||||
{
|
|
||||||
from: './src/entry.js',
|
|
||||||
to: 'script.min.js',
|
|
||||||
transform: content => {
|
|
||||||
const text = content.toString('utf8');
|
|
||||||
const minified = Terser.minify(text);
|
|
||||||
return (minified && minified.code) ? Buffer.from(minified.code) : content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
new ManifestPlugin({
|
|
||||||
basePath: 'clips/',
|
|
||||||
publicPath: 'clips/',
|
|
||||||
map: data => {
|
|
||||||
if ( data.name.endsWith('.scss') )
|
|
||||||
data.name = `${data.name.substr(0,data.name.length - 5)}.css`;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
|
||||||
|
|
||||||
output: {
|
|
||||||
publicPath: '//cdn.frankerfacez.com/static/clips/',
|
|
||||||
path: path.resolve(__dirname, 'dist/clips'),
|
|
||||||
filename: '[name].[hash].js'
|
|
||||||
}
|
|
||||||
});
|
|
Loading…
Add table
Add a link
Reference in a new issue