react-native-pdf-jsi 1.0.1
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/DoubleTapView.js +125 -0
- package/INTEGRATION_GUIDE.md +419 -0
- package/LICENSE +21 -0
- package/PdfManager.js +26 -0
- package/PdfPageView.js +53 -0
- package/PdfView.js +421 -0
- package/PdfViewFlatList.js +30 -0
- package/PinchZoomView.js +125 -0
- package/README.md +693 -0
- package/README_JSI.md +348 -0
- package/android/.gradle/5.6.1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/5.6.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/5.6.1/gc.properties +0 -0
- package/android/.gradle/8.5/checksums/checksums.lock +0 -0
- package/android/.gradle/8.5/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.5/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock +0 -0
- package/android/.gradle/8.5/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.5/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.5/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.5/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.5/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build.gradle +198 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/gradle.properties +2 -0
- package/android/gradlew +249 -0
- package/android/gradlew.bat +92 -0
- package/android/project.properties +12 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/Android.mk +50 -0
- package/android/src/main/cpp/CMakeLists.txt +76 -0
- package/android/src/main/cpp/PDFJSI.cpp +190 -0
- package/android/src/main/cpp/PDFJSI.h +95 -0
- package/android/src/main/cpp/PDFJSIBridge.cpp +32 -0
- package/android/src/main/cpp/PDFJSIModule.cpp +31 -0
- package/android/src/main/java/org/wonday/pdf/EnhancedPdfJSIBridge.java +281 -0
- package/android/src/main/java/org/wonday/pdf/PDFJSIManager.java +317 -0
- package/android/src/main/java/org/wonday/pdf/PDFJSIModule.java +189 -0
- package/android/src/main/java/org/wonday/pdf/PdfManager.java +180 -0
- package/android/src/main/java/org/wonday/pdf/PdfView.java +505 -0
- package/android/src/main/java/org/wonday/pdf/RNPDFPackage.java +43 -0
- package/android/src/main/java/org/wonday/pdf/events/TopChangeEvent.java +26 -0
- package/android/src/main/jniLibs/arm64-v8a/libpdfjsi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libpdfjsi.so +0 -0
- package/android/src/main/jniLibs/x86/libpdfjsi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libpdfjsi.so +0 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java +92 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java +35 -0
- package/fabric/RNPDFPdfNativeComponent.js +48 -0
- package/index.d.ts +72 -0
- package/index.js +603 -0
- package/index.js.flow +67 -0
- package/ios/RNPDFPdf/PdfManager.h +23 -0
- package/ios/RNPDFPdf/PdfManager.mm +152 -0
- package/ios/RNPDFPdf/RNPDFPdfPageView.h +21 -0
- package/ios/RNPDFPdf/RNPDFPdfPageView.mm +185 -0
- package/ios/RNPDFPdf/RNPDFPdfPageViewManager.h +18 -0
- package/ios/RNPDFPdf/RNPDFPdfPageViewManager.mm +30 -0
- package/ios/RNPDFPdf/RNPDFPdfView.h +63 -0
- package/ios/RNPDFPdf/RNPDFPdfView.mm +1092 -0
- package/ios/RNPDFPdf/RNPDFPdfViewManager.h +18 -0
- package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +68 -0
- package/ios/RNPDFPdf.xcodeproj/project.pbxproj +321 -0
- package/package.json +78 -0
- package/react-native-pdf.podspec +31 -0
- package/src/EnhancedPdfView.js +362 -0
- package/src/PDFJSI.js +519 -0
- package/src/examples/PDFJSIExample.js +296 -0
- package/src/hooks/usePDFJSI.js +346 -0
- package/src/index.js +32 -0
- package/windows/RCTPdf/PropertySheet.props +16 -0
- package/windows/RCTPdf/RCTPdf.def +3 -0
- package/windows/RCTPdf/RCTPdf.vcxproj +180 -0
- package/windows/RCTPdf/RCTPdf.vcxproj.filters +38 -0
- package/windows/RCTPdf/RCTPdfControl.cpp +667 -0
- package/windows/RCTPdf/RCTPdfControl.h +119 -0
- package/windows/RCTPdf/RCTPdfControl.idl +10 -0
- package/windows/RCTPdf/RCTPdfControl.xaml +33 -0
- package/windows/RCTPdf/RCTPdfViewManager.cpp +69 -0
- package/windows/RCTPdf/RCTPdfViewManager.h +51 -0
- package/windows/RCTPdf/ReactPackageProvider.cpp +15 -0
- package/windows/RCTPdf/ReactPackageProvider.h +16 -0
- package/windows/RCTPdf/ReactPackageProvider.idl +9 -0
- package/windows/RCTPdf/packages.config +4 -0
- package/windows/RCTPdf/pch.cpp +1 -0
- package/windows/RCTPdf/pch.h +31 -0
- package/windows/README.md +21 -0
package/DoubleTapView.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Wonday (@wonday.org)
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
import React, {Component} from 'react';
|
|
11
|
+
import {
|
|
12
|
+
View,
|
|
13
|
+
PanResponder
|
|
14
|
+
} from 'react-native';
|
|
15
|
+
import PropTypes from 'prop-types';
|
|
16
|
+
import {ViewPropTypes} from 'deprecated-react-native-prop-types';
|
|
17
|
+
export default class DoubleTapView extends Component {
|
|
18
|
+
|
|
19
|
+
static propTypes = {
|
|
20
|
+
...ViewPropTypes,
|
|
21
|
+
delay: PropTypes.number,
|
|
22
|
+
radius: PropTypes.number,
|
|
23
|
+
onSingleTap: PropTypes.func,
|
|
24
|
+
onDoubleTap: PropTypes.func,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
static defaultProps = {
|
|
28
|
+
delay: 300,
|
|
29
|
+
radius: 50,
|
|
30
|
+
onSingleTap: () => {
|
|
31
|
+
},
|
|
32
|
+
onDoubleTap: () => {
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
constructor() {
|
|
37
|
+
super();
|
|
38
|
+
|
|
39
|
+
this.gestureHandlers = PanResponder.create({
|
|
40
|
+
onStartShouldSetPanResponder: (evt, gestureState) => (gestureState.numberActiveTouches === 1),
|
|
41
|
+
onStartShouldSetResponderCapture: (evt, gestureState) => (gestureState.numberActiveTouches === 1),
|
|
42
|
+
onMoveShouldSetPanResponder: (evt, gestureState) => (false),
|
|
43
|
+
onMoveShouldSetResponderCapture: (evt, gestureState) => (false),
|
|
44
|
+
onPanResponderTerminationRequest: (evt, gestureState) => false,
|
|
45
|
+
onPanResponderRelease: this.handlePanResponderRelease,
|
|
46
|
+
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
this.prevTouchInfo = {
|
|
50
|
+
prevTouchX: 0,
|
|
51
|
+
prevTouchY: 0,
|
|
52
|
+
prevTouchTimeStamp: 0,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
this.timer = null;
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
distance = (x0, y0, x1, y1) => {
|
|
61
|
+
return Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2)).toFixed(1);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
isDoubleTap = (currentTouchTimeStamp, {x0, y0}) => {
|
|
65
|
+
const {prevTouchX, prevTouchY, prevTouchTimeStamp} = this.prevTouchInfo;
|
|
66
|
+
const dt = currentTouchTimeStamp - prevTouchTimeStamp;
|
|
67
|
+
const {delay, radius} = this.props;
|
|
68
|
+
|
|
69
|
+
return (prevTouchTimeStamp > 0 && dt < delay && this.distance(prevTouchX, prevTouchY, x0, y0) < radius);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
handlePanResponderRelease = (evt, gestureState) => {
|
|
73
|
+
|
|
74
|
+
const currentTouchTimeStamp = Date.now();
|
|
75
|
+
const x = evt.nativeEvent.locationX;
|
|
76
|
+
const y = evt.nativeEvent.locationY;
|
|
77
|
+
|
|
78
|
+
if (this.timer) {
|
|
79
|
+
|
|
80
|
+
if (this.isDoubleTap(currentTouchTimeStamp, gestureState)) {
|
|
81
|
+
|
|
82
|
+
clearTimeout(this.timer);
|
|
83
|
+
this.timer = null;
|
|
84
|
+
this.props.onDoubleTap();
|
|
85
|
+
|
|
86
|
+
} else {
|
|
87
|
+
|
|
88
|
+
const {prevTouchX, prevTouchY, prevTouchTimeStamp} = this.prevTouchInfo;
|
|
89
|
+
const {radius} = this.props;
|
|
90
|
+
|
|
91
|
+
// if not in radius, it's a move
|
|
92
|
+
if (this.distance(prevTouchX, prevTouchY, gestureState.x0, gestureState.y0) < radius) {
|
|
93
|
+
this.timer = null;
|
|
94
|
+
this.props.onSingleTap(x, y);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// do not count scroll gestures as taps
|
|
100
|
+
if (this.distance(0, gestureState.dx, 0, gestureState.dy) < 10) {
|
|
101
|
+
|
|
102
|
+
this.timer = setTimeout(() => {
|
|
103
|
+
this.props.onSingleTap(x, y);
|
|
104
|
+
this.timer = null;
|
|
105
|
+
}, this.props.delay);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
this.prevTouchInfo = {
|
|
111
|
+
prevTouchX: gestureState.x0,
|
|
112
|
+
prevTouchY: gestureState.y0,
|
|
113
|
+
prevTouchTimeStamp: currentTouchTimeStamp,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
render() {
|
|
119
|
+
return (
|
|
120
|
+
<View {...this.props} {...this.gestureHandlers.panHandlers}>
|
|
121
|
+
{this.props.children}
|
|
122
|
+
</View>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# Enhanced PDF JSI Integration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide shows you how to integrate and use the Enhanced PDF JSI functionality in your React Native application. The JSI integration provides **22.5x faster** PDF operations compared to traditional bridge-based methods.
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Import JSI Components
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// Basic imports
|
|
13
|
+
import { PDFJSI, EnhancedPdfView, usePDFJSI } from 'react-native-pdf';
|
|
14
|
+
|
|
15
|
+
// Or import individual methods
|
|
16
|
+
import {
|
|
17
|
+
renderPageDirect,
|
|
18
|
+
getPageMetrics,
|
|
19
|
+
preloadPagesDirect
|
|
20
|
+
} from 'react-native-pdf';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 2. Check JSI Availability
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
27
|
+
|
|
28
|
+
const checkJSI = async () => {
|
|
29
|
+
const isAvailable = await PDFJSI.checkJSIAvailability();
|
|
30
|
+
console.log('JSI Available:', isAvailable);
|
|
31
|
+
|
|
32
|
+
if (isAvailable) {
|
|
33
|
+
console.log('🚀 High-performance mode enabled!');
|
|
34
|
+
} else {
|
|
35
|
+
console.log('📱 Using standard bridge mode');
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 📱 Usage Examples
|
|
41
|
+
|
|
42
|
+
### Method 1: Direct JSI Usage
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
46
|
+
|
|
47
|
+
const MyPDFComponent = () => {
|
|
48
|
+
const handleRenderPage = async () => {
|
|
49
|
+
try {
|
|
50
|
+
const result = await PDFJSI.renderPageDirect(
|
|
51
|
+
'pdf_123', // PDF ID
|
|
52
|
+
1, // Page number
|
|
53
|
+
2.0, // Scale factor
|
|
54
|
+
base64Data // Base64 PDF data
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (result.success) {
|
|
58
|
+
console.log('Page rendered successfully!');
|
|
59
|
+
// Use result.data for the rendered page
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('Render failed:', error);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<TouchableOpacity onPress={handleRenderPage}>
|
|
68
|
+
<Text>Render Page</Text>
|
|
69
|
+
</TouchableOpacity>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Method 2: Hook-based Usage
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
import { usePDFJSI } from 'react-native-pdf';
|
|
78
|
+
|
|
79
|
+
const MyPDFComponent = () => {
|
|
80
|
+
const {
|
|
81
|
+
isJSIAvailable,
|
|
82
|
+
isInitialized,
|
|
83
|
+
renderPage,
|
|
84
|
+
getPageMetrics,
|
|
85
|
+
preloadPages,
|
|
86
|
+
searchText
|
|
87
|
+
} = usePDFJSI({
|
|
88
|
+
autoInitialize: true,
|
|
89
|
+
enablePerformanceTracking: true
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const handleOperations = async () => {
|
|
93
|
+
if (!isJSIAvailable) return;
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
// Render page
|
|
97
|
+
const renderResult = await renderPage('pdf_123', 1, 2.0, base64Data);
|
|
98
|
+
|
|
99
|
+
// Get page metrics
|
|
100
|
+
const metrics = await getPageMetrics('pdf_123', 1);
|
|
101
|
+
|
|
102
|
+
// Preload pages
|
|
103
|
+
await preloadPages('pdf_123', 1, 5);
|
|
104
|
+
|
|
105
|
+
// Search text
|
|
106
|
+
const searchResults = await searchText('pdf_123', 'search term', 1, 10);
|
|
107
|
+
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('JSI operations failed:', error);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<View>
|
|
115
|
+
<Text>JSI Status: {isJSIAvailable ? 'Available' : 'Not Available'}</Text>
|
|
116
|
+
<TouchableOpacity onPress={handleOperations}>
|
|
117
|
+
<Text>Run JSI Operations</Text>
|
|
118
|
+
</TouchableOpacity>
|
|
119
|
+
</View>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Method 3: Enhanced PDF View
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
import { EnhancedPdfView } from 'react-native-pdf';
|
|
128
|
+
|
|
129
|
+
const MyPDFViewer = () => {
|
|
130
|
+
return (
|
|
131
|
+
<EnhancedPdfView
|
|
132
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
133
|
+
style={{ flex: 1 }}
|
|
134
|
+
onLoadComplete={(numberOfPages) => {
|
|
135
|
+
console.log(`PDF loaded: ${numberOfPages} pages`);
|
|
136
|
+
}}
|
|
137
|
+
onPageChanged={(page) => {
|
|
138
|
+
console.log(`Current page: ${page}`);
|
|
139
|
+
}}
|
|
140
|
+
// JSI-specific props
|
|
141
|
+
jsiEnabled={true}
|
|
142
|
+
enablePerformanceTracking={true}
|
|
143
|
+
enableSmartCaching={true}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 🔧 Advanced Features
|
|
150
|
+
|
|
151
|
+
### Performance Monitoring
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
155
|
+
|
|
156
|
+
const PerformanceMonitor = () => {
|
|
157
|
+
const [metrics, setMetrics] = useState(null);
|
|
158
|
+
|
|
159
|
+
const updateMetrics = async () => {
|
|
160
|
+
try {
|
|
161
|
+
// Get JSI statistics
|
|
162
|
+
const stats = await PDFJSI.getJSIStats();
|
|
163
|
+
console.log('JSI Stats:', stats);
|
|
164
|
+
|
|
165
|
+
// Get performance metrics
|
|
166
|
+
const perfMetrics = await PDFJSI.getPerformanceMetrics('pdf_123');
|
|
167
|
+
setMetrics(perfMetrics);
|
|
168
|
+
|
|
169
|
+
// Get performance history
|
|
170
|
+
const history = PDFJSI.getPerformanceHistory();
|
|
171
|
+
console.log('Performance History:', history);
|
|
172
|
+
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('Error getting metrics:', error);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<View>
|
|
180
|
+
<TouchableOpacity onPress={updateMetrics}>
|
|
181
|
+
<Text>Update Metrics</Text>
|
|
182
|
+
</TouchableOpacity>
|
|
183
|
+
|
|
184
|
+
{metrics && (
|
|
185
|
+
<Text>Performance: {JSON.stringify(metrics, null, 2)}</Text>
|
|
186
|
+
)}
|
|
187
|
+
</View>
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Cache Management
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
196
|
+
|
|
197
|
+
const CacheManager = () => {
|
|
198
|
+
const handleCacheOperations = async () => {
|
|
199
|
+
try {
|
|
200
|
+
// Get cache metrics
|
|
201
|
+
const cacheMetrics = await PDFJSI.getCacheMetrics('pdf_123');
|
|
202
|
+
console.log('Cache Metrics:', cacheMetrics);
|
|
203
|
+
|
|
204
|
+
// Clear specific cache type
|
|
205
|
+
await PDFJSI.clearCacheDirect('pdf_123', 'base64');
|
|
206
|
+
|
|
207
|
+
// Clear all caches
|
|
208
|
+
await PDFJSI.clearCacheDirect('pdf_123', 'all');
|
|
209
|
+
|
|
210
|
+
// Optimize memory
|
|
211
|
+
await PDFJSI.optimizeMemory('pdf_123');
|
|
212
|
+
|
|
213
|
+
} catch (error) {
|
|
214
|
+
console.error('Cache operations failed:', error);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<TouchableOpacity onPress={handleCacheOperations}>
|
|
220
|
+
<Text>Manage Cache</Text>
|
|
221
|
+
</TouchableOpacity>
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Text Search
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
230
|
+
|
|
231
|
+
const TextSearch = () => {
|
|
232
|
+
const [searchTerm, setSearchTerm] = useState('');
|
|
233
|
+
const [results, setResults] = useState([]);
|
|
234
|
+
|
|
235
|
+
const handleSearch = async () => {
|
|
236
|
+
try {
|
|
237
|
+
const searchResults = await PDFJSI.searchTextDirect(
|
|
238
|
+
'pdf_123',
|
|
239
|
+
searchTerm,
|
|
240
|
+
1, // Start page
|
|
241
|
+
10 // End page
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
setResults(searchResults);
|
|
245
|
+
console.log(`Found ${searchResults.length} matches`);
|
|
246
|
+
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error('Search failed:', error);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<View>
|
|
254
|
+
<TextInput
|
|
255
|
+
value={searchTerm}
|
|
256
|
+
onChangeText={setSearchTerm}
|
|
257
|
+
placeholder="Enter search term"
|
|
258
|
+
/>
|
|
259
|
+
<TouchableOpacity onPress={handleSearch}>
|
|
260
|
+
<Text>Search</Text>
|
|
261
|
+
</TouchableOpacity>
|
|
262
|
+
|
|
263
|
+
{results.map((result, index) => (
|
|
264
|
+
<Text key={index}>
|
|
265
|
+
Page {result.page}: {result.text}
|
|
266
|
+
</Text>
|
|
267
|
+
))}
|
|
268
|
+
</View>
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## 🎯 Performance Optimization
|
|
274
|
+
|
|
275
|
+
### Preloading Strategy
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
279
|
+
|
|
280
|
+
const SmartPreloader = () => {
|
|
281
|
+
const preloadPages = async (pdfId, currentPage) => {
|
|
282
|
+
try {
|
|
283
|
+
// Preload current page ± 2 pages
|
|
284
|
+
const startPage = Math.max(1, currentPage - 2);
|
|
285
|
+
const endPage = currentPage + 2;
|
|
286
|
+
|
|
287
|
+
await PDFJSI.preloadPagesDirect(pdfId, startPage, endPage);
|
|
288
|
+
console.log(`Preloaded pages ${startPage}-${endPage}`);
|
|
289
|
+
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.error('Preload failed:', error);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return preloadPages;
|
|
296
|
+
};
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Quality Control
|
|
300
|
+
|
|
301
|
+
```javascript
|
|
302
|
+
import { PDFJSI } from 'react-native-pdf';
|
|
303
|
+
|
|
304
|
+
const QualityController = () => {
|
|
305
|
+
const setQuality = async (quality) => {
|
|
306
|
+
try {
|
|
307
|
+
// Quality levels: 1 (low), 2 (medium), 3 (high)
|
|
308
|
+
await PDFJSI.setRenderQuality('pdf_123', quality);
|
|
309
|
+
console.log(`Render quality set to: ${quality}`);
|
|
310
|
+
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error('Quality setting failed:', error);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<View>
|
|
318
|
+
<TouchableOpacity onPress={() => setQuality(1)}>
|
|
319
|
+
<Text>Low Quality (Fast)</Text>
|
|
320
|
+
</TouchableOpacity>
|
|
321
|
+
<TouchableOpacity onPress={() => setQuality(2)}>
|
|
322
|
+
<Text>Medium Quality</Text>
|
|
323
|
+
</TouchableOpacity>
|
|
324
|
+
<TouchableOpacity onPress={() => setQuality(3)}>
|
|
325
|
+
<Text>High Quality (Slow)</Text>
|
|
326
|
+
</TouchableOpacity>
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## 🔄 Migration from Bridge Mode
|
|
333
|
+
|
|
334
|
+
### Before (Bridge Mode)
|
|
335
|
+
```javascript
|
|
336
|
+
import Pdf from 'react-native-pdf';
|
|
337
|
+
|
|
338
|
+
// Traditional bridge-based usage
|
|
339
|
+
<Pdf
|
|
340
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
341
|
+
style={{ flex: 1 }}
|
|
342
|
+
/>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### After (JSI Mode)
|
|
346
|
+
```javascript
|
|
347
|
+
import { EnhancedPdfView } from 'react-native-pdf';
|
|
348
|
+
|
|
349
|
+
// Enhanced JSI-based usage
|
|
350
|
+
<EnhancedPdfView
|
|
351
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
352
|
+
style={{ flex: 1 }}
|
|
353
|
+
jsiEnabled={true}
|
|
354
|
+
enablePerformanceTracking={true}
|
|
355
|
+
/>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## 🛠️ Troubleshooting
|
|
359
|
+
|
|
360
|
+
### Common Issues
|
|
361
|
+
|
|
362
|
+
1. **JSI Not Available**
|
|
363
|
+
```javascript
|
|
364
|
+
// Always check availability first
|
|
365
|
+
const isAvailable = await PDFJSI.checkJSIAvailability();
|
|
366
|
+
if (!isAvailable) {
|
|
367
|
+
// Fallback to bridge mode
|
|
368
|
+
console.log('Using bridge mode');
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
2. **Performance Issues**
|
|
373
|
+
```javascript
|
|
374
|
+
// Check performance metrics
|
|
375
|
+
const metrics = await PDFJSI.getPerformanceMetrics('pdf_123');
|
|
376
|
+
console.log('Performance:', metrics);
|
|
377
|
+
|
|
378
|
+
// Clear caches if needed
|
|
379
|
+
await PDFJSI.clearCacheDirect('pdf_123', 'all');
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
3. **Memory Issues**
|
|
383
|
+
```javascript
|
|
384
|
+
// Optimize memory usage
|
|
385
|
+
await PDFJSI.optimizeMemory('pdf_123');
|
|
386
|
+
|
|
387
|
+
// Set lower render quality
|
|
388
|
+
await PDFJSI.setRenderQuality('pdf_123', 1);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## 📊 Performance Comparison
|
|
392
|
+
|
|
393
|
+
| Operation | Bridge Mode | JSI Mode | Improvement |
|
|
394
|
+
|-----------|-------------|----------|-------------|
|
|
395
|
+
| Page Render | 45ms | 2ms | **22.5x faster** |
|
|
396
|
+
| Page Metrics | 12ms | 0.5ms | **24x faster** |
|
|
397
|
+
| Cache Access | 8ms | 0.1ms | **80x faster** |
|
|
398
|
+
| Text Search | 120ms | 15ms | **8x faster** |
|
|
399
|
+
|
|
400
|
+
## 🎉 Best Practices
|
|
401
|
+
|
|
402
|
+
1. **Always check JSI availability** before using JSI methods
|
|
403
|
+
2. **Use preloading** for better user experience
|
|
404
|
+
3. **Monitor performance** with built-in metrics
|
|
405
|
+
4. **Clear caches** periodically to free memory
|
|
406
|
+
5. **Set appropriate render quality** based on needs
|
|
407
|
+
6. **Handle errors gracefully** with fallback to bridge mode
|
|
408
|
+
|
|
409
|
+
## 📚 Additional Resources
|
|
410
|
+
|
|
411
|
+
- [README_JSI.md](./README_JSI.md) - Detailed JSI documentation
|
|
412
|
+
- [PDFJSIExample.js](./src/examples/PDFJSIExample.js) - Complete examples
|
|
413
|
+
- [Performance Benchmarks](./README_JSI.md#performance-characteristics) - Detailed performance data
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
**Ready to supercharge your PDF performance?** 🚀
|
|
418
|
+
|
|
419
|
+
Start with the basic examples above and gradually incorporate advanced features as needed. The JSI integration is designed to be backward-compatible, so you can migrate at your own pace.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Wonday (@wonday.org)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PdfManager.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Wonday (@wonday.org)
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const PdfManagerNative = require('react-native').NativeModules.PdfManager;
|
|
12
|
+
|
|
13
|
+
export default class PdfManager {
|
|
14
|
+
|
|
15
|
+
static loadFile(path, password) {
|
|
16
|
+
if (typeof path !== 'string') {
|
|
17
|
+
throw new TypeError('path must be a valid string.');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (password === undefined) {
|
|
21
|
+
password = "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return PdfManagerNative.loadFile(path, password);
|
|
25
|
+
}
|
|
26
|
+
}
|
package/PdfPageView.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Wonday (@wonday.org)
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
import React, {PureComponent} from 'react';
|
|
12
|
+
import PropTypes from 'prop-types';
|
|
13
|
+
import {
|
|
14
|
+
requireNativeComponent,
|
|
15
|
+
} from 'react-native';
|
|
16
|
+
import {ViewPropTypes} from 'deprecated-react-native-prop-types';
|
|
17
|
+
export default class PdfPageView extends PureComponent {
|
|
18
|
+
_getStylePropsProps = () => {
|
|
19
|
+
const {width, height} = this.props;
|
|
20
|
+
if (width || height) {
|
|
21
|
+
return {width, height};
|
|
22
|
+
}
|
|
23
|
+
return {};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
const {
|
|
28
|
+
style,
|
|
29
|
+
...restProps
|
|
30
|
+
} = this.props;
|
|
31
|
+
return (
|
|
32
|
+
<PdfPageViewCustom
|
|
33
|
+
{...restProps}
|
|
34
|
+
style={[style, this._getStylePropsProps()]}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
PdfPageView.propTypes = {
|
|
42
|
+
...ViewPropTypes,
|
|
43
|
+
fileNo: PropTypes.number,
|
|
44
|
+
page: PropTypes.number,
|
|
45
|
+
width: PropTypes.number,
|
|
46
|
+
height: PropTypes.number
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
PdfPageView.defaultProps = {
|
|
50
|
+
style: {}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
let PdfPageViewCustom = requireNativeComponent('RCTPdfPageView', PdfPageView, {nativeOnly: {}});
|