mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
chat portion of unencrypted open groups
This commit is contained in:
parent
50955941e4
commit
4cafd57abe
@ -664,8 +664,7 @@ const handleNotification = async (groups) => {
|
|||||||
const data = groups.filter(
|
const data = groups.filter(
|
||||||
(group) =>
|
(group) =>
|
||||||
group?.sender !== address &&
|
group?.sender !== address &&
|
||||||
!mutedGroups.includes(group.groupId) &&
|
!mutedGroups.includes(group.groupId)
|
||||||
!isUpdateMsg(group?.data)
|
|
||||||
);
|
);
|
||||||
const dataWithUpdates = groups.filter(
|
const dataWithUpdates = groups.filter(
|
||||||
(group) => group?.sender !== address && !mutedGroups.includes(group.groupId)
|
(group) => group?.sender !== address && !mutedGroups.includes(group.groupId)
|
||||||
@ -716,8 +715,7 @@ const handleNotification = async (groups) => {
|
|||||||
Date.now() - lastGroupNotification >= 120000
|
Date.now() - lastGroupNotification >= 120000
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
!newestLatestTimestamp?.data ||
|
!newestLatestTimestamp?.data
|
||||||
!isExtMsg(newestLatestTimestamp?.data)
|
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import { throttle } from 'lodash'
|
|||||||
|
|
||||||
const uid = new ShortUniqueId({ length: 5 });
|
const uid = new ShortUniqueId({ length: 5 });
|
||||||
|
|
||||||
export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance, getTimestampEnterChatParent, hideView}) => {
|
export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance, getTimestampEnterChatParent, hideView, isPrivate}) => {
|
||||||
const [messages, setMessages] = useState([])
|
const [messages, setMessages] = useState([])
|
||||||
const [chatReferences, setChatReferences] = useState({})
|
const [chatReferences, setChatReferences] = useState({})
|
||||||
const [isSending, setIsSending] = useState(false)
|
const [isSending, setIsSending] = useState(false)
|
||||||
@ -223,7 +223,7 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
setChatReferences((prev) => {
|
setChatReferences((prev) => {
|
||||||
const organizedChatReferences = { ...prev };
|
const organizedChatReferences = { ...prev };
|
||||||
combineUIAndExtensionMsgs
|
combineUIAndExtensionMsgs
|
||||||
.filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit"))
|
.filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
|
||||||
.forEach((item) => {
|
.forEach((item) => {
|
||||||
try {
|
try {
|
||||||
if(item.decryptedData?.type === "edit"){
|
if(item.decryptedData?.type === "edit"){
|
||||||
@ -231,11 +231,16 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
...(organizedChatReferences[item.chatReference] || {}),
|
...(organizedChatReferences[item.chatReference] || {}),
|
||||||
edit: item.decryptedData,
|
edit: item.decryptedData,
|
||||||
};
|
};
|
||||||
|
} else if(item?.type === "edit"){
|
||||||
|
organizedChatReferences[item.chatReference] = {
|
||||||
|
...(organizedChatReferences[item.chatReference] || {}),
|
||||||
|
edit: item,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
const content = item.decryptedData?.content;
|
const content = item?.content || item.decryptedData?.content;
|
||||||
const sender = item.sender;
|
const sender = item.sender;
|
||||||
const newTimestamp = item.timestamp;
|
const newTimestamp = item.timestamp;
|
||||||
const contentState = item.decryptedData?.contentState;
|
const contentState = item?.contentState || item.decryptedData?.contentState;
|
||||||
|
|
||||||
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
||||||
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
||||||
@ -306,7 +311,7 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
const organizedChatReferences = { ...prev };
|
const organizedChatReferences = { ...prev };
|
||||||
|
|
||||||
combineUIAndExtensionMsgs
|
combineUIAndExtensionMsgs
|
||||||
.filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit"))
|
.filter((rawItem) => rawItem && rawItem.chatReference && (rawItem.decryptedData?.type === "reaction" || rawItem.decryptedData?.type === "edit" || rawItem?.type === "edit" || rawItem?.type === "reaction"))
|
||||||
.forEach((item) => {
|
.forEach((item) => {
|
||||||
try {
|
try {
|
||||||
if(item.decryptedData?.type === "edit"){
|
if(item.decryptedData?.type === "edit"){
|
||||||
@ -314,11 +319,16 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
...(organizedChatReferences[item.chatReference] || {}),
|
...(organizedChatReferences[item.chatReference] || {}),
|
||||||
edit: item.decryptedData,
|
edit: item.decryptedData,
|
||||||
};
|
};
|
||||||
|
} else if(item?.type === "edit"){
|
||||||
|
organizedChatReferences[item.chatReference] = {
|
||||||
|
...(organizedChatReferences[item.chatReference] || {}),
|
||||||
|
edit: item,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
const content = item.decryptedData?.content;
|
const content = item?.content || item.decryptedData?.content;
|
||||||
const sender = item.sender;
|
const sender = item.sender;
|
||||||
const newTimestamp = item.timestamp;
|
const newTimestamp = item.timestamp;
|
||||||
const contentState = item.decryptedData?.contentState;
|
const contentState = item?.contentState || item.decryptedData?.contentState;
|
||||||
|
|
||||||
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
if (!content || typeof content !== "string" || !sender || typeof sender !== "string" || !newTimestamp) {
|
||||||
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
console.warn("Invalid content, sender, or timestamp in reaction data", item);
|
||||||
@ -453,10 +463,11 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
initWebsocketMessageGroup()
|
initWebsocketMessageGroup()
|
||||||
}
|
}
|
||||||
}, [triedToFetchSecretKey, secretKey])
|
}, [triedToFetchSecretKey, secretKey, isPrivate])
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
if(!secretKey || hasInitializedWebsocket.current) return
|
if(isPrivate === null) return
|
||||||
|
if(isPrivate === false || !secretKey || hasInitializedWebsocket.current) return
|
||||||
forceCloseWebSocket()
|
forceCloseWebSocket()
|
||||||
setMessages([])
|
setMessages([])
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
@ -466,7 +477,7 @@ const [messageSize, setMessageSize] = useState(0)
|
|||||||
}, 6000);
|
}, 6000);
|
||||||
initWebsocketMessageGroup()
|
initWebsocketMessageGroup()
|
||||||
hasInitializedWebsocket.current = true
|
hasInitializedWebsocket.current = true
|
||||||
}, [secretKey])
|
}, [secretKey, isPrivate])
|
||||||
|
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
@ -551,6 +562,7 @@ const clearEditorContent = () => {
|
|||||||
|
|
||||||
const sendMessage = async ()=> {
|
const sendMessage = async ()=> {
|
||||||
try {
|
try {
|
||||||
|
if(isPrivate === null) throw new Error('Unable to determine if group is private')
|
||||||
if(isSending) return
|
if(isSending) return
|
||||||
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
|
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
|
||||||
pauseAllQueues()
|
pauseAllQueues()
|
||||||
@ -558,8 +570,10 @@ const clearEditorContent = () => {
|
|||||||
const htmlContent = editorRef.current.getHTML();
|
const htmlContent = editorRef.current.getHTML();
|
||||||
|
|
||||||
if(!htmlContent?.trim() || htmlContent?.trim() === '<p></p>') return
|
if(!htmlContent?.trim() || htmlContent?.trim() === '<p></p>') return
|
||||||
|
|
||||||
|
|
||||||
setIsSending(true)
|
setIsSending(true)
|
||||||
const message = htmlContent
|
const message = isPrivate === false ? editorRef.current.getJSON() : htmlContent
|
||||||
const secretKeyObject = await getSecretKey(false, true)
|
const secretKeyObject = await getSecretKey(false, true)
|
||||||
|
|
||||||
let repliedTo = replyMessage?.signature
|
let repliedTo = replyMessage?.signature
|
||||||
@ -569,19 +583,24 @@ const clearEditorContent = () => {
|
|||||||
}
|
}
|
||||||
let chatReference = onEditMessage?.signature
|
let chatReference = onEditMessage?.signature
|
||||||
|
|
||||||
|
const publicData = isPrivate ? {} : {
|
||||||
|
isEdited : chatReference ? true : false,
|
||||||
|
}
|
||||||
const otherData = {
|
const otherData = {
|
||||||
repliedTo,
|
repliedTo,
|
||||||
...(onEditMessage?.decryptedData || {}),
|
...(onEditMessage?.decryptedData || {}),
|
||||||
type: chatReference ? 'edit' : '',
|
type: chatReference ? 'edit' : '',
|
||||||
specialId: uid.rnd(),
|
specialId: uid.rnd(),
|
||||||
|
...publicData
|
||||||
}
|
}
|
||||||
const objectMessage = {
|
const objectMessage = {
|
||||||
...(otherData || {}),
|
...(otherData || {}),
|
||||||
message
|
[isPrivate ? 'message' : 'messageText']: message,
|
||||||
|
version: 3
|
||||||
}
|
}
|
||||||
const message64: any = await objectToBase64(objectMessage)
|
const message64: any = await objectToBase64(objectMessage)
|
||||||
|
|
||||||
const encryptSingle = await encryptChatMessage(message64, secretKeyObject)
|
const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject)
|
||||||
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
|
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
|
||||||
|
|
||||||
const sendMessageFunc = async () => {
|
const sendMessageFunc = async () => {
|
||||||
@ -591,7 +610,7 @@ const clearEditorContent = () => {
|
|||||||
// Add the function to the queue
|
// Add the function to the queue
|
||||||
const messageObj = {
|
const messageObj = {
|
||||||
message: {
|
message: {
|
||||||
text: message,
|
text: htmlContent,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
senderName: myName,
|
senderName: myName,
|
||||||
sender: myAddress,
|
sender: myAddress,
|
||||||
@ -668,7 +687,7 @@ const clearEditorContent = () => {
|
|||||||
const onEdit = useCallback((message)=> {
|
const onEdit = useCallback((message)=> {
|
||||||
setOnEditMessage(message)
|
setOnEditMessage(message)
|
||||||
setReplyMessage(null)
|
setReplyMessage(null)
|
||||||
editorRef.current.chain().focus().setContent(message?.text).run();
|
editorRef.current.chain().focus().setContent(message?.messageText || message?.text).run();
|
||||||
|
|
||||||
}, [])
|
}, [])
|
||||||
const handleReaction = useCallback(async (reaction, chatMessage, reactionState = true)=> {
|
const handleReaction = useCallback(async (reaction, chatMessage, reactionState = true)=> {
|
||||||
@ -696,7 +715,7 @@ const clearEditorContent = () => {
|
|||||||
}
|
}
|
||||||
const message64: any = await objectToBase64(objectMessage)
|
const message64: any = await objectToBase64(objectMessage)
|
||||||
const reactiontypeNumber = RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS
|
const reactiontypeNumber = RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS
|
||||||
const encryptSingle = await encryptChatMessage(message64, secretKeyObject, reactiontypeNumber)
|
const encryptSingle = isPrivate === false ? JSON.stringify(objectMessage) : await encryptChatMessage(message64, secretKeyObject, reactiontypeNumber)
|
||||||
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
|
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
|
||||||
|
|
||||||
const sendMessageFunc = async () => {
|
const sendMessageFunc = async () => {
|
||||||
@ -752,9 +771,9 @@ const clearEditorContent = () => {
|
|||||||
left: hide && '-100000px',
|
left: hide && '-100000px',
|
||||||
}}>
|
}}>
|
||||||
|
|
||||||
<ChatList hasSecretKey={!!secretKey} openQManager={openQManager} enableMentions onReply={onReply} onEdit={onEdit} chatId={selectedGroup} initialMessages={messages} myAddress={myAddress} tempMessages={tempMessages} handleReaction={handleReaction} chatReferences={chatReferences} tempChatReferences={tempChatReferences} members={members} myName={myName} selectedGroup={selectedGroup} />
|
<ChatList isPrivate={isPrivate} hasSecretKey={!!secretKey} openQManager={openQManager} enableMentions onReply={onReply} onEdit={onEdit} chatId={selectedGroup} initialMessages={messages} myAddress={myAddress} tempMessages={tempMessages} handleReaction={handleReaction} chatReferences={chatReferences} tempChatReferences={tempChatReferences} members={members} myName={myName} selectedGroup={selectedGroup} />
|
||||||
|
|
||||||
{!!secretKey && (
|
{(!!secretKey || isPrivate === false) && (
|
||||||
<div style={{
|
<div style={{
|
||||||
// position: 'fixed',
|
// position: 'fixed',
|
||||||
// bottom: '0px',
|
// bottom: '0px',
|
||||||
|
@ -28,13 +28,13 @@ export const ChatList = ({
|
|||||||
selectedGroup,
|
selectedGroup,
|
||||||
enableMentions,
|
enableMentions,
|
||||||
openQManager,
|
openQManager,
|
||||||
hasSecretKey
|
hasSecretKey,
|
||||||
|
isPrivate
|
||||||
}) => {
|
}) => {
|
||||||
const parentRef = useRef();
|
const parentRef = useRef();
|
||||||
const [messages, setMessages] = useState(initialMessages);
|
const [messages, setMessages] = useState(initialMessages);
|
||||||
const [showScrollButton, setShowScrollButton] = useState(false);
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
||||||
const [showScrollDownButton, setShowScrollDownButton] = useState(false);
|
const [showScrollDownButton, setShowScrollDownButton] = useState(false);
|
||||||
|
|
||||||
const hasLoadedInitialRef = useRef(false);
|
const hasLoadedInitialRef = useRef(false);
|
||||||
const scrollingIntervalRef = useRef(null);
|
const scrollingIntervalRef = useRef(null);
|
||||||
const lastSeenUnreadMessageTimestamp = useRef(null);
|
const lastSeenUnreadMessageTimestamp = useRef(null);
|
||||||
@ -272,7 +272,10 @@ export const ChatList = ({
|
|||||||
message.text = chatReferences[message.signature]?.edit?.message;
|
message.text = chatReferences[message.signature]?.edit?.message;
|
||||||
message.isEdit = true
|
message.isEdit = true
|
||||||
}
|
}
|
||||||
|
if (chatReferences[message.signature]?.edit?.messageText && message?.messageText) {
|
||||||
|
message.messageText = chatReferences[message.signature]?.edit?.messageText;
|
||||||
|
message.isEdit = true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +318,6 @@ export const ChatList = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-index={virtualRow.index} //needed for dynamic row height measurement
|
data-index={virtualRow.index} //needed for dynamic row height measurement
|
||||||
@ -357,6 +359,7 @@ export const ChatList = ({
|
|||||||
handleReaction={handleReaction}
|
handleReaction={handleReaction}
|
||||||
reactions={reactions}
|
reactions={reactions}
|
||||||
isUpdating={isUpdating}
|
isUpdating={isUpdating}
|
||||||
|
isPrivate={isPrivate}
|
||||||
/>
|
/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
@ -408,7 +411,7 @@ export const ChatList = ({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{enableMentions && hasSecretKey && (
|
{enableMentions && (hasSecretKey || isPrivate === false) && (
|
||||||
<ChatOptions
|
<ChatOptions
|
||||||
openQManager={openQManager}
|
openQManager={openQManager}
|
||||||
messages={messages}
|
messages={messages}
|
||||||
@ -416,6 +419,7 @@ export const ChatList = ({
|
|||||||
members={members}
|
members={members}
|
||||||
myName={myName}
|
myName={myName}
|
||||||
selectedGroup={selectedGroup}
|
selectedGroup={selectedGroup}
|
||||||
|
isPrivate={isPrivate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -13,6 +13,10 @@ import { Spacer } from "../../common/Spacer";
|
|||||||
import AlternateEmailIcon from "@mui/icons-material/AlternateEmail";
|
import AlternateEmailIcon from "@mui/icons-material/AlternateEmail";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
import InsertLinkIcon from '@mui/icons-material/InsertLink';
|
import InsertLinkIcon from '@mui/icons-material/InsertLink';
|
||||||
|
import Highlight from "@tiptap/extension-highlight";
|
||||||
|
import Mention from "@tiptap/extension-mention";
|
||||||
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
|
import Underline from "@tiptap/extension-underline";
|
||||||
import {
|
import {
|
||||||
AppsSearchContainer,
|
AppsSearchContainer,
|
||||||
AppsSearchLeft,
|
AppsSearchLeft,
|
||||||
@ -32,6 +36,8 @@ import { useVirtualizer } from "@tanstack/react-virtual";
|
|||||||
import { formatTimestamp } from "../../utils/time";
|
import { formatTimestamp } from "../../utils/time";
|
||||||
import { ContextMenuMentions } from "../ContextMenuMentions";
|
import { ContextMenuMentions } from "../ContextMenuMentions";
|
||||||
import { convert } from 'html-to-text';
|
import { convert } from 'html-to-text';
|
||||||
|
import { generateHTML } from "@tiptap/react";
|
||||||
|
import ErrorBoundary from "../../common/ErrorBoundary";
|
||||||
|
|
||||||
const extractTextFromHTML = (htmlString = '') => {
|
const extractTextFromHTML = (htmlString = '') => {
|
||||||
return convert(htmlString, {
|
return convert(htmlString, {
|
||||||
@ -43,7 +49,7 @@ const cache = new CellMeasurerCache({
|
|||||||
defaultHeight: 50,
|
defaultHeight: 50,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGroup, openQManager }) => {
|
export const ChatOptions = ({ messages : untransformedMessages, goToMessage, members, myName, selectedGroup, openQManager, isPrivate }) => {
|
||||||
const [mode, setMode] = useState("default");
|
const [mode, setMode] = useState("default");
|
||||||
const [searchValue, setSearchValue] = useState("");
|
const [searchValue, setSearchValue] = useState("");
|
||||||
const [selectedMember, setSelectedMember] = useState(0);
|
const [selectedMember, setSelectedMember] = useState(0);
|
||||||
@ -52,7 +58,27 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
const parentRefMentions = useRef();
|
const parentRefMentions = useRef();
|
||||||
const [lastMentionTimestamp, setLastMentionTimestamp] = useState(null)
|
const [lastMentionTimestamp, setLastMentionTimestamp] = useState(null)
|
||||||
const [debouncedValue, setDebouncedValue] = useState(""); // Debounced value
|
const [debouncedValue, setDebouncedValue] = useState(""); // Debounced value
|
||||||
|
const messages = useMemo(()=> {
|
||||||
|
return untransformedMessages?.map((item)=> {
|
||||||
|
if(item?.messageText){
|
||||||
|
let transformedMessage = item?.messageText
|
||||||
|
try {
|
||||||
|
transformedMessage = generateHTML(item?.messageText, [
|
||||||
|
StarterKit,
|
||||||
|
Underline,
|
||||||
|
Highlight,
|
||||||
|
Mention
|
||||||
|
])
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
messageText: transformedMessage
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// error
|
||||||
|
}
|
||||||
|
} else return item
|
||||||
|
})
|
||||||
|
}, [untransformedMessages])
|
||||||
const getTimestampMention = async () => {
|
const getTimestampMention = async () => {
|
||||||
try {
|
try {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
@ -124,7 +150,7 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
.filter(
|
.filter(
|
||||||
(message) =>
|
(message) =>
|
||||||
message?.senderName === selectedMember &&
|
message?.senderName === selectedMember &&
|
||||||
extractTextFromHTML(message?.decryptedData?.message)?.includes(
|
extractTextFromHTML(isPrivate ? message?.messageText : message?.decryptedData?.message)?.includes(
|
||||||
debouncedValue.toLowerCase()
|
debouncedValue.toLowerCase()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -132,20 +158,27 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
}
|
}
|
||||||
return messages
|
return messages
|
||||||
.filter((message) =>
|
.filter((message) =>
|
||||||
extractTextFromHTML(message?.decryptedData?.message)?.includes(debouncedValue.toLowerCase())
|
extractTextFromHTML(isPrivate === false ? message?.messageText : message?.decryptedData?.message)?.includes(debouncedValue.toLowerCase())
|
||||||
)
|
)
|
||||||
?.sort((a, b) => b?.timestamp - a?.timestamp);
|
?.sort((a, b) => b?.timestamp - a?.timestamp);
|
||||||
}, [debouncedValue, messages, selectedMember]);
|
}, [debouncedValue, messages, selectedMember, isPrivate]);
|
||||||
|
|
||||||
const mentionList = useMemo(() => {
|
const mentionList = useMemo(() => {
|
||||||
if(!messages || messages.length === 0 || !myName) return []
|
if(!messages || messages.length === 0 || !myName) return []
|
||||||
|
if(isPrivate === false){
|
||||||
|
return messages
|
||||||
|
.filter((message) =>
|
||||||
|
extractTextFromHTML(message?.messageText)?.includes(`@${myName}`)
|
||||||
|
)
|
||||||
|
?.sort((a, b) => b?.timestamp - a?.timestamp);
|
||||||
|
|
||||||
|
}
|
||||||
return messages
|
return messages
|
||||||
.filter((message) =>
|
.filter((message) =>
|
||||||
extractTextFromHTML(message?.decryptedData?.message)?.includes(`@${myName}`)
|
extractTextFromHTML(message?.decryptedData?.message)?.includes(`@${myName}`)
|
||||||
)
|
)
|
||||||
?.sort((a, b) => b?.timestamp - a?.timestamp);
|
?.sort((a, b) => b?.timestamp - a?.timestamp);
|
||||||
}, [messages, myName]);
|
}, [messages, myName, isPrivate]);
|
||||||
|
|
||||||
const rowVirtualizer = useVirtualizer({
|
const rowVirtualizer = useVirtualizer({
|
||||||
count: searchedList.length,
|
count: searchedList.length,
|
||||||
@ -291,7 +324,8 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
gap: "5px",
|
gap: "5px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<ShowMessage messages={messages} goToMessage={goToMessage} message={message} />
|
||||||
|
{/* <Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
@ -363,7 +397,7 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -544,6 +578,7 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
const index = virtualRow.index;
|
const index = virtualRow.index;
|
||||||
let message = searchedList[index];
|
let message = searchedList[index];
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-index={virtualRow.index} //needed for dynamic row height measurement
|
data-index={virtualRow.index} //needed for dynamic row height measurement
|
||||||
ref={rowVirtualizer.measureElement} //measure dynamic row height
|
ref={rowVirtualizer.measureElement} //measure dynamic row height
|
||||||
@ -562,80 +597,17 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
gap: "5px",
|
gap: "5px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<ErrorBoundary
|
||||||
sx={{
|
fallback={
|
||||||
display: "flex",
|
<Typography>
|
||||||
flexDirection: "column",
|
Error loading content: Invalid Data
|
||||||
width: "100%",
|
</Typography>
|
||||||
padding: "0px 20px",
|
}
|
||||||
}}
|
>
|
||||||
>
|
<ShowMessage message={message} goToMessage={goToMessage} messages={messages} />
|
||||||
<Box
|
</ErrorBoundary>
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "15px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
sx={{
|
|
||||||
backgroundColor: "#27282c",
|
|
||||||
color: "white",
|
|
||||||
height: "25px",
|
|
||||||
width: "25px",
|
|
||||||
}}
|
|
||||||
alt={message?.senderName}
|
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
|
||||||
message?.senderName
|
|
||||||
}/qortal_avatar?async=true`}
|
|
||||||
>
|
|
||||||
{message?.senderName?.charAt(0)}
|
|
||||||
</Avatar>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontWight: 600,
|
|
||||||
fontFamily: "Inter",
|
|
||||||
color: "cadetBlue",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{message?.senderName}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Spacer height="5px" />
|
|
||||||
<Typography sx={{
|
|
||||||
fontSize: '12px'
|
|
||||||
}}>{formatTimestamp(message.timestamp)}</Typography>
|
|
||||||
<Box
|
|
||||||
style={{
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
const findMsgIndex = messages.findIndex(
|
|
||||||
(item) =>
|
|
||||||
item?.signature === message?.signature
|
|
||||||
);
|
|
||||||
if (findMsgIndex !== -1) {
|
|
||||||
goToMessage(findMsgIndex);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MessageDisplay
|
|
||||||
htmlContent={
|
|
||||||
message?.decryptedData?.message || "<p></p>"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@ -705,3 +677,91 @@ export const ChatOptions = ({ messages, goToMessage, members, myName, selectedGr
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const ShowMessage = ({message, goToMessage, messages})=> {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
padding: "0px 20px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#27282c",
|
||||||
|
color: "white",
|
||||||
|
height: "25px",
|
||||||
|
width: "25px",
|
||||||
|
}}
|
||||||
|
alt={message?.senderName}
|
||||||
|
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||||
|
message?.senderName
|
||||||
|
}/qortal_avatar?async=true`}
|
||||||
|
>
|
||||||
|
{message?.senderName?.charAt(0)}
|
||||||
|
</Avatar>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWight: 600,
|
||||||
|
fontFamily: "Inter",
|
||||||
|
color: "cadetBlue",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{message?.senderName}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Spacer height="5px" />
|
||||||
|
<Typography sx={{
|
||||||
|
fontSize: '12px'
|
||||||
|
}}>{formatTimestamp(message.timestamp)}</Typography>
|
||||||
|
<Box
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
const findMsgIndex = messages.findIndex(
|
||||||
|
(item) =>
|
||||||
|
item?.signature === message?.signature
|
||||||
|
);
|
||||||
|
if (findMsgIndex !== -1) {
|
||||||
|
goToMessage(findMsgIndex);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{message?.messageText && (
|
||||||
|
<MessageDisplay
|
||||||
|
htmlContent={message?.messageText}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{message?.decryptedData?.message && (
|
||||||
|
<MessageDisplay
|
||||||
|
htmlContent={
|
||||||
|
message?.decryptedData?.message || "<p></p>"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
@ -106,7 +106,7 @@ export const MessageDisplay = ({ htmlContent, isReply }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const embedLink = htmlContent.match(/qortal:\/\/use-embed\/[^\s<>]+/);
|
const embedLink = htmlContent?.match(/qortal:\/\/use-embed\/[^\s<>]+/);
|
||||||
|
|
||||||
let embedData = null;
|
let embedData = null;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import { getBaseApi } from "../../background";
|
|||||||
import { getBaseApiReact } from "../../App";
|
import { getBaseApiReact } from "../../App";
|
||||||
import { generateHTML } from "@tiptap/react";
|
import { generateHTML } from "@tiptap/react";
|
||||||
import Highlight from "@tiptap/extension-highlight";
|
import Highlight from "@tiptap/extension-highlight";
|
||||||
|
import Mention from "@tiptap/extension-mention";
|
||||||
import StarterKit from "@tiptap/starter-kit";
|
import StarterKit from "@tiptap/starter-kit";
|
||||||
import Underline from "@tiptap/extension-underline";
|
import Underline from "@tiptap/extension-underline";
|
||||||
import { executeEvent } from "../../utils/events";
|
import { executeEvent } from "../../utils/events";
|
||||||
@ -33,13 +34,15 @@ export const MessageItem = ({
|
|||||||
reactions,
|
reactions,
|
||||||
isUpdating,
|
isUpdating,
|
||||||
lastSignature,
|
lastSignature,
|
||||||
onEdit
|
onEdit,
|
||||||
|
isPrivate
|
||||||
}) => {
|
}) => {
|
||||||
const { ref, inView } = useInView({
|
const { ref, inView } = useInView({
|
||||||
threshold: 0.7, // Fully visible
|
threshold: 0.7, // Fully visible
|
||||||
triggerOnce: false, // Only trigger once when it becomes visible
|
triggerOnce: false, // Only trigger once when it becomes visible
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const [anchorEl, setAnchorEl] = useState(null);
|
const [anchorEl, setAnchorEl] = useState(null);
|
||||||
const [selectedReaction, setSelectedReaction] = useState(null);
|
const [selectedReaction, setSelectedReaction] = useState(null);
|
||||||
|
|
||||||
@ -136,7 +139,7 @@ export const MessageItem = ({
|
|||||||
gap: '10px',
|
gap: '10px',
|
||||||
alignItems: 'center'
|
alignItems: 'center'
|
||||||
}}>
|
}}>
|
||||||
{message?.sender === myAddress && !message?.isNotEncrypted && (
|
{message?.sender === myAddress && (!message?.isNotEncrypted || isPrivate === false) && (
|
||||||
<ButtonBase
|
<ButtonBase
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onEdit(message);
|
onEdit(message);
|
||||||
@ -205,6 +208,7 @@ export const MessageItem = ({
|
|||||||
StarterKit,
|
StarterKit,
|
||||||
Underline,
|
Underline,
|
||||||
Highlight,
|
Highlight,
|
||||||
|
Mention
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -223,6 +227,7 @@ export const MessageItem = ({
|
|||||||
StarterKit,
|
StarterKit,
|
||||||
Underline,
|
Underline,
|
||||||
Highlight,
|
Highlight,
|
||||||
|
Mention
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -341,7 +346,7 @@ export const MessageItem = ({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '15px'
|
gap: '15px'
|
||||||
}}>
|
}}>
|
||||||
{message?.isNotEncrypted && (
|
{message?.isNotEncrypted && isPrivate && (
|
||||||
<KeyOffIcon sx={{
|
<KeyOffIcon sx={{
|
||||||
color: 'white',
|
color: 'white',
|
||||||
marginLeft: '10px'
|
marginLeft: '10px'
|
||||||
@ -456,6 +461,7 @@ export const ReplyPreview = ({message, isEdit})=> {
|
|||||||
StarterKit,
|
StarterKit,
|
||||||
Underline,
|
Underline,
|
||||||
Highlight,
|
Highlight,
|
||||||
|
Mention
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tiptap .mention {
|
.tiptap [data-type="mention"] {
|
||||||
box-decoration-break: clone;
|
box-decoration-break: clone;
|
||||||
color: lightblue;
|
color: lightblue;
|
||||||
padding: 0.1rem 0.3rem;
|
padding: 0.1rem 0.3rem;
|
||||||
|
@ -19,6 +19,8 @@ import { ChatIcon } from "../../assets/Icons/ChatIcon";
|
|||||||
import { ThreadsIcon } from "../../assets/Icons/ThreadsIcon";
|
import { ThreadsIcon } from "../../assets/Icons/ThreadsIcon";
|
||||||
import { MembersIcon } from "../../assets/Icons/MembersIcon";
|
import { MembersIcon } from "../../assets/Icons/MembersIcon";
|
||||||
import { AdminsIcon } from "../../assets/Icons/AdminsIcon";
|
import { AdminsIcon } from "../../assets/Icons/AdminsIcon";
|
||||||
|
import LockIcon from '@mui/icons-material/Lock';
|
||||||
|
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||||
|
|
||||||
const IconWrapper = ({ children, label, color, selected, selectColor, customHeight }) => {
|
const IconWrapper = ({ children, label, color, selected, selectColor, customHeight }) => {
|
||||||
return (
|
return (
|
||||||
@ -80,7 +82,8 @@ export const DesktopHeader = ({
|
|||||||
hasUnreadChat,
|
hasUnreadChat,
|
||||||
isChat,
|
isChat,
|
||||||
isForum,
|
isForum,
|
||||||
setGroupSection
|
setGroupSection,
|
||||||
|
isPrivate
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = React.useState(0);
|
const [value, setValue] = React.useState(0);
|
||||||
return (
|
return (
|
||||||
@ -95,7 +98,20 @@ export const DesktopHeader = ({
|
|||||||
padding: "10px",
|
padding: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box>
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
gap: '10px'
|
||||||
|
}}>
|
||||||
|
{isPrivate && (
|
||||||
|
<LockIcon sx={{
|
||||||
|
color: 'var(--green)'
|
||||||
|
}} />
|
||||||
|
)}
|
||||||
|
{isPrivate === false && (
|
||||||
|
<NoEncryptionGmailerrorredIcon sx={{
|
||||||
|
color: 'var(--unread)'
|
||||||
|
}} />
|
||||||
|
)}
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import React, {
|
import React, {
|
||||||
|
useCallback,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
@ -77,8 +78,8 @@ import { useSetRecoilState } from "recoil";
|
|||||||
import { selectedGroupIdAtom } from "../../atoms/global";
|
import { selectedGroupIdAtom } from "../../atoms/global";
|
||||||
import { sortArrayByTimestampAndGroupName } from "../../utils/time";
|
import { sortArrayByTimestampAndGroupName } from "../../utils/time";
|
||||||
|
|
||||||
|
import LockIcon from '@mui/icons-material/Lock';
|
||||||
|
import NoEncryptionGmailerrorredIcon from '@mui/icons-material/NoEncryptionGmailerrorred';
|
||||||
|
|
||||||
|
|
||||||
export const getPublishesFromAdmins = async (admins: string[], groupId) => {
|
export const getPublishesFromAdmins = async (admins: string[], groupId) => {
|
||||||
@ -347,6 +348,19 @@ export const getNamesForAdmins = async (admins) => {
|
|||||||
return members;
|
return members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function areKeysEqual(array1, array2) {
|
||||||
|
// If lengths differ, the arrays cannot be equal
|
||||||
|
if (array1?.length !== array2?.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort both arrays and compare their elements
|
||||||
|
const sortedArray1 = [...array1].sort();
|
||||||
|
const sortedArray2 = [...array2].sort();
|
||||||
|
|
||||||
|
return sortedArray1.every((key, index) => key === sortedArray2[index]);
|
||||||
|
}
|
||||||
|
|
||||||
export const Group = ({
|
export const Group = ({
|
||||||
myAddress,
|
myAddress,
|
||||||
isFocused,
|
isFocused,
|
||||||
@ -418,6 +432,17 @@ export const Group = ({
|
|||||||
const [appsModeDev, setAppsModeDev] = useState('home')
|
const [appsModeDev, setAppsModeDev] = useState('home')
|
||||||
const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
|
const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
|
||||||
const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
|
const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
|
||||||
|
|
||||||
|
|
||||||
|
const [groupsProperties, setGroupsProperties] = useState({})
|
||||||
|
|
||||||
|
const isPrivate = useMemo(()=> {
|
||||||
|
if(!selectedGroup?.groupId || !groupsProperties[selectedGroup?.groupId]) return null
|
||||||
|
if(groupsProperties[selectedGroup?.groupId]?.isOpen === true) return false
|
||||||
|
if(groupsProperties[selectedGroup?.groupId]?.isOpen === false) return true
|
||||||
|
return null
|
||||||
|
}, [selectedGroup])
|
||||||
|
|
||||||
const setSelectedGroupId = useSetRecoilState(selectedGroupIdAtom)
|
const setSelectedGroupId = useSetRecoilState(selectedGroupIdAtom)
|
||||||
const toggleSideViewDirects = ()=> {
|
const toggleSideViewDirects = ()=> {
|
||||||
if(isOpenSideViewGroups){
|
if(isOpenSideViewGroups){
|
||||||
@ -569,9 +594,8 @@ export const Group = ({
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
group?.data &&
|
group?.data &&
|
||||||
isExtMsg(group?.data) &&
|
|
||||||
group?.sender !== myAddress &&
|
group?.sender !== myAddress &&
|
||||||
group?.timestamp && (!isUpdateMsg(group?.data) || groupChatTimestamps[group?.groupId]) &&
|
group?.timestamp && groupChatTimestamps[group?.groupId] &&
|
||||||
((!timestampEnterData[group?.groupId] &&
|
((!timestampEnterData[group?.groupId] &&
|
||||||
Date.now() - group?.timestamp < timeDifferenceForNotificationChats) ||
|
Date.now() - group?.timestamp < timeDifferenceForNotificationChats) ||
|
||||||
timestampEnterData[group?.groupId] < group?.timestamp)
|
timestampEnterData[group?.groupId] < group?.timestamp)
|
||||||
@ -706,12 +730,19 @@ export const Group = ({
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedGroup) {
|
if (selectedGroup && isPrivate !== null) {
|
||||||
setTriedToFetchSecretKey(false);
|
if(isPrivate){
|
||||||
getSecretKey(true);
|
setTriedToFetchSecretKey(false);
|
||||||
|
getSecretKey(true);
|
||||||
|
}
|
||||||
|
|
||||||
getGroupOwner(selectedGroup?.groupId);
|
getGroupOwner(selectedGroup?.groupId);
|
||||||
}
|
}
|
||||||
}, [selectedGroup]);
|
if(isPrivate === false){
|
||||||
|
setTriedToFetchSecretKey(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [selectedGroup, isPrivate]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -735,9 +766,8 @@ export const Group = ({
|
|||||||
const groupData = {}
|
const groupData = {}
|
||||||
|
|
||||||
const getGroupData = groups.map(async(group)=> {
|
const getGroupData = groups.map(async(group)=> {
|
||||||
const isUpdate = isUpdateMsg(group?.data)
|
|
||||||
if(!group.groupId || !group?.timestamp) return null
|
if(!group.groupId || !group?.timestamp) return null
|
||||||
if(isUpdate && (!groupData[group.groupId] || groupData[group.groupId] < group.timestamp)){
|
if((!groupData[group.groupId] || groupData[group.groupId] < group.timestamp)){
|
||||||
const hasMoreRecentMsg = await getCountNewMesg(group.groupId, timestampEnterDataRef.current[group?.groupId] || Date.now() - 24 * 60 * 60 * 1000)
|
const hasMoreRecentMsg = await getCountNewMesg(group.groupId, timestampEnterDataRef.current[group?.groupId] || Date.now() - 24 * 60 * 60 * 1000)
|
||||||
if(hasMoreRecentMsg){
|
if(hasMoreRecentMsg){
|
||||||
groupData[group.groupId] = hasMoreRecentMsg
|
groupData[group.groupId] = hasMoreRecentMsg
|
||||||
@ -754,6 +784,32 @@ export const Group = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getGroupsProperties = useCallback(async(address)=> {
|
||||||
|
try {
|
||||||
|
const url = `${getBaseApiReact()}/groups/member/${address}`;
|
||||||
|
const response = await fetch(url);
|
||||||
|
if(!response.ok) throw new Error('Cannot get group properties')
|
||||||
|
let data = await response.json();
|
||||||
|
const transformToObject = data.reduce((result, item) => {
|
||||||
|
|
||||||
|
result[item.groupId] = item
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
setGroupsProperties(transformToObject)
|
||||||
|
} catch (error) {
|
||||||
|
// error
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(()=> {
|
||||||
|
if(!myAddress) return
|
||||||
|
if(areKeysEqual(groups?.map((grp)=> grp?.groupId), Object.keys(groupsProperties))){
|
||||||
|
} else {
|
||||||
|
getGroupsProperties(myAddress)
|
||||||
|
}
|
||||||
|
}, [groups, myAddress])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -941,9 +997,9 @@ export const Group = ({
|
|||||||
.filter((group) => group?.sender !== myAddress)
|
.filter((group) => group?.sender !== myAddress)
|
||||||
.find((gr) => gr?.groupId === selectedGroup?.groupId);
|
.find((gr) => gr?.groupId === selectedGroup?.groupId);
|
||||||
if (!findGroup) return false;
|
if (!findGroup) return false;
|
||||||
if (!findGroup?.data || !isExtMsg(findGroup?.data)) return false;
|
if (!findGroup?.data) return false;
|
||||||
return (
|
return (
|
||||||
findGroup?.timestamp && (!isUpdateMsg(findGroup?.data) || groupChatTimestamps[findGroup?.groupId]) &&
|
findGroup?.timestamp && groupChatTimestamps[findGroup?.groupId] &&
|
||||||
((!timestampEnterData[selectedGroup?.groupId] &&
|
((!timestampEnterData[selectedGroup?.groupId] &&
|
||||||
Date.now() - findGroup?.timestamp <
|
Date.now() - findGroup?.timestamp <
|
||||||
timeDifferenceForNotificationChats) ||
|
timeDifferenceForNotificationChats) ||
|
||||||
@ -1657,6 +1713,7 @@ export const Group = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const renderGroups = () => {
|
const renderGroups = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -1805,15 +1862,45 @@ export const Group = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<Avatar
|
{groupsProperties[group?.groupId]?.isOpen === false ? (
|
||||||
sx={{
|
<Box sx={{
|
||||||
|
width: '40px',
|
||||||
|
height: '40px',
|
||||||
|
borderRadius: '50%',
|
||||||
background: "#232428",
|
background: "#232428",
|
||||||
color: "white",
|
display: 'flex',
|
||||||
}}
|
alignItems: 'center',
|
||||||
alt={group?.groupName}
|
justifyContent: 'center'
|
||||||
>
|
}}>
|
||||||
{group.groupName?.charAt(0)}
|
<LockIcon sx={{
|
||||||
</Avatar>
|
color: 'var(--green)'
|
||||||
|
}} />
|
||||||
|
</Box>
|
||||||
|
): (
|
||||||
|
<Box sx={{
|
||||||
|
width: '40px',
|
||||||
|
height: '40px',
|
||||||
|
borderRadius: '50%',
|
||||||
|
background: "#232428",
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
}}>
|
||||||
|
<NoEncryptionGmailerrorredIcon sx={{
|
||||||
|
color: 'var(--unread)'
|
||||||
|
}} />
|
||||||
|
</Box>
|
||||||
|
// <Avatar
|
||||||
|
// sx={{
|
||||||
|
// background: "#232428",
|
||||||
|
// color: "white",
|
||||||
|
// }}
|
||||||
|
// alt={group?.groupName}
|
||||||
|
// >
|
||||||
|
// {group.groupName?.charAt(0)}
|
||||||
|
// </Avatar>
|
||||||
|
)}
|
||||||
|
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={group.groupName}
|
primary={group.groupName}
|
||||||
@ -1849,7 +1936,7 @@ export const Group = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{group?.data &&
|
{group?.data &&
|
||||||
isExtMsg(group?.data) && (!isUpdateMsg(group?.data) || groupChatTimestamps[group?.groupId]) &&
|
groupChatTimestamps[group?.groupId] &&
|
||||||
group?.sender !== myAddress &&
|
group?.sender !== myAddress &&
|
||||||
group?.timestamp &&
|
group?.timestamp &&
|
||||||
((!timestampEnterData[group?.groupId] &&
|
((!timestampEnterData[group?.groupId] &&
|
||||||
@ -2085,6 +2172,7 @@ export const Group = ({
|
|||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
|
|
||||||
<DesktopHeader
|
<DesktopHeader
|
||||||
|
isPrivate={isPrivate}
|
||||||
selectedGroup={selectedGroup}
|
selectedGroup={selectedGroup}
|
||||||
groupSection={groupSection}
|
groupSection={groupSection}
|
||||||
isUnread={isUnread}
|
isUnread={isUnread}
|
||||||
@ -2138,6 +2226,7 @@ export const Group = ({
|
|||||||
selectedGroup={selectedGroup?.groupId}
|
selectedGroup={selectedGroup?.groupId}
|
||||||
getSecretKey={getSecretKey}
|
getSecretKey={getSecretKey}
|
||||||
secretKey={secretKey}
|
secretKey={secretKey}
|
||||||
|
isPrivate={isPrivate}
|
||||||
setSecretKey={setSecretKey}
|
setSecretKey={setSecretKey}
|
||||||
handleNewEncryptionNotification={
|
handleNewEncryptionNotification={
|
||||||
setNewEncryptionNotification
|
setNewEncryptionNotification
|
||||||
@ -2153,7 +2242,7 @@ export const Group = ({
|
|||||||
getTimestampEnterChatParent={getTimestampEnterChat}
|
getTimestampEnterChatParent={getTimestampEnterChat}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{firstSecretKeyInCreation &&
|
{isPrivate &&firstSecretKeyInCreation &&
|
||||||
triedToFetchSecretKey &&
|
triedToFetchSecretKey &&
|
||||||
!secretKeyPublishDate && (
|
!secretKeyPublishDate && (
|
||||||
<div
|
<div
|
||||||
@ -2174,7 +2263,7 @@ export const Group = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!admins.includes(myAddress) &&
|
{isPrivate && !admins.includes(myAddress) &&
|
||||||
!secretKey &&
|
!secretKey &&
|
||||||
triedToFetchSecretKey ? (
|
triedToFetchSecretKey ? (
|
||||||
<>
|
<>
|
||||||
@ -2231,7 +2320,7 @@ export const Group = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
) : admins.includes(myAddress) &&
|
) : admins.includes(myAddress) &&
|
||||||
!secretKey &&
|
(!secretKey && isPrivate) &&
|
||||||
triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : (
|
triedToFetchSecretKey ? null : !triedToFetchSecretKey ? null : (
|
||||||
<>
|
<>
|
||||||
<GroupAnnouncements
|
<GroupAnnouncements
|
||||||
@ -2273,7 +2362,7 @@ export const Group = ({
|
|||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{admins.includes(myAddress) &&
|
{isPrivate && admins.includes(myAddress) &&
|
||||||
shouldReEncrypt &&
|
shouldReEncrypt &&
|
||||||
triedToFetchSecretKey &&
|
triedToFetchSecretKey &&
|
||||||
!firstSecretKeyInCreation &&
|
!firstSecretKeyInCreation &&
|
||||||
|
@ -217,12 +217,12 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
|
|||||||
try {
|
try {
|
||||||
const decoded = atob(msg?.data);
|
const decoded = atob(msg?.data);
|
||||||
const parseDecoded =JSON.parse(decodeURIComponent(escape(decoded)))
|
const parseDecoded =JSON.parse(decodeURIComponent(escape(decoded)))
|
||||||
if(parseDecoded?.messageText){
|
|
||||||
msgs.push({
|
msgs.push({
|
||||||
...msg,
|
...msg,
|
||||||
...parseDecoded
|
...parseDecoded
|
||||||
})
|
})
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user