From 3d9d3dff33e1d55653fd836ae1c38c4b66cb6125 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Wed, 18 Jun 2025 22:27:36 +0300 Subject: [PATCH] added txGroupId and chunk status --- src/background.ts | 52 +++++++++++------- src/components/Apps/AppViewer.tsx | 45 ++++++++++++++- .../Apps/useQortalMessageListener.tsx | 4 +- src/qdn/publish/pubish.ts | 55 ++++++++++++++++++- src/qortalRequests.ts | 2 +- src/qortalRequests/get.ts | 28 ++++++++-- 6 files changed, 153 insertions(+), 33 deletions(-) diff --git a/src/background.ts b/src/background.ts index d74d3e4..8368aca 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2466,7 +2466,7 @@ export async function joinGroup({ groupId }) { return res; } -export async function cancelInvitationToGroup({ groupId, qortalAddress }) { +export async function cancelInvitationToGroup({ groupId, qortalAddress, txGroupId = 0}) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); const parsedData = JSON.parse(resKeyPair); @@ -2483,6 +2483,7 @@ export async function cancelInvitationToGroup({ groupId, qortalAddress }) { recipient: qortalAddress, rGroupId: groupId, lastReference: lastReference, + groupID: txGroupId, }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2493,7 +2494,7 @@ export async function cancelInvitationToGroup({ groupId, qortalAddress }) { return res; } -export async function cancelBan({ groupId, qortalAddress }) { +export async function cancelBan({ groupId, qortalAddress, txGroupId = 0 }) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); const parsedData = JSON.parse(resKeyPair); @@ -2510,6 +2511,7 @@ export async function cancelBan({ groupId, qortalAddress }) { recipient: qortalAddress, rGroupId: groupId, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2574,7 +2576,7 @@ export async function updateName({ newName, oldName, description }) { return res; } -export async function makeAdmin({ groupId, qortalAddress }) { +export async function makeAdmin({ groupId, qortalAddress, txGroupId = 0 }) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); const parsedData = JSON.parse(resKeyPair); @@ -2591,6 +2593,7 @@ export async function makeAdmin({ groupId, qortalAddress }) { recipient: qortalAddress, rGroupId: groupId, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2601,7 +2604,7 @@ export async function makeAdmin({ groupId, qortalAddress }) { return res; } -export async function removeAdmin({ groupId, qortalAddress }) { +export async function removeAdmin({ groupId, qortalAddress, txGroupId = 0 }) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); const parsedData = JSON.parse(resKeyPair); @@ -2618,6 +2621,7 @@ export async function removeAdmin({ groupId, qortalAddress }) { recipient: qortalAddress, rGroupId: groupId, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2633,6 +2637,7 @@ export async function banFromGroup({ qortalAddress, rBanReason = "", rBanTime, + txGroupId = 0 }) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); @@ -2652,6 +2657,7 @@ export async function banFromGroup({ rBanReason: rBanReason, rBanTime, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2662,7 +2668,7 @@ export async function banFromGroup({ return res; } -export async function kickFromGroup({ groupId, qortalAddress, rBanReason = "" }) { +export async function kickFromGroup({ groupId, qortalAddress, rBanReason = "" , txGroupId = 0 }) { const lastReference = await getLastRef(); const resKeyPair = await getKeyPair(); const parsedData = JSON.parse(resKeyPair); @@ -2680,6 +2686,7 @@ export async function kickFromGroup({ groupId, qortalAddress, rBanReason = "" }) rGroupId: groupId, rBanReason: rBanReason, lastReference: lastReference, +groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2837,7 +2844,8 @@ export async function updateGroup({ newDescription, newApprovalThreshold, newMinimumBlockDelay, - newMaximumBlockDelay + newMaximumBlockDelay, + txGroupId = 0 }) { const wallet = await getSaveWallet(); const address = wallet.address0; @@ -2863,6 +2871,7 @@ export async function updateGroup({ newMinimumBlockDelay, newMaximumBlockDelay, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -2874,7 +2883,7 @@ export async function updateGroup({ } -export async function inviteToGroup({ groupId, qortalAddress, inviteTime }) { +export async function inviteToGroup({ groupId, qortalAddress, inviteTime, txGroupId = 0 }) { const address = await getNameOrAddress(qortalAddress); if (!address) throw new Error("Cannot find user"); const lastReference = await getLastRef(); @@ -2894,6 +2903,7 @@ export async function inviteToGroup({ groupId, qortalAddress, inviteTime }) { rGroupId: groupId, rInviteTime: inviteTime, lastReference: lastReference, + groupID: txGroupId }); const signedBytes = Base58.encode(tx.signedBytes); @@ -3635,8 +3645,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "inviteToGroup": { - const { groupId, qortalAddress, inviteTime } = request.payload; - inviteToGroup({ groupId, qortalAddress, inviteTime }) + const { groupId, qortalAddress, inviteTime, txGroupId = 0 } = request.payload; + inviteToGroup({ groupId, qortalAddress, inviteTime, txGroupId }) .then((res) => { sendResponse(res); }) @@ -3705,8 +3715,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "cancelInvitationToGroup": { - const { groupId, qortalAddress } = request.payload; - cancelInvitationToGroup({ groupId, qortalAddress }) + const { groupId, qortalAddress, txGroupId = 0 } = request.payload; + cancelInvitationToGroup({ groupId, qortalAddress, txGroupId }) .then((res) => { sendResponse(res); }) @@ -3748,8 +3758,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { case "kickFromGroup": { - const { groupId, qortalAddress, rBanReason } = request.payload; - kickFromGroup({ groupId, qortalAddress, rBanReason }) + const { groupId, qortalAddress, rBanReason, txGroupId = 0 } = request.payload; + kickFromGroup({ groupId, qortalAddress, rBanReason, txGroupId }) .then((res) => { sendResponse(res); }) @@ -3762,9 +3772,9 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "banFromGroup": { - const { groupId, qortalAddress, rBanReason, rBanTime } = + const { groupId, qortalAddress, rBanReason, rBanTime, txGroupId = 0 } = request.payload; - banFromGroup({ groupId, qortalAddress, rBanReason, rBanTime }) + banFromGroup({ groupId, qortalAddress, rBanReason, rBanTime , txGroupId}) .then((res) => { sendResponse(res); }) @@ -3829,8 +3839,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "cancelBan": { - const { groupId, qortalAddress } = request.payload; - cancelBan({ groupId, qortalAddress }) + const { groupId, qortalAddress, txGroupId = 0 } = request.payload; + cancelBan({ groupId, qortalAddress, txGroupId }) .then((res) => { sendResponse(res); }) @@ -3880,8 +3890,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "makeAdmin": { - const { groupId, qortalAddress } = request.payload; - makeAdmin({ groupId, qortalAddress }) + const { groupId, qortalAddress , txGroupId = 0} = request.payload; + makeAdmin({ groupId, qortalAddress , txGroupId}) .then((res) => { sendResponse(res); }) @@ -3894,8 +3904,8 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { break; case "removeAdmin": { - const { groupId, qortalAddress } = request.payload; - removeAdmin({ groupId, qortalAddress }) + const { groupId, qortalAddress, txGroupId = 0 } = request.payload; + removeAdmin({ groupId, qortalAddress, txGroupId }) .then((res) => { sendResponse(res); }) diff --git a/src/components/Apps/AppViewer.tsx b/src/components/Apps/AppViewer.tsx index a582ce1..2f1ab45 100644 --- a/src/components/Apps/AppViewer.tsx +++ b/src/components/Apps/AppViewer.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useMemo, useState } from "react"; +import React, { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { Avatar, Box, } from "@mui/material"; import { Add } from "@mui/icons-material"; @@ -100,6 +100,49 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i }; }, [app, path]); + const receiveChunksFunc = useCallback( + (e) => { + const iframe = iframeRef?.current; + if (!iframe || !iframe?.src) return; + if (app?.tabId !== e.detail?.tabId) return; + const publishLocation = e.detail?.publishLocation; + const chunksSubmitted = e.detail?.chunksSubmitted; + const totalChunks = e.detail?.totalChunks; + try { + if (publishLocation === undefined || publishLocation === null) return; + const dataToBeSent = {}; + if (chunksSubmitted !== undefined && chunksSubmitted !== null) { + dataToBeSent.chunks = chunksSubmitted; + } + if (totalChunks !== undefined && totalChunks !== null) { + dataToBeSent.totalChunks = totalChunks; + } + const targetOrigin = new URL(iframe.src).origin; + iframe.contentWindow?.postMessage( + { + action: 'PUBLISH_STATUS', + publishLocation, + ...dataToBeSent, + requestedHandler: 'UI', + processed: e.detail?.processed || false, + }, + targetOrigin + ); + } catch (err) { + console.error('Failed to send status to iframe:', err); + } + }, + [iframeRef, app?.tabId] + ); + + useEffect(() => { + subscribeToEvent('receiveChunks', receiveChunksFunc); + + return () => { + unsubscribeFromEvent('receiveChunks', receiveChunksFunc); + }; + }, [receiveChunksFunc]); + // Function to navigate back in iframe const navigateBackInIframe = async () => { if (iframeRef.current && iframeRef.current.contentWindow && history?.currentIndex > 0) { diff --git a/src/components/Apps/useQortalMessageListener.tsx b/src/components/Apps/useQortalMessageListener.tsx index 4cb08fd..2343a2e 100644 --- a/src/components/Apps/useQortalMessageListener.tsx +++ b/src/components/Apps/useQortalMessageListener.tsx @@ -657,7 +657,7 @@ isDOMContentLoaded: false if (UIQortalRequests.includes(event.data.action)) { sendMessageToRuntime( { action: event.data.action, type: 'qortalRequest', payload: event.data, isExtension: true, appInfo: { - name: appName, service: appService + name: appName, service: appService, tabId }, skipAuth }, event.ports[0] ); @@ -907,7 +907,7 @@ isDOMContentLoaded: false }; - }, [appName, appService]); // Empty dependency array to run once when the component mounts + }, [appName, appService, tabId]); // Empty dependency array to run once when the component mounts useEffect(() => { const listener = (message, sender, sendResponse) => { diff --git a/src/qdn/publish/pubish.ts b/src/qdn/publish/pubish.ts index 91dfbd6..10e7814 100644 --- a/src/qdn/publish/pubish.ts +++ b/src/qdn/publish/pubish.ts @@ -6,6 +6,7 @@ import nacl from '../../deps/nacl-fast'; import utils from '../../utils/utils'; import { createEndpoint, getBaseApi, getKeyPair } from '../../background'; import { sendDataChunksToCore } from '../../qortalRequests/get'; +import { executeEvent } from '../../utils/events'; export async function reusableGet(endpoint) { const validApi = await getBaseApi(); @@ -91,7 +92,8 @@ export const publishData = async ({ tag4, tag5, feeAmount, - sender + sender, + appInfo, }: any) => { const validateName = async (receiverName: string) => { return await reusableGet(`/names/${receiverName}`); @@ -193,7 +195,17 @@ export const publishData = async ({ } else { myResponse = response; } - + if (appInfo?.tabId) { + executeEvent('receiveChunks', { + tabId: appInfo.tabId, + publishLocation: { + name: registeredName, + identifier, + service, + }, + processed: true, + }); + } return myResponse; }; @@ -306,6 +318,19 @@ export const publishData = async ({ uploadDataUrl = uploadDataUrl + urlSuffix; } uploadDataUrl = uploadDataUrl + paramQueries; + if (appInfo?.tabId) { + executeEvent('receiveChunks', { + tabId: appInfo.tabId, + publishLocation: { + name: registeredName, + identifier, + service, + }, + chunksSubmitted: 1, + totalChunks: 1, + processed: false, + }); + } return await reusablePost(uploadDataUrl, postBody); } @@ -327,7 +352,19 @@ export const publishData = async ({ const chunkSize = 5 * 1024 * 1024; // 5MB const totalChunks = Math.ceil(file.size / chunkSize); - + if (appInfo?.tabId) { + executeEvent('receiveChunks', { + tabId: appInfo.tabId, + publishLocation: { + name: registeredName, + identifier, + service, + }, + chunksSubmitted: 0, + totalChunks, + processed: false, + }); + } for (let index = 0; index < totalChunks; index++) { const start = index * chunkSize; const end = Math.min(start + chunkSize, file.size); @@ -337,6 +374,18 @@ export const publishData = async ({ formData.append('index', index); await uploadChunkWithRetry(chunkUrl, formData, index); + if (appInfo?.tabId) { + executeEvent('receiveChunks', { + tabId: appInfo.tabId, + publishLocation: { + name: registeredName, + identifier, + service, + }, + chunksSubmitted: index + 1, + totalChunks, + }); + } } } diff --git a/src/qortalRequests.ts b/src/qortalRequests.ts index 0ef92d1..1724daf 100644 --- a/src/qortalRequests.ts +++ b/src/qortalRequests.ts @@ -258,7 +258,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { case "PUBLISH_MULTIPLE_QDN_RESOURCES": { const data = request.payload; - publishMultipleQDNResources(data, sender, isFromExtension) + publishMultipleQDNResources(data, sender, isFromExtension, appInfo) .then((res) => { sendResponse(res); }) diff --git a/src/qortalRequests/get.ts b/src/qortalRequests/get.ts index 6989094..bc06513 100644 --- a/src/qortalRequests/get.ts +++ b/src/qortalRequests/get.ts @@ -1074,7 +1074,7 @@ export const checkArrrSyncStatus = async (seed) => { }; -export const publishMultipleQDNResources = async (data: any, sender, isFromExtension) => { +export const publishMultipleQDNResources = async (data: any, sender, isFromExtension, appInfo) => { const requiredFields = ["resources"]; const missingFields: string[] = []; let feeAmount = null; @@ -1340,7 +1340,8 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten tag5, apiVersion: 2, withFee: true, - sender + sender, + appInfo }, ], true); await new Promise((res) => { @@ -4261,6 +4262,7 @@ export const inviteToGroupRequest = async (data, isFromExtension) => { const groupId = data.groupId const qortalAddress = data?.inviteeAddress const inviteTime = data?.inviteTime + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4291,6 +4293,7 @@ export const inviteToGroupRequest = async (data, isFromExtension) => { groupId, qortalAddress, inviteTime, + txGroupId }) return response @@ -4315,6 +4318,7 @@ export const kickFromGroupRequest = async (data, isFromExtension) => { const groupId = data.groupId const qortalAddress = data?.qortalAddress const reason = data?.reason + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4344,7 +4348,8 @@ export const kickFromGroupRequest = async (data, isFromExtension) => { const response = await kickFromGroup({ groupId, qortalAddress, - rBanReason: reason + rBanReason: reason, + txGroupId }) return response @@ -4370,6 +4375,8 @@ export const banFromGroupRequest = async (data, isFromExtension) => { const qortalAddress = data?.qortalAddress const rBanTime = data?.banTime const reason = data?.reason + const txGroupId = data?.txGroupId || 0; + let groupInfo = null; try { const url = await createEndpoint(`/groups/${groupId}`); @@ -4399,7 +4406,8 @@ export const banFromGroupRequest = async (data, isFromExtension) => { groupId, qortalAddress, rBanTime, - rBanReason: reason + rBanReason: reason, + txGroupId }) return response @@ -4423,6 +4431,7 @@ export const cancelGroupBanRequest = async (data, isFromExtension) => { } const groupId = data.groupId const qortalAddress = data?.qortalAddress + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4452,6 +4461,7 @@ export const cancelGroupBanRequest = async (data, isFromExtension) => { const response = await cancelBan({ groupId, qortalAddress, + txGroupId }) return response @@ -4475,6 +4485,7 @@ export const addGroupAdminRequest = async (data, isFromExtension) => { } const groupId = data.groupId const qortalAddress = data?.qortalAddress + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4504,6 +4515,7 @@ export const addGroupAdminRequest = async (data, isFromExtension) => { const response = await makeAdmin({ groupId, qortalAddress, + txGroupId }) return response @@ -4527,6 +4539,7 @@ export const removeGroupAdminRequest = async (data, isFromExtension) => { } const groupId = data.groupId const qortalAddress = data?.qortalAddress + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4556,6 +4569,7 @@ export const removeGroupAdminRequest = async (data, isFromExtension) => { const response = await removeAdmin({ groupId, qortalAddress, + txGroupId }) return response @@ -4579,6 +4593,7 @@ export const cancelGroupInviteRequest = async (data, isFromExtension) => { } const groupId = data.groupId const qortalAddress = data?.qortalAddress + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4608,6 +4623,7 @@ export const cancelGroupInviteRequest = async (data, isFromExtension) => { const response = await cancelInvitationToGroup({ groupId, qortalAddress, + txGroupId }) return response @@ -4922,6 +4938,7 @@ export const updateGroupRequest = async (data, isFromExtension) => { const approvalThreshold = +data?.approvalThreshold const minBlock = +data?.minBlock const maxBlock = +data.maxBlock + const txGroupId = data?.txGroupId || 0; let groupInfo = null; try { @@ -4957,7 +4974,8 @@ export const updateGroupRequest = async (data, isFromExtension) => { newDescription: description, newApprovalThreshold: approvalThreshold, newMinimumBlockDelay: minBlock, - newMaximumBlockDelay: maxBlock + newMaximumBlockDelay: maxBlock, + txGroupId }) return response