save file qortalrequest

This commit is contained in:
PhilReact 2024-10-16 02:34:10 +03:00
parent 638c673845
commit 12013947af
4 changed files with 196 additions and 10 deletions

View File

@ -551,7 +551,32 @@ const testAsync = async (sendResponse)=> {
sendResponse({ result: null, error: "Testing" });
}
const showSaveFilePicker = async (data) => {
try {
const {filename, mimeType, fileHandleOptions, fileId} = data
const blob = await retrieveFileFromIndexedDB(fileId)
const fileHandle = await window.showSaveFilePicker({
suggestedName: filename,
types: [
{
description: mimeType,
...fileHandleOptions
}
]
})
const writeFile = async (fileHandle, contents) => {
const writable = await fileHandle.createWritable()
await writable.write(contents)
await writable.close()
}
writeFile(fileHandle, blob).then(() => console.log("FILE SAVED"))
} catch (error) {
FileSaver.saveAs(blob, filename)
}
}
chrome.runtime?.onMessage.addListener( function (message, sender, sendResponse) {
console.log('message', message)
if (message.type === "LOGOUT") {
// Notify the web page
window.postMessage(
@ -571,6 +596,8 @@ chrome.runtime?.onMessage.addListener( function (message, sender, sendResponse)
},
"*"
);
} else if(message.action === "SHOW_SAVE_FILE_PICKER"){
showSaveFilePicker(message?.data)
}
else if (message.action === "getFileFromIndexedDB") {
@ -696,9 +723,27 @@ async function storeFilesInIndexedDB(obj) {
obj.fileId = fileId;
delete obj.file;
}
if (obj.blob instanceof Blob) {
const fileId = "objFile_qortalfile";
// Store the file in IndexedDB
const fileData = {
id: fileId,
data: obj.blob,
};
objectStore.put(fileData);
// Replace the file object with the file ID in the original object
let blobObj = {
type: obj.blob?.type
}
obj.fileId = fileId;
delete obj.blob;
obj.blob = blobObj
}
// Iterate through resources to find files and save them to IndexedDB
for (let resource of obj.resources) {
for (let resource of (obj?.resources || [])) {
if (resource.file instanceof File) {
const fileId = resource.identifier + "_qortalfile";
@ -729,7 +774,7 @@ async function storeFilesInIndexedDB(obj) {
const UIQortalRequests = ['GET_USER_ACCOUNT', 'ENCRYPT_DATA', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', 'ADD_LIST_ITEMS', 'DELETE_LIST_ITEM', 'VOTE_ON_POLL', 'CREATE_POLL', 'SEND_CHAT_MESSAGE', 'JOIN_GROUP']
const UIQortalRequests = ['GET_USER_ACCOUNT', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', 'ADD_LIST_ITEMS', 'DELETE_LIST_ITEM', 'VOTE_ON_POLL', 'CREATE_POLL', 'SEND_CHAT_MESSAGE', 'JOIN_GROUP']
if (!window.hasAddedQortalListener) {
console.log("Listener added");
@ -768,7 +813,7 @@ if (!window.hasAddedQortalListener) {
{ action: event.data.action, type: 'qortalRequest', payload: event.data },
event.ports[0]
);
} else if (event?.data?.action === 'PUBLISH_MULTIPLE_QDN_RESOURCES' || event?.data?.action === 'PUBLISH_QDN_RESOURCE') {
} 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') {
let data;
try {
data = await storeFilesInIndexedDB(event.data);

View File

@ -1,4 +1,4 @@
import { addListItems, createPoll, decryptData, deleteListItems, encryptData, getListItems, getUserAccount, joinGroup, publishMultipleQDNResources, publishQDNResource, sendChatMessage, sendCoin, voteOnPoll } from "./qortalRequests/get";
import { addListItems, createPoll, decryptData, deleteListItems, encryptData, getListItems, getUserAccount, joinGroup, publishMultipleQDNResources, publishQDNResource, saveFile, sendChatMessage, sendCoin, voteOnPoll } from "./qortalRequests/get";
@ -78,7 +78,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
case "ENCRYPT_DATA": {
const data = request.payload;
encryptData(data)
encryptData(data, sender)
.then((res) => {
sendResponse(res);
})
@ -207,7 +207,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
}
case "JOIN_GROUP": {
const data = request.payload;
console.log('data', data)
joinGroup(data)
.then((res) => {
sendResponse(res);
@ -218,6 +218,19 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
break;
}
case "SAVE_FILE": {
const data = request.payload;
saveFile(data, sender)
.then((res) => {
sendResponse(res);
})
.catch((error) => {
sendResponse({ error: error.message });
});
break;
}
case "SEND_COIN": {
const data = request.payload;
const requiredFields = ["coin", "destinationAddress", "amount"];

View File

@ -25,6 +25,7 @@ import { publishData } from "../qdn/publish/pubish";
import { getPermission, setPermission } from "../qortalRequests";
import { createTransaction } from "../transactions/transactions";
import { fileToBase64 } from "../utils/fileReading";
import { mimeToExtensionMap } from "../utils/memeTypes";
const _createPoll = async (pollName, pollDescription, options) => {
const fee = await getFee("CREATE_POLL");
@ -127,6 +128,15 @@ function getFileFromContentScript(fileId, sender) {
);
});
}
function sendToSaveFilePicker(data, sender) {
console.log("sender", sender);
chrome.tabs.sendMessage(
sender.tab.id,
{ action: "SHOW_SAVE_FILE_PICKER", data }
);
}
async function getUserPermission(payload: any) {
function waitForWindowReady(windowId) {
@ -251,11 +261,11 @@ export const getUserAccount = async () => {
}
};
export const encryptData = async (data) => {
export const encryptData = async (data, sender) => {
let data64 = data.data64;
let publicKeys = data.publicKeys || [];
if (data.file) {
data64 = await fileToBase64(data.file);
if (data.fileId) {
data64 = await getFileFromContentScript(data.fileId, sender)
}
if (!data64) {
throw new Error("Please include data to encrypt");
@ -509,7 +519,6 @@ export const publishQDNResource = async (data: any, sender) => {
const tag3 = data.tag3;
const tag4 = data.tag4;
const tag5 = data.tag5;
let feeAmount = null;
if (data.identifier == null) {
identifier = "default";
}
@ -1114,6 +1123,69 @@ export const joinGroup = async (data) => {
};
export const saveFile = async (data, sender) => {
try {
const requiredFields = ['filename', 'fileId']
const missingFields: string[] = []
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field)
}
})
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ')
const errorMsg = `Missing fields: ${missingFieldsString}`
throw new Error(errorMsg)
}
const filename = data.filename
const blob = data.blob
const fileId = data.fileId
const resPermission = await getUserPermission({
text1: "Would you like to download:",
highlightedText: `${filename}`,
});
const { accepted } = resPermission;
if(accepted){
const mimeType = blob.type || data.mimeType
let backupExention = filename.split('.').pop()
if (backupExention) {
backupExention = '.' + backupExention
}
const fileExtension = mimeToExtensionMap[mimeType] || backupExention
let fileHandleOptions = {}
if (!mimeType) {
throw new Error('A mimeType could not be derived')
}
if (!fileExtension) {
const obj = {}
throw new Error('A file extension could not be derived')
}
if (fileExtension && mimeType) {
fileHandleOptions = {
accept: {
[mimeType]: [fileExtension]
}
}
}
sendToSaveFilePicker( {
filename, mimeType, blob, fileId, fileHandleOptions
} ,sender)
return true
} else {
throw new Error("User declined add to list");
}
} catch (error) {
throw new Error(error?.message || 'Failed to initiate download')
}
};
export const sendCoin = async () => {
try {
const wallet = await getSaveWallet();

56
src/utils/memeTypes.ts Normal file
View File

@ -0,0 +1,56 @@
export const mimeToExtensionMap = {
// Documents
"application/pdf": ".pdf",
"application/msword": ".doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
"application/vnd.ms-excel": ".xls",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
"application/vnd.ms-powerpoint": ".ppt",
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
"application/vnd.oasis.opendocument.text": ".odt",
"application/vnd.oasis.opendocument.spreadsheet": ".ods",
"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",
// Images
"image/jpeg": ".jpg",
"image/png": ".png",
"image/gif": ".gif",
"image/webp": ".webp",
"image/svg+xml": ".svg",
"image/tiff": ".tif",
"image/bmp": ".bmp",
// Audio
"audio/mpeg": ".mp3",
"audio/ogg": ".ogg",
"audio/wav": ".wav",
"audio/webm": ".weba",
"audio/aac": ".aac",
// Video
"video/mp4": ".mp4",
"video/webm": ".webm",
"video/ogg": ".ogv",
"video/x-msvideo": ".avi",
"video/quicktime": ".mov",
"video/x-ms-wmv": ".wmv",
"video/mpeg": ".mpeg",
"video/3gpp": ".3gp",
"video/3gpp2": ".3g2",
"video/x-matroska": ".mkv",
"video/x-flv": ".flv",
// Archives
"application/zip": ".zip",
"application/x-rar-compressed": ".rar",
"application/x-tar": ".tar",
"application/x-7z-compressed": ".7z",
"application/x-gzip": ".gz",
"application/x-bzip2": ".bz2",
}