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.
Files changed (91) hide show
  1. package/DoubleTapView.js +125 -0
  2. package/INTEGRATION_GUIDE.md +419 -0
  3. package/LICENSE +21 -0
  4. package/PdfManager.js +26 -0
  5. package/PdfPageView.js +53 -0
  6. package/PdfView.js +421 -0
  7. package/PdfViewFlatList.js +30 -0
  8. package/PinchZoomView.js +125 -0
  9. package/README.md +693 -0
  10. package/README_JSI.md +348 -0
  11. package/android/.gradle/5.6.1/fileChanges/last-build.bin +0 -0
  12. package/android/.gradle/5.6.1/fileHashes/fileHashes.lock +0 -0
  13. package/android/.gradle/5.6.1/gc.properties +0 -0
  14. package/android/.gradle/8.5/checksums/checksums.lock +0 -0
  15. package/android/.gradle/8.5/checksums/md5-checksums.bin +0 -0
  16. package/android/.gradle/8.5/checksums/sha1-checksums.bin +0 -0
  17. package/android/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock +0 -0
  18. package/android/.gradle/8.5/dependencies-accessors/gc.properties +0 -0
  19. package/android/.gradle/8.5/executionHistory/executionHistory.lock +0 -0
  20. package/android/.gradle/8.5/fileChanges/last-build.bin +0 -0
  21. package/android/.gradle/8.5/fileHashes/fileHashes.lock +0 -0
  22. package/android/.gradle/8.5/gc.properties +0 -0
  23. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  24. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  25. package/android/.gradle/vcs-1/gc.properties +0 -0
  26. package/android/build.gradle +198 -0
  27. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  28. package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  29. package/android/gradle.properties +2 -0
  30. package/android/gradlew +249 -0
  31. package/android/gradlew.bat +92 -0
  32. package/android/project.properties +12 -0
  33. package/android/src/main/AndroidManifest.xml +4 -0
  34. package/android/src/main/cpp/Android.mk +50 -0
  35. package/android/src/main/cpp/CMakeLists.txt +76 -0
  36. package/android/src/main/cpp/PDFJSI.cpp +190 -0
  37. package/android/src/main/cpp/PDFJSI.h +95 -0
  38. package/android/src/main/cpp/PDFJSIBridge.cpp +32 -0
  39. package/android/src/main/cpp/PDFJSIModule.cpp +31 -0
  40. package/android/src/main/java/org/wonday/pdf/EnhancedPdfJSIBridge.java +281 -0
  41. package/android/src/main/java/org/wonday/pdf/PDFJSIManager.java +317 -0
  42. package/android/src/main/java/org/wonday/pdf/PDFJSIModule.java +189 -0
  43. package/android/src/main/java/org/wonday/pdf/PdfManager.java +180 -0
  44. package/android/src/main/java/org/wonday/pdf/PdfView.java +505 -0
  45. package/android/src/main/java/org/wonday/pdf/RNPDFPackage.java +43 -0
  46. package/android/src/main/java/org/wonday/pdf/events/TopChangeEvent.java +26 -0
  47. package/android/src/main/jniLibs/arm64-v8a/libpdfjsi.so +0 -0
  48. package/android/src/main/jniLibs/armeabi-v7a/libpdfjsi.so +0 -0
  49. package/android/src/main/jniLibs/x86/libpdfjsi.so +0 -0
  50. package/android/src/main/jniLibs/x86_64/libpdfjsi.so +0 -0
  51. package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java +92 -0
  52. package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java +35 -0
  53. package/fabric/RNPDFPdfNativeComponent.js +48 -0
  54. package/index.d.ts +72 -0
  55. package/index.js +603 -0
  56. package/index.js.flow +67 -0
  57. package/ios/RNPDFPdf/PdfManager.h +23 -0
  58. package/ios/RNPDFPdf/PdfManager.mm +152 -0
  59. package/ios/RNPDFPdf/RNPDFPdfPageView.h +21 -0
  60. package/ios/RNPDFPdf/RNPDFPdfPageView.mm +185 -0
  61. package/ios/RNPDFPdf/RNPDFPdfPageViewManager.h +18 -0
  62. package/ios/RNPDFPdf/RNPDFPdfPageViewManager.mm +30 -0
  63. package/ios/RNPDFPdf/RNPDFPdfView.h +63 -0
  64. package/ios/RNPDFPdf/RNPDFPdfView.mm +1092 -0
  65. package/ios/RNPDFPdf/RNPDFPdfViewManager.h +18 -0
  66. package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +68 -0
  67. package/ios/RNPDFPdf.xcodeproj/project.pbxproj +321 -0
  68. package/package.json +78 -0
  69. package/react-native-pdf.podspec +31 -0
  70. package/src/EnhancedPdfView.js +362 -0
  71. package/src/PDFJSI.js +519 -0
  72. package/src/examples/PDFJSIExample.js +296 -0
  73. package/src/hooks/usePDFJSI.js +346 -0
  74. package/src/index.js +32 -0
  75. package/windows/RCTPdf/PropertySheet.props +16 -0
  76. package/windows/RCTPdf/RCTPdf.def +3 -0
  77. package/windows/RCTPdf/RCTPdf.vcxproj +180 -0
  78. package/windows/RCTPdf/RCTPdf.vcxproj.filters +38 -0
  79. package/windows/RCTPdf/RCTPdfControl.cpp +667 -0
  80. package/windows/RCTPdf/RCTPdfControl.h +119 -0
  81. package/windows/RCTPdf/RCTPdfControl.idl +10 -0
  82. package/windows/RCTPdf/RCTPdfControl.xaml +33 -0
  83. package/windows/RCTPdf/RCTPdfViewManager.cpp +69 -0
  84. package/windows/RCTPdf/RCTPdfViewManager.h +51 -0
  85. package/windows/RCTPdf/ReactPackageProvider.cpp +15 -0
  86. package/windows/RCTPdf/ReactPackageProvider.h +16 -0
  87. package/windows/RCTPdf/ReactPackageProvider.idl +9 -0
  88. package/windows/RCTPdf/packages.config +4 -0
  89. package/windows/RCTPdf/pch.cpp +1 -0
  90. package/windows/RCTPdf/pch.h +31 -0
  91. 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>
@@ -0,0 +1,3 @@
1
+ EXPORTS
2
+ DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
3
+ DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE