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