feat: センシティブなカスタム絵文字のリアクションを受け入れない設定を追加
This commit is contained in:
parent
527a13b77d
commit
3804c6e7ad
8 changed files with 27 additions and 14 deletions
|
@ -17,6 +17,8 @@
|
||||||
### General
|
### General
|
||||||
- カスタム絵文字ごとにそれをリアクションとして使えるロールを設定できるように
|
- カスタム絵文字ごとにそれをリアクションとして使えるロールを設定できるように
|
||||||
- カスタム絵文字ごとに連合するかどうか設定できるように
|
- カスタム絵文字ごとに連合するかどうか設定できるように
|
||||||
|
- カスタム絵文字ごとにセンシティブフラグを設定できるように
|
||||||
|
- センシティブなカスタム絵文字のリアクションを受け入れない設定が可能に
|
||||||
- タイムラインにフォロイーの行った他人へのリプライを含めるかどうかの設定をアカウントに保存するのをやめるように
|
- タイムラインにフォロイーの行った他人へのリプライを含めるかどうかの設定をアカウントに保存するのをやめるように
|
||||||
- 今後はAPI呼び出し時およびストリーミング接続時に設定するようになります
|
- 今後はAPI呼び出し時およびストリーミング接続時に設定するようになります
|
||||||
|
|
||||||
|
|
|
@ -990,7 +990,9 @@ postToTheChannel: "チャンネルに投稿"
|
||||||
cannotBeChangedLater: "後から変更できません。"
|
cannotBeChangedLater: "後から変更できません。"
|
||||||
reactionAcceptance: "リアクションの受け入れ"
|
reactionAcceptance: "リアクションの受け入れ"
|
||||||
likeOnly: "いいねのみ"
|
likeOnly: "いいねのみ"
|
||||||
likeOnlyForRemote: "リモートからはいいねのみ"
|
likeOnlyForRemote: "全て (リモートはいいねのみ)"
|
||||||
|
nonSensitiveOnly: "非センシティブのみ"
|
||||||
|
nonSensitiveOnlyForLocalLikeOnlyForRemote: "非センシティブのみ (リモートはいいねのみ)"
|
||||||
rolesAssignedToMe: "自分に割り当てられたロール"
|
rolesAssignedToMe: "自分に割り当てられたロール"
|
||||||
resetPasswordConfirm: "パスワードリセットしますか?"
|
resetPasswordConfirm: "パスワードリセットしますか?"
|
||||||
sensitiveWords: "センシティブワード"
|
sensitiveWords: "センシティブワード"
|
||||||
|
|
|
@ -106,7 +106,7 @@ export class ReactionService {
|
||||||
|
|
||||||
let reaction = _reaction ?? FALLBACK;
|
let reaction = _reaction ?? FALLBACK;
|
||||||
|
|
||||||
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote') && (user.host != null))) {
|
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && (user.host != null))) {
|
||||||
reaction = '❤️';
|
reaction = '❤️';
|
||||||
} else if (_reaction) {
|
} else if (_reaction) {
|
||||||
const custom = reaction.match(isCustomEmojiRegexp);
|
const custom = reaction.match(isCustomEmojiRegexp);
|
||||||
|
@ -124,6 +124,11 @@ export class ReactionService {
|
||||||
if (emoji) {
|
if (emoji) {
|
||||||
if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || (await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) {
|
if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || (await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) {
|
||||||
reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
|
reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
|
||||||
|
|
||||||
|
// センシティブ
|
||||||
|
if ((note.reactionAcceptance === 'nonSensitiveOnly') && emoji.isSensitive) {
|
||||||
|
reaction = FALLBACK;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// リアクションとして使う権限がない
|
// リアクションとして使う権限がない
|
||||||
reaction = FALLBACK;
|
reaction = FALLBACK;
|
||||||
|
|
|
@ -90,7 +90,7 @@ export class Note {
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 64, nullable: true,
|
length: 64, nullable: true,
|
||||||
})
|
})
|
||||||
public reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | null;
|
public reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null;
|
||||||
|
|
||||||
@Column('smallint', {
|
@Column('smallint', {
|
||||||
default: 0,
|
default: 0,
|
||||||
|
|
|
@ -99,7 +99,7 @@ export const paramDef = {
|
||||||
} },
|
} },
|
||||||
cw: { type: 'string', nullable: true, maxLength: 100 },
|
cw: { type: 'string', nullable: true, maxLength: 100 },
|
||||||
localOnly: { type: 'boolean', default: false },
|
localOnly: { type: 'boolean', default: false },
|
||||||
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote'], default: null },
|
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },
|
||||||
noExtractMentions: { type: 'boolean', default: false },
|
noExtractMentions: { type: 'boolean', default: false },
|
||||||
noExtractHashtags: { type: 'boolean', default: false },
|
noExtractHashtags: { type: 'boolean', default: false },
|
||||||
noExtractEmojis: { type: 'boolean', default: false },
|
noExtractEmojis: { type: 'boolean', default: false },
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
|
<span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
|
||||||
<span v-else><i class="ti ti-rocket-off"></i></span>
|
<span v-else><i class="ti ti-rocket-off"></i></span>
|
||||||
</button>
|
</button>
|
||||||
<button v-click-anime v-tooltip="i18n.ts.reactionAcceptance" :class="['_button', $style.headerRightItem, $style.reactionAcceptance, { [$style.danger]: reactionAcceptance }]" @click="toggleReactionAcceptance">
|
<button v-click-anime v-tooltip="i18n.ts.reactionAcceptance" :class="['_button', $style.headerRightItem, $style.reactionAcceptance, { [$style.danger]: reactionAcceptance === 'likeOnly' }]" @click="toggleReactionAcceptance">
|
||||||
<span v-if="reactionAcceptance === 'likeOnly'"><i class="ti ti-heart"></i></span>
|
<span v-if="reactionAcceptance === 'likeOnly'"><i class="ti ti-heart"></i></span>
|
||||||
<span v-else-if="reactionAcceptance === 'likeOnlyForRemote'"><i class="ti ti-heart-plus"></i></span>
|
<span v-else-if="reactionAcceptance === 'likeOnlyForRemote'"><i class="ti ti-heart-plus"></i></span>
|
||||||
<span v-else><i class="ti ti-icons"></i></span>
|
<span v-else><i class="ti ti-icons"></i></span>
|
||||||
|
@ -484,8 +484,10 @@ async function toggleReactionAcceptance() {
|
||||||
title: i18n.ts.reactionAcceptance,
|
title: i18n.ts.reactionAcceptance,
|
||||||
items: [
|
items: [
|
||||||
{ value: null, text: i18n.ts.all },
|
{ value: null, text: i18n.ts.all },
|
||||||
{ value: 'likeOnly' as const, text: i18n.ts.likeOnly },
|
|
||||||
{ value: 'likeOnlyForRemote' as const, text: i18n.ts.likeOnlyForRemote },
|
{ value: 'likeOnlyForRemote' as const, text: i18n.ts.likeOnlyForRemote },
|
||||||
|
{ value: 'nonSensitiveOnly' as const, text: i18n.ts.nonSensitiveOnly },
|
||||||
|
{ value: 'nonSensitiveOnlyForLocalLikeOnlyForRemote' as const, text: i18n.ts.nonSensitiveOnlyForLocalLikeOnlyForRemote },
|
||||||
|
{ value: 'likeOnly' as const, text: i18n.ts.likeOnly },
|
||||||
],
|
],
|
||||||
default: reactionAcceptance,
|
default: reactionAcceptance,
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,21 +8,21 @@
|
||||||
<MkButton primary rounded :class="$style.bannerEdit" @click="changeBanner">{{ i18n.ts._profile.changeBanner }}</MkButton>
|
<MkButton primary rounded :class="$style.bannerEdit" @click="changeBanner">{{ i18n.ts._profile.changeBanner }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkInput v-model="profile.name" :max="30" manual-save>
|
<MkInput v-model="profile.name" :max="30" manualSave>
|
||||||
<template #label>{{ i18n.ts._profile.name }}</template>
|
<template #label>{{ i18n.ts._profile.name }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
|
||||||
<MkTextarea v-model="profile.description" :max="500" tall manual-save>
|
<MkTextarea v-model="profile.description" :max="500" tall manualSave>
|
||||||
<template #label>{{ i18n.ts._profile.description }}</template>
|
<template #label>{{ i18n.ts._profile.description }}</template>
|
||||||
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
|
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
|
||||||
</MkTextarea>
|
</MkTextarea>
|
||||||
|
|
||||||
<MkInput v-model="profile.location" manual-save>
|
<MkInput v-model="profile.location" manualSave>
|
||||||
<template #label>{{ i18n.ts.location }}</template>
|
<template #label>{{ i18n.ts.location }}</template>
|
||||||
<template #prefix><i class="ti ti-map-pin"></i></template>
|
<template #prefix><i class="ti ti-map-pin"></i></template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
|
||||||
<MkInput v-model="profile.birthday" type="date" manual-save>
|
<MkInput v-model="profile.birthday" type="date" manualSave>
|
||||||
<template #label>{{ i18n.ts.birthday }}</template>
|
<template #label>{{ i18n.ts.birthday }}</template>
|
||||||
<template #prefix><i class="ti ti-cake"></i></template>
|
<template #prefix><i class="ti ti-cake"></i></template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
<Sortable
|
<Sortable
|
||||||
v-model="fields"
|
v-model="fields"
|
||||||
class="_gaps_s"
|
class="_gaps_s"
|
||||||
item-key="id"
|
itemKey="id"
|
||||||
:animation="150"
|
:animation="150"
|
||||||
:handle="'.' + $style.dragItemHandle"
|
:handle="'.' + $style.dragItemHandle"
|
||||||
@start="e => e.item.classList.add('active')"
|
@start="e => e.item.classList.add('active')"
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
<button v-if="!fieldEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
|
<button v-if="!fieldEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
|
||||||
<button v-if="fieldEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteField(index)"><i class="ti ti-x"></i></button>
|
<button v-if="fieldEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteField(index)"><i class="ti ti-x"></i></button>
|
||||||
<div :class="$style.dragItemForm">
|
<div :class="$style.dragItemForm">
|
||||||
<FormSplit :min-width="200">
|
<FormSplit :minWidth="200">
|
||||||
<MkInput v-model="element.name" small>
|
<MkInput v-model="element.name" small>
|
||||||
<template #label>{{ i18n.ts._profile.metadataLabel }}</template>
|
<template #label>{{ i18n.ts._profile.metadataLabel }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
@ -88,8 +88,10 @@
|
||||||
<MkSelect v-model="reactionAcceptance">
|
<MkSelect v-model="reactionAcceptance">
|
||||||
<template #label>{{ i18n.ts.reactionAcceptance }}</template>
|
<template #label>{{ i18n.ts.reactionAcceptance }}</template>
|
||||||
<option :value="null">{{ i18n.ts.all }}</option>
|
<option :value="null">{{ i18n.ts.all }}</option>
|
||||||
<option value="likeOnly">{{ i18n.ts.likeOnly }}</option>
|
|
||||||
<option value="likeOnlyForRemote">{{ i18n.ts.likeOnlyForRemote }}</option>
|
<option value="likeOnlyForRemote">{{ i18n.ts.likeOnlyForRemote }}</option>
|
||||||
|
<option value="nonSensitiveOnly">{{ i18n.ts.nonSensitiveOnly }}</option>
|
||||||
|
<option value="nonSensitiveOnlyForLocalLikeOnlyForRemote">{{ i18n.ts.nonSensitiveOnlyForLocalLikeOnlyForRemote }}</option>
|
||||||
|
<option value="likeOnly">{{ i18n.ts.likeOnly }}</option>
|
||||||
</MkSelect>
|
</MkSelect>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -92,7 +92,7 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||||
},
|
},
|
||||||
reactionAcceptance: {
|
reactionAcceptance: {
|
||||||
where: 'account',
|
where: 'account',
|
||||||
default: null as 'likeOnly' | 'likeOnlyForRemote' | null,
|
default: 'nonSensitiveOnly' as 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null,
|
||||||
},
|
},
|
||||||
mutedWords: {
|
mutedWords: {
|
||||||
where: 'account',
|
where: 'account',
|
||||||
|
|
Loading…
Reference in a new issue