Storage queueing
This commit is contained in:
@@ -1,29 +1,67 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
const reData = new RegExp('^data:(.*?);base64,(.*)$');
|
const reData = new RegExp('^data:(.*?);base64,(.*)$');
|
||||||
|
|
||||||
async function handleClick(tab, e) {
|
async function handleClick(tab, e) {
|
||||||
const imgURL = await browser.tabs.captureTab(tab.id);
|
const imgURL = await browser.tabs.captureTab(tab.id);
|
||||||
const [_, imgType, imgBase64] = imgURL.match(reData);
|
|
||||||
const img = atob(imgBase64);
|
|
||||||
|
|
||||||
const store = {};
|
const store = {};
|
||||||
store[`create_${crypto.randomUUID()}`] = {
|
store[`create_${crypto.randomUUID()}`] = {
|
||||||
title: tab.title,
|
name: tab.title,
|
||||||
url: tab.url,
|
notes: tab.url,
|
||||||
imgURL: imgURL,
|
attach: imgURL,
|
||||||
|
filename: 'screenshot.png',
|
||||||
};
|
};
|
||||||
await browser.storage.local.set(store);
|
await browser.storage.local.set(store);
|
||||||
|
|
||||||
if (!e.modifiers.includes('Command')) {
|
if (!e.modifiers.includes('Command')) {
|
||||||
browser.tabs.remove([tab.id]);
|
browser.tabs.remove([tab.id]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let inHandleChange = false;
|
||||||
|
|
||||||
|
async function handleChange(e) {
|
||||||
|
if (inHandleChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
inHandleChange = true;
|
||||||
|
await handleChangeInt(e);
|
||||||
|
} finally {
|
||||||
|
inHandleChange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleChangeInt(e) {
|
||||||
|
const queue = await browser.storage.local.get();
|
||||||
|
const keys = Object.getOwnPropertyNames(queue);
|
||||||
|
|
||||||
|
if (keys.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If some tasks cause issues, make progress on the others over time
|
||||||
|
const rand = Math.floor(Math.random() * keys.length);
|
||||||
|
const key = keys[rand];
|
||||||
|
const task = queue[key];
|
||||||
|
|
||||||
const cfg = await browser.storage.sync.get();
|
const cfg = await browser.storage.sync.get();
|
||||||
|
|
||||||
|
const type = key.split('_', 1)[0];
|
||||||
|
await typeHandlers.get(type)(cfg, task);
|
||||||
|
|
||||||
|
await browser.storage.local.remove([key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(cfg, task) {
|
||||||
const req = {
|
const req = {
|
||||||
data: {
|
data: {
|
||||||
workspace: cfg['workspace'],
|
workspace: cfg['workspace'],
|
||||||
assignee: cfg['assignee'],
|
assignee: cfg['assignee'],
|
||||||
name: tab.title,
|
name: task.name,
|
||||||
notes: tab.url,
|
notes: task.notes,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -36,35 +74,68 @@ async function handleClick(tab, e) {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
},
|
},
|
||||||
|
credentials: 'omit',
|
||||||
body: JSON.stringify(req),
|
body: JSON.stringify(req),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!createResp.ok) {
|
||||||
|
throw createResp.statusText;
|
||||||
|
}
|
||||||
|
|
||||||
const create = await createResp.json();
|
const create = await createResp.json();
|
||||||
|
|
||||||
const imgBytes = new Uint8Array(img.length);
|
if (task['attach']) {
|
||||||
for (let i = 0; i < img.length; i++) {
|
const store = {};
|
||||||
imgBytes[i] = img.charCodeAt(i);
|
store[`attach_${crypto.randomUUID()}`] = {
|
||||||
|
gid: create['data']['gid'],
|
||||||
|
attach: task.attach,
|
||||||
|
filename: task.filename,
|
||||||
|
};
|
||||||
|
await browser.storage.local.set(store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function attach(cfg, task) {
|
||||||
|
const [_, type, base64] = task.attach.match(reData);
|
||||||
|
const bytes = atob(base64);
|
||||||
|
|
||||||
|
const arr = new Uint8Array(bytes.length);
|
||||||
|
for (let i = 0; i < bytes.length; i++) {
|
||||||
|
arr[i] = bytes.charCodeAt(i);
|
||||||
}
|
}
|
||||||
const blob = new Blob(
|
const blob = new Blob(
|
||||||
[imgBytes],
|
[arr],
|
||||||
{
|
{
|
||||||
type: imgType,
|
type: type,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = new FormData();
|
const data = new FormData();
|
||||||
data.append('file', blob, 'screenshot.png');
|
data.append('file', blob, task.filename);
|
||||||
|
|
||||||
const attachResp = await fetch(
|
const attachResp = await fetch(
|
||||||
`https://app.asana.com/api/1.0/tasks/${encodeURIComponent(create['data']['gid'])}/attachments`,
|
`https://app.asana.com/api/1.0/tasks/${encodeURIComponent(task.gid)}/attachments`,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${cfg['token']}`,
|
'Authorization': `Bearer ${cfg['token']}`,
|
||||||
},
|
},
|
||||||
|
credentials: 'omit',
|
||||||
body: data,
|
body: data,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!attachResp.ok) {
|
||||||
|
throw attachResp.statusText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const typeHandlers = new Map([
|
||||||
|
['create', create],
|
||||||
|
['attach', attach],
|
||||||
|
]);
|
||||||
|
|
||||||
browser.browserAction.onClicked.addListener(handleClick);
|
browser.browserAction.onClicked.addListener(handleClick);
|
||||||
|
browser.storage.local.onChanged.addListener(handleChange);
|
||||||
|
setInterval(handleChange, 10000);
|
||||||
|
|||||||
Reference in New Issue
Block a user