react-native-pdf-jsi 2.1.0 → 2.2.0
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/README.md +652 -157
- package/android/build.gradle +4 -3
- package/android/src/main/cpp/CMakeLists.txt +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Starting November 1, 2025, Google Play will require apps to support 16KB page si
|
|
|
35
35
|
- ✅ **Google Play Approved** - Meets all current and future requirements
|
|
36
36
|
- ✅ **Drop-in Replacement** - Easy migration from existing libraries
|
|
37
37
|
|
|
38
|
-
## 🎉 Version 2.
|
|
38
|
+
## 🎉 Version 2.1.0 - Enhanced 16KB Compliance & Documentation!
|
|
39
39
|
|
|
40
40
|
**We've completely rewritten the core architecture with revolutionary performance improvements!**
|
|
41
41
|
|
|
@@ -148,17 +148,25 @@ yarn add react-native-pdf-jsi react-native-blob-util
|
|
|
148
148
|
## 🚀 **Quick Start**
|
|
149
149
|
|
|
150
150
|
```jsx
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
// Import the Pdf component from react-native-pdf-jsi
|
|
152
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
153
|
+
const Pdf = PdfModule.default;
|
|
154
|
+
|
|
155
|
+
// Use the component with the same API as react-native-pdf
|
|
156
|
+
<Pdf
|
|
157
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
158
|
+
style={{ flex: 1 }}
|
|
159
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
160
|
+
console.log(`PDF loaded: ${numberOfPages} pages`);
|
|
161
|
+
}}
|
|
162
|
+
onPageChanged={(page, numberOfPages) => {
|
|
163
|
+
console.log(`Current page: ${page} of ${numberOfPages}`);
|
|
164
|
+
}}
|
|
165
|
+
trustAllCerts={false}
|
|
166
|
+
/>
|
|
159
167
|
```
|
|
160
168
|
|
|
161
|
-
**
|
|
169
|
+
**Drop-in replacement for react-native-pdf with enhanced performance and Google Play compliance.**
|
|
162
170
|
|
|
163
171
|
Then follow the instructions for your platform to link react-native-pdf-jsi into your project:
|
|
164
172
|
|
|
@@ -275,127 +283,285 @@ protected List<ReactPackage> getPackages() {
|
|
|
275
283
|
|
|
276
284
|
### Basic Usage
|
|
277
285
|
|
|
278
|
-
```
|
|
279
|
-
import React from 'react';
|
|
280
|
-
import { StyleSheet, Dimensions, View } from 'react-native';
|
|
281
|
-
import Pdf from 'react-native-pdf-enhanced';
|
|
286
|
+
```jsx
|
|
287
|
+
import React, { useState } from 'react';
|
|
288
|
+
import { StyleSheet, Dimensions, View, Modal, TouchableOpacity, Text } from 'react-native';
|
|
282
289
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
//const source = require('./test.pdf'); // ios only
|
|
287
|
-
//const source = {uri:'bundle-assets://test.pdf' };
|
|
288
|
-
//const source = {uri:'file:///sdcard/test.pdf'};
|
|
289
|
-
//const source = {uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."};
|
|
290
|
-
//const source = {uri:"content://com.example.blobs/xxxxxxxx-...?offset=0&size=xxx"};
|
|
291
|
-
//const source = {uri:"blob:xxxxxxxx-...?offset=0&size=xxx"};
|
|
290
|
+
// Import the Pdf component from react-native-pdf-jsi
|
|
291
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
292
|
+
const Pdf = PdfModule.default;
|
|
292
293
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
</
|
|
311
|
-
|
|
312
|
-
|
|
294
|
+
export default function PDFExample() {
|
|
295
|
+
const [visible, setVisible] = useState(false);
|
|
296
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
297
|
+
const [totalPages, setTotalPages] = useState(0);
|
|
298
|
+
|
|
299
|
+
const source = {
|
|
300
|
+
uri: 'http://samples.leanpub.com/thereactnativebook-sample.pdf',
|
|
301
|
+
cache: true
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<View style={styles.container}>
|
|
306
|
+
<TouchableOpacity
|
|
307
|
+
style={styles.button}
|
|
308
|
+
onPress={() => setVisible(true)}
|
|
309
|
+
>
|
|
310
|
+
<Text style={styles.buttonText}>Open PDF</Text>
|
|
311
|
+
</TouchableOpacity>
|
|
312
|
+
|
|
313
|
+
<Modal
|
|
314
|
+
visible={visible}
|
|
315
|
+
animationType="slide"
|
|
316
|
+
onRequestClose={() => setVisible(false)}
|
|
317
|
+
>
|
|
318
|
+
<View style={styles.modalContainer}>
|
|
319
|
+
<View style={styles.header}>
|
|
320
|
+
<Text style={styles.pageInfo}>
|
|
321
|
+
Page {currentPage} of {totalPages}
|
|
322
|
+
</Text>
|
|
323
|
+
<TouchableOpacity
|
|
324
|
+
style={styles.closeButton}
|
|
325
|
+
onPress={() => setVisible(false)}
|
|
326
|
+
>
|
|
327
|
+
<Text style={styles.closeButtonText}>Close</Text>
|
|
328
|
+
</TouchableOpacity>
|
|
329
|
+
</View>
|
|
330
|
+
|
|
331
|
+
<Pdf
|
|
332
|
+
source={source}
|
|
333
|
+
style={styles.pdf}
|
|
334
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
335
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
336
|
+
setTotalPages(numberOfPages);
|
|
337
|
+
}}
|
|
338
|
+
onPageChanged={(page, numberOfPages) => {
|
|
339
|
+
console.log(`📄 Current page: ${page}`);
|
|
340
|
+
setCurrentPage(page);
|
|
341
|
+
}}
|
|
342
|
+
onError={(error) => {
|
|
343
|
+
console.error('📄 PDF Error:', error);
|
|
344
|
+
}}
|
|
345
|
+
trustAllCerts={false}
|
|
346
|
+
/>
|
|
347
|
+
</View>
|
|
348
|
+
</Modal>
|
|
349
|
+
</View>
|
|
350
|
+
);
|
|
313
351
|
}
|
|
314
352
|
|
|
315
353
|
const styles = StyleSheet.create({
|
|
316
354
|
container: {
|
|
317
355
|
flex: 1,
|
|
318
|
-
justifyContent: '
|
|
356
|
+
justifyContent: 'center',
|
|
357
|
+
alignItems: 'center',
|
|
358
|
+
padding: 20,
|
|
359
|
+
},
|
|
360
|
+
button: {
|
|
361
|
+
backgroundColor: '#007AFF',
|
|
362
|
+
paddingHorizontal: 20,
|
|
363
|
+
paddingVertical: 10,
|
|
364
|
+
borderRadius: 8,
|
|
365
|
+
},
|
|
366
|
+
buttonText: {
|
|
367
|
+
color: 'white',
|
|
368
|
+
fontSize: 16,
|
|
369
|
+
fontWeight: 'bold',
|
|
370
|
+
},
|
|
371
|
+
modalContainer: {
|
|
372
|
+
flex: 1,
|
|
373
|
+
backgroundColor: '#fff',
|
|
374
|
+
},
|
|
375
|
+
header: {
|
|
376
|
+
flexDirection: 'row',
|
|
377
|
+
justifyContent: 'space-between',
|
|
319
378
|
alignItems: 'center',
|
|
320
|
-
|
|
379
|
+
padding: 15,
|
|
380
|
+
backgroundColor: '#f5f5f5',
|
|
381
|
+
borderBottomWidth: 1,
|
|
382
|
+
borderBottomColor: '#ddd',
|
|
383
|
+
},
|
|
384
|
+
pageInfo: {
|
|
385
|
+
fontSize: 16,
|
|
386
|
+
fontWeight: 'bold',
|
|
387
|
+
},
|
|
388
|
+
closeButton: {
|
|
389
|
+
backgroundColor: '#FF3B30',
|
|
390
|
+
paddingHorizontal: 15,
|
|
391
|
+
paddingVertical: 8,
|
|
392
|
+
borderRadius: 6,
|
|
393
|
+
},
|
|
394
|
+
closeButtonText: {
|
|
395
|
+
color: 'white',
|
|
396
|
+
fontSize: 14,
|
|
397
|
+
fontWeight: 'bold',
|
|
321
398
|
},
|
|
322
399
|
pdf: {
|
|
323
|
-
flex:1,
|
|
324
|
-
width:Dimensions.get('window').width,
|
|
325
|
-
height:Dimensions.get('window').height,
|
|
400
|
+
flex: 1,
|
|
401
|
+
width: Dimensions.get('window').width,
|
|
402
|
+
height: Dimensions.get('window').height - 100,
|
|
326
403
|
}
|
|
327
404
|
});
|
|
328
405
|
```
|
|
329
406
|
|
|
330
407
|
### 🚀 JSI Enhanced Usage
|
|
331
408
|
|
|
332
|
-
####
|
|
333
|
-
```
|
|
334
|
-
import React from 'react';
|
|
335
|
-
import { View } from 'react-native';
|
|
336
|
-
import { EnhancedPdfView } from 'react-native-pdf-enhanced';
|
|
409
|
+
#### Real-World JSI Integration Pattern
|
|
410
|
+
```jsx
|
|
411
|
+
import React, { useState, useEffect } from 'react';
|
|
412
|
+
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
337
413
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
414
|
+
// Import JSI modules with proper error handling
|
|
415
|
+
let PDFJSI = null;
|
|
416
|
+
let usePDFJSI = null;
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
// Import JSI functionality with dynamic imports for release mode compatibility
|
|
420
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
421
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
422
|
+
|
|
423
|
+
PDFJSI = PDFJSIModule.default;
|
|
424
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
425
|
+
|
|
426
|
+
console.log(`🔍 PDFJSI found: ${PDFJSI ? '✅' : '❌'} (type: ${typeof PDFJSI})`);
|
|
427
|
+
console.log(`🔍 usePDFJSI found: ${usePDFJSI ? '✅' : '❌'} (type: ${typeof usePDFJSI})`);
|
|
428
|
+
|
|
429
|
+
} catch (error) {
|
|
430
|
+
console.log('📱 JSI: PDFJSI not available, using fallback - Error:', error.message);
|
|
350
431
|
}
|
|
351
|
-
```
|
|
352
432
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
433
|
+
// Create fallback functions for release builds
|
|
434
|
+
if (!PDFJSI || !usePDFJSI) {
|
|
435
|
+
console.log('🛡️ Creating JSI fallback functions for stability');
|
|
436
|
+
|
|
437
|
+
PDFJSI = {
|
|
438
|
+
checkJSIAvailability: async () => false,
|
|
439
|
+
getJSIStats: async () => ({ jsiEnabled: false }),
|
|
440
|
+
// ... other fallback methods
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
usePDFJSI = (options) => ({
|
|
444
|
+
isJSIAvailable: false,
|
|
445
|
+
isInitialized: true,
|
|
446
|
+
renderPage: () => Promise.resolve({ success: false, error: 'JSI not available' }),
|
|
447
|
+
// ... other fallback methods
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export default function EnhancedPDFExample() {
|
|
452
|
+
const [isJSIAvailable, setIsJSIAvailable] = useState(false);
|
|
453
|
+
const [jsiStats, setJsiStats] = useState(null);
|
|
454
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
455
|
+
|
|
456
|
+
// 🚀 JSI Hook Integration with Fallback
|
|
457
|
+
const jsiHookResult = usePDFJSI({
|
|
367
458
|
autoInitialize: true,
|
|
368
|
-
enablePerformanceTracking: true
|
|
459
|
+
enablePerformanceTracking: true,
|
|
460
|
+
enableCaching: true,
|
|
461
|
+
maxCacheSize: 200,
|
|
369
462
|
});
|
|
370
463
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const result = await renderPage('pdf_123', 1, 2.0, 'base64data');
|
|
375
|
-
console.log('🚀 JSI Render result:', result);
|
|
376
|
-
|
|
377
|
-
// Preload pages for faster access
|
|
378
|
-
const preloadSuccess = await preloadPages('pdf_123', 1, 5);
|
|
379
|
-
console.log('🚀 Preload success:', preloadSuccess);
|
|
464
|
+
useEffect(() => {
|
|
465
|
+
initializeJSI();
|
|
466
|
+
}, []);
|
|
380
467
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
468
|
+
const initializeJSI = async () => {
|
|
469
|
+
try {
|
|
470
|
+
if (PDFJSI && typeof PDFJSI.checkJSIAvailability === 'function') {
|
|
471
|
+
const isAvailable = await PDFJSI.checkJSIAvailability();
|
|
472
|
+
setIsJSIAvailable(isAvailable);
|
|
473
|
+
|
|
474
|
+
if (isAvailable) {
|
|
475
|
+
const stats = await PDFJSI.getJSIStats();
|
|
476
|
+
setJsiStats(stats);
|
|
477
|
+
console.log('🚀 JSI Stats:', stats);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.log('📱 JSI initialization failed:', error);
|
|
482
|
+
}
|
|
483
|
+
};
|
|
384
484
|
|
|
485
|
+
const handleJSIOperations = async () => {
|
|
486
|
+
try {
|
|
487
|
+
if (jsiHookResult.isJSIAvailable) {
|
|
488
|
+
// High-performance page rendering
|
|
489
|
+
const result = await jsiHookResult.renderPage('pdf_123', 1, 2.0, 'base64data');
|
|
490
|
+
console.log('🚀 JSI Render result:', result);
|
|
491
|
+
|
|
492
|
+
// Preload pages for faster access
|
|
493
|
+
const preloadSuccess = await jsiHookResult.preloadPages('pdf_123', 1, 5);
|
|
494
|
+
console.log('🚀 Preload success:', preloadSuccess);
|
|
495
|
+
|
|
496
|
+
// Get performance metrics
|
|
497
|
+
const metrics = await jsiHookResult.getPerformanceMetrics('pdf_123');
|
|
498
|
+
console.log('🚀 Performance metrics:', metrics);
|
|
499
|
+
} else {
|
|
500
|
+
console.log('📱 JSI not available, using standard methods');
|
|
501
|
+
}
|
|
385
502
|
} catch (error) {
|
|
386
503
|
console.log('JSI operations failed:', error);
|
|
387
504
|
}
|
|
388
505
|
};
|
|
389
506
|
|
|
390
507
|
return (
|
|
391
|
-
<View style={
|
|
392
|
-
<
|
|
393
|
-
|
|
508
|
+
<View style={styles.container}>
|
|
509
|
+
<View style={styles.statusContainer}>
|
|
510
|
+
<Text style={styles.statusText}>
|
|
511
|
+
JSI Status: {isJSIAvailable ? '✅ Available' : '❌ Not Available'}
|
|
512
|
+
</Text>
|
|
513
|
+
{jsiStats && (
|
|
514
|
+
<Text style={styles.statsText}>
|
|
515
|
+
Performance Level: {jsiStats.performanceLevel}
|
|
516
|
+
</Text>
|
|
517
|
+
)}
|
|
518
|
+
</View>
|
|
519
|
+
|
|
520
|
+
<TouchableOpacity
|
|
521
|
+
style={styles.button}
|
|
394
522
|
onPress={handleJSIOperations}
|
|
395
|
-
|
|
523
|
+
>
|
|
524
|
+
<Text style={styles.buttonText}>
|
|
525
|
+
Test JSI Operations
|
|
526
|
+
</Text>
|
|
527
|
+
</TouchableOpacity>
|
|
396
528
|
</View>
|
|
397
529
|
);
|
|
398
530
|
}
|
|
531
|
+
|
|
532
|
+
const styles = StyleSheet.create({
|
|
533
|
+
container: {
|
|
534
|
+
flex: 1,
|
|
535
|
+
padding: 20,
|
|
536
|
+
justifyContent: 'center',
|
|
537
|
+
},
|
|
538
|
+
statusContainer: {
|
|
539
|
+
backgroundColor: '#f5f5f5',
|
|
540
|
+
padding: 15,
|
|
541
|
+
borderRadius: 8,
|
|
542
|
+
marginBottom: 20,
|
|
543
|
+
},
|
|
544
|
+
statusText: {
|
|
545
|
+
fontSize: 16,
|
|
546
|
+
fontWeight: 'bold',
|
|
547
|
+
marginBottom: 5,
|
|
548
|
+
},
|
|
549
|
+
statsText: {
|
|
550
|
+
fontSize: 14,
|
|
551
|
+
color: '#666',
|
|
552
|
+
},
|
|
553
|
+
button: {
|
|
554
|
+
backgroundColor: '#007AFF',
|
|
555
|
+
padding: 15,
|
|
556
|
+
borderRadius: 8,
|
|
557
|
+
alignItems: 'center',
|
|
558
|
+
},
|
|
559
|
+
buttonText: {
|
|
560
|
+
color: 'white',
|
|
561
|
+
fontSize: 16,
|
|
562
|
+
fontWeight: 'bold',
|
|
563
|
+
},
|
|
564
|
+
});
|
|
399
565
|
```
|
|
400
566
|
|
|
401
567
|
#### Advanced JSI Operations
|
|
@@ -466,6 +632,125 @@ export default function AdvancedJSIExample() {
|
|
|
466
632
|
}
|
|
467
633
|
```
|
|
468
634
|
|
|
635
|
+
## 🛡️ **ProGuard Configuration (Required for Production)**
|
|
636
|
+
|
|
637
|
+
**IMPORTANT**: For production builds, you MUST add ProGuard rules to prevent obfuscation of JSI classes. Without these rules, your app will crash in release mode.
|
|
638
|
+
|
|
639
|
+
### **Add to `android/app/proguard-rules.pro`:**
|
|
640
|
+
|
|
641
|
+
```proguard
|
|
642
|
+
# Add project specific ProGuard rules here.
|
|
643
|
+
# By default, the flags in this file are appended to flags specified
|
|
644
|
+
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
|
645
|
+
# You can edit the include path and order by changing the proguardFiles
|
|
646
|
+
# directive in build.gradle.
|
|
647
|
+
#
|
|
648
|
+
# For more details, see
|
|
649
|
+
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
650
|
+
|
|
651
|
+
# Add any project specific keep options here:
|
|
652
|
+
|
|
653
|
+
# 🚀 JSI Module ProGuard Rules - Prevent obfuscation of JSI classes
|
|
654
|
+
# react-native-pdf-jsi package classes
|
|
655
|
+
-keep class org.wonday.pdf.PDFJSIManager { *; }
|
|
656
|
+
-keep class org.wonday.pdf.PDFJSIModule { *; }
|
|
657
|
+
-keep class org.wonday.pdf.EnhancedPdfJSIBridge { *; }
|
|
658
|
+
-keep class org.wonday.pdf.RNPDFPackage { *; }
|
|
659
|
+
-keep class org.wonday.pdf.PdfManager { *; }
|
|
660
|
+
-keep class org.wonday.pdf.PDFNativeCacheManager { *; }
|
|
661
|
+
-keep class org.wonday.pdf.PdfView { *; }
|
|
662
|
+
-keep class org.wonday.pdf.events.TopChangeEvent { *; }
|
|
663
|
+
|
|
664
|
+
# Keep all JSI native methods
|
|
665
|
+
-keepclasseswithmembernames class * {
|
|
666
|
+
native <methods>;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
# Keep JSI bridge methods
|
|
670
|
+
-keepclassmembers class * {
|
|
671
|
+
@com.facebook.react.bridge.ReactMethod <methods>;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
# Keep React Native bridge classes
|
|
675
|
+
-keep class com.facebook.react.bridge.** { *; }
|
|
676
|
+
-keep class com.facebook.react.turbomodule.** { *; }
|
|
677
|
+
|
|
678
|
+
# Keep native library loading
|
|
679
|
+
-keep class com.facebook.soloader.** { *; }
|
|
680
|
+
|
|
681
|
+
# Keep JSI related classes
|
|
682
|
+
-keep class com.facebook.jni.** { *; }
|
|
683
|
+
|
|
684
|
+
# Prevent obfuscation of PDF JSI native methods
|
|
685
|
+
-keepclassmembers class org.wonday.pdf.PDFJSIManager {
|
|
686
|
+
native void nativeInitializeJSI(java.lang.Object);
|
|
687
|
+
native boolean nativeIsJSIAvailable();
|
|
688
|
+
native com.facebook.react.bridge.WritableMap nativeRenderPageDirect(java.lang.String, int, float, java.lang.String);
|
|
689
|
+
native com.facebook.react.bridge.WritableMap nativeGetPageMetrics(java.lang.String, int);
|
|
690
|
+
native boolean nativePreloadPagesDirect(java.lang.String, int, int);
|
|
691
|
+
native com.facebook.react.bridge.WritableMap nativeGetCacheMetrics(java.lang.String);
|
|
692
|
+
native boolean nativeClearCacheDirect(java.lang.String, java.lang.String);
|
|
693
|
+
native boolean nativeOptimizeMemory(java.lang.String);
|
|
694
|
+
native com.facebook.react.bridge.ReadableArray nativeSearchTextDirect(java.lang.String, java.lang.String, int, int);
|
|
695
|
+
native com.facebook.react.bridge.WritableMap nativeGetPerformanceMetrics(java.lang.String);
|
|
696
|
+
native boolean nativeSetRenderQuality(java.lang.String, int);
|
|
697
|
+
native void nativeCleanupJSI();
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
# Keep all PDF related classes
|
|
701
|
+
-keep class org.wonday.pdf.** { *; }
|
|
702
|
+
|
|
703
|
+
# Keep React Native modules
|
|
704
|
+
-keep class * extends com.facebook.react.bridge.ReactContextBaseJavaModule { *; }
|
|
705
|
+
-keep class * extends com.facebook.react.ReactPackage { *; }
|
|
706
|
+
|
|
707
|
+
# Keep native library names
|
|
708
|
+
-keepnames class * {
|
|
709
|
+
native <methods>;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
# Keep crypto-js classes (dependency of react-native-pdf-jsi)
|
|
713
|
+
-keep class com.google.crypto.** { *; }
|
|
714
|
+
-keep class javax.crypto.** { *; }
|
|
715
|
+
|
|
716
|
+
# Keep JSI specific classes and methods
|
|
717
|
+
-keepclassmembers class org.wonday.pdf.** {
|
|
718
|
+
public <methods>;
|
|
719
|
+
protected <methods>;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
# Keep all event classes
|
|
723
|
+
-keep class org.wonday.pdf.events.** { *; }
|
|
724
|
+
|
|
725
|
+
# Keep React Native JSI specific classes
|
|
726
|
+
-keep class com.facebook.jsi.** { *; }
|
|
727
|
+
-keep class com.facebook.hermes.** { *; }
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### **Why These Rules Are Essential:**
|
|
731
|
+
|
|
732
|
+
1. **JSI Class Protection**: Prevents ProGuard from obfuscating JSI-related classes
|
|
733
|
+
2. **Native Method Preservation**: Keeps native method signatures intact
|
|
734
|
+
3. **Bridge Method Safety**: Protects React Native bridge methods
|
|
735
|
+
4. **Event System**: Maintains event handling functionality
|
|
736
|
+
5. **Crypto Dependencies**: Preserves cryptographic functionality
|
|
737
|
+
|
|
738
|
+
### **Build Configuration:**
|
|
739
|
+
|
|
740
|
+
Make sure your `android/app/build.gradle` has ProGuard enabled:
|
|
741
|
+
|
|
742
|
+
```gradle
|
|
743
|
+
android {
|
|
744
|
+
buildTypes {
|
|
745
|
+
release {
|
|
746
|
+
minifyEnabled true
|
|
747
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
748
|
+
// ... other release config
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
469
754
|
## 🚨 Expo Support
|
|
470
755
|
|
|
471
756
|
This package is not available in the [Expo Go](https://expo.dev/client) app. Learn how you can use this package in [Custom Dev Clients](https://docs.expo.dev/development/getting-started/) via the out-of-tree [Expo Config Plugin](https://github.com/expo/config-plugins/tree/master/packages/react-native-pdf). Example: [`with-pdf`](https://github.com/expo/examples/tree/master/with-pdf).
|
|
@@ -526,27 +811,115 @@ react-native run-ios
|
|
|
526
811
|
|
|
527
812
|
**Q6. How do I enable JSI mode?**
|
|
528
813
|
A6: JSI mode is automatically enabled on Android. Check JSI availability with:
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
|
|
814
|
+
```jsx
|
|
815
|
+
// Import JSI modules
|
|
816
|
+
let PDFJSI = null;
|
|
817
|
+
try {
|
|
818
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
819
|
+
PDFJSI = PDFJSIModule.default;
|
|
820
|
+
} catch (error) {
|
|
821
|
+
console.log('JSI not available');
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Check availability
|
|
825
|
+
const isAvailable = await PDFJSI?.checkJSIAvailability();
|
|
826
|
+
console.log('JSI Available:', isAvailable);
|
|
532
827
|
```
|
|
533
828
|
|
|
534
829
|
**Q7. What if JSI is not available?**
|
|
535
|
-
A7: The package automatically falls back to standard bridge mode.
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
830
|
+
A7: The package automatically falls back to standard bridge mode. Always implement fallbacks:
|
|
831
|
+
```jsx
|
|
832
|
+
// Import with fallback
|
|
833
|
+
let PDFJSI = null;
|
|
834
|
+
let usePDFJSI = null;
|
|
835
|
+
|
|
836
|
+
try {
|
|
837
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
838
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
839
|
+
|
|
840
|
+
PDFJSI = PDFJSIModule.default;
|
|
841
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
842
|
+
} catch (error) {
|
|
843
|
+
console.log('JSI not available, using fallback');
|
|
543
844
|
}
|
|
845
|
+
|
|
846
|
+
// Use with fallback
|
|
847
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
848
|
+
autoInitialize: true,
|
|
849
|
+
enablePerformanceTracking: true,
|
|
850
|
+
}) : { isJSIAvailable: false, isInitialized: true };
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
**Q8. My app crashes in release mode with JSI errors**
|
|
854
|
+
A8: You need to add ProGuard rules. Add the complete ProGuard configuration from the documentation to your `android/app/proguard-rules.pro` file.
|
|
855
|
+
|
|
856
|
+
**Q9. How do I migrate from react-native-pdf?**
|
|
857
|
+
A9: Follow the migration steps in the documentation:
|
|
858
|
+
1. Update package: `npm install react-native-pdf-jsi`
|
|
859
|
+
2. Update imports: Use `require('react-native-pdf-jsi')`
|
|
860
|
+
3. Add ProGuard rules
|
|
861
|
+
4. Update component usage (same API)
|
|
862
|
+
5. Optionally add JSI integration
|
|
863
|
+
|
|
864
|
+
**Q10. The shimmer loader gets stuck and documents don't load**
|
|
865
|
+
A10: This usually means JSI initialization is failing. Ensure:
|
|
866
|
+
- ProGuard rules are properly configured
|
|
867
|
+
- JSI modules are imported correctly with error handling
|
|
868
|
+
- Fallback mechanisms are in place
|
|
869
|
+
- Check console logs for JSI availability status
|
|
870
|
+
|
|
871
|
+
**Q11. TypeError: constructor is not callable**
|
|
872
|
+
A11: This error occurs when the Pdf component is not imported correctly. Use:
|
|
873
|
+
```jsx
|
|
874
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
875
|
+
const Pdf = PdfModule.default;
|
|
876
|
+
// NOT: const Pdf = require('react-native-pdf-jsi');
|
|
544
877
|
```
|
|
545
878
|
</details>
|
|
546
879
|
|
|
547
880
|
## 📝 Changelog
|
|
548
881
|
|
|
549
|
-
### v2.0
|
|
882
|
+
### v2.1.0 (2025) - Latest ✅ ENHANCED 16KB COMPLIANCE & DOCUMENTATION
|
|
883
|
+
|
|
884
|
+
#### 🚀 **16KB Page Alignment Enhancements**
|
|
885
|
+
- **Dependency Updates**: Updated `io.legere:pdfiumandroid` from v1.0.24 to v1.0.32 for optimal 16KB support
|
|
886
|
+
- **Gson Update**: Updated `com.google.code.gson:gson` from v2.8.5 to v2.11.0 for compatibility
|
|
887
|
+
- **Build Configuration**: Updated `compileSdkVersion` and `targetSdkVersion` from 34 to 35 for Android 15+ compatibility
|
|
888
|
+
- **CMakeLists Enhancement**: Added missing executable linker flag `-Wl,-z,max-page-size=16384` for complete 16KB page alignment
|
|
889
|
+
- **Dependency Management**: Added exclusion for bundled PdfiumAndroid to prevent conflicts with specific version
|
|
890
|
+
|
|
891
|
+
#### 📚 **Documentation Overhaul**
|
|
892
|
+
- **README Rewrite**: Complete rewrite of README with real-world usage examples from production projects
|
|
893
|
+
- **Import Patterns**: Updated all examples to show correct import patterns using `require('react-native-pdf-jsi')`
|
|
894
|
+
- **Error Handling**: Added comprehensive error handling and fallback mechanisms in all examples
|
|
895
|
+
- **Modal Implementation**: Added complete modal-based PDF viewer example matching production usage
|
|
896
|
+
- **JSI Integration**: Updated JSI usage examples with proper initialization and error handling patterns
|
|
897
|
+
|
|
898
|
+
#### 🛡️ **Production Safety & ProGuard**
|
|
899
|
+
- **ProGuard Rules**: Added comprehensive ProGuard configuration documentation with complete rule set
|
|
900
|
+
- **Release Build Safety**: Added critical warnings about ProGuard rules preventing production crashes
|
|
901
|
+
- **JSI Class Protection**: Documented all necessary ProGuard rules for JSI class preservation
|
|
902
|
+
- **Native Method Safety**: Added rules for preserving native method signatures and React Native bridge methods
|
|
903
|
+
|
|
904
|
+
#### 📖 **Migration & FAQ Enhancement**
|
|
905
|
+
- **Step-by-Step Migration**: Complete migration guide from react-native-pdf with 5 clear steps
|
|
906
|
+
- **Common Issues**: Added solutions for shimmer loader stuck, constructor errors, and JSI initialization failures
|
|
907
|
+
- **Production Troubleshooting**: Added FAQ entries for release build crashes and ProGuard configuration
|
|
908
|
+
- **Error Solutions**: Documented solutions for "TypeError: constructor is not callable" and other common errors
|
|
909
|
+
|
|
910
|
+
#### ⚡ **Performance & Reliability**
|
|
911
|
+
- **JSI Fallback Patterns**: Enhanced JSI integration with robust fallback mechanisms for production stability
|
|
912
|
+
- **Error Handling**: Added comprehensive try-catch patterns for JSI module loading
|
|
913
|
+
- **Release Build Compatibility**: Ensured compatibility with both debug and release builds
|
|
914
|
+
- **Memory Management**: Enhanced memory optimization patterns for large PDF files
|
|
915
|
+
|
|
916
|
+
#### 📊 **Google Play Compliance**
|
|
917
|
+
- **16KB Verification**: Complete implementation of Google Play 16KB page size requirements
|
|
918
|
+
- **Android 15+ Ready**: Full compatibility with Android 15+ requirements
|
|
919
|
+
- **Future-Proof**: Ensures long-term compatibility with Google Play policy changes
|
|
920
|
+
- **Compliance Testing**: Added verification methods for 16KB page size support
|
|
921
|
+
|
|
922
|
+
### v2.0.1 (2025) - ✅ GOOGLE PLAY COMPLIANT
|
|
550
923
|
- 🚨 **Google Play 16KB Compliance**: Added full support for Google Play's 16KB page size requirement
|
|
551
924
|
- 🔧 **NDK r27+ Support**: Updated to NDK version 27.0.12077973 for Android 15+ compatibility
|
|
552
925
|
- 📱 **16KB Page Size Check**: Added `check16KBSupport()` method to verify compliance
|
|
@@ -602,67 +975,189 @@ if (stats.jsiEnabled) {
|
|
|
602
975
|
|
|
603
976
|
## 🔄 Migration from react-native-pdf
|
|
604
977
|
|
|
605
|
-
|
|
606
|
-
// Old import
|
|
607
|
-
import Pdf from 'react-native-pdf';
|
|
978
|
+
### **Step 1: Update Package**
|
|
608
979
|
|
|
609
|
-
|
|
610
|
-
|
|
980
|
+
```bash
|
|
981
|
+
# Remove old package
|
|
982
|
+
npm uninstall react-native-pdf
|
|
611
983
|
|
|
612
|
-
|
|
613
|
-
|
|
984
|
+
# Install new package
|
|
985
|
+
npm install react-native-pdf-jsi react-native-blob-util
|
|
614
986
|
```
|
|
615
987
|
|
|
616
|
-
|
|
988
|
+
### **Step 2: Update Imports**
|
|
617
989
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
import Pdf from 'react-native-pdf-enhanced';
|
|
990
|
+
```jsx
|
|
991
|
+
// ❌ Old import
|
|
992
|
+
import Pdf from 'react-native-pdf';
|
|
622
993
|
|
|
623
|
-
//
|
|
624
|
-
|
|
994
|
+
// ✅ New import
|
|
995
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
996
|
+
const Pdf = PdfModule.default;
|
|
997
|
+
```
|
|
625
998
|
|
|
626
|
-
|
|
627
|
-
import { usePDFJSI } from 'react-native-pdf-enhanced';
|
|
999
|
+
### **Step 3: Add ProGuard Rules**
|
|
628
1000
|
|
|
629
|
-
|
|
630
|
-
|
|
1001
|
+
Add the ProGuard rules from the section above to your `android/app/proguard-rules.pro`.
|
|
1002
|
+
|
|
1003
|
+
### **Step 4: Update Component Usage**
|
|
1004
|
+
|
|
1005
|
+
```jsx
|
|
1006
|
+
// ❌ Old usage
|
|
1007
|
+
<Pdf
|
|
1008
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1009
|
+
/>
|
|
1010
|
+
|
|
1011
|
+
// ✅ New usage (same API, enhanced performance)
|
|
1012
|
+
<Pdf
|
|
1013
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1014
|
+
style={{ flex: 1 }}
|
|
1015
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
1016
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
1017
|
+
}}
|
|
1018
|
+
onPageChanged={(page, numberOfPages) => {
|
|
1019
|
+
console.log(`📄 Current page: ${page}`);
|
|
1020
|
+
}}
|
|
1021
|
+
trustAllCerts={false}
|
|
1022
|
+
/>
|
|
631
1023
|
```
|
|
632
1024
|
|
|
633
|
-
###
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
renderPageDirect,
|
|
637
|
-
getPageMetrics,
|
|
638
|
-
preloadPagesDirect,
|
|
639
|
-
getCacheMetrics,
|
|
640
|
-
clearCacheDirect,
|
|
641
|
-
optimizeMemory,
|
|
642
|
-
searchTextDirect,
|
|
643
|
-
getPerformanceMetrics,
|
|
644
|
-
setRenderQuality,
|
|
645
|
-
getJSIStats,
|
|
646
|
-
getPerformanceHistory,
|
|
647
|
-
clearPerformanceHistory
|
|
648
|
-
} from 'react-native-pdf-enhanced';
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
### Utility Functions
|
|
652
|
-
```js
|
|
653
|
-
import { EnhancedPdfUtils } from 'react-native-pdf-enhanced';
|
|
1025
|
+
### **Step 5: Add JSI Integration (Optional)**
|
|
1026
|
+
|
|
1027
|
+
For enhanced performance, add JSI integration:
|
|
654
1028
|
|
|
655
|
-
|
|
656
|
-
|
|
1029
|
+
```jsx
|
|
1030
|
+
// Import JSI modules with error handling
|
|
1031
|
+
let PDFJSI = null;
|
|
1032
|
+
let usePDFJSI = null;
|
|
1033
|
+
|
|
1034
|
+
try {
|
|
1035
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
1036
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
1037
|
+
|
|
1038
|
+
PDFJSI = PDFJSIModule.default;
|
|
1039
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
console.log('JSI not available, using fallback');
|
|
1042
|
+
}
|
|
657
1043
|
|
|
658
|
-
//
|
|
659
|
-
const
|
|
1044
|
+
// Use JSI hook
|
|
1045
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
1046
|
+
autoInitialize: true,
|
|
1047
|
+
enablePerformanceTracking: true,
|
|
1048
|
+
}) : { isJSIAvailable: false };
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
### **Migration Benefits:**
|
|
660
1052
|
|
|
661
|
-
|
|
662
|
-
|
|
1053
|
+
- ✅ **Same API**: No code changes required for basic usage
|
|
1054
|
+
- ✅ **Enhanced Performance**: Up to 80x faster on Android
|
|
1055
|
+
- ✅ **Google Play Compliant**: 16KB page size support
|
|
1056
|
+
- ✅ **Future-Proof**: Built with latest NDK and modern toolchain
|
|
1057
|
+
- ✅ **Better Caching**: Advanced persistent cache system
|
|
663
1058
|
|
|
664
|
-
|
|
665
|
-
|
|
1059
|
+
## 📦 Available Exports
|
|
1060
|
+
|
|
1061
|
+
### **Core Components**
|
|
1062
|
+
```jsx
|
|
1063
|
+
// Standard PDF component (enhanced with JSI)
|
|
1064
|
+
const PdfModule = require('react-native-pdf-jsi');
|
|
1065
|
+
const Pdf = PdfModule.default;
|
|
1066
|
+
|
|
1067
|
+
// Usage
|
|
1068
|
+
<Pdf
|
|
1069
|
+
source={{ uri: 'https://example.com/document.pdf' }}
|
|
1070
|
+
style={{ flex: 1 }}
|
|
1071
|
+
onLoadComplete={(numberOfPages, filePath) => {
|
|
1072
|
+
console.log(`📄 PDF loaded: ${numberOfPages} pages`);
|
|
1073
|
+
}}
|
|
1074
|
+
trustAllCerts={false}
|
|
1075
|
+
/>
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
### **JSI Modules (Advanced Usage)**
|
|
1079
|
+
```jsx
|
|
1080
|
+
// Import JSI functionality with error handling
|
|
1081
|
+
let PDFJSI = null;
|
|
1082
|
+
let usePDFJSI = null;
|
|
1083
|
+
|
|
1084
|
+
try {
|
|
1085
|
+
const PDFJSIModule = require('react-native-pdf-jsi/src/PDFJSI');
|
|
1086
|
+
const usePDFJSIModule = require('react-native-pdf-jsi/src/hooks/usePDFJSI');
|
|
1087
|
+
|
|
1088
|
+
PDFJSI = PDFJSIModule.default;
|
|
1089
|
+
usePDFJSI = usePDFJSIModule.default;
|
|
1090
|
+
} catch (error) {
|
|
1091
|
+
console.log('JSI not available, using fallback');
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// Use JSI hook for enhanced operations
|
|
1095
|
+
const jsiHookResult = usePDFJSI ? usePDFJSI({
|
|
1096
|
+
autoInitialize: true,
|
|
1097
|
+
enablePerformanceTracking: true,
|
|
1098
|
+
enableCaching: true,
|
|
1099
|
+
maxCacheSize: 200,
|
|
1100
|
+
}) : {
|
|
1101
|
+
isJSIAvailable: false,
|
|
1102
|
+
isInitialized: true
|
|
1103
|
+
};
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
### **JSI Methods Available**
|
|
1107
|
+
```jsx
|
|
1108
|
+
// When JSI is available, these methods provide enhanced performance:
|
|
1109
|
+
const methods = {
|
|
1110
|
+
// High-performance page rendering
|
|
1111
|
+
renderPage: (pdfId, pageNumber, scale, base64Data) => Promise,
|
|
1112
|
+
|
|
1113
|
+
// Get page metrics
|
|
1114
|
+
getPageMetrics: (pdfId, pageNumber) => Promise,
|
|
1115
|
+
|
|
1116
|
+
// Preload pages for faster access
|
|
1117
|
+
preloadPages: (pdfId, startPage, endPage) => Promise,
|
|
1118
|
+
|
|
1119
|
+
// Cache management
|
|
1120
|
+
getCacheMetrics: (pdfId) => Promise,
|
|
1121
|
+
clearCache: (pdfId, cacheType) => Promise,
|
|
1122
|
+
|
|
1123
|
+
// Memory optimization
|
|
1124
|
+
optimizeMemory: (pdfId) => Promise,
|
|
1125
|
+
|
|
1126
|
+
// Text search
|
|
1127
|
+
searchText: (pdfId, query, startPage, endPage) => Promise,
|
|
1128
|
+
|
|
1129
|
+
// Performance monitoring
|
|
1130
|
+
getPerformanceMetrics: (pdfId) => Promise,
|
|
1131
|
+
|
|
1132
|
+
// Render quality control
|
|
1133
|
+
setRenderQuality: (pdfId, quality) => Promise,
|
|
1134
|
+
|
|
1135
|
+
// JSI availability check
|
|
1136
|
+
checkJSIAvailability: () => Promise,
|
|
1137
|
+
|
|
1138
|
+
// Get JSI statistics
|
|
1139
|
+
getJSIStats: () => Promise
|
|
1140
|
+
};
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### **Error Handling Pattern**
|
|
1144
|
+
```jsx
|
|
1145
|
+
// Always wrap JSI operations in try-catch with fallbacks
|
|
1146
|
+
const handleJSIOperation = async () => {
|
|
1147
|
+
try {
|
|
1148
|
+
if (PDFJSI && jsiHookResult.isJSIAvailable) {
|
|
1149
|
+
// Use JSI for enhanced performance
|
|
1150
|
+
const result = await PDFJSI.renderPageDirect('pdf_123', 1, 2.0, 'base64data');
|
|
1151
|
+
console.log('🚀 JSI operation successful:', result);
|
|
1152
|
+
} else {
|
|
1153
|
+
// Fallback to standard methods
|
|
1154
|
+
console.log('📱 Using standard PDF methods');
|
|
1155
|
+
}
|
|
1156
|
+
} catch (error) {
|
|
1157
|
+
console.log('❌ Operation failed:', error);
|
|
1158
|
+
// Handle error gracefully
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
666
1161
|
```
|
|
667
1162
|
|
|
668
1163
|
### Check Google Play 16KB Compliance
|
|
@@ -937,7 +1432,7 @@ For issues and questions:
|
|
|
937
1432
|
|
|
938
1433
|
*Transform your PDF viewing experience with enterprise-grade performance and reliability.*
|
|
939
1434
|
|
|
940
|
-
**
|
|
1435
|
+
**v2.1.0 - Enhanced 16KB Compliance & Documentation**
|
|
941
1436
|
**Copyright (c) 2025-present, Punith M (punithm300@gmail.com). Enhanced PDF JSI Integration. All rights reserved.**
|
|
942
1437
|
|
|
943
1438
|
*Original work Copyright (c) 2017-present, Wonday (@wonday.org). All rights reserved.*
|
package/android/build.gradle
CHANGED
|
@@ -93,14 +93,15 @@ android {
|
|
|
93
93
|
if (agpVersion.tokenize('.')[0].toInteger() >= 7) {
|
|
94
94
|
namespace "org.wonday.pdf"
|
|
95
95
|
}
|
|
96
|
-
compileSdkVersion safeExtGet('compileSdkVersion',
|
|
96
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
97
97
|
|
|
98
98
|
// 🚀 NDK Configuration for 16KB Page Size Support
|
|
99
|
-
|
|
99
|
+
// Use NDK r28 which provides proper 16KB page alignment toolchain
|
|
100
|
+
ndkVersion "28.0.12674087"
|
|
100
101
|
|
|
101
102
|
defaultConfig {
|
|
102
103
|
minSdkVersion safeExtGet('minSdkVersion', 21)
|
|
103
|
-
targetSdkVersion safeExtGet('targetSdkVersion',
|
|
104
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
104
105
|
buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
|
|
105
106
|
|
|
106
107
|
// 🚀 JSI Configuration with 16KB Page Support
|
|
@@ -69,6 +69,10 @@ target_compile_options(
|
|
|
69
69
|
-fvisibility=hidden
|
|
70
70
|
)
|
|
71
71
|
|
|
72
|
+
# 16KB page size alignment for shared objects
|
|
73
|
+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
|
74
|
+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
|
|
75
|
+
|
|
72
76
|
# Set output directory
|
|
73
77
|
set_target_properties(
|
|
74
78
|
pdfjsi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pdf-jsi",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"summary": "High-performance React Native PDF viewer with JSI acceleration - up to 80x faster than traditional bridge",
|
|
5
5
|
"description": "🚀 Ultra-fast React Native PDF viewer with JSI (JavaScript Interface) integration for maximum performance. Features lazy loading, smart caching, progressive loading, and zero-bridge overhead operations. Perfect for large PDF files with 30-day persistent cache and advanced memory optimization. Google Play 16KB page size compliant for Android 15+. Supports iOS, Android, and Windows platforms.",
|
|
6
6
|
"main": "index.js",
|