add to list delete get

This commit is contained in:
PhilReact 2024-10-14 20:20:15 +03:00
parent 771d6c16f1
commit 9521978335
4 changed files with 292 additions and 264 deletions

View File

@ -453,22 +453,7 @@ chrome.runtime?.onMessage.addListener(function (message, sender, sendResponse) {
} }
}); });
const lastActionTimestamps = {}; const UIQortalRequests = ['GET_USER_ACCOUNT', 'ENCRYPT_DATA', 'DECRYPT_DATA', 'SEND_COIN', 'GET_LIST_ITEMS', 'ADD_LIST_ITEMS', 'DELETE_LIST_ITEM']
// Function to debounce actions based on message.action
function debounceAction(action, wait = 500) {
const currentTime = Date.now();
// Check if this action has been recently triggered
if (lastActionTimestamps[action] && currentTime - lastActionTimestamps[action] < wait) {
// Ignore this action if it occurred within the debounce time window
return false;
}
// Update the last timestamp for this action
lastActionTimestamps[action] = currentTime;
return true;
}
if (!window.hasAddedQortalListener) { if (!window.hasAddedQortalListener) {
console.log("Listener added"); console.log("Listener added");
@ -480,91 +465,14 @@ if (!window.hasAddedQortalListener) {
event.stopImmediatePropagation(); // Stop other listeners from firing event.stopImmediatePropagation(); // Stop other listeners from firing
// Verify that the message is from the web page and contains expected data // Verify that the message is from the web page and contains expected data
if (event.source !== window || !event.data || !event.data.action) return; if (event.source !== window || !event.data || !event.data.action) return;
// // Check if this action should be processed (debounced)
// if (!debounceAction(event.data.action)) {
// console.log(`Debounced action: ${event.data.action}`);
// return;
// }
if(event?.data?.requestedHandler !== 'UI') return
if (event.data.action === "GET_USER_ACCOUNT") {
chrome?.runtime?.sendMessage(
{ action: "GET_USER_ACCOUNT", type: "qortalRequest" },
(response) => {
if (response.error) {
event.ports[0].postMessage({
result: null,
error: response.error,
});
} else {
event.ports[0].postMessage({
result: response,
error: null,
});
}
}
);
} else if (event.data.action === "SEND_COIN") {
chrome?.runtime?.sendMessage(
{ action: "SEND_COIN", type: "qortalRequest", payload: event.data },
(response) => {
if (response.error) {
event.ports[0].postMessage({
result: null,
error: response.error,
});
} else {
event.ports[0].postMessage({
result: response,
error: null,
});
}
}
);
} else if (event.data.action === "ENCRYPT_DATA") {
chrome?.runtime?.sendMessage(
{ action: "ENCRYPT_DATA", type: "qortalRequest", payload: event.data },
(response) => {
if (response.error) {
event.ports[0].postMessage({
result: null,
error: response.error,
});
} else {
event.ports[0].postMessage({
result: response,
error: null,
});
}
}
);
} else if (event.data.action === "DECRYPT_DATA") {
chrome?.runtime?.sendMessage(
{ action: "DECRYPT_DATA", type: "qortalRequest", payload: event.data },
(response) => {
if (response.error) {
event.ports[0].postMessage({
result: null,
error: response.error,
});
} else {
event.ports[0].postMessage({
result: response,
error: null,
});
}
}
);
} else if (event.data.action === "GET_LIST_ITEMS") {
console.log("message", event);
if(event?.data?.requestedHandler !== 'UI') return
if (UIQortalRequests.includes(event.data.action)) {
chrome?.runtime?.sendMessage( chrome?.runtime?.sendMessage(
{ { action: event.data.action, type: "qortalRequest", payload: event.data },
action: "GET_LIST_ITEMS",
type: "qortalRequest",
payload: event.data,
},
(response) => { (response) => {
console.log("response", response); console.log('response', response)
if (response.error) { if (response.error) {
event.ports[0].postMessage({ event.ports[0].postMessage({
result: null, result: null,
@ -578,7 +486,7 @@ if (!window.hasAddedQortalListener) {
} }
} }
); );
} }
}; };
window.addEventListener("message", listener); window.addEventListener("message", listener);
} }

View File

@ -1816,7 +1816,8 @@ function App() {
<TextP <TextP
sx={{ sx={{
textAlign: "center", textAlign: "center",
lineHeight: "15px", lineHeight: 1.2,
maxWidth: '90%'
}} }}
> >
{messageQortalRequest?.text1} {messageQortalRequest?.text1}
@ -1825,8 +1826,10 @@ function App() {
<TextP <TextP
sx={{ sx={{
textAlign: "center", textAlign: "center",
lineHeight: "15px", lineHeight: 1.2,
fontSize: "10px", fontSize: "16px",
fontWeight: "normal",
maxWidth: '90%'
}} }}
> >
{messageQortalRequest?.text2} {messageQortalRequest?.text2}
@ -1838,6 +1841,7 @@ function App() {
lineHeight: 1.2, lineHeight: 1.2,
fontSize: "16px", fontSize: "16px",
fontWeight: 700, fontWeight: 700,
maxWidth: '90%'
}} }}
> >
{messageQortalRequest?.text3} {messageQortalRequest?.text3}

View File

@ -1,4 +1,4 @@
import { decryptData, encryptData, getListItems, getUserAccount, sendCoin } from "./qortalRequests/get"; import { addListItems, decryptData, deleteListItems, encryptData, getListItems, getUserAccount, sendCoin } from "./qortalRequests/get";
chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
if (request) { if (request) {
@ -53,6 +53,32 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
break; break;
} }
case "ADD_LIST_ITEMS": {
const data = request.payload;
addListItems(data)
.then((res) => {
sendResponse(res);
})
.catch((error) => {
sendResponse({ error: error.message });
});
break;
}
case "DELETE_LIST_ITEM": {
const data = request.payload;
deleteListItems(data)
.then((res) => {
sendResponse(res);
})
.catch((error) => {
sendResponse({ error: error.message });
});
break;
}
case "SEND_COIN": { case "SEND_COIN": {
const data = request.payload; const data = request.payload;
const requiredFields = ["coin", "destinationAddress", "amount"]; const requiredFields = ["coin", "destinationAddress", "amount"];

View File

@ -1,4 +1,9 @@
import { createEndpoint, getKeyPair, getSaveWallet, removeDuplicateWindow } from "../background"; import {
createEndpoint,
getKeyPair,
getSaveWallet,
removeDuplicateWindow,
} from "../background";
import Base58 from "../deps/Base58"; import Base58 from "../deps/Base58";
import { import {
base64ToUint8Array, base64ToUint8Array,
@ -11,121 +16,113 @@ import {
import { fileToBase64 } from "../utils/fileReading"; import { fileToBase64 } from "../utils/fileReading";
async function getUserPermission(payload: any) { async function getUserPermission(payload: any) {
function waitForWindowReady(windowId) {
function waitForWindowReady(windowId) {
return new Promise((resolve) => {
const checkInterval = setInterval(() => {
chrome.windows.get(windowId, (win) => {
if (chrome.runtime.lastError) {
clearInterval(checkInterval); // Stop polling if there's an error
resolve(false);
} else if (win.state === 'normal' || win.state === 'maximized') {
clearInterval(checkInterval); // Window is ready
resolve(true);
}
});
}, 100); // Check every 100ms
});
}
await new Promise((res)=> {
const popupUrl = chrome.runtime.getURL(
"index.html?secondary=true"
);
console.log('popupUrl', popupUrl)
chrome.windows.getAll(
{ populate: true, windowTypes: ["popup"] },
(windows) => {
console.log('windows', windows)
// Attempt to find an existing popup window that has a tab with the correct URL
const existingPopup = windows.find(
(w) =>
w.tabs &&
w.tabs.some(
(tab) => tab.url && tab.url.startsWith(popupUrl)
)
);
if (existingPopup) {
// If the popup exists but is minimized or not focused, focus it
chrome.windows.update(existingPopup.id, {
focused: true,
state: "normal",
});
res(null)
} else {
// No existing popup found, create a new one
chrome.system.display.getInfo((displays) => {
// Assuming the primary display is the first one (adjust logic as needed)
const primaryDisplay = displays[0];
const screenWidth = primaryDisplay.bounds.width;
const windowHeight = 500; // Your window height
const windowWidth = 400; // Your window width
// Calculate left position for the window to appear on the right of the screen
const leftPosition = screenWidth - windowWidth;
// Calculate top position for the window, adjust as desired
const topPosition =
(primaryDisplay.bounds.height - windowHeight) / 2;
chrome.windows.create(
{
url: popupUrl,
type: "popup",
width: windowWidth,
height: windowHeight,
left: leftPosition,
top: 0,
},
async (newWindow) => {
removeDuplicateWindow(popupUrl);
await waitForWindowReady(newWindow.id);
res(null)
}
);
});
}
}
);
})
await new Promise((res)=> {
setTimeout(() => {
chrome.runtime.sendMessage({
action: "SET_COUNTDOWN",
payload: 15,
});
res(true)
}, 450);
})
return new Promise((resolve) => { return new Promise((resolve) => {
// Set a timeout for 1 second const checkInterval = setInterval(() => {
const timeout = setTimeout(() => { chrome.windows.get(windowId, (win) => {
resolve(false); // No response within 10 second, assume not focused if (chrome.runtime.lastError) {
}, 15000); clearInterval(checkInterval); // Stop polling if there's an error
resolve(false);
// Send message to the content script to check focus } else if (win.state === "normal" || win.state === "maximized") {
console.log('send msg') clearInterval(checkInterval); // Window is ready
chrome.runtime.sendMessage({ action: "QORTAL_REQUEST_PERMISSION", payload }, (response) => { resolve(true);
console.log('permission response', response) }
if(response === undefined) return });
}, 100); // Check every 100ms
});
}
await new Promise((res) => {
const popupUrl = chrome.runtime.getURL("index.html?secondary=true");
console.log("popupUrl", popupUrl);
chrome.windows.getAll(
{ populate: true, windowTypes: ["popup"] },
(windows) => {
console.log("windows", windows);
// Attempt to find an existing popup window that has a tab with the correct URL
const existingPopup = windows.find(
(w) =>
w.tabs &&
w.tabs.some((tab) => tab.url && tab.url.startsWith(popupUrl))
);
if (existingPopup) {
// If the popup exists but is minimized or not focused, focus it
chrome.windows.update(existingPopup.id, {
focused: true,
state: "normal",
});
res(null);
} else {
// No existing popup found, create a new one
chrome.system.display.getInfo((displays) => {
// Assuming the primary display is the first one (adjust logic as needed)
const primaryDisplay = displays[0];
const screenWidth = primaryDisplay.bounds.width;
const windowHeight = 500; // Your window height
const windowWidth = 400; // Your window width
// Calculate left position for the window to appear on the right of the screen
const leftPosition = screenWidth - windowWidth;
// Calculate top position for the window, adjust as desired
const topPosition =
(primaryDisplay.bounds.height - windowHeight) / 2;
chrome.windows.create(
{
url: popupUrl,
type: "popup",
width: windowWidth,
height: windowHeight,
left: leftPosition,
top: 0,
},
async (newWindow) => {
removeDuplicateWindow(popupUrl);
await waitForWindowReady(newWindow.id);
res(null);
}
);
});
}
}
);
});
await new Promise((res) => {
setTimeout(() => {
chrome.runtime.sendMessage({
action: "SET_COUNTDOWN",
payload: 30,
});
res(true);
}, 700);
});
return new Promise((resolve) => {
// Set a timeout for 1 second
const timeout = setTimeout(() => {
resolve(false); // No response within 10 second, assume not focused
}, 30000);
// Send message to the content script to check focus
console.log("send msg");
chrome.runtime.sendMessage(
{ action: "QORTAL_REQUEST_PERMISSION", payload },
(response) => {
console.log("permission response", response);
if (response === undefined) return;
clearTimeout(timeout); // Clear the timeout if we get a response clearTimeout(timeout); // Clear the timeout if we get a response
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {
resolve(false); // Error occurred, assume not focused resolve(false); // Error occurred, assume not focused
} else { } else {
resolve(response); // Resolve based on the response resolve(response); // Resolve based on the response
} }
}); }
}); );
} });
}
export const getUserAccount = async () => { export const getUserAccount = async () => {
try { try {
@ -171,7 +168,6 @@ export const encryptData = async (data) => {
export const decryptData = async (data) => { export const decryptData = async (data) => {
const { encryptedData, publicKey } = data; const { encryptedData, publicKey } = data;
if (!encryptedData) { if (!encryptedData) {
throw new Error(`Missing fields: encryptedData`); throw new Error(`Missing fields: encryptedData`);
} }
@ -210,61 +206,155 @@ export const decryptData = async (data) => {
throw new Error("Unable to decrypt"); throw new Error("Unable to decrypt");
}; };
export const getListItems = async (data) => { export const getListItems = async (data) => {
const requiredFields = ['list_name'] const requiredFields = ["list_name"];
const missingFields: string[] = [] const missingFields: string[] = [];
requiredFields.forEach((field) => { requiredFields.forEach((field) => {
if (!data[field]) { if (!data[field]) {
missingFields.push(field) missingFields.push(field);
} }
}) });
if (missingFields.length > 0) { if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ') const missingFieldsString = missingFields.join(", ");
const errorMsg = `Missing fields: ${missingFieldsString}` const errorMsg = `Missing fields: ${missingFieldsString}`;
throw new Error(errorMsg) throw new Error(errorMsg);
} }
let skip = false let skip = false;
// if (window.parent.reduxStore.getState().app.qAPPAutoLists) { // if (window.parent.reduxStore.getState().app.qAPPAutoLists) {
// skip = true // skip = true
// } // }
let resPermission let resPermission;
if (!skip) { if (!skip) {
// res1 = await showModalAndWait( // res1 = await showModalAndWait(
// actions.GET_LIST_ITEMS, // actions.GET_LIST_ITEMS,
// { // {
// list_name: data.list_name // list_name: data.list_name
// } // }
// ) // )
resPermission = await getUserPermission({ resPermission = await getUserPermission({
text1: 'Do you give this application permission to', text1: "Do you give this application permission to",
text2: 'Access the list', text2: "Access the list",
text3: data.list_name text3: data.list_name,
}) });
}
console.log("resPermission", resPermission);
if (resPermission || skip) {
const url = await createEndpoint(`/lists/${data.list_name}`);
console.log("url", url);
const response = await fetch(url);
console.log("response", response);
if (!response.ok) throw new Error("Failed to fetch");
} const list = await response.json();
console.log('resPermission', resPermission) return list;
if (resPermission || skip) { } else {
try { throw new Error("User declined to share list");
}
const url = await createEndpoint(`/lists/${data.list_name}`); };
console.log('url', url)
const response = await fetch(url);
console.log('response', response)
if (!response.ok) throw new Error("Failed to fetch");
const list = await response.json();
return list
} catch (error) { export const addListItems = async (data) => {
throw new Error("Error in retrieving list") const requiredFields = ["list_name", "items"];
} const missingFields: string[] = [];
} else { requiredFields.forEach((field) => {
const data = {} if (!data[field]) {
throw new Error("User declined to share list") missingFields.push(field);
} }
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(", ");
const errorMsg = `Missing fields: ${missingFieldsString}`;
throw new Error(errorMsg);
}
const items = data.items;
const list_name = data.list_name;
const resPermission = await getUserPermission({
text1: "Do you give this application permission to",
text2: `Add the following to the list ${list_name}:`,
text3: items.join(', ')
});
if (resPermission) {
const url = await createEndpoint(`/lists/${list_name}`);
console.log("url", url);
const body = {
items: items,
};
const bodyToString = JSON.stringify(body);
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: bodyToString,
});
console.log("response", response);
if (!response.ok) throw new Error("Failed to add to list");
let res;
try {
res = await response.clone().json();
} catch (e) {
res = await response.text();
}
return res
} else {
throw new Error("User declined add to list");
}
};
export const deleteListItems = async (data) => {
const requiredFields = ['list_name', 'item']
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 item = data.item;
const list_name = data.list_name;
const resPermission = await getUserPermission({
text1: "Do you give this application permission to",
text2: `Remove the following from the list ${list_name}:`,
text3: item
});
if (resPermission) {
const url = await createEndpoint(`/lists/${list_name}`);
console.log("url", url);
const body = {
items: [item],
};
const bodyToString = JSON.stringify(body);
const response = await fetch(url, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: bodyToString,
});
console.log("response", response);
if (!response.ok) throw new Error("Failed to add to list");
let res;
try {
res = await response.clone().json();
} catch (e) {
res = await response.text();
}
return res
} else {
throw new Error("User declined add to list");
}
}; };
export const sendCoin = async () => { export const sendCoin = async () => {