Identifiers.ts created, all identifiers used in app are located here.
Fixed warning involving messages in Thread.tsx not having a key prop.
This commit is contained in:
parent
8d54ec7d1c
commit
6ad071376b
@ -1,21 +1,22 @@
|
||||
import React from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { setNotification } from '../../state/features/notificationsSlice'
|
||||
import { RootState } from '../../state/store'
|
||||
import ShortUniqueId from 'short-unique-id'
|
||||
import React from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AUDIO_BASE } from "../../constants/Identifiers";
|
||||
import { setNotification } from "../../state/features/notificationsSlice";
|
||||
import { RootState } from "../../state/store";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
|
||||
const uid = new ShortUniqueId()
|
||||
const uid = new ShortUniqueId();
|
||||
|
||||
interface IPublishVideo {
|
||||
title: string
|
||||
description: string
|
||||
base64: string
|
||||
category: string
|
||||
title: string;
|
||||
description: string;
|
||||
base64: string;
|
||||
category: string;
|
||||
}
|
||||
|
||||
export const usePublishAudio = () => {
|
||||
const { user } = useSelector((state: RootState) => state.auth)
|
||||
const dispatch = useDispatch()
|
||||
const { user } = useSelector((state: RootState) => state.auth);
|
||||
const dispatch = useDispatch();
|
||||
const publishAudio = async ({
|
||||
title,
|
||||
description,
|
||||
@ -23,84 +24,83 @@ export const usePublishAudio = () => {
|
||||
category,
|
||||
...rest
|
||||
}: IPublishVideo) => {
|
||||
let address
|
||||
let name
|
||||
let errorMsg = ''
|
||||
let address;
|
||||
let name;
|
||||
let errorMsg = "";
|
||||
|
||||
address = user?.address
|
||||
name = user?.name || ''
|
||||
address = user?.address;
|
||||
name = user?.name || "";
|
||||
|
||||
const missingFields = []
|
||||
const missingFields = [];
|
||||
if (!address) {
|
||||
errorMsg = "Cannot post: your address isn't available"
|
||||
errorMsg = "Cannot post: your address isn't available";
|
||||
}
|
||||
if (!name) {
|
||||
errorMsg = 'Cannot post without a name'
|
||||
errorMsg = "Cannot post without a name";
|
||||
}
|
||||
if (!title) missingFields.push('title')
|
||||
if (!title) missingFields.push("title");
|
||||
if (missingFields.length > 0) {
|
||||
const missingFieldsString = missingFields.join(', ')
|
||||
const errMsg = `Missing: ${missingFieldsString}`
|
||||
errorMsg = errMsg
|
||||
const missingFieldsString = missingFields.join(", ");
|
||||
const errMsg = `Missing: ${missingFieldsString}`;
|
||||
errorMsg = errMsg;
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
dispatch(
|
||||
setNotification({
|
||||
msg: errorMsg,
|
||||
alertType: 'error'
|
||||
alertType: "error",
|
||||
})
|
||||
)
|
||||
throw new Error(errorMsg)
|
||||
);
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
try {
|
||||
const id = uid()
|
||||
const id = uid();
|
||||
|
||||
const identifier = `qaudio_qblog_${id}`
|
||||
const identifier = AUDIO_BASE + id;
|
||||
|
||||
const resourceResponse = await qortalRequest({
|
||||
action: 'PUBLISH_QDN_RESOURCE',
|
||||
action: "PUBLISH_QDN_RESOURCE",
|
||||
name: name,
|
||||
service: 'AUDIO',
|
||||
service: "AUDIO",
|
||||
data64: base64,
|
||||
title: title,
|
||||
description: description,
|
||||
category: category,
|
||||
...rest,
|
||||
identifier: identifier
|
||||
})
|
||||
identifier: identifier,
|
||||
});
|
||||
dispatch(
|
||||
setNotification({
|
||||
msg: 'Audio successfully published',
|
||||
alertType: 'success'
|
||||
msg: "Audio successfully published",
|
||||
alertType: "success",
|
||||
})
|
||||
)
|
||||
return resourceResponse
|
||||
);
|
||||
return resourceResponse;
|
||||
} catch (error: any) {
|
||||
let notificationObj = null
|
||||
if (typeof error === 'string') {
|
||||
let notificationObj = null;
|
||||
if (typeof error === "string") {
|
||||
notificationObj = {
|
||||
msg: error || 'Failed to publish audio',
|
||||
alertType: 'error'
|
||||
}
|
||||
} else if (typeof error?.error === 'string') {
|
||||
msg: error || "Failed to publish audio",
|
||||
alertType: "error",
|
||||
};
|
||||
} else if (typeof error?.error === "string") {
|
||||
notificationObj = {
|
||||
msg: error?.error || 'Failed to publish audio',
|
||||
alertType: 'error'
|
||||
}
|
||||
msg: error?.error || "Failed to publish audio",
|
||||
alertType: "error",
|
||||
};
|
||||
} else {
|
||||
notificationObj = {
|
||||
msg: error?.message || error?.message || 'Failed to publish audio',
|
||||
alertType: 'error'
|
||||
}
|
||||
}
|
||||
if (!notificationObj) return
|
||||
dispatch(setNotification(notificationObj))
|
||||
|
||||
msg: error?.message || error?.message || "Failed to publish audio",
|
||||
alertType: "error",
|
||||
};
|
||||
}
|
||||
if (!notificationObj) return;
|
||||
dispatch(setNotification(notificationObj));
|
||||
}
|
||||
};
|
||||
return {
|
||||
publishAudio
|
||||
}
|
||||
}
|
||||
publishAudio,
|
||||
};
|
||||
};
|
||||
|
6
src/constants/Identifiers.ts
Normal file
6
src/constants/Identifiers.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export const AUDIO_BASE = "qaudio_qblog_";
|
||||
export const THREAD_BASE = "qortal_qmail_thread_group";
|
||||
export const ATTATCHMENT_BASE = "attachments_qmail_";
|
||||
export const QMAIL_BASE = "_mail_qortal_qmail_";
|
||||
|
||||
export const THREAD_MESSAGE = "qortal_qmail_thmsg_group";
|
@ -8,6 +8,7 @@ import React, {
|
||||
} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { THREAD_BASE, THREAD_MESSAGE } from "../../constants/Identifiers";
|
||||
import { RootState } from "../../state/store";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import {
|
||||
@ -128,7 +129,7 @@ export const GroupMail = ({
|
||||
if (isInitial) {
|
||||
dispatch(setIsLoadingCustom("Loading threads"));
|
||||
}
|
||||
const query = `qortal_qmail_thread_group${groupId}`;
|
||||
const query = `${THREAD_BASE}${groupId}`;
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${THREAD_SERVICE_TYPE}&query=${query}&limit=${20}&includemetadata=true&offset=${offset}&reverse=${isReverse}&excludeblocked=true`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
@ -213,7 +214,7 @@ export const GroupMail = ({
|
||||
.join("");
|
||||
|
||||
dispatch(setIsLoadingCustom("Loading recent threads"));
|
||||
const query = `qortal_qmail_thmsg_group${groupId}`;
|
||||
const query = `${THREAD_MESSAGE}${groupId}`;
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&query=${query}&limit=100&includemetadata=false&offset=${0}&reverse=true&excludeblocked=true${queryString}`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
@ -237,7 +238,7 @@ export const GroupMail = ({
|
||||
.map(key => {
|
||||
return {
|
||||
...messagesForThread[key],
|
||||
threadId: `qortal_qmail_thread_group${groupId}_${key}`,
|
||||
threadId: `${THREAD_BASE}${groupId}_${key}`,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => b.created - a.created)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,8 @@
|
||||
import React, { Dispatch, useCallback, useEffect, useState } from "react";
|
||||
import { ReusableModal } from "../../components/modals/ReusableModal";
|
||||
import { Box, Button, Input, Typography, useTheme } from "@mui/material";
|
||||
import { ATTATCHMENT_BASE, THREAD_BASE } from "../../constants/Identifiers";
|
||||
import { getFileExtension } from "../../utils/helpers";
|
||||
import { BuilderButton } from "../CreatePost/CreatePost-styles";
|
||||
import BlogEditor from "../../components/editor/BlogEditor";
|
||||
import EmailIcon from "@mui/icons-material/Email";
|
||||
@ -19,7 +21,6 @@ import ModalCloseSVG from "../../assets/svgs/ModalClose.svg";
|
||||
import AttachmentSVG from "../../assets/svgs/NewMessageAttachment.svg";
|
||||
import CreateThreadSVG from "../../assets/svgs/CreateThread.svg";
|
||||
|
||||
|
||||
import {
|
||||
objectToBase64,
|
||||
objectToUint8Array,
|
||||
@ -70,7 +71,7 @@ interface NewMessageProps {
|
||||
currentThread?: any;
|
||||
isMessage?: boolean;
|
||||
messageCallback?: (val: any) => void;
|
||||
threadCallback?: (val: any)=> void;
|
||||
threadCallback?: (val: any) => void;
|
||||
refreshLatestThreads?: () => void;
|
||||
members: any;
|
||||
}
|
||||
@ -83,7 +84,7 @@ export const NewThread = ({
|
||||
isMessage = false,
|
||||
messageCallback,
|
||||
refreshLatestThreads,
|
||||
threadCallback
|
||||
threadCallback,
|
||||
}: NewMessageProps) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const [value, setValue] = useState("");
|
||||
@ -98,7 +99,6 @@ export const NewThread = ({
|
||||
const [publishes, setPublishes] = useState<any>(null);
|
||||
const [callbackContent, setCallbackContent] = useState<any>(null);
|
||||
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -115,7 +115,7 @@ export const NewThread = ({
|
||||
files.push({
|
||||
file: item,
|
||||
mimetype: null,
|
||||
extension: null,
|
||||
extension: getFileExtension(item.name),
|
||||
});
|
||||
} else {
|
||||
const extension = mime.getExtension(type);
|
||||
@ -123,7 +123,7 @@ export const NewThread = ({
|
||||
files.push({
|
||||
file: item,
|
||||
mimetype: type,
|
||||
extension: null,
|
||||
extension: getFileExtension(item.name),
|
||||
});
|
||||
} else {
|
||||
files.push({
|
||||
@ -169,7 +169,6 @@ export const NewThread = ({
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
subscribeToEvent("openNewThreadModal", openModalFromEvent);
|
||||
|
||||
@ -264,7 +263,7 @@ export const NewThread = ({
|
||||
|
||||
const id = uid();
|
||||
const id2 = uid();
|
||||
const identifier = `attachments_qmail_${id}_${id2}`;
|
||||
const identifier = `${ATTATCHMENT_BASE}${id}_${id2}`;
|
||||
let fileExtension = attachment?.name?.split(".")?.pop();
|
||||
if (!fileExtension) {
|
||||
fileExtension = singleAttachment.extension;
|
||||
@ -314,7 +313,7 @@ export const NewThread = ({
|
||||
name,
|
||||
};
|
||||
const threadToBase64 = await objectToBase64(threadObject);
|
||||
let identifierThread = `qortal_qmail_thread_group${groupInfo.id}_${idThread}`;
|
||||
let identifierThread = `${THREAD_BASE}${groupInfo.id}_${idThread}`;
|
||||
let requestBodyThread: any = {
|
||||
name: name,
|
||||
service: THREAD_SERVICE_TYPE,
|
||||
@ -366,10 +365,10 @@ export const NewThread = ({
|
||||
name,
|
||||
threadId: identifierThread,
|
||||
created: Date.now(),
|
||||
service: 'MAIL_PRIVATE',
|
||||
identifier: identifier
|
||||
}
|
||||
})
|
||||
service: "MAIL_PRIVATE",
|
||||
identifier: identifier,
|
||||
},
|
||||
});
|
||||
}
|
||||
closeModal();
|
||||
} else {
|
||||
@ -410,8 +409,8 @@ export const NewThread = ({
|
||||
service: MAIL_SERVICE_TYPE,
|
||||
created: Date.now(),
|
||||
...mailObject,
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
// messageCallback({
|
||||
// identifier,
|
||||
// id: identifier,
|
||||
@ -502,27 +501,27 @@ export const NewThread = ({
|
||||
<Input
|
||||
id="standard-adornment-name"
|
||||
value={threadTitle}
|
||||
onChange={(e) => {
|
||||
setThreadTitle(e.target.value)
|
||||
onChange={e => {
|
||||
setThreadTitle(e.target.value);
|
||||
}}
|
||||
placeholder="Thread Title"
|
||||
disableUnderline
|
||||
autoComplete='off'
|
||||
autoCorrect='off'
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
sx={{
|
||||
width: '100%',
|
||||
color: 'var(--new-message-text)',
|
||||
'& .MuiInput-input::placeholder': {
|
||||
color: 'rgba(84, 84, 84, 0.70) !important',
|
||||
fontSize: '20px',
|
||||
fontStyle: 'normal',
|
||||
width: "100%",
|
||||
color: "var(--new-message-text)",
|
||||
"& .MuiInput-input::placeholder": {
|
||||
color: "rgba(84, 84, 84, 0.70) !important",
|
||||
fontSize: "20px",
|
||||
fontStyle: "normal",
|
||||
fontWeight: 400,
|
||||
lineHeight: '120%', // 24px
|
||||
letterSpacing: '0.15px',
|
||||
opacity: 1
|
||||
lineHeight: "120%", // 24px
|
||||
letterSpacing: "0.15px",
|
||||
opacity: 1,
|
||||
},
|
||||
'&:focus': {
|
||||
outline: 'none',
|
||||
"&:focus": {
|
||||
outline: "none",
|
||||
},
|
||||
// Add any additional styles for the input here
|
||||
}}
|
||||
@ -532,11 +531,11 @@ export const NewThread = ({
|
||||
)}
|
||||
|
||||
<Spacer height="10px" />
|
||||
<NewMessageInputRow sx={{
|
||||
gap: '10px'
|
||||
}}>
|
||||
|
||||
|
||||
<NewMessageInputRow
|
||||
sx={{
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
<AttachmentContainer
|
||||
{...getRootProps()}
|
||||
sx={{
|
||||
@ -562,6 +561,7 @@ export const NewThread = ({
|
||||
alignItems: "center",
|
||||
gap: "15px",
|
||||
}}
|
||||
key={file.name + index}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
@ -635,48 +635,50 @@ export const NewThread = ({
|
||||
width="25px"
|
||||
/>
|
||||
) : (
|
||||
<CreateThreadIcon color="red"
|
||||
opacity={1} height="25px" width="25px" />
|
||||
<CreateThreadIcon
|
||||
color="red"
|
||||
opacity={1}
|
||||
height="25px"
|
||||
width="25px"
|
||||
/>
|
||||
)}
|
||||
|
||||
</NewMessageSendButton>
|
||||
</InstanceFooter>
|
||||
|
||||
</ReusableModal>
|
||||
{isOpenMultiplePublish && (
|
||||
<MultiplePublish
|
||||
isOpen={isOpenMultiplePublish}
|
||||
onError={(messageNotification)=> {
|
||||
onError={messageNotification => {
|
||||
setIsOpenMultiplePublish(false);
|
||||
setPublishes(null)
|
||||
setCallbackContent(null)
|
||||
if(messageNotification){
|
||||
setPublishes(null);
|
||||
setCallbackContent(null);
|
||||
if (messageNotification) {
|
||||
dispatch(
|
||||
setNotification({
|
||||
msg: messageNotification,
|
||||
alertType: 'error'
|
||||
alertType: "error",
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
onSubmit={() => {
|
||||
dispatch(
|
||||
setNotification({
|
||||
msg: 'Posted',
|
||||
alertType: 'success'
|
||||
msg: "Posted",
|
||||
alertType: "success",
|
||||
})
|
||||
)
|
||||
if(messageCallback && callbackContent?.message){
|
||||
messageCallback(callbackContent.message)
|
||||
);
|
||||
if (messageCallback && callbackContent?.message) {
|
||||
messageCallback(callbackContent.message);
|
||||
}
|
||||
if(threadCallback && callbackContent?.thread){
|
||||
threadCallback(callbackContent.thread)
|
||||
if (threadCallback && callbackContent?.thread) {
|
||||
threadCallback(callbackContent.thread);
|
||||
}
|
||||
setCallbackContent(null)
|
||||
setCallbackContent(null);
|
||||
setIsOpenMultiplePublish(false);
|
||||
setPublishes(null)
|
||||
setPublishes(null);
|
||||
|
||||
closeModal()
|
||||
closeModal();
|
||||
}}
|
||||
publishes={publishes}
|
||||
/>
|
||||
|
@ -4,112 +4,125 @@ import React, {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { RootState } from '../../state/store'
|
||||
import EditIcon from '@mui/icons-material/Edit'
|
||||
import { Box, Button, CircularProgress, Input, Typography, useTheme } from '@mui/material'
|
||||
import { useFetchPosts } from '../../hooks/useFetchPosts'
|
||||
import LazyLoad from '../../components/common/LazyLoad'
|
||||
import { removePrefix } from '../../utils/blogIdformats'
|
||||
import { NewMessage } from './NewMessage'
|
||||
import Tabs from '@mui/material/Tabs'
|
||||
import Tab from '@mui/material/Tab'
|
||||
import { useFetchMail } from '../../hooks/useFetchMail'
|
||||
import { ShowMessage } from './ShowMessage'
|
||||
import { addToHashMapMail } from '../../state/features/mailSlice'
|
||||
useState,
|
||||
} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { QMAIL_BASE } from "../../constants/Identifiers";
|
||||
import { RootState } from "../../state/store";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Input,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { useFetchPosts } from "../../hooks/useFetchPosts";
|
||||
import LazyLoad from "../../components/common/LazyLoad";
|
||||
import { removePrefix } from "../../utils/blogIdformats";
|
||||
import { NewMessage } from "./NewMessage";
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
import { useFetchMail } from "../../hooks/useFetchMail";
|
||||
import { ShowMessage } from "./ShowMessage";
|
||||
import { addToHashMapMail } from "../../state/features/mailSlice";
|
||||
import {
|
||||
setIsLoadingGlobal,
|
||||
setUserAvatarHash
|
||||
} from '../../state/features/globalSlice'
|
||||
import SimpleTable from './MailTable'
|
||||
import { MAIL_SERVICE_TYPE } from '../../constants/mail'
|
||||
import { BlogPost } from '../../state/features/blogSlice'
|
||||
import { setNotification } from '../../state/features/notificationsSlice'
|
||||
import { useModal } from '../../components/common/useModal'
|
||||
import { OpenMail } from './OpenMail'
|
||||
import { MessagesContainer } from './Mail-styles'
|
||||
import { MailMessageRow } from './MailMessageRow'
|
||||
setUserAvatarHash,
|
||||
} from "../../state/features/globalSlice";
|
||||
import SimpleTable from "./MailTable";
|
||||
import { MAIL_SERVICE_TYPE } from "../../constants/mail";
|
||||
import { BlogPost } from "../../state/features/blogSlice";
|
||||
import { setNotification } from "../../state/features/notificationsSlice";
|
||||
import { useModal } from "../../components/common/useModal";
|
||||
import { OpenMail } from "./OpenMail";
|
||||
import { MessagesContainer } from "./Mail-styles";
|
||||
import { MailMessageRow } from "./MailMessageRow";
|
||||
|
||||
interface SentMailProps {
|
||||
onOpen: (user: string, identifier: string, content: any, to?:string)=> Promise<void>
|
||||
onOpen: (
|
||||
user: string,
|
||||
identifier: string,
|
||||
content: any,
|
||||
to?: string
|
||||
) => Promise<void>;
|
||||
}
|
||||
export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
const {isShow, onCancel, onOk, show} = useModal()
|
||||
export const SentMail = ({ onOpen }: SentMailProps) => {
|
||||
const { isShow, onCancel, onOk, show } = useModal();
|
||||
|
||||
const theme = useTheme()
|
||||
const { user } = useSelector((state: RootState) => state.auth)
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||
const theme = useTheme();
|
||||
const { user } = useSelector((state: RootState) => state.auth);
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [message, setMessage] = useState<any>(null)
|
||||
const [replyTo, setReplyTo] = useState<any>(null)
|
||||
const [valueTab, setValueTab] = React.useState(0)
|
||||
const [aliasValue, setAliasValue] = useState('')
|
||||
const [alias, setAlias] = useState<string[]>([])
|
||||
const [mailInfo, setMailInfo] = useState<any>(null)
|
||||
const [message, setMessage] = useState<any>(null);
|
||||
const [replyTo, setReplyTo] = useState<any>(null);
|
||||
const [valueTab, setValueTab] = React.useState(0);
|
||||
const [aliasValue, setAliasValue] = useState("");
|
||||
const [alias, setAlias] = useState<string[]>([]);
|
||||
const [mailInfo, setMailInfo] = useState<any>(null);
|
||||
const hashMapPosts = useSelector(
|
||||
(state: RootState) => state.blog.hashMapPosts
|
||||
)
|
||||
const [mailMessages, setMailMessages] = useState<any[]>([])
|
||||
);
|
||||
const [mailMessages, setMailMessages] = useState<any[]>([]);
|
||||
const hashMapMailMessages = useSelector(
|
||||
(state: RootState) => state.mail.hashMapMailMessages
|
||||
)
|
||||
);
|
||||
|
||||
const fullMailMessages = useMemo(() => {
|
||||
return mailMessages.map((msg) => {
|
||||
let message = msg
|
||||
const existingMessage = hashMapMailMessages[msg.id]
|
||||
return mailMessages.map(msg => {
|
||||
let message = msg;
|
||||
const existingMessage = hashMapMailMessages[msg.id];
|
||||
if (existingMessage) {
|
||||
message = existingMessage
|
||||
message = existingMessage;
|
||||
}
|
||||
return message
|
||||
})
|
||||
}, [mailMessages, hashMapMailMessages, user])
|
||||
const dispatch = useDispatch()
|
||||
const navigate = useNavigate()
|
||||
return message;
|
||||
});
|
||||
}, [mailMessages, hashMapMailMessages, user]);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getAvatar = async (user: string) => {
|
||||
try {
|
||||
let url = await qortalRequest({
|
||||
action: 'GET_QDN_RESOURCE_URL',
|
||||
action: "GET_QDN_RESOURCE_URL",
|
||||
name: user,
|
||||
service: 'THUMBNAIL',
|
||||
identifier: 'qortal_avatar'
|
||||
})
|
||||
service: "THUMBNAIL",
|
||||
identifier: "qortal_avatar",
|
||||
});
|
||||
dispatch(
|
||||
setUserAvatarHash({
|
||||
name: user,
|
||||
url
|
||||
url,
|
||||
})
|
||||
)
|
||||
);
|
||||
} catch (error) {}
|
||||
}
|
||||
};
|
||||
|
||||
const checkNewMessages = React.useCallback(
|
||||
async (recipientName: string, recipientAddress: string) => {
|
||||
try {
|
||||
if (!user?.name) return
|
||||
const query = `_mail_qortal_qmail_`
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&identifier=_mail_&query=${query}&name=${user?.name}&limit=20&includemetadata=true&reverse=true&excludeblocked=true`
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
const responseData = await response.json()
|
||||
if (!user?.name) return;
|
||||
|
||||
const latestPost = mailMessages[0]
|
||||
if (!latestPost) return
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&identifier=_mail_&query=${QMAIL_BASE}&name=${user?.name}&limit=20&includemetadata=true&reverse=true&excludeblocked=true`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const responseData = await response.json();
|
||||
|
||||
const latestPost = mailMessages[0];
|
||||
if (!latestPost) return;
|
||||
const findPost = responseData?.findIndex(
|
||||
(item: any) => item?.identifier === latestPost?.id
|
||||
)
|
||||
);
|
||||
if (findPost === -1) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
const newArray = responseData.slice(0, findPost)
|
||||
const newArray = responseData.slice(0, findPost);
|
||||
const structureData = newArray.map((post: any): BlogPost => {
|
||||
return {
|
||||
title: post?.metadata?.title,
|
||||
@ -120,50 +133,50 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
createdAt: post?.created,
|
||||
updated: post?.updated,
|
||||
user: post.name,
|
||||
id: post.identifier
|
||||
}
|
||||
})
|
||||
setMailMessages((prev) => {
|
||||
const updatedMessages = [...prev]
|
||||
id: post.identifier,
|
||||
};
|
||||
});
|
||||
setMailMessages(prev => {
|
||||
const updatedMessages = [...prev];
|
||||
|
||||
structureData.forEach((newMessage: any) => {
|
||||
const existingIndex = updatedMessages.findIndex(
|
||||
(prevMessage) => prevMessage.id === newMessage.id
|
||||
)
|
||||
prevMessage => prevMessage.id === newMessage.id
|
||||
);
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
// Replace existing message
|
||||
updatedMessages[existingIndex] = newMessage
|
||||
updatedMessages[existingIndex] = newMessage;
|
||||
} else {
|
||||
// Add new message
|
||||
updatedMessages.unshift(newMessage)
|
||||
updatedMessages.unshift(newMessage);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return updatedMessages
|
||||
})
|
||||
return
|
||||
return updatedMessages;
|
||||
});
|
||||
return;
|
||||
} catch (error) {}
|
||||
},
|
||||
[mailMessages]
|
||||
)
|
||||
);
|
||||
|
||||
const getMailMessages = React.useCallback(
|
||||
async (recipientName: string, recipientAddress: string) => {
|
||||
try {
|
||||
if (!user?.name) return
|
||||
const offset = mailMessages.length
|
||||
if (!user?.name) return;
|
||||
const offset = mailMessages.length;
|
||||
|
||||
// dispatch(setIsLoadingGlobal(true))
|
||||
const query = `_mail_qortal_qmail_`
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&identifier=_mail_&query=${query}&name=${user.name}&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true`
|
||||
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&identifier=_mail_&query=${QMAIL_BASE}&name=${user.name}&limit=20&includemetadata=true&offset=${offset}&reverse=true&excludeblocked=true`;
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
const responseData = await response.json()
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const responseData = await response.json();
|
||||
const structureData = responseData.map((post: any): BlogPost => {
|
||||
return {
|
||||
title: post?.metadata?.title,
|
||||
@ -174,32 +187,32 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
createdAt: post?.created,
|
||||
updated: post?.updated,
|
||||
user: post.name,
|
||||
id: post.identifier
|
||||
}
|
||||
})
|
||||
setMailMessages((prev) => {
|
||||
const updatedMessages = [...prev]
|
||||
id: post.identifier,
|
||||
};
|
||||
});
|
||||
setMailMessages(prev => {
|
||||
const updatedMessages = [...prev];
|
||||
|
||||
structureData.forEach((newMessage: any) => {
|
||||
const existingIndex = updatedMessages.findIndex(
|
||||
(prevMessage) => prevMessage.id === newMessage.id
|
||||
)
|
||||
prevMessage => prevMessage.id === newMessage.id
|
||||
);
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
// Replace existing message
|
||||
updatedMessages[existingIndex] = newMessage
|
||||
updatedMessages[existingIndex] = newMessage;
|
||||
} else {
|
||||
// Add new message
|
||||
updatedMessages.push(newMessage)
|
||||
updatedMessages.push(newMessage);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return updatedMessages
|
||||
})
|
||||
return updatedMessages;
|
||||
});
|
||||
|
||||
for (const content of structureData) {
|
||||
if (content.user && content.id) {
|
||||
getAvatar(content.user)
|
||||
getAvatar(content.user);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@ -208,8 +221,9 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
}
|
||||
},
|
||||
[mailMessages, hashMapMailMessages, user]
|
||||
)
|
||||
const getMessages = React.useCallback(async (isOnMount?: boolean) => {
|
||||
);
|
||||
const getMessages = React.useCallback(
|
||||
async (isOnMount?: boolean) => {
|
||||
if (!user?.name || !user?.address) return;
|
||||
try {
|
||||
if (isOnMount) {
|
||||
@ -220,7 +234,9 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [getMailMessages, user])
|
||||
},
|
||||
[getMailMessages, user]
|
||||
);
|
||||
|
||||
const firstMount = useRef(false);
|
||||
useEffect(() => {
|
||||
@ -230,30 +246,27 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
}
|
||||
}, [user]);
|
||||
|
||||
const interval = useRef<any>(null)
|
||||
const interval = useRef<any>(null);
|
||||
|
||||
const checkNewMessagesFunc = useCallback(() => {
|
||||
if (!user?.name || !user?.address) return
|
||||
let isCalling = false
|
||||
if (!user?.name || !user?.address) return;
|
||||
let isCalling = false;
|
||||
interval.current = setInterval(async () => {
|
||||
if (isCalling || !user?.name || !user?.address) return
|
||||
isCalling = true
|
||||
const res = await checkNewMessages(user?.name, user.address)
|
||||
isCalling = false
|
||||
}, 30000)
|
||||
}, [checkNewMessages, user])
|
||||
if (isCalling || !user?.name || !user?.address) return;
|
||||
isCalling = true;
|
||||
const res = await checkNewMessages(user?.name, user.address);
|
||||
isCalling = false;
|
||||
}, 30000);
|
||||
}, [checkNewMessages, user]);
|
||||
|
||||
useEffect(() => {
|
||||
checkNewMessagesFunc()
|
||||
checkNewMessagesFunc();
|
||||
return () => {
|
||||
if (interval?.current) {
|
||||
clearInterval(interval.current)
|
||||
clearInterval(interval.current);
|
||||
}
|
||||
}
|
||||
}, [checkNewMessagesFunc])
|
||||
|
||||
|
||||
|
||||
};
|
||||
}, [checkNewMessagesFunc]);
|
||||
|
||||
const openMessage = async (
|
||||
user: string,
|
||||
@ -262,16 +275,15 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
to?: string
|
||||
) => {
|
||||
try {
|
||||
onOpen(user, messageIdentifier, {}, to)
|
||||
|
||||
onOpen(user, messageIdentifier, {}, to);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{mailInfo && isShow && (
|
||||
<OpenMail open={isShow} handleClose={onOk} fileInfo={mailInfo}/>
|
||||
<OpenMail open={isShow} handleClose={onOk} fileInfo={mailInfo} />
|
||||
)}
|
||||
{/* <NewMessage replyTo={replyTo} setReplyTo={setReplyTo} hideButton /> */}
|
||||
<ShowMessage
|
||||
@ -292,11 +304,13 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
})}
|
||||
<LazyLoad onLoadMore={getMessages}></LazyLoad>
|
||||
{isLoading && (
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
@ -307,5 +321,5 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
||||
></SimpleTable>
|
||||
<LazyLoad onLoadMore={getMessages}></LazyLoad> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ export const ShowMessage = ({ message }: any) => {
|
||||
height: "auto",
|
||||
alignItems: "flex-start",
|
||||
cursor: "default",
|
||||
borderRadius: '35px 4px 4px 4px'
|
||||
borderRadius: "35px 4px 4px 4px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -71,7 +71,7 @@ export const ShowMessage = ({ message }: any) => {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
width: '100%'
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -79,7 +79,6 @@ export const ShowMessage = ({ message }: any) => {
|
||||
display: "flex",
|
||||
alignItems: "flex-start",
|
||||
gap: "10px",
|
||||
|
||||
}}
|
||||
>
|
||||
<AvatarWrapper
|
||||
@ -108,17 +107,21 @@ export const ShowMessage = ({ message }: any) => {
|
||||
marginTop: "10px",
|
||||
}}
|
||||
>
|
||||
{message?.attachments
|
||||
.map((file: any, index: number) => {
|
||||
const isFirst = index === 0
|
||||
{message?.attachments.map((file: any, index: number) => {
|
||||
const isFirst = index === 0;
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: expandAttachments ? "flex" : !expandAttachments && isFirst ? 'flex' : 'none',
|
||||
display: expandAttachments
|
||||
? "flex"
|
||||
: !expandAttachments && isFirst
|
||||
? "flex"
|
||||
: "none",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
width: "100%",
|
||||
}}
|
||||
key={file.name + index}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
@ -140,11 +143,11 @@ export const ShowMessage = ({ message }: any) => {
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
transition: '0.2s all',
|
||||
transition: "0.2s all",
|
||||
"&:hover": {
|
||||
color: 'rgba(255, 255, 255, 0.90)',
|
||||
textDecoration: 'underline'
|
||||
}
|
||||
color: "rgba(255, 255, 255, 0.90)",
|
||||
textDecoration: "underline",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{file?.originalFilename || file?.filename}
|
||||
@ -171,19 +174,18 @@ export const ShowMessage = ({ message }: any) => {
|
||||
src={MoreSVG}
|
||||
/>
|
||||
<MoreP>
|
||||
{expandAttachments ? 'hide' : `(${message?.attachments?.length - 1} more)`}
|
||||
|
||||
{expandAttachments
|
||||
? "hide"
|
||||
: `(${message?.attachments?.length - 1} more)`}
|
||||
</MoreP>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
}
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</Box>
|
||||
<Spacer height="20px" />
|
||||
@ -198,9 +200,6 @@ export const ShowMessage = ({ message }: any) => {
|
||||
<div dangerouslySetInnerHTML={{ __html: cleanHTML }} />
|
||||
)}
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
</SingleTheadMessageParent>
|
||||
);
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ import React, {
|
||||
} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { THREAD_MESSAGE } from "../../constants/Identifiers";
|
||||
import { RootState } from "../../state/store";
|
||||
|
||||
import {
|
||||
@ -98,7 +99,7 @@ export const Thread = ({
|
||||
let result = parts[0];
|
||||
const threadId = result;
|
||||
const offset = messages.length;
|
||||
const query = `qortal_qmail_thmsg_group${groupInfo?.threadData?.groupId}_${threadId}`;
|
||||
const query = `${THREAD_MESSAGE}${groupInfo?.threadData?.groupId}_${threadId}`;
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&query=${query}&limit=20&includemetadata=false&offset=${offset}&reverse=true&excludeblocked=true`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
@ -194,7 +195,7 @@ export const Thread = ({
|
||||
let parts = str.split("_").reverse();
|
||||
let result = parts[0];
|
||||
const threadId = result;
|
||||
const query = `qortal_qmail_thmsg_group${groupInfo?.threadData?.groupId}_${threadId}`;
|
||||
const query = `${THREAD_MESSAGE}${groupInfo?.threadData?.groupId}_${threadId}`;
|
||||
const url = `/arbitrary/resources/search?mode=ALL&service=${MAIL_SERVICE_TYPE}&query=${query}&limit=20&includemetadata=false&offset=${0}&reverse=true&excludeblocked=true`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
@ -328,8 +329,7 @@ export const Thread = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<SingleThreadParent>
|
||||
key={message?.identifier}
|
||||
<SingleThreadParent key={message?.identifier}>
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
style={{
|
||||
|
@ -1,12 +1,10 @@
|
||||
import moment from "moment";
|
||||
|
||||
export const delay = (time: number) => new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error('Request timed out')), time)
|
||||
);
|
||||
export const delay = (time: number) =>
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error("Request timed out")), time)
|
||||
);
|
||||
|
||||
// const originalHtml = `<p>---------- Forwarded message ---------</p><p>From: Alex</p><p>Date: Mon, Jun 9 2014 9:32 PM</p><p>Subject: Batteries </p><p>To: Jessica</p><p><br></p><p><br></p>`;
|
||||
|
||||
|
||||
// export function updateMessageDetails(newFrom: string, newDateMillis: number, newTo: string) {
|
||||
// let htmlString = originalHtml
|
||||
// // Use Moment.js to format the date from milliseconds
|
||||
@ -22,13 +20,27 @@ export const delay = (time: number) => new Promise((_, reject) =>
|
||||
|
||||
const originalHtml = `<p>---------- Forwarded message ---------</p><p>From: Alex</p><p>Subject: Batteries </p><p>To: Jessica</p><p><br></p><p><br></p>`;
|
||||
|
||||
export function updateMessageDetails(
|
||||
newFrom: string,
|
||||
newSubject: string,
|
||||
newTo: string
|
||||
) {
|
||||
let htmlString = originalHtml;
|
||||
|
||||
export function updateMessageDetails(newFrom: string, newSubject: string, newTo: string) {
|
||||
let htmlString = originalHtml
|
||||
|
||||
htmlString = htmlString.replace(/<p>From:.*?<\/p>/, `<p>From: ${newFrom}</p>`);
|
||||
htmlString = htmlString.replace(/<p>Subject:.*?<\/p>/, `<p>Subject: ${newSubject}</p>`);
|
||||
htmlString = htmlString.replace(
|
||||
/<p>From:.*?<\/p>/,
|
||||
`<p>From: ${newFrom}</p>`
|
||||
);
|
||||
htmlString = htmlString.replace(
|
||||
/<p>Subject:.*?<\/p>/,
|
||||
`<p>Subject: ${newSubject}</p>`
|
||||
);
|
||||
htmlString = htmlString.replace(/<p>To:.*?<\/p>/, `<p>To: ${newTo}</p>`);
|
||||
|
||||
return htmlString;
|
||||
}
|
||||
|
||||
export const getFileExtension = (fileName: string) => {
|
||||
if (!fileName.includes(".")) return null;
|
||||
return fileName.split(".").at(-1);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user