絵文字申請

This commit is contained in:
mattyatea 2023-10-14 04:51:57 +09:00
parent ad27562269
commit f9efc37eb1
6 changed files with 37 additions and 58 deletions

View File

@ -828,7 +828,7 @@ list: "一覧"
emailNotConfiguredWarning: "メールアドレスの設定がされていません。" emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
ratio: "比率" ratio: "比率"
newEmojis: "新しい絵文字" newEmojis: "新しい絵文字"
draftEmojis: "ドラフトされてる絵文字" draftEmojis: "申請されている絵文字"
previewNoteText: "本文をプレビュー" previewNoteText: "本文をプレビュー"
customCss: "カスタムCSS" customCss: "カスタムCSS"
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。" customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"

View File

@ -1,6 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import rndstr from 'rndstr'; import { Endpoint } from '@/server/api/endpoint-base.js';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { DriveFilesRepository } from '@/models/index.js'; import type { DriveFilesRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js';
@ -73,10 +72,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
roleIdsThatCanBeUsedThisEmojiAsReaction: [], roleIdsThatCanBeUsedThisEmojiAsReaction: [],
}); });
this.moderationLogService.insertModerationLog(me, 'addEmoji', {
emojiId: emoji.id,
});
return { return {
id: emoji.id, id: emoji.id,
}; };

View File

@ -10,21 +10,21 @@
<div class="imgDark"><img :src="emoji.url" :alt="emoji.name"/></div> <div class="imgDark"><img :src="emoji.url" :alt="emoji.name"/></div>
</div> </div>
<div class="info"> <div class="info">
<div class="name _monospace">{{ i18n.ts.name }}: {{ emoji.name }}</div> <div class="name">{{ i18n.ts.name }}: {{ emoji.name }}</div>
<div class="category">{{ i18n.ts.category }}:{{ emoji.category }}</div> <div class="category">{{ i18n.ts.category }}:{{ emoji.category }}</div>
<div class="aliases">{{ i18n.ts.tags }}:{{ emoji.aliases.join(' ') }}</div> <div class="aliases">{{ i18n.ts.tags }}:{{ emoji.aliases.join(' ') }}</div>
<div class="license">{{ i18n.ts.license }}:{{ emoji.license }}</div> <div class="license">{{ i18n.ts.license }}:{{ emoji.license }}</div>
</div> </div>
<div class="edit-button"> <div class="edit-button">
<button class="edit _button" @click="editDraft(emoji)"> <MkButton primary class="edit" @click="editDraft(emoji)">
{{ i18n.ts.edit }} {{ i18n.ts.edit }}
</button> </MkButton>
<button class="draft _button" @click="undrafted(emoji)"> <MkButton class="draft" @click="undrafted(emoji)">
{{ i18n.ts.undrafted }} {{ i18n.ts.undrafted }}
</button> </MkButton>
<button class="delete _button" @click="deleteDraft(emoji)"> <MkButton danger class="delete" @click="deleteDraft(emoji)">
{{ i18n.ts.delete }} {{ i18n.ts.delete }}
</button> </MkButton>
</div> </div>
</div> </div>
</template> </template>
@ -38,6 +38,7 @@ import { computed, defineAsyncComponent, ref, shallowRef } from 'vue';
import MkPagination from '@/components/MkPagination.vue'; import MkPagination from '@/components/MkPagination.vue';
import * as os from '@/os'; import * as os from '@/os';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
import MkButton from '@/components/MkButton.vue';
const emojisDraftPaginationComponent = shallowRef<InstanceType<typeof MkPagination>>(); const emojisDraftPaginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
@ -87,7 +88,7 @@ async function undrafted(emoji) {
license: emoji.license, license: emoji.license,
draft: false, draft: false,
isSensitive: emoji.isSensitive, isSensitive: emoji.isSensitive,
localOnly: emoji.localOnly, localOnly: emoji.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction, roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
}); });
@ -118,14 +119,10 @@ async function deleteDraft(emoji) {
.ldhfsamy { .ldhfsamy {
> .emoji { > .emoji {
display: grid;
grid-template-rows: 40px 1fr;
grid-template-columns: 1fr 150px;
align-items: center; align-items: center;
padding: 11px; padding: 11px;
text-align: left; text-align: left;
border: solid 1px var(--panel); border: solid 1px var(--panel);
width: 100%;
margin: 10px; margin: 10px;
> .img { > .img {
@ -140,9 +137,9 @@ async function deleteDraft(emoji) {
display: grid; display: grid;
grid-column: 1; grid-column: 1;
background-color: #fff; background-color: #fff;
margin-bottom: 12px;
> img { > img {
max-height: 30px; max-height: 64px;
max-width: 100%; max-width: 100%;
} }
} }
@ -151,9 +148,9 @@ async function deleteDraft(emoji) {
display: grid; display: grid;
grid-column: 2; grid-column: 2;
background-color: #000; background-color: #000;
margin-bottom: 12px;
> img { > img {
max-height: 30px; max-height: 64px;
max-width: 100%; max-width: 100%;
} }
} }
@ -191,37 +188,25 @@ async function deleteDraft(emoji) {
> .edit-button { > .edit-button {
display: grid; display: grid;
grid-row: 2; grid-template-rows: 42px;
grid-template-rows: 30px 30px 30px; margin-top: 6px;
> .edit { > .edit {
grid-row: 1; grid-row: 1;
background-color: var(--buttonBg); width: 100%;
margin: 2px; margin: 6px 0;
&:hover {
color: var(--accent);
}
} }
> .draft { > .draft {
grid-row: 2; grid-row: 2;
background-color: var(--buttonBg); width: 100%;
margin: 2px; margin: 6px 0;
&:hover {
color: var(--accent);
}
} }
> .delete { > .delete {
background-color: var(--buttonBg);
grid-row: 3; grid-row: 3;
margin: 2px; width: 100%;
margin: 6px 0;
&:hover {
color: var(--accent);
}
} }
} }
} }

View File

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkModalWindow <MkModalWindow
ref="dialog" ref="dialog"
:width="400" :width="400"
:with-ok-button="true" :with-ok-button="false "
@close="dialog.close()" @close="dialog.close()"
@closed="$emit('closed')" @closed="$emit('closed')"
> >
@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction }}</template> <template #label>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction }}</template>
<template #suffix>{{ rolesThatCanBeUsedThisEmojiAsReaction.length === 0 ? i18n.ts.all : rolesThatCanBeUsedThisEmojiAsReaction.length }}</template> <template #suffix>{{ rolesThatCanBeUsedThisEmojiAsReaction.length === 0 ? i18n.ts.all : rolesThatCanBeUsedThisEmojiAsReaction.length }}</template>
<div class="_gaps"> <div class="_gaps" v-if="!isRequest">
<MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton> <MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
<div v-for="role in rolesThatCanBeUsedThisEmojiAsReaction" :key="role.id" :class="$style.roleItem"> <div v-for="role in rolesThatCanBeUsedThisEmojiAsReaction" :key="role.id" :class="$style.roleItem">
@ -69,7 +69,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-if="!isRequest" v-model="draft" :disabled="isRequest"> <MkSwitch v-if="!isRequest" v-model="draft" :disabled="isRequest">
{{ i18n.ts.draft }} {{ i18n.ts.draft }}
</MkSwitch> </MkSwitch>
<MkButton v-if="emoji" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton>
</div> </div>
</MkSpacer> </MkSpacer>
<div :class="$style.footer"> <div :class="$style.footer">
@ -227,7 +226,7 @@ async function done() {
if (file) { if (file) {
params.fileId = file.id; params.fileId = file.id;
} }
console.log(props.emoji)
if (props.emoji) { if (props.emoji) {
await os.apiWithDialog('admin/emoji/update', { await os.apiWithDialog('admin/emoji/update', {
id: props.emoji.id, id: props.emoji.id,

View File

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer v-if="tab === 'emojis'" :contentMax="1000" :marginMin="20"> <MkSpacer v-if="tab === 'emojis'" :contentMax="1000" :marginMin="20">
<MkButton v-if="$i && ($i.isModerator || $i.policies.canManageCustomEmojis)" primary link to="/custom-emojis-manager">{{ i18n.ts.manageCustomEmojis }}</MkButton> <MkButton v-if="$i && ($i.isModerator || $i.policies.canManageCustomEmojis)" primary link to="/custom-emojis-manager">{{ i18n.ts.manageCustomEmojis }}</MkButton>
<MkButton v-if="$i && (!$i.isModerator && !$i.policies.canManageCustomEmojis && $i.policies.canRequestCustomEmojis)" primary @click="edit">{{ i18n.ts.requestCustomEmojis }}</MkButton> <MkButton v-if="$i && (!$i.isModerator || !$i.policies.canManageCustomEmojis || $i.policies.canRequestCustomEmojis)" primary @click="edit" style='margin-top: 8px;' >{{ i18n.ts.requestCustomEmojis }}</MkButton>
<div class="query" style="margin-top: 10px;"> <div class="query" style="margin-top: 10px;">
<MkInput v-model="q" class="" :placeholder="i18n.ts.search"> <MkInput v-model="q" class="" :placeholder="i18n.ts.search">
@ -36,11 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
</MkFoldableSection> </MkFoldableSection>
</MkSpacer> </MkSpacer>
<MkSpacer v-if="tab === 'new'" :contentMax="1000" :marginMin="20">
<div :class="$style.emojis">
<XEmoji v-for="emoji in newEmojis" :key="emoji.name" :emoji="emoji" :draft="emoji.draft"/>
</div>
</MkSpacer>
<MkSpacer v-if="tab === 'draft'" :contentMax="1000" :marginMin="20"> <MkSpacer v-if="tab === 'draft'" :contentMax="1000" :marginMin="20">
<div :class="$style.emojis"> <div :class="$style.emojis">
<XEmoji v-for="emoji in draftEmojis" :key="emoji.name" :emoji="emoji" :draft="emoji.draft"/> <XEmoji v-for="emoji in draftEmojis" :key="emoji.name" :emoji="emoji" :draft="emoji.draft"/>
@ -68,9 +64,6 @@ const headerActions = $computed(() => []);
const headerTabs = $computed(() => [{ const headerTabs = $computed(() => [{
key: 'emojis', key: 'emojis',
title: i18n.ts.list, title: i18n.ts.list,
}, {
key: 'new',
title: i18n.ts.newEmojis,
}, { }, {
key: 'draft', key: 'draft',
title: i18n.ts.draftEmojis, title: i18n.ts.draftEmojis,
@ -89,7 +82,7 @@ const pagination = {
let q = $ref(''); let q = $ref('');
let searchEmojis = $ref<Misskey.entities.CustomEmoji[]>(null); let searchEmojis = $ref<Misskey.entities.CustomEmoji[]>(null);
let selectedTags = $ref(new Set()); let selectedTags = $ref(new Set());
const draftEmojis = customEmojis.value.filter(emoji => emoji.draft);
function search() { function search() {
if ((q === '' || q == null) && selectedTags.size === 0) { if ((q === '' || q == null) && selectedTags.size === 0) {
searchEmojis = null; searchEmojis = null;
@ -136,6 +129,11 @@ watch($$(q), () => {
watch($$(selectedTags), () => { watch($$(selectedTags), () => {
search(); search();
}, { deep: true }); }, { deep: true });
definePageMetadata({
title: i18n.ts.customEmojis,
icon: null,
});
</script> </script>
<style lang="scss" module> <style lang="scss" module>

View File

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-else class="_button" :class="$style.root" @click="menu"> <button v-else class="_button" :class="$style.root" @click="menu">
<img :src="emoji.url" :class="$style.img" loading="lazy"/> <img :src="emoji.url" :class="$style.img" loading="lazy"/>
<div :class="$style.body"> <div :class="$style.body">
<div :class="$style.name" class="_monospace">{{ emoji.name }}</div> <div :class="$style.name" >{{ emoji.name }}</div>
<div :class="$style.info">{{ emoji.aliases.join(' ') }}</div> <div :class="$style.info">{{ emoji.aliases.join(' ') }}</div>
</div> </div>
</button> </button>
@ -104,5 +104,7 @@ function menu(ev) {
--c: rgb(255 196 0 / 15%);; --c: rgb(255 196 0 / 15%);;
background-image: linear-gradient(45deg,var(--c) 16.67%,transparent 16.67%,transparent 50%,var(--c) 50%,var(--c) 66.67%,transparent 66.67%,transparent 100%); background-image: linear-gradient(45deg,var(--c) 16.67%,transparent 16.67%,transparent 50%,var(--c) 50%,var(--c) 66.67%,transparent 66.67%,transparent 100%);
background-size: 16px 16px; background-size: 16px 16px;
max-width: 64px;
width: 100%;
} }
</style> </style>