Fix and attach image annotation renderer
This commit is contained in:
parent
3e4ad18b2a
commit
83109fc076
3 changed files with 84 additions and 33 deletions
|
@ -977,6 +977,21 @@ class EditorInstance {
|
|||
if (!annotations.length) {
|
||||
throw new Error("No annotations provided");
|
||||
}
|
||||
|
||||
for (let annotation of annotations) {
|
||||
if (annotation.annotationType === 'image'
|
||||
&& !await Zotero.Annotations.hasCacheImage(annotation)) {
|
||||
try {
|
||||
await Zotero.PDFRenderer.renderAttachmentAnnotations(annotation.parentID);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.debug(e);
|
||||
throw e;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let note = new Zotero.Item('note');
|
||||
note.libraryID = annotations[0].libraryID;
|
||||
note.parentID = parentID;
|
||||
|
|
|
@ -82,7 +82,6 @@ class PDFWorker {
|
|||
this._worker = new Worker(WORKER_URL);
|
||||
this._worker.addEventListener('message', async (event) => {
|
||||
let message = event.data;
|
||||
// console.log(event.data)
|
||||
if (message.responseID) {
|
||||
let { resolve, reject } = this._waitingPromises[message.responseID];
|
||||
delete this._waitingPromises[message.responseID];
|
||||
|
@ -141,8 +140,8 @@ class PDFWorker {
|
|||
*
|
||||
* @param {Integer} itemID
|
||||
* @param {String} path
|
||||
* @param {Boolean} isPriority
|
||||
* @param {String} password
|
||||
* @param {Boolean} [isPriority]
|
||||
* @param {String} [password]
|
||||
* @returns {Promise<Integer>} Number of written annotations
|
||||
*/
|
||||
async export(itemID, path, isPriority, password) {
|
||||
|
@ -165,7 +164,7 @@ class PDFWorker {
|
|||
dateModified: item.dateModified
|
||||
});
|
||||
}
|
||||
let attachmentPath = await attachment.getFilePath();
|
||||
let attachmentPath = await attachment.getFilePathAsync();
|
||||
let buf = await OS.File.read(attachmentPath, {});
|
||||
buf = new Uint8Array(buf).buffer;
|
||||
|
||||
|
@ -193,7 +192,7 @@ class PDFWorker {
|
|||
*
|
||||
* @param {Zotero.Item} item
|
||||
* @param {String} directory
|
||||
* @param {Boolean} isPriority
|
||||
* @param {Boolean} [isPriority]
|
||||
*/
|
||||
async exportParent(item, directory, isPriority) {
|
||||
if (!item.isRegularItem()) {
|
||||
|
@ -218,8 +217,8 @@ class PDFWorker {
|
|||
* Import annotations from PDF attachment
|
||||
*
|
||||
* @param {Integer} itemID Attachment item id
|
||||
* @param {Boolean} isPriority
|
||||
* @param {String} password
|
||||
* @param {Boolean} [isPriority]
|
||||
* @param {String} [password]
|
||||
* @returns {Promise<Integer>} Number of annotations
|
||||
*/
|
||||
async import(itemID, isPriority, password) {
|
||||
|
@ -244,7 +243,7 @@ class PDFWorker {
|
|||
comment: annotation.annotationComment || ''
|
||||
}));
|
||||
|
||||
let path = await attachment.getFilePath();
|
||||
let path = await attachment.getFilePathAsync();
|
||||
let buf = await OS.File.read(path, {});
|
||||
buf = new Uint8Array(buf).buffer;
|
||||
|
||||
|
@ -284,7 +283,7 @@ class PDFWorker {
|
|||
* Import annotations for each PDF attachment of parent item
|
||||
*
|
||||
* @param {Zotero.Item} item
|
||||
* @param {Boolean} isPriority
|
||||
* @param {Boolean} [isPriority]
|
||||
*/
|
||||
async importParent(item, isPriority) {
|
||||
if (!item.isRegularItem()) {
|
||||
|
@ -379,6 +378,9 @@ class PDFRenderer {
|
|||
this._browser.loadURI(RENDERER_URL);
|
||||
|
||||
let _handleMessage = async (event) => {
|
||||
if (event.source !== this._browser.contentWindow) {
|
||||
return;
|
||||
}
|
||||
let message = event.data;
|
||||
if (message.responseID) {
|
||||
let { resolve, reject } = this._waitingPromises[message.responseID];
|
||||
|
@ -395,18 +397,29 @@ class PDFRenderer {
|
|||
}
|
||||
|
||||
if (message.action === 'initialized') {
|
||||
this._browser.contentWindow.postMessage(
|
||||
{ responseID: message.id, data: {} },
|
||||
this._browser.contentWindow.origin
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
else if (message.action === 'renderedAnnotation') {
|
||||
let { id, image } = message.data.annotation;
|
||||
let item = await Zotero.Items.getAsync(id);
|
||||
let win = Zotero.getMainWindow();
|
||||
if (!win) {
|
||||
return;
|
||||
|
||||
try {
|
||||
let item = await Zotero.Items.getAsync(id);
|
||||
let win = Zotero.getMainWindow();
|
||||
let blob = new win.Blob([new Uint8Array(image)]);
|
||||
await Zotero.Annotations.saveCacheImage(item, blob);
|
||||
await Zotero.Notifier.trigger('modify', 'item', [item.id]);
|
||||
} catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
let blob = new win.Blob([new Uint8Array(image)]);
|
||||
await Zotero.Annotations.saveCacheImage(item, blob);
|
||||
await Zotero.Notifier.trigger('modify', 'item', [item.id]);
|
||||
|
||||
this._browser.contentWindow.postMessage(
|
||||
{ responseID: message.id, data: {} },
|
||||
this._browser.contentWindow.origin
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -416,7 +429,7 @@ class PDFRenderer {
|
|||
* Render missing image annotation images for attachment
|
||||
*
|
||||
* @param {Integer} itemID Attachment item id
|
||||
* @param {Boolean} isPriority
|
||||
* @param {Boolean} [isPriority]
|
||||
* @returns {Promise<Integer>}
|
||||
*/
|
||||
async renderAttachmentAnnotations(itemID, isPriority) {
|
||||
|
@ -435,7 +448,7 @@ class PDFRenderer {
|
|||
if (!annotations.length) {
|
||||
return 0;
|
||||
}
|
||||
let path = await attachment.getFilePath();
|
||||
let path = await attachment.getFilePathAsync();
|
||||
let buf = await OS.File.read(path, {});
|
||||
buf = new Uint8Array(buf).buffer;
|
||||
return this._query('renderAnnotations', { buf, annotations }, [buf]);
|
||||
|
@ -446,7 +459,7 @@ class PDFRenderer {
|
|||
* Render image annotation image
|
||||
*
|
||||
* @param {Integer} itemID Attachment item id
|
||||
* @param {Boolean} isPriority
|
||||
* @param {Boolean} [isPriority]
|
||||
* @returns {Promise<Boolean>}
|
||||
*/
|
||||
async renderAnnotation(itemID, isPriority) {
|
||||
|
@ -456,7 +469,7 @@ class PDFRenderer {
|
|||
return false;
|
||||
}
|
||||
let attachment = await Zotero.Items.getAsync(annotation.parentID);
|
||||
let path = await attachment.getFilePath();
|
||||
let path = await attachment.getFilePathAsync();
|
||||
let buf = await OS.File.read(path, {});
|
||||
buf = new Uint8Array(buf).buffer;
|
||||
let annotations = [{
|
||||
|
|
|
@ -31,7 +31,22 @@ function errObject(err) {
|
|||
return JSON.parse(JSON.stringify(err, Object.getOwnPropertyNames(err)));
|
||||
}
|
||||
|
||||
async function renderAnnotations(buf, annotations, send) {
|
||||
let lastPromiseID = 0;
|
||||
let waitingPromises = {};
|
||||
|
||||
async function query(action, data, transfer) {
|
||||
return new Promise((resolve, reject) => {
|
||||
lastPromiseID++;
|
||||
waitingPromises[lastPromiseID] = { resolve, reject };
|
||||
parent.postMessage({
|
||||
id: lastPromiseID,
|
||||
action,
|
||||
data
|
||||
}, parent.origin, transfer);
|
||||
});
|
||||
}
|
||||
|
||||
async function renderAnnotations(buf, annotations) {
|
||||
let num = 0;
|
||||
let pdfDocument = await window.pdfjsLib.getDocument({ data: buf }).promise;
|
||||
let pages = new Map();
|
||||
|
@ -54,10 +69,9 @@ async function renderAnnotations(buf, annotations, send) {
|
|||
newCanvas.height = height;
|
||||
let newCanvasContext = newCanvas.getContext('2d');
|
||||
newCanvasContext.drawImage(canvas, left, top, width, height, 0, 0, width, height);
|
||||
newCanvas.toBlob(async (blob) => {
|
||||
let image = await new Response(blob).arrayBuffer();
|
||||
send({ id: annotation.id, image });
|
||||
}, 'image/png');
|
||||
let blob = await new Promise(resolve => newCanvas.toBlob(resolve, 'image/png'));
|
||||
let image = await new Response(blob).arrayBuffer();
|
||||
await query('renderedAnnotation', { annotation: { id: annotation.id, image } }, [image]);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
@ -91,16 +105,25 @@ window.addEventListener('message', async (event) => {
|
|||
return;
|
||||
}
|
||||
let message = event.data;
|
||||
|
||||
if (message.responseID) {
|
||||
let { resolve, reject } = waitingPromises[message.responseID];
|
||||
delete waitingPromises[message.responseID];
|
||||
if (message.data) {
|
||||
resolve(message.data);
|
||||
}
|
||||
else {
|
||||
let err = new Error(message.error.message);
|
||||
Object.assign(err, message.error);
|
||||
reject(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.action === 'renderAnnotations') {
|
||||
try {
|
||||
let { buf, annotations } = message.data;
|
||||
let num = await renderAnnotations(
|
||||
buf,
|
||||
annotations,
|
||||
(annotation) => {
|
||||
parent.postMessage({ action: 'renderedAnnotation', data: { annotation } }, parent.origin, [annotation.image]);
|
||||
}
|
||||
);
|
||||
let num = await renderAnnotations(buf, annotations);
|
||||
parent.postMessage({ responseID: message.id, data: num }, parent.origin);
|
||||
}
|
||||
catch (e) {
|
||||
|
@ -114,5 +137,5 @@ window.addEventListener('message', async (event) => {
|
|||
});
|
||||
|
||||
setTimeout(() => {
|
||||
parent.postMessage({ action: 'initialized' }, parent.origin);
|
||||
query('initialized', {});
|
||||
}, 100);
|
||||
|
|
Loading…
Reference in a new issue