This commit is contained in:
parent
b40ecc6159
commit
e9ffc01929
|
@ -4,107 +4,107 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
||||||
<input ref="searchEl" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter">
|
<input ref="searchEl" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" autocapitalize="off" @input="input()" @paste.stop="paste" @keydown.stop.prevent.enter="onEnter">
|
||||||
<!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 -->
|
<!-- FirefoxのTabフォーカスが想定外の挙動となるためtabindex="-1"を追加 https://github.com/misskey-dev/misskey/issues/10744 -->
|
||||||
<div ref="emojisEl" class="emojis" tabindex="-1">
|
<div ref="emojisEl" class="emojis" tabindex="-1">
|
||||||
<section class="result">
|
<section class="result">
|
||||||
<div v-if="searchResultCustom.length > 0" class="body">
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
|
<button
|
||||||
|
v-for="emoji in searchResultCustom"
|
||||||
|
:key="emoji.name"
|
||||||
|
class="_button item"
|
||||||
|
:disabled="!canReact(emoji)"
|
||||||
|
:title="emoji.name"
|
||||||
|
tabindex="0"
|
||||||
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkCustomEmoji class="emoji" :name="emoji.name" :fallbackToImage="true"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||||
|
<button
|
||||||
|
v-for="emoji in searchResultUnicode"
|
||||||
|
:key="emoji.name"
|
||||||
|
class="_button item"
|
||||||
|
:title="emoji.name"
|
||||||
|
tabindex="0"
|
||||||
|
@click="chosen(emoji, $event)"
|
||||||
|
>
|
||||||
|
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div v-if="tab === 'index'" class="group index">
|
||||||
|
<section v-if="showPinned">
|
||||||
|
<div style="display: flex; ">
|
||||||
|
<div v-for="a in profileMax" :key="a" :title="defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`]" class="sllfktkhgl" :class="{ active: activeIndex === a || isDefaultProfile === a }" @click="pinnedProfileSelect(a)">
|
||||||
|
{{ defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`] }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="body">
|
||||||
<button
|
<button
|
||||||
v-for="emoji in searchResultCustom"
|
v-for="emoji in pinnedEmojisDef"
|
||||||
:key="emoji.name"
|
:key="getKey(emoji)"
|
||||||
|
:data-emoji="getKey(emoji)"
|
||||||
class="_button item"
|
class="_button item"
|
||||||
:disabled="!canReact(emoji)"
|
:disabled="!canReact(emoji)"
|
||||||
:title="emoji.name"
|
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
|
@pointerenter="computeButtonTitle"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkCustomEmoji class="emoji" :name="emoji.name" :fallbackToImage="true"/>
|
<MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/>
|
||||||
</button>
|
<MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/>
|
||||||
</div>
|
|
||||||
<div v-if="searchResultUnicode.length > 0" class="body">
|
|
||||||
<button
|
|
||||||
v-for="emoji in searchResultUnicode"
|
|
||||||
:key="emoji.name"
|
|
||||||
class="_button item"
|
|
||||||
:title="emoji.name"
|
|
||||||
tabindex="0"
|
|
||||||
@click="chosen(emoji, $event)"
|
|
||||||
>
|
|
||||||
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div v-if="tab === 'index'" class="group index">
|
<section>
|
||||||
<section v-if="showPinned && (pinned && pinned.length > 0)">
|
<header class="_acrylic"><i class="ti ti-clock ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
||||||
<div style="display: flex; ">
|
<div class="body">
|
||||||
<div v-for="a in profileMax" :key="a" :title="defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`]" class="sllfktkhgl" :class="{ active: activeIndex === a || isDefaultProfile === a }" @click="pinnedProfileSelect(a)">
|
<button
|
||||||
{{ defaultStore.state[`pickerProfileName${a > 1 ? a - 1 : ''}`] }}
|
v-for="emoji in recentlyUsedEmojisDef"
|
||||||
</div>
|
:key="getKey(emoji)"
|
||||||
</div>
|
class="_button item"
|
||||||
<div class="body">
|
|
||||||
<button
|
|
||||||
v-for="emoji in pinnedEmojisDef"
|
|
||||||
:key="getKey(emoji)"
|
|
||||||
:data-emoji="getKey(emoji)"
|
|
||||||
class="_button item"
|
|
||||||
:disabled="!canReact(emoji)"
|
|
||||||
tabindex="0"
|
|
||||||
@pointerenter="computeButtonTitle"
|
|
||||||
@click="chosen(emoji, $event)"
|
|
||||||
>
|
|
||||||
<MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/>
|
|
||||||
<MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<header class="_acrylic"><i class="ti ti-clock ti-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
|
||||||
<div class="body">
|
|
||||||
<button
|
|
||||||
v-for="emoji in recentlyUsedEmojisDef"
|
|
||||||
:key="getKey(emoji)"
|
|
||||||
class="_button item"
|
|
||||||
:disabled="!canReact(emoji)"
|
:disabled="!canReact(emoji)"
|
||||||
:data-emoji="getKey(emoji)"
|
:data-emoji="getKey(emoji)"
|
||||||
@pointerenter="computeButtonTitle"
|
@pointerenter="computeButtonTitle"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/>
|
<MkCustomEmoji v-if="!emoji.hasOwnProperty('char')" class="emoji" :name="getKey(emoji)" :normal="true"/>
|
||||||
<MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/>
|
<MkEmoji v-else class="emoji" :emoji="getKey(emoji)" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
<div v-once class="group">
|
|
||||||
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
|
||||||
<XSection
|
|
||||||
v-for="child in customEmojiFolderRoot.children"
|
|
||||||
:key="`custom:${child.value}`"
|
|
||||||
:initialShown="false"
|
|
||||||
:emojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value)).map(e => `:${e.name}:`))"
|
|
||||||
:disabledEmojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value && !customEmojis.some(emoji => emoji.category !== null && emoji.category.includes(e.category+'/')) || e.category === child.category+'/'+child.category && !e.category)).filter(e => !canReact(e)).map(e => `:${e.name}:`))"
|
|
||||||
:hasChildSection="child.children.length !== 0"
|
|
||||||
:customEmojiTree="child.children"
|
|
||||||
@chosen="chosen"
|
|
||||||
>
|
|
||||||
{{ child.value || i18n.ts.other }}
|
|
||||||
</XSection>
|
|
||||||
</div>
|
|
||||||
<div v-once class="group">
|
|
||||||
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
|
||||||
<XSection v-for="category in categories" :key="category" :emojis="emojiCharByCategory.get(category) ?? []" :hasChildSection="false" @chosen="chosen">{{ category }}</XSection>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs">
|
<div v-once class="group">
|
||||||
<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ti ti-asterisk ti-fw"></i></button>
|
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
||||||
<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ti ti-mood-happy ti-fw"></i></button>
|
<XSection
|
||||||
<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ti ti-leaf ti-fw"></i></button>
|
v-for="child in customEmojiFolderRoot.children"
|
||||||
<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ti ti-hash ti-fw"></i></button>
|
:key="`custom:${child.value}`"
|
||||||
|
:initialShown="false"
|
||||||
|
:emojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value)).map(e => `:${e.name}:`))"
|
||||||
|
:disabledEmojis="computed(() => customEmojis.filter(e => filterCategory(e, child.value && !customEmojis.some(emoji => emoji.category !== null && emoji.category.includes(e.category+'/')) || e.category === child.category+'/'+child.category && !e.category)).filter(e => !canReact(e)).map(e => `:${e.name}:`))"
|
||||||
|
:hasChildSection="child.children.length !== 0"
|
||||||
|
:customEmojiTree="child.children"
|
||||||
|
@chosen="chosen"
|
||||||
|
>
|
||||||
|
{{ child.value || i18n.ts.other }}
|
||||||
|
</XSection>
|
||||||
|
</div>
|
||||||
|
<div v-once class="group">
|
||||||
|
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
||||||
|
<XSection v-for="category in categories" :key="category" :emojis="emojiCharByCategory.get(category) ?? []" :hasChildSection="false" @chosen="chosen">{{ category }}</XSection>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tabs">
|
||||||
|
<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="ti ti-asterisk ti-fw"></i></button>
|
||||||
|
<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="ti ti-mood-happy ti-fw"></i></button>
|
||||||
|
<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="ti ti-leaf ti-fw"></i></button>
|
||||||
|
<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="ti ti-hash ti-fw"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -130,8 +130,8 @@ import { customEmojiCategories, customEmojis, customEmojisMap } from '@/custom-e
|
||||||
import { signinRequired } from '@/account.js';
|
import { signinRequired } from '@/account.js';
|
||||||
import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js';
|
import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.js';
|
||||||
import { deepClone } from '@/scripts/clone.js';
|
import { deepClone } from '@/scripts/clone.js';
|
||||||
import MkCustomEmoji from "@/components/global/MkCustomEmoji.vue";
|
import MkCustomEmoji from '@/components/global/MkCustomEmoji.vue';
|
||||||
import MkEmoji from "@/components/global/MkEmoji.vue";
|
import MkEmoji from '@/components/global/MkEmoji.vue';
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
showPinned?: boolean;
|
showPinned?: boolean;
|
||||||
|
@ -163,7 +163,7 @@ const recentlyUsedEmojisDef = computed(() => {
|
||||||
return recentlyUsedEmojis.value.map(getDef);
|
return recentlyUsedEmojis.value.map(getDef);
|
||||||
});
|
});
|
||||||
const pinnedEmojisDef = computed(() => {
|
const pinnedEmojisDef = computed(() => {
|
||||||
return pinned.value?.map(getDef);
|
return pinnedEmojis.value?.map(getDef);
|
||||||
});
|
});
|
||||||
|
|
||||||
const pinned = computed(() => props.pinnedEmojis);
|
const pinned = computed(() => props.pinnedEmojis);
|
||||||
|
|
Loading…
Reference in New Issue