diff options
| author | taichan <40626578+tai-cha@users.noreply.github.com> | 2025-01-14 22:49:59 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-14 13:49:59 +0000 |
| commit | 9760f3d7c9113f5436732bf6d6e454b253061b1d (patch) | |
| tree | ecc41ca918feec1d8a45f2e91e1bf03cab2604c9 /packages/frontend/src | |
| parent | Bump version to 2025.1.0-beta.1 (diff) | |
| download | misskey-9760f3d7c9113f5436732bf6d6e454b253061b1d.tar.gz misskey-9760f3d7c9113f5436732bf6d6e454b253061b1d.tar.bz2 misskey-9760f3d7c9113f5436732bf6d6e454b253061b1d.zip | |
enhance(frontend): ワードミュートで引っかかったワードを表示可能にする (#15195)
* feat(frontend): ソフトミュートで引っかかったものを表示できるように
* ソフトワードミュートのミュート文字列表示を切り替え可能に
* Chore(docs): Update CHANGELOG
* Fix: language file
* Fixed by review
* Fix by review
* Fix: reloadAskなおしきれていなかった
* perf: filter -> findに変更して最初の一個のみを表示するように変更
* Revert "perf: filter -> findに変更して最初の一個のみを表示するように変更"
This reverts commit 72ef92f0d62828754702cd00e26ad873adb4652f.
Diffstat (limited to 'packages/frontend/src')
| -rw-r--r-- | packages/frontend/src/components/MkNote.vue | 32 | ||||
| -rw-r--r-- | packages/frontend/src/pages/settings/mute-block.vue | 14 | ||||
| -rw-r--r-- | packages/frontend/src/scripts/check-word-mute.ts | 6 | ||||
| -rw-r--r-- | packages/frontend/src/store.ts | 6 |
4 files changed, 45 insertions, 13 deletions
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 1a8814b7cb..4c26444b35 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -150,13 +150,23 @@ SPDX-License-Identifier: AGPL-3.0-only </MkA> </template> </I18n> - <I18n v-else :src="i18n.ts.userSaysSomething" tag="small"> + <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> <div v-else> <!-- @@ -272,6 +282,7 @@ const collapsed = ref(appearNote.value.cw == null && isLong); const isDeleted = ref(false); const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); const hardMuted = ref(props.withHardMute && checkMute(appearNote.value, $i?.hardMutedWords, true)); +const showSoftWordMutedWord = computed(() => defaultStore.state.showSoftWordMutedWord); const translation = ref<Misskey.entities.NotesTranslateResponse | null>(null); const translating = ref(false); const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.value.user.instance); @@ -290,14 +301,19 @@ const pleaseLoginContext = computed<OpenOnRemoteOptions>(() => ({ /* 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): boolean | 'sensitiveMute'; +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): boolean | 'sensitiveMute' { - if (mutedWords != null) { - if (checkWordMute(noteToCheck, $i, mutedWords)) return true; - if (noteToCheck.reply && checkWordMute(noteToCheck.reply, $i, mutedWords)) return true; - if (noteToCheck.renote && checkWordMute(noteToCheck.renote, $i, mutedWords)) return true; - } +function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array<string | string[]> | undefined | null, checkOnly = false): Array<string | string[]> | false | 'sensitiveMute' { + if (mutedWords == null) return false; + + 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; diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index d32d4842bd..4caa556b15 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -11,6 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only <div class="_gaps_m"> <MkInfo>{{ i18n.ts.wordMuteDescription }}</MkInfo> + <MkSwitch v-model="showSoftWordMutedWord">{{ i18n.ts.showMutedWord }}</MkSwitch> <XWordMute :muted="$i.mutedWords" @save="saveMutedWords"/> </div> </MkFolder> @@ -132,7 +133,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <script lang="ts" setup> -import { ref, computed } from 'vue'; +import { ref, computed, watch } from 'vue'; import XInstanceMute from './mute-block.instance-mute.vue'; import XWordMute from './mute-block.word-mute.vue'; import MkPagination from '@/components/MkPagination.vue'; @@ -146,6 +147,9 @@ import { instance, infoImageUrl } from '@/instance.js'; import { signinRequired } from '@/account.js'; import MkInfo from '@/components/MkInfo.vue'; import MkFolder from '@/components/MkFolder.vue'; +import MkSwitch from '@/components/MkSwitch.vue'; +import { defaultStore } from '@/store'; +import { reloadAsk } from '@/scripts/reload-ask.js'; const $i = signinRequired(); @@ -168,6 +172,14 @@ const expandedRenoteMuteItems = ref([]); const expandedMuteItems = ref([]); const expandedBlockItems = ref([]); +const showSoftWordMutedWord = computed(defaultStore.makeGetterSetter('showSoftWordMutedWord')); + +watch([ + showSoftWordMutedWord, +], async () => { + await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true }); +}); + async function unrenoteMute(user, ev) { os.popupMenu([{ text: i18n.ts.renoteUnmute, diff --git a/packages/frontend/src/scripts/check-word-mute.ts b/packages/frontend/src/scripts/check-word-mute.ts index 0a37a08bf0..98fea1bced 100644 --- a/packages/frontend/src/scripts/check-word-mute.ts +++ b/packages/frontend/src/scripts/check-word-mute.ts @@ -4,7 +4,7 @@ */ import * as Misskey from 'misskey-js'; -export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities.UserLite | null | undefined, mutedWords: Array<string | string[]>): boolean { +export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities.UserLite | null | undefined, mutedWords: Array<string | string[]>): Array<string | string[]> | false { // 自分自身 if (me && (note.userId === me.id)) return false; @@ -13,7 +13,7 @@ export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities. if (text === '') return false; - const matched = mutedWords.some(filter => { + const matched = mutedWords.filter(filter => { if (Array.isArray(filter)) { // Clean up const filteredFilter = filter.filter(keyword => keyword !== ''); @@ -36,7 +36,7 @@ export function checkWordMute(note: Misskey.entities.Note, me: Misskey.entities. } }); - if (matched) return true; + if (matched.length > 0) return matched; } return false; diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 1d981e897b..dbe90dba86 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -9,10 +9,10 @@ import { hemisphere } from '@@/js/intl-const.js'; import lightTheme from '@@/themes/l-light.json5'; import darkTheme from '@@/themes/d-green-lime.json5'; import type { SoundType } from '@/scripts/sound.js'; +import type { Ast } from '@syuilo/aiscript'; import { DEFAULT_DEVICE_KIND, type DeviceKind } from '@/scripts/device-kind.js'; import { miLocalStorage } from '@/local-storage.js'; import { Storage } from '@/pizzax.js'; -import type { Ast } from '@syuilo/aiscript'; interface PostFormAction { title: string, @@ -474,6 +474,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: true, }, + showSoftWordMutedWord: { + where: 'device', + default: false, + }, sound_masterVolume: { where: 'device', |