don't recursively check mute text and improve grouping
This commit is contained in:
parent
179c7e18bd
commit
ba433d8914
23 changed files with 122 additions and 51 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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/>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}>();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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[]>(() => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ defineProps<{
|
|||
h: number,
|
||||
page: Misskey.entities.Page,
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
(ev: 'expandMute', note: Misskey.entities.Note): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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[])[]) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue