diff --git a/public/assets/banners/banner-60.jpg b/public/assets/banners/banner-60.jpg
new file mode 100644
index 00000000..fe1346cf
Binary files /dev/null and b/public/assets/banners/banner-60.jpg differ
diff --git a/public/assets/icons/offline-red.png b/public/assets/icons/offline-red.png
new file mode 100644
index 00000000..a0227105
Binary files /dev/null and b/public/assets/icons/offline-red.png differ
diff --git a/public/translations/ar/default.json b/public/translations/ar/default.json
index f102f2d4..735cd85b 100644
--- a/public/translations/ar/default.json
+++ b/public/translations/ar/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "عرض لوحات آمنة للعمل فقط",
"show_all_content": "عرض جميع المحتويات",
"link_type": "نوع الرابط",
- "comment_edited_at_timestamp": "تم تحرير التعليق في {{timestamp}}.",
+ "comment_edited_at_timestamp": "تم تحرير التعليق في <1>{{timestamp}}1>",
"reason_reason": "السبب: \"{{reason}}\".",
"click_here_to_show_original": "<1>انقر هنا1> لعرض الأصل.",
"click_here_to_hide_original": "<1>انقر هنا1> لإخفاء الأصل.",
diff --git a/public/translations/bn/default.json b/public/translations/bn/default.json
index c043baaa..e8f5ae40 100644
--- a/public/translations/bn/default.json
+++ b/public/translations/bn/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "শুধুমাত্র কাজ-সম্পূর্ণ বোর্ড দেখান",
"show_all_content": "সমস্ত কন্টেন্ট দেখান",
"link_type": "লিংক প্রকার",
- "comment_edited_at_timestamp": "মন্তব্য সম্পাদনা করা হয়েছে {{timestamp}} তারিখে।",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> এ মন্তব্য সম্পাদিত হয়েছে",
"reason_reason": "কারণ: \"{{reason}}\".",
"click_here_to_show_original": "<1>এখানে ক্লিক করুন1> অসল দেখানোর জন্য।",
"click_here_to_hide_original": "<1>এখানে ক্লিক করুন1> অসল লুকাতে।",
diff --git a/public/translations/cs/default.json b/public/translations/cs/default.json
index 61a0378b..8ad8c915 100644
--- a/public/translations/cs/default.json
+++ b/public/translations/cs/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Zobrazit pouze bezpečné pracovní desky",
"show_all_content": "Zobrazit veškerý obsah",
"link_type": "Typ odkazu",
- "comment_edited_at_timestamp": "Komentář byl upraven dne {{timestamp}}.",
+ "comment_edited_at_timestamp": "Komentář byl upraven dne <1>{{timestamp}}1>",
"reason_reason": "Důvod: \"{{reason}}\".",
"click_here_to_show_original": "Klikněte <1>zde1> pro zobrazení původního.",
"click_here_to_hide_original": "Klikněte <1>zde1> pro skrytí původního.",
diff --git a/public/translations/da/default.json b/public/translations/da/default.json
index 392f5205..f10191b8 100644
--- a/public/translations/da/default.json
+++ b/public/translations/da/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Vis kun Worksafe boards",
"show_all_content": "Vis alt indhold",
"link_type": "Link type",
- "comment_edited_at_timestamp": "Kommentaren blev redigeret den {{timestamp}}.",
+ "comment_edited_at_timestamp": "Kommentaren blev redigeret den <1>{{timestamp}}1>",
"reason_reason": "Grund: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klik her1> for at vise originalen.",
"click_here_to_hide_original": "<1>Klik her1> for at skjule originalen.",
diff --git a/public/translations/de/default.json b/public/translations/de/default.json
index c7fb6016..a119a0a1 100644
--- a/public/translations/de/default.json
+++ b/public/translations/de/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Nur sichere Boards anzeigen",
"show_all_content": "Alle Inhalte anzeigen",
"link_type": "Linktyp",
- "comment_edited_at_timestamp": "Kommentar bearbeitet am {{timestamp}}.",
+ "comment_edited_at_timestamp": "Kommentar bearbeitet am <1>{{timestamp}}1>",
"reason_reason": "Grund: \"{{reason}}\".",
"click_here_to_show_original": "<1>Hier klicken1>, um das Original anzuzeigen.",
"click_here_to_hide_original": "<1>Hier klicken1>, um das Original zu verstecken.",
diff --git a/public/translations/el/default.json b/public/translations/el/default.json
index fc5e766e..d2dd32ff 100644
--- a/public/translations/el/default.json
+++ b/public/translations/el/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Εμφάνιση μόνο ασφαλών πινάκων εργασίας",
"show_all_content": "Εμφάνιση όλων των περιεχομένων",
"link_type": "Τύπος συνδέσμου",
- "comment_edited_at_timestamp": "Επεξεργασία σχολίου στις {{timestamp}}.",
+ "comment_edited_at_timestamp": "Σχόλιο επεξεργασμένο στις <1>{{timestamp}}1>",
"reason_reason": "Λόγος: \"{{reason}}\".",
"click_here_to_show_original": "<1>Κάντε κλικ εδώ1> για να εμφανιστεί το αρχικό.",
"click_here_to_hide_original": "<1>Κάντε κλικ εδώ1> για να κρύψετε το αρχικό.",
diff --git a/public/translations/en/default.json b/public/translations/en/default.json
index 695f5b88..aa04d0db 100644
--- a/public/translations/en/default.json
+++ b/public/translations/en/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Show Worksafe Boards Only",
"show_all_content": "Show All Content",
"link_type": "Link type",
- "comment_edited_at_timestamp": "Comment edited at {{timestamp}}.",
+ "comment_edited_at_timestamp": "Comment edited at <1>{{timestamp}}1>",
"reason_reason": "Reason: \"{{reason}}\".",
"click_here_to_show_original": "<1>Click here1> to show the original.",
"click_here_to_hide_original": "<1>Click here1> to hide the original.",
diff --git a/public/translations/es/default.json b/public/translations/es/default.json
index aa5b4c1f..f0a15fbb 100644
--- a/public/translations/es/default.json
+++ b/public/translations/es/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Mostrar solo tableros seguros para el trabajo",
"show_all_content": "Mostrar todo el contenido",
"link_type": "Tipo de enlace",
- "comment_edited_at_timestamp": "Comentario editado en {{timestamp}}.",
+ "comment_edited_at_timestamp": "Comentario editado el <1>{{timestamp}}1>",
"reason_reason": "Motivo: \"{{reason}}\".",
"click_here_to_show_original": "<1>Haga clic aquí1> para mostrar el original.",
"click_here_to_hide_original": "<1>Haga clic aquí1> para ocultar el original.",
diff --git a/public/translations/fa/default.json b/public/translations/fa/default.json
index e0574fb6..693e9bc9 100644
--- a/public/translations/fa/default.json
+++ b/public/translations/fa/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "نمایش تنها بوردهای ایمن برای کار",
"show_all_content": "نمایش تمام محتوا",
"link_type": "نوع پیوند",
- "comment_edited_at_timestamp": "ویرایش نظر در {{timestamp}}.",
+ "comment_edited_at_timestamp": "نظر ویرایش شده در <1>{{timestamp}}1>",
"reason_reason": "دلیل: \"{{reason}}\".",
"click_here_to_show_original": "<1>برای نمایش اصلی اینجا کلیک کنید1>.",
"click_here_to_hide_original": "<1>برای پنهان کردن اصل اینجا کلیک کنید1>.",
diff --git a/public/translations/fi/default.json b/public/translations/fi/default.json
index c73b7953..7f4e8c7d 100644
--- a/public/translations/fi/default.json
+++ b/public/translations/fi/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Näytä vain työturvalliset hallit",
"show_all_content": "Näytä kaikki sisällöt",
"link_type": "Linkin tyyppi",
- "comment_edited_at_timestamp": "Kommentti muokattu {{timestamp}}.",
+ "comment_edited_at_timestamp": "Kommentti muokattu <1>{{timestamp}}1>",
"reason_reason": "Syy: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klikkaa tästä1> näyttääksesi alkuperäisen.",
"click_here_to_hide_original": "<1>Klikkaa tästä1> piilottaaksesi alkuperäisen.",
diff --git a/public/translations/fil/default.json b/public/translations/fil/default.json
index 4086bb76..3235c8ce 100644
--- a/public/translations/fil/default.json
+++ b/public/translations/fil/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Ipakita lamang ang mga Worksafe boards",
"show_all_content": "Ipakita lahat ng nilalaman",
"link_type": "Uri ng Link",
- "comment_edited_at_timestamp": "Inedit na komento sa {{timestamp}}.",
+ "comment_edited_at_timestamp": "Na-edit ang komento sa <1>{{timestamp}}1>",
"reason_reason": "Dahilan: \"{{reason}}\".",
"click_here_to_show_original": "<1>I-click dito1> upang ipakita ang orihinal.",
"click_here_to_hide_original": "<1>I-click dito1> upang itago ang orihinal.",
diff --git a/public/translations/fr/default.json b/public/translations/fr/default.json
index afd4786d..9e2d1278 100644
--- a/public/translations/fr/default.json
+++ b/public/translations/fr/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Afficher uniquement les tableaux Worksafe",
"show_all_content": "Afficher tout le contenu",
"link_type": "Type de lien",
- "comment_edited_at_timestamp": "Commentaire modifié à {{timestamp}}.",
+ "comment_edited_at_timestamp": "Commentaire modifié le <1>{{timestamp}}1>",
"reason_reason": "Raison: \"{{reason}}\".",
"click_here_to_show_original": "<1>Cliquez ici1> pour afficher l'original.",
"click_here_to_hide_original": "<1>Cliquez ici1> pour masquer l'original.",
diff --git a/public/translations/he/default.json b/public/translations/he/default.json
index b0808479..9224e779 100644
--- a/public/translations/he/default.json
+++ b/public/translations/he/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "הצג לוחות עבודה בטוחים בלבד",
"show_all_content": "הצג את כל התוכן",
"link_type": "סוג קישור",
- "comment_edited_at_timestamp": "התגובה עודכנה ב {{timestamp}}.",
+ "comment_edited_at_timestamp": "התגובה נערכה ב-<1>{{timestamp}}1>",
"reason_reason": "סיבה: \"{{reason}}\".",
"click_here_to_show_original": "<1>לחץ כאן1> כדי להציג את המקור.",
"click_here_to_hide_original": "<1>לחץ כאן1> כדי להסתיר את המקור.",
diff --git a/public/translations/hi/default.json b/public/translations/hi/default.json
index 05422457..086ac424 100644
--- a/public/translations/hi/default.json
+++ b/public/translations/hi/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "केवल कामसुरक्षित बोर्ड्स दिखाएं",
"show_all_content": "सभी सामग्री दिखाएं",
"link_type": "लिंक प्रकार",
- "comment_edited_at_timestamp": "टिप्पणी {{timestamp}} पर संपादित की गई।",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> पर टिप्पणी संपादित की गई",
"reason_reason": "कारण: \"{{reason}}\".",
"click_here_to_show_original": "<1>यहां क्लिक करें1> मूल दिखाने के लिए।",
"click_here_to_hide_original": "<1>यहां क्लिक करें1> मूल छुपाने के लिए।",
diff --git a/public/translations/hu/default.json b/public/translations/hu/default.json
index 155a9da7..e67e0445 100644
--- a/public/translations/hu/default.json
+++ b/public/translations/hu/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Csak munkabiztos táblák mutatása",
"show_all_content": "Mutasd az összes tartalmat",
"link_type": "Link típusa",
- "comment_edited_at_timestamp": "Hozzászólás szerkesztve itt: {{timestamp}}.",
+ "comment_edited_at_timestamp": "Megjegyzés szerkesztve ekkor: <1>{{timestamp}}1>",
"reason_reason": "Ok: \"{{reason}}\".",
"click_here_to_show_original": "<1>Kattints ide1> az eredeti megjelenítéséhez.",
"click_here_to_hide_original": "<1>Kattints ide1> az eredeti elrejtéséhez.",
diff --git a/public/translations/id/default.json b/public/translations/id/default.json
index 3e5a6d58..8ed56d4a 100644
--- a/public/translations/id/default.json
+++ b/public/translations/id/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Tampilkan Hanya Board Worksafe",
"show_all_content": "Tampilkan Semua Konten",
"link_type": "Tipe tautan",
- "comment_edited_at_timestamp": "Komentar diedit pada {{timestamp}}.",
+ "comment_edited_at_timestamp": "Komentar diedit pada <1>{{timestamp}}1>",
"reason_reason": "Alasan: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klik di sini1> untuk menampilkan aslinya.",
"click_here_to_hide_original": "<1>Klik di sini1> untuk menyembunyikan aslinya.",
diff --git a/public/translations/it/default.json b/public/translations/it/default.json
index 3616a655..e8d4c99a 100644
--- a/public/translations/it/default.json
+++ b/public/translations/it/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Mostra solo le board Worksafe",
"show_all_content": "Mostra tutti i contenuti",
"link_type": "Tipo di link",
- "comment_edited_at_timestamp": "Commento modificato il {{timestamp}}.",
+ "comment_edited_at_timestamp": "Commento modificato il <1>{{timestamp}}1>",
"reason_reason": "Motivo: \"{{reason}}\".",
"click_here_to_show_original": "<1>Clicca qui1> per mostrare l'originale.",
"click_here_to_hide_original": "<1>Clicca qui1> per nascondere l'originale.",
diff --git a/public/translations/ja/default.json b/public/translations/ja/default.json
index 320acfb1..87c47f4e 100644
--- a/public/translations/ja/default.json
+++ b/public/translations/ja/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Worksafeボードのみ表示",
"show_all_content": "すべてのコンテンツを表示",
"link_type": "リンクの種類",
- "comment_edited_at_timestamp": "コメントは{{timestamp}}に編集されました。",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> にコメントを編集しました",
"reason_reason": "理由: \"{{reason}}\".",
"click_here_to_show_original": "<1>ここをクリック1> して元の表示。",
"click_here_to_hide_original": "<1>ここをクリック1> して元を非表示にする。",
diff --git a/public/translations/ko/default.json b/public/translations/ko/default.json
index 18b159b9..1648ee59 100644
--- a/public/translations/ko/default.json
+++ b/public/translations/ko/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "작업 안전 보드만 표시",
"show_all_content": "모든 콘텐츠 보기",
"link_type": "링크 유형",
- "comment_edited_at_timestamp": "댓글 편집 날짜: {{timestamp}}",
+ "comment_edited_at_timestamp": "댓글 편집 시간: <1>{{timestamp}}1>",
"reason_reason": "이유: \"{{reason}}\".",
"click_here_to_show_original": "<1>여기를 클릭1> 하여 원본 표시.",
"click_here_to_hide_original": "<1>여기를 클릭1> 하여 원본 숨기기.",
diff --git a/public/translations/mr/default.json b/public/translations/mr/default.json
index 9b498f1d..27edb988 100644
--- a/public/translations/mr/default.json
+++ b/public/translations/mr/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "केवळ कामसुरक्षित बोर्ड्स दाखवा",
"show_all_content": "सर्व सामग्री दाखवा",
"link_type": "लिंक प्रकार",
- "comment_edited_at_timestamp": "टिप्पणी {{timestamp}} वर संपादित केली आहे.",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> ला संपादित केला",
"reason_reason": "कारण: \"{{reason}}\".",
"click_here_to_show_original": "<1>येथे क्लिक करा1> मूळ पाहण्यासाठी।",
"click_here_to_hide_original": "<1>येथे क्लिक करा1> मूळ लपविण्यासाठी।",
diff --git a/public/translations/nl/default.json b/public/translations/nl/default.json
index 1ea59755..6958932e 100644
--- a/public/translations/nl/default.json
+++ b/public/translations/nl/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Toon alleen Worksafe boards",
"show_all_content": "Toon alle inhoud",
"link_type": "Link type",
- "comment_edited_at_timestamp": "Reactie bewerkt op {{timestamp}}.",
+ "comment_edited_at_timestamp": "Reactie bewerkt op <1>{{timestamp}}1>",
"reason_reason": "Reden: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klik hier1> om de originele te tonen.",
"click_here_to_hide_original": "<1>Klik hier1> om de originele te verbergen.",
diff --git a/public/translations/no/default.json b/public/translations/no/default.json
index 7519dd04..57745775 100644
--- a/public/translations/no/default.json
+++ b/public/translations/no/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Vis kun Worksafe boards",
"show_all_content": "Vis allt innhold",
"link_type": "Lenketype",
- "comment_edited_at_timestamp": "Kommentaren ble redigert på {{timestamp}}.",
+ "comment_edited_at_timestamp": "Kommentaren ble redigert på <1>{{timestamp}}1>",
"reason_reason": "Årsak: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klikk her1> for å vise originalen.",
"click_here_to_hide_original": "<1>Klikk her1> for å skjule originalen.",
diff --git a/public/translations/pl/default.json b/public/translations/pl/default.json
index aca5770a..c2a90851 100644
--- a/public/translations/pl/default.json
+++ b/public/translations/pl/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Pokaż tylko bezpieczne tablice",
"show_all_content": "Pokaż całą zawartość",
"link_type": "Typ łącza",
- "comment_edited_at_timestamp": "Komentarz edytowany o {{timestamp}}.",
+ "comment_edited_at_timestamp": "Komentarz edytowany <1>{{timestamp}}1>",
"reason_reason": "Powód: \"{{reason}}\".",
"click_here_to_show_original": "<1>Kliknij tutaj1>, aby pokazać oryginał.",
"click_here_to_hide_original": "<1>Kliknij tutaj1>, aby ukryć oryginał.",
diff --git a/public/translations/pt/default.json b/public/translations/pt/default.json
index 206f9dd8..f399d951 100644
--- a/public/translations/pt/default.json
+++ b/public/translations/pt/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Mostrar apenas boards Worksafe",
"show_all_content": "Mostrar Todo o Conteúdo",
"link_type": "Tipo de link",
- "comment_edited_at_timestamp": "Comentário editado em {{timestamp}}.",
+ "comment_edited_at_timestamp": "Comentário editado em <1>{{timestamp}}1>",
"reason_reason": "Razão: \"{{reason}}\".",
"click_here_to_show_original": "<1>Clique aqui1> para mostrar o original.",
"click_here_to_hide_original": "<1>Clique aqui1> para ocultar o original.",
diff --git a/public/translations/ro/default.json b/public/translations/ro/default.json
index 479778f1..2a97e2e1 100644
--- a/public/translations/ro/default.json
+++ b/public/translations/ro/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Afișați doar tablourile Worksafe",
"show_all_content": "Afișați tot conținutul",
"link_type": "Tipul linkului",
- "comment_edited_at_timestamp": "Comentariu editat la {{timestamp}}.",
+ "comment_edited_at_timestamp": "Comentariu editat la <1>{{timestamp}}1>",
"reason_reason": "Motiv: \"{{reason}}\".",
"click_here_to_show_original": "<1>Click aici1> pentru a arăta originalul.",
"click_here_to_hide_original": "<1>Click aici1> pentru a ascunde originalul.",
diff --git a/public/translations/ru/default.json b/public/translations/ru/default.json
index 32b62dc0..ab83b7ca 100644
--- a/public/translations/ru/default.json
+++ b/public/translations/ru/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Показывать только безопасные доски",
"show_all_content": "Показать весь контент",
"link_type": "Тип ссылки",
- "comment_edited_at_timestamp": "Комментарий изменён {{timestamp}}.",
+ "comment_edited_at_timestamp": "Комментарий изменен в <1>{{timestamp}}1>",
"reason_reason": "Причина: \"{{reason}}\".",
"click_here_to_show_original": "<1>Нажмите здесь1> для отображения оригинала.",
"click_here_to_hide_original": "<1>Нажмите здесь1> чтобы скрыть оригинал.",
diff --git a/public/translations/sq/default.json b/public/translations/sq/default.json
index dcea602d..dbe3121f 100644
--- a/public/translations/sq/default.json
+++ b/public/translations/sq/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Shfaq vetëm taulat e sigurta të punës",
"show_all_content": "Shfaq të gjitha përmbajtjet",
"link_type": "Lloji i lidhjes",
- "comment_edited_at_timestamp": "Komenti është ndryshuar në {{timestamp}}.",
+ "comment_edited_at_timestamp": "Komenti u redaktua në <1>{{timestamp}}1>",
"reason_reason": "Arsye: \"{{reason}}\".",
"click_here_to_show_original": "<1>Kliko këtu1> për të treguar origjinalin.",
"click_here_to_hide_original": "<1>Kliko këtu1> për të fshehur origjinalin.",
diff --git a/public/translations/sv/default.json b/public/translations/sv/default.json
index 99eff5df..b13a061f 100644
--- a/public/translations/sv/default.json
+++ b/public/translations/sv/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Visa endast Worksafe-styrelser",
"show_all_content": "Visa allt innehåll",
"link_type": "Länktyp",
- "comment_edited_at_timestamp": "Kommentaren redigerades den {{timestamp}}.",
+ "comment_edited_at_timestamp": "Kommentar redigerad vid <1>{{timestamp}}1>",
"reason_reason": "Anledning: \"{{reason}}\".",
"click_here_to_show_original": "<1>Klicka här1> för att visa original.",
"click_here_to_hide_original": "<1>Klicka här1> för att dölja original.",
diff --git a/public/translations/te/default.json b/public/translations/te/default.json
index 3107441f..9a196891 100644
--- a/public/translations/te/default.json
+++ b/public/translations/te/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "పనిమాడు భద్రపరిచిన బోర్డులను మాత్రమే చూపించు",
"show_all_content": "అన్ని కాంటెంట్ చూపించు",
"link_type": "లింక్ రకం",
- "comment_edited_at_timestamp": "వ్యాఖ్యను {{timestamp}} లో సవరించబడింది.",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> లో సమీక్ష సవరించబడింది",
"reason_reason": "కారణం: \"{{reason}}\".",
"click_here_to_show_original": "<1>ఇక్కడ క్లిక్ చేయండి1> అసలు చూపించడానికి.",
"click_here_to_hide_original": "<1>ఇక్కడ క్లిక్ చేయండి1> అసలు దాచడానికి.",
diff --git a/public/translations/th/default.json b/public/translations/th/default.json
index 83d06973..96bd70b3 100644
--- a/public/translations/th/default.json
+++ b/public/translations/th/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "แสดงบอร์ด Worksafe เท่านั้น",
"show_all_content": "แสดงเนื้อหาทั้งหมด",
"link_type": "ประเภทลิงก์",
- "comment_edited_at_timestamp": "แก้ไขความคิดเห็นที่ {{timestamp}}",
+ "comment_edited_at_timestamp": "แก้ไขความคิดเห็นที่ <1>{{timestamp}}1>",
"reason_reason": "เหตุผล: \"{{reason}}\".",
"click_here_to_show_original": "<1>คลิกที่นี่1> เพื่อแสดงข้อมูลต้นฉบับ",
"click_here_to_hide_original": "<1>คลิกที่นี่1> เพื่อซ่อนข้อมูลต้นฉบับ",
diff --git a/public/translations/tr/default.json b/public/translations/tr/default.json
index b5ab4b44..cba587fd 100644
--- a/public/translations/tr/default.json
+++ b/public/translations/tr/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Sadece Worksafe Panoları Göster",
"show_all_content": "Tüm İçeriği Göster",
"link_type": "Bağlantı türü",
- "comment_edited_at_timestamp": "Yorum {{timestamp}} tarihinde düzenlendi.",
+ "comment_edited_at_timestamp": "<1>{{timestamp}}1> tarihinde yorum düzenlendi",
"reason_reason": "Sebep: \"{{reason}}\".",
"click_here_to_show_original": "<1>Buraya tıklayın1> orijinali göstermek için.",
"click_here_to_hide_original": "<1>Buraya tıklayın1> orijinali gizlemek için.",
diff --git a/public/translations/uk/default.json b/public/translations/uk/default.json
index 7dd54634..8714d547 100644
--- a/public/translations/uk/default.json
+++ b/public/translations/uk/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Показувати лише безпечні дошки",
"show_all_content": "Показати весь вміст",
"link_type": "Тип посилання",
- "comment_edited_at_timestamp": "Коментар було відредаговано {{timestamp}}.",
+ "comment_edited_at_timestamp": "Коментар відредаговано в <1>{{timestamp}}1>",
"reason_reason": "Причина: \"{{reason}}\".",
"click_here_to_show_original": "<1>Натисніть тут1> для відображення оригіналу.",
"click_here_to_hide_original": "<1>Натисніть тут1> для приховання оригіналу.",
diff --git a/public/translations/ur/default.json b/public/translations/ur/default.json
index 138ad8e0..937b57b7 100644
--- a/public/translations/ur/default.json
+++ b/public/translations/ur/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "صرف کام سے بچائے گئے بورڈز دکھائیں",
"show_all_content": "تمام مواد دکھائیں",
"link_type": "لنک کی قسم",
- "comment_edited_at_timestamp": "تبدیل کی گئی تبدیلی کا {{timestamp}}۔",
+ "comment_edited_at_timestamp": "تبدیل کیا گیا تبصرہ <1>{{timestamp}}1> پر",
"reason_reason": "وجہ: \"{{reason}}\".",
"click_here_to_show_original": "<1>یہاں کلک کریں1> تاکہ اصل دکھائی دے۔",
"click_here_to_hide_original": "<1>یہاں کلک کریں1> تاکہ اصل چھپ جائے۔",
diff --git a/public/translations/vi/default.json b/public/translations/vi/default.json
index 5510836d..79cee730 100644
--- a/public/translations/vi/default.json
+++ b/public/translations/vi/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "Chỉ hiển thị bảng Worksafe",
"show_all_content": "Hiển thị tất cả nội dung",
"link_type": "Loại liên kết",
- "comment_edited_at_timestamp": "Bình luận được chỉnh sửa lúc {{timestamp}}.",
+ "comment_edited_at_timestamp": "Bình luận được chỉnh sửa lúc <1>{{timestamp}}1>",
"reason_reason": "Lý do: \"{{reason}}\".",
"click_here_to_show_original": "<1>Nhấp vào đây1> để hiển thị nguyên bản.",
"click_here_to_hide_original": "<1>Nhấp vào đây1> để ẩn nguyên bản.",
diff --git a/public/translations/zh/default.json b/public/translations/zh/default.json
index 96e7de3b..2f044b17 100644
--- a/public/translations/zh/default.json
+++ b/public/translations/zh/default.json
@@ -195,7 +195,7 @@
"show_worksafe_boards_only": "仅显示安全工作板",
"show_all_content": "显示所有内容",
"link_type": "链接类型",
- "comment_edited_at_timestamp": "评论于{{timestamp}}进行了编辑。",
+ "comment_edited_at_timestamp": "评论于 <1>{{timestamp}}1> 被编辑",
"reason_reason": "原因: \"{{reason}}\".",
"click_here_to_show_original": "<1>点击这里1> 显示原文。",
"click_here_to_hide_original": "<1>点击这里1> 隐藏原文。",
diff --git a/src/app.module.css b/src/app.module.css
index 98d8d6cf..3b84f8f8 100644
--- a/src/app.module.css
+++ b/src/app.module.css
@@ -1,5 +1,6 @@
.app {
z-index: 1;
+ color-scheme: var(--color-scheme, revert) !important;
}
.boardLayout {
diff --git a/src/components/board-buttons/board-buttons.module.css b/src/components/board-buttons/board-buttons.module.css
index 36a20ac2..68e2416b 100644
--- a/src/components/board-buttons/board-buttons.module.css
+++ b/src/components/board-buttons/board-buttons.module.css
@@ -32,6 +32,7 @@
display: flex;
align-items: center;
justify-content: space-between; /* Ensure elements are spaced out properly */
+ padding-right: 5px;
}
.desktopBoardButtons::after {
diff --git a/src/components/board-buttons/board-buttons.tsx b/src/components/board-buttons/board-buttons.tsx
index fbcc9be4..2eccddab 100644
--- a/src/components/board-buttons/board-buttons.tsx
+++ b/src/components/board-buttons/board-buttons.tsx
@@ -1,13 +1,15 @@
import { useTranslation } from 'react-i18next';
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
-import { useAccountComment, useSubscribe } from '@plebbit/plebbit-react-hooks';
-import { isAllView, isCatalogView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
+import { useAccountComment, useComment, useSubscribe } from '@plebbit/plebbit-react-hooks';
+import { isAllView, isCatalogView, isDescriptionView, isPendingPostView, isPostPageView, isRulesView, isSubscriptionsView } from '../../lib/utils/view-utils';
import useCatalogStyleStore from '../../stores/use-catalog-style-store';
import useFeedResetStore from '../../stores/use-feed-reset-store';
import useSortingStore from '../../stores/use-sorting-store';
import useTimeFilter from '../../hooks/use-time-filter';
import CatalogFilters from '../../views/catalog/catalog-filters/';
import styles from './board-buttons.module.css';
+import Tooltip from '../tooltip';
+import useCountLinksInReplies from '../../hooks/use-count-links-in-replies';
interface BoardButtonsProps {
address?: string | undefined;
@@ -220,6 +222,25 @@ export const MobileBoardButtons = () => {
);
};
+const PostPageStats = () => {
+ const params = useParams();
+ const location = useLocation();
+ const isInDescriptionView = isDescriptionView(location.pathname, params);
+ const isInRulesView = isRulesView(location.pathname, params);
+
+ const comment = useComment({ commentCid: params?.commentCid });
+ const { closed, pinned, replyCount } = comment || {};
+ const linkCount = useCountLinksInReplies(comment);
+
+ return (
+
+ {(pinned || isInDescriptionView || isInRulesView) && 'Sticky / '}
+ {(closed || isInDescriptionView || isInRulesView) && 'Closed / '}
+
- {isReply && !(removed || deleted) && isReplyingToReply &&} + {isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && } {removed ? ( ({t('this_post_was_removed')})} @@ -251,12 +252,17 @@ const PostMessage = ({ post }: PostProps) => { {t('user_deleted_this_post')}} content={reason && `${t('reason')}: ${reason}`} /> ) : ( <> - {!showOriginal && } + {!showOriginal && } {edit && original?.content !== post?.content && ( {showOriginal && }
- {t('comment_edited_at_timestamp', { timestamp: getFormattedDate(edit?.timestamp), interpolation: { escapeValue: false } })}{' '} +>} /> }} + />{' '} {reason && <>{t('reason_reason', { reason: reason, interpolation: { escapeValue: false } })} >} {showOriginal ? ( { )} > )} - {banned && ( + {/* TODO: commentAuthor is not available outside of editedComment, update when available */} + {/* {banned && (
@@ -288,7 +295,7 @@ const PostMessage = ({ post }: PostProps) => { })}${reason ? `. ${_.capitalize(t('reason'))}: "${reason}"` : ''}`} /> - )} + )} */} {!isReply && content.length > 1000 && !isInPostView && (
@@ -348,9 +355,9 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies const replies = useReplies(post); const visiblelinksCount = useCountLinksInReplies(post, 5); - const totallinksCount = useCountLinksInReplies(post); + const totalLinksCount = useCountLinksInReplies(post); const repliesCount = pinned ? replyCount : replyCount - 5; - const linksCount = pinned ? totallinksCount : totallinksCount - visiblelinksCount; + const linksCount = pinned ? totalLinksCount : totalLinksCount - visiblelinksCount; const { showOmittedReplies, setShowOmittedReplies } = useShowOmittedReplies(); // scroll to reply if pathname is reply permalink (backlink) diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index 7d871f68..287cbbf8 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -12,7 +12,7 @@ import useReply from '../../hooks/use-reply'; import useChallengesStore from '../../stores/use-challenges-store'; import styles from './post-form.module.css'; import _ from 'lodash'; -import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; +import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline'; type SubmitState = { subplebbitAddress: string | undefined; @@ -272,17 +272,12 @@ const PostForm = () => { const [showForm, setShowForm] = useState(false); const subplebbit = useSubplebbit({ subplebbitAddress: params?.subplebbitAddress }); - const { updatedAt } = subplebbit || {}; - const isBoardOffline = updatedAt && updatedAt < Date.now() / 1000 - 60 * 60; - - const offlineMessage = updatedAt - ? isBoardOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) - : t('subplebbit_offline_info'); + const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit); return ( <>- {!(isInAllView || isInSubscriptionsView) && showForm && isBoardOffline &&{offlineMessage}} + {!(isInAllView || isInSubscriptionsView) && showForm && isOffline &&{offlineTitle}} {isThreadClosed ? ({t('thread_closed')} @@ -302,7 +297,7 @@ const PostForm = () => { )}- {!(isInAllView || isInSubscriptionsView) && showForm && isBoardOffline &&{offlineMessage}} + {!(isInAllView || isInSubscriptionsView) && showForm && isOffline &&{offlineTitle}} {isThreadClosed ? ({t('thread_closed')} diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index cb0e227d..542fb75d 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -152,8 +152,9 @@ const ReplyBacklinks = ({ post }: PostProps) => { const PostMessageMobile = ({ post }: PostProps) => { const { t } = useTranslation(); - const { cid, commentAuthor, content, deleted, edit, original, parentCid, postCid, reason, removed, spoiler, state, subplebbitAddress } = post || {}; - const banned = !!commentAuthor?.banExpiresAt; + const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {}; + // TODO: commentAuthor is not available outside of editedComment, update when available + // const banned = !!post?.commentAuthor?.banExpiresAt; const [showOriginal, setShowOriginal] = useState(false); const params = useParams(); @@ -176,7 +177,7 @@ const PostMessageMobile = ({ post }: PostProps) => { return ( content && (- {isReply && !(removed || deleted) && isReplyingToReply &&} + {isReply && !(removed || deleted) && state !== 'failed' && isReplyingToReply && } {removed ? ( ({t('this_post_was_removed')})} @@ -187,7 +188,7 @@ const PostMessageMobile = ({ post }: PostProps) => { {t('user_deleted_this_post')}} content={reason && `${t('reason')}: ${reason}`} /> ) : ( <> - {!showOriginal && } + {!showOriginal && } {edit && original?.content !== post?.content && ( {showOriginal && } @@ -211,7 +212,8 @@ const PostMessageMobile = ({ post }: PostProps) => { )} > )} - {banned && ( + {/* TODO: commentAuthor is not available outside of editedComment, update when available */} + {/* {banned && (
@@ -224,7 +226,7 @@ const PostMessageMobile = ({ post }: PostProps) => { })}${reason ? `. ${_.capitalize(t('reason'))}: "${reason}"` : ''}`} /> - )} + )} */} {!isReply && content.length > 1000 && !isInPostView && (
diff --git a/src/hooks/use-is-subplebbit-offline.ts b/src/hooks/use-is-subplebbit-offline.ts new file mode 100644 index 00000000..33875c20 --- /dev/null +++ b/src/hooks/use-is-subplebbit-offline.ts @@ -0,0 +1,19 @@ +import { useTranslation } from 'react-i18next'; +import { Subplebbit } from '@plebbit/plebbit-react-hooks'; +import { getFormattedTimeAgo } from '../lib/utils/time-utils'; + +const useIsSubplebbitOffline = (subplebbit: Subplebbit) => { + const { t } = useTranslation(); + const { updatedAt, updatingState } = subplebbit || {}; + const isProbablyOffline = !updatedAt || (updatedAt && updatedAt < Date.now() / 1000 - 60 * 60); + const isDefinitelyOffline = updatingState === 'failed'; + const isOffline = isProbablyOffline || isDefinitelyOffline; + + const offlineTitle = updatedAt + ? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) + : t('subplebbit_offline_info'); + + return { isOffline, isDefinitelyOffline, offlineTitle }; +}; + +export default useIsSubplebbitOffline; diff --git a/src/index.css b/src/index.css index 073f0c2a..ae102085 100644 --- a/src/index.css +++ b/src/index.css @@ -30,8 +30,12 @@ hr { text-transform: capitalize; } -* { - color-scheme: var(--color-scheme, revert); +.red { + color: red !important; +} + +:root { + color-scheme: dark; } @media (max-width: 640px) { diff --git a/src/themes.css b/src/themes.css index ed177355..35d05a2f 100644 --- a/src/themes.css +++ b/src/themes.css @@ -1,4 +1,6 @@ :root .yotsuba { + --color-scheme: light; + /* backlink */ --post-backlink-text-color: navy; --post-backlink-text-decoration: underline; @@ -204,6 +206,8 @@ } :root .yotsuba-b { + --color-scheme: light; + /* backlink */ --post-backlink-text-color: #34345C; --post-backlink-text-decoration: underline; @@ -409,6 +413,8 @@ } :root .futaba { + --color-scheme: light; + /* backlink */ --post-backlink-text-color: navy; --post-backlink-text-decoration: underline; @@ -581,6 +587,8 @@ } :root .burichan { + --color-scheme: light; + /* backlink */ --post-backlink-text-color: #34345C; --post-backlink-text-decoration: underline; @@ -976,6 +984,8 @@ } :root .photon { + --color-scheme: light; + /* backlink */ --post-backlink-text-color: #f60; --post-backlink-text-decoration: underline; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index 3a82e812..eb1a87ad 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -72,14 +72,14 @@ const Board = () => { const loadingString = ({state === 'failed' ? ( - state + {state} ) : isInSubscriptionsView && subscriptions?.length === 0 ? ( t('not_subscribed_to_any_board') ) : (); diff --git a/src/views/post/post.module.css b/src/views/post/post.module.css index 9767a21c..72d448fa 100644 --- a/src/views/post/post.module.css +++ b/src/views/post/post.module.css @@ -3,6 +3,12 @@ overflow-x: hidden; } +.error { + color: red; + padding: 5px; + display: block; +} + .thread { clear: both; } @@ -508,6 +514,11 @@ } @media (min-width: 640px) { + .error { + padding-left: 0; + padding-bottom: 0; + } + .replyQuotePreview { padding-right: 7px; padding-left: 2px; diff --git a/src/views/post/post.tsx b/src/views/post/post.tsx index 415839cd..16846192 100644 --- a/src/views/post/post.tsx +++ b/src/views/post/post.tsx @@ -75,7 +75,7 @@ const PostPage = () => { post = comment; } - const { deleted, locked, removed } = post || {}; + const { error, deleted, locked, removed, replyCount } = post || {}; const isThreadClosed = deleted || locked || removed; useEffect(() => { @@ -92,6 +92,9 @@ const PostPage = () => {)} {error && ( - +diff --git a/src/views/home/boards-box/boards-box.tsx b/src/views/home/boards-box/boards-box.tsx index 7dbee2d8..6f9cda02 100644 --- a/src/views/home/boards-box/boards-box.tsx +++ b/src/views/home/boards-box/boards-box.tsx @@ -2,12 +2,12 @@ import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Subplebbit, useAccount, useAccountSubplebbits } from '@plebbit/plebbit-react-hooks'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; -import { getFormattedTimeAgo } from '../../../lib/utils/time-utils'; import useHomeFiltersStore from '../../../stores/use-home-filters-store'; import { useMultisubMetadata } from '../../../hooks/use-default-subplebbits'; import styles from '../home.module.css'; import { nsfwTags } from '../home'; import BoxModal from '../box-modal'; +import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline'; const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbits: any }) => { const { t } = useTranslation(); @@ -18,15 +18,12 @@ const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbit const boardLink = useCatalog ? `/p/${address}/catalog` : `/p/${address}`; const subplebbitData = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address); - const updatedAt = subplebbitData?.updatedAt; - const isOffline = updatedAt && updatedAt < Date.now() / 1000 - 60 * 60; - const offlineTitle = updatedAt - ? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) - : t('subplebbit_offline_info'); + const { isDefinitelyOffline, isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbitData); + const iconClass = `${styles.offlineIcon} ${isDefinitelyOffline ? styles.redOfflineIcon : ''}`; return (
{error.message}- {isOffline && } + {isOffline && } {title || address} {nsfwTag && ({t(nsfwTag)})}diff --git a/src/views/home/home.module.css b/src/views/home/home.module.css index 043f746c..9e28a197 100644 --- a/src/views/home/home.module.css +++ b/src/views/home/home.module.css @@ -187,6 +187,10 @@ image-rendering: pixelated; } +.redOfflineIcon { + background-image: url('/public/assets/icons/offline-red.png') !important; +} + .boardsBoxContent { font-size: 93%; padding: 0.5em; diff --git a/src/views/home/popular-threads-box/popular-threads-box.tsx b/src/views/home/popular-threads-box/popular-threads-box.tsx index 338dc4c8..6e6a58ae 100644 --- a/src/views/home/popular-threads-box/popular-threads-box.tsx +++ b/src/views/home/popular-threads-box/popular-threads-box.tsx @@ -30,8 +30,13 @@ const PopularThreadCard = ({ post, boardTitle, boardShortAddress }: PopularThrea- {title && {title}} - {content && (content.length > 99 ? `: ${content.substring(0, 99)}...` : `: ${content}`)} + {title && ( + <> + {title.trim()} + {content && ': '} + > + )} + {content && (content.length > 99 ? `${content.substring(0, 99).trim()}...` : `${content}`)}{isInSettigsView &&} {showReplyModal && activeCid && } + {/* TODO: remove this replyCount error once api supports scrolling replies pages */} + {replyCount > 60 && Error: this thread has too many replies, some of them cannot be displayed right now.} + {error && Error: {error.message}} {isInDescriptionView ? (