mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "قد يكون الرد على الرسائل غير متاح حالياً وقد تفشل النشر.",
|
||||
"posts_last_synced_info": "آخر تزامن الرسائل {{time}}، قد يكون الرد على الرسائل غير متاح حالياً وقد تفشل النشر.",
|
||||
"newer_than": "أحدث من",
|
||||
"no_posts": "لا توجد مشاركات"
|
||||
"no_posts": "لا توجد مشاركات",
|
||||
"unblock": "إلغاء الحظر",
|
||||
"unblock_all": "إلغاء حظر الكل",
|
||||
"blocked_addresses": "العناوين المحظورة",
|
||||
"you_have_not_blocked": "لم تقم بحظر أي عنوان للمجلس أو عنوان مستخدم.",
|
||||
"block_user": "حظر المستخدم",
|
||||
"unblock_user": "إلغاء حظر المستخدم",
|
||||
"block_board": "حظر المجلس",
|
||||
"unblock_board": "إلغاء حظر المجلس",
|
||||
"unblock_all_confirm": "هل أنت متأكد أنك تريد إلغاء حظر جميع عناوين المجالس وعناوين المستخدمين؟"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "সাবপ্লেবিট অফলাইন হতে পারে এবং প্রকাশনা ব্যর্থ হতে পারে।",
|
||||
"posts_last_synced_info": "পোস্টগুলি সর্বশেষ সিঙ্ক হয়েছে {{time}}, সাবপ্লেবিট অফলাইন হতে পারে এবং প্রকাশনা ব্যর্থ হতে পারে।",
|
||||
"newer_than": "নতুন পরে",
|
||||
"no_posts": "কোন পোস্ট নেই"
|
||||
"no_posts": "কোন পোস্ট নেই",
|
||||
"unblock": "অনবন্ধ করুন",
|
||||
"unblock_all": "সব আনবলক করুন",
|
||||
"blocked_addresses": "অবরোধিত ঠিকানা",
|
||||
"you_have_not_blocked": "আপনি কোনও বোর্ড ঠিকানা বা ব্যবহারকারী ঠিকানা বন্ধ করেন নি।",
|
||||
"block_user": "ব্যবহারকারী ব্লক",
|
||||
"unblock_user": "ব্যবহারকারী অনবন্ধ করুন",
|
||||
"block_board": "ফোরাম ব্লক",
|
||||
"unblock_board": "ফোরাম অনবন্ধ করুন",
|
||||
"unblock_all_confirm": "আপনি কি নিশ্চিত যে আপনি সমস্ত বোর্ড ঠিকানা এবং ব্যবহারকারী ঠিকানা অনবন্ধ করতে চান?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit může být offline a zveřejnění může selhat.",
|
||||
"posts_last_synced_info": "Poslední synchronizace příspěvků {{time}}, subplebbit může být offline a zveřejňování může selhat.",
|
||||
"newer_than": "novější než",
|
||||
"no_posts": "žádné příspěvky"
|
||||
"no_posts": "žádné příspěvky",
|
||||
"unblock": "Odblokovat",
|
||||
"unblock_all": "Odblokovat všechny",
|
||||
"blocked_addresses": "Blokované adresy",
|
||||
"you_have_not_blocked": "Neblokovali jste žádnou adresu desky ani adresu uživatele.",
|
||||
"block_user": "Blokovat uživatele",
|
||||
"unblock_user": "Odblokovat uživatele",
|
||||
"block_board": "Blokovat diskuzní fórum",
|
||||
"unblock_board": "Odblokovat diskuzní fórum",
|
||||
"unblock_all_confirm": "Jste si jisti, že chcete odblokovat všechny adresy diskuzních fór a adresy uživatelů?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbiten kan være offline, og offentliggørelse kan mislykkes.",
|
||||
"posts_last_synced_info": "Seneste synkroniserede indlæg {{time}}, subplebbiten kan være offline, og offentliggørelse kan mislykkes.",
|
||||
"newer_than": "nyere end",
|
||||
"no_posts": "ingen indlæg"
|
||||
"no_posts": "ingen indlæg",
|
||||
"unblock": "Fjern blokering",
|
||||
"unblock_all": "Fjern alle blokeringer",
|
||||
"blocked_addresses": "Blokerede adresser",
|
||||
"you_have_not_blocked": "Du har ikke blokeret nogen brætadresse eller brugeradresse.",
|
||||
"block_user": "Bloker bruger",
|
||||
"unblock_user": "Fjern blokering af bruger",
|
||||
"block_board": "Bloker forum",
|
||||
"unblock_board": "Fjern blokering af forum",
|
||||
"unblock_all_confirm": "Er du sikker på, at du vil ophæve blokeringen af alle boardadresser og brugeradresser?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Der Subplebbit könnte offline sein und das Veröffentlichen könnte fehlschlagen.",
|
||||
"posts_last_synced_info": "Beiträge zuletzt synchronisiert {{time}}, der Subplebbit könnte offline sein und das Veröffentlichen könnte fehlschlagen.",
|
||||
"newer_than": "neuer als",
|
||||
"no_posts": "keine Beiträge"
|
||||
"no_posts": "keine Beiträge",
|
||||
"unblock": "Entsperren",
|
||||
"unblock_all": "Alle entsperren",
|
||||
"blocked_addresses": "Blockierte Adressen",
|
||||
"you_have_not_blocked": "Sie haben keine Board-Adresse oder Benutzeradresse blockiert.",
|
||||
"block_user": "Benutzer blockieren",
|
||||
"unblock_user": "Benutzer entsperren",
|
||||
"block_board": "Forum blockieren",
|
||||
"unblock_board": "Forum entsperren",
|
||||
"unblock_all_confirm": "Möchten Sie wirklich alle Boardadressen und Benutzeradressen entsperren?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Το subplebbit ενδέχεται να είναι εκτός σύνδεσης και η δημοσίευση μπορεί να αποτύχει.",
|
||||
"posts_last_synced_info": "Τελευταία συγχρονισμένες αναρτήσεις {{time}}, το subplebbit ενδέχεται να είναι εκτός σύνδεσης και η δημοσίευση μπορεί να αποτύχει.",
|
||||
"newer_than": "πιο πρόσφατο από",
|
||||
"no_posts": "κανένα άρθρο"
|
||||
"no_posts": "κανένα άρθρο",
|
||||
"unblock": "Ξεκλείδωμα",
|
||||
"unblock_all": "Ξεκλειδώστε όλα",
|
||||
"blocked_addresses": "Αποκλεισμένες διευθύνσεις",
|
||||
"you_have_not_blocked": "Δεν έχετε αποκλείσει καμία διεύθυνση συμβουλίου ή χρήστη.",
|
||||
"block_user": "Αποκλεισμός χρήστη",
|
||||
"unblock_user": "Αποκλεισμός χρήστη αναίρεσης",
|
||||
"block_board": "Αποκλεισμός συμβουλίου",
|
||||
"unblock_board": "Αναίρεση αποκλεισμού συμβουλίου",
|
||||
"unblock_all_confirm": "Είστε σίγουροι ότι θέλετε να ξεκλειδώσετε όλες τις διευθύνσεις συμβουλίων και χρηστών;"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "The subplebbit might be offline and publishing might fail.",
|
||||
"posts_last_synced_info": "Posts last synced {{time}}, the subplebbit might be offline and publishing might fail.",
|
||||
"newer_than": "newer than",
|
||||
"no_posts": "no posts"
|
||||
"no_posts": "no posts",
|
||||
"unblock": "Unblock",
|
||||
"unblock_all": "Unblock all",
|
||||
"blocked_addresses": "Blocked addresses",
|
||||
"you_have_not_blocked": "You have not blocked any board address or user address.",
|
||||
"block_user": "Block user",
|
||||
"unblock_user": "Unblock user",
|
||||
"block_board": "Block board",
|
||||
"unblock_board": "Unblock board",
|
||||
"unblock_all_confirm": "Are you sure you want to unblock all board addresses and user addresses?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "El subplebbit podría estar fuera de línea y la publicación podría fallar.",
|
||||
"posts_last_synced_info": "Últimas publicaciones sincronizadas {{time}}, el subplebbit podría estar fuera de línea y la publicación podría fallar.",
|
||||
"newer_than": "más reciente que",
|
||||
"no_posts": "sin publicaciones"
|
||||
"no_posts": "sin publicaciones",
|
||||
"unblock": "Desbloquear",
|
||||
"unblock_all": "Desbloquear todo",
|
||||
"blocked_addresses": "Direcciones bloqueadas",
|
||||
"you_have_not_blocked": "No has bloqueado ninguna dirección de tablero o dirección de usuario.",
|
||||
"block_user": "Bloquear usuario",
|
||||
"unblock_user": "Desbloquear usuario",
|
||||
"block_board": "Bloquear foro",
|
||||
"unblock_board": "Desbloquear foro",
|
||||
"unblock_all_confirm": "¿Estás seguro de que quieres desbloquear todas las direcciones de foro y las direcciones de usuario?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "زیرپلبیت ممکن است آفلاین باشد و انتشار ممکن است شکست خورده باشد.",
|
||||
"posts_last_synced_info": "آخرین پستها همگامسازی شدهاند {{time}}، زیرپلبیت ممکن است آفلاین باشد و انتشار ممکن است شکست خورده باشد.",
|
||||
"newer_than": "جدیدتر از",
|
||||
"no_posts": "بدون پست"
|
||||
"no_posts": "بدون پست",
|
||||
"unblock": "رفع مسدودیت",
|
||||
"unblock_all": "رفع مسدودیت همه",
|
||||
"blocked_addresses": "آدرسهای مسدود شده",
|
||||
"you_have_not_blocked": "هیچ آدرس تالار یا آدرس کاربری را مسدود نکردهاید.",
|
||||
"block_user": "بلاک کاربر",
|
||||
"unblock_user": "آزاد کاربر",
|
||||
"block_board": "بلاک تالار",
|
||||
"unblock_board": "آزاد کردن تالار",
|
||||
"unblock_all_confirm": "آیا از می خواهید تمام آدرس های بورد و آدرس های کاربر را از مسدودیت خارج کنید؟"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit voi olla offline-tilassa, ja julkaisu voi epäonnistua.",
|
||||
"posts_last_synced_info": "Viimeksi synkronoidut viestit {{time}}, subplebbit voi olla offline-tilassa, ja julkaisu voi epäonnistua.",
|
||||
"newer_than": "uudempi kuin",
|
||||
"no_posts": "ei viestejä"
|
||||
"no_posts": "ei viestejä",
|
||||
"unblock": "Poista estäminen",
|
||||
"unblock_all": "Poista kaikki estot",
|
||||
"blocked_addresses": "Estetyt osoitteet",
|
||||
"you_have_not_blocked": "Et ole estänyt mitään hallituksen osoitetta tai käyttäjän osoitetta.",
|
||||
"block_user": "Estä käyttäjä",
|
||||
"unblock_user": "Estä käyttäjä",
|
||||
"block_board": "Estä foorumi",
|
||||
"unblock_board": "Poista foorumin esto",
|
||||
"unblock_all_confirm": "Oletko varma, että haluat poistaa estoja kaikista foorumin osoitteista ja käyttäjien osoitteista?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Maaaring offline ang subplebbit at maaaring mabigo ang paglalathala.",
|
||||
"posts_last_synced_info": "Huling naka-sync na mga post {{time}}, maaaring offline ang subplebbit at maaaring mabigo ang paglalathala.",
|
||||
"newer_than": "mas bago kaysa",
|
||||
"no_posts": "walang post"
|
||||
"no_posts": "walang post",
|
||||
"unblock": "I-unblock",
|
||||
"unblock_all": "I-unblock ang lahat",
|
||||
"blocked_addresses": "Mga blocked na address",
|
||||
"you_have_not_blocked": "Hindi mo na-block ang anumang address ng board o address ng user.",
|
||||
"block_user": "I-block ang user",
|
||||
"unblock_user": "I-unblock ang user",
|
||||
"block_board": "I-block ang board",
|
||||
"unblock_board": "I-unblock ang board",
|
||||
"unblock_all_confirm": "Sigurado ka bang gusto mong i-unblock ang lahat ng mga board address at mga user address?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Le subplebbit pourrait être hors ligne et la publication pourrait échouer.",
|
||||
"posts_last_synced_info": "Dernières publications synchronisées {{time}}, le subplebbit pourrait être hors ligne et la publication pourrait échouer.",
|
||||
"newer_than": "plus récent que",
|
||||
"no_posts": "pas de publications"
|
||||
"no_posts": "pas de publications",
|
||||
"unblock": "Débloquer",
|
||||
"unblock_all": "Débloquer tout",
|
||||
"blocked_addresses": "Adresses bloquées",
|
||||
"you_have_not_blocked": "Vous n'avez bloqué aucune adresse de board ou d'utilisateur.",
|
||||
"block_user": "Bloquer l'utilisateur",
|
||||
"unblock_user": "Débloquer l'utilisateur",
|
||||
"block_board": "Bloquer le forum",
|
||||
"unblock_board": "Débloquer le forum",
|
||||
"unblock_all_confirm": "Êtes-vous sûr de vouloir débloquer toutes les adresses de forum et les adresses d'utilisateur ?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "הסאבפלביט עשוי להיות לא מקוון והפרסום עשוי להכשל.",
|
||||
"posts_last_synced_info": "הפוסטים סונכרנו לאחרונה {{time}}, הסאבפלביט עשוי להיות לא מקוון והפרסום עשוי להכשל.",
|
||||
"newer_than": "חדש יותר מ",
|
||||
"no_posts": "אין פוסטים"
|
||||
"no_posts": "אין פוסטים",
|
||||
"unblock": "בטל חסימה",
|
||||
"unblock_all": "בטל את כל החסימות",
|
||||
"blocked_addresses": "כתובות מובלגות",
|
||||
"you_have_not_blocked": "לא חסמת שום כתובת לוח או כתובת משתמש.",
|
||||
"block_user": "חסום משתמש",
|
||||
"unblock_user": "ביטול חסימת משתמש",
|
||||
"block_board": "חסום פורום",
|
||||
"unblock_board": "ביטול חסימת פורום",
|
||||
"unblock_all_confirm": "האם אתה בטוח שברצונך לבטל את חסימת כל כתובות הפורום וכתובות המשתמש?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "सबप्लेबिट ऑफलाइन हो सकता है और प्रकाशन विफल हो सकता है।",
|
||||
"posts_last_synced_info": "आखिरी बार सिंक की गई पोस्ट {{time}}, सबप्लेबिट ऑफलाइन हो सकता है और प्रकाशन विफल हो सकता है।",
|
||||
"newer_than": "से नई",
|
||||
"no_posts": "कोई पोस्ट नहीं"
|
||||
"no_posts": "कोई पोस्ट नहीं",
|
||||
"unblock": "अनब्लॉक",
|
||||
"unblock_all": "सभी को अनब्लॉक करें",
|
||||
"blocked_addresses": "ब्लॉक किए गए पते",
|
||||
"you_have_not_blocked": "आपने कोई भी बोर्ड पता या उपयोगकर्ता पता ब्लॉक नहीं किया है।",
|
||||
"block_user": "उपयोगकर्ता अवरोधित करें",
|
||||
"unblock_user": "उपयोगकर्ता को अनब्लॉक करें",
|
||||
"block_board": "फ़ोरम अवरोधित करें",
|
||||
"unblock_board": "फ़ोरम को अनब्लॉक करें",
|
||||
"unblock_all_confirm": "क्या आप सभी बोर्ड पतों और उपयोगकर्ता पतों को अनब्लॉक करना चाहते हैं, क्या आप सुनिश्चित हैं?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "A subplebbit offline lehet, és a közzététel sikertelen lehet.",
|
||||
"posts_last_synced_info": "Legutóbb szinkronizált bejegyzések {{time}}, a subplebbit offline lehet, és a közzététel sikertelen lehet.",
|
||||
"newer_than": "újabb, mint",
|
||||
"no_posts": "nincsenek hozzászólások"
|
||||
"no_posts": "nincsenek hozzászólások",
|
||||
"unblock": "Blokkolás feloldása",
|
||||
"unblock_all": "Összes feloldása",
|
||||
"blocked_addresses": "Blokkolt címek",
|
||||
"you_have_not_blocked": "Nem tiltottál le egyetlen táblacímet vagy felhasználói címet sem.",
|
||||
"block_user": "Felhasználó blokkolása",
|
||||
"unblock_user": "Felhasználó feloldása",
|
||||
"block_board": "Fórum blokkolása",
|
||||
"unblock_board": "Fórum feloldása",
|
||||
"unblock_all_confirm": "Biztos vagy benne, hogy fel akarod oldani az összes fórumcímet és felhasználói címet?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit mungkin offline dan penerbitan mungkin gagal.",
|
||||
"posts_last_synced_info": "Posting terakhir disinkronkan {{time}}, subplebbit mungkin offline dan penerbitan mungkin gagal.",
|
||||
"newer_than": "baru daripada",
|
||||
"no_posts": "tidak ada posting"
|
||||
"no_posts": "tidak ada posting",
|
||||
"unblock": "Buka blokir",
|
||||
"unblock_all": "Buka semua blokir",
|
||||
"blocked_addresses": "Alamat yang diblokir",
|
||||
"you_have_not_blocked": "Anda belum memblokir alamat papan atau alamat pengguna apa pun.",
|
||||
"block_user": "Blokir pengguna",
|
||||
"unblock_user": "Buka blokir pengguna",
|
||||
"block_board": "Blokir papan",
|
||||
"unblock_board": "Buka blokir forum",
|
||||
"unblock_all_confirm": "Apakah Anda yakin ingin membuka blokir semua alamat board dan alamat pengguna?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Il subplebbit potrebbe essere offline e la pubblicazione potrebbe fallire.",
|
||||
"posts_last_synced_info": "Ultimi post sincronizzati {{time}}, il subplebbit potrebbe essere offline e la pubblicazione potrebbe fallire.",
|
||||
"newer_than": "più recente di",
|
||||
"no_posts": "nessun post"
|
||||
"no_posts": "nessun post",
|
||||
"unblock": "Sblocca",
|
||||
"unblock_all": "Sblocca tutti",
|
||||
"blocked_addresses": "Indirizzi bloccati",
|
||||
"you_have_not_blocked": "Non hai bloccato nessun indirizzo di forum o utente.",
|
||||
"block_user": "Blocca utente",
|
||||
"unblock_user": "Sblocca utente",
|
||||
"block_board": "Blocca forum",
|
||||
"unblock_board": "Sblocca forum",
|
||||
"unblock_all_confirm": "Sei sicuro di voler sbloccare tutti gli indirizzi del forum e gli indirizzi degli utenti?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "サブプレビットがオフラインになっている可能性があり、公開が失敗することがあります。",
|
||||
"posts_last_synced_info": "最後に同期された投稿 {{time}}, サブプレビットがオフラインになっている可能性があり、公開が失敗することがあります。",
|
||||
"newer_than": "より新しい",
|
||||
"no_posts": "投稿はありません"
|
||||
"no_posts": "投稿はありません",
|
||||
"unblock": "ブロック解除",
|
||||
"unblock_all": "すべてのブロックを解除",
|
||||
"blocked_addresses": "ブロックされたアドレス",
|
||||
"you_have_not_blocked": "ボードアドレスまたはユーザーアドレスをブロックしていません。",
|
||||
"block_user": "ユーザーをブロックする",
|
||||
"unblock_user": "ユーザーのブロックを解除する",
|
||||
"block_board": "掲示板をブロックする",
|
||||
"unblock_board": "掲示板のブロックを解除する",
|
||||
"unblock_all_confirm": "すべての掲示板アドレスとユーザーアドレスを解除してもよろしいですか?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "서브플레빗이 오프라인 일 수 있으며 게시가 실패할 수 있습니다.",
|
||||
"posts_last_synced_info": "최근 동기화된 게시물 {{time}}, 서브플레빗이 오프라인 일 수 있으며 게시가 실패할 수 있습니다.",
|
||||
"newer_than": "이전보다 최신",
|
||||
"no_posts": "게시물이 없습니다"
|
||||
"no_posts": "게시물이 없습니다",
|
||||
"unblock": "차단 해제",
|
||||
"unblock_all": "모두 차단 해제",
|
||||
"blocked_addresses": "차단된 주소",
|
||||
"you_have_not_blocked": "게시판 주소나 사용자 주소를 차단하지 않았습니다.",
|
||||
"block_user": "사용자 차단",
|
||||
"unblock_user": "사용자 차단 해제",
|
||||
"block_board": "게시판 차단",
|
||||
"unblock_board": "게시판 차단 해제",
|
||||
"unblock_all_confirm": "모든 게시판 주소와 사용자 주소를 해제하시겠습니까?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "सबप्लेबिट मोबाइल असून प्रकाशन अयशस्वी होऊ शकतो.",
|
||||
"posts_last_synced_info": "शेवटच्या बारीस सिन्क केलेले पोस्ट {{time}}, सबप्लेबिट मोबाइल असून प्रकाशन अयशस्वी होऊ शकतो.",
|
||||
"newer_than": "नवीनतम आहे",
|
||||
"no_posts": "कोणतेही पोस्ट नाहीत"
|
||||
"no_posts": "कोणतेही पोस्ट नाहीत",
|
||||
"unblock": "ब्लॉक सोडा",
|
||||
"unblock_all": "सर्व ब्लॉक सोडा",
|
||||
"blocked_addresses": "ब्लॉक केलेले पत्ते",
|
||||
"you_have_not_blocked": "आपण कोणत्याही बोर्ड पत्ता किंवा वापरकर्ता पत्ता ब्लॉक केलेला नाही.",
|
||||
"block_user": "वापरकर्ता अवरोधित करा",
|
||||
"unblock_user": "वापरकर्ता अनब्लॉक करा",
|
||||
"block_board": "फोरम अवरोधित करा",
|
||||
"unblock_board": "फोरम अनब्लॉक करा",
|
||||
"unblock_all_confirm": "आपल्याला सर्व बोर्ड पत्ते आणि वापरकर्ता पत्ते अनब्लॉक करायचं आहे का?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "De subplebbit kan offline zijn en publiceren kan mislukken.",
|
||||
"posts_last_synced_info": "Laatste keer gesynchroniseerde berichten {{time}}, de subplebbit kan offline zijn en publiceren kan mislukken.",
|
||||
"newer_than": "nieuwer dan",
|
||||
"no_posts": "geen berichten"
|
||||
"no_posts": "geen berichten",
|
||||
"unblock": "Deblokkeren",
|
||||
"unblock_all": "Alles deblokkeren",
|
||||
"blocked_addresses": "Geblokkeerde adressen",
|
||||
"you_have_not_blocked": "U heeft geen enkel bordadres of gebruikersadres geblokkeerd.",
|
||||
"block_user": "Gebruiker blokkeren",
|
||||
"unblock_user": "Gebruiker deblokkeren",
|
||||
"block_board": "Forum blokkeren",
|
||||
"unblock_board": "Deblokkeer forum",
|
||||
"unblock_all_confirm": "Weet u zeker dat u alle boardadressen en gebruikersadressen wilt deblokkeren?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbiten kan være offline, og publisering kan mislykkes.",
|
||||
"posts_last_synced_info": "Siste synkroniserte innlegg {{time}}, subplebbiten kan være offline, og publisering kan mislykkes.",
|
||||
"newer_than": "nyere enn",
|
||||
"no_posts": "ingen innlegg"
|
||||
"no_posts": "ingen innlegg",
|
||||
"unblock": "Fjern blokkering",
|
||||
"unblock_all": "Fjern alle blokkeringer",
|
||||
"blocked_addresses": "Blokkerte adresser",
|
||||
"you_have_not_blocked": "Du har ikke blokkert noen bordadresse eller brukeradresse.",
|
||||
"block_user": "Blokker bruker",
|
||||
"unblock_user": "Fjern blokkering av bruker",
|
||||
"block_board": "Blokker forum",
|
||||
"unblock_board": "Fjern blokkering av forum",
|
||||
"unblock_all_confirm": "Er du sikker på at du vil fjerne blokkeringen av alle bordadresser og brukeradresser?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit może być offline, a publikacja może się nie powieść.",
|
||||
"posts_last_synced_info": "Ostatnio zsynchronizowane posty {{time}}, subplebbit może być offline, a publikacja może się nie powieść.",
|
||||
"newer_than": "nowsze niż",
|
||||
"no_posts": "brak postów"
|
||||
"no_posts": "brak postów",
|
||||
"unblock": "Odblokuj",
|
||||
"unblock_all": "Odblokuj wszystkie",
|
||||
"blocked_addresses": "Zablokowane adresy",
|
||||
"you_have_not_blocked": "Nie zablokowałeś żadnego adresu forum ani użytkownika.",
|
||||
"block_user": "Zablokuj użytkownika",
|
||||
"unblock_user": "Odblokuj użytkownika",
|
||||
"block_board": "Zablokuj forum",
|
||||
"unblock_board": "Odblokuj forum",
|
||||
"unblock_all_confirm": "Jesteś pewien, że chcesz odblokować wszystkie adresy forum i adresy użytkowników?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "O subplebbit pode estar offline e a publicação pode falhar.",
|
||||
"posts_last_synced_info": "Posts sincronizados pela última vez {{time}}, o subplebbit pode estar offline e a publicação pode falhar.",
|
||||
"newer_than": "mais recente que",
|
||||
"no_posts": "sem publicações"
|
||||
"no_posts": "sem publicações",
|
||||
"unblock": "Desbloquear",
|
||||
"unblock_all": "Desbloquear tudo",
|
||||
"blocked_addresses": "Endereços bloqueados",
|
||||
"you_have_not_blocked": "Você não bloqueou nenhum endereço de quadro ou endereço de usuário.",
|
||||
"block_user": "Bloquear usuário",
|
||||
"unblock_user": "Desbloquear usuário",
|
||||
"block_board": "Bloquear fórum",
|
||||
"unblock_board": "Desbloquear fórum",
|
||||
"unblock_all_confirm": "Tem certeza de que deseja desbloquear todos os endereços de board e endereços de usuário?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbitul ar putea fi offline și publicarea ar putea eșua.",
|
||||
"posts_last_synced_info": "Ultimele postări sincronizate {{time}}, subplebbitul ar putea fi offline și publicarea ar putea eșua.",
|
||||
"newer_than": "mai nou decât",
|
||||
"no_posts": "niciun post"
|
||||
"no_posts": "niciun post",
|
||||
"unblock": "Deblocare",
|
||||
"unblock_all": "Deblocare toate",
|
||||
"blocked_addresses": "Adrese blocate",
|
||||
"you_have_not_blocked": "Nu ați blocat nicio adresă de bord sau adresă de utilizator.",
|
||||
"block_user": "Blochează utilizatorul",
|
||||
"unblock_user": "Deblochează utilizatorul",
|
||||
"block_board": "Blochează forumul",
|
||||
"unblock_board": "Deblochează forumul",
|
||||
"unblock_all_confirm": "Sunteți sigur că doriți să deblocați toate adresele de board și adresele de utilizatori?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Сабплеббит может быть офлайн, и публикация может не удалиться.",
|
||||
"posts_last_synced_info": "Последние синхронизированные сообщения {{time}}, сабплеббит может быть офлайн, и публикация может не удалиться.",
|
||||
"newer_than": "новее чем",
|
||||
"no_posts": "нет записей"
|
||||
"no_posts": "нет записей",
|
||||
"unblock": "Разблокировать",
|
||||
"unblock_all": "Разблокировать все",
|
||||
"blocked_addresses": "Заблокированные адреса",
|
||||
"you_have_not_blocked": "Вы не заблокировали ни одного адреса доски или пользователя.",
|
||||
"block_user": "Заблокировать пользователя",
|
||||
"unblock_user": "Разблокировать пользователя",
|
||||
"block_board": "Заблокировать форум",
|
||||
"unblock_board": "Разблокировать форум",
|
||||
"unblock_all_confirm": "Вы уверены, что хотите разблокировать все адреса форума и адреса пользователей?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbiti mund të jetë jashtë linje dhe publikimi mund të dështojë.",
|
||||
"posts_last_synced_info": "Postimet e fundit të sinkronizuara {{time}}, subplebbiti mund të jetë jashtë linje dhe publikimi mund të dështojë.",
|
||||
"newer_than": "më i ri se",
|
||||
"no_posts": "asnjë postim"
|
||||
"no_posts": "asnjë postim",
|
||||
"unblock": "Zhblloko",
|
||||
"unblock_all": "Zhblloko të gjitha",
|
||||
"blocked_addresses": "Adresat e bllokuara",
|
||||
"you_have_not_blocked": "Ju nuk keni bllokuar asnjë adresë bordi ose adresë përdoruesi.",
|
||||
"block_user": "Blloko përdoruesin",
|
||||
"unblock_user": "Hiq bllokimin e përdoruesit",
|
||||
"block_board": "Blloko bordi",
|
||||
"unblock_board": "Hiq bllokimin e bordit",
|
||||
"unblock_all_confirm": "A jeni i sigurt se doni të hiqni bllokimin e të gjitha adresave të bordit dhe adresave të përdoruesit?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit kan vara offline och publicering kan misslyckas.",
|
||||
"posts_last_synced_info": "Inlägg senast synkroniserade {{time}}, subplebbit kan vara offline och publicering kan misslyckas.",
|
||||
"newer_than": "nyare än",
|
||||
"no_posts": "inga inlägg"
|
||||
"no_posts": "inga inlägg",
|
||||
"unblock": "Avblockera",
|
||||
"unblock_all": "Avblockera alla",
|
||||
"blocked_addresses": "Blockerade adresser",
|
||||
"you_have_not_blocked": "Du har inte blockerat någon brädadress eller användaradress.",
|
||||
"block_user": "Blockera användare",
|
||||
"unblock_user": "Avblockera användare",
|
||||
"block_board": "Blockera forum",
|
||||
"unblock_board": "Avblockera forum",
|
||||
"unblock_all_confirm": "Är du säker på att du vill låsa upp alla boardadresser och användaradresser?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "సబ్ప్లెబిట్ ఆఫ్లైన్ ఉండవచ్చు మరియు ప్రచురణ విఫలమైనా ఉంటుంది.",
|
||||
"posts_last_synced_info": "ఇటీవలే సింక్ చేసిన పోస్ట్లు {{time}}, సబ్ప్లెబిట్ ఆఫ్లైన్ ఉండవచ్చు, మరియు ప్రకటన విఫలమవుతుంది.",
|
||||
"newer_than": "కనునుగా",
|
||||
"no_posts": "పోస్టులు లేవు"
|
||||
"no_posts": "పోస్టులు లేవు",
|
||||
"unblock": "బ్లాక్ను తీసుకో",
|
||||
"unblock_all": "అన్ని బ్లాక్ తీసుకో",
|
||||
"blocked_addresses": "నిషేధింపబడిన చిరునామాలు",
|
||||
"you_have_not_blocked": "మీరు ఏ బోర్డ్ చిరునామా లేదా వాడుకరి చిరునామాను నిలిచింది.",
|
||||
"block_user": "వాడుకరిని నిలిపించు",
|
||||
"unblock_user": "వాడుకరిని అన్బ్లాక్ చేయండి",
|
||||
"block_board": "బోర్డును నిలిపించు",
|
||||
"unblock_board": "బోర్డును అన్బ్లాక్ చేయండి",
|
||||
"unblock_all_confirm": "మీరు అన్బ్లాక్ చేయడానికి అన్ని బోర్డు చిరునామాలను మరియు వాడుకరి చిరునామాలను ఖాళీ చేస్తున్నారా?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "เซ็บเพล็บบิทอาจออฟไลน์และการเผยแพร่อาจล้มเหลว",
|
||||
"posts_last_synced_info": "โพสต์ล่าสุดที่ซิงค์ {{time}}, ซับเพลบบิทอาจออฟไลน์และการเผยแพร่อาจล้มเหลว",
|
||||
"newer_than": "ใหม่กว่า",
|
||||
"no_posts": "ไม่มีโพสต์"
|
||||
"no_posts": "ไม่มีโพสต์",
|
||||
"unblock": "ยกเลิกการบล็อก",
|
||||
"unblock_all": "ยกเลิกการบล็อกทั้งหมด",
|
||||
"blocked_addresses": "ที่อยู่ที่ถูกบล็อก",
|
||||
"you_have_not_blocked": "คุณยังไม่ได้บล็อกที่อยู่ของกระดานหรือที่อยู่ของผู้ใช้ใด ๆ",
|
||||
"block_user": "บล็อกผู้ใช้",
|
||||
"unblock_user": "ยกเลิกการบล็อกผู้ใช้",
|
||||
"block_board": "บล็อกบอร์ด",
|
||||
"unblock_board": "ยกเลิกการบล็อกบอร์ด",
|
||||
"unblock_all_confirm": "คุณแน่ใจหรือไม่ว่าต้องการยกเลิกการบล็อกทุกที่อยู่ของบอร์ดและผู้ใช้?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit çevrimdışı olabilir ve yayınlama başarısız olabilir.",
|
||||
"posts_last_synced_info": "Son senkronize edilen gönderiler {{time}}, subplebbit çevrimdışı olabilir ve yayınlama başarısız olabilir.",
|
||||
"newer_than": "daha yeni",
|
||||
"no_posts": "gönderi yok"
|
||||
"no_posts": "gönderi yok",
|
||||
"unblock": "Engeli kaldır",
|
||||
"unblock_all": "Tüm engelleri kaldır",
|
||||
"blocked_addresses": "Engellenen adresler",
|
||||
"you_have_not_blocked": "Herhangi bir board adresi veya kullanıcı adresi engellemediniz.",
|
||||
"block_user": "Kullanıcıyı engelle",
|
||||
"unblock_user": "Kullanıcı engelini kaldır",
|
||||
"block_board": "Forumu engelle",
|
||||
"unblock_board": "Forumu engeli kaldır",
|
||||
"unblock_all_confirm": "Tüm forum adreslerini ve kullanıcı adreslerini engellemek istediğinizden emin misiniz?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Сабплебіт може бути офлайн, а публікація може не вдастися.",
|
||||
"posts_last_synced_info": "Останні синхронізовані повідомлення {{time}}, сабплебіт може бути офлайн, а публікація може не вдастися.",
|
||||
"newer_than": "новіше ніж",
|
||||
"no_posts": "немає повідомлень"
|
||||
"no_posts": "немає повідомлень",
|
||||
"unblock": "Розблокувати",
|
||||
"unblock_all": "Розблокувати всі",
|
||||
"blocked_addresses": "Заблоковані адреси",
|
||||
"you_have_not_blocked": "Ви не заблокували жодної адреси дошки або користувача.",
|
||||
"block_user": "Заблокувати користувача",
|
||||
"unblock_user": "Розблокувати користувача",
|
||||
"block_board": "Заблокувати форум",
|
||||
"unblock_board": "Розблокувати форум",
|
||||
"unblock_all_confirm": "Ви впевнені, що хочете розблокувати всі адреси форуму та адреси користувачів?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "سب پلیبٹ آف لائن ہوسکتا ہے اور شائع ہونے میں ناکام ہوسکتا ہے۔",
|
||||
"posts_last_synced_info": "آخری بار پوسٹ سنک کی گئی {{time}}, سب پلیبٹ آف لائن ہوسکتا ہے اور شائع ہونے میں ناکام ہوسکتا ہے۔",
|
||||
"newer_than": "نئی سے",
|
||||
"no_posts": "کوئی پوسٹ نہیں"
|
||||
"no_posts": "کوئی پوسٹ نہیں",
|
||||
"unblock": "بلاک ہٹائیں",
|
||||
"unblock_all": "سب کو انبلاک کریں",
|
||||
"blocked_addresses": "مسدود شدہ پتوں",
|
||||
"you_have_not_blocked": "آپ نے کسی بھی بورڈ کا پتہ یا صارف کا پتہ بلاک نہیں کیا ہے۔",
|
||||
"block_user": "صارف کو بلاک کریں",
|
||||
"unblock_user": "صارف کو انبلاک کریں",
|
||||
"block_board": "فورم کو بلاک کریں",
|
||||
"unblock_board": "فورم کو انبلاک کریں",
|
||||
"unblock_all_confirm": "کیا آپ بورڈ کے تمام پتے اور صارف پتے کھولنے کے لیے یقینی ہیں؟"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "Subplebbit có thể ngoại tuyến và việc xuất bản có thể thất bại.",
|
||||
"posts_last_synced_info": "Bài viết được đồng bộ lần cuối {{time}}, subplebbit có thể ngoại tuyến và việc xuất bản có thể thất bại.",
|
||||
"newer_than": "mới hơn",
|
||||
"no_posts": "không có bài viết"
|
||||
"no_posts": "không có bài viết",
|
||||
"unblock": "Bỏ chặn",
|
||||
"unblock_all": "Bỏ chặn tất cả",
|
||||
"blocked_addresses": "Địa chỉ bị chặn",
|
||||
"you_have_not_blocked": "Bạn chưa chặn bất kỳ địa chỉ bảng nào hoặc địa chỉ người dùng.",
|
||||
"block_user": "Chặn người dùng",
|
||||
"unblock_user": "Bỏ chặn người dùng",
|
||||
"block_board": "Chặn diễn đàn",
|
||||
"unblock_board": "Bỏ chặn diễn đàn",
|
||||
"unblock_all_confirm": "Bạn có chắc chắn muốn bỏ chặn tất cả các địa chỉ diễn đàn và địa chỉ người dùng không?"
|
||||
}
|
||||
@@ -167,5 +167,14 @@
|
||||
"subplebbit_offline_info": "子维基可能离线,发布可能失败。",
|
||||
"posts_last_synced_info": "最后同步的帖子 {{time}}, 子维基可能离线,发布可能失败。",
|
||||
"newer_than": "新于",
|
||||
"no_posts": "没有帖子"
|
||||
"no_posts": "没有帖子",
|
||||
"unblock": "解除封禁",
|
||||
"unblock_all": "解除全部封禁",
|
||||
"blocked_addresses": "被阻止的地址",
|
||||
"you_have_not_blocked": "您尚未封锁任何板块地址或用户地址。",
|
||||
"block_user": "封锁用户",
|
||||
"unblock_user": "解除封锁用户",
|
||||
"block_board": "封锁论坛",
|
||||
"unblock_board": "解除封锁论坛",
|
||||
"unblock_all_confirm": "您确定要解锁所有论坛地址和用户地址吗?"
|
||||
}
|
||||
@@ -16,6 +16,10 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mediaPaddingWrapper {
|
||||
padding-bottom: 5px;
|
||||
display: inline-flex;
|
||||
|
||||
@@ -7,9 +7,10 @@ import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floati
|
||||
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import { getFormattedTimeAgo } from '../../lib/utils/time-utils';
|
||||
import { isAllView } from '../../lib/utils/view-utils';
|
||||
import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useEditCommentPrivileges from '../../hooks/use-author-privileges';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useFetchGifFirstFrame from '../../hooks/use-fetch-gif-first-frame';
|
||||
import useHide from '../../hooks/use-hide';
|
||||
import PostMenuDesktop from '../post-desktop/post-menu-desktop';
|
||||
import styles from './catalog-row.module.css';
|
||||
import _ from 'lodash';
|
||||
@@ -85,6 +86,7 @@ const CatalogPost = ({ post }: { post: Comment }) => {
|
||||
post || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
|
||||
const { hidden } = useHide({ cid });
|
||||
|
||||
const location = useLocation();
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
@@ -154,7 +156,7 @@ const CatalogPost = ({ post }: { post: Comment }) => {
|
||||
subplebbitAddress,
|
||||
});
|
||||
|
||||
const postContent = (
|
||||
const postContent = !hidden && (
|
||||
<div className={styles.teaser}>
|
||||
<b>{title && `${title}${content ? ': ' : ''}`}</b>
|
||||
{content}
|
||||
@@ -163,9 +165,9 @@ const CatalogPost = ({ post }: { post: Comment }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.post}>
|
||||
<div className={`${styles.post} ${hidden && styles.hidden}`}>
|
||||
<div onMouseOver={() => setHoveredCid(isDescription ? 'd' : isRules ? 'r' : cid)} onMouseLeave={() => setHoveredCid(null)}>
|
||||
{hasThumbnail ? (
|
||||
{hasThumbnail && !hidden ? (
|
||||
<Link to={postLink}>
|
||||
<div
|
||||
className={styles.mediaPaddingWrapper}
|
||||
|
||||
@@ -142,7 +142,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
[
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.deleted} type='checkbox' id='deleted' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.deleted ?? false} type='checkbox' id='deleted' />
|
||||
{_.capitalize(t('delete'))}? ]
|
||||
</label>
|
||||
</div>
|
||||
@@ -157,7 +157,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div>
|
||||
<textarea
|
||||
className={styles.editTextarea}
|
||||
value={publishCommentEditOptions.content}
|
||||
value={publishCommentEditOptions.content ?? ''}
|
||||
ref={contentEditorRef}
|
||||
onChange={(e) => setPublishCommentEditOptions((state) => ({ ...state, content: e.target.value }))}
|
||||
/>
|
||||
@@ -170,7 +170,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
<label>
|
||||
[
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed ?? false} type='checkbox' id='removed' />
|
||||
{_.capitalize(t('remove'))}?]
|
||||
</label>
|
||||
</div>
|
||||
@@ -178,7 +178,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked} type='checkbox' id='locked' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked ?? false} type='checkbox' id='locked' />
|
||||
{_.capitalize(t('close_thread'))}?
|
||||
</label>
|
||||
]
|
||||
@@ -187,7 +187,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler} type='checkbox' id='spoiler' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler ?? false} type='checkbox' id='spoiler' />
|
||||
{_.capitalize(t('spoiler'))}?
|
||||
</label>
|
||||
]
|
||||
@@ -195,7 +195,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned} type='checkbox' id='pinned' />
|
||||
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned ?? false} type='checkbox' id='pinned' />
|
||||
{_.capitalize(t('sticky'))}?
|
||||
</label>
|
||||
]
|
||||
@@ -204,7 +204,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
<div className={styles.menuItem}>
|
||||
[
|
||||
<label>
|
||||
<input onChange={onCheckbox} checked={!!publishCommentEditOptions.commentAuthor?.banExpiresAt} type='checkbox' id='banUser' />
|
||||
<input onChange={onCheckbox} checked={!!publishCommentEditOptions.commentAuthor?.banExpiresAt ?? false} type='checkbox' id='banUser' />
|
||||
<Trans
|
||||
i18nKey='ban_user_for'
|
||||
shouldUnescape={true}
|
||||
@@ -221,7 +221,7 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA
|
||||
)}
|
||||
<div className={`${styles.menuItem} ${styles.menuReason}`}>
|
||||
{_.capitalize(t('reason'))}? ({t('optional')})
|
||||
<input type='text' onChange={onReason} defaultValue={post?.reason} size={14} />
|
||||
<input type='text' onChange={onReason} defaultValue={post?.reason ?? ''} size={14} />
|
||||
</div>
|
||||
<div className={styles.bottom}>
|
||||
<button className={isMobile ? 'button' : ''} onClick={_publishCommentEdit}>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { Comment, useAccount, useBlock, useComment } from '@plebbit/plebbit-react-hooks';
|
||||
import { Comment, useAccount, useComment } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import styles from '../../views/post/post.module.css';
|
||||
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import { isValidURL } from '../../lib/utils/url-utils';
|
||||
import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useEditCommentPrivileges from '../../hooks/use-author-privileges';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useHide from '../../hooks/use-hide';
|
||||
import useReplies from '../../hooks/use-replies';
|
||||
import useStateString from '../../hooks/use-state-string';
|
||||
import CommentMedia from '../comment-media';
|
||||
@@ -212,6 +213,23 @@ const PostMessage = ({ post }: PostProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Reply = ({ openReplyModal, reply, roles }: PostProps) => {
|
||||
const { cid, subplebbitAddress } = reply || {};
|
||||
const isRouteLinkToReply = useLocation().pathname.startsWith(`/p/${subplebbitAddress}/c/${cid}`);
|
||||
const { hidden } = useHide({ cid });
|
||||
|
||||
return (
|
||||
<div className={styles.replyDesktop}>
|
||||
<div className={styles.sideArrows}>{'>>'}</div>
|
||||
<div className={`${styles.reply} ${isRouteLinkToReply && styles.highlight} ${hidden && styles.postDesktopHidden}`} id={reply?.cid}>
|
||||
<PostInfo openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.link && !hidden && isValidURL(reply.link) && <PostMedia post={reply} />}
|
||||
{reply.content && !hidden && <PostMessage post={reply} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies = true }: PostProps) => {
|
||||
const { cid, content, link, pinned, replyCount, subplebbitAddress } = post || {};
|
||||
const { isDescription, isRules } = post || {}; // custom properties, not from api
|
||||
@@ -220,8 +238,8 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
|
||||
const { blocked, unblock, block } = useBlock({ cid });
|
||||
const isHidden = blocked && !isInPostPageView;
|
||||
const { hidden, unhide, hide } = useHide({ cid });
|
||||
const isHidden = hidden && !isInPostPageView;
|
||||
|
||||
const replies = useReplies(post);
|
||||
const visiblelinksCount = useCountLinksInReplies(post, 5);
|
||||
@@ -247,10 +265,10 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
||||
) : (
|
||||
<div className={styles.replyQuotePreviewSpacer} />
|
||||
)}
|
||||
<div className={isHidden ? styles.postDesktopBlocked : ''}>
|
||||
<div className={isHidden ? styles.postDesktopHidden : ''}>
|
||||
{!isInPostPageView && !isDescription && !isRules && showReplies && (
|
||||
<span className={styles.hideButtonWrapper}>
|
||||
<span className={`${styles.hideButton} ${blocked ? styles.unhideThread : styles.hideThread}`} onClick={blocked ? unblock : block} />
|
||||
<span className={`${styles.hideButton} ${hidden ? styles.unhideThread : styles.hideThread}`} onClick={hidden ? unhide : hide} />
|
||||
</span>
|
||||
)}
|
||||
{link && !isHidden && isValidURL(link) && <PostMedia post={post} />}
|
||||
@@ -281,21 +299,11 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
|
||||
!isRules &&
|
||||
replies &&
|
||||
showReplies &&
|
||||
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => {
|
||||
const isRouteLinkToReply = location.pathname.startsWith(`/p/${subplebbitAddress}/c/${reply?.cid}`);
|
||||
return (
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<div className={styles.replyDesktop}>
|
||||
<div className={styles.sideArrows}>{'>>'}</div>
|
||||
<div className={`${styles.reply} ${isRouteLinkToReply && styles.highlight}`} id={reply?.cid}>
|
||||
<PostInfo openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.link && isValidURL(reply.link) && <PostMedia post={reply} />}
|
||||
{reply.content && <PostMessage post={reply} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<Reply openReplyModal={openReplyModal} reply={reply} roles={roles} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './post-menu-desktop';
|
||||
export { BlockBoardButton, BlockUserButton, default } from './post-menu-desktop';
|
||||
|
||||
@@ -8,6 +8,7 @@ import styles from './post-menu-desktop.module.css';
|
||||
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils';
|
||||
import { isAllView, isCatalogView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils';
|
||||
import useHide from '../../../hooks/use-hide';
|
||||
import _ from 'lodash';
|
||||
|
||||
interface PostMenuDesktopProps {
|
||||
@@ -102,14 +103,34 @@ const ViewOnButton = ({ cid, isDescription, isInAllView, isInSubscriptionsView,
|
||||
);
|
||||
};
|
||||
|
||||
export const BlockUserButton = ({ address }: { address: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { blocked, unblock, block } = useBlock({ address });
|
||||
return (
|
||||
<div className={styles.postMenuItem} onClick={blocked ? unblock : block}>
|
||||
{blocked ? t('unblock_user') : t('block_user')}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const BlockBoardButton = ({ address }: { address: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { blocked, unblock, block } = useBlock({ address });
|
||||
return (
|
||||
<div className={styles.postMenuItem} onClick={blocked ? unblock : block}>
|
||||
{blocked ? t('unblock_board') : t('block_board')}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PostMenuDesktop = ({ post }: { post: Comment }) => {
|
||||
const { t } = useTranslation();
|
||||
const { cid, isDescription, isRules, link, postCid, subplebbitAddress } = post || {};
|
||||
const { author, cid, isDescription, isRules, link, postCid, subplebbitAddress } = post || {};
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const { thumbnail, type, url } = commentMediaInfo || {};
|
||||
const [menuBtnRotated, setMenuBtnRotated] = useState(false);
|
||||
|
||||
const { blocked, unblock, block } = useBlock({ cid });
|
||||
const { hidden, unhide, hide } = useHide({ cid });
|
||||
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
@@ -154,11 +175,11 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => {
|
||||
<div
|
||||
className={styles.postMenuItem}
|
||||
onClick={() => {
|
||||
blocked ? unblock() : block();
|
||||
hidden ? unhide() : hide();
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
{blocked ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
|
||||
{hidden ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
|
||||
</div>
|
||||
)}
|
||||
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && <ImageSearchButton url={url} onClose={handleClose} />}
|
||||
@@ -171,6 +192,8 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => {
|
||||
subplebbitAddress={subplebbitAddress}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
<BlockUserButton address={author?.address} />
|
||||
{(isInAllView || isInSubscriptionsView) && <BlockBoardButton address={subplebbitAddress} />}
|
||||
</div>
|
||||
</FloatingFocusManager>,
|
||||
document.body,
|
||||
|
||||
@@ -262,6 +262,8 @@ const PostForm = () => {
|
||||
const isInDescriptionView = isDescriptionView(location.pathname, params);
|
||||
const isInPostView = isPostPageView(location.pathname, params);
|
||||
const isInRulesView = isRulesView(location.pathname, params);
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname);
|
||||
|
||||
const comment = useComment({ commentCid: useParams().commentCid });
|
||||
const { deleted, locked, removed } = comment || {};
|
||||
@@ -286,7 +288,7 @@ const PostForm = () => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.postFormDesktop}>
|
||||
{offlineAlert}
|
||||
{!(isInAllView || isInSubscriptionsView) && offlineAlert}
|
||||
{isThreadClosed ? (
|
||||
<div className={styles.closed}>
|
||||
{t('thread_closed')}
|
||||
@@ -306,7 +308,7 @@ const PostForm = () => {
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.postFormMobile}>
|
||||
{offlineAlert}
|
||||
{!(isInAllView || isInSubscriptionsView) && offlineAlert}
|
||||
{isThreadClosed ? (
|
||||
<div className={styles.closed}>
|
||||
{t('thread_closed')}
|
||||
|
||||
@@ -7,14 +7,20 @@ import styles from './post-menu-mobile.module.css';
|
||||
import { getCommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import { copyShareLinkToClipboard, isValidURL } from '../../../lib/utils/url-utils';
|
||||
import useEditCommentPrivileges from '../../../hooks/use-author-privileges';
|
||||
import useHide from '../../../hooks/use-hide';
|
||||
import { BlockBoardButton, BlockUserButton } from '../../post-desktop/post-menu-desktop';
|
||||
import EditMenu from '../../edit-menu/edit-menu';
|
||||
import { isBoardView, isPostPageView } from '../../../lib/utils/view-utils';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
|
||||
interface PostMenuMobileProps {
|
||||
cid: string;
|
||||
isDescription?: boolean;
|
||||
isReply?: boolean;
|
||||
isRules?: boolean;
|
||||
subplebbitAddress: string;
|
||||
onClose: () => void;
|
||||
postCid?: string;
|
||||
subplebbitAddress?: string;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const CopyLinkButton = ({ cid, subplebbitAddress, onClose }: PostMenuMobileProps) => {
|
||||
@@ -22,8 +28,10 @@ const CopyLinkButton = ({ cid, subplebbitAddress, onClose }: PostMenuMobileProps
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
copyShareLinkToClipboard(subplebbitAddress, cid);
|
||||
onClose();
|
||||
if (subplebbitAddress) {
|
||||
copyShareLinkToClipboard(subplebbitAddress, cid);
|
||||
}
|
||||
onClose && onClose();
|
||||
}}
|
||||
>
|
||||
<div className={styles.postMenuItem}>{t('copy_link')}</div>
|
||||
@@ -63,13 +71,28 @@ const ViewOnButtons = ({ cid, isDescription, isRules, subplebbitAddress, onClose
|
||||
);
|
||||
};
|
||||
|
||||
const HidePostButton = ({ cid, isReply, postCid }: PostMenuMobileProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { hide, hidden, unhide } = useHide({ cid });
|
||||
const isInPostView = isPostPageView(useLocation().pathname, useParams());
|
||||
|
||||
return (
|
||||
(!isInPostView || isReply) && (
|
||||
<div onClick={hidden ? unhide : hide}>
|
||||
<div className={styles.postMenuItem}>
|
||||
{hidden ? (postCid === cid ? t('unhide_thread') : t('unhide_post')) : postCid === cid ? t('hide_thread') : t('hide_post')}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const PostMenuMobile = ({ post }: { post: Comment }) => {
|
||||
const { author, cid, isDescription, isRules, link, subplebbitAddress } = post || {};
|
||||
const { author, cid, isDescription, isRules, link, parentCid, subplebbitAddress } = post || {};
|
||||
const { isCommentAuthorMod, isAccountMod, isAccountCommentAuthor } = useEditCommentPrivileges({ commentAuthorAddress: author?.address, subplebbitAddress });
|
||||
const commentMediaInfo = getCommentMediaInfo(post);
|
||||
const { thumbnail, type, url } = commentMediaInfo || {};
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
const { refs, floatingStyles, context } = useFloating({
|
||||
placement: 'bottom-start',
|
||||
open: isMenuOpen,
|
||||
@@ -85,6 +108,8 @@ const PostMenuMobile = ({ post }: { post: Comment }) => {
|
||||
|
||||
const handleClose = () => setIsMenuOpen(false);
|
||||
|
||||
const isInBoardView = isBoardView(useLocation().pathname, useParams());
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className={styles.postMenuBtn} title='Post menu' onClick={() => setIsMenuOpen((prev) => !prev)} ref={refs.setReference} {...getReferenceProps()}>
|
||||
@@ -95,6 +120,9 @@ const PostMenuMobile = ({ post }: { post: Comment }) => {
|
||||
<FloatingFocusManager context={context} modal={false}>
|
||||
<div className={styles.postMenu} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
|
||||
{cid && subplebbitAddress && <CopyLinkButton cid={cid} subplebbitAddress={subplebbitAddress} onClose={handleClose} />}
|
||||
{cid && subplebbitAddress && <HidePostButton cid={cid} isReply={parentCid} postCid={post.postCid} />}
|
||||
{cid && subplebbitAddress && <BlockUserButton address={author?.address} />}
|
||||
{cid && subplebbitAddress && !isInBoardView && <BlockBoardButton address={subplebbitAddress} />}
|
||||
{link && isValidURL(link) && (type === 'image' || type === 'gif' || thumbnail) && url && <ImageSearchButtons url={url} onClose={handleClose} />}
|
||||
<ViewOnButtons cid={cid} isDescription={isDescription} isRules={isRules} subplebbitAddress={subplebbitAddress} onClose={handleClose} />
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import styles from '../../views/post/post.module.css';
|
||||
import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||
import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
|
||||
import useHide from '../../hooks/use-hide';
|
||||
import useReplies from '../../hooks/use-replies';
|
||||
import useStateString from '../../hooks/use-state-string';
|
||||
import CommentMedia from '../comment-media';
|
||||
@@ -171,6 +172,24 @@ const PostMessageMobile = ({ post }: PostProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Reply = ({ openReplyModal, reply, roles }: PostProps) => {
|
||||
const { subplebbitAddress, cid } = reply || {};
|
||||
const isRouteLinkToReply = useLocation().pathname.startsWith(`/p/${subplebbitAddress}/c/${cid}`);
|
||||
const { hidden } = useHide({ cid });
|
||||
|
||||
return (
|
||||
<div className={styles.replyMobile}>
|
||||
<div className={styles.reply}>
|
||||
<div className={`${styles.replyContainer} ${isRouteLinkToReply && styles.highlight}`} id={reply?.cid}>
|
||||
<PostInfoAndMedia openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.content && !hidden && <PostMessageMobile post={reply} />}
|
||||
<ReplyBacklinks post={reply} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies = true }: PostProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { cid, content, pinned, replyCount, subplebbitAddress } = post || {};
|
||||
@@ -183,6 +202,9 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
||||
const linksCount = useCountLinksInReplies(post);
|
||||
const replies = useReplies(post);
|
||||
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const { hidden, unhide } = useHide({ cid });
|
||||
|
||||
// scroll to reply if pathname is reply permalink (backlink)
|
||||
const replyRefs = useRef<(HTMLDivElement | null)[]>([]);
|
||||
useEffect(() => {
|
||||
@@ -193,57 +215,59 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
|
||||
}, [location.pathname, replies, subplebbitAddress]);
|
||||
|
||||
return (
|
||||
<div className={styles.postMobile}>
|
||||
{showReplies && (
|
||||
<div className={styles.hrWrapper}>
|
||||
<hr />
|
||||
</div>
|
||||
)}
|
||||
<div className={showReplies ? styles.thread : styles.quotePreview}>
|
||||
<div className={styles.postContainer}>
|
||||
<div className={styles.postOp}>
|
||||
<PostInfoAndMedia openReplyModal={openReplyModal} post={post} roles={roles} />
|
||||
{content && <PostMessageMobile post={post} />}
|
||||
</div>
|
||||
{!isInPostView && !isInPendingPostView && showReplies && (
|
||||
<div className={styles.postLink}>
|
||||
<span className={styles.info}>
|
||||
{replyCount > 0 && `${replyCount} Replies`}
|
||||
{linksCount > 0 && ` / ${linksCount} Links`}
|
||||
</span>
|
||||
<Link
|
||||
to={isInAllView && isDescription ? '/p/all/description' : `/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${cid}`}`}
|
||||
className='button'
|
||||
>
|
||||
{t('view_thread')}
|
||||
</Link>
|
||||
<>
|
||||
{hidden && !isInPostPageView ? (
|
||||
<>
|
||||
<hr className={styles.unhideButtonHr} />
|
||||
<span className={styles.mobileUnhideButton}>
|
||||
<span className='button' onClick={unhide}>
|
||||
Show Hidden Thread
|
||||
</span>
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<div className={styles.postMobile}>
|
||||
{showReplies && (
|
||||
<div className={styles.hrWrapper}>
|
||||
<hr />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!(pinned && !isInPostView) &&
|
||||
!isInPendingPostView &&
|
||||
!isDescription &&
|
||||
!isRules &&
|
||||
replies &&
|
||||
showReplies &&
|
||||
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => {
|
||||
const isRouteLinkToReply = location.pathname.startsWith(`/p/${subplebbitAddress}/c/${reply?.cid}`);
|
||||
return (
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<div className={styles.replyMobile}>
|
||||
<div className={styles.reply}>
|
||||
<div className={`${styles.replyContainer} ${isRouteLinkToReply && styles.highlight}`} id={reply?.cid}>
|
||||
<PostInfoAndMedia openReplyModal={openReplyModal} post={reply} roles={roles} />
|
||||
{reply.content && <PostMessageMobile post={reply} />}
|
||||
<ReplyBacklinks post={reply} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={showReplies ? styles.thread : styles.quotePreview}>
|
||||
<div className={styles.postContainer}>
|
||||
<div className={styles.postOp}>
|
||||
<PostInfoAndMedia openReplyModal={openReplyModal} post={post} roles={roles} />
|
||||
{content && <PostMessageMobile post={post} />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{!isInPostView && !isInPendingPostView && showReplies && (
|
||||
<div className={styles.postLink}>
|
||||
<span className={styles.info}>
|
||||
{replyCount > 0 && `${replyCount} Replies`}
|
||||
{linksCount > 0 && ` / ${linksCount} Links`}
|
||||
</span>
|
||||
<Link
|
||||
to={isInAllView && isDescription ? '/p/all/description' : `/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${cid}`}`}
|
||||
className='button'
|
||||
>
|
||||
{t('view_thread')}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!(pinned && !isInPostView) &&
|
||||
!isInPendingPostView &&
|
||||
!isDescription &&
|
||||
!isRules &&
|
||||
replies &&
|
||||
showReplies &&
|
||||
(showAllReplies ? replies : replies.slice(-5)).map((reply, index) => (
|
||||
<div key={index} className={styles.replyContainer} ref={(el) => (replyRefs.current[index] = el)}>
|
||||
<Reply openReplyModal={openReplyModal} reply={reply} roles={roles} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Draggable from 'react-draggable';
|
||||
import { setAccount, useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import { getFormattedTimeAgo } from '../../lib/utils/time-utils';
|
||||
import { isValidURL } from '../../lib/utils/url-utils';
|
||||
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||
import useReply from '../../hooks/use-reply';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import styles from './reply-modal.module.css';
|
||||
@@ -76,6 +77,9 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
|
||||
}
|
||||
}, [parentCid]);
|
||||
|
||||
const location = useLocation();
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname);
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const { updatedAt } = subplebbit || {};
|
||||
const isBoardOffline = subplebbit?.updatedAt && subplebbit.updatedAt < Date.now() / 1000 - 60 * 60;
|
||||
@@ -134,7 +138,7 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
|
||||
autoFocus={!isMobile} // autofocus causes auto scroll to top on mobile
|
||||
/>
|
||||
</div>
|
||||
{offlineAlert}
|
||||
{!(isInAllView || isInSubscriptionsView) && offlineAlert}
|
||||
<div className={styles.offlineAlert}></div>
|
||||
<div className={styles.footer}>
|
||||
{url && (
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
.setting {
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.blockedAddress {
|
||||
padding-bottom: 5px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.unblockAll {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.button {
|
||||
text-transform: capitalize;
|
||||
color: var(--button-desktop-text-color);
|
||||
text-decoration: var(--button-text-decoration);
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: var(--button-desktop-text-color-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { setAccount, useAccount, useBlock } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import styles from './blocked-addresses-setting.module.css';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const UnblockButton = ({ address }: { address: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { unblock } = useBlock({ address });
|
||||
|
||||
return (
|
||||
<span className={styles.button} onClick={unblock}>
|
||||
{t('unblock')}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const BlockedAddressesSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
const { blockedAddresses } = useAccount() || {};
|
||||
const addressList = blockedAddresses ? Object.keys(blockedAddresses) : [];
|
||||
const account = useAccount();
|
||||
|
||||
const unblockAll = () => {
|
||||
window.confirm(t('unblock_all_confirm')) && setAccount({ ...account, blockedAddresses: {} });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.setting}>
|
||||
{addressList.length > 0 ? (
|
||||
<>
|
||||
{addressList.length > 1 && (
|
||||
<div className={styles.unblockAll}>
|
||||
[
|
||||
<span className={styles.button} onClick={unblockAll}>
|
||||
{t('unblock_all')}
|
||||
</span>
|
||||
]
|
||||
</div>
|
||||
)}
|
||||
<ul className={styles.blockedAddresses}>
|
||||
{addressList.map((address: string) => (
|
||||
<li key={address} className={styles.blockedAddress}>
|
||||
{address && Plebbit.getShortAddress(address)} [<UnblockButton address={address} />]
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
t('you_have_not_blocked')
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlockedAddressesSetting;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './blocked-addresses-setting';
|
||||
@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './settings-modal.module.css';
|
||||
import AccountSettings from './account-settings';
|
||||
import BlockedAddressesSetting from './blocked-addresses-setting';
|
||||
import CryptoAddressSetting from './crypto-address-setting';
|
||||
import CryptoWalletsSetting from './crypto-wallets-setting';
|
||||
import InterfaceSettings from './interface-settings';
|
||||
@@ -19,6 +20,7 @@ const SettingsModal = () => {
|
||||
const [showAccountSettings, setShowAccountSettings] = useState(false);
|
||||
const [showCryptoAddressSetting, setShowCryptoAddressSetting] = useState(false);
|
||||
const [showCryptoWalletSettings, setShowCryptoWalletSettings] = useState(false);
|
||||
const [showBlockedAddressesSetting, setShowBlockedAddressesSetting] = useState(false);
|
||||
const [expandAll, setExpandAll] = useState(false);
|
||||
|
||||
const handleExpandAll = () => {
|
||||
@@ -28,6 +30,7 @@ const SettingsModal = () => {
|
||||
setShowAccountSettings(newExpandState);
|
||||
setShowCryptoAddressSetting(newExpandState);
|
||||
setShowCryptoWalletSettings(newExpandState);
|
||||
setShowBlockedAddressesSetting(newExpandState);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -69,6 +72,13 @@ const SettingsModal = () => {
|
||||
</label>
|
||||
</div>
|
||||
{showCryptoWalletSettings && <CryptoWalletsSetting />}
|
||||
<div className={`${styles.setting} ${styles.category}`}>
|
||||
<label onClick={() => setShowBlockedAddressesSetting(!showBlockedAddressesSetting)}>
|
||||
<span className={showBlockedAddressesSetting ? styles.hideButton : styles.showButton} />
|
||||
{t('blocked_addresses')}
|
||||
</label>
|
||||
</div>
|
||||
{showBlockedAddressesSetting && <BlockedAddressesSetting />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1 +1,61 @@
|
||||
import { useCallback } from 'react';
|
||||
import { create } from 'zustand';
|
||||
import localForageLru from '@plebbit/plebbit-react-hooks/dist/lib/localforage-lru/index.js';
|
||||
|
||||
interface HideStoreState {
|
||||
hiddenCids: { [key: string]: boolean };
|
||||
hide: (cid: string) => void;
|
||||
unhide: (cid: string) => void;
|
||||
}
|
||||
|
||||
const hideStore = localForageLru.createInstance({
|
||||
name: 'hideStore',
|
||||
size: 1000,
|
||||
});
|
||||
|
||||
const useHideStore = create<HideStoreState>((set) => ({
|
||||
hiddenCids: {},
|
||||
hide: (cid: string) => {
|
||||
set((state) => ({
|
||||
hiddenCids: { ...state.hiddenCids, [cid]: true },
|
||||
}));
|
||||
hideStore.setItem(cid, true);
|
||||
},
|
||||
unhide: (cid: string) => {
|
||||
set((state) => {
|
||||
const newHiddenCids = { ...state.hiddenCids };
|
||||
delete newHiddenCids[cid];
|
||||
return { hiddenCids: newHiddenCids };
|
||||
});
|
||||
hideStore.removeItem(cid);
|
||||
},
|
||||
}));
|
||||
|
||||
const initializeHideStore = async () => {
|
||||
const entries: [string, boolean][] = await hideStore.entries();
|
||||
const hiddenCids: { [key: string]: boolean } = {};
|
||||
entries.forEach(([key, value]) => {
|
||||
hiddenCids[key] = value;
|
||||
});
|
||||
|
||||
useHideStore.setState((state) => ({
|
||||
hiddenCids: { ...hiddenCids, ...state.hiddenCids },
|
||||
}));
|
||||
};
|
||||
|
||||
initializeHideStore();
|
||||
|
||||
const useHide = ({ cid }: { cid: string }) => {
|
||||
const hiddenCids = useHideStore((state) => state.hiddenCids);
|
||||
const hide = useHideStore((state) => state.hide);
|
||||
const unhide = useHideStore((state) => state.unhide);
|
||||
|
||||
const hidden = !!hiddenCids[cid];
|
||||
|
||||
const hideCallback = useCallback(() => hide(cid), [hide, cid]);
|
||||
const unhideCallback = useCallback(() => unhide(cid), [unhide, cid]);
|
||||
|
||||
return { hidden, hide: hideCallback, unhide: unhideCallback };
|
||||
};
|
||||
|
||||
export default useHide;
|
||||
|
||||
@@ -9,14 +9,7 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
|
||||
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;
|
||||
}
|
||||
const postsPerSub = [0, 8, 4, 3, 2, 2, 2, 2, 1][Math.min(subplebbits.length, 8)];
|
||||
|
||||
subplebbits.forEach((subplebbit: any) => {
|
||||
let subplebbitPosts: Comment[] = [];
|
||||
|
||||
@@ -29,7 +29,7 @@ const useHomeFiltersStore = create<HomeFiltersStore>((set) => ({
|
||||
set({ useCatalog: value });
|
||||
localStorage.setItem('useCatalog', value.toString());
|
||||
},
|
||||
showWorksafeContentOnly: localStorage.getItem('showWorksafeContentOnly') === 'true' ? true : false,
|
||||
showWorksafeContentOnly: localStorage.getItem('showWorksafeContentOnly') === 'true' || localStorage.getItem('showWorksafeContentOnly') === null ? true : false,
|
||||
setShowWorksafeContentOnly: (value: boolean) => {
|
||||
set({ showWorksafeContentOnly: value });
|
||||
localStorage.setItem('showWorksafeContentOnly', value.toString());
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.button {
|
||||
text-transform: capitalize;
|
||||
color: var(--button-desktop-text-color);
|
||||
text-decoration: var(--button-text-decoration);
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: var(--button-desktop-text-color-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.footer {
|
||||
padding-left: 5px;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { useAccount, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { useAccount, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import styles from './board.module.css';
|
||||
@@ -87,15 +87,40 @@ const Board = () => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const { blocked, unblock } = useBlock({ address: subplebbitAddress });
|
||||
|
||||
const Footer = () => {
|
||||
let footerContent;
|
||||
if (feed.length === 0) {
|
||||
footerContent = t('no_posts');
|
||||
if (blocked) {
|
||||
footerContent = 'you have blocked this board';
|
||||
} else {
|
||||
footerContent = t('no_posts');
|
||||
}
|
||||
}
|
||||
if (hasMore || subplebbitAddresses.length === 0) {
|
||||
footerContent = loadingString;
|
||||
}
|
||||
return <div className={styles.footer}>{footerContent}</div>;
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
{footerContent}
|
||||
{blocked && (
|
||||
<>
|
||||
[
|
||||
<span
|
||||
className={styles.button}
|
||||
onClick={() => {
|
||||
unblock();
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
Unblock
|
||||
</span>
|
||||
]
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// save the last Virtuoso state to restore it when navigating back
|
||||
|
||||
@@ -342,4 +342,8 @@
|
||||
color: var(--homepage-box-bar-text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: var(--homepage-box-bar-text-color-hover);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.postDesktopBlocked {
|
||||
.postDesktopHidden {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@@ -216,6 +216,20 @@
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.mobileUnhideButton {
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mobileUnhideButton span {
|
||||
padding: 5px 18px 5px;
|
||||
}
|
||||
|
||||
.unhideButtonHr {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.quotePreview {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user