diff --git a/package.json b/package.json
index 3b661da1..ebe49ab3 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"@babel/plugin-transform-react-jsx": "7.21.0",
"@capacitor/android": "3.6.0",
"@capacitor/core": "3.6.0",
- "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#5c5521672fac68ab00c83b96614445f7ccfd5b04",
+ "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#e741b0dad5bba65cf1f0896053f25cd91ed55cf1",
"@testing-library/dom": "9.0.1",
"@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "14.0.0",
diff --git a/src/components/BoardStats.jsx b/src/components/BoardStats.jsx
new file mode 100644
index 00000000..5f1adc98
--- /dev/null
+++ b/src/components/BoardStats.jsx
@@ -0,0 +1,38 @@
+import React from "react";
+import { 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});
+
+ return (
+
+
+
+
+
+ | In the past hour: {stats.hourActiveUserCount} users, {stats.hourPostCount} posts. Past day: {stats.dayActiveUserCount} users, {stats.dayPostCount} posts. |
+
+
+ |
+
+
+ | Past week: {stats.weekActiveUserCount} users, {stats.weekPostCount} posts. Past month: {stats.monthActiveUserCount} users, {stats.monthPostCount} posts. |
+
+
+ |
+
+
+ | Since inception: {stats.allActiveUserCount} users browsed; {stats.allPostCount} posts made. |
+
+
+
+
+ );
+};
+
+export default BoardStats;
\ No newline at end of file
diff --git a/src/components/ForwardRefLink.jsx b/src/components/ForwardRefLink.jsx
index 2e579e72..d66c9b51 100644
--- a/src/components/ForwardRefLink.jsx
+++ b/src/components/ForwardRefLink.jsx
@@ -3,7 +3,16 @@ import { Link } from "react-router-dom";
const ForwardRefLink = React.forwardRef((props, ref) => {
const { children, setRefAndCid, onMouseOver, onMouseLeave, onClick, ...otherProps } = props;
-
+
+ const handleClick = (event) => {
+ if (otherProps.to === "#void") {
+ event.preventDefault();
+ }
+ if (onClick) {
+ onClick(event);
+ }
+ };
+
useEffect(() => {
if (ref.current && typeof setRefAndCid === 'function') {
setRefAndCid(ref.current);
@@ -16,7 +25,7 @@ const ForwardRefLink = React.forwardRef((props, ref) => {
{...otherProps}
onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave}
- onClick={onClick}
+ onClick={handleClick}
>
{children}
diff --git a/src/components/Post.jsx b/src/components/Post.jsx
index 4d94e10c..16d3d6bd 100644
--- a/src/components/Post.jsx
+++ b/src/components/Post.jsx
@@ -74,7 +74,7 @@ const Post = ({ content, postQuoteOnClick, postQuoteOnOver, postQuoteOnLeave, po
const linkTarget = matchedText.startsWith('u/') ? "_blank" : "_self";
if (matchedText.startsWith('u/')) {
- linkTo = () => {};
+ linkTo = "#void";
} else if (matchedText.startsWith('p/') || matchedText.startsWith('p/')) {
linkTo = `/${matchedText}`;
}
diff --git a/src/components/StateLabel.jsx b/src/components/StateLabel.jsx
index 57e436f7..e3d55c36 100644
--- a/src/components/StateLabel.jsx
+++ b/src/components/StateLabel.jsx
@@ -6,11 +6,11 @@ const StateLabel = ({ commentIndex, className }) => {
const comment = useAccountComment({commentIndex: commentIndex});
const stateString = useStateString(comment);
- if (comment.updatedAt !== undefined) {
+ if (comment.updatedAt !== undefined || comment.index === undefined) {
return null;
}
- if (comment.state === "failed") {
+ if (comment.state === "failed" || comment.state === "succeeded") {
return null;
}
diff --git a/src/components/modals/SettingsModal.jsx b/src/components/modals/SettingsModal.jsx
index 9aee5831..892aa118 100755
--- a/src/components/modals/SettingsModal.jsx
+++ b/src/components/modals/SettingsModal.jsx
@@ -1,7 +1,7 @@
-import React, { useState, useEffect, useRef } from "react";
+import React, { useState, useEffect, useMemo, useRef } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import Modal from "react-modal";
-import { deleteAccount, deleteCaches, exportAccount, importAccount, setAccount, setActiveAccount, useAccount, useAccounts, useResolvedAuthorAddress } from "@plebbit/plebbit-react-hooks";
+import { deleteAccount, deleteCaches, importAccount, setAccount, setActiveAccount, useAccount, useAccounts, useResolvedAuthorAddress } from "@plebbit/plebbit-react-hooks";
import stringify from "json-stringify-pretty-compact"
import { StyledModal } from "../styled/modals/SettingsModal.styled";
import useError from "../../hooks/useError";
@@ -13,16 +13,12 @@ const {version} = packageJson;
const SettingsModal = ({ isOpen, closeModal }) => {
- const {
- selectedStyle,
- } = useGeneralStore(state => state);
-
+ const { selectedStyle } = useGeneralStore(state => state);
const { anonymousMode, setAnonymousMode } = useAnonModeStore();
-
const navigate = useNavigate();
const location = useLocation();
+
const [expanded, setExpanded] = useState([]);
- const [accountJson, setAccountJson] = useState("");
const [copyStatus, setCopyStatus] = useState(false);
const [ensName, setEnsName] = useState('');
const [checkedENS, setCheckedENS] = useState(false);
@@ -32,6 +28,9 @@ const SettingsModal = ({ isOpen, closeModal }) => {
const account = useAccount();
const { accounts } = useAccounts();
+ const accountJson = useMemo(() => stringify({...account}), [account])
+ const [editedAccountJson, setEditedAccountJson] = useState(accountJson);
+ useEffect(() => { setEditedAccountJson(accountJson)}, [accountJson])
const gatewayRef = useRef();
const ipfsRef = useRef();
@@ -47,7 +46,6 @@ const SettingsModal = ({ isOpen, closeModal }) => {
const author = {...account?.author, address: ensName};
const { resolvedAddress, state } = useResolvedAuthorAddress({ author, cache: false });
-
const defaultGatewayUrls = isElectron ? undefined : [
'https://ipfs.io',
'https://ipfsgateway.xyz',
@@ -71,36 +69,6 @@ const SettingsModal = ({ isOpen, closeModal }) => {
];
- useEffect(() => {
- if (account) {
- const fetchAccountData = async () => {
- const data = await exportAccount();
- try {
- const parsedData = JSON.parse(data);
- setAccountJson(stringify(parsedData));
- } catch (error) {
- console.error("Failed to pretty-print the JSON:", error);
- setAccountJson(data);
- }
- };
- fetchAccountData();
- }
- }, [account]);
-
-
-
- const handleAccountJsonChange = (e) => {
- try {
- const parsedData = JSON.parse(e.target.value);
- setAccountJson(stringify(parsedData));
- } catch (error) {
- console.error("Failed to pretty-print the JSON:", error);
- setAccountJson(e.target.value);
- }
- };
-
-
-
useEffect(() => {
if (checkedENS && resolvedAddress && state === 'succeeded') {
setCheckedENS(false);
@@ -130,7 +98,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
address: ensName,
},
});
- setNewSuccessMessage("ENS Name Saved");
+ setNewSuccessMessage("ENS name saved successfully.");
} catch (error) {
setNewErrorMessage(error.message);
@@ -214,7 +182,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
try {
await setAccount({ ...account, plebbitOptions });
- localStorage.setItem("successToast", "Settings Saved");
+ localStorage.setItem("successToast", "Settings saved successfully.");
window.location.reload();
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
@@ -263,7 +231,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
chainProviders,
},
});
- localStorage.setItem("successToast", "Blockchain Options Saved");
+ localStorage.setItem("successToast", "Blockchain options saved successfully.");
window.location.reload();
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
@@ -289,7 +257,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
pubsubHttpClientsOptions: defaultPubsubHttpClientsOptions,
},
});
- localStorage.setItem("successToast", "Settings Reset");
+ localStorage.setItem("successToast", "Settings reset successfully.");
window.location.reload();
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
@@ -323,7 +291,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
chainProviders,
},
});
- localStorage.setItem("successToast", "Blockchain Options Reset");
+ localStorage.setItem("successToast", "Blockchain options reset successfully.");
window.location.reload();
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
@@ -367,7 +335,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
useEffect(() => {
if (localStorage.getItem("cacheCleared") === "true") {
- setNewSuccessMessage("Cache Cleared");
+ setNewSuccessMessage("Cache cleared successfully.");
localStorage.removeItem("cacheCleared");
}
}, [setNewSuccessMessage]);
@@ -375,9 +343,9 @@ const SettingsModal = ({ isOpen, closeModal }) => {
const handleSaveAccount = async () => {
try {
- const parsedJson = JSON.parse(accountJson);
+ const parsedJson = JSON.parse(editedAccountJson);
await setAccount(parsedJson);
- setNewSuccessMessage("Account Data Saved Successfully");
+ setNewSuccessMessage("Account data saved successfully.");
} catch (error) {
setNewErrorMessage("Error saving account data: " + error.message);
console.error(error);
@@ -385,25 +353,14 @@ const SettingsModal = ({ isOpen, closeModal }) => {
};
- const handleResetAccount = async () => {
- try {
- const data = await exportAccount();
- setAccountJson(data);
- } catch (error) {
- setNewErrorMessage("Error resetting account data: " + error.message);
- console.error(error);
- }
- };
-
-
const handleImportAccount = async () => {
- const accountJson = importRef.current.value;
+ const data = importRef.current.value;
try {
- const parsedJson = JSON.parse(accountJson);
- await importAccount(accountJson);
+ const parsedJson = JSON.parse(data);
+ await importAccount(data);
setActiveAccount(parsedJson.account?.name);
- setNewSuccessMessage("Account Imported");
+ setNewSuccessMessage("Account imported successfully.");
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
@@ -415,7 +372,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
if (window.confirm("Are you sure you want to delete this account?")) {
try {
await deleteAccount(account?.name);
- localStorage.setItem("successToast", "Account Deleted Successfully");
+ localStorage.setItem("successToast", "Account deleted successfully.");
window.location.reload();
} catch (error) {
setNewErrorMessage("Error deleting account: " + error.message);
@@ -440,7 +397,7 @@ const SettingsModal = ({ isOpen, closeModal }) => {
...account?.author,
displayName: name,
}});
- setNewSuccessMessage("Account Name Saved");
+ setNewSuccessMessage("Account name saved successfully.");
} catch (error) {
setNewErrorMessage(error.message); console.log(error);
}
@@ -514,9 +471,9 @@ const SettingsModal = ({ isOpen, closeModal }) => {