diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-05-10 20:01:26 -0400 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-05-12 21:46:03 -0400 |
| commit | 05e5be821885ea0a1d79f15b8aa7d26e542e9c2e (patch) | |
| tree | 28d05f45a6847938a09ab6481f9260bcbe7f4cf9 /packages | |
| parent | return actual muted word from check-word-mute.ts (diff) | |
| download | sharkey-05e5be821885ea0a1d79f15b8aa7d26e542e9c2e.tar.gz sharkey-05e5be821885ea0a1d79f15b8aa7d26e542e9c2e.tar.bz2 sharkey-05e5be821885ea0a1d79f15b8aa7d26e542e9c2e.zip | |
show muted words in NoteDetailed / NoteSub components
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/frontend-shared/js/i18n.ts | 1 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkNoteDetailed.vue | 51 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkNoteSub.vue | 49 | ||||
| -rw-r--r-- | packages/frontend/src/components/SkNoteDetailed.vue | 51 | ||||
| -rw-r--r-- | packages/frontend/src/components/SkNoteSub.vue | 49 |
5 files changed, 191 insertions, 10 deletions
diff --git a/packages/frontend-shared/js/i18n.ts b/packages/frontend-shared/js/i18n.ts index 480cfcd642..d38bad45d9 100644 --- a/packages/frontend-shared/js/i18n.ts +++ b/packages/frontend-shared/js/i18n.ts @@ -59,6 +59,7 @@ export class I18n<T extends ILocale> { if (typeof value === 'string') { const parameters = Array.from(value.matchAll(/\{(\w+)\}/g), ([, parameter]) => parameter); + // TODO add a flag to suppress this warning from uses of <I18n> component if (parameters.length) { console.error(`Missing locale parameters: ${parameters.join(', ')} at ${String(p)}`); } diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 5bf1cde456..f702c7c422 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -230,11 +230,28 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </div> <div v-else class="_panel" :class="$style.muted" @click="muted = false"> - <I18n :src="i18n.ts.userSaysSomething" tag="small"> + <I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small"> <template #name> <MkUserName :user="appearNote.user"/> </template> </I18n> + <I18n v-else-if="showSoftWordMutedWord !== true" :src="i18n.ts.userSaysSomething" tag="small"> + <template #name> + <MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)"> + <MkUserName :user="appearNote.user"/> + </MkA> + </template> + </I18n> + <I18n v-else :src="i18n.ts.userSaysSomethingAbout" tag="small"> + <template #name> + <MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)"> + <MkUserName :user="appearNote.user"/> + </MkA> + </template> + <template #word> + {{ Array.isArray(muted) ? muted.map(words => Array.isArray(words) ? words.join() : words).slice(0, 3).join(' ') : muted }} + </template> + </I18n> </div> </template> @@ -245,6 +262,7 @@ import * as Misskey from 'misskey-js'; import { isLink } from '@@/js/is-link.js'; import { host } from '@@/js/config.js'; import { computeMergedCw } from '@@/js/compute-merged-cw.js'; +import type { Ref } from 'vue'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; import type { Paging } from '@/components/MkPagination.vue'; import type { Keymap } from '@/utility/hotkey.js'; @@ -340,7 +358,6 @@ const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(prefer.s.uncollapseCW); const isDeleted = ref(false); const renoted = ref(false); -const muted = ref($i ? checkWordMute(appearNote.value, $i, $i.mutedWords) : false); const translation = ref<Misskey.entities.NotesTranslateResponse | null>(null); const translating = ref(false); const parsed = appearNote.value.text ? mfm.parse(appearNote.value.text) : null; @@ -358,6 +375,36 @@ const mergedCW = computed(() => computeMergedCw(appearNote.value)); const renoteTooltip = computeRenoteTooltip(renoted); +const inTimeline = inject<boolean>('inTimeline', false); +const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(true)); +const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); +const showSoftWordMutedWord = computed(() => prefer.s.showSoftWordMutedWord); + +/* Overload FunctionにLintが対応していないのでコメントアウト +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean; +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): Array<string | string[]> | false | 'sensitiveMute'; +*/ +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' { + if (mutedWords != null) { + const result = checkWordMute(noteToCheck, $i, mutedWords); + if (Array.isArray(result)) return result; + + const replyResult = noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords); + if (Array.isArray(replyResult)) return replyResult; + + const renoteResult = noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords); + if (Array.isArray(renoteResult)) return renoteResult; + } + + if (checkOnly) return false; + + if (inTimeline && tl_withSensitive.value === false && noteToCheck.files?.some((v) => v.isSensitive)) { + return 'sensitiveMute'; + } + + return false; +} + watch(() => props.expandAllCws, (expandAllCws) => { if (expandAllCws !== showContent.value) showContent.value = expandAllCws; }); diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue index 9751dbbc5c..c017efa3f3 100644 --- a/packages/frontend/src/components/MkNoteSub.vue +++ b/packages/frontend/src/components/MkNoteSub.vue @@ -73,19 +73,33 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </div> <div v-else :class="$style.muted" @click="muted = false"> - <I18n :src="i18n.ts.userSaysSomething" tag="small"> + <I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small"> <template #name> <MkUserName :user="appearNote.user"/> </template> </I18n> + <I18n v-else-if="showSoftWordMutedWord !== true" :src="i18n.ts.userSaysSomething" tag="small"> + <template #name> + <MkUserName :user="appearNote.user"/> + </template> + </I18n> + <I18n v-else :src="i18n.ts.userSaysSomethingAbout" tag="small"> + <template #name> + <MkUserName :user="appearNote.user"/> + </template> + <template #word> + {{ Array.isArray(muted) ? muted.map(words => Array.isArray(words) ? words.join() : words).slice(0, 3).join(' ') : muted }} + </template> + </I18n> </div> </template> <script lang="ts" setup> -import { computed, ref, shallowRef, watch } from 'vue'; +import { computed, inject, ref, shallowRef, watch } from 'vue'; import * as Misskey from 'misskey-js'; import { computeMergedCw } from '@@/js/compute-merged-cw.js'; import { host } from '@@/js/config.js'; +import type { Ref } from 'vue'; import type { Visibility } from '@/utility/boost-quote.js'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; import MkNoteHeader from '@/components/MkNoteHeader.vue'; @@ -126,7 +140,6 @@ const props = withDefaults(defineProps<{ const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i?.id); const el = shallowRef<HTMLElement>(); -const muted = computed(() => $i ? checkWordMute(props.note, $i, $i.mutedWords) : false); const translation = ref<any>(null); const translating = ref(false); const isDeleted = ref(false); @@ -170,6 +183,36 @@ async function removeReply(id: Misskey.entities.Note['id']) { } } +const inTimeline = inject<boolean>('inTimeline', false); +const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(true)); +const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); +const showSoftWordMutedWord = computed(() => prefer.s.showSoftWordMutedWord); + +/* Overload FunctionにLintが対応していないのでコメントアウト +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean; +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): Array<string | string[]> | false | 'sensitiveMute'; +*/ +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' { + if (mutedWords != null) { + const result = checkWordMute(noteToCheck, $i, mutedWords); + if (Array.isArray(result)) return result; + + const replyResult = noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords); + if (Array.isArray(replyResult)) return replyResult; + + const renoteResult = noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords); + if (Array.isArray(renoteResult)) return renoteResult; + } + + if (checkOnly) return false; + + if (inTimeline && tl_withSensitive.value === false && noteToCheck.files?.some((v) => v.isSensitive)) { + return 'sensitiveMute'; + } + + return false; +} + useNoteCapture({ rootEl: el, note: appearNote, diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index c785a82bae..71670c8f51 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -235,11 +235,28 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </div> <div v-else class="_panel" :class="$style.muted" @click="muted = false"> - <I18n :src="i18n.ts.userSaysSomething" tag="small"> + <I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small"> <template #name> <MkUserName :user="appearNote.user"/> </template> </I18n> + <I18n v-else-if="showSoftWordMutedWord !== true" :src="i18n.ts.userSaysSomething" tag="small"> + <template #name> + <MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)"> + <MkUserName :user="appearNote.user"/> + </MkA> + </template> + </I18n> + <I18n v-else :src="i18n.ts.userSaysSomethingAbout" tag="small"> + <template #name> + <MkA v-user-preview="appearNote.userId" :to="userPage(appearNote.user)"> + <MkUserName :user="appearNote.user"/> + </MkA> + </template> + <template #word> + {{ Array.isArray(muted) ? muted.map(words => Array.isArray(words) ? words.join() : words).slice(0, 3).join(' ') : muted }} + </template> + </I18n> </div> </template> @@ -250,6 +267,7 @@ import * as Misskey from 'misskey-js'; import { isLink } from '@@/js/is-link.js'; import { host } from '@@/js/config.js'; import { computeMergedCw } from '@@/js/compute-merged-cw.js'; +import type { Ref } from 'vue'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; import type { Paging } from '@/components/MkPagination.vue'; import type { Keymap } from '@/utility/hotkey.js'; @@ -346,7 +364,6 @@ const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(prefer.s.uncollapseCW); const isDeleted = ref(false); const renoted = ref(false); -const muted = ref($i ? checkWordMute(appearNote.value, $i, $i.mutedWords) : false); const translation = ref<Misskey.entities.NotesTranslateResponse | null>(null); const translating = ref(false); const parsed = appearNote.value.text ? mfm.parse(appearNote.value.text) : null; @@ -364,6 +381,36 @@ const mergedCW = computed(() => computeMergedCw(appearNote.value)); const renoteTooltip = computeRenoteTooltip(renoted); +const inTimeline = inject<boolean>('inTimeline', false); +const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(true)); +const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); +const showSoftWordMutedWord = computed(() => prefer.s.showSoftWordMutedWord); + +/* Overload FunctionにLintが対応していないのでコメントアウト +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean; +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): Array<string | string[]> | false | 'sensitiveMute'; +*/ +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' { + if (mutedWords != null) { + const result = checkWordMute(noteToCheck, $i, mutedWords); + if (Array.isArray(result)) return result; + + const replyResult = noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords); + if (Array.isArray(replyResult)) return replyResult; + + const renoteResult = noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords); + if (Array.isArray(renoteResult)) return renoteResult; + } + + if (checkOnly) return false; + + if (inTimeline && tl_withSensitive.value === false && noteToCheck.files?.some((v) => v.isSensitive)) { + return 'sensitiveMute'; + } + + return false; +} + watch(() => props.expandAllCws, (expandAllCws) => { if (expandAllCws !== showContent.value) showContent.value = expandAllCws; }); diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue index 8d3a643b13..143642f64f 100644 --- a/packages/frontend/src/components/SkNoteSub.vue +++ b/packages/frontend/src/components/SkNoteSub.vue @@ -81,19 +81,33 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </div> <div v-else :class="$style.muted" @click="muted = false"> - <I18n :src="i18n.ts.userSaysSomething" tag="small"> + <I18n v-if="muted === 'sensitiveMute'" :src="i18n.ts.userSaysSomethingSensitive" tag="small"> <template #name> <MkUserName :user="appearNote.user"/> </template> </I18n> + <I18n v-else-if="showSoftWordMutedWord !== true" :src="i18n.ts.userSaysSomething" tag="small"> + <template #name> + <MkUserName :user="appearNote.user"/> + </template> + </I18n> + <I18n v-else :src="i18n.ts.userSaysSomethingAbout" tag="small"> + <template #name> + <MkUserName :user="appearNote.user"/> + </template> + <template #word> + {{ Array.isArray(muted) ? muted.map(words => Array.isArray(words) ? words.join() : words).slice(0, 3).join(' ') : muted }} + </template> + </I18n> </div> </template> <script lang="ts" setup> -import { computed, ref, shallowRef, watch } from 'vue'; +import { computed, inject, ref, shallowRef, watch } from 'vue'; import * as Misskey from 'misskey-js'; import { computeMergedCw } from '@@/js/compute-merged-cw.js'; import { host } from '@@/js/config.js'; +import type { Ref } from 'vue'; import type { Visibility } from '@/utility/boost-quote.js'; import type { OpenOnRemoteOptions } from '@/utility/please-login.js'; import SkNoteHeader from '@/components/SkNoteHeader.vue'; @@ -140,7 +154,6 @@ const canRenote = computed(() => ['public', 'home'].includes(props.note.visibili const hideLine = computed(() => props.detail); const el = shallowRef<HTMLElement>(); -const muted = ref($i ? checkWordMute(props.note, $i, $i.mutedWords) : false); const translation = ref<any>(null); const translating = ref(false); const isDeleted = ref(false); @@ -184,6 +197,36 @@ async function removeReply(id: Misskey.entities.Note['id']) { } } +const inTimeline = inject<boolean>('inTimeline', false); +const tl_withSensitive = inject<Ref<boolean>>('tl_withSensitive', ref(true)); +const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); +const showSoftWordMutedWord = computed(() => prefer.s.showSoftWordMutedWord); + +/* Overload FunctionにLintが対応していないのでコメントアウト +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: true): boolean; +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly: false): Array<string | string[]> | false | 'sensitiveMute'; +*/ +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' { + if (mutedWords != null) { + const result = checkWordMute(noteToCheck, $i, mutedWords); + if (Array.isArray(result)) return result; + + const replyResult = noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords); + if (Array.isArray(replyResult)) return replyResult; + + const renoteResult = noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords); + if (Array.isArray(renoteResult)) return renoteResult; + } + + if (checkOnly) return false; + + if (inTimeline && tl_withSensitive.value === false && noteToCheck.files?.some((v) => v.isSensitive)) { + return 'sensitiveMute'; + } + + return false; +} + useNoteCapture({ rootEl: el, note: appearNote, |