Custom emoji (#3061)

* wip

* wip

* wip
This commit is contained in:
syuilo 2018-11-01 11:51:49 +09:00 committed by GitHub
parent 86fcd3a378
commit c21caad1c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 8 deletions

View file

@ -14,7 +14,8 @@
</ol> </ol>
<ol class="emojis" ref="suggests" v-if="emojis.length > 0"> <ol class="emojis" ref="suggests" v-if="emojis.length > 0">
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1"> <li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
<span class="emoji">{{ emoji.emoji }}</span> <span class="emoji" v-if="emoji.url"><img :src="emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else>{{ emoji.emoji }}</span>
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span> <span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
<span class="alias" v-if="emoji.alias">({{ emoji.alias }})</span> <span class="alias" v-if="emoji.alias">({{ emoji.alias }})</span>
</li> </li>
@ -169,22 +170,45 @@ export default Vue.extend({
} }
} else if (this.type == 'emoji') { } else if (this.type == 'emoji') {
const matched = []; const matched = [];
const max = 30;
const customEmojis = (this.os.getMetaSync() || { emojis: [] }).emojis;
customEmojis.some(x => {
if (x.name.startsWith(this.q)) matched.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url
});
return matched.length == max;
});
customEmojis.some(x => {
const alias = (x.aliases || []).find(a => a.startsWith(this.q));
if (alias) matched.push({
alias: x.name,
name: alias,
emoji: `:${x.name}:`,
url: x.url
});
return matched.length == max;
});
emjdb.some(x => { emjdb.some(x => {
if (x.name.indexOf(this.q) == 0 && !x.alias && !matched.some(y => y.emoji == x.emoji)) matched.push(x); if (x.name.indexOf(this.q) == 0 && !x.alias && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30; return matched.length == max;
}); });
if (matched.length < 30) { if (matched.length < max) {
emjdb.some(x => { emjdb.some(x => {
if (x.name.indexOf(this.q) == 0 && !matched.some(y => y.emoji == x.emoji)) matched.push(x); if (x.name.indexOf(this.q) == 0 && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30; return matched.length == max;
}); });
} }
if (matched.length < 30) { if (matched.length < max) {
emjdb.some(x => { emjdb.some(x => {
if (x.name.indexOf(this.q) > -1 && !matched.some(y => y.emoji == x.emoji)) matched.push(x); if (x.name.indexOf(this.q) > -1 && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
return matched.length == 30; return matched.length == max;
}); });
} }
this.emojis = matched; this.emojis = matched;
} }
}, },
@ -340,6 +364,10 @@ export default Vue.extend({
margin 0 4px 0 0 margin 0 4px 0 0
width 24px width 24px
> img
width 24px
vertical-align bottom
.name .name
color var(--autocompleteItemText) color var(--autocompleteItemText)

View file

@ -3,7 +3,6 @@ import * as emojilib from 'emojilib';
import { length } from 'stringz'; import { length } from 'stringz';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import getAcct from '../../../../../misc/acct/render'; import getAcct from '../../../../../misc/acct/render';
import { url } from '../../../config';
import MkUrl from './url.vue'; import MkUrl from './url.vue';
import MkGoogle from './google.vue'; import MkGoogle from './google.vue';
import { concat } from '../../../../../prelude/array'; import { concat } from '../../../../../prelude/array';
@ -186,6 +185,21 @@ export default Vue.component('misskey-flavored-markdown', {
} }
case 'emoji': { case 'emoji': {
//#region カスタム絵文字
const customEmojis = (this.os.getMetaSync() || { emojis: [] }).emojis;
const customEmoji = customEmojis.find(e => e.name == token.emoji || (e.aliases || []).includes(token.emoji));
if (customEmoji) {
return [createElement('img', {
attrs: {
src: customEmoji.url,
alt: token.emoji,
title: token.emoji,
style: 'height: 2.5em; vertical-align: middle;'
}
})];
}
//#endregion
const emoji = emojilib.lib[token.emoji]; const emoji = emojilib.lib[token.emoji];
return [createElement('span', emoji ? emoji.char : token.content)]; return [createElement('span', emoji ? emoji.char : token.content)];
} }

View file

@ -222,13 +222,15 @@ class Autocomplete {
const trimmedBefore = before.substring(0, before.lastIndexOf(':')); const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
const after = source.substr(caret); const after = source.substr(caret);
if (value.startsWith(':')) value = value + ' ';
// 挿入 // 挿入
this.text = trimmedBefore + value + after; this.text = trimmedBefore + value + after;
// キャレットを戻す // キャレットを戻す
this.vm.$nextTick(() => { this.vm.$nextTick(() => {
this.textarea.focus(); this.textarea.focus();
const pos = trimmedBefore.length + 1; const pos = trimmedBefore.length + (value.startsWith(':') ? value.length : 1);
this.textarea.setSelectionRange(pos, pos); this.textarea.setSelectionRange(pos, pos);
}); });
} }

View file

@ -510,6 +510,14 @@ export default class MiOS extends EventEmitter {
return promise; return promise;
} }
/**
* Misskeyのメタ情報を取得します
*/
@autobind
public getMetaSync() {
return this.meta ? this.meta.data : null;
}
/** /**
* Misskeyのメタ情報を取得します * Misskeyのメタ情報を取得します
* @param force * @param force

View file

@ -15,4 +15,24 @@ export type IMeta = {
disableLocalTimeline?: boolean; disableLocalTimeline?: boolean;
hidedTags?: string[]; hidedTags?: string[];
bannerUrl?: string; bannerUrl?: string;
/**
*
*/
emojis?: {
/**
* (: thinking_ai)
*/
name: string;
/**
*
*/
aliases?: string[];
/**
* URL
*/
url: string;
}[];
}; };

View file

@ -17,6 +17,12 @@ export const meta = {
} }
}), }),
emojis: $.arr($.obj()).optional.note({
desc: {
'ja-JP': 'カスタム絵文字定義'
}
}),
disableRegistration: $.bool.optional.nullable.note({ disableRegistration: $.bool.optional.nullable.note({
desc: { desc: {
'ja-JP': '招待制か否か' 'ja-JP': '招待制か否か'
@ -53,6 +59,10 @@ export default (params: any) => new Promise(async (res, rej) => {
set.broadcasts = ps.broadcasts; set.broadcasts = ps.broadcasts;
} }
if (ps.emojis) {
set.emojis = ps.emojis;
}
if (typeof ps.disableRegistration === 'boolean') { if (typeof ps.disableRegistration === 'boolean') {
set.disableRegistration = ps.disableRegistration; set.disableRegistration = ps.disableRegistration;
} }

View file

@ -50,6 +50,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined, hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined,
bannerUrl: meta.bannerUrl, bannerUrl: meta.bannerUrl,
maxNoteTextLength: config.maxNoteTextLength, maxNoteTextLength: config.maxNoteTextLength,
emojis: meta.emojis,
features: { features: {
registration: !meta.disableRegistration, registration: !meta.disableRegistration,