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/src/PDFJSI.js
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025-present, Punith M (punithm300@gmail.com)
|
|
3
|
+
* Enhanced PDF JSI JavaScript Bridge with high-performance operations
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* JavaScript interface for high-performance PDF operations via JSI
|
|
7
|
+
* Provides direct access to native PDF functions without bridge overhead
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
11
|
+
|
|
12
|
+
const { PDFJSIManager: PDFJSIManagerNative, EnhancedPdfJSIBridge, RNPDFPdfViewManager } = NativeModules;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Enhanced PDF JSI Manager
|
|
16
|
+
* Provides high-performance PDF operations via JSI
|
|
17
|
+
*/
|
|
18
|
+
class PDFJSIManager {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.isJSIAvailable = false;
|
|
21
|
+
this.performanceMetrics = new Map();
|
|
22
|
+
this.cacheMetrics = new Map();
|
|
23
|
+
this.initializationPromise = null;
|
|
24
|
+
|
|
25
|
+
this.initializeJSI();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initialize JSI availability check
|
|
30
|
+
*/
|
|
31
|
+
async initializeJSI() {
|
|
32
|
+
if (this.initializationPromise) {
|
|
33
|
+
return this.initializationPromise;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.initializationPromise = this.checkJSIAvailability();
|
|
37
|
+
return this.initializationPromise;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if JSI is available
|
|
42
|
+
*/
|
|
43
|
+
async checkJSIAvailability() {
|
|
44
|
+
try {
|
|
45
|
+
let isAvailable = false;
|
|
46
|
+
|
|
47
|
+
if (Platform.OS === 'android') {
|
|
48
|
+
isAvailable = await PDFJSIManagerNative.isJSIAvailable();
|
|
49
|
+
} else if (Platform.OS === 'ios') {
|
|
50
|
+
// For iOS, we use the native module methods directly
|
|
51
|
+
isAvailable = await RNPDFPdfViewManager.checkJSIAvailability();
|
|
52
|
+
} else {
|
|
53
|
+
console.log('📱 PDFJSI: Platform not supported:', Platform.OS);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.isJSIAvailable = isAvailable;
|
|
58
|
+
|
|
59
|
+
console.log(`📱 PDFJSI: JSI availability on ${Platform.OS}: ${isAvailable ? 'AVAILABLE' : 'NOT AVAILABLE'}`);
|
|
60
|
+
return isAvailable;
|
|
61
|
+
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('📱 PDFJSI: Error checking JSI availability:', error);
|
|
64
|
+
this.isJSIAvailable = false;
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Render page directly via JSI (high-performance)
|
|
71
|
+
* @param {string} pdfId - PDF identifier
|
|
72
|
+
* @param {number} pageNumber - Page number to render
|
|
73
|
+
* @param {number} scale - Render scale factor
|
|
74
|
+
* @param {string} base64Data - Base64 encoded PDF data
|
|
75
|
+
* @returns {Promise<Object>} Render result
|
|
76
|
+
*/
|
|
77
|
+
async renderPageDirect(pdfId, pageNumber, scale, base64Data) {
|
|
78
|
+
if (!this.isJSIAvailable) {
|
|
79
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const startTime = performance.now();
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
console.log(`📱 PDFJSI: Rendering page ${pageNumber} at scale ${scale} for PDF ${pdfId}`);
|
|
86
|
+
|
|
87
|
+
let result;
|
|
88
|
+
if (Platform.OS === 'android') {
|
|
89
|
+
result = await PDFJSIManagerNative.renderPageDirect(pdfId, pageNumber, scale, base64Data);
|
|
90
|
+
} else if (Platform.OS === 'ios') {
|
|
91
|
+
result = await RNPDFPdfViewManager.renderPageDirect(pdfId, pageNumber, scale, base64Data);
|
|
92
|
+
} else {
|
|
93
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const endTime = performance.now();
|
|
97
|
+
const renderTime = endTime - startTime;
|
|
98
|
+
|
|
99
|
+
// Track performance
|
|
100
|
+
this.trackPerformance('renderPageDirect', renderTime, {
|
|
101
|
+
pdfId,
|
|
102
|
+
pageNumber,
|
|
103
|
+
scale,
|
|
104
|
+
success: result.success
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(`📱 PDFJSI: Page rendered in ${renderTime.toFixed(2)}ms`);
|
|
108
|
+
|
|
109
|
+
return result;
|
|
110
|
+
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const endTime = performance.now();
|
|
113
|
+
const renderTime = endTime - startTime;
|
|
114
|
+
|
|
115
|
+
console.error(`📱 PDFJSI: Error rendering page in ${renderTime.toFixed(2)}ms:`, error);
|
|
116
|
+
|
|
117
|
+
this.trackPerformance('renderPageDirect', renderTime, {
|
|
118
|
+
pdfId,
|
|
119
|
+
pageNumber,
|
|
120
|
+
scale,
|
|
121
|
+
success: false,
|
|
122
|
+
error: error.message
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get page metrics via JSI
|
|
131
|
+
* @param {string} pdfId - PDF identifier
|
|
132
|
+
* @param {number} pageNumber - Page number
|
|
133
|
+
* @returns {Promise<Object>} Page metrics
|
|
134
|
+
*/
|
|
135
|
+
async getPageMetrics(pdfId, pageNumber) {
|
|
136
|
+
if (!this.isJSIAvailable) {
|
|
137
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
console.log(`📱 PDFJSI: Getting metrics for page ${pageNumber} of PDF ${pdfId}`);
|
|
142
|
+
|
|
143
|
+
let metrics;
|
|
144
|
+
if (Platform.OS === 'android') {
|
|
145
|
+
metrics = await PDFJSIManagerNative.getPageMetrics(pdfId, pageNumber);
|
|
146
|
+
} else if (Platform.OS === 'ios') {
|
|
147
|
+
metrics = await RNPDFPdfViewManager.getPageMetrics(pdfId, pageNumber);
|
|
148
|
+
} else {
|
|
149
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log(`📱 PDFJSI: Page metrics retrieved:`, metrics);
|
|
153
|
+
|
|
154
|
+
return metrics;
|
|
155
|
+
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error(`📱 PDFJSI: Error getting page metrics:`, error);
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Preload pages directly via JSI
|
|
164
|
+
* @param {string} pdfId - PDF identifier
|
|
165
|
+
* @param {number} startPage - Start page number
|
|
166
|
+
* @param {number} endPage - End page number
|
|
167
|
+
* @returns {Promise<boolean>} Success status
|
|
168
|
+
*/
|
|
169
|
+
async preloadPagesDirect(pdfId, startPage, endPage) {
|
|
170
|
+
if (!this.isJSIAvailable) {
|
|
171
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const startTime = performance.now();
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
console.log(`📱 PDFJSI: Preloading pages ${startPage}-${endPage} for PDF ${pdfId}`);
|
|
178
|
+
|
|
179
|
+
let success;
|
|
180
|
+
if (Platform.OS === 'android') {
|
|
181
|
+
success = await PDFJSIManagerNative.preloadPagesDirect(pdfId, startPage, endPage);
|
|
182
|
+
} else if (Platform.OS === 'ios') {
|
|
183
|
+
success = await RNPDFPdfViewManager.preloadPagesDirect(pdfId, startPage, endPage);
|
|
184
|
+
} else {
|
|
185
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const endTime = performance.now();
|
|
189
|
+
const preloadTime = endTime - startTime;
|
|
190
|
+
|
|
191
|
+
console.log(`📱 PDFJSI: Pages preloaded in ${preloadTime.toFixed(2)}ms, Success: ${success}`);
|
|
192
|
+
|
|
193
|
+
this.trackPerformance('preloadPagesDirect', preloadTime, {
|
|
194
|
+
pdfId,
|
|
195
|
+
startPage,
|
|
196
|
+
endPage,
|
|
197
|
+
success
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return success;
|
|
201
|
+
|
|
202
|
+
} catch (error) {
|
|
203
|
+
const endTime = performance.now();
|
|
204
|
+
const preloadTime = endTime - startTime;
|
|
205
|
+
|
|
206
|
+
console.error(`📱 PDFJSI: Error preloading pages in ${preloadTime.toFixed(2)}ms:`, error);
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get cache metrics via JSI
|
|
213
|
+
* @param {string} pdfId - PDF identifier
|
|
214
|
+
* @returns {Promise<Object>} Cache metrics
|
|
215
|
+
*/
|
|
216
|
+
async getCacheMetrics(pdfId) {
|
|
217
|
+
if (!this.isJSIAvailable) {
|
|
218
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
console.log(`📱 PDFJSI: Getting cache metrics for PDF ${pdfId}`);
|
|
223
|
+
|
|
224
|
+
let metrics;
|
|
225
|
+
if (Platform.OS === 'android') {
|
|
226
|
+
metrics = await PDFJSIManagerNative.getCacheMetrics(pdfId);
|
|
227
|
+
} else if (Platform.OS === 'ios') {
|
|
228
|
+
metrics = await RNPDFPdfViewManager.getCacheMetrics();
|
|
229
|
+
} else {
|
|
230
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Cache the metrics
|
|
234
|
+
this.cacheMetrics.set(pdfId, metrics);
|
|
235
|
+
|
|
236
|
+
console.log(`📱 PDFJSI: Cache metrics retrieved:`, metrics);
|
|
237
|
+
|
|
238
|
+
return metrics;
|
|
239
|
+
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error(`📱 PDFJSI: Error getting cache metrics:`, error);
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Clear cache directly via JSI
|
|
248
|
+
* @param {string} pdfId - PDF identifier
|
|
249
|
+
* @param {string} cacheType - Cache type to clear ('all', 'base64', 'bytes')
|
|
250
|
+
* @returns {Promise<boolean>} Success status
|
|
251
|
+
*/
|
|
252
|
+
async clearCacheDirect(pdfId, cacheType = 'all') {
|
|
253
|
+
if (!this.isJSIAvailable) {
|
|
254
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
console.log(`📱 PDFJSI: Clearing cache type '${cacheType}' for PDF ${pdfId}`);
|
|
259
|
+
|
|
260
|
+
let success;
|
|
261
|
+
if (Platform.OS === 'android') {
|
|
262
|
+
success = await PDFJSIManagerNative.clearCacheDirect(pdfId, cacheType);
|
|
263
|
+
} else if (Platform.OS === 'ios') {
|
|
264
|
+
success = await RNPDFPdfViewManager.clearCacheDirect(pdfId, cacheType);
|
|
265
|
+
} else {
|
|
266
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Clear local cache metrics
|
|
270
|
+
if (success) {
|
|
271
|
+
this.cacheMetrics.delete(pdfId);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
console.log(`📱 PDFJSI: Cache cleared, Success: ${success}`);
|
|
275
|
+
|
|
276
|
+
return success;
|
|
277
|
+
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error(`📱 PDFJSI: Error clearing cache:`, error);
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Optimize memory via JSI
|
|
286
|
+
* @param {string} pdfId - PDF identifier
|
|
287
|
+
* @returns {Promise<boolean>} Success status
|
|
288
|
+
*/
|
|
289
|
+
async optimizeMemory(pdfId) {
|
|
290
|
+
if (!this.isJSIAvailable) {
|
|
291
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
console.log(`📱 PDFJSI: Optimizing memory for PDF ${pdfId}`);
|
|
296
|
+
|
|
297
|
+
let success;
|
|
298
|
+
if (Platform.OS === 'android') {
|
|
299
|
+
success = await PDFJSIManagerNative.optimizeMemory(pdfId);
|
|
300
|
+
} else if (Platform.OS === 'ios') {
|
|
301
|
+
success = await RNPDFPdfViewManager.optimizeMemory(pdfId);
|
|
302
|
+
} else {
|
|
303
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
console.log(`📱 PDFJSI: Memory optimization completed, Success: ${success}`);
|
|
307
|
+
|
|
308
|
+
return success;
|
|
309
|
+
|
|
310
|
+
} catch (error) {
|
|
311
|
+
console.error(`📱 PDFJSI: Error optimizing memory:`, error);
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Search text directly via JSI
|
|
318
|
+
* @param {string} pdfId - PDF identifier
|
|
319
|
+
* @param {string} searchTerm - Search term
|
|
320
|
+
* @param {number} startPage - Start page number
|
|
321
|
+
* @param {number} endPage - End page number
|
|
322
|
+
* @returns {Promise<Array>} Search results
|
|
323
|
+
*/
|
|
324
|
+
async searchTextDirect(pdfId, searchTerm, startPage, endPage) {
|
|
325
|
+
if (!this.isJSIAvailable) {
|
|
326
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const startTime = performance.now();
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
console.log(`📱 PDFJSI: Searching for '${searchTerm}' in pages ${startPage}-${endPage}`);
|
|
333
|
+
|
|
334
|
+
let results;
|
|
335
|
+
if (Platform.OS === 'android') {
|
|
336
|
+
results = await PDFJSIManagerNative.searchTextDirect(pdfId, searchTerm, startPage, endPage);
|
|
337
|
+
} else if (Platform.OS === 'ios') {
|
|
338
|
+
results = await RNPDFPdfViewManager.searchTextDirect(pdfId, searchTerm);
|
|
339
|
+
} else {
|
|
340
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const endTime = performance.now();
|
|
344
|
+
const searchTime = endTime - startTime;
|
|
345
|
+
|
|
346
|
+
console.log(`📱 PDFJSI: Search completed in ${searchTime.toFixed(2)}ms, Results: ${results.length}`);
|
|
347
|
+
|
|
348
|
+
this.trackPerformance('searchTextDirect', searchTime, {
|
|
349
|
+
pdfId,
|
|
350
|
+
searchTerm,
|
|
351
|
+
startPage,
|
|
352
|
+
endPage,
|
|
353
|
+
resultCount: results.length
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
return results;
|
|
357
|
+
|
|
358
|
+
} catch (error) {
|
|
359
|
+
const endTime = performance.now();
|
|
360
|
+
const searchTime = endTime - startTime;
|
|
361
|
+
|
|
362
|
+
console.error(`📱 PDFJSI: Error searching text in ${searchTime.toFixed(2)}ms:`, error);
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Get performance metrics via JSI
|
|
369
|
+
* @param {string} pdfId - PDF identifier
|
|
370
|
+
* @returns {Promise<Object>} Performance metrics
|
|
371
|
+
*/
|
|
372
|
+
async getPerformanceMetrics(pdfId) {
|
|
373
|
+
if (!this.isJSIAvailable) {
|
|
374
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
console.log(`📱 PDFJSI: Getting performance metrics for PDF ${pdfId}`);
|
|
379
|
+
|
|
380
|
+
let metrics;
|
|
381
|
+
if (Platform.OS === 'android') {
|
|
382
|
+
metrics = await PDFJSIManagerNative.getPerformanceMetrics(pdfId);
|
|
383
|
+
} else if (Platform.OS === 'ios') {
|
|
384
|
+
metrics = await RNPDFPdfViewManager.getPerformanceMetricsDirect(pdfId);
|
|
385
|
+
} else {
|
|
386
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
console.log(`📱 PDFJSI: Performance metrics retrieved:`, metrics);
|
|
390
|
+
|
|
391
|
+
return metrics;
|
|
392
|
+
|
|
393
|
+
} catch (error) {
|
|
394
|
+
console.error(`📱 PDFJSI: Error getting performance metrics:`, error);
|
|
395
|
+
throw error;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Set render quality via JSI
|
|
401
|
+
* @param {string} pdfId - PDF identifier
|
|
402
|
+
* @param {number} quality - Render quality (1-3)
|
|
403
|
+
* @returns {Promise<boolean>} Success status
|
|
404
|
+
*/
|
|
405
|
+
async setRenderQuality(pdfId, quality) {
|
|
406
|
+
if (!this.isJSIAvailable) {
|
|
407
|
+
throw new Error('JSI not available - falling back to bridge mode');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (quality < 1 || quality > 3) {
|
|
411
|
+
throw new Error('Render quality must be between 1 and 3');
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
console.log(`📱 PDFJSI: Setting render quality to ${quality} for PDF ${pdfId}`);
|
|
416
|
+
|
|
417
|
+
let success;
|
|
418
|
+
if (Platform.OS === 'android') {
|
|
419
|
+
success = await PDFJSIManagerNative.setRenderQuality(pdfId, quality);
|
|
420
|
+
} else if (Platform.OS === 'ios') {
|
|
421
|
+
success = await RNPDFPdfViewManager.setRenderQuality(pdfId, quality);
|
|
422
|
+
} else {
|
|
423
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
console.log(`📱 PDFJSI: Render quality set, Success: ${success}`);
|
|
427
|
+
|
|
428
|
+
return success;
|
|
429
|
+
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.error(`📱 PDFJSI: Error setting render quality:`, error);
|
|
432
|
+
throw error;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Get JSI performance statistics
|
|
438
|
+
* @returns {Promise<Object>} JSI stats
|
|
439
|
+
*/
|
|
440
|
+
async getJSIStats() {
|
|
441
|
+
try {
|
|
442
|
+
console.log(`📱 PDFJSI: Getting JSI stats`);
|
|
443
|
+
|
|
444
|
+
let stats;
|
|
445
|
+
if (Platform.OS === 'android') {
|
|
446
|
+
stats = await EnhancedPdfJSIBridge.getJSIStats();
|
|
447
|
+
} else if (Platform.OS === 'ios') {
|
|
448
|
+
stats = await RNPDFPdfViewManager.getJSIStats();
|
|
449
|
+
} else {
|
|
450
|
+
throw new Error(`Platform ${Platform.OS} not supported`);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
console.log(`📱 PDFJSI: JSI stats retrieved:`, stats);
|
|
454
|
+
|
|
455
|
+
return stats;
|
|
456
|
+
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.error(`📱 PDFJSI: Error getting JSI stats:`, error);
|
|
459
|
+
throw error;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Track performance metrics
|
|
465
|
+
* @private
|
|
466
|
+
*/
|
|
467
|
+
trackPerformance(operation, duration, metadata = {}) {
|
|
468
|
+
const key = `${operation}_${Date.now()}`;
|
|
469
|
+
this.performanceMetrics.set(key, {
|
|
470
|
+
operation,
|
|
471
|
+
duration,
|
|
472
|
+
timestamp: Date.now(),
|
|
473
|
+
metadata
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// Keep only last 100 performance entries
|
|
477
|
+
if (this.performanceMetrics.size > 100) {
|
|
478
|
+
const firstKey = this.performanceMetrics.keys().next().value;
|
|
479
|
+
this.performanceMetrics.delete(firstKey);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Get all performance metrics
|
|
485
|
+
* @returns {Array} Performance metrics array
|
|
486
|
+
*/
|
|
487
|
+
getPerformanceHistory() {
|
|
488
|
+
return Array.from(this.performanceMetrics.values());
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Clear performance history
|
|
493
|
+
*/
|
|
494
|
+
clearPerformanceHistory() {
|
|
495
|
+
this.performanceMetrics.clear();
|
|
496
|
+
console.log('📱 PDFJSI: Performance history cleared');
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Create singleton instance
|
|
501
|
+
const pdfJSIManager = new PDFJSIManager();
|
|
502
|
+
|
|
503
|
+
export default pdfJSIManager;
|
|
504
|
+
|
|
505
|
+
// Export individual methods for convenience
|
|
506
|
+
export const {
|
|
507
|
+
renderPageDirect,
|
|
508
|
+
getPageMetrics,
|
|
509
|
+
preloadPagesDirect,
|
|
510
|
+
getCacheMetrics,
|
|
511
|
+
clearCacheDirect,
|
|
512
|
+
optimizeMemory,
|
|
513
|
+
searchTextDirect,
|
|
514
|
+
getPerformanceMetrics,
|
|
515
|
+
setRenderQuality,
|
|
516
|
+
getJSIStats,
|
|
517
|
+
getPerformanceHistory,
|
|
518
|
+
clearPerformanceHistory
|
|
519
|
+
} = pdfJSIManager;
|