diff --git a/src/components/BoardAvatar.jsx b/src/components/BoardAvatar.jsx
index 3499cf93..f94359d6 100644
--- a/src/components/BoardAvatar.jsx
+++ b/src/components/BoardAvatar.jsx
@@ -1,24 +1,17 @@
-import React, { useEffect, useState } from "react";
-import { useSubplebbit } from "@plebbit/plebbit-react-hooks";
-
+import React, { useEffect, useState } from 'react';
+import { useSubplebbit } from '@plebbit/plebbit-react-hooks';
const BoardAvatar = ({ address }) => {
- const [avatarUrl, setAvatarUrl] = useState("assets/plebchan.png");
- const subplebbit = useSubplebbit({ subplebbitAddress: address });
+ const [avatarUrl, setAvatarUrl] = useState('assets/plebchan.png');
+ const subplebbit = useSubplebbit({ subplebbitAddress: address });
- useEffect(() => {
- if (subplebbit.suggested?.avatarUrl) {
- setAvatarUrl(subplebbit.suggested?.avatarUrl);
- }
- }, [subplebbit.suggested?.avatarUrl, subplebbit]);
+ useEffect(() => {
+ if (subplebbit.suggested?.avatarUrl) {
+ setAvatarUrl(subplebbit.suggested?.avatarUrl);
+ }
+ }, [subplebbit.suggested?.avatarUrl, subplebbit]);
- return (
-
- );
+ return ;
};
-export default BoardAvatar;
\ No newline at end of file
+export default BoardAvatar;
diff --git a/src/components/BoardSettings.jsx b/src/components/BoardSettings.jsx
index a183737b..113d0449 100644
--- a/src/components/BoardSettings.jsx
+++ b/src/components/BoardSettings.jsx
@@ -1,332 +1,315 @@
-import React, { useEffect, useRef, useState } from "react";
-import { Link } from "react-router-dom";
-import { usePublishSubplebbitEdit } from "@plebbit/plebbit-react-hooks";
+import React, { useEffect, useRef, useState } from 'react';
+import { Link } from 'react-router-dom';
+import { usePublishSubplebbitEdit } from '@plebbit/plebbit-react-hooks';
import { StyledModal } from './styled/modals/ModerationModal.styled';
-import useError from "../hooks/useError";
-import useSuccess from "../hooks/useSuccess";
+import useError from '../hooks/useError';
+import useSuccess from '../hooks/useSuccess';
import useGeneralStore from '../hooks/stores/useGeneralStore';
const BoardSettings = ({ subplebbit }) => {
- const {
- setCaptchaResponse,
- setChallengesArray,
- setIsCaptchaOpen,
- setResolveCaptchaPromise,
- selectedAddress,
- selectedStyle,
- } = useGeneralStore(state => state);
+ const { setCaptchaResponse, setChallengesArray, setIsCaptchaOpen, setResolveCaptchaPromise, selectedAddress, selectedStyle } = useGeneralStore((state) => state);
- const allowedSettings = {
- address: subplebbit.address,
- apiUrl: subplebbit.apiUrl,
- description: subplebbit.description,
- pubsubTopic: subplebbit.pubsubTopic,
- settings: {
- fetchThumbnailUrls: subplebbit.settings?.fetchThumbnailUrls,
- fetchThumbnailUrlsProxyUrl: subplebbit.settings?.fetchThumbnailUrlsProxyUrl,
- },
- roles: subplebbit.roles,
- rules: subplebbit.rules,
- suggested: {
- avatarUrl: subplebbit.suggested?.avatarUrl,
- backgroundUrl: subplebbit.suggested?.backgroundUrl,
- bannerUrl: subplebbit.suggested?.bannerUrl,
- language: subplebbit.suggested?.language,
- primaryColor: subplebbit.suggested?.primaryColor,
- secondaryColor: subplebbit.suggested?.secondaryColor,
- },
- title: subplebbit.title,
- };
+ const allowedSettings = {
+ address: subplebbit.address,
+ apiUrl: subplebbit.apiUrl,
+ description: subplebbit.description,
+ pubsubTopic: subplebbit.pubsubTopic,
+ settings: {
+ fetchThumbnailUrls: subplebbit.settings?.fetchThumbnailUrls,
+ fetchThumbnailUrlsProxyUrl: subplebbit.settings?.fetchThumbnailUrlsProxyUrl,
+ },
+ roles: subplebbit.roles,
+ rules: subplebbit.rules,
+ suggested: {
+ avatarUrl: subplebbit.suggested?.avatarUrl,
+ backgroundUrl: subplebbit.suggested?.backgroundUrl,
+ bannerUrl: subplebbit.suggested?.bannerUrl,
+ language: subplebbit.suggested?.language,
+ primaryColor: subplebbit.suggested?.primaryColor,
+ secondaryColor: subplebbit.suggested?.secondaryColor,
+ },
+ title: subplebbit.title,
+ };
- const generateSettingsFromSubplebbit = (subplebbitData) => ({
- address: subplebbitData.address,
- apiUrl: subplebbitData.apiUrl,
- description: subplebbitData.description,
- pubsubTopic: subplebbitData.pubsubTopic,
- settings: {
- fetchThumbnailUrls: subplebbitData.settings?.fetchThumbnailUrls,
- fetchThumbnailUrlsProxyUrl: subplebbitData.settings?.fetchThumbnailUrlsProxyUrl,
- },
- roles: subplebbitData.roles,
- rules: subplebbitData.rules,
- suggested: {
- avatarUrl: subplebbitData.suggested?.avatarUrl,
- backgroundUrl: subplebbitData.suggested?.backgroundUrl,
- bannerUrl: subplebbitData.suggested?.bannerUrl,
- language: subplebbitData.suggested?.language,
- primaryColor: subplebbitData.suggested?.primaryColor,
- secondaryColor: subplebbitData.suggested?.secondaryColor,
- },
- title: subplebbitData.title,
- });
+ const generateSettingsFromSubplebbit = (subplebbitData) => ({
+ address: subplebbitData.address,
+ apiUrl: subplebbitData.apiUrl,
+ description: subplebbitData.description,
+ pubsubTopic: subplebbitData.pubsubTopic,
+ settings: {
+ fetchThumbnailUrls: subplebbitData.settings?.fetchThumbnailUrls,
+ fetchThumbnailUrlsProxyUrl: subplebbitData.settings?.fetchThumbnailUrlsProxyUrl,
+ },
+ roles: subplebbitData.roles,
+ rules: subplebbitData.rules,
+ suggested: {
+ avatarUrl: subplebbitData.suggested?.avatarUrl,
+ backgroundUrl: subplebbitData.suggested?.backgroundUrl,
+ bannerUrl: subplebbitData.suggested?.bannerUrl,
+ language: subplebbitData.suggested?.language,
+ primaryColor: subplebbitData.suggested?.primaryColor,
+ secondaryColor: subplebbitData.suggested?.secondaryColor,
+ },
+ title: subplebbitData.title,
+ });
- const initialSettings = generateSettingsFromSubplebbit(subplebbit);
- const [isModalOpen, setIsModalOpen] = useState(false);
- const [boardSettingsJson, setBoardSettingsJson] = useState(JSON.stringify(initialSettings, null, 2));
- const [triggerPublilshSubplebbitEdit, setTriggerPublishCommentEdit] = useState(false);
+ const initialSettings = generateSettingsFromSubplebbit(subplebbit);
+ const [isModalOpen, setIsModalOpen] = useState(false);
+ const [boardSettingsJson, setBoardSettingsJson] = useState(JSON.stringify(initialSettings, null, 2));
+ const [triggerPublilshSubplebbitEdit, setTriggerPublishCommentEdit] = useState(false);
- const [, setNewErrorMessage] = useError();
- const [, setNewSuccessMessage] = useSuccess();
-
+ const [, setNewErrorMessage] = useError();
+ const [, setNewSuccessMessage] = useSuccess();
- const getDifferences = (oldObj, newObj) => {
- let differences = {};
-
- for (let key in oldObj) {
- if (typeof oldObj[key] === 'object' && oldObj[key] !== null) {
- const nestedDifferences = getDifferences(oldObj[key], newObj[key] || {});
- if (Object.keys(nestedDifferences).length > 0) {
- differences[key] = nestedDifferences;
- }
- } else if (oldObj[key] !== newObj[key]) {
- differences[key] = newObj[key];
- }
- }
-
- for (let key in newObj) {
- if (!oldObj.hasOwnProperty(key)) {
- differences[key] = newObj[key];
- }
- }
-
- return differences;
- };
+ const getDifferences = (oldObj, newObj) => {
+ let differences = {};
+ for (let key in oldObj) {
+ if (typeof oldObj[key] === 'object' && oldObj[key] !== null) {
+ const nestedDifferences = getDifferences(oldObj[key], newObj[key] || {});
+ if (Object.keys(nestedDifferences).length > 0) {
+ differences[key] = nestedDifferences;
+ }
+ } else if (oldObj[key] !== newObj[key]) {
+ differences[key] = newObj[key];
+ }
+ }
- const isInitialMount = useRef(true);
+ for (let key in newObj) {
+ if (!oldObj.hasOwnProperty(key)) {
+ differences[key] = newObj[key];
+ }
+ }
- useEffect(() => {
- if (isInitialMount.current) {
- setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2));
- isInitialMount.current = false;
- }
- }, [subplebbit]);
+ return differences;
+ };
+ const isInitialMount = useRef(true);
- function validateSettings(updatedSettings, allowedSettings) {
- for (let key in updatedSettings) {
- if (!allowedSettings.hasOwnProperty(key) && !initialSettings.hasOwnProperty(key)) {
- throw new Error(`Unexpected setting: ${key}`);
- }
+ useEffect(() => {
+ if (isInitialMount.current) {
+ setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2));
+ isInitialMount.current = false;
+ }
+ }, [subplebbit]);
- if (typeof updatedSettings[key] === 'object' && updatedSettings[key] !== null
- && !Array.isArray(updatedSettings[key])) {
- if (typeof allowedSettings[key] !== 'object' || allowedSettings[key] === null
- || Array.isArray(allowedSettings[key])) {
- throw new Error(`Expected ${key} to be an object in allowedSettings`);
- }
- validateSettings(updatedSettings[key], allowedSettings[key]);
- }
- }
- }
+ function validateSettings(updatedSettings, allowedSettings) {
+ for (let key in updatedSettings) {
+ if (!allowedSettings.hasOwnProperty(key) && !initialSettings.hasOwnProperty(key)) {
+ throw new Error(`Unexpected setting: ${key}`);
+ }
+ if (typeof updatedSettings[key] === 'object' && updatedSettings[key] !== null && !Array.isArray(updatedSettings[key])) {
+ if (typeof allowedSettings[key] !== 'object' || allowedSettings[key] === null || Array.isArray(allowedSettings[key])) {
+ throw new Error(`Expected ${key} to be an object in allowedSettings`);
+ }
+ validateSettings(updatedSettings[key], allowedSettings[key]);
+ }
+ }
+ }
- const onChallenge = async (challenges, subplebbitEdit) => {
- let challengeAnswers = [];
-
- try {
- challengeAnswers = await getChallengeAnswersFromUser(challenges)
- }
- catch (error) {
- setNewErrorMessage(error.message); console.log(error);
- }
- if (challengeAnswers) {
- await subplebbitEdit.publishChallengeAnswers(challengeAnswers)
- }
- };
+ const onChallenge = async (challenges, subplebbitEdit) => {
+ let challengeAnswers = [];
+ try {
+ challengeAnswers = await getChallengeAnswersFromUser(challenges);
+ } catch (error) {
+ setNewErrorMessage(error.message);
+ console.log(error);
+ }
+ if (challengeAnswers) {
+ await subplebbitEdit.publishChallengeAnswers(challengeAnswers);
+ }
+ };
- const onChallengeVerification = (challengeVerification) => {
- if (challengeVerification.challengeSuccess === true) {
- setNewSuccessMessage('Challenge Success'); console.log('challenge success', challengeVerification);
- } else if (challengeVerification.challengeSuccess === false) {
- setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`);
- console.log('challenge failed', challengeVerification);
- }
- };
+ const onChallengeVerification = (challengeVerification) => {
+ if (challengeVerification.challengeSuccess === true) {
+ setNewSuccessMessage('Challenge Success');
+ console.log('challenge success', challengeVerification);
+ } else if (challengeVerification.challengeSuccess === false) {
+ setNewErrorMessage(`Challenge Failed, reason: ${challengeVerification.reason}. Errors: ${challengeVerification.errors}`);
+ console.log('challenge failed', challengeVerification);
+ }
+ };
+ const getChallengeAnswersFromUser = async (challenges) => {
+ setChallengesArray(challenges);
- const getChallengeAnswersFromUser = async (challenges) => {
- setChallengesArray(challenges);
-
- return new Promise((resolve, reject) => {
- const imageString = challenges?.challenges[0].challenge;
- const imageSource = `data:image/png;base64,${imageString}`;
- const challengeImg = new Image();
- challengeImg.src = imageSource;
-
- challengeImg.onload = () => {
- setIsCaptchaOpen(true);
-
- const handleKeyDown = async (event) => {
- if (event.key === 'Enter') {
- const currentCaptchaResponse = useGeneralStore.getState().captchaResponse;
- resolve(currentCaptchaResponse);
- setIsCaptchaOpen(false);
- document.removeEventListener('keydown', handleKeyDown);
- event.preventDefault();
- }
- };
+ return new Promise((resolve, reject) => {
+ const imageString = challenges?.challenges[0].challenge;
+ const imageSource = `data:image/png;base64,${imageString}`;
+ const challengeImg = new Image();
+ challengeImg.src = imageSource;
- setCaptchaResponse('');
- document.addEventListener('keydown', handleKeyDown);
+ challengeImg.onload = () => {
+ setIsCaptchaOpen(true);
- setResolveCaptchaPromise(resolve);
- };
-
- challengeImg.onerror = () => {
- reject(setNewErrorMessage('Could not load challenges'));
- };
- });
- };
+ const handleKeyDown = async (event) => {
+ if (event.key === 'Enter') {
+ const currentCaptchaResponse = useGeneralStore.getState().captchaResponse;
+ resolve(currentCaptchaResponse);
+ setIsCaptchaOpen(false);
+ document.removeEventListener('keydown', handleKeyDown);
+ event.preventDefault();
+ }
+ };
+ setCaptchaResponse('');
+ document.addEventListener('keydown', handleKeyDown);
- const [editSubplebbitOptions, setEditSubplebbitOptions] = useState({
- subplebbitAddress: selectedAddress,
- onChallenge,
- onChallengeVerification,
- onError: (error) => {
- setNewErrorMessage(error.message); console.log(error);
- }
- });
+ setResolveCaptchaPromise(resolve);
+ };
+ challengeImg.onerror = () => {
+ reject(setNewErrorMessage('Could not load challenges'));
+ };
+ });
+ };
- const { publishSubplebbitEdit } = usePublishSubplebbitEdit(editSubplebbitOptions);
+ const [editSubplebbitOptions, setEditSubplebbitOptions] = useState({
+ subplebbitAddress: selectedAddress,
+ onChallenge,
+ onChallengeVerification,
+ onError: (error) => {
+ setNewErrorMessage(error.message);
+ console.log(error);
+ },
+ });
+ const { publishSubplebbitEdit } = usePublishSubplebbitEdit(editSubplebbitOptions);
- useEffect(() => {
- let isActive = true;
- if (editSubplebbitOptions && triggerPublilshSubplebbitEdit) {
- (async () => {
- await publishSubplebbitEdit(editSubplebbitOptions);
- if (isActive) {
- setTriggerPublishCommentEdit(false);
- }
- })();
- }
+ useEffect(() => {
+ let isActive = true;
+ if (editSubplebbitOptions && triggerPublilshSubplebbitEdit) {
+ (async () => {
+ await publishSubplebbitEdit(editSubplebbitOptions);
+ if (isActive) {
+ setTriggerPublishCommentEdit(false);
+ }
+ })();
+ }
- return () => {
- isActive = false;
- };
- }, [editSubplebbitOptions, publishSubplebbitEdit, triggerPublilshSubplebbitEdit]);
+ return () => {
+ isActive = false;
+ };
+ }, [editSubplebbitOptions, publishSubplebbitEdit, triggerPublilshSubplebbitEdit]);
-
- const handleSaveChanges = async () => {
- try {
- const updatedSettings = JSON.parse(boardSettingsJson);
- validateSettings(updatedSettings, allowedSettings);
- const changes = getDifferences(initialSettings, updatedSettings);
- if (Object.keys(changes).length > 0) {
- setEditSubplebbitOptions(prevOptions => ({
- ...prevOptions,
- ...changes
- }));
- setTriggerPublishCommentEdit(true);
- } else {
- setNewErrorMessage("No changes detected");
- }
- } catch (error) {
- setNewErrorMessage(`Error saving changes: ${error}`);
- console.log(error);
- }
- };
+ const handleSaveChanges = async () => {
+ try {
+ const updatedSettings = JSON.parse(boardSettingsJson);
+ validateSettings(updatedSettings, allowedSettings);
+ const changes = getDifferences(initialSettings, updatedSettings);
+ if (Object.keys(changes).length > 0) {
+ setEditSubplebbitOptions((prevOptions) => ({
+ ...prevOptions,
+ ...changes,
+ }));
+ setTriggerPublishCommentEdit(true);
+ } else {
+ setNewErrorMessage('No changes detected');
+ }
+ } catch (error) {
+ setNewErrorMessage(`Error saving changes: ${error}`);
+ console.log(error);
+ }
+ };
+ const handleResetChanges = () => {
+ setBoardSettingsJson(JSON.stringify(initialSettings, null, 2));
+ };
- const handleResetChanges = () => {
- setBoardSettingsJson(JSON.stringify(initialSettings, null, 2));
- };
-
+ function generateSettingsList(settingsObj, parentKey = '') {
+ let result = [];
- function generateSettingsList(settingsObj, parentKey = '') {
- let result = [];
-
- for (let key in settingsObj) {
- if (typeof settingsObj[key] === 'object' && settingsObj[key] !== null) {
- const nestedItems = generateSettingsList(settingsObj[key], `${parentKey}${key}.`);
- if (nestedItems.length > 1) {
- result.push(`${parentKey}${key}: { ${nestedItems.join(', ')} }`);
- } else {
- result.push(...nestedItems);
- }
- } else {
- result.push(`${parentKey}${key}`);
- }
- }
-
- return result;
- }
-
+ for (let key in settingsObj) {
+ if (typeof settingsObj[key] === 'object' && settingsObj[key] !== null) {
+ const nestedItems = generateSettingsList(settingsObj[key], `${parentKey}${key}.`);
+ if (nestedItems.length > 1) {
+ result.push(`${parentKey}${key}: { ${nestedItems.join(', ')} }`);
+ } else {
+ result.push(...nestedItems);
+ }
+ } else {
+ result.push(`${parentKey}${key}`);
+ }
+ }
- const possibleSettingsList = generateSettingsList(initialSettings);
+ return result;
+ }
+ const possibleSettingsList = generateSettingsList(initialSettings);
- const handleCloseModal = () => {
- setIsModalOpen(false);
- setBoardSettingsJson(JSON.stringify(initialSettings, null, 2));
- };
+ const handleCloseModal = () => {
+ setIsModalOpen(false);
+ setBoardSettingsJson(JSON.stringify(initialSettings, null, 2));
+ };
- const openModal = () => {
- setIsModalOpen(true);
- setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2));
- };
+ const openModal = () => {
+ setIsModalOpen(true);
+ setBoardSettingsJson(JSON.stringify(generateSettingsFromSubplebbit(subplebbit), null, 2));
+ };
-
- return (
- <>
-
-
-
- Board Settings
-
-
-
-
-
-
-
- [
-
- {
- window.electron && window.electron.isElectron
- ? openModal()
- : alert(
- 'To edit this board you must be using the plebchan desktop app, which is a plebbit full node that seeds the board automatically.\n\nDownload plebchan here:\n\nhttps://github.com/plebbit/plebchan/releases/latest'
- );
- }}
- >
- Settings
-
-
- ]
- >
- );
+ return (
+ <>
+
+
+
+ Board Settings
+
+
+
+
+
+
+
+ [
+
+ {
+ window.electron && window.electron.isElectron
+ ? openModal()
+ : alert(
+ 'To edit this board you must be using the plebchan desktop app, which is a plebbit full node that seeds the board automatically.\n\nDownload plebchan here:\n\nhttps://github.com/plebbit/plebchan/releases/latest',
+ );
+ }}
+ >
+ Settings
+
+
+ ]
+ >
+ );
};
-export default BoardSettings;
\ No newline at end of file
+export default BoardSettings;
diff --git a/src/components/BoardStats.jsx b/src/components/BoardStats.jsx
index 05851879..fdd6ec34 100644
--- a/src/components/BoardStats.jsx
+++ b/src/components/BoardStats.jsx
@@ -1,62 +1,74 @@
-import React, { useState } from "react";
-import { useSubplebbit, useSubplebbitStats } from "@plebbit/plebbit-react-hooks/dist";
-import { BoardStatsContainer } from "./styled/BoardStats.styled";
-import { Break } from "./styled/views/Board.styled";
+import React, { useState } from 'react';
+import { useSubplebbit, useSubplebbitStats } from '@plebbit/plebbit-react-hooks/dist';
+import { BoardStatsContainer } from './styled/BoardStats.styled';
+import { Break } from './styled/views/Board.styled';
import useGeneralStore from '../hooks/stores/useGeneralStore';
-
-
const BoardStats = ({ subplebbitAddress }) => {
- const { selectedStyle } = useGeneralStore(state => state);
- const stats = useSubplebbitStats({subplebbitAddress});
- const [showStats, setShowStats] = useState(true);
- const subplebbit = useSubplebbit({subplebbitAddress});
+ const { selectedStyle } = useGeneralStore((state) => state);
+ const stats = useSubplebbitStats({ subplebbitAddress });
+ const [showStats, setShowStats] = useState(true);
+ const subplebbit = useSubplebbit({ subplebbitAddress });
- const handleToggleStats = () => {
- setShowStats(!showStats);
- };
+ const handleToggleStats = () => {
+ setShowStats(!showStats);
+ };
- const unixToMMDDYYYY = (timestamp) => {
- const date = new Date(timestamp * 1000);
- const month = ('0' + (date.getMonth() + 1)).slice(-2);
- const day = ('0' + date.getDate()).slice(-2);
- const year = date.getFullYear().toString().slice(-2);
- return month + '/' + day + '/' + year;
- };
+ const unixToMMDDYYYY = (timestamp) => {
+ const date = new Date(timestamp * 1000);
+ const month = ('0' + (date.getMonth() + 1)).slice(-2);
+ const day = ('0' + date.getDate()).slice(-2);
+ const year = date.getFullYear().toString().slice(-2);
+ return month + '/' + day + '/' + year;
+ };
- const pluralize = (count, singular, plural) => count === 1 ? singular : plural;
+ const pluralize = (count, singular, plural) => (count === 1 ? singular : plural);
- return (
-
-
-
- {showStats && (
-
-
- In the past hour, {stats.hourActiveUserCount} {pluralize(stats.hourActiveUserCount, 'user', 'users')} made {stats.hourPostCount} {pluralize(stats.hourPostCount, 'post', 'posts')} / in the past day, {stats.dayActiveUserCount} {pluralize(stats.dayActiveUserCount, 'user', 'users')} made {stats.dayPostCount} {pluralize(stats.dayPostCount, 'post', 'posts')}
-
-
- In the past week, {stats.weekActiveUserCount} {pluralize(stats.weekActiveUserCount, 'user', 'users')} made {stats.weekPostCount} {pluralize(stats.weekPostCount, 'post', 'posts')} / in the past month, {stats.monthActiveUserCount} {pluralize(stats.monthActiveUserCount, 'user', 'users')} made {stats.monthPostCount} {pluralize(stats.monthPostCount, 'post', 'posts')}
-
-
- {unixToMMDDYYYY(subplebbit.createdAt)} board created / since then, {stats.allActiveUserCount} {pluralize(stats.allActiveUserCount, 'user', 'users')} have made {stats.allPostCount} {pluralize(stats.allPostCount, 'post', 'posts')}
-
-
- )}
-
-
-
- [
-
- {showStats ? 'Hide' : 'Show Stats'}
-
- ]
-
-
-
-
-
- );
+ return (
+
+
+
+ {showStats && (
+
+
+
+ In the past hour, {stats.hourActiveUserCount} {pluralize(stats.hourActiveUserCount, 'user', 'users')} made{' '}
+ {stats.hourPostCount} {pluralize(stats.hourPostCount, 'post', 'posts')} / in the past day,{' '}
+ {stats.dayActiveUserCount} {pluralize(stats.dayActiveUserCount, 'user', 'users')} made{' '}
+ {stats.dayPostCount} {pluralize(stats.dayPostCount, 'post', 'posts')}
+
+
+
+
+ In the past week, {stats.weekActiveUserCount} {pluralize(stats.weekActiveUserCount, 'user', 'users')} made{' '}
+ {stats.weekPostCount} {pluralize(stats.weekPostCount, 'post', 'posts')} / in the past month,{' '}
+ {stats.monthActiveUserCount} {pluralize(stats.monthActiveUserCount, 'user', 'users')} made{' '}
+ {stats.monthPostCount} {pluralize(stats.monthPostCount, 'post', 'posts')}
+
+
+
+
+ {unixToMMDDYYYY(subplebbit.createdAt)} board created / since then, {stats.allActiveUserCount} {' '}
+ {pluralize(stats.allActiveUserCount, 'user', 'users')} have made {stats.allPostCount} {' '}
+ {pluralize(stats.allPostCount, 'post', 'posts')}
+
+
+
+ )}
+
+
+
+ [
+
+ {showStats ? 'Hide' : 'Show Stats'}
+
+ ]
+
+
+
+
+
+ );
};
-export default BoardStats;
\ No newline at end of file
+export default BoardStats;
diff --git a/src/components/CatalogLoader.jsx b/src/components/CatalogLoader.jsx
index 22e55ffc..ba0740d6 100644
--- a/src/components/CatalogLoader.jsx
+++ b/src/components/CatalogLoader.jsx
@@ -2,50 +2,48 @@ import React from 'react';
import ContentLoader from 'react-content-loader';
import useGeneralStore from '../hooks/stores/useGeneralStore';
-
const SingleRectLoader = () => {
- const selectedStyle = useGeneralStore((state) => state.selectedStyle);
- const backgroundColor = selectedStyle === 'Tomorrow' ? '#333' : '#f3f3f3';
- const foregroundColor = selectedStyle === 'Tomorrow' ? '#555' : '#ecebeb';
-
- return (
-
-
-
-
-
- );
-};
+ const selectedStyle = useGeneralStore((state) => state.selectedStyle);
+ const backgroundColor = selectedStyle === 'Tomorrow' ? '#333' : '#f3f3f3';
+ const foregroundColor = selectedStyle === 'Tomorrow' ? '#555' : '#ecebeb';
+ return (
+
+
+
+
+
+ );
+};
const CatalogLoader = () => {
- return (
-
- {[...Array(24)].map((_, index) => (
-
- ))}
-
- );
+ return (
+
+ {[...Array(24)].map((_, index) => (
+
+ ))}
+
+ );
};
-export default CatalogLoader;
\ No newline at end of file
+export default CatalogLoader;
diff --git a/src/components/EditLabel.jsx b/src/components/EditLabel.jsx
index aa3e3b76..7f901563 100644
--- a/src/components/EditLabel.jsx
+++ b/src/components/EditLabel.jsx
@@ -1,71 +1,67 @@
-import React, { useState } from "react";
-import { useComment, useEditedComment } from "@plebbit/plebbit-react-hooks";
-import { Link } from "react-router-dom";
-import OriginalCommentModal from "./modals/OriginalCommentModal";
-import getDate from "../utils/getDate";
-import useGeneralStore from "../hooks/stores/useGeneralStore";
-
+import React, { useState } from 'react';
+import { useComment, useEditedComment } from '@plebbit/plebbit-react-hooks';
+import { Link } from 'react-router-dom';
+import OriginalCommentModal from './modals/OriginalCommentModal';
+import getDate from '../utils/getDate';
+import useGeneralStore from '../hooks/stores/useGeneralStore';
const EditLabel = ({ commentCid, className }) => {
- const { editedComments, setEditedComments } = useGeneralStore(state => state);
- const [isOriginalCommentModalOpen, setIsOriginalCommentModalOpen] = useState(false);
- const comment = useComment({commentCid});
- const timestamp = getDate(comment.edit?.timestamp);
- const {state: editedCommentState, editedComment} = useEditedComment({comment});
+ const { editedComments, setEditedComments } = useGeneralStore((state) => state);
+ const [isOriginalCommentModalOpen, setIsOriginalCommentModalOpen] = useState(false);
+ const comment = useComment({ commentCid });
+ const timestamp = getDate(comment.edit?.timestamp);
+ const { state: editedCommentState, editedComment } = useEditedComment({ comment });
- if (editedCommentState === 'pending' && !(commentCid in editedComments)) {
- setEditedComments({...editedComments, [commentCid]: editedComment})
- }
+ if (editedCommentState === 'pending' && !(commentCid in editedComments)) {
+ setEditedComments({ ...editedComments, [commentCid]: editedComment });
+ }
- const conditionsCheck = () => {
- let conditions = [];
+ const conditionsCheck = () => {
+ let conditions = [];
- if (editedComment?.removed && !comment.removed) {
- conditions.push("removal");
- }
- if (editedComment?.edit && !comment.edit) {
- conditions.push("edit");
- }
- if (editedComment?.locked && !comment.locked) {
- conditions.push("lock");
- }
- if (editedComment?.pinned && !comment.pinned) {
- conditions.push("sticky");
- }
+ if (editedComment?.removed && !comment.removed) {
+ conditions.push('removal');
+ }
+ if (editedComment?.edit && !comment.edit) {
+ conditions.push('edit');
+ }
+ if (editedComment?.locked && !comment.locked) {
+ conditions.push('lock');
+ }
+ if (editedComment?.pinned && !comment.pinned) {
+ conditions.push('sticky');
+ }
- return conditions.length > 0 ? conditions.join(', ') : null;
- };
+ return conditions.length > 0 ? conditions.join(', ') : null;
+ };
+ const conditionsString = conditionsCheck();
- const conditionsString = conditionsCheck();
-
-
- return (
- <>
- setIsOriginalCommentModalOpen(false)}
- comment={comment}/>
- {comment.edit && (
- <>
-
-
- (Edited at {timestamp}, setIsOriginalCommentModalOpen(true)
- }>show original)
-
- >
- )}
- {((editedCommentState === 'pending' || editedCommentState === 'failed') && conditionsString) ? (
- <>
-
-
- ({editedCommentState === 'pending' ? 'Pending' : 'Failed'} {conditionsString})
-
- >
- ) : null}
- >
- );
+ return (
+ <>
+ setIsOriginalCommentModalOpen(false)} comment={comment} />
+ {comment.edit && (
+ <>
+
+
+ (Edited at {timestamp},{' '}
+ setIsOriginalCommentModalOpen(true)}>
+ show original
+
+ )
+
+ >
+ )}
+ {(editedCommentState === 'pending' || editedCommentState === 'failed') && conditionsString ? (
+ <>
+
+
+ ({editedCommentState === 'pending' ? 'Pending' : 'Failed'} {conditionsString})
+
+ >
+ ) : null}
+ >
+ );
};
-export default EditLabel;
\ No newline at end of file
+export default EditLabel;
diff --git a/src/components/Embed.jsx b/src/components/Embed.jsx
index 67150c6e..59973474 100644
--- a/src/components/Embed.jsx
+++ b/src/components/Embed.jsx
@@ -1,96 +1,100 @@
-const Embed = ({url}) => {
- const parsedUrl = new URL(url);
+const Embed = ({ url }) => {
+ const parsedUrl = new URL(url);
- if (youtubeHosts.has(parsedUrl.host)) {
- return ;
- }
- if (twitterHosts.has(parsedUrl.host)) {
- return ;
- }
- if (redditHosts.has(parsedUrl.host)) {
- return ;
- }
- if (twitchHosts.has(parsedUrl.host)) {
- return ;
- }
- if (tiktokHosts.has(parsedUrl.host)) {
- return ;
- }
- if (instagramHosts.has(parsedUrl.host)) {
- return ;
- }
- if (odyseeHosts.has(parsedUrl.host)) {
- return ;
- }
- if (bitchuteHosts.has(parsedUrl.host)) {
- return ;
- }
- if (streamableHosts.has(parsedUrl.host)) {
- return ;
- }
- if (spotifyHosts.has(parsedUrl.host)) {
- return ;
- }
+ if (youtubeHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (twitterHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (redditHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (twitchHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (tiktokHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (instagramHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (odyseeHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (bitchuteHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (streamableHosts.has(parsedUrl.host)) {
+ return ;
+ }
+ if (spotifyHosts.has(parsedUrl.host)) {
+ return ;
+ }
};
const youtubeHosts = new Set(['youtube.com', 'www.youtube.com', 'youtu.be', 'www.youtu.be']);
-const YoutubeEmbed = ({parsedUrl}) => {
- let youtubeId;
- if (parsedUrl.host.endsWith('youtu.be')) {
- youtubeId = parsedUrl.pathname.replaceAll('/', '');
- }
- else {
- youtubeId = parsedUrl.searchParams.get('v');
- }
- return ;
+const YoutubeEmbed = ({ parsedUrl }) => {
+ let youtubeId;
+ if (parsedUrl.host.endsWith('youtu.be')) {
+ youtubeId = parsedUrl.pathname.replaceAll('/', '');
+ } else {
+ youtubeId = parsedUrl.searchParams.get('v');
+ }
+ return (
+
+ );
};
const twitterHosts = new Set(['twitter.com', 'www.twitter.com', 'x.com', 'www.x.com']);
-const TwitterEmbed = ({parsedUrl}) => {
- return