Merge pull request #600 from plebbit/development

Development
This commit is contained in:
Tom (plebeius.eth)
2024-11-10 12:58:27 +01:00
committed by GitHub
4 changed files with 66 additions and 48 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"dependencies": { "dependencies": {
"@capacitor/app": "6.0.1", "@capacitor/app": "6.0.1",
"@floating-ui/react": "0.26.1", "@floating-ui/react": "0.26.1",
"@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#de80441257496942063bf032d48e955b7f812937", "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#0d4219ad95c3322eac78db23091eb57239be8776",
"@testing-library/jest-dom": "5.14.1", "@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "13.0.0", "@testing-library/react": "13.0.0",
"@testing-library/user-event": "13.2.1", "@testing-library/user-event": "13.2.1",
+60 -40
View File
@@ -1,7 +1,14 @@
import { useEffect, useState, useMemo, useCallback } from 'react'; import { useEffect, useState, useMemo, useCallback } from 'react';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import { autoUpdate, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react'; import { autoUpdate, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
import { Comment, PublishCommentEditOptions, useAccount, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks'; import {
Comment,
PublishCommentEditOptions,
useAccount,
usePublishCommentEdit,
usePublishCommentModeration,
PublishCommentModerationOptions,
} from '@plebbit/plebbit-react-hooks';
import styles from './edit-menu.module.css'; import styles from './edit-menu.module.css';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils'; import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
import useChallengesStore from '../../stores/use-challenges-store'; import useChallengesStore from '../../stores/use-challenges-store';
@@ -27,7 +34,7 @@ const timestampToDays = (timestamp: number) => {
const EditMenu = ({ post }: { post: Comment }) => { const EditMenu = ({ post }: { post: Comment }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { author, cid, commentAuthor, content, deleted, locked, parentCid, pinned, postCid, reason, removed, spoiler, subplebbitAddress } = post || {}; const { author, cid, content, deleted, locked, parentCid, pinned, postCid, reason, removed, spoiler, subplebbitAddress } = post || {};
const isReply = parentCid; const isReply = parentCid;
const [isEditMenuOpen, setIsEditMenuOpen] = useState(false); const [isEditMenuOpen, setIsEditMenuOpen] = useState(false);
const [isContentEditorOpen, setIsContentEditorOpen] = useState(false); const [isContentEditorOpen, setIsContentEditorOpen] = useState(false);
@@ -49,7 +56,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
if (author?.address !== account?.author?.address) { if (author?.address !== account?.author?.address) {
// Check for existing thread signer first // Check for existing thread signer first
const threadSigner = getThreadSigner(postCid); const threadSigner = getThreadSigner(postCid);
if (threadSigner && threadSigner.address === author?.address) { if (threadSigner && threadSigner?.address === author?.address) {
setSigner(threadSigner); setSigner(threadSigner);
return; return;
} }
@@ -80,16 +87,23 @@ const EditMenu = ({ post }: { post: Comment }) => {
const defaultPublishEditOptions = useMemo(() => { const defaultPublishEditOptions = useMemo(() => {
return { return {
commentAuthor: !isCommentAuthorMod && isAccountMod && !isAccountCommentAuthor ? commentAuthor : undefined,
commentCid: cid, commentCid: cid,
subplebbitAddress,
// Author edit properties
content: isAccountCommentAuthor ? content : undefined, content: isAccountCommentAuthor ? content : undefined,
deleted: isAccountCommentAuthor ? deleted ?? false : undefined, deleted: isAccountCommentAuthor ? deleted ?? false : undefined,
locked: isAccountMod ? locked ?? false : undefined, spoiler: isAccountCommentAuthor ? spoiler ?? false : undefined,
pinned: isAccountMod ? pinned ?? false : undefined, // Mod edit properties
reason, commentModeration: isAccountMod
removed: isAccountMod ? removed ?? false : undefined, ? {
locked: locked ?? false,
pinned: pinned ?? false,
removed: removed ?? false,
spoiler: spoiler ?? false, spoiler: spoiler ?? false,
subplebbitAddress, reason,
banExpiresAt: post?.commentModeration?.banExpiresAt,
}
: undefined,
onChallenge: (...args: any) => addChallenge([...args, post]), onChallenge: (...args: any) => addChallenge([...args, post]),
onChallengeVerification: alertChallengeVerificationFailed, onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => { onError: (error: Error) => {
@@ -97,7 +111,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
alert('Comment edit failed. ' + error.message); alert('Comment edit failed. ' + error.message);
}, },
}; };
}, [isAccountMod, isAccountCommentAuthor, commentAuthor, cid, content, deleted, locked, pinned, reason, removed, spoiler, subplebbitAddress, post, isCommentAuthorMod]); }, [isAccountMod, isAccountCommentAuthor, cid, content, deleted, locked, pinned, reason, removed, spoiler, subplebbitAddress, post]);
const [publishCommentEditOptions, setPublishCommentEditOptions] = useState<PublishCommentEditOptions>(defaultPublishEditOptions); const [publishCommentEditOptions, setPublishCommentEditOptions] = useState<PublishCommentEditOptions>(defaultPublishEditOptions);
@@ -106,13 +120,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
commentCid: cid, commentCid: cid,
subplebbitAddress, subplebbitAddress,
signer, signer,
author: author: signer?.address === author?.address ? { address: signer?.address, displayName: post?.author?.displayName } : account?.author,
signer && signer.address === author?.address
? {
address: signer.address,
displayName: post?.author?.displayName,
}
: account?.author,
content: publishCommentEditOptions.content, content: publishCommentEditOptions.content,
deleted: publishCommentEditOptions.deleted, deleted: publishCommentEditOptions.deleted,
reason: publishCommentEditOptions.reason, reason: publishCommentEditOptions.reason,
@@ -127,47 +135,59 @@ const EditMenu = ({ post }: { post: Comment }) => {
[publishCommentEditOptions, cid, subplebbitAddress, signer, post, account?.author, author?.address], [publishCommentEditOptions, cid, subplebbitAddress, signer, post, account?.author, author?.address],
); );
const modEditOptions = useMemo<PublishCommentEditOptions>( const modEditOptions = useMemo<PublishCommentModerationOptions>(
() => ({ () => ({
commentCid: cid, commentCid: cid,
subplebbitAddress, subplebbitAddress,
locked: parentCid === undefined ? publishCommentEditOptions.locked : undefined, commentModeration: {
pinned: publishCommentEditOptions.pinned, locked: parentCid === undefined ? publishCommentEditOptions.commentModeration?.locked : undefined,
removed: publishCommentEditOptions.removed, pinned: publishCommentEditOptions.commentModeration?.pinned,
removed: publishCommentEditOptions.commentModeration?.removed,
spoiler: publishCommentEditOptions.commentModeration?.spoiler,
reason: publishCommentEditOptions.reason, reason: publishCommentEditOptions.reason,
commentAuthor: !isCommentAuthorMod ? publishCommentEditOptions.commentAuthor : undefined, banExpiresAt: publishCommentEditOptions.commentModeration?.banExpiresAt,
},
author: account?.author, author: account?.author,
onChallenge: (...args: any) => addChallenge([...args, post]), onChallenge: (...args: any) => addChallenge([...args, post]),
onChallengeVerification: alertChallengeVerificationFailed, onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => { onError: (error: Error) => {
console.warn(error); console.warn(error);
alert('Comment edit failed. ' + error.message); alert('Comment moderation failed. ' + error.message);
}, },
}), }),
[publishCommentEditOptions, cid, subplebbitAddress, isCommentAuthorMod, post, account?.author, parentCid], [publishCommentEditOptions, cid, subplebbitAddress, post, account?.author, parentCid],
); );
const { publishCommentEdit: publishAuthorEdit } = usePublishCommentEdit(authorEditOptions); const { publishCommentEdit: publishAuthorEdit } = usePublishCommentEdit(authorEditOptions);
const { publishCommentEdit: publishModEdit } = usePublishCommentEdit(modEditOptions); const { publishCommentModeration } = usePublishCommentModeration(modEditOptions);
useEffect(() => { useEffect(() => {
setPublishCommentEditOptions(defaultPublishEditOptions); setPublishCommentEditOptions(defaultPublishEditOptions);
}, [defaultPublishEditOptions]); }, [defaultPublishEditOptions]);
const [banDuration, setBanDuration] = useState(() => const [banDuration, setBanDuration] = useState(() =>
publishCommentEditOptions.commentAuthor?.banExpiresAt ? timestampToDays(publishCommentEditOptions.commentAuthor.banExpiresAt) : 1, publishCommentEditOptions.commentModeration?.banExpiresAt ? timestampToDays(publishCommentEditOptions.commentModeration.banExpiresAt) : 1,
); );
const onCheckbox = (e: React.ChangeEvent<HTMLInputElement>) => { const onCheckbox = (e: React.ChangeEvent<HTMLInputElement>) => {
const { id, checked } = e.target; const { id, checked } = e.target;
if (id === 'banUser') {
setPublishCommentEditOptions((state) => ({ setPublishCommentEditOptions((state) => {
...state, const newState = { ...state };
commentAuthor: { ...state.commentAuthor, banExpiresAt: checked ? daysToTimestampInSeconds(banDuration) : undefined },
})); if (isAccountMod) {
} else { newState.commentModeration = {
setPublishCommentEditOptions((state) => ({ ...state, [id]: checked })); ...newState.commentModeration,
[id === 'banUser' ? 'banExpiresAt' : id]: id === 'banUser' ? (checked ? daysToTimestampInSeconds(banDuration) : undefined) : checked,
};
} }
if (isAccountCommentAuthor) {
newState[id] = checked;
}
return newState;
});
}; };
const onBanDurationChange = (e: React.ChangeEvent<HTMLInputElement>) => { const onBanDurationChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -199,11 +219,11 @@ const EditMenu = ({ post }: { post: Comment }) => {
try { try {
if (isAccountCommentAuthor && isAccountMod) { if (isAccountCommentAuthor && isAccountMod) {
await publishAuthorEdit(); await publishAuthorEdit();
await publishModEdit(); await publishCommentModeration();
} else if (isAccountCommentAuthor) { } else if (isAccountCommentAuthor) {
await publishAuthorEdit(); await publishAuthorEdit();
} else if (isAccountMod) { } else if (isAccountMod) {
await publishModEdit(); await publishCommentModeration();
} }
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
@@ -258,7 +278,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
<div className={styles.menuItem}> <div className={styles.menuItem}>
<label> <label>
[ [
<input onChange={onCheckbox} checked={publishCommentEditOptions.removed ?? false} type='checkbox' id='removed' /> <input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.removed ?? false} type='checkbox' id='removed' />
{_.capitalize(t('remove'))}?] {_.capitalize(t('remove'))}?]
</label> </label>
</div> </div>
@@ -266,7 +286,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
<div className={styles.menuItem}> <div className={styles.menuItem}>
[ [
<label> <label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.locked ?? false} type='checkbox' id='locked' /> <input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.locked ?? false} type='checkbox' id='locked' />
{_.capitalize(t('close_thread'))}? {_.capitalize(t('close_thread'))}?
</label> </label>
] ]
@@ -275,7 +295,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
<div className={styles.menuItem}> <div className={styles.menuItem}>
[ [
<label> <label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.spoiler ?? false} type='checkbox' id='spoiler' /> <input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.spoiler ?? false} type='checkbox' id='spoiler' />
{_.capitalize(t('spoiler'))}? {_.capitalize(t('spoiler'))}?
</label> </label>
] ]
@@ -283,7 +303,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
<div className={styles.menuItem}> <div className={styles.menuItem}>
[ [
<label> <label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.pinned ?? false} type='checkbox' id='pinned' /> <input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.pinned ?? false} type='checkbox' id='pinned' />
{_.capitalize(t('sticky'))}? {_.capitalize(t('sticky'))}?
</label> </label>
] ]
@@ -292,7 +312,7 @@ const EditMenu = ({ post }: { post: Comment }) => {
<div className={styles.menuItem}> <div className={styles.menuItem}>
[ [
<label> <label>
<input onChange={onCheckbox} checked={publishCommentEditOptions.commentAuthor?.banExpiresAt !== undefined} type='checkbox' id='banUser' /> <input onChange={onCheckbox} checked={publishCommentEditOptions.commentModeration?.banExpiresAt !== undefined} type='checkbox' id='banUser' />
<Trans <Trans
i18nKey='ban_user_for' i18nKey='ban_user_for'
shouldUnescape={true} shouldUnescape={true}
@@ -18,8 +18,6 @@ interface ReplyQuotePreviewProps {
const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => { const handleQuoteHover = (cid: string, onElementOutOfView: () => void) => {
const targetElements = document.querySelectorAll(`[data-cid="${cid}"]`); const targetElements = document.querySelectorAll(`[data-cid="${cid}"]`);
if (targetElements.length === 0) return;
const isInViewport = (element: HTMLElement) => { const isInViewport = (element: HTMLElement) => {
const bounding = element.getBoundingClientRect(); const bounding = element.getBoundingClientRect();
return ( return (
+2 -2
View File
@@ -3338,9 +3338,9 @@
dependencies: dependencies:
debug "4.3.4" debug "4.3.4"
"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#de80441257496942063bf032d48e955b7f812937": "@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#0d4219ad95c3322eac78db23091eb57239be8776":
version "0.0.1" version "0.0.1"
resolved "https://github.com/plebbit/plebbit-react-hooks.git#de80441257496942063bf032d48e955b7f812937" resolved "https://github.com/plebbit/plebbit-react-hooks.git#0d4219ad95c3322eac78db23091eb57239be8776"
dependencies: dependencies:
"@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#20b3c91b30a589ea5728f9a20f61e63700fe0dd4" "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#20b3c91b30a589ea5728f9a20f61e63700fe0dd4"
"@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git"