mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
+1
-1
@@ -7,7 +7,7 @@
|
||||
"dependencies": {
|
||||
"@capacitor/app": "1.1.1",
|
||||
"@floating-ui/react": "0.26.1",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#f0ae8cd285f282d82eafd290e3b73525faa8ec6b",
|
||||
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#d7fa27920f8ec21c9fa08bc216054083e1d59fc0",
|
||||
"@testing-library/jest-dom": "5.14.1",
|
||||
"@testing-library/react": "13.0.0",
|
||||
"@testing-library/user-event": "13.2.1",
|
||||
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "مشرفو المنتدى",
|
||||
"this_post_was_removed": "تمت إزالة هذا المنشور",
|
||||
"user_deleted_this_post": "حذف المستخدم هذا المنشور.",
|
||||
"reason": "السبب"
|
||||
"reason": "السبب",
|
||||
"search": "بحث",
|
||||
"ban_user_for": "حظر المستخدم لمدة <1></1> يوم(أيام)",
|
||||
"optional": "اختياري",
|
||||
"close_thread": "اغلق الموضوع",
|
||||
"view_spoiler": "عرض الحاضر",
|
||||
"filter": "تصفية"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "বোর্ড মডস",
|
||||
"this_post_was_removed": "এই পোস্টটি সরানো হয়েছে",
|
||||
"user_deleted_this_post": "ব্যবহারকারী এই পোস্টটি মুছে ফেলেছে।",
|
||||
"reason": "কারণ"
|
||||
"reason": "কারণ",
|
||||
"search": "অনুসন্ধান",
|
||||
"ban_user_for": "ব্যবহারকারীকে <1></1> দিনের জন্য বন্ধ করুন",
|
||||
"optional": "ঐচ্ছিক",
|
||||
"close_thread": "থ্রেড বন্ধ করুন",
|
||||
"view_spoiler": "স্পোয়ালার দেখুন",
|
||||
"filter": "ফিল্টার"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Nástěnka Mods",
|
||||
"this_post_was_removed": "tento příspěvek byl odstraněn",
|
||||
"user_deleted_this_post": "Uživatel smazal tento příspěvek.",
|
||||
"reason": "důvod"
|
||||
"reason": "důvod",
|
||||
"search": "vyhledat",
|
||||
"ban_user_for": "Zakázat uživatele na <1></1> den (dní)",
|
||||
"optional": "volitelný",
|
||||
"close_thread": "uzavřít vlákno",
|
||||
"view_spoiler": "zobrazit spoiler",
|
||||
"filter": "filtr"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board Mods",
|
||||
"this_post_was_removed": "dette indlæg blev fjernet",
|
||||
"user_deleted_this_post": "Brugeren slettede dette indlæg.",
|
||||
"reason": "grund"
|
||||
"reason": "grund",
|
||||
"search": "søg",
|
||||
"ban_user_for": "Udeluk brugeren i <1></1> dag(e)",
|
||||
"optional": "valgfri",
|
||||
"close_thread": "luk tråd",
|
||||
"view_spoiler": "vis spoiler",
|
||||
"filter": "filtrér"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board-Moderatoren",
|
||||
"this_post_was_removed": "Dieser Beitrag wurde entfernt",
|
||||
"user_deleted_this_post": "Benutzer hat diesen Beitrag gelöscht.",
|
||||
"reason": "Grund"
|
||||
"reason": "Grund",
|
||||
"search": "suche",
|
||||
"ban_user_for": "Benutzer für <1></1> Tag(e) sperren",
|
||||
"optional": "optional",
|
||||
"close_thread": "Thread schließen",
|
||||
"view_spoiler": "Spoiler anzeigen",
|
||||
"filter": "filtern"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Mods του φόρουμ",
|
||||
"this_post_was_removed": "αυτή η ανάρτηση αφαιρέθηκε",
|
||||
"user_deleted_this_post": "Ο χρήστης διέγραψε αυτή την ανάρτηση.",
|
||||
"reason": "λόγος"
|
||||
"reason": "λόγος",
|
||||
"search": "αναζήτηση",
|
||||
"ban_user_for": "Αποκλεισμός χρήστη για <1></1> ημέρα(ες)",
|
||||
"optional": "προαιρετικό",
|
||||
"close_thread": "κλείσιμο νήματος",
|
||||
"view_spoiler": "προβολή spoiler",
|
||||
"filter": "φίλτρο"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board Mods",
|
||||
"this_post_was_removed": "this post was removed",
|
||||
"user_deleted_this_post": "User deleted this post.",
|
||||
"reason": "reason"
|
||||
"reason": "reason",
|
||||
"search": "search",
|
||||
"ban_user_for": "Ban user for <1></1> day(s)",
|
||||
"optional": "optional",
|
||||
"close_thread": "close thread",
|
||||
"view_spoiler": "view spoiler",
|
||||
"filter": "filter"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Mods del foro",
|
||||
"this_post_was_removed": "este mensaje fue eliminado",
|
||||
"user_deleted_this_post": "El usuario eliminó este mensaje.",
|
||||
"reason": "razón"
|
||||
"reason": "razón",
|
||||
"search": "buscar",
|
||||
"ban_user_for": "Prohibir al usuario durante <1></1> día(s)",
|
||||
"optional": "opcional",
|
||||
"close_thread": "cerrar hilo",
|
||||
"view_spoiler": "ver spoiler",
|
||||
"filter": "filtrar"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "مدیران تالار",
|
||||
"this_post_was_removed": "این پست حذف شد",
|
||||
"user_deleted_this_post": "کاربر این پست را حذف کرده است.",
|
||||
"reason": "دلیل"
|
||||
"reason": "دلیل",
|
||||
"search": "جستجو",
|
||||
"ban_user_for": "بستن کاربر برای <1></1> روز",
|
||||
"optional": "اختیاری",
|
||||
"close_thread": "بستن موضوع",
|
||||
"view_spoiler": "نمایش اسپویلر",
|
||||
"filter": "فیلتر"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Hallituksen Mods",
|
||||
"this_post_was_removed": "tämä viesti on poistettu",
|
||||
"user_deleted_this_post": "Käyttäjä poisti tämän viestin.",
|
||||
"reason": "syy"
|
||||
"reason": "syy",
|
||||
"search": "haku",
|
||||
"ban_user_for": "Estä käyttäjä <1></1> päiväksi",
|
||||
"optional": "valinnainen",
|
||||
"close_thread": "sulje keskustelu",
|
||||
"view_spoiler": "näytä spoiler",
|
||||
"filter": "suodatin"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board Mods",
|
||||
"this_post_was_removed": "tinanggal ang post na ito",
|
||||
"user_deleted_this_post": "Tinanggal ng gumagamit ang post na ito.",
|
||||
"reason": "dahilan"
|
||||
"reason": "dahilan",
|
||||
"search": "maghanap",
|
||||
"ban_user_for": "I-ban ang user para sa <1></1> araw",
|
||||
"optional": "opsyonal",
|
||||
"close_thread": "isara ang thread",
|
||||
"view_spoiler": "tingnan ang spoiler",
|
||||
"filter": "salain"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Mods de la table",
|
||||
"this_post_was_removed": "ce post a été supprimé",
|
||||
"user_deleted_this_post": "L'utilisateur a supprimé ce post.",
|
||||
"reason": "raison"
|
||||
"reason": "raison",
|
||||
"search": "chercher",
|
||||
"ban_user_for": "Bannir l'utilisateur pendant <1></1> jour(s)",
|
||||
"optional": "facultatif",
|
||||
"close_thread": "fermer le fil",
|
||||
"view_spoiler": "voir le spoiler",
|
||||
"filter": "filtre"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "מנהלי הפורום",
|
||||
"this_post_was_removed": "הודעה זו הוסרה",
|
||||
"user_deleted_this_post": "המשתמש מחק את הפוסט הזה.",
|
||||
"reason": "סיבה"
|
||||
"reason": "סיבה",
|
||||
"search": "חיפוש",
|
||||
"ban_user_for": "אסור למשתמש למשך <1></1> יום",
|
||||
"optional": "אופציונלי",
|
||||
"close_thread": "סגור את הנושא",
|
||||
"view_spoiler": "הצג ספוילר",
|
||||
"filter": "סנן"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "बोर्ड मॉड्स",
|
||||
"this_post_was_removed": "यह पोस्ट हटा दी गई है",
|
||||
"user_deleted_this_post": "उपयोगकर्ता ने इस पोस्ट को हटा दिया।",
|
||||
"reason": "कारण"
|
||||
"reason": "कारण",
|
||||
"search": "खोज",
|
||||
"ban_user_for": "उपयोगकर्ता को <1></1> दिनों के लिए प्रतिबंधित करें",
|
||||
"optional": "वैकल्पिक",
|
||||
"close_thread": "थ्रेड बंद करें",
|
||||
"view_spoiler": "स्पॉइलर देखें",
|
||||
"filter": "फ़िल्टर"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Tábla Mods",
|
||||
"this_post_was_removed": "ez a bejegyzés eltávolításra került",
|
||||
"user_deleted_this_post": "A felhasználó törölte ezt a bejegyzést.",
|
||||
"reason": "indok"
|
||||
"reason": "indok",
|
||||
"search": "keresés",
|
||||
"ban_user_for": "Felhasználó letiltása <1></1> napra",
|
||||
"optional": "opcionális",
|
||||
"close_thread": "szál bezárása",
|
||||
"view_spoiler": "spoiler megtekintése",
|
||||
"filter": "szűrő"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Papan Pesan Mods",
|
||||
"this_post_was_removed": "posting ini telah dihapus",
|
||||
"user_deleted_this_post": "Pengguna menghapus posting ini.",
|
||||
"reason": "alasan"
|
||||
"reason": "alasan",
|
||||
"search": "cari",
|
||||
"ban_user_for": "Blokir pengguna selama <1></1> hari",
|
||||
"optional": "opsional",
|
||||
"close_thread": "tutup utas",
|
||||
"view_spoiler": "lihat spoiler",
|
||||
"filter": "menyaring"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Moderatori del Forum",
|
||||
"this_post_was_removed": "questo post è stato rimosso",
|
||||
"user_deleted_this_post": "L'utente ha eliminato questo post.",
|
||||
"reason": "motivo"
|
||||
"reason": "motivo",
|
||||
"search": "cerca",
|
||||
"ban_user_for": "Banna l'utente per <1></1> giorno/i",
|
||||
"optional": "opzionale",
|
||||
"close_thread": "chiudi il thread",
|
||||
"view_spoiler": "mostra spoiler",
|
||||
"filter": "filtro"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "ボードの管理者",
|
||||
"this_post_was_removed": "この投稿は削除されました",
|
||||
"user_deleted_this_post": "ユーザーがこの投稿を削除しました。",
|
||||
"reason": "理由"
|
||||
"reason": "理由",
|
||||
"search": "検索",
|
||||
"ban_user_for": "ユーザーを<1></1>日間禁止する",
|
||||
"optional": "オプショナル",
|
||||
"close_thread": "スレッドを閉じる",
|
||||
"view_spoiler": "スポイラーを表示",
|
||||
"filter": "フィルター"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "게시판 모드",
|
||||
"this_post_was_removed": "이 게시물은 삭제되었습니다",
|
||||
"user_deleted_this_post": "사용자가이 게시물을 삭제했습니다.",
|
||||
"reason": "이유"
|
||||
"reason": "이유",
|
||||
"search": "검색",
|
||||
"ban_user_for": "사용자를 <1></1>일 동안 차단하기",
|
||||
"optional": "선택",
|
||||
"close_thread": "스레드 닫기",
|
||||
"view_spoiler": "스포일러 보기",
|
||||
"filter": "필터"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "बोर्ड मॉड्स",
|
||||
"this_post_was_removed": "हा पोस्ट काढून टाकला गेला आहे",
|
||||
"user_deleted_this_post": "वापरकर्ता हे पोस्ट हटवलं आहे.",
|
||||
"reason": "कारण"
|
||||
"reason": "कारण",
|
||||
"search": "शोध",
|
||||
"ban_user_for": "वापरकर्ता ब्लॉक करा <1></1> दिवस",
|
||||
"optional": "वैकल्पिक",
|
||||
"close_thread": "थ्रेड बंद करा",
|
||||
"view_spoiler": "स्पॉईलर पहा",
|
||||
"filter": "फिल्टर"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board Mods",
|
||||
"this_post_was_removed": "deze post is verwijderd",
|
||||
"user_deleted_this_post": "Gebruiker heeft deze post verwijderd.",
|
||||
"reason": "reden"
|
||||
"reason": "reden",
|
||||
"search": "zoeken",
|
||||
"ban_user_for": "Gebruiker verbannen voor <1></1> dag(en)",
|
||||
"optional": "optioneel",
|
||||
"close_thread": "draad sluiten",
|
||||
"view_spoiler": "bekijk spoiler",
|
||||
"filter": "filter"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Board Mods",
|
||||
"this_post_was_removed": "dette innlegget ble fjernet",
|
||||
"user_deleted_this_post": "Brukeren slettet dette innlegget.",
|
||||
"reason": "grunn"
|
||||
"reason": "grunn",
|
||||
"search": "søk",
|
||||
"ban_user_for": "Blokker bruker i <1></1> dag(er)",
|
||||
"optional": "valgfritt",
|
||||
"close_thread": "lukk tråd",
|
||||
"view_spoiler": "se spoiler",
|
||||
"filter": "filter"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Tablica Mods",
|
||||
"this_post_was_removed": "ten post został usunięty",
|
||||
"user_deleted_this_post": "Użytkownik usunął ten post.",
|
||||
"reason": "powód"
|
||||
"reason": "powód",
|
||||
"search": "szukaj",
|
||||
"ban_user_for": "Zablokuj użytkownika na <1></1> dzień (dni)",
|
||||
"optional": "opcjonalnie",
|
||||
"close_thread": "zamknij wątek",
|
||||
"view_spoiler": "pokaż spoiler",
|
||||
"filter": "filtr"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Mods do fórum",
|
||||
"this_post_was_removed": "esta postagem foi removida",
|
||||
"user_deleted_this_post": "O usuário excluiu esta postagem.",
|
||||
"reason": "razão"
|
||||
"reason": "razão",
|
||||
"search": "pesquisar",
|
||||
"ban_user_for": "Banir usuário por <1></1> dia(s)",
|
||||
"optional": "opcional",
|
||||
"close_thread": "fechar tópico",
|
||||
"view_spoiler": "ver spoiler",
|
||||
"filter": "filtro"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Mods de la bord",
|
||||
"this_post_was_removed": "acest mesaj a fost eliminat",
|
||||
"user_deleted_this_post": "Utilizatorul a șters acest mesaj.",
|
||||
"reason": "motiv"
|
||||
"reason": "motiv",
|
||||
"search": "căutare",
|
||||
"ban_user_for": "Interzice utilizatorul pentru <1></1> zi(zile)",
|
||||
"optional": "opțional",
|
||||
"close_thread": "închide firul",
|
||||
"view_spoiler": "vezi spoilerul",
|
||||
"filter": "filtru"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Модераторы форума",
|
||||
"this_post_was_removed": "этот пост был удален",
|
||||
"user_deleted_this_post": "Пользователь удалил этот пост.",
|
||||
"reason": "причина"
|
||||
"reason": "причина",
|
||||
"search": "поиск",
|
||||
"ban_user_for": "Заблокировать пользователя на <1></1> день(дней)",
|
||||
"optional": "необязательный",
|
||||
"close_thread": "закрыть тему",
|
||||
"view_spoiler": "посмотреть спойлер",
|
||||
"filter": "фильтр"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Tabela Mods",
|
||||
"this_post_was_removed": "kjo postim u hoq",
|
||||
"user_deleted_this_post": "Përdoruesi fshiu këtë post.",
|
||||
"reason": "arsye"
|
||||
"reason": "arsye",
|
||||
"search": "kërkim",
|
||||
"ban_user_for": "Ndalo përdoruesin për <1></1> ditë",
|
||||
"optional": "opsionale",
|
||||
"close_thread": "mbyll temën",
|
||||
"view_spoiler": "shikoni spoiler",
|
||||
"filter": "filtruar"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Styrelse Mods",
|
||||
"this_post_was_removed": "detta inlägg togs bort",
|
||||
"user_deleted_this_post": "Användaren tog bort detta inlägg.",
|
||||
"reason": "anledning"
|
||||
"reason": "anledning",
|
||||
"search": "sök",
|
||||
"ban_user_for": "Blockera användaren i <1></1> dag(ar)",
|
||||
"optional": "valfritt",
|
||||
"close_thread": "stäng tråd",
|
||||
"view_spoiler": "visa spoiler",
|
||||
"filter": "filter"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "సందేశ బోర్డుల మాడ్స్",
|
||||
"this_post_was_removed": "ఈ పోస్టు తొలగించబడింది",
|
||||
"user_deleted_this_post": "వాడు ఈ పోస్టును తొలగించాడు.",
|
||||
"reason": "కారణం"
|
||||
"reason": "కారణం",
|
||||
"search": "శోధన",
|
||||
"ban_user_for": "<1></1> రోజుల కోసం వాడుకరినీ బ్యాన్ చేయండి",
|
||||
"optional": "ఐచ్ఛికం",
|
||||
"close_thread": "థ్రెడ్ను మూసేయండి",
|
||||
"view_spoiler": "స్పోయ్లర్ వీక్షించండి",
|
||||
"filter": "వడపోత"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "บอร์ด Mods",
|
||||
"this_post_was_removed": "โพสต์นี้ถูกลบ",
|
||||
"user_deleted_this_post": "ผู้ใช้ได้ลบโพสต์นี้",
|
||||
"reason": "เหตุผล"
|
||||
"reason": "เหตุผล",
|
||||
"search": "ค้นหา",
|
||||
"ban_user_for": "แบนผู้ใช้ <1></1> วัน",
|
||||
"optional": "ไม่จำเป็น",
|
||||
"close_thread": "ปิดกระทู้",
|
||||
"view_spoiler": "ดูสปอยล์เลอร์",
|
||||
"filter": "ตัวกรอง"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Forum Mods",
|
||||
"this_post_was_removed": "bu mesaj kaldırıldı",
|
||||
"user_deleted_this_post": "Kullanıcı bu mesajı sildi.",
|
||||
"reason": "neden"
|
||||
"reason": "neden",
|
||||
"search": "arama",
|
||||
"ban_user_for": "Kullanıcıyı <1></1> gün boyunca yasakla",
|
||||
"optional": "isteğe bağlı",
|
||||
"close_thread": "konuyu kapat",
|
||||
"view_spoiler": "spoileri görüntüle",
|
||||
"filter": "filtre"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Дошка Моди",
|
||||
"this_post_was_removed": "цей пост було видалено",
|
||||
"user_deleted_this_post": "Користувач видалив цей пост.",
|
||||
"reason": "причина"
|
||||
"reason": "причина",
|
||||
"search": "пошук",
|
||||
"ban_user_for": "Заборонити користувача на <1></1> день (днів)",
|
||||
"optional": "необов’язково",
|
||||
"close_thread": "закрити тему",
|
||||
"view_spoiler": "переглянути спойлер",
|
||||
"filter": "фільтр"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "بورڈ موڈس",
|
||||
"this_post_was_removed": "یہ پوسٹ ہٹا دی گئی ہے",
|
||||
"user_deleted_this_post": "صارف نے یہ پوسٹ حذف کردی.",
|
||||
"reason": "وجہ"
|
||||
"reason": "وجہ",
|
||||
"search": "تلاش کریں",
|
||||
"ban_user_for": "<1></1> دنوں کے لیے صارف کو پابندی عائد کریں",
|
||||
"optional": "اختیاری",
|
||||
"close_thread": "موضوع بند کریں",
|
||||
"view_spoiler": "اسپوائلر دیکھیں",
|
||||
"filter": "فلٹر"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "Bảng Mods",
|
||||
"this_post_was_removed": "bài đăng này đã bị xóa",
|
||||
"user_deleted_this_post": "Người dùng đã xóa bài đăng này.",
|
||||
"reason": "lý do"
|
||||
"reason": "lý do",
|
||||
"search": "tìm kiếm",
|
||||
"ban_user_for": "Cấm người dùng trong <1></1> ngày",
|
||||
"optional": "tùy chọn",
|
||||
"close_thread": "đóng chủ đề",
|
||||
"view_spoiler": "xem spoiler",
|
||||
"filter": "bộ lọc"
|
||||
}
|
||||
@@ -141,5 +141,11 @@
|
||||
"board_mods": "董事會版主",
|
||||
"this_post_was_removed": "此帖已被删除",
|
||||
"user_deleted_this_post": "用户删除了这个帖子。",
|
||||
"reason": "原因"
|
||||
"reason": "原因",
|
||||
"search": "搜索",
|
||||
"ban_user_for": "封禁用户 <1></1> 天",
|
||||
"optional": "可选的",
|
||||
"close_thread": "关闭主题",
|
||||
"view_spoiler": "查看剧透",
|
||||
"filter": "过滤器"
|
||||
}
|
||||
+3
-5
@@ -18,15 +18,13 @@ import SubplebbitStats from './components/subplebbit-stats';
|
||||
import TopBar from './components/topbar';
|
||||
|
||||
const BoardLayout = () => {
|
||||
const { accountCommentIndex, commentCid, subplebbitAddress } = useParams();
|
||||
const { accountCommentIndex, subplebbitAddress } = useParams();
|
||||
const location = useLocation();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const isValidAccountCommentIndex = !accountCommentIndex || (!isNaN(parseInt(accountCommentIndex)) && parseInt(accountCommentIndex) >= 0);
|
||||
const isValidCommentCid = !commentCid || /^Qm[a-zA-Z0-9]{44}$/.test(commentCid);
|
||||
const isValidSubplebbitAddress = !subplebbitAddress || subplebbitAddress.includes('.') || /^12D3KooW[a-zA-Z0-9]{44}$/.test(subplebbitAddress);
|
||||
|
||||
if (!isValidAccountCommentIndex || !isValidCommentCid || !isValidSubplebbitAddress) {
|
||||
if (!isValidAccountCommentIndex) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
@@ -45,7 +43,7 @@ const BoardLayout = () => {
|
||||
) : (
|
||||
<>
|
||||
<PostForm key={key} />
|
||||
{subplebbitAddress && isValidSubplebbitAddress && <SubplebbitStats />}
|
||||
{subplebbitAddress && <SubplebbitStats />}
|
||||
<DesktopBoardButtons />
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -13,11 +13,6 @@ interface BoardButtonsProps {
|
||||
isInSubscriptionsView?: boolean;
|
||||
}
|
||||
|
||||
const OptionsButton = () => {
|
||||
const { t } = useTranslation();
|
||||
return <button className='button'>{t('options')}</button>;
|
||||
};
|
||||
|
||||
const CatalogButton = ({ address, isInAllView, isInSubscriptionsView }: BoardButtonsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const link = isInAllView ? `/p/all/catalog` : isInSubscriptionsView ? `/p/subscriptions/catalog` : `/p/${address}/catalog`;
|
||||
@@ -96,7 +91,6 @@ export const MobileBoardButtons = () => {
|
||||
<>
|
||||
<ReturnButton address={subplebbitAddress} />
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />
|
||||
<OptionsButton />
|
||||
<SubscribeButton address={subplebbitAddress} />
|
||||
</>
|
||||
) : (
|
||||
@@ -106,7 +100,6 @@ export const MobileBoardButtons = () => {
|
||||
) : (
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />
|
||||
)}
|
||||
<OptionsButton />
|
||||
<SubscribeButton address={subplebbitAddress} />
|
||||
<RefreshButton />
|
||||
{isInCatalogView && (
|
||||
@@ -143,9 +136,7 @@ export const DesktopBoardButtons = () => {
|
||||
[
|
||||
<ReturnButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />
|
||||
] [
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />
|
||||
] [
|
||||
<OptionsButton />]
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />]
|
||||
{isInPostView && (
|
||||
<span className={styles.rightSideButtons}>
|
||||
[
|
||||
@@ -166,9 +157,7 @@ export const DesktopBoardButtons = () => {
|
||||
<CatalogButton address={subplebbitAddress} isInAllView={isInAllView} isInSubscriptionsView={isInSubscriptionsView} />]{' '}
|
||||
</>
|
||||
)}
|
||||
[
|
||||
<OptionsButton />] [
|
||||
<RefreshButton />]
|
||||
[<RefreshButton />]
|
||||
<span className={styles.rightSideButtons}>
|
||||
{isInCatalogView && <SortOptions />}
|
||||
{!(isInAllView || isInSubscriptionsView) && (
|
||||
|
||||
@@ -39,7 +39,7 @@ const BoardHeader = () => {
|
||||
<div className={styles.bannerCnt}>
|
||||
<ImageBanner key={isInAllView ? 'all' : isInSubscriptionsView ? 'subscriptions' : address} />
|
||||
</div>
|
||||
<div className={styles.boardTitle}>{title || `p/${shortAddress}`}</div>
|
||||
<div className={styles.boardTitle}>{title || `p/${shortAddress || subplebbitAddress}`}</div>
|
||||
<div className={styles.boardSubtitle}>{subtitle}</div>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
@@ -55,7 +55,7 @@ export const CatalogPostMedia = ({ commentMediaInfo, isOutOfFeed, linkWidth, lin
|
||||
<img src={thumbnail} alt='' onLoad={handleLoad} onError={handleError} style={loadingStyle} />
|
||||
) : (
|
||||
// show first frame of the video, as a workaround for Safari not loading thumbnails
|
||||
<video src={`${url}#t=0.001`} onLoad={handleLoad} onError={handleError} style={loadingStyle} />
|
||||
<video src={`${url}#t=0.001`} onError={handleError} />
|
||||
);
|
||||
} else if (type === 'webpage' && !hasError) {
|
||||
thumbnailComponent = <img src={thumbnail} alt='' onLoad={handleLoad} onError={handleError} style={loadingStyle} />;
|
||||
@@ -69,7 +69,7 @@ export const CatalogPostMedia = ({ commentMediaInfo, isOutOfFeed, linkWidth, lin
|
||||
|
||||
return (
|
||||
<div className={hasError ? '' : styles.mediaWrapper} style={thumbnailDimensions}>
|
||||
{!isLoaded && !hasError && <span className={styles.loadingSkeleton} />}
|
||||
{!isLoaded && !hasError && type !== 'video' && <span className={styles.loadingSkeleton} />}
|
||||
{hasError ? <img className={styles.fileDeleted} src='/assets/filedeleted-res.gif' alt='File deleted' /> : thumbnailComponent}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,17 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.spoiler {
|
||||
display: inline-block;
|
||||
margin: 3px 20px 5px 20px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.subplebbitAvatar {
|
||||
max-width: 125px;
|
||||
@@ -52,6 +63,10 @@
|
||||
float: left;
|
||||
}
|
||||
|
||||
.thumbnail video {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from './comment-media.module.css';
|
||||
import { CommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import { getHostname } from '../../lib/utils/url-utils';
|
||||
@@ -9,16 +10,22 @@ import Embed, { canEmbed } from '../embed';
|
||||
|
||||
interface MediaProps {
|
||||
commentMediaInfo?: CommentMediaInfo;
|
||||
isDeleted?: boolean;
|
||||
isOutOfFeed?: boolean; // virtuoso wrapper unneeded
|
||||
isReply: boolean;
|
||||
post?: Comment;
|
||||
isReply?: boolean;
|
||||
linkHeight?: number;
|
||||
linkWidth?: number;
|
||||
showThumbnail?: boolean;
|
||||
setShowThumbnail: (showThumbnail: boolean) => void;
|
||||
}
|
||||
|
||||
const Thumbnail = ({ commentMediaInfo, isDeleted, isOutOfFeed, isReply, linkHeight, linkWidth, setShowThumbnail }: MediaProps) => {
|
||||
const Thumbnail = ({ commentMediaInfo, post, setShowThumbnail }: MediaProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { deleted, linkHeight, linkWidth, parentCid, removed, spoiler } = post || {};
|
||||
const { isDescription, isRules } = post || {}; // custom properties, not from api
|
||||
const isOutOfFeed = isDescription || isRules; // virtuoso wrapper unneeded
|
||||
const isReply = parentCid;
|
||||
const isDeleted = deleted || removed;
|
||||
|
||||
const { patternThumbnailUrl, thumbnail, type, url } = commentMediaInfo || {};
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const handleError = () => setHasError(true);
|
||||
@@ -72,6 +79,10 @@ const Thumbnail = ({ commentMediaInfo, isDeleted, isOutOfFeed, isReply, linkHeig
|
||||
|
||||
return hasError || isDeleted ? (
|
||||
<img className={styles.fileDeleted} src='/assets/filedeleted-res.gif' alt='File deleted' />
|
||||
) : spoiler ? (
|
||||
<span className={styles.spoiler} style={{ width: maxThumbnailSize, height: maxThumbnailSize }} onClick={() => setShowThumbnail(false)}>
|
||||
<span className={styles.spoilerText}>[{t('view_spoiler')}]</span>
|
||||
</span>
|
||||
) : isOutOfFeed ? (
|
||||
<span className={styles.subplebbitAvatar}>{thumbnailComponent}</span>
|
||||
) : isMobile || isReply ? (
|
||||
@@ -133,7 +144,7 @@ const Media = ({ commentMediaInfo, isReply, setShowThumbnail }: MediaProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const CommentMedia = ({ commentMediaInfo, isDeleted, isOutOfFeed, isReply, linkHeight, linkWidth, showThumbnail, setShowThumbnail }: MediaProps) => {
|
||||
const CommentMedia = ({ commentMediaInfo, post, showThumbnail, setShowThumbnail }: MediaProps) => {
|
||||
const { t } = useTranslation();
|
||||
const isMobile = useIsMobile();
|
||||
const { type, url } = commentMediaInfo || {};
|
||||
@@ -141,21 +152,10 @@ const CommentMedia = ({ commentMediaInfo, isDeleted, isOutOfFeed, isReply, linkH
|
||||
return (
|
||||
<span className={styles.content}>
|
||||
<span className={`${showThumbnail ? styles.show : styles.hide} ${styles.thumbnail}`}>
|
||||
{url && (
|
||||
<Thumbnail
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
isDeleted={isDeleted}
|
||||
isOutOfFeed={isOutOfFeed}
|
||||
isReply={isReply}
|
||||
linkHeight={linkHeight}
|
||||
linkWidth={linkWidth}
|
||||
showThumbnail={showThumbnail}
|
||||
setShowThumbnail={setShowThumbnail}
|
||||
/>
|
||||
)}
|
||||
{url && <Thumbnail commentMediaInfo={commentMediaInfo} post={post} setShowThumbnail={setShowThumbnail} />}
|
||||
{isMobile && type && <div className={styles.fileInfo}>{getDisplayMediaInfoType(type, t)}</div>}
|
||||
</span>
|
||||
{!showThumbnail && <Media commentMediaInfo={commentMediaInfo} isReply={isReply} setShowThumbnail={setShowThumbnail} />}
|
||||
{!showThumbnail && <Media commentMediaInfo={commentMediaInfo} isReply={post?.parentCid} setShowThumbnail={setShowThumbnail} />}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -28,4 +28,14 @@
|
||||
.embedButton:hover {
|
||||
cursor: pointer;
|
||||
color: var(--button-desktop-text-color-hover);
|
||||
}
|
||||
|
||||
.spoiler {
|
||||
background-color: black;
|
||||
color: black;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.spoiler:hover {
|
||||
color: white;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import CommentMedia from '../comment-media';
|
||||
|
||||
interface MarkdownProps {
|
||||
content: string;
|
||||
spoiler?: boolean;
|
||||
}
|
||||
|
||||
const MAX_LENGTH_FOR_GFM = 10000; // remarkGfm lags with large content
|
||||
@@ -37,7 +38,7 @@ const blockquoteToGreentext = () => (tree: any) => {
|
||||
});
|
||||
};
|
||||
|
||||
const Markdown = ({ content }: MarkdownProps) => {
|
||||
const Markdown = ({ content, spoiler }: MarkdownProps) => {
|
||||
const remarkPlugins: any[] = [[supersub]];
|
||||
|
||||
if (content && content.length <= MAX_LENGTH_FOR_GFM) {
|
||||
@@ -68,6 +69,7 @@ const Markdown = ({ content }: MarkdownProps) => {
|
||||
remarkPlugins={remarkPlugins}
|
||||
rehypePlugins={[[rehypeSanitize, customSchema]]}
|
||||
components={{
|
||||
p: ({ children }) => <p className=''>{spoiler ? <span className={styles.spoiler}>{children}</span> : children}</p>,
|
||||
img: ({ src }) => <span>{src}</span>,
|
||||
video: ({ src }) => <span>{src}</span>,
|
||||
iframe: ({ src }) => <span>{src}</span>,
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './mod-menu';
|
||||
@@ -0,0 +1,84 @@
|
||||
.checkbox {
|
||||
display: inline-block;
|
||||
padding: 3px 7px 3px 4px;
|
||||
filter: var(--filter80);
|
||||
}
|
||||
|
||||
.button {
|
||||
color: var(--text-info);
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
padding: 0 4px 0 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal {
|
||||
z-index: 7;
|
||||
background-color: var(--challenge-modal-background-color);
|
||||
padding: 1px 0;
|
||||
padding-top: 2px;
|
||||
color: var(--text);
|
||||
border: var(--challenge-modal-border);
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.modal input[type="checkbox"] {
|
||||
margin-right: 3px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
margin: 0 3px;
|
||||
vertical-align: middle;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.menuItem {
|
||||
padding: 2px 3px 1px 3px;
|
||||
}
|
||||
|
||||
.menuItem label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menuReason {
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.menuItem input[type="text"] {
|
||||
padding: 2px;
|
||||
box-shadow: var(--box-shadow-input);
|
||||
margin-top: 2px;
|
||||
width: calc(100% - 6px);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.menuItem input[type="text"], .menuItem input[type='number'] {
|
||||
border: var(--post-form-field-input-border);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.menuItem input[type="text"]:focus, .menuItem input[type='number']:focus {
|
||||
border: var(--post-form-field-input-focus-border);
|
||||
}
|
||||
|
||||
.bottom {
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bottom button {
|
||||
text-transform: capitalize;
|
||||
cursor: pointer;
|
||||
padding: 2px 6px 3px;
|
||||
margin-left: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.optional {
|
||||
color: var(--text-info);
|
||||
}
|
||||
|
||||
@supports (-moz-appearance: none) {
|
||||
.banInput {
|
||||
width: 3.5em;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import { useState } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
|
||||
import { PublishCommentEditOptions, useComment, useEditedComment, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from './mod-menu.module.css';
|
||||
import { alertChallengeVerificationFailed } from '../../../lib/utils/challenge-utils';
|
||||
import useChallengesStore from '../../../stores/use-challenges-store';
|
||||
import _ from 'lodash';
|
||||
|
||||
const { addChallenge } = useChallengesStore.getState();
|
||||
|
||||
type ModMenuProps = {
|
||||
cid: string;
|
||||
isCommentAuthorMod?: boolean;
|
||||
};
|
||||
|
||||
const ModMenu = ({ cid, isCommentAuthorMod }: ModMenuProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
let post: any;
|
||||
const comment = useComment({ commentCid: cid });
|
||||
const { editedComment } = useEditedComment({ comment });
|
||||
if (editedComment) {
|
||||
post = editedComment;
|
||||
} else if (comment) {
|
||||
post = comment;
|
||||
}
|
||||
const isReply = post?.parentCid;
|
||||
const [isModMenuOpen, setIsModMenuOpen] = useState(false);
|
||||
|
||||
const defaultPublishOptions: PublishCommentEditOptions = {
|
||||
removed: post?.removed,
|
||||
locked: post?.locked,
|
||||
spoiler: post?.spoiler,
|
||||
pinned: post?.pinned,
|
||||
commentAuthor: { banExpiresAt: post?.banExpiresAt },
|
||||
commentCid: post?.cid,
|
||||
subplebbitAddress: post?.subplebbitAddress,
|
||||
onChallenge: (...args: any) => addChallenge([...args, post]),
|
||||
onChallengeVerification: alertChallengeVerificationFailed,
|
||||
onError: (error: Error) => {
|
||||
console.warn(error);
|
||||
alert(error.message);
|
||||
},
|
||||
};
|
||||
|
||||
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState(defaultPublishOptions);
|
||||
const { publishCommentEdit } = usePublishCommentEdit(publishCommentEditOptions);
|
||||
|
||||
const [banDuration, setBanDuration] = useState(1);
|
||||
|
||||
const daysToTimestampInSeconds = (days: number) => {
|
||||
const now = new Date();
|
||||
now.setDate(now.getDate() + days);
|
||||
return Math.floor(now.getTime() / 1000);
|
||||
};
|
||||
|
||||
const onCheckbox = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { id, checked } = e.target;
|
||||
if (id === 'banUser') {
|
||||
setPublishCommentEditOptions((state) => ({
|
||||
...state,
|
||||
commentAuthor: { ...state.commentAuthor, banExpiresAt: checked ? daysToTimestampInSeconds(banDuration) : undefined },
|
||||
}));
|
||||
} else {
|
||||
setPublishCommentEditOptions((state) => ({ ...state, [id]: checked }));
|
||||
}
|
||||
};
|
||||
|
||||
const onBanDurationChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const days = parseInt(e.target.value, 10) || 1;
|
||||
setBanDuration(days);
|
||||
setPublishCommentEditOptions((state) => ({
|
||||
...state,
|
||||
commentAuthor: { ...state.commentAuthor, banExpiresAt: daysToTimestampInSeconds(days) },
|
||||
}));
|
||||
};
|
||||
|
||||
const onReason = (e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setPublishCommentEditOptions((state) => ({ ...state, reason: e.target.value ? e.target.value : undefined }));
|
||||
|
||||
const { refs, floatingStyles, context } = useFloating({
|
||||
placement: 'bottom-start',
|
||||
open: isModMenuOpen,
|
||||
onOpenChange: setIsModMenuOpen,
|
||||
middleware: [offset(2), flip({ fallbackAxisSideDirection: 'end' }), shift()],
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const click = useClick(context);
|
||||
const dismiss = useDismiss(context);
|
||||
const role = useRole(context);
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]);
|
||||
|
||||
const headingId = useId();
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
await publishCommentEdit();
|
||||
setIsModMenuOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className={styles.checkbox} ref={refs.setReference} {...(cid && getReferenceProps())}>
|
||||
<input type='checkbox' onChange={() => cid && setIsModMenuOpen(!isModMenuOpen)} checked={isModMenuOpen} />
|
||||
</span>
|
||||
{isModMenuOpen && (
|
||||
<FloatingFocusManager context={context} modal={false}>
|
||||
<div className={styles.modal} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
|
||||
<div className={styles.ModMenu}>
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
[
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' />
|
||||
{_.capitalize(t('remove'))}? ]
|
||||
</label>
|
||||
</div>
|
||||
{!isReply && (
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' id='locked' />
|
||||
{_.capitalize(t('close_thread'))}?
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' id='spoiler' />
|
||||
{_.capitalize(t('spoiler'))}?
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' id='pinned' />
|
||||
{_.capitalize(t('sticky'))}?
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
{!isCommentAuthorMod && (
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={!!publishCommentEditOptions.commentAuthor?.banExpiresAt} type='checkbox' id='banUser' />
|
||||
<Trans
|
||||
i18nKey='ban_user_for'
|
||||
shouldUnescape={true}
|
||||
components={{ 1: <input className={styles.banInput} onChange={onBanDurationChange} type='number' min={1} max={100} defaultValue={banDuration} /> }}
|
||||
/>
|
||||
?
|
||||
</label>
|
||||
]
|
||||
</div>
|
||||
)}
|
||||
<div className={`${styles.menuItem} ${styles.menuReason}`}>
|
||||
{_.capitalize(t('reason'))}?
|
||||
<input type='text' onChange={onReason} defaultValue={post?.reason} size={14} />
|
||||
</div>
|
||||
<div className={styles.bottom}>
|
||||
<button onClick={handleSaveClick}>{t('save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FloatingFocusManager>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModMenu;
|
||||
|
||||
@@ -19,6 +19,7 @@ import Markdown from '../../markdown';
|
||||
import PostMenuDesktop from './post-menu-desktop/';
|
||||
import { PostProps } from '../post';
|
||||
import _ from 'lodash';
|
||||
import ModMenu from '../mod-menu';
|
||||
|
||||
const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -44,11 +45,7 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
|
||||
|
||||
return (
|
||||
<div className={styles.postInfo}>
|
||||
{!isHidden && (
|
||||
<span className={styles.checkbox}>
|
||||
<input type='checkbox' />
|
||||
</span>
|
||||
)}
|
||||
{!isHidden && <ModMenu cid={cid} />}
|
||||
{title && <span className={styles.subject}>{displayTitle} </span>}
|
||||
<span className={styles.nameBlock}>
|
||||
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>
|
||||
@@ -111,16 +108,12 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
|
||||
|
||||
const PostMedia = ({ post }: PostProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { deleted, link, linkHeight, linkWidth, parentCid, removed } = post || {};
|
||||
const { isDescription, isRules } = post || {}; // custom properties, not from api
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const { type, url } = commentMediaInfo || {};
|
||||
const embedUrl = url && new URL(url);
|
||||
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
|
||||
const hasThumbnail = getHasThumbnail(commentMediaInfo, post?.link);
|
||||
const [showThumbnail, setShowThumbnail] = useState(true);
|
||||
|
||||
const isReply = parentCid;
|
||||
|
||||
return (
|
||||
<div className={styles.file}>
|
||||
<div className={styles.fileText}>
|
||||
@@ -152,16 +145,7 @@ const PostMedia = ({ post }: PostProps) => {
|
||||
</div>
|
||||
{(hasThumbnail || (!hasThumbnail && !showThumbnail)) && (
|
||||
<div className={styles.fileThumbnail}>
|
||||
<CommentMedia
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
|
||||
isDeleted={removed || deleted}
|
||||
isReply={isReply}
|
||||
linkHeight={linkHeight}
|
||||
linkWidth={linkWidth}
|
||||
showThumbnail={showThumbnail}
|
||||
setShowThumbnail={setShowThumbnail}
|
||||
/>
|
||||
<CommentMedia commentMediaInfo={commentMediaInfo} post={post} showThumbnail={showThumbnail} setShowThumbnail={setShowThumbnail} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -169,7 +153,7 @@ const PostMedia = ({ post }: PostProps) => {
|
||||
};
|
||||
|
||||
const PostMessage = ({ post }: PostProps) => {
|
||||
const { cid, content, deleted, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {};
|
||||
const { cid, content, deleted, parentCid, postCid, reason, removed, spoiler, state, subplebbitAddress } = post || {};
|
||||
const { t } = useTranslation();
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
@@ -201,7 +185,7 @@ const PostMessage = ({ post }: PostProps) => {
|
||||
) : deleted ? (
|
||||
<span className={styles.removedContent}>{t('user_deleted_this_post')}</span>
|
||||
) : (
|
||||
<Markdown content={displayContent} />
|
||||
<Markdown content={displayContent} spoiler={spoiler} />
|
||||
)}
|
||||
{(removed || deleted) && reason && (
|
||||
<span>
|
||||
|
||||
@@ -19,7 +19,7 @@ import _ from 'lodash';
|
||||
|
||||
const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { author, cid, deleted, link, linkHeight, linkWidth, locked, parentCid, pinned, removed, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
|
||||
const { author, cid, link, locked, parentCid, pinned, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
|
||||
const { isDescription, isRules } = post || {}; // custom properties, not from api
|
||||
const { address, displayName, shortAddress } = author || {};
|
||||
|
||||
@@ -94,18 +94,7 @@ const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => {
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
{(hasThumbnail || link) && (
|
||||
<CommentMedia
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
|
||||
isDeleted={removed || deleted}
|
||||
isReply={isReply}
|
||||
linkHeight={linkHeight}
|
||||
linkWidth={linkWidth}
|
||||
showThumbnail={showThumbnail}
|
||||
setShowThumbnail={setShowThumbnail}
|
||||
/>
|
||||
)}
|
||||
{(hasThumbnail || link) && <CommentMedia commentMediaInfo={commentMediaInfo} post={post} showThumbnail={showThumbnail} setShowThumbnail={setShowThumbnail} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -61,12 +61,6 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.postDesktop .checkbox, .replyDesktop .checkbox {
|
||||
display: inline-block;
|
||||
padding: 3px 7px 3px 4px;
|
||||
filter: var(--filter80);
|
||||
}
|
||||
|
||||
.postDesktop .subject {
|
||||
color: var(--post-subject-text-color);
|
||||
font-weight: var(--post-subject-font-weight);
|
||||
|
||||
@@ -2,16 +2,18 @@
|
||||
.boardNavDesktop {
|
||||
font-size: var(--topbar-font-size);
|
||||
color: var(--topbar-separator-color);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.boardNavDesktop a {
|
||||
.boardNavDesktop a, .navTopRight span {
|
||||
color: var(--topbar-desktop-link-text-color);
|
||||
text-decoration: var(--topbar-desktop-link-text-decoration);
|
||||
}
|
||||
|
||||
.boardNavDesktop a:hover {
|
||||
.boardNavDesktop a:hover, .navTopRight span:hover {
|
||||
color: var(--topbar-desktop-link-text-color-hover);
|
||||
text-decoration: var(--topbar-desktop-link-text-decoration-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navTopRight {
|
||||
@@ -19,6 +21,24 @@
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.searchBar {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
padding: 3px 5px 0 0;
|
||||
}
|
||||
|
||||
.boardNavDesktop .searchBar {
|
||||
margin-right: -7px;
|
||||
}
|
||||
|
||||
.searchBar input[type="text"] {
|
||||
outline: none;
|
||||
margin: 2px;
|
||||
padding: 1px;
|
||||
border: 1px solid #000;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.boardNavMobile {
|
||||
padding: 2px 4px;
|
||||
background-color: var(--topbar-mobile-background-color);
|
||||
@@ -32,11 +52,15 @@
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.boardNavMobile .pageJump a {
|
||||
.boardNavMobile .pageJump a, .boardNavMobile .pageJump span {
|
||||
color: var(--topbar-mobile-button-color);
|
||||
text-decoration: var(--button-text-decoration-mobile);
|
||||
}
|
||||
|
||||
.pageJump {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.boardNavMobile strong {
|
||||
text-transform: capitalize;
|
||||
padding-right: 5px;
|
||||
@@ -55,11 +79,10 @@
|
||||
padding: 3px 5px 0 0;
|
||||
}
|
||||
|
||||
.pageJump a, .mobileSearchButton {
|
||||
.pageJump a, .pageJump span {
|
||||
padding-right: 5px;
|
||||
color: var(--homepage-box-link-text-color);
|
||||
text-decoration: var(--homepage-box-link-text-decoration);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
|
||||
@@ -1,17 +1,63 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isAllView, isCatalogView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||
import styles from './topbar.module.css';
|
||||
import useDefaultSubplebbits, { categorizeSubplebbits, useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import { debounce } from 'lodash';
|
||||
import _, { debounce } from 'lodash';
|
||||
|
||||
const SearchBar = ({ setShowSearchBar }: { setShowSearchBar: (show: boolean) => void }) => {
|
||||
const navigate = useNavigate();
|
||||
const searchBarRef = useRef<HTMLDivElement>(null);
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
const placeholder = `"community.eth/.sol" / "12D3KooW..."`;
|
||||
|
||||
useEffect(() => {
|
||||
searchInputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const handleClickOutside = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
if (searchBarRef.current && !searchBarRef.current.contains(event.target as Node)) {
|
||||
setShowSearchBar(false);
|
||||
}
|
||||
},
|
||||
[searchBarRef, setShowSearchBar],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [handleClickOutside]);
|
||||
|
||||
const handleSearchSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const searchInput = searchInputRef.current?.value;
|
||||
if (searchInput) {
|
||||
searchInputRef.current.value = '';
|
||||
navigate(`/p/${searchInput}`);
|
||||
setShowSearchBar(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.searchBar} ref={searchBarRef}>
|
||||
<form onSubmit={handleSearchSubmit}>
|
||||
<input type='text' autoCorrect='off' autoComplete='off' spellCheck='false' autoCapitalize='off' placeholder={placeholder} ref={searchInputRef} />
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TopBarDesktop = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const isInCatalogView = isCatalogView(location.pathname);
|
||||
const subplebbits = useDefaultSubplebbits();
|
||||
const [showSearchBar, setShowSearchBar] = useState(false);
|
||||
|
||||
const { plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs } = categorizeSubplebbits(subplebbits);
|
||||
|
||||
@@ -33,8 +79,9 @@ const TopBarDesktop = () => {
|
||||
</span>
|
||||
<span className={styles.navTopRight}>
|
||||
[<Link to={!location.pathname.endsWith('settings') ? location.pathname.replace(/\/$/, '') + '/settings' : location.pathname}>{t('settings')}</Link>] [
|
||||
<Link to='/'>{t('home')}</Link>]
|
||||
<span onClick={() => setShowSearchBar(!showSearchBar)}>{t('search')}</span>] [<Link to='/'>{t('home')}</Link>]
|
||||
</span>
|
||||
{showSearchBar && <SearchBar setShowSearchBar={setShowSearchBar} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -44,6 +91,7 @@ const TopBarMobile = ({ subplebbitAddress }: { subplebbitAddress: string }) => {
|
||||
const navigate = useNavigate();
|
||||
const subplebbitAddresses = useDefaultSubplebbitAddresses();
|
||||
const displaySubplebbitAddress = subplebbitAddress && subplebbitAddress.length > 30 ? subplebbitAddress.slice(0, 30).concat('...') : subplebbitAddress;
|
||||
const [showSearchBar, setShowSearchBar] = useState(false);
|
||||
|
||||
const currentSubplebbitIsInList = subplebbitAddresses.some((address: string) => address === subplebbitAddress);
|
||||
|
||||
@@ -95,7 +143,9 @@ const TopBarMobile = ({ subplebbitAddress }: { subplebbitAddress: string }) => {
|
||||
</div>
|
||||
<div className={styles.pageJump}>
|
||||
<Link to={useLocation().pathname.replace(/\/$/, '') + '/settings'}>{t('settings')}</Link>
|
||||
<span onClick={() => setShowSearchBar(!showSearchBar)}>{_.capitalize(t('search'))}</span>
|
||||
<Link to='/'>{t('home')}</Link>
|
||||
{showSearchBar && <SearchBar setShowSearchBar={setShowSearchBar} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,12 +6,20 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
|
||||
const [popularPosts, setPopularPosts] = useState<Comment[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const subplebbitToPost: { [key: string]: any } = {};
|
||||
const uniqueLinks: Set<string> = new Set();
|
||||
const allPosts: Comment[] = [];
|
||||
|
||||
let postsPerSub = 1;
|
||||
if (subplebbits.length == 2) {
|
||||
postsPerSub = 4;
|
||||
} else if (subplebbits.length == 3) {
|
||||
postsPerSub = 3;
|
||||
} else if (subplebbits.length >= 4 && subplebbits.length < 8) {
|
||||
postsPerSub = 2;
|
||||
}
|
||||
|
||||
subplebbits.forEach((subplebbit: any) => {
|
||||
let maxTimestamp = -Infinity;
|
||||
let mostRecentPost = null;
|
||||
let subplebbitPosts: Comment[] = [];
|
||||
|
||||
if (subplebbit?.posts?.pages?.hot?.comments) {
|
||||
for (const post of Object.values(subplebbit.posts.pages.hot.comments as Comment)) {
|
||||
@@ -21,32 +29,27 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
|
||||
|
||||
if (
|
||||
isMediaShowed &&
|
||||
replyCount > 0 &&
|
||||
(replyCount > 0 || postsPerSub > 1) &&
|
||||
!deleted &&
|
||||
!removed &&
|
||||
!locked &&
|
||||
!pinned &&
|
||||
timestamp > Date.now() / 1000 - 60 * 60 * 24 * 30 &&
|
||||
timestamp > maxTimestamp &&
|
||||
!uniqueLinks.has(link)
|
||||
) {
|
||||
maxTimestamp = post.timestamp;
|
||||
mostRecentPost = post;
|
||||
subplebbitPosts.push(post);
|
||||
uniqueLinks.add(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (mostRecentPost) {
|
||||
subplebbitToPost[subplebbit.address] = { post: mostRecentPost, timestamp: maxTimestamp };
|
||||
}
|
||||
subplebbitPosts.sort((a: any, b: any) => b.timestamp - a.timestamp);
|
||||
allPosts.push(...subplebbitPosts.slice(0, postsPerSub));
|
||||
}
|
||||
});
|
||||
|
||||
const sortedPosts = Object.values(subplebbitToPost)
|
||||
.sort((a, b) => b.timestamp - a.timestamp)
|
||||
.slice(0, 8);
|
||||
const sortedPosts = allPosts.sort((a: any, b: any) => b.timestamp - a.timestamp).slice(0, 8);
|
||||
|
||||
setPopularPosts(sortedPosts.map((item) => item.post));
|
||||
setPopularPosts(sortedPosts);
|
||||
}, [subplebbits]);
|
||||
|
||||
return popularPosts;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface HomeFiltersStore {
|
||||
showNsfwBoardsOnly: boolean;
|
||||
setShowNsfwBoardsOnly: (value: boolean) => void;
|
||||
showWorksafeBoardsOnly: boolean;
|
||||
setShowWorksafeBoardsOnly: (value: boolean) => void;
|
||||
useCatalog: boolean;
|
||||
setUseCatalog: (value: boolean) => void;
|
||||
showWorksafeContentOnly: boolean;
|
||||
setShowWorksafeContentOnly: (value: boolean) => void;
|
||||
showNsfwContentOnly: boolean;
|
||||
setShowNsfwContentOnly: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const useHomeFiltersStore = create<HomeFiltersStore>((set) => ({
|
||||
showNsfwBoardsOnly: localStorage.getItem('showNsfwBoardsOnly') === 'true' ? true : false,
|
||||
setShowNsfwBoardsOnly: (value: boolean) => {
|
||||
set({ showNsfwBoardsOnly: value });
|
||||
localStorage.setItem('showNsfwBoardsOnly', value.toString());
|
||||
},
|
||||
showWorksafeBoardsOnly: localStorage.getItem('showWorksafeBoardsOnly') === 'true' ? true : false,
|
||||
setShowWorksafeBoardsOnly: (value: boolean) => {
|
||||
set({ showWorksafeBoardsOnly: value });
|
||||
localStorage.setItem('showWorksafeBoardsOnly', value.toString());
|
||||
},
|
||||
useCatalog: localStorage.getItem('useCatalog') === 'true' ? true : false,
|
||||
setUseCatalog: (value: boolean) => {
|
||||
set({ useCatalog: value });
|
||||
localStorage.setItem('useCatalog', value.toString());
|
||||
},
|
||||
showWorksafeContentOnly: localStorage.getItem('showWorksafeContentOnly') === 'true' ? true : false,
|
||||
setShowWorksafeContentOnly: (value: boolean) => {
|
||||
set({ showWorksafeContentOnly: value });
|
||||
localStorage.setItem('showWorksafeContentOnly', value.toString());
|
||||
},
|
||||
showNsfwContentOnly: localStorage.getItem('showNsfwContentOnly') === 'true' ? true : false,
|
||||
setShowNsfwContentOnly: (value: boolean) => {
|
||||
set({ showNsfwContentOnly: value });
|
||||
localStorage.setItem('showNsfwContentOnly', value.toString());
|
||||
},
|
||||
}));
|
||||
|
||||
export default useHomeFiltersStore;
|
||||
@@ -49,7 +49,7 @@ const Board = () => {
|
||||
setResetFunction(reset);
|
||||
}, [reset, setResetFunction]);
|
||||
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const { subplebbit, error } = useSubplebbit({ subplebbitAddress });
|
||||
const { createdAt, description, rules, shortAddress, state, suggested } = subplebbit || {};
|
||||
const title = isInAllView ? t('all') : isInSubscriptionsView ? t('subscriptions') : subplebbit?.title;
|
||||
|
||||
@@ -65,6 +65,12 @@ const Board = () => {
|
||||
) : (
|
||||
<LoadingEllipsis string={loadingStateString} />
|
||||
)}
|
||||
{error && (
|
||||
<div style={{ color: 'red' }}>
|
||||
<br />
|
||||
{error.message}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -96,8 +102,8 @@ const Board = () => {
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[location.pathname];
|
||||
|
||||
useEffect(() => {
|
||||
document.title = title ? title : shortAddress;
|
||||
}, [title, shortAddress]);
|
||||
document.title = title ? title : shortAddress || subplebbitAddress;
|
||||
}, [title, shortAddress, subplebbitAddress]);
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Subplebbit, useAccount, useAccountSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import useHomeFiltersStore from '../../../stores/use-home-filters';
|
||||
import { useMultisubMetadata } from '../../../hooks/use-default-subplebbits';
|
||||
import styles from '../home.module.css';
|
||||
import { nsfwTags } from '../home';
|
||||
|
||||
const BoxModal = ({ isBoardsBoxModal }: { isBoardsBoxModal: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const [showFilterModal, setShowFilterModal] = useState(false);
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const {
|
||||
showNsfwBoardsOnly,
|
||||
setShowNsfwBoardsOnly,
|
||||
showWorksafeBoardsOnly,
|
||||
setShowWorksafeBoardsOnly,
|
||||
useCatalog,
|
||||
setUseCatalog,
|
||||
showWorksafeContentOnly,
|
||||
setShowWorksafeContentOnly,
|
||||
showNsfwContentOnly,
|
||||
setShowNsfwContentOnly,
|
||||
} = useHomeFiltersStore();
|
||||
|
||||
const handleClickOutside = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
|
||||
setShowFilterModal(false);
|
||||
}
|
||||
},
|
||||
[modalRef, setShowFilterModal],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [handleClickOutside]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span ref={modalRef} onClick={() => setShowFilterModal(true)}>
|
||||
{isBoardsBoxModal ? t('filter') : t('options')} ▼
|
||||
</span>
|
||||
{showFilterModal && (
|
||||
<div ref={modalRef} className={styles.filterModal}>
|
||||
{isBoardsBoxModal ? (
|
||||
<>
|
||||
<div
|
||||
className={`${styles.option} ${!showNsfwBoardsOnly && !showWorksafeBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
setShowNsfwBoardsOnly(false);
|
||||
setShowWorksafeBoardsOnly(false);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show All Boards
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showNsfwBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showWorksafeBoardsOnly) {
|
||||
setShowWorksafeBoardsOnly(false);
|
||||
}
|
||||
setShowNsfwBoardsOnly(!showNsfwBoardsOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show NSFW Boards Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showWorksafeBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showNsfwBoardsOnly) {
|
||||
setShowNsfwBoardsOnly(false);
|
||||
}
|
||||
setShowWorksafeBoardsOnly(!showWorksafeBoardsOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show Worksafe Boards Only
|
||||
</div>
|
||||
<div className={styles.separator} />
|
||||
<div
|
||||
className={`${styles.option} ${useCatalog && styles.selected}`}
|
||||
onClick={() => {
|
||||
setUseCatalog(!useCatalog);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Use Catalog
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className={`${styles.option} ${showWorksafeContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showNsfwContentOnly) {
|
||||
setShowNsfwContentOnly(false);
|
||||
}
|
||||
setShowWorksafeContentOnly(!showWorksafeContentOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show Worksafe Content Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showNsfwContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showWorksafeContentOnly) {
|
||||
setShowWorksafeContentOnly(false);
|
||||
}
|
||||
setShowNsfwContentOnly(!showNsfwContentOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show NSFW Content Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${!showWorksafeContentOnly && !showNsfwContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
setShowWorksafeContentOnly(false);
|
||||
setShowNsfwContentOnly(false);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show All Content
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Board = ({ isOffline, subplebbit }: { isOffline: boolean; subplebbit: Subplebbit }) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, title, tags } = subplebbit || {};
|
||||
const nsfwTag = tags.find((tag: string) => nsfwTags.includes(tag));
|
||||
const { useCatalog } = useHomeFiltersStore();
|
||||
|
||||
const boardLink = useCatalog ? `/p/${address}/catalog` : `/p/${address}`;
|
||||
|
||||
return (
|
||||
<div className={styles.subplebbit} key={address}>
|
||||
{isOffline && <span className={styles.offlineIcon} />}
|
||||
<Link to={boardLink}>{title || address}</Link>
|
||||
{nsfwTag && <span className={styles.nsfw}> ({t(nsfwTag)})</span>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const BoardsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const subscriptions = account?.subscriptions || [];
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
const { showNsfwBoardsOnly, showWorksafeBoardsOnly } = useHomeFiltersStore();
|
||||
|
||||
const filterSubs = (subs: Subplebbit[], includeTags: string[], excludeTags: string[] = []) =>
|
||||
subs.filter((sub) => includeTags.every((tag) => sub.tags?.includes(tag)) && excludeTags.every((tag) => !sub.tags?.includes(tag)));
|
||||
|
||||
let plebbitSubs = filterSubs(multisub, ['plebbit']);
|
||||
let interestsSubs = filterSubs(multisub, ['topic'], ['plebbit', 'country', 'international']);
|
||||
let randomSubs = filterSubs(multisub, ['random'], ['plebbit']);
|
||||
let internationalSubs = filterSubs(multisub, ['international']);
|
||||
let projectsSubs = filterSubs(multisub, ['project'], ['plebbit', 'topic']);
|
||||
|
||||
const filterByNsfw = (subs: Subplebbit[], includeNsfw: boolean) => subs.filter((sub) => sub.tags.some((tag: string) => nsfwTags.includes(tag)) === includeNsfw);
|
||||
|
||||
const filterCategoriesByNsfw = (subsArray: Subplebbit[][], includeNsfw: boolean) => subsArray.map((subs) => filterByNsfw(subs, includeNsfw));
|
||||
|
||||
const includeNsfw = showNsfwBoardsOnly ? true : showWorksafeBoardsOnly ? false : null;
|
||||
|
||||
if (includeNsfw !== null) {
|
||||
[plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs] = filterCategoriesByNsfw(
|
||||
[plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs],
|
||||
includeNsfw,
|
||||
);
|
||||
}
|
||||
|
||||
const isSubOffline = (address: string) => {
|
||||
const subplebbit = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address);
|
||||
const isOffline = subplebbit?.updatedAt && subplebbit.updatedAt < Date.now() / 1000 - 60 * 60;
|
||||
return isOffline;
|
||||
};
|
||||
const multisubMetadata = useMultisubMetadata();
|
||||
|
||||
return (
|
||||
<div className={`${styles.box} ${styles.boardsBox}`}>
|
||||
<div className={styles.boxBar}>
|
||||
<h2 className={styles.capitalize}>{t('boards')}</h2>
|
||||
<BoxModal isBoardsBoxModal={true} />
|
||||
</div>
|
||||
<div className={styles.boardsBoxContent}>
|
||||
<div className={styles.column}>
|
||||
<h3>Multiboards</h3>
|
||||
<div className={styles.list}>
|
||||
<div className={styles.subplebbit}>
|
||||
<Link to='/p/all'>{multisubMetadata?.title || 'All'}</Link>
|
||||
</div>
|
||||
<div className={styles.subplebbit}>
|
||||
<Link to='/p/subscriptions'>Subscriptions</Link>
|
||||
</div>
|
||||
</div>
|
||||
{plebbitSubs.length > 0 && (
|
||||
<>
|
||||
<h3>Plebbit</h3>
|
||||
<div className={styles.list}>
|
||||
{plebbitSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{projectsSubs.length > 0 && (
|
||||
<>
|
||||
<h3>{t('projects')}</h3>
|
||||
<div className={styles.list}>
|
||||
{projectsSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
{interestsSubs.length > 0 && (
|
||||
<>
|
||||
<h3>{t('interests')}</h3>
|
||||
<div className={styles.list}>
|
||||
{interestsSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
{randomSubs.length > 0 && (
|
||||
<>
|
||||
<h3>{t('random')}</h3>
|
||||
<div className={styles.list}>
|
||||
{randomSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{internationalSubs.length > 0 && (
|
||||
<>
|
||||
<h3>{t('international')}</h3>
|
||||
<div className={styles.list}>
|
||||
{internationalSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.list}>
|
||||
<h3>{t('subscriptions')}</h3>
|
||||
{subscriptions.length > 0
|
||||
? subscriptions.map((address: string, index: number) => (
|
||||
<div className={styles.subplebbit} key={index}>
|
||||
<Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
|
||||
</div>
|
||||
))
|
||||
: t('not_subscribed')}
|
||||
</div>
|
||||
<div className={styles.list}>
|
||||
<h3>{t('moderating')}</h3>
|
||||
{accountSubplebbitAddresses.length > 0
|
||||
? accountSubplebbitAddresses.map((address: string, index: number) => (
|
||||
<div className={styles.subplebbit} key={index}>
|
||||
<Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
|
||||
</div>
|
||||
))
|
||||
: t('not_moderating')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoardsBox;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './boards-box';
|
||||
@@ -0,0 +1,138 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import useHomeFiltersStore from '../../../stores/use-home-filters';
|
||||
import styles from '../home.module.css';
|
||||
|
||||
const BoxModal = ({ isBoardsBoxModal }: { isBoardsBoxModal: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const [showFilterModal, setShowFilterModal] = useState(false);
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const {
|
||||
showNsfwBoardsOnly,
|
||||
setShowNsfwBoardsOnly,
|
||||
showWorksafeBoardsOnly,
|
||||
setShowWorksafeBoardsOnly,
|
||||
useCatalog,
|
||||
setUseCatalog,
|
||||
showWorksafeContentOnly,
|
||||
setShowWorksafeContentOnly,
|
||||
showNsfwContentOnly,
|
||||
setShowNsfwContentOnly,
|
||||
} = useHomeFiltersStore();
|
||||
|
||||
const handleClickOutside = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
|
||||
setShowFilterModal(false);
|
||||
}
|
||||
},
|
||||
[modalRef, setShowFilterModal],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, [handleClickOutside]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span ref={modalRef} onClick={() => setShowFilterModal(true)}>
|
||||
{isBoardsBoxModal ? t('filter') : t('options')} ▼
|
||||
</span>
|
||||
{showFilterModal && (
|
||||
<div ref={modalRef} className={styles.filterModal}>
|
||||
{isBoardsBoxModal ? (
|
||||
<>
|
||||
<div
|
||||
className={`${styles.option} ${!showNsfwBoardsOnly && !showWorksafeBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
setShowNsfwBoardsOnly(false);
|
||||
setShowWorksafeBoardsOnly(false);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show All Boards
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showNsfwBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showWorksafeBoardsOnly) {
|
||||
setShowWorksafeBoardsOnly(false);
|
||||
}
|
||||
setShowNsfwBoardsOnly(!showNsfwBoardsOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show NSFW Boards Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showWorksafeBoardsOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showNsfwBoardsOnly) {
|
||||
setShowNsfwBoardsOnly(false);
|
||||
}
|
||||
setShowWorksafeBoardsOnly(!showWorksafeBoardsOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show Worksafe Boards Only
|
||||
</div>
|
||||
<div className={styles.separator} />
|
||||
<div
|
||||
className={`${styles.option} ${useCatalog && styles.selected}`}
|
||||
onClick={() => {
|
||||
setUseCatalog(!useCatalog);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Use Catalog
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
className={`${styles.option} ${showWorksafeContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showNsfwContentOnly) {
|
||||
setShowNsfwContentOnly(false);
|
||||
}
|
||||
setShowWorksafeContentOnly(!showWorksafeContentOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show Worksafe Content Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${showNsfwContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
if (showWorksafeContentOnly) {
|
||||
setShowWorksafeContentOnly(false);
|
||||
}
|
||||
setShowNsfwContentOnly(!showNsfwContentOnly);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show NSFW Content Only
|
||||
</div>
|
||||
<div
|
||||
className={`${styles.option} ${!showWorksafeContentOnly && !showNsfwContentOnly && styles.selected}`}
|
||||
onClick={() => {
|
||||
setShowWorksafeContentOnly(false);
|
||||
setShowNsfwContentOnly(false);
|
||||
setShowFilterModal(false);
|
||||
}}
|
||||
>
|
||||
Show All Content
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default BoxModal;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './box-modal';
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
.boardsBox {
|
||||
overflow: hidden;
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.boxBar, .infoboxBar {
|
||||
@@ -79,7 +80,7 @@
|
||||
color: var(--homepage-infobox-link-text-color);
|
||||
}
|
||||
|
||||
.searchBar {
|
||||
.searchBar form {
|
||||
display: flex;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
@@ -104,7 +105,7 @@
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
.searchBar button {
|
||||
.searchButton {
|
||||
margin-left: 4px;
|
||||
padding: 3px 5px;
|
||||
display: inline-block;
|
||||
@@ -112,6 +113,41 @@
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filterModal {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 5px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: right;
|
||||
background: #fff;
|
||||
border: 1px solid gray;
|
||||
box-shadow: 2px 2px 0 1px rgba(0, 0, 0, .1);
|
||||
padding: 4px 0;
|
||||
line-height: 1.7em;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.filterModal .separator {
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 6px 0 4px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.filterModal .option {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.filterModal .option:hover {
|
||||
background-color: #fca;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.filterModal .selected::before {
|
||||
content: '✔ ';
|
||||
}
|
||||
|
||||
.capitalize {
|
||||
|
||||
+24
-204
@@ -1,23 +1,17 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import styles from './home.module.css';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Comment, Subplebbit, useAccount, useAccountSubplebbits, useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import { useSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from './home.module.css';
|
||||
import packageJson from '../../../package.json';
|
||||
import useDefaultSubplebbits, { useMultisubMetadata, useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import usePopularPosts from '../../hooks/use-popular-posts';
|
||||
import useDefaultSubplebbits, { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import useSubplebbitsStats from '../../hooks/use-subplebbits-stats';
|
||||
import { getCommentMediaInfo } from '../../lib/utils/media-utils';
|
||||
import { CatalogPostMedia } from '../../components/catalog-row';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import PopularThreadsBox from './popular-threads-box';
|
||||
import BoardsBox from './boards-box';
|
||||
|
||||
const isValidAddress = (address: string): boolean => {
|
||||
if (address.includes('/') || address.includes('\\') || address.includes(' ')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// https://github.com/plebbit/temporary-default-subplebbits/blob/master/README.md
|
||||
export const nsfwTags = ['adult', 'anti', 'gore'];
|
||||
|
||||
const SearchBar = () => {
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
@@ -25,32 +19,26 @@ const SearchBar = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSearchSubmit = () => {
|
||||
const inputValue = searchInputRef.current?.value;
|
||||
if (inputValue && isValidAddress(inputValue)) {
|
||||
navigate(`/p/${inputValue}`);
|
||||
} else {
|
||||
alert('invalid address');
|
||||
const searchInput = searchInputRef.current?.value;
|
||||
if (searchInput) {
|
||||
navigate(`/p/${searchInput}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.searchBar}>
|
||||
<input
|
||||
autoCorrect='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
autoCapitalize='off'
|
||||
type='text'
|
||||
placeholder={`"board.eth/.sol" ${t('or')} "12D3KooW..."`}
|
||||
ref={searchInputRef}
|
||||
onSubmit={handleSearchSubmit}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
handleSearchSubmit();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button onClick={handleSearchSubmit}>{t('go')}</button>
|
||||
<form onSubmit={handleSearchSubmit}>
|
||||
<input
|
||||
autoCorrect='off'
|
||||
autoComplete='off'
|
||||
spellCheck='false'
|
||||
autoCapitalize='off'
|
||||
type='text'
|
||||
placeholder={`"board.eth/.sol" ${t('or')} "12D3KooW..."`}
|
||||
ref={searchInputRef}
|
||||
/>
|
||||
<button className={styles.searchButton}>{t('go')}</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -72,171 +60,6 @@ const InfoBox = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Board = ({ isOffline, subplebbit }: { isOffline: boolean; subplebbit: Subplebbit }) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, title, tags } = subplebbit || {};
|
||||
const nsfwTags = ['adult', 'gore'];
|
||||
const nsfwTag = tags.find((tag: string) => nsfwTags.includes(tag));
|
||||
|
||||
return (
|
||||
<div className={styles.subplebbit} key={address}>
|
||||
{isOffline && <span className={styles.offlineIcon} />}
|
||||
<Link to={`/p/${address}`}>{title || address}</Link>
|
||||
{nsfwTag && <span className={styles.nsfw}> ({t(nsfwTag)})</span>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Boards = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const subscriptions = account?.subscriptions || [];
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
|
||||
const plebbitSubs = multisub.filter((sub) => sub.tags?.includes('plebbit'));
|
||||
const interestsSubs = multisub.filter(
|
||||
(sub) => sub.tags?.includes('topic') && !sub.tags?.includes('plebbit') && !sub.tags?.includes('country') && !sub.tags?.includes('international'),
|
||||
);
|
||||
const randomSubs = multisub.filter((sub) => sub.tags?.includes('random') && !sub.tags?.includes('plebbit'));
|
||||
const internationalSubs = multisub.filter((sub) => sub.tags?.includes('international') || sub.tags?.includes('country'));
|
||||
const projectsSubs = multisub.filter((sub) => sub.tags?.includes('project') && !sub.tags?.includes('plebbit') && !sub.tags?.includes('topic'));
|
||||
|
||||
const isSubOffline = (address: string) => {
|
||||
const subplebbit = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address);
|
||||
const isOffline = subplebbit?.updatedAt && subplebbit.updatedAt < Date.now() / 1000 - 60 * 60;
|
||||
return isOffline;
|
||||
};
|
||||
const multisubMetadata = useMultisubMetadata();
|
||||
|
||||
return (
|
||||
<div className={`${styles.box} ${styles.boardsBox}`}>
|
||||
<div className={styles.boxBar}>
|
||||
<h2 className={styles.capitalize}>{t('boards')}</h2>
|
||||
<span>{t('options')} ▼</span>
|
||||
</div>
|
||||
<div className={styles.boardsBoxContent}>
|
||||
<div className={styles.column}>
|
||||
<h3>Multiboards</h3>
|
||||
<div className={styles.list}>
|
||||
<div className={styles.subplebbit}>
|
||||
<Link to='/p/all'>{multisubMetadata?.title || 'All'}</Link>
|
||||
</div>
|
||||
<div className={styles.subplebbit}>
|
||||
<Link to='/p/subscriptions'>Subscriptions</Link>
|
||||
</div>
|
||||
</div>
|
||||
<h3>Plebbit</h3>
|
||||
<div className={styles.list}>
|
||||
{plebbitSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
<h3>{t('projects')}</h3>
|
||||
<div className={styles.list}>
|
||||
{projectsSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<h3>{t('interests')}</h3>
|
||||
<div className={styles.list}>
|
||||
{interestsSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<h3>{t('random')}</h3>
|
||||
<div className={styles.list}>
|
||||
{randomSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
<h3>{t('international')}</h3>
|
||||
<div className={styles.list}>
|
||||
{internationalSubs.map((sub) => (
|
||||
<Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.list}>
|
||||
<h3>{t('subscriptions')}</h3>
|
||||
{subscriptions.length > 0
|
||||
? subscriptions.map((address: string, index: number) => (
|
||||
<div className={styles.subplebbit} key={index}>
|
||||
<Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
|
||||
</div>
|
||||
))
|
||||
: t('not_subscribed')}
|
||||
</div>
|
||||
<div className={styles.list}>
|
||||
<h3>{t('moderating')}</h3>
|
||||
{accountSubplebbitAddresses.length > 0
|
||||
? accountSubplebbitAddresses.map((address: string, index: number) => (
|
||||
<div className={styles.subplebbit} key={index}>
|
||||
<Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
|
||||
</div>
|
||||
))
|
||||
: t('not_moderating')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface PopularThreadProps {
|
||||
post: Comment;
|
||||
boardTitle: string | undefined;
|
||||
boardShortAddress: string;
|
||||
}
|
||||
|
||||
const PopularThreadCard = ({ post, boardTitle, boardShortAddress }: PopularThreadProps) => {
|
||||
const { cid, content, subplebbitAddress, title } = post || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
|
||||
return (
|
||||
<div className={styles.popularThread} key={cid}>
|
||||
<div className={styles.title}>{boardTitle || boardShortAddress}</div>
|
||||
<div className={styles.mediaContainer}>
|
||||
<Link to={`/p/${subplebbitAddress}/c/${cid}`}>
|
||||
<CatalogPostMedia commentMediaInfo={commentMediaInfo} isOutOfFeed={true} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.threadContent}>
|
||||
{title && <b>{title}</b>}
|
||||
{content && (content.length > 99 ? `: ${content.substring(0, 99)}...` : `: ${content}`)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PopularThreads = ({ subplebbits }: { subplebbits: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const popularPosts = usePopularPosts(subplebbits);
|
||||
|
||||
return (
|
||||
<div className={styles.box}>
|
||||
<div className={`${styles.boxBar} ${styles.color2ColorBar}`}>
|
||||
<h2 className={styles.capitalize}>{t('popular_threads')}</h2>
|
||||
<span>{t('options')} ▼</span>
|
||||
</div>
|
||||
<div className={`${styles.boxContent} ${popularPosts.length === 8 ? styles.popularThreads : ''}`}>
|
||||
{popularPosts.length < 8 ? (
|
||||
<LoadingEllipsis string={t('loading')} />
|
||||
) : (
|
||||
popularPosts.map((post: any) => (
|
||||
<PopularThreadCard key={post.cid} post={post} boardTitle={post.subplebbitTitle || post.subplebbitAddress} boardShortAddress={post.subplebbitAddress} />
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Stats = ({ multisub, subplebbitAddresses }: { multisub: any; subplebbitAddresses: string[] }) => {
|
||||
const { t } = useTranslation();
|
||||
const stats = useSubplebbitsStats({ subplebbitAddresses });
|
||||
@@ -268,9 +91,6 @@ const Stats = ({ multisub, subplebbitAddresses }: { multisub: any; subplebbitAdd
|
||||
<h2 className={styles.capitalize}>{t('stats')}</h2>
|
||||
</div>
|
||||
<div className={`${styles.boxContent} ${enoughStats ? styles.stats : ''}`}>
|
||||
{/* <div className={styles.statsInfo}>
|
||||
<p>{t('stats_info')}</p>
|
||||
</div> */}
|
||||
{enoughStats ? (
|
||||
<>
|
||||
<div className={styles.stat}>
|
||||
@@ -403,8 +223,8 @@ const Home = () => {
|
||||
<HomeLogo />
|
||||
<SearchBar />
|
||||
<InfoBox />
|
||||
<Boards multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
||||
<PopularThreads subplebbits={subplebbits} />
|
||||
<BoardsBox multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
||||
<PopularThreadsBox multisub={defaultSubplebbits} subplebbits={subplebbits} />
|
||||
<Stats multisub={defaultSubplebbits} subplebbitAddresses={subplebbitAddresses} />
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './popular-threads-box';
|
||||
@@ -0,0 +1,82 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment, Subplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import styles from '../home.module.css';
|
||||
import usePopularPosts from '../../../hooks/use-popular-posts';
|
||||
import useHomeFiltersStore from '../../../stores/use-home-filters';
|
||||
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import { CatalogPostMedia } from '../../../components/catalog-row';
|
||||
import LoadingEllipsis from '../../../components/loading-ellipsis';
|
||||
import BoxModal from '../box-modal';
|
||||
import { nsfwTags } from '../home';
|
||||
|
||||
interface PopularThreadProps {
|
||||
post: Comment;
|
||||
boardTitle: string | undefined;
|
||||
boardShortAddress: string;
|
||||
}
|
||||
|
||||
const PopularThreadCard = ({ post, boardTitle, boardShortAddress }: PopularThreadProps) => {
|
||||
const { cid, content, subplebbitAddress, title } = post || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
|
||||
return (
|
||||
<div className={styles.popularThread} key={cid}>
|
||||
<div className={styles.title}>{boardTitle || boardShortAddress}</div>
|
||||
<div className={styles.mediaContainer}>
|
||||
<Link to={`/p/${subplebbitAddress}/c/${cid}`}>
|
||||
<CatalogPostMedia commentMediaInfo={commentMediaInfo} isOutOfFeed={true} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.threadContent}>
|
||||
{title && <b>{title}</b>}
|
||||
{content && (content.length > 99 ? `: ${content.substring(0, 99)}...` : `: ${content}`)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
|
||||
const { t } = useTranslation();
|
||||
const { showWorksafeContentOnly, showNsfwContentOnly } = useHomeFiltersStore();
|
||||
|
||||
const getFilteredSubplebbits = () => {
|
||||
if (showWorksafeContentOnly) {
|
||||
return subplebbits.filter((sub: Subplebbit) => {
|
||||
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
|
||||
return multisubEntry ? !multisubEntry.tags.some((tag: string) => nsfwTags.includes(tag)) : true;
|
||||
});
|
||||
}
|
||||
if (showNsfwContentOnly) {
|
||||
return subplebbits.filter((sub: Subplebbit) => {
|
||||
const multisubEntry = multisub.find((ms) => ms?.address === sub?.address);
|
||||
return multisubEntry ? multisubEntry.tags.some((tag: string) => nsfwTags.includes(tag)) : false;
|
||||
});
|
||||
}
|
||||
return subplebbits;
|
||||
};
|
||||
|
||||
const filteredSubplebbits = useMemo(getFilteredSubplebbits, [subplebbits, showWorksafeContentOnly, showNsfwContentOnly, multisub]);
|
||||
const popularPosts = usePopularPosts(filteredSubplebbits);
|
||||
|
||||
return (
|
||||
<div className={styles.box}>
|
||||
<div className={`${styles.boxBar} ${styles.color2ColorBar}`}>
|
||||
<h2 className={styles.capitalize}>{t('popular_threads')}</h2>
|
||||
<BoxModal isBoardsBoxModal={false} />
|
||||
</div>
|
||||
<div className={`${styles.boxContent} ${popularPosts.length === 8 ? styles.popularThreads : ''}`}>
|
||||
{popularPosts.length < 8 ? (
|
||||
<LoadingEllipsis string={t('loading')} />
|
||||
) : (
|
||||
popularPosts.map((post: any) => (
|
||||
<PopularThreadCard key={post.cid} post={post} boardTitle={post.subplebbitTitle || post.subplebbitAddress} boardShortAddress={post.subplebbitAddress} />
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PopularThreadsBox;
|
||||
@@ -1,3 +1,4 @@
|
||||
.content {
|
||||
margin-bottom: 150px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@@ -1529,11 +1529,6 @@
|
||||
minimatch "^3.0.4"
|
||||
plist "^3.0.4"
|
||||
|
||||
"@ensdomains/eth-ens-namehash@2.0.15":
|
||||
version "2.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@ensdomains/eth-ens-namehash/-/eth-ens-namehash-2.0.15.tgz#5e5f2f24ba802aff8bc19edd822c9a11200cdf4a"
|
||||
integrity sha512-JRDFP6+Hczb1E0/HhIg0PONgBYasfGfDheujmfxaZaAv/NAH4jE6Kf48WbqfRZdxt4IZI3jl3Ri7sZ1nP09lgw==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
|
||||
@@ -2165,11 +2160,6 @@
|
||||
"@ethersproject/properties" "^5.7.0"
|
||||
"@ethersproject/strings" "^5.7.0"
|
||||
|
||||
"@fastify/busboy@^2.0.0":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
|
||||
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==
|
||||
|
||||
"@floating-ui/core@^1.0.0":
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1"
|
||||
@@ -2742,21 +2732,6 @@
|
||||
uint8arraylist "^2.4.8"
|
||||
uint8arrays "^5.0.3"
|
||||
|
||||
"@libp2p/crypto@^1.0.11":
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-1.0.17.tgz#e64043328c0c866bf7f4cc8560b4f483e9c745dc"
|
||||
integrity sha512-Oeg0Eb/EvAho0gVkOgemXEgrVxWaT3x/DpFgkBdZ9qGxwq75w/E/oPc7souqBz+l1swfz37GWnwV7bIb4Xv5Ag==
|
||||
dependencies:
|
||||
"@libp2p/interface-keys" "^1.0.2"
|
||||
"@libp2p/interfaces" "^3.2.0"
|
||||
"@noble/ed25519" "^1.6.0"
|
||||
"@noble/secp256k1" "^1.5.4"
|
||||
multiformats "^11.0.0"
|
||||
node-forge "^1.1.0"
|
||||
protons-runtime "^5.0.0"
|
||||
uint8arraylist "^2.4.3"
|
||||
uint8arrays "^4.0.2"
|
||||
|
||||
"@libp2p/crypto@^4.0.0", "@libp2p/crypto@^4.0.1", "@libp2p/crypto@^4.0.2", "@libp2p/crypto@^4.0.5":
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-4.0.5.tgz#9f46ac445906a5a8f21246da75118254521382e6"
|
||||
@@ -2788,17 +2763,6 @@
|
||||
uint8arrays "^5.0.1"
|
||||
wherearewe "^2.0.1"
|
||||
|
||||
"@libp2p/interface-connection@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-connection/-/interface-connection-4.0.0.tgz#fcc830ca891820fac89a4c6bd4fcc2df4874f49b"
|
||||
integrity sha512-6xx/NmEc84HX7QmsjSC3hHredQYjHv4Dkf4G27adAPf+qN+vnPxmQ7gaTnk243a0++DOFTbZ2gKX/15G2B6SRg==
|
||||
dependencies:
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
"@libp2p/interfaces" "^3.0.0"
|
||||
"@multiformats/multiaddr" "^12.0.0"
|
||||
it-stream-types "^1.0.4"
|
||||
uint8arraylist "^2.1.2"
|
||||
|
||||
"@libp2p/interface-internal@^1.0.11", "@libp2p/interface-internal@^1.0.7", "@libp2p/interface-internal@^1.0.8":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-internal/-/interface-internal-1.0.11.tgz#34e548400408e3518566e6d97f3c916f1ef05a9e"
|
||||
@@ -2809,45 +2773,6 @@
|
||||
"@multiformats/multiaddr" "^12.2.1"
|
||||
uint8arraylist "^2.4.8"
|
||||
|
||||
"@libp2p/interface-keychain@^2.0.0":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-keychain/-/interface-keychain-2.0.5.tgz#6ce104f38cf07ad72c9dfbe471a689f4ea4b4687"
|
||||
integrity sha512-mb7QNgn9fIvC7CaJCi06GJ+a6DN6RVT9TmEi0NmedZGATeCArPeWWG7r7IfxNVXb9cVOOE1RzV1swK0ZxEJF9Q==
|
||||
dependencies:
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
multiformats "^11.0.0"
|
||||
|
||||
"@libp2p/interface-keys@^1.0.2":
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-keys/-/interface-keys-1.0.8.tgz#2c6b55136113ae7cf78133d3c459cdf0455b29ae"
|
||||
integrity sha512-CJ1SlrwuoHMquhEEWS77E+4vv7hwB7XORkqzGQrPQmA9MRdIEZRS64bA4JqCLUDa4ltH0l+U1vp0oZHLT67NEA==
|
||||
|
||||
"@libp2p/interface-peer-id@^2.0.0", "@libp2p/interface-peer-id@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-peer-id/-/interface-peer-id-2.0.2.tgz#6302e70b6fc17c451bc3daa11447d059357bcc32"
|
||||
integrity sha512-9pZp9zhTDoVwzRmp0Wtxw0Yfa//Yc0GqBCJi3EznBDE6HGIAVvppR91wSh2knt/0eYg0AQj7Y35VSesUTzMCUg==
|
||||
dependencies:
|
||||
multiformats "^11.0.0"
|
||||
|
||||
"@libp2p/interface-peer-info@^1.0.2":
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-peer-info/-/interface-peer-info-1.0.10.tgz#566026de95a0817b9e853c982b313541b7960c0b"
|
||||
integrity sha512-HQlo8NwQjMyamCHJrnILEZz+YwEOXCB2sIIw3slIrhVUYeYlTaia1R6d9umaAeLHa255Zmdm4qGH8rJLRqhCcg==
|
||||
dependencies:
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
"@multiformats/multiaddr" "^12.0.0"
|
||||
|
||||
"@libp2p/interface-pubsub@^3.0.0":
|
||||
version "3.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface-pubsub/-/interface-pubsub-3.0.7.tgz#cc1c7c47c883daddd2b84d83d719b3826943be3b"
|
||||
integrity sha512-+c74EVUBTfw2sx1GE/z/IjsYO6dhur+ukF0knAppeZsRQ1Kgg6K5R3eECtT28fC6dBWLjFpAvW/7QGfiDAL4RA==
|
||||
dependencies:
|
||||
"@libp2p/interface-connection" "^4.0.0"
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
"@libp2p/interfaces" "^3.0.0"
|
||||
it-pushable "^3.0.0"
|
||||
uint8arraylist "^2.1.2"
|
||||
|
||||
"@libp2p/interface@^1.0.0", "@libp2p/interface@^1.1.2", "@libp2p/interface@^1.1.3", "@libp2p/interface@^1.1.6":
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.1.6.tgz#379e3201f776ca13482ea60d31c4c5d40d88f7de"
|
||||
@@ -2872,11 +2797,6 @@
|
||||
progress-events "^1.0.0"
|
||||
uint8arraylist "^2.4.8"
|
||||
|
||||
"@libp2p/interfaces@^3.0.0", "@libp2p/interfaces@^3.2.0":
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/interfaces/-/interfaces-3.3.2.tgz#5d8079be845b0960939b5b18880e785a4714465a"
|
||||
integrity sha512-p/M7plbrxLzuQchvNwww1Was7ZeGE2NaOFulMaZBYIihU8z3fhaV+a033OqnC/0NTX/yhfdNOG7znhYq3XoR/g==
|
||||
|
||||
"@libp2p/kad-dht@12.0.7":
|
||||
version "12.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/kad-dht/-/kad-dht-12.0.7.tgz#f4ee2d815f8e13976cb79ac7c32e4e34553918fb"
|
||||
@@ -2914,17 +2834,6 @@
|
||||
uint8arraylist "^2.4.8"
|
||||
uint8arrays "^5.0.1"
|
||||
|
||||
"@libp2p/logger@^2.0.5":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-2.1.1.tgz#e12e6c320ea64252af954bcec996895098d1cd36"
|
||||
integrity sha512-2UbzDPctg3cPupF6jrv6abQnAUTrbLybNOj0rmmrdGm1cN2HJ1o/hBu0sXuq4KF9P1h/eVRn1HIRbVIEKnEJrA==
|
||||
dependencies:
|
||||
"@libp2p/interface-peer-id" "^2.0.2"
|
||||
"@multiformats/multiaddr" "^12.1.3"
|
||||
debug "^4.3.4"
|
||||
interface-datastore "^8.2.0"
|
||||
multiformats "^11.0.2"
|
||||
|
||||
"@libp2p/logger@^4.0.10":
|
||||
version "4.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.13.tgz#9a32d933c79be8854726a1d3c69d95ed69e1f677"
|
||||
@@ -3008,16 +2917,6 @@
|
||||
uint8arraylist "^2.4.8"
|
||||
uint8arrays "^5.0.3"
|
||||
|
||||
"@libp2p/peer-id@^2.0.0":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-2.0.4.tgz#d50d2ae4663ef79f6e31ce4eaf25e1f44e1667ab"
|
||||
integrity sha512-gcOsN8Fbhj6izIK+ejiWsqiqKeJ2yWPapi/m55VjOvDa52/ptQzZszxQP8jUk93u36de92ATFXDfZR/Bi6eeUQ==
|
||||
dependencies:
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
"@libp2p/interfaces" "^3.2.0"
|
||||
multiformats "^11.0.0"
|
||||
uint8arrays "^4.0.2"
|
||||
|
||||
"@libp2p/peer-id@^4.0.0", "@libp2p/peer-id@^4.0.5", "@libp2p/peer-id@^4.0.6", "@libp2p/peer-id@^4.0.9":
|
||||
version "4.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-4.0.9.tgz#2a08374f234e3d56c4b8a04ac434ab2f1d6cd143"
|
||||
@@ -3227,26 +3126,7 @@
|
||||
dependencies:
|
||||
"@multiformats/multiaddr" "^12.0.0"
|
||||
|
||||
"@multiformats/multiaddr-to-uri@^9.0.1":
|
||||
version "9.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@multiformats/multiaddr-to-uri/-/multiaddr-to-uri-9.0.8.tgz#c0b1491b26a4d52273ddc16024c59ba47ef8583f"
|
||||
integrity sha512-4eiN5iEiQfy2A98BxekUfW410L/ivg0sgjYSgSqmklnrBhK+QyMz4yqgfkub8xDTXOc7O5jp4+LVyM3ZqMeWNw==
|
||||
dependencies:
|
||||
"@multiformats/multiaddr" "^12.0.0"
|
||||
|
||||
"@multiformats/multiaddr@^11.1.5":
|
||||
version "11.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-11.6.1.tgz#ec46984a298e715e27a398434c087856db5f3185"
|
||||
integrity sha512-doST0+aB7/3dGK9+U5y3mtF3jq85KGbke1QiH0KE1F5mGQ9y56mFebTeu2D9FNOm+OT6UHb8Ss8vbSnpGjeLNw==
|
||||
dependencies:
|
||||
"@chainsafe/is-ip" "^2.0.1"
|
||||
dns-over-http-resolver "^2.1.0"
|
||||
err-code "^3.0.1"
|
||||
multiformats "^11.0.0"
|
||||
uint8arrays "^4.0.2"
|
||||
varint "^6.0.0"
|
||||
|
||||
"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.14", "@multiformats/multiaddr@^12.1.3", "@multiformats/multiaddr@^12.2.1":
|
||||
"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.14", "@multiformats/multiaddr@^12.2.1":
|
||||
version "12.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.2.1.tgz#d95d1590b17dbe39dcefbb4d832d14434d3fe075"
|
||||
integrity sha512-UwjoArBbv64FlaetV4DDwh+PUMfzXUBltxQwdh+uTYnGFzVa8ZfJsn1vt1RJlJ6+Xtrm3RMekF/B+K338i2L5Q==
|
||||
@@ -3305,7 +3185,7 @@
|
||||
dependencies:
|
||||
"@noble/hashes" "1.4.0"
|
||||
|
||||
"@noble/ed25519@^1.5.1", "@noble/ed25519@^1.6.0":
|
||||
"@noble/ed25519@^1.5.1":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.3.tgz#57e1677bf6885354b466c38e2b620c62f45a7123"
|
||||
integrity sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==
|
||||
@@ -3330,7 +3210,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
|
||||
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
|
||||
|
||||
"@noble/secp256k1@^1.3.0", "@noble/secp256k1@^1.5.4":
|
||||
"@noble/secp256k1@^1.3.0":
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c"
|
||||
integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==
|
||||
@@ -3377,69 +3257,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#3debda4034d18cf62ae46a4257a47284a8281e31":
|
||||
version "0.0.3"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#3debda4034d18cf62ae46a4257a47284a8281e31"
|
||||
dependencies:
|
||||
"@bonfida/spl-name-service" "2.4.2"
|
||||
"@chainsafe/libp2p-gossipsub" "12.0.0"
|
||||
"@chainsafe/libp2p-noise" "15.0.0"
|
||||
"@chainsafe/libp2p-yamux" "6.0.2"
|
||||
"@ensdomains/eth-ens-namehash" "2.0.15"
|
||||
"@keyv/sqlite" "3.6.7"
|
||||
"@libp2p/autonat" "1.0.12"
|
||||
"@libp2p/bootstrap" "10.0.15"
|
||||
"@libp2p/circuit-relay-v2" "^1.0.15"
|
||||
"@libp2p/identify" "1.0.14"
|
||||
"@libp2p/kad-dht" "12.0.7"
|
||||
"@libp2p/mplex" "10.0.15"
|
||||
"@libp2p/peer-id-factory" "4.0.6"
|
||||
"@libp2p/webrtc" "4.0.19"
|
||||
"@libp2p/webtransport" "4.0.19"
|
||||
"@plebbit/plebbit-logger" "github:plebbit/plebbit-logger#355a96d7659ed820047980049dfa627d30d83a69"
|
||||
"@plebbit/proper-lockfile" "github:plebbit/node-proper-lockfile#7fd6332117340c1d3d98dd0afee2d31cc06f72b8"
|
||||
"@types/proper-lockfile" "4.1.2"
|
||||
"@types/uuid" "8.3.4"
|
||||
assert "2.1.0"
|
||||
better-sqlite3 "9.3.0"
|
||||
buffer "6.0.3"
|
||||
captcha-canvas "3.2.1"
|
||||
cbor "9.0.1"
|
||||
debounce "1.2.1"
|
||||
err-code "3.0.1"
|
||||
ethers "6.10.0"
|
||||
ext-name "5.0.0"
|
||||
file-type "16.5.4"
|
||||
hpagent "1.2.0"
|
||||
ipfs-only-hash "4.0.0"
|
||||
jose "4.11.0"
|
||||
js-sha256 "0.9.0"
|
||||
js-sha512 "0.9.0"
|
||||
keyv "4.5.4"
|
||||
knex "3.1.0"
|
||||
kubo-rpc-client "3.0.3"
|
||||
libp2p "1.2.1"
|
||||
libp2p-crypto "0.21.2"
|
||||
limiter-es6-compat "2.1.2"
|
||||
localforage "1.10.0"
|
||||
lodash-es "4.17.21"
|
||||
lru-cache "10.1.0"
|
||||
open-graph-scraper "6.3.3"
|
||||
p-limit "4.0.0"
|
||||
p-timeout "6.1.2"
|
||||
peer-id "0.16.0"
|
||||
probe-image-size "7.2.3"
|
||||
retry "0.13.1"
|
||||
rpc-websockets "7.10.0"
|
||||
safe-stable-stringify "2.4.3"
|
||||
sha1-uint8array "0.10.7"
|
||||
skia-canvas "1.0.0"
|
||||
tiny-typed-emitter "2.1.0"
|
||||
tinycache "1.1.2"
|
||||
ts-custom-error "3.3.1"
|
||||
uuid "9.0.1"
|
||||
viem "1.5.2"
|
||||
|
||||
"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#b6f43c4b639b57622318c46a2e46792ae5fb01c3":
|
||||
version "0.0.3"
|
||||
resolved "https://github.com/plebbit/plebbit-js.git#b6f43c4b639b57622318c46a2e46792ae5fb01c3"
|
||||
@@ -3515,11 +3332,11 @@
|
||||
dependencies:
|
||||
debug "4.3.4"
|
||||
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#ebad94cad75020c6eef2516fffc87f5a7b7181ff":
|
||||
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#d7fa27920f8ec21c9fa08bc216054083e1d59fc0":
|
||||
version "0.0.1"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#ebad94cad75020c6eef2516fffc87f5a7b7181ff"
|
||||
resolved "https://github.com/plebbit/plebbit-react-hooks.git#d7fa27920f8ec21c9fa08bc216054083e1d59fc0"
|
||||
dependencies:
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#3debda4034d18cf62ae46a4257a47284a8281e31"
|
||||
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#b6f43c4b639b57622318c46a2e46792ae5fb01c3"
|
||||
"@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"
|
||||
assert "2.0.0"
|
||||
ethers "5.6.9"
|
||||
@@ -4230,11 +4047,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
|
||||
|
||||
"@types/minimatch@^3.0.4":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
||||
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
|
||||
|
||||
"@types/minimist@^1.2.0":
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e"
|
||||
@@ -4279,13 +4091,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.96.tgz#eb0012d23ff53d14d64ec8a352bf89792de6aade"
|
||||
integrity sha512-84iSqGXoO+Ha16j8pRZ/L90vDMKX04QTYMTfYeE1WrjWaZXuchBehGUZEpNgx7JnmlrIHdnABmpjrQjhCnNldQ==
|
||||
|
||||
"@types/node@^18.0.0":
|
||||
version "18.19.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.31.tgz#b7d4a00f7cb826b60a543cebdbda5d189aaecdcd"
|
||||
integrity sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/normalize-package-data@^2.4.0", "@types/normalize-package-data@^2.4.1":
|
||||
version "2.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
|
||||
@@ -4960,11 +4765,6 @@ any-promise@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
|
||||
|
||||
any-signal@^3.0.0, any-signal@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/any-signal/-/any-signal-3.0.1.tgz#49cae34368187a3472e31de28fb5cb1430caa9a6"
|
||||
integrity sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==
|
||||
|
||||
any-signal@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/any-signal/-/any-signal-4.1.1.tgz#928416c355c66899e6b2a91cad4488f0324bae03"
|
||||
@@ -5590,13 +5390,6 @@ blakejs@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814"
|
||||
integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==
|
||||
|
||||
blob-to-it@^2.0.0:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blob-to-it/-/blob-to-it-2.0.5.tgz#5c7af31b139fde37b7f7d8e82dff8358ae38a63f"
|
||||
integrity sha512-3VIFla8L4JuB+0WCdf+0POI7E1tTl8mhdGiwwwmnZEu6QjRJciS9fIvz8NgWY9URb0iagXYModGEYTcYeq9BMg==
|
||||
dependencies:
|
||||
browser-readablestream-to-it "^2.0.0"
|
||||
|
||||
blob-to-it@^2.0.5:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/blob-to-it/-/blob-to-it-2.0.7.tgz#637b8bb14963a7fce658ee758d9251dd1ee9fd3c"
|
||||
@@ -5734,11 +5527,6 @@ browser-process-hrtime@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
|
||||
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
|
||||
|
||||
browser-readablestream-to-it@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/browser-readablestream-to-it/-/browser-readablestream-to-it-1.0.3.tgz#ac3e406c7ee6cdf0a502dd55db33bab97f7fba76"
|
||||
integrity sha512-+12sHB+Br8HIh6VAMVEG5r3UXCyESIgDW7kzk3BjIXa43DVqVwL7GC5TW3jeh+72dtcH99pPVpw0X8i0jt+/kw==
|
||||
|
||||
browser-readablestream-to-it@^2.0.0:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/browser-readablestream-to-it/-/browser-readablestream-to-it-2.0.5.tgz#61539778c800930dfee1d4c361a060c99bbaa760"
|
||||
@@ -5813,7 +5601,7 @@ buffer-from@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer@6.0.3, buffer@^6.0.1, buffer@^6.0.3, buffer@~6.0.3:
|
||||
buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
@@ -7045,14 +6833,6 @@ d@1, d@^1.0.1, d@^1.0.2:
|
||||
es5-ext "^0.10.64"
|
||||
type "^2.7.2"
|
||||
|
||||
dag-jose@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dag-jose/-/dag-jose-4.0.0.tgz#4e65f62af58dd5203b2b094eb52142ffe0cdec1d"
|
||||
integrity sha512-tw595L3UYoOUT9dSJPbBEG/qpRpw24kRZxa5SLRnlnr+g5L7O8oEs1d3W5TiVA1oJZbthVsf0Vi3zFN66qcEBA==
|
||||
dependencies:
|
||||
"@ipld/dag-cbor" "^9.0.0"
|
||||
multiformats "^11.0.0"
|
||||
|
||||
dag-jose@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dag-jose/-/dag-jose-5.1.0.tgz#1c87391b199444ce5fb78cb53e708b7d79e095d8"
|
||||
@@ -7506,16 +7286,6 @@ dmg-license@^1.0.11:
|
||||
smart-buffer "^4.0.2"
|
||||
verror "^1.10.0"
|
||||
|
||||
dns-over-http-resolver@^2.1.0:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/dns-over-http-resolver/-/dns-over-http-resolver-2.1.3.tgz#bb7f2e10cc18d960339a6e30e21b8c1d99be7b38"
|
||||
integrity sha512-zjRYFhq+CsxPAouQWzOsxNMvEN+SHisjzhX8EMxd2Y0EG3thvn6wXQgMJLnTDImkhe4jhLbOQpXtL10nALBOSA==
|
||||
dependencies:
|
||||
debug "^4.3.1"
|
||||
native-fetch "^4.0.2"
|
||||
receptacle "^1.3.2"
|
||||
undici "^5.12.0"
|
||||
|
||||
dns-packet@^5.2.2, dns-packet@^5.6.1:
|
||||
version "5.6.1"
|
||||
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f"
|
||||
@@ -7725,7 +7495,7 @@ electron-dl@^3.2.1:
|
||||
pupa "^2.0.1"
|
||||
unused-filename "^2.1.0"
|
||||
|
||||
electron-fetch@^1.7.2, electron-fetch@^1.9.1:
|
||||
electron-fetch@^1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/electron-fetch/-/electron-fetch-1.9.1.tgz#e28bfe78d467de3f2dec884b1d72b8b05322f30f"
|
||||
integrity sha512-M9qw6oUILGVrcENMSRRefE1MbHPIz0h79EKIeJWK9v563aT9Qkh8aEHPO1H5vi970wPirNY+jO9OpFoLiMsMGA==
|
||||
@@ -9914,15 +9684,6 @@ inquirer@8.2.5:
|
||||
through "^2.3.6"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
interface-datastore@^7.0.0:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-7.0.4.tgz#f09ae4e2896f57f876d5d742a59e982fb3f42891"
|
||||
integrity sha512-Q8LZS/jfFFHz6XyZazLTAc078SSCoa27ZPBOfobWdpDiFO7FqPA2yskitUJIhaCgxNK8C+/lMBUTBNfVIDvLiw==
|
||||
dependencies:
|
||||
interface-store "^3.0.0"
|
||||
nanoid "^4.0.0"
|
||||
uint8arrays "^4.0.2"
|
||||
|
||||
interface-datastore@^8.0.0, interface-datastore@^8.2.0, interface-datastore@^8.2.10, interface-datastore@^8.2.11:
|
||||
version "8.2.11"
|
||||
resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-8.2.11.tgz#1d555ce6218ab6cba6291fc361debe9713590207"
|
||||
@@ -9940,11 +9701,6 @@ interface-ipld-format@^1.0.0:
|
||||
multicodec "^3.0.1"
|
||||
multihashes "^4.0.2"
|
||||
|
||||
interface-store@^3.0.0:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-3.0.4.tgz#670d95ef45f3b7061d154c3cbfaf39a538167ad7"
|
||||
integrity sha512-OjHUuGXbH4eXSBx1TF1tTySvjLldPLzRSYYXJwrEQI+XfH5JWYZofr0gVMV4F8XTwC+4V7jomDYkvGRmDSRKqQ==
|
||||
|
||||
interface-store@^5.0.0:
|
||||
version "5.1.8"
|
||||
resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-5.1.8.tgz#94bf867d165b5c904cccf09adeba215a5b0f459e"
|
||||
@@ -9987,49 +9743,7 @@ ipaddr.js@^2.0.1, ipaddr.js@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f"
|
||||
integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==
|
||||
|
||||
ipfs-core-types@^0.14.1:
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/ipfs-core-types/-/ipfs-core-types-0.14.1.tgz#c69f4dd873324e975ef43c391c0692b96863b13c"
|
||||
integrity sha512-4ujF8NlM9bYi2I6AIqPP9wfGGX0x/gRCkMoFdOQfxxrFg6HcAdfS+0/irK8mp4e7znOHWReOHeWqCGw+dAPwsw==
|
||||
dependencies:
|
||||
"@ipld/dag-pb" "^4.0.0"
|
||||
"@libp2p/interface-keychain" "^2.0.0"
|
||||
"@libp2p/interface-peer-id" "^2.0.0"
|
||||
"@libp2p/interface-peer-info" "^1.0.2"
|
||||
"@libp2p/interface-pubsub" "^3.0.0"
|
||||
"@multiformats/multiaddr" "^11.1.5"
|
||||
"@types/node" "^18.0.0"
|
||||
interface-datastore "^7.0.0"
|
||||
ipfs-unixfs "^9.0.0"
|
||||
multiformats "^11.0.0"
|
||||
|
||||
ipfs-core-utils@^0.18.0:
|
||||
version "0.18.1"
|
||||
resolved "https://registry.yarnpkg.com/ipfs-core-utils/-/ipfs-core-utils-0.18.1.tgz#d5fae11bfdb511749c6f905b0d0da3174eb50909"
|
||||
integrity sha512-P7jTpdfvlyBG3JR4o+Th3QJADlmXmwMxbkjszXry6VAjfSfLIIqXsdeYPoVRkV69GFEeQozuz2k/jR+U8cUH/Q==
|
||||
dependencies:
|
||||
"@libp2p/logger" "^2.0.5"
|
||||
"@multiformats/multiaddr" "^11.1.5"
|
||||
"@multiformats/multiaddr-to-uri" "^9.0.1"
|
||||
any-signal "^3.0.0"
|
||||
blob-to-it "^2.0.0"
|
||||
browser-readablestream-to-it "^2.0.0"
|
||||
err-code "^3.0.1"
|
||||
ipfs-core-types "^0.14.1"
|
||||
ipfs-unixfs "^9.0.0"
|
||||
ipfs-utils "^9.0.13"
|
||||
it-all "^2.0.0"
|
||||
it-map "^2.0.0"
|
||||
it-peekable "^2.0.0"
|
||||
it-to-stream "^1.0.0"
|
||||
merge-options "^3.0.4"
|
||||
multiformats "^11.0.0"
|
||||
nanoid "^4.0.0"
|
||||
parse-duration "^1.0.0"
|
||||
timeout-abort-controller "^3.0.0"
|
||||
uint8arrays "^4.0.2"
|
||||
|
||||
ipfs-only-hash@4.0.0, ipfs-only-hash@^4.0.0:
|
||||
ipfs-only-hash@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ipfs-only-hash/-/ipfs-only-hash-4.0.0.tgz#b3bd60a244d9eb7394961aa9d812a2e5ac7c04d6"
|
||||
integrity sha512-TE1DZCvfw8i3gcsTq3P4TFx3cKFJ3sluu/J3XINkJhIN9OwJgNMqKA+WnKx6ByCb1IoPXsTp1KM7tupElb6SyA==
|
||||
@@ -10074,36 +9788,6 @@ ipfs-unixfs@^4.0.3:
|
||||
err-code "^3.0.1"
|
||||
protobufjs "^6.10.2"
|
||||
|
||||
ipfs-unixfs@^9.0.0:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ipfs-unixfs/-/ipfs-unixfs-9.0.1.tgz#d06e688e07ef4ce08d610337ba2fe8c143c386e7"
|
||||
integrity sha512-jh2CbXyxID+v3jLml9CqMwjdSS9ZRnsGfQGGPOfem0/hT/L48xUeTPvh7qLFWkZcIMhZtG+fnS1teei8x5uGBg==
|
||||
dependencies:
|
||||
err-code "^3.0.1"
|
||||
protobufjs "^7.0.0"
|
||||
|
||||
ipfs-utils@^9.0.13, ipfs-utils@^9.0.7:
|
||||
version "9.0.14"
|
||||
resolved "https://registry.yarnpkg.com/ipfs-utils/-/ipfs-utils-9.0.14.tgz#24f5fda1f4567685eb32bca2543d518f95fd8704"
|
||||
integrity sha512-zIaiEGX18QATxgaS0/EOQNoo33W0islREABAcxXE8n7y2MGAlB+hdsxXn4J0hGZge8IqVQhW8sWIb+oJz2yEvg==
|
||||
dependencies:
|
||||
any-signal "^3.0.0"
|
||||
browser-readablestream-to-it "^1.0.0"
|
||||
buffer "^6.0.1"
|
||||
electron-fetch "^1.7.2"
|
||||
err-code "^3.0.1"
|
||||
is-electron "^2.2.0"
|
||||
iso-url "^1.1.5"
|
||||
it-all "^1.0.4"
|
||||
it-glob "^1.0.1"
|
||||
it-to-stream "^1.0.0"
|
||||
merge-options "^3.0.4"
|
||||
nanoid "^3.1.20"
|
||||
native-fetch "^3.0.0"
|
||||
node-fetch "^2.6.8"
|
||||
react-native-fetch-api "^3.0.0"
|
||||
stream-to-it "^0.2.2"
|
||||
|
||||
ipld-dag-pb@^0.22.2:
|
||||
version "0.22.3"
|
||||
resolved "https://registry.yarnpkg.com/ipld-dag-pb/-/ipld-dag-pb-0.22.3.tgz#6d5af28b5752236a5cb0e0a1888c87dd733b55cd"
|
||||
@@ -10555,7 +10239,7 @@ iso-random-stream@^2.0.0:
|
||||
events "^3.3.0"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
iso-url@^1.1.5, iso-url@^1.2.1:
|
||||
iso-url@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-1.2.1.tgz#db96a49d8d9a64a1c889fc07cc525d093afb1811"
|
||||
integrity sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==
|
||||
@@ -10612,16 +10296,11 @@ istanbul-reports@^3.1.3:
|
||||
html-escaper "^2.0.0"
|
||||
istanbul-lib-report "^3.0.0"
|
||||
|
||||
it-all@^1.0.4, it-all@^1.0.5:
|
||||
it-all@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/it-all/-/it-all-1.0.6.tgz#852557355367606295c4c3b7eff0136f07749335"
|
||||
integrity sha512-3cmCc6Heqe3uWi3CVM/k51fa/XbMFpQVzFoDsV0IZNHSQDyAXl3c4MjHkFX5kF3922OGj7Myv1nSEUgRtcuM1A==
|
||||
|
||||
it-all@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-all/-/it-all-2.0.1.tgz#45d530ecf6e13fb81d7ba583cdfd55ffdb376b05"
|
||||
integrity sha512-9UuJcCRZsboz+HBQTNOau80Dw+ryGaHYFP/cPYzFBJBFcfDathMYnhHk4t52en9+fcyDGPTdLB+lFc1wzQIroA==
|
||||
|
||||
it-all@^3.0.0, it-all@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/it-all/-/it-all-3.0.4.tgz#08f2e3eb3df04fa4525a343dcacfbdf91ffee162"
|
||||
@@ -10659,11 +10338,6 @@ it-first@^1.0.6:
|
||||
resolved "https://registry.yarnpkg.com/it-first/-/it-first-1.0.7.tgz#a4bef40da8be21667f7d23e44dae652f5ccd7ab1"
|
||||
integrity sha512-nvJKZoBpZD/6Rtde6FXqwDqDZGF1sCADmr2Zoc0hZsIvnE449gRFnGctxDf09Bzc/FWnHXAdaHVIetY6lrE0/g==
|
||||
|
||||
it-first@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-first/-/it-first-2.0.1.tgz#75d66b254c385ae3a1906def060a69006a437cef"
|
||||
integrity sha512-noC1oEQcWZZMUwq7VWxHNLML43dM+5bviZpfmkxkXlvBe60z7AFRqpZSga9uQBo792jKv9otnn1IjA4zwgNARw==
|
||||
|
||||
it-first@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/it-first/-/it-first-3.0.4.tgz#d68c8ae646ea402cd5e650c352da69988a310342"
|
||||
@@ -10676,14 +10350,6 @@ it-foreach@^2.0.6:
|
||||
dependencies:
|
||||
it-peekable "^3.0.0"
|
||||
|
||||
it-glob@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/it-glob/-/it-glob-1.0.2.tgz#bab9b04d6aaac42884502f3a0bfee84c7a29e15e"
|
||||
integrity sha512-Ch2Dzhw4URfB9L/0ZHyY+uqOnKvBNeS/SMcRiPmJfpHiM0TsUZn+GkpcZxAoF3dJVdPm/PuIk3A4wlV7SUo23Q==
|
||||
dependencies:
|
||||
"@types/minimatch" "^3.0.4"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
it-glob@^2.0.6:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/it-glob/-/it-glob-2.0.7.tgz#9c65a14dd89d3c19c0eaec50d382ee2b2396caba"
|
||||
@@ -10691,11 +10357,6 @@ it-glob@^2.0.6:
|
||||
dependencies:
|
||||
minimatch "^9.0.4"
|
||||
|
||||
it-last@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-last/-/it-last-2.0.1.tgz#a6f3253459cb77e917aeada3b2c4ae9f3e66c64b"
|
||||
integrity sha512-uVMedYW0wa2Cx0TAmcOCLbfuLLII7+vyURmhKa8Zovpd+aBTMsmINtsta2n364wJ5qsEDBH+akY1sUtAkaYBlg==
|
||||
|
||||
it-last@^3.0.4:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/it-last/-/it-last-3.0.6.tgz#53b1463e47fcaa950375968002598686101de6ab"
|
||||
@@ -10728,11 +10389,6 @@ it-length@^3.0.4:
|
||||
resolved "https://registry.yarnpkg.com/it-length/-/it-length-3.0.4.tgz#d178a18a6baf2cb448aeed53b6c854262abf38a1"
|
||||
integrity sha512-RS3thYkvqtWksrV7SaAnTv+pgY7ozpS17HlRvWvcnoRjVyNJMuffdCkIKpKNPTq5uZw9zVnkVKLO077pJn5Yhg==
|
||||
|
||||
it-map@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-map/-/it-map-2.0.1.tgz#d5251fd6b222d6ee39293d406a3f8fce54fb9220"
|
||||
integrity sha512-a2GcYDHiAh/eSU628xlvB56LA98luXZnniH2GlD0IdBzf15shEq9rBeb0Rg3o1SWtNILUAwqmQxEXcewGCdvmQ==
|
||||
|
||||
it-map@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/it-map/-/it-map-3.0.5.tgz#30b1e1324cdb4aaadba29cd989485168d1dc4136"
|
||||
@@ -10769,11 +10425,6 @@ it-parallel@^3.0.6:
|
||||
dependencies:
|
||||
p-defer "^4.0.0"
|
||||
|
||||
it-peekable@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-peekable/-/it-peekable-2.0.1.tgz#1e118610473aa511efc70f3bb7a7066178728dd3"
|
||||
integrity sha512-fJ/YTU9rHRhGJOM2hhQKKEfRM6uKB9r4yGGFLBHqp72ACC8Yi6+7/FhuBAMG8cpN6mLoj9auVX7ZJ3ul6qFpTA==
|
||||
|
||||
it-peekable@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/it-peekable/-/it-peekable-3.0.3.tgz#5f5741f34f3acd5735804f40d198652c54a3d8c1"
|
||||
@@ -10803,7 +10454,7 @@ it-protobuf-stream@^1.1.2:
|
||||
protons-runtime "^5.0.0"
|
||||
uint8arraylist "^2.4.1"
|
||||
|
||||
it-pushable@^3.0.0, it-pushable@^3.1.2, it-pushable@^3.2.0, it-pushable@^3.2.3:
|
||||
it-pushable@^3.1.2, it-pushable@^3.2.0, it-pushable@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-3.2.3.tgz#e2b80aed90cfbcd54b620c0a0785e546d4e5f334"
|
||||
integrity sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==
|
||||
@@ -10825,11 +10476,6 @@ it-sort@^3.0.4:
|
||||
dependencies:
|
||||
it-all "^3.0.0"
|
||||
|
||||
it-stream-types@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/it-stream-types/-/it-stream-types-1.0.5.tgz#9c72e6adefdea9dac69d0a28fbea783deebd508d"
|
||||
integrity sha512-I88Ka1nHgfX62e5mi5LLL+oueqz7Ltg0bUdtsUKDe9SoUqbQPf2Mp5kxDTe9pNhHQGs4pvYPAINwuZ1HAt42TA==
|
||||
|
||||
it-stream-types@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-stream-types/-/it-stream-types-2.0.1.tgz#69cb4d7e79e707b8257a8997e02751ccb6c3af32"
|
||||
@@ -11714,31 +11360,6 @@ knex@3.1.0:
|
||||
tarn "^3.0.2"
|
||||
tildify "2.0.0"
|
||||
|
||||
kubo-rpc-client@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kubo-rpc-client/-/kubo-rpc-client-3.0.3.tgz#7b6e51e0e6be9b0c999af2456ad45398c456c517"
|
||||
integrity sha512-PK+a1uOSYheu9y5+vh6WBfJT3pRl5LPUVdmaeg/wTpwSLL8VLgDmimtgybG7Z0SvM2UAA/cmrc32626/w+GS9Q==
|
||||
dependencies:
|
||||
"@ipld/dag-cbor" "^9.0.0"
|
||||
"@ipld/dag-json" "^10.0.0"
|
||||
"@ipld/dag-pb" "^4.0.0"
|
||||
"@libp2p/crypto" "^1.0.11"
|
||||
"@libp2p/logger" "^2.0.5"
|
||||
"@libp2p/peer-id" "^2.0.0"
|
||||
"@multiformats/multiaddr" "^12.1.10"
|
||||
any-signal "^3.0.1"
|
||||
dag-jose "^4.0.0"
|
||||
err-code "^3.0.1"
|
||||
ipfs-core-utils "^0.18.0"
|
||||
ipfs-utils "^9.0.7"
|
||||
it-first "^2.0.0"
|
||||
it-last "^2.0.0"
|
||||
merge-options "^3.0.4"
|
||||
multiformats "^11.0.0"
|
||||
parse-duration "^1.0.2"
|
||||
stream-to-it "^0.2.4"
|
||||
uint8arrays "^4.0.3"
|
||||
|
||||
kubo-rpc-client@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/kubo-rpc-client/-/kubo-rpc-client-4.1.1.tgz#31ca09b24233948919be43bc3971708313c09bf1"
|
||||
@@ -11997,11 +11618,6 @@ locate-path@^7.1.0:
|
||||
dependencies:
|
||||
p-locate "^6.0.0"
|
||||
|
||||
lodash-es@4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
@@ -12075,11 +11691,6 @@ long@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||
|
||||
long@^5.0.0:
|
||||
version "5.2.3"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
|
||||
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
|
||||
|
||||
longest-streak@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4"
|
||||
@@ -12984,16 +12595,6 @@ multicodec@^3.0.1:
|
||||
uint8arrays "^3.0.0"
|
||||
varint "^6.0.0"
|
||||
|
||||
multiformats@^11.0.0, multiformats@^11.0.2:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-11.0.2.tgz#b14735efc42cd8581e73895e66bebb9752151b60"
|
||||
integrity sha512-b5mYMkOkARIuVZCpvijFj9a6m5wMVLC7cf/jIPd5D/ARDOfLC5+IFkbgDXQgcU2goIsTD/O9NY4DI/Mt4OGvlg==
|
||||
|
||||
multiformats@^12.0.1:
|
||||
version "12.1.3"
|
||||
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-12.1.3.tgz#cbf7a9861e11e74f8228b21376088cb43ba8754e"
|
||||
integrity sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw==
|
||||
|
||||
multiformats@^13.0.0, multiformats@^13.0.1, multiformats@^13.1.0:
|
||||
version "13.1.0"
|
||||
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.1.0.tgz#5aa9d2175108a448fc3bdb54ba8a3d0b6cab3ac3"
|
||||
@@ -13044,16 +12645,11 @@ mz@^2.7.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.1.20, nanoid@^3.3.7:
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
nanoid@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
|
||||
integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==
|
||||
|
||||
nanoid@^5.0.7:
|
||||
version "5.0.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.7.tgz#6452e8c5a816861fd9d2b898399f7e5fd6944cc6"
|
||||
@@ -13064,11 +12660,6 @@ napi-build-utils@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
|
||||
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
|
||||
|
||||
native-fetch@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-3.0.0.tgz#06ccdd70e79e171c365c75117959cf4fe14a09bb"
|
||||
integrity sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==
|
||||
|
||||
native-fetch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-4.0.2.tgz#75c8a44c5f3bb021713e5e24f2846750883e49af"
|
||||
@@ -13173,14 +12764,14 @@ node-domexception@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-2.0.1.tgz#83b0d101123b5bbf91018fd569a58b88ae985e5b"
|
||||
integrity sha512-M85rnSC7WQ7wnfQTARPT4LrK7nwCHLdDFOCcItZMhTQjyCebJH8GciKqYJNgaOFZs9nFmTmd/VMyi3OW5jA47w==
|
||||
|
||||
node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7, node-fetch@^2.6.8, node-fetch@^2.7.0:
|
||||
node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7, node-fetch@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-forge@^1, node-forge@^1.1.0, node-forge@^1.2.1:
|
||||
node-forge@^1, node-forge@^1.2.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
||||
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
|
||||
@@ -13697,7 +13288,7 @@ parenthesis@^3.1.5:
|
||||
resolved "https://registry.yarnpkg.com/parenthesis/-/parenthesis-3.1.8.tgz#3457fccb8f05db27572b841dad9d2630b912f125"
|
||||
integrity sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==
|
||||
|
||||
parse-duration@^1.0.0, parse-duration@^1.0.2:
|
||||
parse-duration@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-1.1.0.tgz#5192084c5d8f2a3fd676d04a451dbd2e05a1819c"
|
||||
integrity sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ==
|
||||
@@ -14655,24 +14246,6 @@ protobufjs@^6.10.2, protobufjs@^6.11.2:
|
||||
"@types/node" ">=13.7.0"
|
||||
long "^4.0.0"
|
||||
|
||||
protobufjs@^7.0.0:
|
||||
version "7.2.6"
|
||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215"
|
||||
integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==
|
||||
dependencies:
|
||||
"@protobufjs/aspromise" "^1.1.2"
|
||||
"@protobufjs/base64" "^1.1.2"
|
||||
"@protobufjs/codegen" "^2.0.4"
|
||||
"@protobufjs/eventemitter" "^1.1.0"
|
||||
"@protobufjs/fetch" "^1.1.0"
|
||||
"@protobufjs/float" "^1.0.2"
|
||||
"@protobufjs/inquire" "^1.1.0"
|
||||
"@protobufjs/path" "^1.1.2"
|
||||
"@protobufjs/pool" "^1.1.0"
|
||||
"@protobufjs/utf8" "^1.1.0"
|
||||
"@types/node" ">=13.7.0"
|
||||
long "^5.0.0"
|
||||
|
||||
protons-runtime@5.4.0, protons-runtime@^5.0.0, protons-runtime@^5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/protons-runtime/-/protons-runtime-5.4.0.tgz#2751ce22cae6c35eebba89acfd9d783419ae3726"
|
||||
@@ -15122,13 +14695,6 @@ readdirp@~3.6.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
receptacle@^1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/receptacle/-/receptacle-1.3.2.tgz#a7994c7efafc7a01d0e2041839dab6c4951360d2"
|
||||
integrity sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
rechoir@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
|
||||
@@ -15396,11 +14962,6 @@ restore-cursor@^3.1.0:
|
||||
onetime "^5.1.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
retimer@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/retimer/-/retimer-3.0.0.tgz#98b751b1feaf1af13eb0228f8ea68b8f9da530df"
|
||||
integrity sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==
|
||||
|
||||
retry@0.13.1, retry@^0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||
@@ -16188,13 +15749,6 @@ stream-parser@~0.3.1:
|
||||
dependencies:
|
||||
debug "2"
|
||||
|
||||
stream-to-it@^0.2.2, stream-to-it@^0.2.4:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/stream-to-it/-/stream-to-it-0.2.4.tgz#d2fd7bfbd4a899b4c0d6a7e6a533723af5749bd0"
|
||||
integrity sha512-4vEbkSs83OahpmBybNJXlJd7d6/RxzkkSdT3I0mnGt79Xd2Kk+e1JqbvAvsQfCeKj3aKb0QIWkyK3/n0j506vQ==
|
||||
dependencies:
|
||||
get-iterator "^1.0.2"
|
||||
|
||||
stream-to-it@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-to-it/-/stream-to-it-1.0.1.tgz#7d5e1b04bab70facd48273279bfa49f0d0165950"
|
||||
@@ -16761,13 +16315,6 @@ tildify@2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/tildify/-/tildify-2.0.0.tgz#f205f3674d677ce698b7067a99e949ce03b4754a"
|
||||
integrity sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==
|
||||
|
||||
timeout-abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz#dd57ffca041652c03769904f8d95afd93fb95595"
|
||||
integrity sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==
|
||||
dependencies:
|
||||
retimer "^3.0.0"
|
||||
|
||||
timers-ext@^0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6"
|
||||
@@ -17125,7 +16672,7 @@ uint8-varint@^2.0.1, uint8-varint@^2.0.2, uint8-varint@^2.0.4:
|
||||
uint8arraylist "^2.0.0"
|
||||
uint8arrays "^5.0.0"
|
||||
|
||||
uint8arraylist@^2.0.0, uint8arraylist@^2.1.2, uint8arraylist@^2.4.1, uint8arraylist@^2.4.3, uint8arraylist@^2.4.8:
|
||||
uint8arraylist@^2.0.0, uint8arraylist@^2.4.1, uint8arraylist@^2.4.3, uint8arraylist@^2.4.8:
|
||||
version "2.4.8"
|
||||
resolved "https://registry.yarnpkg.com/uint8arraylist/-/uint8arraylist-2.4.8.tgz#5a4d17f4defd77799cb38e93fd5db0f0dceddc12"
|
||||
integrity sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==
|
||||
@@ -17146,13 +16693,6 @@ uint8arrays@^2.0.5, uint8arrays@^2.1.2:
|
||||
dependencies:
|
||||
multiformats "^9.4.2"
|
||||
|
||||
uint8arrays@^4.0.2, uint8arrays@^4.0.3:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-4.0.10.tgz#3ec5cde3348903c140e87532fc53f46b8f2e921f"
|
||||
integrity sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA==
|
||||
dependencies:
|
||||
multiformats "^12.0.1"
|
||||
|
||||
uint8arrays@^5.0.0, uint8arrays@^5.0.1, uint8arrays@^5.0.2, uint8arrays@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-5.0.3.tgz#92b894d9c4269ba97c51544d6e1f279fe6f80d1f"
|
||||
@@ -17195,13 +16735,6 @@ undici-types@~5.26.4:
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
undici@^5.12.0:
|
||||
version "5.28.4"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068"
|
||||
integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==
|
||||
dependencies:
|
||||
"@fastify/busboy" "^2.0.0"
|
||||
|
||||
undici@^6.4.0:
|
||||
version "6.12.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-6.12.0.tgz#396d4dbd2ea2351094c00be44655d489afe4fb8a"
|
||||
|
||||
Reference in New Issue
Block a user