@papyrus-sdk/ui-react-native 0.2.26 → 0.2.27
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.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +418 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +447 -122
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25460,6 +25460,12 @@ var resolvePageTapChromeVisibility = ({
|
|
|
25460
25460
|
return !chromeVisible;
|
|
25461
25461
|
};
|
|
25462
25462
|
|
|
25463
|
+
// components/selectionContentInteraction.ts
|
|
25464
|
+
var shouldDismissSelectionOnContentInteraction = ({
|
|
25465
|
+
selectionActive,
|
|
25466
|
+
interaction
|
|
25467
|
+
}) => selectionActive && (interaction === "tap" || interaction === "scroll");
|
|
25468
|
+
|
|
25463
25469
|
// components/DedicatedAndroidPdfViewer.tsx
|
|
25464
25470
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
25465
25471
|
var TEXT_MARKUP_TOOLS2 = /* @__PURE__ */ new Set(["highlight", "underline", "squiggly", "strikeout"]);
|
|
@@ -25640,6 +25646,13 @@ function DedicatedAndroidPdfViewer({
|
|
|
25640
25646
|
setSelectedAnnotation(event.nativeEvent.id);
|
|
25641
25647
|
},
|
|
25642
25648
|
onTap: () => {
|
|
25649
|
+
if (shouldDismissSelectionOnContentInteraction({
|
|
25650
|
+
selectionActive: selectionRef.current !== null,
|
|
25651
|
+
interaction: "tap"
|
|
25652
|
+
})) {
|
|
25653
|
+
setSelection(null);
|
|
25654
|
+
selectionRef.current = null;
|
|
25655
|
+
}
|
|
25643
25656
|
const nextVisible = resolvePageTapChromeVisibility({
|
|
25644
25657
|
chromeVisible: chromeVisibleRef.current,
|
|
25645
25658
|
selectionActive: selectionRef.current !== null,
|
|
@@ -25666,66 +25679,61 @@ function DedicatedAndroidPdfViewer({
|
|
|
25666
25679
|
}
|
|
25667
25680
|
},
|
|
25668
25681
|
onScroll: (event) => {
|
|
25682
|
+
if (shouldDismissSelectionOnContentInteraction({
|
|
25683
|
+
selectionActive: selectionRef.current !== null,
|
|
25684
|
+
interaction: "scroll"
|
|
25685
|
+
})) {
|
|
25686
|
+
setSelection(null);
|
|
25687
|
+
selectionRef.current = null;
|
|
25688
|
+
}
|
|
25669
25689
|
trackMobileChromeByOffset(event.nativeEvent.offsetY, "native.scroll");
|
|
25670
25690
|
}
|
|
25671
25691
|
}
|
|
25672
25692
|
),
|
|
25673
|
-
selection && /* @__PURE__ */ (0, import_jsx_runtime5.
|
|
25693
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native3.View, { style: styles3.selectionToolbar, pointerEvents: "box-none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native3.View, { style: styles3.toolbarContent, children: [
|
|
25674
25694
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25675
25695
|
import_react_native3.Pressable,
|
|
25676
25696
|
{
|
|
25677
|
-
style: styles3.overlay,
|
|
25678
25697
|
onPress: () => {
|
|
25679
|
-
|
|
25680
|
-
|
|
25681
|
-
|
|
25698
|
+
void copySelection();
|
|
25699
|
+
},
|
|
25700
|
+
style: styles3.toolbarButton,
|
|
25701
|
+
accessibilityRole: "button",
|
|
25702
|
+
accessibilityLabel: "Copy selected text",
|
|
25703
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconCopy, { size: 20, color: "#fff", strokeWidth: 2 })
|
|
25682
25704
|
}
|
|
25683
25705
|
),
|
|
25684
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25685
|
-
|
|
25686
|
-
|
|
25687
|
-
{
|
|
25688
|
-
|
|
25689
|
-
|
|
25690
|
-
|
|
25691
|
-
|
|
25692
|
-
|
|
25693
|
-
|
|
25694
|
-
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25699
|
-
|
|
25700
|
-
|
|
25701
|
-
|
|
25702
|
-
|
|
25703
|
-
|
|
25704
|
-
|
|
25705
|
-
|
|
25706
|
-
|
|
25707
|
-
|
|
25708
|
-
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
|
|
25712
|
-
|
|
25713
|
-
|
|
25714
|
-
|
|
25715
|
-
}
|
|
25716
|
-
),
|
|
25717
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25718
|
-
import_react_native3.Pressable,
|
|
25719
|
-
{
|
|
25720
|
-
onPress: () => {
|
|
25721
|
-
applySelection("comment");
|
|
25722
|
-
},
|
|
25723
|
-
style: styles3.toolbarButton,
|
|
25724
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconCommentBubble, { size: 22, color: "#fff" })
|
|
25725
|
-
}
|
|
25726
|
-
)
|
|
25727
|
-
] }) })
|
|
25728
|
-
] })
|
|
25706
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25707
|
+
import_react_native3.Pressable,
|
|
25708
|
+
{
|
|
25709
|
+
onPress: () => {
|
|
25710
|
+
applySelection("highlight");
|
|
25711
|
+
},
|
|
25712
|
+
style: styles3.toolbarButton,
|
|
25713
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconHighlight, { size: 22, color: "#fbbf24" })
|
|
25714
|
+
}
|
|
25715
|
+
),
|
|
25716
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25717
|
+
import_react_native3.Pressable,
|
|
25718
|
+
{
|
|
25719
|
+
onPress: () => {
|
|
25720
|
+
applySelection("underline");
|
|
25721
|
+
},
|
|
25722
|
+
style: styles3.toolbarButton,
|
|
25723
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconUnderline, { size: 22, color: "#60a5fa" })
|
|
25724
|
+
}
|
|
25725
|
+
),
|
|
25726
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
25727
|
+
import_react_native3.Pressable,
|
|
25728
|
+
{
|
|
25729
|
+
onPress: () => {
|
|
25730
|
+
applySelection("comment");
|
|
25731
|
+
},
|
|
25732
|
+
style: styles3.toolbarButton,
|
|
25733
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconCommentBubble, { size: 22, color: "#fff" })
|
|
25734
|
+
}
|
|
25735
|
+
)
|
|
25736
|
+
] }) }) })
|
|
25729
25737
|
] });
|
|
25730
25738
|
}
|
|
25731
25739
|
var styles3 = import_react_native3.StyleSheet.create({
|
|
@@ -25765,10 +25773,6 @@ var styles3 = import_react_native3.StyleSheet.create({
|
|
|
25765
25773
|
alignItems: "center",
|
|
25766
25774
|
justifyContent: "center"
|
|
25767
25775
|
},
|
|
25768
|
-
overlay: {
|
|
25769
|
-
...import_react_native3.StyleSheet.absoluteFillObject,
|
|
25770
|
-
zIndex: 40
|
|
25771
|
-
},
|
|
25772
25776
|
toolbarButtonText: {
|
|
25773
25777
|
color: "#fff",
|
|
25774
25778
|
fontSize: 11,
|
|
@@ -25923,6 +25927,87 @@ function createScrollPerfSession({
|
|
|
25923
25927
|
return { begin, track, end };
|
|
25924
25928
|
}
|
|
25925
25929
|
|
|
25930
|
+
// components/pageScrubberModel.ts
|
|
25931
|
+
var shouldRenderPageScrubber = ({
|
|
25932
|
+
mobileChromeVisible,
|
|
25933
|
+
mobileProgressPillVisible,
|
|
25934
|
+
isScrubbing
|
|
25935
|
+
}) => mobileProgressPillVisible && (mobileChromeVisible || isScrubbing);
|
|
25936
|
+
var shouldEnableViewerScrollForPageScrub = ({
|
|
25937
|
+
viewerScrollEnabled,
|
|
25938
|
+
isScrubbing
|
|
25939
|
+
}) => viewerScrollEnabled && !isScrubbing;
|
|
25940
|
+
var resolvePageScrubberTouchPolicy = () => ({
|
|
25941
|
+
responderTarget: "pill",
|
|
25942
|
+
claimOnStart: true,
|
|
25943
|
+
captureOnStart: true,
|
|
25944
|
+
captureOnMove: true,
|
|
25945
|
+
childConsumesTouch: false
|
|
25946
|
+
});
|
|
25947
|
+
var resolvePageScrubberReleaseAction = ({
|
|
25948
|
+
hasMoved,
|
|
25949
|
+
pendingPage
|
|
25950
|
+
}) => hasMoved && pendingPage !== null ? { kind: "navigate", page: pendingPage } : { kind: "open" };
|
|
25951
|
+
var createPageScrubberNavigationController = (onRelease) => {
|
|
25952
|
+
let active = false;
|
|
25953
|
+
let pendingPage = null;
|
|
25954
|
+
return {
|
|
25955
|
+
begin: () => {
|
|
25956
|
+
active = true;
|
|
25957
|
+
pendingPage = null;
|
|
25958
|
+
},
|
|
25959
|
+
update: (page) => {
|
|
25960
|
+
if (active) pendingPage = page;
|
|
25961
|
+
},
|
|
25962
|
+
release: () => {
|
|
25963
|
+
active = false;
|
|
25964
|
+
const page = pendingPage;
|
|
25965
|
+
pendingPage = null;
|
|
25966
|
+
if (page !== null) onRelease(page);
|
|
25967
|
+
return page;
|
|
25968
|
+
},
|
|
25969
|
+
cancel: () => {
|
|
25970
|
+
active = false;
|
|
25971
|
+
pendingPage = null;
|
|
25972
|
+
}
|
|
25973
|
+
};
|
|
25974
|
+
};
|
|
25975
|
+
var resolvePageScrubberThumbTopFromPosition = ({
|
|
25976
|
+
position,
|
|
25977
|
+
trackHeight,
|
|
25978
|
+
thumbHeight
|
|
25979
|
+
}) => Math.max(0, Math.min(trackHeight - thumbHeight, position - thumbHeight / 2));
|
|
25980
|
+
var resolvePageScrubberThumbTop = ({
|
|
25981
|
+
currentPage,
|
|
25982
|
+
trackHeight,
|
|
25983
|
+
thumbHeight,
|
|
25984
|
+
pageCount
|
|
25985
|
+
}) => {
|
|
25986
|
+
if (pageCount <= 1) return 0;
|
|
25987
|
+
const travel = Math.max(0, trackHeight - thumbHeight);
|
|
25988
|
+
const ratio = Math.max(
|
|
25989
|
+
0,
|
|
25990
|
+
Math.min(1, (currentPage - 1) / Math.max(1, pageCount - 1))
|
|
25991
|
+
);
|
|
25992
|
+
return ratio * travel;
|
|
25993
|
+
};
|
|
25994
|
+
var resolvePageScrubberPage = ({
|
|
25995
|
+
position,
|
|
25996
|
+
trackHeight,
|
|
25997
|
+
thumbHeight,
|
|
25998
|
+
pageCount
|
|
25999
|
+
}) => {
|
|
26000
|
+
if (!Number.isFinite(pageCount) || pageCount <= 0) return null;
|
|
26001
|
+
if (pageCount === 1) return 1;
|
|
26002
|
+
const travel = Math.max(0, trackHeight - thumbHeight);
|
|
26003
|
+
const thumbTop = Math.max(0, Math.min(travel, position - thumbHeight / 2));
|
|
26004
|
+
const ratio = travel === 0 ? 0 : thumbTop / travel;
|
|
26005
|
+
return Math.max(
|
|
26006
|
+
1,
|
|
26007
|
+
Math.min(pageCount, Math.round(ratio * (pageCount - 1)) + 1)
|
|
26008
|
+
);
|
|
26009
|
+
};
|
|
26010
|
+
|
|
25926
26011
|
// components/viewerNavigation.ts
|
|
25927
26012
|
var resolveViewerScrollTarget = (pageIndex, isDouble) => ({
|
|
25928
26013
|
pageIndex,
|
|
@@ -25982,7 +26067,8 @@ var Viewer = ({
|
|
|
25982
26067
|
maxToRenderPerBatch,
|
|
25983
26068
|
removeClippedSubviews,
|
|
25984
26069
|
useDedicatedAndroidPdfViewer,
|
|
25985
|
-
viewerMode
|
|
26070
|
+
viewerMode,
|
|
26071
|
+
pageScrubActive = false
|
|
25986
26072
|
}) => {
|
|
25987
26073
|
const pageCount = (0, import_core4.useViewerStore)((state) => state.pageCount);
|
|
25988
26074
|
const currentPage = (0, import_core4.useViewerStore)((state) => state.currentPage);
|
|
@@ -26057,6 +26143,8 @@ var Viewer = ({
|
|
|
26057
26143
|
const selectionDragActiveRef = (0, import_react5.useRef)(false);
|
|
26058
26144
|
const [gestureScrollLockActive, setGestureScrollLockActive] = (0, import_react5.useState)(false);
|
|
26059
26145
|
const gestureScrollLockActiveRef = (0, import_react5.useRef)(false);
|
|
26146
|
+
const pageScrubActiveRef = (0, import_react5.useRef)(pageScrubActive);
|
|
26147
|
+
pageScrubActiveRef.current = pageScrubActive;
|
|
26060
26148
|
const pinchPreviewScale = (0, import_react5.useRef)(new import_react_native4.Animated.Value(1)).current;
|
|
26061
26149
|
const pinchPreviewFocalX = (0, import_react5.useRef)(new import_react_native4.Animated.Value(0)).current;
|
|
26062
26150
|
const pinchPreviewFocalY = (0, import_react5.useRef)(new import_react_native4.Animated.Value(0)).current;
|
|
@@ -26571,16 +26659,20 @@ var Viewer = ({
|
|
|
26571
26659
|
selectionDragActive,
|
|
26572
26660
|
gestureScrollLockActive
|
|
26573
26661
|
});
|
|
26662
|
+
const pageScrubResolvedScrollEnabled = shouldEnableViewerScrollForPageScrub({
|
|
26663
|
+
viewerScrollEnabled: resolvedViewerScrollEnabled,
|
|
26664
|
+
isScrubbing: pageScrubActive
|
|
26665
|
+
});
|
|
26574
26666
|
const setViewerScrollEnabledNative = (0, import_react5.useCallback)((enabled) => {
|
|
26575
26667
|
const scrollNode = listRef.current;
|
|
26576
26668
|
scrollNode?.setNativeProps?.({ scrollEnabled: enabled });
|
|
26577
26669
|
}, []);
|
|
26578
26670
|
const syncViewerScrollEnabled = (0, import_react5.useCallback)(
|
|
26579
|
-
(nextSelectionDragActive = selectionDragActiveRef.current, nextGestureScrollLockActive = gestureScrollLockActiveRef.current) => {
|
|
26671
|
+
(nextSelectionDragActive = selectionDragActiveRef.current, nextGestureScrollLockActive = gestureScrollLockActiveRef.current, nextPageScrubActive = pageScrubActiveRef.current) => {
|
|
26580
26672
|
setViewerScrollEnabledNative(
|
|
26581
26673
|
shouldEnableViewerScroll({
|
|
26582
26674
|
selectionDragActive: nextSelectionDragActive,
|
|
26583
|
-
gestureScrollLockActive: nextGestureScrollLockActive
|
|
26675
|
+
gestureScrollLockActive: nextGestureScrollLockActive || nextPageScrubActive
|
|
26584
26676
|
})
|
|
26585
26677
|
);
|
|
26586
26678
|
},
|
|
@@ -26853,6 +26945,13 @@ var Viewer = ({
|
|
|
26853
26945
|
gestureScrollLockActiveRef.current
|
|
26854
26946
|
);
|
|
26855
26947
|
}, [selectionDragActive, syncViewerScrollEnabled]);
|
|
26948
|
+
(0, import_react5.useEffect)(() => {
|
|
26949
|
+
syncViewerScrollEnabled(
|
|
26950
|
+
selectionDragActiveRef.current,
|
|
26951
|
+
gestureScrollLockActiveRef.current,
|
|
26952
|
+
pageScrubActive
|
|
26953
|
+
);
|
|
26954
|
+
}, [pageScrubActive, syncViewerScrollEnabled]);
|
|
26856
26955
|
(0, import_react5.useEffect)(() => {
|
|
26857
26956
|
const pendingRestore = pendingPinchAnchorRestoreRef.current;
|
|
26858
26957
|
if (!pendingRestore) return;
|
|
@@ -27422,7 +27521,7 @@ var Viewer = ({
|
|
|
27422
27521
|
{
|
|
27423
27522
|
ref: horizontalScrollRef,
|
|
27424
27523
|
horizontal: true,
|
|
27425
|
-
scrollEnabled: !gestureScrollLockActive && documentSurfaceWidth > windowWidth,
|
|
27524
|
+
scrollEnabled: !gestureScrollLockActive && !pageScrubActive && documentSurfaceWidth > windowWidth,
|
|
27426
27525
|
showsHorizontalScrollIndicator: false,
|
|
27427
27526
|
onScroll: (event) => {
|
|
27428
27527
|
horizontalScrollOffsetRef.current = event.nativeEvent.contentOffset?.x ?? 0;
|
|
@@ -27438,7 +27537,7 @@ var Viewer = ({
|
|
|
27438
27537
|
style: { width: documentSurfaceWidth },
|
|
27439
27538
|
contentContainerStyle: styles4.singleContent,
|
|
27440
27539
|
showsVerticalScrollIndicator: false,
|
|
27441
|
-
scrollEnabled:
|
|
27540
|
+
scrollEnabled: pageScrubResolvedScrollEnabled,
|
|
27442
27541
|
onLayout: () => captureViewerFrame(listRef.current),
|
|
27443
27542
|
onContentSizeChange: (_, height) => {
|
|
27444
27543
|
viewerContentHeightRef.current = height;
|
|
@@ -27511,7 +27610,7 @@ var Viewer = ({
|
|
|
27511
27610
|
{
|
|
27512
27611
|
ref: horizontalScrollRef,
|
|
27513
27612
|
horizontal: true,
|
|
27514
|
-
scrollEnabled: !gestureScrollLockActive && documentSurfaceWidth > windowWidth,
|
|
27613
|
+
scrollEnabled: !gestureScrollLockActive && !pageScrubActive && documentSurfaceWidth > windowWidth,
|
|
27515
27614
|
showsHorizontalScrollIndicator: false,
|
|
27516
27615
|
onScroll: (event) => {
|
|
27517
27616
|
horizontalScrollOffsetRef.current = event.nativeEvent.contentOffset?.x ?? 0;
|
|
@@ -27534,7 +27633,7 @@ var Viewer = ({
|
|
|
27534
27633
|
renderItem,
|
|
27535
27634
|
onViewableItemsChanged,
|
|
27536
27635
|
viewabilityConfig: { itemVisiblePercentThreshold: 60 },
|
|
27537
|
-
scrollEnabled:
|
|
27636
|
+
scrollEnabled: pageScrubResolvedScrollEnabled,
|
|
27538
27637
|
onLayout: () => {
|
|
27539
27638
|
captureViewerFrame(listRef.current);
|
|
27540
27639
|
restoreOrientationScrollOffset();
|
|
@@ -29422,6 +29521,11 @@ var resolveRightSheetHeight = ({
|
|
|
29422
29521
|
}) => showingNotes ? Math.min(440, windowHeight * 0.56) : Math.min(640, windowHeight * 0.72);
|
|
29423
29522
|
var supportsPageThumbnails = (documentType) => documentType !== "text" && documentType !== "epub";
|
|
29424
29523
|
|
|
29524
|
+
// components/thumbnailClipping.ts
|
|
29525
|
+
var shouldRemoveThumbnailClipping = ({
|
|
29526
|
+
useNativePreview
|
|
29527
|
+
}) => !useNativePreview;
|
|
29528
|
+
|
|
29425
29529
|
// components/RightSheet.tsx
|
|
29426
29530
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
29427
29531
|
var THUMBNAILS_INITIAL_NUM_TO_RENDER = 4;
|
|
@@ -29937,7 +30041,9 @@ var RightSheet = ({
|
|
|
29937
30041
|
windowSize: THUMBNAILS_WINDOW_SIZE,
|
|
29938
30042
|
maxToRenderPerBatch: THUMBNAILS_MAX_TO_RENDER_PER_BATCH,
|
|
29939
30043
|
updateCellsBatchingPeriod: THUMBNAILS_UPDATE_CELLS_BATCHING_PERIOD,
|
|
29940
|
-
removeClippedSubviews:
|
|
30044
|
+
removeClippedSubviews: shouldRemoveThumbnailClipping({
|
|
30045
|
+
useNativePreview
|
|
30046
|
+
}),
|
|
29941
30047
|
viewabilityConfig: { itemVisiblePercentThreshold: 20 },
|
|
29942
30048
|
onViewableItemsChanged: onThumbnailsViewableItemsChanged,
|
|
29943
30049
|
renderItem: renderThumbnailItem
|
|
@@ -31884,22 +31990,14 @@ var styles16 = import_react_native16.StyleSheet.create({
|
|
|
31884
31990
|
var import_react14 = require("react");
|
|
31885
31991
|
var import_react_native17 = require("react-native");
|
|
31886
31992
|
var import_core14 = require("@papyrus-sdk/core");
|
|
31887
|
-
|
|
31888
|
-
// components/progressPillInteraction.ts
|
|
31889
|
-
var getProgressPillInteraction = (onPress, onLongPress) => ({
|
|
31890
|
-
onPress,
|
|
31891
|
-
onLongPress,
|
|
31892
|
-
accessibilityLabel: "Open document navigation",
|
|
31893
|
-
accessibilityRole: "button"
|
|
31894
|
-
});
|
|
31895
|
-
|
|
31896
|
-
// components/ProgressPill.tsx
|
|
31897
31993
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
31898
31994
|
var clampPercent = (value) => Math.max(0, Math.min(100, Math.round(value)));
|
|
31899
31995
|
function ProgressPill({
|
|
31900
31996
|
documentType,
|
|
31901
31997
|
onPress,
|
|
31902
|
-
onOpenPageJump
|
|
31998
|
+
onOpenPageJump,
|
|
31999
|
+
onNavigateToPage,
|
|
32000
|
+
onScrubbingChange
|
|
31903
32001
|
}) {
|
|
31904
32002
|
const {
|
|
31905
32003
|
currentPage,
|
|
@@ -31911,18 +32009,193 @@ function ProgressPill({
|
|
|
31911
32009
|
} = (0, import_core14.useViewerStore)();
|
|
31912
32010
|
const isDark = uiTheme === "dark";
|
|
31913
32011
|
const offsets = resolveMobileChromeOffsets(usePapyrusSafeAreaInsets());
|
|
32012
|
+
const { height: windowHeight } = (0, import_react_native17.useWindowDimensions)();
|
|
32013
|
+
const trackHeight = Math.max(
|
|
32014
|
+
180,
|
|
32015
|
+
Math.min(520, windowHeight - offsets.progress - offsets.bottom - 132)
|
|
32016
|
+
);
|
|
32017
|
+
const thumbHeight = 44;
|
|
32018
|
+
const trackYRef = (0, import_react14.useRef)(0);
|
|
32019
|
+
const scrubberRef = (0, import_react14.useRef)(null);
|
|
32020
|
+
const currentPageRef = (0, import_react14.useRef)(currentPage);
|
|
32021
|
+
currentPageRef.current = currentPage;
|
|
32022
|
+
const isScrubbingRef = (0, import_react14.useRef)(false);
|
|
32023
|
+
const hasMovedRef = (0, import_react14.useRef)(false);
|
|
32024
|
+
const longPressTriggeredRef = (0, import_react14.useRef)(false);
|
|
32025
|
+
const longPressTimerRef = (0, import_react14.useRef)(null);
|
|
32026
|
+
const pendingReleasedScrubPageRef = (0, import_react14.useRef)(null);
|
|
32027
|
+
const [scrubPreviewPage, setScrubPreviewPage] = (0, import_react14.useState)(null);
|
|
32028
|
+
const onNavigateToPageRef = (0, import_react14.useRef)(onNavigateToPage);
|
|
32029
|
+
const onPressRef = (0, import_react14.useRef)(onPress);
|
|
32030
|
+
const onOpenPageJumpRef = (0, import_react14.useRef)(onOpenPageJump);
|
|
32031
|
+
const onScrubbingChangeRef = (0, import_react14.useRef)(onScrubbingChange);
|
|
32032
|
+
onScrubbingChangeRef.current = onScrubbingChange;
|
|
32033
|
+
const scrubToPositionRef = (0, import_react14.useRef)(() => {
|
|
32034
|
+
});
|
|
32035
|
+
const scrubNavigationControllerRef = (0, import_react14.useRef)(
|
|
32036
|
+
createPageScrubberNavigationController((page) => {
|
|
32037
|
+
onNavigateToPageRef.current?.(page);
|
|
32038
|
+
})
|
|
32039
|
+
);
|
|
32040
|
+
const scrubberResponderRef = (0, import_react14.useRef)(null);
|
|
32041
|
+
const touchPolicy = resolvePageScrubberTouchPolicy();
|
|
32042
|
+
const displayedPage = scrubPreviewPage ?? currentPage;
|
|
31914
32043
|
const label = (0, import_react14.useMemo)(() => {
|
|
31915
32044
|
const total = Math.max(pageCount, 1);
|
|
31916
|
-
const percent = clampPercent(
|
|
32045
|
+
const percent = clampPercent(displayedPage / total * 100);
|
|
31917
32046
|
if (documentType === "pdf") {
|
|
31918
|
-
return `${
|
|
32047
|
+
return `${displayedPage}/${pageCount || 0}`;
|
|
31919
32048
|
}
|
|
31920
32049
|
if (documentType === "epub") {
|
|
31921
|
-
return `Cap. ${
|
|
32050
|
+
return `Cap. ${displayedPage} \xB7 ${percent}%`;
|
|
31922
32051
|
}
|
|
31923
32052
|
return `${percent}%`;
|
|
31924
|
-
}, [
|
|
31925
|
-
|
|
32053
|
+
}, [displayedPage, documentType, pageCount]);
|
|
32054
|
+
const thumbTop = resolvePageScrubberThumbTop({
|
|
32055
|
+
currentPage,
|
|
32056
|
+
trackHeight,
|
|
32057
|
+
thumbHeight,
|
|
32058
|
+
pageCount
|
|
32059
|
+
});
|
|
32060
|
+
const thumbTopRef = (0, import_react14.useRef)(new import_react_native17.Animated.Value(thumbTop));
|
|
32061
|
+
const thumbTopSnapshotRef = (0, import_react14.useRef)(thumbTop);
|
|
32062
|
+
thumbTopSnapshotRef.current = thumbTop;
|
|
32063
|
+
const scrubberMetricsRef = (0, import_react14.useRef)({ trackHeight, thumbHeight, pageCount });
|
|
32064
|
+
scrubberMetricsRef.current = { trackHeight, thumbHeight, pageCount };
|
|
32065
|
+
(0, import_react14.useEffect)(() => {
|
|
32066
|
+
onNavigateToPageRef.current = onNavigateToPage;
|
|
32067
|
+
}, [onNavigateToPage]);
|
|
32068
|
+
(0, import_react14.useEffect)(() => {
|
|
32069
|
+
onPressRef.current = onPress;
|
|
32070
|
+
onOpenPageJumpRef.current = onOpenPageJump;
|
|
32071
|
+
}, [onOpenPageJump, onPress]);
|
|
32072
|
+
(0, import_react14.useEffect)(() => {
|
|
32073
|
+
const pendingPage = pendingReleasedScrubPageRef.current;
|
|
32074
|
+
if (pendingPage !== null && currentPage === pendingPage) {
|
|
32075
|
+
pendingReleasedScrubPageRef.current = null;
|
|
32076
|
+
setScrubPreviewPage(null);
|
|
32077
|
+
}
|
|
32078
|
+
}, [currentPage]);
|
|
32079
|
+
(0, import_react14.useEffect)(() => {
|
|
32080
|
+
if (!isScrubbingRef.current) {
|
|
32081
|
+
thumbTopRef.current.setValue(thumbTop);
|
|
32082
|
+
}
|
|
32083
|
+
}, [thumbTop, thumbTopRef]);
|
|
32084
|
+
(0, import_react14.useEffect)(
|
|
32085
|
+
() => () => {
|
|
32086
|
+
if (longPressTimerRef.current !== null) {
|
|
32087
|
+
clearTimeout(longPressTimerRef.current);
|
|
32088
|
+
}
|
|
32089
|
+
},
|
|
32090
|
+
[]
|
|
32091
|
+
);
|
|
32092
|
+
if (!shouldRenderPageScrubber({
|
|
32093
|
+
mobileChromeVisible,
|
|
32094
|
+
mobileProgressPillVisible,
|
|
32095
|
+
isScrubbing: isScrubbingRef.current
|
|
32096
|
+
})) {
|
|
32097
|
+
return null;
|
|
32098
|
+
}
|
|
32099
|
+
const scrubToPosition = (position) => {
|
|
32100
|
+
const { trackHeight: trackHeight2, thumbHeight: thumbHeight2, pageCount: pageCount2 } = scrubberMetricsRef.current;
|
|
32101
|
+
const visualPosition = resolvePageScrubberThumbTopFromPosition({
|
|
32102
|
+
position,
|
|
32103
|
+
trackHeight: trackHeight2,
|
|
32104
|
+
thumbHeight: thumbHeight2
|
|
32105
|
+
});
|
|
32106
|
+
thumbTopRef.current.setValue(visualPosition);
|
|
32107
|
+
const nextPage = resolvePageScrubberPage({
|
|
32108
|
+
position,
|
|
32109
|
+
trackHeight: trackHeight2,
|
|
32110
|
+
thumbHeight: thumbHeight2,
|
|
32111
|
+
pageCount: pageCount2
|
|
32112
|
+
});
|
|
32113
|
+
if (nextPage === null) return;
|
|
32114
|
+
scrubNavigationControllerRef.current.update(nextPage);
|
|
32115
|
+
setScrubPreviewPage(nextPage);
|
|
32116
|
+
};
|
|
32117
|
+
scrubToPositionRef.current = scrubToPosition;
|
|
32118
|
+
if (scrubberResponderRef.current === null) {
|
|
32119
|
+
scrubberResponderRef.current = import_react_native17.PanResponder.create({
|
|
32120
|
+
onStartShouldSetPanResponder: () => touchPolicy.claimOnStart,
|
|
32121
|
+
onStartShouldSetPanResponderCapture: () => touchPolicy.captureOnStart,
|
|
32122
|
+
onMoveShouldSetPanResponder: () => true,
|
|
32123
|
+
onMoveShouldSetPanResponderCapture: () => touchPolicy.captureOnMove,
|
|
32124
|
+
onPanResponderTerminationRequest: () => false,
|
|
32125
|
+
onPanResponderGrant: () => {
|
|
32126
|
+
isScrubbingRef.current = true;
|
|
32127
|
+
onScrubbingChangeRef.current?.(true);
|
|
32128
|
+
hasMovedRef.current = false;
|
|
32129
|
+
longPressTriggeredRef.current = false;
|
|
32130
|
+
scrubNavigationControllerRef.current.begin();
|
|
32131
|
+
pendingReleasedScrubPageRef.current = null;
|
|
32132
|
+
setScrubPreviewPage(currentPageRef.current);
|
|
32133
|
+
if (longPressTimerRef.current !== null) {
|
|
32134
|
+
clearTimeout(longPressTimerRef.current);
|
|
32135
|
+
}
|
|
32136
|
+
longPressTimerRef.current = onOpenPageJumpRef.current ? setTimeout(() => {
|
|
32137
|
+
longPressTimerRef.current = null;
|
|
32138
|
+
if (!hasMovedRef.current) {
|
|
32139
|
+
longPressTriggeredRef.current = true;
|
|
32140
|
+
onOpenPageJumpRef.current?.();
|
|
32141
|
+
}
|
|
32142
|
+
}, 500) : null;
|
|
32143
|
+
},
|
|
32144
|
+
onPanResponderMove: (_, gestureState) => {
|
|
32145
|
+
if (Math.abs(gestureState.dy) <= 4) return;
|
|
32146
|
+
hasMovedRef.current = true;
|
|
32147
|
+
if (longPressTimerRef.current !== null) {
|
|
32148
|
+
clearTimeout(longPressTimerRef.current);
|
|
32149
|
+
longPressTimerRef.current = null;
|
|
32150
|
+
}
|
|
32151
|
+
scrubToPositionRef.current(gestureState.moveY - trackYRef.current);
|
|
32152
|
+
},
|
|
32153
|
+
onPanResponderRelease: () => {
|
|
32154
|
+
if (longPressTimerRef.current !== null) {
|
|
32155
|
+
clearTimeout(longPressTimerRef.current);
|
|
32156
|
+
longPressTimerRef.current = null;
|
|
32157
|
+
}
|
|
32158
|
+
isScrubbingRef.current = false;
|
|
32159
|
+
onScrubbingChangeRef.current?.(false);
|
|
32160
|
+
const releasedPage = scrubNavigationControllerRef.current.release();
|
|
32161
|
+
const releaseAction = resolvePageScrubberReleaseAction({
|
|
32162
|
+
hasMoved: hasMovedRef.current,
|
|
32163
|
+
pendingPage: releasedPage
|
|
32164
|
+
});
|
|
32165
|
+
if (releaseAction.kind === "navigate") {
|
|
32166
|
+
pendingReleasedScrubPageRef.current = releaseAction.page;
|
|
32167
|
+
if (!onNavigateToPageRef.current) {
|
|
32168
|
+
setScrubPreviewPage(null);
|
|
32169
|
+
}
|
|
32170
|
+
} else {
|
|
32171
|
+
scrubNavigationControllerRef.current.cancel();
|
|
32172
|
+
pendingReleasedScrubPageRef.current = null;
|
|
32173
|
+
setScrubPreviewPage(null);
|
|
32174
|
+
if (!longPressTriggeredRef.current) onPressRef.current();
|
|
32175
|
+
}
|
|
32176
|
+
hasMovedRef.current = false;
|
|
32177
|
+
longPressTriggeredRef.current = false;
|
|
32178
|
+
},
|
|
32179
|
+
onPanResponderTerminate: () => {
|
|
32180
|
+
if (longPressTimerRef.current !== null) {
|
|
32181
|
+
clearTimeout(longPressTimerRef.current);
|
|
32182
|
+
longPressTimerRef.current = null;
|
|
32183
|
+
}
|
|
32184
|
+
isScrubbingRef.current = false;
|
|
32185
|
+
onScrubbingChangeRef.current?.(false);
|
|
32186
|
+
scrubNavigationControllerRef.current.cancel();
|
|
32187
|
+
pendingReleasedScrubPageRef.current = null;
|
|
32188
|
+
setScrubPreviewPage(null);
|
|
32189
|
+
hasMovedRef.current = false;
|
|
32190
|
+
longPressTriggeredRef.current = false;
|
|
32191
|
+
thumbTopRef.current.setValue(thumbTopSnapshotRef.current);
|
|
32192
|
+
}
|
|
32193
|
+
});
|
|
32194
|
+
}
|
|
32195
|
+
const responderPanHandlers = scrubberResponderRef.current?.panHandlers ?? {};
|
|
32196
|
+
const responderTarget = touchPolicy.responderTarget;
|
|
32197
|
+
const scrubberPanHandlers = responderTarget === "track" ? responderPanHandlers : {};
|
|
32198
|
+
const pillPanHandlers = responderTarget === "pill" ? responderPanHandlers : {};
|
|
31926
32199
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
31927
32200
|
import_react_native17.View,
|
|
31928
32201
|
{
|
|
@@ -31931,32 +32204,45 @@ function ProgressPill({
|
|
|
31931
32204
|
styles17.frame,
|
|
31932
32205
|
{
|
|
31933
32206
|
top: offsets.progress,
|
|
31934
|
-
|
|
31935
|
-
right: 0,
|
|
31936
|
-
paddingLeft: offsets.left + MOBILE_CHROME_METRICS.progressHorizontalOffset,
|
|
31937
|
-
paddingRight: offsets.right
|
|
32207
|
+
right: offsets.right
|
|
31938
32208
|
}
|
|
31939
32209
|
],
|
|
31940
32210
|
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
31941
|
-
import_react_native17.
|
|
32211
|
+
import_react_native17.View,
|
|
31942
32212
|
{
|
|
31943
|
-
|
|
31944
|
-
style: [
|
|
31945
|
-
|
|
31946
|
-
|
|
31947
|
-
|
|
31948
|
-
|
|
31949
|
-
|
|
32213
|
+
ref: scrubberRef,
|
|
32214
|
+
style: [styles17.scrubber, { height: trackHeight }],
|
|
32215
|
+
...scrubberPanHandlers,
|
|
32216
|
+
onLayout: () => {
|
|
32217
|
+
scrubberRef.current?.measureInWindow((_x, y) => {
|
|
32218
|
+
trackYRef.current = y;
|
|
32219
|
+
});
|
|
32220
|
+
},
|
|
31950
32221
|
children: [
|
|
31951
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.View, { style: styles17.
|
|
31952
|
-
|
|
32222
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.View, { style: [styles17.track, isDark && styles17.trackDark] }),
|
|
32223
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.Animated.View, { style: [styles17.thumb, { top: thumbTopRef.current }], children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
32224
|
+
import_react_native17.View,
|
|
31953
32225
|
{
|
|
31954
|
-
|
|
31955
|
-
|
|
31956
|
-
|
|
32226
|
+
style: [
|
|
32227
|
+
styles17.pill,
|
|
32228
|
+
isDark && styles17.pillDark,
|
|
32229
|
+
{ borderColor: `${accentColor}33` }
|
|
32230
|
+
],
|
|
32231
|
+
...pillPanHandlers,
|
|
32232
|
+
testID: "papyrus-progress-pill",
|
|
32233
|
+
children: [
|
|
32234
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.View, { style: styles17.labelHit, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.Text, { style: [styles17.label, isDark && styles17.labelDark], children: label }) }),
|
|
32235
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.View, { style: styles17.iconHit, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
32236
|
+
IconPageNav,
|
|
32237
|
+
{
|
|
32238
|
+
size: 20,
|
|
32239
|
+
color: isDark ? "#f8fafc" : "#111827",
|
|
32240
|
+
strokeWidth: 1.8
|
|
32241
|
+
}
|
|
32242
|
+
) })
|
|
32243
|
+
]
|
|
31957
32244
|
}
|
|
31958
|
-
) })
|
|
31959
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.View, { style: styles17.labelHit, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_native17.Text, { style: [styles17.label, isDark && styles17.labelDark], children: label }) })
|
|
32245
|
+
) })
|
|
31960
32246
|
]
|
|
31961
32247
|
}
|
|
31962
32248
|
)
|
|
@@ -31970,9 +32256,31 @@ var styles17 = import_react_native17.StyleSheet.create({
|
|
|
31970
32256
|
left: 0,
|
|
31971
32257
|
right: 0,
|
|
31972
32258
|
bottom: "auto",
|
|
31973
|
-
alignItems: "flex-
|
|
32259
|
+
alignItems: "flex-end",
|
|
31974
32260
|
zIndex: 18
|
|
31975
32261
|
},
|
|
32262
|
+
scrubber: {
|
|
32263
|
+
width: 132,
|
|
32264
|
+
position: "relative",
|
|
32265
|
+
marginRight: 4
|
|
32266
|
+
},
|
|
32267
|
+
track: {
|
|
32268
|
+
position: "absolute",
|
|
32269
|
+
top: 0,
|
|
32270
|
+
right: 30,
|
|
32271
|
+
bottom: 0,
|
|
32272
|
+
width: 3,
|
|
32273
|
+
borderRadius: 2,
|
|
32274
|
+
backgroundColor: "rgba(15,23,42,0.16)"
|
|
32275
|
+
},
|
|
32276
|
+
trackDark: {
|
|
32277
|
+
backgroundColor: "rgba(248,250,252,0.22)"
|
|
32278
|
+
},
|
|
32279
|
+
thumb: {
|
|
32280
|
+
position: "absolute",
|
|
32281
|
+
right: 0,
|
|
32282
|
+
height: 44
|
|
32283
|
+
},
|
|
31976
32284
|
pill: {
|
|
31977
32285
|
minWidth: 92,
|
|
31978
32286
|
borderRadius: 999,
|
|
@@ -32447,6 +32755,7 @@ function ReadingShell({
|
|
|
32447
32755
|
const [settingsOpen, setSettingsOpen] = (0, import_react16.useState)(false);
|
|
32448
32756
|
const [searchResultsOpen, setSearchResultsOpen] = (0, import_react16.useState)(false);
|
|
32449
32757
|
const [pageJumpOpen, setPageJumpOpen] = (0, import_react16.useState)(false);
|
|
32758
|
+
const [pageScrubActive, setPageScrubActive] = (0, import_react16.useState)(false);
|
|
32450
32759
|
const isDark = uiTheme === "dark";
|
|
32451
32760
|
import_react16.default.useEffect(() => {
|
|
32452
32761
|
const showSubscription = import_react_native20.Keyboard.addListener("keyboardDidShow", () => {
|
|
@@ -32523,15 +32832,24 @@ function ReadingShell({
|
|
|
32523
32832
|
showPageNavigationControls: false
|
|
32524
32833
|
}
|
|
32525
32834
|
),
|
|
32526
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native20.View, { style: styles20.viewerStage, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
32835
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react_native20.View, { style: styles20.viewerStage, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
32836
|
+
Viewer_default,
|
|
32837
|
+
{
|
|
32838
|
+
engine,
|
|
32839
|
+
...viewerProps,
|
|
32840
|
+
pageScrubActive
|
|
32841
|
+
}
|
|
32842
|
+
) }),
|
|
32527
32843
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
32528
32844
|
ProgressPill,
|
|
32529
32845
|
{
|
|
32530
32846
|
documentType,
|
|
32847
|
+
onNavigateToPage: navigateToPage,
|
|
32531
32848
|
onPress: () => openDestination(
|
|
32532
32849
|
documentType === "pdf" ? "pages" : documentType === "epub" ? "contents" : "progress"
|
|
32533
32850
|
),
|
|
32534
|
-
onOpenPageJump: () => setPageJumpOpen(true)
|
|
32851
|
+
onOpenPageJump: () => setPageJumpOpen(true),
|
|
32852
|
+
onScrubbingChange: setPageScrubActive
|
|
32535
32853
|
}
|
|
32536
32854
|
),
|
|
32537
32855
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|