add mandatory CW for instances
This commit is contained in:
parent
595c004a74
commit
5e0115335a
26 changed files with 282 additions and 8 deletions
|
|
@ -26,6 +26,14 @@ Displays a placeholder for a muted note.
|
|||
{{ mute.userMandatoryCW }}
|
||||
</template>
|
||||
</I18n>
|
||||
<I18n v-if="mute.instanceMandatoryCW" :src="i18n.ts.instanceIsFlaggedAs" tag="small">
|
||||
<template #name>
|
||||
{{ note.user.instance?.name ?? note.user.host }}
|
||||
</template>
|
||||
<template #cw>
|
||||
{{ mute.instanceMandatoryCW }}
|
||||
</template>
|
||||
</I18n>
|
||||
|
||||
<!-- Muted notes/threads -->
|
||||
<I18n v-if="mute.noteMuted" :src="i18n.ts.userSaysSomethingInMutedNote" tag="small">
|
||||
|
|
@ -89,7 +97,7 @@ const expandNote = ref(false);
|
|||
|
||||
const mute = computed(() => checkMute(props.note, props.withHardMute));
|
||||
const mutedWords = computed(() => mute.value.softMutedWords?.join(', '));
|
||||
const isMuted = computed(() => mute.value.hardMuted || mutedWords.value || mute.value.noteMandatoryCW || mute.value.userMandatoryCW || mute.value.noteMuted || mute.value.threadMuted || mute.value.sensitiveMuted);
|
||||
const isMuted = computed(() => mute.value.hardMuted || mutedWords.value || mute.value.noteMandatoryCW || mute.value.userMandatoryCW || mute.value.instanceMandatoryCW || mute.value.noteMuted || mute.value.threadMuted || mute.value.sensitiveMuted);
|
||||
const isExpanded = computed(() => expandNote.value || !isMuted.value);
|
||||
const rootClass = computed(() => isExpanded.value ? props.expandedClass : undefined);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
'resetPassword',
|
||||
'setMandatoryCW',
|
||||
'setMandatoryCWForNote',
|
||||
'setMandatoryCWForInstance',
|
||||
'suspendRemoteInstance',
|
||||
'setRemoteInstanceNSFW',
|
||||
'unsetRemoteInstanceNSFW',
|
||||
|
|
@ -81,6 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-else-if="log.type === 'resetPassword'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'setMandatoryCW'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'setMandatoryCWForNote'">: @{{ log.info.noteUserUsername }}{{ log.info.noteUserHost ? '@' + log.info.noteUserHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'setMandatoryCWForInstance'">: {{ log.info.host }}</span>
|
||||
<span v-else-if="log.type === 'assignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-arrow-right"></i> {{ log.info.roleName }}</span>
|
||||
<span v-else-if="log.type === 'unassignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-equal-not"></i> {{ log.info.roleName }}</span>
|
||||
<span v-else-if="log.type === 'createRole'">: {{ log.info.role.name }}</span>
|
||||
|
|
@ -217,6 +219,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<CodeDiff :context="0" :hideHeader="true" :oldString="log.info.oldCW ?? ''" :newString="log.info.newCW ?? ''" maxHeight="150px"/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="log.type === 'setMandatoryCWForInstance'">
|
||||
<div :class="$style.diff">
|
||||
<CodeDiff :context="0" :hideHeader="true" :oldString="log.info.oldCW ?? ''" :newString="log.info.newCW ?? ''" maxHeight="150px"/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="log.type === 'unsuspend'">
|
||||
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkInfo v-if="isBaseMediaSilenced" warn>{{ i18n.ts.mediaSilencedByBase }}</MkInfo>
|
||||
<MkSwitch v-model="isMediaSilenced" :disabled="!meta || !instance || isBaseMediaSilenced" @update:modelValue="toggleMediaSilenced">{{ i18n.ts.mediaSilenceThisInstance }}</MkSwitch>
|
||||
|
||||
<MkInput v-model="mandatoryCW" type="text" manualSave @update:modelValue="onMandatoryCWChanged">
|
||||
<template #label>{{ i18n.ts.mandatoryCW }}</template>
|
||||
<template #caption>{{ i18n.ts.mandatoryCWDescription }}</template>
|
||||
</MkInput>
|
||||
|
||||
<div :class="$style.buttonStrip">
|
||||
<MkButton inline :disabled="!instance" @click="refreshMetadata"><i class="ph-cloud-arrow-down ph-bold ph-lg"></i> {{ i18n.ts.updateRemoteUser }}</MkButton>
|
||||
<MkButton inline :disabled="!instance" danger @click="deleteAllFiles"><i class="ph-trash ph-bold ph-lg"></i> {{ i18n.ts.deleteAllFiles }}</MkButton>
|
||||
|
|
@ -234,6 +239,7 @@ import { copyToClipboard } from '@/utility/copy-to-clipboard';
|
|||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import MkNumber from '@/components/MkNumber.vue';
|
||||
import SkBadgeStrip from '@/components/SkBadgeStrip.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
host: string;
|
||||
|
|
@ -259,6 +265,7 @@ const rejectReports = ref(false);
|
|||
const isMediaSilenced = ref(false);
|
||||
const faviconUrl = ref<string | null>(null);
|
||||
const moderationNote = ref('');
|
||||
const mandatoryCW = ref<string | null>(null);
|
||||
|
||||
const baseDomains = computed(() => {
|
||||
const domains: string[] = [];
|
||||
|
|
@ -306,6 +313,13 @@ const badges = computed(() => {
|
|||
style: 'warning',
|
||||
});
|
||||
}
|
||||
if (instance.value.mandatoryCW) {
|
||||
arr.push({
|
||||
key: 'cw',
|
||||
label: i18n.ts.cw,
|
||||
style: 'warning',
|
||||
});
|
||||
}
|
||||
if (instance.value.isNSFW) {
|
||||
arr.push({
|
||||
key: 'nsfw',
|
||||
|
|
@ -365,6 +379,13 @@ async function saveModerationNote() {
|
|||
}
|
||||
}
|
||||
|
||||
async function onMandatoryCWChanged(value: string | number) {
|
||||
await os.promiseDialog(async () => {
|
||||
await misskeyApi('admin/cw-instance', { host: props.host, cw: String(value) || null });
|
||||
await fetch();
|
||||
});
|
||||
}
|
||||
|
||||
async function fetch(withHint = false): Promise<void> {
|
||||
const [m, i] = await Promise.all([
|
||||
(withHint && props.metaHint)
|
||||
|
|
@ -389,6 +410,7 @@ async function fetch(withHint = false): Promise<void> {
|
|||
isMediaSilenced.value = instance.value?.isMediaSilenced ?? false;
|
||||
faviconUrl.value = getProxiedImageUrlNullable(instance.value?.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.value?.iconUrl, 'preview');
|
||||
moderationNote.value = instance.value?.moderationNote ?? '';
|
||||
mandatoryCW.value = instance.value?.mandatoryCW ?? '';
|
||||
}
|
||||
|
||||
async function toggleBlock(): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export interface Mute {
|
|||
noteMandatoryCW?: string | null;
|
||||
// TODO show this as a single block on user timelines
|
||||
userMandatoryCW?: string | null;
|
||||
instanceMandatoryCW?: string | null;
|
||||
}
|
||||
|
||||
export function checkMute(note: Misskey.entities.Note, withHardMute?: boolean): Mute {
|
||||
|
|
@ -35,20 +36,21 @@ export function checkMute(note: Misskey.entities.Note, withHardMute?: boolean):
|
|||
const noteMuted = note.isMutingNote;
|
||||
const noteMandatoryCW = note.mandatoryCW;
|
||||
const userMandatoryCW = note.user.mandatoryCW;
|
||||
const instanceMandatoryCW = note.user.instance?.mandatoryCW;
|
||||
|
||||
// Hard mute
|
||||
if (withHardMute && isHardMuted(note)) {
|
||||
return { hardMuted: true, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW };
|
||||
return { hardMuted: true, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
|
||||
}
|
||||
|
||||
// Soft mute
|
||||
const softMutedWords = isSoftMuted(note);
|
||||
if (softMutedWords.length > 0) {
|
||||
return { softMutedWords, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW };
|
||||
return { softMutedWords, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
|
||||
}
|
||||
|
||||
// Other / no mute
|
||||
return { sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW };
|
||||
return { sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
|
||||
}
|
||||
|
||||
function isHardMuted(note: Misskey.entities.Note): boolean {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue