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
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;