@papyrus-sdk/ui-react-native 0.2.11 → 0.2.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/LICENSE +21 -0
- package/README.md +12 -2
- package/dist/chunk-GCVUTXFR.mjs +63 -0
- package/dist/chunk-GCVUTXFR.mjs.map +1 -0
- package/dist/chunk-PE5U4ZWV.mjs +101 -0
- package/dist/chunk-PE5U4ZWV.mjs.map +1 -0
- package/dist/chunk-ZD7AOCMD.mjs +9 -0
- package/dist/chunk-ZD7AOCMD.mjs.map +1 -0
- package/dist/gesture/pinchZoom.js +135 -0
- package/dist/gesture/pinchZoom.js.map +1 -0
- package/dist/gesture/pinchZoom.mjs +30 -0
- package/dist/gesture/pinchZoom.mjs.map +1 -0
- package/dist/gesture/selectionInteraction.js +90 -0
- package/dist/gesture/selectionInteraction.js.map +1 -0
- package/dist/gesture/selectionInteraction.mjs +16 -0
- package/dist/gesture/selectionInteraction.mjs.map +1 -0
- package/dist/index.d.mts +11 -73
- package/dist/index.d.ts +11 -73
- package/dist/index.js +1284 -287
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1172 -280
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -7
package/dist/index.js
CHANGED
|
@@ -21033,11 +21033,13 @@ module.exports = __toCommonJS(ui_react_native_exports);
|
|
|
21033
21033
|
// components/Viewer.tsx
|
|
21034
21034
|
var import_react3 = require("react");
|
|
21035
21035
|
var import_react_native3 = require("react-native");
|
|
21036
|
+
var import_react_native_gesture_handler2 = require("react-native-gesture-handler");
|
|
21036
21037
|
var import_core3 = require("@papyrus-sdk/core");
|
|
21037
21038
|
|
|
21038
21039
|
// components/PageRenderer.tsx
|
|
21039
21040
|
var import_react = require("react");
|
|
21040
21041
|
var import_react_native = require("react-native");
|
|
21042
|
+
var import_react_native_gesture_handler = require("react-native-gesture-handler");
|
|
21041
21043
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
21042
21044
|
var import_core = require("@papyrus-sdk/core");
|
|
21043
21045
|
var import_engine_native = require("@papyrus-sdk/engine-native");
|
|
@@ -21224,6 +21226,126 @@ var createScrollPerfMonitor = (scope, label = "scroll") => {
|
|
|
21224
21226
|
};
|
|
21225
21227
|
var logPerfEvent = logPerf;
|
|
21226
21228
|
|
|
21229
|
+
// gesture/pinchZoom.ts
|
|
21230
|
+
var DEFAULT_PINCH_ZOOM_BOUNDS = {
|
|
21231
|
+
minZoom: 0.5,
|
|
21232
|
+
maxZoom: 4
|
|
21233
|
+
};
|
|
21234
|
+
var PINCH_PRESS_SUPPRESSION_MS = 120;
|
|
21235
|
+
var clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
21236
|
+
var resolvePinchPreviewScale = (startZoom, previewZoom) => {
|
|
21237
|
+
const safeStartZoom = Math.max(1e-4, Math.abs(startZoom));
|
|
21238
|
+
return previewZoom / safeStartZoom;
|
|
21239
|
+
};
|
|
21240
|
+
var sanitizePinchPreviewScale = (value) => {
|
|
21241
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
21242
|
+
return 1;
|
|
21243
|
+
}
|
|
21244
|
+
return value;
|
|
21245
|
+
};
|
|
21246
|
+
var resolvePinchGestureZoom = (startZoom, scaleFactor, bounds = DEFAULT_PINCH_ZOOM_BOUNDS) => clamp(
|
|
21247
|
+
(Number.isFinite(startZoom) && startZoom > 0 ? startZoom : 1) * (Number.isFinite(scaleFactor) && scaleFactor > 0 ? scaleFactor : 1),
|
|
21248
|
+
bounds.minZoom,
|
|
21249
|
+
bounds.maxZoom
|
|
21250
|
+
);
|
|
21251
|
+
var resolveAnchoredViewportOffset = ({
|
|
21252
|
+
viewportOffset,
|
|
21253
|
+
startScrollOffset,
|
|
21254
|
+
startItemOffset,
|
|
21255
|
+
startItemLength,
|
|
21256
|
+
endItemOffset,
|
|
21257
|
+
endItemLength,
|
|
21258
|
+
viewportLength,
|
|
21259
|
+
endContentLength
|
|
21260
|
+
}) => {
|
|
21261
|
+
const safeViewportOffset = Number.isFinite(viewportOffset) ? viewportOffset : 0;
|
|
21262
|
+
const safeStartScrollOffset = Number.isFinite(startScrollOffset) ? startScrollOffset : 0;
|
|
21263
|
+
const safeStartItemOffset = Number.isFinite(startItemOffset) ? startItemOffset : 0;
|
|
21264
|
+
const safeStartItemLength = Number.isFinite(startItemLength) && startItemLength > 0 ? startItemLength : 1;
|
|
21265
|
+
const safeEndItemOffset = Number.isFinite(endItemOffset) ? endItemOffset : 0;
|
|
21266
|
+
const safeEndItemLength = Number.isFinite(endItemLength) && endItemLength > 0 ? endItemLength : 1;
|
|
21267
|
+
const safeViewportLength = Number.isFinite(viewportLength) && viewportLength > 0 ? viewportLength : 0;
|
|
21268
|
+
const safeEndContentLength = Number.isFinite(endContentLength) && endContentLength > 0 ? endContentLength : safeEndItemOffset + safeEndItemLength;
|
|
21269
|
+
const contentPoint = safeStartScrollOffset + safeViewportOffset - safeStartItemOffset;
|
|
21270
|
+
const normalizedPoint = clamp(contentPoint / safeStartItemLength, 0, 1);
|
|
21271
|
+
const anchoredContentPoint = safeEndItemOffset + normalizedPoint * safeEndItemLength;
|
|
21272
|
+
return clamp(
|
|
21273
|
+
anchoredContentPoint - safeViewportOffset,
|
|
21274
|
+
0,
|
|
21275
|
+
Math.max(0, safeEndContentLength - safeViewportLength)
|
|
21276
|
+
);
|
|
21277
|
+
};
|
|
21278
|
+
var resolveClampedScrollOffset = (offset, contentLength, viewportLength) => {
|
|
21279
|
+
const safeOffset = Number.isFinite(offset) ? offset : 0;
|
|
21280
|
+
const safeContentLength = Number.isFinite(contentLength) && contentLength > 0 ? contentLength : 0;
|
|
21281
|
+
const safeViewportLength = Number.isFinite(viewportLength) && viewportLength > 0 ? viewportLength : 0;
|
|
21282
|
+
return clamp(
|
|
21283
|
+
safeOffset,
|
|
21284
|
+
0,
|
|
21285
|
+
Math.max(0, safeContentLength - safeViewportLength)
|
|
21286
|
+
);
|
|
21287
|
+
};
|
|
21288
|
+
var shouldSuppressPressAfterPinch = (lastPinchEndedAt, now = Date.now(), windowMs = PINCH_PRESS_SUPPRESSION_MS) => {
|
|
21289
|
+
if (typeof lastPinchEndedAt !== "number") return false;
|
|
21290
|
+
const elapsedMs = now - lastPinchEndedAt;
|
|
21291
|
+
return elapsedMs >= 0 && elapsedMs < windowMs;
|
|
21292
|
+
};
|
|
21293
|
+
|
|
21294
|
+
// gesture/selectionInteraction.ts
|
|
21295
|
+
var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
21296
|
+
var DRAG_SELECTION_TOOLS = /* @__PURE__ */ new Set([
|
|
21297
|
+
"highlight",
|
|
21298
|
+
"underline",
|
|
21299
|
+
"squiggly",
|
|
21300
|
+
"strikeout"
|
|
21301
|
+
]);
|
|
21302
|
+
var resolveAxisAutoscroll = (coordinate, size, threshold, maxStep) => {
|
|
21303
|
+
if (size <= 0 || threshold <= 0 || maxStep <= 0) return 0;
|
|
21304
|
+
const startDistance = clamp2(coordinate, 0, size);
|
|
21305
|
+
if (startDistance < threshold) {
|
|
21306
|
+
const intensity = 1 - startDistance / threshold;
|
|
21307
|
+
return -Math.round(maxStep * intensity);
|
|
21308
|
+
}
|
|
21309
|
+
const endDistance = clamp2(size - coordinate, 0, size);
|
|
21310
|
+
if (endDistance < threshold) {
|
|
21311
|
+
const intensity = 1 - endDistance / threshold;
|
|
21312
|
+
return Math.round(maxStep * intensity);
|
|
21313
|
+
}
|
|
21314
|
+
return 0;
|
|
21315
|
+
};
|
|
21316
|
+
var shouldEnableViewerScroll = ({
|
|
21317
|
+
selectionDragActive,
|
|
21318
|
+
gestureScrollLockActive = false
|
|
21319
|
+
}) => !selectionDragActive && !gestureScrollLockActive;
|
|
21320
|
+
var shouldEnableSelectionDrag = ({
|
|
21321
|
+
activeTool,
|
|
21322
|
+
interactionMode
|
|
21323
|
+
}) => DRAG_SELECTION_TOOLS.has(activeTool) || activeTool === "select" && interactionMode === "select";
|
|
21324
|
+
var isToolDockToolSelected = ({
|
|
21325
|
+
activeTool,
|
|
21326
|
+
interactionMode,
|
|
21327
|
+
toolId
|
|
21328
|
+
}) => toolId === "select" ? activeTool === "select" && interactionMode === "select" : activeTool === toolId;
|
|
21329
|
+
var getToolDockDismissState = ({
|
|
21330
|
+
activeTool,
|
|
21331
|
+
interactionMode
|
|
21332
|
+
}) => ({
|
|
21333
|
+
toolDockOpen: false,
|
|
21334
|
+
activeTool,
|
|
21335
|
+
interactionMode: activeTool === "select" && interactionMode === "select" ? "pan" : interactionMode
|
|
21336
|
+
});
|
|
21337
|
+
var getSelectionEdgeAutoscroll = ({
|
|
21338
|
+
x,
|
|
21339
|
+
y,
|
|
21340
|
+
width,
|
|
21341
|
+
height,
|
|
21342
|
+
threshold,
|
|
21343
|
+
maxStep
|
|
21344
|
+
}) => ({
|
|
21345
|
+
dx: resolveAxisAutoscroll(x, width, threshold, maxStep),
|
|
21346
|
+
dy: resolveAxisAutoscroll(y, height, threshold, maxStep)
|
|
21347
|
+
});
|
|
21348
|
+
|
|
21227
21349
|
// components/PageRenderer.tsx
|
|
21228
21350
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
21229
21351
|
var TEXT_MARKUP_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -21286,6 +21408,9 @@ var buildSquigglyPath = (segments = 16) => {
|
|
|
21286
21408
|
return path;
|
|
21287
21409
|
};
|
|
21288
21410
|
var SQUIGGLY_PATH = buildSquigglyPath();
|
|
21411
|
+
var SELECTION_EDGE_THRESHOLD_PX = 48;
|
|
21412
|
+
var SELECTION_EDGE_MAX_STEP_PX = 24;
|
|
21413
|
+
var SELECTION_AUTOSCROLL_INTERVAL_MS = 16;
|
|
21289
21414
|
var PageRenderer = ({
|
|
21290
21415
|
engine,
|
|
21291
21416
|
pageIndex,
|
|
@@ -21293,26 +21418,37 @@ var PageRenderer = ({
|
|
|
21293
21418
|
PageViewComponent = import_engine_native.PapyrusPageView,
|
|
21294
21419
|
availableWidth,
|
|
21295
21420
|
horizontalPadding = 16,
|
|
21296
|
-
spacing = 24
|
|
21421
|
+
spacing = 24,
|
|
21422
|
+
onSelectionDragActiveChange,
|
|
21423
|
+
gestureScrollLockActive = false,
|
|
21424
|
+
lastPinchEndedAt = null,
|
|
21425
|
+
onHorizontalScrollOffsetChange,
|
|
21426
|
+
horizontalScrollRestore = null,
|
|
21427
|
+
requestSelectionVerticalAutoscroll
|
|
21297
21428
|
}) => {
|
|
21298
21429
|
const viewRef = (0, import_react.useRef)(null);
|
|
21430
|
+
const pageScrollRef = (0, import_react.useRef)(null);
|
|
21299
21431
|
const [layout, setLayout] = (0, import_react.useState)({ width: 0, height: 0 });
|
|
21300
21432
|
const [pageSize, setPageSize] = (0, import_react.useState)(null);
|
|
21301
21433
|
const { width: windowWidth } = (0, import_react_native.useWindowDimensions)();
|
|
21302
21434
|
const isNative = import_react_native.Platform.OS === "android" || import_react_native.Platform.OS === "ios";
|
|
21303
21435
|
const perfEnabled = isMobilePerfEnabled();
|
|
21304
21436
|
const renderCountRef = (0, import_react.useRef)(0);
|
|
21305
|
-
const
|
|
21306
|
-
|
|
21307
|
-
);
|
|
21437
|
+
const inkDrawingActiveRef = (0, import_react.useRef)(false);
|
|
21438
|
+
const horizontalScrollOffsetRef = (0, import_react.useRef)(0);
|
|
21439
|
+
const selectionDragActiveRef = (0, import_react.useRef)(false);
|
|
21440
|
+
const selectionDragPointRef = (0, import_react.useRef)(null);
|
|
21441
|
+
const lastAppliedHorizontalRestoreRef = (0, import_react.useRef)(null);
|
|
21442
|
+
const selectionAutoscrollIntervalRef = (0, import_react.useRef)(null);
|
|
21443
|
+
const rawTouchMoveLoggedAtRef = (0, import_react.useRef)(0);
|
|
21308
21444
|
const zoom = (0, import_core.useViewerStore)((state) => state.zoom);
|
|
21309
21445
|
const rotation = (0, import_core.useViewerStore)((state) => state.rotation);
|
|
21310
21446
|
const pageTheme = (0, import_core.useViewerStore)((state) => state.pageTheme);
|
|
21311
21447
|
const annotations = (0, import_core.useViewerStore)((state) => state.annotations);
|
|
21312
21448
|
const annotationColor = (0, import_core.useViewerStore)((state) => state.annotationColor);
|
|
21313
21449
|
const addAnnotation = (0, import_core.useViewerStore)((state) => state.addAnnotation);
|
|
21314
|
-
const setDocumentState = (0, import_core.useViewerStore)((state) => state.setDocumentState);
|
|
21315
21450
|
const activeTool = (0, import_core.useViewerStore)((state) => state.activeTool);
|
|
21451
|
+
const interactionMode = (0, import_core.useViewerStore)((state) => state.interactionMode);
|
|
21316
21452
|
const accentColor = (0, import_core.useViewerStore)((state) => state.accentColor);
|
|
21317
21453
|
const selectedAnnotationId = (0, import_core.useViewerStore)(
|
|
21318
21454
|
(state) => state.selectedAnnotationId
|
|
@@ -21326,19 +21462,6 @@ var PageRenderer = ({
|
|
|
21326
21462
|
const setSelectionActive = (0, import_core.useViewerStore)(
|
|
21327
21463
|
(state) => state.setSelectionActive
|
|
21328
21464
|
);
|
|
21329
|
-
const setDocumentStateTracked = (0, import_react.useCallback)(
|
|
21330
|
-
(state, reason) => {
|
|
21331
|
-
if (perfEnabled) {
|
|
21332
|
-
setStateBurstRef.current({
|
|
21333
|
-
reason,
|
|
21334
|
-
page: pageIndex + 1,
|
|
21335
|
-
keys: Object.keys(state).join(",")
|
|
21336
|
-
});
|
|
21337
|
-
}
|
|
21338
|
-
setDocumentState(state);
|
|
21339
|
-
},
|
|
21340
|
-
[pageIndex, perfEnabled, setDocumentState]
|
|
21341
|
-
);
|
|
21342
21465
|
const logSelectionPerf = (0, import_react.useCallback)(
|
|
21343
21466
|
(event, payload) => {
|
|
21344
21467
|
if (!perfEnabled) return;
|
|
@@ -21349,6 +21472,56 @@ var PageRenderer = ({
|
|
|
21349
21472
|
},
|
|
21350
21473
|
[pageIndex, perfEnabled]
|
|
21351
21474
|
);
|
|
21475
|
+
const logGestureDebug = (0, import_react.useCallback)(
|
|
21476
|
+
(event, payload) => {
|
|
21477
|
+
if (!perfEnabled || !isNative) return;
|
|
21478
|
+
logPerfEvent("PageRenderer", `gesture.${event}`, {
|
|
21479
|
+
page: pageIndex + 1,
|
|
21480
|
+
activeTool,
|
|
21481
|
+
interactionMode,
|
|
21482
|
+
pinchActive: gestureScrollLockActive,
|
|
21483
|
+
gestureLockActive: gestureScrollLockActive,
|
|
21484
|
+
selectionEnabled: import_react_native.Platform.OS === "web" || isNative && shouldEnableSelectionDrag({
|
|
21485
|
+
activeTool,
|
|
21486
|
+
interactionMode
|
|
21487
|
+
}),
|
|
21488
|
+
zoom: Math.round(zoom * 100) / 100,
|
|
21489
|
+
...payload
|
|
21490
|
+
});
|
|
21491
|
+
},
|
|
21492
|
+
[activeTool, interactionMode, isNative, pageIndex, perfEnabled, zoom]
|
|
21493
|
+
);
|
|
21494
|
+
const logRawTouchDebug = (0, import_react.useCallback)(
|
|
21495
|
+
(phase, event) => {
|
|
21496
|
+
if (!perfEnabled || !isNative) return;
|
|
21497
|
+
const touches = Array.isArray(event?.nativeEvent?.touches) ? event.nativeEvent.touches.length : 0;
|
|
21498
|
+
const changedTouches = Array.isArray(event?.nativeEvent?.changedTouches) ? event.nativeEvent.changedTouches.length : 0;
|
|
21499
|
+
if (phase === "move") {
|
|
21500
|
+
if (touches < 2 && !gestureScrollLockActive) return;
|
|
21501
|
+
const now = Date.now();
|
|
21502
|
+
if (now - rawTouchMoveLoggedAtRef.current < 120) return;
|
|
21503
|
+
rawTouchMoveLoggedAtRef.current = now;
|
|
21504
|
+
}
|
|
21505
|
+
logGestureDebug(`touch.${phase}`, {
|
|
21506
|
+
touches,
|
|
21507
|
+
changedTouches,
|
|
21508
|
+
target: event?.nativeEvent?.target ?? null,
|
|
21509
|
+
locationX: Math.round((event?.nativeEvent?.locationX ?? 0) * 100) / 100,
|
|
21510
|
+
locationY: Math.round((event?.nativeEvent?.locationY ?? 0) * 100) / 100,
|
|
21511
|
+
pageX: Math.round((event?.nativeEvent?.pageX ?? 0) * 100) / 100,
|
|
21512
|
+
pageY: Math.round((event?.nativeEvent?.pageY ?? 0) * 100) / 100
|
|
21513
|
+
});
|
|
21514
|
+
},
|
|
21515
|
+
[isNative, logGestureDebug, perfEnabled]
|
|
21516
|
+
);
|
|
21517
|
+
const setSelectionDragState = (0, import_react.useCallback)(
|
|
21518
|
+
(active) => {
|
|
21519
|
+
if (selectionDragActiveRef.current === active) return;
|
|
21520
|
+
selectionDragActiveRef.current = active;
|
|
21521
|
+
onSelectionDragActiveChange?.(active);
|
|
21522
|
+
},
|
|
21523
|
+
[onSelectionDragActiveChange]
|
|
21524
|
+
);
|
|
21352
21525
|
const pageAnnotations = (0, import_react.useMemo)(
|
|
21353
21526
|
() => annotations.filter((ann) => ann.pageIndex === pageIndex),
|
|
21354
21527
|
[annotations, pageIndex]
|
|
@@ -21377,12 +21550,6 @@ var PageRenderer = ({
|
|
|
21377
21550
|
const selectionRectRef = (0, import_react.useRef)(null);
|
|
21378
21551
|
const selectionBoundsRef = (0, import_react.useRef)(null);
|
|
21379
21552
|
const selectionBoundsStart = (0, import_react.useRef)(null);
|
|
21380
|
-
const lastTapRef = (0, import_react.useRef)(
|
|
21381
|
-
null
|
|
21382
|
-
);
|
|
21383
|
-
const pinchRef = (0, import_react.useRef)(null);
|
|
21384
|
-
const isPinchingRef = (0, import_react.useRef)(false);
|
|
21385
|
-
const pinchLogZoomRef = (0, import_react.useRef)(zoom);
|
|
21386
21553
|
const [isInkDrawing, setIsInkDrawing] = (0, import_react.useState)(false);
|
|
21387
21554
|
const [inkPoints, setInkPoints] = (0, import_react.useState)(
|
|
21388
21555
|
[]
|
|
@@ -21480,7 +21647,7 @@ var PageRenderer = ({
|
|
|
21480
21647
|
createdAt: Date.now()
|
|
21481
21648
|
});
|
|
21482
21649
|
};
|
|
21483
|
-
const
|
|
21650
|
+
const clamp3 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
21484
21651
|
const getBoundsFromRects = (rects) => {
|
|
21485
21652
|
let minX = 1;
|
|
21486
21653
|
let minY = 1;
|
|
@@ -21494,10 +21661,10 @@ var PageRenderer = ({
|
|
|
21494
21661
|
});
|
|
21495
21662
|
if (maxX <= minX || maxY <= minY) return null;
|
|
21496
21663
|
return {
|
|
21497
|
-
x:
|
|
21498
|
-
y:
|
|
21499
|
-
width:
|
|
21500
|
-
height:
|
|
21664
|
+
x: clamp3(minX, 0, 1),
|
|
21665
|
+
y: clamp3(minY, 0, 1),
|
|
21666
|
+
width: clamp3(maxX - minX, 0, 1),
|
|
21667
|
+
height: clamp3(maxY - minY, 0, 1)
|
|
21501
21668
|
};
|
|
21502
21669
|
};
|
|
21503
21670
|
(0, import_react.useEffect)(() => {
|
|
@@ -21505,11 +21672,30 @@ var PageRenderer = ({
|
|
|
21505
21672
|
}, [inkPoints]);
|
|
21506
21673
|
(0, import_react.useEffect)(() => {
|
|
21507
21674
|
if (activeTool === "ink") return;
|
|
21675
|
+
inkDrawingActiveRef.current = false;
|
|
21508
21676
|
setIsInkDrawing(false);
|
|
21509
21677
|
setInkPoints([]);
|
|
21510
21678
|
inkPointsRef.current = [];
|
|
21511
21679
|
}, [activeTool]);
|
|
21512
|
-
const
|
|
21680
|
+
const pageViewportWidth = Math.max(
|
|
21681
|
+
0,
|
|
21682
|
+
(availableWidth ?? windowWidth) - horizontalPadding * 2
|
|
21683
|
+
);
|
|
21684
|
+
const selectionEnabled = import_react_native.Platform.OS === "web" || isNative && shouldEnableSelectionDrag({
|
|
21685
|
+
activeTool,
|
|
21686
|
+
interactionMode
|
|
21687
|
+
});
|
|
21688
|
+
const inkEnabled = isNative && activeTool === "ink";
|
|
21689
|
+
const stopSelectionAutoscroll = (0, import_react.useCallback)(() => {
|
|
21690
|
+
if (selectionAutoscrollIntervalRef.current) {
|
|
21691
|
+
clearInterval(selectionAutoscrollIntervalRef.current);
|
|
21692
|
+
selectionAutoscrollIntervalRef.current = null;
|
|
21693
|
+
}
|
|
21694
|
+
}, []);
|
|
21695
|
+
const clearSelection = (0, import_react.useCallback)(() => {
|
|
21696
|
+
stopSelectionAutoscroll();
|
|
21697
|
+
selectionDragPointRef.current = null;
|
|
21698
|
+
setSelectionDragState(false);
|
|
21513
21699
|
setSelectionRect(null);
|
|
21514
21700
|
selectionRectRef.current = null;
|
|
21515
21701
|
setSelectionRects([]);
|
|
@@ -21519,13 +21705,19 @@ var PageRenderer = ({
|
|
|
21519
21705
|
setIsSelecting(false);
|
|
21520
21706
|
selectionStart.current = null;
|
|
21521
21707
|
selectionBoundsStart.current = null;
|
|
21522
|
-
lastTapRef.current = null;
|
|
21523
21708
|
setSelectionActive(false);
|
|
21524
|
-
};
|
|
21709
|
+
}, [setSelectionActive, setSelectionDragState, stopSelectionAutoscroll]);
|
|
21525
21710
|
(0, import_react.useEffect)(() => {
|
|
21526
21711
|
if (activeTool === "select") return;
|
|
21527
21712
|
clearSelection();
|
|
21528
21713
|
}, [activeTool]);
|
|
21714
|
+
(0, import_react.useEffect)(
|
|
21715
|
+
() => () => {
|
|
21716
|
+
stopSelectionAutoscroll();
|
|
21717
|
+
setSelectionDragState(false);
|
|
21718
|
+
},
|
|
21719
|
+
[setSelectionDragState, stopSelectionAutoscroll]
|
|
21720
|
+
);
|
|
21529
21721
|
const stopPressPropagation = (event) => {
|
|
21530
21722
|
event.stopPropagation?.();
|
|
21531
21723
|
};
|
|
@@ -21592,8 +21784,8 @@ var PageRenderer = ({
|
|
|
21592
21784
|
if (!layout.width || !layout.height) return;
|
|
21593
21785
|
const size = 26;
|
|
21594
21786
|
const half = size / 2;
|
|
21595
|
-
const left =
|
|
21596
|
-
const top =
|
|
21787
|
+
const left = clamp3(x - half, 0, Math.max(0, layout.width - size));
|
|
21788
|
+
const top = clamp3(y - half, 0, Math.max(0, layout.height - size));
|
|
21597
21789
|
const bounds = {
|
|
21598
21790
|
x: left / layout.width,
|
|
21599
21791
|
y: top / layout.height,
|
|
@@ -21602,50 +21794,193 @@ var PageRenderer = ({
|
|
|
21602
21794
|
};
|
|
21603
21795
|
await selectFromBounds(bounds);
|
|
21604
21796
|
};
|
|
21605
|
-
const
|
|
21606
|
-
|
|
21607
|
-
|
|
21608
|
-
|
|
21609
|
-
|
|
21610
|
-
|
|
21611
|
-
|
|
21612
|
-
|
|
21613
|
-
|
|
21614
|
-
|
|
21615
|
-
|
|
21616
|
-
|
|
21617
|
-
|
|
21618
|
-
|
|
21619
|
-
|
|
21797
|
+
const cancelSelectionDrag = (0, import_react.useCallback)(() => {
|
|
21798
|
+
stopSelectionAutoscroll();
|
|
21799
|
+
selectionDragPointRef.current = null;
|
|
21800
|
+
setSelectionDragState(false);
|
|
21801
|
+
setIsSelecting(false);
|
|
21802
|
+
selectionStart.current = null;
|
|
21803
|
+
selectionRectRef.current = null;
|
|
21804
|
+
setSelectionRect(null);
|
|
21805
|
+
}, [setSelectionDragState, stopSelectionAutoscroll]);
|
|
21806
|
+
const updateSelectionRectFromPoint = (0, import_react.useCallback)(
|
|
21807
|
+
(x, y) => {
|
|
21808
|
+
const start = selectionStart.current;
|
|
21809
|
+
if (!start || !layout.width || !layout.height) return;
|
|
21810
|
+
const left = Math.max(0, Math.min(start.x, x));
|
|
21811
|
+
const top = Math.max(0, Math.min(start.y, y));
|
|
21812
|
+
const right = Math.min(layout.width, Math.max(start.x, x));
|
|
21813
|
+
const bottom = Math.min(layout.height, Math.max(start.y, y));
|
|
21814
|
+
const rect = {
|
|
21815
|
+
x: left,
|
|
21816
|
+
y: top,
|
|
21817
|
+
width: right - left,
|
|
21818
|
+
height: bottom - top
|
|
21819
|
+
};
|
|
21820
|
+
selectionRectRef.current = rect;
|
|
21821
|
+
setSelectionRect(rect);
|
|
21822
|
+
},
|
|
21823
|
+
[layout.height, layout.width]
|
|
21824
|
+
);
|
|
21825
|
+
const applySelectionEdgeAutoscroll = (0, import_react.useCallback)(() => {
|
|
21826
|
+
const point = selectionDragPointRef.current;
|
|
21827
|
+
if (!point || !selectionStart.current || !layout.width || !layout.height) {
|
|
21828
|
+
stopSelectionAutoscroll();
|
|
21829
|
+
return;
|
|
21830
|
+
}
|
|
21831
|
+
const visibleX = point.x - horizontalScrollOffsetRef.current;
|
|
21832
|
+
const { dx } = getSelectionEdgeAutoscroll({
|
|
21833
|
+
x: visibleX,
|
|
21834
|
+
y: SELECTION_EDGE_THRESHOLD_PX,
|
|
21835
|
+
width: pageViewportWidth,
|
|
21836
|
+
height: SELECTION_EDGE_THRESHOLD_PX * 2,
|
|
21837
|
+
threshold: SELECTION_EDGE_THRESHOLD_PX,
|
|
21838
|
+
maxStep: SELECTION_EDGE_MAX_STEP_PX
|
|
21620
21839
|
});
|
|
21621
|
-
|
|
21622
|
-
|
|
21623
|
-
|
|
21624
|
-
|
|
21625
|
-
|
|
21626
|
-
|
|
21627
|
-
|
|
21628
|
-
|
|
21629
|
-
|
|
21630
|
-
|
|
21631
|
-
|
|
21632
|
-
|
|
21633
|
-
|
|
21634
|
-
distance: Math.round(distance * 100) / 100,
|
|
21635
|
-
zoom: Math.round(nextZoom * 100) / 100
|
|
21636
|
-
});
|
|
21840
|
+
let appliedDx = 0;
|
|
21841
|
+
if (dx !== 0 && pageViewportWidth > 0) {
|
|
21842
|
+
const maxOffsetX = Math.max(0, layout.width - pageViewportWidth);
|
|
21843
|
+
const nextOffsetX = clamp3(
|
|
21844
|
+
horizontalScrollOffsetRef.current + dx,
|
|
21845
|
+
0,
|
|
21846
|
+
maxOffsetX
|
|
21847
|
+
);
|
|
21848
|
+
appliedDx = nextOffsetX - horizontalScrollOffsetRef.current;
|
|
21849
|
+
if (appliedDx !== 0) {
|
|
21850
|
+
horizontalScrollOffsetRef.current = nextOffsetX;
|
|
21851
|
+
pageScrollRef.current?.scrollTo({ x: nextOffsetX, animated: false });
|
|
21852
|
+
}
|
|
21637
21853
|
}
|
|
21638
|
-
|
|
21639
|
-
|
|
21640
|
-
|
|
21641
|
-
|
|
21642
|
-
tool: activeTool,
|
|
21643
|
-
zoom: Math.round(zoom * 100) / 100
|
|
21644
|
-
});
|
|
21854
|
+
const appliedDy = requestSelectionVerticalAutoscroll?.(point.absoluteY) ?? 0;
|
|
21855
|
+
if (appliedDx === 0 && appliedDy === 0) {
|
|
21856
|
+
stopSelectionAutoscroll();
|
|
21857
|
+
return;
|
|
21645
21858
|
}
|
|
21646
|
-
|
|
21647
|
-
|
|
21859
|
+
const nextX = clamp3(point.x + appliedDx, 0, layout.width);
|
|
21860
|
+
const nextY = clamp3(point.y + appliedDy, 0, layout.height);
|
|
21861
|
+
selectionDragPointRef.current = {
|
|
21862
|
+
absoluteY: point.absoluteY,
|
|
21863
|
+
x: nextX,
|
|
21864
|
+
y: nextY
|
|
21865
|
+
};
|
|
21866
|
+
updateSelectionRectFromPoint(nextX, nextY);
|
|
21867
|
+
}, [
|
|
21868
|
+
layout.height,
|
|
21869
|
+
layout.width,
|
|
21870
|
+
pageViewportWidth,
|
|
21871
|
+
requestSelectionVerticalAutoscroll,
|
|
21872
|
+
stopSelectionAutoscroll,
|
|
21873
|
+
updateSelectionRectFromPoint
|
|
21874
|
+
]);
|
|
21875
|
+
const ensureSelectionAutoscroll = (0, import_react.useCallback)(() => {
|
|
21876
|
+
if (selectionAutoscrollIntervalRef.current) return;
|
|
21877
|
+
selectionAutoscrollIntervalRef.current = setInterval(
|
|
21878
|
+
applySelectionEdgeAutoscroll,
|
|
21879
|
+
SELECTION_AUTOSCROLL_INTERVAL_MS
|
|
21880
|
+
);
|
|
21881
|
+
}, [applySelectionEdgeAutoscroll]);
|
|
21882
|
+
const beginSelectionDrag = (0, import_react.useCallback)(
|
|
21883
|
+
(x, y, absoluteY) => {
|
|
21884
|
+
if (!selectionEnabled || !layout.width || !layout.height || selectionRects.length > 0 || selectionBounds) {
|
|
21885
|
+
return;
|
|
21886
|
+
}
|
|
21887
|
+
const start = {
|
|
21888
|
+
x: clamp3(x, 0, layout.width),
|
|
21889
|
+
y: clamp3(y, 0, layout.height)
|
|
21890
|
+
};
|
|
21891
|
+
selectionStart.current = start;
|
|
21892
|
+
selectionDragPointRef.current = { absoluteY, ...start };
|
|
21893
|
+
setSelectionDragState(true);
|
|
21894
|
+
setIsSelecting(true);
|
|
21895
|
+
const rect = { x: start.x, y: start.y, width: 0, height: 0 };
|
|
21896
|
+
selectionRectRef.current = rect;
|
|
21897
|
+
setSelectionRect(rect);
|
|
21898
|
+
},
|
|
21899
|
+
[
|
|
21900
|
+
layout.height,
|
|
21901
|
+
layout.width,
|
|
21902
|
+
selectionBounds,
|
|
21903
|
+
selectionEnabled,
|
|
21904
|
+
selectionRects.length,
|
|
21905
|
+
setSelectionDragState
|
|
21906
|
+
]
|
|
21907
|
+
);
|
|
21908
|
+
const updateSelectionDrag = (0, import_react.useCallback)(
|
|
21909
|
+
(x, y, absoluteY) => {
|
|
21910
|
+
if (!selectionEnabled || !selectionStart.current) return;
|
|
21911
|
+
const nextX = clamp3(x, 0, layout.width);
|
|
21912
|
+
const nextY = clamp3(y, 0, layout.height);
|
|
21913
|
+
selectionDragPointRef.current = {
|
|
21914
|
+
absoluteY,
|
|
21915
|
+
x: nextX,
|
|
21916
|
+
y: nextY
|
|
21917
|
+
};
|
|
21918
|
+
updateSelectionRectFromPoint(nextX, nextY);
|
|
21919
|
+
ensureSelectionAutoscroll();
|
|
21920
|
+
},
|
|
21921
|
+
[
|
|
21922
|
+
ensureSelectionAutoscroll,
|
|
21923
|
+
layout.height,
|
|
21924
|
+
layout.width,
|
|
21925
|
+
selectionEnabled,
|
|
21926
|
+
updateSelectionRectFromPoint
|
|
21927
|
+
]
|
|
21928
|
+
);
|
|
21929
|
+
const finishSelectionDrag = (0, import_react.useCallback)(async () => {
|
|
21930
|
+
stopSelectionAutoscroll();
|
|
21931
|
+
selectionDragPointRef.current = null;
|
|
21932
|
+
setSelectionDragState(false);
|
|
21933
|
+
const rect = selectionRectRef.current;
|
|
21934
|
+
if (!selectionEnabled || !rect || !layout.width || !layout.height) {
|
|
21935
|
+
setIsSelecting(false);
|
|
21936
|
+
selectionStart.current = null;
|
|
21937
|
+
return;
|
|
21938
|
+
}
|
|
21939
|
+
setIsSelecting(false);
|
|
21940
|
+
selectionStart.current = null;
|
|
21941
|
+
const minSize = 6;
|
|
21942
|
+
if (rect.width < minSize || rect.height < minSize) {
|
|
21943
|
+
clearSelection();
|
|
21944
|
+
return;
|
|
21945
|
+
}
|
|
21946
|
+
const normalized = {
|
|
21947
|
+
x: rect.x / layout.width,
|
|
21948
|
+
y: rect.y / layout.height,
|
|
21949
|
+
width: rect.width / layout.width,
|
|
21950
|
+
height: rect.height / layout.height
|
|
21951
|
+
};
|
|
21952
|
+
await selectFromBounds(normalized);
|
|
21953
|
+
setSelectionRect(null);
|
|
21954
|
+
}, [
|
|
21955
|
+
clearSelection,
|
|
21956
|
+
layout.height,
|
|
21957
|
+
layout.width,
|
|
21958
|
+
selectionEnabled,
|
|
21959
|
+
setSelectionDragState,
|
|
21960
|
+
stopSelectionAutoscroll
|
|
21961
|
+
]);
|
|
21962
|
+
const handleDoubleTap = (0, import_react.useCallback)(
|
|
21963
|
+
(x, y) => {
|
|
21964
|
+
if (shouldSuppressPressAfterPinch(lastPinchEndedAt)) {
|
|
21965
|
+
return;
|
|
21966
|
+
}
|
|
21967
|
+
if (!isNative || activeTool !== "select" || selectionRects.length > 0 || selectionBounds) {
|
|
21968
|
+
return;
|
|
21969
|
+
}
|
|
21970
|
+
void selectAtPoint(x, y);
|
|
21971
|
+
},
|
|
21972
|
+
[
|
|
21973
|
+
activeTool,
|
|
21974
|
+
isNative,
|
|
21975
|
+
lastPinchEndedAt,
|
|
21976
|
+
selectionBounds,
|
|
21977
|
+
selectionRects.length
|
|
21978
|
+
]
|
|
21979
|
+
);
|
|
21648
21980
|
const handlePress = (event) => {
|
|
21981
|
+
if (shouldSuppressPressAfterPinch(lastPinchEndedAt)) {
|
|
21982
|
+
return;
|
|
21983
|
+
}
|
|
21649
21984
|
if (!layout.width || !layout.height) return;
|
|
21650
21985
|
const { locationX, locationY } = event.nativeEvent;
|
|
21651
21986
|
if (selectionRects.length > 0 || selectionBounds) {
|
|
@@ -21666,20 +22001,7 @@ var PageRenderer = ({
|
|
|
21666
22001
|
return;
|
|
21667
22002
|
}
|
|
21668
22003
|
setSelectedAnnotation(null);
|
|
21669
|
-
if (!isNative || activeTool === "ink") return;
|
|
21670
|
-
const now = Date.now();
|
|
21671
|
-
const lastTap = lastTapRef.current;
|
|
21672
|
-
lastTapRef.current = { time: now, x: locationX, y: locationY };
|
|
21673
|
-
if (!lastTap) return;
|
|
21674
|
-
const timeDelta = now - lastTap.time;
|
|
21675
|
-
const distance = Math.hypot(locationX - lastTap.x, locationY - lastTap.y);
|
|
21676
|
-
if (timeDelta < 280 && distance < 24 && activeTool === "select") {
|
|
21677
|
-
void selectAtPoint(locationX, locationY);
|
|
21678
|
-
}
|
|
21679
22004
|
};
|
|
21680
|
-
const selectionEnabled = import_react_native.Platform.OS === "web" || isNative && (activeTool === "select" || TEXT_MARKUP_TOOLS.has(activeTool));
|
|
21681
|
-
const inkEnabled = isNative && activeTool === "ink";
|
|
21682
|
-
const pinchEnabled = isNative;
|
|
21683
22005
|
const toNormalizedPoint = (x, y) => {
|
|
21684
22006
|
if (!layout.width || !layout.height) return null;
|
|
21685
22007
|
return {
|
|
@@ -21691,6 +22013,7 @@ var PageRenderer = ({
|
|
|
21691
22013
|
const point = toNormalizedPoint(x, y);
|
|
21692
22014
|
if (!point) return;
|
|
21693
22015
|
clearSelection();
|
|
22016
|
+
inkDrawingActiveRef.current = true;
|
|
21694
22017
|
setIsInkDrawing(true);
|
|
21695
22018
|
setInkPoints([point]);
|
|
21696
22019
|
inkPointsRef.current = [point];
|
|
@@ -21709,6 +22032,7 @@ var PageRenderer = ({
|
|
|
21709
22032
|
const finishInkDrawing = () => {
|
|
21710
22033
|
const points = inkPointsRef.current;
|
|
21711
22034
|
if (points.length === 0) return;
|
|
22035
|
+
inkDrawingActiveRef.current = false;
|
|
21712
22036
|
setIsInkDrawing(false);
|
|
21713
22037
|
setInkPoints([]);
|
|
21714
22038
|
inkPointsRef.current = [];
|
|
@@ -21731,31 +22055,18 @@ var PageRenderer = ({
|
|
|
21731
22055
|
const panResponder = (0, import_react.useMemo)(
|
|
21732
22056
|
() => import_react_native.PanResponder.create({
|
|
21733
22057
|
onStartShouldSetPanResponder: (event) => {
|
|
22058
|
+
if (isNative) return false;
|
|
21734
22059
|
const touches = event.nativeEvent.touches ?? [];
|
|
21735
|
-
|
|
22060
|
+
if (touches.length !== 1) return false;
|
|
22061
|
+
return inkEnabled;
|
|
21736
22062
|
},
|
|
21737
22063
|
onMoveShouldSetPanResponder: (event) => {
|
|
22064
|
+
if (isNative) return false;
|
|
21738
22065
|
const touches = event.nativeEvent.touches ?? [];
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
onStartShouldSetPanResponderCapture: (event) => {
|
|
21742
|
-
const touches = event.nativeEvent.touches ?? [];
|
|
21743
|
-
return pinchEnabled && shouldHandlePinch(touches);
|
|
21744
|
-
},
|
|
21745
|
-
onMoveShouldSetPanResponderCapture: (event) => {
|
|
21746
|
-
const touches = event.nativeEvent.touches ?? [];
|
|
21747
|
-
return pinchEnabled && shouldHandlePinch(touches);
|
|
22066
|
+
if (touches.length !== 1) return false;
|
|
22067
|
+
return selectionEnabled || inkEnabled;
|
|
21748
22068
|
},
|
|
21749
22069
|
onPanResponderGrant: (event) => {
|
|
21750
|
-
const touches = event.nativeEvent.touches ?? [];
|
|
21751
|
-
if (pinchEnabled && shouldHandlePinch(touches)) {
|
|
21752
|
-
isPinchingRef.current = true;
|
|
21753
|
-
setIsSelecting(false);
|
|
21754
|
-
selectionStart.current = null;
|
|
21755
|
-
handlePinchStart(touches);
|
|
21756
|
-
return;
|
|
21757
|
-
}
|
|
21758
|
-
isPinchingRef.current = false;
|
|
21759
22070
|
if (inkEnabled) {
|
|
21760
22071
|
beginInkDrawing(
|
|
21761
22072
|
event.nativeEvent.locationX,
|
|
@@ -21763,26 +22074,13 @@ var PageRenderer = ({
|
|
|
21763
22074
|
);
|
|
21764
22075
|
return;
|
|
21765
22076
|
}
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
selectionRectRef.current = rect;
|
|
21772
|
-
setSelectionRect(rect);
|
|
22077
|
+
beginSelectionDrag(
|
|
22078
|
+
event.nativeEvent.locationX,
|
|
22079
|
+
event.nativeEvent.locationY,
|
|
22080
|
+
event.nativeEvent.pageY ?? event.nativeEvent.locationY
|
|
22081
|
+
);
|
|
21773
22082
|
},
|
|
21774
|
-
onPanResponderMove: (event
|
|
21775
|
-
const touches = event.nativeEvent.touches ?? [];
|
|
21776
|
-
if (pinchEnabled && (shouldHandlePinch(touches) || isPinchingRef.current)) {
|
|
21777
|
-
if (shouldHandlePinch(touches)) {
|
|
21778
|
-
if (!isPinchingRef.current) {
|
|
21779
|
-
isPinchingRef.current = true;
|
|
21780
|
-
handlePinchStart(touches);
|
|
21781
|
-
}
|
|
21782
|
-
handlePinchMove(touches);
|
|
21783
|
-
}
|
|
21784
|
-
return;
|
|
21785
|
-
}
|
|
22083
|
+
onPanResponderMove: (event) => {
|
|
21786
22084
|
if (inkEnabled) {
|
|
21787
22085
|
pushInkPoint(
|
|
21788
22086
|
event.nativeEvent.locationX,
|
|
@@ -21790,79 +22088,90 @@ var PageRenderer = ({
|
|
|
21790
22088
|
);
|
|
21791
22089
|
return;
|
|
21792
22090
|
}
|
|
21793
|
-
|
|
21794
|
-
|
|
21795
|
-
|
|
21796
|
-
|
|
21797
|
-
|
|
21798
|
-
const top = Math.max(0, Math.min(start.y, currentY));
|
|
21799
|
-
const right = Math.min(layout.width, Math.max(start.x, currentX));
|
|
21800
|
-
const bottom = Math.min(layout.height, Math.max(start.y, currentY));
|
|
21801
|
-
const rect = {
|
|
21802
|
-
x: left,
|
|
21803
|
-
y: top,
|
|
21804
|
-
width: right - left,
|
|
21805
|
-
height: bottom - top
|
|
21806
|
-
};
|
|
21807
|
-
selectionRectRef.current = rect;
|
|
21808
|
-
setSelectionRect(rect);
|
|
22091
|
+
updateSelectionDrag(
|
|
22092
|
+
event.nativeEvent.locationX,
|
|
22093
|
+
event.nativeEvent.locationY,
|
|
22094
|
+
event.nativeEvent.pageY ?? event.nativeEvent.locationY
|
|
22095
|
+
);
|
|
21809
22096
|
},
|
|
21810
22097
|
onPanResponderRelease: async () => {
|
|
21811
|
-
if (isPinchingRef.current) {
|
|
21812
|
-
isPinchingRef.current = false;
|
|
21813
|
-
handlePinchEnd();
|
|
21814
|
-
return;
|
|
21815
|
-
}
|
|
21816
22098
|
if (inkEnabled) {
|
|
21817
22099
|
finishInkDrawing();
|
|
21818
22100
|
return;
|
|
21819
22101
|
}
|
|
21820
|
-
|
|
21821
|
-
if (!selectionEnabled || !rect || !layout.width || !layout.height) {
|
|
21822
|
-
setIsSelecting(false);
|
|
21823
|
-
selectionStart.current = null;
|
|
21824
|
-
return;
|
|
21825
|
-
}
|
|
21826
|
-
setIsSelecting(false);
|
|
21827
|
-
selectionStart.current = null;
|
|
21828
|
-
const minSize = 6;
|
|
21829
|
-
if (rect.width < minSize || rect.height < minSize) {
|
|
21830
|
-
clearSelection();
|
|
21831
|
-
return;
|
|
21832
|
-
}
|
|
21833
|
-
const normalized = {
|
|
21834
|
-
x: rect.x / layout.width,
|
|
21835
|
-
y: rect.y / layout.height,
|
|
21836
|
-
width: rect.width / layout.width,
|
|
21837
|
-
height: rect.height / layout.height
|
|
21838
|
-
};
|
|
21839
|
-
await selectFromBounds(normalized);
|
|
21840
|
-
setSelectionRect(null);
|
|
22102
|
+
await finishSelectionDrag();
|
|
21841
22103
|
},
|
|
21842
22104
|
onPanResponderTerminate: () => {
|
|
21843
|
-
if (isPinchingRef.current) {
|
|
21844
|
-
isPinchingRef.current = false;
|
|
21845
|
-
handlePinchEnd();
|
|
21846
|
-
return;
|
|
21847
|
-
}
|
|
21848
22105
|
if (inkEnabled) {
|
|
21849
22106
|
finishInkDrawing();
|
|
21850
22107
|
return;
|
|
21851
22108
|
}
|
|
21852
|
-
|
|
21853
|
-
selectionStart.current = null;
|
|
22109
|
+
cancelSelectionDrag();
|
|
21854
22110
|
}
|
|
21855
22111
|
}),
|
|
21856
22112
|
[
|
|
21857
|
-
|
|
22113
|
+
beginSelectionDrag,
|
|
22114
|
+
cancelSelectionDrag,
|
|
22115
|
+
finishSelectionDrag,
|
|
22116
|
+
isNative,
|
|
21858
22117
|
inkEnabled,
|
|
21859
|
-
|
|
21860
|
-
|
|
21861
|
-
|
|
21862
|
-
|
|
21863
|
-
|
|
22118
|
+
beginInkDrawing,
|
|
22119
|
+
finishInkDrawing,
|
|
22120
|
+
pushInkPoint,
|
|
22121
|
+
selectionEnabled,
|
|
22122
|
+
updateSelectionDrag
|
|
22123
|
+
]
|
|
22124
|
+
);
|
|
22125
|
+
const selectionGesture = (0, import_react.useMemo)(
|
|
22126
|
+
() => import_react_native_gesture_handler.Gesture.Pan().enabled(
|
|
22127
|
+
isNative && selectionEnabled && selectionRects.length === 0 && !selectionBounds
|
|
22128
|
+
).maxPointers(1).minDistance(4).runOnJS(true).onStart((event) => {
|
|
22129
|
+
beginSelectionDrag(event.x, event.y, event.absoluteY);
|
|
22130
|
+
}).onUpdate((event) => {
|
|
22131
|
+
updateSelectionDrag(event.x, event.y, event.absoluteY);
|
|
22132
|
+
}).onEnd(() => {
|
|
22133
|
+
void finishSelectionDrag();
|
|
22134
|
+
}).onFinalize(() => {
|
|
22135
|
+
if (selectionDragActiveRef.current) {
|
|
22136
|
+
cancelSelectionDrag();
|
|
22137
|
+
}
|
|
22138
|
+
}),
|
|
22139
|
+
[
|
|
22140
|
+
beginSelectionDrag,
|
|
22141
|
+
cancelSelectionDrag,
|
|
22142
|
+
finishSelectionDrag,
|
|
22143
|
+
isNative,
|
|
22144
|
+
selectionBounds,
|
|
22145
|
+
selectionEnabled,
|
|
22146
|
+
selectionRects.length,
|
|
22147
|
+
updateSelectionDrag
|
|
21864
22148
|
]
|
|
21865
22149
|
);
|
|
22150
|
+
const inkGesture = (0, import_react.useMemo)(
|
|
22151
|
+
() => import_react_native_gesture_handler.Gesture.Pan().enabled(isNative && inkEnabled).maxPointers(1).minDistance(0).runOnJS(true).onStart((event) => {
|
|
22152
|
+
beginInkDrawing(event.x, event.y);
|
|
22153
|
+
}).onUpdate((event) => {
|
|
22154
|
+
pushInkPoint(event.x, event.y);
|
|
22155
|
+
}).onEnd(() => {
|
|
22156
|
+
finishInkDrawing();
|
|
22157
|
+
}).onFinalize(() => {
|
|
22158
|
+
if (inkDrawingActiveRef.current) {
|
|
22159
|
+
finishInkDrawing();
|
|
22160
|
+
}
|
|
22161
|
+
}),
|
|
22162
|
+
[beginInkDrawing, finishInkDrawing, inkEnabled, isNative, pushInkPoint]
|
|
22163
|
+
);
|
|
22164
|
+
const doubleTapGesture = (0, import_react.useMemo)(
|
|
22165
|
+
() => import_react_native_gesture_handler.Gesture.Tap().enabled(isNative && activeTool === "select").numberOfTaps(2).maxDistance(24).maxDelay(280).maxDuration(250).runOnJS(true).onEnd((event, success) => {
|
|
22166
|
+
if (!success) return;
|
|
22167
|
+
handleDoubleTap(event.x, event.y);
|
|
22168
|
+
}),
|
|
22169
|
+
[activeTool, handleDoubleTap, isNative]
|
|
22170
|
+
);
|
|
22171
|
+
const contentGesture = (0, import_react.useMemo)(
|
|
22172
|
+
() => import_react_native_gesture_handler.Gesture.Simultaneous(selectionGesture, inkGesture, doubleTapGesture),
|
|
22173
|
+
[doubleTapGesture, inkGesture, selectionGesture]
|
|
22174
|
+
);
|
|
21866
22175
|
const selectionBoundsPx = (0, import_react.useMemo)(() => {
|
|
21867
22176
|
if (!selectionBounds || !layout.width || !layout.height) return null;
|
|
21868
22177
|
return {
|
|
@@ -21886,8 +22195,8 @@ var PageRenderer = ({
|
|
|
21886
22195
|
const minSize = 0.01;
|
|
21887
22196
|
let next = { ...start };
|
|
21888
22197
|
if (handle === "start") {
|
|
21889
|
-
const newX =
|
|
21890
|
-
const newY =
|
|
22198
|
+
const newX = clamp3(start.x + dx, 0, start.x + start.width - minSize);
|
|
22199
|
+
const newY = clamp3(start.y + dy, 0, start.y + start.height - minSize);
|
|
21891
22200
|
next = {
|
|
21892
22201
|
x: newX,
|
|
21893
22202
|
y: newY,
|
|
@@ -21895,8 +22204,8 @@ var PageRenderer = ({
|
|
|
21895
22204
|
height: start.y + start.height - newY
|
|
21896
22205
|
};
|
|
21897
22206
|
} else {
|
|
21898
|
-
const maxX =
|
|
21899
|
-
const maxY =
|
|
22207
|
+
const maxX = clamp3(start.x + start.width + dx, start.x + minSize, 1);
|
|
22208
|
+
const maxY = clamp3(start.y + start.height + dy, start.y + minSize, 1);
|
|
21900
22209
|
next = {
|
|
21901
22210
|
x: start.x,
|
|
21902
22211
|
y: start.y,
|
|
@@ -21970,29 +22279,83 @@ var PageRenderer = ({
|
|
|
21970
22279
|
const pageWidth = isNative ? baseWidth * zoom : baseWidth;
|
|
21971
22280
|
const pageHeight = pageWidth / aspectRatio;
|
|
21972
22281
|
const hasActiveSelection = selectionRects.length > 0 || !!selectionBounds || isSelecting;
|
|
21973
|
-
const scrollEnabled = isNative && zoom > 1 && !hasActiveSelection && !isInkDrawing;
|
|
22282
|
+
const scrollEnabled = isNative && zoom > 1 && !hasActiveSelection && !isInkDrawing && !gestureScrollLockActive;
|
|
22283
|
+
(0, import_react.useEffect)(() => {
|
|
22284
|
+
if (!horizontalScrollRestore) return;
|
|
22285
|
+
if (lastAppliedHorizontalRestoreRef.current === horizontalScrollRestore.requestId) {
|
|
22286
|
+
return;
|
|
22287
|
+
}
|
|
22288
|
+
const nextOffsetX = resolveClampedScrollOffset(
|
|
22289
|
+
horizontalScrollRestore.offsetX,
|
|
22290
|
+
pageWidth,
|
|
22291
|
+
pageViewportWidth
|
|
22292
|
+
);
|
|
22293
|
+
lastAppliedHorizontalRestoreRef.current = horizontalScrollRestore.requestId;
|
|
22294
|
+
horizontalScrollOffsetRef.current = nextOffsetX;
|
|
22295
|
+
pageScrollRef.current?.scrollTo({ x: nextOffsetX, animated: false });
|
|
22296
|
+
onHorizontalScrollOffsetChange?.(pageIndex, nextOffsetX);
|
|
22297
|
+
}, [
|
|
22298
|
+
horizontalScrollRestore,
|
|
22299
|
+
onHorizontalScrollOffsetChange,
|
|
22300
|
+
pageIndex,
|
|
22301
|
+
pageViewportWidth,
|
|
22302
|
+
pageWidth
|
|
22303
|
+
]);
|
|
21974
22304
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21975
22305
|
import_react_native.ScrollView,
|
|
21976
22306
|
{
|
|
22307
|
+
ref: pageScrollRef,
|
|
21977
22308
|
horizontal: true,
|
|
21978
22309
|
scrollEnabled,
|
|
21979
22310
|
showsHorizontalScrollIndicator: false,
|
|
22311
|
+
onScroll: (event) => {
|
|
22312
|
+
const nextOffsetX = event.nativeEvent.contentOffset?.x ?? 0;
|
|
22313
|
+
horizontalScrollOffsetRef.current = nextOffsetX;
|
|
22314
|
+
},
|
|
22315
|
+
onScrollEndDrag: () => {
|
|
22316
|
+
onHorizontalScrollOffsetChange?.(
|
|
22317
|
+
pageIndex,
|
|
22318
|
+
horizontalScrollOffsetRef.current
|
|
22319
|
+
);
|
|
22320
|
+
},
|
|
22321
|
+
onMomentumScrollEnd: () => {
|
|
22322
|
+
onHorizontalScrollOffsetChange?.(
|
|
22323
|
+
pageIndex,
|
|
22324
|
+
horizontalScrollOffsetRef.current
|
|
22325
|
+
);
|
|
22326
|
+
},
|
|
22327
|
+
scrollEventThrottle: 16,
|
|
21980
22328
|
contentContainerStyle: [
|
|
21981
22329
|
styles.scrollContent,
|
|
21982
22330
|
{ paddingHorizontal: horizontalPadding }
|
|
21983
22331
|
],
|
|
21984
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
22332
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native_gesture_handler.GestureDetector, { gesture: contentGesture, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
21985
22333
|
import_react_native.Pressable,
|
|
21986
22334
|
{
|
|
21987
22335
|
...panResponder.panHandlers,
|
|
21988
22336
|
style: [
|
|
21989
22337
|
styles.container,
|
|
21990
|
-
{
|
|
22338
|
+
{
|
|
22339
|
+
width: pageWidth,
|
|
22340
|
+
height: pageHeight,
|
|
22341
|
+
marginBottom: spacing
|
|
22342
|
+
}
|
|
21991
22343
|
],
|
|
21992
22344
|
onLayout: handleLayout,
|
|
22345
|
+
onTouchStart: (event) => logRawTouchDebug("start", event),
|
|
22346
|
+
onTouchMove: (event) => logRawTouchDebug("move", event),
|
|
22347
|
+
onTouchEnd: (event) => logRawTouchDebug("end", event),
|
|
22348
|
+
onTouchCancel: (event) => logRawTouchDebug("cancel", event),
|
|
21993
22349
|
onPress: handlePress,
|
|
21994
22350
|
children: [
|
|
21995
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22351
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22352
|
+
PageViewComponent,
|
|
22353
|
+
{
|
|
22354
|
+
ref: viewRef,
|
|
22355
|
+
pointerEvents: "none",
|
|
22356
|
+
style: styles.page
|
|
22357
|
+
}
|
|
22358
|
+
),
|
|
21996
22359
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
21997
22360
|
import_react_native.View,
|
|
21998
22361
|
{
|
|
@@ -22129,7 +22492,9 @@ var PageRenderer = ({
|
|
|
22129
22492
|
const isSelected = selectedAnnotationId === ann.id;
|
|
22130
22493
|
const isText = ann.type === "comment" || ann.type === "text";
|
|
22131
22494
|
const isInk = ann.type === "ink" && Array.isArray(ann.path) && ann.path.length > 1;
|
|
22132
|
-
const isMarkup = TEXT_MARKUP_TOOLS.has(
|
|
22495
|
+
const isMarkup = TEXT_MARKUP_TOOLS.has(
|
|
22496
|
+
ann.type
|
|
22497
|
+
);
|
|
22133
22498
|
const rects = ann.rects && ann.rects.length > 0 ? ann.rects : [ann.rect];
|
|
22134
22499
|
const hitTargetStyle = {
|
|
22135
22500
|
left: `${ann.rect.x * 100}%`,
|
|
@@ -22169,7 +22534,10 @@ var PageRenderer = ({
|
|
|
22169
22534
|
import_react_native.View,
|
|
22170
22535
|
{
|
|
22171
22536
|
pointerEvents: "none",
|
|
22172
|
-
style: [
|
|
22537
|
+
style: [
|
|
22538
|
+
styles.annotationLineContainer,
|
|
22539
|
+
rectStyle
|
|
22540
|
+
],
|
|
22173
22541
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22174
22542
|
import_react_native.View,
|
|
22175
22543
|
{
|
|
@@ -22188,7 +22556,10 @@ var PageRenderer = ({
|
|
|
22188
22556
|
import_react_native.View,
|
|
22189
22557
|
{
|
|
22190
22558
|
pointerEvents: "none",
|
|
22191
|
-
style: [
|
|
22559
|
+
style: [
|
|
22560
|
+
styles.annotationLineContainer,
|
|
22561
|
+
rectStyle
|
|
22562
|
+
],
|
|
22192
22563
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
22193
22564
|
import_react_native.View,
|
|
22194
22565
|
{
|
|
@@ -22421,7 +22792,7 @@ var PageRenderer = ({
|
|
|
22421
22792
|
) : null
|
|
22422
22793
|
]
|
|
22423
22794
|
}
|
|
22424
|
-
)
|
|
22795
|
+
) })
|
|
22425
22796
|
}
|
|
22426
22797
|
);
|
|
22427
22798
|
};
|
|
@@ -22648,7 +23019,7 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
22648
23019
|
borderRadius: 3
|
|
22649
23020
|
}
|
|
22650
23021
|
});
|
|
22651
|
-
var arePageRendererPropsEqual = (previous, next) => previous.engine === next.engine && previous.pageIndex === next.pageIndex && previous.scale === next.scale && previous.PageViewComponent === next.PageViewComponent && previous.availableWidth === next.availableWidth && previous.horizontalPadding === next.horizontalPadding && previous.spacing === next.spacing;
|
|
23022
|
+
var arePageRendererPropsEqual = (previous, next) => previous.engine === next.engine && previous.pageIndex === next.pageIndex && previous.scale === next.scale && previous.PageViewComponent === next.PageViewComponent && previous.availableWidth === next.availableWidth && previous.horizontalPadding === next.horizontalPadding && previous.spacing === next.spacing && previous.onSelectionDragActiveChange === next.onSelectionDragActiveChange && previous.gestureScrollLockActive === next.gestureScrollLockActive && previous.lastPinchEndedAt === next.lastPinchEndedAt && previous.onHorizontalScrollOffsetChange === next.onHorizontalScrollOffsetChange && previous.horizontalScrollRestore?.requestId === next.horizontalScrollRestore?.requestId && previous.horizontalScrollRestore?.offsetX === next.horizontalScrollRestore?.offsetX && previous.requestSelectionVerticalAutoscroll === next.requestSelectionVerticalAutoscroll;
|
|
22652
23023
|
var PageRenderer_default = (0, import_react.memo)(PageRenderer, arePageRendererPropsEqual);
|
|
22653
23024
|
|
|
22654
23025
|
// components/WebViewViewer.tsx
|
|
@@ -22800,6 +23171,8 @@ var MOBILE_CHROME_HIDE_DELTA = 28;
|
|
|
22800
23171
|
var MOBILE_CHROME_SHOW_DELTA = 22;
|
|
22801
23172
|
var MOBILE_CHROME_SHOW_DELAY_MS = 180;
|
|
22802
23173
|
var MOBILE_CHROME_TOP_RESET = 16;
|
|
23174
|
+
var SELECTION_EDGE_THRESHOLD_PX2 = 48;
|
|
23175
|
+
var SELECTION_EDGE_MAX_STEP_PX2 = 24;
|
|
22803
23176
|
var resolvePositiveInt = (value, fallback, min, max) => {
|
|
22804
23177
|
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
22805
23178
|
const rounded = Math.round(value);
|
|
@@ -22857,6 +23230,26 @@ var Viewer = ({
|
|
|
22857
23230
|
const scrollDownAccumRef = (0, import_react3.useRef)(0);
|
|
22858
23231
|
const scrollUpAccumRef = (0, import_react3.useRef)(0);
|
|
22859
23232
|
const [layoutRevision, setLayoutRevision] = (0, import_react3.useState)(0);
|
|
23233
|
+
const [selectionDragActive, setSelectionDragActive] = (0, import_react3.useState)(false);
|
|
23234
|
+
const selectionDragActiveRef = (0, import_react3.useRef)(false);
|
|
23235
|
+
const [gestureScrollLockActive, setGestureScrollLockActive] = (0, import_react3.useState)(false);
|
|
23236
|
+
const gestureScrollLockActiveRef = (0, import_react3.useRef)(false);
|
|
23237
|
+
const [pinchPreviewScale, setPinchPreviewScale] = (0, import_react3.useState)(1);
|
|
23238
|
+
const [lastPinchEndedAt, setLastPinchEndedAt] = (0, import_react3.useState)(null);
|
|
23239
|
+
const [horizontalScrollRestore, setHorizontalScrollRestore] = (0, import_react3.useState)(null);
|
|
23240
|
+
const pinchGestureActiveRef = (0, import_react3.useRef)(false);
|
|
23241
|
+
const pinchStartZoomRef = (0, import_react3.useRef)(1);
|
|
23242
|
+
const pinchPreviewZoomRef = (0, import_react3.useRef)(1);
|
|
23243
|
+
const pinchFocalPointRef = (0, import_react3.useRef)({ x: 0, y: 0 });
|
|
23244
|
+
const pinchUpdateLoggedAtRef = (0, import_react3.useRef)(0);
|
|
23245
|
+
const horizontalScrollOffsetsRef = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
|
|
23246
|
+
const pendingPinchAnchorRestoreRef = (0, import_react3.useRef)(
|
|
23247
|
+
null
|
|
23248
|
+
);
|
|
23249
|
+
const pinchAnchorRestoreFrameRef = (0, import_react3.useRef)(null);
|
|
23250
|
+
const nextHorizontalRestoreRequestIdRef = (0, import_react3.useRef)(0);
|
|
23251
|
+
const viewerFrameRef = (0, import_react3.useRef)({ y: 0, height: 0 });
|
|
23252
|
+
const viewerContentHeightRef = (0, import_react3.useRef)(0);
|
|
22860
23253
|
const resolvedWindowSize = (0, import_react3.useMemo)(
|
|
22861
23254
|
() => resolvePositiveInt(virtualWindowSize, FLATLIST_WINDOW_SIZE, 2, 30),
|
|
22862
23255
|
[virtualWindowSize]
|
|
@@ -22955,6 +23348,9 @@ var Viewer = ({
|
|
|
22955
23348
|
if (layoutRefreshTimeoutRef.current) {
|
|
22956
23349
|
clearTimeout(layoutRefreshTimeoutRef.current);
|
|
22957
23350
|
}
|
|
23351
|
+
if (pinchAnchorRestoreFrameRef.current !== null) {
|
|
23352
|
+
cancelAnimationFrame(pinchAnchorRestoreFrameRef.current);
|
|
23353
|
+
}
|
|
22958
23354
|
clearPendingScrollRetry();
|
|
22959
23355
|
clearPendingChromeShow();
|
|
22960
23356
|
},
|
|
@@ -23121,6 +23517,513 @@ var Viewer = ({
|
|
|
23121
23517
|
const columnGap = 12;
|
|
23122
23518
|
const horizontalPadding = 16;
|
|
23123
23519
|
const columnWidth = isDouble ? (windowWidth - horizontalPadding * 2 - columnGap) / 2 : windowWidth;
|
|
23520
|
+
const getPageWidthForZoom = (0, import_react3.useCallback)(
|
|
23521
|
+
(pageIndex, zoomValue) => {
|
|
23522
|
+
const safeZoom = Math.max(zoomValue, 0.25);
|
|
23523
|
+
const baseWidth = isDouble ? columnWidth * 0.92 : windowWidth * 0.92;
|
|
23524
|
+
return baseWidth * safeZoom;
|
|
23525
|
+
},
|
|
23526
|
+
[columnWidth, isDouble, windowWidth]
|
|
23527
|
+
);
|
|
23528
|
+
const getPageHeightForZoom = (0, import_react3.useCallback)(
|
|
23529
|
+
(pageIndex, zoomValue) => getPageWidthForZoom(pageIndex, zoomValue) / getPageAspectRatio(pageIndex),
|
|
23530
|
+
[getPageAspectRatio, getPageWidthForZoom]
|
|
23531
|
+
);
|
|
23532
|
+
const getPageViewportMetrics = (0, import_react3.useCallback)(
|
|
23533
|
+
(pageIndex) => {
|
|
23534
|
+
if (isDouble) {
|
|
23535
|
+
const isRight = pageIndex % 2 === 1;
|
|
23536
|
+
return {
|
|
23537
|
+
viewportWidth: columnWidth,
|
|
23538
|
+
horizontalPadding: 8,
|
|
23539
|
+
viewportOffsetX: horizontalPadding + (isRight ? columnWidth + columnGap : 0)
|
|
23540
|
+
};
|
|
23541
|
+
}
|
|
23542
|
+
return {
|
|
23543
|
+
viewportWidth: windowWidth,
|
|
23544
|
+
horizontalPadding: 16,
|
|
23545
|
+
viewportOffsetX: 0
|
|
23546
|
+
};
|
|
23547
|
+
},
|
|
23548
|
+
[columnGap, columnWidth, horizontalPadding, isDouble, windowWidth]
|
|
23549
|
+
);
|
|
23550
|
+
const getPageLayoutForZoom = (0, import_react3.useCallback)(
|
|
23551
|
+
(pageIndex, zoomValue) => {
|
|
23552
|
+
if (isSingle) {
|
|
23553
|
+
const pageHeight = getPageHeightForZoom(pageIndex, zoomValue);
|
|
23554
|
+
return {
|
|
23555
|
+
pageOffsetY: 18,
|
|
23556
|
+
pageHeight,
|
|
23557
|
+
totalContentHeight: 18 + pageHeight + 140
|
|
23558
|
+
};
|
|
23559
|
+
}
|
|
23560
|
+
if (isDouble) {
|
|
23561
|
+
let offsetY2 = LIST_TOP_PADDING;
|
|
23562
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
|
|
23563
|
+
const row = rows[rowIndex];
|
|
23564
|
+
const leftHeight = getPageHeightForZoom(row.left, zoomValue);
|
|
23565
|
+
const rightHeight = row.right === null ? leftHeight : getPageHeightForZoom(row.right, zoomValue);
|
|
23566
|
+
const rowLength = Math.max(leftHeight, rightHeight) + DOUBLE_PAGE_SPACING;
|
|
23567
|
+
if (row.left === pageIndex || row.right === pageIndex) {
|
|
23568
|
+
let totalContentHeight = LIST_TOP_PADDING;
|
|
23569
|
+
for (let totalRowIndex = 0; totalRowIndex < rows.length; totalRowIndex += 1) {
|
|
23570
|
+
const totalRow = rows[totalRowIndex];
|
|
23571
|
+
const totalLeftHeight = getPageHeightForZoom(
|
|
23572
|
+
totalRow.left,
|
|
23573
|
+
zoomValue
|
|
23574
|
+
);
|
|
23575
|
+
const totalRightHeight = totalRow.right === null ? totalLeftHeight : getPageHeightForZoom(totalRow.right, zoomValue);
|
|
23576
|
+
totalContentHeight += Math.max(totalLeftHeight, totalRightHeight) + DOUBLE_PAGE_SPACING;
|
|
23577
|
+
}
|
|
23578
|
+
totalContentHeight += LIST_BOTTOM_PADDING;
|
|
23579
|
+
return {
|
|
23580
|
+
pageOffsetY: offsetY2,
|
|
23581
|
+
pageHeight: getPageHeightForZoom(pageIndex, zoomValue),
|
|
23582
|
+
totalContentHeight
|
|
23583
|
+
};
|
|
23584
|
+
}
|
|
23585
|
+
offsetY2 += rowLength;
|
|
23586
|
+
}
|
|
23587
|
+
}
|
|
23588
|
+
let offsetY = LIST_TOP_PADDING;
|
|
23589
|
+
for (let currentPageIndex = 0; currentPageIndex < pageCount; currentPageIndex += 1) {
|
|
23590
|
+
const currentPageHeight = getPageHeightForZoom(
|
|
23591
|
+
currentPageIndex,
|
|
23592
|
+
zoomValue
|
|
23593
|
+
);
|
|
23594
|
+
if (currentPageIndex === pageIndex) {
|
|
23595
|
+
let totalContentHeight = LIST_TOP_PADDING;
|
|
23596
|
+
for (let totalPageIndex = 0; totalPageIndex < pageCount; totalPageIndex += 1) {
|
|
23597
|
+
totalContentHeight += getPageHeightForZoom(totalPageIndex, zoomValue) + CONTINUOUS_PAGE_SPACING;
|
|
23598
|
+
}
|
|
23599
|
+
totalContentHeight += LIST_BOTTOM_PADDING;
|
|
23600
|
+
return {
|
|
23601
|
+
pageOffsetY: offsetY,
|
|
23602
|
+
pageHeight: currentPageHeight,
|
|
23603
|
+
totalContentHeight
|
|
23604
|
+
};
|
|
23605
|
+
}
|
|
23606
|
+
offsetY += currentPageHeight + CONTINUOUS_PAGE_SPACING;
|
|
23607
|
+
}
|
|
23608
|
+
return {
|
|
23609
|
+
pageOffsetY: LIST_TOP_PADDING,
|
|
23610
|
+
pageHeight: getPageHeightForZoom(pageIndex, zoomValue),
|
|
23611
|
+
totalContentHeight: LIST_TOP_PADDING + getPageHeightForZoom(pageIndex, zoomValue) + CONTINUOUS_PAGE_SPACING + LIST_BOTTOM_PADDING
|
|
23612
|
+
};
|
|
23613
|
+
},
|
|
23614
|
+
[getPageHeightForZoom, isDouble, isSingle, pageCount, rows]
|
|
23615
|
+
);
|
|
23616
|
+
const resolvePinchAnchorPageIndex = (0, import_react3.useCallback)(
|
|
23617
|
+
(focalX, focalY, zoomValue, scrollOffsetY = lastScrollOffsetYRef.current) => {
|
|
23618
|
+
if (isSingle) {
|
|
23619
|
+
return Math.max(0, currentPage - 1);
|
|
23620
|
+
}
|
|
23621
|
+
const contentY = Math.max(0, scrollOffsetY + focalY);
|
|
23622
|
+
if (isDouble) {
|
|
23623
|
+
let offsetY2 = LIST_TOP_PADDING;
|
|
23624
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
|
|
23625
|
+
const row = rows[rowIndex];
|
|
23626
|
+
const leftHeight = getPageHeightForZoom(row.left, zoomValue);
|
|
23627
|
+
const rightHeight = row.right === null ? leftHeight : getPageHeightForZoom(row.right, zoomValue);
|
|
23628
|
+
const rowLength = Math.max(leftHeight, rightHeight) + DOUBLE_PAGE_SPACING;
|
|
23629
|
+
if (contentY <= offsetY2 + rowLength || rowIndex === rows.length - 1) {
|
|
23630
|
+
const isRight = row.right !== null && focalX > horizontalPadding + columnWidth + columnGap / 2;
|
|
23631
|
+
return isRight ? row.right : row.left;
|
|
23632
|
+
}
|
|
23633
|
+
offsetY2 += rowLength;
|
|
23634
|
+
}
|
|
23635
|
+
return rows[rows.length - 1]?.left ?? 0;
|
|
23636
|
+
}
|
|
23637
|
+
let offsetY = LIST_TOP_PADDING;
|
|
23638
|
+
for (let pageIndex = 0; pageIndex < pageCount; pageIndex += 1) {
|
|
23639
|
+
const pageLength = getPageHeightForZoom(pageIndex, zoomValue) + CONTINUOUS_PAGE_SPACING;
|
|
23640
|
+
if (contentY <= offsetY + pageLength || pageIndex === pageCount - 1) {
|
|
23641
|
+
return pageIndex;
|
|
23642
|
+
}
|
|
23643
|
+
offsetY += pageLength;
|
|
23644
|
+
}
|
|
23645
|
+
return Math.max(0, pageCount - 1);
|
|
23646
|
+
},
|
|
23647
|
+
[
|
|
23648
|
+
columnGap,
|
|
23649
|
+
columnWidth,
|
|
23650
|
+
currentPage,
|
|
23651
|
+
getPageHeightForZoom,
|
|
23652
|
+
horizontalPadding,
|
|
23653
|
+
isDouble,
|
|
23654
|
+
isSingle,
|
|
23655
|
+
pageCount,
|
|
23656
|
+
rows
|
|
23657
|
+
]
|
|
23658
|
+
);
|
|
23659
|
+
const resolvedViewerScrollEnabled = shouldEnableViewerScroll({
|
|
23660
|
+
selectionDragActive,
|
|
23661
|
+
gestureScrollLockActive
|
|
23662
|
+
});
|
|
23663
|
+
const setViewerScrollEnabledNative = (0, import_react3.useCallback)((enabled) => {
|
|
23664
|
+
const scrollNode = listRef.current;
|
|
23665
|
+
scrollNode?.setNativeProps?.({ scrollEnabled: enabled });
|
|
23666
|
+
}, []);
|
|
23667
|
+
const syncViewerScrollEnabled = (0, import_react3.useCallback)(
|
|
23668
|
+
(nextSelectionDragActive = selectionDragActiveRef.current, nextGestureScrollLockActive = gestureScrollLockActiveRef.current) => {
|
|
23669
|
+
setViewerScrollEnabledNative(
|
|
23670
|
+
shouldEnableViewerScroll({
|
|
23671
|
+
selectionDragActive: nextSelectionDragActive,
|
|
23672
|
+
gestureScrollLockActive: nextGestureScrollLockActive
|
|
23673
|
+
})
|
|
23674
|
+
);
|
|
23675
|
+
},
|
|
23676
|
+
[setViewerScrollEnabledNative]
|
|
23677
|
+
);
|
|
23678
|
+
const handleGestureScrollLockChange = (0, import_react3.useCallback)(
|
|
23679
|
+
(active) => {
|
|
23680
|
+
if (gestureScrollLockActiveRef.current === active) return;
|
|
23681
|
+
gestureScrollLockActiveRef.current = active;
|
|
23682
|
+
setGestureScrollLockActive(active);
|
|
23683
|
+
syncViewerScrollEnabled(selectionDragActiveRef.current, active);
|
|
23684
|
+
},
|
|
23685
|
+
[syncViewerScrollEnabled]
|
|
23686
|
+
);
|
|
23687
|
+
const handlePinchPreviewScaleChange = (0, import_react3.useCallback)((scale) => {
|
|
23688
|
+
const nextScale = sanitizePinchPreviewScale(scale);
|
|
23689
|
+
setPinchPreviewScale((current) => {
|
|
23690
|
+
if (Math.abs(current - nextScale) < 5e-4) {
|
|
23691
|
+
return current;
|
|
23692
|
+
}
|
|
23693
|
+
return nextScale;
|
|
23694
|
+
});
|
|
23695
|
+
}, []);
|
|
23696
|
+
const resetViewerPinchPreview = (0, import_react3.useCallback)(() => {
|
|
23697
|
+
pinchPreviewZoomRef.current = pinchStartZoomRef.current;
|
|
23698
|
+
handlePinchPreviewScaleChange(1);
|
|
23699
|
+
}, [handlePinchPreviewScaleChange]);
|
|
23700
|
+
const beginViewerPinch = (0, import_react3.useCallback)(
|
|
23701
|
+
(focalX, focalY) => {
|
|
23702
|
+
pinchGestureActiveRef.current = true;
|
|
23703
|
+
pinchStartZoomRef.current = zoom;
|
|
23704
|
+
pinchPreviewZoomRef.current = zoom;
|
|
23705
|
+
pinchFocalPointRef.current = { x: focalX, y: focalY };
|
|
23706
|
+
pinchUpdateLoggedAtRef.current = 0;
|
|
23707
|
+
setLastPinchEndedAt(null);
|
|
23708
|
+
handlePinchPreviewScaleChange(1);
|
|
23709
|
+
handleGestureScrollLockChange(true);
|
|
23710
|
+
if (perfEnabled) {
|
|
23711
|
+
logPerfEvent("Viewer", "pinch.start", {
|
|
23712
|
+
zoom: Math.round(zoom * 100) / 100
|
|
23713
|
+
});
|
|
23714
|
+
}
|
|
23715
|
+
},
|
|
23716
|
+
[
|
|
23717
|
+
handleGestureScrollLockChange,
|
|
23718
|
+
handlePinchPreviewScaleChange,
|
|
23719
|
+
perfEnabled,
|
|
23720
|
+
zoom
|
|
23721
|
+
]
|
|
23722
|
+
);
|
|
23723
|
+
const updateViewerPinch = (0, import_react3.useCallback)(
|
|
23724
|
+
(scaleFactor, focalX, focalY) => {
|
|
23725
|
+
if (!pinchGestureActiveRef.current) return;
|
|
23726
|
+
pinchFocalPointRef.current = { x: focalX, y: focalY };
|
|
23727
|
+
const nextZoom = resolvePinchGestureZoom(
|
|
23728
|
+
pinchStartZoomRef.current,
|
|
23729
|
+
scaleFactor
|
|
23730
|
+
);
|
|
23731
|
+
pinchPreviewZoomRef.current = nextZoom;
|
|
23732
|
+
handlePinchPreviewScaleChange(
|
|
23733
|
+
resolvePinchPreviewScale(pinchStartZoomRef.current, nextZoom)
|
|
23734
|
+
);
|
|
23735
|
+
if (!perfEnabled) return;
|
|
23736
|
+
const now = Date.now();
|
|
23737
|
+
if (now - pinchUpdateLoggedAtRef.current < 120) return;
|
|
23738
|
+
pinchUpdateLoggedAtRef.current = now;
|
|
23739
|
+
logPerfEvent("Viewer", "pinch.update", {
|
|
23740
|
+
scale: Math.round(scaleFactor * 1e3) / 1e3,
|
|
23741
|
+
nextZoom: Math.round(nextZoom * 100) / 100
|
|
23742
|
+
});
|
|
23743
|
+
},
|
|
23744
|
+
[handlePinchPreviewScaleChange, perfEnabled]
|
|
23745
|
+
);
|
|
23746
|
+
const finishViewerPinch = (0, import_react3.useCallback)(() => {
|
|
23747
|
+
if (!pinchGestureActiveRef.current) return;
|
|
23748
|
+
pinchGestureActiveRef.current = false;
|
|
23749
|
+
const focalX = pinchFocalPointRef.current.x;
|
|
23750
|
+
const focalY = pinchFocalPointRef.current.y;
|
|
23751
|
+
const viewerScrollOffsetY = lastScrollOffsetYRef.current;
|
|
23752
|
+
const finalZoom = resolvePinchGestureZoom(
|
|
23753
|
+
pinchPreviewZoomRef.current || pinchStartZoomRef.current,
|
|
23754
|
+
1,
|
|
23755
|
+
DEFAULT_PINCH_ZOOM_BOUNDS
|
|
23756
|
+
);
|
|
23757
|
+
setLastPinchEndedAt(Date.now());
|
|
23758
|
+
if (Math.abs(finalZoom - zoom) >= 1e-3) {
|
|
23759
|
+
const anchorPageIndex = resolvePinchAnchorPageIndex(
|
|
23760
|
+
focalX,
|
|
23761
|
+
focalY,
|
|
23762
|
+
zoom,
|
|
23763
|
+
viewerScrollOffsetY
|
|
23764
|
+
);
|
|
23765
|
+
const { pageOffsetY: startPageOffsetY, pageHeight: startPageHeight } = getPageLayoutForZoom(anchorPageIndex, zoom);
|
|
23766
|
+
const startPageWidth = getPageWidthForZoom(anchorPageIndex, zoom);
|
|
23767
|
+
const {
|
|
23768
|
+
viewportWidth: pageViewportWidth,
|
|
23769
|
+
horizontalPadding: pageHorizontalPadding,
|
|
23770
|
+
viewportOffsetX
|
|
23771
|
+
} = getPageViewportMetrics(anchorPageIndex);
|
|
23772
|
+
const pageViewportContentWidth = Math.max(
|
|
23773
|
+
0,
|
|
23774
|
+
pageViewportWidth - pageHorizontalPadding * 2
|
|
23775
|
+
);
|
|
23776
|
+
pendingPinchAnchorRestoreRef.current = {
|
|
23777
|
+
finalZoom,
|
|
23778
|
+
focalY,
|
|
23779
|
+
viewerScrollOffsetY,
|
|
23780
|
+
pageIndex: anchorPageIndex,
|
|
23781
|
+
startPageOffsetY,
|
|
23782
|
+
startPageHeight,
|
|
23783
|
+
startPageWidth,
|
|
23784
|
+
startPageScrollX: horizontalScrollOffsetsRef.current.get(anchorPageIndex) ?? 0,
|
|
23785
|
+
pageViewportWidth,
|
|
23786
|
+
pageHorizontalPadding,
|
|
23787
|
+
pageViewportContentOffsetX: Math.max(
|
|
23788
|
+
0,
|
|
23789
|
+
Math.min(
|
|
23790
|
+
pageViewportContentWidth,
|
|
23791
|
+
focalX - viewportOffsetX - pageHorizontalPadding
|
|
23792
|
+
)
|
|
23793
|
+
)
|
|
23794
|
+
};
|
|
23795
|
+
setDocumentStateTracked({ zoom: finalZoom }, "pinch.viewerEnd");
|
|
23796
|
+
engine.setZoom(finalZoom);
|
|
23797
|
+
} else {
|
|
23798
|
+
pendingPinchAnchorRestoreRef.current = null;
|
|
23799
|
+
}
|
|
23800
|
+
resetViewerPinchPreview();
|
|
23801
|
+
handleGestureScrollLockChange(false);
|
|
23802
|
+
if (perfEnabled) {
|
|
23803
|
+
logPerfEvent("Viewer", "pinch.end", {
|
|
23804
|
+
finalZoom: Math.round(finalZoom * 100) / 100,
|
|
23805
|
+
page: pendingPinchAnchorRestoreRef.current?.pageIndex ?? null
|
|
23806
|
+
});
|
|
23807
|
+
}
|
|
23808
|
+
}, [
|
|
23809
|
+
engine,
|
|
23810
|
+
getPageLayoutForZoom,
|
|
23811
|
+
getPageViewportMetrics,
|
|
23812
|
+
getPageWidthForZoom,
|
|
23813
|
+
handleGestureScrollLockChange,
|
|
23814
|
+
perfEnabled,
|
|
23815
|
+
resetViewerPinchPreview,
|
|
23816
|
+
resolvePinchAnchorPageIndex,
|
|
23817
|
+
setDocumentStateTracked,
|
|
23818
|
+
zoom
|
|
23819
|
+
]);
|
|
23820
|
+
const handlePageHorizontalScrollOffsetChange = (0, import_react3.useCallback)(
|
|
23821
|
+
(pageIndex, offsetX) => {
|
|
23822
|
+
horizontalScrollOffsetsRef.current.set(pageIndex, Math.max(0, offsetX));
|
|
23823
|
+
const pageWidth = getPageWidthForZoom(pageIndex, zoom);
|
|
23824
|
+
const { viewportWidth, horizontalPadding: horizontalPadding2 } = getPageViewportMetrics(pageIndex);
|
|
23825
|
+
const pageViewportWidth = Math.max(
|
|
23826
|
+
0,
|
|
23827
|
+
viewportWidth - horizontalPadding2 * 2
|
|
23828
|
+
);
|
|
23829
|
+
const nextOffsetX = resolveClampedScrollOffset(
|
|
23830
|
+
offsetX,
|
|
23831
|
+
pageWidth,
|
|
23832
|
+
pageViewportWidth
|
|
23833
|
+
);
|
|
23834
|
+
setHorizontalScrollRestore((current) => {
|
|
23835
|
+
if (current && Math.abs(current.offsetX - nextOffsetX) < 0.5) {
|
|
23836
|
+
return current;
|
|
23837
|
+
}
|
|
23838
|
+
const requestId = nextHorizontalRestoreRequestIdRef.current + 1;
|
|
23839
|
+
nextHorizontalRestoreRequestIdRef.current = requestId;
|
|
23840
|
+
return {
|
|
23841
|
+
pageIndex,
|
|
23842
|
+
requestId,
|
|
23843
|
+
offsetX: nextOffsetX
|
|
23844
|
+
};
|
|
23845
|
+
});
|
|
23846
|
+
},
|
|
23847
|
+
[getPageViewportMetrics, getPageWidthForZoom, zoom]
|
|
23848
|
+
);
|
|
23849
|
+
const viewerPinchGesture = (0, import_react3.useMemo)(
|
|
23850
|
+
() => import_react_native_gesture_handler2.Gesture.Pinch().enabled(!isWebView && pageCount > 0).onTouchesDown((event) => {
|
|
23851
|
+
if ((event.allTouches?.length ?? 0) >= 2) {
|
|
23852
|
+
handleGestureScrollLockChange(true);
|
|
23853
|
+
}
|
|
23854
|
+
}).onTouchesUp((event) => {
|
|
23855
|
+
if ((event.allTouches?.length ?? 0) < 2 && !pinchGestureActiveRef.current) {
|
|
23856
|
+
handleGestureScrollLockChange(false);
|
|
23857
|
+
}
|
|
23858
|
+
}).runOnJS(true).onStart((event) => {
|
|
23859
|
+
beginViewerPinch(event.focalX, event.focalY);
|
|
23860
|
+
}).onUpdate((event) => {
|
|
23861
|
+
updateViewerPinch(event.scale, event.focalX, event.focalY);
|
|
23862
|
+
}).onEnd(() => {
|
|
23863
|
+
finishViewerPinch();
|
|
23864
|
+
}).onFinalize(() => {
|
|
23865
|
+
finishViewerPinch();
|
|
23866
|
+
resetViewerPinchPreview();
|
|
23867
|
+
handleGestureScrollLockChange(false);
|
|
23868
|
+
}),
|
|
23869
|
+
[
|
|
23870
|
+
beginViewerPinch,
|
|
23871
|
+
finishViewerPinch,
|
|
23872
|
+
handleGestureScrollLockChange,
|
|
23873
|
+
isWebView,
|
|
23874
|
+
pageCount,
|
|
23875
|
+
resetViewerPinchPreview,
|
|
23876
|
+
updateViewerPinch
|
|
23877
|
+
]
|
|
23878
|
+
);
|
|
23879
|
+
(0, import_react3.useEffect)(() => {
|
|
23880
|
+
selectionDragActiveRef.current = selectionDragActive;
|
|
23881
|
+
syncViewerScrollEnabled(
|
|
23882
|
+
selectionDragActive,
|
|
23883
|
+
gestureScrollLockActiveRef.current
|
|
23884
|
+
);
|
|
23885
|
+
}, [selectionDragActive, syncViewerScrollEnabled]);
|
|
23886
|
+
(0, import_react3.useEffect)(() => {
|
|
23887
|
+
const pendingRestore = pendingPinchAnchorRestoreRef.current;
|
|
23888
|
+
if (!pendingRestore) return;
|
|
23889
|
+
if (Math.abs(pendingRestore.finalZoom - zoom) >= 1e-3) return;
|
|
23890
|
+
if (pinchAnchorRestoreFrameRef.current !== null) {
|
|
23891
|
+
cancelAnimationFrame(pinchAnchorRestoreFrameRef.current);
|
|
23892
|
+
}
|
|
23893
|
+
pinchAnchorRestoreFrameRef.current = requestAnimationFrame(() => {
|
|
23894
|
+
pinchAnchorRestoreFrameRef.current = null;
|
|
23895
|
+
const {
|
|
23896
|
+
pageOffsetY: endPageOffsetY,
|
|
23897
|
+
pageHeight: endPageHeight,
|
|
23898
|
+
totalContentHeight: endContentHeight
|
|
23899
|
+
} = getPageLayoutForZoom(pendingRestore.pageIndex, zoom);
|
|
23900
|
+
const viewerViewportHeight = viewerFrameRef.current.height;
|
|
23901
|
+
const nextScrollY = resolveAnchoredViewportOffset({
|
|
23902
|
+
viewportOffset: pendingRestore.focalY,
|
|
23903
|
+
startScrollOffset: pendingRestore.viewerScrollOffsetY,
|
|
23904
|
+
startItemOffset: pendingRestore.startPageOffsetY,
|
|
23905
|
+
startItemLength: pendingRestore.startPageHeight,
|
|
23906
|
+
endItemOffset: endPageOffsetY,
|
|
23907
|
+
endItemLength: endPageHeight,
|
|
23908
|
+
viewportLength: viewerViewportHeight,
|
|
23909
|
+
endContentLength: endContentHeight
|
|
23910
|
+
});
|
|
23911
|
+
if (isSingle) {
|
|
23912
|
+
listRef.current?.scrollTo?.({
|
|
23913
|
+
y: nextScrollY,
|
|
23914
|
+
animated: false
|
|
23915
|
+
});
|
|
23916
|
+
} else {
|
|
23917
|
+
listRef.current?.scrollToOffset({
|
|
23918
|
+
offset: nextScrollY,
|
|
23919
|
+
animated: false
|
|
23920
|
+
});
|
|
23921
|
+
}
|
|
23922
|
+
lastScrollOffsetYRef.current = nextScrollY;
|
|
23923
|
+
const endPageWidth = getPageWidthForZoom(pendingRestore.pageIndex, zoom);
|
|
23924
|
+
const pageViewportContentWidth = Math.max(
|
|
23925
|
+
0,
|
|
23926
|
+
pendingRestore.pageViewportWidth - pendingRestore.pageHorizontalPadding * 2
|
|
23927
|
+
);
|
|
23928
|
+
const nextOffsetX = resolveAnchoredViewportOffset({
|
|
23929
|
+
viewportOffset: pendingRestore.pageViewportContentOffsetX,
|
|
23930
|
+
startScrollOffset: pendingRestore.startPageScrollX,
|
|
23931
|
+
startItemOffset: 0,
|
|
23932
|
+
startItemLength: pendingRestore.startPageWidth,
|
|
23933
|
+
endItemOffset: 0,
|
|
23934
|
+
endItemLength: endPageWidth,
|
|
23935
|
+
viewportLength: pageViewportContentWidth,
|
|
23936
|
+
endContentLength: endPageWidth
|
|
23937
|
+
});
|
|
23938
|
+
const requestId = nextHorizontalRestoreRequestIdRef.current + 1;
|
|
23939
|
+
nextHorizontalRestoreRequestIdRef.current = requestId;
|
|
23940
|
+
setHorizontalScrollRestore({
|
|
23941
|
+
pageIndex: pendingRestore.pageIndex,
|
|
23942
|
+
requestId,
|
|
23943
|
+
offsetX: nextOffsetX
|
|
23944
|
+
});
|
|
23945
|
+
pendingPinchAnchorRestoreRef.current = null;
|
|
23946
|
+
if (perfEnabled) {
|
|
23947
|
+
logPerfEvent("Viewer", "pinch.anchorRestore", {
|
|
23948
|
+
page: pendingRestore.pageIndex + 1,
|
|
23949
|
+
scrollY: Math.round(nextScrollY * 100) / 100,
|
|
23950
|
+
scrollX: Math.round(nextOffsetX * 100) / 100,
|
|
23951
|
+
zoom: Math.round(zoom * 100) / 100
|
|
23952
|
+
});
|
|
23953
|
+
}
|
|
23954
|
+
});
|
|
23955
|
+
return () => {
|
|
23956
|
+
if (pinchAnchorRestoreFrameRef.current !== null) {
|
|
23957
|
+
cancelAnimationFrame(pinchAnchorRestoreFrameRef.current);
|
|
23958
|
+
pinchAnchorRestoreFrameRef.current = null;
|
|
23959
|
+
}
|
|
23960
|
+
};
|
|
23961
|
+
}, [getPageLayoutForZoom, getPageWidthForZoom, isSingle, perfEnabled, zoom]);
|
|
23962
|
+
(0, import_react3.useEffect)(() => {
|
|
23963
|
+
if (zoom > 1) return;
|
|
23964
|
+
setHorizontalScrollRestore((current) => {
|
|
23965
|
+
if (!current || Math.abs(current.offsetX) < 0.5) {
|
|
23966
|
+
return current;
|
|
23967
|
+
}
|
|
23968
|
+
const requestId = nextHorizontalRestoreRequestIdRef.current + 1;
|
|
23969
|
+
nextHorizontalRestoreRequestIdRef.current = requestId;
|
|
23970
|
+
return {
|
|
23971
|
+
pageIndex: current.pageIndex,
|
|
23972
|
+
requestId,
|
|
23973
|
+
offsetX: 0
|
|
23974
|
+
};
|
|
23975
|
+
});
|
|
23976
|
+
}, [zoom]);
|
|
23977
|
+
const captureViewerFrame = (0, import_react3.useCallback)((node) => {
|
|
23978
|
+
const measurable = node;
|
|
23979
|
+
measurable?.measureInWindow?.((_, y, __, height) => {
|
|
23980
|
+
viewerFrameRef.current = { y, height };
|
|
23981
|
+
});
|
|
23982
|
+
}, []);
|
|
23983
|
+
const scrollViewerBy = (0, import_react3.useCallback)(
|
|
23984
|
+
(deltaY) => {
|
|
23985
|
+
if (!Number.isFinite(deltaY) || deltaY === 0) return 0;
|
|
23986
|
+
const viewportHeight = viewerFrameRef.current.height;
|
|
23987
|
+
const maxOffset = Math.max(
|
|
23988
|
+
0,
|
|
23989
|
+
viewerContentHeightRef.current - viewportHeight
|
|
23990
|
+
);
|
|
23991
|
+
const nextOffset = Math.max(
|
|
23992
|
+
0,
|
|
23993
|
+
Math.min(maxOffset, lastScrollOffsetYRef.current + deltaY)
|
|
23994
|
+
);
|
|
23995
|
+
const appliedDelta = nextOffset - lastScrollOffsetYRef.current;
|
|
23996
|
+
if (appliedDelta === 0) return 0;
|
|
23997
|
+
lastScrollOffsetYRef.current = nextOffset;
|
|
23998
|
+
if (isSingle) {
|
|
23999
|
+
listRef.current?.scrollTo?.({
|
|
24000
|
+
y: nextOffset,
|
|
24001
|
+
animated: false
|
|
24002
|
+
});
|
|
24003
|
+
return appliedDelta;
|
|
24004
|
+
}
|
|
24005
|
+
listRef.current?.scrollToOffset({ offset: nextOffset, animated: false });
|
|
24006
|
+
return appliedDelta;
|
|
24007
|
+
},
|
|
24008
|
+
[isSingle]
|
|
24009
|
+
);
|
|
24010
|
+
const handleSelectionVerticalAutoscroll = (0, import_react3.useCallback)(
|
|
24011
|
+
(absoluteY) => {
|
|
24012
|
+
const frame = viewerFrameRef.current;
|
|
24013
|
+
if (!Number.isFinite(absoluteY) || frame.height <= 0) return 0;
|
|
24014
|
+
const relativeY = absoluteY - frame.y;
|
|
24015
|
+
const { dy } = getSelectionEdgeAutoscroll({
|
|
24016
|
+
x: SELECTION_EDGE_THRESHOLD_PX2,
|
|
24017
|
+
y: relativeY,
|
|
24018
|
+
width: SELECTION_EDGE_THRESHOLD_PX2 * 2,
|
|
24019
|
+
height: frame.height,
|
|
24020
|
+
threshold: SELECTION_EDGE_THRESHOLD_PX2,
|
|
24021
|
+
maxStep: SELECTION_EDGE_MAX_STEP_PX2
|
|
24022
|
+
});
|
|
24023
|
+
return scrollViewerBy(dy);
|
|
24024
|
+
},
|
|
24025
|
+
[scrollViewerBy]
|
|
24026
|
+
);
|
|
23124
24027
|
const listLayoutMetrics = (0, import_react3.useMemo)(() => {
|
|
23125
24028
|
const offsets = [];
|
|
23126
24029
|
const lengths = [];
|
|
@@ -23361,7 +24264,13 @@ var Viewer = ({
|
|
|
23361
24264
|
pageIndex: row.left,
|
|
23362
24265
|
availableWidth: columnWidth,
|
|
23363
24266
|
horizontalPadding: 8,
|
|
23364
|
-
spacing: DOUBLE_PAGE_SPACING
|
|
24267
|
+
spacing: DOUBLE_PAGE_SPACING,
|
|
24268
|
+
onSelectionDragActiveChange: setSelectionDragActive,
|
|
24269
|
+
gestureScrollLockActive,
|
|
24270
|
+
lastPinchEndedAt,
|
|
24271
|
+
onHorizontalScrollOffsetChange: handlePageHorizontalScrollOffsetChange,
|
|
24272
|
+
horizontalScrollRestore,
|
|
24273
|
+
requestSelectionVerticalAutoscroll: handleSelectionVerticalAutoscroll
|
|
23365
24274
|
}
|
|
23366
24275
|
) }),
|
|
23367
24276
|
row.right !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: { width: columnWidth }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -23371,7 +24280,13 @@ var Viewer = ({
|
|
|
23371
24280
|
pageIndex: row.right,
|
|
23372
24281
|
availableWidth: columnWidth,
|
|
23373
24282
|
horizontalPadding: 8,
|
|
23374
|
-
spacing: DOUBLE_PAGE_SPACING
|
|
24283
|
+
spacing: DOUBLE_PAGE_SPACING,
|
|
24284
|
+
onSelectionDragActiveChange: setSelectionDragActive,
|
|
24285
|
+
gestureScrollLockActive,
|
|
24286
|
+
lastPinchEndedAt,
|
|
24287
|
+
onHorizontalScrollOffsetChange: handlePageHorizontalScrollOffsetChange,
|
|
24288
|
+
horizontalScrollRestore,
|
|
24289
|
+
requestSelectionVerticalAutoscroll: handleSelectionVerticalAutoscroll
|
|
23375
24290
|
}
|
|
23376
24291
|
) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: { width: columnWidth } })
|
|
23377
24292
|
] });
|
|
@@ -23381,114 +24296,170 @@ var Viewer = ({
|
|
|
23381
24296
|
{
|
|
23382
24297
|
engine,
|
|
23383
24298
|
pageIndex: item,
|
|
23384
|
-
spacing: CONTINUOUS_PAGE_SPACING
|
|
24299
|
+
spacing: CONTINUOUS_PAGE_SPACING,
|
|
24300
|
+
onSelectionDragActiveChange: setSelectionDragActive,
|
|
24301
|
+
gestureScrollLockActive,
|
|
24302
|
+
lastPinchEndedAt,
|
|
24303
|
+
onHorizontalScrollOffsetChange: handlePageHorizontalScrollOffsetChange,
|
|
24304
|
+
horizontalScrollRestore,
|
|
24305
|
+
requestSelectionVerticalAutoscroll: handleSelectionVerticalAutoscroll
|
|
23385
24306
|
}
|
|
23386
24307
|
);
|
|
23387
24308
|
},
|
|
23388
|
-
[
|
|
24309
|
+
[
|
|
24310
|
+
columnWidth,
|
|
24311
|
+
engine,
|
|
24312
|
+
handlePageHorizontalScrollOffsetChange,
|
|
24313
|
+
handleSelectionVerticalAutoscroll,
|
|
24314
|
+
gestureScrollLockActive,
|
|
24315
|
+
horizontalScrollRestore,
|
|
24316
|
+
horizontalPadding,
|
|
24317
|
+
isDouble,
|
|
24318
|
+
lastPinchEndedAt
|
|
24319
|
+
]
|
|
23389
24320
|
);
|
|
23390
24321
|
if (isWebView) {
|
|
23391
24322
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.container, isDark && styles3.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WebViewViewer_default, { engine }) });
|
|
23392
24323
|
}
|
|
23393
24324
|
if (isSingle) {
|
|
23394
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.container, isDark && styles3.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
23395
|
-
import_react_native3.
|
|
24325
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.container, isDark && styles3.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_gesture_handler2.GestureDetector, { gesture: viewerPinchGesture, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
24326
|
+
import_react_native3.View,
|
|
23396
24327
|
{
|
|
23397
|
-
|
|
23398
|
-
|
|
23399
|
-
|
|
23400
|
-
|
|
23401
|
-
onScrollBeginDrag: perfEnabled ? () => {
|
|
23402
|
-
scrollMonitorRef.current.begin("single.beginDrag");
|
|
23403
|
-
} : void 0,
|
|
23404
|
-
onMomentumScrollBegin: perfEnabled ? () => {
|
|
23405
|
-
scrollMonitorRef.current.begin("single.momentumBegin");
|
|
23406
|
-
} : void 0,
|
|
23407
|
-
onScrollEndDrag: perfEnabled ? () => {
|
|
23408
|
-
scrollMonitorRef.current.end("single.endDrag");
|
|
23409
|
-
sampleMemory("Viewer", "single.endDrag", { pageCount });
|
|
23410
|
-
} : void 0,
|
|
23411
|
-
onMomentumScrollEnd: perfEnabled ? () => {
|
|
23412
|
-
scrollMonitorRef.current.end("single.momentumEnd");
|
|
23413
|
-
sampleMemory("Viewer", "single.momentumEnd", { pageCount });
|
|
23414
|
-
} : void 0,
|
|
23415
|
-
scrollEventThrottle: 16,
|
|
24328
|
+
style: [
|
|
24329
|
+
styles3.gestureSurface,
|
|
24330
|
+
{ transform: [{ scale: pinchPreviewScale }] }
|
|
24331
|
+
],
|
|
23416
24332
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
23417
|
-
|
|
24333
|
+
import_react_native3.ScrollView,
|
|
23418
24334
|
{
|
|
23419
|
-
|
|
23420
|
-
|
|
23421
|
-
|
|
24335
|
+
ref: (node) => {
|
|
24336
|
+
captureViewerFrame(node);
|
|
24337
|
+
listRef.current = node;
|
|
24338
|
+
},
|
|
24339
|
+
contentContainerStyle: styles3.singleContent,
|
|
24340
|
+
showsVerticalScrollIndicator: false,
|
|
24341
|
+
scrollEnabled: resolvedViewerScrollEnabled,
|
|
24342
|
+
onLayout: () => captureViewerFrame(listRef.current),
|
|
24343
|
+
onContentSizeChange: (_, height) => {
|
|
24344
|
+
viewerContentHeightRef.current = height;
|
|
24345
|
+
},
|
|
24346
|
+
onScroll: (event) => handleViewerScroll(event, "single"),
|
|
24347
|
+
onScrollBeginDrag: perfEnabled ? () => {
|
|
24348
|
+
scrollMonitorRef.current.begin("single.beginDrag");
|
|
24349
|
+
} : void 0,
|
|
24350
|
+
onMomentumScrollBegin: perfEnabled ? () => {
|
|
24351
|
+
scrollMonitorRef.current.begin("single.momentumBegin");
|
|
24352
|
+
} : void 0,
|
|
24353
|
+
onScrollEndDrag: perfEnabled ? () => {
|
|
24354
|
+
scrollMonitorRef.current.end("single.endDrag");
|
|
24355
|
+
sampleMemory("Viewer", "single.endDrag", { pageCount });
|
|
24356
|
+
} : void 0,
|
|
24357
|
+
onMomentumScrollEnd: perfEnabled ? () => {
|
|
24358
|
+
scrollMonitorRef.current.end("single.momentumEnd");
|
|
24359
|
+
sampleMemory("Viewer", "single.momentumEnd", {
|
|
24360
|
+
pageCount
|
|
24361
|
+
});
|
|
24362
|
+
} : void 0,
|
|
24363
|
+
scrollEventThrottle: 16,
|
|
24364
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
24365
|
+
PageRenderer_default,
|
|
24366
|
+
{
|
|
24367
|
+
engine,
|
|
24368
|
+
pageIndex: Math.max(0, currentPage - 1),
|
|
24369
|
+
spacing: 32,
|
|
24370
|
+
onSelectionDragActiveChange: setSelectionDragActive,
|
|
24371
|
+
gestureScrollLockActive,
|
|
24372
|
+
lastPinchEndedAt,
|
|
24373
|
+
onHorizontalScrollOffsetChange: handlePageHorizontalScrollOffsetChange,
|
|
24374
|
+
horizontalScrollRestore,
|
|
24375
|
+
requestSelectionVerticalAutoscroll: handleSelectionVerticalAutoscroll
|
|
24376
|
+
}
|
|
24377
|
+
)
|
|
23422
24378
|
}
|
|
23423
24379
|
)
|
|
23424
24380
|
}
|
|
23425
|
-
) });
|
|
24381
|
+
) }) });
|
|
23426
24382
|
}
|
|
23427
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.container, isDark && styles3.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
23428
|
-
import_react_native3.
|
|
24383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: [styles3.container, isDark && styles3.containerDark], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native_gesture_handler2.GestureDetector, { gesture: viewerPinchGesture, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
24384
|
+
import_react_native3.View,
|
|
23429
24385
|
{
|
|
23430
|
-
|
|
23431
|
-
|
|
23432
|
-
|
|
23433
|
-
|
|
23434
|
-
|
|
23435
|
-
|
|
23436
|
-
|
|
23437
|
-
|
|
23438
|
-
|
|
23439
|
-
|
|
23440
|
-
|
|
23441
|
-
|
|
23442
|
-
|
|
23443
|
-
|
|
23444
|
-
|
|
23445
|
-
|
|
23446
|
-
|
|
23447
|
-
|
|
23448
|
-
|
|
23449
|
-
|
|
23450
|
-
|
|
23451
|
-
|
|
23452
|
-
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
|
|
24386
|
+
style: [
|
|
24387
|
+
styles3.gestureSurface,
|
|
24388
|
+
{ transform: [{ scale: pinchPreviewScale }] }
|
|
24389
|
+
],
|
|
24390
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
24391
|
+
import_react_native3.FlatList,
|
|
24392
|
+
{
|
|
24393
|
+
ref: listRef,
|
|
24394
|
+
data: isDouble ? rows : pages,
|
|
24395
|
+
initialNumToRender: FLATLIST_INITIAL_NUM_TO_RENDER,
|
|
24396
|
+
windowSize: resolvedWindowSize,
|
|
24397
|
+
maxToRenderPerBatch: resolvedMaxToRenderPerBatch,
|
|
24398
|
+
updateCellsBatchingPeriod: FLATLIST_UPDATE_CELLS_BATCHING_PERIOD,
|
|
24399
|
+
removeClippedSubviews: resolvedRemoveClippedSubviews,
|
|
24400
|
+
getItemLayout,
|
|
24401
|
+
keyExtractor,
|
|
24402
|
+
contentContainerStyle: styles3.listContent,
|
|
24403
|
+
renderItem,
|
|
24404
|
+
onViewableItemsChanged,
|
|
24405
|
+
viewabilityConfig: { itemVisiblePercentThreshold: 60 },
|
|
24406
|
+
scrollEnabled: resolvedViewerScrollEnabled,
|
|
24407
|
+
onLayout: () => captureViewerFrame(listRef.current),
|
|
24408
|
+
onContentSizeChange: (_, height) => {
|
|
24409
|
+
viewerContentHeightRef.current = height;
|
|
24410
|
+
},
|
|
24411
|
+
onScrollToIndexFailed: ({ index, averageItemLength }) => {
|
|
24412
|
+
const dataLength = isDouble ? rows.length : pages.length;
|
|
24413
|
+
if (index < 0 || index >= dataLength) return;
|
|
24414
|
+
pendingScrollIndexRef.current = index;
|
|
24415
|
+
const offset = Math.max(0, getFallbackOffsetForIndex(index));
|
|
24416
|
+
listRef.current?.scrollToOffset({ offset, animated: false });
|
|
24417
|
+
if (!isDouble) {
|
|
24418
|
+
ensurePageDimensions(index);
|
|
24419
|
+
} else {
|
|
24420
|
+
const row = rows[index];
|
|
24421
|
+
if (row) {
|
|
24422
|
+
ensurePageDimensions(row.left);
|
|
24423
|
+
if (row.right !== null) {
|
|
24424
|
+
ensurePageDimensions(row.right);
|
|
24425
|
+
}
|
|
24426
|
+
}
|
|
23458
24427
|
}
|
|
23459
|
-
|
|
23460
|
-
|
|
23461
|
-
|
|
23462
|
-
|
|
23463
|
-
|
|
23464
|
-
|
|
23465
|
-
|
|
23466
|
-
|
|
23467
|
-
|
|
23468
|
-
|
|
23469
|
-
|
|
23470
|
-
}
|
|
24428
|
+
scheduleScrollRetry("onScrollToIndexFailed");
|
|
24429
|
+
if (perfEnabled) {
|
|
24430
|
+
logPerfEvent("Viewer", "scrollToIndexFailed", {
|
|
24431
|
+
index,
|
|
24432
|
+
averageItemLength,
|
|
24433
|
+
fallbackOffset: offset,
|
|
24434
|
+
fallbackSource: "cached-item-layout",
|
|
24435
|
+
itemCount: dataLength,
|
|
24436
|
+
retryAttempt: pendingScrollAttemptsRef.current
|
|
24437
|
+
});
|
|
24438
|
+
}
|
|
24439
|
+
},
|
|
24440
|
+
onScroll: (event) => handleViewerScroll(event, "continuous"),
|
|
24441
|
+
onScrollBeginDrag: perfEnabled ? () => {
|
|
24442
|
+
scrollMonitorRef.current.begin("continuous.beginDrag");
|
|
24443
|
+
} : void 0,
|
|
24444
|
+
onMomentumScrollBegin: perfEnabled ? () => {
|
|
24445
|
+
scrollMonitorRef.current.begin("continuous.momentumBegin");
|
|
24446
|
+
} : void 0,
|
|
24447
|
+
onScrollEndDrag: perfEnabled ? () => {
|
|
24448
|
+
scrollMonitorRef.current.end("continuous.endDrag");
|
|
24449
|
+
sampleMemory("Viewer", "continuous.endDrag", { pageCount });
|
|
24450
|
+
} : void 0,
|
|
24451
|
+
onMomentumScrollEnd: perfEnabled ? () => {
|
|
24452
|
+
scrollMonitorRef.current.end("continuous.momentumEnd");
|
|
24453
|
+
sampleMemory("Viewer", "continuous.momentumEnd", {
|
|
24454
|
+
pageCount
|
|
24455
|
+
});
|
|
24456
|
+
} : void 0,
|
|
24457
|
+
scrollEventThrottle: 16,
|
|
24458
|
+
showsVerticalScrollIndicator: false
|
|
23471
24459
|
}
|
|
23472
|
-
|
|
23473
|
-
onScroll: (event) => handleViewerScroll(event, "continuous"),
|
|
23474
|
-
onScrollBeginDrag: perfEnabled ? () => {
|
|
23475
|
-
scrollMonitorRef.current.begin("continuous.beginDrag");
|
|
23476
|
-
} : void 0,
|
|
23477
|
-
onMomentumScrollBegin: perfEnabled ? () => {
|
|
23478
|
-
scrollMonitorRef.current.begin("continuous.momentumBegin");
|
|
23479
|
-
} : void 0,
|
|
23480
|
-
onScrollEndDrag: perfEnabled ? () => {
|
|
23481
|
-
scrollMonitorRef.current.end("continuous.endDrag");
|
|
23482
|
-
sampleMemory("Viewer", "continuous.endDrag", { pageCount });
|
|
23483
|
-
} : void 0,
|
|
23484
|
-
onMomentumScrollEnd: perfEnabled ? () => {
|
|
23485
|
-
scrollMonitorRef.current.end("continuous.momentumEnd");
|
|
23486
|
-
sampleMemory("Viewer", "continuous.momentumEnd", { pageCount });
|
|
23487
|
-
} : void 0,
|
|
23488
|
-
scrollEventThrottle: 16,
|
|
23489
|
-
showsVerticalScrollIndicator: false
|
|
24460
|
+
)
|
|
23490
24461
|
}
|
|
23491
|
-
) });
|
|
24462
|
+
) }) });
|
|
23492
24463
|
};
|
|
23493
24464
|
var styles3 = import_react_native3.StyleSheet.create({
|
|
23494
24465
|
container: {
|
|
@@ -23498,6 +24469,9 @@ var styles3 = import_react_native3.StyleSheet.create({
|
|
|
23498
24469
|
containerDark: {
|
|
23499
24470
|
backgroundColor: "#0f1115"
|
|
23500
24471
|
},
|
|
24472
|
+
gestureSurface: {
|
|
24473
|
+
flex: 1
|
|
24474
|
+
},
|
|
23501
24475
|
listContent: {
|
|
23502
24476
|
paddingTop: LIST_TOP_PADDING,
|
|
23503
24477
|
paddingBottom: LIST_BOTTOM_PADDING
|
|
@@ -24170,6 +25144,7 @@ var ToolDock = () => {
|
|
|
24170
25144
|
setAnnotationColor,
|
|
24171
25145
|
accentColor,
|
|
24172
25146
|
activeTool,
|
|
25147
|
+
interactionMode,
|
|
24173
25148
|
toolDockOpen,
|
|
24174
25149
|
setDocumentState
|
|
24175
25150
|
} = (0, import_core5.useViewerStore)();
|
|
@@ -24181,7 +25156,12 @@ var ToolDock = () => {
|
|
|
24181
25156
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24182
25157
|
import_react_native5.Pressable,
|
|
24183
25158
|
{
|
|
24184
|
-
onPress: () => setDocumentState(
|
|
25159
|
+
onPress: () => setDocumentState(
|
|
25160
|
+
getToolDockDismissState({
|
|
25161
|
+
activeTool,
|
|
25162
|
+
interactionMode
|
|
25163
|
+
})
|
|
25164
|
+
),
|
|
24185
25165
|
style: [styles5.closeButton, isDark && styles5.closeButtonDark],
|
|
24186
25166
|
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24187
25167
|
import_react_native5.Text,
|
|
@@ -24194,12 +25174,29 @@ var ToolDock = () => {
|
|
|
24194
25174
|
)
|
|
24195
25175
|
] }),
|
|
24196
25176
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.View, { style: styles5.toolsRow, children: TOOL_OPTIONS.map((tool) => {
|
|
24197
|
-
const isSelected =
|
|
25177
|
+
const isSelected = isToolDockToolSelected({
|
|
25178
|
+
toolId: tool.id,
|
|
25179
|
+
activeTool,
|
|
25180
|
+
interactionMode
|
|
25181
|
+
});
|
|
24198
25182
|
const label = tool.label === "note" ? t.note : tool.label === "select" ? t.select : tool.label === "underline" ? t.underline : tool.label === "squiggly" ? t.squiggly : tool.label === "strikeout" ? t.strikeout : tool.label === "ink" ? t.ink : t.highlight;
|
|
24199
25183
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
24200
25184
|
import_react_native5.Pressable,
|
|
24201
25185
|
{
|
|
24202
|
-
onPress: () =>
|
|
25186
|
+
onPress: () => {
|
|
25187
|
+
if (tool.id === "select") {
|
|
25188
|
+
const shouldArmSelection = activeTool !== "select" || interactionMode !== "select";
|
|
25189
|
+
setDocumentState({
|
|
25190
|
+
activeTool: "select",
|
|
25191
|
+
interactionMode: shouldArmSelection ? "select" : "pan"
|
|
25192
|
+
});
|
|
25193
|
+
return;
|
|
25194
|
+
}
|
|
25195
|
+
setDocumentState({
|
|
25196
|
+
activeTool: tool.id,
|
|
25197
|
+
interactionMode: "pan"
|
|
25198
|
+
});
|
|
25199
|
+
},
|
|
24203
25200
|
style: [
|
|
24204
25201
|
styles5.toolButton,
|
|
24205
25202
|
isDark && styles5.toolButtonDark,
|