Merge pull request #364 from plebbit/development

Development
This commit is contained in:
Tom (plebeius.eth)
2024-05-16 19:12:21 +02:00
committed by GitHub
43 changed files with 541 additions and 593 deletions
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "عنوان العملة الرقمية ينتمي إلى حساب آخر.",
"enter_crypto_address": "الرجاء إدخال عنوان كريبتو صالح.",
"crypto_address_not_resolved": "لم يتم حل عنوان العملة الرقمية بعد.",
"copy_message_etherscan": "<1>{{copy}}</1> رسالة للتوقيع على <2>etherscan</2>",
"copy_message_etherscan": "انسخ الرسالة للتوقيع على <1>etherscan</1>",
"account": "حساب",
"crypto_address": "عنوان العملة الرقمية",
"crypto_wallets": "محافظ العملات الرقمية",
@@ -113,5 +113,6 @@
"export": "تصدير",
"full_account_data": "بيانات الحساب الكاملة",
"this_account": "هذا الحساب",
"delete": "حذف"
"delete": "حذف",
"delete_account": "حذف الحساب"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "প্রকল্পসমূহ",
"challenge_counter": "{{index}} থেকে {{total}}",
"embed": "এম্বেড",
"remove": "মুছে ফেলুন",
"remove": "অপসারণ",
"download_latest_desktop": "সর্বশেষ ডেস্কটপ সংস্করণ এখানে ডাউনলোড করুন: {{link}}",
"new_stable_version": "নতুন স্থিতিশীল সংস্করণ উপলব্ধ, plebchan v{{newVersion}}। আপনি plebchan v{{oldVersion}} ব্যবহার করছেন।",
"refresh_to_update": "আপডেট করতে পৃষ্ঠাটি রিফ্রেশ করুন",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "ক্রিপ্টো ঠিকানা অন্য একটি অ্যাকাউন্টের অংশ।",
"enter_crypto_address": "দয়া করে একটি বৈধ ক্রিপ্টো ঠিকানা দিন।",
"crypto_address_not_resolved": "ক্রিপ্টো ঠিকানা এখনো সমাধান করা হয়নি।",
"copy_message_etherscan": "<1>{{copy}}</1> বার্তা সাইন করতে <2>etherscan</2> এ",
"copy_message_etherscan": "<1>etherscan</1> এ সাইন করার জন্য বার্তা অনুলিপি করুন",
"account": "অ্যাকাউন্ট",
"crypto_address": "ক্রিপ্টো ঠিকানা",
"crypto_wallets": "ক্রিপ্টো ওয়ালেট",
@@ -113,5 +113,6 @@
"export": "রপ্তানি",
"full_account_data": "সম্পূর্ণ অ্যাকাউন্ট ডেটা",
"this_account": "এই অ্যাকাউন্ট",
"delete": "মুছে ফেলা"
"delete": "মুছে ফেলা",
"delete_account": "অ্যাকাউন্ট মুছুন"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projekty",
"challenge_counter": "{{index}} z {{total}}",
"embed": "vložit",
"remove": "Odebrat",
"remove": "odstranit",
"download_latest_desktop": "Stáhněte si nejnovější verzi pro stolní počítače zde: {{link}}",
"new_stable_version": "Nová stabilní verze k dispozici, plebchan v{{newVersion}}. Používáte plebchan v{{oldVersion}}.",
"refresh_to_update": "Obnovte stránku pro aktualizaci",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Adresa kryptoměny patří k jinému účtu.",
"enter_crypto_address": "Zadejte prosím platnou kryptoadresu.",
"crypto_address_not_resolved": "Adresa kryptoměny ještě není vyřešena.",
"copy_message_etherscan": "<1>{{copy}}</1> zpráva k podpisu na <2>etherscan</2>",
"copy_message_etherscan": "Zkopírujte zprávu k podpisu na <1>etherscan</1>",
"account": "účet",
"crypto_address": "adresa kryptoměny",
"crypto_wallets": "Kryptoměny",
@@ -113,5 +113,6 @@
"export": "export",
"full_account_data": "plná účetní data",
"this_account": "tento účet",
"delete": "smazat"
"delete": "smazat",
"delete_account": "smazat účet"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projekter",
"challenge_counter": "{{index}} af {{total}}",
"embed": "integrer",
"remove": "Fjern",
"remove": "fjern",
"download_latest_desktop": "Download den seneste version til skrivebordet her: {{link}}",
"new_stable_version": "Ny stabil version tilgængelig, plebchan v{{newVersion}}. Du bruger plebchan v{{oldVersion}}.",
"refresh_to_update": "Opdater siden for at opdatere",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Crypto-adresse tilhører en anden konto.",
"enter_crypto_address": "Indtast venligst en gyldig krypto adresse.",
"crypto_address_not_resolved": "Crypto-adresse er endnu ikke løst.",
"copy_message_etherscan": "<1>{{copy}}</1> besked at underskrive på <2>etherscan</2>",
"copy_message_etherscan": "Kopiér besked til at underskrive på <1>etherscan</1>",
"account": "konto",
"crypto_address": "kryptoadresse",
"crypto_wallets": "Crypto Wallets",
@@ -113,5 +113,6 @@
"export": "eksportér",
"full_account_data": "fulde kontodata",
"this_account": "denne konto",
"delete": "slet"
"delete": "slet",
"delete_account": "slet konto"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "Projekte",
"challenge_counter": "{{index}} von {{total}}",
"embed": "einbetten",
"remove": "Entfernen",
"remove": "entfernen",
"download_latest_desktop": "Laden Sie hier die neueste Desktop-Version herunter: {{link}}",
"new_stable_version": "Neue stabile Version verfügbar, plebchan v{{newVersion}}. Du verwendest plebchan v{{oldVersion}}.",
"refresh_to_update": "Aktualisieren Sie die Seite, um zu aktualisieren",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Krypto-Adresse gehört zu einem anderen Konto.",
"enter_crypto_address": "Bitte geben Sie eine gültige Krypto-Adresse ein.",
"crypto_address_not_resolved": "Krypto-Adresse ist noch nicht aufgelöst.",
"copy_message_etherscan": "<1>{{copy}}</1> Nachricht zum Signieren auf <2>etherscan</2>",
"copy_message_etherscan": "Nachricht zum Signieren auf <1>etherscan</1> kopieren",
"account": "Konto",
"crypto_address": "Krypto-Adresse",
"crypto_wallets": "Krypto-Wallets",
@@ -113,5 +113,6 @@
"export": "exportiere",
"full_account_data": "vollständige Kontodaten",
"this_account": "dieses Konto",
"delete": "löschen"
"delete": "löschen",
"delete_account": "Konto löschen"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "έργα",
"challenge_counter": "{{index}} από {{total}}",
"embed": "ενσωμάτωση",
"remove": "Αφαίρεση",
"remove": "αφαίρεση",
"download_latest_desktop": "Κατεβάστε την πιο πρόσφατη έκδοση για επιτραπέζιο υπολογιστή εδώ: {{link}}",
"new_stable_version": "Νέα σταθερή έκδοση διαθέσιμη, plebchan v{{newVersion}}. Χρησιμοποιείτε plebchan v{{oldVersion}}.",
"refresh_to_update": "Ανανεώστε τη σελίδα για να ενημερωθεί",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Η διεύθυνση κρυπτονομίσματος ανήκει σε άλλο λογαριασμό.",
"enter_crypto_address": "Παρακαλώ εισαγάγετε μια έγκυρη διεύθυνση κρυπτονομίσματος.",
"crypto_address_not_resolved": "Η διεύθυνση κρυπτονομίσματος δεν έχει ακόμη επιλυθεί.",
"copy_message_etherscan": "<1>{{copy}}</1> μήνυμα για υπογραφή στο <2>etherscan</2>",
"copy_message_etherscan": "Αντιγράψτε το μήνυμα για υπογραφή στο <1>etherscan</1>",
"account": "λογαριασμός",
"crypto_address": "διεύθυνση κρυπτονομίσματος",
"crypto_wallets": "Πορτοφόλια κρυπτονομισμάτων",
@@ -113,5 +113,6 @@
"export": "εξαγωγή",
"full_account_data": "πλήρα δεδομένα λογαριασμού",
"this_account": "αυτός ο λογαριασμός",
"delete": "διαγραφή"
"delete": "διαγραφή",
"delete_account": "διαγραφή λογαριασμού"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projects",
"challenge_counter": "{{index}} of {{total}}",
"embed": "embed",
"remove": "Remove",
"remove": "remove",
"download_latest_desktop": "Download the latest desktop version here: {{link}}",
"new_stable_version": "New stable version available, plebchan v{{newVersion}}. You are using plebchan v{{oldVersion}}.",
"refresh_to_update": "Refresh the page to update",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Crypto address belongs to another account.",
"enter_crypto_address": "Please enter a valid crypto address.",
"crypto_address_not_resolved": "Crypto address is not resolved yet.",
"copy_message_etherscan": "<1>{{copy}}</1> message to sign on <2>etherscan</2>",
"copy_message_etherscan": "Copy message to sign on <1>etherscan</1>",
"account": "account",
"crypto_address": "crypto address",
"crypto_wallets": "Crypto Wallets",
@@ -113,5 +113,6 @@
"export": "export",
"full_account_data": "full account data",
"this_account": "this account",
"delete": "delete"
"delete": "delete",
"delete_account": "delete account"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "proyectos",
"challenge_counter": "{{index}} de {{total}}",
"embed": "incrustar",
"remove": "Eliminar",
"remove": "eliminar",
"download_latest_desktop": "Descarga la última versión de escritorio aquí: {{link}}",
"new_stable_version": "Nueva versión estable disponible, plebchan v{{newVersion}}. Estás usando plebchan v{{oldVersion}}.",
"refresh_to_update": "Actualiza la página para actualizar",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "La dirección de criptomoneda pertenece a otra cuenta.",
"enter_crypto_address": "Por favor, introduzca una dirección de cripto válida.",
"crypto_address_not_resolved": "La dirección de criptomoneda aún no está resuelta.",
"copy_message_etherscan": "<1>{{copy}}</1> mensaje para firmar en <2>etherscan</2>",
"copy_message_etherscan": "Copiar mensaje para firmar en <1>etherscan</1>",
"account": "cuenta",
"crypto_address": "dirección de cripto",
"crypto_wallets": "Billeteras cripto",
@@ -113,5 +113,6 @@
"export": "exportar",
"full_account_data": "datos completos de la cuenta",
"this_account": "esta cuenta",
"delete": "eliminar"
"delete": "eliminar",
"delete_account": "eliminar cuenta"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "آدرس رمزارز به حساب دیگری تعلق دارد.",
"enter_crypto_address": "لطفاً یک آدرس کریپتو صحیح وارد کنید.",
"crypto_address_not_resolved": "آدرس رمزارز هنوز حل نشده است.",
"copy_message_etherscan": "<1>{{copy}}</1> پیامی برای امضا در <2>etherscan</2>",
"copy_message_etherscan": "پیام را برای امضا در <1>etherscan</1> کپی کنید",
"account": "حساب",
"crypto_address": "آدرس رمزارز",
"crypto_wallets": "کیف پول رمز ارز",
@@ -113,5 +113,6 @@
"export": "صدور",
"full_account_data": "داده حساب کامل",
"this_account": "این حساب",
"delete": "حذف کنید"
"delete": "حذف کنید",
"delete_account": "حذف حساب"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projektit",
"challenge_counter": "{{index}} / {{total}}",
"embed": "upota",
"remove": "Poista",
"remove": "poista",
"download_latest_desktop": "Lataa uusin työpöytäversio täältä: {{link}}",
"new_stable_version": "Uusi vakaa versio saatavilla, plebchan v{{newVersion}}. Käytät plebchan v{{oldVersion}}.",
"refresh_to_update": "Päivitä sivu päivittääksesi",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Krypto-osoite kuuluu toiseen tiliin.",
"enter_crypto_address": "Syötä voimassa oleva krypto-osoite.",
"crypto_address_not_resolved": "Krypto-osoitetta ei ole vielä ratkaistu.",
"copy_message_etherscan": "<1>{{copy}}</1> viesti allekirjoitettavaksi <2>etherscan</2>:ssa",
"copy_message_etherscan": "Kopioi viesti allekirjoitettavaksi <1>etherscan</1>",
"account": "tili",
"crypto_address": "krypto-osoite",
"crypto_wallets": "Krypto-lompakot",
@@ -113,5 +113,6 @@
"export": "vie",
"full_account_data": "täydelliset tilitiedot",
"this_account": "tämä tili",
"delete": "poista"
"delete": "poista",
"delete_account": "poista tili"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "mga proyekto",
"challenge_counter": "{{index}} ng {{total}}",
"embed": "i-embed",
"remove": "Alisin",
"remove": "alisin",
"download_latest_desktop": "I-download ang pinakabagong bersyon ng desktop dito: {{link}}",
"new_stable_version": "Bagong stable na bersyon na magagamit, plebchan v{{newVersion}}. Ginagamit mo ang plebchan v{{oldVersion}}.",
"refresh_to_update": "I-refresh ang pahina upang i-update",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Ang crypto address ay nauugnay sa ibang account.",
"enter_crypto_address": "Mangyaring magpasok ng wastong crypto address.",
"crypto_address_not_resolved": "Hindi pa naresolba ang crypto address.",
"copy_message_etherscan": "<1>{{copy}}</1> mensahe na pipirmahan sa <2>etherscan</2>",
"copy_message_etherscan": "Kopyahin ang mensahe upang pirmahan sa <1>etherscan</1>",
"account": "account",
"crypto_address": "crypto address",
"crypto_wallets": "Mga Wallet ng Crypto",
@@ -113,5 +113,6 @@
"export": "i-export",
"full_account_data": "buong account data",
"this_account": "ang account na ito",
"delete": "burahin"
"delete": "burahin",
"delete_account": "tanggalin ang account"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projets",
"challenge_counter": "{{index}} sur {{total}}",
"embed": "intégrer",
"remove": "Retirer",
"remove": "supprimer",
"download_latest_desktop": "Téléchargez la dernière version de bureau ici : {{link}}",
"new_stable_version": "Nouvelle version stable disponible, plebchan v{{newVersion}}. Vous utilisez plebchan v{{oldVersion}}.",
"refresh_to_update": "Actualisez la page pour mettre à jour",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "L'adresse crypto appartient à un autre compte.",
"enter_crypto_address": "Veuillez entrer une adresse crypto valide.",
"crypto_address_not_resolved": "L'adresse crypto n'est pas encore résolue.",
"copy_message_etherscan": "<1>{{copy}}</1> message à signer sur <2>etherscan</2>",
"copy_message_etherscan": "Copier le message à signer sur <1>etherscan</1>",
"account": "compte",
"crypto_address": "adresse crypto",
"crypto_wallets": "Portefeuilles de crypto",
@@ -113,5 +113,6 @@
"export": "exporter",
"full_account_data": "données complètes du compte",
"this_account": "ce compte",
"delete": "supprimer"
"delete": "supprimer",
"delete_account": "supprimer le compte"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "כתובת המטבע הקריפטוגרפי שייכת לחשבון אחר.",
"enter_crypto_address": "אנא הזן כתובת קריפטו תקף.",
"crypto_address_not_resolved": "כתובת המטבע הקריפטוגרפית עדיין לא נפתרה.",
"copy_message_etherscan": "<1>{{copy}}</1> הודעה לחתימה ב-<2>etherscan</2>",
"copy_message_etherscan": "העתק הודעה לחתימה ב-<1>etherscan</1>",
"account": "חשבון",
"crypto_address": "כתובת קריפטו",
"crypto_wallets": "ארנק קריפטו",
@@ -113,5 +113,6 @@
"export": "יצוא",
"full_account_data": "נתוני החשבון המלאים",
"this_account": "החשבון הזה",
"delete": "מחק"
"delete": "מחק",
"delete_account": "מחק חשבון"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "क्रिप्टो पता दूसरे खाते से संबंधित है।",
"enter_crypto_address": "कृपया एक मान्य क्रिप्टो पता दर्ज करें।",
"crypto_address_not_resolved": "क्रिप्टो पता अभी तक हल नहीं किया गया है।",
"copy_message_etherscan": "<1>{{copy}}</1> संदेश को <2>etherscan</2> पर हस्ताक्षर करें",
"copy_message_etherscan": "<1>etherscan</1> पर साइन करने के लिए संदेश कॉपी करें",
"account": "खाता",
"crypto_address": "क्रिप्टो पता",
"crypto_wallets": "क्रिप्टो वॉलेट्स",
@@ -113,5 +113,6 @@
"export": "निर्यात",
"full_account_data": "पूरे खाते का डेटा",
"this_account": "इस खाता",
"delete": "हटाएँ"
"delete": "हटाएँ",
"delete_account": "खाता हटाएं"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projektek",
"challenge_counter": "{{index}} a(z) {{total}}-ból/ből",
"embed": "beágyaz",
"remove": "Eltávolítás",
"remove": "eltávolít",
"download_latest_desktop": "Töltsd le a legújabb asztali verziót itt: {{link}}",
"new_stable_version": "Új stabil verzió elérhető, plebchan v{{newVersion}}. A plebchan v{{oldVersion}}-t használod.",
"refresh_to_update": "Frissítse az oldalt az frissítéshez",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "A kripto-cím egy másik fiókhoz tartozik.",
"enter_crypto_address": "Kérjük, adjon meg egy érvényes kripto címet.",
"crypto_address_not_resolved": "A kripto cím még nem oldódott meg.",
"copy_message_etherscan": "<1>{{copy}}</1> üzenet aláírásához az <2>etherscan</2>-en",
"copy_message_etherscan": "Üzenet másolása aláíráshoz a <1>etherscan</1>",
"account": "fiók",
"crypto_address": "kriptovaluta cím",
"crypto_wallets": "Kriptopénztárcák",
@@ -113,5 +113,6 @@
"export": "exportálás",
"full_account_data": "teljes fiókadata",
"this_account": "ez a fiók",
"delete": "töröl"
"delete": "töröl",
"delete_account": "fiók törlése"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "proyek",
"challenge_counter": "{{index}} dari {{total}}",
"embed": "sematkan",
"remove": "Hapus",
"remove": "hapus",
"download_latest_desktop": "Unduh versi desktop terbaru di sini: {{link}}",
"new_stable_version": "Versi stabil baru tersedia, plebchan v{{newVersion}}. Anda menggunakan plebchan v{{oldVersion}}.",
"refresh_to_update": "Segarkan halaman untuk memperbarui",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Alamat kripto milik akun lain.",
"enter_crypto_address": "Harap masukkan alamat kripto yang valid.",
"crypto_address_not_resolved": "Alamat kripto belum terpecahkan.",
"copy_message_etherscan": "<1>{{copy}}</1> pesan untuk ditandatangani di <2>etherscan</2>",
"copy_message_etherscan": "Salin pesan untuk ditandatangani di <1>etherscan</1>",
"account": "akun",
"crypto_address": "alamat kripto",
"crypto_wallets": "Dompet Crypto",
@@ -113,5 +113,6 @@
"export": "ekspor",
"full_account_data": "data akun lengkap",
"this_account": "akun ini",
"delete": "hapus"
"delete": "hapus",
"delete_account": "hapus akun"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "progetti",
"challenge_counter": "{{index}} di {{total}}",
"embed": "incorpora",
"remove": "Rimuovi",
"remove": "rimuovi",
"download_latest_desktop": "Scarica l'ultima versione desktop qui: {{link}}",
"new_stable_version": "Nuova versione stabile disponibile, plebchan v{{newVersion}}. Stai utilizzando plebchan v{{oldVersion}}.",
"refresh_to_update": "Ricarica la pagina per aggiornare",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "L'indirizzo cripto appartiene a un altro account.",
"enter_crypto_address": "Inserisci un indirizzo cripto valido.",
"crypto_address_not_resolved": "L'indirizzo cripto non è ancora risolto.",
"copy_message_etherscan": "<1>{{copy}}</1> messaggio da firmare su <2>etherscan</2>",
"copy_message_etherscan": "Copia messaggio da firmare su <1>etherscan</1>",
"account": "account",
"crypto_address": "indirizzo crypto",
"crypto_wallets": "Wallet crypto",
@@ -113,5 +113,6 @@
"export": "esporta",
"full_account_data": "i dati completi dell'account",
"this_account": "questo account",
"delete": "elimina"
"delete": "elimina",
"delete_account": "elimina account"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "暗号通貨アドレスは別のアカウントに属しています。",
"enter_crypto_address": "有効な暗号通貨アドレスを入力してください。",
"crypto_address_not_resolved": "暗号通貨アドレスはまだ解決されていません。",
"copy_message_etherscan": "<1>{{copy}}</1> メッセージを<2>etherscan</2>でサイン",
"copy_message_etherscan": "<1>etherscan</1>で署名するメッセージをコピー",
"account": "アカウント",
"crypto_address": "暗号通貨アドレス",
"crypto_wallets": "暗号通貨ウォレット",
@@ -113,5 +113,6 @@
"export": "エクスポート",
"full_account_data": "フルアカウントデータ",
"this_account": "このアカウント",
"delete": "削除"
"delete": "削除",
"delete_account": "アカウントを削除"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "프로젝트",
"challenge_counter": "{{index}} 중 {{total}}",
"embed": "임베드",
"remove": "제",
"remove": "제",
"download_latest_desktop": "최신 데스크톱 버전을 여기에서 다운로드하세요: {{link}}",
"new_stable_version": "새로운 안정 버전이 사용 가능합니다, plebchan v{{newVersion}}. plebchan v{{oldVersion}}을(를) 사용 중입니다.",
"refresh_to_update": "업데이트를 위해 페이지를 새로 고칩니다",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "암호 주소는 다른 계정에 속합니다.",
"enter_crypto_address": "유효한 암호 주소를 입력하세요.",
"crypto_address_not_resolved": "암호 주소가 아직 해결되지 않았습니다.",
"copy_message_etherscan": "<1>{{copy}}</1> 메시지를 <2>etherscan</2>에서 서명",
"copy_message_etherscan": "<1>etherscan</1>에서 서명할 메시지 복사",
"account": "계정",
"crypto_address": "암호 화폐 주소",
"crypto_wallets": "암호 화폐 지갑",
@@ -113,5 +113,6 @@
"export": "내보내기",
"full_account_data": "전체 계정 데이터",
"this_account": "이 계정",
"delete": "삭제"
"delete": "삭제",
"delete_account": "계정 삭제"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "क्रिप्टो पत्ता इतर खात्याशी संबंधित आहे.",
"enter_crypto_address": "कृपया मान्य क्रिप्टो पत्ता प्रविष्ट करा.",
"crypto_address_not_resolved": "क्रिप्टो पत्ता अजून सोपवला नाही.",
"copy_message_etherscan": "<1>{{copy}}</1> संदेश <2>etherscan</2> वर स्ाक्षर करण्यासाठी",
"copy_message_etherscan": "<1>etherscan</1> वर स्ाक्षरीसाठी संदेश कॉपी करा",
"account": "खाता",
"crypto_address": "क्रिप्टो पत्ता",
"crypto_wallets": "क्रिप्टो बटव्या",
@@ -113,5 +113,6 @@
"export": "निर्यात करा",
"full_account_data": "पूर्ण खाते डेटा",
"this_account": "हे खाते",
"delete": "काढा"
"delete": "काढा",
"delete_account": "खाते हटवा"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projecten",
"challenge_counter": "{{index}} van {{total}}",
"embed": "insluiten",
"remove": "Verwijderen",
"remove": "verwijderen",
"download_latest_desktop": "Download de nieuwste desktopversie hier: {{link}}",
"new_stable_version": "Nieuwe stabiele versie beschikbaar, plebchan v{{newVersion}}. Je gebruikt plebchan v{{oldVersion}}.",
"refresh_to_update": "Vernieuw de pagina om bij te werken",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Crypto-adres behoort tot een andere account.",
"enter_crypto_address": "Voer alstublieft een geldig crypto-adres in.",
"crypto_address_not_resolved": "Crypto-adres is nog niet opgelost.",
"copy_message_etherscan": "<1>{{copy}}</1> bericht om te ondertekenen op <2>etherscan</2>",
"copy_message_etherscan": "Kopieer bericht om te ondertekenen op <1>etherscan</1>",
"account": "account",
"crypto_address": "crypto adres",
"crypto_wallets": "Crypto-portefeuilles",
@@ -113,5 +113,6 @@
"export": "exporteer",
"full_account_data": "volledige accountgegevens",
"this_account": "dit account",
"delete": "verwijderen"
"delete": "verwijderen",
"delete_account": "account verwijderen"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "prosjekter",
"challenge_counter": "{{index}} av {{total}}",
"embed": "bygg inn",
"remove": "Fjern",
"remove": "fjern",
"download_latest_desktop": "Last ned den nyeste skrivebordsversjonen her: {{link}}",
"new_stable_version": "Ny stabil versjon tilgjengelig, plebchan v{{newVersion}}. Du bruker plebchan v{{oldVersion}}.",
"refresh_to_update": "Oppdater siden for å oppdatere",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Crypto-adressen tilhører en annen konto.",
"enter_crypto_address": "Vennligst skriv inn en gyldig kryptoadresse.",
"crypto_address_not_resolved": "Crypto-adresse er ikke løst ennå.",
"copy_message_etherscan": "<1>{{copy}}</1> melding å signere på <2>etherscan</2>",
"copy_message_etherscan": "Kopier melding for å signere på <1>etherscan</1>",
"account": "konto",
"crypto_address": "kryptoadresse",
"crypto_wallets": "Crypto-lommebøker",
@@ -113,5 +113,6 @@
"export": "eksporter",
"full_account_data": "full kontodata",
"this_account": "denne kontoen",
"delete": "slett"
"delete": "slett",
"delete_account": "slett konto"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projekty",
"challenge_counter": "{{index}} z {{total}}",
"embed": "osadź",
"remove": "Usuń",
"remove": "usuń",
"download_latest_desktop": "Pobierz najnowszą wersję na pulpit tutaj: {{link}}",
"new_stable_version": "Nowa stabilna wersja dostępna, plebchan v{{newVersion}}. Używasz plebchan v{{oldVersion}}.",
"refresh_to_update": "Odśwież stronę, aby zaktualizować",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Adres kryptowaluty należy do innego konta.",
"enter_crypto_address": "Proszę podać prawidłowy adres kryptowalutowy.",
"crypto_address_not_resolved": "Adres kryptowaluty nie jest jeszcze rozwiązany.",
"copy_message_etherscan": "<1>{{copy}}</1> wiadomość do podpisania na <2>etherscan</2>",
"copy_message_etherscan": "Skopiuj wiadomość do podpisania na <1>etherscan</1>",
"account": "konto",
"crypto_address": "adres kryptowalutowy",
"crypto_wallets": "Portfele kryptowalut",
@@ -113,5 +113,6 @@
"export": "eksportuj",
"full_account_data": "pełne dane konta",
"this_account": "ten rachunek",
"delete": "usuń"
"delete": "usuń",
"delete_account": "usuń konto"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projetos",
"challenge_counter": "{{index}} de {{total}}",
"embed": "embutir",
"remove": "Remover",
"remove": "remover",
"download_latest_desktop": "Baixe a versão mais recente para desktop aqui: {{link}}",
"new_stable_version": "Nova versão estável disponível, plebchan v{{newVersion}}. Você está usando plebchan v{{oldVersion}}.",
"refresh_to_update": "Atualize a página para atualizar",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "O endereço de criptomoeda pertence a outra conta.",
"enter_crypto_address": "Por favor, insira um endereço de cripto válido.",
"crypto_address_not_resolved": "O endereço de criptomoeda ainda não foi resolvido.",
"copy_message_etherscan": "<1>{{copy}}</1> mensagem para assinar no <2>etherscan</2>",
"copy_message_etherscan": "Copiar mensagem para assinar no <1>etherscan</1>",
"account": "conta",
"crypto_address": "endereço de cripto",
"crypto_wallets": "Carteiras cripto",
@@ -113,5 +113,6 @@
"export": "exportar",
"full_account_data": "dados completos da conta",
"this_account": "esta conta",
"delete": "apagar"
"delete": "apagar",
"delete_account": "excluir conta"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "proiecte",
"challenge_counter": "{{index}} din {{total}}",
"embed": "încorpora",
"remove": "Elimină",
"remove": "elimina",
"download_latest_desktop": "Descărcați cea mai recentă versiune de desktop aici: {{link}}",
"new_stable_version": "Noua versiune stabilă disponibilă, plebchan v{{newVersion}}. Folosiți plebchan v{{oldVersion}}.",
"refresh_to_update": "Actualizați pagina pentru a actualiza",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Adresa crypto aparține unui alt cont.",
"enter_crypto_address": "Vă rugăm să introduceți o adresă crypto validă.",
"crypto_address_not_resolved": "Adresa crypto nu este încă rezolvată.",
"copy_message_etherscan": "<1>{{copy}}</1> mesaj de semnat pe <2>etherscan</2>",
"copy_message_etherscan": "Copiați mesajul pentru a semna pe <1>etherscan</1>",
"account": "cont",
"crypto_address": "adresa cripto",
"crypto_wallets": "Portofele crypto",
@@ -113,5 +113,6 @@
"export": "exportați",
"full_account_data": "date complete ale contului",
"this_account": "acest cont",
"delete": "ștergeți"
"delete": "ștergeți",
"delete_account": "șterge contul"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "проекты",
"challenge_counter": "{{index}} из {{total}}",
"embed": "встроить",
"remove": "Удалить",
"remove": "удалить",
"download_latest_desktop": "Скачать последнюю версию для рабочего стола здесь: {{link}}",
"new_stable_version": "Доступна новая стабильная версия, plebchan v{{newVersion}}. Вы используете plebchan v{{oldVersion}}.",
"refresh_to_update": "Обновите страницу, чтобы обновить",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Адрес криптовалюты принадлежит другому аккаунту.",
"enter_crypto_address": "Пожалуйста, введите действительный криптовалютный адрес.",
"crypto_address_not_resolved": "Адрес криптовалюты еще не решен.",
"copy_message_etherscan": "<1>{{copy}}</1> сообщение для подписи на <2>etherscan</2>",
"copy_message_etherscan": "Скопируйте сообщение для подписи на <1>etherscan</1>",
"account": "аккаунт",
"crypto_address": "адрес криптовалюты",
"crypto_wallets": "Криптокошельки",
@@ -113,5 +113,6 @@
"export": "экспортировать",
"full_account_data": "полные данные аккаунта",
"this_account": "этот аккаунт",
"delete": "удалить"
"delete": "удалить",
"delete_account": "удалить аккаунт"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projekte",
"challenge_counter": "{{index}} nga {{total}}",
"embed": "integro",
"remove": "Hiqni",
"remove": "hiq",
"download_latest_desktop": "Shkarko versionin më të ri të desktopit këtu: {{link}}",
"new_stable_version": "Version i ri i qëndrueshëm është në dispozicion, plebchan v{{newVersion}}. Ju po përdorni plebchan v{{oldVersion}}.",
"refresh_to_update": "Rifresko faqen për të rifreskuar",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Adresa e kriptovalutës i përket një llogarie tjetër.",
"enter_crypto_address": "Ju lutemi vendosni një adresë kripto të vlefshme.",
"crypto_address_not_resolved": "Adresa e kriptovalutës nuk është ende e zgjidhur.",
"copy_message_etherscan": "<1>{{copy}}</1> mesazh për nënshkrim në <2>etherscan</2>",
"copy_message_etherscan": "Kopjoni mesazhin për nënshkruar në <1>etherscan</1>",
"account": "llogari",
"crypto_address": "adresa e kripto",
"crypto_wallets": "Portofolitë e cryptos",
@@ -113,5 +113,6 @@
"export": "eksport",
"full_account_data": "të dhënat e plotë të llogarisë",
"this_account": "kjo llogaria",
"delete": "fshij"
"delete": "fshij",
"delete_account": "fshi llogarinë"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projekt",
"challenge_counter": "{{index}} av {{total}}",
"embed": "bädda in",
"remove": "Ta bort",
"remove": "ta bort",
"download_latest_desktop": "Ladda ner den senaste skrivbordsversionen här: {{link}}",
"new_stable_version": "Ny stabil version tillgänglig, plebchan v{{newVersion}}. Du använder plebchan v{{oldVersion}}.",
"refresh_to_update": "Uppdatera sidan för att uppdatera",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Crypto-adress tillhör ett annat konto.",
"enter_crypto_address": "Ange en giltig kryptoadress.",
"crypto_address_not_resolved": "Crypto-adressen är ännu inte löst.",
"copy_message_etherscan": "<1>{{copy}}</1> meddelande att signera på <2>etherscan</2>",
"copy_message_etherscan": "Kopiera meddelande för att signera på <1>etherscan</1>",
"account": "konto",
"crypto_address": "kryptoadress",
"crypto_wallets": "Crypto-plånböcker",
@@ -113,5 +113,6 @@
"export": "exportera",
"full_account_data": "fullständig kontodata",
"this_account": "detta konto",
"delete": "ta bort"
"delete": "ta bort",
"delete_account": "ta bort konto"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "క్రిప్టో చిరునామా మరొక ఖాతాకు చేరుకుంది.",
"enter_crypto_address": "దయచేసి చేసిన క్రిప్టో చిరునామాను నమోదు చేయండి.",
"crypto_address_not_resolved": "క్రిప్టో చిరునామా ఇంకా పరిష్కరించబడలేదు.",
"copy_message_etherscan": "<1>{{copy}}</1> సందేశం సాఇన్ చేయడానికి <2>etherscan</2> మీద",
"copy_message_etherscan": "<1>etherscan</1> లో సైన్ చేయడానికి సందేశాన్ని కాపీ చేయండి",
"account": "ఖాతా",
"crypto_address": "క్రిప్టో చిరునామా",
"crypto_wallets": "క్రిప్టో వాలెట్‌లు",
@@ -113,5 +113,6 @@
"export": "ఎగుమతి",
"full_account_data": "పూర్తి ఖాతా డేటా",
"this_account": "ఈ ఖాతా",
"delete": "తొలగించండి"
"delete": "తొలగించండి",
"delete_account": "ఖాతాను తొలగించు"
}
+3 -2
View File
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "ที่อยู่คริปโตเป็นของบัญชีอื่น",
"enter_crypto_address": "โปรดป้อนที่อยู่คริปโตที่ถูกต้อง",
"crypto_address_not_resolved": "ที่อยู่คริปโตยังไม่ได้รับการแก้ไข",
"copy_message_etherscan": "<1>{{copy}}</1> ข้อความเพื่อเซ็นบน <2>etherscan</2>",
"copy_message_etherscan": "คัดลอกข้อความเพื่อลงนามบน <1>etherscan</1>",
"account": "บัญชี",
"crypto_address": "ที่อยู่คริปโต",
"crypto_wallets": "กระเป๋าเงินดิจิทัล",
@@ -113,5 +113,6 @@
"export": "ส่งออก",
"full_account_data": "ข้อมูลบัญชีเต็มรูปแบบ",
"this_account": "บัญชีนี้",
"delete": "ลบ"
"delete": "ลบ",
"delete_account": "ลบบัญชี"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "projeler",
"challenge_counter": "{{index}} / {{total}}",
"embed": "göm",
"remove": "Kaldır",
"remove": "kaldır",
"download_latest_desktop": "Son masaüstü sürümünü buradan indirin: {{link}}",
"new_stable_version": "Yeni stabil sürüm kullanılabilir, plebchan v{{newVersion}}. plebchan v{{oldVersion}} kullanıyorsunuz.",
"refresh_to_update": "Güncellemek için sayfayı yenileyin",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Kripto adres başka bir hesaba aittir.",
"enter_crypto_address": "Lütfen geçerli bir kripto adresi girin.",
"crypto_address_not_resolved": "Kripto adres henüz çözülmedi.",
"copy_message_etherscan": "<1>{{copy}}</1> <2>etherscan</2> üzerinde imzalanacak mesaj",
"copy_message_etherscan": "<1>etherscan</1> üzerinde imzalamak için mesajı kopyala",
"account": "hesap",
"crypto_address": "kripto adres",
"crypto_wallets": "Kripto Cüzdanlar",
@@ -113,5 +113,6 @@
"export": "dışa aktar",
"full_account_data": "tam hesap verisi",
"this_account": "bu hesap",
"delete": "sil"
"delete": "sil",
"delete_account": "hesabı sil"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "проекти",
"challenge_counter": "{{index}} з {{total}}",
"embed": "вбудувати",
"remove": "Видалити",
"remove": "видалити",
"download_latest_desktop": "Завантажте останню версію для робочого столу тут: {{link}}",
"new_stable_version": "Нова стабільна версія доступна, plebchan v{{newVersion}}. Ви використовуєте plebchan v{{oldVersion}}.",
"refresh_to_update": "Оновіть сторінку, щоб оновити",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Адреса криптовалюти належить до іншого облікового запису.",
"enter_crypto_address": "Будь ласка, введіть дійсну криптовалютну адресу.",
"crypto_address_not_resolved": "Адреса криптовалюти ще не вирішена.",
"copy_message_etherscan": "<1>{{copy}}</1> повідомлення для підпису на <2>etherscan</2>",
"copy_message_etherscan": "Скопіюйте повідомлення для підпису на <1>etherscan</1>",
"account": "рахунок",
"crypto_address": "адреса криптовалюти",
"crypto_wallets": "Криптокошельки",
@@ -113,5 +113,6 @@
"export": "експортувати",
"full_account_data": "повні дані аккаунта",
"this_account": "цей аккаунт",
"delete": "видалити"
"delete": "видалити",
"delete_account": "видалити обліковий запис"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "منصوبے",
"challenge_counter": "{{index}} میں سے {{total}}",
"embed": "ایمبیڈ",
"remove": "ہٹا دو",
"remove": "ہٹائیں",
"download_latest_desktop": "یہاں سب سے تازہ ڈیسک ٹاپ ورژن ڈاؤن لوڈ کریں: {{link}}",
"new_stable_version": "نیو مستقر ورژن دستیاب ہے, plebchan v{{newVersion}}۔ آپ plebchan v{{oldVersion}} استعمال کر رہے ہیں۔",
"refresh_to_update": "اپ ڈیٹ کرنے کے لئے صفحہ تازہ کریں",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "کرپٹو پتا دوسرے اکاؤنٹ کا حصہ ہے۔",
"enter_crypto_address": "براہ کرم ایک معتبر کرپٹو پتہ داخل کریں۔",
"crypto_address_not_resolved": "کرپٹو پتا ابھی تک حل نہیں ہوا ہے۔",
"copy_message_etherscan": "<1>{{copy}}</1> پیغام <2>etherscan</2> پر دستخط کریں",
"copy_message_etherscan": "<1>etherscan</1> پر دستخط کرنے کے لیے پیغام کاپی کریں",
"account": "اکاؤنٹ",
"crypto_address": "کرپٹو پتہ",
"crypto_wallets": "کرپٹو والٹس",
@@ -113,5 +113,6 @@
"export": "برآمد کریں",
"full_account_data": "مکمل اکاؤنٹ ڈیٹا",
"this_account": "یہ اکاؤنٹ",
"delete": "حذف کریں"
"delete": "حذف کریں",
"delete_account": "اکاؤنٹ حذف کریں"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "dự án",
"challenge_counter": "{{index}} trong {{total}}",
"embed": "nhúng",
"remove": "Xóa bỏ",
"remove": "xóa",
"download_latest_desktop": "Tải xuống phiên bản máy tính để bàn mới nhất tại đây: {{link}}",
"new_stable_version": "Phiên bản ổn định mới có sẵn, plebchan v{{newVersion}}. Bạn đang sử dụng plebchan v{{oldVersion}}.",
"refresh_to_update": "Làm mới trang để cập nhật",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "Địa chỉ tiền điện tử thuộc về một tài khoản khác.",
"enter_crypto_address": "Vui lòng nhập địa chỉ tiền điện tử hợp lệ.",
"crypto_address_not_resolved": "Địa chỉ tiền điện tử vẫn chưa được giải quyết.",
"copy_message_etherscan": "<1>{{copy}}</1> tin nhắn để ký trên <2>etherscan</2>",
"copy_message_etherscan": "Sao chép tin nhắn để ký trên <1>etherscan</1>",
"account": "tài khoản",
"crypto_address": "địa chỉ tiền điện tử",
"crypto_wallets": "Ví tiền điện tử",
@@ -113,5 +113,6 @@
"export": "xuất",
"full_account_data": "dữ liệu tài khoản đầy đủ",
"this_account": "tài khoản này",
"delete": "xóa"
"delete": "xóa",
"delete_account": "xóa tài khoản"
}
+4 -3
View File
@@ -75,7 +75,7 @@
"projects": "项目",
"challenge_counter": "{{index}} / {{total}}",
"embed": "嵌入",
"remove": "除",
"remove": "除",
"download_latest_desktop": "在这里下载最新的桌面版本: {{link}}",
"new_stable_version": "新的稳定版可用,plebchan v{{newVersion}}。您正在使用plebchan v{{oldVersion}}。",
"refresh_to_update": "刷新页面以更新",
@@ -103,7 +103,7 @@
"crypto_address_not_yours": "加密地址属于另一个帐户。",
"enter_crypto_address": "请输入有效的加密货币地址。",
"crypto_address_not_resolved": "加密地址尚未解析。",
"copy_message_etherscan": "<1>{{copy}}</1> 在<2>etherscan</2>上签名的消息",
"copy_message_etherscan": "复制消息以在<1>etherscan</1>上签名",
"account": "帐户",
"crypto_address": "加密地址",
"crypto_wallets": "加密货币钱包",
@@ -113,5 +113,6 @@
"export": "导出",
"full_account_data": "完整帐户数据",
"this_account": "此帐户",
"delete": "删除"
"delete": "删除",
"delete_account": "删除账户"
}
+333 -440
View File
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Link, useLocation, useParams } from 'react-router-dom';
import { Trans, useTranslation } from 'react-i18next';
import { Role, useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks';
@@ -20,6 +20,8 @@ import { getDisplayMediaInfoType } from '../../lib/utils/media-utils';
interface PostProps {
index?: number;
isInPostPage?: boolean;
isPendingPostPage?: boolean;
post?: any;
reply?: any;
roles?: Role[];
@@ -27,46 +29,215 @@ interface PostProps {
openReplyModal?: (cid: string) => void;
}
const PostDesktop = ({ openReplyModal, post, roles, showAllReplies }: PostProps) => {
const PostInfoDesktop = ({ isInPostPage, openReplyModal, post, roles }: PostProps) => {
const { t } = useTranslation();
const { author, cid, content, link, linkHeight, linkWidth, locked, pinned, postCid, replyCount, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
const { author, cid, locked, pinned, parentCid, postCid, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
const { address, displayName, shortAddress } = author || {};
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const authorRole = roles?.[address]?.role;
const { isDescription, isRules } = post || {}; // custom properties, not from api
const params = useParams();
const location = useLocation();
const isInPostPage = isPostPageView(location.pathname, params);
const isPendingPostPage = isPendingPostView(location.pathname, params);
const stateString = useStateString(post);
const isReply = parentCid;
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const authorRole = roles?.[address]?.role;
const displayTitle = title && title.length > 75 ? title?.slice(0, 75) + '...' : title;
const displayContent = content && !isInPostPage && content.length > 1000 ? content?.slice(0, 1000) + '(...)' : content;
// pending reply by account is not yet published
const account = useAccount();
const accountShortAddress = account?.author?.shortAddress;
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
const menuRef = useRef<HTMLDivElement>(null);
const handleMenuButtonClick = () => {
setMenuBtnRotated((prev) => !prev);
};
const handleClickOutside = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
setMenuBtnRotated(false);
}
};
useEffect(() => {
if (menuBtnRotated) {
document.addEventListener('mousedown', handleClickOutside);
} else {
document.removeEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [menuBtnRotated]);
return (
<div className={styles.postInfo}>
<span className={styles.checkbox}>
<input type='checkbox' />
</span>
{title && <span className={styles.subject}>{displayTitle} </span>}
<span className={styles.nameBlock}>
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
</span>
{!(isDescription || isRules) && <span className={styles.userAddress}>(u/{shortAddress || accountShortAddress}) </span>}
</span>
<span className={styles.dateTime}>
{getFormattedDate(timestamp)}
{isDescription || isRules ? '' : ' '}
</span>
<span className={styles.postNum}>
{!(isDescription || isRules) && (
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} className={styles.linkToPost} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
c/
</Link>
{!cid ? (
<span className={styles.pendingCid}>{state === 'failed' || stateString === 'Failed' ? 'Failed' : 'Pending'}</span>
) : (
<span className={styles.replyToPost} title={t('reply_to_post')} onClick={() => openReplyModal && openReplyModal(cid)}>
{shortCid}
</span>
)}
</span>
)}
{pinned && (
<span className={`${styles.stickyIconWrapper} ${!locked && styles.addPaddingBeforeReply}`}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
)}
{locked && (
<span className={`${styles.closedIconWrapper} ${styles.addPaddingBeforeReply} ${pinned && styles.addPaddingInBetween}`}>
<img src='assets/icons/closed.gif' alt='' className={styles.closedIcon} title={t('closed')} />
</span>
)}
{!isInPostPage && !isReply && (
<span className={styles.replyButton}>
[<Link to={`/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${postCid}`}`}>{t('reply')}</Link>]
</span>
)}
</span>
<span className={styles.postMenuBtnWrapper} ref={menuRef}>
<span className={styles.postMenuBtn} title='Post menu' onClick={handleMenuButtonClick} style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }}>
</span>
</span>
</div>
);
};
const PostMediaDesktop = ({ post }: PostProps) => {
const { t } = useTranslation();
const { link, linkHeight, linkWidth, parentCid } = 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 [showThumbnail, setShowThumbnail] = useState(true);
const isReply = parentCid;
return (
url && (
<div className={styles.file}>
<div className={styles.fileText}>
{t('link')}:{' '}
<a href={url} target='_blank' rel='noopener noreferrer'>
{url.length > 30 ? url.slice(0, 30) + '...' : url}
</a>{' '}
({type && _.lowerCase(getDisplayMediaInfoType(type, t))})
{!showThumbnail && (type === 'iframe' || type === 'video' || type === 'audio') && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(true)}>
{t('close')}
</span>
]
</span>
)}
{showThumbnail && !hasThumbnail && embedUrl && canEmbed(embedUrl) && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(false)}>
{t('open')}
</span>
]
</span>
)}
</div>
{(hasThumbnail || (!hasThumbnail && !showThumbnail)) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
isReply={isReply}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
</div>
)
);
};
const PostMessageDesktop = ({ isInPostPage, post }: PostProps) => {
const { cid, content, parentCid, postCid, state, subplebbitAddress } = post || {};
const displayContent = content && !isInPostPage && content.length > 1000 ? content?.slice(0, 1000) + '(...)' : content;
const isReply = parentCid;
const isReplyingToReply = postCid !== parentCid;
const stateString = useStateString(post);
const loadingString = stateString && (
<div className={`${styles.stateString} ${styles.ellipsis}`}>{stateString !== 'Failed' ? <LoadingEllipsis string={stateString} /> : stateString}</div>
);
return (
content && (
<blockquote className={styles.postMessage}>
{isReply && isReplyingToReply && (
<>
<Link to={`/p/${subplebbitAddress}/c/${parentCid}`} className={styles.quoteLink}>
{`c/${parentCid && Plebbit.getShortCid(parentCid)}`}
</Link>
<br />
</>
)}
<Markdown content={displayContent} />
{!isReply && content.length > 1000 && !isInPostPage && (
<span className={styles.abbr}>
<br />
<Trans i18nKey={'comment_too_long'} shouldUnescape={true} components={{ 1: <Link to={`/p/${subplebbitAddress}/c/${cid}`} /> }} />
</span>
)}
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)
);
};
const PostDesktop = ({ isInPostPage, isPendingPostPage, openReplyModal, post, roles, showAllReplies }: PostProps) => {
const { cid, content, pinned, replyCount, subplebbitAddress } = post || {};
const { isDescription, isRules } = post || {}; // custom properties, not from api
const replies = useReplies(post);
const visiblelinksCount = useCountLinksInReplies(post, 5);
const totallinksCount = useCountLinksInReplies(post);
const repliesCount = pinned ? replyCount : replyCount - 5;
const linksCount = pinned ? totallinksCount : totallinksCount - visiblelinksCount;
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
// pending reply by account is not yet published
const account = useAccount();
const accountShortAddress = account?.author?.shortAddress;
const stateString = useStateString(post);
const loadingString = stateString && (
<div className={`${styles.stateString} ${styles.ellipsis}`}>{stateString !== 'Failed' ? <LoadingEllipsis string={stateString} /> : stateString}</div>
);
return (
<div className={styles.postDesktop}>
<div className={styles.hrWrapper}>
@@ -77,124 +248,10 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies }: PostProps)
<span className={`${styles.hideButton} ${styles.hideThread}`} />
</span>
)}
{url && (
<div className={styles.file}>
<div className={styles.fileText}>
{t('link')}:{' '}
<a href={url} target='_blank' rel='noopener noreferrer'>
{url.length > 30 ? url.slice(0, 30) + '...' : url}
</a>{' '}
({type && _.lowerCase(getDisplayMediaInfoType(type, t))})
{!showThumbnail && (type === 'iframe' || type === 'video' || type === 'audio') && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(true)}>
{t('close')}
</span>
]
</span>
)}
{showThumbnail && !hasThumbnail && embedUrl && canEmbed(embedUrl) && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(false)}>
{t('open')}
</span>
]
</span>
)}
</div>
{(hasThumbnail || (!hasThumbnail && !showThumbnail)) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
isReply={false}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
</div>
)}
<div className={styles.postInfo}>
<span className={styles.checkbox}>
<input type='checkbox' />
</span>
{title && <span className={styles.subject}>{displayTitle} </span>}
<span className={styles.nameBlock}>
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
</span>
{!(isDescription || isRules) && <span className={styles.userAddress}>(u/{shortAddress || accountShortAddress}) </span>}
</span>
<span className={styles.dateTime}>
{getFormattedDate(timestamp)}
{isDescription || isRules ? '' : ' '}
</span>
<span className={styles.postNum}>
{!(isDescription || isRules) && (
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} className={styles.linkToPost} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
c/
</Link>
{!cid ? (
<span className={styles.pendingCid}>{state === 'failed' || stateString === 'Failed' ? 'Failed' : 'Pending'}</span>
) : (
<span className={styles.replyToPost} title={t('reply_to_post')} onClick={() => openReplyModal && openReplyModal(cid)}>
{shortCid}
</span>
)}
</span>
)}
{pinned && (
<span className={`${styles.stickyIconWrapper} ${!locked && styles.addPaddingBeforeReply}`}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
)}
{locked && (
<span className={`${styles.closedIconWrapper} ${styles.addPaddingBeforeReply} ${pinned && styles.addPaddingInBetween}`}>
<img src='assets/icons/closed.gif' alt='' className={styles.closedIcon} title={t('closed')} />
</span>
)}
{!isInPostPage && (
<span className={styles.replyButton}>
[<Link to={`/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${postCid}`}`}>{t('reply')}</Link>]
</span>
)}
</span>
<span className={styles.postMenuBtnWrapper}>
<span
className={styles.postMenuBtn}
title='Post menu'
onClick={() => setMenuBtnRotated(!menuBtnRotated)}
style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }}
>
</span>
</span>
</div>
<PostMediaDesktop post={post} />
<PostInfoDesktop isInPostPage={isInPostPage} isPendingPostPage={isPendingPostPage} openReplyModal={openReplyModal} post={post} roles={roles} />
{!content && <div className={styles.spacer} />}
{content && (
<blockquote className={styles.postMessage}>
<Markdown content={displayContent} />
{content.length > 1000 && !isInPostPage && (
<span className={styles.abbr}>
<br />
<Trans i18nKey={'comment_too_long'} shouldUnescape={true} components={{ 1: <Link to={`/p/${subplebbitAddress}/c/${cid}`} /> }} />
</span>
)}
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)}
<PostMessageDesktop isInPostPage={isInPostPage} post={post} />
{!isDescription && !isRules && !isPendingPostPage && (replies.length > 5 || (pinned && replies.length > 0)) && !isInPostPage && (
<span className={styles.summary}>
<span className={styles.expandButtonWrapper}>
@@ -219,56 +276,74 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies }: PostProps)
replies &&
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
<div key={index} className={styles.replyContainer}>
<ReplyDesktop index={index} reply={reply} roles={roles} openReplyModal={openReplyModal} />
<div className={styles.replyDesktop}>
<div className={styles.sideArrows}>{'>>'}</div>
<div className={styles.reply}>
<PostInfoDesktop isInPostPage={isInPostPage} isPendingPostPage={isPendingPostPage} openReplyModal={openReplyModal} post={reply} roles={roles} />
<PostMediaDesktop post={reply} />
<PostMessageDesktop isInPostPage={isInPostPage} post={reply} />
</div>
</div>
</div>
))}
</div>
);
};
const ReplyDesktop = ({ reply, roles, openReplyModal }: PostProps) => {
const PostInfoAndMediaMobile = ({ openReplyModal, post, roles }: PostProps) => {
const { t } = useTranslation();
const { author, cid, content, link, linkHeight, linkWidth, parentCid, pinned, postCid, shortCid, state, subplebbitAddress, timestamp } = reply || {};
const { author, cid, link, linkHeight, linkWidth, locked, parentCid, pinned, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
const { isDescription, isRules } = post || {}; // custom properties, not from api
const { address, displayName, shortAddress } = author || {};
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const authorRole = roles?.[address]?.role;
const commentMediaInfo = getCommentMediaInfo(reply);
const { type, url } = commentMediaInfo || {};
const embedUrl = url && new URL(url);
const authorRole = roles?.[address]?.role;
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const displayTitle = title && title.length > 30 ? title?.slice(0, 30) + '(...)' : title;
const commentMediaInfo = getCommentMediaInfo(post);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
const [showThumbnail, setShowThumbnail] = useState(true);
const isReplyingToReply = postCid !== parentCid;
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
const stateString = useStateString(reply);
const loadingString = stateString && (
<div className={`${styles.stateString} ${styles.ellipsis}`}>{stateString !== 'Failed' ? <LoadingEllipsis string={stateString} /> : stateString}</div>
);
const isReply = parentCid;
// pending reply by account is not yet published
const account = useAccount();
const accountShortAddress = account?.author?.shortAddress;
const stateString = useStateString(post);
return (
<div className={styles.replyDesktop}>
<div className={styles.sideArrows}>{'>>'}</div>
<div className={styles.reply}>
<div className={styles.postInfo}>
<span className={styles.checkbox}>
<input type='checkbox' />
<>
<div className={styles.postInfo}>
<span className={styles.postMenuBtn} title='Post menu'>
...
</span>
<span className={styles.nameBlock}>
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
</span>
<span className={styles.nameBlock}>
<span className={`${styles.name} ${authorRole && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
{!(isDescription || isRules) && <span className={styles.address}>(u/{shortAddress || accountShortAddress})</span>}
{pinned && (
<span className={styles.stickyIconWrapper}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
<span className={styles.userAddress}>(u/{shortAddress || accountShortAddress}) </span>
</span>
<span className={styles.dateTime}>{getFormattedDate(timestamp)} </span>
<span className={styles.postNum}>
)}
{locked && (
<span className={`${styles.closedIconWrapper} ${pinned && styles.addPaddingInBetween}`}>
<img src='assets/icons/closed.gif' alt='' className={styles.closedIcon} title={t('closed')} />
</span>
)}
{title && (
<>
<br />
<span className={styles.subject}>{displayTitle}</span>
</>
)}
</span>
<span className={styles.dateTimePostNum}>
{getFormattedDate(timestamp)}{' '}
{!(isDescription || isRules) && (
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} className={styles.linkToPost} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
c/
@@ -281,121 +356,75 @@ const ReplyDesktop = ({ reply, roles, openReplyModal }: PostProps) => {
</span>
)}
</span>
{pinned && (
<span className={styles.stickyIconWrapper}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
)}
</span>
<span className={styles.postMenuBtnWrapper}>
<span
className={styles.postMenuBtn}
title='Post menu'
onClick={() => setMenuBtnRotated(!menuBtnRotated)}
style={{ transform: menuBtnRotated ? 'rotate(90deg)' : 'rotate(0deg)' }}
>
</span>
</span>
</div>
{url && (
<div className={styles.file}>
<div className={styles.fileText}>
{t('link')}:{' '}
<a href={link} target='_blank' rel='noopener noreferrer'>
{link.length > 30 ? link?.slice(0, 30) + '...' : link}
</a>{' '}
({type && _.lowerCase(getDisplayMediaInfoType(type, t))})
{!showThumbnail && (type === 'iframe' || type === 'video' || type === 'audio') && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(true)}>
{t('close')}
</span>
]
</span>
)}
{showThumbnail && !hasThumbnail && embedUrl && canEmbed(embedUrl) && (
<span>
{' '}
[
<span className={styles.closeMedia} onClick={() => setShowThumbnail(false)}>
{t('open')}
</span>
]
</span>
)}
</div>
{(hasThumbnail || (!hasThumbnail && !showThumbnail)) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isReply={true}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
</div>
)}
{content && (
<blockquote className={styles.postMessage}>
{isReplyingToReply && (
<>
<Link to={`/p/${subplebbitAddress}/c/${parentCid}`} className={styles.quoteLink}>
{`c/${parentCid && Plebbit.getShortCid(parentCid)}`}
</Link>
<br />
</>
)}
<Markdown content={content} />
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)}
)}
</span>
</div>
</div>
{(hasThumbnail || link) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
isReply={isReply}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
</>
);
};
const PostMobile = ({ openReplyModal, post, roles, showAllReplies }: PostProps) => {
const { t } = useTranslation();
const { author, cid, content, link, linkHeight, linkWidth, locked, pinned, replyCount, shortCid, state, subplebbitAddress, timestamp, title } = post || {};
const { address, displayName, shortAddress } = author || {};
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const authorRole = roles?.[address]?.role;
const { isDescription, isRules } = post || {}; // custom properties, not from api
const params = useParams();
const location = useLocation();
const isInPostPage = isPostPageView(location.pathname, params);
const isPendingPostPage = isPendingPostView(location.pathname, params);
const linksCount = useCountLinksInReplies(post);
const displayTitle = title && title.length > 30 ? title?.slice(0, 30) + '(...)' : title;
const PostMessageMobile = ({ isInPostPage, post }: PostProps) => {
const { cid, content, parentCid, postCid, state, subplebbitAddress } = post || {};
const displayContent = content && !isInPostPage && content.length > 1000 ? content?.slice(0, 1000) : content;
const commentMediaInfo = getCommentMediaInfo(post);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
const [showThumbnail, setShowThumbnail] = useState(true);
const replies = useReplies(post);
// pending reply by account is not yet published
const account = useAccount();
const accountShortAddress = account?.author?.shortAddress;
const isReply = parentCid;
const isReplyingToReply = postCid !== parentCid;
const stateString = useStateString(post);
const loadingString = stateString && (
<div className={`${styles.stateString} ${styles.ellipsis}`}>{stateString !== 'Failed' ? <LoadingEllipsis string={stateString} /> : stateString}</div>
);
return (
content && (
<blockquote className={`${styles.postMessage} ${!isReply && styles.clampLines}`}>
{isReply && isReplyingToReply && (
<>
<Link to={`/p/${subplebbitAddress}/c/${parentCid}`} className={styles.quoteLink}>
{`c/${parentCid && Plebbit.getShortCid(parentCid)}`}
</Link>
<br />
</>
)}
<Markdown content={displayContent} />
{!isReply && content.length > 1000 && !isInPostPage && (
<span className={styles.abbr}>
<br />
<Trans i18nKey={'comment_too_long'} shouldUnescape={true} components={{ 1: <Link to={`/p/${subplebbitAddress}/c/${cid}`} /> }} />
</span>
)}
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)
);
};
const PostMobile = ({ isInPostPage, isPendingPostPage, openReplyModal, post, roles, showAllReplies }: PostProps) => {
const { t } = useTranslation();
const { cid, pinned, replyCount, subplebbitAddress } = post || {};
const { isDescription, isRules } = post || {}; // custom properties, not from api
const linksCount = useCountLinksInReplies(post);
const replies = useReplies(post);
return (
<div className={styles.postMobile}>
<div className={styles.hrWrapper}>
@@ -404,79 +433,8 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies }: PostProps)
<div className={styles.thread}>
<div className={styles.postContainer}>
<div className={styles.postOp}>
<div className={styles.postInfo}>
<span className={styles.postMenuBtn} title='Post menu'>
...
</span>
<span className={styles.nameBlock}>
<span className={`${styles.name} ${(isDescription || isRules || authorRole) && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
</span>
{!(isDescription || isRules) && <span className={styles.address}>(u/{shortAddress || accountShortAddress})</span>}
{pinned && (
<span className={styles.stickyIconWrapper}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
)}
{locked && (
<span className={`${styles.closedIconWrapper} ${pinned && styles.addPaddingInBetween}`}>
<img src='assets/icons/closed.gif' alt='' className={styles.closedIcon} title={t('closed')} />
</span>
)}
{title && (
<>
<br />
<span className={styles.subject}>{displayTitle}</span>
</>
)}
</span>
<span className={styles.dateTimePostNum}>
{getFormattedDate(timestamp)}{' '}
{!(isDescription || isRules) && (
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} className={styles.linkToPost} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
c/
</Link>
{!cid ? (
<span className={styles.pendingCid}>{state === 'failed' || stateString === 'Failed' ? 'Failed' : 'Pending'}</span>
) : (
<span className={styles.replyToPost} title={t('reply_to_post')} onClick={() => openReplyModal && openReplyModal(cid)}>
{shortCid}
</span>
)}
</span>
)}
</span>
</div>
{(hasThumbnail || link) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isOutOfFeed={isDescription || isRules} // virtuoso wrapper unneeded
isReply={false}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
{content && (
<blockquote className={`${styles.postMessage} ${styles.clampLines}`}>
<Markdown content={displayContent} />
{content.length > 1000 && !isInPostPage && (
<span className={styles.abbr}>
<br />
<Trans i18nKey={'comment_too_long'} shouldUnescape={true} components={{ 1: <Link to={`/p/${subplebbitAddress}/c/${cid}`} /> }} />
</span>
)}
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)}
<PostInfoAndMediaMobile openReplyModal={openReplyModal} post={post} roles={roles} />
<PostMessageMobile isInPostPage={isInPostPage} post={post} />
</div>
{!isInPostPage && !isPendingPostPage && (
<div className={styles.postLink}>
@@ -495,9 +453,16 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies }: PostProps)
!isDescription &&
!isRules &&
replies &&
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
(showAllReplies ? replies : replies.slice(-5)).map((reply) => (
<div key={reply.cid} className={styles.replyContainer}>
<ReplyMobile index={index} reply={reply} roles={roles} openReplyModal={openReplyModal} />
<div className={styles.replyMobile}>
<div className={styles.reply}>
<div className={styles.replyContainer}>
<PostInfoAndMediaMobile openReplyModal={openReplyModal} post={reply} roles={roles} />
<PostMessageMobile isInPostPage={isInPostPage} post={reply} />
</div>
</div>
</div>
</div>
))}
</div>
@@ -505,108 +470,36 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies }: PostProps)
);
};
const ReplyMobile = ({ reply, roles, openReplyModal }: PostProps) => {
const { t } = useTranslation();
const { author, content, cid, link, linkHeight, linkWidth, parentCid, pinned, postCid, shortCid, state, subplebbitAddress, timestamp } = reply || {};
const { address, displayName, shortAddress } = author || {};
const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim();
const authorRole = roles?.[address]?.role;
const commentMediaInfo = getCommentMediaInfo(reply);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
const [showThumbnail, setShowThumbnail] = useState(true);
const isReplyingToReply = postCid !== parentCid;
// pending reply by account is not yet published
const account = useAccount();
const accountShortAddress = account?.author?.shortAddress;
const stateString = useStateString(reply);
const loadingString = stateString && (
<div className={`${styles.stateString} ${styles.ellipsis}`}>{stateString !== 'Failed' ? <LoadingEllipsis string={stateString} /> : stateString}</div>
);
return (
<div className={styles.replyMobile}>
<div className={styles.reply}>
<div className={styles.replyContainer}>
<div className={styles.postInfo}>
<span className={styles.postMenuBtn}>...</span>
<span className={styles.nameBlock}>
<span className={`${styles.name} ${authorRole && styles.capcodeMod}`}>
{shortDisplayName || _.capitalize(t('anonymous'))}
{authorRole && ` ## Board ${authorRole}`}{' '}
</span>
<span className={styles.address}>(u/{shortAddress || accountShortAddress})</span>
{pinned && (
<span className={styles.stickyIconWrapper}>
<img src='assets/icons/sticky.gif' alt='' className={styles.stickyIcon} title={t('sticky')} />
</span>
)}
</span>
<span className={styles.dateTimePostNum}>
{getFormattedDate(timestamp)}{' '}
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
c/
</Link>
</span>
{!cid ? (
<span className={styles.pendingCid}>{state === 'failed' || stateString === 'Failed' ? 'Failed' : 'Pending'}</span>
) : (
<span className={styles.replyToPost} title={t('reply_to_post')} onClick={() => openReplyModal && openReplyModal(cid)}>
{shortCid}
</span>
)}
</span>
</div>
{(hasThumbnail || link) && (
<CommentMedia
commentMediaInfo={commentMediaInfo}
isReply={false}
linkHeight={linkHeight}
linkWidth={linkWidth}
showThumbnail={showThumbnail}
setShowThumbnail={setShowThumbnail}
/>
)}
{content && (
<blockquote className={styles.postMessage}>
{isReplyingToReply && (
<>
<Link to={`/p/${subplebbitAddress}/c/${parentCid}`} className={styles.quoteLink}>
{`c/${parentCid && Plebbit.getShortCid(parentCid)}`}
</Link>
<br />
</>
)}
<Markdown content={content} />
{!cid && state === 'pending' && stateString !== 'Failed' && (
<>
<br />
{loadingString}
</>
)}
</blockquote>
)}
</div>
</div>
</div>
);
};
const Post = ({ post, showAllReplies = false, openReplyModal }: PostProps) => {
const subplebbit = useSubplebbit({ subplebbitAddress: post?.subplebbitAddress });
const isMobile = useWindowWidth() < 640;
const params = useParams();
const location = useLocation();
const isInPostPage = isPostPageView(location.pathname, params);
const isPendingPostPage = isPendingPostView(location.pathname, params);
return (
<div className={styles.thread}>
<div className={styles.postContainer}>
{isMobile ? (
<PostMobile post={post} roles={subplebbit?.roles} showAllReplies={showAllReplies} openReplyModal={openReplyModal} />
<PostMobile
isInPostPage={isInPostPage}
isPendingPostPage={isPendingPostPage}
post={post}
roles={subplebbit?.roles}
showAllReplies={showAllReplies}
openReplyModal={openReplyModal}
/>
) : (
<PostDesktop post={post} roles={subplebbit?.roles} showAllReplies={showAllReplies} openReplyModal={openReplyModal} />
<PostDesktop
isInPostPage={isInPostPage}
isPendingPostPage={isPendingPostPage}
post={post}
roles={subplebbit?.roles}
showAllReplies={showAllReplies}
openReplyModal={openReplyModal}
/>
)}
</div>
</div>
@@ -34,8 +34,10 @@
margin-top: 5px;
}
.deleteAccount, .deleteAccount button {
.deleteAccount {
color: red;
display: block;
margin-top: 10px;
}
.setting .createAccount {
@@ -165,16 +165,11 @@ const AccountSettings = () => {
<div></div>
<textarea value={text} onChange={(e) => setText(e.target.value)} autoCorrect='off' autoComplete='off' spellCheck='false' />
<div>
<button onClick={saveAccount}>{t('save')}</button> <button onClick={() => setText(accountJson)}>{t('reset')}</button>
</div>
<div>
<button onClick={_importAccount}>{t('import')}</button> {t('full_account_data')}
</div>
<div>
<button onClick={_exportAccount}>{t('export')}</button> {t('full_account_data')}
</div>
<div className={styles.deleteAccount}>
<button onClick={() => _deleteAccount(account?.name)}>{t('delete')}</button> {t('this_account')}
<button onClick={saveAccount}>{t('save')}</button> <button onClick={() => setText(accountJson)}>{t('reset')}</button>{' '}
<button onClick={_importAccount}>{t('import')}</button> <button onClick={_exportAccount}>{t('export')}</button>{' '}
<button className={styles.deleteAccount} onClick={() => _deleteAccount(account?.name)}>
{t('delete_account')}
</button>
</div>
</div>
);
@@ -8,7 +8,7 @@
}
.cryptoAddressInput input[type="text"] {
padding: 2px 0;
padding: 2px;
margin-bottom: 5px;
}
@@ -16,7 +16,7 @@
padding: 0 5px;
}
.cryptoAddressInfo {
.cryptoAddressInfo {
word-break: break-word;
}
@@ -25,6 +25,16 @@
padding-left: 15px;
}
.cryptoAddressInfo a {
color: var(--post-link-text-color);
text-decoration: var(--post-content-link-text-decoration);
}
.cryptoAddressInfo a:hover {
color: var(--post-link-text-color-hover);
text-decoration: var(--post-content-link-text-decoration-hover);
}
.saveButton {
margin: 0 5px;
}
@@ -11,7 +11,7 @@ const CryptoAddressSetting = () => {
cryptoAddress: '',
checkingCryptoAddress: false,
showResolvingMessage: false,
resolveString: t('crypto_address_verification'),
resolveString: '',
resolveClass: '',
});
@@ -1,5 +1,6 @@
.setting {
margin-left: 10px;
margin-bottom: 10px;
}
.addWallet select {
@@ -7,10 +8,6 @@
margin-bottom: 5px;
}
.save {
margin-left: 5px;
}
.walletTitle {
text-transform: lowercase;
font-style: italic;
@@ -18,13 +15,16 @@
.removeWallet {
color: red;
margin-top: 15px;
}
.walletFieldTitle {
.save {
margin-top: 10px;
margin-right: 5px;
}
.walletField {
margin-top: 5px;
font-style: italic;
text-transform: lowercase;
margin-left: 5px;
}
.walletField input {
@@ -33,6 +33,16 @@
box-shadow: var(--box-shadow-input);
}
.walletField a {
color: var(--post-link-text-color);
text-decoration: var(--post-content-link-text-decoration);
}
.walletField a:hover {
color: var(--post-link-text-color-hover);
text-decoration: var(--post-content-link-text-decoration-hover);
}
.copyMessage {
padding-top: 10px;
}
@@ -2,6 +2,7 @@ import { useState } from 'react';
import { Account, setAccount, useAccount } from '@plebbit/plebbit-react-hooks';
import styles from './crypto-wallets-setting.module.css';
import { Trans, useTranslation } from 'react-i18next';
import _ from 'lodash';
interface Wallet {
chainTicker: string;
@@ -89,11 +90,9 @@ const CryptoWalletsForm = ({ account }: { account: Account | undefined }) => {
const _removeWallet = (index: number) => {
const wallet = walletsArray[index];
if (window.confirm(t('delete_confirm', { value: wallet.chainTicker, interpolation: { escapeValue: false } }))) {
if (window.confirm(t('double_confirm'))) {
const newArray = [...walletsArray.slice(0, index), ...walletsArray.slice(index + 1)];
setWalletsArray(newArray);
setSelectedWallet(0);
}
const newArray = [...walletsArray.slice(0, index), ...walletsArray.slice(index + 1)];
setWalletsArray(newArray);
setSelectedWallet(0);
} else {
return;
}
@@ -103,7 +102,7 @@ const CryptoWalletsForm = ({ account }: { account: Account | undefined }) => {
walletsArray.length > 0 ? (
<div key={selectedWallet} className={styles.walletBox}>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('chain_ticker')}</div>
<span className={styles.walletFieldTitle}>{_.capitalize(t('chain_ticker'))}: </span>
<input
type='text'
onChange={(e) => setWalletsArrayProperty(selectedWallet, 'chainTicker', e.target.value)}
@@ -112,7 +111,7 @@ const CryptoWalletsForm = ({ account }: { account: Account | undefined }) => {
/>
</div>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('wallet_address')}</div>
<span className={styles.walletFieldTitle}>{_.capitalize(t('wallet_address'))}: </span>
<input
type='text'
onChange={(e) => setWalletsArrayProperty(selectedWallet, 'address', e.target.value)}
@@ -120,32 +119,36 @@ const CryptoWalletsForm = ({ account }: { account: Account | undefined }) => {
placeholder='0x...'
/>
</div>
<div className={`${styles.walletField} ${styles.copyMessage}`}>
<Trans
i18nKey='copy_message_etherscan'
values={{ copy: hasCopied ? t('copied') : t('copy') }}
components={{
1: <button onClick={() => copyMessageToSign(walletsArray[selectedWallet], selectedWallet)} />,
// eslint-disable-next-line
2: <a href='https://etherscan.io/verifiedSignatures' target='_blank' rel='noopener noreferrer' />,
}}
/>
<div className={styles.walletField}>
<span className={styles.walletFieldTitle}>
<Trans
i18nKey='copy_message_etherscan'
components={{
// eslint-disable-next-line
1: <a href='https://etherscan.io/verifiedSignatures' target='_blank' rel='noopener noreferrer' />,
}}
/>
:{' '}
</span>
<button onClick={() => copyMessageToSign(walletsArray[selectedWallet], selectedWallet)}>{hasCopied ? t('copied') : t('copy')}</button>
</div>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('paste_signature')}</div>
<span className={styles.walletFieldTitle}>{_.capitalize(t('paste_signature'))}: </span>
<input
type='text'
onChange={(e) => setWalletsArrayProperty(selectedWallet, 'signature', e.target.value)}
value={walletsArray[selectedWallet].signature}
placeholder='0x...'
/>
<button className={styles.save} onClick={save}>
{t('save')}
</button>
<div className={styles.buttons}>
<button className={styles.save} onClick={save}>
{t('save')}
</button>
<button className={styles.removeWallet} onClick={() => _removeWallet(selectedWallet)}>
{t('remove')}
</button>
</div>
</div>
<button className={styles.removeWallet} onClick={() => _removeWallet(selectedWallet)}>
{t('remove')}
</button>
</div>
) : null;
@@ -105,13 +105,13 @@ const InterfaceLanguage = () => {
);
};
const PlebbitOptionsSettings = () => {
return (
<>
<div className={styles.setting}></div>
</>
);
};
// const PlebbitOptionsSettings = () => {
// return (
// <>
// <div className={styles.setting}></div>
// </>
// );
// };
const SettingsModal = () => {
const { t } = useTranslation();
@@ -124,7 +124,7 @@ const SettingsModal = () => {
const [showAccountSettings, setShowAccountSettings] = useState(false);
const [showCryptoAddressSetting, setShowCryptoAddressSetting] = useState(false);
const [showCryptoWalletSettings, setShowCryptoWalletSettings] = useState(false);
const [showPlebbitOptionsSettings, setShowPlebbitOptionsSettings] = useState(false);
// const [showPlebbitOptionsSettings, setShowPlebbitOptionsSettings] = useState(false);
return (
<>
@@ -174,13 +174,13 @@ const SettingsModal = () => {
</label>
</div>
{showCryptoWalletSettings && <CryptoWalletsSetting />}
<div className={`${styles.setting} ${styles.category}`}>
{/* <div className={`${styles.setting} ${styles.category}`}>
<label onClick={() => setShowPlebbitOptionsSettings(!showPlebbitOptionsSettings)}>
<span className={showPlebbitOptionsSettings ? styles.hideButton : styles.showButton} />
{t('plebbit_options')}
</label>
</div>
{showPlebbitOptionsSettings && <PlebbitOptionsSettings />}
{showPlebbitOptionsSettings && <PlebbitOptionsSettings />} */}
</div>
</>
);