This commit is contained in:
syuilo 2023-05-18 20:17:32 +09:00
parent db1098a180
commit 231506772a
6 changed files with 73 additions and 50 deletions

View file

@ -1052,6 +1052,7 @@ failedToPreviewUrl: "プレビューできません"
update: "更新" update: "更新"
rolesThatCanBeUsedThisEmojiAsReaction: "リアクションとして使えるロール" rolesThatCanBeUsedThisEmojiAsReaction: "リアクションとして使えるロール"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ロールの指定が一つもない場合、誰でもリアクションとして使えます。" rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ロールの指定が一つもない場合、誰でもリアクションとして使えます。"
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "ロールは公開ロールである必要があります。"
_initialAccountSetting: _initialAccountSetting:
accountCreated: "アカウントの作成が完了しました!" accountCreated: "アカウントの作成が完了しました!"

View file

@ -26,7 +26,8 @@ export class EmojiEntityService {
category: emoji.category, category: emoji.category,
// || emoji.originalUrl してるのは後方互換性のためpublicUrlはstringなので??はだめ) // || emoji.originalUrl してるのは後方互換性のためpublicUrlはstringなので??はだめ)
url: emoji.publicUrl || emoji.originalUrl, url: emoji.publicUrl || emoji.originalUrl,
isSensitive: emoji.isSensitive, isSensitive: emoji.isSensitive ? true : undefined,
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0 ? emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : undefined,
}; };
} }

View file

@ -24,7 +24,16 @@ export const packedEmojiSimpleSchema = {
}, },
isSensitive: { isSensitive: {
type: 'boolean', type: 'boolean',
optional: true, nullable: false,
},
roleIdsThatCanBeUsedThisEmojiAsReaction: {
type: 'array',
optional: true, nullable: false,
items: {
type: 'string',
optional: false, nullable: false, optional: false, nullable: false,
format: 'id',
},
}, },
}, },
} as const; } as const;

View file

@ -3,11 +3,11 @@ import * as misskey from 'misskey-js';
import { showSuspendedDialog } from './scripts/show-suspended-dialog'; import { showSuspendedDialog } from './scripts/show-suspended-dialog';
import { i18n } from './i18n'; import { i18n } from './i18n';
import { miLocalStorage } from './local-storage'; import { miLocalStorage } from './local-storage';
import { MenuButton } from './types/menu';
import { del, get, set } from '@/scripts/idb-proxy'; import { del, get, set } from '@/scripts/idb-proxy';
import { apiUrl } from '@/config'; import { apiUrl } from '@/config';
import { waiting, api, popup, popupMenu, success, alert } from '@/os'; import { waiting, api, popup, popupMenu, success, alert } from '@/os';
import { unisonReload, reloadChannel } from '@/scripts/unison-reload'; import { unisonReload, reloadChannel } from '@/scripts/unison-reload';
import { MenuButton } from './types/menu';
// TODO: 他のタブと永続化されたstateを同期 // TODO: 他のタブと永続化されたstateを同期
@ -305,3 +305,7 @@ export async function openAccountMenu(opts: {
}); });
} }
} }
if (_DEV_) {
(window as any).$i = $i;
}

View file

@ -69,8 +69,8 @@
<XSection <XSection
v-for="category in customEmojiCategories" v-for="category in customEmojiCategories"
:key="`custom:${category}`" :key="`custom:${category}`"
:initial-shown="false" :initialShown="false"
:emojis="computed(() => customEmojis.filter(e => category === null ? (e.category === 'null' || !e.category) : e.category === category).map(e => `:${e.name}:`))" :emojis="computed(() => customEmojis.filter(e => category === null ? (e.category === 'null' || !e.category) : e.category === category).filter(filterAvailable).map(e => `:${e.name}:`))"
@chosen="chosen" @chosen="chosen"
> >
{{ category || i18n.ts.other }} {{ category || i18n.ts.other }}
@ -102,6 +102,7 @@ import { deviceKind } from '@/scripts/device-kind';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
import { customEmojiCategories, customEmojis } from '@/custom-emojis'; import { customEmojiCategories, customEmojis } from '@/custom-emojis';
import { $i } from '@/account';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
showPinned?: boolean; showPinned?: boolean;
@ -274,10 +275,14 @@ watch(q, () => {
return matches; return matches;
}; };
searchResultCustom.value = Array.from(searchCustom()); searchResultCustom.value = Array.from(searchCustom()).filter(filterAvailable);
searchResultUnicode.value = Array.from(searchUnicode()); searchResultUnicode.value = Array.from(searchUnicode());
}); });
function filterAvailable(emoji: Misskey.entities.CustomEmoji): boolean {
return (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction == null || emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0) || ($i && $i.roles.some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id)));
}
function focus() { function focus() {
if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) { if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) {
searchEl.value?.focus({ searchEl.value?.focus({

View file

@ -41,16 +41,19 @@
</MkInput> </MkInput>
<MkFolder> <MkFolder>
<template #label>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction }}</template> <template #label>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction }}</template>
<div class="_gaps"> <template #suffix>{{ rolesThatCanBeUsedThisEmojiAsReaction.length === 0 ? i18n.ts.all : rolesThatCanBeUsedThisEmojiAsReaction.length }}</template>
<MkInfo>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription }}</MkInfo>
<div class="_gaps">
<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">
<MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false"/> <MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false" style="pointer-events: none;"/>
<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="removeRole(role, $event)"><i class="ti ti-x"></i></button> <button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnassign" @click="removeRole(role, $event)"><i class="ti ti-x"></i></button>
<button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button> <button v-else class="_button" :class="$style.roleUnassign" disabled><i class="ti ti-ban"></i></button>
</div> </div>
<MkInfo>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription }}</MkInfo>
<MkInfo warn>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn }}</MkInfo>
</div> </div>
</MkFolder> </MkFolder>
<MkSwitch v-model="isSensitive">isSensitive</MkSwitch> <MkSwitch v-model="isSensitive">isSensitive</MkSwitch>
@ -128,8 +131,8 @@ async function removeRole(role, ev) {
async function done() { async function done() {
const params = { const params = {
name, name,
category, category: category === '' ? null : category,
aliases: aliases.split(' '), aliases: aliases.split(' ').filter(x => x !== ''),
license: license === '' ? null : license, license: license === '' ? null : license,
isSensitive, isSensitive,
localOnly, localOnly,