feat(reader): polish the PDF reading experience

Make long PDF reading sessions easier to navigate across desktop and mobile. Keep document loading recoverable when EmbedPDF initializes or tears down out of order, without enabling document-editing capabilities.
This commit is contained in:
neon
2026-07-11 15:29:34 +00:00
parent 4a8b793c65
commit 870abecb01
38 changed files with 15871 additions and 7541 deletions
+65
View File
@@ -0,0 +1,65 @@
diff --git a/dist/vue/index.js b/dist/vue/index.js
index 0794dffc1ec042f66f9eb36192f46df2615ebb06..fc83b348e33658d615e178c638b69167eb0d905e 100644
--- a/dist/vue/index.js
+++ b/dist/vue/index.js
@@ -270,6 +270,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
const coreState = ref(null);
const isInit = ref(true);
const pluginsOk = ref(false);
+ let pendingRegistry = null;
+ let unsubscribe = null;
const activeDocumentId = computed(() => {
var _a;
return ((_a = coreState.value) == null ? void 0 : _a.activeDocumentId) ?? null;
@@ -302,6 +304,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
documents,
documentStates
});
+ onBeforeUnmount(() => {
+ unsubscribe == null ? void 0 : unsubscribe();
+ pendingRegistry == null ? void 0 : pendingRegistry.destroy();
+ registry.value == null ? void 0 : registry.value.destroy();
+ });
onMounted(async () => {
var _a, _b;
const finalConfig = {
@@ -309,6 +316,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
logger: ((_a = props.config) == null ? void 0 : _a.logger) ?? props.logger
};
const reg = new PluginRegistry(props.engine, finalConfig);
+ pendingRegistry = reg;
reg.registerPluginBatch(props.plugins);
await reg.initialize();
if (reg.isDestroyed()) {
@@ -316,28 +324,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
}
const store = reg.getStore();
coreState.value = store.getState().core;
- const unsubscribe = store.subscribe((action, newState, oldState) => {
+ unsubscribe = store.subscribe((action, newState, oldState) => {
if (store.isCoreAction(action) && newState.core !== oldState.core) {
coreState.value = newState.core;
}
});
await ((_b = props.onInitialized) == null ? void 0 : _b.call(props, reg));
if (reg.isDestroyed()) {
- unsubscribe();
+ unsubscribe == null ? void 0 : unsubscribe();
return;
}
registry.value = reg;
+ pendingRegistry = null;
isInit.value = false;
reg.pluginsReady().then(() => {
if (!reg.isDestroyed()) {
pluginsOk.value = true;
}
});
- onBeforeUnmount(() => {
- var _a2;
- unsubscribe();
- (_a2 = registry.value) == null ? void 0 : _a2.destroy();
- });
});
return (_ctx, _cache) => {
return pluginsOk.value && __props.autoMountDomElements ? (openBlock(), createBlock(_sfc_main$1, {
+21
View File
@@ -0,0 +1,21 @@
diff --git a/dist/lib/pdfium/web/worker-engine.js b/dist/lib/pdfium/web/worker-engine.js
index 1c40ef8dd3aa8050f3a23242d23258dbd04b3604..b81a6a9b879ecb4016a8ee1ad7da552f0ae5a13e 100644
--- a/dist/lib/pdfium/web/worker-engine.js
+++ b/dist/lib/pdfium/web/worker-engine.js
@@ -10,6 +10,16 @@ const _RemoteExecutor = class _RemoteExecutor {
this.requestCounter = 0;
this.handleMessage = (event) => {
const response = event.data;
+ if (response.type === "wasmError") {
+ const message = typeof response.error === "string" ? response.error : "Unknown worker initialization error";
+ this.logger.error(LOG_SOURCE$1, LOG_CATEGORY$1, "Worker initialization failed:", message);
+ this.readyTask.reject({
+ code: PdfErrorCode.Initialization,
+ message
+ });
+ this.pendingRequests.delete(_RemoteExecutor.READY_TASK_ID);
+ return;
+ }
if (response.type === "ready") {
this.logger.debug(LOG_SOURCE$1, LOG_CATEGORY$1, "Worker is ready");
this.readyTask.resolve(true);