mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-02-15 19:55:50 +00:00
optimizations, see ui direct chat, fixes
This commit is contained in:
parent
5327c79543
commit
eebcd8c36f
26
package-lock.json
generated
26
package-lock.json
generated
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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}
|
||||||
|
@ -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 });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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={{
|
||||||
|
@ -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)
|
||||||
|
@ -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])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user