pdfjs-reader-core 0.5.10 → 0.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +186 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +192 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2031,6 +2031,22 @@ interface EngineDeps {
|
|
|
2031
2031
|
* visually in a narration context. Default: 3500ms.
|
|
2032
2032
|
*/
|
|
2033
2033
|
minOverlayDurationMs?: number;
|
|
2034
|
+
/**
|
|
2035
|
+
* When true, only ONE annotation overlay is on-screen at any time: every
|
|
2036
|
+
* new overlay-emitting step first clears all prior overlays and their
|
|
2037
|
+
* auto-removal timers.
|
|
2038
|
+
*
|
|
2039
|
+
* Defaults to `isIOSMobile()` — on iOS Safari/WebKit, stacking 2-3 overlays
|
|
2040
|
+
* (e.g. highlight + box + underline + callout) on the same anchor is the
|
|
2041
|
+
* single biggest remaining crash vector we've measured. The GPU
|
|
2042
|
+
* compositor rejects the layer combination long before the canvas cap
|
|
2043
|
+
* kicks in. Dropping to one overlay at a time sacrifices overlay chaining
|
|
2044
|
+
* on iOS for a hard stability guarantee.
|
|
2045
|
+
*
|
|
2046
|
+
* Pass `false` explicitly to force multi-overlay mode even on iOS (e.g.
|
|
2047
|
+
* for tests or a deliberate opt-out in the consumer).
|
|
2048
|
+
*/
|
|
2049
|
+
singleActiveOverlay?: boolean;
|
|
2034
2050
|
}
|
|
2035
2051
|
declare class StoryboardEngine {
|
|
2036
2052
|
private deps;
|
|
@@ -2049,6 +2065,13 @@ declare class StoryboardEngine {
|
|
|
2049
2065
|
*/
|
|
2050
2066
|
private overlayRemovalTimers;
|
|
2051
2067
|
private currentStoryboardId;
|
|
2068
|
+
/**
|
|
2069
|
+
* Resolved value of `deps.singleActiveOverlay`. Cached at construction so
|
|
2070
|
+
* each step dispatch is a single branch rather than a per-call
|
|
2071
|
+
* userAgent sniff, and so the policy stays stable for the engine's
|
|
2072
|
+
* lifetime (a viewport flip that recreates the engine will re-evaluate).
|
|
2073
|
+
*/
|
|
2074
|
+
private readonly singleActiveOverlay;
|
|
2052
2075
|
constructor(deps: EngineDeps);
|
|
2053
2076
|
/**
|
|
2054
2077
|
* Execute a new storyboard. Cancels in-flight steps from the previous storyboard
|
package/dist/index.d.ts
CHANGED
|
@@ -2031,6 +2031,22 @@ interface EngineDeps {
|
|
|
2031
2031
|
* visually in a narration context. Default: 3500ms.
|
|
2032
2032
|
*/
|
|
2033
2033
|
minOverlayDurationMs?: number;
|
|
2034
|
+
/**
|
|
2035
|
+
* When true, only ONE annotation overlay is on-screen at any time: every
|
|
2036
|
+
* new overlay-emitting step first clears all prior overlays and their
|
|
2037
|
+
* auto-removal timers.
|
|
2038
|
+
*
|
|
2039
|
+
* Defaults to `isIOSMobile()` — on iOS Safari/WebKit, stacking 2-3 overlays
|
|
2040
|
+
* (e.g. highlight + box + underline + callout) on the same anchor is the
|
|
2041
|
+
* single biggest remaining crash vector we've measured. The GPU
|
|
2042
|
+
* compositor rejects the layer combination long before the canvas cap
|
|
2043
|
+
* kicks in. Dropping to one overlay at a time sacrifices overlay chaining
|
|
2044
|
+
* on iOS for a hard stability guarantee.
|
|
2045
|
+
*
|
|
2046
|
+
* Pass `false` explicitly to force multi-overlay mode even on iOS (e.g.
|
|
2047
|
+
* for tests or a deliberate opt-out in the consumer).
|
|
2048
|
+
*/
|
|
2049
|
+
singleActiveOverlay?: boolean;
|
|
2034
2050
|
}
|
|
2035
2051
|
declare class StoryboardEngine {
|
|
2036
2052
|
private deps;
|
|
@@ -2049,6 +2065,13 @@ declare class StoryboardEngine {
|
|
|
2049
2065
|
*/
|
|
2050
2066
|
private overlayRemovalTimers;
|
|
2051
2067
|
private currentStoryboardId;
|
|
2068
|
+
/**
|
|
2069
|
+
* Resolved value of `deps.singleActiveOverlay`. Cached at construction so
|
|
2070
|
+
* each step dispatch is a single branch rather than a per-call
|
|
2071
|
+
* userAgent sniff, and so the policy stays stable for the engine's
|
|
2072
|
+
* lifetime (a viewport flip that recreates the engine will re-evaluate).
|
|
2073
|
+
*/
|
|
2074
|
+
private readonly singleActiveOverlay;
|
|
2052
2075
|
constructor(deps: EngineDeps);
|
|
2053
2076
|
/**
|
|
2054
2077
|
* Execute a new storyboard. Cancels in-flight steps from the previous storyboard
|
package/dist/index.js
CHANGED
|
@@ -1879,6 +1879,15 @@ function detectDeviceCapabilities() {
|
|
|
1879
1879
|
screenSize
|
|
1880
1880
|
};
|
|
1881
1881
|
}
|
|
1882
|
+
function isIOSMobile() {
|
|
1883
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
1884
|
+
return false;
|
|
1885
|
+
}
|
|
1886
|
+
const ua = navigator.userAgent || "";
|
|
1887
|
+
if (/iPhone|iPad|iPod/i.test(ua)) return true;
|
|
1888
|
+
const isAppleTouch = /Mac/i.test(ua) && typeof navigator.maxTouchPoints === "number" && navigator.maxTouchPoints > 1;
|
|
1889
|
+
return isAppleTouch;
|
|
1890
|
+
}
|
|
1882
1891
|
function getRenderConfig(quality = "auto", capabilities) {
|
|
1883
1892
|
const caps = capabilities ?? detectDeviceCapabilities();
|
|
1884
1893
|
if (quality === "auto") {
|
|
@@ -1893,8 +1902,10 @@ function getRenderConfig(quality = "auto", capabilities) {
|
|
|
1893
1902
|
switch (quality) {
|
|
1894
1903
|
case "low":
|
|
1895
1904
|
return {
|
|
1896
|
-
canvasScaleFactor:
|
|
1897
|
-
|
|
1905
|
+
canvasScaleFactor: caps.devicePixelRatio,
|
|
1906
|
+
// 3072² ≈ 9 MP — fits a full-DPR US Letter (DPR=3 → 1836×2376) at
|
|
1907
|
+
// default scale and caps at deep zoom on memory-constrained iPhones.
|
|
1908
|
+
maxCanvasDimension: 3072,
|
|
1898
1909
|
overscanPages: 1,
|
|
1899
1910
|
maxPagesInMemory: 3,
|
|
1900
1911
|
scrollDebounceMs: 100,
|
|
@@ -1907,7 +1918,8 @@ function getRenderConfig(quality = "auto", capabilities) {
|
|
|
1907
1918
|
};
|
|
1908
1919
|
case "medium":
|
|
1909
1920
|
return {
|
|
1910
|
-
canvasScaleFactor:
|
|
1921
|
+
canvasScaleFactor: caps.devicePixelRatio,
|
|
1922
|
+
// 4096² ≈ 16 MP — within iOS Safari per-canvas budget across versions.
|
|
1911
1923
|
maxCanvasDimension: 4096,
|
|
1912
1924
|
overscanPages: 2,
|
|
1913
1925
|
maxPagesInMemory: 5,
|
|
@@ -5181,9 +5193,37 @@ var init_ThumbnailPanel = __esm({
|
|
|
5181
5193
|
onClick,
|
|
5182
5194
|
scale
|
|
5183
5195
|
}) {
|
|
5196
|
+
const buttonRef = useRef7(null);
|
|
5184
5197
|
const canvasRef = useRef7(null);
|
|
5185
5198
|
const [isRendered, setIsRendered] = useState6(false);
|
|
5199
|
+
const [shouldRender, setShouldRender] = useState6(false);
|
|
5186
5200
|
useEffect9(() => {
|
|
5201
|
+
if (shouldRender) return;
|
|
5202
|
+
const el = buttonRef.current;
|
|
5203
|
+
if (!el) return;
|
|
5204
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
5205
|
+
setShouldRender(true);
|
|
5206
|
+
return;
|
|
5207
|
+
}
|
|
5208
|
+
const observer = new IntersectionObserver(
|
|
5209
|
+
(entries) => {
|
|
5210
|
+
for (const entry of entries) {
|
|
5211
|
+
if (entry.isIntersecting) {
|
|
5212
|
+
setShouldRender(true);
|
|
5213
|
+
observer.disconnect();
|
|
5214
|
+
break;
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
},
|
|
5218
|
+
// 200px root margin so the page is fetched just before it scrolls
|
|
5219
|
+
// into view, hiding the render latency.
|
|
5220
|
+
{ rootMargin: "200px" }
|
|
5221
|
+
);
|
|
5222
|
+
observer.observe(el);
|
|
5223
|
+
return () => observer.disconnect();
|
|
5224
|
+
}, [shouldRender]);
|
|
5225
|
+
useEffect9(() => {
|
|
5226
|
+
if (!shouldRender) return;
|
|
5187
5227
|
let cancelled = false;
|
|
5188
5228
|
const renderThumbnail = async () => {
|
|
5189
5229
|
const canvas = canvasRef.current;
|
|
@@ -5217,10 +5257,11 @@ var init_ThumbnailPanel = __esm({
|
|
|
5217
5257
|
return () => {
|
|
5218
5258
|
cancelled = true;
|
|
5219
5259
|
};
|
|
5220
|
-
}, [document2, pageNumber, scale]);
|
|
5260
|
+
}, [document2, pageNumber, scale, shouldRender]);
|
|
5221
5261
|
return /* @__PURE__ */ jsxs3(
|
|
5222
5262
|
"button",
|
|
5223
5263
|
{
|
|
5264
|
+
ref: buttonRef,
|
|
5224
5265
|
onClick,
|
|
5225
5266
|
className: cn(
|
|
5226
5267
|
"thumbnail-item",
|
|
@@ -9443,6 +9484,11 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9443
9484
|
selectHighlight,
|
|
9444
9485
|
activeColor
|
|
9445
9486
|
} = useHighlights();
|
|
9487
|
+
const [defaultDims, setDefaultDims] = useState19({
|
|
9488
|
+
width: DEFAULT_PAGE_WIDTH2,
|
|
9489
|
+
height: DEFAULT_PAGE_HEIGHT2
|
|
9490
|
+
});
|
|
9491
|
+
const [dimsVersion, setDimsVersion] = useState19(0);
|
|
9446
9492
|
useEffect20(() => {
|
|
9447
9493
|
if (document2 !== documentRef.current) {
|
|
9448
9494
|
documentRef.current = document2;
|
|
@@ -9451,39 +9497,47 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9451
9497
|
setPageObjects(/* @__PURE__ */ new Map());
|
|
9452
9498
|
}
|
|
9453
9499
|
}, [document2]);
|
|
9500
|
+
useEffect20(() => {
|
|
9501
|
+
pageDimensionsCache.current.clear();
|
|
9502
|
+
setDimsVersion((v) => v + 1);
|
|
9503
|
+
}, [rotation]);
|
|
9454
9504
|
useEffect20(() => {
|
|
9455
9505
|
if (!document2 || numPages === 0) return;
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
dimensions = { width: viewport.width, height: viewport.height };
|
|
9469
|
-
pageDimensionsCache.current.set(i, dimensions);
|
|
9470
|
-
} catch {
|
|
9471
|
-
dimensions = { width: DEFAULT_PAGE_WIDTH2, height: DEFAULT_PAGE_HEIGHT2 };
|
|
9472
|
-
}
|
|
9473
|
-
}
|
|
9474
|
-
const scaledHeight = Math.floor(dimensions.height * scale);
|
|
9475
|
-
infos.push({
|
|
9476
|
-
pageNumber: i,
|
|
9477
|
-
top: currentTop,
|
|
9478
|
-
height: scaledHeight
|
|
9479
|
-
});
|
|
9480
|
-
currentTop += scaledHeight + pageGap;
|
|
9506
|
+
let cancelled = false;
|
|
9507
|
+
(async () => {
|
|
9508
|
+
try {
|
|
9509
|
+
const page = pageCache.current.get(1) ?? await document2.getPage(1);
|
|
9510
|
+
if (cancelled) return;
|
|
9511
|
+
pageCache.current.set(1, page);
|
|
9512
|
+
const viewport = page.getViewport({ scale: 1, rotation });
|
|
9513
|
+
const dims = { width: viewport.width, height: viewport.height };
|
|
9514
|
+
pageDimensionsCache.current.set(1, dims);
|
|
9515
|
+
setDefaultDims(dims);
|
|
9516
|
+
setDimsVersion((v) => v + 1);
|
|
9517
|
+
} catch {
|
|
9481
9518
|
}
|
|
9482
|
-
|
|
9483
|
-
|
|
9519
|
+
})();
|
|
9520
|
+
return () => {
|
|
9521
|
+
cancelled = true;
|
|
9484
9522
|
};
|
|
9485
|
-
|
|
9486
|
-
|
|
9523
|
+
}, [document2, numPages, rotation]);
|
|
9524
|
+
useEffect20(() => {
|
|
9525
|
+
if (!document2 || numPages === 0) {
|
|
9526
|
+
setPageInfos([]);
|
|
9527
|
+
setTotalHeight(0);
|
|
9528
|
+
return;
|
|
9529
|
+
}
|
|
9530
|
+
const infos = [];
|
|
9531
|
+
let currentTop = 0;
|
|
9532
|
+
for (let i = 1; i <= numPages; i++) {
|
|
9533
|
+
const dimensions = pageDimensionsCache.current.get(i) ?? defaultDims;
|
|
9534
|
+
const scaledHeight = Math.floor(dimensions.height * scale);
|
|
9535
|
+
infos.push({ pageNumber: i, top: currentTop, height: scaledHeight });
|
|
9536
|
+
currentTop += scaledHeight + pageGap;
|
|
9537
|
+
}
|
|
9538
|
+
setPageInfos(infos);
|
|
9539
|
+
setTotalHeight(Math.max(0, currentTop - pageGap));
|
|
9540
|
+
}, [document2, numPages, scale, rotation, pageGap, defaultDims, dimsVersion]);
|
|
9487
9541
|
const updateVisiblePages = useCallback30(() => {
|
|
9488
9542
|
if (!scrollContainerRef.current || pageInfos.length === 0) return;
|
|
9489
9543
|
const container = scrollContainerRef.current;
|
|
@@ -9531,6 +9585,7 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9531
9585
|
const loadPages = async () => {
|
|
9532
9586
|
const newPageObjects = new Map(pageObjects);
|
|
9533
9587
|
let hasChanges = false;
|
|
9588
|
+
let dimsChanged = false;
|
|
9534
9589
|
for (const pageNum of visiblePages) {
|
|
9535
9590
|
if (!newPageObjects.has(pageNum)) {
|
|
9536
9591
|
try {
|
|
@@ -9541,6 +9596,14 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9541
9596
|
}
|
|
9542
9597
|
newPageObjects.set(pageNum, page);
|
|
9543
9598
|
hasChanges = true;
|
|
9599
|
+
if (!pageDimensionsCache.current.has(pageNum)) {
|
|
9600
|
+
const vp = page.getViewport({ scale: 1, rotation });
|
|
9601
|
+
pageDimensionsCache.current.set(pageNum, {
|
|
9602
|
+
width: vp.width,
|
|
9603
|
+
height: vp.height
|
|
9604
|
+
});
|
|
9605
|
+
dimsChanged = true;
|
|
9606
|
+
}
|
|
9544
9607
|
} catch (error) {
|
|
9545
9608
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
9546
9609
|
const isDocumentDestroyed = errorMessage.includes("destroyed") || errorMessage.includes("sendWithStream") || errorMessage.includes("sendWithPromise") || errorMessage.includes("Cannot read properties of null");
|
|
@@ -9560,9 +9623,12 @@ var init_VirtualizedDocumentContainer = __esm({
|
|
|
9560
9623
|
if (hasChanges) {
|
|
9561
9624
|
setPageObjects(newPageObjects);
|
|
9562
9625
|
}
|
|
9626
|
+
if (dimsChanged) {
|
|
9627
|
+
setDimsVersion((v) => v + 1);
|
|
9628
|
+
}
|
|
9563
9629
|
};
|
|
9564
9630
|
loadPages();
|
|
9565
|
-
}, [document2, visiblePages, pageObjects]);
|
|
9631
|
+
}, [document2, visiblePages, pageObjects, rotation]);
|
|
9566
9632
|
useEffect20(() => {
|
|
9567
9633
|
if (!scrollToPageRequest || !scrollContainerRef.current || pageInfos.length === 0) return;
|
|
9568
9634
|
const { page, requestId, behavior } = scrollToPageRequest;
|
|
@@ -10127,10 +10193,10 @@ var init_DualPageContainer = __esm({
|
|
|
10127
10193
|
});
|
|
10128
10194
|
|
|
10129
10195
|
// src/components/PDFViewer/BookModeContainer.tsx
|
|
10130
|
-
import React, { memo as memo26, useEffect as useEffect22, useState as useState21, useRef as useRef19, useCallback as useCallback32 } from "react";
|
|
10196
|
+
import React, { memo as memo26, useEffect as useEffect22, useMemo as useMemo14, useState as useState21, useRef as useRef19, useCallback as useCallback32 } from "react";
|
|
10131
10197
|
import HTMLFlipBook from "react-pageflip";
|
|
10132
10198
|
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
10133
|
-
var BookPage, BookModeContainer;
|
|
10199
|
+
var BOOK_MODE_OVERSCAN, BookPage, BookModeContainer;
|
|
10134
10200
|
var init_BookModeContainer = __esm({
|
|
10135
10201
|
"src/components/PDFViewer/BookModeContainer.tsx"() {
|
|
10136
10202
|
"use strict";
|
|
@@ -10138,6 +10204,7 @@ var init_BookModeContainer = __esm({
|
|
|
10138
10204
|
init_PDFLoadingScreen2();
|
|
10139
10205
|
init_hooks();
|
|
10140
10206
|
init_utils();
|
|
10207
|
+
BOOK_MODE_OVERSCAN = 4;
|
|
10141
10208
|
BookPage = React.forwardRef(function BookPage2({ pageNumber, page, scale, rotation, width, height }, ref) {
|
|
10142
10209
|
return /* @__PURE__ */ jsx27("div", { ref, className: "book-page", "data-page-number": pageNumber, children: /* @__PURE__ */ jsx27("div", { style: { width, height, overflow: "hidden" }, children: /* @__PURE__ */ jsx27(
|
|
10143
10210
|
PDFPage,
|
|
@@ -10170,9 +10237,10 @@ var init_BookModeContainer = __esm({
|
|
|
10170
10237
|
} = usePDFViewer();
|
|
10171
10238
|
const scrollToPageRequest = useViewerStore((s) => s.scrollToPageRequest);
|
|
10172
10239
|
const { viewerStore } = usePDFViewerStores();
|
|
10173
|
-
const [pages, setPages] = useState21(
|
|
10240
|
+
const [pages, setPages] = useState21(/* @__PURE__ */ new Map());
|
|
10174
10241
|
const [rawPageDims, setRawPageDims] = useState21({ width: 612, height: 792 });
|
|
10175
|
-
const [
|
|
10242
|
+
const [hasFirstPage, setHasFirstPage] = useState21(false);
|
|
10243
|
+
const pageRequestsRef = useRef19(/* @__PURE__ */ new Set());
|
|
10176
10244
|
const containerRef = useRef19(null);
|
|
10177
10245
|
const [containerSize, setContainerSize] = useState21({ width: 0, height: 0 });
|
|
10178
10246
|
const flipBookRef = useRef19(null);
|
|
@@ -10189,41 +10257,67 @@ var init_BookModeContainer = __esm({
|
|
|
10189
10257
|
return () => ro.disconnect();
|
|
10190
10258
|
}, []);
|
|
10191
10259
|
useEffect22(() => {
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10260
|
+
setPages(/* @__PURE__ */ new Map());
|
|
10261
|
+
pageRequestsRef.current.clear();
|
|
10262
|
+
setHasFirstPage(false);
|
|
10263
|
+
}, [document2]);
|
|
10264
|
+
useEffect22(() => {
|
|
10265
|
+
if (!document2 || numPages === 0) return;
|
|
10266
|
+
const start = Math.max(1, currentPage - BOOK_MODE_OVERSCAN);
|
|
10267
|
+
const end = Math.min(numPages, currentPage + BOOK_MODE_OVERSCAN);
|
|
10268
|
+
const isFirstLoad = !hasFirstPage;
|
|
10196
10269
|
let cancelled = false;
|
|
10197
|
-
const
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10270
|
+
const wanted = [];
|
|
10271
|
+
if (isFirstLoad && !pages.has(1) && !pageRequestsRef.current.has(1)) {
|
|
10272
|
+
wanted.push(1);
|
|
10273
|
+
pageRequestsRef.current.add(1);
|
|
10274
|
+
}
|
|
10275
|
+
for (let i = start; i <= end; i++) {
|
|
10276
|
+
if (pages.has(i) || pageRequestsRef.current.has(i)) continue;
|
|
10277
|
+
wanted.push(i);
|
|
10278
|
+
pageRequestsRef.current.add(i);
|
|
10279
|
+
}
|
|
10280
|
+
if (wanted.length === 0) return;
|
|
10281
|
+
(async () => {
|
|
10282
|
+
const results = await Promise.allSettled(
|
|
10283
|
+
wanted.map((i) => document2.getPage(i).then((p) => [i, p]))
|
|
10284
|
+
);
|
|
10285
|
+
if (cancelled) return;
|
|
10286
|
+
const next = new Map(pages);
|
|
10287
|
+
let firstPageJustLoaded = null;
|
|
10288
|
+
for (const r of results) {
|
|
10289
|
+
if (r.status === "fulfilled") {
|
|
10290
|
+
const [i, page] = r.value;
|
|
10291
|
+
next.set(i, page);
|
|
10292
|
+
if (i === 1) firstPageJustLoaded = page;
|
|
10203
10293
|
}
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
const firstPage = loaded2[0];
|
|
10209
|
-
if (firstPage) {
|
|
10210
|
-
const vp = firstPage.getViewport({ scale: 1, rotation });
|
|
10211
|
-
setRawPageDims({ width: vp.width, height: vp.height });
|
|
10212
|
-
}
|
|
10294
|
+
}
|
|
10295
|
+
for (const i of next.keys()) {
|
|
10296
|
+
if (i !== 1 && (i < start || i > end)) {
|
|
10297
|
+
next.delete(i);
|
|
10213
10298
|
}
|
|
10214
|
-
} catch {
|
|
10215
|
-
} finally {
|
|
10216
|
-
if (!cancelled) setIsLoadingPages(false);
|
|
10217
10299
|
}
|
|
10218
|
-
|
|
10219
|
-
|
|
10300
|
+
setPages(next);
|
|
10301
|
+
if (firstPageJustLoaded) {
|
|
10302
|
+
const vp = firstPageJustLoaded.getViewport({ scale: 1, rotation });
|
|
10303
|
+
setRawPageDims({ width: vp.width, height: vp.height });
|
|
10304
|
+
setHasFirstPage(true);
|
|
10305
|
+
}
|
|
10306
|
+
for (const i of wanted) {
|
|
10307
|
+
pageRequestsRef.current.delete(i);
|
|
10308
|
+
}
|
|
10309
|
+
})();
|
|
10220
10310
|
return () => {
|
|
10221
10311
|
cancelled = true;
|
|
10312
|
+
for (const i of wanted) {
|
|
10313
|
+
pageRequestsRef.current.delete(i);
|
|
10314
|
+
}
|
|
10222
10315
|
};
|
|
10223
|
-
}, [document2, numPages, rotation]);
|
|
10316
|
+
}, [document2, numPages, currentPage, rotation, pages, hasFirstPage]);
|
|
10224
10317
|
useEffect22(() => {
|
|
10225
|
-
|
|
10226
|
-
|
|
10318
|
+
const firstPage = pages.get(1);
|
|
10319
|
+
if (firstPage) {
|
|
10320
|
+
const vp = firstPage.getViewport({ scale: 1, rotation });
|
|
10227
10321
|
setRawPageDims({ width: vp.width, height: vp.height });
|
|
10228
10322
|
}
|
|
10229
10323
|
}, [pages, rotation]);
|
|
@@ -10274,8 +10368,28 @@ var init_BookModeContainer = __esm({
|
|
|
10274
10368
|
sepia: "bg-amber-50"
|
|
10275
10369
|
};
|
|
10276
10370
|
const themeClass = theme === "dark" ? "dark" : theme === "sepia" ? "sepia" : "";
|
|
10277
|
-
const ready = !!document2 &&
|
|
10371
|
+
const ready = !!document2 && hasFirstPage;
|
|
10278
10372
|
const hasContainer = containerSize.width > 0 && containerSize.height > 0;
|
|
10373
|
+
const pageChildren = useMemo14(() => {
|
|
10374
|
+
if (numPages === 0) return null;
|
|
10375
|
+
const out = new Array(numPages);
|
|
10376
|
+
for (let i = 0; i < numPages; i++) {
|
|
10377
|
+
const pageNumber = i + 1;
|
|
10378
|
+
out[i] = /* @__PURE__ */ jsx27(
|
|
10379
|
+
BookPage,
|
|
10380
|
+
{
|
|
10381
|
+
pageNumber,
|
|
10382
|
+
page: pages.get(pageNumber) ?? null,
|
|
10383
|
+
scale: renderScale,
|
|
10384
|
+
rotation,
|
|
10385
|
+
width: displayWidth,
|
|
10386
|
+
height: displayHeight
|
|
10387
|
+
},
|
|
10388
|
+
pageNumber
|
|
10389
|
+
);
|
|
10390
|
+
}
|
|
10391
|
+
return out;
|
|
10392
|
+
}, [numPages, pages, renderScale, rotation, displayWidth, displayHeight]);
|
|
10279
10393
|
return /* @__PURE__ */ jsxs23(
|
|
10280
10394
|
"div",
|
|
10281
10395
|
{
|
|
@@ -10325,18 +10439,7 @@ var init_BookModeContainer = __esm({
|
|
|
10325
10439
|
autoSize: false,
|
|
10326
10440
|
renderOnlyPageLengthChange: false,
|
|
10327
10441
|
disableFlipByClick: false,
|
|
10328
|
-
children:
|
|
10329
|
-
BookPage,
|
|
10330
|
-
{
|
|
10331
|
-
pageNumber: index + 1,
|
|
10332
|
-
page,
|
|
10333
|
-
scale: renderScale,
|
|
10334
|
-
rotation,
|
|
10335
|
-
width: displayWidth,
|
|
10336
|
-
height: displayHeight
|
|
10337
|
-
},
|
|
10338
|
-
index
|
|
10339
|
-
))
|
|
10442
|
+
children: pageChildren
|
|
10340
10443
|
}
|
|
10341
10444
|
)
|
|
10342
10445
|
]
|
|
@@ -12512,7 +12615,7 @@ var AskAboutTrigger = memo36(function AskAboutTrigger2({
|
|
|
12512
12615
|
// src/components/Minimap/Minimap.tsx
|
|
12513
12616
|
init_hooks();
|
|
12514
12617
|
init_utils();
|
|
12515
|
-
import { memo as memo37, useMemo as
|
|
12618
|
+
import { memo as memo37, useMemo as useMemo15, useCallback as useCallback41 } from "react";
|
|
12516
12619
|
import { Fragment as Fragment3, jsx as jsx38, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
12517
12620
|
var PageIndicator = memo37(function PageIndicator2({
|
|
12518
12621
|
pageNumber,
|
|
@@ -12563,7 +12666,7 @@ var Minimap = memo37(function Minimap2({
|
|
|
12563
12666
|
const currentPage = useViewerStore((s) => s.currentPage);
|
|
12564
12667
|
const numPages = useViewerStore((s) => s.numPages);
|
|
12565
12668
|
const goToPage = useViewerStore((s) => s.goToPage);
|
|
12566
|
-
const bookmarkedPages =
|
|
12669
|
+
const bookmarkedPages = useMemo15(() => {
|
|
12567
12670
|
return new Set(bookmarks.map((b) => b.pageNumber));
|
|
12568
12671
|
}, [bookmarks]);
|
|
12569
12672
|
const compact = numPages > 50;
|
|
@@ -12583,7 +12686,7 @@ var Minimap = memo37(function Minimap2({
|
|
|
12583
12686
|
},
|
|
12584
12687
|
[currentPage, visitedPages, bookmarkedPages]
|
|
12585
12688
|
);
|
|
12586
|
-
const pageIndicators =
|
|
12689
|
+
const pageIndicators = useMemo15(() => {
|
|
12587
12690
|
const pages = [];
|
|
12588
12691
|
for (let i = 1; i <= numPages; i++) {
|
|
12589
12692
|
pages.push(
|
|
@@ -13085,7 +13188,7 @@ init_PDFLoadingScreen2();
|
|
|
13085
13188
|
// src/components/TutorMode/TutorModeContainer.tsx
|
|
13086
13189
|
init_PDFPage2();
|
|
13087
13190
|
init_hooks();
|
|
13088
|
-
import { useEffect as useEffect28, useMemo as
|
|
13191
|
+
import { useEffect as useEffect28, useMemo as useMemo16, useRef as useRef27, useState as useState30 } from "react";
|
|
13089
13192
|
import { useStore as useStore2 } from "zustand";
|
|
13090
13193
|
|
|
13091
13194
|
// src/components/TutorMode/CameraView.tsx
|
|
@@ -14811,6 +14914,7 @@ function SubtitleBar({ text }) {
|
|
|
14811
14914
|
// src/director/storyboard-engine.ts
|
|
14812
14915
|
init_narration_store();
|
|
14813
14916
|
init_camera_math();
|
|
14917
|
+
init_mobile_config();
|
|
14814
14918
|
var DEFAULT_MIN_OVERLAY_MS = 3500;
|
|
14815
14919
|
var StoryboardEngine = class {
|
|
14816
14920
|
constructor(deps) {
|
|
@@ -14830,6 +14934,7 @@ var StoryboardEngine = class {
|
|
|
14830
14934
|
this.overlayRemovalTimers = /* @__PURE__ */ new Map();
|
|
14831
14935
|
this.currentStoryboardId = 0;
|
|
14832
14936
|
this.deps = deps;
|
|
14937
|
+
this.singleActiveOverlay = deps.singleActiveOverlay ?? isIOSMobile();
|
|
14833
14938
|
}
|
|
14834
14939
|
/**
|
|
14835
14940
|
* Execute a new storyboard. Cancels in-flight steps from the previous storyboard
|
|
@@ -14999,6 +15104,10 @@ var StoryboardEngine = class {
|
|
|
14999
15104
|
createdAt: Date.now(),
|
|
15000
15105
|
expiresAt: Date.now() + visibleMs
|
|
15001
15106
|
};
|
|
15107
|
+
if (this.singleActiveOverlay) {
|
|
15108
|
+
this.cancelAllRemovalTimers();
|
|
15109
|
+
narrationStore.getState().clearOverlays();
|
|
15110
|
+
}
|
|
15002
15111
|
narrationStore.getState().addOverlay(overlay);
|
|
15003
15112
|
const timer = setTimeout(() => {
|
|
15004
15113
|
narrationStore.getState().removeOverlay(overlay.id);
|
|
@@ -16071,7 +16180,7 @@ function TutorModeContainer({
|
|
|
16071
16180
|
className
|
|
16072
16181
|
}) {
|
|
16073
16182
|
const containerRef = useRef27(null);
|
|
16074
|
-
const index =
|
|
16183
|
+
const index = useMemo16(() => buildBBoxIndex(bboxData), [bboxData]);
|
|
16075
16184
|
const {
|
|
16076
16185
|
document: document2,
|
|
16077
16186
|
currentPage: viewerCurrentPage,
|