optimizations, see ui direct chat, fixes

This commit is contained in:
PhilReact 2024-09-12 22:23:47 +03:00
parent 5327c79543
commit eebcd8c36f
11 changed files with 262 additions and 99 deletions

26
package-lock.json generated
View File

@ -18,9 +18,11 @@
"@testing-library/jest-dom": "^6.4.6", "@testing-library/jest-dom": "^6.4.6",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@tiptap/extension-color": "^2.5.9", "@tiptap/extension-color": "^2.5.9",
"@tiptap/extension-highlight": "^2.6.6",
"@tiptap/extension-image": "^2.6.6", "@tiptap/extension-image": "^2.6.6",
"@tiptap/extension-placeholder": "^2.6.2", "@tiptap/extension-placeholder": "^2.6.2",
"@tiptap/extension-text-style": "^2.5.9", "@tiptap/extension-text-style": "^2.5.9",
"@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.5.9", "@tiptap/pm": "^2.5.9",
"@tiptap/react": "^2.5.9", "@tiptap/react": "^2.5.9",
"@tiptap/starter-kit": "^2.5.9", "@tiptap/starter-kit": "^2.5.9",
@ -2300,6 +2302,18 @@
"@tiptap/core": "^2.5.9" "@tiptap/core": "^2.5.9"
} }
}, },
"node_modules/@tiptap/extension-highlight": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-2.6.6.tgz",
"integrity": "sha512-Z02AYWm1AJAfhmfT4fGCI3YitijF4uNu+eiuq7OxhCiVf9IYaq8xlH2YMxa09QvMUo70ovklxk97+vQUUHeqfQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.6.6"
}
},
"node_modules/@tiptap/extension-history": { "node_modules/@tiptap/extension-history": {
"version": "2.5.9", "version": "2.5.9",
"resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.5.9.tgz", "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.5.9.tgz",
@ -2435,6 +2449,18 @@
"@tiptap/core": "^2.5.9" "@tiptap/core": "^2.5.9"
} }
}, },
"node_modules/@tiptap/extension-underline": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.6.6.tgz",
"integrity": "sha512-3A4HqsDM/AFb2VaeWACpGexjgI257kz0yU4jNV8uyydDR2KhqeinuEnoSoOmx9T3pL006TWfPg4vaQYPO3qvrQ==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^2.6.6"
}
},
"node_modules/@tiptap/pm": { "node_modules/@tiptap/pm": {
"version": "2.6.6", "version": "2.6.6",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.6.6.tgz", "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.6.6.tgz",

View File

@ -22,9 +22,11 @@
"@testing-library/jest-dom": "^6.4.6", "@testing-library/jest-dom": "^6.4.6",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@tiptap/extension-color": "^2.5.9", "@tiptap/extension-color": "^2.5.9",
"@tiptap/extension-highlight": "^2.6.6",
"@tiptap/extension-image": "^2.6.6", "@tiptap/extension-image": "^2.6.6",
"@tiptap/extension-placeholder": "^2.6.2", "@tiptap/extension-placeholder": "^2.6.2",
"@tiptap/extension-text-style": "^2.5.9", "@tiptap/extension-text-style": "^2.5.9",
"@tiptap/extension-underline": "^2.6.6",
"@tiptap/pm": "^2.5.9", "@tiptap/pm": "^2.5.9",
"@tiptap/react": "^2.5.9", "@tiptap/react": "^2.5.9",
"@tiptap/starter-kit": "^2.5.9", "@tiptap/starter-kit": "^2.5.9",

View File

@ -1263,6 +1263,7 @@ function App() {
<CustomButton <CustomButton
onClick={() => { onClick={() => {
setExtstate("send-qort"); setExtstate("send-qort");
setIsOpenDrawerProfile(false)
}} }}
> >
Transfer QORT Transfer QORT
@ -1291,6 +1292,7 @@ function App() {
<img <img
onClick={() => { onClick={() => {
setExtstate("download-wallet"); setExtstate("download-wallet");
setIsOpenDrawerProfile(false)
}} }}
src={Download} src={Download}
style={{ style={{
@ -1300,7 +1302,10 @@ function App() {
<Spacer height="20px" /> <Spacer height="20px" />
<img <img
src={Logout} src={Logout}
onClick={logoutFunc} onClick={()=> {
logoutFunc()
setIsOpenDrawerProfile(false)
}}
style={{ style={{
cursor: "pointer", cursor: "pointer",
}} }}
@ -1554,7 +1559,7 @@ function App() {
<Group <Group
balance={balance} balance={balance}
userInfo={userInfo} userInfo={userInfo}
myAddress={userInfo?.address} myAddress={address}
isFocused={isFocused} isFocused={isFocused}
isMain={isMain} isMain={isMain}
isOpenDrawerProfile={isOpenDrawerProfile} isOpenDrawerProfile={isOpenDrawerProfile}

View File

@ -237,7 +237,7 @@ const handleNotificationDirect = async (directs)=> {
const address = wallet.address0; const address = wallet.address0;
const dataDirects = directs.filter((direct)=> direct?.sender !== address) const dataDirects = directs.filter((direct)=> direct?.sender !== address)
try { try {
if(!dataDirects || dataDirects?.length === 0) return
isFocused = await checkWebviewFocus() isFocused = await checkWebviewFocus()
if(isFocused){ if(isFocused){
@ -264,7 +264,7 @@ if (!oldestLatestTimestamp || oldChat?.timestamp > oldestLatestTimestamp?.timest
} }
}); });
console.log('newestLatestTimestamp', newestLatestTimestamp)
if(checkDifference(newestLatestTimestamp.timestamp) && !oldestLatestTimestamp || (newestLatestTimestamp && newestLatestTimestamp?.timestamp > oldestLatestTimestamp?.timestamp)){ if(checkDifference(newestLatestTimestamp.timestamp) && !oldestLatestTimestamp || (newestLatestTimestamp && newestLatestTimestamp?.timestamp > oldestLatestTimestamp?.timestamp)){
const notificationId = 'chat_notification_' + Date.now() + '_type=direct' + `_from=${newestLatestTimestamp.address}`; const notificationId = 'chat_notification_' + Date.now() + '_type=direct' + `_from=${newestLatestTimestamp.address}`;
chrome.notifications.create(notificationId, { chrome.notifications.create(notificationId, {
@ -1062,7 +1062,7 @@ async function getNameOrAddress(receiver) {
} }
} }
async function getPublicKey(receiver) { export async function getPublicKey(receiver) {
try { try {
const validApi = await getBaseApi() const validApi = await getBaseApi()
@ -1326,8 +1326,8 @@ async function sendChatGroup({
privateKey: uint8PrivateKey, privateKey: uint8PrivateKey,
publicKey: uint8PublicKey, publicKey: uint8PublicKey,
}; };
const balance = await getBalanceInfo(); // const balance = await getBalanceInfo();
const hasEnoughBalance = +balance < 4 ? false : true; // const hasEnoughBalance = +balance < 4 ? false : true;
const difficulty = 8; const difficulty = 8;
const tx = await createTransaction(181, keyPair, { const tx = await createTransaction(181, keyPair, {
@ -1343,9 +1343,9 @@ async function sendChatGroup({
isText: 1, isText: 1,
}); });
if (!hasEnoughBalance) { // if (!hasEnoughBalance) {
throw new Error("Must have at least 4 QORT to send a chat message"); // throw new Error("Must have at least 4 QORT to send a chat message");
} // }
const path = chrome.runtime.getURL("memory-pow.wasm.full"); const path = chrome.runtime.getURL("memory-pow.wasm.full");
const { nonce, chatBytesArray } = await computePow({ const { nonce, chatBytesArray } = await computePow({
@ -1366,15 +1366,27 @@ async function sendChatGroup({
} }
async function sendChatDirect({ async function sendChatDirect({
address,
directTo, directTo,
typeMessage, typeMessage,
chatReference, chatReference,
messageText, messageText,
publicKeyOfRecipient
}) { }) {
let recipientPublicKey
let recipientAddress = address
if(publicKeyOfRecipient){
recipientPublicKey = publicKeyOfRecipient
} else {
recipientAddress = await getNameOrAddress(directTo)
recipientPublicKey = await getPublicKey(recipientAddress)
}
if(!recipientAddress){
recipientAddress = await getNameOrAddress(directTo)
}
const recipientAddress = await getNameOrAddress(directTo)
const recipientPublicKey = await getPublicKey(recipientAddress)
if(!recipientPublicKey) throw new Error('Cannot retrieve publickey') if(!recipientPublicKey) throw new Error('Cannot retrieve publickey')
@ -1390,8 +1402,8 @@ async function sendChatDirect({
privateKey: uint8PrivateKey, privateKey: uint8PrivateKey,
publicKey: uint8PublicKey, publicKey: uint8PublicKey,
}; };
const balance = await getBalanceInfo(); // const balance = await getBalanceInfo();
const hasEnoughBalance = +balance < 4 ? false : true; // const hasEnoughBalance = +balance < 4 ? false : true;
const difficulty = 8; const difficulty = 8;
@ -1412,9 +1424,9 @@ async function sendChatDirect({
isText: 1, isText: 1,
}); });
if (!hasEnoughBalance) { // if (!hasEnoughBalance) {
throw new Error("Must have at least 4 QORT to send a chat message"); // throw new Error("Must have at least 4 QORT to send a chat message");
} // }
const path = chrome.runtime.getURL("memory-pow.wasm.full"); const path = chrome.runtime.getURL("memory-pow.wasm.full");
@ -1490,6 +1502,7 @@ async function decryptDirectFunc({ messages, involvingAddress }) {
publicKey: uint8PublicKey, publicKey: uint8PublicKey,
}; };
for (const message of messages) { for (const message of messages) {
console.log('messagedep', message)
try { try {
const decodedMessage = decryptChatMessage( const decodedMessage = decryptChatMessage(
message.data, message.data,
@ -3607,9 +3620,11 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
typeMessage = undefined, typeMessage = undefined,
chatReference = undefined, chatReference = undefined,
messageText, messageText,
publicKeyOfRecipient,
address
} = request.payload; } = request.payload;
sendChatDirect({ directTo, chatReference, messageText, typeMessage }) sendChatDirect({ directTo, chatReference, messageText, typeMessage, publicKeyOfRecipient, address })
.then((res) => { .then((res) => {
sendResponse(res); sendResponse(res);
@ -3669,8 +3684,9 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
const wallet = await getSaveWallet(); const wallet = await getSaveWallet();
const address = wallet.address0; const address = wallet.address0;
const key1 = `tempPublish-${address}` const key1 = `tempPublish-${address}`
const key2 = `group-data-${address}`
chrome.storage.local.remove(["keyPair", "walletInfo", "apiKey", "active-groups-directs", key1], () => {
chrome.storage.local.remove(["keyPair", "walletInfo", "apiKey", "active-groups-directs", key1, key2], () => {
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {
// Handle error // Handle error
console.error(chrome.runtime.lastError.message); console.error(chrome.runtime.lastError.message);
@ -4009,7 +4025,7 @@ chrome.runtime?.onInstalled.addListener((details) => {
chrome.alarms?.get("checkForNotifications", (existingAlarm) => { chrome.alarms?.get("checkForNotifications", (existingAlarm) => {
if (!existingAlarm) { if (!existingAlarm) {
// If the alarm does not exist, create it // If the alarm does not exist, create it
chrome.alarms.create("checkForNotifications", { periodInMinutes: 4 }); chrome.alarms.create("checkForNotifications", { periodInMinutes: 10 });
} }
}); });

View File

@ -11,13 +11,18 @@ import { LoadingSnackbar } from '../Snackbar/LoadingSnackbar';
import { getNameInfo } from '../Group/Group'; import { getNameInfo } from '../Group/Group';
import { Spacer } from '../../common/Spacer'; import { Spacer } from '../../common/Spacer';
import { CustomizedSnackbars } from '../Snackbar/Snackbar'; import { CustomizedSnackbars } from '../Snackbar/Snackbar';
import { getBaseApiReactSocket, isMobile } from '../../App'; import { getBaseApiReactSocket, isMobile, pauseAllQueues, resumeAllQueues } from '../../App';
import { getPublicKey } from '../../background';
import { useMessageQueue } from '../../MessageQueueContext';
import { executeEvent } from '../../utils/events';
export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDirect, setNewChat, getTimestampEnterChat, myName}) => { export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDirect, setNewChat, getTimestampEnterChat, myName, balance}) => {
const { queueChats, addToQueue, } = useMessageQueue();
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [isSending, setIsSending] = useState(false) const [isSending, setIsSending] = useState(false)
const [directToValue, setDirectToValue] = useState('') const [directToValue, setDirectToValue] = useState('')
@ -25,14 +30,41 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [openSnack, setOpenSnack] = React.useState(false); const [openSnack, setOpenSnack] = React.useState(false);
const [infoSnack, setInfoSnack] = React.useState(null); const [infoSnack, setInfoSnack] = React.useState(null);
const [publicKeyOfRecipient, setPublicKeyOfRecipient] = React.useState("")
const hasInitializedWebsocket = useRef(false) const hasInitializedWebsocket = useRef(false)
const editorRef = useRef(null); const editorRef = useRef(null);
const socketRef = useRef(null);
const timeoutIdRef = useRef(null);
const groupSocketTimeoutRef = useRef(null);
const setEditorRef = (editorInstance) => { const setEditorRef = (editorInstance) => {
editorRef.current = editorInstance; editorRef.current = editorInstance;
}; };
const publicKeyOfRecipientRef = useRef(null)
const getPublicKeyFunc = async (address)=> {
try {
const publicKey = await getPublicKey(address)
if(publicKeyOfRecipientRef.current !== selectedDirect?.address) return
setPublicKeyOfRecipient(publicKey)
} catch (error) {
}
}
const tempMessages = useMemo(()=> {
if(!selectedDirect?.address) return []
if(queueChats[selectedDirect?.address]){
return queueChats[selectedDirect?.address]
}
return []
}, [selectedDirect?.address, queueChats])
useEffect(()=> {
if(selectedDirect?.address){
publicKeyOfRecipientRef.current = selectedDirect?.address
getPublicKeyFunc(publicKeyOfRecipientRef.current)
}
}, [selectedDirect?.address])
@ -54,7 +86,7 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
...item, ...item,
id: item.signature, id: item.signature,
text: item.message, text: item.message,
unread: true unread: item?.sender === myAddress ? false : true
} }
} ) } )
setMessages((prev)=> [...prev, ...formatted]) setMessages((prev)=> [...prev, ...formatted])
@ -80,78 +112,106 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
} }
} }
const forceCloseWebSocket = () => {
if (socketRef.current) {
console.log('Force closing the WebSocket');
clearTimeout(timeoutIdRef.current);
clearTimeout(groupSocketTimeoutRef.current);
socketRef.current.close(1000, 'forced');
socketRef.current = null;
}
};
const pingWebSocket = () => {
try {
if (socketRef.current?.readyState === WebSocket.OPEN) {
socketRef.current.send('ping');
timeoutIdRef.current = setTimeout(() => {
if (socketRef.current) {
socketRef.current.close();
clearTimeout(groupSocketTimeoutRef.current);
}
}, 5000); // Close if no pong in 5 seconds
}
} catch (error) {
console.error('Error during ping:', error);
}
};
const initWebsocketMessageGroup = () => { const initWebsocketMessageGroup = () => {
let timeoutId forceCloseWebSocket(); // Close any existing connection
let groupSocketTimeout
if (!selectedDirect?.address || !myAddress) return;
let socketTimeout: any
let socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?involving=${selectedDirect?.address}&involving=${myAddress}&encoding=BASE64&limit=100` const socketLink = `${getBaseApiReactSocket()}/websockets/chat/messages?involving=${selectedDirect?.address}&involving=${myAddress}&encoding=BASE64&limit=100`;
const socket = new WebSocket(socketLink) socketRef.current = new WebSocket(socketLink);
const pingGroupSocket = () => { socketRef.current.onopen = () => {
socket.send('ping') console.log('WebSocket connection opened');
timeoutId = setTimeout(() => { setTimeout(pingWebSocket, 50); // Initial ping
socket.close() };
clearTimeout(groupSocketTimeout)
}, 5000) // Close the WebSocket connection if no pong message is received within 5 seconds. socketRef.current.onmessage = (e) => {
}
socket.onopen = () => {
setTimeout(pingGroupSocket, 50)
}
socket.onmessage = (e) => {
try { try {
if (e.data === 'pong') { if (e.data === 'pong') {
clearTimeout(timeoutIdRef.current);
clearTimeout(timeoutId) groupSocketTimeoutRef.current = setTimeout(pingWebSocket, 45000); // Ping every 45 seconds
groupSocketTimeout = setTimeout(pingGroupSocket, 45000)
return
} else { } else {
decryptMessages(JSON.parse(e.data)) decryptMessages(JSON.parse(e.data));
setIsLoading(false) setIsLoading(false);
} }
} catch (error) { } catch (error) {
console.error('Error handling WebSocket message:', error);
} }
};
}
socket.onclose = () => { socketRef.current.onclose = (event) => {
console.log('closed') clearTimeout(groupSocketTimeoutRef.current);
clearTimeout(socketTimeout) clearTimeout(timeoutIdRef.current);
setTimeout(() => initWebsocketMessageGroup(), 50) console.warn(`WebSocket closed: ${event.reason || 'unknown reason'}`);
if (event.reason !== 'forced' && event.code !== 1000) {
} setTimeout(() => initWebsocketMessageGroup(), 10000); // Retry after 10 seconds
socket.onerror = (e) => { }
clearTimeout(groupSocketTimeout) };
socket.close()
} socketRef.current.onerror = (error) => {
} console.error('WebSocket error:', error);
clearTimeout(groupSocketTimeoutRef.current);
clearTimeout(timeoutIdRef.current);
if (socketRef.current) {
socketRef.current.close();
}
};
};
useEffect(()=> { useEffect(() => {
if(hasInitializedWebsocket.current) return if (hasInitializedWebsocket.current || isNewChat) return;
setIsLoading(true) setIsLoading(true);
initWebsocketMessageGroup() initWebsocketMessageGroup();
hasInitializedWebsocket.current = true hasInitializedWebsocket.current = true;
}, [])
return () => {
forceCloseWebSocket(); // Clean up WebSocket on component unmount
};
}, [selectedDirect?.address, myAddress, isNewChat]);
const sendChatDirect = async ({ chatReference = undefined, messageText}: any)=> { const sendChatDirect = async ({ chatReference = undefined, messageText}: any, address, publicKeyOfRecipient, isNewChatVar)=> {
try { try {
const directTo = isNewChat ? directToValue : selectedDirect.address const directTo = isNewChatVar ? directToValue : address
if(!directTo) return if(!directTo) return
return new Promise((res, rej)=> { return new Promise((res, rej)=> {
chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: { chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: {
directTo, chatReference, messageText directTo, chatReference, messageText, publicKeyOfRecipient, address: directTo
}}, async (response) => { }}, async (response) => {
if (!response?.error) { if (!response?.error) {
if(isNewChat){ if(isNewChatVar){
let getRecipientName = null let getRecipientName = null
try { try {
@ -186,6 +246,7 @@ const sendChatDirect = async ({ chatReference = undefined, messageText}: any)=>
}) })
} catch (error) { } catch (error) {
throw new Error(error) throw new Error(error)
} finally {
} }
} }
const clearEditorContent = () => { const clearEditorContent = () => {
@ -197,33 +258,60 @@ const clearEditorContent = () => {
const sendMessage = async ()=> { const sendMessage = async ()=> {
try { try {
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
if(isSending) return if(isSending) return
if (editorRef.current) { if (editorRef.current) {
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)
pauseAllQueues()
const message = JSON.stringify(htmlContent) const message = JSON.stringify(htmlContent)
const res = await sendChatDirect({ messageText: htmlContent})
if(isNewChat){
await sendChatDirect({ messageText: htmlContent}, null, null, true)
return
}
const sendMessageFunc = async () => {
await sendChatDirect({ messageText: htmlContent}, selectedDirect?.address, publicKeyOfRecipient, false)
};
// Add the function to the queue
const messageObj = {
message: {
text: htmlContent,
timestamp: Date.now(),
senderName: myName,
sender: myAddress
},
}
addToQueue(sendMessageFunc, messageObj, 'chat-direct',
selectedDirect?.address );
setTimeout(() => {
executeEvent("sent-new-message-group", {})
}, 150);
clearEditorContent()
clearEditorContent() clearEditorContent()
} }
// send chat message // send chat message
} catch (error) { } catch (error) {
const errorMsg = error?.message || error
setInfoSnack({ setInfoSnack({
type: "error", type: "error",
message: error, message: errorMsg === 'invalid signature' ? 'You need at least 4 QORT to send a message' : errorMsg,
}); });
setOpenSnack(true); setOpenSnack(true);
console.error(error) console.error(error)
} finally { } finally {
setIsSending(false) setIsSending(false)
resumeAllQueues()
} }
} }
return ( return (
<div style={{ <div style={{
height: isMobile ? '100%' : '100vh', height: isMobile ? '100%' : '100vh',
@ -241,7 +329,7 @@ const clearEditorContent = () => {
</> </>
)} )}
<ChatList initialMessages={messages} myAddress={myAddress} tempMessages={[]}/> <ChatList initialMessages={messages} myAddress={myAddress} tempMessages={tempMessages}/>
<div style={{ <div style={{

View File

@ -20,7 +20,7 @@ import { executeEvent } from '../../utils/events'
export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName}) => { export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, myAddress, handleNewEncryptionNotification, hide, handleSecretKeyCreationInProgress, triedToFetchSecretKey, myName, balance}) => {
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [isSending, setIsSending] = useState(false) const [isSending, setIsSending] = useState(false)
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
@ -277,6 +277,7 @@ const clearEditorContent = () => {
const sendMessage = async ()=> { const sendMessage = async ()=> {
try { try {
if(isSending) return if(isSending) return
if(+balance < 4) throw new Error('You need at least 4 QORT to send a message')
pauseAllQueues() pauseAllQueues()
if (editorRef.current) { if (editorRef.current) {
const htmlContent = editorRef.current.getHTML(); const htmlContent = editorRef.current.getHTML();
@ -313,9 +314,10 @@ const clearEditorContent = () => {
} }
// send chat message // send chat message
} catch (error) { } catch (error) {
const errorMsg = error?.message || error
setInfoSnack({ setInfoSnack({
type: "error", type: "error",
message: error, message: errorMsg,
}); });
setOpenSnack(true); setOpenSnack(true);
console.error(error) console.error(error)

View File

@ -335,11 +335,11 @@ export const GroupAnnouncements = ({
); );
React.useEffect(() => { React.useEffect(() => {
if (selectedGroup && secretKey && !hasInitialized.current) { if (selectedGroup && secretKey && !hasInitialized.current && !hide) {
getAnnouncements(selectedGroup); getAnnouncements(selectedGroup);
hasInitialized.current = true hasInitialized.current = true
} }
}, [selectedGroup, secretKey]); }, [selectedGroup, secretKey, hide]);
const loadMore = async()=> { const loadMore = async()=> {
@ -428,14 +428,14 @@ export const GroupAnnouncements = ({
}, [checkNewMessages]) }, [checkNewMessages])
useEffect(() => { useEffect(() => {
if(!secretKey) return if(!secretKey || hide) return
checkNewMessagesFunc() checkNewMessagesFunc()
return () => { return () => {
if (interval?.current) { if (interval?.current) {
clearInterval(interval.current) clearInterval(interval.current)
} }
} }
}, [checkNewMessagesFunc]) }, [checkNewMessagesFunc, hide])

View File

@ -46,7 +46,7 @@ export const GroupForum = ({
left: hide && '-1000px' left: hide && '-1000px'
}} }}
> >
<GroupMail getSecretKey={getSecretKey} selectedGroup={selectedGroup} userInfo={userInfo} secretKey={secretKey} defaultThread={defaultThread} setDefaultThread={setDefaultThread} /> <GroupMail hide={hide} getSecretKey={getSecretKey} selectedGroup={selectedGroup} userInfo={userInfo} secretKey={secretKey} defaultThread={defaultThread} setDefaultThread={setDefaultThread} />
</div> </div>
); );

View File

@ -6,7 +6,10 @@ import { Avatar, Box, Typography } from "@mui/material";
import { formatTimestamp } from "../../utils/time"; import { formatTimestamp } from "../../utils/time";
import { getBaseApi } from "../../background"; import { getBaseApi } from "../../background";
import { getBaseApiReact } from "../../App"; import { getBaseApiReact } from "../../App";
import { generateHTML } from "@tiptap/react";
import Highlight from '@tiptap/extension-highlight'
import StarterKit from '@tiptap/starter-kit'
import Underline from '@tiptap/extension-underline'
export const MessageItem = ({ message, onSeen, isLast, isTemp }) => { export const MessageItem = ({ message, onSeen, isLast, isTemp }) => {
const { ref, inView } = useInView({ const { ref, inView } = useInView({
@ -60,6 +63,9 @@ export const MessageItem = ({ message, onSeen, isLast, isTemp }) => {
> >
{message?.senderName || message?.sender} {message?.senderName || message?.sender}
</Typography> </Typography>
{message?.messageText && (
<MessageDisplay htmlContent={generateHTML(message?.messageText, [StarterKit, Underline, Highlight])} />
)}
{message?.text?.type === "notification" ? ( {message?.text?.type === "notification" ? (
<MessageDisplay htmlContent={message.text?.data?.message} /> <MessageDisplay htmlContent={message.text?.data?.message} />
) : ( ) : (

View File

@ -63,7 +63,8 @@ export const GroupMail = ({
getSecretKey, getSecretKey,
secretKey, secretKey,
defaultThread, defaultThread,
setDefaultThread setDefaultThread,
hide
}) => { }) => {
const [viewedThreads, setViewedThreads] = React.useState<any>({}); const [viewedThreads, setViewedThreads] = React.useState<any>({});
const [filterMode, setFilterMode] = useState<string>("Recently active"); const [filterMode, setFilterMode] = useState<string>("Recently active");
@ -353,6 +354,7 @@ export const GroupMail = ({
const filterModeRef = useRef(""); const filterModeRef = useRef("");
useEffect(() => { useEffect(() => {
if(hide) return
if (filterModeRef.current !== filterMode) { if (filterModeRef.current !== filterMode) {
firstMount.current = false; firstMount.current = false;
} }
@ -368,7 +370,7 @@ export const GroupMail = ({
setTempData() setTempData()
firstMount.current = true; firstMount.current = true;
} }
}, [groupId, members, filterMode]); }, [groupId, members, filterMode, hide]);
const closeThread = useCallback(() => { const closeThread = useCallback(() => {
setCurrentThread(null); setCurrentThread(null);

View File

@ -332,7 +332,6 @@ export const Group = ({
const [directs, setDirects] = useState([]); const [directs, setDirects] = useState([]);
const [admins, setAdmins] = useState([]); const [admins, setAdmins] = useState([]);
const [adminsWithNames, setAdminsWithNames] = useState([]); const [adminsWithNames, setAdminsWithNames] = useState([]);
console.log('adminsWithNames', {adminsWithNames}, {admins})
const [members, setMembers] = useState([]); const [members, setMembers] = useState([]);
const [groupOwner, setGroupOwner] = useState(null); const [groupOwner, setGroupOwner] = useState(null);
const [triedToFetchSecretKey, setTriedToFetchSecretKey] = useState(false); const [triedToFetchSecretKey, setTriedToFetchSecretKey] = useState(false);
@ -574,7 +573,6 @@ console.log('adminsWithNames', {adminsWithNames}, {admins})
let publishFromStorage let publishFromStorage
let adminsFromStorage let adminsFromStorage
const groupData = await getGroupDataSingle(selectedGroup?.groupId) const groupData = await getGroupDataSingle(selectedGroup?.groupId)
console.log('groupData', groupData)
if(groupData?.secretKeyData && Date.now() - groupData?.timestampLastSet < 3600000 ){ if(groupData?.secretKeyData && Date.now() - groupData?.timestampLastSet < 3600000 ){
dataFromStorage = groupData.secretKeyData dataFromStorage = groupData.secretKeyData
@ -1518,27 +1516,42 @@ console.log('adminsWithNames', {adminsWithNames}, {admins})
setMemberCountFromSecretKeyData(null); setMemberCountFromSecretKeyData(null);
setTriedToFetchSecretKey(false); setTriedToFetchSecretKey(false);
setFirstSecretKeyInCreation(false); setFirstSecretKeyInCreation(false);
setGroupSection("announcement"); // setGroupSection("announcement");
setGroupSection("chat");
setIsOpenDrawer(false) setIsOpenDrawer(false)
setTimeout(() => { setTimeout(() => {
setSelectedGroup(group); setSelectedGroup(group);
getTimestampEnterChat(); // getTimestampEnterChat();
}, 200); }, 200);
if (groupSectionRef.current === "announcement") {
chrome?.runtime?.sendMessage({ chrome?.runtime?.sendMessage({
action: "addGroupNotificationTimestamp", action: "addTimestampEnterChat",
payload: { payload: {
timestamp: Date.now(), timestamp: Date.now(),
groupId: group.groupId, groupId: group.groupId,
}, },
}); });
}
setTimeout(() => {
getTimestampEnterChat();
}, 200);
setTimeout(() => { // if (groupSectionRef.current === "announcement") {
getGroupAnnouncements(); // chrome?.runtime?.sendMessage({
}, 600); // action: "addGroupNotificationTimestamp",
// payload: {
// timestamp: Date.now(),
// groupId: group.groupId,
// },
// });
// }
// setTimeout(() => {
// getGroupAnnouncements();
// }, 600);
}} }}
sx={{ sx={{
display: "flex", display: "flex",
@ -1700,6 +1713,7 @@ console.log('adminsWithNames', {adminsWithNames}, {admins})
setSelectedDirect={setSelectedDirect} setSelectedDirect={setSelectedDirect}
setNewChat={setNewChat} setNewChat={setNewChat}
getTimestampEnterChat={getTimestampEnterChat} getTimestampEnterChat={getTimestampEnterChat}
balance={balance}
/> />
</> </>
)} )}
@ -1727,6 +1741,7 @@ console.log('adminsWithNames', {adminsWithNames}, {admins})
} }
triedToFetchSecretKey={triedToFetchSecretKey} triedToFetchSecretKey={triedToFetchSecretKey}
myName={userInfo?.name} myName={userInfo?.name}
balance={balance}
/> />
)} )}
{firstSecretKeyInCreation && {firstSecretKeyInCreation &&
@ -1892,6 +1907,7 @@ console.log('adminsWithNames', {adminsWithNames}, {admins})
setSelectedDirect={setSelectedDirect} setSelectedDirect={setSelectedDirect}
setNewChat={setNewChat} setNewChat={setNewChat}
getTimestampEnterChat={getTimestampEnterChat} getTimestampEnterChat={getTimestampEnterChat}
myName={userInfo?.name}
/> />
</Box> </Box>
</> </>