絵文字ダイアログの不具合の修正

(cherry picked from commit c9d6c17353a663bf68cdea9bcef100f5de5edb68)
This commit is contained in:
tar_bin 2023-05-19 01:43:42 +09:00 committed by mattyatea
parent ffa81260ac
commit d607f34380
4 changed files with 50 additions and 23 deletions

View File

@ -653,6 +653,8 @@ other: "その他"
regenerateLoginToken: "ログイントークンを再生成" regenerateLoginToken: "ログイントークンを再生成"
regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。" regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。"
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。" setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
emojiNameValidation: "名前には英数字と_が利用できます。"
isSensitive: "センシティブ"
fileIdOrUrl: "ファイルIDまたはURL" fileIdOrUrl: "ファイルIDまたはURL"
behavior: "動作" behavior: "動作"
sample: "サンプル" sample: "サンプル"

View File

@ -36,6 +36,8 @@ export const paramDef = {
} }, } },
license: { type: 'string', nullable: true }, license: { type: 'string', nullable: true },
fileId: { type: 'string', format: 'misskey:id' }, fileId: { type: 'string', format: 'misskey:id' },
isSensitive: { type: 'boolean' },
localOnly: { type: 'boolean' },
}, },
required: ['name', 'fileId'], required: ['name', 'fileId'],
} as const; } as const;
@ -66,6 +68,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
license: ps.license ?? null, license: ps.license ?? null,
host: null, host: null,
draft: true, draft: true,
isSensitive: ps.isSensitive ?? false,
localOnly: ps.localOnly ?? false,
roleIdsThatCanBeUsedThisEmojiAsReaction: [],
}); });
this.moderationLogService.insertModerationLog(me, 'addEmoji', { this.moderationLogService.insertModerationLog(me, 'addEmoji', {

View File

@ -84,14 +84,6 @@ function toggleTag(tag) {
const edit = () => { const edit = () => {
os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), { os.popup(defineAsyncComponent(() => import('./emoji-edit-dialog.vue')), {
emoji: {
name: '',
category: null,
aliases: [],
license: '',
url: '',
draft: true,
},
isRequest: true, isRequest: true,
}, { }, {
done: result => { done: result => {

View File

@ -12,6 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@closed="$emit('closed')" @closed="$emit('closed')"
> >
<template v-if="emoji" #header>:{{ emoji.name }}:</template> <template v-if="emoji" #header>:{{ emoji.name }}:</template>
<template v-else-if="isRequest" #header>{{ i18n.ts.requestCustomEmojis }}</template>
<template v-else #header>New emoji</template> <template v-else #header>New emoji</template>
<div> <div>
@ -34,6 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton rounded style="margin: 0 auto;" @click="changeImage">{{ i18n.ts.selectFile }}</MkButton> <MkButton rounded style="margin: 0 auto;" @click="changeImage">{{ i18n.ts.selectFile }}</MkButton>
<MkInput v-model="name" pattern="[a-z0-9_]"> <MkInput v-model="name" pattern="[a-z0-9_]">
<template #label>{{ i18n.ts.name }}</template> <template #label>{{ i18n.ts.name }}</template>
<template #caption>{{ i18n.ts.emojiNameValidation }}</template>
</MkInput> </MkInput>
<MkInput v-model="category" :datalist="customEmojiCategories"> <MkInput v-model="category" :datalist="customEmojiCategories">
<template #label>{{ i18n.ts.category }}</template> <template #label>{{ i18n.ts.category }}</template>
@ -45,7 +47,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInput v-model="license"> <MkInput v-model="license">
<template #label>{{ i18n.ts.license }}</template> <template #label>{{ i18n.ts.license }}</template>
</MkInput> </MkInput>
<MkFolder> <MkFolder v-if="!isRequest" >
<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>
@ -62,13 +64,20 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInfo warn>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn }}</MkInfo> <MkInfo warn>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn }}</MkInfo>
</div> </div>
</MkFolder> </MkFolder>
<MkSwitch v-model="isSensitive">isSensitive</MkSwitch> <MkSwitch v-model="isSensitive">{{ i18n.ts.isSensitive }}</MkSwitch>
<MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch> <MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch>
<MkSwitch v-if="!isRequest" v-model="draft" :disabled="isRequest">
{{ i18n.ts.draft }}
</MkSwitch>
<MkButton v-if="emoji" danger @click="del()"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton> <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">
<MkButton primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.emoji ? i18n.ts.update : i18n.ts.create }}</MkButton> <div :class="$style.footerButtons">
<MkButton v-if="!isRequest" danger rounded style="margin: 0 auto;" @click="del()"><i class="ti ti-check"></i> {{ i18n.ts.delete }}</MkButton>
<MkButton v-if="validation" primary rounded style="margin: 0 auto;" @click="done"><i class="ti ti-check"></i> {{ props.emoji ? i18n.ts.update : i18n.ts.create }}</MkButton>
<MkButton v-else rounded style="margin: 0 auto;"><i class="ti ti-check"></i> {{ props.emoji ? i18n.ts.update : i18n.ts.create }}</MkButton>
</div>
<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>
@ -110,7 +119,7 @@ let roleIdsThatCanBeUsedThisEmojiAsReaction = $ref(props.emoji ? props.emoji.rol
let rolesThatCanBeUsedThisEmojiAsReaction = $ref([]); let rolesThatCanBeUsedThisEmojiAsReaction = $ref([]);
let file = $ref<Misskey.entities.DriveFile>(); let file = $ref<Misskey.entities.DriveFile>();
let chooseFile: DriveFile|null = $ref(null); let chooseFile: DriveFile|null = $ref(null);
let draft = $ref(props.emoji.draft); let draft = $ref(props.emoji ? props.emoji.draft : false);
let isRequest = $ref(props.isRequest); let isRequest = $ref(props.isRequest);
watch($$(roleIdsThatCanBeUsedThisEmojiAsReaction), async () => { watch($$(roleIdsThatCanBeUsedThisEmojiAsReaction), async () => {
@ -120,7 +129,9 @@ watch($$(roleIdsThatCanBeUsedThisEmojiAsReaction), async () => {
const imgUrl = computed(() => file ? file.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null); const imgUrl = computed(() => file ? file.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null);
let draft = $ref(props.emoji.draft); let draft = $ref(props.emoji.draft);
let isRequest = $ref(props.isRequest); let isRequest = $ref(props.isRequest);
const validation = computed(() => {
return name.match(/^[a-zA-Z0-9_]+$/) && imgUrl.value != null;
})
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'done', v: { deleted?: boolean; updated?: any; created?: any }): void, (ev: 'done', v: { deleted?: boolean; updated?: any; created?: any }): void,
(ev: 'closed'): void (ev: 'closed'): void
@ -207,15 +218,16 @@ async function update() {
} }
async function done() { async function done() {
const params = { const params = {
name, name,
category: category === '' ? null : category, category: category === '' ? null : category,
aliases: aliases.split(' ').filter(x => x !== ''), aliases: aliases.replace(' ', ' ').split(' ').filter(x => x !== ''),
license: license === '' ? null : license, license: license === '' ? null : license,
isSensitive, draft: draft,
localOnly, isSensitive,
roleIdsThatCanBeUsedThisEmojiAsReaction: rolesThatCanBeUsedThisEmojiAsReaction.map(x => x.id), localOnly,
}; roleIdsThatCanBeUsedThisEmojiAsReaction: rolesThatCanBeUsedThisEmojiAsReaction.map(x => x.id),
};
if (file) { if (file) {
params.fileId = file.id; params.fileId = file.id;
@ -236,7 +248,9 @@ async function done() {
dialog.close(); dialog.close();
} else { } else {
const created = await os.apiWithDialog('admin/emoji/add', params); const created = isRequest
? await os.apiWithDialog('admin/emoji/add-draft', params)
: await os.apiWithDialog('admin/emoji/add', params);
emit('done', { emit('done', {
created: created, created: created,
@ -246,6 +260,13 @@ async function done() {
} }
} }
function chooseFileFrom(ev) {
selectFiles(ev.currentTarget ?? ev.target, i18n.ts.attachFile).then(files_ => {
chooseFile = files_[0];
url = chooseFile.url;
});
}
async function del() { async function del() {
const { canceled } = await os.confirm({ const { canceled } = await os.confirm({
type: 'warning', type: 'warning',
@ -308,4 +329,11 @@ async function del() {
-webkit-backdrop-filter: var(--blur, blur(15px)); -webkit-backdrop-filter: var(--blur, blur(15px));
backdrop-filter: var(--blur, blur(15px)); backdrop-filter: var(--blur, blur(15px));
} }
.footerButtons {
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: center;
}
</style> </style>