don't recursively check mute text and improve grouping

This commit is contained in:
Hazelnoot 2025-07-06 19:40:22 -04:00
parent 179c7e18bd
commit ba433d8914
23 changed files with 122 additions and 51 deletions

View file

@ -10,8 +10,10 @@ Displays a note in the simple view with either Misskey or Sharkey style, based o
ref="rootEl"
:note="note"
:expandAllCws="expandAllCws"
:skipMute="skipMute"
:hideFiles="hideFiles"
@editScheduledNote="() => emit('editScheduleNote')"
@expandMute="n => emit('expandMute', n)"
/>
</template>
@ -38,10 +40,12 @@ defineProps<{
scheduledNoteId?: string
};
expandAllCws?: boolean;
skipMute?: boolean;
hideFiles?: boolean;
}>();
const emit = defineEmits<{
(ev: 'editScheduleNote'): void;
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
</script>

View file

@ -98,9 +98,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :local="!appearNote.user.host" :author="appearNote.user" :emojiUrls="appearNote.emojis" :class="$style.poll" @click.stop/>
<div v-if="isEnabledUrlPreview" :class="[$style.urlPreview, '_gaps_s']" @click.stop>
<SkUrlPreviewGroup :sourceUrls="urls" :sourceNote="appearNote" :compact="true" :detail="false" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds"/>
<SkUrlPreviewGroup :sourceUrls="urls" :sourceNote="appearNote" :compact="true" :detail="false" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" @expandMute="n => emit('expandMute', n)"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" @expandMute="n => emit('expandMute', n)"/></div>
<button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click.stop @click="collapsed = false">
<span :class="$style.collapsedLabel">{{ i18n.ts.showMore }}</span>
</button>

View file

@ -113,9 +113,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :local="!appearNote.user.host" :class="$style.poll" :author="appearNote.user" :emojiUrls="appearNote.emojis"/>
<div v-if="isEnabledUrlPreview" class="_gaps_s" style="margin-top: 6px;" @click.stop>
<SkUrlPreviewGroup :sourceNodes="parsed" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds"/>
<SkUrlPreviewGroup :sourceNodes="parsed" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" @expandMute="n => emit('expandMute', n)"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws"/></div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws" @expandMute="n => emit('expandMute', n)"/></div>
</div>
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA>
</div>

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div v-if="!isDeleted" :class="$style.root">
<SkMutedNote v-if="!isDeleted" :note="note" :skipMute="skipMute" :class="$style.root" @expandMute="n => emit('expandMute', n)">
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
<div :class="$style.main">
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
</div>
</div>
</div>
</SkMutedNote>
</template>
<script lang="ts" setup>
@ -33,6 +33,7 @@ import MkNoteHeader from '@/components/MkNoteHeader.vue';
import MkSubNoteContent from '@/components/MkSubNoteContent.vue';
import MkCwButton from '@/components/MkCwButton.vue';
import MkButton from '@/components/MkButton.vue';
import SkMutedNote from '@/components/SkMutedNote.vue';
import { i18n } from '@/i18n.js';
import { prefer } from '@/preferences.js';
import { setupNoteViewInterruptors } from '@/plugin.js';
@ -44,6 +45,7 @@ const props = defineProps<{
scheduledNoteId?: string
};
expandAllCws?: boolean;
skipMute?: boolean;
hideFiles?: boolean;
}>();

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<SkMutedNote v-show="!isDeleted" ref="rootComp" :note="appearNote" :dive="false" :mutedClass="$style.muted" :expandedClass="[$style.root, { [$style.children]: depth > 1 }]" @expandMute="n => emit('expandMute', n)">
<SkMutedNote v-show="!isDeleted" ref="rootComp" :note="appearNote" :mutedClass="$style.muted" :expandedClass="[$style.root, { [$style.children]: depth > 1 }]" @expandMute="n => emit('expandMute', n)">
<div :class="$style.main">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>

View file

@ -52,8 +52,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</button>
</div>
</header>
<MkNoteSimple v-if="reply" :class="$style.targetNote" :hideFiles="true" :note="reply"/>
<MkNoteSimple v-if="renoteTargetNote" :class="$style.targetNote" :hideFiles="true" :note="renoteTargetNote"/>
<MkNoteSimple v-if="reply" :class="$style.targetNote" :hideFiles="true" :note="reply" :skipMute="true"/>
<MkNoteSimple v-if="renoteTargetNote" :class="$style.targetNote" :hideFiles="true" :note="renoteTargetNote" :skipMute="true"/>
<div v-if="quoteId" :class="$style.withQuote"><i class="ti ti-quote"></i> {{ i18n.ts.quoteAttached }}<button @click="quoteId = null; renoteTargetNote = null;"><i class="ti ti-x"></i></button></div>
<div v-if="visibility === 'specified'" :class="$style.toSpecified">
<span style="margin-right: 8px;">{{ i18n.ts.recipient }}</span>

View file

@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #default="{ items }">
<div class="_gaps">
<MkNoteSimple v-for="item in items" :key="item.id" :scheduled="true" :note="item.note" @editScheduleNote="listUpdate"/>
<MkNoteSimple v-for="item in items" :key="item.id" :scheduled="true" :note="item.note" :skipMute="true" @editScheduleNote="listUpdate"/>
</div>
</template>
</MkPagination>

View file

@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkButton>
</div>
</template>
<div v-else-if="theNote" :class="[$style.link, { [$style.compact]: compact }]"><DynamicNoteSimple :note="theNote" :class="$style.body"/></div>
<div v-else-if="theNote" :class="[$style.link, { [$style.compact]: compact }]"><DynamicNoteSimple :note="theNote" :class="$style.body" @expandMute="n => emit('expandMute', n)"/></div>
<div v-else-if="!hidePreview">
<component :is="self ? 'MkA' : 'a'" :class="[$style.link, { [$style.compact]: compact }]" :[attr]="maybeRelativeUrl" rel="nofollow noopener" :target="target" :title="url" @click.prevent="self ? true : warningExternalWebsite(url)" @click.stop>
<div v-if="thumbnail && !sensitive" :class="$style.thumbnail" :style="prefer.s.dataSaver.urlPreview ? '' : { backgroundImage: `url('${thumbnail}')` }">
@ -151,6 +151,10 @@ const props = withDefaults(defineProps<{
attributionHint: undefined,
});
const emit = defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
const MOBILE_THRESHOLD = 500;
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);

View file

@ -6,7 +6,7 @@ Selectable entry on the "Following" feed, displaying a user with their most rece
-->
<template>
<SkMutedNote :note="note" :dive="false" :mutedClass="$style.muted" :expandedClass="$style.root" @click="$emit('select', note.user)">
<SkMutedNote :note="note" :mutedClass="$style.muted" :expandedClass="$style.root" @click="$emit('select', note.user)">
<div :class="$style.avatar">
<MkAvatar :class="$style.icon" :user="note.user" indictor/>
</div>

View file

@ -86,14 +86,14 @@ import { checkMute } from '@/utility/check-word-mute.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
withHardMute?: boolean;
dive?: boolean;
mutedClass?: string | string[] | Record<string, boolean> | (string | string[] | Record<string, boolean>)[];
expandedClass?: string | string[] | Record<string, boolean> | (string | string[] | Record<string, boolean>)[];
skipMute?: boolean;
}>(), {
withHardMute: true,
dive: true,
mutedClass: undefined,
expandedClass: undefined,
skipMute: false,
});
const emit = defineEmits<{
@ -107,14 +107,10 @@ function expand() {
emit('expandMute', props.note);
}
const mute = checkMute(
computed(() => props.note),
computed(() => props.withHardMute),
computed(() => props.dive),
);
const mute = checkMute(computed(() => props.note), computed(() => props.withHardMute));
const mutedWords = computed(() => mute.value.softMutedWords?.join(', '));
const isExpanded = computed(() => expandNote.value || !mute.value.hasMute);
const isExpanded = computed(() => props.skipMute || expandNote.value || !mute.value.hasMute);
const rootClass = computed(() => isExpanded.value ? props.expandedClass : undefined);
const instanceName = computed(() => {

View file

@ -101,7 +101,7 @@ Displays a note in the Sharkey style. Used to show the "main" note in a given co
</div>
<MkPoll v-if="appearNote.poll" :noteId="appearNote.id" :poll="appearNote.poll" :local="!appearNote.user.host" :author="appearNote.user" :emojiUrls="appearNote.emojis" :class="$style.poll" @click.stop/>
<div v-if="isEnabledUrlPreview" :class="[$style.urlPreview, '_gaps_s']" @click.stop>
<SkUrlPreviewGroup :sourceUrls="urls" :sourceNote="appearNote" :compact="true" :detail="false" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds"/>
<SkUrlPreviewGroup :sourceUrls="urls" :sourceNote="appearNote" :compact="true" :detail="false" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" @expandMute="n => emit('expandMute', n)"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><SkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
<button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click.stop @click="collapsed = false">

View file

@ -119,7 +119,7 @@ Detailed view of a note in the Sharkey style. Used when opening a note onto its
</div>
<MkPoll v-if="appearNote.poll" ref="pollViewer" :noteId="appearNote.id" :poll="appearNote.poll" :local="!appearNote.user.host" :class="$style.poll" :author="appearNote.user" :emojiUrls="appearNote.emojis"/>
<div v-if="isEnabledUrlPreview" class="_gaps_s" style="margin-top: 6px;" @click.stop>
<SkUrlPreviewGroup :sourceNodes="parsed" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds"/>
<SkUrlPreviewGroup :sourceNodes="parsed" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds" @expandMute="n => emit('expandMute', n)"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><SkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :expandAllCws="props.expandAllCws"/></div>
</div>

View file

@ -6,7 +6,7 @@ Simple view of a note in the Sharkey style. Used in quote renotes, link previews
-->
<template>
<div :class="$style.root">
<SkMutedNote :note="note" :skipMute="skipMute" :class="$style.root" @expandMute="n => emit('expandMute', n)">
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
<div :class="$style.main">
<MkNoteHeader :class="$style.header" :classic="true" :note="note" :mini="true"/>
@ -20,7 +20,7 @@ Simple view of a note in the Sharkey style. Used in quote renotes, link previews
</div>
</div>
</div>
</div>
</SkMutedNote>
</template>
<script lang="ts" setup>
@ -32,6 +32,7 @@ import MkCwButton from '@/components/MkCwButton.vue';
import { prefer } from '@/preferences.js';
import { setupNoteViewInterruptors } from '@/plugin.js';
import { deepClone } from '@/utility/clone.js';
import SkMutedNote from '@/components/SkMutedNote.vue';
const props = defineProps<{
note: Misskey.entities.Note & {
@ -39,10 +40,11 @@ const props = defineProps<{
scheduledNoteId?: string
};
expandAllCws?: boolean;
skipMute?: boolean;
hideFiles?: boolean;
}>();
defineEmits<{
const emit = defineEmits<{
(ev: 'editScheduleNote'): void;
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();

View file

@ -8,7 +8,7 @@ For example, when viewing a reply on the timeline, SkNoteSub will be used to dis
-->
<template>
<SkMutedNote v-show="!isDeleted" ref="rootComp" :note="appearNote" :dive="false" :mutedClass="$style.muted" :expandedClass="[$style.root, { [$style.children]: depth > 1, [$style.isReply]: props.isReply, [$style.detailed]: props.detailed }]" @expandMute="n => emit('expandMute', n)">
<SkMutedNote v-show="!isDeleted" ref="rootComp" :note="appearNote" :mutedClass="$style.muted" :expandedClass="[$style.root, { [$style.children]: depth > 1, [$style.isReply]: props.isReply, [$style.detailed]: props.detailed }]" @expandMute="n => emit('expandMute', n)">
<div v-if="!hideLine" :class="$style.line"></div>
<div :class="$style.main">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>

View file

@ -52,7 +52,7 @@ Displays an old version of an edited note.
<div class="_gaps_s" style="margin-top: 6px;" @click.stop>
<SkUrlPreviewGroup :sourceNodes="parsed" :sourceNote="appearNote" :compact="true" :detail="true" :showAsQuote="!appearNote.user.rejectQuotes" :skipNoteIds="selfNoteIds"/>
</div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div>
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote" :skipMute="true"/></div>
</div>
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ph-television ph-bold ph-lg"></i> {{ appearNote.channel.name }}</MkA>
</div>

View file

@ -25,6 +25,7 @@ Attempts to avoid displaying the same preview twice, even if multiple URLs point
:showAsQuote="showAsQuote"
:showActions="showActions"
:skipNoteIds="skipNoteIds"
@expandMute="n => onExpandNote(n)"
></MkUrlPreview>
</template>
</template>
@ -42,6 +43,8 @@ import { $i } from '@/i';
import { misskeyApi } from '@/utility/misskey-api';
import MkUrlPreview from '@/components/MkUrlPreview.vue';
import { getNoteUrls } from '@/utility/getNoteUrls';
import { deepAssign } from '@/utility/merge';
import { useMuteOverrides } from '@/utility/check-word-mute';
type Summary = SummalyResult & {
note?: Misskey.entities.Note | null;
@ -74,6 +77,30 @@ const props = withDefaults(defineProps<{
skipNoteIds: () => [],
});
const emit = defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
const muteOverrides = useMuteOverrides();
function onExpandNote(note: Misskey.entities.Note) {
// Expand related mutes within this preview group
deepAssign(muteOverrides, {
user: {
[note.user.id]: {
userMandatoryCW: null,
},
},
instance: {
[note.user.host ?? '']: {
instanceMandatoryCW: null,
},
},
});
emit('expandMute', note);
}
const urlPreviews = ref<Summary[]>([]);
const urls = computed<string[]>(() => {

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<component :is="getComponent(block.type)" :key="block.id" :page="page" :block="block" :h="h"/>
<component :is="getComponent(block.type)" :key="block.id" :page="page" :block="block" :h="h" @expandMute="n => onExpandNote(n)"/>
</template>
<script lang="ts" setup>
@ -15,6 +15,8 @@ import XSection from './page.section.vue';
import XImage from './page.image.vue';
import XNote from './page.note.vue';
import XDynamic from './page.dynamic.vue';
import { deepAssign } from '@/utility/merge';
import { useMuteOverrides } from '@/utility/check-word-mute';
function getComponent(type: string) {
switch (type) {
@ -45,4 +47,28 @@ defineProps<{
h: number,
page: Misskey.entities.Page,
}>();
const emit = defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
const muteOverrides = useMuteOverrides();
function onExpandNote(note: Misskey.entities.Note) {
// Expand related mutes within this page group
deepAssign(muteOverrides, {
user: {
[note.user.id]: {
userMandatoryCW: null,
},
},
instance: {
[note.user.host ?? '']: {
instanceMandatoryCW: null,
},
},
});
emit('expandMute', note);
}
</script>

View file

@ -23,6 +23,10 @@ const props = defineProps<{
block: Misskey.entities.PageBlock,
page: Misskey.entities.Page,
}>();
defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
</script>
<style lang="scss" module>

View file

@ -19,6 +19,10 @@ const props = defineProps<{
page: Misskey.entities.Page,
}>();
defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
const image = ref<Misskey.entities.DriveFile | null>(null);
onMounted(() => {

View file

@ -5,8 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div :class="$style.root">
<MkNote v-if="note && !block.detailed" :key="note.id + ':normal'" :note="note"/>
<MkNoteDetailed v-if="note && block.detailed" :key="note.id + ':detail'" :note="note"/>
<MkNote v-if="note && !block.detailed" :key="note.id + ':normal'" :note="note" @expandMute="n => emit('expandMute', n)"/>
<MkNoteDetailed v-if="note && block.detailed" :key="note.id + ':detail'" :note="note" @expandMute="n => emit('expandMute', n)"/>
</div>
</template>
@ -24,6 +24,10 @@ const props = defineProps<{
index: number;
}>();
const emit = defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
const note = ref<Misskey.entities.Note | null>(null);
// eslint-disable-next-line id-denylist

View file

@ -33,6 +33,10 @@ defineProps<{
h: number,
page: Misskey.entities.Page,
}>();
defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
</script>
<style lang="scss" module>

View file

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_gaps" :class="$style.textRoot">
<Mfm :text="block.text ?? ''" :isBlock="true" :isNote="false"/>
<div v-if="isEnabledUrlPreview" class="_gaps_s" @click.stop>
<SkUrlPreviewGroup :sourceText="block.text" :showAsQuote="!page.user.rejectQuotes"/>
<SkUrlPreviewGroup :sourceText="block.text" :showAsQuote="!page.user.rejectQuotes" @expandMute="n => emit('expandMute', n)"/>
</div>
</div>
</template>
@ -21,6 +21,10 @@ defineProps<{
block: Misskey.entities.PageBlock,
page: Misskey.entities.Page,
}>();
const emit = defineEmits<{
(ev: 'expandMute', note: Misskey.entities.Note): void;
}>();
</script>
<style lang="scss" module>

View file

@ -84,19 +84,18 @@ function provideMuteOverrides(overrides: Reactive<MuteOverrides> | null) {
provide(muteOverridesSymbol, overrides);
}
export function checkMute(note: Misskey.entities.Note | ComputedRef<Misskey.entities.Note>, withHardMute?: boolean | ComputedRef<boolean>, dive?: boolean | ComputedRef<boolean>): ComputedRef<Mute> {
export function checkMute(note: Misskey.entities.Note | ComputedRef<Misskey.entities.Note>, withHardMute?: boolean | ComputedRef<boolean>): ComputedRef<Mute> {
// inject() can only be used inside script setup, so it MUST be outside the computed block!
const overrides = injectMuteOverrides();
return computed(() => {
const _note = unref(note);
const _withHardMute = unref(withHardMute) ?? true;
const _dive = unref(dive) ?? false;
return getMutes(_note, _withHardMute, _dive, overrides);
return getMutes(_note, _withHardMute, overrides);
});
}
function getMutes(note: Misskey.entities.Note, withHardMute: boolean, dive: boolean, overrides: MuteOverrides | null): Mute {
function getMutes(note: Misskey.entities.Note, withHardMute: boolean, overrides: MuteOverrides | null): Mute {
const override: Partial<Mute> = overrides ? deepAssign(
{},
note.user.host ? overrides.instance[note.user.host] : undefined,
@ -108,8 +107,8 @@ function getMutes(note: Misskey.entities.Note, withHardMute: boolean, dive: bool
const isMe = $i != null && $i.id === note.userId;
const hardMuted = override.hardMuted ?? (!isMe && withHardMute && isHardMuted(note, dive));
const softMutedWords = override.softMutedWords ?? (isMe ? [] : isSoftMuted(note, dive));
const hardMuted = override.hardMuted ?? (!isMe && withHardMute && isHardMuted(note));
const softMutedWords = override.softMutedWords ?? (isMe ? [] : isSoftMuted(note));
const sensitiveMuted = override.sensitiveMuted ?? isSensitiveMuted(note);
const threadMuted = override.threadMuted ?? (!isMe && note.isMutingThread);
const noteMuted = override.noteMuted ?? (!isMe && note.isMutingNote);
@ -130,17 +129,17 @@ function getMutes(note: Misskey.entities.Note, withHardMute: boolean, dive: bool
return { hasMute, hardMuted, softMutedWords, sensitiveMuted, threadMuted, noteMuted, noteMandatoryCW, userMandatoryCW, instanceMandatoryCW };
}
function isHardMuted(note: Misskey.entities.Note, dive: boolean): boolean {
function isHardMuted(note: Misskey.entities.Note): boolean {
if (!$i?.hardMutedWords.length) return false;
const inputs = expandNote(note, dive);
const inputs = expandNote(note);
return containsMutedWord($i.hardMutedWords, inputs);
}
function isSoftMuted(note: Misskey.entities.Note, dive: boolean): string[] {
function isSoftMuted(note: Misskey.entities.Note): string[] {
if (!$i?.mutedWords.length) return [];
const inputs = expandNote(note, dive);
const inputs = expandNote(note);
return getMutedWords($i.mutedWords, inputs);
}
@ -215,7 +214,7 @@ export function containsMutedWord(mutedWords: (string | string[])[], inputs: Ite
return false;
}
export function *expandNote(note: Misskey.entities.Note, dive: boolean): Generator<string> {
export function *expandNote(note: Misskey.entities.Note): Generator<string> {
if (note.cw) yield note.cw;
if (note.text) yield note.text;
if (note.files) {
@ -228,15 +227,6 @@ export function *expandNote(note: Misskey.entities.Note, dive: boolean): Generat
if (choice.text) yield choice.text;
}
}
if (dive) {
if (note.reply) {
yield* expandNote(note.reply, true);
}
if (note.renote) {
yield* expandNote(note.renote, true);
}
}
}
function parseMutes(mutedWords: (string | string[])[]) {