changed logic for file save qortalrequest

This commit is contained in:
PhilReact 2024-10-31 11:41:28 +02:00
parent 72281c7fad
commit d57ab6e9d3
5 changed files with 199 additions and 60 deletions

View File

@ -716,10 +716,8 @@ function App() {
message?.isFromExtension
) {
qortalRequestPermissonFromExtension(message, event);
} else if(message?.action === 'SHOW_SAVE_FILE_PICKER'){
showSaveFilePicker(message?.payload)
} else if(message?.action === 'getFileFromIndexedDB'){
}
else if(message?.action === 'getFileFromIndexedDB'){
handleGetFileFromIndexedDB(event);
}
};
@ -1521,7 +1519,11 @@ function App() {
show,
message,
rootHeight,
showInfo
showInfo,
openSnackGlobal: openSnack,
setOpenSnackGlobal: setOpenSnack,
infoSnackCustom: infoSnack,
setInfoSnackCustom: setInfoSnack
}}
>
<Box

View File

@ -1,19 +1,60 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { executeEvent } from '../../utils/events';
import { useSetRecoilState } from 'recoil';
import { navigationControllerAtom } from '../../atoms/global';
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
import { Browser } from '@capacitor/browser';
import { saveFile } from '../../qortalRequests/get';
import { mimeToExtensionMap } from '../../utils/memeTypes';
import { MyContext } from '../../App';
export const saveFileInChunks = async (blob: Blob, fileName: string, chunkSize = 1024 * 1024) => {
const base64Prefix = 'data:video/mp4;base64,';
export const saveFileInChunks = async (
blob: Blob,
fileName: string,
chunkSize = 1024 * 1024
) => {
try {
let offset = 0;
let isFirstChunk = true;
const fullFileName = fileName + Date.now() + '.mp4'
// Extract the MIME type from the blob
const mimeType = blob.type || 'application/octet-stream';
// Create the dynamic base64 prefix
const base64Prefix = `data:${mimeType};base64,`;
// Function to extract extension from fileName
const getExtensionFromFileName = (name: string): string => {
const lastDotIndex = name.lastIndexOf('.');
if (lastDotIndex !== -1) {
return name.substring(lastDotIndex); // includes the dot
}
return '';
};
// Extract existing extension from fileName
const existingExtension = getExtensionFromFileName(fileName);
// Remove existing extension from fileName to avoid duplication
if (existingExtension) {
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
}
// Map MIME type to file extension
const mimeTypeToExtension = (mimeType: string): string => {
return mimeToExtensionMap[mimeType] || existingExtension || ''; // Use existing extension if MIME type not found
};
// Determine the final extension to use
const extension = mimeTypeToExtension(mimeType);
// Construct the full file name with timestamp and extension
const fullFileName = `${fileName}_${Date.now()}${extension}`;
// Read the blob in chunks
while (offset < blob.size) {
// Extract the current chunk
@ -28,7 +69,7 @@ export const saveFileInChunks = async (blob: Blob, fileName: string, chunkSize =
data: isFirstChunk ? base64Prefix + base64Chunk : base64Chunk,
directory: Directory.Documents,
recursive: true,
append: !isFirstChunk // Append after the first chunk
append: !isFirstChunk, // Append after the first chunk
});
// Update offset and flag
@ -36,13 +77,14 @@ export const saveFileInChunks = async (blob: Blob, fileName: string, chunkSize =
isFirstChunk = false;
}
console.log("File saved successfully in chunks:", fileName);
console.log('File saved successfully in chunks:', fullFileName);
} catch (error) {
console.error("Error saving file in chunks:", error);
console.error('Error saving file in chunks:', error);
}
};
// Helper function to convert a Blob to a Base64 string
const blobToBase64 = (blob: Blob): Promise<string> => {
return new Promise((resolve, reject) => {
@ -220,19 +262,42 @@ const UIQortalRequests = [
export const showSaveFilePicker = async (data) => {
let blob;
let fileName;
export const showSaveFilePicker = async (data, {openSnackGlobal,
setOpenSnackGlobal,
infoSnackCustom,
setInfoSnackCustom}) => {
try {
const { filename, mimeType, fileId } = data;
const { filename, mimeType, blob } = data;
// Retrieve file from IndexedDB or any other source
blob = await retrieveFileFromIndexedDB(fileId);
fileName = filename;
setInfoSnackCustom({
type: "info",
message:
"Saving file...",
});
setOpenSnackGlobal(true);
await saveFileInChunks(blob, filename)
setInfoSnackCustom({
type: "success",
message:
"Saving file success!",
});
await saveFileInChunks(blob, fileName)
setOpenSnackGlobal(true);
} catch (error) {
setInfoSnackCustom({
type: "error",
message:
error?.message ? `Error saving file: ${error?.message}` : 'Error saving file',
});
setOpenSnackGlobal(true);
console.error("Error saving file:", error);
}
@ -323,6 +388,10 @@ currentIndex: -1,
isDOMContentLoaded: false
})
const setHasSettingsChangedAtom = useSetRecoilState(navigationControllerAtom);
const { openSnackGlobal,
setOpenSnackGlobal,
infoSnackCustom,
setInfoSnackCustom } = useContext(MyContext);
useEffect(()=> {
@ -391,10 +460,23 @@ isDOMContentLoaded: false
{ action: event.data.action, type: 'qortalRequest', payload: event.data, isExtension: true },
event.ports[0]
);
} else if(event?.data?.action === 'SAVE_FILE'
){
try {
const res = await saveFile( event.data, null, true, {
openSnackGlobal,
setOpenSnackGlobal,
infoSnackCustom,
setInfoSnackCustom
});
} catch (error) {
}
} else if (
event?.data?.action === 'PUBLISH_MULTIPLE_QDN_RESOURCES' ||
event?.data?.action === 'PUBLISH_QDN_RESOURCE' ||
event?.data?.action === 'ENCRYPT_DATA' || event?.data?.action === 'SAVE_FILE'
event?.data?.action === 'ENCRYPT_DATA'
) {
let data;

View File

@ -303,25 +303,7 @@ function setLocalStorage(key, data) {
break;
}
case "SAVE_FILE": {
try {
const res = await saveFile(request.payload, event.source, isFromExtension);
event.source.postMessage({
requestId: request.requestId,
action: request.action,
payload: res,
type: "backgroundMessageResponse",
}, event.origin);
} catch (error) {
event.source.postMessage({
requestId: request.requestId,
action: request.action,
error: error.message,
type: "backgroundMessageResponse",
}, event.origin);
}
break;
}
case "DEPLOY_AT": {
try {

View File

@ -15,6 +15,7 @@ import {
isUsingLocal
} from "../background";
import { getNameInfo } from "../backgroundFunctions/encryption";
import { showSaveFilePicker } from "../components/Apps/useQortalMessageListener";
import { QORT_DECIMALS } from "../constants/constants";
import Base58 from "../deps/Base58";
import {
@ -223,12 +224,12 @@ function getFileFromContentScript(fileId) {
}
function sendToSaveFilePicker(data) {
window.postMessage({
action: "SHOW_SAVE_FILE_PICKER",
payload: data,
}, "*");
}
// function sendToSaveFilePicker(data) {
// window.postMessage({
// action: "SHOW_SAVE_FILE_PICKER",
// payload: data,
// }, "*");
// }
const responseResolvers = new Map();
@ -1149,9 +1150,9 @@ export const joinGroup = async (data, isFromExtension) => {
}
};
export const saveFile = async (data, sender, isFromExtension) => {
export const saveFile = async (data, sender, isFromExtension, snackMethods) => {
try {
const requiredFields = ["filename", "fileId"];
const requiredFields = ['filename', 'blob']
const missingFields: string[] = [];
requiredFields.forEach((field) => {
if (!data[field]) {
@ -1194,15 +1195,20 @@ export const saveFile = async (data, sender, isFromExtension) => {
},
};
}
sendToSaveFilePicker(
{
filename,
mimeType,
blob,
fileId,
fileHandleOptions,
}
);
showSaveFilePicker( {
filename,
mimeType,
blob
}, snackMethods)
// sendToSaveFilePicker(
// {
// filename,
// mimeType,
// blob,
// fileId
// }
// );
return true;
} else {
throw new Error("User declined to save file");

View File

@ -12,10 +12,13 @@ export const mimeToExtensionMap = {
"application/vnd.oasis.opendocument.presentation": ".odp",
"text/plain": ".txt",
"text/csv": ".csv",
"text/html": ".html",
"application/xhtml+xml": ".xhtml",
"application/xml": ".xml",
"application/json": ".json",
"application/rtf": ".rtf",
"application/vnd.apple.pages": ".pages",
"application/vnd.google-apps.document": ".gdoc",
"application/vnd.google-apps.spreadsheet": ".gsheet",
"application/vnd.google-apps.presentation": ".gslides",
// Images
"image/jpeg": ".jpg",
@ -25,6 +28,11 @@ export const mimeToExtensionMap = {
"image/svg+xml": ".svg",
"image/tiff": ".tif",
"image/bmp": ".bmp",
"image/x-icon": ".ico",
"image/heic": ".heic",
"image/heif": ".heif",
"image/apng": ".apng",
"image/avif": ".avif",
// Audio
"audio/mpeg": ".mp3",
@ -32,6 +40,11 @@ export const mimeToExtensionMap = {
"audio/wav": ".wav",
"audio/webm": ".weba",
"audio/aac": ".aac",
"audio/flac": ".flac",
"audio/x-m4a": ".m4a",
"audio/x-ms-wma": ".wma",
"audio/midi": ".midi",
"audio/x-midi": ".mid",
// Video
"video/mp4": ".mp4",
@ -45,6 +58,7 @@ export const mimeToExtensionMap = {
"video/3gpp2": ".3g2",
"video/x-matroska": ".mkv",
"video/x-flv": ".flv",
"video/x-ms-asf": ".asf",
// Archives
"application/zip": ".zip",
@ -53,4 +67,57 @@ export const mimeToExtensionMap = {
"application/x-7z-compressed": ".7z",
"application/x-gzip": ".gz",
"application/x-bzip2": ".bz2",
}
"application/x-apple-diskimage": ".dmg",
"application/vnd.android.package-archive": ".apk",
"application/x-iso9660-image": ".iso",
// Code Files
"text/javascript": ".js",
"text/css": ".css",
"text/html": ".html",
"application/json": ".json",
"text/xml": ".xml",
"application/x-sh": ".sh",
"application/x-csh": ".csh",
"text/x-python": ".py",
"text/x-java-source": ".java",
"application/java-archive": ".jar",
"application/vnd.microsoft.portable-executable": ".exe",
"application/x-msdownload": ".msi",
"text/x-c": ".c",
"text/x-c++": ".cpp",
"text/x-go": ".go",
"application/x-perl": ".pl",
"text/x-php": ".php",
"text/x-ruby": ".rb",
"text/x-sql": ".sql",
"application/x-httpd-php": ".php",
"application/x-python-code": ".pyc",
// ROM Files
"application/x-nintendo-nes-rom": ".nes",
"application/x-snes-rom": ".smc",
"application/x-gameboy-rom": ".gb",
"application/x-gameboy-advance-rom": ".gba",
"application/x-n64-rom": ".n64",
"application/x-sega-genesis-rom": ".gen",
"application/x-sega-master-system-rom": ".sms",
"application/x-psx-rom": ".iso", // PlayStation ROMs
"application/x-bios-rom": ".rom",
"application/x-flash-rom": ".bin",
"application/x-eeprom": ".eep",
"application/x-c64-rom": ".prg",
// Miscellaneous
"application/octet-stream": ".bin", // General binary files
"application/x-shockwave-flash": ".swf",
"application/x-silverlight-app": ".xap",
"application/x-ms-shortcut": ".lnk",
"application/vnd.ms-fontobject": ".eot",
"font/woff": ".woff",
"font/woff2": ".woff2",
"font/ttf": ".ttf",
"font/otf": ".otf",
"application/vnd.visio": ".vsd",
"application/vnd.ms-project": ".mpp",
};