mirror of
https://github.com/plebbit/seedit.git
synced 2026-02-08 04:50:57 -05:00
Binary file not shown.
|
Before Width: | Height: | Size: 831 B |
Binary file not shown.
|
Before Width: | Height: | Size: 835 B |
BIN
public/assets/over18.png
Normal file
BIN
public/assets/over18.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
BIN
public/assets/thumbnail-icon-nsfw-dark.png
Normal file
BIN
public/assets/thumbnail-icon-nsfw-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
BIN
public/assets/thumbnail-icon-nsfw.png
Normal file
BIN
public/assets/thumbnail-icon-nsfw.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -25,6 +25,64 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
|
||||
<!-- Preload assets -->
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/all_feed_subscribe.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/all_feed_subscribe_hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/all_feed_subscribed.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/arrow-up.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/arrow-upvoted.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/arrow-down.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/arrow-downvoted.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-background-green.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-background-red.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-background-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-disabled-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-disabled.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-hover-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub-disabled-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub-disabled.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub-hover-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub-hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large-nub.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/button-large.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/close-button.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/close-button-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/close-button-hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/close-x-button.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/continue-this-thread-arrow-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/continue-this-thread-arrow.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/delete-button.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/droparrowblue.gif" as="image" type="image/gif" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/droparrowgray.gif" as="image" type="image/gif" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/play-button-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/play-button-hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/play-button.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/text-button-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/text-button-hover.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/buttons/text-button.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/community_settings.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/indicator-offline.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/indicator-online.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/locked-icon.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/logo/seedit.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/logo/seedit-text-dark.svg" as="image" type="image/svg+xml" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/logo/seedit-text-light.svg" as="image" type="image/svg+xml" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/mail-unread.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/mail.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/mod.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/over18.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-link-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-link.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-nsfw-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-nsfw.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-spoiler-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-spoiler.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-text-dark.png" as="image" type="image/png" />
|
||||
<link rel="preload" href="%PUBLIC_URL%/assets/thumbnail-icon-text.png" as="image" type="image/png" />
|
||||
|
||||
<title>seedit</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "عنوان قصير لمجتمعك",
|
||||
"anti_spam_challenges": "تحديات مكافحة البريد العشوائي",
|
||||
"anti_spam_challenges_subtitle": "اختر تحدي أو أكثر لمنع الرسائل غير المرغوب فيها",
|
||||
"add_a_challenge": "إضافة تحدي"
|
||||
"add_a_challenge": "إضافة تحدي",
|
||||
"communities_you_moderate": "المجتمعات التي تشرف عليها",
|
||||
"blur_media": "تمويه الوسائط المعلمة كـ NSFW/18+",
|
||||
"nsfw_content": "محتوى NSFW",
|
||||
"nsfw_communities": "مجتمعات NSFW",
|
||||
"hide_adult": "إخفاء المجتمعات المعلَمة كـ \"بالغ\"",
|
||||
"hide_gore": "إخفاء المجتمعات المعلَمة كـ \"دموي\"",
|
||||
"hide_anti": "إخفاء المجتمعات المعلَمة كـ \"مناهض\"",
|
||||
"filters": "مرشحات",
|
||||
"see_nsfw": "انقر لرؤية NSFW",
|
||||
"see_nsfw_spoiler": "انقر لرؤية NSFW المفسد",
|
||||
"always_show_nsfw": "هل تريد دائمًا عرض وسائل الإعلام NSFW؟",
|
||||
"always_show_nsfw_notice": "حسنًا، لقد غيرنا تفضيلاتك لعرض وسائل الإعلام NSFW دائمًا.",
|
||||
"content_options": "خيارات المحتوى",
|
||||
"hide_vulgar": "إخفاء المجتمعات المعلَمة كـ \"فاحش\"",
|
||||
"over_18": "أكثر من 18؟",
|
||||
"must_be_over_18": "يجب أن تكون فوق 18 عامًا لعرض هذه المجتمع",
|
||||
"must_be_over_18_explanation": "يجب أن تكون في سن 18 عامًا على الأقل لعرض هذا المحتوى. هل أنت فوق 18 عامًا ومستعد لرؤية المحتوى البالغ؟",
|
||||
"no_thank_you": "لا، شكرًا",
|
||||
"continue": "استمر",
|
||||
"download_latest_android": "تحميل أحدث إصدار من أندرويد؟",
|
||||
"submitter": "مقدّم"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "আপনার সম্প্রদায়ের জন্য একটি সংক্ষিপ্ত শিরোনাম",
|
||||
"anti_spam_challenges": "অ্যান্টি-স্প্যাম চ্যালেঞ্জ",
|
||||
"anti_spam_challenges_subtitle": "স্প্যাম প্রতিরোধ করতে এক বা একাধিক চ্যালেঞ্জ নির্বাচন করুন",
|
||||
"add_a_challenge": "একটি চ্যালেঞ্জ যোগ করুন"
|
||||
"add_a_challenge": "একটি চ্যালেঞ্জ যোগ করুন",
|
||||
"communities_you_moderate": "আপনি যে কমিউনিটিগুলি পরিচালনা করেন",
|
||||
"blur_media": "NSFW/18+ হিসেবে চিহ্নিত মিডিয়া ব্লার করুন",
|
||||
"nsfw_content": "NSFW কনটেন্ট",
|
||||
"nsfw_communities": "NSFW কমিউনিটিজ",
|
||||
"hide_adult": "এডাল্ট হিসেবে ট্যাগ করা কমিউনিটিগুলি লুকান",
|
||||
"hide_gore": "গোর হিসেবে ট্যাগ করা কমিউনিটিগুলি লুকান",
|
||||
"hide_anti": "অ্যান্টি হিসেবে ট্যাগ করা কমিউনিটিগুলি লুকান",
|
||||
"filters": "ফিল্টার",
|
||||
"see_nsfw": "NSFW দেখতে ক্লিক করুন",
|
||||
"see_nsfw_spoiler": "NSFW স্পয়লার দেখতে ক্লিক করুন",
|
||||
"always_show_nsfw": "আপনি কি সর্বদা NSFW মিডিয়া দেখাতে চান?",
|
||||
"always_show_nsfw_notice": "ওকে, আমরা আপনার পছন্দগুলি সর্বদা NSFW মিডিয়া দেখাতে পরিবর্তন করেছি।",
|
||||
"content_options": "সামগ্রী বিকল্প",
|
||||
"hide_vulgar": "ভুলগার হিসেবে ট্যাগ করা কমিউনিটিগুলি লুকান",
|
||||
"over_18": "১৮ এর উপরে?",
|
||||
"must_be_over_18": "এই কমিউনিটি দেখতে আপনাকে ১৮+ হতে হবে",
|
||||
"must_be_over_18_explanation": "এই কন্টেন্ট দেখতে আপনাকে অন্তত ১৮ বছর বয়সী হতে হবে। আপনি কি ১৮ বছরের উপরে এবং প্রাপ্তবয়স্ক কন্টেন্ট দেখতে ইচ্ছুক?",
|
||||
"no_thank_you": "না, ধন্যবাদ",
|
||||
"continue": "অবস্থান করুন",
|
||||
"download_latest_android": "সর্বশেষ অ্যান্ড্রয়েড সংস্করণ ডাউনলোড করুন?",
|
||||
"submitter": "জমাদাতা"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Krátký název pro vaši komunitu",
|
||||
"anti_spam_challenges": "Anti-spam výzvy",
|
||||
"anti_spam_challenges_subtitle": "Vyberte jednu nebo více výzev k prevenci spamu",
|
||||
"add_a_challenge": "Přidat výzvu"
|
||||
"add_a_challenge": "Přidat výzvu",
|
||||
"communities_you_moderate": "Komunity, které moderujete",
|
||||
"blur_media": "Zamázat média označená jako NSFW/18+",
|
||||
"nsfw_content": "NSFW obsah",
|
||||
"nsfw_communities": "NSFW komunity",
|
||||
"hide_adult": "Skrýt komunity označené jako \"dospělý\"",
|
||||
"hide_gore": "Skrýt komunity označené jako \"gore\"",
|
||||
"hide_anti": "Skrýt komunity označené jako \"anti\"",
|
||||
"filters": "Filtry",
|
||||
"see_nsfw": "Klikněte pro zobrazení NSFW",
|
||||
"see_nsfw_spoiler": "Klikněte pro zobrazení NSFW spoileru",
|
||||
"always_show_nsfw": "Chcete vždy zobrazit NSFW média?",
|
||||
"always_show_nsfw_notice": "Dobře, změnili jsme vaše preference na vždy zobrazovat NSFW média.",
|
||||
"content_options": "Možnosti obsahu",
|
||||
"hide_vulgar": "Skrýt komunity označené jako \"vulgar\"",
|
||||
"over_18": "Více než 18?",
|
||||
"must_be_over_18": "Musíte být starší 18 let, abyste si mohli prohlédnout tuto komunitu",
|
||||
"must_be_over_18_explanation": "Musíte být alespoň 18 let starý/á, abyste si mohli prohlédnout tento obsah. Jste starší 18 let a ochotni vidět obsah pro dospělé?",
|
||||
"no_thank_you": "Ne, děkuji",
|
||||
"continue": "Pokračovat",
|
||||
"download_latest_android": "Stáhněte si nejnovější verzi Androidu?",
|
||||
"submitter": "Odesílatel"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "En kort titel til dit fællesskab",
|
||||
"anti_spam_challenges": "Anti-spam udfordringer",
|
||||
"anti_spam_challenges_subtitle": "Vælg en eller flere udfordringer for at forhindre spam",
|
||||
"add_a_challenge": "Tilføj en udfordring"
|
||||
"add_a_challenge": "Tilføj en udfordring",
|
||||
"communities_you_moderate": "De samfund, du modererer",
|
||||
"blur_media": "Slør medier markeret som NSFW/18+",
|
||||
"nsfw_content": "NSFW indhold",
|
||||
"nsfw_communities": "NSFW fællesskaber",
|
||||
"hide_adult": "Skjul samfund markeret som \"voksen\"",
|
||||
"hide_gore": "Skjul samfund markeret som \"gore\"",
|
||||
"hide_anti": "Skjul samfund markeret som \"anti\"",
|
||||
"filters": "Filtre",
|
||||
"see_nsfw": "Klik for at se NSFW",
|
||||
"see_nsfw_spoiler": "Klik for at se NSFW spoiler",
|
||||
"always_show_nsfw": "Vil du altid vise NSFW medier?",
|
||||
"always_show_nsfw_notice": "Okay, vi har ændret dine præferencer til altid at vise NSFW medier.",
|
||||
"content_options": "Indholdsindstillinger",
|
||||
"hide_vulgar": "Skjul samfund markeret som \"vulgar\"",
|
||||
"over_18": "Over 18?",
|
||||
"must_be_over_18": "Du skal være over 18 år for at se dette fællesskab",
|
||||
"must_be_over_18_explanation": "Du skal være mindst 18 år gammel for at se dette indhold. Er du over 18 og villig til at se voksenindhold?",
|
||||
"no_thank_you": "Nej, tak tak",
|
||||
"continue": "Fortsæt",
|
||||
"download_latest_android": "Download den nyeste Android-version?",
|
||||
"submitter": "Indsender"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Ein kurzer Titel für deine Gemeinschaft",
|
||||
"anti_spam_challenges": "Anti-Spam-Herausforderungen",
|
||||
"anti_spam_challenges_subtitle": "Wählen Sie eine oder mehrere Herausforderungen zur Vermeidung von Spam",
|
||||
"add_a_challenge": "Herausforderung hinzufügen"
|
||||
"add_a_challenge": "Herausforderung hinzufügen",
|
||||
"communities_you_moderate": "Gemeinschaften, die du moderierst",
|
||||
"blur_media": "Unschärfe Medien, die als NSFW/18+ markiert sind",
|
||||
"nsfw_content": "NSFW-Inhalt",
|
||||
"nsfw_communities": "NSFW-Communities",
|
||||
"hide_adult": "Verstecke Communities, die als \"Erwachsene\" markiert sind",
|
||||
"hide_gore": "Verstecke Communities, die als \"Gore\" markiert sind",
|
||||
"hide_anti": "Verstecke Communities, die als \"Anti\" markiert sind",
|
||||
"filters": "Filter",
|
||||
"see_nsfw": "Klicken Sie, um NSFW zu sehen",
|
||||
"see_nsfw_spoiler": "Klicken Sie, um den NSFW Spoiler zu sehen",
|
||||
"always_show_nsfw": "Möchten Sie immer NSFW-Medien anzeigen?",
|
||||
"always_show_nsfw_notice": "Okay, wir haben deine Präferenzen geändert, um immer NSFW-Medien anzuzeigen.",
|
||||
"content_options": "Inhaltsoptionen",
|
||||
"hide_vulgar": "Verstecke Communities, die als \"Vulgar\" markiert sind",
|
||||
"over_18": "Über 18?",
|
||||
"must_be_over_18": "Sie müssen über 18 Jahre alt sein, um diese Community zu sehen",
|
||||
"must_be_over_18_explanation": "Sie müssen mindestens 18 Jahre alt sein, um diesen Inhalt zu sehen. Sind Sie über 18 Jahre alt und bereit, Erwachsenen-Inhalte zu sehen?",
|
||||
"no_thank_you": "Nein, danke",
|
||||
"continue": "Weiter",
|
||||
"download_latest_android": "Laden Sie die neueste Android-Version herunter?",
|
||||
"submitter": "Einreicher"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Ένας σύντομος τίτλος για την κοινότητά σας",
|
||||
"anti_spam_challenges": "Προκλήσεις κατά του spam",
|
||||
"anti_spam_challenges_subtitle": "Επιλέξτε μία ή περισσότερες προκλήσεις για την αποτροπή των spam",
|
||||
"add_a_challenge": "Προσθήκη πρόκλησης"
|
||||
"add_a_challenge": "Προσθήκη πρόκλησης",
|
||||
"communities_you_moderate": "Κοινότητες που moderates",
|
||||
"blur_media": "Θολώστε τα μέσα που είναι επισημασμένα ως NSFW/18+",
|
||||
"nsfw_content": "Περιεχόμενο NSFW",
|
||||
"nsfw_communities": "Κοινότητες NSFW",
|
||||
"hide_adult": "Απόκρυψη κοινοτήτων που είναι επισημασμένες ως \"ενήλικες\"",
|
||||
"hide_gore": "Απόκρυψη κοινοτήτων που είναι επισημασμένες ως \"gore\"",
|
||||
"hide_anti": "Απόκρυψη κοινοτήτων που είναι επισημασμένες ως \"αντι\"",
|
||||
"filters": "Φίλτρα",
|
||||
"see_nsfw": "Κλικ για να δείτε το NSFW",
|
||||
"see_nsfw_spoiler": "Κλικ για να δείτε το NSFW spoiler",
|
||||
"always_show_nsfw": "Θέλετε να εμφανίζετε πάντα τα μέσα NSFW;",
|
||||
"always_show_nsfw_notice": "Εντάξει, αλλάξαμε τις προτιμήσεις σας για να εμφανίζετε πάντα τα μέσα NSFW.",
|
||||
"content_options": "Επιλογές περιεχομένου",
|
||||
"hide_vulgar": "Απόκρυψη κοινοτήτων που είναι επισημασμένες ως \"vulgar\"",
|
||||
"over_18": "Άνω των 18;",
|
||||
"must_be_over_18": "Πρέπει να είστε άνω των 18 για να δείτε αυτήν την κοινότητα",
|
||||
"must_be_over_18_explanation": "Πρέπει να είστε τουλάχιστον 18 ετών για να δείτε αυτό το περιεχόμενο. Είστε άνω των 18 και πρόθυμοι να δείτε περιεχόμενο για ενήλικες;",
|
||||
"no_thank_you": "Όχι, ευχαριστώ",
|
||||
"continue": "Συνέχεια",
|
||||
"download_latest_android": "Κατεβάστε την τελευταία έκδοση Android;",
|
||||
"submitter": "Υποβολέας"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "A short title for your community",
|
||||
"anti_spam_challenges": "Anti-spam challenges",
|
||||
"anti_spam_challenges_subtitle": "Choose one or more challenges to prevent spam",
|
||||
"add_a_challenge": "Add a challenge"
|
||||
"add_a_challenge": "Add a challenge",
|
||||
"communities_you_moderate": "Communities you moderate",
|
||||
"blur_media": "Blur media marked as NSFW/18+",
|
||||
"nsfw_content": "NSFW content",
|
||||
"nsfw_communities": "NSFW communities",
|
||||
"hide_adult": "Hide communities tagged as \"adult\"",
|
||||
"hide_gore": "Hide communities tagged as \"gore\"",
|
||||
"hide_anti": "Hide communities tagged as \"anti\"",
|
||||
"filters": "Filters",
|
||||
"see_nsfw": "Click to see nsfw",
|
||||
"see_nsfw_spoiler": "Click to see nsfw spoiler",
|
||||
"always_show_nsfw": "Always show NSFW media?",
|
||||
"always_show_nsfw_notice": "Ok, we changed your preferences to always show NSFW media.",
|
||||
"content_options": "Content options",
|
||||
"hide_vulgar": "Hide communities tagged as \"vulgar\"",
|
||||
"over_18": "Over 18?",
|
||||
"must_be_over_18": "You must be 18+ to view this community",
|
||||
"must_be_over_18_explanation": "You must be at least eighteen years old to view this content. Are you over eighteen and willing to see adult content?",
|
||||
"no_thank_you": "No thank you",
|
||||
"continue": "Continue",
|
||||
"download_latest_android": "Download the latest android version?",
|
||||
"submitter": "Submitter"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Un título corto para tu comunidad",
|
||||
"anti_spam_challenges": "Desafíos anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Elige uno o más desafíos para prevenir el spam",
|
||||
"add_a_challenge": "Añadir un desafío"
|
||||
"add_a_challenge": "Añadir un desafío",
|
||||
"communities_you_moderate": "Comunidades que moderas",
|
||||
"blur_media": "Difuminar los medios marcados como NSFW/18+",
|
||||
"nsfw_content": "Contenido NSFW",
|
||||
"nsfw_communities": "Comunidades NSFW",
|
||||
"hide_adult": "Ocultar comunidades etiquetadas como \"adulto\"",
|
||||
"hide_gore": "Ocultar comunidades etiquetadas como \"gore\"",
|
||||
"hide_anti": "Ocultar comunidades etiquetadas como \"anti\"",
|
||||
"filters": "Filtros",
|
||||
"see_nsfw": "Haz clic para ver NSFW",
|
||||
"see_nsfw_spoiler": "Haz clic para ver el spoiler NSFW",
|
||||
"always_show_nsfw": "¿Siempre mostrar medios NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, cambiamos tus preferencias para mostrar siempre medios NSFW.",
|
||||
"content_options": "Opciones de contenido",
|
||||
"hide_vulgar": "Ocultar comunidades etiquetadas como \"vulgar\"",
|
||||
"over_18": "¿Más de 18?",
|
||||
"must_be_over_18": "Debes tener más de 18 años para ver esta comunidad",
|
||||
"must_be_over_18_explanation": "Debe tener al menos dieciocho años para ver este contenido. ¿Tienes más de dieciocho años y estás dispuesto a ver contenido para adultos?",
|
||||
"no_thank_you": "No gracias",
|
||||
"continue": "Continuar",
|
||||
"download_latest_android": "¿Descargar la última versión de Android?",
|
||||
"submitter": "Remitente"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "یک عنوان کوتاه برای جامعه شما",
|
||||
"anti_spam_challenges": "چالشهای ضد هرزنامه",
|
||||
"anti_spam_challenges_subtitle": "یک یا چند چالش برای جلوگیری از هرزنامه انتخاب کنید",
|
||||
"add_a_challenge": "یک چالش اضافه کنید"
|
||||
"add_a_challenge": "یک چالش اضافه کنید",
|
||||
"communities_you_moderate": "انجمنهایی که شما مدیریت میکنید",
|
||||
"blur_media": "پوشاندن رسانههای علامتگذاری شده به عنوان NSFW/18+",
|
||||
"nsfw_content": "محتوای NSFW",
|
||||
"nsfw_communities": "انجمنهای NSFW",
|
||||
"hide_adult": "پنهان کردن جوامع برچسبخورده به عنوان \"بزرگسال\"",
|
||||
"hide_gore": "پنهان کردن جوامع برچسبخورده به عنوان \"گور\"",
|
||||
"hide_anti": "پنهان کردن جوامع برچسبخورده به عنوان \"ضد\"",
|
||||
"filters": "فیلترها",
|
||||
"see_nsfw": "برای مشاهده NSFW کلیک کنید",
|
||||
"see_nsfw_spoiler": "برای مشاهده NSFW اسپویلر کلیک کنید",
|
||||
"always_show_nsfw": "آیا میخواهید همیشه رسانههای NSFW را نمایش دهید؟",
|
||||
"always_show_nsfw_notice": "باشه، ما تنظیمات شما را برای نمایش دائمی رسانههای NSFW تغییر دادیم.",
|
||||
"content_options": "گزینههای محتوا",
|
||||
"hide_vulgar": "پنهان کردن جوامع برچسبخورده به عنوان \"زشت\"",
|
||||
"over_18": "بالای 18؟",
|
||||
"must_be_over_18": "برای مشاهده این جامعه باید بالای ۱۸ سال باشید",
|
||||
"must_be_over_18_explanation": "برای مشاهده این محتوا باید حداقل هجده سال داشته باشید. آیا شما بالای هجده سال دارید و آماده مشاهده محتوای بزرگسالان هستید؟",
|
||||
"no_thank_you": "نه، ممنون",
|
||||
"continue": "ادامه بده",
|
||||
"download_latest_android": "دانلود آخرین نسخه اندروید؟",
|
||||
"submitter": "ارسالکننده"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Lyhyt otsikko yhteisöllesi",
|
||||
"anti_spam_challenges": "Vasta-roskapostin haasteet",
|
||||
"anti_spam_challenges_subtitle": "Valitse yksi tai useampi haaste estämään roskapostia",
|
||||
"add_a_challenge": "Lisää haaste"
|
||||
"add_a_challenge": "Lisää haaste",
|
||||
"communities_you_moderate": "Yhteisöt, joita moderoinnit",
|
||||
"blur_media": "Sumenna media, jotka on merkitty NSFW/18+",
|
||||
"nsfw_content": "NSFW-sisältö",
|
||||
"nsfw_communities": "NSFW-yhteisöt",
|
||||
"hide_adult": "Piilota yhteisöt, jotka on merkitty \"aikuiseksi\"",
|
||||
"hide_gore": "Piilota yhteisöt, jotka on merkitty \"gore\"",
|
||||
"hide_anti": "Piilota yhteisöt, jotka on merkitty \"anti\"",
|
||||
"filters": "Suodattimet",
|
||||
"see_nsfw": "Napsauta nähdäksesi NSFW",
|
||||
"see_nsfw_spoiler": "Napsauta nähdäksesi NSFW-spoilerin",
|
||||
"always_show_nsfw": "Haluatko aina näyttää NSFW-mediaa?",
|
||||
"always_show_nsfw_notice": "Ok, muutimme asetuksesi aina näyttääksesi NSFW-mediaa.",
|
||||
"content_options": "Sisältöasetukset",
|
||||
"hide_vulgar": "Piilota yhteisöt, jotka on merkitty \"vulgar\"",
|
||||
"over_18": "Yli 18?",
|
||||
"must_be_over_18": "Sinun täytyy olla yli 18-vuotias nähdäksesi tämän yhteisön",
|
||||
"must_be_over_18_explanation": "Sinun täytyy olla vähintään kahdeksantoista vuotta vanha nähdäksesi tämän sisällön. Oletko yli 18-vuotias ja halukas katsomaan aikuisille tarkoitettua sisältöä?",
|
||||
"no_thank_you": "Ei kiitos",
|
||||
"continue": "Jatka",
|
||||
"download_latest_android": "Lataa uusin Android-versio?",
|
||||
"submitter": "Lähettäjä"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Isang maikling pamagat para sa iyong komunidad",
|
||||
"anti_spam_challenges": "Mga anti-spam na hamon",
|
||||
"anti_spam_challenges_subtitle": "Pumili ng isa o higit pang mga hamon upang maiwasan ang spam",
|
||||
"add_a_challenge": "Magdagdag ng hamon"
|
||||
"add_a_challenge": "Magdagdag ng hamon",
|
||||
"communities_you_moderate": "Mga komunidad na iyong mino-moderate",
|
||||
"blur_media": "I-blur ang media na minarkahan bilang NSFW/18+",
|
||||
"nsfw_content": "Nilalaman ng NSFW",
|
||||
"nsfw_communities": "NSFW na komunidad",
|
||||
"hide_adult": "Itago ang mga komunidad na minarkahan bilang \"adult\"",
|
||||
"hide_gore": "Itago ang mga komunidad na minarkahan bilang \"gore\"",
|
||||
"hide_anti": "Itago ang mga komunidad na minarkahan bilang \"anti\"",
|
||||
"filters": "Mga filter",
|
||||
"see_nsfw": "I-click upang makita ang NSFW",
|
||||
"see_nsfw_spoiler": "I-click upang makita ang NSFW spoiler",
|
||||
"always_show_nsfw": "Palaging ipakita ang mga media ng NSFW?",
|
||||
"always_show_nsfw_notice": "Okay, binago namin ang iyong mga preference upang palaging ipakita ang NSFW media.",
|
||||
"content_options": "Mga opsyon sa nilalaman",
|
||||
"hide_vulgar": "Itago ang mga komunidad na minarkahan bilang \"vulgar\"",
|
||||
"over_18": "Higit sa 18?",
|
||||
"must_be_over_18": "Dapat kang 18+ upang makita ang komunidad na ito",
|
||||
"must_be_over_18_explanation": "Dapat kang hindi bababa sa labing walong taon upang makita ang nilalamang ito. Ikaw ba ay higit sa labing walong taon at handang makita ang nilalamang pang-adulto?",
|
||||
"no_thank_you": "Hindi, salamat",
|
||||
"continue": "Magpatuloy",
|
||||
"download_latest_android": "I-download ang pinakabagong bersyon ng Android?",
|
||||
"submitter": "Nagpadala"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Un titre court pour votre communauté",
|
||||
"anti_spam_challenges": "Défis anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Choisissez un ou plusieurs défis pour prévenir le spam",
|
||||
"add_a_challenge": "Ajouter un défi"
|
||||
"add_a_challenge": "Ajouter un défi",
|
||||
"communities_you_moderate": "Communautés que vous modérez",
|
||||
"blur_media": "Flouter les médias marqués comme NSFW/18+",
|
||||
"nsfw_content": "Contenu NSFW",
|
||||
"nsfw_communities": "Communautés NSFW",
|
||||
"hide_adult": "Cacher les communautés étiquetées comme \"adulte\"",
|
||||
"hide_gore": "Cacher les communautés étiquetées comme \"gore\"",
|
||||
"hide_anti": "Cacher les communautés étiquetées comme \"anti\"",
|
||||
"filters": "Filtres",
|
||||
"see_nsfw": "Cliquez pour voir le NSFW",
|
||||
"see_nsfw_spoiler": "Cliquez pour voir le spoiler NSFW",
|
||||
"always_show_nsfw": "Voulez-vous toujours afficher les médias NSFW ?",
|
||||
"always_show_nsfw_notice": "D'accord, nous avons modifié vos préférences pour afficher toujours les médias NSFW.",
|
||||
"content_options": "Options de contenu",
|
||||
"hide_vulgar": "Cacher les communautés étiquetées comme \"vulgaire\"",
|
||||
"over_18": "Plus de 18?",
|
||||
"must_be_over_18": "Vous devez avoir 18 ans ou plus pour voir cette communauté",
|
||||
"must_be_over_18_explanation": "Vous devez avoir au moins dix-huit ans pour voir ce contenu. Avez-vous plus de dix-huit ans et êtes-vous prêt à voir du contenu pour adultes ?",
|
||||
"no_thank_you": "Non merci",
|
||||
"continue": "Continuer",
|
||||
"download_latest_android": "Télécharger la dernière version d'Android ?",
|
||||
"submitter": "Soumetteur"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "כותרת קצרה עבור הקהילה שלך",
|
||||
"anti_spam_challenges": "אתגרים נגד ספאם",
|
||||
"anti_spam_challenges_subtitle": "בחר אתגר אחד או יותר כדי למנוע דואר זבל",
|
||||
"add_a_challenge": "הוסף אתגר"
|
||||
"add_a_challenge": "הוסף אתגר",
|
||||
"communities_you_moderate": "קהילות שאתה מנהל",
|
||||
"blur_media": "הטשטש מדיה שסומנה כ-NSFW/18+",
|
||||
"nsfw_content": "תוכן NSFW",
|
||||
"nsfw_communities": "קהילות NSFW",
|
||||
"hide_adult": "הסתר קהילות שסומנו כ\"מבוגר\"",
|
||||
"hide_gore": "הסתר קהילות שסומנו כ\"גור\"",
|
||||
"hide_anti": "הסתר קהילות שסומנו כ\"נגד\"",
|
||||
"filters": "סינונים",
|
||||
"see_nsfw": "לחץ כדי לראות NSFW",
|
||||
"see_nsfw_spoiler": "לחץ כדי לראות את ה-NSFW ספוילר",
|
||||
"always_show_nsfw": "האם תמיד להציג מדיה NSFW?",
|
||||
"always_show_nsfw_notice": "אוקי, שינינו את ההעדפות שלך להציג תמיד מדיה NSFW.",
|
||||
"content_options": "אפשרויות תוכן",
|
||||
"hide_vulgar": "הסתר קהילות שסומנו כ\"גס\"",
|
||||
"over_18": "מעל גיל 18?",
|
||||
"must_be_over_18": "אתה חייב להיות מעל גיל 18 כדי לראות את הקהילה הזאת",
|
||||
"must_be_over_18_explanation": "עליך להיות לפחות בן 18 על מנת לצפות בתוכן הזה. האם אתה מעל גיל 18 ומוכן לראות תוכן למבוגרים?",
|
||||
"no_thank_you": "לא תודה",
|
||||
"continue": "המשך",
|
||||
"download_latest_android": "להוריד את הגרסה האחרונה של אנדרואיד?",
|
||||
"submitter": "שולח"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "आपके समुदाय के लिए एक छोटा शीर्षक",
|
||||
"anti_spam_challenges": "एंटी-स्पैम चुनौतियाँ",
|
||||
"anti_spam_challenges_subtitle": "स्पैम को रोकने के लिए एक या अधिक चुनौतियाँ चुनें",
|
||||
"add_a_challenge": "एक चुनौती जोड़ें"
|
||||
"add_a_challenge": "एक चुनौती जोड़ें",
|
||||
"communities_you_moderate": "आप जो समुदाय मॉडरेट करते हैं",
|
||||
"blur_media": "NSFW/18+ के रूप में चिह्नित मीडिया को ब्लर करें",
|
||||
"nsfw_content": "NSFW सामग्री",
|
||||
"nsfw_communities": "NSFW समुदाय",
|
||||
"hide_adult": "जो \"वयस्क\" के रूप में टैग की गई समुदायों को छिपाएं",
|
||||
"hide_gore": "जो \"गोर\" के रूप में टैग की गई समुदायों को छिपाएं",
|
||||
"hide_anti": "जो \"एंटी\" के रूप में टैग की गई समुदायों को छिपाएं",
|
||||
"filters": "फ़िल्टर",
|
||||
"see_nsfw": "NSFW देखने के लिए क्लिक करें",
|
||||
"see_nsfw_spoiler": "NSFW स्पॉयलर देखने के लिए क्लिक करें",
|
||||
"always_show_nsfw": "क्या आप हमेशा NSFW मीडिया दिखाना चाहते हैं?",
|
||||
"always_show_nsfw_notice": "ठीक है, हमने आपकी प्राथमिकताएँ हमेशा NSFW मीडिया दिखाने के लिए बदल दी हैं।",
|
||||
"content_options": "सामग्री विकल्प",
|
||||
"hide_vulgar": "जो \"वुल्गर\" के रूप में टैग की गई समुदायों को छिपाएं",
|
||||
"over_18": "18 से ऊपर?",
|
||||
"must_be_over_18": "आपको इस समुदाय को देखने के लिए 18+ होना चाहिए",
|
||||
"must_be_over_18_explanation": "इस सामग्री को देखने के लिए आपको कम से कम अठारह साल का होना चाहिए। क्या आप अठारह साल से ऊपर हैं और वयस्क सामग्री देखने के इच्छुक हैं?",
|
||||
"no_thank_you": "नहीं, धन्यवाद",
|
||||
"continue": "जारी रखें",
|
||||
"download_latest_android": "नवीनतम एंड्रॉइड संस्करण डाउनलोड करें?",
|
||||
"submitter": "प्रस्तावक"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Egy rövid cím a közösségednek",
|
||||
"anti_spam_challenges": "Anti-spam kihívások",
|
||||
"anti_spam_challenges_subtitle": "Válasszon egy vagy több kihívást a spam megelőzésére",
|
||||
"add_a_challenge": "Hozzáad egy kihívást"
|
||||
"add_a_challenge": "Hozzáad egy kihívást",
|
||||
"communities_you_moderate": "Közösségek, amelyeket moderálsz",
|
||||
"blur_media": "Elhomályosítja az NSFW/18+ jelöléssel ellátott médiát",
|
||||
"nsfw_content": "NSFW tartalom",
|
||||
"nsfw_communities": "NSFW közösségek",
|
||||
"hide_adult": "Rejtse el a \"felnőtt\" címkével ellátott közösségeket",
|
||||
"hide_gore": "Rejtse el a \"gore\" címkével ellátott közösségeket",
|
||||
"hide_anti": "Rejtse el a \"anti\" címkével ellátott közösségeket",
|
||||
"filters": "Szűrők",
|
||||
"see_nsfw": "Kattintson a NSFW megtekintéséhez",
|
||||
"see_nsfw_spoiler": "Kattintson a NSFW spoiler megtekintéséhez",
|
||||
"always_show_nsfw": "Mindig meg szeretné jeleníteni az NSFW médiát?",
|
||||
"always_show_nsfw_notice": "Rendben, megváltoztattuk az preferenciáit, hogy mindig megjelenítse az NSFW médiát.",
|
||||
"content_options": "Tartalombeállítások",
|
||||
"hide_vulgar": "Rejtse el a \"vulgar\" címkével ellátott közösségeket",
|
||||
"over_18": "18 felett?",
|
||||
"must_be_over_18": "18 évesnek kell lenned ahhoz, hogy megnézd ezt a közösséget",
|
||||
"must_be_over_18_explanation": "Legalább tizennyolc évesnek kell lenned ahhoz, hogy megtekinthesd ezt a tartalmat. Több mint tizennyolc éves vagy, és hajlandó vagy felnőtteknek szóló tartalmat nézni?",
|
||||
"no_thank_you": "Nem, köszönöm",
|
||||
"continue": "Folytatás",
|
||||
"download_latest_android": "Töltse le a legújabb Android verziót?",
|
||||
"submitter": "Beküldő"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Judul singkat untuk komunitas Anda",
|
||||
"anti_spam_challenges": "Tantangan anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Pilih satu atau lebih tantangan untuk mencegah spam",
|
||||
"add_a_challenge": "Tambahkan tantangan"
|
||||
"add_a_challenge": "Tambahkan tantangan",
|
||||
"communities_you_moderate": "Komunitas yang Anda moderasi",
|
||||
"blur_media": "Blur media yang ditandai sebagai NSFW/18+",
|
||||
"nsfw_content": "Konten NSFW",
|
||||
"nsfw_communities": "Komunitas NSFW",
|
||||
"hide_adult": "Sembunyikan komunitas yang diberi label \"dewasa\"",
|
||||
"hide_gore": "Sembunyikan komunitas yang diberi label \"gore\"",
|
||||
"hide_anti": "Sembunyikan komunitas yang diberi label \"anti\"",
|
||||
"filters": "Filter",
|
||||
"see_nsfw": "Klik untuk melihat NSFW",
|
||||
"see_nsfw_spoiler": "Klik untuk melihat NSFW spoiler",
|
||||
"always_show_nsfw": "Apakah Anda ingin selalu menampilkan media NSFW?",
|
||||
"always_show_nsfw_notice": "Oke, kami mengubah preferensi Anda untuk selalu menampilkan media NSFW.",
|
||||
"content_options": "Opsi konten",
|
||||
"hide_vulgar": "Sembunyikan komunitas yang diberi label \"vulgar\"",
|
||||
"over_18": "Di atas 18?",
|
||||
"must_be_over_18": "Anda harus berusia 18+ untuk melihat komunitas ini",
|
||||
"must_be_over_18_explanation": "Anda harus berusia minimal delapan belas tahun untuk melihat konten ini. Apakah Anda berusia lebih dari delapan belas tahun dan bersedia melihat konten dewasa?",
|
||||
"no_thank_you": "Tidak, terima kasih",
|
||||
"continue": "Lanjutkan",
|
||||
"download_latest_android": "Unduh versi Android terbaru?",
|
||||
"submitter": "Pengirim"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Un titolo breve per la tua comunità",
|
||||
"anti_spam_challenges": "challenge anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Scegli una o più challenge per prevenire lo spam",
|
||||
"add_a_challenge": "Aggiungi un challenge"
|
||||
"add_a_challenge": "Aggiungi un challenge",
|
||||
"communities_you_moderate": "Comunità che moderi",
|
||||
"blur_media": "Offusca media contrassegnati come NSFW/18+",
|
||||
"nsfw_content": "Contenuti NSFW",
|
||||
"nsfw_communities": "Comunità NSFW",
|
||||
"hide_adult": "Nascondi le comunità contrassegnate come \"adulto\"",
|
||||
"hide_gore": "Nascondi le comunità contrassegnate come \"gore\"",
|
||||
"hide_anti": "Nascondi le comunità contrassegnate come \"anti\"",
|
||||
"filters": "Filtri",
|
||||
"see_nsfw": "Clicca per vedere NSFW",
|
||||
"see_nsfw_spoiler": "Clicca per vedere il spoiler NSFW",
|
||||
"always_show_nsfw": "Mostrare sempre i media NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, abbiamo cambiato le tue preferenze per mostrare sempre i media NSFW.",
|
||||
"content_options": "Opzioni dei contenuti",
|
||||
"hide_vulgar": "Nascondi le comunità contrassegnate come \"vulgar\"",
|
||||
"over_18": "Sopra i 18?",
|
||||
"must_be_over_18": "Devi avere più di 18 anni per visualizzare questa comunità",
|
||||
"must_be_over_18_explanation": "Devi avere almeno diciotto anni per visualizzare questo contenuto. Hai più di diciotto anni e sei disposto a vedere contenuti per adulti?",
|
||||
"no_thank_you": "No, grazie",
|
||||
"continue": "Continua",
|
||||
"download_latest_android": "Scarica l'ultima versione di Android?",
|
||||
"submitter": "Inviatore"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "あなたのコミュニティのための短いタイトル",
|
||||
"anti_spam_challenges": "アンチスパムチャレンジ",
|
||||
"anti_spam_challenges_subtitle": "スパムを防ぐために1つ以上のチャレンジを選択してください",
|
||||
"add_a_challenge": "チャレンジを追加"
|
||||
"add_a_challenge": "チャレンジを追加",
|
||||
"communities_you_moderate": "あなたが管理するコミュニティ",
|
||||
"blur_media": "NSFW/18+としてマークされたメディアをぼかす",
|
||||
"nsfw_content": "NSFWコンテンツ",
|
||||
"nsfw_communities": "NSFWコミュニティ",
|
||||
"hide_adult": "\"成人\"としてタグ付けされたコミュニティを非表示にする",
|
||||
"hide_gore": "\"ゴア\"としてタグ付けされたコミュニティを非表示にする",
|
||||
"hide_anti": "\"アンチ\"としてタグ付けされたコミュニティを非表示にする",
|
||||
"filters": "フィルター",
|
||||
"see_nsfw": "NSFWを見るにはクリック",
|
||||
"see_nsfw_spoiler": "NSFWのネタバレを見るにはクリック",
|
||||
"always_show_nsfw": "常にNSFWメディアを表示しますか?",
|
||||
"always_show_nsfw_notice": "はい、NSFWメディアを常に表示するように設定を変更しました。",
|
||||
"content_options": "コンテンツオプション",
|
||||
"hide_vulgar": "\"ヴァルガー\"としてタグ付けされたコミュニティを非表示にする",
|
||||
"over_18": "18歳以上?",
|
||||
"must_be_over_18": "このコミュニティを見るには18歳以上でなければなりません",
|
||||
"must_be_over_18_explanation": "このコンテンツを見るには少なくとも18歳でなければなりません。あなたは18歳以上で、成人向けコンテンツを見る準備ができていますか?",
|
||||
"no_thank_you": "いいえ、ありがとう",
|
||||
"continue": "続ける",
|
||||
"download_latest_android": "最新のAndroidバージョンをダウンロードしますか?",
|
||||
"submitter": "提出者"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "귀하의 커뮤니티를 위한 짧은 제목",
|
||||
"anti_spam_challenges": "스팸 방지 챌린지",
|
||||
"anti_spam_challenges_subtitle": "스팸을 방지하기 위해 하나 이상의 챌린지를 선택하세요",
|
||||
"add_a_challenge": "도전 추가"
|
||||
"add_a_challenge": "도전 추가",
|
||||
"communities_you_moderate": "당신이 관리하는 커뮤니티",
|
||||
"blur_media": "NSFW/18+로 표시된 미디어 흐리게 처리",
|
||||
"nsfw_content": "NSFW 콘텐츠",
|
||||
"nsfw_communities": "NSFW 커뮤니티",
|
||||
"hide_adult": "\"성인\"으로 태그된 커뮤니티 숨기기",
|
||||
"hide_gore": "\"고어\"로 태그된 커뮤니티 숨기기",
|
||||
"hide_anti": "\"반대\"로 태그된 커뮤니티 숨기기",
|
||||
"filters": "필터",
|
||||
"see_nsfw": "NSFW를 보려면 클릭",
|
||||
"see_nsfw_spoiler": "NSFW 스포일러를 보려면 클릭",
|
||||
"always_show_nsfw": "항상 NSFW 미디어를 표시하시겠습니까?",
|
||||
"always_show_nsfw_notice": "알겠습니다, 항상 NSFW 미디어를 표시하도록 기본 설정을 변경했습니다.",
|
||||
"content_options": "콘텐츠 옵션",
|
||||
"hide_vulgar": "\"벌거벗은\"으로 태그된 커뮤니티 숨기기",
|
||||
"over_18": "18세 이상?",
|
||||
"must_be_over_18": "이 커뮤니티를 보려면 18세 이상이어야 합니다",
|
||||
"must_be_over_18_explanation": "이 콘텐츠를 보려면 최소한 18세 이상이어야 합니다. 당신은 18세 이상이며 성인 콘텐츠를 볼 준비가 되셨나요?",
|
||||
"no_thank_you": "아니요, 감사합니다",
|
||||
"continue": "계속",
|
||||
"download_latest_android": "최신 Android 버전을 다운로드하시겠습니까?",
|
||||
"submitter": "제출자"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "तुमच्या समुदायासाठी एक छोटा शीर्षक",
|
||||
"anti_spam_challenges": "ॲंटी-स्पॅम चॅलेंजेस",
|
||||
"anti_spam_challenges_subtitle": "स्पॅम रोखण्यासाठी एक किंवा अधिक आव्हाने निवडा",
|
||||
"add_a_challenge": "एक आव्हान जोडा"
|
||||
"add_a_challenge": "एक आव्हान जोडा",
|
||||
"communities_you_moderate": "तुम्ही ज्या समुदायाचे व्यवस्थापन करता",
|
||||
"blur_media": "NSFW/18+ म्हणून चिन्हांकित केलेली मीडिया धूसर करा",
|
||||
"nsfw_content": "NSFW सामग्री",
|
||||
"nsfw_communities": "NSFW समुदाय",
|
||||
"hide_adult": "\"प्रौढ़\" म्हणून टॅग केलेल्या समुदायांना लपवा",
|
||||
"hide_gore": "\"गोर\" म्हणून टॅग केलेल्या समुदायांना लपवा",
|
||||
"hide_anti": "\"अँटी\" म्हणून टॅग केलेल्या समुदायांना लपवा",
|
||||
"filters": "फिल्टर",
|
||||
"see_nsfw": "NSFW पाहण्यासाठी क्लिक करा",
|
||||
"see_nsfw_spoiler": "NSFW स्पॉयलर पाहण्यासाठी क्लिक करा",
|
||||
"always_show_nsfw": "तुम्ही नेहमी NSFW मीडिया दाखवू इच्छिता का?",
|
||||
"always_show_nsfw_notice": "ठीक आहे, आम्ही तुमची प्राधान्ये नेहमी NSFW मीडिया दर्शवण्यासाठी बदलली आहेत.",
|
||||
"content_options": "सामग्री पर्याय",
|
||||
"hide_vulgar": "\"वुल्गर\" म्हणून टॅग केलेल्या समुदायांना लपवा",
|
||||
"over_18": "१८ वर्षांपेक्षा जास्त?",
|
||||
"must_be_over_18": "या समुदायाला पाहण्यासाठी तुम्ही १८+ असणे आवश्यक आहे",
|
||||
"must_be_over_18_explanation": "या सामग्रीला पाहण्यासाठी तुम्हाला किमान अठरा वर्षे वयाचे असावे लागेल. तुम्ही अठरा वर्षे वयाच्या वरील आहात का आणि प्रौढ सामग्री पाहण्यास तयार आहात?",
|
||||
"no_thank_you": "नाही, धन्यवाद",
|
||||
"continue": "सुरू ठेवा",
|
||||
"download_latest_android": "ताज्या Android आवृत्तीचे डाउनलोड करा?",
|
||||
"submitter": "समीक्षक"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Een korte titel voor je gemeenschap",
|
||||
"anti_spam_challenges": "Anti-spam uitdagingen",
|
||||
"anti_spam_challenges_subtitle": "Kies een of meer uitdagingen om spam te voorkomen",
|
||||
"add_a_challenge": "Voeg een uitdaging toe"
|
||||
"add_a_challenge": "Voeg een uitdaging toe",
|
||||
"communities_you_moderate": "Gemeenschappen die je modereert",
|
||||
"blur_media": "Vervagen media gemarkeerd als NSFW/18+",
|
||||
"nsfw_content": "NSFW-inhoud",
|
||||
"nsfw_communities": "NSFW-gemeenschappen",
|
||||
"hide_adult": "Verberg gemeenschappen die zijn gemarkeerd als \"volwassen\"",
|
||||
"hide_gore": "Verberg gemeenschappen die zijn gemarkeerd als \"gore\"",
|
||||
"hide_anti": "Verberg gemeenschappen die zijn gemarkeerd als \"anti\"",
|
||||
"filters": "Filters",
|
||||
"see_nsfw": "Klik om NSFW te zien",
|
||||
"see_nsfw_spoiler": "Klik om NSFW spoiler te zien",
|
||||
"always_show_nsfw": "Altijd NSFW-media weergeven?",
|
||||
"always_show_nsfw_notice": "Oké, we hebben je voorkeuren veranderd om altijd NSFW-media weer te geven.",
|
||||
"content_options": "Inhoudsopties",
|
||||
"hide_vulgar": "Verberg gemeenschappen die zijn gemarkeerd als \"vulgar\"",
|
||||
"over_18": "Boven de 18?",
|
||||
"must_be_over_18": "Je moet 18+ zijn om deze gemeenschap te bekijken",
|
||||
"must_be_over_18_explanation": "Je moet minstens achttien jaar oud zijn om deze inhoud te bekijken. Ben je ouder dan achttien en bereid om volwassen inhoud te bekijken?",
|
||||
"no_thank_you": "Nee, bedankt",
|
||||
"continue": "Doorgaan",
|
||||
"download_latest_android": "Download de nieuwste Android-versie?",
|
||||
"submitter": "Indiener"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "En kort tittel for ditt fellesskap",
|
||||
"anti_spam_challenges": "Anti-spam utfordringer",
|
||||
"anti_spam_challenges_subtitle": "Velg en eller flere utfordringer for å hindre spam",
|
||||
"add_a_challenge": "Legg til en utfordring"
|
||||
"add_a_challenge": "Legg til en utfordring",
|
||||
"communities_you_moderate": "Samfunnene du modererer",
|
||||
"blur_media": "Uskarpe media merket som NSFW/18+",
|
||||
"nsfw_content": "NSFW-innhold",
|
||||
"nsfw_communities": "NSFW-fellesskap",
|
||||
"hide_adult": "Skjul samfunn merket som \"voksen\"",
|
||||
"hide_gore": "Skjul samfunn merket som \"gore\"",
|
||||
"hide_anti": "Skjul samfunn merket som \"anti\"",
|
||||
"filters": "Filtre",
|
||||
"see_nsfw": "Klikk for å se NSFW",
|
||||
"see_nsfw_spoiler": "Klikk for å se NSFW-spoiler",
|
||||
"always_show_nsfw": "Vil du alltid vise NSFW-media?",
|
||||
"always_show_nsfw_notice": "Ok, vi har endret preferansene dine for å alltid vise NSFW-media.",
|
||||
"content_options": "Innstillinger for innhold",
|
||||
"hide_vulgar": "Skjul samfunn merket som \"vulgar\"",
|
||||
"over_18": "Over 18?",
|
||||
"must_be_over_18": "Du må være over 18 for å se dette fellesskapet",
|
||||
"must_be_over_18_explanation": "Du må være minst 18 år gammel for å se dette innholdet. Er du over 18 og villig til å se vokseninnhold?",
|
||||
"no_thank_you": "Nei, takk",
|
||||
"continue": "Fortsett",
|
||||
"download_latest_android": "Last ned den nyeste Android-versjonen?",
|
||||
"submitter": "Innsender"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Krótki tytuł dla twojej społeczności",
|
||||
"anti_spam_challenges": "Wyzwania przeciw spamowi",
|
||||
"anti_spam_challenges_subtitle": "Wybierz jedno lub więcej wyzwań, aby zapobiec spamowi",
|
||||
"add_a_challenge": "Dodaj wyzwanie"
|
||||
"add_a_challenge": "Dodaj wyzwanie",
|
||||
"communities_you_moderate": "Społeczności, którymi moderujesz",
|
||||
"blur_media": "Rozmyj media oznaczone jako NSFW/18+",
|
||||
"nsfw_content": "Treść NSFW",
|
||||
"nsfw_communities": "Społeczności NSFW",
|
||||
"hide_adult": "Ukryj społeczności oznaczone jako \"dorosły\"",
|
||||
"hide_gore": "Ukryj społeczności oznaczone jako \"gore\"",
|
||||
"hide_anti": "Ukryj społeczności oznaczone jako \"anti\"",
|
||||
"filters": "Filtry",
|
||||
"see_nsfw": "Kliknij, aby zobaczyć NSFW",
|
||||
"see_nsfw_spoiler": "Kliknij, aby zobaczyć spoiler NSFW",
|
||||
"always_show_nsfw": "Zawsze wyświetlać media NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, zmieniliśmy twoje preferencje, aby zawsze wyświetlać media NSFW.",
|
||||
"content_options": "Opcje treści",
|
||||
"hide_vulgar": "Ukryj społeczności oznaczone jako \"vulgar\"",
|
||||
"over_18": "Powyżej 18?",
|
||||
"must_be_over_18": "Musisz mieć więcej niż 18 lat, aby zobaczyć tę społeczność",
|
||||
"must_be_over_18_explanation": "Musisz mieć co najmniej osiemnaście lat, aby oglądać tę treść. Masz ponad osiemnaście lat i chcesz oglądać treści dla dorosłych?",
|
||||
"no_thank_you": "Nie, dziękuję",
|
||||
"continue": "Kontynuować",
|
||||
"download_latest_android": "Pobierz najnowszą wersję Androida?",
|
||||
"submitter": "Nadawca"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Um título curto para sua comunidade",
|
||||
"anti_spam_challenges": "Desafios anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Escolha um ou mais desafios para evitar spam",
|
||||
"add_a_challenge": "Adicionar um desafio"
|
||||
"add_a_challenge": "Adicionar um desafio",
|
||||
"communities_you_moderate": "Comunidades que você modera",
|
||||
"blur_media": "Desfoque mídias marcadas como NSFW/18+",
|
||||
"nsfw_content": "Conteúdo NSFW",
|
||||
"nsfw_communities": "Comunidades NSFW",
|
||||
"hide_adult": "Ocultar comunidades marcadas como \"adulto\"",
|
||||
"hide_gore": "Ocultar comunidades marcadas como \"gore\"",
|
||||
"hide_anti": "Ocultar comunidades marcadas como \"anti\"",
|
||||
"filters": "Filtros",
|
||||
"see_nsfw": "Clique para ver NSFW",
|
||||
"see_nsfw_spoiler": "Clique para ver o spoiler NSFW",
|
||||
"always_show_nsfw": "Sempre mostrar mídias NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, mudamos suas preferências para mostrar sempre mídias NSFW.",
|
||||
"content_options": "Opções de conteúdo",
|
||||
"hide_vulgar": "Ocultar comunidades marcadas como \"vulgar\"",
|
||||
"over_18": "Acima de 18?",
|
||||
"must_be_over_18": "Você precisa ter 18 anos ou mais para ver esta comunidade",
|
||||
"must_be_over_18_explanation": "Você deve ter pelo menos dezoito anos para ver este conteúdo. Você tem mais de dezoito anos e está disposto a ver conteúdo para adultos?",
|
||||
"no_thank_you": "Não, obrigado",
|
||||
"continue": "Continuar",
|
||||
"download_latest_android": "Baixar a versão mais recente do Android?",
|
||||
"submitter": "Submissor"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Un titlu scurt pentru comunitatea ta",
|
||||
"anti_spam_challenges": "Provocări anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Alegeți unul sau mai multe provocări pentru a preveni spamul",
|
||||
"add_a_challenge": "Adăugați o provocare"
|
||||
"add_a_challenge": "Adăugați o provocare",
|
||||
"communities_you_moderate": "Comunități pe care le moderezi",
|
||||
"blur_media": "Estompați media marcate ca NSFW/18+",
|
||||
"nsfw_content": "Conținut NSFW",
|
||||
"nsfw_communities": "Comunități NSFW",
|
||||
"hide_adult": "Ascunde comunitățile etichetate ca \"adult\"",
|
||||
"hide_gore": "Ascunde comunitățile etichetate ca \"gore\"",
|
||||
"hide_anti": "Ascunde comunitățile etichetate ca \"anti\"",
|
||||
"filters": "Filtre",
|
||||
"see_nsfw": "Faceți clic pentru a vedea NSFW",
|
||||
"see_nsfw_spoiler": "Faceți clic pentru a vedea spoilerul NSFW",
|
||||
"always_show_nsfw": "Doriți să arătați întotdeauna media NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, am schimbat preferințele tale pentru a arăta întotdeauna media NSFW.",
|
||||
"content_options": "Opțiuni de conținut",
|
||||
"hide_vulgar": "Ascunde comunitățile etichetate ca \"vulgar\"",
|
||||
"over_18": "Peste 18?",
|
||||
"must_be_over_18": "Trebuie să ai 18+ ani pentru a vizualiza această comunitate",
|
||||
"must_be_over_18_explanation": "Trebuie să ai cel puțin optsprezece ani pentru a vizualiza acest conținut. Ai peste optsprezece ani și ești dispus să vizionezi conținut pentru adulți?",
|
||||
"no_thank_you": "Nu, mulțumesc",
|
||||
"continue": "Continuă",
|
||||
"download_latest_android": "Descărcați cea mai recentă versiune Android?",
|
||||
"submitter": "Trimis"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Короткое название для вашего сообщества",
|
||||
"anti_spam_challenges": "Антиспам вызовы",
|
||||
"anti_spam_challenges_subtitle": "Выберите одну или несколько задач для предотвращения спама",
|
||||
"add_a_challenge": "Добавить задачу"
|
||||
"add_a_challenge": "Добавить задачу",
|
||||
"communities_you_moderate": "Сообщества, которые вы модерируете",
|
||||
"blur_media": "Размыть медиа, помеченные как NSFW/18+",
|
||||
"nsfw_content": "Контент NSFW",
|
||||
"nsfw_communities": "NSFW сообщества",
|
||||
"hide_adult": "Скрыть сообщества, помеченные как \"взрослый\"",
|
||||
"hide_gore": "Скрыть сообщества, помеченные как \"горе\"",
|
||||
"hide_anti": "Скрыть сообщества, помеченные как \"анти\"",
|
||||
"filters": "Фильтры",
|
||||
"see_nsfw": "Нажмите, чтобы увидеть NSFW",
|
||||
"see_nsfw_spoiler": "Нажмите, чтобы увидеть NSFW спойлер",
|
||||
"always_show_nsfw": "Хотите всегда показывать NSFW медиа?",
|
||||
"always_show_nsfw_notice": "Окей, мы изменили ваши предпочтения, чтобы всегда показывать медиа NSFW.",
|
||||
"content_options": "Параметры контента",
|
||||
"hide_vulgar": "Скрыть сообщества, помеченные как \"вульгарные\"",
|
||||
"over_18": "Больше 18?",
|
||||
"must_be_over_18": "Вы должны быть старше 18 лет, чтобы просматривать это сообщество",
|
||||
"must_be_over_18_explanation": "Вы должны быть как минимум восемнадцати лет, чтобы просматривать этот контент. Вам больше восемнадцати лет, и вы готовы просматривать контент для взрослых?",
|
||||
"no_thank_you": "Нет, спасибо",
|
||||
"continue": "Продолжить",
|
||||
"download_latest_android": "Скачать последнюю версию Android?",
|
||||
"submitter": "Отправитель"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Një titull i shkurtër për komunitetin tuaj",
|
||||
"anti_spam_challenges": "challenget anti-spam",
|
||||
"anti_spam_challenges_subtitle": "Zgjidhni një ose më shumë challenge për të parandaluar spam",
|
||||
"add_a_challenge": "Shtoni një sfidë"
|
||||
"add_a_challenge": "Shtoni një sfidë",
|
||||
"communities_you_moderate": "Komunitetet që moderoni",
|
||||
"blur_media": "Bluroni mediat e shënuara si NSFW/18+",
|
||||
"nsfw_content": "Përmbajtje NSFW",
|
||||
"nsfw_communities": "Komunitete NSFW",
|
||||
"hide_adult": "Fsheh komunitetet e etiketuar si \"të rritur\"",
|
||||
"hide_gore": "Fsheh komunitetet e etiketuar si \"gore\"",
|
||||
"hide_anti": "Fsheh komunitetet e etiketuar si \"anti\"",
|
||||
"filters": "Filtra",
|
||||
"see_nsfw": "Klikoni për të parë NSFW",
|
||||
"see_nsfw_spoiler": "Klikoni për të parë NSFW spoiler",
|
||||
"always_show_nsfw": "A dëshironi të shfaqni gjithmonë mediat NSFW?",
|
||||
"always_show_nsfw_notice": "Ok, ne ndryshuam preferencat tuaja për të shfaqur gjithmonë mediat NSFW.",
|
||||
"content_options": "Opsionet e përmbajtjes",
|
||||
"hide_vulgar": "Fsheh komunitetet e etiketuar si \"vulgar\"",
|
||||
"over_18": "Mbi 18?",
|
||||
"must_be_over_18": "Duhet të jeni 18+ për të parë këtë komunitet",
|
||||
"must_be_over_18_explanation": "Duhet të jeni të paktën tetëmbëdhjetë vjeç për të parë këtë përmbajtje. A jeni mbi tetëmbëdhjetë vjeç dhe jeni të gatshëm të shihni përmbajtje për të rritur?",
|
||||
"no_thank_you": "Jo, faleminderit",
|
||||
"continue": "Vazhdoni",
|
||||
"download_latest_android": "Shkarkoni versionin më të fundit të Android?",
|
||||
"submitter": "Dërguesi"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "En kort titel för ditt samhälle",
|
||||
"anti_spam_challenges": "Anti-spam-utmaningar",
|
||||
"anti_spam_challenges_subtitle": "Välj en eller flera utmaningar för att förhindra spam",
|
||||
"add_a_challenge": "Lägg till en utmaning"
|
||||
"add_a_challenge": "Lägg till en utmaning",
|
||||
"communities_you_moderate": "Gemenskaper du modererar",
|
||||
"blur_media": "Sudda ut media markerade som NSFW/18+",
|
||||
"nsfw_content": "NSFW-innehåll",
|
||||
"nsfw_communities": "NSFW-gemenskaper",
|
||||
"hide_adult": "Dölj samhällen märkta som \"vuxen\"",
|
||||
"hide_gore": "Dölj samhällen märkta som \"gore\"",
|
||||
"hide_anti": "Dölj samhällen märkta som \"anti\"",
|
||||
"filters": "Filter",
|
||||
"see_nsfw": "Klicka för att se NSFW",
|
||||
"see_nsfw_spoiler": "Klicka för att se NSFW-spoiler",
|
||||
"always_show_nsfw": "Vill du alltid visa NSFW-media?",
|
||||
"always_show_nsfw_notice": "Okej, vi har ändrat dina inställningar för att alltid visa NSFW-media.",
|
||||
"content_options": "Innehållsoptioner",
|
||||
"hide_vulgar": "Dölj samhällen märkta som \"vulgar\"",
|
||||
"over_18": "Över 18?",
|
||||
"must_be_over_18": "Du måste vara 18+ för att se denna gemenskap",
|
||||
"must_be_over_18_explanation": "Du måste vara minst arton år gammal för att se detta innehåll. Är du över arton och villig att se vuxeninnehåll?",
|
||||
"no_thank_you": "Nej, tack",
|
||||
"continue": "Fortsätt",
|
||||
"download_latest_android": "Ladda ner den senaste Android-versionen?",
|
||||
"submitter": "Inlämnare"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "మీ సముదాయం కోసం ఒక చిన్న శీర్షిక",
|
||||
"anti_spam_challenges": "ఏంటి-స్పామ్ సవాళ్ళు",
|
||||
"anti_spam_challenges_subtitle": "స్పామ్ ను నివారించడానికి ఒకటి లేదా ఎక్కువ సవాళ్లను ఎంచుకోండి",
|
||||
"add_a_challenge": "ఒక సవాలు జోడించండి"
|
||||
"add_a_challenge": "ఒక సవాలు జోడించండి",
|
||||
"communities_you_moderate": "మీరు నిర్వహించే కమ్యూనిటీలు",
|
||||
"blur_media": "NSFW/18+ గా గుర్తించిన మీడియాను బ్లర్ చేయండి",
|
||||
"nsfw_content": "NSFW కంటెంట్",
|
||||
"nsfw_communities": "NSFW కమ్యూనిటీల",
|
||||
"hide_adult": "\"వయస్సు\" గా ట్యాగ్ చేసిన సమాజాలను దాచండి",
|
||||
"hide_gore": "\"గోర్\" గా ట్యాగ్ చేసిన సమాజాలను దాచండి",
|
||||
"hide_anti": "\"ఎంటీ\" గా ట్యాగ్ చేసిన సమాజాలను దాచండి",
|
||||
"filters": "ఫిల్టర్లు",
|
||||
"see_nsfw": "NSFW చూడటానికి క్లిక్ చేయండి",
|
||||
"see_nsfw_spoiler": "NSFW స్పోయిలర్ చూడటానికి క్లిక్ చేయండి",
|
||||
"always_show_nsfw": "ఎల్లప్పుడూ NSFW మీడియాను చూపాలా?",
|
||||
"always_show_nsfw_notice": "సరే, మేము మీ ఇష్టాలను ఎల్లప్పుడూ NSFW మీడియా చూపించడానికి మార్చాము.",
|
||||
"content_options": "కంటెంట్ ఎంపికలు",
|
||||
"hide_vulgar": "\"వుల్గర్\" గా ట్యాగ్ చేసిన సమాజాలను దాచండి",
|
||||
"over_18": "18 సంవత్సరాలు పైగా?",
|
||||
"must_be_over_18": "ఈ సమాజాన్ని చూడటానికి మీరు 18+ అవ్వాలి",
|
||||
"must_be_over_18_explanation": "ఈ కంటెంట్ను చూడడానికి మీరు కనీసం పద్దెనిమిది సంవత్సరాలు వయస్సు ఉన్నట్లయితే కావాలి. మీరు పద్దెనిమిది సంవత్సరాలు పైగా ఉన్నారా మరియు వయస్సు ఆధారిత కంటెంట్ చూడడానికి సిద్ధంగా ఉన్నారా?",
|
||||
"no_thank_you": "లేదు, ధన్యవాదాలు",
|
||||
"continue": "కొనసాగించండి",
|
||||
"download_latest_android": "తాజా Android వెర్షన్ డౌన్లోడ్ చేసుకోండి?",
|
||||
"submitter": "సమర్పకుడు"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "ชื่อเรื่องสั้นๆ สำหรับชุมชนของคุณ",
|
||||
"anti_spam_challenges": "ความท้าทายต่อต้านสแปม",
|
||||
"anti_spam_challenges_subtitle": "เลือกความท้าทายหนึ่งหรือหลายรายการเพื่อป้องกันสแปม",
|
||||
"add_a_challenge": "เพิ่มความท้าทาย"
|
||||
"add_a_challenge": "เพิ่มความท้าทาย",
|
||||
"communities_you_moderate": "ชุมชนที่คุณเป็นผู้ดูแล",
|
||||
"blur_media": "เบลอเนื้อหาที่ถูกทำเครื่องหมายว่า NSFW/18+",
|
||||
"nsfw_content": "เนื้อหา NSFW",
|
||||
"nsfw_communities": "ชุมชน NSFW",
|
||||
"hide_adult": "ซ่อนชุมชนที่ถูกแท็กว่า \"ผู้ใหญ่\"",
|
||||
"hide_gore": "ซ่อนชุมชนที่ถูกแท็กว่า \"กอร์\"",
|
||||
"hide_anti": "ซ่อนชุมชนที่ถูกแท็กว่า \"ต่อต้าน\"",
|
||||
"filters": "ตัวกรอง",
|
||||
"see_nsfw": "คลิกเพื่อดู NSFW",
|
||||
"see_nsfw_spoiler": "คลิกเพื่อดู NSFW สปอยเลอร์",
|
||||
"always_show_nsfw": "คุณต้องการแสดงสื่อ NSFW ตลอดเวลาหรือไม่?",
|
||||
"always_show_nsfw_notice": "ตกลง, เราเปลี่ยนการตั้งค่าของคุณเพื่อแสดงสื่อ NSFW ตลอดเวลา",
|
||||
"content_options": "ตัวเลือกเนื้อหา",
|
||||
"hide_vulgar": "ซ่อนชุมชนที่ถูกแท็กว่า \"หยาบคาย\"",
|
||||
"over_18": "เกิน 18?",
|
||||
"must_be_over_18": "คุณต้องอายุ 18 ปีขึ้นไปเพื่อดูชุมชนนี้",
|
||||
"must_be_over_18_explanation": "คุณต้องมีอายุอย่างน้อย 18 ปีเพื่อดูเนื้อหานี้ คุณอายุเกิน 18 ปีและพร้อมที่จะดูเนื้อหาผู้ใหญ่หรือไม่?",
|
||||
"no_thank_you": "ไม่ ขอบคุณ",
|
||||
"continue": "ดำเนินการต่อ",
|
||||
"download_latest_android": "ดาวน์โหลดเวอร์ชันล่าสุดของ Android?",
|
||||
"submitter": "ผู้ส่ง"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Topluluğunuz için kısa bir başlık",
|
||||
"anti_spam_challenges": "Anti-spam zorlukları",
|
||||
"anti_spam_challenges_subtitle": "Spam önlemek için bir veya daha fazla zorluk seçin",
|
||||
"add_a_challenge": "Bir zorluk ekle"
|
||||
"add_a_challenge": "Bir zorluk ekle",
|
||||
"communities_you_moderate": "Moderatörlük yaptığınız topluluklar",
|
||||
"blur_media": "NSFW/18+ olarak işaretlenmiş medyayı bulanıklaştırın",
|
||||
"nsfw_content": "NSFW içeriği",
|
||||
"nsfw_communities": "NSFW toplulukları",
|
||||
"hide_adult": "\"Yetişkin\" olarak etiketlenen toplulukları gizle",
|
||||
"hide_gore": "\"Gore\" olarak etiketlenen toplulukları gizle",
|
||||
"hide_anti": "\"Anti\" olarak etiketlenen toplulukları gizle",
|
||||
"filters": "Filtreler",
|
||||
"see_nsfw": "NSFW görmek için tıklayın",
|
||||
"see_nsfw_spoiler": "NSFW spoiler görmek için tıklayın",
|
||||
"always_show_nsfw": "Her zaman NSFW medyasını göstermek ister misiniz?",
|
||||
"always_show_nsfw_notice": "Tamam, tercihlerinizi her zaman NSFW medyasını gösterecek şekilde değiştirdik.",
|
||||
"content_options": "İçerik seçenekleri",
|
||||
"hide_vulgar": "\"Vulgar\" olarak etiketlenen toplulukları gizle",
|
||||
"over_18": "18 yaş üstü?",
|
||||
"must_be_over_18": "Bu topluluğu görmek için 18 yaş ve üzeri olmalısınız",
|
||||
"must_be_over_18_explanation": "Bu içeriği görmek için en az on sekiz yaşında olmanız gerekir. On sekiz yaşından büyük müsünüz ve yetişkin içeriği görmeye istekli misiniz?",
|
||||
"no_thank_you": "Hayır, teşekkür ederim",
|
||||
"continue": "Devam et",
|
||||
"download_latest_android": "Son Android sürümünü indir?",
|
||||
"submitter": "Gönderen"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Короткий заголовок для вашої спільноти",
|
||||
"anti_spam_challenges": "Антиспам виклики",
|
||||
"anti_spam_challenges_subtitle": "Виберіть одне або кілька завдань для запобігання спаму",
|
||||
"add_a_challenge": "Додати завдання"
|
||||
"add_a_challenge": "Додати завдання",
|
||||
"communities_you_moderate": "Спільноти, які ви модеруєте",
|
||||
"blur_media": "Розмити медіа, позначені як NSFW/18+",
|
||||
"nsfw_content": "Контент NSFW",
|
||||
"nsfw_communities": "NSFW спільноти",
|
||||
"hide_adult": "Сховати спільноти, позначені як \"дорослі\"",
|
||||
"hide_gore": "Сховати спільноти, позначені як \"горе\"",
|
||||
"hide_anti": "Сховати спільноти, позначені як \"анти\"",
|
||||
"filters": "Фільтри",
|
||||
"see_nsfw": "Натисніть, щоб побачити NSFW",
|
||||
"see_nsfw_spoiler": "Натисніть, щоб побачити NSFW спойлер",
|
||||
"always_show_nsfw": "Чи хочете ви завжди показувати медіа NSFW?",
|
||||
"always_show_nsfw_notice": "Добре, ми змінили ваші налаштування, щоб завжди показувати медіа NSFW.",
|
||||
"content_options": "Параметри контенту",
|
||||
"hide_vulgar": "Сховати спільноти, позначені як \"вульгарні\"",
|
||||
"over_18": "Понад 18?",
|
||||
"must_be_over_18": "Ви повинні бути старше 18 років, щоб переглядати це співтовариство",
|
||||
"must_be_over_18_explanation": "Ви повинні бути принаймні вісімнадцяти років, щоб переглядати цей контент. Вам більше вісімнадцяти років, і ви готові переглядати контент для дорослих?",
|
||||
"no_thank_you": "Ні, дякую",
|
||||
"continue": "Продовжити",
|
||||
"download_latest_android": "Завантажити останню версію Android?",
|
||||
"submitter": "Відправник"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "آپ کی کمیونٹی کے لیے ایک مختصر عنوان",
|
||||
"anti_spam_challenges": "اینٹی اسپام چیلنجز",
|
||||
"anti_spam_challenges_subtitle": "اسپام کو روکنے کے لیے ایک یا زیادہ چیلنجز منتخب کریں",
|
||||
"add_a_challenge": "ایک چیلنج شامل کریں"
|
||||
"add_a_challenge": "ایک چیلنج شامل کریں",
|
||||
"communities_you_moderate": "کمیونٹیز جو آپ ماڈریٹ کرتے ہیں",
|
||||
"blur_media": "NSFW/18+ کے طور پر نشان زد میڈیا کو دھندلا کریں",
|
||||
"nsfw_content": "NSFW مواد",
|
||||
"nsfw_communities": "NSFW کمیونٹیز",
|
||||
"hide_adult": "\"بالغ\" کے طور پر ٹیگ کی گئی کمیونٹیز کو چھپائیں",
|
||||
"hide_gore": "\"گور\" کے طور پر ٹیگ کی گئی کمیونٹیز کو چھپائیں",
|
||||
"hide_anti": "\"اینٹی\" کے طور پر ٹیگ کی گئی کمیونٹیز کو چھپائیں",
|
||||
"filters": "فلٹرز",
|
||||
"see_nsfw": "NSFW دیکھنے کے لیے کلک کریں",
|
||||
"see_nsfw_spoiler": "NSFW سپوائلر دیکھنے کے لیے کلک کریں",
|
||||
"always_show_nsfw": "کیا آپ ہمیشہ NSFW میڈیا دکھانا چاہتے ہیں؟",
|
||||
"always_show_nsfw_notice": "اوکے، ہم نے آپ کی ترجیحات ہمیشہ کے لئے NSFW میڈیا دکھانے کے لئے تبدیل کر دی ہیں۔",
|
||||
"content_options": "مواد کے اختیارات",
|
||||
"hide_vulgar": "\"ولگر\" کے طور پر ٹیگ کی گئی کمیونٹیز کو چھپائیں",
|
||||
"over_18": "18 سال سے اوپر؟",
|
||||
"must_be_over_18": "اس کمیونٹی کو دیکھنے کے لیے آپ کو 18+ ہونا ضروری ہے",
|
||||
"must_be_over_18_explanation": "اس مواد کو دیکھنے کے لیے آپ کو کم از کم اٹھارہ سال کا ہونا ضروری ہے۔ کیا آپ اٹھارہ سال سے اوپر ہیں اور بالغ مواد دیکھنے کے لیے تیار ہیں؟",
|
||||
"no_thank_you": "نہیں، شکریہ",
|
||||
"continue": "جاری رکھیں",
|
||||
"download_latest_android": "آخری Android ورژن ڈاؤن لوڈ کریں؟",
|
||||
"submitter": "جمع کرانے والا"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "Một tiêu đề ngắn cho cộng đồng của bạn",
|
||||
"anti_spam_challenges": "Thử thách chống spam",
|
||||
"anti_spam_challenges_subtitle": "Chọn một hoặc nhiều thử thách để ngừng spam",
|
||||
"add_a_challenge": "Thêm một thử thách"
|
||||
"add_a_challenge": "Thêm một thử thách",
|
||||
"communities_you_moderate": "Cộng đồng bạn quản lý",
|
||||
"blur_media": "Mờ phương tiện được đánh dấu là NSFW/18+",
|
||||
"nsfw_content": "Nội dung NSFW",
|
||||
"nsfw_communities": "Cộng đồng NSFW",
|
||||
"hide_adult": "Ẩn cộng đồng được gắn thẻ là \"người lớn\"",
|
||||
"hide_gore": "Ẩn cộng đồng được gắn thẻ là \"gore\"",
|
||||
"hide_anti": "Ẩn cộng đồng được gắn thẻ là \"anti\"",
|
||||
"filters": "Bộ lọc",
|
||||
"see_nsfw": "Nhấp để xem NSFW",
|
||||
"see_nsfw_spoiler": "Nhấp để xem NSFW spoiler",
|
||||
"always_show_nsfw": "Luôn hiển thị media NSFW?",
|
||||
"always_show_nsfw_notice": "Được rồi, chúng tôi đã thay đổi sở thích của bạn để luôn hiển thị media NSFW.",
|
||||
"content_options": "Tùy chọn nội dung",
|
||||
"hide_vulgar": "Ẩn cộng đồng được gắn thẻ là \"vulgar\"",
|
||||
"over_18": "Trên 18?",
|
||||
"must_be_over_18": "Bạn phải trên 18 tuổi để xem cộng đồng này",
|
||||
"must_be_over_18_explanation": "Bạn phải ít nhất mười tám tuổi để xem nội dung này. Bạn có trên mười tám tuổi và sẵn sàng xem nội dung người lớn không?",
|
||||
"no_thank_you": "Không, cảm ơn",
|
||||
"continue": "Tiếp tục",
|
||||
"download_latest_android": "Tải phiên bản Android mới nhất?",
|
||||
"submitter": "Người gửi"
|
||||
}
|
||||
@@ -330,5 +330,26 @@
|
||||
"a_short_title": "为您的社区提供一个简短的标题",
|
||||
"anti_spam_challenges": "反垃圾邮件挑战",
|
||||
"anti_spam_challenges_subtitle": "选择一个或多个挑战来防止垃圾邮件",
|
||||
"add_a_challenge": "添加一个挑战"
|
||||
"add_a_challenge": "添加一个挑战",
|
||||
"communities_you_moderate": "您管理的社区",
|
||||
"blur_media": "模糊标记为NSFW/18+的媒体",
|
||||
"nsfw_content": "NSFW 内容",
|
||||
"nsfw_communities": "NSFW 社区",
|
||||
"hide_adult": "隐藏标记为“成人”的社区",
|
||||
"hide_gore": "隐藏标记为“gore”的社区",
|
||||
"hide_anti": "隐藏标记为“anti”的社区",
|
||||
"filters": "过滤器",
|
||||
"see_nsfw": "点击查看 NSFW",
|
||||
"see_nsfw_spoiler": "点击查看 NSFW 剧透",
|
||||
"always_show_nsfw": "始终显示NSFW媒体?",
|
||||
"always_show_nsfw_notice": "好的,我们已将您的偏好更改为始终显示NSFW媒体。",
|
||||
"content_options": "内容选项",
|
||||
"hide_vulgar": "隐藏标记为“vulgar”的社区",
|
||||
"over_18": "超过18岁?",
|
||||
"must_be_over_18": "您必须年满18岁才能查看此社区",
|
||||
"must_be_over_18_explanation": "您必须至少年满18岁才能查看此内容。您是否已超过18岁并愿意查看成人内容?",
|
||||
"no_thank_you": "不,谢谢",
|
||||
"continue": "继续",
|
||||
"download_latest_android": "下载最新的安卓版本?",
|
||||
"submitter": "提交者"
|
||||
}
|
||||
11
src/app.tsx
11
src/app.tsx
@@ -3,12 +3,12 @@ import { Outlet, Route, Routes, useLocation, useNavigate } from 'react-router-do
|
||||
import useTheme from './hooks/use-theme';
|
||||
import useValidateRouteParams from './hooks/use-validate-route-params';
|
||||
import styles from './app.module.css';
|
||||
import About from './views/about';
|
||||
import AboutView from './views/about';
|
||||
import All from './views/all';
|
||||
import Author from './views/author';
|
||||
import Home from './views/home';
|
||||
import Inbox from './views/inbox';
|
||||
import AboutView from './views/about';
|
||||
import Mod from './views/mod';
|
||||
import NotFound from './views/not-found';
|
||||
import PendingPost from './views/pending-post';
|
||||
import PostPage from './views/post-page';
|
||||
@@ -84,11 +84,8 @@ const App = () => {
|
||||
<Routes>
|
||||
<Route element={globalLayout}>
|
||||
<Route element={pagesLayout}>
|
||||
<Route path='/about' element={<About />} />
|
||||
<Route path='/submit' element={<SubmitPage />} />
|
||||
<Route path='/about' element={<AboutView />} />
|
||||
|
||||
<Route path='/p/all/about' element={<AboutView />} />
|
||||
<Route path='/submit' element={<SubmitPage />} />
|
||||
|
||||
<Route path='/p/:subplebbitAddress/c/:commentCid' element={<PostPage />} />
|
||||
<Route path='/p/:subplebbitAddress/c/:commentCid?context=3' element={<PostPage />} />
|
||||
@@ -129,6 +126,8 @@ const App = () => {
|
||||
|
||||
<Route path='/p/all/:sortType?/:timeFilterName?' element={<All />} />
|
||||
|
||||
<Route path='/p/mod/:sortType?/:timeFilterName?' element={<Mod />} />
|
||||
|
||||
<Route path='/p/:subplebbitAddress/:sortType?/:timeFilterName?' element={<Subplebbit />} />
|
||||
|
||||
<Route path='/profile/:accountCommentIndex' element={<PendingPost />} />
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
|
||||
.pageName {
|
||||
font-weight: bold;
|
||||
padding-right: 1ex;
|
||||
font-variant: small-caps;
|
||||
font-size: 1.2em;
|
||||
color: var(--text);
|
||||
@@ -92,6 +91,12 @@
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.allOrModPageName {
|
||||
position: absolute;
|
||||
top: 26px;
|
||||
left: 140px;
|
||||
}
|
||||
|
||||
.submitTitle {
|
||||
text-transform: uppercase;
|
||||
font-size: 11px
|
||||
@@ -103,6 +108,18 @@
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
text-transform: lowercase;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.tabMenu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.allOrModPageName {
|
||||
top: 46px;
|
||||
left: 138px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabMenu li {
|
||||
@@ -149,7 +166,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
@media (max-width: 639px) {
|
||||
.tabMenu {
|
||||
order: 1;
|
||||
}
|
||||
@@ -161,6 +178,7 @@
|
||||
.joinButton {
|
||||
order: 3;
|
||||
margin-bottom: 3px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
isHomeAboutView,
|
||||
isHomeView,
|
||||
isInboxView,
|
||||
isModView,
|
||||
isPendingPostView,
|
||||
isPostPageView,
|
||||
isProfileView,
|
||||
@@ -42,6 +43,8 @@ import useTheme from '../../hooks/use-theme';
|
||||
import useWindowWidth from '../../hooks/use-window-width';
|
||||
import styles from './header.module.css';
|
||||
import SubscribeButton from '../subscribe-button';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
|
||||
const AboutButton = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -79,6 +82,7 @@ const SortItems = () => {
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const sortLabels = [t('hot'), t('new'), t('active'), t('controversial'), t('top')];
|
||||
const [selectedSortType, setSelectedSortType] = useState(params.sortType || '/hot');
|
||||
@@ -95,7 +99,7 @@ const SortItems = () => {
|
||||
}, [params.sortType, isInHomeAboutView, isInSubplebbitAboutView]);
|
||||
|
||||
return sortTypes.map((sortType, index) => {
|
||||
let sortLink = isInSubplebbitView ? `/p/${params.subplebbitAddress}/${sortType}` : isInAllView ? `p/all/${sortType}` : sortType;
|
||||
let sortLink = isInSubplebbitView ? `/p/${params.subplebbitAddress}/${sortType}` : isInAllView ? `p/all/${sortType}` : isInModView ? `p/mod/${sortType}` : sortType;
|
||||
if (timeFilterName) {
|
||||
sortLink = sortLink + `/${timeFilterName}`;
|
||||
}
|
||||
@@ -242,6 +246,7 @@ const HeaderTabs = () => {
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInInboxView = isInboxView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
@@ -255,7 +260,7 @@ const HeaderTabs = () => {
|
||||
|
||||
if (isInPostPageView) {
|
||||
return <CommentsButton />;
|
||||
} else if (isInHomeView || isInHomeAboutView || (isInSubplebbitView && !isInSubplebbitSubmitView && !isInSubplebbitSettingsView) || isInAllView) {
|
||||
} else if (isInHomeView || isInHomeAboutView || (isInSubplebbitView && !isInSubplebbitSubmitView && !isInSubplebbitSettingsView) || isInAllView || isInModView) {
|
||||
return <SortItems />;
|
||||
} else if ((isInProfileView || isInAuthorView) && !isInPendingPostView) {
|
||||
return <AuthorHeaderTabs />;
|
||||
@@ -279,6 +284,7 @@ const HeaderTitle = ({ title, shortAddress }: { title: string; shortAddress: str
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInAuthorView = isAuthorView(location.pathname);
|
||||
const isInInboxView = isInboxView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
const isInSettingsView = isSettingsView(location.pathname);
|
||||
@@ -291,12 +297,24 @@ const HeaderTitle = ({ title, shortAddress }: { title: string; shortAddress: str
|
||||
const isInCreateSubplebbitView = isCreateSubplebbitView(location.pathname);
|
||||
const isInNotFoundView = useNotFoundStore((state) => state.isNotFound);
|
||||
|
||||
const subplebbitTitle = <Link to={`/p/${params.subplebbitAddress}`}>{title || shortAddress}</Link>;
|
||||
const subplebbitAddress = params.subplebbitAddress;
|
||||
|
||||
const contentOptionsStore = useContentOptionsStore();
|
||||
const hasUnhiddenAnyNsfwCommunity =
|
||||
!contentOptionsStore.hideAdultCommunities ||
|
||||
!contentOptionsStore.hideGoreCommunities ||
|
||||
!contentOptionsStore.hideAntiCommunities ||
|
||||
!contentOptionsStore.hideVulgarCommunities;
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
const subplebbitTitle = <Link to={`/p/${subplebbitAddress}`}>{title || shortAddress}</Link>;
|
||||
const submitTitle = <span className={styles.submitTitle}>{t('submit')}</span>;
|
||||
const profileTitle = <Link to='/profile'>{account?.author?.shortAddress}</Link>;
|
||||
const authorTitle = <Link to={`/u/${params.authorAddress}/c/${params.commentCid}`}>{params.authorAddress && Plebbit.getShortAddress(params.authorAddress)}</Link>;
|
||||
|
||||
if (isInSubplebbitSubmitView) {
|
||||
if (isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) {
|
||||
return <span>{t('over_18')}</span>;
|
||||
} else if (isInSubplebbitSubmitView) {
|
||||
return (
|
||||
<>
|
||||
{subplebbitTitle}: {submitTitle}
|
||||
@@ -328,6 +346,8 @@ const HeaderTitle = ({ title, shortAddress }: { title: string; shortAddress: str
|
||||
return <span className={styles.lowercase}>{t('page_not_found')}</span>;
|
||||
} else if (isInAllView) {
|
||||
return t('all');
|
||||
} else if (isInModView) {
|
||||
return <span className={styles.lowercase}>{t('communities_you_moderate')}</span>;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -346,6 +366,7 @@ const Header = () => {
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInInboxView = isInboxView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
const isInSettingsView = isSettingsView(location.pathname);
|
||||
@@ -364,10 +385,22 @@ const Header = () => {
|
||||
(isInSubplebbitView && !isInSubplebbitSubmitView && !isInSubplebbitSettingsView && !isInPostPageView && !isInHomeAboutView && !isInSubplebbitAboutView) ||
|
||||
(isInProfileView && !isInHomeAboutView) ||
|
||||
(isInAllView && !isInAllAboutView) ||
|
||||
(isInModView && !isInHomeAboutView) ||
|
||||
(isInAuthorView && !isInHomeAboutView);
|
||||
const logoSrc = isInSubplebbitView && suggested?.avatarUrl ? suggested?.avatarUrl : 'assets/logo/seedit.png';
|
||||
const logoIsAvatar = isInSubplebbitView && suggested?.avatarUrl;
|
||||
const logoLink = isInSubplebbitView ? `/p/${params.subplebbitAddress}` : isInProfileView ? '/profile' : '/';
|
||||
|
||||
const subplebbitAddress = params.subplebbitAddress;
|
||||
|
||||
const contentOptionsStore = useContentOptionsStore();
|
||||
const hasUnhiddenAnyNsfwCommunity =
|
||||
!contentOptionsStore.hideAdultCommunities ||
|
||||
!contentOptionsStore.hideGoreCommunities ||
|
||||
!contentOptionsStore.hideAntiCommunities ||
|
||||
!contentOptionsStore.hideVulgarCommunities;
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
const logoIsAvatar = isInSubplebbitView && suggested?.avatarUrl && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity);
|
||||
const logoSrc = logoIsAvatar ? suggested?.avatarUrl : 'assets/logo/seedit.png';
|
||||
const logoLink = isInSubplebbitView ? `/p/${subplebbitAddress}` : isInProfileView ? '/profile' : '/';
|
||||
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
@@ -378,35 +411,40 @@ const Header = () => {
|
||||
>
|
||||
<div className={styles.logoContainer}>
|
||||
<Link to={logoLink} className={styles.logoLink}>
|
||||
{(logoIsAvatar || (!isInSubplebbitView && !isInProfileView && !isInAuthorView) || (isInSubplebbitView && !suggested?.avatarUrl)) && (
|
||||
{(logoIsAvatar || (!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
<img className={`${logoIsAvatar ? styles.avatar : styles.logo}`} src={logoSrc} alt='' />
|
||||
)}
|
||||
{((!isInSubplebbitView && !isInProfileView && !isInAuthorView) || (isInSubplebbitView && !suggested?.avatarUrl)) && (
|
||||
{((!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
<img src={`assets/logo/seedit-text-${theme === 'dark' ? 'dark' : 'light'}.svg`} className={styles.logoText} alt='' />
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
{!isInHomeView && !isInHomeAboutView && (
|
||||
{!isInHomeView && !isInHomeAboutView && !isInModView && !isInAllView && (
|
||||
<span className={`${styles.pageName} ${!logoIsAvatar && styles.soloPageName}`}>
|
||||
<HeaderTitle title={title} shortAddress={shortAddress} />
|
||||
</span>
|
||||
)}
|
||||
{isInSubplebbitView && !isInSubplebbitSubmitView && (
|
||||
{(isInModView || isInAllView) && (
|
||||
<div className={`${styles.pageName} ${styles.allOrModPageName}`}>
|
||||
<HeaderTitle title={title} shortAddress={shortAddress} />
|
||||
</div>
|
||||
)}
|
||||
{isInSubplebbitView && !isInSubplebbitSubmitView && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) && (
|
||||
<span className={styles.joinButton}>
|
||||
<SubscribeButton address={params.subplebbitAddress} />
|
||||
</span>
|
||||
)}
|
||||
{!isMobile && (
|
||||
{!isMobile && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) && (
|
||||
<ul className={styles.tabMenu}>
|
||||
<HeaderTabs />
|
||||
{(isInHomeView || isInHomeAboutView) && <AboutButton />}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
{isMobile && !isInSubplebbitSubmitView && (
|
||||
{isMobile && !isInSubplebbitSubmitView && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) && (
|
||||
<ul className={`${styles.tabMenu} ${isInProfileView ? styles.horizontalScroll : ''}`}>
|
||||
<HeaderTabs />
|
||||
{(isInHomeView || isInHomeAboutView || isInSubplebbitView || isInHomeAboutView || isInAllView || isInPostPageView) && <AboutButton />}
|
||||
{(isInHomeView || isInHomeAboutView || isInSubplebbitView || isInHomeAboutView || isInPostPageView) && <AboutButton />}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,7 @@ interface CommentToolsProps {
|
||||
isCommentAuthorMod?: boolean;
|
||||
isReply?: boolean;
|
||||
isSingleReply?: boolean;
|
||||
nsfw?: boolean;
|
||||
parentCid?: string;
|
||||
postCid?: string;
|
||||
removed?: boolean;
|
||||
@@ -215,7 +216,7 @@ const SingleReplyTools = ({
|
||||
);
|
||||
};
|
||||
|
||||
const CommentToolsLabel = ({ cid, deleted, failed, editState, isReply, removed, spoiler }: CommentToolsProps) => {
|
||||
const CommentToolsLabel = ({ cid, deleted, failed, editState, isReply, nsfw, removed, spoiler }: CommentToolsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const pending = cid === undefined && !isReply && !failed;
|
||||
const failedEdit = editState === 'failed';
|
||||
@@ -223,6 +224,7 @@ const CommentToolsLabel = ({ cid, deleted, failed, editState, isReply, removed,
|
||||
|
||||
return (
|
||||
<>
|
||||
{nsfw && <Label color='nsfw-red' text={t('nsfw')} />}
|
||||
{spoiler && <Label color='black' text={t('spoiler')} />}
|
||||
{pending && <Label color='yellow' text={t('pending')} />}
|
||||
{failed && <Label color='red' text={t('failed')} />}
|
||||
@@ -244,6 +246,7 @@ const CommentTools = ({
|
||||
index,
|
||||
isReply,
|
||||
isSingleReply,
|
||||
nsfw,
|
||||
parentCid,
|
||||
postCid,
|
||||
removed,
|
||||
@@ -305,6 +308,7 @@ const CommentTools = ({
|
||||
failed={failed}
|
||||
editState={editState}
|
||||
isReply={isReply}
|
||||
nsfw={nsfw}
|
||||
removed={removed}
|
||||
spoiler={spoiler}
|
||||
subplebbitAddress={subplebbitAddress}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
.expando {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
padding-right: 0;
|
||||
padding-top: 5px;
|
||||
clear: left;
|
||||
position: relative;
|
||||
}
|
||||
@@ -17,19 +16,6 @@
|
||||
.usertext {
|
||||
unicode-bidi: isolate;
|
||||
font-size: small;
|
||||
width: 862px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.usertext {
|
||||
width: calc(100vw - 335px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.usertext {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown {
|
||||
@@ -59,13 +45,16 @@
|
||||
|
||||
.mediaPreview {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.mediaPreview img,
|
||||
.mediaPreview video,
|
||||
.mediaPreview iframe {
|
||||
max-width: calc(100vw - 335px) !important;
|
||||
max-width: calc(100vw - 435px) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,3 +125,103 @@
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.blurContent {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(40px);
|
||||
}
|
||||
|
||||
.unblurButton {
|
||||
color: white;
|
||||
position: absolute;
|
||||
font-size: 13px;
|
||||
z-index: 1;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
cursor: pointer;
|
||||
border: 1px solid #ffffff;
|
||||
padding: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwButton {
|
||||
color: white;
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
z-index: 1;
|
||||
top: calc(50% + 45px);
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwButton:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwNotice {
|
||||
background: #fafaf8;
|
||||
border: 1px solid #e5e3da;
|
||||
clear: left;
|
||||
margin-top: 5px;
|
||||
padding: 5px 10px;
|
||||
position: relative;
|
||||
unicode-bidi: isolate;
|
||||
font-size: small;
|
||||
margin-bottom: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwNotice p {
|
||||
color: #222222;
|
||||
font-weight: 400;
|
||||
word-wrap: break-word;
|
||||
line-height: 15px;
|
||||
margin: 5px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwNotice button {
|
||||
background-color: #4f86b5;
|
||||
color: #ffffff;
|
||||
margin-bottom: 0;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
padding: 4px 12px 3px;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
border-radius: 3px;
|
||||
margin-left: auto;
|
||||
display: block;
|
||||
border-bottom: 2px solid #4270a2;
|
||||
}
|
||||
|
||||
.alwaysShowNsfwNotice button:hover {
|
||||
background-color: #4980ae;
|
||||
}
|
||||
|
||||
@media (max-width: 770px) {
|
||||
.mediaPreview {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.expando {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import useContentOptionsStore from '../../../stores/use-content-options-store';
|
||||
import { useIsNsfwSubplebbit } from '../../../hooks/use-is-nsfw-subplebbit';
|
||||
import styles from './expando.module.css';
|
||||
import Embed from '../embed';
|
||||
import { CommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import Markdown from '../../markdown';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface ExpandoProps {
|
||||
authorEditReason?: string;
|
||||
@@ -14,6 +16,7 @@ interface ExpandoProps {
|
||||
expanded: boolean;
|
||||
link?: string;
|
||||
modEditReason?: string;
|
||||
nsfw?: boolean;
|
||||
removed?: boolean;
|
||||
showContent: boolean;
|
||||
spoiler?: boolean;
|
||||
@@ -28,14 +31,28 @@ const Expando = ({
|
||||
expanded,
|
||||
link,
|
||||
modEditReason,
|
||||
nsfw,
|
||||
removed,
|
||||
showContent,
|
||||
spoiler = false,
|
||||
toggleExpanded,
|
||||
}: ExpandoProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { blurNsfwThumbnails, setBlurNsfwThumbnails } = useContentOptionsStore();
|
||||
const [hideContent, setHideContent] = useState(blurNsfwThumbnails);
|
||||
const [alwaysShowNsfw, setAlwaysShowNsfw] = useState(false);
|
||||
|
||||
const [showSpoiler, setShowSpoiler] = useState(false);
|
||||
useEffect(() => {
|
||||
if (!expanded) {
|
||||
setHideContent(true);
|
||||
}
|
||||
}, [expanded]);
|
||||
|
||||
const handleAlwaysShowNsfw = () => {
|
||||
setBlurNsfwThumbnails(false);
|
||||
setHideContent(false);
|
||||
setAlwaysShowNsfw(true);
|
||||
};
|
||||
|
||||
let mediaComponent = null;
|
||||
|
||||
@@ -51,53 +68,62 @@ const Expando = ({
|
||||
mediaComponent = <Embed url={commentMediaInfo.url} />;
|
||||
}
|
||||
|
||||
const pageSubplebbitAddress = useParams().subplebbitAddress;
|
||||
const isNsfwSubplebbit = useIsNsfwSubplebbit(pageSubplebbitAddress || '');
|
||||
|
||||
return (
|
||||
<div className={expanded ? styles.expando : styles.expandoHidden}>
|
||||
<div
|
||||
className={styles.expandoContent}
|
||||
onClick={() => {
|
||||
spoiler && !showSpoiler && setShowSpoiler(true);
|
||||
}}
|
||||
>
|
||||
{spoiler && !showSpoiler && !(deleted || removed) && (
|
||||
<>
|
||||
<div className={styles.hideSpoiler} />
|
||||
<span className={styles.showSpoilerButton}>{t('view_spoiler')}</span>
|
||||
</>
|
||||
)}
|
||||
{link && !removed && commentMediaInfo?.type !== 'webpage' && (
|
||||
<div className={styles.mediaPreview}>
|
||||
<Link
|
||||
to={link}
|
||||
onClick={(e) => {
|
||||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
toggleExpanded && toggleExpanded();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{mediaComponent}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{content && showContent && (
|
||||
<div className={styles.usertext}>
|
||||
<div className={styles.markdown}>
|
||||
<Markdown content={content} />
|
||||
{modEditReason && (
|
||||
<p>
|
||||
{t('mod_reason')}: {modEditReason}
|
||||
</p>
|
||||
{link && !removed && commentMediaInfo?.type !== 'webpage' && (
|
||||
<div className={styles.mediaPreview} onClick={() => setHideContent(false)}>
|
||||
{((nsfw && blurNsfwThumbnails && !isNsfwSubplebbit) || spoiler) && hideContent && link && commentMediaInfo?.type !== 'webpage' && !(deleted || removed) && (
|
||||
<>
|
||||
<div className={styles.blurContent} />
|
||||
<span className={styles.unblurButton}>{nsfw && spoiler ? t('see_nsfw_spoiler') : spoiler ? t('view_spoiler') : nsfw ? t('see_nsfw') : ''}</span>
|
||||
{nsfw && (
|
||||
<span className={styles.alwaysShowNsfwButton} onClick={handleAlwaysShowNsfw}>
|
||||
{t('always_show_nsfw')}
|
||||
</span>
|
||||
)}
|
||||
{authorEditReason && !(removed || deleted) && (
|
||||
<p>
|
||||
{t('edit')}: {authorEditReason}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Link
|
||||
to={link}
|
||||
onClick={(e) => {
|
||||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
toggleExpanded && toggleExpanded();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{mediaComponent}
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{alwaysShowNsfw && (
|
||||
<div className={styles.alwaysShowNsfwContainer}>
|
||||
<div className={styles.alwaysShowNsfwNotice}>
|
||||
<p>{t('always_show_nsfw_notice')}</p>
|
||||
<button onClick={() => setAlwaysShowNsfw(false)}>{t('undo')}</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{content && showContent && (
|
||||
<div className={styles.usertext}>
|
||||
<div className={styles.markdown}>
|
||||
<Markdown content={content} />
|
||||
{modEditReason && (
|
||||
<p>
|
||||
{t('mod_reason')}: {modEditReason}
|
||||
</p>
|
||||
)}
|
||||
{authorEditReason && !(removed || deleted) && (
|
||||
<p>
|
||||
{t('edit')}: {authorEditReason}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
padding: 0 4px;
|
||||
margin: 0 2px 2px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.label {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.black {
|
||||
color: var(--text);
|
||||
border-color: currentColor;
|
||||
@@ -27,4 +30,9 @@
|
||||
.green {
|
||||
color: var(--green);
|
||||
border-color: var(--green);
|
||||
}
|
||||
}
|
||||
|
||||
.nsfw-red {
|
||||
color: var(--red-nsfw);
|
||||
border-color: var(--red-nsfw);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@ interface LabelProps {
|
||||
const Label = ({ color, text }: LabelProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return <span className={`${styles.stamp} ${styles[color]}`}>{t(text)}</span>;
|
||||
return (
|
||||
<span className={styles.label}>
|
||||
<span className={`${styles.stamp} ${styles[color]}`}>{t(text)}</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default Label;
|
||||
|
||||
@@ -3,7 +3,7 @@ import styles from './post.module.css';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { Comment, useAuthorAddress, useBlock, useComment, useEditedComment, useSubplebbit, useSubscribe } from '@plebbit/plebbit-react-hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isAllView, isHomeView, isPostPageView, isProfileHiddenView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
import { isAllView, isPostPageView, isProfileHiddenView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
import { getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import { getPostScore, formatScore } from '../../lib/utils/post-utils';
|
||||
import { getHostname } from '../../lib/utils/url-utils';
|
||||
@@ -20,6 +20,8 @@ import useUpvote from '../../hooks/use-upvote';
|
||||
import _ from 'lodash';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import { usePinnedPostsStore } from '../../stores/use-pinned-posts-store';
|
||||
import useWindowWidth from '../../hooks/use-window-width';
|
||||
import { useIsNsfwSubplebbit } from '../../hooks/use-is-nsfw-subplebbit';
|
||||
|
||||
interface PostAuthorProps {
|
||||
authorAddress: string;
|
||||
@@ -106,6 +108,11 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
title,
|
||||
upvoteCount,
|
||||
} = post || {};
|
||||
|
||||
// Check if the subplebbit is NSFW based on its tags
|
||||
const isNsfwSubplebbit = useIsNsfwSubplebbit(subplebbitAddress);
|
||||
const nsfw = post?.nsfw || isNsfwSubplebbit;
|
||||
|
||||
const { displayName, shortAddress } = author || {};
|
||||
const { shortAuthorAddress, authorAddressChanged } = useAuthorAddress({ comment: post });
|
||||
|
||||
@@ -121,7 +128,6 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInProfileHiddenView = isProfileHiddenView(location.pathname);
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
|
||||
const commentMediaInfo = useCommentMediaInfo(post);
|
||||
@@ -160,9 +166,10 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
};
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const windowWidth = useWindowWidth();
|
||||
const pinnedPostsCount = usePinnedPostsStore((state) => state.pinnedPostsCount);
|
||||
let rank = (index ?? 0) + 1;
|
||||
if (!isInHomeView) {
|
||||
if (isInSubplebbitView) {
|
||||
rank = rank - pinnedPostsCount;
|
||||
}
|
||||
|
||||
@@ -177,7 +184,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
</div>
|
||||
<div className={`${styles.container} ${blocked && !isInProfileHiddenView ? styles.hidden : styles.visible}`}>
|
||||
<div className={styles.row}>
|
||||
{!isMobile && <div className={styles.rank}>{pinned ? undefined : rank}</div>}
|
||||
{!isMobile && !isInPostPageView && <div className={styles.rank}>{pinned ? undefined : rank}</div>}
|
||||
<div className={styles.leftcol}>
|
||||
<div className={styles.midcol}>
|
||||
<div className={styles.arrowWrapper}>
|
||||
@@ -194,8 +201,9 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
isReply={false}
|
||||
isLink={!hasThumbnail && link}
|
||||
isNsfw={nsfw}
|
||||
isSpoiler={spoiler}
|
||||
isText={!hasThumbnail && content?.trim().length > 0}
|
||||
isText={!hasThumbnail && !link}
|
||||
link={link}
|
||||
linkHeight={linkHeight}
|
||||
linkWidth={linkWidth}
|
||||
@@ -231,16 +239,17 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
{(!(commentMediaInfo?.type === 'webpage') || (commentMediaInfo?.type === 'webpage' && content?.trim().length > 0)) && (
|
||||
<ExpandButton
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
content={content}
|
||||
expanded={isExpanded}
|
||||
hasThumbnail={hasThumbnail}
|
||||
link={link}
|
||||
toggleExpanded={toggleExpanded}
|
||||
/>
|
||||
)}
|
||||
{(!(commentMediaInfo?.type === 'webpage') || (commentMediaInfo?.type === 'webpage' && content?.trim().length > 0)) &&
|
||||
!(isInPostPageView && !link && content?.trim().length > 0) && (
|
||||
<ExpandButton
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
content={content}
|
||||
expanded={isExpanded}
|
||||
hasThumbnail={hasThumbnail}
|
||||
link={link}
|
||||
toggleExpanded={toggleExpanded}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.tagline}>
|
||||
{t('submitted')} <span title={postDate}>{getFormattedTimeAgo(timestamp)}</span>{' '}
|
||||
{edit && isInPostPageView && <span className={styles.timeEdit}>{t('last_edited', { timestamp: getFormattedTimeAgo(edit.timestamp) })}</span>}{' '}
|
||||
@@ -285,6 +294,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
failed={state === 'failed'}
|
||||
editState={editState}
|
||||
index={post?.index}
|
||||
nsfw={nsfw}
|
||||
removed={removed}
|
||||
replyCount={replyCount}
|
||||
showCommentEditForm={showCommentEditForm}
|
||||
@@ -292,23 +302,49 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
subplebbitAddress={subplebbitAddress}
|
||||
/>
|
||||
</div>
|
||||
{!(windowWidth < 770) && (
|
||||
<>
|
||||
{isEditing ? (
|
||||
<CommentEditForm commentCid={cid} hideCommentEditForm={hideCommentEditForm} />
|
||||
) : (
|
||||
<Expando
|
||||
authorEditReason={edit?.reason}
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
content={removed ? `[${_.lowerCase(t('removed'))}]` : deleted ? `[${_.lowerCase(t('deleted'))}]` : content}
|
||||
expanded={isExpanded}
|
||||
link={link}
|
||||
modEditReason={reason}
|
||||
nsfw={nsfw}
|
||||
deleted={deleted}
|
||||
removed={removed}
|
||||
showContent={true}
|
||||
spoiler={spoiler && (content || link)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{isEditing ? (
|
||||
<CommentEditForm commentCid={cid} hideCommentEditForm={hideCommentEditForm} />
|
||||
) : (
|
||||
<Expando
|
||||
authorEditReason={edit?.reason}
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
content={removed ? `[${_.lowerCase(t('removed'))}]` : deleted ? `[${_.lowerCase(t('deleted'))}]` : content}
|
||||
expanded={isExpanded}
|
||||
link={link}
|
||||
modEditReason={reason}
|
||||
deleted={deleted}
|
||||
removed={removed}
|
||||
showContent={true}
|
||||
spoiler={spoiler && (content || link)}
|
||||
/>
|
||||
{windowWidth < 770 && (
|
||||
<>
|
||||
{isEditing ? (
|
||||
<CommentEditForm commentCid={cid} hideCommentEditForm={hideCommentEditForm} />
|
||||
) : (
|
||||
<Expando
|
||||
authorEditReason={edit?.reason}
|
||||
commentMediaInfo={commentMediaInfo}
|
||||
content={removed ? `[${_.lowerCase(t('removed'))}]` : deleted ? `[${_.lowerCase(t('deleted'))}]` : content}
|
||||
expanded={isExpanded}
|
||||
link={link}
|
||||
modEditReason={reason}
|
||||
nsfw={nsfw}
|
||||
deleted={deleted}
|
||||
removed={removed}
|
||||
showContent={true}
|
||||
spoiler={spoiler && (content || link)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,4 +53,8 @@
|
||||
|
||||
.spoilerIcon {
|
||||
background-image: var(--thumbnail-icon-spoiler);
|
||||
}
|
||||
}
|
||||
|
||||
.nsfwIcon {
|
||||
background-image: var(--thumbnail-icon-nsfw);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import styles from './thumbnail.module.css';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { CommentMediaInfo } from '../../../lib/utils/media-utils';
|
||||
import useFetchGifFirstFrame from '../../../hooks/use-fetch-gif-first-frame';
|
||||
import useContentOptionsStore from '../../../stores/use-content-options-store';
|
||||
import { useIsNsfwSubplebbit } from '../../../hooks/use-is-nsfw-subplebbit';
|
||||
|
||||
interface ThumbnailProps {
|
||||
cid?: string;
|
||||
commentMediaInfo?: CommentMediaInfo;
|
||||
expanded?: boolean;
|
||||
isLink: boolean;
|
||||
isNsfw?: boolean;
|
||||
isReply: boolean;
|
||||
isSpoiler?: boolean;
|
||||
isText: boolean;
|
||||
@@ -23,6 +26,7 @@ const Thumbnail = ({
|
||||
commentMediaInfo,
|
||||
expanded = false,
|
||||
isLink = false,
|
||||
isNsfw = false,
|
||||
isReply = false,
|
||||
isSpoiler = false,
|
||||
isText = false,
|
||||
@@ -36,6 +40,10 @@ const Thumbnail = ({
|
||||
let displayWidth, displayHeight, hasLinkDimensions;
|
||||
const thumbnailClass = expanded ? styles.thumbnailHidden : styles.thumbnailVisible;
|
||||
|
||||
const { blurNsfwThumbnails } = useContentOptionsStore();
|
||||
const pageSubplebbitAddress = useParams().subplebbitAddress;
|
||||
const isNsfwSubplebbit = useIsNsfwSubplebbit(pageSubplebbitAddress || '');
|
||||
|
||||
if (linkWidth && linkHeight) {
|
||||
let scale = Math.min(1, 70 / Math.max(linkWidth, linkHeight));
|
||||
displayWidth = `${linkWidth * scale}px`;
|
||||
@@ -47,7 +55,7 @@ const Thumbnail = ({
|
||||
hasLinkDimensions = false;
|
||||
}
|
||||
|
||||
if (isText || isLink || isSpoiler) {
|
||||
if (isText || isLink || isSpoiler || (isNsfw && !isNsfwSubplebbit)) {
|
||||
displayWidth = '50px';
|
||||
displayHeight = '50px';
|
||||
hasLinkDimensions = true;
|
||||
@@ -82,6 +90,10 @@ const Thumbnail = ({
|
||||
mediaComponent = <span className={`${styles.iconThumbnail} ${styles.spoilerIcon}`} />;
|
||||
}
|
||||
|
||||
if (isNsfw && blurNsfwThumbnails && !isNsfwSubplebbit) {
|
||||
mediaComponent = <span className={`${styles.iconThumbnail} ${styles.nsfwIcon}`} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={`${styles.thumbnail} ${thumbnailClass}`} style={style}>
|
||||
<span className={hasLinkDimensions ? styles.transparentThumbnailWrapper : styles.thumbnailWrapper}>
|
||||
|
||||
@@ -369,4 +369,12 @@
|
||||
font-size: x-small;
|
||||
line-height: normal;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.submitter {
|
||||
color: var(--submitter-color);
|
||||
}
|
||||
|
||||
.submitter:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -37,9 +37,25 @@ interface ReplyAuthorProps {
|
||||
isAvatarDefined: boolean;
|
||||
removed: boolean;
|
||||
shortAuthorAddress: string | undefined;
|
||||
submitterAddress: string;
|
||||
subplebbitAddress: string;
|
||||
postCid: string;
|
||||
}
|
||||
|
||||
const ReplyAuthor = ({ address, authorRole, cid, deleted, displayName, imageUrl, isAvatarDefined, removed, shortAuthorAddress }: ReplyAuthorProps) => {
|
||||
const ReplyAuthor = ({
|
||||
address,
|
||||
authorRole,
|
||||
cid,
|
||||
deleted,
|
||||
displayName,
|
||||
imageUrl,
|
||||
isAvatarDefined,
|
||||
removed,
|
||||
shortAuthorAddress,
|
||||
submitterAddress,
|
||||
subplebbitAddress,
|
||||
postCid,
|
||||
}: ReplyAuthorProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { hideAvatars } = useAvatarVisibilityStore();
|
||||
const isAuthorAdmin = authorRole === 'admin';
|
||||
@@ -48,6 +64,8 @@ const ReplyAuthor = ({ address, authorRole, cid, deleted, displayName, imageUrl,
|
||||
const authorRoleInitial = (isAuthorOwner && 'O') || (isAuthorAdmin && 'A') || (isAuthorModerator && 'M') || '';
|
||||
const moderatorClass = `${isAuthorOwner ? styles.owner : isAuthorAdmin ? styles.admin : isAuthorModerator ? styles.moderator : ''}`;
|
||||
const shortDisplayName = displayName?.length > 20 ? displayName?.slice(0, 20) + '...' : displayName;
|
||||
const isAuthorSubmitter = address === submitterAddress;
|
||||
|
||||
return (
|
||||
<>
|
||||
{removed || deleted ? (
|
||||
@@ -60,20 +78,28 @@ const ReplyAuthor = ({ address, authorRole, cid, deleted, displayName, imageUrl,
|
||||
</span>
|
||||
)}
|
||||
{displayName && (
|
||||
<Link to={`/u/${address}/c/${cid}`} className={`${styles.author} ${moderatorClass}`}>
|
||||
<Link to={`/u/${address}/c/${cid}`} className={`${styles.author} ${moderatorClass} ${!moderatorClass && isAuthorSubmitter ? styles.submitter : ''}`}>
|
||||
{shortDisplayName}{' '}
|
||||
</Link>
|
||||
)}
|
||||
<Link to={`/u/${address}/c/${cid}`} className={`${styles.author} ${moderatorClass}`}>
|
||||
<Link to={`/u/${address}/c/${cid}`} className={`${styles.author} ${moderatorClass} ${!moderatorClass && isAuthorSubmitter ? styles.submitter : ''}`}>
|
||||
{displayName ? `u/${shortAuthorAddress}` : shortAuthorAddress}
|
||||
</Link>
|
||||
{authorRole && (
|
||||
{(authorRole || isAuthorSubmitter) && (
|
||||
<span className={styles.moderatorBrackets}>
|
||||
{' '}
|
||||
[
|
||||
<span className={moderatorClass} title={authorRole}>
|
||||
{authorRoleInitial}
|
||||
</span>
|
||||
{isAuthorSubmitter && (
|
||||
<Link to={`/p/${subplebbitAddress}/c/${postCid}`} className={styles.submitter} title={t('submitter')}>
|
||||
S
|
||||
</Link>
|
||||
)}
|
||||
{isAuthorSubmitter && authorRole && ','}
|
||||
{authorRole && (
|
||||
<span className={moderatorClass} title={authorRole}>
|
||||
{authorRoleInitial}
|
||||
</span>
|
||||
)}
|
||||
]
|
||||
</span>
|
||||
)}
|
||||
@@ -348,6 +374,8 @@ const Reply = ({ cidOfReplyWithContext, depth = 0, isSingleComment, isSingleRepl
|
||||
</span>
|
||||
);
|
||||
|
||||
const post = useComment({ commentCid: postCid });
|
||||
|
||||
return (
|
||||
<div className={styles.reply}>
|
||||
{isSingleReply && !isInInboxView && <ParentLink postCid={cid ? postCid : parentOfPendingReply?.postCid} />}
|
||||
@@ -376,6 +404,9 @@ const Reply = ({ cidOfReplyWithContext, depth = 0, isSingleComment, isSingleRepl
|
||||
isAvatarDefined={!!author?.avatar}
|
||||
removed={removed}
|
||||
shortAuthorAddress={shortAuthorAddress}
|
||||
submitterAddress={post?.author?.address}
|
||||
subplebbitAddress={subplebbitAddress}
|
||||
postCid={postCid}
|
||||
/>
|
||||
<span className={styles.score}>{scoreString}</span>{' '}
|
||||
<span className={styles.time}>
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
isAllView,
|
||||
isHomeAboutView,
|
||||
isHomeView,
|
||||
isModView,
|
||||
isPendingPostView,
|
||||
isPostPageView,
|
||||
isSubplebbitAboutView,
|
||||
@@ -220,6 +221,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInSubplebbitsView = isSubplebbitsView(location.pathname);
|
||||
@@ -230,7 +232,11 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
const subplebbitCreator = findSubplebbitCreator(roles);
|
||||
const creatorAddress = subplebbitCreator === 'anonymous' ? 'anonymous' : `${Plebbit.getShortAddress(subplebbitCreator)}`;
|
||||
const submitRoute =
|
||||
isInHomeView || isInHomeAboutView || isInAllView ? '/submit' : isInPendingPostView ? `/p/${pendingPost?.subplebbitAddress}/submit` : `/p/${address}/submit`;
|
||||
isInHomeView || isInHomeAboutView || isInAllView || isInModView
|
||||
? '/submit'
|
||||
: isInPendingPostView
|
||||
? `/p/${pendingPost?.subplebbitAddress}/submit`
|
||||
: `/p/${address}/submit`;
|
||||
|
||||
const { blocked, unblock, block } = useBlock({ address });
|
||||
|
||||
@@ -287,7 +293,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
<div className={styles.nub} />
|
||||
</div>
|
||||
</Link>
|
||||
{!isInHomeView && !isInHomeAboutView && !isInAllView && !isInPendingPostView && !isInSubplebbitsView && !isInHomeAboutView && (
|
||||
{!isInHomeView && !isInHomeAboutView && !isInAllView && !isInModView && !isInPendingPostView && !isInSubplebbitsView && !isInHomeAboutView && (
|
||||
<div className={styles.titleBox}>
|
||||
<Link className={styles.title} to={`/p/${address}`}>
|
||||
{subplebbit?.address}
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
}
|
||||
|
||||
.homeButton {
|
||||
padding-left: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.moreLink {
|
||||
@@ -162,7 +162,7 @@
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.homeButton {
|
||||
padding-left: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAccount } from '@plebbit/plebbit-react-hooks';
|
||||
import { useAccount, useAccountSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import styles from './topbar.module.css';
|
||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import useTimeFilter from '../../hooks/use-time-filter';
|
||||
import { isAllView, isHomeView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
import { isAllView, isHomeView, isModView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
|
||||
const sortTypes = ['hot', 'new', 'active', 'controversialAll', 'topAll'];
|
||||
const isElectron = window.isElectron === true;
|
||||
@@ -20,9 +20,13 @@ const TopBar = () => {
|
||||
const subscriptions = account?.subscriptions;
|
||||
const isinAllView = isAllView(location.pathname);
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const homeButtonClass = isInHomeView ? styles.selected : styles.choice;
|
||||
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
|
||||
const { timeFilterName, timeFilterNames } = useTimeFilter();
|
||||
const selectedTimeFilter = timeFilterName || (isInSubplebbitView ? 'all' : timeFilterName);
|
||||
|
||||
@@ -52,6 +56,8 @@ const TopBar = () => {
|
||||
? `/p/${params.subplebbitAddress}/${selectedSortType}/${timeFilterName}`
|
||||
: isinAllView
|
||||
? `p/all/${selectedSortType}/${timeFilterName}`
|
||||
: isInModView
|
||||
? `/p/mod/${selectedSortType}/${timeFilterName}`
|
||||
: `/${selectedSortType}/${timeFilterName}`;
|
||||
};
|
||||
|
||||
@@ -174,6 +180,14 @@ const TopBar = () => {
|
||||
{t('all')}
|
||||
</Link>
|
||||
</li>
|
||||
{accountSubplebbitAddresses.length > 0 && (
|
||||
<li>
|
||||
<span className={styles.separator}>-</span>
|
||||
<Link to='/p/mod' className={isInModView ? styles.selected : styles.choice}>
|
||||
{t('mod')}
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
<span className={styles.separator}> | </span>
|
||||
{subplebbitAddresses?.map((address, index) => {
|
||||
const displayAddress = address.endsWith('.eth') ? address.slice(0, -4) : address.endsWith('.sol') ? address.slice(0, -4) : address;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useLocation, useParams } from 'react-router-dom';
|
||||
import { Comment } from '@plebbit/plebbit-react-hooks';
|
||||
import { getCommentMediaInfo, fetchWebpageThumbnailIfNeeded } from '../lib/utils/media-utils';
|
||||
@@ -9,21 +9,23 @@ export const useCommentMediaInfo = (comment: Comment) => {
|
||||
const params = useParams();
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
// some sites have CORS access, so the thumbnail can be fetched client-side, which is helpful if subplebbit.settings.fetchThumbnailUrls is false
|
||||
const initialCommentMediaInfo = useMemo(() => getCommentMediaInfo(comment), [comment]);
|
||||
const [commentMediaInfo, setCommentMediaInfo] = useState(initialCommentMediaInfo);
|
||||
const fetchThumbnail = useCallback(async () => {
|
||||
if (!isInPostPageView && !isInPendingPostView) {
|
||||
return; // don't fetch in feed view, it displaces the posts
|
||||
}
|
||||
if (initialCommentMediaInfo?.type === 'webpage' && !initialCommentMediaInfo.thumbnail) {
|
||||
const newMediaInfo = await fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo);
|
||||
setCommentMediaInfo(newMediaInfo);
|
||||
}
|
||||
}, [initialCommentMediaInfo, isInPostPageView, isInPendingPostView]);
|
||||
useEffect(() => {
|
||||
fetchThumbnail();
|
||||
}, [fetchThumbnail]);
|
||||
|
||||
return commentMediaInfo;
|
||||
// some sites have CORS access, so the thumbnail can be fetched client-side, which is helpful if subplebbit.settings.fetchThumbnailUrls is false
|
||||
const fetchThumbnail = useCallback(async () => {
|
||||
let commentMediaInfo = getCommentMediaInfo(comment);
|
||||
if (commentMediaInfo?.type === 'webpage' && !commentMediaInfo.thumbnail) {
|
||||
const newMediaInfo = await fetchWebpageThumbnailIfNeeded(commentMediaInfo);
|
||||
commentMediaInfo = newMediaInfo;
|
||||
}
|
||||
return commentMediaInfo;
|
||||
}, [comment]);
|
||||
|
||||
useEffect(() => {
|
||||
// don't fetch in feed view, it displaces the posts
|
||||
if (isInPostPageView || isInPendingPostView) {
|
||||
fetchThumbnail();
|
||||
}
|
||||
}, [fetchThumbnail, isInPostPageView, isInPendingPostView]);
|
||||
|
||||
return getCommentMediaInfo(comment);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useAccount } from '@plebbit/plebbit-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
|
||||
import useContentOptionsStore from '../stores/use-content-options-store';
|
||||
|
||||
interface Subplebbit {
|
||||
title?: string;
|
||||
@@ -28,8 +29,6 @@ export const categorizeSubplebbits = (subplebbits: Subplebbit[]) => {
|
||||
return { plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs };
|
||||
};
|
||||
|
||||
const nsfwTags = ['gore', 'adult', 'anti'];
|
||||
|
||||
export const useDefaultSubplebbits = () => {
|
||||
const [subplebbits, setSubplebbits] = useState<Subplebbit[]>([]);
|
||||
|
||||
@@ -39,17 +38,9 @@ export const useDefaultSubplebbits = () => {
|
||||
}
|
||||
(async () => {
|
||||
try {
|
||||
const multisub = await fetch(
|
||||
'https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json',
|
||||
// { cache: 'no-cache' }
|
||||
).then((res) => res.json());
|
||||
|
||||
const filteredSubplebbits = multisub.subplebbits.filter((subplebbit: Subplebbit) => {
|
||||
return !subplebbit.tags?.some((tag) => nsfwTags.includes(tag));
|
||||
});
|
||||
|
||||
cache = filteredSubplebbits;
|
||||
setSubplebbits(filteredSubplebbits);
|
||||
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => res.json());
|
||||
cache = multisub.subplebbits;
|
||||
setSubplebbits(multisub.subplebbits);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
@@ -61,7 +52,21 @@ export const useDefaultSubplebbits = () => {
|
||||
|
||||
export const useDefaultSubplebbitAddresses = () => {
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
const categorizedSubplebbits = useMemo(() => categorizeSubplebbits(defaultSubplebbits), [defaultSubplebbits]);
|
||||
const { hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities } = useContentOptionsStore();
|
||||
|
||||
const filteredSubplebbits = useMemo(() => {
|
||||
return defaultSubplebbits.filter((subplebbit: Subplebbit) => {
|
||||
const tags = subplebbit.tags || [];
|
||||
if (hideAdultCommunities && tags.includes('adult')) return false;
|
||||
if (hideGoreCommunities && tags.includes('gore')) return false;
|
||||
if (hideAntiCommunities && tags.includes('anti')) return false;
|
||||
if (hideVulgarCommunities && tags.includes('vulgar')) return false;
|
||||
return true;
|
||||
});
|
||||
}, [defaultSubplebbits, hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities]);
|
||||
|
||||
const categorizedSubplebbits = useMemo(() => categorizeSubplebbits(filteredSubplebbits), [filteredSubplebbits]);
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
[
|
||||
|
||||
18
src/hooks/use-is-broadly-nsfw-subplebbit.ts
Normal file
18
src/hooks/use-is-broadly-nsfw-subplebbit.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useDefaultSubplebbits } from './use-default-subplebbits';
|
||||
|
||||
const SENSITIVE_TAGS = ['adult', 'gore', 'anti', 'vulgar'];
|
||||
|
||||
export const useIsBroadlyNsfwSubplebbit = (subplebbitAddress: string) => {
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
|
||||
return useMemo(() => {
|
||||
if (!subplebbitAddress || !defaultSubplebbits) return false;
|
||||
|
||||
// Find the subplebbit in the default list
|
||||
const subplebbit = defaultSubplebbits.find((sub) => sub.address === subplebbitAddress);
|
||||
|
||||
// Check if the subplebbit has any of the sensitive tags
|
||||
return Boolean(subplebbit?.tags?.some((tag) => SENSITIVE_TAGS.includes(tag)));
|
||||
}, [subplebbitAddress, defaultSubplebbits]);
|
||||
};
|
||||
16
src/hooks/use-is-nsfw-subplebbit.ts
Normal file
16
src/hooks/use-is-nsfw-subplebbit.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useDefaultSubplebbits } from './use-default-subplebbits';
|
||||
|
||||
export const useIsNsfwSubplebbit = (subplebbitAddress: string) => {
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
|
||||
return useMemo(() => {
|
||||
if (!subplebbitAddress || !defaultSubplebbits) return false;
|
||||
|
||||
// Find the subplebbit in the default list
|
||||
const subplebbit = defaultSubplebbits.find((sub) => sub.address === subplebbitAddress);
|
||||
|
||||
// Check if the subplebbit has adult or gore tags
|
||||
return Boolean(subplebbit?.tags?.includes('adult') || subplebbit?.tags?.includes('gore'));
|
||||
}, [subplebbitAddress, defaultSubplebbits]);
|
||||
};
|
||||
@@ -30,7 +30,7 @@ export const getAboutLink = (pathname: string, params: ParamsType): string => {
|
||||
};
|
||||
|
||||
export const isAllView = (pathname: string): boolean => {
|
||||
return pathname.startsWith('/p/all');
|
||||
return pathname === '/p/all' || pathname.startsWith('/p/all/');
|
||||
};
|
||||
|
||||
export const isAllAboutView = (pathname: string): boolean => {
|
||||
@@ -85,6 +85,10 @@ export const isInboxUnreadView = (pathname: string): boolean => {
|
||||
return pathname === `/inbox/unread`;
|
||||
};
|
||||
|
||||
export const isModView = (pathname: string): boolean => {
|
||||
return pathname === `/p/mod` || pathname.startsWith(`/p/mod/`);
|
||||
};
|
||||
|
||||
export const isPendingPostView = (pathname: string, params: ParamsType): boolean => {
|
||||
return pathname === `/profile/${params.accountCommentIndex}`;
|
||||
};
|
||||
|
||||
37
src/stores/use-content-options-store.ts
Normal file
37
src/stores/use-content-options-store.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
interface ContentOptionsState {
|
||||
blurNsfwThumbnails: boolean;
|
||||
hideAdultCommunities: boolean;
|
||||
hideGoreCommunities: boolean;
|
||||
hideAntiCommunities: boolean;
|
||||
hideVulgarCommunities: boolean;
|
||||
setBlurNsfwThumbnails: (blur: boolean) => void;
|
||||
setHideAdultCommunities: (hide: boolean) => void;
|
||||
setHideGoreCommunities: (hide: boolean) => void;
|
||||
setHideAntiCommunities: (hide: boolean) => void;
|
||||
setHideVulgarCommunities: (hide: boolean) => void;
|
||||
}
|
||||
|
||||
const useContentOptionsStore = create<ContentOptionsState>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
blurNsfwThumbnails: true,
|
||||
hideAdultCommunities: true,
|
||||
hideGoreCommunities: true,
|
||||
hideAntiCommunities: true,
|
||||
hideVulgarCommunities: true,
|
||||
setBlurNsfwThumbnails: (blur) => set({ blurNsfwThumbnails: blur }),
|
||||
setHideAdultCommunities: (hide) => set({ hideAdultCommunities: hide }),
|
||||
setHideGoreCommunities: (hide) => set({ hideGoreCommunities: hide }),
|
||||
setHideAntiCommunities: (hide) => set({ hideAntiCommunities: hide }),
|
||||
setHideVulgarCommunities: (hide) => set({ hideVulgarCommunities: hide }),
|
||||
}),
|
||||
{
|
||||
name: 'content-options',
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export default useContentOptionsStore;
|
||||
@@ -48,13 +48,17 @@
|
||||
--markdown-blockquote-border: rgb(65, 70, 73);
|
||||
--markdown-link: rgb(74, 183, 255);
|
||||
--orange: #FF7500;
|
||||
--over18image: url("/public/assets/over18.png");
|
||||
--over18-alert-color: #ffffff;
|
||||
--pagination-button-background: rgb(29, 31, 34);
|
||||
--pagination-button-border: 1px solid rgb(55, 59, 62);
|
||||
--pagination-button-border-hover: 1px solid #5a728a;
|
||||
--play-button: url("/public/assets/buttons/play-button-dark.png");
|
||||
--play-button-hover: url("/public/assets/buttons/play-button-hover.png");
|
||||
--red: rgb(255, 21, 21);
|
||||
--red-nsfw: rgb(255, 55, 89);
|
||||
--removed-reply-backgrouhd-color: rgb(27, 30, 32);
|
||||
--submitter-color: rgb(67, 166, 255);
|
||||
--text: #bfbfbf;
|
||||
--text-button: url("/public/assets/buttons/text-button-dark.png");
|
||||
--text-button-hover: url("/public/assets/buttons/text-button-hover.png");
|
||||
@@ -62,9 +66,10 @@
|
||||
--text-info: #757575;
|
||||
--text-markdown: #f0f0f0;
|
||||
--text-primary: #c7c7c7;
|
||||
--thumbnail-icon-text: url('/public/assets/thumbnail-icon-text-dark.png');
|
||||
--thumbnail-icon-link: url('/public/assets/thumbnail-icon-link-dark.png');
|
||||
--thumbnail-icon-nsfw: url('/public/assets/thumbnail-icon-nsfw-dark.png');
|
||||
--thumbnail-icon-spoiler: url('/public/assets/thumbnail-icon-spoiler-dark.png');
|
||||
--thumbnail-icon-text: url('/public/assets/thumbnail-icon-text-dark.png');
|
||||
--yellow: rgb(200, 171, 0);
|
||||
--yellow-box-background: rgb(56, 45, 0);
|
||||
--yellow-box-contrast: rgb(163, 130, 0);
|
||||
@@ -123,13 +128,17 @@
|
||||
--markdown-blockquote-border: #c5c1ad;
|
||||
--markdown-link: #0079d3;
|
||||
--orange: #FF7500;
|
||||
--over18image: url("/public/assets/over18.png");
|
||||
--over18-alert-color: #ffffff;
|
||||
--pagination-button-background: #eee;
|
||||
--pagination-button-border: 1px solid #ddd;
|
||||
--pagination-button-border-hover: 1px solid #82A6C9;
|
||||
--play-button: url("/public/assets/buttons/play-button.png");
|
||||
--play-button-hover: url("/public/assets/buttons/play-button-hover.png");
|
||||
--red: red;
|
||||
--red-nsfw: #d10023;
|
||||
--removed-reply-backgrouhd-color: #f0f0f0;
|
||||
--submitter-color: #0055df;
|
||||
--text: black;
|
||||
--text-button: url("/public/assets/buttons/text-button.png");
|
||||
--text-button-hover: url("/public/assets/buttons/text-button-hover.png");
|
||||
@@ -137,9 +146,10 @@
|
||||
--text-info: #888;
|
||||
--text-markdown: #222222;
|
||||
--text-primary: #369;
|
||||
--thumbnail-icon-text: url('/public/assets/thumbnail-icon-text.png');
|
||||
--thumbnail-icon-link: url('/public/assets/thumbnail-icon-link.png');
|
||||
--thumbnail-icon-nsfw: url('/public/assets/thumbnail-icon-nsfw.png');
|
||||
--thumbnail-icon-spoiler: url('/public/assets/thumbnail-icon-spoiler.png');
|
||||
--thumbnail-icon-text: url('/public/assets/thumbnail-icon-text.png');
|
||||
--yellow: goldenrod;
|
||||
--yellow-box-background: #fff7d7;
|
||||
--yellow-box-contrast: #ffd634;
|
||||
|
||||
@@ -18,8 +18,7 @@ const All = () => {
|
||||
const subplebbitAddresses = useDefaultSubplebbitAddresses();
|
||||
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
|
||||
const sortType = params?.sortType || 'hot';
|
||||
const timeFilterName = params.timeFilterName;
|
||||
const { timeFilterSeconds } = useTimeFilter();
|
||||
const { timeFilterName, timeFilterSeconds } = useTimeFilter();
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed({ subplebbitAddresses, sortType, newerThan: timeFilterSeconds });
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -49,7 +48,7 @@ const All = () => {
|
||||
if (feed.length === 0) {
|
||||
footerContent = t('no_posts');
|
||||
}
|
||||
if (hasMore || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||
if (hasMore || subplebbitAddresses.length > 0 || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||
footerContent = (
|
||||
<>
|
||||
{subplebbitAddressesWithNewerPosts.length > 0 ? (
|
||||
@@ -69,7 +68,7 @@ const All = () => {
|
||||
i18nKey='more_posts_last_week'
|
||||
values={{ currentTimeFilterName }}
|
||||
components={{
|
||||
1: <Link to={'/' + (params?.sortType || 'hot') + '/1w'} />,
|
||||
1: <Link to={'/p/all/' + (params?.sortType || 'hot') + '/1w'} />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -79,7 +78,7 @@ const All = () => {
|
||||
i18nKey='more_posts_last_month'
|
||||
values={{ currentTimeFilterName }}
|
||||
components={{
|
||||
1: <Link to={'/' + (params?.sortType || 'hot') + '/1m'} />,
|
||||
1: <Link to={'/p/all/' + (params?.sortType || 'hot') + '/1m'} />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -111,7 +110,7 @@ const All = () => {
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||
if (snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[sortType + timeFilterName] = snapshot;
|
||||
lastVirtuosoStates[sortType + timeFilterName + 'all'] = snapshot;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -119,7 +118,7 @@ const All = () => {
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [sortType, timeFilterName]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterName];
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterName + 'all'];
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.morePostsSuggestion {
|
||||
font-size: 11px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.morePostsSuggestion a, .link {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
@@ -32,7 +39,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
@media (max-width: 639px) {
|
||||
.content {
|
||||
padding: 7px 2px 0px 2px;
|
||||
}
|
||||
@@ -50,4 +57,129 @@
|
||||
.stateString {
|
||||
max-width: calc(100% - 305px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.over18 {
|
||||
font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
max-width: 650px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.over18 img {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 60px;
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.over18 img {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.over18 h3 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.over18 p {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.over18 .warningButtons {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.over18 .warningButtons button {
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.over18 h3 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.over18 .warning {
|
||||
unicode-bidi: isolate;
|
||||
font-size: 14px;
|
||||
color: var(--text-markdown);
|
||||
max-width: 60em;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.over18 h3 {
|
||||
font-size: 20px;
|
||||
line-height: 1.25em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.over18 p {
|
||||
font-weight: 300;
|
||||
font-size: 18px;
|
||||
line-height: 25px;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.over18 .warningButtons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 30px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.over18 .warningButtons button {
|
||||
color: var(--over18-alert-color);
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
background-image: none;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
border-radius: 3px;
|
||||
flex: 1;
|
||||
margin: 3px 5px;
|
||||
background-color: #4f86b5;
|
||||
border-bottom: 2px solid #4270a2;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.over18 .warningButtons {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.over18 .warningButtons button {
|
||||
margin: 5px 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.over18 .warningButtons button:hover {
|
||||
background-color: #4980ae;
|
||||
}
|
||||
|
||||
.over18 .warningButtons button a {
|
||||
color: var(--over18-alert-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ const Home = () => {
|
||||
if (feed.length === 0) {
|
||||
footerContent = t('no_posts');
|
||||
}
|
||||
if (hasMore || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||
if (hasMore || subplebbitAddresses.length > 0 || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||
footerContent = (
|
||||
<>
|
||||
{subplebbitAddressesWithNewerPosts.length > 0 ? (
|
||||
@@ -99,7 +99,7 @@ const Home = () => {
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||
if (snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[sortType + timeFilterName] = snapshot;
|
||||
lastVirtuosoStates[sortType + timeFilterName + 'home'] = snapshot;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -107,7 +107,7 @@ const Home = () => {
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [sortType, timeFilterName]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterName];
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterName + 'home'];
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `Seedit`;
|
||||
|
||||
1
src/views/mod/index.ts
Normal file
1
src/views/mod/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './mod';
|
||||
146
src/views/mod/mod.tsx
Normal file
146
src/views/mod/mod.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
import { useAccountSubplebbits, useFeed } from '@plebbit/plebbit-react-hooks';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import styles from '../home/home.module.css';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
import useFeedStateString from '../../hooks/use-feed-state-string';
|
||||
import useTimeFilter from '../../hooks/use-time-filter';
|
||||
import _ from 'lodash';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
const Mod = () => {
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const subplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
|
||||
const sortType = params?.sortType || 'hot';
|
||||
const { timeFilterName, timeFilterSeconds } = useTimeFilter();
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed({ subplebbitAddresses, sortType, newerThan: timeFilterSeconds });
|
||||
const { t } = useTranslation();
|
||||
|
||||
// suggest the user to change time filter if there aren't enough posts
|
||||
const { feed: weeklyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 7 });
|
||||
const { feed: monthlyFeed } = useFeed({ subplebbitAddresses, sortType, newerThan: 60 * 60 * 24 * 30 });
|
||||
|
||||
const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');
|
||||
|
||||
const handleNewerPostsButtonClick = () => {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
||||
setTimeout(() => {
|
||||
reset();
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const currentTimeFilterName = params.timeFilterName || timeFilterName;
|
||||
|
||||
const documentTitle = _.capitalize(t('Mod')) + ' - Seedit';
|
||||
useEffect(() => {
|
||||
document.title = documentTitle;
|
||||
}, [documentTitle]);
|
||||
|
||||
const Footer = () => {
|
||||
let footerContent;
|
||||
|
||||
if (feed.length === 0) {
|
||||
footerContent = t('no_posts');
|
||||
}
|
||||
if (hasMore || subplebbitAddresses.length > 0 || (subplebbitAddresses && subplebbitAddresses.length === 0)) {
|
||||
footerContent = (
|
||||
<>
|
||||
{subplebbitAddressesWithNewerPosts.length > 0 ? (
|
||||
<div className={styles.morePostsSuggestion}>
|
||||
<Trans
|
||||
i18nKey='newer_posts_available'
|
||||
components={{
|
||||
1: <span onClick={handleNewerPostsButtonClick} />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
monthlyFeed.length > feed.length &&
|
||||
(weeklyFeed.length > feed.length ? (
|
||||
<div className={styles.morePostsSuggestion}>
|
||||
<Trans
|
||||
i18nKey='more_posts_last_week'
|
||||
values={{ currentTimeFilterName }}
|
||||
components={{
|
||||
1: <Link to={'/p/mod/' + (params?.sortType || 'hot') + '/1w'} />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.morePostsSuggestion}>
|
||||
<Trans
|
||||
i18nKey='more_posts_last_month'
|
||||
values={{ currentTimeFilterName }}
|
||||
components={{
|
||||
1: <Link to={'/p/mod/' + (params?.sortType || 'hot') + '/1m'} />,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
<div className={styles.stateString}>
|
||||
{subplebbitAddresses.length === 0 ? (
|
||||
<div>
|
||||
<Trans
|
||||
i18nKey='no_communities_found'
|
||||
components={[<a href='https://github.com/plebbit/temporary-default-subplebbits'>https://github.com/plebbit/temporary-default-subplebbits</a>]}
|
||||
/>
|
||||
<br />
|
||||
{t('connect_community_notice')}
|
||||
</div>
|
||||
) : (
|
||||
<LoadingEllipsis string={loadingStateString} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return <div className={styles.footer}>{footerContent}</div>;
|
||||
};
|
||||
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||
if (snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[sortType + timeFilterName + 'mod'] = snapshot;
|
||||
}
|
||||
});
|
||||
};
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [sortType, timeFilterName]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterName + 'mod'];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.content}>
|
||||
<div className={`${styles.sidebar}`}>
|
||||
<Sidebar />
|
||||
</div>
|
||||
<Virtuoso
|
||||
increaseViewportBy={{ bottom: 1200, top: 600 }}
|
||||
totalCount={feed?.length || 0}
|
||||
data={feed}
|
||||
itemContent={(index, post) => <Post index={index} post={post} />}
|
||||
useWindowScroll={true}
|
||||
components={{ Footer }}
|
||||
endReached={loadMore}
|
||||
ref={virtuosoRef}
|
||||
restoreStateFrom={lastVirtuosoState}
|
||||
initialScrollTop={lastVirtuosoState?.scrollTop}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Mod;
|
||||
@@ -134,4 +134,11 @@ div[data-viewport-type="window"] {
|
||||
font-family: verdana, Arial, Helvetica, sans-serif;
|
||||
margin-top: -2px;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
padding: 0 3px;
|
||||
|
||||
}
|
||||
@@ -240,35 +240,45 @@ const Profile = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
const isMobile = useWindowWidth() < 640;
|
||||
const [showInfobar, setShowInfobar] = useState(false);
|
||||
// Show infobar for first 3 visits if account wasn't imported
|
||||
const [showInfobar, setShowInfobar] = useState(() => {
|
||||
const profileVisits = parseInt(localStorage.getItem('profileVisits') || '0');
|
||||
const importedAccountAddress = localStorage.getItem('importedAccountAddress');
|
||||
const shouldShow = profileVisits < 4 && importedAccountAddress !== account?.author?.address;
|
||||
|
||||
if (shouldShow) {
|
||||
localStorage.setItem('profileVisits', (profileVisits + 1).toString());
|
||||
}
|
||||
|
||||
return shouldShow;
|
||||
});
|
||||
|
||||
const profileTitle = account?.author?.displayName ? `${account?.author?.displayName} (u/${account?.author?.shortAddress})` : `u/${account?.author?.shortAddress}`;
|
||||
useEffect(() => {
|
||||
document.title = profileTitle + ' - Seedit';
|
||||
}, [t, profileTitle]);
|
||||
|
||||
// only show infobar on first profile access and if the current account wasn't imported
|
||||
useEffect(() => {
|
||||
const wasProfileAccessed = localStorage.getItem('wasProfileAccessed');
|
||||
const importedAccountAddress = localStorage.getItem('importedAccountAddress');
|
||||
|
||||
if (!wasProfileAccessed && importedAccountAddress !== account?.author?.address) {
|
||||
setShowInfobar(true);
|
||||
localStorage.setItem('wasProfileAccessed', 'true');
|
||||
}
|
||||
}, [account?.author?.address]);
|
||||
const handleCloseInfobar = useCallback(() => {
|
||||
setShowInfobar(false);
|
||||
localStorage.setItem('profileVisits', '4');
|
||||
}, []);
|
||||
|
||||
const infobar = showInfobar && (
|
||||
<div className={styles.infobar}>
|
||||
<Trans
|
||||
i18nKey='profile_info'
|
||||
values={{ shortAddress: account?.author?.shortAddress }}
|
||||
components={{
|
||||
1: <HashLink to='/settings#displayName' />,
|
||||
2: <HashLink to='/settings#exportAccount' />,
|
||||
3: <HashLink to='/about#newUsers' />,
|
||||
}}
|
||||
/>
|
||||
<div className={styles.infobarContent}>
|
||||
<Trans
|
||||
i18nKey='profile_info'
|
||||
values={{ shortAddress: account?.author?.shortAddress }}
|
||||
components={{
|
||||
1: <HashLink to='/settings#displayName' />,
|
||||
2: <HashLink to='/settings#exportAccount' />,
|
||||
3: <HashLink to='/about#newUsers' />,
|
||||
}}
|
||||
/>
|
||||
<button onClick={handleCloseInfobar} className={styles.closeButton}>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -99,12 +99,22 @@
|
||||
.categoryTitle {
|
||||
flex: 0 0 65px;
|
||||
}
|
||||
|
||||
.categorySettings input {
|
||||
width: 35vw;
|
||||
}
|
||||
}
|
||||
|
||||
.highlightedSetting {
|
||||
background-color: var(--yellow-highlight);
|
||||
}
|
||||
|
||||
.filterSettingTitle {
|
||||
font-style: italic;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.filters input[type='checkbox'] {
|
||||
margin: 2px 0.5em 0 0;
|
||||
}
|
||||
|
||||
.filters label {
|
||||
margin-top: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { setAccount, useAccount } from '@plebbit/plebbit-react-hooks';
|
||||
import { isSettingsPlebbitOptionsView } from '../../lib/utils/view-utils';
|
||||
import styles from './settings.module.css';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
import useTheme from '../../hooks/use-theme';
|
||||
import AccountSettings from './account-settings';
|
||||
import AddressSettings from './address-settings';
|
||||
import AvatarSettings from './avatar-settings';
|
||||
import PlebbitOptions from './plebbit-options';
|
||||
import WalletSettings from './wallet-settings';
|
||||
import useTheme from '../../hooks/use-theme';
|
||||
import styles from './settings.module.css';
|
||||
import packageJson from '../../../package.json';
|
||||
import _ from 'lodash';
|
||||
|
||||
const commitRef = process.env.REACT_APP_COMMIT_REF;
|
||||
const isElectron = window.isElectron === true;
|
||||
const isAndroid = Capacitor.getPlatform() === 'android';
|
||||
|
||||
const CheckForUpdates = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -31,8 +34,16 @@ const CheckForUpdates = () => {
|
||||
const newVersionText = t('new_stable_version', { newVersion: packageData.version, oldVersion: packageJson.version });
|
||||
const updateActionText = isElectron
|
||||
? t('download_latest_desktop', { link: 'https://github.com/plebbit/seedit/releases/latest', interpolation: { escapeValue: false } })
|
||||
: isAndroid
|
||||
? t('download_latest_android')
|
||||
: t('refresh_to_update');
|
||||
alert(newVersionText + ' ' + updateActionText);
|
||||
if (isAndroid) {
|
||||
if (window.confirm(newVersionText + ' ' + updateActionText)) {
|
||||
window.open(`https://github.com/plebbit/seedit/releases/download/v${packageData.version}/seedit-${packageData.version}.apk`, '_blank', 'noreferrer');
|
||||
}
|
||||
} else {
|
||||
alert(newVersionText + ' ' + updateActionText);
|
||||
}
|
||||
updateAvailable = true;
|
||||
}
|
||||
|
||||
@@ -111,6 +122,44 @@ const ThemeSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const ContentOptions = () => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
blurNsfwThumbnails,
|
||||
hideAdultCommunities,
|
||||
hideGoreCommunities,
|
||||
hideAntiCommunities,
|
||||
hideVulgarCommunities,
|
||||
setBlurNsfwThumbnails,
|
||||
setHideAdultCommunities,
|
||||
setHideGoreCommunities,
|
||||
setHideAntiCommunities,
|
||||
setHideVulgarCommunities,
|
||||
} = useContentOptionsStore();
|
||||
|
||||
return (
|
||||
<div className={styles.filters}>
|
||||
<div className={styles.filterSettingTitle}>{t('nsfw_content')}</div>
|
||||
<input type='checkbox' id='blurNsfwThumbnails' checked={blurNsfwThumbnails} onChange={(e) => setBlurNsfwThumbnails(e.target.checked)} />
|
||||
<label htmlFor='blurNsfwThumbnails'>{t('blur_media')}</label>
|
||||
<br />
|
||||
<br />
|
||||
<div className={styles.filterSettingTitle}>{t('communities')}</div>
|
||||
<input type='checkbox' id='hideAdultCommunities' checked={hideAdultCommunities} onChange={(e) => setHideAdultCommunities(e.target.checked)} />
|
||||
<label htmlFor='hideAdultCommunities'>{t('hide_adult')} (NSFW/18+)</label>
|
||||
<br />
|
||||
<input type='checkbox' id='hideAntiCommunities' checked={hideAntiCommunities} onChange={(e) => setHideAntiCommunities(e.target.checked)} />
|
||||
<label htmlFor='hideAntiCommunities'>{t('hide_anti')}</label>
|
||||
<br />
|
||||
<input type='checkbox' id='hideGoreCommunities' checked={hideGoreCommunities} onChange={(e) => setHideGoreCommunities(e.target.checked)} />
|
||||
<label htmlFor='hideGoreCommunities'>{t('hide_gore')} (NSFW/18+)</label>
|
||||
<br />
|
||||
<input type='checkbox' id='hideVulgarCommunities' checked={hideVulgarCommunities} onChange={(e) => setHideVulgarCommunities(e.target.checked)} />
|
||||
<label htmlFor='hideVulgarCommunities'>{t('hide_vulgar')}</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DisplayNameSetting = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
@@ -192,6 +241,12 @@ const GeneralSettings = () => {
|
||||
<ThemeSettings />
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.category}>
|
||||
<span className={styles.categoryTitle}>{t('content_options')}</span>
|
||||
<span className={styles.categorySettings}>
|
||||
<ContentOptions />
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.category}>
|
||||
<span className={styles.categoryTitle}>{t('avatar')}</span>
|
||||
<span className={styles.categorySettings}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { useAccountComments, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
@@ -10,6 +10,8 @@ import Sidebar from '../../components/sidebar';
|
||||
import useFeedStateString from '../../hooks/use-feed-state-string';
|
||||
import useTimeFilter from '../../hooks/use-time-filter';
|
||||
import { usePinnedPostsStore } from '../../stores/use-pinned-posts-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
@@ -19,6 +21,23 @@ const Subplebbit = () => {
|
||||
const subplebbitAddress = params.subplebbitAddress;
|
||||
const subplebbitAddresses = useMemo(() => [subplebbitAddress], [subplebbitAddress]) as string[];
|
||||
|
||||
const contentOptionsStore = useContentOptionsStore();
|
||||
const hasUnhiddenAnyNsfwCommunity =
|
||||
!contentOptionsStore.hideAdultCommunities ||
|
||||
!contentOptionsStore.hideGoreCommunities ||
|
||||
!contentOptionsStore.hideAntiCommunities ||
|
||||
!contentOptionsStore.hideVulgarCommunities;
|
||||
const [hasAcceptedWarning, setHasAcceptedWarning] = useState(hasUnhiddenAnyNsfwCommunity);
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
const handleAcceptWarning = () => {
|
||||
contentOptionsStore.setHideAdultCommunities(false);
|
||||
contentOptionsStore.setHideGoreCommunities(false);
|
||||
contentOptionsStore.setHideAntiCommunities(false);
|
||||
contentOptionsStore.setHideVulgarCommunities(false);
|
||||
setHasAcceptedWarning(true);
|
||||
};
|
||||
|
||||
const sortType = params?.sortType || 'hot';
|
||||
const timeFilterName = params.timeFilterName || 'all';
|
||||
const { timeFilterSeconds } = useTimeFilter();
|
||||
@@ -162,7 +181,21 @@ const Subplebbit = () => {
|
||||
}
|
||||
}, [feed, setPinnedPostsCount]);
|
||||
|
||||
return (
|
||||
return isBroadlyNsfwSubplebbit && !hasAcceptedWarning ? (
|
||||
<div className={styles.over18}>
|
||||
<img src={`${process.env.PUBLIC_URL}/assets/over18.png`} alt='over 18' />
|
||||
<div className={styles.warning}>
|
||||
<h3>{t('must_be_over_18')}</h3>
|
||||
<p>{t('must_be_over_18_explanation')}</p>
|
||||
</div>
|
||||
<div className={styles.warningButtons}>
|
||||
<button>
|
||||
<Link to='/'>{t('no_thank_you')}</Link>
|
||||
</button>
|
||||
<button onClick={handleAcceptWarning}>{t('continue')}</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.content}>
|
||||
<div className={styles.sidebar}>
|
||||
<Sidebar subplebbit={subplebbit} isSubCreatedButNotYetPublished={started && isSubCreatedButNotYetPublished} settings={settings} />
|
||||
|
||||
@@ -72,6 +72,16 @@
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.defaultAvatar {
|
||||
width: 70px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
@@ -80,6 +90,11 @@
|
||||
max-height: 70px;
|
||||
}
|
||||
|
||||
.defaultAvatar img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.entry {
|
||||
overflow: hidden;
|
||||
opacity: 1;
|
||||
|
||||
@@ -146,13 +146,11 @@ const Subplebbit = ({ subplebbit }: SubplebbitProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{suggested?.avatarUrl && (
|
||||
<div className={styles.avatar}>
|
||||
<Link to={`/p/${address}`}>
|
||||
<img src={suggested?.avatarUrl} alt={address} />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<div className={`${styles.avatar} ${!suggested?.avatarUrl ? styles.defaultAvatar : ''}`}>
|
||||
<Link to={`/p/${address}`}>
|
||||
<img src={suggested?.avatarUrl || 'assets/logo/seedit.png'} alt={address} />
|
||||
</Link>
|
||||
</div>
|
||||
<div className={styles.entry}>
|
||||
<div className={styles.title}>
|
||||
<div className={styles.titleWrapper}>
|
||||
|
||||
Reference in New Issue
Block a user