From bd6340bbc76840a35655209f70db64df75f9902f Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 19 Mar 2026 22:27:11 +0800 Subject: [PATCH] feat: add protected badge for NIP-70 events Display a subtle green "Protected" badge next to the username for events with the `-` tag (NIP-70), indicating restricted distribution. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/Note/index.tsx | 2 ++ src/components/ProtectedBadge/index.tsx | 22 ++++++++++++++++++++++ src/i18n/locales/ar.ts | 4 +++- src/i18n/locales/de.ts | 4 +++- src/i18n/locales/en.ts | 4 +++- src/i18n/locales/es.ts | 4 +++- src/i18n/locales/fa.ts | 4 +++- src/i18n/locales/fr.ts | 4 +++- src/i18n/locales/hi.ts | 4 +++- src/i18n/locales/hu.ts | 4 +++- src/i18n/locales/it.ts | 4 +++- src/i18n/locales/ja.ts | 4 +++- src/i18n/locales/ko.ts | 4 +++- src/i18n/locales/pl.ts | 4 +++- src/i18n/locales/pt-BR.ts | 4 +++- src/i18n/locales/pt-PT.ts | 4 +++- src/i18n/locales/ru.ts | 4 +++- src/i18n/locales/th.ts | 4 +++- src/i18n/locales/zh-TW.ts | 4 +++- src/i18n/locales/zh.ts | 4 +++- 20 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 src/components/ProtectedBadge/index.tsx diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx index ac68284..5dd1ced 100644 --- a/src/components/Note/index.tsx +++ b/src/components/Note/index.tsx @@ -11,6 +11,7 @@ import AudioPlayer from '../AudioPlayer' import ClientTag from '../ClientTag' import Content from '../Content' import FollowingBadge from '../FollowingBadge' +import ProtectedBadge from '../ProtectedBadge' import { FormattedTimestamp } from '../FormattedTimestamp' import Nip05 from '../Nip05' import NoteOptions from '../NoteOptions' @@ -134,6 +135,7 @@ export default function Note({ /> +
diff --git a/src/components/ProtectedBadge/index.tsx b/src/components/ProtectedBadge/index.tsx new file mode 100644 index 0000000..3b2deae --- /dev/null +++ b/src/components/ProtectedBadge/index.tsx @@ -0,0 +1,22 @@ +import { isProtectedEvent } from '@/lib/event' +import { Event } from 'nostr-tools' +import { useMemo } from 'react' +import { useTranslation } from 'react-i18next' + +export default function ProtectedBadge({ event }: { event: Event }) { + const { t } = useTranslation() + const isProtected = useMemo(() => isProtectedEvent(event), [event]) + + if (!isProtected) return null + + return ( +
+ + {t('Protected')} + +
+ ) +} diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts index 0413279..98f235c 100644 --- a/src/i18n/locales/ar.ts +++ b/src/i18n/locales/ar.ts @@ -671,6 +671,8 @@ export default { 'Copy note content': 'نسخ محتوى الملاحظة', 'Video loop': 'تكرار الفيديو', 'Automatically replay videos when they end': 'إعادة تشغيل مقاطع الفيديو تلقائيًا عند انتهائها', - 'Relays used for searching notes (NIP-50)': 'الريلايات المستخدمة للبحث عن الملاحظات (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'الريلايات المستخدمة للبحث عن الملاحظات (NIP-50)', + 'Protected event (NIP-70)': 'حدث محمي (NIP-70)', + 'Protected': 'محمي' } } diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index 8f884ad..34f2e64 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -695,6 +695,8 @@ export default { 'Copy note content': 'Notizinhalt kopieren', 'Video loop': 'Video-Schleife', 'Automatically replay videos when they end': 'Videos automatisch wiederholen, wenn sie enden', - 'Relays used for searching notes (NIP-50)': 'Relays für die Notizsuche (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relays für die Notizsuche (NIP-50)', + 'Protected event (NIP-70)': 'Geschütztes Ereignis (NIP-70)', + 'Protected': 'Geschützt' } } diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 7e5558d..cef8a28 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -677,6 +677,8 @@ export default { 'Copy note content': 'Copy note content', 'Video loop': 'Video loop', 'Automatically replay videos when they end': 'Automatically replay videos when they end', - 'Relays used for searching notes (NIP-50)': 'Relays used for searching notes (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relays used for searching notes (NIP-50)', + 'Protected event (NIP-70)': 'Protected event (NIP-70)', + 'Protected': 'Protected' } } diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 2ec5a63..99a29b1 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -688,6 +688,8 @@ export default { 'Copy note content': 'Copiar contenido de la nota', 'Video loop': 'Repetir video', 'Automatically replay videos when they end': 'Reproducir automáticamente los videos cuando terminen', - 'Relays used for searching notes (NIP-50)': 'Relés utilizados para buscar notas (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relés utilizados para buscar notas (NIP-50)', + 'Protected event (NIP-70)': 'Evento protegido (NIP-70)', + 'Protected': 'Protegido' } } diff --git a/src/i18n/locales/fa.ts b/src/i18n/locales/fa.ts index 9201c6e..01ab315 100644 --- a/src/i18n/locales/fa.ts +++ b/src/i18n/locales/fa.ts @@ -683,6 +683,8 @@ export default { 'Copy note content': 'کپی محتوای یادداشت', 'Video loop': 'تکرار ویدیو', 'Automatically replay videos when they end': 'پخش خودکار ویدیوها پس از پایان', - 'Relays used for searching notes (NIP-50)': 'رله‌هایی که برای جستجوی یادداشت‌ها استفاده می‌شوند (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'رله‌هایی که برای جستجوی یادداشت‌ها استفاده می‌شوند (NIP-50)', + 'Protected event (NIP-70)': 'رویداد محافظت‌شده (NIP-70)', + 'Protected': 'محافظت‌شده' } } diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 9aed909..ee1a8cd 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -692,6 +692,8 @@ export default { 'Copy note content': 'Copier le contenu de la note', 'Video loop': 'Boucle vidéo', 'Automatically replay videos when they end': 'Rejouer automatiquement les vidéos à la fin', - 'Relays used for searching notes (NIP-50)': 'Relais utilisés pour rechercher des notes (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relais utilisés pour rechercher des notes (NIP-50)', + 'Protected event (NIP-70)': 'Événement protégé (NIP-70)', + 'Protected': 'Protégé' } } diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts index 82f8f5f..52da36e 100644 --- a/src/i18n/locales/hi.ts +++ b/src/i18n/locales/hi.ts @@ -683,6 +683,8 @@ export default { 'Copy note content': 'नोट सामग्री कॉपी करें', 'Video loop': 'वीडियो लूप', 'Automatically replay videos when they end': 'वीडियो समाप्त होने पर स्वचालित रूप से दोबारा चलाएं', - 'Relays used for searching notes (NIP-50)': 'नोट्स खोजने के लिए उपयोग किए जाने वाले रिले (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'नोट्स खोजने के लिए उपयोग किए जाने वाले रिले (NIP-50)', + 'Protected event (NIP-70)': 'संरक्षित इवेंट (NIP-70)', + 'Protected': 'संरक्षित' } } diff --git a/src/i18n/locales/hu.ts b/src/i18n/locales/hu.ts index ddd7d22..eb8679a 100644 --- a/src/i18n/locales/hu.ts +++ b/src/i18n/locales/hu.ts @@ -677,6 +677,8 @@ export default { 'Copy note content': 'Jegyzet tartalmának másolása', 'Video loop': 'Videó ismétlése', 'Automatically replay videos when they end': 'Videók automatikus újrajátszása, amikor véget érnek', - 'Relays used for searching notes (NIP-50)': 'Jegyzetek kereséséhez használt csomópontok (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Jegyzetek kereséséhez használt csomópontok (NIP-50)', + 'Protected event (NIP-70)': 'Védett esemény (NIP-70)', + 'Protected': 'Védett' } } diff --git a/src/i18n/locales/it.ts b/src/i18n/locales/it.ts index e06b7ef..127cd8a 100644 --- a/src/i18n/locales/it.ts +++ b/src/i18n/locales/it.ts @@ -688,6 +688,8 @@ export default { 'Copy note content': 'Copia contenuto della nota', 'Video loop': 'Ripetizione video', 'Automatically replay videos when they end': 'Riprodurre automaticamente i video quando terminano', - 'Relays used for searching notes (NIP-50)': 'Relay utilizzati per cercare le note (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relay utilizzati per cercare le note (NIP-50)', + 'Protected event (NIP-70)': 'Evento protetto (NIP-70)', + 'Protected': 'Protetto' } } diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts index d27b6e9..1642f35 100644 --- a/src/i18n/locales/ja.ts +++ b/src/i18n/locales/ja.ts @@ -683,6 +683,8 @@ export default { 'Copy note content': 'ノート内容をコピー', 'Video loop': 'ビデオループ', 'Automatically replay videos when they end': 'ビデオ終了時に自動的にリプレイする', - 'Relays used for searching notes (NIP-50)': 'ノート検索に使用するリレー (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'ノート検索に使用するリレー (NIP-50)', + 'Protected event (NIP-70)': '保護されたイベント (NIP-70)', + 'Protected': '保護' } } diff --git a/src/i18n/locales/ko.ts b/src/i18n/locales/ko.ts index 2bfde05..795ca35 100644 --- a/src/i18n/locales/ko.ts +++ b/src/i18n/locales/ko.ts @@ -677,6 +677,8 @@ export default { 'Copy note content': '노트 내용 복사', 'Video loop': '비디오 반복', 'Automatically replay videos when they end': '비디오가 끝나면 자동으로 다시 재생', - 'Relays used for searching notes (NIP-50)': '노트 검색에 사용되는 릴레이 (NIP-50)' + 'Relays used for searching notes (NIP-50)': '노트 검색에 사용되는 릴레이 (NIP-50)', + 'Protected event (NIP-70)': '보호된 이벤트 (NIP-70)', + 'Protected': '보호됨' } } diff --git a/src/i18n/locales/pl.ts b/src/i18n/locales/pl.ts index 19ba0ae..85a2836 100644 --- a/src/i18n/locales/pl.ts +++ b/src/i18n/locales/pl.ts @@ -689,6 +689,8 @@ export default { 'Copy note content': 'Kopiuj treść notatki', 'Video loop': 'Zapętlanie wideo', 'Automatically replay videos when they end': 'Automatycznie powtarzaj filmy po zakończeniu', - 'Relays used for searching notes (NIP-50)': 'Przekaźniki używane do wyszukiwania notatek (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Przekaźniki używane do wyszukiwania notatek (NIP-50)', + 'Protected event (NIP-70)': 'Chronione zdarzenie (NIP-70)', + 'Protected': 'Chronione' } } diff --git a/src/i18n/locales/pt-BR.ts b/src/i18n/locales/pt-BR.ts index cc671e8..bb3d9f2 100644 --- a/src/i18n/locales/pt-BR.ts +++ b/src/i18n/locales/pt-BR.ts @@ -686,6 +686,8 @@ export default { 'Copy note content': 'Copiar conteúdo da nota', 'Video loop': 'Repetir vídeo', 'Automatically replay videos when they end': 'Reproduzir automaticamente os vídeos quando terminarem', - 'Relays used for searching notes (NIP-50)': 'Relays usados para buscar notas (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relays usados para buscar notas (NIP-50)', + 'Protected event (NIP-70)': 'Evento protegido (NIP-70)', + 'Protected': 'Protegido' } } diff --git a/src/i18n/locales/pt-PT.ts b/src/i18n/locales/pt-PT.ts index 06e8086..6d18ad2 100644 --- a/src/i18n/locales/pt-PT.ts +++ b/src/i18n/locales/pt-PT.ts @@ -689,6 +689,8 @@ export default { 'Copy note content': 'Copiar conteúdo da nota', 'Video loop': 'Repetir vídeo', 'Automatically replay videos when they end': 'Reproduzir automaticamente os vídeos quando terminarem', - 'Relays used for searching notes (NIP-50)': 'Relés usados para pesquisar notas (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Relés usados para pesquisar notas (NIP-50)', + 'Protected event (NIP-70)': 'Evento protegido (NIP-70)', + 'Protected': 'Protegido' } } diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index 3772519..b9be787 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -688,6 +688,8 @@ export default { 'Copy note content': 'Скопировать содержимое заметки', 'Video loop': 'Зацикливание видео', 'Automatically replay videos when they end': 'Автоматически воспроизводить видео заново после окончания', - 'Relays used for searching notes (NIP-50)': 'Ретрансляторы для поиска заметок (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'Ретрансляторы для поиска заметок (NIP-50)', + 'Protected event (NIP-70)': 'Защищённое событие (NIP-70)', + 'Protected': 'Защищённый' } } diff --git a/src/i18n/locales/th.ts b/src/i18n/locales/th.ts index 74680e4..2c24539 100644 --- a/src/i18n/locales/th.ts +++ b/src/i18n/locales/th.ts @@ -673,6 +673,8 @@ export default { 'Copy note content': 'คัดลอกเนื้อหาโน้ต', 'Video loop': 'เล่นวิดีโอซ้ำ', 'Automatically replay videos when they end': 'เล่นวิดีโอซ้ำอัตโนมัติเมื่อจบ', - 'Relays used for searching notes (NIP-50)': 'รีเลย์ที่ใช้สำหรับค้นหาโน้ต (NIP-50)' + 'Relays used for searching notes (NIP-50)': 'รีเลย์ที่ใช้สำหรับค้นหาโน้ต (NIP-50)', + 'Protected event (NIP-70)': 'เหตุการณ์ที่ได้รับการป้องกัน (NIP-70)', + 'Protected': 'ป้องกัน' } } diff --git a/src/i18n/locales/zh-TW.ts b/src/i18n/locales/zh-TW.ts index b9e00dc..f2435c7 100644 --- a/src/i18n/locales/zh-TW.ts +++ b/src/i18n/locales/zh-TW.ts @@ -655,6 +655,8 @@ export default { 'Copy note content': '複製筆記內容', 'Video loop': '影片循環', 'Automatically replay videos when they end': '影片播放結束後自動重新播放', - 'Relays used for searching notes (NIP-50)': '用於搜尋筆記的伺服器 (NIP-50)' + 'Relays used for searching notes (NIP-50)': '用於搜尋筆記的伺服器 (NIP-50)', + 'Protected event (NIP-70)': '受保護的事件 (NIP-70)', + 'Protected': '受保護' } } diff --git a/src/i18n/locales/zh.ts b/src/i18n/locales/zh.ts index 8a96710..71c0014 100644 --- a/src/i18n/locales/zh.ts +++ b/src/i18n/locales/zh.ts @@ -660,6 +660,8 @@ export default { 'Copy note content': '复制笔记内容', 'Video loop': '视频循环', 'Automatically replay videos when they end': '视频播放结束后自动重新播放', - 'Relays used for searching notes (NIP-50)': '用于搜索笔记的服务器 (NIP-50)' + 'Relays used for searching notes (NIP-50)': '用于搜索笔记的服务器 (NIP-50)', + 'Protected event (NIP-70)': '受保护的事件 (NIP-70)', + 'Protected': '受保护' } }