diff --git a/src/background.ts b/src/background.ts index f604691..edd5398 100644 --- a/src/background.ts +++ b/src/background.ts @@ -187,6 +187,25 @@ export async function findUsableApi() { throw new Error("No usable API found"); } +export function isExtMsg(data){ + let isMsgFromExtensionGroup = true + try { + const decode1 = atob(data) + const decode2 = atob(decode1) + const keyStr = decode2.slice(0, 10); + + // Convert the key string back to a number + const highestKey = parseInt(keyStr, 10); + if(isNaN(highestKey)){ + isMsgFromExtensionGroup = false + } + } catch (error) { + isMsgFromExtensionGroup = false + } +console.log('isMsgFromExtensionGroup', isMsgFromExtensionGroup) + return isMsgFromExtensionGroup +} + async function checkWebviewFocus() { return new Promise((resolve) => { @@ -440,7 +459,8 @@ const handleNotification = async (groups)=> { if(checkDifference(newestLatestTimestamp.timestamp) && !oldestLatestTimestamp || (newestLatestTimestamp && newestLatestTimestamp?.timestamp > oldestLatestTimestamp?.timestamp)){ if (!lastGroupNotification || ((Date.now() - lastGroupNotification) >= 120000)) { - + if(!newestLatestTimestamp?.data || !isExtMsg(newestLatestTimestamp?.data)) return + console.log('newestLatestTimestamp', newestLatestTimestamp) const notificationId = 'chat_notification_' + Date.now() + '_type=group' + `_from=${newestLatestTimestamp.groupId}`; chrome.notifications.create(notificationId, { @@ -2318,6 +2338,57 @@ async function addTimestampGroupAnnouncement({groupId, timestamp, seenTimestamp} }); } +async function getGroupData(){ + const wallet = await getSaveWallet(); + const address = wallet.address0; + const key = `group-data-${address}` + const res = await chrome.storage.local.get([key]); +if (res?.[key]) { + const parsedData = JSON.parse(res[key]) + return parsedData; +} else { + return {} +} +} +async function getGroupDataSingle(groupId){ + const wallet = await getSaveWallet(); + const address = wallet.address0; + const key = `group-data-${address}` + const res = await chrome.storage.local.get([key]); +if (res?.[key]) { + const parsedData = JSON.parse(res[key]) + return parsedData[groupId] || null; +} else { + return null +} +} + +async function setGroupData({groupId, + secretKeyData, + secretKeyResource, + admins}){ + const wallet = await getSaveWallet(); + const address = wallet.address0; + const data = await getGroupData() || {} + data[groupId] = { + timestampLastSet: Date.now(), + admins, + secretKeyData, + secretKeyResource, + } + const dataString = JSON.stringify(data); + return await new Promise((resolve, reject) => { + chrome.storage.local.set({ [`group-data-${address}`]: dataString }, () => { + if (chrome.runtime.lastError) { + reject(new Error(chrome.runtime.lastError.message)); + } else { + resolve(true); + } + }); + }); +} + + async function addTimestampEnterChat({groupId, timestamp}){ const wallet = await getSaveWallet(); @@ -2821,6 +2892,41 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { }); break; } + case "setGroupData": { + + const { groupId, + secretKeyData, + secretKeyResource, + admins} = + request.payload; + setGroupData({ + groupId, + secretKeyData, + secretKeyResource, + admins + }) + .then((res) => { + sendResponse(res); + }) + .catch((error) => { + sendResponse({ error: error.message }); + console.error(error.message); + }); + break; + } + case "getGroupDataSingle": { + const {groupId} = request.payload + getGroupDataSingle(groupId) + .then((res) => { + sendResponse(res); + }) + .catch((error) => { + sendResponse({ error: error.message }); + console.error(error.message); + }); + return true + break; + } case "getTimestampEnterChat": { getTimestampEnterChat() .then((res) => { diff --git a/src/components/Chat/CreateCommonSecret.tsx b/src/components/Chat/CreateCommonSecret.tsx index 119fb52..2bfa604 100644 --- a/src/components/Chat/CreateCommonSecret.tsx +++ b/src/components/Chat/CreateCommonSecret.tsx @@ -51,11 +51,11 @@ export const CreateCommonSecret = ({groupId, secretKey, isOwner, myAddress, sec - const groupAdmins = await getGroupAdimns(groupId); - if(!groupAdmins.length){ + const {names} = await getGroupAdimns(groupId); + if(!names.length){ throw new Error('Network error') } - const publish = await getPublishesFromAdmins(groupAdmins); + const publish = await getPublishesFromAdmins(names); if (publish === false) { diff --git a/src/components/Group/Group.tsx b/src/components/Group/Group.tsx index f66b085..be246e6 100644 --- a/src/components/Group/Group.tsx +++ b/src/components/Group/Group.tsx @@ -73,6 +73,7 @@ import { WebSocketActive } from "./WebsocketActive"; import { flushSync } from "react-dom"; import { useMessageQueue } from "../../MessageQueueContext"; import { DrawerComponent } from "../Drawer/Drawer"; +import { isExtMsg } from "../../background"; // let touchStartY = 0; // let disablePullToRefresh = false; @@ -222,6 +223,8 @@ export const getGroupAdimns = async (groupNumber: number) => { ); const groupData = await response.json(); let members: any = []; + let membersAddresses = [] + let both = [] // if (groupData && Array.isArray(groupData?.members)) { // for (const member of groupData.members) { // if (member.member) { @@ -240,14 +243,16 @@ export const getGroupAdimns = async (groupNumber: number) => { }); if (name) { members.push(name); + both.push({name, address: member.member}) } + membersAddresses.push(member.member) } return true; }); await Promise.all(getMemNames); - return members; + return {names: members, addresses: membersAddresses, both}; }; export const getNames = async (listOfMembers) => { @@ -327,7 +332,7 @@ export const Group = ({ const [directs, setDirects] = useState([]); const [admins, setAdmins] = useState([]); const [adminsWithNames, setAdminsWithNames] = useState([]); - +console.log('adminsWithNames', {adminsWithNames}, {admins}) const [members, setMembers] = useState([]); const [groupOwner, setGroupOwner] = useState(null); const [triedToFetchSecretKey, setTriedToFetchSecretKey] = useState(false); @@ -342,7 +347,7 @@ export const Group = ({ const [openSnack, setOpenSnack] = React.useState(false); const [infoSnack, setInfoSnack] = React.useState(null); const [isLoadingNotifyAdmin, setIsLoadingNotifyAdmin] = React.useState(false); - const [isLoadingGroups, setIsLoadingGroups] = React.useState(false); + const [isLoadingGroups, setIsLoadingGroups] = React.useState(true); const [isLoadingGroup, setIsLoadingGroup] = React.useState(false); const [firstSecretKeyInCreation, setFirstSecretKeyInCreation] = React.useState(false); @@ -361,7 +366,7 @@ export const Group = ({ const setupGroupWebsocketInterval = useRef(null); const settimeoutForRefetchSecretKey = useRef(null); const { clearStatesMessageQueueProvider } = useMessageQueue(); - + const initiatedGetMembers = useRef(false); // useEffect(()=> { // setFullHeight() // }, []) @@ -399,6 +404,30 @@ export const Group = ({ }); } catch (error) {} }; + const getGroupDataSingle = async (groupId) => { + try { + return new Promise((res, rej) => { + chrome?.runtime?.sendMessage( + { + action: "getGroupDataSingle", + payload: { + groupId + } + }, + (response) => { + if (!response?.error) { + + res(response); + return + } + rej(response.error); + } + ); + }); + } catch (error) { + return {} + } + }; const refreshHomeDataFunc = () => { setGroupSection("default"); setTimeout(() => { @@ -539,7 +568,20 @@ export const Group = ({ secretKeyToPublish?: boolean ) => { try { + // setGroupDataLastSet(null) pauseAllQueues(); + let dataFromStorage + let publishFromStorage + let adminsFromStorage + const groupData = await getGroupDataSingle(selectedGroup?.groupId) + console.log('groupData', groupData) + if(groupData?.secretKeyData && Date.now() - groupData?.timestampLastSet < 3600000 ){ + + dataFromStorage = groupData.secretKeyData + publishFromStorage = groupData.secretKeyResource + adminsFromStorage = groupData.admins + // setGroupDataLastSet(groupData.timestampLastSet) + } if ( secretKeyToPublish && @@ -559,12 +601,13 @@ export const Group = ({ } const prevGroupId = selectedGroupRef.current.groupId; // const validApi = await findUsableApi(); - const groupAdmins = await getGroupAdimns(selectedGroup?.groupId); - setAdmins(groupAdmins); - if (!groupAdmins.length) { + const {names, addresses, both} = adminsFromStorage || await getGroupAdimns(selectedGroup?.groupId); + setAdmins(addresses); + setAdminsWithNames(both) + if (!names.length) { throw new Error("Network error"); } - const publish = await getPublishesFromAdmins(groupAdmins); + const publish = publishFromStorage || await getPublishesFromAdmins(names); if (prevGroupId !== selectedGroupRef.current.groupId) { if (settimeoutForRefetchSecretKey.current) { @@ -580,13 +623,18 @@ export const Group = ({ return false; } setSecretKeyPublishDate(publish?.updated || publish?.created); - - const res = await fetch( - `${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ - publish.identifier - }?encoding=base64` - ); - const data = await res.text(); + let data + if(dataFromStorage){ + data = dataFromStorage + } else { + const res = await fetch( + `${getBaseApiReact()}/arbitrary/DOCUMENT_PRIVATE/${publish.name}/${ + publish.identifier + }?encoding=base64` + ); + data = await res.text(); + } + const decryptedKey: any = await decryptResource(data); @@ -599,6 +647,17 @@ export const Group = ({ setSecretKey(decryptedKeyToObject); lastFetchedSecretKey.current = Date.now(); setMemberCountFromSecretKeyData(decryptedKey.count); + chrome?.runtime?.sendMessage( + { + action: "setGroupData", + payload: { + groupId: selectedGroup?.groupId, + secretKeyData: data, + secretKeyResource: publish, + admins: {names, addresses, both} + }, + } + ); if (decryptedKeyToObject) { setTriedToFetchSecretKey(true); setFirstSecretKeyInCreation(false); @@ -616,7 +675,7 @@ export const Group = ({ } finally { setIsLoadingGroup(false); if (!secretKeyToPublish) { - await getAdmins(selectedGroup?.groupId); + // await getAdmins(selectedGroup?.groupId); } resumeAllQueues(); } @@ -828,11 +887,14 @@ export const Group = ({ } catch (error) {} }; useEffect(() => { - if (selectedGroup?.groupId) { + if (!initiatedGetMembers.current && selectedGroup?.groupId && secretKey && admins.includes(myAddress)) { + + console.log('goung through', admins) // getAdmins(selectedGroup?.groupId); getMembers(selectedGroup?.groupId); + initiatedGetMembers.current = true } - }, [selectedGroup?.groupId]); + }, [selectedGroup?.groupId, secretKey, myAddress, admins]); const shouldReEncrypt = useMemo(() => { if (triedToFetchSecretKey && !secretKeyPublishDate) return true; @@ -908,6 +970,7 @@ export const Group = ({ .filter((group) => group?.sender !== myAddress) .find((gr) => gr?.groupId === selectedGroup?.groupId); if (!findGroup) return false; + if(!findGroup?.data || !isExtMsg(findGroup?.data)) return false return ( findGroup?.timestamp && ((!timestampEnterData[selectedGroup?.groupId] && @@ -1015,6 +1078,7 @@ export const Group = ({ isLoadingOpenSectionFromNotification.current = false; setupGroupWebsocketInterval.current = null; settimeoutForRefetchSecretKey.current = null; + initiatedGetMembers.current = false }; const logoutEventFunc = () => { @@ -1537,7 +1601,7 @@ export const Group = ({ }} /> )} - {group?.sender !== myAddress && + {group?.data && isExtMsg(group?.data) && group?.sender !== myAddress && group?.timestamp && ((!timestampEnterData[group?.groupId] && Date.now() - group?.timestamp < @@ -1864,36 +1928,38 @@ export const Group = ({ Refresh home data - - - - - - - + {!isLoadingGroups && ( + + + + + + + )} + )} { const [groupsWithJoinRequests, setGroupsWithJoinRequests] = React.useState([])