feat: muted words
This commit is contained in:
parent
3c74c8c5db
commit
603bd35b4a
25 changed files with 282 additions and 87 deletions
|
|
@ -80,7 +80,7 @@ const NoteList = forwardRef<
|
|||
const { startLogin } = useNostr()
|
||||
const { isSpammer, meetsMinTrustScore } = useUserTrust()
|
||||
const { mutePubkeySet } = useMuteList()
|
||||
const { hideContentMentioningMutedUsers } = useContentPolicy()
|
||||
const { hideContentMentioningMutedUsers, mutedWords } = useContentPolicy()
|
||||
const { isEventDeleted } = useDeletedEvent()
|
||||
const [storedEvents, setStoredEvents] = useState<Event[]>([])
|
||||
const [events, setEvents] = useState<Event[]>([])
|
||||
|
|
@ -131,10 +131,18 @@ const NoteList = forwardRef<
|
|||
if (filterFn && !filterFn(evt)) {
|
||||
return true
|
||||
}
|
||||
if (mutedWords.length > 0) {
|
||||
const contentLower = evt.content.toLowerCase()
|
||||
for (const word of mutedWords) {
|
||||
if (contentLower.includes(word)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
[mutePubkeySet, JSON.stringify(pinnedEventIds), isEventDeleted, filterFn]
|
||||
[mutePubkeySet, JSON.stringify(pinnedEventIds), isEventDeleted, filterFn, mutedWords]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export const StorageKey = {
|
|||
NSFW_DISPLAY_POLICY: 'nsfwDisplayPolicy',
|
||||
MIN_TRUST_SCORE: 'minTrustScore',
|
||||
DEFAULT_RELAY_URLS: 'defaultRelayUrls',
|
||||
MUTED_WORDS: 'mutedWords',
|
||||
ENABLE_LIVE_FEED: 'enableLiveFeed', // deprecated
|
||||
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes', // deprecated
|
||||
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions', // deprecated
|
||||
|
|
|
|||
|
|
@ -648,16 +648,20 @@ export default {
|
|||
'trust-filter.quick-presets': 'إعدادات سريعة',
|
||||
'trust-filter.show-all-content': 'إظهار جميع المحتويات',
|
||||
'trust-filter.only-show-wot': 'إظهار شبكة الثقة الخاصة بك فقط (المتابَعون + متابَعوهم)',
|
||||
'trust-filter.hide-bottom-percent':
|
||||
'تصفية أدنى {{score}}٪ من المستخدمين حسب تصنيف الثقة',
|
||||
'trust-filter.trust-score-description': 'محسوبة بناءً على سمعة المستخدم والنسبة المئوية للشبكة الاجتماعية',
|
||||
'trust-filter.hide-bottom-percent': 'تصفية أدنى {{score}}٪ من المستخدمين حسب تصنيف الثقة',
|
||||
'trust-filter.trust-score-description':
|
||||
'محسوبة بناءً على سمعة المستخدم والنسبة المئوية للشبكة الاجتماعية',
|
||||
'Auto-load profile pictures': 'تحميل صور الملف الشخصي تلقائيًا',
|
||||
'Disable live feed': 'تعطيل التغذية المباشرة',
|
||||
'Enable live feed': 'تفعيل التغذية المباشرة',
|
||||
'Default relays': 'المرحلات الافتراضية',
|
||||
'Reset to default': 'إعادة تعيين إلى الافتراضي',
|
||||
'Default relays description': 'تُستخدم للاستعلام عن تكوينات المرحلات للمستخدمين الآخرين وكبديل احتياطي عندما لا يكون لدى المستخدمين مرحلات مكوّنة.',
|
||||
'Default relays warning': 'تحذير: يرجى عدم تعديل هذه الإعدادات بشكل عشوائي، فقد يؤثر ذلك على تجربتك الأساسية.',
|
||||
'Invalid relay URL': 'عنوان URL للمرحل غير صالح'
|
||||
'Default relays description':
|
||||
'تُستخدم للاستعلام عن تكوينات المرحلات للمستخدمين الآخرين وكبديل احتياطي عندما لا يكون لدى المستخدمين مرحلات مكوّنة.',
|
||||
'Default relays warning':
|
||||
'تحذير: يرجى عدم تعديل هذه الإعدادات بشكل عشوائي، فقد يؤثر ذلك على تجربتك الأساسية.',
|
||||
'Invalid relay URL': 'عنوان URL للمرحل غير صالح',
|
||||
'Muted words': 'الكلمات المحظورة',
|
||||
'Add muted word': 'إضافة كلمة محظورة'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -678,8 +678,12 @@ export default {
|
|||
'Enable live feed': 'Live-Feed aktivieren',
|
||||
'Default relays': 'Standard-Relays',
|
||||
'Reset to default': 'Auf Standard zurücksetzen',
|
||||
'Default relays description': 'Werden verwendet, um die Relay-Konfigurationen anderer Benutzer abzufragen und als Fallback, wenn Benutzer keine Relays konfiguriert haben.',
|
||||
'Default relays warning': 'Warnung: Ändern Sie diese Einstellungen nicht leichtfertig, da dies Ihre grundlegende Erfahrung beeinträchtigen kann.',
|
||||
'Invalid relay URL': 'Ungültige Relay-URL'
|
||||
'Default relays description':
|
||||
'Werden verwendet, um die Relay-Konfigurationen anderer Benutzer abzufragen und als Fallback, wenn Benutzer keine Relays konfiguriert haben.',
|
||||
'Default relays warning':
|
||||
'Warnung: Ändern Sie diese Einstellungen nicht leichtfertig, da dies Ihre grundlegende Erfahrung beeinträchtigen kann.',
|
||||
'Invalid relay URL': 'Ungültige Relay-URL',
|
||||
'Muted words': 'Stummgeschaltete Wörter',
|
||||
'Add muted word': 'Stummgeschaltetes Wort hinzufügen'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -653,16 +653,20 @@ export default {
|
|||
'trust-filter.quick-presets': 'Quick presets',
|
||||
'trust-filter.show-all-content': 'Show all content',
|
||||
'trust-filter.only-show-wot': 'Only show your Web of Trust (follows + their follows)',
|
||||
'trust-filter.hide-bottom-percent':
|
||||
'Filter out bottom {{score}}% of users by trust rank',
|
||||
'trust-filter.trust-score-description': 'Calculated based on user reputation and social network percentile',
|
||||
'trust-filter.hide-bottom-percent': 'Filter out bottom {{score}}% of users by trust rank',
|
||||
'trust-filter.trust-score-description':
|
||||
'Calculated based on user reputation and social network percentile',
|
||||
'Auto-load profile pictures': 'Auto-load profile pictures',
|
||||
'Disable live feed': 'Disable live feed',
|
||||
'Enable live feed': 'Enable live feed',
|
||||
'Default relays': 'Default relays',
|
||||
'Reset to default': 'Reset to default',
|
||||
'Default relays description': 'Used to query other users\' relay configurations and as a fallback when users have no relays configured.',
|
||||
'Default relays warning': 'Warning: Please do not modify these settings casually, as it may affect your basic experience.',
|
||||
'Invalid relay URL': 'Invalid relay URL'
|
||||
'Default relays description':
|
||||
"Used to query other users' relay configurations and as a fallback when users have no relays configured.",
|
||||
'Default relays warning':
|
||||
'Warning: Please do not modify these settings casually, as it may affect your basic experience.',
|
||||
'Invalid relay URL': 'Invalid relay URL',
|
||||
'Muted words': 'Muted words',
|
||||
'Add muted word': 'Add muted word'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,8 +672,12 @@ export default {
|
|||
'Enable live feed': 'Activar feed en vivo',
|
||||
'Default relays': 'Relés predeterminados',
|
||||
'Reset to default': 'Restablecer valores predeterminados',
|
||||
'Default relays description': 'Se utilizan para consultar las configuraciones de relés de otros usuarios y como respaldo cuando los usuarios no tienen relés configurados.',
|
||||
'Default relays warning': 'Advertencia: No modifiques estas configuraciones a la ligera, ya que puede afectar tu experiencia básica.',
|
||||
'Invalid relay URL': 'URL de relé no válida'
|
||||
'Default relays description':
|
||||
'Se utilizan para consultar las configuraciones de relés de otros usuarios y como respaldo cuando los usuarios no tienen relés configurados.',
|
||||
'Default relays warning':
|
||||
'Advertencia: No modifiques estas configuraciones a la ligera, ya que puede afectar tu experiencia básica.',
|
||||
'Invalid relay URL': 'URL de relé no válida',
|
||||
'Muted words': 'Palabras silenciadas',
|
||||
'Add muted word': 'Agregar palabra silenciada'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,15 +661,18 @@ export default {
|
|||
'فقط شبکه اعتماد شما را نشان دهید (دنبالشوندگان + دنبالشوندگان آنها)',
|
||||
'trust-filter.hide-bottom-percent':
|
||||
'فیلتر کردن {{score}}٪ پایینترین کاربران بر اساس رتبه اعتماد',
|
||||
'trust-filter.trust-score-description':
|
||||
'بر اساس شهرت کاربر و صدک شبکه اجتماعی محاسبه میشود',
|
||||
'trust-filter.trust-score-description': 'بر اساس شهرت کاربر و صدک شبکه اجتماعی محاسبه میشود',
|
||||
'Auto-load profile pictures': 'بارگذاری خودکار تصاویر پروفایل',
|
||||
'Disable live feed': 'غیرفعال کردن فید زنده',
|
||||
'Enable live feed': 'فعال کردن فید زنده',
|
||||
'Default relays': 'رلههای پیشفرض',
|
||||
'Reset to default': 'بازنشانی به پیشفرض',
|
||||
'Default relays description': 'برای پرسوجو از پیکربندیهای رله کاربران دیگر و به عنوان جایگزین زمانی که کاربران رله پیکربندی نکردهاند استفاده میشود.',
|
||||
'Default relays warning': 'هشدار: لطفاً این تنظیمات را به صورت تصادفی تغییر ندهید، ممکن است بر تجربه اولیه شما تأثیر بگذارد.',
|
||||
'Invalid relay URL': 'آدرس URL رله نامعتبر است'
|
||||
'Default relays description':
|
||||
'برای پرسوجو از پیکربندیهای رله کاربران دیگر و به عنوان جایگزین زمانی که کاربران رله پیکربندی نکردهاند استفاده میشود.',
|
||||
'Default relays warning':
|
||||
'هشدار: لطفاً این تنظیمات را به صورت تصادفی تغییر ندهید، ممکن است بر تجربه اولیه شما تأثیر بگذارد.',
|
||||
'Invalid relay URL': 'آدرس URL رله نامعتبر است',
|
||||
'Muted words': 'کلمات بیصدا شده',
|
||||
'Add muted word': 'افزودن کلمه بیصدا'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -676,8 +676,12 @@ export default {
|
|||
'Enable live feed': 'Activer le flux en direct',
|
||||
'Default relays': 'Relais par défaut',
|
||||
'Reset to default': 'Réinitialiser par défaut',
|
||||
'Default relays description': 'Utilisés pour interroger les configurations de relais d\'autres utilisateurs et comme solution de secours lorsque les utilisateurs n\'ont pas de relais configurés.',
|
||||
'Default relays warning': 'Attention : Ne modifiez pas ces paramètres à la légère, car cela pourrait affecter votre expérience de base.',
|
||||
'Invalid relay URL': 'URL de relais non valide'
|
||||
'Default relays description':
|
||||
"Utilisés pour interroger les configurations de relais d'autres utilisateurs et comme solution de secours lorsque les utilisateurs n'ont pas de relais configurés.",
|
||||
'Default relays warning':
|
||||
'Attention : Ne modifiez pas ces paramètres à la légère, car cela pourrait affecter votre expérience de base.',
|
||||
'Invalid relay URL': 'URL de relais non valide',
|
||||
'Muted words': 'Mots masqués',
|
||||
'Add muted word': 'Ajouter un mot masqué'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -668,8 +668,12 @@ export default {
|
|||
'Enable live feed': 'लाइव फ़ीड सक्षम करें',
|
||||
'Default relays': 'डिफ़ॉल्ट रिले',
|
||||
'Reset to default': 'डिफ़ॉल्ट पर रीसेट करें',
|
||||
'Default relays description': 'अन्य उपयोगकर्ताओं के रिले कॉन्फ़िगरेशन की जांच करने के लिए उपयोग किया जाता है और जब उपयोगकर्ताओं के पास रिले कॉन्फ़िगर नहीं है तो फ़ॉलबैक के रूप में।',
|
||||
'Default relays warning': 'चेतावनी: कृपया इन सेटिंग्स को बेतरतीब ढंग से संशोधित न करें, क्योंकि यह आपके बुनियादी अनुभव को प्रभावित कर सकता है।',
|
||||
'Invalid relay URL': 'अमान्य रिले URL'
|
||||
'Default relays description':
|
||||
'अन्य उपयोगकर्ताओं के रिले कॉन्फ़िगरेशन की जांच करने के लिए उपयोग किया जाता है और जब उपयोगकर्ताओं के पास रिले कॉन्फ़िगर नहीं है तो फ़ॉलबैक के रूप में।',
|
||||
'Default relays warning':
|
||||
'चेतावनी: कृपया इन सेटिंग्स को बेतरतीब ढंग से संशोधित न करें, क्योंकि यह आपके बुनियादी अनुभव को प्रभावित कर सकता है।',
|
||||
'Invalid relay URL': 'अमान्य रिले URL',
|
||||
'Muted words': 'म्यूट किए गए शब्द',
|
||||
'Add muted word': 'म्यूट शब्द जोड़ें'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,8 +661,12 @@ export default {
|
|||
'Enable live feed': 'Élő hírfolyam engedélyezése',
|
||||
'Default relays': 'Alapértelmezett továbbítók',
|
||||
'Reset to default': 'Visszaállítás alapértelmezettre',
|
||||
'Default relays description': 'Más felhasználók továbbító konfigurációinak lekérdezésére használatos, és tartalékként szolgál, ha a felhasználóknak nincsenek továbbítóik beállítva.',
|
||||
'Default relays warning': 'Figyelmeztetés: Ne módosítsa ezeket a beállításokat meggondolatlanul, mert ez befolyásolhatja az alapvető élményt.',
|
||||
'Invalid relay URL': 'Érvénytelen továbbító URL'
|
||||
'Default relays description':
|
||||
'Más felhasználók továbbító konfigurációinak lekérdezésére használatos, és tartalékként szolgál, ha a felhasználóknak nincsenek továbbítóik beállítva.',
|
||||
'Default relays warning':
|
||||
'Figyelmeztetés: Ne módosítsa ezeket a beállításokat meggondolatlanul, mert ez befolyásolhatja az alapvető élményt.',
|
||||
'Invalid relay URL': 'Érvénytelen továbbító URL',
|
||||
'Muted words': 'Némított szavak',
|
||||
'Add muted word': 'Némított szó hozzáadása'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,8 +672,12 @@ export default {
|
|||
'Enable live feed': 'Attiva feed live',
|
||||
'Default relays': 'Relay predefiniti',
|
||||
'Reset to default': 'Ripristina predefiniti',
|
||||
'Default relays description': 'Utilizzati per interrogare le configurazioni dei relay di altri utenti e come fallback quando gli utenti non hanno relay configurati.',
|
||||
'Default relays warning': 'Attenzione: Non modificare queste impostazioni alla leggera, potrebbe influire sull\'esperienza di base.',
|
||||
'Invalid relay URL': 'URL relay non valido'
|
||||
'Default relays description':
|
||||
'Utilizzati per interrogare le configurazioni dei relay di altri utenti e come fallback quando gli utenti non hanno relay configurati.',
|
||||
'Default relays warning':
|
||||
"Attenzione: Non modificare queste impostazioni alla leggera, potrebbe influire sull'esperienza di base.",
|
||||
'Invalid relay URL': 'URL relay non valido',
|
||||
'Muted words': 'Parole silenziate',
|
||||
'Add muted word': 'Aggiungi parola silenziata'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -666,8 +666,12 @@ export default {
|
|||
'Enable live feed': 'ライブフィードを有効にする',
|
||||
'Default relays': 'デフォルトリレー',
|
||||
'Reset to default': 'デフォルトにリセット',
|
||||
'Default relays description': '他のユーザーのリレー設定を照会するために使用され、ユーザーがリレーを設定していない場合のフォールバックとして機能します。',
|
||||
'Default relays warning': '警告:これらの設定を無闇に変更しないでください。基本的な体験に影響を与える可能性があります。',
|
||||
'Invalid relay URL': '無効なリレーURL'
|
||||
'Default relays description':
|
||||
'他のユーザーのリレー設定を照会するために使用され、ユーザーがリレーを設定していない場合のフォールバックとして機能します。',
|
||||
'Default relays warning':
|
||||
'警告:これらの設定を無闇に変更しないでください。基本的な体験に影響を与える可能性があります。',
|
||||
'Invalid relay URL': '無効なリレーURL',
|
||||
'Muted words': 'ミュートワード',
|
||||
'Add muted word': 'ミュートワードを追加'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -655,14 +655,19 @@ export default {
|
|||
'trust-filter.show-all-content': '모든 콘텐츠 표시',
|
||||
'trust-filter.only-show-wot': '신뢰 네트워크만 표시 (팔로우 + 팔로우의 팔로우)',
|
||||
'trust-filter.hide-bottom-percent': '신뢰도 하위 {{score}}% 사용자 필터링',
|
||||
'trust-filter.trust-score-description': '사용자의 평판과 소셜 네트워크를 기반으로 신뢰도 백분위수 계산',
|
||||
'trust-filter.trust-score-description':
|
||||
'사용자의 평판과 소셜 네트워크를 기반으로 신뢰도 백분위수 계산',
|
||||
'Auto-load profile pictures': '프로필 사진 자동 로드',
|
||||
'Disable live feed': '라이브 피드 비활성화',
|
||||
'Enable live feed': '라이브 피드 활성화',
|
||||
'Default relays': '기본 릴레이',
|
||||
'Reset to default': '기본값으로 재설정',
|
||||
'Default relays description': '다른 사용자의 릴레이 구성을 조회하는 데 사용되며, 사용자가 릴레이를 구성하지 않은 경우 대체 수단으로 사용됩니다.',
|
||||
'Default relays warning': '경고: 이러한 설정을 임의로 수정하지 마십시오. 기본 경험에 영향을 줄 수 있습니다.',
|
||||
'Invalid relay URL': '유효하지 않은 릴레이 URL'
|
||||
'Default relays description':
|
||||
'다른 사용자의 릴레이 구성을 조회하는 데 사용되며, 사용자가 릴레이를 구성하지 않은 경우 대체 수단으로 사용됩니다.',
|
||||
'Default relays warning':
|
||||
'경고: 이러한 설정을 임의로 수정하지 마십시오. 기본 경험에 영향을 줄 수 있습니다.',
|
||||
'Invalid relay URL': '유효하지 않은 릴레이 URL',
|
||||
'Muted words': '차단 단어',
|
||||
'Add muted word': '차단 단어 추가'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -673,8 +673,12 @@ export default {
|
|||
'Enable live feed': 'Włącz kanał na żywo',
|
||||
'Default relays': 'Domyślne przekaźniki',
|
||||
'Reset to default': 'Przywróć domyślne',
|
||||
'Default relays description': 'Używane do odpytywania konfiguracji przekaźników innych użytkowników i jako rozwiązanie awaryjne, gdy użytkownicy nie mają skonfigurowanych przekaźników.',
|
||||
'Default relays warning': 'Ostrzeżenie: Nie modyfikuj tych ustawień pochopnie, może to wpłynąć na podstawowe doświadczenie.',
|
||||
'Invalid relay URL': 'Nieprawidłowy adres URL przekaźnika'
|
||||
'Default relays description':
|
||||
'Używane do odpytywania konfiguracji przekaźników innych użytkowników i jako rozwiązanie awaryjne, gdy użytkownicy nie mają skonfigurowanych przekaźników.',
|
||||
'Default relays warning':
|
||||
'Ostrzeżenie: Nie modyfikuj tych ustawień pochopnie, może to wpłynąć na podstawowe doświadczenie.',
|
||||
'Invalid relay URL': 'Nieprawidłowy adres URL przekaźnika',
|
||||
'Muted words': 'Wyciszone słowa',
|
||||
'Add muted word': 'Dodaj wyciszone słowo'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,8 +669,12 @@ export default {
|
|||
'Enable live feed': 'Ativar feed ao vivo',
|
||||
'Default relays': 'Relays padrão',
|
||||
'Reset to default': 'Redefinir para padrão',
|
||||
'Default relays description': 'Usados para consultar as configurações de relays de outros usuários e como alternativa quando os usuários não têm relays configurados.',
|
||||
'Default relays warning': 'Aviso: Não modifique essas configurações casualmente, pois pode afetar sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relay inválida'
|
||||
'Default relays description':
|
||||
'Usados para consultar as configurações de relays de outros usuários e como alternativa quando os usuários não têm relays configurados.',
|
||||
'Default relays warning':
|
||||
'Aviso: Não modifique essas configurações casualmente, pois pode afetar sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relé inválida',
|
||||
'Muted words': 'Palavras silenciadas',
|
||||
'Add muted word': 'Adicionar palavra silenciada'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,8 +672,12 @@ export default {
|
|||
'Enable live feed': 'Ativar feed ao vivo',
|
||||
'Default relays': 'Relays predefinidos',
|
||||
'Reset to default': 'Repor predefinições',
|
||||
'Default relays description': 'Utilizados para consultar as configurações de relays de outros utilizadores e como alternativa quando os utilizadores não têm relays configurados.',
|
||||
'Default relays warning': 'Aviso: Não modifique estas configurações casualmente, pois pode afetar a sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relay inválido'
|
||||
'Default relays description':
|
||||
'Utilizados para consultar as configurações de relays de outros utilizadores e como alternativa quando os utilizadores não têm relays configurados.',
|
||||
'Default relays warning':
|
||||
'Aviso: Não modifique estas configurações casualmente, pois pode afetar a sua experiência básica.',
|
||||
'Invalid relay URL': 'URL de relay inválido',
|
||||
'Muted words': 'Palavras silenciadas',
|
||||
'Add muted word': 'Adicionar palavra silenciada'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,8 +672,12 @@ export default {
|
|||
'Enable live feed': 'Включить прямую трансляцию',
|
||||
'Default relays': 'Реле по умолчанию',
|
||||
'Reset to default': 'Сбросить по умолчанию',
|
||||
'Default relays description': 'Используются для запроса конфигураций реле других пользователей и в качестве резервного варианта, когда у пользователей не настроены реле.',
|
||||
'Default relays warning': 'Предупреждение: Не изменяйте эти настройки без необходимости, это может повлиять на базовый опыт использования.',
|
||||
'Invalid relay URL': 'Неверный URL реле'
|
||||
'Default relays description':
|
||||
'Используются для запроса конфигураций реле других пользователей и в качестве резервного варианта, когда у пользователей не настроены реле.',
|
||||
'Default relays warning':
|
||||
'Предупреждение: Не изменяйте эти настройки без необходимости, это может повлиять на базовый опыт использования.',
|
||||
'Invalid relay URL': 'Неверный URL реле',
|
||||
'Muted words': 'Заблокированные слова',
|
||||
'Add muted word': 'Добавить заблокированное слово'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -649,8 +649,7 @@ export default {
|
|||
'trust-filter.show-all-content': 'แสดงเนื้อหาทั้งหมด',
|
||||
'trust-filter.only-show-wot':
|
||||
'แสดงเฉพาะเครือข่ายความไว้วางใจของคุณ (ผู้ติดตาม + ผู้ติดตามของพวกเขา)',
|
||||
'trust-filter.hide-bottom-percent':
|
||||
'กรอง {{score}}% ล่างสุดของผู้ใช้ตามอันดับความไว้วางใจ',
|
||||
'trust-filter.hide-bottom-percent': 'กรอง {{score}}% ล่างสุดของผู้ใช้ตามอันดับความไว้วางใจ',
|
||||
'trust-filter.trust-score-description':
|
||||
'คำนวณจากชื่อเสียงของผู้ใช้และเปอร์เซ็นไทล์ของเครือข่ายสังคม',
|
||||
'Auto-load profile pictures': 'โหลดรูปโปรไฟล์อัตโนมัติ',
|
||||
|
|
@ -658,8 +657,12 @@ export default {
|
|||
'Enable live feed': 'เปิดฟีดสด',
|
||||
'Default relays': 'รีเลย์เริ่มต้น',
|
||||
'Reset to default': 'รีเซ็ตเป็นค่าเริ่มต้น',
|
||||
'Default relays description': 'ใช้สำหรับสอบถามการกำหนดค่ารีเลย์ของผู้ใช้อื่นและเป็นทางเลือกสำรองเมื่อผู้ใช้ไม่ได้กำหนดค่ารีเลย์',
|
||||
'Default relays warning': 'คำเตือน: กรุณาอย่าแก้ไขการตั้งค่าเหล่านี้โดยไม่ระมัดระวัง เพราะอาจส่งผลต่อประสบการณ์พื้นฐานของคุณ',
|
||||
'Invalid relay URL': 'URL รีเลย์ไม่ถูกต้อง'
|
||||
'Default relays description':
|
||||
'ใช้สำหรับสอบถามการกำหนดค่ารีเลย์ของผู้ใช้อื่นและเป็นทางเลือกสำรองเมื่อผู้ใช้ไม่ได้กำหนดค่ารีเลย์',
|
||||
'Default relays warning':
|
||||
'คำเตือน: กรุณาอย่าแก้ไขการตั้งค่าเหล่านี้โดยไม่ระมัดระวัง เพราะอาจส่งผลต่อประสบการณ์พื้นฐานของคุณ',
|
||||
'Invalid relay URL': 'URL รีเลย์ไม่ถูกต้อง',
|
||||
'Muted words': 'คำที่ถูกปิดเสียง',
|
||||
'Add muted word': 'เพิ่มคำที่ถูกปิดเสียง'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -641,8 +641,11 @@ export default {
|
|||
'Enable live feed': '啟用即時推送',
|
||||
'Default relays': '預設中繼',
|
||||
'Reset to default': '重置為預設',
|
||||
'Default relays description': '用於查詢其他使用者的中繼配置,並在使用者沒有配置中繼時作為回退策略。',
|
||||
'Default relays description':
|
||||
'用於查詢其他使用者的中繼配置,並在使用者沒有配置中繼時作為回退策略。',
|
||||
'Default relays warning': '警告:請不要隨意修改這些設定,可能會影響基礎體驗。',
|
||||
'Invalid relay URL': '無效的中繼地址'
|
||||
'Invalid relay URL': '無效的中繼地址',
|
||||
'Muted words': '屏蔽詞',
|
||||
'Add muted word': '添加屏蔽詞'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -646,8 +646,11 @@ export default {
|
|||
'Enable live feed': '启用实时推送',
|
||||
'Default relays': '默认中继',
|
||||
'Reset to default': '重置为默认',
|
||||
'Default relays description': '用于查询其他用户的中继配置,并在用户没有配置中继时作为回退策略。',
|
||||
'Default relays warning': '警告:请不要随意修改这些设置,可能会影响基础体验。',
|
||||
'Invalid relay URL': '无效的中继地址'
|
||||
'Default relays description':
|
||||
'用于查询其他用户的中继配置,以及当用户没有配置中继时的备用选项。',
|
||||
'Default relays warning': '警告:请不要随意修改这些设置,可能会影响您的基本体验。',
|
||||
'Invalid relay URL': '无效的中继地址',
|
||||
'Muted words': '屏蔽词',
|
||||
'Add muted word': '添加屏蔽词'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
78
src/pages/secondary/GeneralSettingsPage/MutedWords.tsx
Normal file
78
src/pages/secondary/GeneralSettingsPage/MutedWords.tsx
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
||||
import { Plus, X } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import SettingItem from './SettingItem'
|
||||
|
||||
export default function MutedWords() {
|
||||
const { t } = useTranslation()
|
||||
const { mutedWords, setMutedWords } = useContentPolicy()
|
||||
const [newMutedWord, setNewMutedWord] = useState('')
|
||||
|
||||
const handleAddMutedWord = () => {
|
||||
const word = newMutedWord.trim().toLowerCase()
|
||||
if (word && !mutedWords.includes(word)) {
|
||||
setMutedWords([...mutedWords, word])
|
||||
setNewMutedWord('')
|
||||
}
|
||||
}
|
||||
|
||||
const handleRemoveMutedWord = (word: string) => {
|
||||
setMutedWords(mutedWords.filter((w) => w !== word))
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
handleAddMutedWord()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingItem className="flex-col items-start gap-2">
|
||||
<Label className="text-base font-normal">{t('Muted words')}</Label>
|
||||
<div className="w-full space-y-2">
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
placeholder={t('Add muted word')}
|
||||
value={newMutedWord}
|
||||
onChange={(e) => setNewMutedWord(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="flex-1"
|
||||
/>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleAddMutedWord}
|
||||
disabled={!newMutedWord.trim() || mutedWords.includes(newMutedWord.trim())}
|
||||
>
|
||||
<Plus />
|
||||
</Button>
|
||||
</div>
|
||||
{mutedWords.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{mutedWords.map((word) => (
|
||||
<div
|
||||
key={word}
|
||||
className="flex items-center gap-1 bg-muted px-2 py-1 rounded-md text-sm"
|
||||
>
|
||||
<span>{word}</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-4 w-4 hover:bg-transparent"
|
||||
onClick={() => handleRemoveMutedWord(word)}
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</SettingItem>
|
||||
)
|
||||
}
|
||||
21
src/pages/secondary/GeneralSettingsPage/SettingItem.tsx
Normal file
21
src/pages/secondary/GeneralSettingsPage/SettingItem.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { cn } from '@/lib/utils'
|
||||
import { forwardRef, HTMLProps } from 'react'
|
||||
|
||||
const SettingItem = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>(
|
||||
({ children, className, ...props }, ref) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex justify-between select-none items-center px-4 min-h-9 [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
SettingItem.displayName = 'SettingItem'
|
||||
export default SettingItem
|
||||
|
|
@ -11,14 +11,16 @@ import {
|
|||
} from '@/constants'
|
||||
import { LocalizedLanguageNames, TLanguage } from '@/i18n'
|
||||
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
|
||||
import { cn, isSupportCheckConnectionType } from '@/lib/utils'
|
||||
import { isSupportCheckConnectionType } from '@/lib/utils'
|
||||
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
||||
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||
import { TMediaAutoLoadPolicy, TNsfwDisplayPolicy, TProfilePictureAutoLoadPolicy } from '@/types'
|
||||
import { SelectValue } from '@radix-ui/react-select'
|
||||
import { RotateCcw } from 'lucide-react'
|
||||
import { forwardRef, HTMLProps, useState } from 'react'
|
||||
import { forwardRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import MutedWords from './MutedWords'
|
||||
import SettingItem from './SettingItem'
|
||||
|
||||
const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
||||
const { t, i18n } = useTranslation()
|
||||
|
|
@ -188,27 +190,10 @@ const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||
</div>
|
||||
</SettingItem>
|
||||
)}
|
||||
<MutedWords />
|
||||
</div>
|
||||
</SecondaryPageLayout>
|
||||
)
|
||||
})
|
||||
GeneralSettingsPage.displayName = 'GeneralSettingsPage'
|
||||
export default GeneralSettingsPage
|
||||
|
||||
const SettingItem = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>(
|
||||
({ children, className, ...props }, ref) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex justify-between select-none items-center px-4 min-h-9 [&_svg]:size-4 [&_svg]:shrink-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
SettingItem.displayName = 'SettingItem'
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ type TContentPolicyContext = {
|
|||
|
||||
faviconUrlTemplate: string
|
||||
setFaviconUrlTemplate: (template: string) => void
|
||||
|
||||
mutedWords: string[]
|
||||
setMutedWords: (words: string[]) => void
|
||||
}
|
||||
|
||||
const ContentPolicyContext = createContext<TContentPolicyContext | undefined>(undefined)
|
||||
|
|
@ -46,6 +49,7 @@ export function ContentPolicyProvider({ children }: { children: React.ReactNode
|
|||
storage.getProfilePictureAutoLoadPolicy()
|
||||
)
|
||||
const [faviconUrlTemplate, setFaviconUrlTemplate] = useState(storage.getFaviconUrlTemplate())
|
||||
const [mutedWords, setMutedWords] = useState(storage.getMutedWords())
|
||||
const [connectionType, setConnectionType] = useState((navigator as any).connection?.type)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -115,6 +119,11 @@ export function ContentPolicyProvider({ children }: { children: React.ReactNode
|
|||
setFaviconUrlTemplate(template)
|
||||
}
|
||||
|
||||
const updateMutedWords = (words: string[]) => {
|
||||
storage.setMutedWords(words)
|
||||
setMutedWords(words)
|
||||
}
|
||||
|
||||
return (
|
||||
<ContentPolicyContext.Provider
|
||||
value={{
|
||||
|
|
@ -131,7 +140,9 @@ export function ContentPolicyProvider({ children }: { children: React.ReactNode
|
|||
profilePictureAutoLoadPolicy,
|
||||
setProfilePictureAutoLoadPolicy: updateProfilePictureAutoLoadPolicy,
|
||||
faviconUrlTemplate,
|
||||
setFaviconUrlTemplate: updateFaviconUrlTemplate
|
||||
setFaviconUrlTemplate: updateFaviconUrlTemplate,
|
||||
mutedWords,
|
||||
setMutedWords: updateMutedWords
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ class LocalStorageService {
|
|||
private nsfwDisplayPolicy: TNsfwDisplayPolicy = NSFW_DISPLAY_POLICY.HIDE_CONTENT
|
||||
private minTrustScore: number = 40
|
||||
private defaultRelayUrls: string[] = BIG_RELAY_URLS
|
||||
private mutedWords: string[] = []
|
||||
|
||||
constructor() {
|
||||
if (!LocalStorageService.instance) {
|
||||
|
|
@ -293,6 +294,18 @@ class LocalStorageService {
|
|||
}
|
||||
}
|
||||
|
||||
const mutedWordsStr = window.localStorage.getItem(StorageKey.MUTED_WORDS)
|
||||
if (mutedWordsStr) {
|
||||
try {
|
||||
const words = JSON.parse(mutedWordsStr)
|
||||
if (Array.isArray(words) && words.every((word) => typeof word === 'string')) {
|
||||
this.mutedWords = words
|
||||
}
|
||||
} catch {
|
||||
// Invalid JSON, use default
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up deprecated data
|
||||
window.localStorage.removeItem(StorageKey.PINNED_PUBKEYS)
|
||||
window.localStorage.removeItem(StorageKey.ACCOUNT_PROFILE_EVENT_MAP)
|
||||
|
|
@ -640,6 +653,15 @@ class LocalStorageService {
|
|||
this.defaultRelayUrls = urls
|
||||
window.localStorage.setItem(StorageKey.DEFAULT_RELAY_URLS, JSON.stringify(urls))
|
||||
}
|
||||
|
||||
getMutedWords() {
|
||||
return this.mutedWords
|
||||
}
|
||||
|
||||
setMutedWords(words: string[]) {
|
||||
this.mutedWords = words
|
||||
window.localStorage.setItem(StorageKey.MUTED_WORDS, JSON.stringify(this.mutedWords))
|
||||
}
|
||||
}
|
||||
|
||||
const instance = new LocalStorageService()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue