Skip to content

Commit

Permalink
refactor: posting comments effects
Browse files Browse the repository at this point in the history
  • Loading branch information
cswni committed Dec 17, 2024
1 parent 2e12a99 commit d561dc9
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 84 deletions.
32 changes: 18 additions & 14 deletions src/redux/comments/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { AnyPublication } from '@lens-protocol/api-bindings';

type PendingComment = AnyPublication & { uri: string };

export type CommentsReducerState = {
refetchTriggerByPublication: {
[publicationId: string]: number;
};
hiddenComments: AnyPublication[];
counterLikes: { [publicationId: string]: number };
comments: { [publicationId: string]: AnyPublication[] };
pendingComments: { [publicationId: string]: AnyPublication[] };
pendingComments: { [publicationId: string]: PendingComment[] };
};

const initialState: CommentsReducerState = {
Expand Down Expand Up @@ -49,25 +51,28 @@ const commentsSlice = createSlice({
state.counterLikes[publicationId] -= 1;
}
},
addComment: (state, action: PayloadAction<{ publicationId: string; comment: AnyPublication }>) => {
const { publicationId, comment } = action.payload;
if (!state.comments[publicationId]) {
state.comments[publicationId] = [];
}
state.comments[publicationId].push(comment);
},
addPendingComment: (state, action: PayloadAction<{ publicationId: string; comment: AnyPublication }>) => {

addPendingComment: (state, action: PayloadAction<{ publicationId: string; comment: PendingComment }>) => {
const { publicationId, comment } = action.payload;
if (!state.pendingComments[publicationId]) {
state.pendingComments[publicationId] = [];
}
// Prepend new comment to the beginning of the list
state.pendingComments[publicationId] = [comment, ...state.pendingComments[publicationId]];
},
updateCommentStatus: (state, action: PayloadAction<{ publicationId: string; commentId: string; status: string }>) => {
const { publicationId, commentId, status } = action.payload;
removePendingComment: (state, action: PayloadAction<{ publicationId: string; commentId: string;}>) => {
console.log('publicationID', action.payload.publicationId);
console.log('commentID', action.payload.commentId);

const { publicationId, commentId } = action.payload;
const comment = state.comments[publicationId]?.find(comment => comment.id === commentId);
state.comments[publicationId] = state.comments[publicationId].filter(comment => comment.id !== commentId);

console.log('comment', comment);

// Delete the comment from the pending list
state.pendingComments[publicationId] = state.pendingComments[publicationId].filter(comment => comment.id !== commentId);

// Search by uuid and delete from state

},
},
Expand All @@ -79,9 +84,8 @@ export const {
setCounterLikes,
incrementCounterLikes,
decrementCounterLikes,
addComment,
addPendingComment,
updateCommentStatus,
removePendingComment,
} = commentsSlice.actions;

export default commentsSlice.reducer;
103 changes: 103 additions & 0 deletions src/sections/publication/NeonPaperContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {FC, ReactNode} from "react";

import { Paper, styled } from '@mui/material';
import {PaperProps} from "@mui/material/Paper";
import {SxProps, Theme} from "@mui/material/styles";
import {COLORS} from "@src/layouts/config-layout.ts";

interface NeonPaperProps {
children: ReactNode;
colors?: string[];
animationSpeed?: string;
sx?: SxProps<Theme>;
}

const NeonPaperContainer = styled(Paper, {
shouldForwardProp: (prop) => prop !== 'colors' && prop !== 'animationSpeed',
})<PaperProps & {colors?: string[], animationSpeed?: string} >(({ colors, animationSpeed }) => ({
'--gradient-pos-x': '50%',
'--gradient-pos-y': '50%',
'--border-radius': '10px',
'--border-gap': '3px',
width: '100%',
position: 'relative',
padding: 'var(--border-gap)',
borderRadius: 'var(--border-radius)',
cursor: 'pointer',
overflow: 'hidden',
'&:hover .gradient': {
animation: `rotate ${animationSpeed || '1s'} linear infinite`,
},
'& .content': {
position: 'relative',
padding: '1rem',
color: '#ffffff',
borderRadius: 'var(--border-radius)',
backgroundColor: `${COLORS.GRAY_LIGHT}`,
zIndex: 1,
width: '100%',
},
'& .border, & .neon': {
position: 'absolute',
width: '100%',
height: '100%',
top: 0,
left: 0,
borderRadius: 'var(--border-radius)',
overflow: 'hidden',
},
'& .neon': {
filter: 'blur(10px)',
opacity: 0.5,
},
'& .gradient': {
position: 'absolute',
inset: '-200px',
background: `conic-gradient(
from 0deg at var(--gradient-pos-x) var(--gradient-pos-y),
${colors?.join(', ') || '#1e87ff, #5c13c4, #ff0033, #ffda00, #64bc26, #1e87ff'}
)`,
borderRadius: 'var(--border-radius)',
animation: `rotate ${animationSpeed || '1s'} linear infinite`,
},
'@keyframes rotate': {
'0%': { transform: 'rotate(0deg)' },
'100%': { transform: 'rotate(360deg)' },
},
}));

const NeonPaper: FC<NeonPaperProps> = ({ children, colors, animationSpeed }) => {
const handleMouseMove = (e) => {
const rect = e.target.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;

e.target.style.setProperty('--gradient-pos-x', `${x}%`);
e.target.style.setProperty('--gradient-pos-y', `${y}%`);
};

const handleMouseOut = (e) => {
e.target.style.setProperty('--gradient-pos-x', '50%');
e.target.style.setProperty('--gradient-pos-y', '50%');
};

return (
<NeonPaperContainer
elevation={3}
onMouseMove={handleMouseMove}
onMouseOut={handleMouseOut}
colors={colors}
animationSpeed={animationSpeed}
>
<div className="neon">
<div className="gradient"></div>
</div>
<div className="border">
<div className="gradient"></div>
</div>
<div className="content">{children}</div>
</NeonPaperContainer>
);
};

export default NeonPaper;
135 changes: 72 additions & 63 deletions src/sections/publication/publication-comment-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
decrementCounterLikes,
setCounterLikes,
} from '@redux/comments';
import NeonPaperContainer from "@src/sections/publication/NeonPaperContainer.tsx";

// Components Lazy
const LazyPopover = lazy(() => import('@mui/material/Popover'));
Expand All @@ -60,6 +61,8 @@ type Props = {
};

export default function PublicationCommentItem({ comment, hasReply, canReply }: Props) {
const isPendingComment = comment?.uri

const [openConfirmModal, setOpenConfirmModal] = useState(false);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const openMenu = Boolean(anchorEl);
Expand Down Expand Up @@ -161,7 +164,7 @@ export default function PublicationCommentItem({ comment, hasReply, canReply }:
}}
/>

{sessionData?.authenticated && comment?.by?.id === sessionData?.profile?.id && (
{sessionData?.authenticated && comment?.by?.id === sessionData?.profile?.id && !isPendingComment && (
<Button
variant="text"
sx={{
Expand Down Expand Up @@ -218,7 +221,9 @@ export default function PublicationCommentItem({ comment, hasReply, canReply }:
)}
</Suspense>

<Paper
<NeonPaperContainer
colors={['#1e87ff', '#5c13c4', '#ff0033', '#ffda00', '#64bc26', '#1e87ff']}
animationSpeed={'2s'}
sx={{
p: 1.5,
pt: 0.7,
Expand All @@ -242,73 +247,77 @@ export default function PublicationCommentItem({ comment, hasReply, canReply }:
<Box sx={{ typography: 'body2', color: 'text.secondary' }}>
{comment?.metadata?.content}
</Box>
</Paper>
</NeonPaperContainer>
</Stack>
<Box sx={{ display: 'flex', pl: 7 }}>
<Button
variant="text"
sx={{
borderColor: '#FFFFFF',
color: '#FFFFFF',
height: '30px',
minWidth: '40px',
}}
onClick={toggleReaction}
disabled={loadingLike}
>
{loadingLike ? (
<CircularProgress size="25px" sx={{ color: '#fff' }} />
) : (
<>
{hasLiked ? (
<IconHeartFilled size={22} color="#FFFFFF" />
) : (
<IconHeart size={22} color="#FFFFFF" />
)}
<Typography
variant="body2"
sx={{
lineHeight: 1,
ml: 1,
fontWeight: '700',
}}
>
{likes}
</Typography>
</>
)}
</Button>
{canReply && (
<Button
variant="text"
sx={{
borderColor: '#FFFFFF',
color: '#FFFFFF',
height: '30px',
minWidth: '40px',
}}
onClick={() => setShowComments(!showComments)}
>
<>
{showComments ? (
<IconMessageCircleFilled size={22} color="#FFFFFF" />

<Box sx={{ display: 'flex', pl: 7 }}>
<Button
variant="text"
sx={{
borderColor: '#FFFFFF',
color: '#FFFFFF',
height: '30px',
minWidth: '40px',
}}
onClick={toggleReaction}
disabled={loadingLike || isPendingComment}
>
{loadingLike ? (
<CircularProgress size="25px" sx={{ color: '#fff' }} />
) : (
<IconMessageCircle size={22} color="#FFFFFF" />
<>
{hasLiked ? (
<IconHeartFilled size={22} color="#FFFFFF" />
) : (
<IconHeart size={22} color="#FFFFFF" />
)}
<Typography
variant="body2"
sx={{
lineHeight: 1,
ml: 1,
fontWeight: '700',
}}
>
{likes}
</Typography>
</>
)}
<Typography
variant="body2"
</Button>
{canReply && (
<Button
disabled={isPendingComment }
variant="text"
sx={{
lineHeight: 1,
ml: 1,
fontWeight: '700',
borderColor: '#FFFFFF',
color: '#FFFFFF',
height: '30px',
minWidth: '40px',
}}
onClick={() => setShowComments(!showComments)}
>
{comment?.stats?.comments}
</Typography>
</>
</Button>
)}
</Box>
<>
{showComments ? (
<IconMessageCircleFilled size={22} color="#FFFFFF" />
) : (
<IconMessageCircle size={22} color="#FFFFFF" />
)}
<Typography
variant="body2"
sx={{
lineHeight: 1,
ml: 1,
fontWeight: '700',
}}
>
{comment?.stats?.comments}
</Typography>
</>
</Button>
)}
</Box>


</Stack>
{showComments && (
<>
Expand Down
Loading

0 comments on commit d561dc9

Please sign in to comment.