Merge pull request #403 from plebbit/development

Development
This commit is contained in:
Tom (plebeius.eth)
2024-06-14 17:27:10 +02:00
committed by GitHub
56 changed files with 752 additions and 145 deletions
+10 -1
View File
@@ -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": "هل أنت متأكد أنك تريد إلغاء حظر جميع عناوين المجالس وعناوين المستخدمين؟"
}
+10 -1
View File
@@ -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": "আপনি কি নিশ্চিত যে আপনি সমস্ত বোর্ড ঠিকানা এবং ব্যবহারকারী ঠিকানা অনবন্ধ করতে চান?"
}
+10 -1
View File
@@ -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ů?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "Είστε σίγουροι ότι θέλετε να ξεκλειδώσετε όλες τις διευθύνσεις συμβουλίων και χρηστών;"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "آیا از می خواهید تمام آدرس های بورد و آدرس های کاربر را از مسدودیت خارج کنید؟"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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 ?"
}
+10 -1
View File
@@ -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": "האם אתה בטוח שברצונך לבטל את חסימת כל כתובות הפורום וכתובות המשתמש?"
}
+10 -1
View File
@@ -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": "क्या आप सभी बोर्ड पतों और उपयोगकर्ता पतों को अनब्लॉक करना चाहते हैं, क्या आप सुनिश्चित हैं?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "すべての掲示板アドレスとユーザーアドレスを解除してもよろしいですか?"
}
+10 -1
View File
@@ -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": "모든 게시판 주소와 사용자 주소를 해제하시겠습니까?"
}
+10 -1
View File
@@ -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": "आपल्याला सर्व बोर्ड पत्ते आणि वापरकर्ता पत्ते अनब्लॉक करायचं आहे का?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "Вы уверены, что хотите разблокировать все адреса форума и адреса пользователей?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "మీరు అన్‌బ్లాక్ చేయడానికి అన్ని బోర్డు చిరునామాలను మరియు వాడుకరి చిరునామాలను ఖాళీ చేస్తున్నారా?"
}
+10 -1
View File
@@ -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": "คุณแน่ใจหรือไม่ว่าต้องการยกเลิกการบล็อกทุกที่อยู่ของบอร์ดและผู้ใช้?"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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": "Ви впевнені, що хочете розблокувати всі адреси форуму та адреси користувачів?"
}
+10 -1
View File
@@ -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": "کیا آپ بورڈ کے تمام پتے اور صارف پتے کھولنے کے لیے یقینی ہیں؟"
}
+10 -1
View File
@@ -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?"
}
+10 -1
View File
@@ -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 -5
View File
@@ -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}
+8 -8
View File
@@ -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}>
+29 -21
View File
@@ -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,
+4 -2
View File
@@ -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>
+72 -48
View File
@@ -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>
)}
</>
);
};
+6 -2
View File
@@ -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 && (
@@ -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>
</>
);
+60
View File
@@ -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;
+1 -8
View File
@@ -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[] = [];
+1 -1
View File
@@ -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());
+11
View File
@@ -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;
+28 -3
View File
@@ -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 && (
<>
&nbsp;&nbsp;[
<span
className={styles.button}
onClick={() => {
unblock();
reset();
}}
>
Unblock
</span>
]
</>
)}
</div>
);
};
// save the last Virtuoso state to restore it when navigating back
+4
View File
@@ -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);
}
}
+15 -1
View File
@@ -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;
}