@@ -205,7 +295,7 @@ const PostFormTable = ({ closeForm }: { closeForm: () => void }) => {
ref={textRef}
onChange={(e) => {
const content = e.target.value.replace(/\n/g, '\n\n');
- isInPostView ? setContent.content(content) : setSubmitStore({ content });
+ isInPostView ? setPublishReplyOptions({ content }) : setSubmitStore({ content });
}}
/>
@@ -221,7 +311,7 @@ const PostFormTable = ({ closeForm }: { closeForm: () => void }) => {
ref={urlRef}
onChange={(e) => {
setUrl(e.target.value);
- isInPostView ? setContent.link(e.target.value) : setSubmitStore({ link: e.target.value });
+ isInPostView ? setPublishReplyOptions({ link: e.target.value }) : setSubmitStore({ link: e.target.value });
}}
/>
{url && }
@@ -232,7 +322,10 @@ const PostFormTable = ({ closeForm }: { closeForm: () => void }) => {
[
- (isInPostView ? setContent.spoiler(e.target.checked) : setSubmitStore({ spoiler: e.target.checked }))} />
+ (isInPostView ? setPublishReplyOptions({ spoiler: e.target.checked }) : setSubmitStore({ spoiler: e.target.checked }))}
+ />
{_.capitalize(t('spoiler'))}?
]
@@ -283,7 +376,7 @@ const PostForm = () => {
comment = editedComment;
}
- const { deleted, locked, removed } = comment || {};
+ const { deleted, locked, removed, postCid } = comment || {};
const isThreadClosed = deleted || locked || removed || isInDescriptionView || isInRulesView;
const [showForm, setShowForm] = useState(false);
@@ -310,7 +403,7 @@ const PostForm = () => {
]
) : (
- setShowForm(false)} />
+ setShowForm(false)} postCid={postCid} />
)}
@@ -326,7 +419,7 @@ const PostForm = () => {
setShowForm(showForm ? false : true)}>
{showForm ? t('close_post_form') : isInPostView ? t('post_a_reply') : t('start_new_thread')}
- {showForm &&
setShowForm(false)} />}
+ {showForm && setShowForm(false)} postCid={postCid} />}
>
)}
diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx
index 0eb84770..025b65e5 100644
--- a/src/components/post-mobile/post-mobile.tsx
+++ b/src/components/post-mobile/post-mobile.tsx
@@ -74,7 +74,7 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P
{!(isDescription || isRules) && (
<>
- {isReply && author?.avatar && (
+ {author?.avatar && (
@@ -127,7 +127,7 @@ const PostInfoAndMedia = ({ openReplyModal, post, postReplyCount = 0, roles }: P
!cid && e.preventDefault()}>
c/
- openReplyModal && openReplyModal(cid)}>
+ openReplyModal && openReplyModal(cid, postCid)}>
{shortCid}
>
@@ -164,6 +164,7 @@ const ReplyBacklinks = ({ post }: PostProps) => {
const PostMessageMobile = ({ post }: PostProps) => {
const { t } = useTranslation();
const { cid, content, deleted, edit, original, parentCid, postCid, reason, removed, state, subplebbitAddress } = post || {};
+ const { isDescription, isRules } = post || {}; // custom properties, not from api
// TODO: commentAuthor is not available outside of editedComment, update when available
// const banned = !!post?.commentAuthor?.banExpiresAt;
const [showOriginal, setShowOriginal] = useState(false);
@@ -202,7 +203,12 @@ const PostMessageMobile = ({ post }: PostProps) => {
{showOriginal && }
- {t('comment_edited_at_timestamp', { timestamp: getFormattedDate(edit?.timestamp), interpolation: { escapeValue: false } })}{' '}
+ >} /> }}
+ />{' '}
{reason && <>{t('reason_reason', { reason: reason, interpolation: { escapeValue: false } })} >}
{showOriginal ? (
{
{!isReply && content.length > 1000 && !isInPostView && (
- }} />
+ }}
+ />
)}
{!cid && state === 'pending' && stateString !== 'Failed' && (
diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx
index c8842b93..f320a9f8 100644
--- a/src/components/reply-modal/reply-modal.tsx
+++ b/src/components/reply-modal/reply-modal.tsx
@@ -1,29 +1,31 @@
-import { useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import Draggable from 'react-draggable';
-import { setAccount, useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks';
+import { setAccount, useAccount, useComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import { getFormattedTimeAgo } from '../../lib/utils/time-utils';
import { isValidURL } from '../../lib/utils/url-utils';
import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils';
import useSelectedTextStore from '../../stores/use-selected-text-store';
-import useReply from '../../hooks/use-reply';
+import usePublishReply from '../../hooks/use-publish-reply';
import useIsMobile from '../../hooks/use-is-mobile';
import styles from './reply-modal.module.css';
import { LinkTypePreviewer } from '../post-form';
import _ from 'lodash';
+import useAnonMode from '../../hooks/use-anon-mode';
interface ReplyModalProps {
closeModal: () => void;
parentCid: string;
+ postCid: string;
scrollY: number;
}
-const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
+const ReplyModal = ({ closeModal, parentCid, postCid, scrollY }: ReplyModalProps) => {
const { t } = useTranslation();
const { subplebbitAddress } = useParams() as { subplebbitAddress: string };
- const { setContent, publishReply } = useReply({ cid: parentCid, subplebbitAddress });
+ const { setPublishReplyOptions, publishReply } = usePublishReply({ cid: parentCid, subplebbitAddress });
const account = useAccount();
const { displayName } = account?.author || {};
const [url, setUrl] = useState('');
@@ -31,7 +33,38 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
const urlRef = useRef(null);
const { selectedText } = useSelectedTextStore();
- const onPublishReply = () => {
+ const { anonMode, getNewSigner, getExistingSigner } = useAnonMode(postCid);
+ const comment = useComment({ commentCid: postCid });
+ const address = comment?.author?.address;
+
+ const hasCalledAnonAddressRef = useRef(false);
+
+ const getAnonAddressForReply = useCallback(async () => {
+ if (anonMode && !hasCalledAnonAddressRef.current) {
+ hasCalledAnonAddressRef.current = true;
+ let signer = getExistingSigner(address);
+ if (!signer) {
+ signer = await getNewSigner();
+ if (signer) {
+ setPublishReplyOptions({
+ signer,
+ author: {
+ displayName,
+ address: signer.address,
+ },
+ });
+ }
+ }
+ }
+ }, [anonMode, address, getExistingSigner, getNewSigner, displayName, setPublishReplyOptions]);
+
+ useEffect(() => {
+ if (anonMode) {
+ getAnonAddressForReply();
+ }
+ }, [anonMode, getAnonAddressForReply]);
+
+ const onPublishReply = async () => {
const currentContent = textRef.current?.value || '';
const currentUrl = urlRef.current?.value || '';
@@ -44,6 +77,7 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
alert('The provided link is not a valid URL.');
return;
}
+
publishReply();
closeModal();
};
@@ -109,7 +143,7 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
// remove the prefix from the content to publish, and also add newlines for markdown
const contentWithoutPrefix = e.target.value.slice(contentPrefix.length).replace(/\n/g, '\n\n');
if (textRef.current && textRef.current.value !== contentWithoutPrefix) {
- setContent.content(contentWithoutPrefix);
+ setPublishReplyOptions({ content: contentWithoutPrefix });
}
};
@@ -142,7 +176,7 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
placeholder={_.capitalize(t('link'))}
onChange={(e) => {
setUrl(e.target.value);
- setContent.link(e.target.value);
+ setPublishReplyOptions({ link: e.target.value });
}}
/>
@@ -169,7 +203,7 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => {
[
- setContent.spoiler(e.target.checked)} />
+ setPublishReplyOptions({ spoiler: e.target.checked })} />
{_.capitalize(t('spoiler'))}?
]
diff --git a/src/components/settings-modal/account-settings/account-settings.module.css b/src/components/settings-modal/account-settings/account-settings.module.css
index 2371bb88..1fd66e37 100644
--- a/src/components/settings-modal/account-settings/account-settings.module.css
+++ b/src/components/settings-modal/account-settings/account-settings.module.css
@@ -36,11 +36,32 @@
}
.deleteAccount {
- color: red;
display: block;
- margin-top: 10px;
+}
+
+.deleteAccount:not(:disabled) {
+ color: red;
}
.setting .createAccount {
margin-left: 5px;
+}
+
+.settingTip {
+ display: block;
+ font-size: 0.85em;
+ margin: 2px 0 10px 0;
+ padding-left: 19px;
+}
+
+.anonMode {
+ padding: 10px 0;
+}
+
+.anonMode label {
+ text-transform: capitalize;
+}
+
+.anonMode input[type="checkbox"] {
+ margin-right: 3px;
}
\ No newline at end of file
diff --git a/src/components/settings-modal/account-settings/account-settings.tsx b/src/components/settings-modal/account-settings/account-settings.tsx
index df7e74b6..c8a48dc8 100644
--- a/src/components/settings-modal/account-settings/account-settings.tsx
+++ b/src/components/settings-modal/account-settings/account-settings.tsx
@@ -3,6 +3,21 @@ import { useTranslation } from 'react-i18next';
import { createAccount, deleteAccount, exportAccount, importAccount, setAccount, setActiveAccount, useAccount, useAccounts } from '@plebbit/plebbit-react-hooks';
import stringify from 'json-stringify-pretty-compact';
import styles from './account-settings.module.css';
+import useAnonModeStore from '../../../stores/use-anon-mode-store';
+
+const AnonMode = () => {
+ const anonMode = useAnonModeStore((state) => state.anonMode);
+ const setAnonMode = useAnonModeStore((state) => state.setAnonMode);
+
+ return (
+
+
+ setAnonMode(e.target.checked)} /> anon mode
+
+ Automatically use a different user ID in each thread
+
+ );
+};
const AccountSettings = () => {
const { t } = useTranslation();
@@ -167,7 +182,7 @@ const AccountSettings = () => {