Merge pull request #391 from plebbit/development

Development
This commit is contained in:
Tom (plebeius.eth)
2024-06-08 17:25:39 +02:00
committed by GitHub
62 changed files with 1011 additions and 167 deletions
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "اغلق الموضوع",
"view_spoiler": "عرض الحاضر",
"filter": "تصفية",
"edit": "تحرير"
"edit": "تحرير",
"time_1_minute_ago": "منذ دقيقة واحدة",
"time_x_minutes_ago": "منذ {{count}} دقائق",
"time_1_hour_ago": "منذ ساعة واحدة",
"time_x_hours_ago": "منذ {{count}} ساعات",
"time_1_day_ago": "منذ يوم واحد",
"time_x_days_ago": "منذ {{count}} أيام",
"time_1_month_ago": "منذ شهر واحد",
"time_x_months_ago": "منذ {{count}} شهور",
"time_1_year_ago": "منذ عام واحد",
"time_x_years_ago": "منذ {{count}} سنوات",
"open": "فتح"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "থ্রেড বন্ধ করুন",
"view_spoiler": "স্পোয়ালার দেখুন",
"filter": "ফিল্টার",
"edit": "সম্পাদনা"
"edit": "সম্পাদনা",
"time_1_minute_ago": "১ মিনিট আগে",
"time_x_minutes_ago": "{{count}} মিনিট আগে",
"time_1_hour_ago": "১ ঘণ্টা আগে",
"time_x_hours_ago": "{{count}} ঘণ্টা আগে",
"time_1_day_ago": "১ দিন আগে",
"time_x_days_ago": "{{count}} দিন আগে",
"time_1_month_ago": "১ মাস আগে",
"time_x_months_ago": "{{count}} মাস আগে",
"time_1_year_ago": "১ বছর আগে",
"time_x_years_ago": "{{count}} বছর আগে",
"open": "খুলুন"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "uzavřít vlákno",
"view_spoiler": "zobrazit spoiler",
"filter": "filtr",
"edit": "upravit"
"edit": "upravit",
"time_1_minute_ago": "Před 1 minutou",
"time_x_minutes_ago": "Před {{count}} minutami",
"time_1_hour_ago": "Před 1 hodinou",
"time_x_hours_ago": "Před {{count}} hodinami",
"time_1_day_ago": "Před 1 dnem",
"time_x_days_ago": "Před {{count}} dny",
"time_1_month_ago": "Před 1 měsícem",
"time_x_months_ago": "Před {{count}} měsíci",
"time_1_year_ago": "Před 1 rokem",
"time_x_years_ago": "Před {{count}} roky",
"open": "otevřít"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "luk tråd",
"view_spoiler": "vis spoiler",
"filter": "filtrér",
"edit": "rediger"
"edit": "rediger",
"time_1_minute_ago": "1 minut siden",
"time_x_minutes_ago": "{{count}} minutter siden",
"time_1_hour_ago": "1 time siden",
"time_x_hours_ago": "{{count}} timer siden",
"time_1_day_ago": "1 dag siden",
"time_x_days_ago": "{{count}} dage siden",
"time_1_month_ago": "1 måned siden",
"time_x_months_ago": "{{count}} måneder siden",
"time_1_year_ago": "1 år siden",
"time_x_years_ago": "{{count}} år siden",
"open": "åben"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "Thread schließen",
"view_spoiler": "Spoiler anzeigen",
"filter": "filtern",
"edit": "bearbeiten"
"edit": "bearbeiten",
"time_1_minute_ago": "vor 1 Minute",
"time_x_minutes_ago": "vor {{count}} Minuten",
"time_1_hour_ago": "vor 1 Stunde",
"time_x_hours_ago": "vor {{count}} Stunden",
"time_1_day_ago": "vor 1 Tag",
"time_x_days_ago": "vor {{count}} Tagen",
"time_1_month_ago": "vor 1 Monat",
"time_x_months_ago": "vor {{count}} Monaten",
"time_1_year_ago": "vor 1 Jahr",
"time_x_years_ago": "vor {{count}} Jahren",
"open": "öffnen"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "κλείσιμο νήματος",
"view_spoiler": "προβολή spoiler",
"filter": "φίλτρο",
"edit": "επεξεργασία"
"edit": "επεξεργασία",
"time_1_minute_ago": "Πριν από 1 λεπτό",
"time_x_minutes_ago": "Πριν από {{count}} λεπτά",
"time_1_hour_ago": "Πριν από 1 ώρα",
"time_x_hours_ago": "Πριν από {{count}} ώρες",
"time_1_day_ago": "Πριν από 1 ημέρα",
"time_x_days_ago": "Πριν από {{count}} ημέρες",
"time_1_month_ago": "Πριν από 1 μήνα",
"time_x_months_ago": "Πριν από {{count}} μήνες",
"time_1_year_ago": "Πριν από 1 έτος",
"time_x_years_ago": "Πριν από {{count}} έτη",
"open": "ανοικτό"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "close thread",
"view_spoiler": "view spoiler",
"filter": "filter",
"edit": "edit"
"edit": "edit",
"time_1_minute_ago": "1 minute ago",
"time_x_minutes_ago": "{{count}} minutes ago",
"time_1_hour_ago": "1 hour ago",
"time_x_hours_ago": "{{count}} hours ago",
"time_1_day_ago": "1 day ago",
"time_x_days_ago": "{{count}} days ago",
"time_1_month_ago": "1 month ago",
"time_x_months_ago": "{{count}} months ago",
"time_1_year_ago": "1 year ago",
"time_x_years_ago": "{{count}} years ago",
"open": "open"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "cerrar hilo",
"view_spoiler": "ver spoiler",
"filter": "filtrar",
"edit": "editar"
"edit": "editar",
"time_1_minute_ago": "hace 1 minuto",
"time_x_minutes_ago": "hace {{count}} minutos",
"time_1_hour_ago": "hace 1 hora",
"time_x_hours_ago": "hace {{count}} horas",
"time_1_day_ago": "hace 1 día",
"time_x_days_ago": "hace {{count}} días",
"time_1_month_ago": "hace 1 mes",
"time_x_months_ago": "hace {{count}} meses",
"time_1_year_ago": "hace 1 año",
"time_x_years_ago": "hace {{count}} años",
"open": "abrir"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "بستن موضوع",
"view_spoiler": "نمایش اسپویلر",
"filter": "فیلتر",
"edit": "ویرایش"
"edit": "ویرایش",
"time_1_minute_ago": "1 دقیقه پیش",
"time_x_minutes_ago": "{{count}} دقیقه پیش",
"time_1_hour_ago": "1 ساعت پیش",
"time_x_hours_ago": "{{count}} ساعت پیش",
"time_1_day_ago": "1 روز پیش",
"time_x_days_ago": "{{count}} روز پیش",
"time_1_month_ago": "1 ماه پیش",
"time_x_months_ago": "{{count}} ماه پیش",
"time_1_year_ago": "1 سال پیش",
"time_x_years_ago": "{{count}} سال پیش",
"open": "باز کردن"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "sulje keskustelu",
"view_spoiler": "näytä spoiler",
"filter": "suodatin",
"edit": "muokkaa"
"edit": "muokkaa",
"time_1_minute_ago": "1 minuutti sitten",
"time_x_minutes_ago": "{{count}} minuuttia sitten",
"time_1_hour_ago": "1 tunti sitten",
"time_x_hours_ago": "{{count}} tuntia sitten",
"time_1_day_ago": "1 päivä sitten",
"time_x_days_ago": "{{count}} päivää sitten",
"time_1_month_ago": "1 kuukausi sitten",
"time_x_months_ago": "{{count}} kuukautta sitten",
"time_1_year_ago": "1 vuosi sitten",
"time_x_years_ago": "{{count}} vuotta sitten",
"open": "avata"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "isara ang thread",
"view_spoiler": "tingnan ang spoiler",
"filter": "salain",
"edit": "i-edit"
"edit": "i-edit",
"time_1_minute_ago": "1 minuto ang nakalipas",
"time_x_minutes_ago": "{{count}} minuto ang nakalipas",
"time_1_hour_ago": "1 oras ang nakalipas",
"time_x_hours_ago": "{{count}} oras ang nakalipas",
"time_1_day_ago": "1 araw ang nakalipas",
"time_x_days_ago": "{{count}} araw ang nakalipas",
"time_1_month_ago": "1 buwan ang nakalipas",
"time_x_months_ago": "{{count}} buwan ang nakalipas",
"time_1_year_ago": "1 taon ang nakalipas",
"time_x_years_ago": "{{count}} taon ang nakalipas",
"open": "buksan"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "fermer le fil",
"view_spoiler": "voir le spoiler",
"filter": "filtre",
"edit": "modifier"
"edit": "modifier",
"time_1_minute_ago": "il y a 1 minute",
"time_x_minutes_ago": "il y a {{count}} minutes",
"time_1_hour_ago": "il y a 1 heure",
"time_x_hours_ago": "il y a {{count}} heures",
"time_1_day_ago": "il y a 1 jour",
"time_x_days_ago": "il y a {{count}} jours",
"time_1_month_ago": "il y a 1 mois",
"time_x_months_ago": "il y a {{count}} mois",
"time_1_year_ago": "il y a 1 an",
"time_x_years_ago": "il y a {{count}} ans",
"open": "ouvrir"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "סגור את הנושא",
"view_spoiler": "הצג ספוילר",
"filter": "סנן",
"edit": "ערוך"
"edit": "ערוך",
"time_1_minute_ago": "לפני דקה",
"time_x_minutes_ago": "לפני {{count}} דקות",
"time_1_hour_ago": "לפני שעה",
"time_x_hours_ago": "לפני {{count}} שעות",
"time_1_day_ago": "לפני יום",
"time_x_days_ago": "לפני {{count}} ימים",
"time_1_month_ago": "לפני חודש",
"time_x_months_ago": "לפני {{count}} חודשים",
"time_1_year_ago": "לפני שנה",
"time_x_years_ago": "לפני {{count}} שנים",
"open": "לפתוח"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "थ्रेड बंद करें",
"view_spoiler": "स्पॉइलर देखें",
"filter": "फ़िल्टर",
"edit": "संपादित करें"
"edit": "संपादित करें",
"time_1_minute_ago": "1 मिनट पहले",
"time_x_minutes_ago": "{{count}} मिनट पहले",
"time_1_hour_ago": "1 घंटा पहले",
"time_x_hours_ago": "{{count}} घंटे पहले",
"time_1_day_ago": "1 दिन पहले",
"time_x_days_ago": "{{count}} दिन पहले",
"time_1_month_ago": "1 महीना पहले",
"time_x_months_ago": "{{count}} महीने पहले",
"time_1_year_ago": "1 साल पहले",
"time_x_years_ago": "{{count}} साल पहले",
"open": "खोलें"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "szál bezárása",
"view_spoiler": "spoiler megtekintése",
"filter": "szűrő",
"edit": "szerkesztés"
"edit": "szerkesztés",
"time_1_minute_ago": "1 perce",
"time_x_minutes_ago": "{{count}} perce",
"time_1_hour_ago": "1 órája",
"time_x_hours_ago": "{{count}} órája",
"time_1_day_ago": "1 napja",
"time_x_days_ago": "{{count}} napja",
"time_1_month_ago": "1 hónapja",
"time_x_months_ago": "{{count}} hónapja",
"time_1_year_ago": "1 éve",
"time_x_years_ago": "{{count}} éve",
"open": "nyit"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "tutup utas",
"view_spoiler": "lihat spoiler",
"filter": "menyaring",
"edit": "sunting"
"edit": "sunting",
"time_1_minute_ago": "1 menit yang lalu",
"time_x_minutes_ago": "{{count}} menit yang lalu",
"time_1_hour_ago": "1 jam yang lalu",
"time_x_hours_ago": "{{count}} jam yang lalu",
"time_1_day_ago": "1 hari yang lalu",
"time_x_days_ago": "{{count}} hari yang lalu",
"time_1_month_ago": "1 bulan yang lalu",
"time_x_months_ago": "{{count}} bulan yang lalu",
"time_1_year_ago": "1 tahun yang lalu",
"time_x_years_ago": "{{count}} tahun yang lalu",
"open": "buka"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "chiudi il thread",
"view_spoiler": "mostra spoiler",
"filter": "filtro",
"edit": "modifica"
"edit": "modifica",
"time_1_minute_ago": "1 minuto fa",
"time_x_minutes_ago": "{{count}} minuti fa",
"time_1_hour_ago": "1 ora fa",
"time_x_hours_ago": "{{count}} ore fa",
"time_1_day_ago": "1 giorno fa",
"time_x_days_ago": "{{count}} giorni fa",
"time_1_month_ago": "1 mese fa",
"time_x_months_ago": "{{count}} mesi fa",
"time_1_year_ago": "1 anno fa",
"time_x_years_ago": "{{count}} anni fa",
"open": "apri"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "スレッドを閉じる",
"view_spoiler": "スポイラーを表示",
"filter": "フィルター",
"edit": "編集"
"edit": "編集",
"time_1_minute_ago": "1分前",
"time_x_minutes_ago": "{{count}}分前",
"time_1_hour_ago": "1時間前",
"time_x_hours_ago": "{{count}}時間前",
"time_1_day_ago": "1日前",
"time_x_days_ago": "{{count}}日前",
"time_1_month_ago": "1ヶ月前",
"time_x_months_ago": "{{count}}ヶ月前",
"time_1_year_ago": "1年前",
"time_x_years_ago": "{{count}}年前",
"open": "開く"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "스레드 닫기",
"view_spoiler": "스포일러 보기",
"filter": "필터",
"edit": "편집"
"edit": "편집",
"time_1_minute_ago": "1분 전",
"time_x_minutes_ago": "{{count}}분 전",
"time_1_hour_ago": "1시간 전",
"time_x_hours_ago": "{{count}}시간 전",
"time_1_day_ago": "1일 전",
"time_x_days_ago": "{{count}}일 전",
"time_1_month_ago": "1개월 전",
"time_x_months_ago": "{{count}}개월 전",
"time_1_year_ago": "1년 전",
"time_x_years_ago": "{{count}}년 전",
"open": "열기"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "थ्रेड बंद करा",
"view_spoiler": "स्पॉईलर पहा",
"filter": "फिल्टर",
"edit": "संपादित करा"
"edit": "संपादित करा",
"time_1_minute_ago": "१ मिनिटांपूर्वी",
"time_x_minutes_ago": "{{count}} मिनिटांपूर्वी",
"time_1_hour_ago": "१ तासांपूर्वी",
"time_x_hours_ago": "{{count}} तासांपूर्वी",
"time_1_day_ago": "१ दिवसांपूर्वी",
"time_x_days_ago": "{{count}} दिवसांपूर्वी",
"time_1_month_ago": "१ महिन्यांपूर्वी",
"time_x_months_ago": "{{count}} महिन्यांपूर्वी",
"time_1_year_ago": "१ वर्षांपूर्वी",
"time_x_years_ago": "{{count}} वर्षांपूर्वी",
"open": "उघडा"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "draad sluiten",
"view_spoiler": "bekijk spoiler",
"filter": "filter",
"edit": "bewerken"
"edit": "bewerken",
"time_1_minute_ago": "1 minuut geleden",
"time_x_minutes_ago": "{{count}} minuten geleden",
"time_1_hour_ago": "1 uur geleden",
"time_x_hours_ago": "{{count}} uur geleden",
"time_1_day_ago": "1 dag geleden",
"time_x_days_ago": "{{count}} dagen geleden",
"time_1_month_ago": "1 maand geleden",
"time_x_months_ago": "{{count}} maanden geleden",
"time_1_year_ago": "1 jaar geleden",
"time_x_years_ago": "{{count}} jaar geleden",
"open": "openen"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "lukk tråd",
"view_spoiler": "se spoiler",
"filter": "filter",
"edit": "rediger"
"edit": "rediger",
"time_1_minute_ago": "1 minutt siden",
"time_x_minutes_ago": "{{count}} minutter siden",
"time_1_hour_ago": "1 time siden",
"time_x_hours_ago": "{{count}} timer siden",
"time_1_day_ago": "1 dag siden",
"time_x_days_ago": "{{count}} dager siden",
"time_1_month_ago": "1 måned siden",
"time_x_months_ago": "{{count}} måneder siden",
"time_1_year_ago": "1 år siden",
"time_x_years_ago": "{{count}} år siden",
"open": "åpne"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "zamknij wątek",
"view_spoiler": "pokaż spoiler",
"filter": "filtr",
"edit": "edytuj"
"edit": "edytuj",
"time_1_minute_ago": "1 minutę temu",
"time_x_minutes_ago": "{{count}} minut temu",
"time_1_hour_ago": "1 godzinę temu",
"time_x_hours_ago": "{{count}} godzin temu",
"time_1_day_ago": "1 dzień temu",
"time_x_days_ago": "{{count}} dni temu",
"time_1_month_ago": "1 miesiąc temu",
"time_x_months_ago": "{{count}} miesięcy temu",
"time_1_year_ago": "1 rok temu",
"time_x_years_ago": "{{count}} lat temu",
"open": "otwórz"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "fechar tópico",
"view_spoiler": "ver spoiler",
"filter": "filtro",
"edit": "editar"
"edit": "editar",
"time_1_minute_ago": "há 1 minuto",
"time_x_minutes_ago": "há {{count}} minutos",
"time_1_hour_ago": "há 1 hora",
"time_x_hours_ago": "há {{count}} horas",
"time_1_day_ago": "há 1 dia",
"time_x_days_ago": "há {{count}} dias",
"time_1_month_ago": "há 1 mês",
"time_x_months_ago": "há {{count}} meses",
"time_1_year_ago": "há 1 ano",
"time_x_years_ago": "há {{count}} anos",
"open": "abrir"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "închide firul",
"view_spoiler": "vezi spoilerul",
"filter": "filtru",
"edit": "editați"
"edit": "editați",
"time_1_minute_ago": "Acum 1 minut",
"time_x_minutes_ago": "Acum {{count}} minute",
"time_1_hour_ago": "Acum 1 oră",
"time_x_hours_ago": "Acum {{count}} ore",
"time_1_day_ago": "Acum 1 zi",
"time_x_days_ago": "Acum {{count}} zile",
"time_1_month_ago": "Acum 1 lună",
"time_x_months_ago": "Acum {{count}} luni",
"time_1_year_ago": "Acum 1 an",
"time_x_years_ago": "Acum {{count}} ani",
"open": "deschis"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "закрыть тему",
"view_spoiler": "посмотреть спойлер",
"filter": "фильтр",
"edit": "редактировать"
"edit": "редактировать",
"time_1_minute_ago": "1 минуту назад",
"time_x_minutes_ago": "{{count}} минут назад",
"time_1_hour_ago": "1 час назад",
"time_x_hours_ago": "{{count}} часов назад",
"time_1_day_ago": "1 день назад",
"time_x_days_ago": "{{count}} дней назад",
"time_1_month_ago": "1 месяц назад",
"time_x_months_ago": "{{count}} месяцев назад",
"time_1_year_ago": "1 год назад",
"time_x_years_ago": "{{count}} лет назад",
"open": "открыть"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "mbyll temën",
"view_spoiler": "shikoni spoiler",
"filter": "filtruar",
"edit": "redakto"
"edit": "redakto",
"time_1_minute_ago": "1 minutë më parë",
"time_x_minutes_ago": "{{count}} minuta më parë",
"time_1_hour_ago": "1 orë më parë",
"time_x_hours_ago": "{{count}} orë më parë",
"time_1_day_ago": "1 ditë më parë",
"time_x_days_ago": "{{count}} ditë më parë",
"time_1_month_ago": "1 muaj më parë",
"time_x_months_ago": "{{count}} muaj më parë",
"time_1_year_ago": "1 vit më parë",
"time_x_years_ago": "{{count}} vite më parë",
"open": "hap"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "stäng tråd",
"view_spoiler": "visa spoiler",
"filter": "filter",
"edit": "redigera"
"edit": "redigera",
"time_1_minute_ago": "För 1 minut sedan",
"time_x_minutes_ago": "För {{count}} minuter sedan",
"time_1_hour_ago": "För 1 timme sedan",
"time_x_hours_ago": "För {{count}} timmar sedan",
"time_1_day_ago": "För 1 dag sedan",
"time_x_days_ago": "För {{count}} dagar sedan",
"time_1_month_ago": "För 1 månad sedan",
"time_x_months_ago": "För {{count}} månader sedan",
"time_1_year_ago": "För 1 år sedan",
"time_x_years_ago": "För {{count}} år sedan",
"open": "öppna"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "థ్రెడ్‌ను మూసేయండి",
"view_spoiler": "స్పోయ్లర్ వీక్షించండి",
"filter": "వడపోత",
"edit": "సవరించు"
"edit": "సవరించు",
"time_1_minute_ago": "1 నిమిషం క్రితం",
"time_x_minutes_ago": "{{count}} నిమిషాల క్రితం",
"time_1_hour_ago": "1 గంట క్రితం",
"time_x_hours_ago": "{{count}} గంటల క్రితం",
"time_1_day_ago": "1 రోజు క్రితం",
"time_x_days_ago": "{{count}} రోజుల క్రితం",
"time_1_month_ago": "1 నెల క్రితం",
"time_x_months_ago": "{{count}} నెలల క్రితం",
"time_1_year_ago": "1 సంవత్సరం క్రితం",
"time_x_years_ago": "{{count}} సంవత్సరాల క్రితం",
"open": "తెరవండి"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "ปิดกระทู้",
"view_spoiler": "ดูสปอยล์เลอร์",
"filter": "ตัวกรอง",
"edit": "แก้ไข"
"edit": "แก้ไข",
"time_1_minute_ago": "1 นาทีที่ผ่านมา",
"time_x_minutes_ago": "{{count}} นาทีที่ผ่านมา",
"time_1_hour_ago": "1 ชั่วโมงที่ผ่านมา",
"time_x_hours_ago": "{{count}} ชั่วโมงที่ผ่านมา",
"time_1_day_ago": "1 วันที่ผ่านมา",
"time_x_days_ago": "{{count}} วันที่ผ่านมา",
"time_1_month_ago": "1 เดือนที่ผ่านมา",
"time_x_months_ago": "{{count}} เดือนที่ผ่านมา",
"time_1_year_ago": "1 ปีที่ผ่านมา",
"time_x_years_ago": "{{count}} ปีที่ผ่านมา",
"open": "เปิด"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "konuyu kapat",
"view_spoiler": "spoileri görüntüle",
"filter": "filtre",
"edit": "düzenle"
"edit": "düzenle",
"time_1_minute_ago": "1 dakika önce",
"time_x_minutes_ago": "{{count}} dakika önce",
"time_1_hour_ago": "1 saat önce",
"time_x_hours_ago": "{{count}} saat önce",
"time_1_day_ago": "1 gün önce",
"time_x_days_ago": "{{count}} gün önce",
"time_1_month_ago": "1 ay önce",
"time_x_months_ago": "{{count}} ay önce",
"time_1_year_ago": "1 yıl önce",
"time_x_years_ago": "{{count}} yıl önce",
"open": "aç"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "закрити тему",
"view_spoiler": "переглянути спойлер",
"filter": "фільтр",
"edit": "редагувати"
"edit": "редагувати",
"time_1_minute_ago": "1 хвилину тому",
"time_x_minutes_ago": "{{count}} хвилин тому",
"time_1_hour_ago": "1 годину тому",
"time_x_hours_ago": "{{count}} годин тому",
"time_1_day_ago": "1 день тому",
"time_x_days_ago": "{{count}} днів тому",
"time_1_month_ago": "1 місяць тому",
"time_x_months_ago": "{{count}} місяців тому",
"time_1_year_ago": "1 рік тому",
"time_x_years_ago": "{{count}} років тому",
"open": "відкрити"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "موضوع بند کریں",
"view_spoiler": "اسپوائلر دیکھیں",
"filter": "فلٹر",
"edit": "ترمیم کریں"
"edit": "ترمیم کریں",
"time_1_minute_ago": "1 منٹ پہلے",
"time_x_minutes_ago": "{{count}} منٹ پہلے",
"time_1_hour_ago": "1 گھنٹہ پہلے",
"time_x_hours_ago": "{{count}} گھنٹے پہلے",
"time_1_day_ago": "1 دن پہلے",
"time_x_days_ago": "{{count}} دن پہلے",
"time_1_month_ago": "1 مہینہ پہلے",
"time_x_months_ago": "{{count}} مہینے پہلے",
"time_1_year_ago": "1 سال پہلے",
"time_x_years_ago": "{{count}} سال پہلے",
"open": "کھولیں"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "đóng chủ đề",
"view_spoiler": "xem spoiler",
"filter": "bộ lọc",
"edit": "chỉnh sửa"
"edit": "chỉnh sửa",
"time_1_minute_ago": "1 phút trước",
"time_x_minutes_ago": "{{count}} phút trước",
"time_1_hour_ago": "1 giờ trước",
"time_x_hours_ago": "{{count}} giờ trước",
"time_1_day_ago": "1 ngày trước",
"time_x_days_ago": "{{count}} ngày trước",
"time_1_month_ago": "1 tháng trước",
"time_x_months_ago": "{{count}} tháng trước",
"time_1_year_ago": "1 năm trước",
"time_x_years_ago": "{{count}} năm trước",
"open": "mở"
}
+12 -1
View File
@@ -148,5 +148,16 @@
"close_thread": "关闭主题",
"view_spoiler": "查看剧透",
"filter": "过滤器",
"edit": "编辑"
"edit": "编辑",
"time_1_minute_ago": "1分钟前",
"time_x_minutes_ago": "{{count}}分钟前",
"time_1_hour_ago": "1小时前",
"time_x_hours_ago": "{{count}}小时前",
"time_1_day_ago": "1天前",
"time_x_days_ago": "{{count}}天前",
"time_1_month_ago": "1个月前",
"time_x_months_ago": "{{count}}个月前",
"time_1_year_ago": "1年前",
"time_x_years_ago": "{{count}}年前",
"open": "打开"
}
+6 -4
View File
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom';
import { isHomeView } from './lib/utils/view-utils';
import { isAllView, isHomeView, isSubscriptionsView } from './lib/utils/view-utils';
import useIsMobile from './hooks/use-is-mobile';
import useTheme from './hooks/use-theme';
import styles from './app.module.css';
@@ -21,6 +21,8 @@ const BoardLayout = () => {
const { accountCommentIndex, subplebbitAddress } = useParams();
const location = useLocation();
const isMobile = useIsMobile();
const isInAllView = isAllView(location.pathname);
const isInSubscriptionsView = isSubscriptionsView(location.pathname);
const isValidAccountCommentIndex = !accountCommentIndex || (!isNaN(parseInt(accountCommentIndex)) && parseInt(accountCommentIndex) >= 0);
@@ -36,16 +38,16 @@ const BoardLayout = () => {
<TopBar />
<BoardHeader />
{isMobile
? subplebbitAddress && (
? (subplebbitAddress || isInAllView || isInSubscriptionsView) && (
<>
<PostForm key={key} />
<MobileBoardButtons />
</>
)
: subplebbitAddress && (
: (subplebbitAddress || isInAllView || isInSubscriptionsView) && (
<>
<PostForm key={key} />
<SubplebbitStats />
{!(isInAllView || isInSubscriptionsView) && <SubplebbitStats />}
<DesktopBoardButtons />
</>
)}
@@ -83,8 +83,8 @@
visibility: hidden;
}
.post:hover .postMenu {
visibility: visible;
.postMenuVisible {
visibility: visible !important;
}
.loadingSkeleton {
@@ -95,4 +95,37 @@
.fileDeleted {
image-rendering: pixelated;
}
.postPreview {
background-color: var(--catalog-post-preview-background-color);
border-radius: 3px;
padding: 5px 8px 4px;
z-index: 100000;
word-wrap: break-word;
white-space: pre-line;
max-width: 500px;
color: var(--catalog-post-preview-color);
font-family: arial, helvetica, sans-serif;
font-size: 10pt;
}
.postPreview .postSubject {
font-weight: 700;
color: var(--catalog-post-preview-subject-color);
}
.postPreview .postAuthor {
color: var(--catalog-post-preview-author-color);
font-weight: 700;
}
.postPreview .postLast {
color: var(--catalog-post-preview-last-color);
font-size: 90%;
margin-top: 3px;
}
.postPreview .capcode {
color: var(--catalog-post-preview-author-capcode-color);
}
+137 -37
View File
@@ -1,14 +1,18 @@
import { Link, useLocation } from 'react-router-dom';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { Comment } from '@plebbit/plebbit-react-hooks';
import styles from './catalog-row.module.css';
import { Link, useLocation } from 'react-router-dom';
import { Comment, useComment } from '@plebbit/plebbit-react-hooks';
import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react';
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 PostMenuDesktop from '../post/post-desktop/post-menu-desktop/';
import React, { useState } from 'react';
import styles from './catalog-row.module.css';
import _ from 'lodash';
interface CatalogPostMediaProps {
commentMediaInfo: any;
@@ -69,7 +73,7 @@ export const CatalogPostMedia = ({ commentMediaInfo, isOutOfFeed, linkWidth, lin
return (
<div className={hasError ? '' : styles.mediaWrapper} style={thumbnailDimensions}>
{!isLoaded && !hasError && type !== 'video' && <span className={styles.loadingSkeleton} />}
{!isLoaded && !hasError && type !== 'video' && type !== 'audio' && <span className={styles.loadingSkeleton} />}
{hasError ? <img className={styles.fileDeleted} src='/assets/filedeleted-res.gif' alt='File deleted' /> : thumbnailComponent}
</div>
);
@@ -77,7 +81,8 @@ export const CatalogPostMedia = ({ commentMediaInfo, isOutOfFeed, linkWidth, lin
const CatalogPost = ({ post }: { post: Comment }) => {
const { t } = useTranslation();
const { cid, content, isDescription, isRules, link, linkHeight, linkWidth, locked, pinned, replyCount, subplebbitAddress, title } = post || {};
const { author, cid, content, isDescription, isRules, lastChildCid, link, linkHeight, linkWidth, locked, pinned, replyCount, subplebbitAddress, timestamp, title } =
post || {};
const commentMediaInfo = getCommentMediaInfo(post);
const hasThumbnail = getHasThumbnail(commentMediaInfo, link);
@@ -95,38 +100,133 @@ const CatalogPost = ({ post }: { post: Comment }) => {
</div>
);
return (
<div className={styles.post}>
{hasThumbnail ? (
<Link to={postLink}>
<div className={styles.mediaPaddingWrapper}>
{threadIcons}
<CatalogPostMedia commentMediaInfo={commentMediaInfo} isOutOfFeed={isDescription || isRules} linkWidth={linkWidth} linkHeight={linkHeight} />
</div>
</Link>
) : (
threadIcons
)}
<div className={styles.meta}>
R: <b>{replyCount || '0'}</b>
{linkCount > 0 && (
<span>
{' '}
/ L: <b>{linkCount}</b>
</span>
)}
<span className={styles.postMenu}>
<PostMenuDesktop post={post} />
</span>
</div>
<Link to={postLink}>
<div className={styles.teaser}>
<b>{title && `${title}${content ? ': ' : ''}`}</b>
{content}
</div>
</Link>
const [hoveredCid, setHoveredCid] = useState<string | null>(null);
const [showPortal, setShowPortal] = useState<boolean>(false);
const placementRef = useRef<Placement>('right-start');
const availableWidthRef = useRef<number>(0);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const { refs, floatingStyles, update } = useFloating({
open: showPortal,
placement: placementRef.current,
middleware: [
shift({ padding: 10 }),
offset({ mainAxis: 5 }),
size({
apply({ availableWidth, elements }) {
availableWidthRef.current = availableWidth;
if (availableWidth >= 250) {
elements.floating.style.maxWidth = `${availableWidth - 12}px`;
} else if (placementRef.current === 'right-start') {
placementRef.current = 'left-start';
}
},
}),
],
whileElementsMounted: autoUpdate,
});
useEffect(() => {
const handleResize = () => {
const availableWidth = availableWidthRef.current;
if (availableWidth >= 250) {
placementRef.current = 'right-start';
} else {
placementRef.current = 'left-start';
}
update();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [update]);
const lastReply = useComment({ commentCid: lastChildCid });
const { isCommentAuthorMod: isCatalogPostAuthorMod, commentAuthorRole: catalogPostAuthorRole } = useEditCommentPrivileges({
commentAuthorAddress: author?.address,
subplebbitAddress,
});
const { isCommentAuthorMod: isLastReplyAuthorMod, commentAuthorRole: lastReplyAuthorRole } = useEditCommentPrivileges({
commentAuthorAddress: lastReply?.author?.address,
subplebbitAddress,
});
const postContent = (
<div className={styles.teaser}>
<b>{title && `${title}${content ? ': ' : ''}`}</b>
{content}
</div>
);
return (
<>
<div className={styles.post}>
<div onMouseOver={() => setHoveredCid(cid)} onMouseLeave={() => setHoveredCid(null)}>
{hasThumbnail ? (
<Link to={postLink}>
<div
className={styles.mediaPaddingWrapper}
ref={refs.setReference}
onMouseOver={() => (timeoutRef.current = setTimeout(() => setShowPortal(true), 250))}
onMouseLeave={() => {
setShowPortal(false);
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
}}
>
{threadIcons}
<CatalogPostMedia commentMediaInfo={commentMediaInfo} isOutOfFeed={isDescription || isRules} linkWidth={linkWidth} linkHeight={linkHeight} />
</div>
</Link>
) : (
threadIcons
)}
<div className={styles.meta}>
R: <b>{replyCount || '0'}</b>
{linkCount > 0 && (
<span>
{' '}
/ L: <b>{linkCount}</b>
</span>
)}
<span className={`${styles.postMenu} ${hoveredCid && styles.postMenuVisible}`}>
<PostMenuDesktop post={post} />
</span>
</div>
{hasThumbnail ? postContent : <Link to={postLink}>{postContent}</Link>}
</div>
</div>
{hoveredCid === cid &&
showPortal &&
createPortal(
<div className={styles.postPreview} ref={refs.setFloating} style={floatingStyles}>
<span className={styles.postSubject}>{title}</span>
{' by '}
<span className={`${styles.postAuthor} ${(isCatalogPostAuthorMod || isRules || isDescription) && styles.capcode}`}>
{author?.displayName || _.capitalize(t('anonymous'))}
{isCatalogPostAuthorMod && <span className='capitalize'>{` ## Board ${catalogPostAuthorRole}`}</span>}
</span>
<span className={styles.postAgo}> {getFormattedTimeAgo(timestamp)}</span>
{replyCount > 0 && (
<div className={styles.postLast}>
Last reply by{' '}
<span className={`${styles.postAuthor} ${isLastReplyAuthorMod && styles.capcode}`}>
{lastReply?.author?.displayName || _.capitalize(t('anonymous'))}
{isLastReplyAuthorMod && ` ## Board ${lastReplyAuthorRole}`}
</span>
<span className={styles.postAgo}> {getFormattedTimeAgo(lastReply?.timestamp)}</span>
</div>
)}
</div>,
document.body,
)}
</>
);
};
interface CatalogRowProps {
@@ -11,13 +11,16 @@
overflow: hidden;
}
.subplebbitAvatar {
.floatingEmbed, .subplebbitAvatar {
max-width: 250px;
max-height: 250px;
margin: 3px 20px 5px 0;
display: inline-block;
}
.subplebbitAvatar {
margin: 3px 20px 5px 0;
}
.spoiler {
display: inline-block;
margin: 3px 20px 5px 20px;
@@ -131,4 +134,11 @@
.fileDeleted {
image-rendering: pixelated;
}
@media (min-width: 640px) {
.thumbnail,
.content {
line-height: 0; /* Ensure no extra space due to line-height */
}
}
@@ -11,6 +11,7 @@ import Embed, { canEmbed } from '../embed';
interface MediaProps {
commentMediaInfo?: CommentMediaInfo;
post?: Comment;
isFloatingEmbed?: boolean;
isReply?: boolean;
linkHeight?: number;
linkWidth?: number;
@@ -18,11 +19,11 @@ interface MediaProps {
setShowThumbnail: (showThumbnail: boolean) => void;
}
const Thumbnail = ({ commentMediaInfo, post, setShowThumbnail }: MediaProps) => {
const Thumbnail = ({ commentMediaInfo, isFloatingEmbed, post, setShowThumbnail }: MediaProps) => {
const { t } = useTranslation();
const { deleted, linkHeight, linkWidth, parentCid, removed, spoiler } = post || {};
const { isDescription, isRules } = post || {}; // custom properties, not from api
const isOutOfFeed = isDescription || isRules; // virtuoso wrapper unneeded
const isOutOfFeed = isDescription || isRules || isFloatingEmbed; // virtuoso wrapper unneeded
const isReply = parentCid;
const isDeleted = deleted || removed;
@@ -84,7 +85,7 @@ const Thumbnail = ({ commentMediaInfo, post, setShowThumbnail }: MediaProps) =>
<span className={styles.spoilerText}>[{t('view_spoiler')}]</span>
</span>
) : isOutOfFeed ? (
<span className={styles.subplebbitAvatar}>{thumbnailComponent}</span>
<span className={`${isFloatingEmbed ? styles.floatingEmbed : styles.subplebbitAvatar}`}>{thumbnailComponent}</span>
) : isMobile || isReply ? (
<span className={`${styles.thumbnailSmall} ${thumbnailSmallPadding}`} style={thumbnailDimensions}>
{thumbnailComponent}
@@ -135,7 +136,7 @@ const Media = ({ commentMediaInfo, isReply, setShowThumbnail }: MediaProps) => {
)}
{isMobile && (type === 'iframe' || type === 'video' || type === 'audio') && (
<div className={styles.closeButton}>
<span className='button' onClick={() => setShowThumbnail(true)}>
<span className='button' onClick={() => setShowThumbnail(false)}>
{t('close')}
</span>
</div>
@@ -144,7 +145,7 @@ const Media = ({ commentMediaInfo, isReply, setShowThumbnail }: MediaProps) => {
);
};
const CommentMedia = ({ commentMediaInfo, post, showThumbnail, setShowThumbnail }: MediaProps) => {
const CommentMedia = ({ commentMediaInfo, isFloatingEmbed, post, showThumbnail, setShowThumbnail }: MediaProps) => {
const { t } = useTranslation();
const isMobile = useIsMobile();
const { type, url } = commentMediaInfo || {};
@@ -152,7 +153,7 @@ const CommentMedia = ({ commentMediaInfo, post, showThumbnail, setShowThumbnail
return (
<span className={styles.content}>
<span className={`${showThumbnail ? styles.show : styles.hide} ${styles.thumbnail}`}>
{url && <Thumbnail commentMediaInfo={commentMediaInfo} post={post} setShowThumbnail={setShowThumbnail} />}
{url && <Thumbnail commentMediaInfo={commentMediaInfo} isFloatingEmbed={isFloatingEmbed} post={post} setShowThumbnail={setShowThumbnail} />}
{isMobile && type && <div className={styles.fileInfo}>{getDisplayMediaInfoType(type, t)}</div>}
</span>
{!showThumbnail && <Media commentMediaInfo={commentMediaInfo} isReply={post?.parentCid} setShowThumbnail={setShowThumbnail} />}
@@ -38,4 +38,10 @@
.spoiler:hover {
color: white;
}
.floatingEmbed {
background-color: #d6daf0;
border: 1px solid #b7c5d9;
padding: 2px;
}
+95 -28
View File
@@ -1,18 +1,100 @@
import React, { useMemo, useState } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import supersub from 'remark-supersub';
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
import styles from './markdown.module.css';
import { useTranslation } from 'react-i18next';
import { useDismiss, useFloating, useFocus, useHover, useInteractions, offset, shift, size, autoUpdate, Placement, FloatingPortal } from '@floating-ui/react';
import { getLinkMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils';
import useIsMobile from '../../hooks/use-is-mobile';
import CommentMedia from '../comment-media';
import styles from './markdown.module.css';
interface MarkdownProps {
content: string;
spoiler?: boolean;
interface ContentLinkEmbedProps {
children: any;
href: string;
linkMediaInfo: any;
}
const ContentLinkEmbed = ({ children, href, linkMediaInfo }: ContentLinkEmbedProps) => {
const { t } = useTranslation();
const isMobile = useIsMobile();
const [isOpen, setIsOpen] = useState(false);
const [showMedia, setShowMedia] = useState(false);
const placementRef = useRef<Placement>('right');
const availableWidthRef = useRef<number>(0);
const { refs, floatingStyles, update, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
placement: placementRef.current,
middleware: [
shift({ padding: 10 }),
offset({ mainAxis: 5 }),
size({
apply({ availableWidth, elements }) {
availableWidthRef.current = availableWidth;
if (availableWidth >= 250) {
elements.floating.style.maxWidth = `${availableWidth - 12}px`;
} else if (placementRef.current === 'right') {
placementRef.current = 'left';
}
},
}),
],
whileElementsMounted: autoUpdate,
});
const hover = useHover(context, { move: false });
const focus = useFocus(context);
const dismiss = useDismiss(context);
const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, dismiss]);
useEffect(() => {
const handleResize = () => {
const availableWidth = availableWidthRef.current;
if (availableWidth >= 250) {
placementRef.current = 'right';
} else {
placementRef.current = 'left';
}
update();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [update]);
return (
<>
<a href={href} target='_blank' rel='noopener noreferrer'>
{children}
</a>{' '}
[
<span className={styles.embedButton} onClick={() => setShowMedia(!showMedia)} ref={refs.setReference} {...getReferenceProps()}>
{showMedia ? t('remove') : isMobile ? t('open') : t('embed')}
</span>
]
{showMedia && (
<>
<br />
<CommentMedia isReply={false} setShowThumbnail={setShowMedia} commentMediaInfo={linkMediaInfo} showThumbnail={false} />
</>
)}
<FloatingPortal>
{isOpen && !isMobile && (
<div className={styles.floatingEmbed} ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>
<CommentMedia isReply={false} isFloatingEmbed={true} setShowThumbnail={setShowMedia} commentMediaInfo={linkMediaInfo} showThumbnail={true} />
</div>
)}
</FloatingPortal>
</>
);
};
const MAX_LENGTH_FOR_GFM = 10000; // remarkGfm lags with large content
const blockquoteToGreentext = () => (tree: any) => {
@@ -38,6 +120,11 @@ const blockquoteToGreentext = () => (tree: any) => {
});
};
interface MarkdownProps {
content: string;
spoiler?: boolean;
}
const Markdown = ({ content, spoiler }: MarkdownProps) => {
const remarkPlugins: any[] = [[supersub]];
@@ -59,9 +146,6 @@ const Markdown = ({ content, spoiler }: MarkdownProps) => {
remarkPlugins.push([blockquoteToGreentext]);
const { t } = useTranslation();
const [showMedia, setShowMedia] = useState(false);
return (
<span className={styles.markdown}>
<ReactMarkdown
@@ -69,7 +153,7 @@ const Markdown = ({ content, spoiler }: MarkdownProps) => {
remarkPlugins={remarkPlugins}
rehypePlugins={[[rehypeSanitize, customSchema]]}
components={{
p: ({ children }) => <p className=''>{spoiler ? <span className={styles.spoiler}>{children}</span> : children}</p>,
p: ({ children }) => <p>{spoiler ? <span className={styles.spoiler}>{children}</span> : children}</p>,
img: ({ src }) => <span>{src}</span>,
video: ({ src }) => <span>{src}</span>,
iframe: ({ src }) => <span>{src}</span>,
@@ -83,24 +167,7 @@ const Markdown = ({ content, spoiler }: MarkdownProps) => {
if (href) {
const linkMediaInfo = getLinkMediaInfo(href);
if (getHasThumbnail(linkMediaInfo, href)) {
return (
<>
<a href={href} target='_blank' rel='noopener noreferrer'>
{children}
</a>{' '}
[
<span className={styles.embedButton} onClick={() => setShowMedia(!showMedia)}>
{showMedia ? t('remove') : t('embed')}
</span>
]
{showMedia && (
<>
<br />
<CommentMedia isReply={false} setShowThumbnail={setShowMedia} commentMediaInfo={linkMediaInfo} showThumbnail={false} />
</>
)}
</>
);
return <ContentLinkEmbed children={children} href={href} linkMediaInfo={linkMediaInfo} />;
} else {
return (
<a href={href} target='_blank' rel='noopener noreferrer'>
@@ -5,11 +5,10 @@ import { Comment, useAccount, useBlock, useComment } from '@plebbit/plebbit-reac
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import styles from '../post.module.css';
import { getCommentMediaInfo, getDisplayMediaInfoType, getHasThumbnail } from '../../../lib/utils/media-utils';
import { getFormattedDate } from '../../../lib/utils/time-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-edit-comment-privileges';
import useEditCommentPrivileges from '../../../hooks/use-author-privileges';
import useReplies from '../../../hooks/use-replies';
import useStateString from '../../../hooks/use-state-string';
import CommentMedia from '../../comment-media';
@@ -20,6 +19,7 @@ import PostMenuDesktop from './post-menu-desktop/';
import EditMenu from '../edit-menu/edit-menu';
import ReplyQuotePreview from '../reply-quote-preview';
import { PostProps } from '../post';
import Timestamp from '../timestamp';
import _ from 'lodash';
const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
@@ -58,7 +58,7 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => {
{!(isDescription || isRules) && <span className={styles.userAddress}>(u/{shortAddress || accountShortAddress}) </span>}
</span>
<span className={styles.dateTime}>
{getFormattedDate(timestamp)}
<Timestamp timestamp={timestamp} />
{isDescription || isRules ? '' : ' '}
</span>
<span className={styles.postNum}>
@@ -185,7 +185,7 @@ const PostMessage = ({ post }: PostProps) => {
{removed ? (
<span className={styles.removedContent}>({t('this_post_was_removed')})</span>
) : deleted ? (
<span className={styles.removedContent}>{t('user_deleted_this_post')}</span>
<span className={styles.deletedContent}>{t('user_deleted_this_post')}</span>
) : (
<Markdown content={displayContent} spoiler={spoiler} />
)}
@@ -232,7 +232,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
// scroll to reply if pathname is reply permalink (backlink)
const replyRefs = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => {
const replyIndex = replies.findIndex((reply) => location.pathname.startsWith(`/p/${subplebbitAddress}/c/${reply?.cid}`));
const replyIndex = replies.findIndex((reply) => location.pathname === `/p/${subplebbitAddress}/c/${reply?.cid}`);
if (replyIndex !== -1 && replyRefs.current[replyIndex]) {
replyRefs.current[replyIndex]?.scrollIntoView();
}
@@ -240,7 +240,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
return (
<div className={styles.postDesktop}>
{showAllReplies ? (
{showReplies ? (
<div className={styles.hrWrapper}>
<hr />
</div>
@@ -248,7 +248,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
<div className={styles.replyQuotePreviewSpacer} />
)}
<div className={isHidden ? styles.postDesktopBlocked : ''}>
{!isInPostPageView && !isDescription && !isRules && (
{!isInPostPageView && !isDescription && !isRules && showReplies && (
<span className={styles.hideButtonWrapper}>
<span className={`${styles.hideButton} ${blocked ? styles.unhideThread : styles.hideThread}`} onClick={blocked ? unblock : block} />
</span>
@@ -287,7 +287,7 @@ const PostDesktop = ({ openReplyModal, post, roles, showAllReplies, showReplies
<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}`}>
<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} />}
@@ -10,6 +10,7 @@
font-weight: 700;
font-size: 16px;
height: 100%;
cursor: pointer;
}
.postMenu {
@@ -6,7 +6,7 @@ import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDis
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-edit-comment-privileges';
import useEditCommentPrivileges from '../../../../hooks/use-author-privileges';
import EditMenu from '../../edit-menu/edit-menu';
interface PostMenuMobileProps {
+10 -11
View File
@@ -5,7 +5,6 @@ import { Comment, useAccount, useComment } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import styles from '../post.module.css';
import { getCommentMediaInfo, getHasThumbnail } from '../../../lib/utils/media-utils';
import { getFormattedDate } from '../../../lib/utils/time-utils';
import { isAllView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../../lib/utils/view-utils';
import useCountLinksInReplies from '../../../hooks/use-count-links-in-replies';
import useReplies from '../../../hooks/use-replies';
@@ -16,6 +15,7 @@ import Markdown from '../../markdown';
import ReplyQuotePreview from '../reply-quote-preview';
import PostMenuMobile from './post-menu-mobile';
import { PostProps } from '../post';
import Timestamp from '../timestamp';
import _ from 'lodash';
const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => {
@@ -78,7 +78,7 @@ const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => {
<Link to={`/p/${subplebbitAddress}`}>p/{subplebbitAddress && Plebbit.getShortAddress(subplebbitAddress)}</Link>
</div>
)}
{getFormattedDate(timestamp)}{' '}
<Timestamp timestamp={timestamp} />{' '}
{!(isDescription || isRules) && (
<span className={styles.postNumLink}>
<Link to={`/p/${subplebbitAddress}/c/${cid}`} className={styles.linkToPost} title={t('link_to_post')} onClick={(e) => !cid && e.preventDefault()}>
@@ -117,7 +117,7 @@ const ReplyBacklinks = ({ post }: PostProps) => {
const PostMessageMobile = ({ post }: PostProps) => {
const { t } = useTranslation();
const { cid, content, deleted, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {};
const { cid, content, deleted, parentCid, postCid, reason, removed, spoiler, state, subplebbitAddress } = post || {};
const params = useParams();
const location = useLocation();
@@ -145,7 +145,7 @@ const PostMessageMobile = ({ post }: PostProps) => {
) : deleted ? (
<span className={styles.removedContent}>{t('user_deleted_this_post')}</span>
) : (
<Markdown content={displayContent} />
<Markdown content={displayContent} spoiler={spoiler} />
)}
{(removed || deleted) && reason && (
<span>
@@ -183,11 +183,10 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
const linksCount = useCountLinksInReplies(post);
const replies = useReplies(post);
// scroll to reply if pathname is reply permalink (backlink)
const replyRefs = useRef<(HTMLDivElement | null)[]>([]);
useEffect(() => {
const replyIndex = replies.findIndex((reply) => location.pathname.startsWith(`/p/${subplebbitAddress}/c/${reply?.cid}`));
const replyIndex = replies.findIndex((reply) => location.pathname === `/p/${subplebbitAddress}/c/${reply?.cid}`);
if (replyIndex !== -1 && replyRefs.current[replyIndex]) {
replyRefs.current[replyIndex]?.scrollIntoView();
}
@@ -195,18 +194,18 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
return (
<div className={styles.postMobile}>
{showAllReplies && (
{showReplies && (
<div className={styles.hrWrapper}>
<hr />
</div>
)}
<div className={showAllReplies ? styles.thread : styles.quotePreview}>
<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 && (
{!isInPostView && !isInPendingPostView && showReplies && (
<div className={styles.postLink}>
<span className={styles.info}>
{replyCount > 0 && `${replyCount} Replies`}
@@ -233,7 +232,7 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies =
<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}`}>
<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} />
+5 -2
View File
@@ -392,12 +392,15 @@
cursor: pointer;
}
.removedContent {
text-transform: uppercase;
.removedContent, .deletedContent {
font-weight: 700;
color: red;
}
.removedContent {
text-transform: uppercase;
}
.backlink, .backlinkHash {
font-size: 0.8em;
}
@@ -1,8 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Link } from 'react-router-dom';
import { Comment } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import { Comment, useAccount } from '@plebbit/plebbit-react-hooks';
import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react';
import useIsMobile from '../../../hooks/use-is-mobile';
import styles from '../post.module.css';
@@ -15,8 +14,32 @@ interface ReplyQuotePreviewProps {
quotelinkReply?: Comment;
}
const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => {
const targetElement = document.getElementById(cid);
if (!targetElement) return;
const isInViewport = (element: HTMLElement) => {
const bounding = element.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
if (isInViewport(targetElement)) {
targetElement.classList.add('highlight');
} else {
targetElement.classList.remove('highlight');
onElementOutOfView();
}
};
const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply }: ReplyQuotePreviewProps) => {
const [hoveredCid, setHoveredCid] = useState<string | null>(null);
const [outOfViewCid, setOutOfViewCid] = useState<string | null>(null);
const placementRef = useRef<Placement>('right');
const availableWidthRef = useRef<number>(0);
@@ -56,18 +79,37 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
};
}, [update]);
const handleMouseOver = (cid: string | undefined) => {
if (!cid) return;
handleQuoteHover(cid, () => setOutOfViewCid(cid));
setHoveredCid(cid);
};
const handleMouseLeave = (cid: string | null) => {
if (cid) {
const targetElement = document.getElementById(cid);
if (targetElement) {
targetElement.classList.remove('highlight');
}
}
setHoveredCid(null);
setOutOfViewCid(null);
};
const replyBacklink = (
<>
<Link
className={styles.backlink}
to={`/p/${backlinkReply?.subplebbitAddress}/c/${backlinkReply?.cid}`}
ref={refs.setReference}
onMouseOver={() => setHoveredCid(backlinkReply?.cid)}
onMouseLeave={() => setHoveredCid(null)}
onMouseOver={() => handleMouseOver(backlinkReply?.cid)}
onMouseLeave={() => handleMouseLeave(backlinkReply?.cid)}
>
c/{backlinkReply?.shortCid}
</Link>
{hoveredCid === backlinkReply?.cid &&
outOfViewCid === backlinkReply?.cid &&
createPortal(
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
<Post post={backlinkReply} showReplies={false} />
@@ -77,19 +119,23 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
</>
);
const account = useAccount();
const replyQuotelink = (
<>
<Link
to={`/p/${quotelinkReply?.subplebbitAddress}/c/${quotelinkReply?.cid}`}
ref={refs.setReference}
className={styles.quoteLink}
onMouseOver={() => setHoveredCid(quotelinkReply?.cid)}
onMouseLeave={() => setHoveredCid(null)}
onMouseOver={() => handleMouseOver(quotelinkReply?.cid)}
onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)}
>
{`c/${quotelinkReply?.cid && Plebbit.getShortCid(quotelinkReply.cid)}`}
{`c/${quotelinkReply?.shortCid}`}
{quotelinkReply?.author?.address === account?.author?.address && ' (You)'}
</Link>
<br />
{hoveredCid === quotelinkReply?.cid &&
outOfViewCid === quotelinkReply?.cid &&
createPortal(
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
<Post post={quotelinkReply} showReplies={false} />
@@ -104,6 +150,7 @@ const DesktopQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, i
const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, isQuotelinkReply }: ReplyQuotePreviewProps) => {
const [hoveredCid, setHoveredCid] = useState<string | null>(null);
const [outOfViewCid, setOutOfViewCid] = useState<string | null>(null);
const { refs, floatingStyles, update } = useFloating({
placement: 'bottom',
@@ -118,15 +165,39 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is
};
}, [update]);
const handleMouseOver = (cid: string | undefined) => {
if (!cid) return;
handleQuoteHover(cid, () => setOutOfViewCid(cid));
setHoveredCid(cid);
};
const handleMouseLeave = (cid: string | null) => {
if (cid) {
const targetElement = document.getElementById(cid);
if (targetElement) {
targetElement.classList.remove('highlight');
}
}
setHoveredCid(null);
setOutOfViewCid(null);
};
const replyBacklink = (
<>
<span className={styles.backlink} ref={refs.setReference} onMouseOver={() => setHoveredCid(backlinkReply?.cid)} onMouseLeave={() => setHoveredCid(null)}>
<span
className={styles.backlink}
ref={refs.setReference}
onMouseOver={() => handleMouseOver(backlinkReply?.cid)}
onMouseLeave={() => handleMouseLeave(backlinkReply?.cid)}
>
c/{backlinkReply?.shortCid}{' '}
</span>
<Link to={`/p/${backlinkReply?.subplebbitAddress}/c/${backlinkReply?.cid}`} className={styles.backlinkHash}>
#
</Link>
{hoveredCid === backlinkReply?.cid &&
outOfViewCid === backlinkReply?.cid &&
createPortal(
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
<Post post={backlinkReply} showReplies={false} />
@@ -136,16 +207,26 @@ const MobileQuotePreview = ({ backlinkReply, quotelinkReply, isBacklinkReply, is
</>
);
const account = useAccount();
const replyQuotelink = (
<>
<span ref={refs.setReference} className={styles.quoteLink} onMouseOver={() => setHoveredCid(quotelinkReply?.cid)} onMouseLeave={() => setHoveredCid(null)}>
c/{quotelinkReply?.shortCid}{' '}
<span
ref={refs.setReference}
className={styles.quoteLink}
onMouseOver={() => handleMouseOver(quotelinkReply?.cid)}
onMouseLeave={() => handleMouseLeave(quotelinkReply?.cid)}
>
c/{quotelinkReply?.shortCid}
{quotelinkReply?.author?.address === account?.author?.address && ' (You)'}
</span>
<Link className={styles.quoteLink} to={`/p/${quotelinkReply?.subplebbitAddress}/c/${quotelinkReply?.cid}`}>
{' '}
#
</Link>
<br />
{hoveredCid === quotelinkReply?.cid &&
outOfViewCid === quotelinkReply?.cid &&
createPortal(
<div className={styles.replyQuotePreview} ref={refs.setFloating} style={floatingStyles}>
<Post post={quotelinkReply} showReplies={false} />
+1
View File
@@ -0,0 +1 @@
export { default } from './timestamp';
@@ -0,0 +1,45 @@
import { useState } from 'react';
import { getFormattedDate, getFormattedTimeAgo } from '../../../lib/utils/time-utils';
import { useFloating, autoUpdate, offset, flip, shift, useHover, useFocus, useDismiss, useRole, useInteractions, FloatingPortal } from '@floating-ui/react';
const Timestamp = ({ timestamp }: { timestamp: number }) => {
const [isOpen, setIsOpen] = useState(false);
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
placement: 'top',
whileElementsMounted: autoUpdate,
middleware: [
offset(5),
flip({
fallbackAxisSideDirection: 'start',
}),
shift(),
],
});
const hover = useHover(context, { move: false, delay: { open: 250, close: 0 } });
const focus = useFocus(context);
const dismiss = useDismiss(context);
const role = useRole(context, { role: 'tooltip' });
const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, dismiss, role]);
return (
<>
<span ref={refs.setReference} {...getReferenceProps()}>
{getFormattedDate(timestamp)}
</span>
<FloatingPortal>
{isOpen && (
<div className='tooltip' ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>
{getFormattedTimeAgo(timestamp)}
</div>
)}
</FloatingPortal>
</>
);
};
export default Timestamp;
@@ -1,11 +1,11 @@
import { useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks';
interface EditCommentPrivileges {
interface AuthorPrivilegesProps {
commentAuthorAddress: string;
subplebbitAddress: string;
}
const useEditCommentPrivileges = ({ commentAuthorAddress, subplebbitAddress }: EditCommentPrivileges) => {
const useAuthorPrivileges = ({ commentAuthorAddress, subplebbitAddress }: AuthorPrivilegesProps) => {
const accountAuthorAddress = useAccount()?.author?.address;
const { roles } = useSubplebbit({ subplebbitAddress }) || {};
@@ -15,7 +15,7 @@ const useEditCommentPrivileges = ({ commentAuthorAddress, subplebbitAddress }: E
const isAccountMod = accountAuthorRole === 'admin' || accountAuthorRole === 'owner' || accountAuthorRole === 'moderator';
const isAccountCommentAuthor = accountAuthorAddress === commentAuthorAddress;
return { isCommentAuthorMod, isAccountMod, isAccountCommentAuthor };
return { isCommentAuthorMod, isAccountMod, isAccountCommentAuthor, commentAuthorRole, accountAuthorRole };
};
export default useEditCommentPrivileges;
export default useAuthorPrivileges;
+2 -2
View File
@@ -10,9 +10,9 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
const allPosts: Comment[] = [];
let postsPerSub = 1;
if (subplebbits.length == 2) {
if (subplebbits.length === 2) {
postsPerSub = 4;
} else if (subplebbits.length == 3) {
} else if (subplebbits.length === 3) {
postsPerSub = 3;
} else if (subplebbits.length >= 4 && subplebbits.length < 8) {
postsPerSub = 2;
+2 -2
View File
@@ -2,7 +2,7 @@ import { useMemo, useCallback } from 'react';
import { Comment, useAccountComments } from '@plebbit/plebbit-react-hooks';
import { flattenCommentsPages } from '@plebbit/plebbit-react-hooks/dist/lib/utils';
const useRepliesAndAccountReplies = (comment: Comment) => {
const useReplies = (comment: Comment) => {
// flatten all replies including nested ones from the original comment
const flattenedReplies = useMemo(() => flattenCommentsPages(comment.replies), [comment.replies]);
@@ -45,4 +45,4 @@ const useRepliesAndAccountReplies = (comment: Comment) => {
return repliesAndNotYetPublishedReplies;
};
export default useRepliesAndAccountReplies;
export default useReplies;
+36
View File
@@ -26,6 +26,42 @@ hr {
color: var(--post-greentext-color);
}
.highlight {
background: var(--reply-highlight-background-color) !important;
}
.capitalize {
text-transform: capitalize;
}
.tooltip {
position: absolute;
background-color: #181f24;
font-size: 11px;
line-height: 13px;
padding: 3px 6px;
z-index: 100000;
word-wrap: break-word;
white-space: pre-line;
max-width: 400px;
color: #fff;
text-align: center;
}
.tooltip::before {
content: "";
display: block;
width: 0;
height: 0;
position: absolute;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #181f24;
margin-left: -4px;
bottom: -4px;
left: 50%;
}
@media (max-width: 640px) {
.button {
font-size: var(--button-font-size-mobile);
+35
View File
@@ -33,3 +33,38 @@ export const getFormattedDate = (commentTimestamp: number) => {
}
return string;
};
export const getFormattedTimeAgo = (unixTimestamp: number): string => {
const currentTime = Date.now() / 1000;
const timeDifference = currentTime - unixTimestamp;
const t = i18next.t;
if (timeDifference < 120) {
return t('time_1_minute_ago');
}
if (timeDifference < 3600) {
return t('time_x_minutes_ago', { count: Math.floor(timeDifference / 60) });
}
if (timeDifference < 7200) {
return t('time_1_hour_ago');
}
if (timeDifference < 86400) {
return t('time_x_hours_ago', { count: Math.floor(timeDifference / 3600) });
}
if (timeDifference < 172800) {
return t('time_1_day_ago');
}
if (timeDifference < 2592000) {
return t('time_x_days_ago', { count: Math.floor(timeDifference / 86400) });
}
if (timeDifference < 5184000) {
return t('time_1_month_ago');
}
if (timeDifference < 31104000) {
return t('time_x_months_ago', { count: Math.floor(timeDifference / 2592000) });
}
if (timeDifference < 62208000) {
return t('time_1_year_ago');
}
return t('time_x_years_ago', { count: Math.floor(timeDifference / 31104000) });
};
+3 -2
View File
@@ -45,12 +45,13 @@ export const isRulesView = (pathname: string, params: ParamsType): boolean => {
};
export const isSettingsView = (pathname: string, params: ParamsType): boolean => {
const { subplebbitAddress, commentCid } = params;
const { accountCommentIndex, commentCid, subplebbitAddress } = params;
const decodedPathname = decodeURIComponent(pathname);
return (
decodedPathname === `/p/${subplebbitAddress}/c/${commentCid}/settings` ||
decodedPathname === `/p/${subplebbitAddress}/description/settings` ||
decodedPathname === `/p/${subplebbitAddress}/rules/settings`
decodedPathname === `/p/${subplebbitAddress}/rules/settings` ||
decodedPathname === `/profile/${accountCommentIndex}/settings`
);
};
+33 -1
View File
@@ -25,6 +25,12 @@
--catalog-post-menu-desktop-btn-hover-color: red;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-subject-color: #cc1105;
--catalog-post-preview-author-color: #00a550;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #f0e0d6;
@@ -226,6 +232,11 @@
--catalog-post-menu-desktop-btn-hover-color: #d00;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-author-color: #00a550;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #d6daf0;
@@ -421,6 +432,12 @@
--catalog-post-menu-desktop-btn-hover-color: red;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-subject-color: #cc1105;
--catalog-post-preview-author-color: #00a550;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #f0e0d6;
@@ -590,6 +607,11 @@
--catalog-post-menu-desktop-btn-hover-color: red;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-author-color: #00a550;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #d6daf0;
@@ -766,12 +788,18 @@
--catalog-post-menu-desktop-btn-hover-color: #5f89ac;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-subject-color: #b294bb;
--catalog-post-preview-author-color: #00a550;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #282a2e;
--challenge-modal-border: 1px solid #111;
--challenge-modal-title-background-color: #282a2e;
--challenge-modal-title-text-color: #c5c8c6;
--challenge-modal-title-text-color: #b0cab9;
--challenge-modal-title-border: unset;
--challenge-modal-title-font-size: 10pt;
--challenge-modal-title-font-weight: 700;
@@ -969,6 +997,10 @@
--catalog-post-menu-desktop-btn-hover-color: #f30;
--catalog-post-menu-desktop-btn-opacity: 0.5;
--catalog-post-menu-desktop-btn-hover-opacity: 1;
--catalog-post-preview-background-color: #181f24;
--catalog-post-preview-color: #dedede;
--catalog-post-preview-last-color: #bbbfbd;
--catalog-post-preview-author-capcode-color: purple;
/* challenge modal */
--challenge-modal-background-color: #ddd;
+1 -1
View File
@@ -197,7 +197,7 @@ const BoardsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebb
return (
<div className={`${styles.box} ${styles.boardsBox}`}>
<div className={styles.boxBar}>
<h2 className={styles.capitalize}>{t('boards')}</h2>
<h2 className='capitalize'>{t('boards')}</h2>
<BoxModal isBoardsBoxModal={true} />
</div>
<div className={styles.boardsBoxContent}>
-4
View File
@@ -150,10 +150,6 @@
content: '✔ ';
}
.capitalize {
text-transform: capitalize;
}
.list a {
color: var(--homepage-box-link-text-color);
text-decoration: var(--homepage-box-link-text-decoration);
+2 -2
View File
@@ -88,7 +88,7 @@ const Stats = ({ multisub, subplebbitAddresses }: { multisub: any; subplebbitAdd
return (
<div className={styles.box}>
<div className={`${styles.boxBar} ${styles.color2ColorBar}`}>
<h2 className={styles.capitalize}>{t('stats')}</h2>
<h2 className='capitalize'>{t('stats')}</h2>
</div>
<div className={`${styles.boxContent} ${enoughStats ? styles.stats : ''}`}>
{enoughStats ? (
@@ -143,7 +143,7 @@ const Footer = () => {
</a>
</li>
<li>
<a href='https://twitter.com/plebchan_eth' target='_blank' rel='noopener noreferrer'>
<a href='https://twitter.com/getplebchan' target='_blank' rel='noopener noreferrer'>
Twitter
</a>
</li>
@@ -63,7 +63,7 @@ const PopularThreadsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[];
return (
<div className={styles.box}>
<div className={`${styles.boxBar} ${styles.color2ColorBar}`}>
<h2 className={styles.capitalize}>{t('popular_threads')}</h2>
<h2 className='capitalize'>{t('popular_threads')}</h2>
<BoxModal isBoardsBoxModal={false} />
</div>
<div className={`${styles.boxContent} ${popularPosts.length === 8 ? styles.popularThreads : ''}`}>
+12 -2
View File
@@ -1,13 +1,18 @@
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
import { isSettingsView } from '../../lib/utils/view-utils';
import Post from '../../components/post';
import SettingsModal from '../../components/settings-modal';
const PendingPost = () => {
const { accountCommentIndex } = useParams<{ accountCommentIndex?: string }>();
const commentIndex = accountCommentIndex ? parseInt(accountCommentIndex) : undefined;
const post = useAccountComment({ commentIndex });
const navigate = useNavigate();
const location = useLocation();
const params = useParams();
const isInSettingsView = isSettingsView(location.pathname, params);
useEffect(() => window.scrollTo(0, 0), []);
@@ -17,7 +22,12 @@ const PendingPost = () => {
}
}, [post, navigate]);
return <Post post={post} />;
return (
<>
{isInSettingsView && <SettingsModal />}
<Post post={post} showReplies={false} />;
</>
);
};
export default PendingPost;