fixes to publish and status

This commit is contained in:
PhilReact 2025-06-21 06:21:07 +03:00
parent 9e5c39fede
commit 07620054ca
7 changed files with 191 additions and 46 deletions

View File

@ -826,6 +826,11 @@ function App() {
executeEvent("openThreadNewPost", {
data: message.payload.data,
});
} else if (
message.action === "receiveChunks" &&
isMainWindow
) {
executeEvent('receiveChunks', message.payload?.data);
}
// Call the permission request handler for "QORTAL_REQUEST_PERMISSION"

View File

@ -102,12 +102,15 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i
const receiveChunksFunc = useCallback(
(e) => {
console.log('eee', 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;
const retry = e.detail?.retry;
const filename = e.detail?.filename;
try {
if (publishLocation === undefined || publishLocation === null) return;
const dataToBeSent = {};
@ -117,8 +120,15 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i
if (totalChunks !== undefined && totalChunks !== null) {
dataToBeSent.totalChunks = totalChunks;
}
const targetOrigin = new URL(iframe.src).origin;
iframe.contentWindow?.postMessage(
if (retry !== undefined && retry !== null) {
dataToBeSent.retry = retry;
}
if (filename !== undefined && filename !== null) {
dataToBeSent.filename = filename;
}
const targetOrigin = iframeRef.current ? new URL(iframeRef.current.src).origin : "*";
console.log('targetOrigin', targetOrigin)
iframeRef.current?.contentWindow?.postMessage(
{
action: 'PUBLISH_STATUS',
publishLocation,
@ -128,6 +138,7 @@ export const AppViewer = React.forwardRef(({ app , hide, isDevMode, skipAuth}, i
},
targetOrigin
);
} catch (err) {
console.error('Failed to send status to iframe:', err);
}

View File

@ -6,6 +6,7 @@ import { navigationControllerAtom } from '../../atoms/global';
import { extractComponents } from '../Chat/MessageDisplay';
import { isRunningGateway } from '../../qortalRequests';
import { MAX_SIZE_PUBLIC_NODE, MAX_SIZE_PUBLISH } from '../../constants/constants';
import { createEndpoint } from '../../background';
@ -303,14 +304,26 @@ async function handleGetFileFromIndexedDB(fileId, sendResponse) {
}
}
async function handleSendDataChunksToCore(fileId, chunkUrl, sendResponse){
async function handleSendDataChunksToCore(fileId, chunkUrl, sendResponse, appInfo, resourceInfo){
try {
if(!fileReferences[fileId]) throw new Error('No file reference found')
const chunkSize = 5 * 1024 * 1024; // 5MB
const file = fileReferences[fileId]
const totalChunks = Math.ceil(file.size / chunkSize);
executeEvent('receiveChunks', {
tabId: appInfo.tabId,
publishLocation: {
name: resourceInfo?.name,
identifier: resourceInfo?.identifier,
service: resourceInfo?.service,
},
chunksSubmitted: 0,
totalChunks,
processed: false,
filename:
resourceInfo?.filename
})
for (let index = 0; index < totalChunks; index++) {
const start = index * chunkSize;
const end = Math.min(start + chunkSize, file.size);
@ -321,6 +334,16 @@ async function handleGetFileFromIndexedDB(fileId, sendResponse) {
formData.append('index', index);
await uploadChunkWithRetry(chunkUrl, formData, index);
executeEvent('receiveChunks', {
tabId: appInfo.tabId,
publishLocation: {
name: resourceInfo?.name,
identifier: resourceInfo?.identifier,
service: resourceInfo?.service,
},
chunksSubmitted: index + 1,
totalChunks,
})
}
sendResponse({ result: true });
} catch (error) {
@ -678,7 +701,9 @@ isDOMContentLoaded: false
}
if (data) {
sendMessageToRuntime(
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true },
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true, appInfo: {
name: appName, service: appService, tabId
} },
event.ports[0]
);
} else {
@ -709,7 +734,9 @@ isDOMContentLoaded: false
}
if (data) {
sendMessageToRuntime(
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true },
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true, appInfo: {
name: appName, service: appService, tabId
} },
event.ports[0]
);
} else {
@ -761,6 +788,22 @@ isDOMContentLoaded: false
);
}
}
const totalFileSize = resources.reduce((acc, resource) => {
const file = resource?.file;
if (file && file?.size && !isNaN(file?.size)) {
return acc + file.size;
}
return acc;
}, 0);
if (totalFileSize > 0) {
const urlCheck = `/arbitrary/check/tmp?totalSize=${totalFileSize}`;
const checkEndpoint = await createEndpoint(urlCheck);
const checkRes = await fetch(checkEndpoint);
if (!checkRes.ok) {
throw new Error('Not enough space on your hard drive');
}
}
const hasOversizedFile = resources.some((resource) => {
const file = resource?.file;
@ -793,7 +836,9 @@ isDOMContentLoaded: false
}
sendMessageToRuntime(
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true },
{ action: event.data.action, type: 'qortalRequest', payload: data, isExtension: true , appInfo: {
name: appName, service: appService, tabId
}},
event.ports[0]
);
} else if(event?.data?.action === 'LINK_TO_QDN_RESOURCE' ||
@ -917,7 +962,8 @@ isDOMContentLoaded: false
handleGetFileFromIndexedDB(message.fileId, sendResponse);
return true; // Keep channel open for async
} else if (message.action === 'sendDataChunksToCore') {
handleSendDataChunksToCore(message.fileId, message.chunkUrl, sendResponse);
console.log('message', message)
handleSendDataChunksToCore(message.fileId, message.chunkUrl, sendResponse, message?.appInfo, message?.resourceInfo);
return true; // Keep channel open for async
} else if (message.action === 'getFileBase64') {
handleGetFileBase64(message.fileId, sendResponse);

View File

@ -702,7 +702,7 @@ const sendMessage = async ()=> {
}
);
});
if (res !== true) throw new Error('Unable to publish images');
if (res?.error) throw new Error('Unable to publish images');
}
const images =

View File

@ -26,6 +26,10 @@ async function reusablePost(endpoint, _body) {
},
body: _body,
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(errorText);
}
let data;
try {
data = await response.clone().json();
@ -73,7 +77,48 @@ async function uploadChunkWithRetry(endpoint, formData, index, maxRetries = 3) {
}
}
async function resuablePostRetry(
endpoint,
body,
maxRetries = 3,
appInfo,
resourceInfo
) {
let attempt = 0;
while (attempt < maxRetries) {
try {
const response = await reusablePost(endpoint, body);
return response;
} catch (err) {
attempt++;
if (attempt >= maxRetries) {
throw new Error(
err instanceof Error
? err?.message || `Failed to make request`
: `Failed to make request`
);
}
if (appInfo?.tabId && resourceInfo) {
chrome.runtime.sendMessage({
action: "receiveChunks",
payload: { data: {
tabId: appInfo.tabId,
publishLocation: {
name: resourceInfo?.name,
identifier: resourceInfo?.identifier,
service: resourceInfo?.service,
},
retry: true,
} },
});
}
// Wait 10 seconds before next retry
await new Promise((res) => setTimeout(res, 25_000));
}
}
}
export const publishData = async ({
registeredName,
@ -100,7 +145,13 @@ export const publishData = async ({
};
const convertBytesForSigning = async (transactionBytesBase58: string) => {
return await reusablePost('/transactions/convert', transactionBytesBase58);
return await resuablePostRetry(
'/transactions/convert',
transactionBytesBase58,
3,
appInfo,
{ identifier, name: registeredName, service }
);
};
const getArbitraryFee = async () => {
@ -157,9 +208,12 @@ export const publishData = async ({
};
const processTransactionVersion2 = async (bytes) => {
return await reusablePost(
return await resuablePostRetry(
'/transactions/process?apiVersion=2',
Base58.encode(bytes)
Base58.encode(bytes),
3,
appInfo,
{ identifier, name: registeredName, service }
);
};
@ -196,7 +250,10 @@ export const publishData = async ({
myResponse = response;
}
if (appInfo?.tabId) {
executeEvent('receiveChunks', {
chrome.runtime.sendMessage({
action: "receiveChunks",
payload: { data: {
tabId: appInfo.tabId,
publishLocation: {
name: registeredName,
@ -204,6 +261,7 @@ export const publishData = async ({
service,
},
processed: true,
} },
});
}
return myResponse;
@ -319,7 +377,10 @@ export const publishData = async ({
}
uploadDataUrl = uploadDataUrl + paramQueries;
if (appInfo?.tabId) {
executeEvent('receiveChunks', {
chrome.runtime.sendMessage({
action: "receiveChunks",
payload: { data: {
tabId: appInfo.tabId,
publishLocation: {
name: registeredName,
@ -329,9 +390,14 @@ export const publishData = async ({
chunksSubmitted: 1,
totalChunks: 1,
processed: false,
} },
});
}
return await reusablePost(uploadDataUrl, postBody);
return await resuablePostRetry(uploadDataUrl, postBody, 3, appInfo, {
identifier,
name: registeredName,
service,
});
}
const file = data;
@ -346,14 +412,22 @@ export const publishData = async ({
const chunkUrl = uploadDataUrl + `/chunk`;
const createdChunkUrl = await createEndpoint(chunkUrl)
if(sender){
await sendDataChunksToCore(file, createdChunkUrl, sender)
await sendDataChunksToCore(file, createdChunkUrl, sender, appInfo, {
name: registeredName,
identifier,
service,
filename: file?.name || filename || title || `${service}-${identifier || ''}`
})
} else {
const chunkSize = 5 * 1024 * 1024; // 5MB
const totalChunks = Math.ceil(file.size / chunkSize);
if (appInfo?.tabId) {
executeEvent('receiveChunks', {
chrome.runtime.sendMessage({
action: "receiveChunks",
payload: { data: {
tabId: appInfo.tabId,
publishLocation: {
name: registeredName,
@ -363,6 +437,9 @@ export const publishData = async ({
chunksSubmitted: 0,
totalChunks,
processed: false,
filename:
file?.name || filename || title || `${service}-${identifier || ''}`,
} },
});
}
for (let index = 0; index < totalChunks; index++) {
@ -375,7 +452,10 @@ export const publishData = async ({
await uploadChunkWithRetry(chunkUrl, formData, index);
if (appInfo?.tabId) {
executeEvent('receiveChunks', {
chrome.runtime.sendMessage({
action: "receiveChunks",
payload: { data: {
tabId: appInfo.tabId,
publishLocation: {
name: registeredName,
@ -384,6 +464,7 @@ export const publishData = async ({
},
chunksSubmitted: index + 1,
totalChunks,
} },
});
}
}
@ -398,7 +479,7 @@ export const publishData = async ({
headers: {},
});
if (!response.ok) {
if (!response?.ok) {
const errorText = await response.text();
throw new Error(`Finalize failed: ${errorText}`);
}

View File

@ -947,7 +947,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
case "GET_PRIMARY_NAME": {
const data = request.payload;
getNameInfoForOthers(data)
getNameInfoForOthers(data?.address)
.then((res) => {
const resData = res ? res : "";
sendResponse(resData);

View File

@ -425,11 +425,11 @@ function getFileFromContentScript(fileId, sender) {
});
}
export function sendDataChunksToCore(fileId, chunkUrl, sender) {
export function sendDataChunksToCore(fileId, chunkUrl, sender, appInfo, resourceInfo) {
return new Promise((resolve, reject) => {
chrome.tabs.sendMessage(
sender.tab.id,
{ action: "sendDataChunksToCore", fileId: fileId, chunkUrl },
{ action: "sendDataChunksToCore", fileId: fileId, chunkUrl, appInfo, resourceInfo },
(response) => {
if (response && response.result) {
resolve(response.result);
@ -1220,6 +1220,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten
throw new Error("User declined request");
}
let failedPublishesIdentifiers = [];
const publishedResponses = [];
for (const resource of resources) {
try {
const requiredFields = ["service"];
@ -1322,28 +1323,29 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten
(resource?.base64 || resource?.data64 || resourceEncrypt)
? 'base64'
: 'file';
await retryTransaction(publishData, [
{
registeredName: encodeURIComponent(name),
data: rawData,
service: service,
identifier: encodeURIComponent(identifier),
uploadType: dataType,
filename: filename,
title,
description,
const response = await publishData({
apiVersion: 2,
category,
data: rawData,
description,
filename: filename,
identifier: encodeURIComponent(identifier),
registeredName: encodeURIComponent(resource?.name || name),
service: service,
tag1,
tag2,
tag3,
tag4,
tag5,
apiVersion: 2,
withFee: true,
title,
sender,
appInfo
},
], true);
uploadType: dataType,
withFee: true,
appInfo,
});
if (response?.signature) {
publishedResponses.push(response);
}
await new Promise((res) => {
setTimeout(() => {
res();
@ -1382,7 +1384,7 @@ export const publishMultipleQDNResources = async (data: any, sender, isFromExten
receiver: appFeeRecipient
}, true)
}
return true;
return publishedResponses;
};
export const voteOnPoll = async (data, isFromExtension) => {