summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
authortaichan <40626578+tai-cha@users.noreply.github.com>2025-01-14 22:49:59 +0900
committerGitHub <noreply@github.com>2025-01-14 13:49:59 +0000
commit9760f3d7c9113f5436732bf6d6e454b253061b1d (patch)
treeecc41ca918feec1d8a45f2e91e1bf03cab2604c9 /packages/frontend/src
parentBump version to 2025.1.0-beta.1 (diff)
downloadmisskey-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.vue32
-rw-r--r--packages/frontend/src/pages/settings/mute-block.vue14
-rw-r--r--packages/frontend/src/scripts/check-word-mute.ts6
-rw-r--r--packages/frontend/src/store.ts6
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',