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
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025-present, Punith M (punithm300@gmail.com)
|
|
3
|
+
* Enhanced PDF JSI Example Usage
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Example demonstrating how to use the enhanced PDF JSI components
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useState, useRef } from 'react';
|
|
10
|
+
import { View, Text, Button, StyleSheet, Alert, ScrollView } from 'react-native';
|
|
11
|
+
import { usePDFJSI, EnhancedPdfView, EnhancedPdfUtils } from '../index';
|
|
12
|
+
|
|
13
|
+
const PDFJSIExample = () => {
|
|
14
|
+
const pdfRef = useRef(null);
|
|
15
|
+
const [jsiStats, setJsiStats] = useState(null);
|
|
16
|
+
const [performanceHistory, setPerformanceHistory] = useState([]);
|
|
17
|
+
|
|
18
|
+
// Initialize JSI hook
|
|
19
|
+
const {
|
|
20
|
+
isJSIAvailable,
|
|
21
|
+
isInitialized,
|
|
22
|
+
renderPage,
|
|
23
|
+
getPageMetrics,
|
|
24
|
+
preloadPages,
|
|
25
|
+
searchText,
|
|
26
|
+
getCacheMetrics,
|
|
27
|
+
clearCache,
|
|
28
|
+
optimizeMemory,
|
|
29
|
+
setRenderQuality,
|
|
30
|
+
updatePerformanceMetrics,
|
|
31
|
+
getPerformanceHistory,
|
|
32
|
+
createPDFInstance
|
|
33
|
+
} = usePDFJSI({
|
|
34
|
+
autoInitialize: true,
|
|
35
|
+
enablePerformanceTracking: true,
|
|
36
|
+
enableCaching: true
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const handleCheckJSI = async () => {
|
|
40
|
+
try {
|
|
41
|
+
const stats = await EnhancedPdfUtils.getPerformanceBenchmark();
|
|
42
|
+
setJsiStats(stats);
|
|
43
|
+
Alert.alert('JSI Status', `Available: ${stats.jsiAvailable}\nLevel: ${stats.performanceLevel}`);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
Alert.alert('Error', 'Failed to get JSI stats');
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleRenderPage = async () => {
|
|
50
|
+
try {
|
|
51
|
+
const pdfId = 'example_pdf';
|
|
52
|
+
const result = await renderPage(pdfId, 1, 1.5, 'base64data');
|
|
53
|
+
Alert.alert('Success', `Page rendered: ${JSON.stringify(result)}`);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
Alert.alert('Error', `Render failed: ${error.message}`);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const handleGetMetrics = async () => {
|
|
60
|
+
try {
|
|
61
|
+
const pdfId = 'example_pdf';
|
|
62
|
+
const metrics = await getPageMetrics(pdfId, 1);
|
|
63
|
+
Alert.alert('Page Metrics', JSON.stringify(metrics, null, 2));
|
|
64
|
+
} catch (error) {
|
|
65
|
+
Alert.alert('Error', `Failed to get metrics: ${error.message}`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const handlePreloadPages = async () => {
|
|
70
|
+
try {
|
|
71
|
+
const pdfId = 'example_pdf';
|
|
72
|
+
const success = await preloadPages(pdfId, 1, 5);
|
|
73
|
+
Alert.alert('Preload', `Success: ${success}`);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
Alert.alert('Error', `Preload failed: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleSearchText = async () => {
|
|
80
|
+
try {
|
|
81
|
+
const pdfId = 'example_pdf';
|
|
82
|
+
const results = await searchText(pdfId, 'example', 1, 10);
|
|
83
|
+
Alert.alert('Search Results', `Found ${results.length} matches`);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
Alert.alert('Error', `Search failed: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const handleClearCache = async () => {
|
|
90
|
+
try {
|
|
91
|
+
const pdfId = 'example_pdf';
|
|
92
|
+
const success = await clearCache(pdfId, 'all');
|
|
93
|
+
Alert.alert('Cache', `Cleared: ${success}`);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
Alert.alert('Error', `Clear cache failed: ${error.message}`);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const handleOptimizeMemory = async () => {
|
|
100
|
+
try {
|
|
101
|
+
const pdfId = 'example_pdf';
|
|
102
|
+
const success = await optimizeMemory(pdfId);
|
|
103
|
+
Alert.alert('Memory', `Optimized: ${success}`);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
Alert.alert('Error', `Memory optimization failed: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const handleSetQuality = async () => {
|
|
110
|
+
try {
|
|
111
|
+
const pdfId = 'example_pdf';
|
|
112
|
+
const success = await setRenderQuality(pdfId, 3);
|
|
113
|
+
Alert.alert('Quality', `Set to high: ${success}`);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
Alert.alert('Error', `Set quality failed: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const handleGetPerformanceHistory = () => {
|
|
120
|
+
const history = getPerformanceHistory();
|
|
121
|
+
setPerformanceHistory(history);
|
|
122
|
+
Alert.alert('Performance History', `${history.length} operations recorded`);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const handleCreateInstance = () => {
|
|
126
|
+
const instance = createPDFInstance('example_pdf', { quality: 2 });
|
|
127
|
+
Alert.alert('Instance Created', `ID: ${instance.id}`);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<ScrollView style={styles.container}>
|
|
132
|
+
<Text style={styles.title}>Enhanced PDF JSI Example</Text>
|
|
133
|
+
|
|
134
|
+
<View style={styles.statusContainer}>
|
|
135
|
+
<Text style={styles.statusText}>
|
|
136
|
+
JSI Available: {isJSIAvailable ? '✅ Yes' : '❌ No'}
|
|
137
|
+
</Text>
|
|
138
|
+
<Text style={styles.statusText}>
|
|
139
|
+
Initialized: {isInitialized ? '✅ Yes' : '⏳ No'}
|
|
140
|
+
</Text>
|
|
141
|
+
</View>
|
|
142
|
+
|
|
143
|
+
<View style={styles.buttonContainer}>
|
|
144
|
+
<Button title="Check JSI Status" onPress={handleCheckJSI} />
|
|
145
|
+
<Button title="Render Page" onPress={handleRenderPage} />
|
|
146
|
+
<Button title="Get Page Metrics" onPress={handleGetMetrics} />
|
|
147
|
+
<Button title="Preload Pages" onPress={handlePreloadPages} />
|
|
148
|
+
<Button title="Search Text" onPress={handleSearchText} />
|
|
149
|
+
<Button title="Clear Cache" onPress={handleClearCache} />
|
|
150
|
+
<Button title="Optimize Memory" onPress={handleOptimizeMemory} />
|
|
151
|
+
<Button title="Set High Quality" onPress={handleSetQuality} />
|
|
152
|
+
<Button title="Get Performance History" onPress={handleGetPerformanceHistory} />
|
|
153
|
+
<Button title="Create PDF Instance" onPress={handleCreateInstance} />
|
|
154
|
+
</View>
|
|
155
|
+
|
|
156
|
+
{jsiStats && (
|
|
157
|
+
<View style={styles.statsContainer}>
|
|
158
|
+
<Text style={styles.statsTitle}>JSI Statistics:</Text>
|
|
159
|
+
<Text>Available: {jsiStats.jsiAvailable ? 'Yes' : 'No'}</Text>
|
|
160
|
+
<Text>Performance Level: {jsiStats.performanceLevel}</Text>
|
|
161
|
+
<Text>Direct Memory Access: {jsiStats.directMemoryAccess ? 'Yes' : 'No'}</Text>
|
|
162
|
+
<Text>Bridge Optimized: {jsiStats.bridgeOptimized ? 'Yes' : 'No'}</Text>
|
|
163
|
+
<Text>Operations: {jsiStats.operationHistory.length}</Text>
|
|
164
|
+
</View>
|
|
165
|
+
)}
|
|
166
|
+
|
|
167
|
+
{performanceHistory.length > 0 && (
|
|
168
|
+
<View style={styles.historyContainer}>
|
|
169
|
+
<Text style={styles.historyTitle}>Performance History:</Text>
|
|
170
|
+
{performanceHistory.slice(-5).map((entry, index) => (
|
|
171
|
+
<Text key={index} style={styles.historyEntry}>
|
|
172
|
+
{entry.operation}: {entry.duration.toFixed(2)}ms ({entry.mode})
|
|
173
|
+
</Text>
|
|
174
|
+
))}
|
|
175
|
+
</View>
|
|
176
|
+
)}
|
|
177
|
+
|
|
178
|
+
<View style={styles.enhancedViewContainer}>
|
|
179
|
+
<Text style={styles.enhancedTitle}>Enhanced PDF View:</Text>
|
|
180
|
+
<EnhancedPdfView
|
|
181
|
+
ref={pdfRef}
|
|
182
|
+
source={{ uri: 'https://example.com/sample.pdf' }}
|
|
183
|
+
style={styles.pdfView}
|
|
184
|
+
onLoadComplete={(numberOfPages) => {
|
|
185
|
+
console.log(`PDF loaded with ${numberOfPages} pages`);
|
|
186
|
+
}}
|
|
187
|
+
onPageChanged={(page, numberOfPages) => {
|
|
188
|
+
console.log(`Page changed to ${page} of ${numberOfPages}`);
|
|
189
|
+
}}
|
|
190
|
+
onError={(error) => {
|
|
191
|
+
console.error('PDF error:', error);
|
|
192
|
+
}}
|
|
193
|
+
/>
|
|
194
|
+
</View>
|
|
195
|
+
</ScrollView>
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const styles = StyleSheet.create({
|
|
200
|
+
container: {
|
|
201
|
+
flex: 1,
|
|
202
|
+
padding: 20,
|
|
203
|
+
backgroundColor: '#f5f5f5',
|
|
204
|
+
},
|
|
205
|
+
title: {
|
|
206
|
+
fontSize: 24,
|
|
207
|
+
fontWeight: 'bold',
|
|
208
|
+
textAlign: 'center',
|
|
209
|
+
marginBottom: 20,
|
|
210
|
+
color: '#333',
|
|
211
|
+
},
|
|
212
|
+
statusContainer: {
|
|
213
|
+
backgroundColor: '#fff',
|
|
214
|
+
padding: 15,
|
|
215
|
+
borderRadius: 8,
|
|
216
|
+
marginBottom: 20,
|
|
217
|
+
elevation: 2,
|
|
218
|
+
shadowColor: '#000',
|
|
219
|
+
shadowOffset: { width: 0, height: 2 },
|
|
220
|
+
shadowOpacity: 0.1,
|
|
221
|
+
shadowRadius: 4,
|
|
222
|
+
},
|
|
223
|
+
statusText: {
|
|
224
|
+
fontSize: 16,
|
|
225
|
+
marginBottom: 5,
|
|
226
|
+
color: '#666',
|
|
227
|
+
},
|
|
228
|
+
buttonContainer: {
|
|
229
|
+
gap: 10,
|
|
230
|
+
marginBottom: 20,
|
|
231
|
+
},
|
|
232
|
+
statsContainer: {
|
|
233
|
+
backgroundColor: '#fff',
|
|
234
|
+
padding: 15,
|
|
235
|
+
borderRadius: 8,
|
|
236
|
+
marginBottom: 20,
|
|
237
|
+
elevation: 2,
|
|
238
|
+
shadowColor: '#000',
|
|
239
|
+
shadowOffset: { width: 0, height: 2 },
|
|
240
|
+
shadowOpacity: 0.1,
|
|
241
|
+
shadowRadius: 4,
|
|
242
|
+
},
|
|
243
|
+
statsTitle: {
|
|
244
|
+
fontSize: 18,
|
|
245
|
+
fontWeight: 'bold',
|
|
246
|
+
marginBottom: 10,
|
|
247
|
+
color: '#333',
|
|
248
|
+
},
|
|
249
|
+
historyContainer: {
|
|
250
|
+
backgroundColor: '#fff',
|
|
251
|
+
padding: 15,
|
|
252
|
+
borderRadius: 8,
|
|
253
|
+
marginBottom: 20,
|
|
254
|
+
elevation: 2,
|
|
255
|
+
shadowColor: '#000',
|
|
256
|
+
shadowOffset: { width: 0, height: 2 },
|
|
257
|
+
shadowOpacity: 0.1,
|
|
258
|
+
shadowRadius: 4,
|
|
259
|
+
},
|
|
260
|
+
historyTitle: {
|
|
261
|
+
fontSize: 18,
|
|
262
|
+
fontWeight: 'bold',
|
|
263
|
+
marginBottom: 10,
|
|
264
|
+
color: '#333',
|
|
265
|
+
},
|
|
266
|
+
historyEntry: {
|
|
267
|
+
fontSize: 14,
|
|
268
|
+
marginBottom: 5,
|
|
269
|
+
color: '#666',
|
|
270
|
+
fontFamily: 'monospace',
|
|
271
|
+
},
|
|
272
|
+
enhancedViewContainer: {
|
|
273
|
+
backgroundColor: '#fff',
|
|
274
|
+
padding: 15,
|
|
275
|
+
borderRadius: 8,
|
|
276
|
+
marginBottom: 20,
|
|
277
|
+
elevation: 2,
|
|
278
|
+
shadowColor: '#000',
|
|
279
|
+
shadowOffset: { width: 0, height: 2 },
|
|
280
|
+
shadowOpacity: 0.1,
|
|
281
|
+
shadowRadius: 4,
|
|
282
|
+
},
|
|
283
|
+
enhancedTitle: {
|
|
284
|
+
fontSize: 18,
|
|
285
|
+
fontWeight: 'bold',
|
|
286
|
+
marginBottom: 10,
|
|
287
|
+
color: '#333',
|
|
288
|
+
},
|
|
289
|
+
pdfView: {
|
|
290
|
+
height: 400,
|
|
291
|
+
backgroundColor: '#f0f0f0',
|
|
292
|
+
borderRadius: 4,
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
export default PDFJSIExample;
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025-present, Punith M (punithm300@gmail.com)
|
|
3
|
+
* Enhanced PDF JSI Hook with high-performance operations
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* React Hook for easy JSI integration in functional components
|
|
7
|
+
* Provides automatic JSI availability detection and fallback handling
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
11
|
+
import { Platform } from 'react-native';
|
|
12
|
+
import PDFJSI from '../PDFJSI';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hook for PDF JSI functionality
|
|
16
|
+
* @param {Object} options - Configuration options
|
|
17
|
+
* @returns {Object} JSI utilities and state
|
|
18
|
+
*/
|
|
19
|
+
export const usePDFJSI = (options = {}) => {
|
|
20
|
+
const {
|
|
21
|
+
autoInitialize = true,
|
|
22
|
+
enablePerformanceTracking = true,
|
|
23
|
+
enableCaching = true,
|
|
24
|
+
maxCacheSize = 100
|
|
25
|
+
} = options;
|
|
26
|
+
|
|
27
|
+
// State management
|
|
28
|
+
const [isJSIAvailable, setIsJSIAvailable] = useState(false);
|
|
29
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
30
|
+
const [performanceMetrics, setPerformanceMetrics] = useState(null);
|
|
31
|
+
const [jsiStats, setJsiStats] = useState(null);
|
|
32
|
+
|
|
33
|
+
// Refs for tracking
|
|
34
|
+
const pdfInstancesRef = useRef(new Map());
|
|
35
|
+
const performanceHistoryRef = useRef([]);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initialize JSI availability check
|
|
39
|
+
*/
|
|
40
|
+
const initializeJSI = useCallback(async () => {
|
|
41
|
+
try {
|
|
42
|
+
// Enable JSI for both Android and iOS
|
|
43
|
+
// iOS will get enhanced caching and performance optimizations
|
|
44
|
+
if (Platform.OS === 'android') {
|
|
45
|
+
// Android gets full JSI support
|
|
46
|
+
const isAvailable = await PDFJSI.checkJSIAvailability();
|
|
47
|
+
setIsJSIAvailable(isAvailable);
|
|
48
|
+
setIsInitialized(true);
|
|
49
|
+
return isAvailable;
|
|
50
|
+
} else {
|
|
51
|
+
// iOS gets enhanced caching support (bridge mode with optimizations)
|
|
52
|
+
setIsJSIAvailable(true); // Enable enhanced features for iOS
|
|
53
|
+
setIsInitialized(true);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Get JSI stats for performance tracking (Android only)
|
|
58
|
+
if (Platform.OS === 'android' && isJSIAvailable && enablePerformanceTracking) {
|
|
59
|
+
const stats = await PDFJSI.getJSIStats();
|
|
60
|
+
setJsiStats(stats);
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('📱 usePDFJSI: Error initializing JSI:', error);
|
|
64
|
+
setIsJSIAvailable(false);
|
|
65
|
+
setIsInitialized(true);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}, [enablePerformanceTracking]);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Render page with JSI or fallback
|
|
72
|
+
*/
|
|
73
|
+
const renderPage = useCallback(async (pdfId, pageNumber, scale, base64Data) => {
|
|
74
|
+
const startTime = performance.now();
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
if (isJSIAvailable) {
|
|
78
|
+
const result = await PDFJSI.renderPageDirect(pdfId, pageNumber, scale, base64Data);
|
|
79
|
+
|
|
80
|
+
const endTime = performance.now();
|
|
81
|
+
const renderTime = endTime - startTime;
|
|
82
|
+
|
|
83
|
+
// Track performance
|
|
84
|
+
if (enablePerformanceTracking) {
|
|
85
|
+
performanceHistoryRef.current.push({
|
|
86
|
+
operation: 'renderPage',
|
|
87
|
+
duration: renderTime,
|
|
88
|
+
timestamp: Date.now(),
|
|
89
|
+
pdfId,
|
|
90
|
+
pageNumber,
|
|
91
|
+
scale,
|
|
92
|
+
mode: 'JSI'
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return result;
|
|
97
|
+
} else {
|
|
98
|
+
// Fallback to bridge mode (would need to implement)
|
|
99
|
+
throw new Error('JSI not available and bridge fallback not implemented');
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const endTime = performance.now();
|
|
103
|
+
const renderTime = endTime - startTime;
|
|
104
|
+
|
|
105
|
+
if (enablePerformanceTracking) {
|
|
106
|
+
performanceHistoryRef.current.push({
|
|
107
|
+
operation: 'renderPage',
|
|
108
|
+
duration: renderTime,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
pdfId,
|
|
111
|
+
pageNumber,
|
|
112
|
+
scale,
|
|
113
|
+
mode: 'JSI_ERROR',
|
|
114
|
+
error: error.message
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}, [isJSIAvailable, enablePerformanceTracking]);
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get page metrics
|
|
124
|
+
*/
|
|
125
|
+
const getPageMetrics = useCallback(async (pdfId, pageNumber) => {
|
|
126
|
+
try {
|
|
127
|
+
if (isJSIAvailable) {
|
|
128
|
+
return await PDFJSI.getPageMetrics(pdfId, pageNumber);
|
|
129
|
+
} else {
|
|
130
|
+
throw new Error('JSI not available');
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('📱 usePDFJSI: Error getting page metrics:', error);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}, [isJSIAvailable]);
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Preload pages
|
|
140
|
+
*/
|
|
141
|
+
const preloadPages = useCallback(async (pdfId, startPage, endPage) => {
|
|
142
|
+
try {
|
|
143
|
+
if (isJSIAvailable) {
|
|
144
|
+
return await PDFJSI.preloadPagesDirect(pdfId, startPage, endPage);
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error('JSI not available');
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error('📱 usePDFJSI: Error preloading pages:', error);
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}, [isJSIAvailable]);
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Search text
|
|
156
|
+
*/
|
|
157
|
+
const searchText = useCallback(async (pdfId, searchTerm, startPage, endPage) => {
|
|
158
|
+
try {
|
|
159
|
+
if (isJSIAvailable) {
|
|
160
|
+
return await PDFJSI.searchTextDirect(pdfId, searchTerm, startPage, endPage);
|
|
161
|
+
} else {
|
|
162
|
+
throw new Error('JSI not available');
|
|
163
|
+
}
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error('📱 usePDFJSI: Error searching text:', error);
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}, [isJSIAvailable]);
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get cache metrics
|
|
172
|
+
*/
|
|
173
|
+
const getCacheMetrics = useCallback(async (pdfId) => {
|
|
174
|
+
try {
|
|
175
|
+
if (isJSIAvailable) {
|
|
176
|
+
return await PDFJSI.getCacheMetrics(pdfId);
|
|
177
|
+
} else {
|
|
178
|
+
throw new Error('JSI not available');
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('📱 usePDFJSI: Error getting cache metrics:', error);
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}, [isJSIAvailable]);
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Clear cache
|
|
188
|
+
*/
|
|
189
|
+
const clearCache = useCallback(async (pdfId, cacheType = 'all') => {
|
|
190
|
+
try {
|
|
191
|
+
if (isJSIAvailable) {
|
|
192
|
+
return await PDFJSI.clearCacheDirect(pdfId, cacheType);
|
|
193
|
+
} else {
|
|
194
|
+
throw new Error('JSI not available');
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error('📱 usePDFJSI: Error clearing cache:', error);
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}, [isJSIAvailable]);
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Optimize memory
|
|
204
|
+
*/
|
|
205
|
+
const optimizeMemory = useCallback(async (pdfId) => {
|
|
206
|
+
try {
|
|
207
|
+
if (isJSIAvailable) {
|
|
208
|
+
return await PDFJSI.optimizeMemory(pdfId);
|
|
209
|
+
} else {
|
|
210
|
+
throw new Error('JSI not available');
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error('📱 usePDFJSI: Error optimizing memory:', error);
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}, [isJSIAvailable]);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Set render quality
|
|
220
|
+
*/
|
|
221
|
+
const setRenderQuality = useCallback(async (pdfId, quality) => {
|
|
222
|
+
try {
|
|
223
|
+
if (isJSIAvailable) {
|
|
224
|
+
return await PDFJSI.setRenderQuality(pdfId, quality);
|
|
225
|
+
} else {
|
|
226
|
+
throw new Error('JSI not available');
|
|
227
|
+
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('📱 usePDFJSI: Error setting render quality:', error);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}, [isJSIAvailable]);
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Update performance metrics
|
|
236
|
+
*/
|
|
237
|
+
const updatePerformanceMetrics = useCallback(async (pdfId) => {
|
|
238
|
+
try {
|
|
239
|
+
if (isJSIAvailable) {
|
|
240
|
+
const metrics = await PDFJSI.getPerformanceMetrics(pdfId);
|
|
241
|
+
setPerformanceMetrics(metrics);
|
|
242
|
+
return metrics;
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error('📱 usePDFJSI: Error updating performance metrics:', error);
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}, [isJSIAvailable]);
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get performance history
|
|
252
|
+
*/
|
|
253
|
+
const getPerformanceHistory = useCallback(() => {
|
|
254
|
+
return [...performanceHistoryRef.current];
|
|
255
|
+
}, []);
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Clear performance history
|
|
259
|
+
*/
|
|
260
|
+
const clearPerformanceHistory = useCallback(() => {
|
|
261
|
+
performanceHistoryRef.current = [];
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Create PDF instance with tracking
|
|
266
|
+
*/
|
|
267
|
+
const createPDFInstance = useCallback((pdfId, options = {}) => {
|
|
268
|
+
const instance = {
|
|
269
|
+
id: pdfId,
|
|
270
|
+
created: Date.now(),
|
|
271
|
+
options,
|
|
272
|
+
metrics: null,
|
|
273
|
+
cacheMetrics: null
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
pdfInstancesRef.current.set(pdfId, instance);
|
|
277
|
+
return instance;
|
|
278
|
+
}, []);
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Remove PDF instance
|
|
282
|
+
*/
|
|
283
|
+
const removePDFInstance = useCallback((pdfId) => {
|
|
284
|
+
pdfInstancesRef.current.delete(pdfId);
|
|
285
|
+
}, []);
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get all PDF instances
|
|
289
|
+
*/
|
|
290
|
+
const getPDFInstances = useCallback(() => {
|
|
291
|
+
return Array.from(pdfInstancesRef.current.values());
|
|
292
|
+
}, []);
|
|
293
|
+
|
|
294
|
+
// Initialize JSI on mount if autoInitialize is enabled
|
|
295
|
+
useEffect(() => {
|
|
296
|
+
if (autoInitialize && !isInitialized) {
|
|
297
|
+
initializeJSI();
|
|
298
|
+
}
|
|
299
|
+
}, [autoInitialize, isInitialized, initializeJSI]);
|
|
300
|
+
|
|
301
|
+
// Cleanup on unmount
|
|
302
|
+
useEffect(() => {
|
|
303
|
+
return () => {
|
|
304
|
+
// Cleanup PDF instances
|
|
305
|
+
pdfInstancesRef.current.clear();
|
|
306
|
+
|
|
307
|
+
// Clear performance history if needed
|
|
308
|
+
if (!enablePerformanceTracking) {
|
|
309
|
+
performanceHistoryRef.current = [];
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}, [enablePerformanceTracking]);
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
// State
|
|
316
|
+
isJSIAvailable,
|
|
317
|
+
isInitialized,
|
|
318
|
+
performanceMetrics,
|
|
319
|
+
jsiStats,
|
|
320
|
+
|
|
321
|
+
// Core functions
|
|
322
|
+
renderPage,
|
|
323
|
+
getPageMetrics,
|
|
324
|
+
preloadPages,
|
|
325
|
+
searchText,
|
|
326
|
+
getCacheMetrics,
|
|
327
|
+
clearCache,
|
|
328
|
+
optimizeMemory,
|
|
329
|
+
setRenderQuality,
|
|
330
|
+
|
|
331
|
+
// Performance tracking
|
|
332
|
+
updatePerformanceMetrics,
|
|
333
|
+
getPerformanceHistory,
|
|
334
|
+
clearPerformanceHistory,
|
|
335
|
+
|
|
336
|
+
// Instance management
|
|
337
|
+
createPDFInstance,
|
|
338
|
+
removePDFInstance,
|
|
339
|
+
getPDFInstances,
|
|
340
|
+
|
|
341
|
+
// Utilities
|
|
342
|
+
initializeJSI
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export default usePDFJSI;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025-present, Punith M (punithm300@gmail.com)
|
|
3
|
+
* Enhanced PDF JSI Integration - Main Export
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Main export file for enhanced PDF JSI components and utilities
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Core JSI functionality
|
|
10
|
+
export { default as PDFJSI } from './PDFJSI';
|
|
11
|
+
|
|
12
|
+
// Enhanced PDF View component
|
|
13
|
+
export { default as EnhancedPdfView, EnhancedPdfUtils } from './EnhancedPdfView';
|
|
14
|
+
|
|
15
|
+
// React hooks
|
|
16
|
+
export { default as usePDFJSI } from './hooks/usePDFJSI';
|
|
17
|
+
|
|
18
|
+
// Re-export individual JSI methods for convenience
|
|
19
|
+
export {
|
|
20
|
+
renderPageDirect,
|
|
21
|
+
getPageMetrics,
|
|
22
|
+
preloadPagesDirect,
|
|
23
|
+
getCacheMetrics,
|
|
24
|
+
clearCacheDirect,
|
|
25
|
+
optimizeMemory,
|
|
26
|
+
searchTextDirect,
|
|
27
|
+
getPerformanceMetrics,
|
|
28
|
+
setRenderQuality,
|
|
29
|
+
getJSIStats,
|
|
30
|
+
getPerformanceHistory,
|
|
31
|
+
clearPerformanceHistory
|
|
32
|
+
} from './PDFJSI';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
3
|
+
<ImportGroup Label="PropertySheets" />
|
|
4
|
+
<PropertyGroup Label="UserMacros" />
|
|
5
|
+
<!--
|
|
6
|
+
To customize common C++/WinRT project properties:
|
|
7
|
+
* right-click the project node
|
|
8
|
+
* expand the Common Properties item
|
|
9
|
+
* select the C++/WinRT property page
|
|
10
|
+
|
|
11
|
+
For more advanced scenarios, and complete documentation, please see:
|
|
12
|
+
https://github.com/Microsoft/xlang/tree/master/src/package/cppwinrt/nuget
|
|
13
|
+
-->
|
|
14
|
+
<PropertyGroup />
|
|
15
|
+
<ItemDefinitionGroup />
|
|
16
|
+
</Project>
|