1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-28 23:37:41 +00:00

Fix bug tokenizing cheers in messages. Try to fix any bugs getting a user for a room. Strip apollo 404 messages from Sentry. Don't show the expansion arrows in the emote menu when using a filter. Fix emoji tab completion a bit. 🐝 should not match 🍺. Start using crossorigin for script serving. Add a debug transformation for localization.

This commit is contained in:
SirStendec 2018-04-15 17:19:22 -04:00
parent 730e2129e9
commit e581b50b08
13 changed files with 133 additions and 18 deletions

View file

@ -1,3 +1,11 @@
<div class="list-header">4.0.0-beta2.18<span>@c8636911fc387a9f5e0c</span> <time datetime="2018-04-15">(2018-04-15)</time></div>
<ul class="chat-menu-content menu-side-padding">
<li>Added: Debugging setting for localization to help test UI issues, identify strings, and find strings that aren't localized.</li>
<li>Fixed: Issue tokenizing cheers in messages.</li>
<li>Fixed: Clean up tab-completion of emoji a bit more.</li>
<li>Changed: Start using `crossorigin="anonymous"` when loading scripts from our CDN.</li>
</ul>
<div class="list-header">4.0.0-beta2.17<span>@dce1b0c5268bdd3fe086</span> <time datetime="2018-04-13">(2018-04-13)</time></div> <div class="list-header">4.0.0-beta2.17<span>@dce1b0c5268bdd3fe086</span> <time datetime="2018-04-13">(2018-04-13)</time></div>
<ul class="chat-menu-content menu-side-padding"> <ul class="chat-menu-content menu-side-padding">
<li>Fixed: An issue in automatic error reporting potentially swallowing errors when error reporting is disabled.</li> <li>Fixed: An issue in automatic error reporting potentially swallowing errors when error reporting is disabled.</li>

View file

@ -13,6 +13,7 @@
script = document.createElement('script'); script = document.createElement('script');
script.id = 'ffz-script'; script.id = 'ffz-script';
script.crossOrigin = 'anonymous';
script.src = `${SERVER}/script/${BABEL}${FLAVOR}.js?_=${Date.now()}`; script.src = `${SERVER}/script/${BABEL}${FLAVOR}.js?_=${Date.now()}`;
document.head.appendChild(script); document.head.appendChild(script);
})(); })();

View file

@ -7,10 +7,59 @@
// ============================================================================ // ============================================================================
import {SERVER} from 'utilities/constants'; import {SERVER} from 'utilities/constants';
import {has} from 'utilities/object'; import {pick_random, has} from 'utilities/object';
import Module from 'utilities/module'; import Module from 'utilities/module';
const FACES = ['(・`ω´・)', ';;w;;', 'owo', 'UwU', '>w<', '^w^'],
format_text = (phrase, token_regex, formatter) => {
const out = [];
let i = 0, match;
token_regex.lastIndex = 0;
while((match = token_regex.exec(phrase))) {
if ( match.index !== i )
out.push(formatter(phrase.slice(i, match.index)))
out.push(match[0]);
i = match.index + match[0].length;
}
if ( i < phrase.length )
out.push(formatter(phrase.slice(i)));
return out.join('')
},
owo = text => text
.replace(/(?:r|l)/g, 'w')
.replace(/(?:R|L)/g, 'W')
.replace(/n([aeiou])/g, 'ny$1')
.replace(/N([aeiou])/g, 'Ny$1')
.replace(/N([AEIOU])/g, 'NY$1')
.replace(/ove/g, 'uv')
.replace(/!+/g, ` ${pick_random(FACES)} `),
TRANSFORMATIONS = {
double: (key, text) =>
`${text} ${text}`,
upper: (key, text, opts, locale, token_regex) =>
format_text(text, token_regex, t => t.toUpperCase()),
lower: (key, text, opts, locale, token_regex) =>
format_text(text, token_regex, t => t.toLowerCase()),
append_key: (key, text) => `${text} (${key})`,
owo: (key, text, opts, locale, token_regex) =>
format_text(text, token_regex, t => owo(t))
};
// ============================================================================ // ============================================================================
// TranslationManager // TranslationManager
// ============================================================================ // ============================================================================
@ -28,6 +77,31 @@ export class TranslationManager extends Module {
//ja: { name: '日本語' } //ja: { name: '日本語' }
} }
this.settings.add('i18n.debug.transform', {
default: null,
ui: {
path: 'Debugging > Localization >> General',
title: 'Transformation',
description: 'Transform all localized strings to test string coverage as well as length.',
component: 'setting-select-box',
data: [
{value: null, title: 'Disabled'},
{value: 'upper', title: 'Upper Case'},
{value: 'lower', title: 'Lower Case'},
{value: 'append_key', title: 'Append Key'},
{value: 'double', title: 'Double'},
{value: 'owo', title: "owo what's this"}
]
},
changed: val => {
this._.transformation = TRANSFORMATIONS[val];
this.emit(':update')
}
});
this.settings.add('i18n.locale', { this.settings.add('i18n.locale', {
default: -1, default: -1,
process: (ctx, val) => { process: (ctx, val) => {
@ -65,6 +139,7 @@ export class TranslationManager extends Module {
awarn: (...args) => this.log.info(...args) awarn: (...args) => this.log.info(...args)
});*/ });*/
this._.transformation = TRANSFORMATIONS[this.settings.get('i18n.debug.transform')];
this.locale = this.settings.get('i18n.locale'); this.locale = this.settings.get('i18n.locale');
} }
@ -311,6 +386,7 @@ export default class TranslationCore {
this.extend(options.phrases); this.extend(options.phrases);
this.locale = options.locale || 'en'; this.locale = options.locale || 'en';
this.defaultLocale = options.defaultLocale || this.locale; this.defaultLocale = options.defaultLocale || this.locale;
this.transformation = null;
const allowMissing = options.allowMissing ? transformPhrase : null; const allowMissing = options.allowMissing ? transformPhrase : null;
this.onMissingKey = typeof options.onMissingKey === 'function' ? options.onMissingKey : allowMissing; this.onMissingKey = typeof options.onMissingKey === 'function' ? options.onMissingKey : allowMissing;
@ -413,6 +489,9 @@ export default class TranslationCore {
return key; return key;
} }
if ( this.transformation )
p = this.transformation(key, p, opts, locale, this.tokenRegex);
return this.transformPhrase(p, opts, locale, this.tokenRegex, this.formatters); return this.transformPhrase(p, opts, locale, this.tokenRegex, this.formatters);
} }
} }

View file

@ -100,7 +100,7 @@ class FrankerFaceZ extends Module {
FrankerFaceZ.Logger = Logger; FrankerFaceZ.Logger = Logger;
const VER = FrankerFaceZ.version_info = { const VER = FrankerFaceZ.version_info = {
major: 4, minor: 0, revision: 0, extra: '-beta2.17', major: 4, minor: 0, revision: 0, extra: '-beta2.18',
build: __webpack_hash__, build: __webpack_hash__,
toString: () => toString: () =>
`${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${DEBUG ? '-dev' : ''}` `${VER.major}.${VER.minor}.${VER.revision}${VER.extra || ''}${DEBUG ? '-dev' : ''}`

View file

@ -116,7 +116,7 @@ export default class Room {
} }
getUser(id, login, no_create, no_login) { getUser(id, login, no_create, no_login, error = false) {
if ( this.destroyed ) if ( this.destroyed )
return null; return null;
@ -130,18 +130,29 @@ export default class Room {
else if ( this.users[login] && ! no_login ) else if ( this.users[login] && ! no_login )
user = this.users[login]; user = this.users[login];
else if ( no_create ) if ( user && user.destroyed )
user = null;
if ( ! user ) {
if ( no_create )
return null; return null;
else
user = new User(this.manager, this, id, login); user = new User(this.manager, this, id, login);
}
if ( id && id !== user.id ) { if ( id && id !== user.id ) {
// If the ID isn't what we expected, something is very wrong here. // If the ID isn't what we expected, something is very wrong here.
// Blame name changes. // Blame name changes.
if ( user.id ) 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'); 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;
}
// Otherwise, we're just here to set the ID. // Otherwise, we're just here to set the ID.
user._id = id; user._id = id;
this.user_ids[id] = user; this.user_ids[id] = user;

View file

@ -389,6 +389,8 @@ export const CheerEmotes = {
token.hidden = true; token.hidden = true;
} }
text.push('');
} else } else
text.push(segment); text.push(segment);
} }

View file

@ -112,7 +112,7 @@ export default class RavenLogger extends Module {
} }
})); }));
}) })
}) });
}); });
this.raven = Raven; this.raven = Raven;

View file

@ -351,7 +351,7 @@ export default class EmoteMenu extends Module {
} }
clickHeading() { clickHeading() {
if ( this.props.filter ) if ( this.props.filtered )
return; return;
const collapsed = storage.get('emote-menu.collapsed') || [], const collapsed = storage.get('emote-menu.collapsed') || [],
@ -440,7 +440,7 @@ export default class EmoteMenu extends Module {
</div> </div>
<div class="tw-flex-grow-1" /> <div class="tw-flex-grow-1" />
{data.source || 'FrankerFaceZ'} {data.source || 'FrankerFaceZ'}
<figure class={`tw-pd-l-05 ffz-i-${collapsed ? 'left' : 'down'}-dir`} /> {filtered ? '' : <figure class={`tw-pd-l-05 ffz-i-${collapsed ? 'left' : 'down'}-dir`} />}
</heading>) : null} </heading>) : null}
{collapsed || this.renderBody(show_heading)} {collapsed || this.renderBody(show_heading)}
</section>) </section>)

View file

@ -147,13 +147,14 @@ export default class TabCompletion extends Module {
getEmojiSuggestions(input, inst) { getEmojiSuggestions(input, inst) {
let search = input.slice(1).toLowerCase(); let search = input.slice(1).toLowerCase();
const style = this.chat.context.get('chat.emoji.style'), const style = this.chat.context.get('chat.emoji.style'),
results = []; results = [],
has_colon = search.endsWith(':');
if ( search.endsWith(':') ) if ( has_colon )
search = search.slice(0,-1); search = search.slice(0,-1);
for(const name in this.emoji.names) for(const name in this.emoji.names)
if ( name.startsWith(search) ) { if ( has_colon ? name === search : name.startsWith(search) ) {
const emoji = this.emoji.emoji[this.emoji.names[name]]; const emoji = this.emoji.emoji[this.emoji.names[name]];
if ( emoji && (style === 0 || emoji.has[style]) ) if ( emoji && (style === 0 || emoji.has[style]) )
results.push({ results.push({

View file

@ -14,6 +14,7 @@ const BAD_ERRORS = [
'unable to load', 'unable to load',
'error internal', 'error internal',
'context deadline exceeded', 'context deadline exceeded',
'404',
'500', '500',
'501', '501',
'502', '502',

View file

@ -235,6 +235,17 @@ export function split_chars(str) {
} }
export function pick_random(obj) {
if ( ! obj )
return null;
if ( ! Array.isArray(obj) )
return obj[pick_random(Object.keys(obj))]
return obj[Math.floor(Math.random() * obj.length)];
}
export class SourcedSet { export class SourcedSet {
constructor() { constructor() {
this._cache = []; this._cache = [];

View file

@ -73,7 +73,7 @@ export class Tooltip {
} else if ( this.live ) { } else if ( this.live ) {
this._onMouseOver = e => { this._onMouseOver = e => {
const target = e.target; const target = e.target;
if ( target && target.classList.contains(this.cls) ) if ( target && target.classList && target.classList.contains(this.cls) )
this._enter(target); this._enter(target);
}; };
@ -296,8 +296,8 @@ export class Tooltip {
// Add everything to the DOM and create the Popper instance. // Add everything to the DOM and create the Popper instance.
this.parent.appendChild(el);
tip.popper = new Popper(target, el, pop_opts); tip.popper = new Popper(target, el, pop_opts);
this.parent.appendChild(el);
tip.visible = true; tip.visible = true;
if ( opts.onShow ) if ( opts.onShow )

View file

@ -27,7 +27,8 @@ module.exports = {
output: { output: {
chunkFilename: '[name].[chunkhash].js', chunkFilename: '[name].[chunkhash].js',
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
jsonpFunction: 'ffzWebpackJsonp' jsonpFunction: 'ffzWebpackJsonp',
crossOriginLoading: 'anonymous'
}, },
plugins: [ plugins: [
new webpack.ExtendedAPIPlugin() new webpack.ExtendedAPIPlugin()