diff --git a/src/components/Group/AddGroup.tsx b/src/components/Group/AddGroup.tsx index 470cd3f..91552cb 100644 --- a/src/components/Group/AddGroup.tsx +++ b/src/components/Group/AddGroup.tsx @@ -91,7 +91,7 @@ export const AddGroup = ({ address, open, setOpen }) => { if (!name) throw new Error('Please provide a name'); if (!description) throw new Error('Please provide a description'); - const fee = await getFee('CREATE_GROUP'); + const fee = await getFee('CREATE_GROUP'); // TODO translate await show({ message: 'Would you like to perform an CREATE_GROUP transaction?', publishFee: fee.fee + ' QORT', diff --git a/src/components/Group/AddGroupList.tsx b/src/components/Group/AddGroupList.tsx index 433d0e4..b80cc34 100644 --- a/src/components/Group/AddGroupList.tsx +++ b/src/components/Group/AddGroupList.tsx @@ -101,7 +101,7 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => { const handleJoinGroup = async (group, isOpen) => { try { const groupId = group.groupId; - const fee = await getFee('JOIN_GROUP'); + const fee = await getFee('JOIN_GROUP'); // TODO translate await show({ message: 'Would you like to perform an JOIN_GROUP transaction?', publishFee: fee.fee + ' QORT', diff --git a/src/components/Group/BlockedUsersModal.tsx b/src/components/Group/BlockedUsersModal.tsx index b2d58e7..80d9c4c 100644 --- a/src/components/Group/BlockedUsersModal.tsx +++ b/src/components/Group/BlockedUsersModal.tsx @@ -129,7 +129,7 @@ export const BlockedUsersModal = () => { executeEvent('updateChatMessagesWithBlocks', true); } } catch (error) { - setOpenSnackGlobal(true); + setOpenSnackGlobal(true); // TODO translate setInfoSnackCustom({ type: 'error', message: error?.message || 'Unable to block user', diff --git a/src/components/Group/Forum/DisplayHtml.tsx b/src/components/Group/Forum/DisplayHtml.tsx index 5bae4a7..786672a 100644 --- a/src/components/Group/Forum/DisplayHtml.tsx +++ b/src/components/Group/Forum/DisplayHtml.tsx @@ -1,21 +1,20 @@ -import { useMemo } from "react"; -import DOMPurify from "dompurify"; -import "react-quill/dist/quill.snow.css"; -import "react-quill/dist/quill.core.css"; -import "react-quill/dist/quill.bubble.css"; -import { Box, styled } from "@mui/material"; -import { convertQortalLinks } from "../../../utils/qortalLink"; - +import { useMemo } from 'react'; +import DOMPurify from 'dompurify'; +import 'react-quill/dist/quill.snow.css'; +import 'react-quill/dist/quill.core.css'; +import 'react-quill/dist/quill.bubble.css'; +import { Box, styled } from '@mui/material'; +import { convertQortalLinks } from '../../../utils/qortalLink'; const CrowdfundInlineContent = styled(Box)(({ theme }) => ({ - display: "flex", - fontFamily: "Mulish", - fontSize: "19px", - fontWeight: 400, - letterSpacing: 0, - color: theme.palette.text.primary, - width: '100%' - })); + display: 'flex', + fontFamily: 'Mulish', + fontSize: '19px', + fontWeight: 400, + letterSpacing: 0, + color: theme.palette.text.primary, + width: '100%', +})); export const DisplayHtml = ({ html, textColor }: any) => { const cleanContent = useMemo(() => { @@ -29,6 +28,7 @@ export const DisplayHtml = ({ html, textColor }: any) => { }, [html]); if (!cleanContent) return null; + return (
{ style={{ color: textColor || 'white', fontWeight: 400, - fontSize: '16px' + fontSize: '16px', }} dangerouslySetInnerHTML={{ __html: cleanContent }} /> diff --git a/src/components/Group/Forum/GroupMail.tsx b/src/components/Group/Forum/GroupMail.tsx index 544634b..3c8972f 100644 --- a/src/components/Group/Forum/GroupMail.tsx +++ b/src/components/Group/Forum/GroupMail.tsx @@ -45,7 +45,6 @@ import { formatDate, formatTimestamp } from '../../../utils/time'; import LazyLoad from '../../../common/LazyLoad'; import { delay } from '../../../utils/helpers'; import { NewThread } from './NewThread'; -import { getBaseApi } from '../../../background'; import { decryptPublishes, getTempPublish, @@ -55,15 +54,11 @@ import CheckSVG from '../../../assets/svgs/Check.svg'; import SortSVG from '../../../assets/svgs/Sort.svg'; import ArrowDownSVG from '../../../assets/svgs/ArrowDown.svg'; import { LoadingSnackbar } from '../../Snackbar/LoadingSnackbar'; -import { - executeEvent, - subscribeToEvent, - unsubscribeFromEvent, -} from '../../../utils/events'; +import { executeEvent } from '../../../utils/events'; import RefreshIcon from '@mui/icons-material/Refresh'; import { getArbitraryEndpointReact, getBaseApiReact } from '../../../App'; -import { WrapperUserAction } from '../../WrapperUserAction'; import { addDataPublishesFunc, getDataPublishesFunc } from '../Group'; + const filterOptions = ['Recently active', 'Newest', 'Oldest']; export const threadIdentifier = 'DOCUMENT'; @@ -183,7 +178,7 @@ export const GroupMail = ({ }); }); } catch (error) { - } finally { + console.log(error); } }; @@ -266,7 +261,6 @@ export const GroupMail = ({ } else { sorted = fullArrayMsg.sort((a: any, b: any) => a.created - b.created); } - setAllThreads(sorted); } catch (error) { console.log({ error }); @@ -376,6 +370,7 @@ export const GroupMail = ({ ); setRecentThreads(sorted); } catch (error) { + console.log(error); } finally { setIsLoading(false); // dispatch(setIsLoadingCustom(null)); @@ -444,7 +439,6 @@ export const GroupMail = ({ } } } - setMembers(members); } catch (error) { console.log({ error }); @@ -754,7 +748,9 @@ export const GroupMail = ({ > {thread?.threadData?.title} + + {filterMode === 'Recently active' && (
Last page diff --git a/src/components/Group/Forum/Mail-styles.ts b/src/components/Group/Forum/Mail-styles.ts index 534304d..368e4cb 100644 --- a/src/components/Group/Forum/Mail-styles.ts +++ b/src/components/Group/Forum/Mail-styles.ts @@ -1,52 +1,47 @@ -import { - AppBar, - Button, - Toolbar, - Typography, - Box, - TextField, -} from "@mui/material"; -import { styled } from "@mui/system"; +import { Typography, Box, TextField } from '@mui/material'; +import { styled } from '@mui/system'; export const InstanceContainer = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - width: "100%", - backgroundColor: "var(--color-instance)", - height: "59px", + display: 'flex', + alignItems: 'center', + width: '100%', + backgroundColor: 'var(--color-instance)', + height: '59px', flexShrink: 0, - justifyContent: "space-between", + justifyContent: 'space-between', })); + export const MailContainer = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "100%", - height: "calc(100vh - 78px)", - overflow: "hidden", + display: 'flex', + flexDirection: 'column', + width: '100%', + height: 'calc(100vh - 78px)', + overflow: 'hidden', })); export const MailBody = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "row", - width: "100%", - height: "calc(100% - 59px)", - // overflow: 'auto !important' + display: 'flex', + flexDirection: 'row', + width: '100%', + height: 'calc(100% - 59px)', })); + export const MailBodyInner = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "50%", - height: "100%", + display: 'flex', + flexDirection: 'column', + width: '50%', + height: '100%', })); + export const MailBodyInnerHeader = styled(Box)(({ theme }) => ({ - display: "flex", - width: "100%", - height: "25px", - marginTop: "50px", - marginBottom: "35px", - justifyContent: "center", - alignItems: "center", - gap: "11px", + display: 'flex', + width: '100%', + height: '25px', + marginTop: '50px', + marginBottom: '35px', + justifyContent: 'center', + alignItems: 'center', + gap: '11px', })); export const MailBodyInnerScroll = styled(Box)` @@ -84,163 +79,174 @@ export const MailBodyInnerScroll = styled(Box)` `; export const ComposeContainer = styled(Box)(({ theme }) => ({ - display: "flex", - width: "150px", - alignItems: "center", - gap: "7px", - height: "100%", - cursor: "pointer", - transition: "0.2s background-color", - justifyContent: "center", - "&:hover": { - backgroundColor: "rgba(67, 68, 72, 1)", + display: 'flex', + width: '150px', + alignItems: 'center', + gap: '7px', + height: '100%', + cursor: 'pointer', + transition: '0.2s background-color', + justifyContent: 'center', + '&:hover': { + backgroundColor: 'rgba(67, 68, 72, 1)', }, })); + export const ComposeContainerBlank = styled(Box)(({ theme }) => ({ - display: "flex", - width: "150px", - alignItems: "center", - gap: "7px", - height: "100%", + display: 'flex', + width: '150px', + alignItems: 'center', + gap: '7px', + height: '100%', })); + export const ComposeP = styled(Typography)(({ theme }) => ({ - fontSize: "15px", + fontSize: '15px', fontWeight: 500, })); -export const ComposeIcon = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - cursor: "pointer", -}); -export const ArrowDownIcon = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - cursor: "pointer", -}); -export const MailIconImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", +export const ComposeIcon = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer', }); -export const MailMessageRowInfoImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", +export const ArrowDownIcon = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer', +}); + +export const MailIconImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', +}); + +export const MailMessageRowInfoImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', }); export const SelectInstanceContainer = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - gap: "17px", + display: 'flex', + alignItems: 'center', + gap: '17px', })); + export const SelectInstanceContainerInner = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - gap: "3px", - cursor: "pointer", - padding: "8px", - transition: "all 0.2s", - "&:hover": { - borderRadius: "8px", - background: "#434448", + display: 'flex', + alignItems: 'center', + gap: '3px', + cursor: 'pointer', + padding: '8px', + transition: 'all 0.2s', + '&:hover': { + borderRadius: '8px', + background: '#434448', }, })); + export const SelectInstanceContainerFilterInner = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - gap: "3px", - cursor: "pointer", - padding: "8px", - transition: "all 0.2s" + display: 'flex', + alignItems: 'center', + gap: '3px', + cursor: 'pointer', + padding: '8px', + transition: 'all 0.2s', })); - export const InstanceLabel = styled(Typography)(({ theme }) => ({ - fontSize: "16px", + fontSize: '16px', fontWeight: 500, - color: "#FFFFFF33", + color: '#FFFFFF33', })); export const InstanceP = styled(Typography)(({ theme }) => ({ - fontSize: "16px", + fontSize: '16px', fontWeight: 500, })); export const MailMessageRowContainer = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - cursor: "pointer", - justifyContent: "space-between", - borderRadius: "56px 5px 10px 56px", - paddingRight: "15px", - transition: "background 0.2s", - gap: "10px", - "&:hover": { - background: "#434448", + display: 'flex', + alignItems: 'center', + cursor: 'pointer', + justifyContent: 'space-between', + borderRadius: '56px 5px 10px 56px', + paddingRight: '15px', + transition: 'background 0.2s', + gap: '10px', + '&:hover': { + background: '#434448', }, })); + export const MailMessageRowProfile = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - cursor: "pointer", - justifyContent: "flex-start", - gap: "10px", - width: "50%", - overflow: "hidden", + display: 'flex', + alignItems: 'center', + cursor: 'pointer', + justifyContent: 'flex-start', + gap: '10px', + width: '50%', + overflow: 'hidden', })); + export const MailMessageRowInfo = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - cursor: "pointer", - justifyContent: "flex-start", - gap: "7px", - width: "50%", + display: 'flex', + alignItems: 'center', + cursor: 'pointer', + justifyContent: 'flex-start', + gap: '7px', + width: '50%', })); + export const MailMessageRowInfoStatusNotDecrypted = styled(Typography)( ({ theme }) => ({ - fontSize: "16px", + fontSize: '16px', fontWeight: 900, - textTransform: "uppercase", - paddingTop: "2px", + textTransform: 'uppercase', + paddingTop: '2px', }) ); + export const MailMessageRowInfoStatusRead = styled(Typography)(({ theme }) => ({ - fontSize: "16px", + fontSize: '16px', fontWeight: 300, })); export const MessageExtraInfo = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - gap: "2px", - overflow: "hidden", + display: 'flex', + flexDirection: 'column', + gap: '2px', + overflow: 'hidden', })); + export const MessageExtraName = styled(Typography)(({ theme }) => ({ - fontSize: "16px", + fontSize: '16px', fontWeight: 900, - whiteSpace: "nowrap", - textOverflow: "ellipsis", - overflow: "hidden", + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + overflow: 'hidden', })); + export const MessageExtraDate = styled(Typography)(({ theme }) => ({ - fontSize: "15px", + fontSize: '15px', fontWeight: 500, })); export const MessagesContainer = styled(Box)(({ theme }) => ({ - width: "460px", - maxWidth: "90%", - display: "flex", - flexDirection: "column", - gap: "12px", + width: '460px', + maxWidth: '90%', + display: 'flex', + flexDirection: 'column', + gap: '12px', })); export const InstanceListParent = styled(Box)` @@ -254,18 +260,21 @@ export const InstanceListParent = styled(Box)` background-color: var(--color-instance-popover-bg); border: 1px solid rgba(0, 0, 0, 0.1); `; + export const InstanceListHeader = styled(Box)` display: flex; flex-direction: column; width: 100%; background-color: var(--color-instance-popover-bg); `; + export const InstanceFooter = styled(Box)` display: flex; flex-direction: column; width: 100%; flex-shrink: 0; `; + export const InstanceListContainer = styled(Box)` width: 100%; display: flex; @@ -301,126 +310,132 @@ export const InstanceListContainer = styled(Box)` } } `; + export const InstanceListContainerRowLabelContainer = styled(Box)( ({ theme }) => ({ - width: "100%", - display: "flex", - alignItems: "center", - gap: "10px", - height: "50px", + width: '100%', + display: 'flex', + alignItems: 'center', + gap: '10px', + height: '50px', }) ); + export const InstanceListContainerRow = styled(Box)(({ theme }) => ({ - width: "100%", - display: "flex", - alignItems: "center", - gap: "10px", - height: "50px", - cursor: "pointer", - transition: "0.2s background", - "&:hover": { - background: "rgba(67, 68, 72, 1)", + width: '100%', + display: 'flex', + alignItems: 'center', + gap: '10px', + height: '50px', + cursor: 'pointer', + transition: '0.2s background', + '&:hover': { + background: 'rgba(67, 68, 72, 1)', }, flexShrink: 0, })); + export const InstanceListContainerRowCheck = styled(Box)(({ theme }) => ({ - width: "47px", - display: "flex", - alignItems: "center", - justifyContent: "center", + width: '47px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', })); + export const InstanceListContainerRowMain = styled(Box)(({ theme }) => ({ - display: "flex", - justifyContent: "space-between", - width: "100%", - alignItems: "center", - paddingRight: "30px", - overflow: "hidden", + display: 'flex', + justifyContent: 'space-between', + width: '100%', + alignItems: 'center', + paddingRight: '30px', + overflow: 'hidden', })); + export const CloseParent = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - gap: "20px", + display: 'flex', + alignItems: 'center', + gap: '20px', })); + export const InstanceListContainerRowMainP = styled(Typography)( ({ theme }) => ({ fontWeight: 500, - fontSize: "16px", - textOverflow: "ellipsis", - overflow: "hidden", + fontSize: '16px', + textOverflow: 'ellipsis', + overflow: 'hidden', }) ); -export const InstanceListContainerRowCheckIcon = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", +export const InstanceListContainerRowCheckIcon = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', }); -export const InstanceListContainerRowGroupIcon = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", +export const InstanceListContainerRowGroupIcon = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', }); export const TypeInAliasTextfield = styled(TextField)({ - width: "340px", // Adjust the width as needed - borderRadius: "5px", - backgroundColor: "rgba(30, 30, 32, 1)", - border: "none", - outline: "none", + width: '340px', // Adjust the width as needed + borderRadius: '5px', + backgroundColor: 'rgba(30, 30, 32, 1)', + border: 'none', + outline: 'none', input: { fontSize: 16, - color: "white", - "&::placeholder": { + color: 'white', + '&::placeholder': { fontSize: 16, - color: "rgba(255, 255, 255, 0.2)", + color: 'rgba(255, 255, 255, 0.2)', }, - border: "none", - outline: "none", - padding: "10px", + border: 'none', + outline: 'none', + padding: '10px', }, - "& .MuiOutlinedInput-root": { - "& fieldset": { - border: "none", + '& .MuiOutlinedInput-root': { + '& fieldset': { + border: 'none', }, - "&:hover fieldset": { - border: "none", + '&:hover fieldset': { + border: 'none', }, - "&.Mui-focused fieldset": { - border: "none", + '&.Mui-focused fieldset': { + border: 'none', }, }, - "& .MuiInput-underline:before": { - borderBottom: "none", + '& .MuiInput-underline:before': { + borderBottom: 'none', }, - "& .MuiInput-underline:hover:not(.Mui-disabled):before": { - borderBottom: "none", + '& .MuiInput-underline:hover:not(.Mui-disabled):before': { + borderBottom: 'none', }, - "& .MuiInput-underline:after": { - borderBottom: "none", + '& .MuiInput-underline:after': { + borderBottom: 'none', }, }); -export const NewMessageCloseImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - cursor: "pointer", +export const NewMessageCloseImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer', }); export const NewMessageHeaderP = styled(Typography)(({ theme }) => ({ - fontSize: "18px", + fontSize: '18px', fontWeight: 600, })); export const NewMessageInputRow = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - justifyContent: "space-between", - borderBottom: "3px solid rgba(237, 239, 241, 1)", - width: "100%", - paddingBottom: "6px", + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + borderBottom: '3px solid rgba(237, 239, 241, 1)', + width: '100%', + paddingBottom: '6px', })); export const NewMessageInputLabelP = styled(Typography)` color: rgba(84, 84, 84, 0.7); @@ -444,25 +459,25 @@ export const AliasLabelP = styled(Typography)` } `; export const NewMessageAliasContainer = styled(Box)(({ theme }) => ({ - display: "flex", - alignItems: "center", - gap: "12px", + display: 'flex', + alignItems: 'center', + gap: '12px', })); export const AttachmentContainer = styled(Box)(({ theme }) => ({ - height: "36px", - width: "100%", - display: "flex", - alignItems: "center", + height: '36px', + width: '100%', + display: 'flex', + alignItems: 'center', })); -export const NewMessageAttachmentImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - cursor: "pointer", - padding: "10px", - border: "1px dashed #646464", +export const NewMessageAttachmentImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer', + padding: '10px', + border: '1px dashed #646464', }); export const NewMessageSendButton = styled(Box)` @@ -582,34 +597,36 @@ export const ShowMessageButtonP = styled(Typography)` color: white; `; -export const ShowMessageButtonImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - cursor: "pointer", +export const ShowMessageButtonImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + cursor: 'pointer', }); -export const MailAttachmentImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", +export const MailAttachmentImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', }); -export const AliasAvatarImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", + +export const AliasAvatarImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', }); -export const MoreImg = styled("img")({ - width: "auto", - height: "auto", - userSelect: "none", - objectFit: "contain", - transition: "0.2s all", - "&:hover": { - transform: "scale(1.3)", + +export const MoreImg = styled('img')({ + width: 'auto', + height: 'auto', + userSelect: 'none', + objectFit: 'contain', + transition: '0.2s all', + '&:hover': { + transform: 'scale(1.3)', }, }); @@ -625,17 +642,19 @@ export const MoreP = styled(Typography)` letter-spacing: -0.16px; white-space: nowrap; `; + export const ThreadContainerFullWidth = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "100%", - alignItems: "center", + display: 'flex', + flexDirection: 'column', + width: '100%', + alignItems: 'center', })); + export const ThreadContainer = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "100%", - maxWidth: "95%", + display: 'flex', + flexDirection: 'column', + width: '100%', + maxWidth: '95%', })); export const GroupNameP = styled(Typography)` @@ -648,130 +667,131 @@ export const GroupNameP = styled(Typography)` `; export const AllThreadP = styled(Typography)` - color: #FFF; -font-size: 20px; -font-style: normal; -font-weight: 400; -line-height: 120%; /* 24px */ -letter-spacing: 0.15px; + color: #fff; + font-size: 20px; + font-style: normal; + font-weight: 400; + line-height: 120%; /* 24px */ + letter-spacing: 0.15px; `; export const SingleThreadParent = styled(Box)` -border-radius: 35px 4px 4px 35px; -position: relative; -background: #434448; -display: flex; -padding: 13px; -cursor: pointer; -margin-bottom: 5px; -height: 76px; -align-items:center; -transition: 0.2s all; -&:hover { -background: rgba(255, 255, 255, 0.20) -} + border-radius: 35px 4px 4px 35px; + position: relative; + background: #434448; + display: flex; + padding: 13px; + cursor: pointer; + margin-bottom: 5px; + height: 76px; + align-items: center; + transition: 0.2s all; + &:hover { + background: rgba(255, 255, 255, 0.2); + } `; -export const SingleTheadMessageParent = styled(Box)` -border-radius: 35px 4px 4px 35px; -background: #434448; -display: flex; -padding: 13px; -cursor: pointer; -margin-bottom: 5px; -height: 76px; -align-items:center; +export const SingleTheadMessageParent = styled(Box)` + border-radius: 35px 4px 4px 35px; + background: #434448; + display: flex; + padding: 13px; + cursor: pointer; + margin-bottom: 5px; + height: 76px; + align-items: center; `; export const ThreadInfoColumn = styled(Box)(({ theme }) => ({ - display: "flex", - flexDirection: "column", - width: "170px", + display: 'flex', + flexDirection: 'column', + width: '170px', gap: '2px', marginLeft: '10px', height: '100%', - justifyContent: 'center' + justifyContent: 'center', })); - export const ThreadInfoColumnNameP = styled(Typography)` -color: #FFF; -font-family: Roboto; -font-size: 16px; -font-style: normal; -font-weight: 900; -line-height: normal; -white-space: nowrap; + color: #fff; + font-family: Roboto; + font-size: 16px; + font-style: normal; + font-weight: 900; + line-height: normal; + white-space: nowrap; text-overflow: ellipsis; overflow: hidden; `; + export const ThreadInfoColumnbyP = styled('span')` -color: rgba(255, 255, 255, 0.80); -font-family: Roboto; -font-size: 16px; -font-style: normal; -font-weight: 500; -line-height: normal; + color: rgba(255, 255, 255, 0.8); + font-family: Roboto; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: normal; `; export const ThreadInfoColumnTime = styled(Typography)` -color: rgba(255, 255, 255, 0.80); -font-family: Roboto; -font-size: 15px; -font-style: normal; -font-weight: 500; -line-height: normal; -` + color: rgba(255, 255, 255, 0.8); + font-family: Roboto; + font-size: 15px; + font-style: normal; + font-weight: 500; + line-height: normal; +`; + export const ThreadSingleTitle = styled(Typography)` -color: #FFF; -font-family: Roboto; -font-size: 23px; -font-style: normal; -font-weight: 700; -line-height: normal; -white-space: wrap; + color: #fff; + font-family: Roboto; + font-size: 23px; + font-style: normal; + font-weight: 700; + line-height: normal; + white-space: wrap; text-overflow: ellipsis; overflow: hidden; -` +`; + export const ThreadSingleLastMessageP = styled(Typography)` -color: #FFF; -font-family: Roboto; -font-size: 12px; -font-style: normal; -font-weight: 600; -line-height: normal; -` + color: #fff; + font-family: Roboto; + font-size: 12px; + font-style: normal; + font-weight: 600; + line-height: normal; +`; + export const ThreadSingleLastMessageSpanP = styled('span')` -color: #FFF; -font-family: Roboto; -font-size: 12px; -font-style: normal; -font-weight: 400; -line-height: normal; + color: #fff; + font-family: Roboto; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; `; export const GroupContainer = styled(Box)` -position: relative; - overflow: auto; - width: 100%; - - -` + position: relative; + overflow: auto; + width: 100%; +`; export const CloseContainer = styled(Box)(({ theme }) => ({ - display: "flex", - width: "50px", - overflow: "hidden", - alignItems: "center", - cursor: "pointer", - transition: "0.2s background-color", - justifyContent: "center", + display: 'flex', + width: '50px', + overflow: 'hidden', + alignItems: 'center', + cursor: 'pointer', + transition: '0.2s background-color', + justifyContent: 'center', position: 'absolute', top: '0px', right: '0px', height: '50px', borderRadius: '0px 12px 0px 0px', - "&:hover": { - backgroundColor: "rgba(162, 31, 31, 1)", + '&:hover': { + backgroundColor: 'rgba(162, 31, 31, 1)', }, -})); \ No newline at end of file +})); diff --git a/src/components/Group/Forum/NewThread.tsx b/src/components/Group/Forum/NewThread.tsx index dc987d9..d5c4384 100644 --- a/src/components/Group/Forum/NewThread.tsx +++ b/src/components/Group/Forum/NewThread.tsx @@ -191,7 +191,7 @@ export const NewThread = ({ } if (!groupInfo) { errorMsg = 'Cannot access group information'; - } + } // TODO translate // if (!description) missingFields.push('subject') if (missingFields.length > 0) { diff --git a/src/components/Group/Forum/ReadOnlySlate.tsx b/src/components/Group/Forum/ReadOnlySlate.tsx index d64cf9e..5724f92 100644 --- a/src/components/Group/Forum/ReadOnlySlate.tsx +++ b/src/components/Group/Forum/ReadOnlySlate.tsx @@ -1,18 +1,24 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { createEditor} from 'slate'; -import { withReact, Slate, Editable, RenderElementProps, RenderLeafProps } from 'slate-react'; +import { createEditor } from 'slate'; +import { + withReact, + Slate, + Editable, + RenderElementProps, + RenderLeafProps, +} from 'slate-react'; -type ExtendedRenderElementProps = RenderElementProps & { mode?: string } +type ExtendedRenderElementProps = RenderElementProps & { mode?: string }; export const renderElement = ({ attributes, children, element, - mode + mode, }: ExtendedRenderElementProps) => { switch (element.type) { case 'block-quote': - return
{children}
+ return
{children}
; case 'heading-2': return (

{children}

- ) + ); case 'heading-3': return (

{children}

- ) + ); case 'code-block': return (
           {children}
         
- ) + ); case 'code-line': - return
{children}
+ return
{children}
; case 'link': return ( {children} - ) + ); default: return (

{children}

- ) + ); } -} - +}; export const renderLeaf = ({ attributes, children, leaf }: RenderLeafProps) => { - let el = children + let el = children; if (leaf.bold) { - el = {el} + el = {el}; } if (leaf.italic) { - el = {el} + el = {el}; } if (leaf.underline) { - el = {el} + el = {el}; } if (leaf.link) { @@ -81,39 +86,35 @@ export const renderLeaf = ({ attributes, children, leaf }: RenderLeafProps) => { {el} - ) + ); } - return {el} -} + return {el}; +}; interface ReadOnlySlateProps { - content: any - mode?: string + content: any; + mode?: string; } const ReadOnlySlate: React.FC = ({ content, mode }) => { - const [load, setLoad] = useState(false) - const editor = useMemo(() => withReact(createEditor()), []) - const value = useMemo(() => content, [content]) + const [load, setLoad] = useState(false); + const editor = useMemo(() => withReact(createEditor()), []); + const value = useMemo(() => content, [content]); - const performUpdate = useCallback(async()=> { - setLoad(true) - await new Promise((res)=> { + const performUpdate = useCallback(async () => { + setLoad(true); + await new Promise((res) => { setTimeout(() => { - res() + res(); }, 250); - }) - setLoad(false) - }, []) - useEffect(()=> { + }); + setLoad(false); + }, []); + useEffect(() => { + performUpdate(); + }, [value]); - - - - performUpdate() - }, [value]) - - if(load) return null + if (load) return null; return ( {}}> @@ -123,7 +124,7 @@ const ReadOnlySlate: React.FC = ({ content, mode }) => { renderLeaf={renderLeaf} /> - ) -} + ); +}; -export default ReadOnlySlate; \ No newline at end of file +export default ReadOnlySlate; diff --git a/src/components/Group/Forum/ShowMessageWithoutModal.tsx b/src/components/Group/Forum/ShowMessageWithoutModal.tsx index 9a079d6..7a4e594 100644 --- a/src/components/Group/Forum/ShowMessageWithoutModal.tsx +++ b/src/components/Group/Forum/ShowMessageWithoutModal.tsx @@ -1,8 +1,8 @@ -import React, { useState } from "react"; -import { Avatar, Box, IconButton } from "@mui/material"; -import DOMPurify from "dompurify"; +import { useState } from 'react'; +import { Avatar, Box, IconButton } from '@mui/material'; +import DOMPurify from 'dompurify'; import FormatQuoteIcon from '@mui/icons-material/FormatQuote'; -import MoreSVG from '../../../assets/svgs/More.svg' +import MoreSVG from '../../../assets/svgs/More.svg'; import { MoreImg, @@ -11,20 +11,18 @@ import { ThreadInfoColumn, ThreadInfoColumnNameP, ThreadInfoColumnTime, -} from "./Mail-styles"; -import { Spacer } from "../../../common/Spacer"; -import { DisplayHtml } from "./DisplayHtml"; -import { formatTimestampForum } from "../../../utils/time"; -import ReadOnlySlate from "./ReadOnlySlate"; -import { MessageDisplay } from "../../Chat/MessageDisplay"; -import { getBaseApi } from "../../../background"; -import { getBaseApiReact } from "../../../App"; -import { WrapperUserAction } from "../../WrapperUserAction"; +} from './Mail-styles'; +import { Spacer } from '../../../common/Spacer'; +import { formatTimestampForum } from '../../../utils/time'; +import ReadOnlySlate from './ReadOnlySlate'; +import { MessageDisplay } from '../../Chat/MessageDisplay'; +import { getBaseApiReact } from '../../../App'; +import { WrapperUserAction } from '../../WrapperUserAction'; export const ShowMessage = ({ message, openNewPostWithQuote, myName }: any) => { const [expandAttachments, setExpandAttachments] = useState(false); - let cleanHTML = ""; + let cleanHTML = ''; if (message?.htmlContent) { cleanHTML = DOMPurify.sanitize(message.htmlContent); } @@ -32,79 +30,94 @@ export const ShowMessage = ({ message, openNewPostWithQuote, myName }: any) => { return ( - - {message?.name?.charAt(0)} - + + + {message?.name?.charAt(0)} + + - - - {message?.name} + + {message?.name} {formatTimestampForum(message?.created)}
- {message?.attachments?.length > 0 && ( - - {message?.attachments - .map((file: any, index: number) => { - const isFirst = index === 0 - return ( - + {message?.attachments?.length > 0 && ( + + {message?.attachments.map((file: any, index: number) => { + const isFirst = index === 0; + return ( - {/* + {/* { {file?.originalFilename || file?.filename} */} - {message?.attachments?.length > 1 && isFirst && ( - { - setExpandAttachments(prev => !prev); - }} - > - 1 && isFirst && ( + - - {expandAttachments ? 'hide' : `(${message?.attachments?.length - 1} more)`} - - - - )} + onClick={() => { + setExpandAttachments((prev) => !prev); + }} + > + + + {expandAttachments + ? 'hide' + : `(${message?.attachments?.length - 1} more)`} + + + )} + - - ); - }) - } - - )} - -
+ ); + })} +
+ )} +
+ + {message?.reply?.textContentV2 && ( <> - + - - {message?.reply?.name?.charAt(0)} - - {message?.reply?.name} - - - - - - + sx={{ + display: 'flex', + alignItems: 'flex-start', + gap: '10px', + }} + > + + {message?.reply?.name?.charAt(0)} + + + + {message?.reply?.name} + + + + + + - )} - + {message?.textContent && ( )} @@ -208,22 +230,18 @@ export const ShowMessage = ({ message, openNewPostWithQuote, myName }: any) => { {message?.htmlContent && (
)} - - openNewPostWithQuote(message)} - + - - + openNewPostWithQuote(message)}> + + - - - ); }; diff --git a/src/components/Group/Forum/TextEditor.tsx b/src/components/Group/Forum/TextEditor.tsx index 874f2e3..ac26275 100644 --- a/src/components/Group/Forum/TextEditor.tsx +++ b/src/components/Group/Forum/TextEditor.tsx @@ -1,32 +1,33 @@ -import React from "react"; -import ReactQuill, { Quill } from "react-quill"; -import "react-quill/dist/quill.snow.css"; -import ImageResize from "quill-image-resize-module-react"; -import './texteditor.css' -Quill.register("modules/imageResize", ImageResize); +import ReactQuill, { Quill } from 'react-quill'; +import 'react-quill/dist/quill.snow.css'; +import ImageResize from 'quill-image-resize-module-react'; +import './texteditor.css'; + +Quill.register('modules/imageResize', ImageResize); const modules = { imageResize: { - parchment: Quill.import("parchment"), - modules: ["Resize", "DisplaySize"], + parchment: Quill.import('parchment'), + modules: ['Resize', 'DisplaySize'], }, toolbar: [ - ["bold", "italic", "underline", "strike"], // styled text - ["blockquote", "code-block"], // blocks + ['bold', 'italic', 'underline', 'strike'], // styled text + ['blockquote', 'code-block'], // blocks [{ header: 1 }, { header: 2 }], // custom button values - [{ list: "ordered" }, { list: "bullet" }], // lists - [{ script: "sub" }, { script: "super" }], // superscript/subscript - [{ indent: "-1" }, { indent: "+1" }], // outdent/indent - [{ direction: "rtl" }], // text direction - [{ size: ["small", false, "large", "huge"] }], // custom dropdown + [{ list: 'ordered' }, { list: 'bullet' }], // lists + [{ script: 'sub' }, { script: 'super' }], // superscript/subscript + [{ indent: '-1' }, { indent: '+1' }], // outdent/indent + [{ direction: 'rtl' }], // text direction + [{ size: ['small', false, 'large', 'huge'] }], // custom dropdown [{ header: [1, 2, 3, 4, 5, 6, false] }], // custom button values [{ color: [] }, { background: [] }], // dropdown with defaults [{ font: [] }], // font family [{ align: [] }], // text align - ["clean"], // remove formatting + ['clean'], // remove formatting // ["image"], // image ], }; + export const TextEditor = ({ inlineContent, setInlineContent }: any) => { return ( Previous diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx index 4573022..a4629ce 100644 --- a/src/components/Group/Group.tsx +++ b/src/components/Group/Group.tsx @@ -2218,7 +2218,8 @@ export const Group = ({ }} > No group selected - + {' '} + // TODO translate )} @@ -2235,39 +2236,39 @@ export const Group = ({ : '0px', }} > - - + - + + /> { Group Invites{' '} {groupsWithJoinRequests?.length > 0 && diff --git a/src/components/Group/GroupJoinRequests.tsx b/src/components/Group/GroupJoinRequests.tsx index 1847bd0..4bc6b21 100644 --- a/src/components/Group/GroupJoinRequests.tsx +++ b/src/components/Group/GroupJoinRequests.tsx @@ -82,6 +82,7 @@ export const GroupJoinRequests = ({ ); setGroupsWithJoinRequests(res); } catch (error) { + console.log(error); } finally { setLoading(false); } @@ -138,7 +139,7 @@ export const GroupJoinRequests = ({ Join Requests{' '} {filteredJoinRequests?.filter((group) => group?.data?.length > 0) diff --git a/src/components/Group/GroupMenu.tsx b/src/components/Group/GroupMenu.tsx index a44c480..0d81cd2 100644 --- a/src/components/Group/GroupMenu.tsx +++ b/src/components/Group/GroupMenu.tsx @@ -1,22 +1,27 @@ -import React, { useState } from "react"; +import { useState } from 'react'; import { Button, Menu, MenuItem, ListItemIcon, ListItemText, - Badge, Box, -} from "@mui/material"; -import ForumIcon from "@mui/icons-material/Forum"; -import GroupIcon from "@mui/icons-material/Group"; -import { ArrowDownIcon } from "../../assets/Icons/ArrowDownIcon"; -import { NotificationIcon2 } from "../../assets/Icons/NotificationIcon2"; -import { ChatIcon } from "../../assets/Icons/ChatIcon"; -import { ThreadsIcon } from "../../assets/Icons/ThreadsIcon"; -import { MembersIcon } from "../../assets/Icons/MembersIcon"; +} from '@mui/material'; +import { ArrowDownIcon } from '../../assets/Icons/ArrowDownIcon'; +import { NotificationIcon2 } from '../../assets/Icons/NotificationIcon2'; +import { ChatIcon } from '../../assets/Icons/ChatIcon'; +import { ThreadsIcon } from '../../assets/Icons/ThreadsIcon'; +import { MembersIcon } from '../../assets/Icons/MembersIcon'; -export const GroupMenu = ({ setGroupSection, groupSection, setOpenManageMembers, goToAnnouncements, goToChat, hasUnreadChat, hasUnreadAnnouncements }) => { +export const GroupMenu = ({ + setGroupSection, + groupSection, + setOpenManageMembers, + goToAnnouncements, + goToChat, + hasUnreadChat, + hasUnreadAnnouncements, +}) => { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); @@ -31,170 +36,217 @@ export const GroupMenu = ({ setGroupSection, groupSection, setOpenManageMembers, return ( + { - goToChat() + goToChat(); handleClose(); }} > - - + + - + { - goToAnnouncements() + goToAnnouncements(); handleClose(); }} > - - + + - + { - setGroupSection("forum"); + setGroupSection('forum'); handleClose(); }} > - - - + + - + { - setOpenManageMembers(true) + setOpenManageMembers(true); handleClose(); }} > - - - + + - + diff --git a/src/components/Group/InviteMember.tsx b/src/components/Group/InviteMember.tsx index 40b44ac..de3dc20 100644 --- a/src/components/Group/InviteMember.tsx +++ b/src/components/Group/InviteMember.tsx @@ -1,13 +1,6 @@ import { LoadingButton } from '@mui/lab'; -import { - Box, - Button, - Input, - MenuItem, - Select, - SelectChangeEvent, -} from '@mui/material'; -import React, { useState } from 'react'; +import { Box, Input, MenuItem, Select, SelectChangeEvent } from '@mui/material'; +import { useState } from 'react'; import { Spacer } from '../../common/Spacer'; import { Label } from './AddGroup'; import { getFee } from '../../background'; @@ -34,6 +27,7 @@ export const InviteMember = ({ groupId, setInfoSnack, setOpenSnack, show }) => { }) .then((response) => { if (!response?.error) { + // TODO translate setInfoSnack({ type: 'success', message: `Successfully invited ${value}. It may take a couple of minutes for the changes to propagate`, diff --git a/src/components/Group/ListOfBans.tsx b/src/components/Group/ListOfBans.tsx index db4c6ba..850ce13 100644 --- a/src/components/Group/ListOfBans.tsx +++ b/src/components/Group/ListOfBans.tsx @@ -1,16 +1,31 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Avatar, Box, Button, ListItem, ListItemAvatar, ListItemButton, ListItemText, Popover } from '@mui/material'; -import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; +import { useEffect, useRef, useState } from 'react'; +import { + Avatar, + Box, + ListItem, + ListItemAvatar, + ListItemButton, + ListItemText, + Popover, +} from '@mui/material'; +import { + AutoSizer, + CellMeasurer, + CellMeasurerCache, + List, +} from 'react-virtualized'; import { getNameInfo } from './Group'; -import { getBaseApi, getFee } from '../../background'; +import { getFee } from '../../background'; import { LoadingButton } from '@mui/lab'; import { getBaseApiReact } from '../../App'; export const getMemberInvites = async (groupNumber) => { - const response = await fetch(`${getBaseApiReact()}/groups/bans/${groupNumber}?limit=0`); + const response = await fetch( + `${getBaseApiReact()}/groups/bans/${groupNumber}?limit=0` + ); const groupData = await response.json(); return groupData; -} +}; const getNames = async (listOfMembers, includeNoNames) => { let members = []; @@ -20,14 +35,14 @@ const getNames = async (listOfMembers, includeNoNames) => { const name = await getNameInfo(member.offender); if (name) { members.push({ ...member, name }); - } else if(includeNoNames){ - members.push({ ...member, name: name || "" }); + } else if (includeNoNames) { + members.push({ ...member, name: name || '' }); } } } } return members; -} +}; const cache = new CellMeasurerCache({ fixedWidth: true, @@ -49,7 +64,7 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => { } catch (error) { console.error(error); } - } + }; useEffect(() => { if (groupId) { @@ -67,33 +82,36 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => { setOpenPopoverIndex(null); }; - const handleCancelBan = async (address)=> { + const handleCancelBan = async (address) => { try { - const fee = await getFee('CANCEL_GROUP_BAN') + // TODO translate + const fee = await getFee('CANCEL_GROUP_BAN'); await show({ - message: "Would you like to perform a CANCEL_GROUP_BAN transaction?" , - publishFee: fee.fee + ' QORT' - }) - setIsLoadingUnban(true) - new Promise((res, rej)=> { - window.sendMessage("cancelBan", { - groupId, - qortalAddress: address, - }) + message: 'Would you like to perform a CANCEL_GROUP_BAN transaction?', + publishFee: fee.fee + ' QORT', + }); + setIsLoadingUnban(true); + new Promise((res, rej) => { + window + .sendMessage('cancelBan', { + groupId, + qortalAddress: address, + }) .then((response) => { if (!response?.error) { res(response); setIsLoadingUnban(false); setInfoSnack({ - type: "success", - message: "Successfully unbanned user. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully unbanned user. It may take a couple of minutes for the changes to propagate', }); handlePopoverClose(); setOpenSnack(true); return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -101,24 +119,22 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => { }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - - }) + }); } catch (error) { - } finally { - setIsLoadingUnban(false) + setIsLoadingUnban(false); } - } + }; const rowRenderer = ({ index, key, parent, style }) => { const member = bans[index]; - + return ( { anchorEl={popoverAnchor} onClose={handlePopoverClose} anchorOrigin={{ - vertical: "bottom", - horizontal: "center", + vertical: 'bottom', + horizontal: 'center', }} transformOrigin={{ - vertical: "top", - horizontal: "center", + vertical: 'top', + horizontal: 'center', }} - style={{ marginTop: "8px" }} + style={{ marginTop: '8px' }} > - - handleCancelBan(member?.offender)}>Cancel Ban + variant="contained" + onClick={() => handleCancelBan(member?.offender)} + > + Cancel Ban + - handlePopoverOpen(event, index)}> + handlePopoverOpen(event, index)} + > @@ -179,7 +206,16 @@ export const ListOfBans = ({ groupId, setInfoSnack, setOpenSnack, show }) => { return (

Ban list

-
+
{({ height, width }) => ( {
); -} +}; diff --git a/src/components/Group/ListOfGroupPromotions.tsx b/src/components/Group/ListOfGroupPromotions.tsx index 9a8c170..35ac442 100644 --- a/src/components/Group/ListOfGroupPromotions.tsx +++ b/src/components/Group/ListOfGroupPromotions.tsx @@ -230,7 +230,7 @@ export const ListOfGroupPromotions = () => { .catch((error) => { rej(error.message || 'An error occurred'); }); - }); + }); // TODO translate setInfoSnack({ type: 'success', message: diff --git a/src/components/Group/ListOfInvites.tsx b/src/components/Group/ListOfInvites.tsx index a41bc47..a571775 100644 --- a/src/components/Group/ListOfInvites.tsx +++ b/src/components/Group/ListOfInvites.tsx @@ -1,16 +1,31 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Avatar, Box, Button, ListItem, ListItemAvatar, ListItemButton, ListItemText, Popover } from '@mui/material'; -import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; +import { useEffect, useRef, useState } from 'react'; +import { + Avatar, + Box, + ListItem, + ListItemAvatar, + ListItemButton, + ListItemText, + Popover, +} from '@mui/material'; +import { + AutoSizer, + CellMeasurer, + CellMeasurerCache, + List, +} from 'react-virtualized'; import { getNameInfo } from './Group'; -import { getBaseApi, getFee } from '../../background'; +import { getFee } from '../../background'; import { LoadingButton } from '@mui/lab'; import { getBaseApiReact } from '../../App'; export const getMemberInvites = async (groupNumber) => { - const response = await fetch(`${getBaseApiReact()}/groups/invites/group/${groupNumber}?limit=0`); + const response = await fetch( + `${getBaseApiReact()}/groups/invites/group/${groupNumber}?limit=0` + ); const groupData = await response.json(); return groupData; -} +}; const getNames = async (listOfMembers, includeNoNames) => { let members = []; @@ -20,21 +35,26 @@ const getNames = async (listOfMembers, includeNoNames) => { const name = await getNameInfo(member.invitee); if (name) { members.push({ ...member, name }); - } else if(includeNoNames){ - members.push({ ...member, name: name || "" }); + } else if (includeNoNames) { + members.push({ ...member, name: name || '' }); } } } } return members; -} +}; const cache = new CellMeasurerCache({ fixedWidth: true, defaultHeight: 50, }); -export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => { +export const ListOfInvites = ({ + groupId, + setInfoSnack, + setOpenSnack, + show, +}) => { const [invites, setInvites] = useState([]); const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open @@ -50,7 +70,7 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => } catch (error) { console.error(error); } - } + }; useEffect(() => { if (groupId) { @@ -68,24 +88,27 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => setOpenPopoverIndex(null); }; - const handleCancelInvitation = async (address)=> { + const handleCancelInvitation = async (address) => { try { - const fee = await getFee('CANCEL_GROUP_INVITE') + // TODO translate + const fee = await getFee('CANCEL_GROUP_INVITE'); await show({ - message: "Would you like to perform a CANCEL_GROUP_INVITE transaction?" , - publishFee: fee.fee + ' QORT' - }) - setIsLoadingCancelInvite(true) - await new Promise((res, rej)=> { - window.sendMessage("cancelInvitationToGroup", { - groupId, - qortalAddress: address, - }) + message: 'Would you like to perform a CANCEL_GROUP_INVITE transaction?', + publishFee: fee.fee + ' QORT', + }); + setIsLoadingCancelInvite(true); + await new Promise((res, rej) => { + window + .sendMessage('cancelInvitationToGroup', { + groupId, + qortalAddress: address, + }) .then((response) => { if (!response?.error) { setInfoSnack({ - type: "success", - message: "Successfully canceled invitation. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully canceled invitation. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); @@ -94,7 +117,7 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -102,24 +125,22 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - - }) + }); } catch (error) { - } finally { - setIsLoadingCancelInvite(false) + setIsLoadingCancelInvite(false); } - } + }; const rowRenderer = ({ index, key, parent, style }) => { const member = invites[index]; - + return ( anchorEl={popoverAnchor} onClose={handlePopoverClose} anchorOrigin={{ - vertical: "bottom", - horizontal: "center", + vertical: 'bottom', + horizontal: 'center', }} transformOrigin={{ - vertical: "top", - horizontal: "center", + vertical: 'top', + horizontal: 'center', }} - style={{ marginTop: "8px" }} + style={{ marginTop: '8px' }} > - - handleCancelInvitation(member?.invitee)}>Cancel Invitation + variant="contained" + onClick={() => handleCancelInvitation(member?.invitee)} + > + Cancel Invitation + - handlePopoverOpen(event, index)}> + handlePopoverOpen(event, index)} + > @@ -180,7 +212,16 @@ export const ListOfInvites = ({ groupId, setInfoSnack, setOpenSnack, show }) => return (

Invitees list

-
+
{({ height, width }) => (
); -} +}; diff --git a/src/components/Group/ListOfJoinRequests.tsx b/src/components/Group/ListOfJoinRequests.tsx index 0f4bd81..d2bd5ad 100644 --- a/src/components/Group/ListOfJoinRequests.tsx +++ b/src/components/Group/ListOfJoinRequests.tsx @@ -1,16 +1,31 @@ -import React, { useContext, useEffect, useRef, useState } from 'react'; -import { Avatar, Box, Button, ListItem, ListItemAvatar, ListItemButton, ListItemText, Popover } from '@mui/material'; -import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; +import { useContext, useEffect, useRef, useState } from 'react'; +import { + Avatar, + Box, + ListItem, + ListItemAvatar, + ListItemButton, + ListItemText, + Popover, +} from '@mui/material'; +import { + AutoSizer, + CellMeasurer, + CellMeasurerCache, + List, +} from 'react-virtualized'; import { getNameInfo } from './Group'; import { getBaseApi, getFee } from '../../background'; import { LoadingButton } from '@mui/lab'; import { MyContext, getBaseApiReact } from '../../App'; export const getMemberInvites = async (groupNumber) => { - const response = await fetch(`${getBaseApiReact()}/groups/joinrequests/${groupNumber}?limit=0`); + const response = await fetch( + `${getBaseApiReact()}/groups/joinrequests/${groupNumber}?limit=0` + ); const groupData = await response.json(); return groupData; -} +}; const getNames = async (listOfMembers, includeNoNames) => { let members = []; @@ -19,24 +34,29 @@ const getNames = async (listOfMembers, includeNoNames) => { if (member.joiner) { const name = await getNameInfo(member.joiner); if (name) { - members.push({ ...member, name: name || "" }); - } else if(includeNoNames){ - members.push({ ...member, name: name || "" }); + members.push({ ...member, name: name || '' }); + } else if (includeNoNames) { + members.push({ ...member, name: name || '' }); } } } } return members; -} +}; const cache = new CellMeasurerCache({ fixedWidth: true, defaultHeight: 50, }); -export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show }) => { +export const ListOfJoinRequests = ({ + groupId, + setInfoSnack, + setOpenSnack, + show, +}) => { const [invites, setInvites] = useState([]); - const {txList, setTxList} = useContext(MyContext) + const { txList, setTxList } = useContext(MyContext); const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open @@ -51,7 +71,7 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } } catch (error) { console.error(error); } - } + }; useEffect(() => { if (groupId) { @@ -69,31 +89,33 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } setOpenPopoverIndex(null); }; - const handleAcceptJoinRequest = async (address)=> { + const handleAcceptJoinRequest = async (address) => { try { - const fee = await getFee('GROUP_INVITE') + const fee = await getFee('GROUP_INVITE'); // TODO translate await show({ - message: "Would you like to perform a GROUP_INVITE transaction?" , - publishFee: fee.fee + ' QORT' - }) - setIsLoadingAccept(true) - await new Promise((res, rej)=> { - window.sendMessage("inviteToGroup", { - groupId, - qortalAddress: address, - inviteTime: 10800, - }) + message: 'Would you like to perform a GROUP_INVITE transaction?', + publishFee: fee.fee + ' QORT', + }); + setIsLoadingAccept(true); + await new Promise((res, rej) => { + window + .sendMessage('inviteToGroup', { + groupId, + qortalAddress: address, + inviteTime: 10800, + }) .then((response) => { if (!response?.error) { setIsLoadingAccept(false); setInfoSnack({ - type: "success", - message: "Successfully accepted join request. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully accepted join request. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); res(response); - + setTxList((prev) => [ { ...response, @@ -106,12 +128,12 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } }, ...prev, ]); - + return; } - + setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -119,25 +141,28 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } }) .catch((error) => { setInfoSnack({ - type: "error", - message: error?.message || "An error occurred", + type: 'error', + message: error?.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - - }) + }); } catch (error) { - } finally { - setIsLoadingAccept(false) + setIsLoadingAccept(false); } - } + }; const rowRenderer = ({ index, key, parent, style }) => { const member = invites[index]; - const findJoinRequsetInTxList = txList?.find((tx)=> tx?.groupId === groupId && tx?.qortalAddress === member?.joiner && tx?.type === 'join-request-accept') - if(findJoinRequsetInTxList) return null + const findJoinRequsetInTxList = txList?.find( + (tx) => + tx?.groupId === groupId && + tx?.qortalAddress === member?.joiner && + tx?.type === 'join-request-accept' + ); + if (findJoinRequsetInTxList) return null; return ( - - handleAcceptJoinRequest(member?.joiner)}>Accept + variant="contained" + onClick={() => handleAcceptJoinRequest(member?.joiner)} + > + Accept + - handlePopoverOpen(event, index)}> + handlePopoverOpen(event, index)} + > @@ -198,7 +234,16 @@ export const ListOfJoinRequests = ({ groupId, setInfoSnack, setOpenSnack, show } return (

Join request list

-
+
{({ height, width }) => (
); -} +}; diff --git a/src/components/Group/ListOfMembers.tsx b/src/components/Group/ListOfMembers.tsx index 9910453..0f227f8 100644 --- a/src/components/Group/ListOfMembers.tsx +++ b/src/components/Group/ListOfMembers.tsx @@ -1,29 +1,29 @@ import { Avatar, Box, - Button, ListItem, ListItemAvatar, ListItemButton, ListItemText, Popover, Typography, -} from "@mui/material"; -import React, { useRef, useState } from "react"; +} from '@mui/material'; +import { useRef, useState } from 'react'; import { AutoSizer, CellMeasurer, CellMeasurerCache, List, -} from "react-virtualized"; -import { LoadingButton } from "@mui/lab"; -import { getBaseApi, getFee } from "../../background"; -import { getBaseApiReact } from "../../App"; +} from 'react-virtualized'; +import { LoadingButton } from '@mui/lab'; +import { getFee } from '../../background'; +import { getBaseApiReact } from '../../App'; const cache = new CellMeasurerCache({ fixedWidth: true, defaultHeight: 50, }); + const ListOfMembers = ({ members, groupId, @@ -40,7 +40,6 @@ const ListOfMembers = ({ const [isLoadingMakeAdmin, setIsLoadingMakeAdmin] = useState(false); const [isLoadingRemoveAdmin, setIsLoadingRemoveAdmin] = useState(false); - const listRef = useRef(); const handlePopoverOpen = (event, index) => { @@ -55,23 +54,25 @@ const ListOfMembers = ({ const handleKick = async (address) => { try { - const fee = await getFee("GROUP_KICK"); + const fee = await getFee('GROUP_KICK'); await show({ - message: "Would you like to perform a GROUP_KICK transaction?", - publishFee: fee.fee + " QORT", + message: 'Would you like to perform a GROUP_KICK transaction?', + publishFee: fee.fee + ' QORT', }); setIsLoadingKick(true); new Promise((res, rej) => { - window.sendMessage("kickFromGroup", { - groupId, - qortalAddress: address, - }) + window + .sendMessage('kickFromGroup', { + groupId, + qortalAddress: address, + }) .then((response) => { if (!response?.error) { setInfoSnack({ - type: "success", - message: "Successfully kicked member from group. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully kicked member from group. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); @@ -79,7 +80,7 @@ const ListOfMembers = ({ return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -87,38 +88,40 @@ const ListOfMembers = ({ }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - }); } catch (error) { + console.log(error); } finally { setIsLoadingKick(false); } }; const handleBan = async (address) => { try { - const fee = await getFee("GROUP_BAN"); + const fee = await getFee('GROUP_BAN'); // TODO translate await show({ - message: "Would you like to perform a GROUP_BAN transaction?", - publishFee: fee.fee + " QORT", + message: 'Would you like to perform a GROUP_BAN transaction?', + publishFee: fee.fee + ' QORT', }); setIsLoadingBan(true); await new Promise((res, rej) => { - window.sendMessage("banFromGroup", { - groupId, - qortalAddress: address, - rBanTime: 0, - }) + window + .sendMessage('banFromGroup', { + groupId, + qortalAddress: address, + rBanTime: 0, + }) .then((response) => { if (!response?.error) { setInfoSnack({ - type: "success", - message: "Successfully banned member from group. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully banned member from group. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); @@ -126,7 +129,7 @@ const ListOfMembers = ({ return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -134,13 +137,12 @@ const ListOfMembers = ({ }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - }); } catch (error) { } finally { @@ -150,22 +152,24 @@ const ListOfMembers = ({ const makeAdmin = async (address) => { try { - const fee = await getFee("ADD_GROUP_ADMIN"); + const fee = await getFee('ADD_GROUP_ADMIN'); await show({ - message: "Would you like to perform a ADD_GROUP_ADMIN transaction?", - publishFee: fee.fee + " QORT", + message: 'Would you like to perform a ADD_GROUP_ADMIN transaction?', + publishFee: fee.fee + ' QORT', }); setIsLoadingMakeAdmin(true); await new Promise((res, rej) => { - window.sendMessage("makeAdmin", { - groupId, - qortalAddress: address, - }) + window + .sendMessage('makeAdmin', { + groupId, + qortalAddress: address, + }) .then((response) => { if (!response?.error) { setInfoSnack({ - type: "success", - message: "Successfully made member an admin. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully made member an admin. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); @@ -173,7 +177,7 @@ const ListOfMembers = ({ return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -181,13 +185,12 @@ const ListOfMembers = ({ }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - }); } catch (error) { } finally { @@ -197,22 +200,24 @@ const ListOfMembers = ({ const removeAdmin = async (address) => { try { - const fee = await getFee("REMOVE_GROUP_ADMIN"); + const fee = await getFee('REMOVE_GROUP_ADMIN'); await show({ - message: "Would you like to perform a REMOVE_GROUP_ADMIN transaction?", - publishFee: fee.fee + " QORT", + message: 'Would you like to perform a REMOVE_GROUP_ADMIN transaction?', + publishFee: fee.fee + ' QORT', }); setIsLoadingRemoveAdmin(true); await new Promise((res, rej) => { - window.sendMessage("removeAdmin", { - groupId, - qortalAddress: address, - }) + window + .sendMessage('removeAdmin', { + groupId, + qortalAddress: address, + }) .then((response) => { if (!response?.error) { setInfoSnack({ - type: "success", - message: "Successfully removed member as an admin. It may take a couple of minutes for the changes to propagate", + type: 'success', + message: + 'Successfully removed member as an admin. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); handlePopoverClose(); @@ -220,7 +225,7 @@ const ListOfMembers = ({ return; } setInfoSnack({ - type: "error", + type: 'error', message: response?.error, }); setOpenSnack(true); @@ -228,13 +233,12 @@ const ListOfMembers = ({ }) .catch((error) => { setInfoSnack({ - type: "error", - message: error.message || "An error occurred", + type: 'error', + message: error.message || 'An error occurred', }); setOpenSnack(true); rej(error); }); - }); } catch (error) { } finally { @@ -260,24 +264,24 @@ const ListOfMembers = ({ anchorEl={popoverAnchor} onClose={handlePopoverClose} anchorOrigin={{ - vertical: "bottom", - horizontal: "center", + vertical: 'bottom', + horizontal: 'center', }} transformOrigin={{ - vertical: "top", - horizontal: "center", + vertical: 'top', + horizontal: 'center', }} - style={{ marginTop: "8px" }} + style={{ marginTop: '8px' }} > {isOwner && ( @@ -336,21 +340,28 @@ const ListOfMembers = ({ {member?.isAdmin && ( - Admin - )} + + Admin + + )} -
)} @@ -363,11 +374,11 @@ const ListOfMembers = ({

Member list

diff --git a/src/components/Group/ListOfThreadPostsWatched.tsx b/src/components/Group/ListOfThreadPostsWatched.tsx index e0a9d00..1cf0d2a 100644 --- a/src/components/Group/ListOfThreadPostsWatched.tsx +++ b/src/components/Group/ListOfThreadPostsWatched.tsx @@ -42,7 +42,7 @@ export const ListOfThreadPostsWatched = () => { rej(response.error); }) .catch((error) => { - rej(error.message || 'An error occurred'); + rej(error.message || 'An error occurred'); // TODO translate }); }); } catch (error) { diff --git a/src/components/Group/ManageMembers.tsx b/src/components/Group/ManageMembers.tsx index a69dde4..05d30aa 100644 --- a/src/components/Group/ManageMembers.tsx +++ b/src/components/Group/ManageMembers.tsx @@ -105,7 +105,7 @@ export const ManageMembers = ({ rej(response.error); }) .catch((error) => { - rej(error.message || 'An error occurred'); + rej(error.message || 'An error occurred'); // TODO translate }); }); } catch (error) { diff --git a/src/components/Group/QMailMessages.tsx b/src/components/Group/QMailMessages.tsx index 857b0db..8673110 100644 --- a/src/components/Group/QMailMessages.tsx +++ b/src/components/Group/QMailMessages.tsx @@ -87,7 +87,7 @@ export const QMailMessages = ({ userName, userAddress }) => { rej(response.error); }) .catch((error) => { - rej(error.message || 'An error occurred'); + rej(error.message || 'An error occurred'); // TODO translate }); }); } catch (error) { diff --git a/src/components/Group/Settings.tsx b/src/components/Group/Settings.tsx index d3ff1f7..fd2f9c2 100644 --- a/src/components/Group/Settings.tsx +++ b/src/components/Group/Settings.tsx @@ -79,7 +79,7 @@ export const Settings = ({ address, open, setOpen }) => { if (response?.error) { console.error('Error adding user settings:', response.error); } else { - console.log('User settings added successfully'); + console.log('User settings added successfully'); // TODO translate } }) .catch((error) => { diff --git a/src/components/Group/UserListOfInvites.tsx b/src/components/Group/UserListOfInvites.tsx index 2a63896..58efd9a 100644 --- a/src/components/Group/UserListOfInvites.tsx +++ b/src/components/Group/UserListOfInvites.tsx @@ -1,240 +1,266 @@ -import { Box, Button, ListItem, ListItemButton, ListItemText, Popover, Typography } from '@mui/material'; -import React, { useContext, useEffect, useRef, useState } from 'react' -import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; +import { + Box, + ListItem, + ListItemButton, + ListItemText, + Popover, + Typography, +} from '@mui/material'; +import { useContext, useEffect, useRef, useState } from 'react'; +import { + AutoSizer, + CellMeasurer, + CellMeasurerCache, + List, +} from 'react-virtualized'; import { MyContext, getBaseApiReact } from '../../App'; import { LoadingButton } from '@mui/lab'; -import { getBaseApi, getFee } from '../../background'; +import { getFee } from '../../background'; import LockIcon from '@mui/icons-material/Lock'; import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred'; -import { Spacer } from "../../common/Spacer"; +import { Spacer } from '../../common/Spacer'; const cache = new CellMeasurerCache({ - fixedWidth: true, - defaultHeight: 50, - }); + fixedWidth: true, + defaultHeight: 50, +}); - - -const getGroupInfo = async (groupId)=> { +const getGroupInfo = async (groupId) => { const response = await fetch(`${getBaseApiReact()}/groups/` + groupId); const groupData = await response.json(); if (groupData) { - return groupData - } -} - export const getGroupNames = async (listOfGroups) => { - let groups = []; - if (listOfGroups && Array.isArray(listOfGroups)) { - for (const group of listOfGroups) { - - const groupInfo = await getGroupInfo(group.groupId); - if (groupInfo) { - groups.push({ ...group, ...groupInfo }); - - } - } - } - return groups; + return groupData; } - -export const UserListOfInvites = ({myAddress, setInfoSnack, setOpenSnack}) => { - const {txList, setTxList, show} = useContext(MyContext) - const [invites, setInvites] = useState([]); - const [isLoading, setIsLoading] = useState(false); - - const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to - const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open - const listRef = useRef(); - - const getRequests = async () => { - try { - const response = await fetch(`${getBaseApiReact()}/groups/invites/${myAddress}/?limit=0`); - const inviteData = await response.json(); - - const resMoreData = await getGroupNames(inviteData) - setInvites(resMoreData); - } catch (error) { - console.error(error); +}; +export const getGroupNames = async (listOfGroups) => { + let groups = []; + if (listOfGroups && Array.isArray(listOfGroups)) { + for (const group of listOfGroups) { + const groupInfo = await getGroupInfo(group.groupId); + if (groupInfo) { + groups.push({ ...group, ...groupInfo }); } } - - useEffect(() => { - - getRequests(); - - }, []); - - const handlePopoverOpen = (event, index) => { - setPopoverAnchor(event.currentTarget); - setOpenPopoverIndex(index); - }; - - const handlePopoverClose = () => { - setPopoverAnchor(null); - setOpenPopoverIndex(null); - }; - - const handleJoinGroup = async (groupId, groupName)=> { - try { - - const fee = await getFee('JOIN_GROUP') - await show({ - message: "Would you like to perform an JOIN_GROUP transaction?" , - publishFee: fee.fee + ' QORT' - }) + } + return groups; +}; - setIsLoading(true); +export const UserListOfInvites = ({ + myAddress, + setInfoSnack, + setOpenSnack, +}) => { + const { txList, setTxList, show } = useContext(MyContext); + const [invites, setInvites] = useState([]); + const [isLoading, setIsLoading] = useState(false); - await new Promise((res, rej)=> { - window.sendMessage("joinGroup", { + const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to + const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open + const listRef = useRef(); + + const getRequests = async () => { + try { + const response = await fetch( + `${getBaseApiReact()}/groups/invites/${myAddress}/?limit=0` + ); + const inviteData = await response.json(); + + const resMoreData = await getGroupNames(inviteData); + setInvites(resMoreData); + } catch (error) { + console.error(error); + } + }; + + useEffect(() => { + getRequests(); + }, []); + + const handlePopoverOpen = (event, index) => { + setPopoverAnchor(event.currentTarget); + setOpenPopoverIndex(index); + }; + + const handlePopoverClose = () => { + setPopoverAnchor(null); + setOpenPopoverIndex(null); + }; + + const handleJoinGroup = async (groupId, groupName) => { + try { + const fee = await getFee('JOIN_GROUP'); // TODO translate + await show({ + message: 'Would you like to perform an JOIN_GROUP transaction?', + publishFee: fee.fee + ' QORT', + }); + + setIsLoading(true); + + await new Promise((res, rej) => { + window + .sendMessage('joinGroup', { groupId, }) - .then((response) => { - if (!response?.error) { - setTxList((prev) => [ - { - ...response, - type: 'joined-group', - label: `Joined Group ${groupName}: awaiting confirmation`, - labelDone: `Joined Group ${groupName}: success!`, - done: false, - groupId, - }, - ...prev, - ]); - res(response); - setInfoSnack({ - type: "success", - message: "Successfully requested to join group. It may take a couple of minutes for the changes to propagate", - }); - setOpenSnack(true); - handlePopoverClose(); - return; - } + .then((response) => { + if (!response?.error) { + setTxList((prev) => [ + { + ...response, + type: 'joined-group', + label: `Joined Group ${groupName}: awaiting confirmation`, + labelDone: `Joined Group ${groupName}: success!`, + done: false, + groupId, + }, + ...prev, + ]); + res(response); setInfoSnack({ - type: "error", - message: response?.error, + type: 'success', + message: + 'Successfully requested to join group. It may take a couple of minutes for the changes to propagate', }); setOpenSnack(true); - rej(response.error); - }) - .catch((error) => { - setInfoSnack({ - type: "error", - message: error.message || "An error occurred", - }); - setOpenSnack(true); - rej(error); + handlePopoverClose(); + return; + } + setInfoSnack({ + type: 'error', + message: response?.error, }); - - }) - - } catch (error) { - - } finally { - setIsLoading(false); - - } + setOpenSnack(true); + rej(response.error); + }) + .catch((error) => { + setInfoSnack({ + type: 'error', + message: error.message || 'An error occurred', + }); + setOpenSnack(true); + rej(error); + }); + }); + } catch (error) { + } finally { + setIsLoading(false); } - - const rowRenderer = ({ index, key, parent, style }) => { - const invite = invites[index]; - - return ( - - {({ measure }) => ( -
- - - { + const invite = invites[index]; + + return ( + + {({ measure }) => ( +
+ + + - Join {invite?.groupName} - Join {invite?.groupName} + handleJoinGroup(invite?.groupId, invite?.groupName)}>Join group - - - handlePopoverOpen(event, index)}> + variant="contained" + onClick={() => + handleJoinGroup(invite?.groupId, invite?.groupName) + } + > + Join group + + + + handlePopoverOpen(event, index)} + > {invite?.isOpen === false && ( - + + )} + {invite?.isOpen === true && ( + + )} + + + + +
)} - {invite?.isOpen === true && ( - - )} - - - -
-
- )} -
- ); - }; - - return ( - + ); + }; + + return ( + -

Invite list

-
+

Invite list

+
- - {({ height, width }) => ( - - )} - -
- - ); -} + + {({ height, width }) => ( + + )} + +
+
+ ); +}; diff --git a/src/components/Group/WalletsAppWrapper.tsx b/src/components/Group/WalletsAppWrapper.tsx index c569425..111e216 100644 --- a/src/components/Group/WalletsAppWrapper.tsx +++ b/src/components/Group/WalletsAppWrapper.tsx @@ -88,7 +88,7 @@ export const WalletsAppWrapper = () => { justifyContent: 'space-between', }} > - Q-Wallets + Q-Wallets // TODO translate { const socketRef = useRef(null); // WebSocket reference const timeoutIdRef = useRef(null); // Timeout ID reference const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference - const initiateRef = useRef(null) + const initiateRef = useRef(null); const forceCloseWebSocket = () => { if (socketRef.current) { clearTimeout(timeoutIdRef.current); @@ -17,21 +21,20 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => { }; const logoutEventFunc = () => { - forceCloseWebSocket() + forceCloseWebSocket(); }; useEffect(() => { - subscribeToEvent("logout-event", logoutEventFunc); + subscribeToEvent('logout-event', logoutEventFunc); return () => { - unsubscribeFromEvent("logout-event", logoutEventFunc); + unsubscribeFromEvent('logout-event', logoutEventFunc); }; }, []); useEffect(() => { if (!myAddress) return; // Only proceed if myAddress is set - const pingHeads = () => { try { if (socketRef.current?.readyState === WebSocket.OPEN) { @@ -53,10 +56,9 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => { const currentAddress = myAddress; try { - if(!initiateRef.current) { - setIsLoadingGroups(true) - pauseAllQueues() - + if (!initiateRef.current) { + setIsLoadingGroups(true); + pauseAllQueues(); } const socketLink = `${getBaseApiReactSocket()}/websockets/chat/active/${currentAddress}?encoding=BASE64&haschatreference=false`; socketRef.current = new WebSocket(socketLink); @@ -71,34 +73,46 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => { clearTimeout(timeoutIdRef.current); groupSocketTimeoutRef.current = setTimeout(pingHeads, 45000); // Ping every 45 seconds } else { - if(!initiateRef.current) { - setIsLoadingGroups(false) - initiateRef.current = true - resumeAllQueues() - + if (!initiateRef.current) { + setIsLoadingGroups(false); + initiateRef.current = true; + resumeAllQueues(); } const data = JSON.parse(e.data); - const copyGroups = [...(data?.groups || [])] - const findIndex = copyGroups?.findIndex(item => item?.groupId === 0) - if(findIndex !== -1){ + const copyGroups = [...(data?.groups || [])]; + const findIndex = copyGroups?.findIndex( + (item) => item?.groupId === 0 + ); + if (findIndex !== -1) { copyGroups[findIndex] = { ...(copyGroups[findIndex] || {}), - groupId: "0" - } + groupId: '0', + }; } - const filteredGroups = copyGroups - const sortedGroups = filteredGroups.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)); - const sortedDirects = (data?.direct || []).filter(item => - item?.name !== 'extension-proxy' && item?.address !== 'QSMMGSgysEuqDCuLw3S4cHrQkBrh3vP3VH' - ).sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)); + const filteredGroups = copyGroups; + const sortedGroups = filteredGroups.sort( + (a, b) => (b.timestamp || 0) - (a.timestamp || 0) + ); + const sortedDirects = (data?.direct || []) + .filter( + (item) => + item?.name !== 'extension-proxy' && + item?.address !== 'QSMMGSgysEuqDCuLw3S4cHrQkBrh3vP3VH' + ) + .sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0)); - window.sendMessage("handleActiveGroupDataFromSocket", { - groups: sortedGroups, - directs: sortedDirects, - }).catch((error) => { - console.error("Failed to handle active group data from socket:", error.message || "An error occurred"); + window + .sendMessage('handleActiveGroupDataFromSocket', { + groups: sortedGroups, + directs: sortedDirects, + }) + .catch((error) => { + // TODO translate + console.error( + 'Failed to handle active group data from socket:', + error.message || 'An error occurred' + ); }); - } } catch (error) { console.error('Error parsing onmessage data:', error); @@ -127,9 +141,7 @@ export const WebSocketActive = ({ myAddress, setIsLoadingGroups }) => { } }; - - initWebsocketMessageGroup(); // Initialize WebSocket on component mount - + initWebsocketMessageGroup(); // Initialize WebSocket on component mount return () => { forceCloseWebSocket(); // Clean up WebSocket on component unmount diff --git a/src/components/Group/useBlockUsers.tsx b/src/components/Group/useBlockUsers.tsx index eeb5361..178c358 100644 --- a/src/components/Group/useBlockUsers.tsx +++ b/src/components/Group/useBlockUsers.tsx @@ -1,218 +1,194 @@ -import React, { useCallback, useEffect, useRef } from "react"; -import { getBaseApiReact } from "../../App"; -import { truncate } from "lodash"; - - +import { useCallback, useEffect, useRef } from 'react'; export const useBlockedAddresses = () => { - const userBlockedRef = useRef({}) - const userNamesBlockedRef = useRef({}) - - const getAllBlockedUsers = useCallback(()=> { + const userBlockedRef = useRef({}); + const userNamesBlockedRef = useRef({}); + const getAllBlockedUsers = useCallback(() => { return { names: userNamesBlockedRef.current, - addresses: userBlockedRef.current - } - }, []) + addresses: userBlockedRef.current, + }; + }, []); - const isUserBlocked = useCallback((address, name)=> { + const isUserBlocked = useCallback((address, name) => { try { - if(!address) return false - if(userBlockedRef.current[address]) return true - return false - - + if (!address) return false; + if (userBlockedRef.current[address]) return true; + return false; } catch (error) { - //error + //error } - }, []) + }, []); - useEffect(()=> { - const fetchBlockedList = async ()=> { + useEffect(() => { + const fetchBlockedList = async () => { try { - const response = await new Promise((res, rej) => { - window.sendMessage("listActions", { - + const response = await new Promise((res, rej) => { + window + .sendMessage('listActions', { type: 'get', listName: `blockedAddresses`, - - }) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - res(response); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - }) - const blockedUsers = {} - response?.forEach((item)=> { - blockedUsers[item] = true - }) - userBlockedRef.current = blockedUsers + }) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + res(response); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); + }); + const blockedUsers = {}; + response?.forEach((item) => { + blockedUsers[item] = true; + }); + userBlockedRef.current = blockedUsers; - const response2 = await new Promise((res, rej) => { - window.sendMessage("listActions", { - + const response2 = await new Promise((res, rej) => { + window + .sendMessage('listActions', { type: 'get', listName: `blockedNames`, - + }) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + res(response); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); + }); + const blockedUsers2 = {}; + response2?.forEach((item) => { + blockedUsers2[item] = true; + }); + userNamesBlockedRef.current = blockedUsers2; + } catch (error) { + console.error(error); + } + }; + fetchBlockedList(); + }, []); + + const removeBlockFromList = useCallback(async (address, name) => { + if (name) { + await new Promise((res, rej) => { + window + .sendMessage('listActions', { + type: 'remove', + items: [name], + listName: 'blockedNames', }) .then((response) => { if (response.error) { rej(response?.message); return; } else { + const copyObject = { ...userNamesBlockedRef.current }; + delete copyObject[name]; + userNamesBlockedRef.current = copyObject; + res(response); } }) .catch((error) => { - console.error("Failed qortalRequest", error); + console.error('Failed qortalRequest', error); }); - }) - const blockedUsers2 = {} - response2?.forEach((item)=> { - blockedUsers2[item] = true - }) - userNamesBlockedRef.current = blockedUsers2 - - - } catch (error) { - console.error(error) - } - } - fetchBlockedList() - }, []) - - const removeBlockFromList = useCallback(async (address, name)=> { - if(name){ - await new Promise((res, rej) => { - window.sendMessage("listActions", { - - type: 'remove', - items: [name] , - listName: 'blockedNames' - - }) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - - const copyObject = {...userNamesBlockedRef.current} - delete copyObject[name] - userNamesBlockedRef.current = copyObject - - - res(response); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - }) + }); } - if(address){ + if (address) { await new Promise((res, rej) => { - window.sendMessage("listActions", { - + window + .sendMessage('listActions', { type: 'remove', items: [address], - listName: 'blockedAddresses' - - }) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - - const copyObject = {...userBlockedRef.current} - delete copyObject[address] - userBlockedRef.current = copyObject - - - res(response); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - }) - } - - - }, []) + listName: 'blockedAddresses', + }) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + const copyObject = { ...userBlockedRef.current }; + delete copyObject[address]; + userBlockedRef.current = copyObject; - const addToBlockList = useCallback(async (address, name)=> { - if(name){ + res(response); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); + }); + } + }, []); + + const addToBlockList = useCallback(async (address, name) => { + if (name) { await new Promise((res, rej) => { - window.sendMessage("listActions", { - + window + .sendMessage('listActions', { type: 'add', items: [name], - listName: 'blockedNames' - - }) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - const copyObject = {...userNamesBlockedRef.current} - copyObject[name] = true - userNamesBlockedRef.current = copyObject - - - res(response); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - }) + listName: 'blockedNames', + }) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + const copyObject = { ...userNamesBlockedRef.current }; + copyObject[name] = true; + userNamesBlockedRef.current = copyObject; + + res(response); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); + }); } - if(address){ + if (address) { await new Promise((res, rej) => { - window.sendMessage("listActions", { - + window + .sendMessage('listActions', { type: 'add', items: [address], - listName: 'blockedAddresses' - - }) - .then((response) => { - if (response.error) { - rej(response?.message); - return; - } else { - - const copyObject = {...userBlockedRef.current} - copyObject[address] = true - userBlockedRef.current = copyObject - - res(response); - } - }) - .catch((error) => { - console.error("Failed qortalRequest", error); - }); - }) + listName: 'blockedAddresses', + }) + .then((response) => { + if (response.error) { + rej(response?.message); + return; + } else { + const copyObject = { ...userBlockedRef.current }; + copyObject[address] = true; + userBlockedRef.current = copyObject; + + res(response); + } + }) + .catch((error) => { + console.error('Failed qortalRequest', error); + }); + }); } - - }, []) + }, []); return { isUserBlocked, addToBlockList, removeBlockFromList, - getAllBlockedUsers + getAllBlockedUsers, }; }; diff --git a/src/components/Group/useHandleUserInfo.tsx b/src/components/Group/useHandleUserInfo.tsx index a497259..622e737 100644 --- a/src/components/Group/useHandleUserInfo.tsx +++ b/src/components/Group/useHandleUserInfo.tsx @@ -1,32 +1,30 @@ -import React, { useCallback, useRef } from "react"; -import { getBaseApiReact } from "../../App"; - - +import { useCallback, useRef } from 'react'; +import { getBaseApiReact } from '../../App'; export const useHandleUserInfo = () => { - const userInfoRef = useRef({}) + const userInfoRef = useRef({}); - - const getIndividualUserInfo = useCallback(async (address)=> { + const getIndividualUserInfo = useCallback(async (address) => { try { - if(!address) return null - if(userInfoRef.current[address] !== undefined) return userInfoRef.current[address] + if (!address) return null; + if (userInfoRef.current[address] !== undefined) + return userInfoRef.current[address]; const url = `${getBaseApiReact()}/addresses/${address}`; - const response = await fetch(url); - if (!response.ok) { - throw new Error("network error"); - } - const data = await response.json(); - userInfoRef.current = { - ...userInfoRef.current, - [address]: data?.level - } - return data?.level + const response = await fetch(url); + if (!response.ok) { + throw new Error('network error'); + } + const data = await response.json(); + userInfoRef.current = { + ...userInfoRef.current, + [address]: data?.level, + }; + return data?.level; } catch (error) { - //error + //error } - }, []) + }, []); return { getIndividualUserInfo, diff --git a/src/components/Home/NewUsersCTA.tsx b/src/components/Home/NewUsersCTA.tsx index 4ad5c79..30dea8a 100644 --- a/src/components/Home/NewUsersCTA.tsx +++ b/src/components/Home/NewUsersCTA.tsx @@ -1,40 +1,40 @@ -import { Box, ButtonBase, Typography } from "@mui/material"; -import React from "react"; -import { Spacer } from "../../common/Spacer"; +import { Box, ButtonBase, Typography } from '@mui/material'; +import { Spacer } from '../../common/Spacer'; export const NewUsersCTA = ({ balance }) => { if (balance === undefined || +balance > 0) return null; return ( Are you a new user? - + {' '} + // TODO translate Please message us on Telegram or Discord if you need 4 QORT to start @@ -43,25 +43,25 @@ export const NewUsersCTA = ({ balance }) => { { if (window?.electronAPI?.openExternal) { window.electronAPI.openExternal( - "https://link.qortal.dev/telegram-invite" + 'https://link.qortal.dev/telegram-invite' ); } else { window.open( - "https://link.qortal.dev/telegram-invite", - "_blank" + 'https://link.qortal.dev/telegram-invite', + '_blank' ); } }} @@ -70,15 +70,15 @@ export const NewUsersCTA = ({ balance }) => { { if (window?.electronAPI?.openExternal) { window.electronAPI.openExternal( - "https://link.qortal.dev/discord-invite" + 'https://link.qortal.dev/discord-invite' ); } else { - window.open("https://link.qortal.dev/discord-invite", "_blank"); + window.open('https://link.qortal.dev/discord-invite', '_blank'); } }} > diff --git a/src/components/Minting/Minting.tsx b/src/components/Minting/Minting.tsx index 84697c8..7187986 100644 --- a/src/components/Minting/Minting.tsx +++ b/src/components/Minting/Minting.tsx @@ -206,7 +206,6 @@ export const Minting = ({ window .sendMessage( 'ADMIN_ACTION', - { type: 'addmintingaccount', value: val, @@ -266,7 +265,7 @@ export const Minting = ({ rej({ message: response.error }); }) .catch((error) => { - rej({ message: error.message || 'An error occurred' }); + rej({ message: error.message || 'An error occurred' }); //TODO translate }); }); } catch (error) {