Skip to content

Commit

Permalink
Refactor PDFWorkerWebViewHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
mvasilak committed Feb 25, 2025
1 parent 70bc91b commit 89bcec0
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 85 deletions.
6 changes: 6 additions & 0 deletions Zotero.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
6102D2B92D6CCDD300505E6A /* RemoteRecognizerResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6102D2B72D6CCDD300505E6A /* RemoteRecognizerResponse.swift */; };
6102D2BC2D6CCF7600505E6A /* RecognizerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6102D2BB2D6CCF7600505E6A /* RecognizerRequest.swift */; };
6102D2BD2D6CCF7600505E6A /* RecognizerRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6102D2BB2D6CCF7600505E6A /* RecognizerRequest.swift */; };
6102D2BF2D6E23D100505E6A /* worker.html in Resources */ = {isa = PBXBuildFile; fileRef = 6102D2BE2D6E23C400505E6A /* worker.html */; };
6102D2C02D6E23D100505E6A /* worker.html in Resources */ = {isa = PBXBuildFile; fileRef = 6102D2BE2D6E23C400505E6A /* worker.html */; };
61099E6E2C91BAF300EDD92C /* NSDecimalNumber+Rounding.m in Sources */ = {isa = PBXBuildFile; fileRef = 61099E6D2C91BAF300EDD92C /* NSDecimalNumber+Rounding.m */; };
61099E6F2C91BAF300EDD92C /* NSDecimalNumber+Rounding.m in Sources */ = {isa = PBXBuildFile; fileRef = 61099E6D2C91BAF300EDD92C /* NSDecimalNumber+Rounding.m */; };
61168F612D50D4B6005495E8 /* PDFWorkerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61168F602D50D4B6005495E8 /* PDFWorkerController.swift */; };
Expand Down Expand Up @@ -1314,6 +1316,7 @@
6102D2B52D68B5DE00505E6A /* bitcoin_pdf_full_text.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = bitcoin_pdf_full_text.json; sourceTree = "<group>"; };
6102D2B72D6CCDD300505E6A /* RemoteRecognizerResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteRecognizerResponse.swift; sourceTree = "<group>"; };
6102D2BB2D6CCF7600505E6A /* RecognizerRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecognizerRequest.swift; sourceTree = "<group>"; };
6102D2BE2D6E23C400505E6A /* worker.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = worker.html; sourceTree = "<group>"; };
61099E6A2C91BAF300EDD92C /* Zotero-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Zotero-Bridging-Header.h"; sourceTree = "<group>"; };
61099E6B2C91BAF300EDD92C /* ZShare-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ZShare-Bridging-Header.h"; sourceTree = "<group>"; };
61099E6C2C91BAF300EDD92C /* NSDecimalNumber+Rounding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDecimalNumber+Rounding.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3633,6 +3636,7 @@
B39E0130283276470091CE4A /* Web View Handling */ = {
isa = PBXGroup;
children = (
6102D2BE2D6E23C400505E6A /* worker.html */,
B323703F2C0DC65600170779 /* LookupWebViewHandler.swift */,
612361062D439D6A007FA575 /* PDFWorkerWebViewHandler.swift */,
B39E0131283276830091CE4A /* WebViewHandler.swift */,
Expand Down Expand Up @@ -4586,6 +4590,7 @@
B37C5B6F26454130009A37E5 /* NoteEditorViewController.xib in Resources */,
B3593F27241A61C700760E20 /* ItemDetailFieldContentView.xib in Resources */,
B34DF1BE2576956F0019CCD1 /* SwitchCell.xib in Resources */,
6102D2C02D6E23D100505E6A /* worker.html in Resources */,
B30B550324B85A3A00F94B59 /* Colors.xcassets in Resources */,
B31CC57D286468C80055C114 /* ManualLookupViewController.xib in Resources */,
B35DC8E6261D9E7C00ED30F4 /* ItemDetailFieldMultilineEditContentView.xib in Resources */,
Expand Down Expand Up @@ -4654,6 +4659,7 @@
B36459DD2644118800A0C2C0 /* TagPickerCell.xib in Resources */,
B337A5AE244F35A900AFD13D /* Localizable.strings in Resources */,
B35F476A24F8F55600FE328D /* webview_extraction.js in Resources */,
6102D2BF2D6E23D100505E6A /* worker.html in Resources */,
B3AB38B8238ED023008A1ABB /* Assets.xcassets in Resources */,
B36459DE2644119100A0C2C0 /* TagPickerViewController.xib in Resources */,
618D83E82BAAC88C00E7966B /* PrivacyInfo.xcprivacy in Resources */,
Expand Down
97 changes: 12 additions & 85 deletions Zotero/Controllers/Web View Handling/PDFWorkerWebViewHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ final class PDFWorkerWebViewHandler {
case log = "logHandler"
}

enum Error: Swift.Error {
case cantFindFile
}

enum PDFWorkerData {
case recognizerData(data: [String: Any])
case fullText(data: [String: Any])
Expand Down Expand Up @@ -65,11 +69,17 @@ final class PDFWorkerWebViewHandler {

func initialize() -> Single<Any> {
DDLogInfo("PDFWorkerWebViewHandler: initialize web view")
let baseURL = Bundle.main.bundleURL.appendingPathComponent("Bundled/pdf_worker", isDirectory: true)
return webViewHandler.loadHTMLString(Self.htmlString, baseURL: baseURL)
return loadIndex()
.flatMap { _ in
Single.just(Void())
}

func loadIndex() -> Single<()> {
guard let indexUrl = Bundle.main.url(forResource: "worker", withExtension: "html") else {
return .error(Error.cantFindFile)
}
return webViewHandler.load(fileUrl: indexUrl)
}
}
}

Expand Down Expand Up @@ -165,87 +175,4 @@ final class PDFWorkerWebViewHandler {
DDLogInfo("JSLOG: \(body)")
}
}

static let htmlString: String = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PDF Worker</title>
</head>
<body>
<script>
function log(message) {
webkit.messageHandlers.logHandler.postMessage(message);
}
let promiseId = 0;
let waitingPromises = {};
let worker = new Worker('worker.js');
async function query(action, data, transfer) {
return new Promise(function (resolve) {
promiseId++;
waitingPromises[promiseId] = resolve;
worker.postMessage({ id: promiseId, action, data }, transfer);
});
}
worker.onmessage = async function (e) {
let message = e.data;
window.webkit.messageHandlers.logHandler.postMessage('Message received', message);
if (message.responseID) {
let resolve = waitingPromises[message.responseID];
if (resolve) {
resolve(message.data);
}
return;
}
if (message.id) {
window.webkit.messageHandlers.logHandler.postMessage('\thas id: ' + message.id);
let respData = null;
if (message.op === 'FetchBuiltInCMap') {
respData = {
compressionType: 1,
cMapData: new Uint8Array(await (await fetch('/cmaps/' + message.data + '.bcmap')).arrayBuffer())
};
}
worker.postMessage({ responseID: e.data.id, data: respData });
return;
}
}
async function fetchLocalFile(filePath) {
log(`fetching ${filePath}`);
let response = await fetch(filePath);
log(`response: ${JSON.stringify(response)}`);
let arrayBuffer = await response.arrayBuffer();
return arrayBuffer.slice();
}
async function recognize(filePath) {
try {
let buf = await fetchLocalFile(filePath)
let recognizerData = await query('getRecognizerData', { buf }, [buf]);
webkit.messageHandlers.recognizerDataHandler.postMessage({"recognizerData": recognizerData});
} catch (error) {
log(`error: ${error}`);
throw error;
}
}
async function getFullText(filePath) {
try {
let buf = await fetchLocalFile(filePath)
let fulltext = await query('getFulltext', { buf }, [buf]);
webkit.messageHandlers.fullTextHandler.postMessage({"fullText": fulltext});
} catch (error) {
log(`error: ${error}`);
throw error;
}
}
</script>
</body>
</html>
"""
}
80 changes: 80 additions & 0 deletions Zotero/Controllers/Web View Handling/worker.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PDF Worker</title>
</head>
<body>
<script>
function log(message) {
webkit.messageHandlers.logHandler.postMessage(message);
}

let promiseId = 0;
let waitingPromises = {};
let worker = new Worker('Bundled/pdf_worker/worker.js');

async function query(action, data, transfer) {
return new Promise(function (resolve) {
promiseId++;
waitingPromises[promiseId] = resolve;
worker.postMessage({ id: promiseId, action, data }, transfer);
});
}

worker.onmessage = async function (e) {
let message = e.data;
window.webkit.messageHandlers.logHandler.postMessage('Message received', message);
if (message.responseID) {
let resolve = waitingPromises[message.responseID];
if (resolve) {
resolve(message.data);
}
return;
}
if (message.id) {
window.webkit.messageHandlers.logHandler.postMessage('\thas id: ' + message.id);
let respData = null;
if (message.op === 'FetchBuiltInCMap') {
respData = {
compressionType: 1,
cMapData: new Uint8Array(await (await fetch('../Bundled/pdf_worker/cmaps/' + message.data + '.bcmap')).arrayBuffer())
};
}
worker.postMessage({ responseID: e.data.id, data: respData });
return;
}
}

async function fetchLocalFile(filePath) {
log(`fetching ${filePath}`);
let response = await fetch(filePath);
log(`response: ${JSON.stringify(response)}`);
let arrayBuffer = await response.arrayBuffer();
return arrayBuffer.slice();
}

async function recognize(filePath) {
try {
let buf = await fetchLocalFile(filePath)
let recognizerData = await query('getRecognizerData', { buf }, [buf]);
webkit.messageHandlers.recognizerDataHandler.postMessage({"recognizerData": recognizerData});
} catch (error) {
log(`error: ${error}`);
throw error;
}
}

async function getFullText(filePath) {
try {
let buf = await fetchLocalFile(filePath)
let fulltext = await query('getFulltext', { buf }, [buf]);
webkit.messageHandlers.fullTextHandler.postMessage({"fullText": fulltext});
} catch (error) {
log(`error: ${error}`);
throw error;
}
}
</script>
</body>
</html>

0 comments on commit 89bcec0

Please sign in to comment.