Merge pull request #175 from plebbit/development

Development
This commit is contained in:
plebeius.eth
2024-01-11 21:53:18 +01:00
committed by GitHub
54 changed files with 564 additions and 165 deletions

View File

@@ -261,12 +261,12 @@ const createMainWindow = () => {
}
const appMenuBack = new MenuItem({
label: '',
label: 'Previous',
enabled: mainWindow?.webContents?.canGoBack(),
click: () => mainWindow?.webContents?.goBack(),
});
const appMenuForward = new MenuItem({
label: '',
label: 'Next',
enabled: mainWindow?.webContents?.canGoForward(),
click: () => mainWindow?.webContents?.goForward(),
});

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#000000" />
<meta
name="description"

View File

@@ -97,7 +97,6 @@
"created_by": "تم إنشاؤها بواسطة {{creatorAddress}}",
"community_for": "مجتمع لمدة {{date}}",
"post_submitted_on": "تم تقديم هذا المنشور في {{postDate}}",
"community_last_seen": "آخر زيارة لعقدة المجتمع في {{dateAgo}}",
"readers_count": "قرّاء {{count}}",
"users_online": "مستخدمين {{count}} هنا الآن",
"point": "نقطة",
@@ -185,5 +184,6 @@
"logo": "شعار",
"address": "عنوان",
"nothing_found": "لا يبدو أن هناك شيء هنا",
"stickied_comment": "التعليق المثبت"
"stickied_comment": "التعليق المثبت",
"posts_last_synced": "آخر مرة تمت مزامنة المشاركات {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "দ্বারা তৈরি {{creatorAddress}}",
"community_for": "মেয়াদ শেষে একটি সম্প্রদায়",
"post_submitted_on": "এই পোস্টটি {{postDate}} তে সাবমিট করা হয়েছে",
"community_last_seen": "সম্প্রদায় নোডটি শেষ দেখা গেছে {{dateAgo}}",
"readers_count": "{{count}} পাঠক",
"users_online": "{{count}} ব্যবহারকারী এখানে এখন",
"point": "পয়েন্ট",
@@ -185,5 +184,6 @@
"logo": "লোগো",
"address": "ঠিকানা",
"nothing_found": "এখানে কিছুই নেই মনে হয় না",
"stickied_comment": "পিন করা মন্তব্য"
"stickied_comment": "পিন করা মন্তব্য",
"posts_last_synced": "পোস্টগুলি সর্বশেষ সিঙ্ক হয়েছে {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "vytvořeno uživatelem {{creatorAddress}}",
"community_for": "komunita po dobu {{date}}",
"post_submitted_on": "tento příspěvek byl odeslán dne {{postDate}}",
"community_last_seen": "poslední viděná komunitní node {{dateAgo}}",
"readers_count": "{{count}} čtenáři",
"users_online": "{{count}} uživatelé zde nyní",
"point": "bod",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresa",
"nothing_found": "Zdá se, že zde nic není",
"stickied_comment": "Připnutý komentář"
"stickied_comment": "Připnutý komentář",
"posts_last_synced": "Poslední synchronizace příspěvků {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "oprettet af {{creatorAddress}}",
"community_for": "fællesskab i {{date}}",
"post_submitted_on": "denne indsendt dette indlæg på {{postDate}}",
"community_last_seen": "fællesskabsnode sidst set {{dateAgo}}",
"readers_count": "{{count}} læsere",
"users_online": "{{count}} brugere her nu",
"point": "punkt",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresse",
"nothing_found": "Der ser ikke ud til at være noget her",
"stickied_comment": "Fastgjort kommentar"
"stickied_comment": "Fastgjort kommentar",
"posts_last_synced": "Seneste opdatering af indlæg {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "erstellt von {{creatorAddress}}",
"community_for": "eine Gemeinschaft seit {{date}}",
"post_submitted_on": "dieser Beitrag wurde am {{postDate}} eingereicht",
"community_last_seen": "Community-Knoten zuletzt gesehen am {{dateAgo}}",
"readers_count": "{{count}} Leser",
"users_online": "{{count}} Nutzer jetzt hier",
"point": "Punkt",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresse",
"nothing_found": "Hier scheint nichts zu sein",
"stickied_comment": "Angehängter Kommentar"
"stickied_comment": "Angehängter Kommentar",
"posts_last_synced": "Zuletzt synchronisierte Beiträge {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "δημιουργήθηκε από {{creatorAddress}}",
"community_for": "κοινότητα για {{date}}",
"post_submitted_on": "αυτή η ανάρτηση κατατέθηκε στις {{postDate}}",
"community_last_seen": "κοινοτικό κόμβο τελευταία φορά που είδαμε {{dateAgo}}",
"readers_count": "{{count}} αναγνώστες",
"users_online": "{{count}} χρήστες εδώ τώρα",
"point": "σημείο",
@@ -185,5 +184,6 @@
"logo": "Λογότυπο",
"address": "Διεύθυνση",
"nothing_found": "Δεν φαίνεται να υπάρχει τίποτα εδώ",
"stickied_comment": "Καρφωμένο σχόλιο"
"stickied_comment": "Καρφωμένο σχόλιο",
"posts_last_synced": "Τελευταία συγχρονισμένες δημοσιεύσεις {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "created by {{creatorAddress}}",
"community_for": "a community for {{date}}",
"post_submitted_on": "this post was submitted on {{postDate}}",
"community_last_seen": "community node last seen {{dateAgo}}",
"readers_count": "{{count}} readers",
"users_online": "{{count}} users here now",
"point": "point",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Address",
"nothing_found": "There doesn't seem to be anything here",
"stickied_comment": "Stickied Comment"
"stickied_comment": "Stickied Comment",
"posts_last_synced": "Posts last synced {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "creado por {{creatorAddress}}",
"community_for": "una comunidad por {{date}}",
"post_submitted_on": "esta publicación se presentó el {{postDate}}",
"community_last_seen": "nodo de comunidad visto por última vez {{dateAgo}}",
"readers_count": "{{count}} lectores",
"users_online": "{{count}} usuarios aquí ahora",
"point": "punto",
@@ -185,5 +184,6 @@
"logo": "Logotipo",
"address": "Dirección",
"nothing_found": "No parece haber nada aquí",
"stickied_comment": "Comentario fijado"
"stickied_comment": "Comentario fijado",
"posts_last_synced": "Últimas publicaciones sincronizadas {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "ساخته شده توسط {{creatorAddress}}",
"community_for": "یک جامعه برای {{date}}",
"post_submitted_on": "این پست در {{postDate}} ارسال شده است",
"community_last_seen": "آخرین باری که گره جامعه دیده شده است {{dateAgo}}",
"readers_count": "{{count}} خوانندگان",
"users_online": "کاربران {{count}} در حال حاضر اینجا هستند",
"point": "نقطه",
@@ -185,5 +184,6 @@
"logo": "آرم",
"address": "آدرس",
"nothing_found": "به نظر نمی رسد که چیزی وجود داشته باشد",
"stickied_comment": "نظر ثابت"
"stickied_comment": "نظر ثابت",
"posts_last_synced": "آخرین باری که پست‌ها همگام‌سازی شدند {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "luonut {{creatorAddress}}",
"community_for": "yhteisössä {{date}}",
"post_submitted_on": "tämä viesti on toimitettu {{postDate}}",
"community_last_seen": "yhteisö solmu viimeksi nähty {{dateAgo}}",
"readers_count": "{{count}} lukijat",
"users_online": "{{count}} käyttäjää täällä nyt",
"point": "piste",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Osoite",
"nothing_found": "Täällä ei näytä olevan mitään",
"stickied_comment": "Kiinnitetty kommentti"
"stickied_comment": "Kiinnitetty kommentti",
"posts_last_synced": "Viimeksi synkronoidut viestit {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "likha ni {{creatorAddress}}",
"community_for": "isang komunidad para sa {{date}}",
"post_submitted_on": "ang post na ito ay isinumite noong {{postDate}}",
"community_last_seen": "komunidad node huli nakita sa {{dateAgo}}",
"readers_count": "{{count}} mga mambabasa",
"users_online": "{{count}} mga gumagamit dito ngayon",
"point": "punto",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Address",
"nothing_found": "Wala yatang nandito",
"stickied_comment": "Naka-pinned na Komento"
"stickied_comment": "Naka-pinned na Komento",
"posts_last_synced": "Mga huling na-synchronize na mga post {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "créé par {{creatorAddress}}",
"community_for": "une communauté depuis {{date}}",
"post_submitted_on": "cette publication a été soumise le {{postDate}}",
"community_last_seen": "nœud communautaire vu pour la dernière fois le {{dateAgo}}",
"readers_count": "{{count}} lecteurs",
"users_online": "{{count}} utilisateurs ici maintenant",
"point": "point",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresse",
"nothing_found": "Il ne semble pas y avoir de contenu ici",
"stickied_comment": "Commentaire épinglé"
"stickied_comment": "Commentaire épinglé",
"posts_last_synced": "Dernières publications synchronisées {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "נוצר על ידי {{creatorAddress}}",
"community_for": "קהילה למשך {{date}}",
"post_submitted_on": "הפוסט הזה הוגש בתאריך {{postDate}}",
"community_last_seen": "צומת קהילה נראה לאחרונה ב {{dateAgo}}",
"readers_count": "{{count}} קוראים",
"users_online": "{{count}} משתמשים כאן עכשיו",
"point": "נקודה",
@@ -185,5 +184,6 @@
"logo": "לוגו",
"address": "כתובת",
"nothing_found": "נראה שאין כאן שום דבר",
"stickied_comment": "תגובה מוצבת"
"stickied_comment": "תגובה מוצבת",
"posts_last_synced": "פוסטים אחרונים שנסנכרנו {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "द्वारा बनाई गई {{creatorAddress}}",
"community_for": "{{date}} के लिए एक समुदाय",
"post_submitted_on": "इस पोस्ट को {{postDate}} को जमा किया गया था",
"community_last_seen": "समुदाय नोड आखिरी बार देखा गया {{dateAgo}}",
"readers_count": "{{count}} पाठक",
"users_online": "{{count}} यहां अभी {{count}} उपयोगकर्ता हैं",
"point": "बिंदु",
@@ -185,5 +184,6 @@
"logo": "लोगो",
"address": "पता",
"nothing_found": "ऐसा कुछ नहीं दिखता है कि यहां कुछ है",
"stickied_comment": "पिन किया गया टिप्पणी"
"stickied_comment": "पिन किया गया टिप्पणी",
"posts_last_synced": "पोस्ट्स अंतिम बार {{dateAgo}} को सिंक की गईं"
}

View File

@@ -97,7 +97,6 @@
"created_by": "készítette {{creatorAddress}}",
"community_for": "egy közösség {{date}}",
"post_submitted_on": "ez a bejegyzés {{postDate}} n lett benyújtva",
"community_last_seen": "közösségi csomópont utoljára látható {{dateAgo}}",
"readers_count": "{{count}} olvasók",
"users_online": "{{count}} felhasználó itt most",
"point": "pont",
@@ -185,5 +184,6 @@
"logo": "Logó",
"address": "Cím",
"nothing_found": "Úgy tűnik, nincs itt semmi",
"stickied_comment": "Kitűzött hozzászólás"
"stickied_comment": "Kitűzött hozzászólás",
"posts_last_synced": "Legutóbb szinkronizált bejegyzések {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "dibuat oleh {{creatorAddress}}",
"community_for": "sebuah komunitas selama {{date}}",
"post_submitted_on": "posting ini diajukan pada {{postDate}}",
"community_last_seen": "node komunitas terakhir terlihat {{dateAgo}}",
"readers_count": "{{count}} pembaca",
"users_online": "{{count}} pengguna di sini sekarang",
"point": "titik",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Alamat",
"nothing_found": "Tidak ada yang tampaknya di sini",
"stickied_comment": "Komentar yang Dipasang"
"stickied_comment": "Komentar yang Dipasang",
"posts_last_synced": "Postingan yang terakhir disinkronkan {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "creata da {{creatorAddress}}",
"community_for": "una comunità da {{date}}",
"post_submitted_on": "questo post è stato inviato il {{postDate}}",
"community_last_seen": "nodo della comunità visto l'ultima volta {{dateAgo}}",
"readers_count": "{{count}} lettori",
"users_online": "{{count}} utenti qui ora",
"point": "punto",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Indirizzo",
"nothing_found": "Sembra che qui non ci sia nulla",
"stickied_comment": "Commento fissato"
"stickied_comment": "Commento fissato",
"posts_last_synced": "Post sincronizzati l'ultima volta {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "作成者:{{creatorAddress}}",
"community_for": "{{date}} のコミュニティ",
"post_submitted_on": "この投稿は{{postDate}}に投稿されました",
"community_last_seen": "コミュニティノードは最後に{{dateAgo}}に見られました",
"readers_count": "{{count}} 読者",
"users_online": "現在{{count}}人のユーザーがここにいます",
"point": "ポイント",
@@ -185,5 +184,6 @@
"logo": "ロゴ",
"address": "住所",
"nothing_found": "ここには何もないようです",
"stickied_comment": "固定されたコメント"
"stickied_comment": "固定されたコメント",
"posts_last_synced": "最後に同期された投稿 {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "만든 사람: {{creatorAddress}}",
"community_for": "{{date}}에 대한 커뮤니티",
"post_submitted_on": "이 게시물은 {{postDate}}에 게시되었습니다",
"community_last_seen": "커뮤니티 노드가 마지막으로 {{dateAgo}}에 본 날",
"readers_count": "{{count}} 독자",
"users_online": "지금 여기 {{count}} 명의 사용자",
"point": "포인트",
@@ -185,5 +184,6 @@
"logo": "로고",
"address": "주소",
"nothing_found": "여기에는 아무것도 없는 것 같습니다",
"stickied_comment": "고정된 댓글"
"stickied_comment": "고정된 댓글",
"posts_last_synced": "마지막 동기화된 게시물 {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "द्वारे तयार केले {{creatorAddress}}",
"community_for": "{{date}}साठी एक समुदाय",
"post_submitted_on": "हा पोस्ट {{postDate}} रोजी सबमिट केला गेला होता",
"community_last_seen": "समुदाय नोड आखाच दिला गेला {{dateAgo}}",
"readers_count": "{{count}} वाचक",
"users_online": "{{count}} युजर्स इथे आत्ता",
"point": "बिंदू",
@@ -185,5 +184,6 @@
"logo": "लोगो",
"address": "पत्ता",
"nothing_found": "काहीतरी दिसत नाही आहे",
"stickied_comment": "टाळलेला टिप्पणी"
"stickied_comment": "टाळलेला टिप्पणी",
"posts_last_synced": "शेवटी सिंक केलेले पोस्ट्स {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "gemaakt door {{creatorAddress}}",
"community_for": "een gemeenschap voor {{date}}",
"post_submitted_on": "deze post is ingediend op {{postDate}}",
"community_last_seen": "laatst gezien gemeenschapsknoop {{dateAgo}}",
"readers_count": "{{count}} lezers",
"users_online": "{{count}} gebruikers hier nu",
"point": "punt",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adres",
"nothing_found": "Het lijkt erop dat hier niets is",
"stickied_comment": "Vastgezette opmerking"
"stickied_comment": "Vastgezette opmerking",
"posts_last_synced": "Laatst gesynchroniseerde berichten {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "opprettet av {{creatorAddress}}",
"community_for": "et fellesskap for {{date}}",
"post_submitted_on": "dette innlegget ble sendt inn på {{postDate}}",
"community_last_seen": "samfunnsnode sist sett {{dateAgo}}",
"readers_count": "{{count}} lesere",
"users_online": "{{count}} brukere her nå",
"point": "punkt",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresse",
"nothing_found": "Det ser ikke ut til å være noe her",
"stickied_comment": "Festet kommentar"
"stickied_comment": "Festet kommentar",
"posts_last_synced": "Innlegg sist synkronisert {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "utworzone przez {{creatorAddress}}",
"community_for": "społeczność przez {{date}}",
"post_submitted_on": "ten post został przesłany w dniu {{postDate}}",
"community_last_seen": "ostatnio widziany węzeł społeczności {{dateAgo}}",
"readers_count": "{{count}} czytelników",
"users_online": "{{count}} użytkowników tutaj teraz",
"point": "punkt",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adres",
"nothing_found": "Nie wydaje się, że jest tu cokolwiek",
"stickied_comment": "Przypięty komentarz"
"stickied_comment": "Przypięty komentarz",
"posts_last_synced": "Ostatnio zsynchronizowane posty {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "criado por {{creatorAddress}}",
"community_for": "uma comunidade por {{date}}",
"post_submitted_on": "esta postagem foi enviada em {{postDate}}",
"community_last_seen": "nó da comunidade visto pela última vez {{dateAgo}}",
"readers_count": "{{count}} leitores",
"users_online": "{{count}} usuários aqui agora",
"point": "ponto",
@@ -185,5 +184,6 @@
"logo": "Logotipo",
"address": "Endereço",
"nothing_found": "Não parece haver nada aqui",
"stickied_comment": "Comentário fixado"
"stickied_comment": "Comentário fixado",
"posts_last_synced": "Últimas postagens sincronizadas {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "creat de {{creatorAddress}}",
"community_for": "o comunitate pentru {{date}}",
"post_submitted_on": "această postare a fost trimisă la {{postDate}}",
"community_last_seen": "nodul comunității văzut ultima dată în {{dateAgo}}",
"readers_count": "{{count}} cititori",
"users_online": "{{count}} utilizatori aici acum",
"point": "punct",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adresă",
"nothing_found": "Nu pare să fie nimic aici",
"stickied_comment": "Comentariu fixat"
"stickied_comment": "Comentariu fixat",
"posts_last_synced": "Ultimele postări sincronizate {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "создано {{creatorAddress}}",
"community_for": "сообщество на {{date}}",
"post_submitted_on": "этот пост был отправлен {{postDate}}",
"community_last_seen": "последний раз увиден узел сообщества {{dateAgo}}",
"readers_count": "{{count}} читатели",
"users_online": "{{count}} пользователей сейчас здесь",
"point": "точка",
@@ -185,5 +184,6 @@
"logo": "Логотип",
"address": "Адрес",
"nothing_found": "Здесь, кажется, ничего нет",
"stickied_comment": "Закрепленный комментарий"
"stickied_comment": "Закрепленный комментарий",
"posts_last_synced": "Последние синхронизированные посты {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "krijuar nga {{creatorAddress}}",
"community_for": "një komunitet për {{date}}",
"post_submitted_on": "ky post u dorëzua më {{postDate}}",
"community_last_seen": "nod komuniteti i fundit i parë në {{dateAgo}}",
"readers_count": "{{count}} lexues",
"users_online": "{{count}} përdorues këtu tani",
"point": "pikë",
@@ -185,5 +184,6 @@
"logo": "Logos",
"address": "Adresë",
"nothing_found": "Nuk duket të ketë asgjë këtu",
"stickied_comment": "Komenti i fiksuar"
"stickied_comment": "Komenti i fiksuar",
"posts_last_synced": "Postimet e fundit të sinkronizuara {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "skapat av {{creatorAddress}}",
"community_for": "en gemenskap för {{date}}",
"post_submitted_on": "detta inlägg skickades in den {{postDate}}",
"community_last_seen": "gemenskapsnoden senast sedd {{dateAgo}}",
"readers_count": "{{count}} läsare",
"users_online": "{{count}} användare här nu",
"point": "punkt",
@@ -185,5 +184,6 @@
"logo": "Logotyp",
"address": "Adress",
"nothing_found": "Det verkar inte finnas något här",
"stickied_comment": "Fast kommentar"
"stickied_comment": "Fast kommentar",
"posts_last_synced": "Senast synkroniserade inlägg {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "ద్వారా రూపొందించబడినది {{creatorAddress}}",
"community_for": "{{date}} కోసం ఒక కమ్యూనిటీ",
"post_submitted_on": "ఈ పోస్టు {{postDate}} న సమర్పించబడింది",
"community_last_seen": "సముదాయ నోడు చివరి సారి చూడబడింది {{dateAgo}}",
"readers_count": "{{count}} రీడర్స్",
"users_online": "ప్రస్తుతం ఇక్కడ {{count}} వినియోగదారులు",
"point": "పాయింట్",
@@ -185,5 +184,6 @@
"logo": "లోగో",
"address": "చిరునామా",
"nothing_found": "ఇక్కడ ఏమి ఉందని లేదని అనుకున్నట్లయిదేమీ లేదు",
"stickied_comment": "పిన్ చేసిన వ్యాఖ్య"
"stickied_comment": "పిన్ చేసిన వ్యాఖ్య",
"posts_last_synced": "పోస్టులు చివరిలో సింక్ అయ్యాయి {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "สร้างโดย {{creatorAddress}}",
"community_for": "ชุมชนสำหรับ {{date}}",
"post_submitted_on": "โพสต์นี้ถูกส่งในวันที่ {{postDate}}",
"community_last_seen": "ชุดความสามารถของคอมมูนิตี้เครือข่ายครั้งสุดท้าย {{dateAgo}}",
"readers_count": "{{count}} ผู้อ่าน",
"users_online": "{{count}} ผู้ใช้ที่นี่ตอนนี้",
"point": "จุด",
@@ -185,5 +184,6 @@
"logo": "โลโก้",
"address": "ที่อยู่",
"nothing_found": "ดูเหมือนว่าจะไม่มีอะไรที่นี่",
"stickied_comment": "ความคิดเห็นที่ตรึง"
"stickied_comment": "ความคิดเห็นที่ตรึง",
"posts_last_synced": "โพสต์ล่าสุดที่ซิงค์ {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "tarafından oluşturuldu {{creatorAddress}}",
"community_for": "{{date}} için bir topluluk",
"post_submitted_on": "bu gönderi {{postDate}} tarihinde gönderildi",
"community_last_seen": "topluluk düğümü son görülen {{dateAgo}}",
"readers_count": "{{count}} okuyucu",
"users_online": "şu anda {{count}} kullanıcı burada",
"point": "nokta",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Adres",
"nothing_found": "Burada hiçbir şey görünmüyor gibi",
"stickied_comment": "Sabitleyici Yorum"
"stickied_comment": "Sabitleyici Yorum",
"posts_last_synced": "Son senkronize edilen gönderiler {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "створено {{creatorAddress}}",
"community_for": "спільнота на {{date}}",
"post_submitted_on": "цей пост був поданий {{postDate}}",
"community_last_seen": "останній раз було помічено вузол спільноти {{dateAgo}}",
"readers_count": "{{count}} читачів",
"users_online": "{{count}} користувачів тут зараз",
"point": "точка",
@@ -185,5 +184,6 @@
"logo": "Логотип",
"address": "Адреса",
"nothing_found": "Тут, здається, нічого немає",
"stickied_comment": "Закріплений коментар"
"stickied_comment": "Закріплений коментар",
"posts_last_synced": "Останні синхронізовані пости {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "کا سروری کیا گیا {{creatorAddress}}",
"community_for": "ایک کمیونٹی کے لئے {{date}}",
"post_submitted_on": "یہ پوسٹ {{postDate}} کو جمع کی گئی تھی",
"community_last_seen": "آخری بار دیکھا گیا سماجی نوڈ {{dateAgo}}",
"readers_count": "{{count}} پڑھنے والے",
"users_online": "اب {{count}} صارفین یہاں ہیں",
"point": "نقطہ",
@@ -185,5 +184,6 @@
"logo": "لوگو",
"address": "پتہ",
"nothing_found": "یہاں کچھ بھی نظر نہیں آرہا",
"stickied_comment": "پن کردہ تبصرہ"
"stickied_comment": "پن کردہ تبصرہ",
"posts_last_synced": "آخری مرتب سبقت کردہ پوسٹس {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "tạo bởi {{creatorAddress}}",
"community_for": "một cộng đồng cho {{date}}",
"post_submitted_on": "bài viết này đã được đăng vào ngày {{postDate}}",
"community_last_seen": "nút cộng đồng cuối cùng được thấy vào {{dateAgo}}",
"readers_count": "{{count}} người đọc",
"users_online": "{{count}} người dùng ở đây bây giờ",
"point": "điểm",
@@ -185,5 +184,6 @@
"logo": "Logo",
"address": "Địa chỉ",
"nothing_found": "Dường như không có gì ở đây",
"stickied_comment": "Bình luận ghim"
"stickied_comment": "Bình luận ghim",
"posts_last_synced": "Bài viết gần nhất đã đồng bộ {{dateAgo}}"
}

View File

@@ -97,7 +97,6 @@
"created_by": "创建者:{{creatorAddress}}",
"community_for": "一个社区{{date}}",
"post_submitted_on": "此帖子提交于{{postDate}}",
"community_last_seen": "社区节点最后一次在{{dateAgo}}看到",
"readers_count": "{{count}} 读者",
"users_online": "现在有{{count}}用户在这里",
"point": "点",
@@ -185,5 +184,6 @@
"logo": "标志",
"address": "地址",
"nothing_found": "这里似乎什么都没有",
"stickied_comment": "置顶评论"
"stickied_comment": "置顶评论",
"posts_last_synced": "最后同步的帖子 {{dateAgo}}"
}

View File

@@ -24,6 +24,9 @@ import {
isSubplebbitSettingsView,
isSubplebbitSubmitView,
isSubplebbitsView,
isSubplebbitsMineView,
isSubplebbitsMineSubscriberView,
isSubplebbitsMineModeratorView,
isProfileUpvotedView,
} from '../../lib/utils/view-utils';
import useTheme from '../../hooks/use-theme';
@@ -196,11 +199,16 @@ const InboxHeaderTabs = () => {
const SubplebbitsHeaderTabs = () => {
const { t } = useTranslation();
const location = useLocation();
const isInSubplebbitsMineSubscriberView = isSubplebbitsMineSubscriberView(location.pathname);
const isInSubplebbitsMineModeratorView = isSubplebbitsMineModeratorView(location.pathname);
const isInSubplebbitsView = isSubplebbitsView(location.pathname) && !isInSubplebbitsMineSubscriberView && !isInSubplebbitsMineModeratorView;
const isInSubplebbitsMineView = isSubplebbitsMineView(location.pathname);
return (
<>
<li>
<Link to={'/communities'} className={styles.choice} onClick={(e) => e.preventDefault()}>
<Link to={'/communities'} className={`${isInSubplebbitsView ? styles.selected : styles.choice}`}>
approved
</Link>
</li>
@@ -210,7 +218,10 @@ const SubplebbitsHeaderTabs = () => {
</Link>
</li>
<li>
<Link to={'/communities'} className={styles.selected} onClick={(e) => e.preventDefault()}>
<Link
to={'/communities/mine'}
className={isInSubplebbitsMineView || isInSubplebbitsMineModeratorView || isInSubplebbitsMineSubscriberView ? styles.selected : styles.choice}
>
{t('my_communities')}
</Link>
</li>

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Author, useAccount, useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import styles from './comment-tools.module.css';
import HideMenu from './hide-menu';
import ModTools from './mod-menu';
import ModMenu from './mod-menu';
import ShareMenu from './share-menu';
import { FailedLabel, PendingLabel, SpoilerLabel } from '../label';
import { isInboxView } from '../../../lib/utils/view-utils';
@@ -39,16 +39,16 @@ const PostTools = ({ author, cid, hasLabel, index, isMod, subplebbitAddress, rep
<span>{t('save')}</span>
</li>
<HideMenu author={author} cid={cid} isMod={isMod} subplebbitAddress={subplebbitAddress} />
<li className={`${styles.button} ${styles.crosspostButton}`}>
<span>{t('crosspost')}</span>
</li>
{isMod ? (
<ModTools cid={cid} />
<ModMenu cid={cid} />
) : (
<li className={`${styles.button} ${styles.reportButton}`}>
<span>{t('report')}</span>
</li>
)}
<li className={`${styles.button} ${styles.crosspostButton}`}>
<span>{t('crosspost')}</span>
</li>
</>
);
};
@@ -66,16 +66,16 @@ const ReplyTools = ({ author, cid, hasLabel, index, isMod, showReplyForm, subple
<span>{t('save')}</span>
</li>
<HideMenu author={author} cid={cid} isMod={isMod} subplebbitAddress={subplebbitAddress} />
<li className={!cid ? styles.hideReply : styles.button}>
<span onClick={() => cid && showReplyForm?.()}>{t('reply_reply')}</span>
</li>
{isMod ? (
<ModTools cid={cid} />
<ModMenu cid={cid} />
) : (
<li className={`${styles.button} ${styles.reportButton}`}>
<span>{t('report')}</span>
</li>
)}
<li className={!cid ? styles.hideReply : styles.button}>
<span onClick={() => cid && showReplyForm?.()}>{t('reply_reply')}</span>
</li>
</>
);
};
@@ -104,6 +104,13 @@ const SingleReplyTools = ({ author, cid, hasLabel, index, isMod, parentCid, show
<li className={!cid ? styles.hideReply : styles.button}>
<span onClick={() => cid && showReplyForm?.()}>{t('reply_reply')}</span>
</li>
{isMod ? (
<ModMenu cid={cid} />
) : (
<li className={`${styles.button} ${styles.reportButton}`}>
<span>{t('report')}</span>
</li>
)}
</>
);
};

View File

@@ -8,15 +8,15 @@ import challengesStore from '../../../../hooks/use-challenges';
const { addChallenge } = challengesStore.getState();
type ModToolsProps = {
type ModMenuProps = {
cid: string;
};
const ModTools = ({ cid }: ModToolsProps) => {
const ModMenu = ({ cid }: ModMenuProps) => {
const { t } = useTranslation();
const post = useComment({ commentCid: cid });
const isReply = post?.parentCid;
const [isModToolsOpen, setIsModToolsOpen] = useState(false);
const [isModMenuOpen, setIsModMenuOpen] = useState(false);
const defaultPublishOptions: PublishCommentEditOptions = {
removed: post?.removed,
@@ -39,9 +39,9 @@ const ModTools = ({ cid }: ModToolsProps) => {
// close the modal after publishing
useEffect(() => {
if (state && state !== 'failed' && state !== 'initializing' && state !== 'ready') {
setIsModToolsOpen(false);
setIsModMenuOpen(false);
}
}, [state, setIsModToolsOpen]);
}, [state, setIsModMenuOpen]);
const onCheckbox = (e: React.ChangeEvent<HTMLInputElement>) => setPublishCommentEditOptions((state) => ({ ...state, [e.target.id]: e.target.checked }));
@@ -50,8 +50,8 @@ const ModTools = ({ cid }: ModToolsProps) => {
const { refs, floatingStyles, context } = useFloating({
placement: 'bottom-start',
open: isModToolsOpen,
onOpenChange: setIsModToolsOpen,
open: isModMenuOpen,
onOpenChange: setIsModMenuOpen,
middleware: [offset(2), flip({ fallbackAxisSideDirection: 'end' }), shift()],
whileElementsMounted: autoUpdate,
});
@@ -67,12 +67,12 @@ const ModTools = ({ cid }: ModToolsProps) => {
return (
<>
<li className={styles.button} ref={refs.setReference} {...getReferenceProps()}>
<span onClick={() => setIsModToolsOpen(!isModToolsOpen)}>{t('moderation')}</span>
<span onClick={() => setIsModMenuOpen(!isModMenuOpen)}>{t('moderation')}</span>
</li>
{isModToolsOpen && (
{isModMenuOpen && (
<FloatingFocusManager context={context} modal={false}>
<div className={styles.modal} ref={refs.setFloating} style={floatingStyles} aria-labelledby={headingId} {...getFloatingProps()}>
<div className={styles.modTools}>
<div className={styles.ModMenu}>
<div className={styles.menuItem}>
<label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed} type='checkbox' id='removed' />
@@ -114,4 +114,4 @@ const ModTools = ({ cid }: ModToolsProps) => {
);
};
export default ModTools;
export default ModMenu;

View File

@@ -213,4 +213,12 @@
font-weight: bold;
font-size: 10px;
cursor: pointer;
}
/* 1px compromise to hide removed posts immediately, before the feed updates, while avoiding virtuoso's zero-sized element error */
.minimalHeight {
visibility: hidden;
padding: 0;
margin: 0;
height: 1px;
}

View File

@@ -123,7 +123,7 @@ const Post = ({ post = {}, index }: PostProps) => {
const { blocked, unblock } = useBlock({ address: cid });
return (
<div className={`${styles.content} ${removed ? styles.hidden : styles.visible}`} key={index}>
<div className={`${styles.content} ${removed ? styles.minimalHeight : ''}`} key={index}>
<div className={`${styles.hiddenPost} ${blocked ? styles.visible : styles.hidden}`}>
<div className={styles.hiddenPostText}>{t('post_hidden').charAt(0).toUpperCase() + t('post_hidden').slice(1)}</div>
<div className={styles.undoHiddenPost} onClick={unblock}>

View File

@@ -49,6 +49,7 @@ a {
}
.onlineLine {
text-transform: lowercase;
padding-bottom: 5px;
}

View File

@@ -78,7 +78,7 @@ const Sidebar = ({ address, cid, createdAt, description, downvoteCount = 0, role
const { allActiveUserCount, hourActiveUserCount } = useSubplebbitStats({ subplebbitAddress: address });
const isOnline = updatedAt && updatedAt > Date.now() / 1000 - 60 * 30;
const onlineNotice = t('users_online', { count: hourActiveUserCount });
const offlineNotice = updatedAt && t('community_last_seen', { dateAgo: getFormattedTimeAgo(updatedAt) });
const offlineNotice = updatedAt && t('posts_last_synced', { dateAgo: getFormattedTimeAgo(updatedAt) });
const onlineStatus = isOnline ? onlineNotice : offlineNotice;
const location = useLocation();

5
src/globals.d.ts vendored
View File

@@ -1,6 +1,11 @@
declare global {
interface Electron {
isElectron: boolean;
}
interface Window {
STICKY_MENU_SCROLL_LISTENER: boolean;
electron: Electron;
}
}

View File

@@ -1,6 +1,6 @@
import { Role, Subplebbit, Comment } from '@plebbit/plebbit-react-hooks';
type RolesCollection = Record<string, Role>;
export type RolesCollection = Record<string, Role>;
export const findSubplebbitCreator = (roles: RolesCollection | undefined): string => {
if (!roles) {

View File

@@ -13,8 +13,6 @@ import useTimeFilter, { TimeFilterKey } from '../../hooks/use-time-filter';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
const NoPosts = () => 'no posts';
const All = () => {
const subplebbitAddresses = useDefaultSubplebbitAddresses();
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
@@ -46,13 +44,19 @@ const All = () => {
document.title = `p/all - seedit`;
}, [t]);
let Footer;
if (feed?.length === 0) {
Footer = NoPosts;
}
if (hasMore || subplebbitAddresses.length === 0) {
Footer = () => loadingString;
}
const Footer = () => {
let footerContent;
if (feed.length === 0) {
footerContent = t('no_posts');
}
if (hasMore || subplebbitAddresses.length === 0) {
footerContent = loadingString;
}
return <div className={styles.footer}>{footerContent}</div>;
};
const virtuosoRef = useRef<VirtuosoHandle | null>(null);

View File

@@ -63,7 +63,7 @@ const Home = () => {
let footerContent;
if (feed.length === 0) {
footerContent = 'no posts';
footerContent = t('no_posts');
}
if (hasMore || (subplebbitAddresses && subplebbitAddresses.length === 0)) {

View File

@@ -29,7 +29,6 @@
}
.boxInput {
vertical-align: top;
margin-top: 5px;
padding: 2px 0px 2px 8px;
width: 500px;
@@ -54,6 +53,110 @@
font-size: 14px;
}
.saveOptions button {
text-transform: lowercase;
margin: 3px 5px;
padding: 2px 5px 3px;
}
.fullSettings textarea {
height: 200px;
}
.noChallengeWarning {
color: var(--red);
font-size: 12px;
margin-left: 10px;
}
.infobar {
background-color: var(--background-orange);
border-color: var(--border-orange);
border-style: solid;
border-width: 1px;
font-size: small;
margin-bottom: 5px;
padding: 6px 10px;
color: var(--text);
word-wrap: break-word;
font-size: 14px;
text-transform: lowercase;
}
.captchaSelect {
padding-top: 0;
margin-top: 3px;
}
.captchaSelect select {
margin-bottom: 5px;
}
.captchaSelect label {
font-size: 15px;
}
.captchaSelect input[type="checkbox"] {
width: auto;
vertical-align: text-bottom;
}
.captchaSelect textarea {
margin-top: 5px;
}
.moderator {
font-size: 15px;
color: var(--text);
margin-top: 20px;
}
.addModerator {
display: block;
}
.moderatorAddress, .moderatorRole {
font-size: 13px;
margin-top: 5px;
}
.moderatorAddress input, .moderatorRole input {
font-size: 15px;
}
.moderatorAddress input {
margin-bottom: 5px;
}
.rule {
font-size: 15px;
margin-top: 10px;
}
.rule input {
margin-top: 3px;
}
.addRule {
display: block;
}
.deleteRule {
background: none no-repeat scroll center right;
background-image: url("/public/assets/buttons/delete-button.png");
padding-right: 10px;
margin-left: 10px;
cursor: pointer;
}
.deleteModerator {
background: none no-repeat scroll center right;
background-image: url("/public/assets/buttons/delete-button.png");
padding-right: 10px;
margin-left: 10px;
cursor: pointer;
}
@media (max-width: 768px) {
.box {
width: 100%;
@@ -64,4 +167,4 @@
width: calc(100% - 104px);
box-sizing: border-box;
}
}
}

View File

@@ -1,14 +1,261 @@
import { useEffect } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useSubplebbit } from '@plebbit/plebbit-react-hooks';
import { useAccount, useSubplebbit, usePublishSubplebbitEdit } from '@plebbit/plebbit-react-hooks';
import { RolesCollection } from '../../../lib/utils/user-utils';
import { useTranslation } from 'react-i18next';
import stringify from 'json-stringify-pretty-compact';
import styles from './subplebbit-settings.module.css';
const isElectron = window.electron && window.electron.isElectron;
const Title = ({ title }: { title: string }) => {
const { t } = useTranslation();
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('title')}</div>
<div className={styles.boxSubtitle}>e.g., books: made from trees or pixels. recommendations, news, or thoughts</div>
<div className={styles.boxInput}>
<input type='text' defaultValue={title} />
</div>
</div>
);
};
const Description = ({ description }: { description: string }) => {
const { t } = useTranslation();
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('description')}</div>
<div className={styles.boxSubtitle}>shown in the sidebar of your community</div>
<div className={styles.boxInput}>
<textarea defaultValue={description} />
</div>
</div>
);
};
const Address = ({ address }: { address: string }) => {
const { t } = useTranslation();
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('address')}</div>
<div className={styles.boxSubtitle}>set a readable community address using ens.domains</div>
<div className={styles.boxInput}>
<input type='text' defaultValue={address} />
</div>
</div>
);
};
const Logo = ({ logo, avatarUrl }: { logo: string; avatarUrl: string | undefined }) => {
const { t } = useTranslation();
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('logo')}</div>
<div className={styles.boxSubtitle}>set a community logo using its direct image link (ending in .jpg, .png)</div>
<div className={styles.boxInput}>
<input type='text' defaultValue={avatarUrl} />
</div>
</div>
);
};
const Rules = ({ rules }: { rules: string[] }) => {
const { t } = useTranslation();
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('rules')}</div>
<div className={styles.boxSubtitle}>shown in the sidebar of your community</div>
<div className={styles.boxInput}>
<button className={styles.addRule}>add a rule</button>
{rules?.map((rule, index) => (
<div className={styles.rule} key={index}>
Rule #{index + 1}
<span className={styles.deleteRule} title='delete rule' />
<br />
<input type='text' defaultValue={rule} />
</div>
))}
</div>
</div>
);
};
const Moderators = ({ roles }: { roles: RolesCollection | undefined }) => {
const { t } = useTranslation();
const rolesList = roles ? Object.entries(roles).map(([address, { role }]) => ({ address, role })) : [];
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('moderators')}</div>
<div className={styles.boxSubtitle}>let other users moderate and post without challenges</div>
<div className={styles.boxInput}>
<button className={styles.addModerator}>add a moderator</button>
{rolesList?.map(({ address, role }, index) => (
<div className={styles.moderator} key={index}>
Moderator #{index + 1}
<span className={styles.deleteModerator} title='delete moderator' />
<br />
<span className={styles.moderatorAddress}>
User address:
<br />
<input type='text' value={address} />
<br />
</span>
<span className={styles.moderatorRole}>
Moderator role:
<br />
<select value={role}>
<option value='moderator'>moderator</option>
<option value='admin'>admin</option>
<option value='owner'>owner</option>
</select>
</span>
</div>
))}
</div>
</div>
);
};
const Challenge = ({ challenge, selected, setSelected }: { challenge: string; selected: string; setSelected: (challenge: string) => void }) => {
const { t } = useTranslation();
const [selectedChallenge, setSelectedChallenge] = useState('captcha');
return (
<div className={styles.box}>
<div className={styles.boxTitle}>{t('challenge')}</div>
<div className={styles.boxSubtitle}>choose a challenge to prevent spam</div>
<div className={`${styles.boxInput} ${styles.captchaSelect}`}>
<select defaultValue='captcha' onChange={(e) => setSelectedChallenge(e.target.value)}>
<option value='captcha'>captcha</option>
<option value='karma'>karma</option>
<option value='token'>token</option>
<option value='password'>password</option>
<option value='custom'>custom</option>
<option value='none'>none</option>
</select>
{selectedChallenge === 'captcha' && (
<>
<br />
<label>
<input type='checkbox' /> case sensitive
</label>
</>
)}
{selectedChallenge === 'karma' && (
<>
<br />
<label>
Minimum karma: <input type='number' />
</label>
</>
)}
{selectedChallenge === 'token' && (
<>
<br />
<label>
Contract address (ERC20): <br />
<input type='text' />
</label>
<br />
<label>
Minumum balance: <br />
<input type='number' />
</label>
</>
)}
{selectedChallenge === 'password' && (
<>
<br />
<label>
Password (case sensitive): <input type='password' />
</label>
</>
)}
{selectedChallenge === 'custom' && (
<>
<br />
<label>
Paste code: <textarea />
</label>
</>
)}
{selectedChallenge === 'none' && <span className={styles.noChallengeWarning}>Warning: vulnerable to spam attacks.</span>}
</div>
</div>
);
};
const SubplebbitSettings = () => {
const { t } = useTranslation();
const account = useAccount();
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
const subplebbit = useSubplebbit({ subplebbitAddress });
const { description, rules, suggested, roles, title } = subplebbit || {};
const userRole = subplebbit?.roles?.[account.author?.address]?.role;
const isAdmin = userRole === 'admin' || userRole === 'owner';
const { address, description, rules, suggested, roles, title } = subplebbit || {};
const [text, setText] = useState('');
let usePublishSubplebbitEditOptions;
try {
usePublishSubplebbitEditOptions = { ...JSON.parse(text), subplebbitAddress };
} catch (e) {}
const { publishSubplebbitEdit } = usePublishSubplebbitEdit(usePublishSubplebbitEditOptions);
const subplebbitJson = useMemo(
() =>
stringify({
...subplebbit,
// remove fields that cant be edited
posts: undefined,
clients: undefined,
state: undefined,
startedState: undefined,
updatingState: undefined,
createdAt: undefined,
updatedAt: undefined,
fetchedAt: undefined,
signature: undefined,
errors: undefined,
error: undefined,
encryption: undefined,
statsCid: undefined,
pubsubTopic: undefined,
lastPostCid: undefined,
shortAddress: undefined,
challenges: undefined,
}),
[subplebbit],
);
// set the initial subplebbit json
useEffect(() => {
setText(subplebbitJson);
}, [subplebbitJson]);
const saveSubplebbit = async () => {
try {
// test parsing the options before saving
JSON.parse(text);
await publishSubplebbitEdit();
alert(`saved`);
} catch (e) {
if (e instanceof Error) {
console.warn(e);
alert(`failed editing subplebbit: ${e.message}`);
} else {
console.error('An unknown error occurred:', e);
}
}
};
useEffect(() => {
document.title = `${t('preferences')} - seedit`;
@@ -16,47 +263,26 @@ const SubplebbitSettings = () => {
return (
<div className={styles.content}>
{!isAdmin && <div className={styles.infobar}>only the admins and the owner of a community can edit its settings</div>}
{!isElectron && isAdmin && <div className={styles.infobar}>you must be using the desktop app to edit community settings</div>}
<Title title={title} />
<Description description={description} />
<Address address={address} />
<Logo logo={''} avatarUrl={suggested?.avatarUrl} />
<Rules rules={rules} />
<Moderators roles={roles} />
<Challenge challenge={''} selected={''} setSelected={() => {}} />
<div className={styles.box}>
<div className={styles.boxTitle}>{t('title')}</div>
<div className={styles.boxSubtitle}>e.g., books: made from trees or pixels. recommendations, news, or thoughts</div>
<div className={styles.boxInput}>
<input type='text' defaultValue={title} />
<div className={styles.boxTitle}>full settings data</div>
<div className={styles.boxSubtitle}>quickly copy or paste the community settings</div>
<div className={`${styles.boxInput} ${styles.fullSettings}`}>
<textarea onChange={(e) => setText(e.target.value)} autoCorrect='off' autoComplete='off' value={text} />
</div>
</div>
<div className={styles.box}>
<div className={styles.boxTitle}>{t('description')}</div>
<div className={styles.boxSubtitle}>shown in the sidebar of your community</div>
<div className={styles.boxInput}>
<textarea defaultValue={description} />
</div>
</div>
<div className={styles.box}>
<div className={styles.boxTitle}>logo</div>
<div className={styles.boxSubtitle}>set a community logo using its direct image link (ending in .jpg, .png)</div>
<div className={styles.boxInput}>
<input type='text' defaultValue={suggested?.avatarUrl} />
</div>
</div>
<div className={styles.box}>
<div className={styles.boxTitle}>{t('rules')}</div>
<div className={styles.boxSubtitle}>shown in the sidebar of your community</div>
<div className={styles.boxInput}>
<textarea defaultValue={rules} autoCorrect='off' autoComplete='off' />
</div>
</div>
<div className={styles.box}>
<div className={styles.boxTitle}>{t('moderators')}</div>
<div className={styles.boxSubtitle}>let other users moderate and post without challenges</div>
<div className={styles.boxInput}>
<textarea defaultValue={roles} autoCorrect='off' autoComplete='off' />
</div>
</div>
<div className={styles.box}>
<div className={styles.boxTitle}>{t('challenge')}</div>
<div className={styles.boxSubtitle}>choose a challenge to prevent spam</div>
<div className={styles.boxInput}>
<textarea autoCorrect='off' autoComplete='off' />
</div>
<div className={styles.saveOptions}>
<button disabled={!isElectron || !isAdmin} onClick={saveSubplebbit}>
{t('save_options')}
</button>
</div>
</div>
);

View File

@@ -35,7 +35,7 @@ const Subplebbit = () => {
let footerContent;
if (feed.length === 0) {
footerContent = 'no posts';
footerContent = t('no_posts');
}
if (hasMore || subplebbitAddresses.length === 0) {

View File

@@ -155,6 +155,10 @@
font-size: 14px;
}
.tagline {
text-transform: lowercase;
}
.subplebbitPreferences {
padding: 0 1px;
line-height: 1.6em;

View File

@@ -1,15 +1,23 @@
import { useEffect, useMemo } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Subplebbit as SubplebbitType, useAccountSubplebbits, useSubplebbitStats } from '@plebbit/plebbit-react-hooks';
import { Subplebbit as SubplebbitType, useAccount, useAccountSubplebbits, useSubplebbits, useSubplebbitStats } from '@plebbit/plebbit-react-hooks';
import styles from './subplebbits.module.css';
import Sidebar from '../../components/sidebar';
import SubscribeButton from '../../components/subscribe-button';
import { getFormattedTimeDuration, getFormattedTimeAgo } from '../../lib/utils/time-utils';
import { isSubplebbitsMineContributorView, isSubplebbitsMineSubscriberView, isSubplebbitsMineModeratorView } from '../../lib/utils/view-utils';
import {
isSubplebbitsView,
isSubplebbitsMineView,
isSubplebbitsMineContributorView,
isSubplebbitsMineSubscriberView,
isSubplebbitsMineModeratorView,
} from '../../lib/utils/view-utils';
import { useDefaultSubplebbitAddresses } from '../../lib/utils/addresses-utils';
interface SubplebbitProps {
subplebbit: SubplebbitType;
index?: number;
subplebbit: SubplebbitType | undefined;
}
const Tabs = () => {
@@ -21,11 +29,7 @@ const Tabs = () => {
return (
<div className={styles.subplebbitsTabs}>
<Link
to='/communities/mine/subscriber'
className={isInSubplebbitsMineSubscriberView ? styles.selected : styles.choice}
onClick={(e) => e.preventDefault()} // TODO: enable after useSubplebbits cache is implemented in the API
>
<Link to='/communities/mine/subscriber' className={isInSubplebbitsMineSubscriberView ? styles.selected : styles.choice}>
subscriber
</Link>
<span className={styles.separator}>|</span>
@@ -83,7 +87,7 @@ const Subplebbit = ({ subplebbit }: SubplebbitProps) => {
const postScore = upvoteCount === 0 && downvoteCount === 0 ? '•' : upvoteCount - downvoteCount || '•';
const isOnline = updatedAt && updatedAt > Date.now() / 1000 - 60 * 30;
const offlineNotice = updatedAt && t('community_last_seen', { dateAgo: getFormattedTimeAgo(updatedAt) });
const offlineNotice = updatedAt && t('posts_last_synced', { dateAgo: getFormattedTimeAgo(updatedAt) });
useEffect(() => {
document.title = `${t('communities')} - seedit`;
@@ -106,7 +110,7 @@ const Subplebbit = ({ subplebbit }: SubplebbitProps) => {
<div className={styles.title}>
<span className={`${styles.onlineIndicator} ${isOnline ? styles.online : styles.offline}`} />
<Link to={`/p/${address}`}>
p/{address.includes('.') ? address : shortAddress}
p/{address?.includes('.') ? address : shortAddress}
{title && `: ${title}`}
</Link>
<span className={styles.subscribeButton}>
@@ -133,18 +137,44 @@ const Subplebbit = ({ subplebbit }: SubplebbitProps) => {
);
};
const Subplebbits = () => {
const AccountSubplebbits = () => {
const { accountSubplebbits } = useAccountSubplebbits();
const accountSubplebbitsArray = useMemo(() => Object.values(accountSubplebbits), [accountSubplebbits]);
return accountSubplebbitsArray?.map((subplebbit, index) => <Subplebbit key={index} subplebbit={subplebbit} />);
};
const SubscriberSubplebbits = () => {
const account = useAccount();
const { subplebbits } = useSubplebbits({ subplebbitAddresses: account?.subscriptions || [] });
const subplebbitsArray = useMemo(() => Object.values(subplebbits), [subplebbits]);
return subplebbitsArray?.map((subplebbit, index) => <Subplebbit key={index} subplebbit={subplebbit} />);
};
const ApprovedSubplebbits = () => {
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const { subplebbits } = useSubplebbits({ subplebbitAddresses: defaultSubplebbitAddresses || [] });
const subplebbitsArray = useMemo(() => Object.values(subplebbits), [subplebbits]);
return subplebbitsArray?.map((subplebbit, index) => <Subplebbit key={index} subplebbit={subplebbit} />);
};
const Subplebbits = () => {
const location = useLocation();
const isInSubplebbitsMineSubscriberView = isSubplebbitsMineSubscriberView(location.pathname);
const isInSubplebbitsMineModeratorView = isSubplebbitsMineModeratorView(location.pathname);
const isInSubplebbitsView = isSubplebbitsView(location.pathname) && !isInSubplebbitsMineSubscriberView && !isInSubplebbitsMineModeratorView;
const isInSubplebbitsMineView = isSubplebbitsMineView(location.pathname);
return (
<div className={styles.content}>
<div className={`${styles.sidebar}`}>
<Sidebar />
</div>
<Tabs />
{(isInSubplebbitsMineView || isInSubplebbitsMineModeratorView || isInSubplebbitsMineSubscriberView) && <Tabs />}
<Infobar />
{accountSubplebbitsArray?.map((subplebbit) => <Subplebbit subplebbit={subplebbit} />)}
{isInSubplebbitsView && <ApprovedSubplebbits />}
{isInSubplebbitsMineModeratorView && <AccountSubplebbits />}
{isInSubplebbitsMineSubscriberView && <SubscriberSubplebbits />}
</div>
);
};