mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-11 00:20:54 +00:00
4.20.32
This release uses an entirely new emoji data source behind the scenes, and there may be bugs with emoji. Different names for certain emoji are also likely. Please report any issues. * Added: Support for Blob and OpenMoji emoji sets. * Changed: Update emoji to support emoji 13. * Changed: Allow searching for emoji by any of their short codes in the emote menu. * Removed: Support for the EmojiOne emoji set. * Fixed: Hover styles for certain elements. * Fixed: Sort emoji categories. * Fixed: Typo in the description of a setting. * Fixed: Do not include the same emoji multiple times in tab completion. * Fixed: Issue viewing chat messages with replies enabled when not logged in. (Closes #889) * Fixed: Twitch Style replies for highlighted messages, resubscription messages, etc. * Fixed: Badge tool-tips not appearing correctly in Firefox.
This commit is contained in:
parent
e7228d2795
commit
fd2977f899
17 changed files with 282 additions and 136 deletions
|
@ -257,7 +257,7 @@ export default class Actions extends Module {
|
|||
reason_elements.push(<li class="tw-full-width tw-relative">
|
||||
<a
|
||||
href="#"
|
||||
class="tw-block tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive tw-pd-05"
|
||||
class="tw-block tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive tw-pd-05"
|
||||
onClick={click_fn(text)}
|
||||
>
|
||||
{text}
|
||||
|
@ -274,7 +274,7 @@ export default class Actions extends Module {
|
|||
reason_elements.push(<li class="tw-full-width tw-relative">
|
||||
<a
|
||||
href="#"
|
||||
class="tw-block tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive tw-pd-05"
|
||||
class="tw-block tw-full-width tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive tw-pd-05"
|
||||
onClick={click_fn(rule)}
|
||||
>
|
||||
{rule}
|
||||
|
|
|
@ -12,14 +12,48 @@ import { getBuster } from 'utilities/time';
|
|||
import splitter from 'emoji-regex/es2015/index';
|
||||
|
||||
|
||||
export const SIZES = {
|
||||
/*export const SIZES = {
|
||||
apple: [64, 160],
|
||||
emojione: [64],
|
||||
facebook: [64, 96],
|
||||
google: [64, 136],
|
||||
messenger: [64, 128],
|
||||
twitter: [64, 72]
|
||||
}
|
||||
}*/
|
||||
|
||||
export const HIDDEN_CATEGORIES = [
|
||||
'component'
|
||||
];
|
||||
|
||||
export const CATEGORIES = {
|
||||
'smileys-emotion': 'Smileys & Emotions',
|
||||
'people-body': 'People',
|
||||
'component': 'Components',
|
||||
'animals-nature': 'Animals & Nature',
|
||||
'food-drink': 'Food & Drink',
|
||||
'travel-places': 'Travel & Places',
|
||||
'activities': 'Activities',
|
||||
'objects': 'Objects',
|
||||
'symbols': 'Symbols',
|
||||
'flags': 'Flags'
|
||||
};
|
||||
|
||||
export const CATEGORY_SORT = Object.keys(CATEGORIES);
|
||||
|
||||
export const SKIN_TONES = {
|
||||
1: '1f3fb',
|
||||
2: '1f3fc',
|
||||
3: '1f3fd',
|
||||
4: '1f3fe',
|
||||
5: '1f3ff'
|
||||
};
|
||||
|
||||
export const IMAGE_PATHS = {
|
||||
google: 'noto',
|
||||
twitter: 'twemoji',
|
||||
open: 'openmoji',
|
||||
blob: 'blob'
|
||||
};
|
||||
|
||||
|
||||
export function codepoint_to_emoji(cp) {
|
||||
|
@ -49,13 +83,11 @@ export default class Emoji extends Module {
|
|||
title: 'Emoji Style',
|
||||
component: 'setting-select-box',
|
||||
data: [
|
||||
{value: 0, title: 'Native'},
|
||||
{value: 'twitter', title: 'Twitter'},
|
||||
{value: 'google', title: 'Google'},
|
||||
//{value: 'apple', title: 'Apple'},
|
||||
{value: 'emojione', title: 'EmojiOne'},
|
||||
//{value: 'facebook', title: 'Facebook'},
|
||||
//{value: 'messenger', title: 'Messenger'}
|
||||
{value: 'twitter', title: 'Twitter (Twemoji)'},
|
||||
{value: 'google', title: 'Google (Noto)'},
|
||||
{value: 'blob', title: 'Blob'},
|
||||
{value: 'open', title: 'OpenMoji'},
|
||||
{value: 0, title: 'Native'}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
@ -75,7 +107,7 @@ export default class Emoji extends Module {
|
|||
async loadEmojiData(tries = 0) {
|
||||
let data;
|
||||
try {
|
||||
data = await fetch(`${SERVER}/script/emoji/v2-.json?_${getBuster(60)}`).then(r =>
|
||||
data = await fetch(`${SERVER}/script/emoji/v3.2.json?_${getBuster(60)}`).then(r =>
|
||||
r.ok ? r.json() : null
|
||||
);
|
||||
|
||||
|
@ -119,11 +151,43 @@ export default class Emoji extends Module {
|
|||
if ( raw[7] ) {
|
||||
const vars = emoji.variants = {};
|
||||
for(const r of raw[7]) {
|
||||
if ( Array.isArray(r[3]) || ! r[3] ) {
|
||||
// The tone picker doesn't support multiple tones
|
||||
// for a single emoji. Just make this variation a
|
||||
// new emoji.
|
||||
const em = Object.assign(hydrate_emoji(r), {
|
||||
category: cats[raw[0]],
|
||||
sort: raw[1],
|
||||
names: r[5],
|
||||
hidden: true
|
||||
});
|
||||
|
||||
if ( ! Array.isArray(em.names) )
|
||||
em.names = [em.names];
|
||||
|
||||
em.name = em.names[0].replace(/_/g, ' ');
|
||||
|
||||
out[em.code] = em;
|
||||
chars.set(em.raw, [em.code, null]);
|
||||
for(const name of em.names)
|
||||
names[name] = em.code;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// We just have a normal tone. We need to look
|
||||
// up the modifier and use it.
|
||||
const tone = SKIN_TONES[r[3]];
|
||||
if ( ! tone ) {
|
||||
console.warn('Unknown tone:', r[3], r, emoji);
|
||||
continue;
|
||||
}
|
||||
|
||||
const vari = Object.assign(hydrate_emoji(r), {
|
||||
key: r[3].toLowerCase()
|
||||
key: tone
|
||||
});
|
||||
|
||||
vars[vari.key] = vari;
|
||||
vars[tone] = vari;
|
||||
chars.set(vari.raw, [emoji.code, vari.key]);
|
||||
}
|
||||
}
|
||||
|
@ -142,41 +206,53 @@ export default class Emoji extends Module {
|
|||
if ( ! style )
|
||||
style = this.parent.context.get('chat.emoji.style');
|
||||
|
||||
if ( ! has(SIZES, style) )
|
||||
if ( ! has(IMAGE_PATHS, style) )
|
||||
style = 'twitter';
|
||||
|
||||
return `${SERVER}/static/emoji/img-${style}-${SIZES[style][0]}/${image}`;
|
||||
return `${SERVER}/static/emoji/images/${IMAGE_PATHS[style]}/${image}`;
|
||||
|
||||
/*if ( ! has(SIZES, style) )
|
||||
style = 'twitter';
|
||||
|
||||
return `${SERVER}/static/emoji/img-${style}-${SIZES[style][0]}/${image}`;*/
|
||||
}
|
||||
|
||||
getFullImageSet(image, style) {
|
||||
if ( ! style )
|
||||
style = this.parent.context.get('chat.emoji.style');
|
||||
|
||||
if ( ! has(SIZES, style) )
|
||||
if ( ! has(IMAGE_PATHS, style) )
|
||||
style = 'twitter';
|
||||
|
||||
return `${SERVER}/static/emoji/images/${IMAGE_PATHS[style]}/${image} 72w`;
|
||||
|
||||
/*if ( ! has(SIZES, style) )
|
||||
style = 'twitter';
|
||||
|
||||
return SIZES[style].map(w =>
|
||||
`${SERVER}/static/emoji/img-${style}-${w}/${image} ${w}w`
|
||||
).join(', ');
|
||||
).join(', ');*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function hydrate_emoji(data) {
|
||||
let code = data[0];
|
||||
if ( data[4] === 0 )
|
||||
code = `${code}-fe0f`;
|
||||
|
||||
return {
|
||||
code: data[0],
|
||||
code,
|
||||
image: `${data[0]}.png`,
|
||||
raw: data[0].split('-').map(codepoint_to_emoji).join(''),
|
||||
raw: code.split('-').map(codepoint_to_emoji).join(''),
|
||||
sheet_x: data[1][0],
|
||||
sheet_y: data[1][1],
|
||||
|
||||
has: {
|
||||
apple: !!(0b100000 & data[2]),
|
||||
google: !!(0b010000 & data[2]),
|
||||
twitter: !!(0b001000 & data[2]),
|
||||
emojione: !!(0b000100 & data[2]),
|
||||
facebook: !!(0b000010 & data[2]),
|
||||
messenger: !!(0b000001 & data[2])
|
||||
google: !!(0b1000 & data[2]),
|
||||
blob: !!(0b0100 & data[2]) || !!(0b1000 & data[2]), // Blob falls back to Noto
|
||||
twitter: !!(0b0010 & data[2]),
|
||||
open: !!(0b0001 & data[2])
|
||||
}
|
||||
};
|
||||
}
|
|
@ -8,6 +8,7 @@ import {sanitize, createElement} from 'utilities/dom';
|
|||
import {has, split_chars} from 'utilities/object';
|
||||
|
||||
import {TWITCH_EMOTE_BASE, EmoteTypes, REPLACEMENT_BASE, REPLACEMENTS} from 'utilities/constants';
|
||||
import {CATEGORIES} from './emoji';
|
||||
|
||||
|
||||
const EMOTE_CLASS = 'chat-image chat-line__message--emote',
|
||||
|
@ -1227,7 +1228,7 @@ export const AddonEmotes = {
|
|||
plain_name = true;
|
||||
name = `:${emoji.names[0]}:${vcode ? `:${vcode.names[0]}:` : ''}`;
|
||||
|
||||
const category = emoji.category ? this.i18n.t(`emoji.category.${emoji.category.toSnakeCase()}`, emoji.category) : null;
|
||||
const category = emoji.category ? this.i18n.t(`emoji.category.${emoji.category.toSnakeCase()}`, CATEGORIES[emoji.category] || emoji.category) : null;
|
||||
source = this.i18n.t('tooltip.emoji', 'Emoji - {category}', {category});
|
||||
|
||||
} else
|
||||
|
|
|
@ -245,7 +245,7 @@
|
|||
</div>
|
||||
<div v-else class="tw-pd-y-1">
|
||||
<button
|
||||
class="tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive tw-full-width"
|
||||
class="tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive tw-full-width"
|
||||
@click="add_pasting = true"
|
||||
>
|
||||
<div class="tw-flex tw-align-items-center tw-pd-y-05 tw-pd-x-1">
|
||||
|
@ -264,7 +264,7 @@
|
|||
v-else
|
||||
:key="idx"
|
||||
:disabled="preset.disabled"
|
||||
class="tw-interactable tw-interactable--hover-enabled tw-interactable--inverted tw-interactive tw-full-width"
|
||||
class="tw-interactable tw-interactable--hover-enabled tw-interactable--default tw-interactive tw-full-width"
|
||||
@click="add(preset.value)"
|
||||
>
|
||||
<div class="tw-flex tw-align-items-center tw-pd-y-05 tw-pd-x-1">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue