react-native-pdf-jsi 3.3.0 → 3.4.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 +106 -7
- package/android/src/main/java/org/wonday/pdf/FileManager.java +2 -0
- package/android/src/main/java/org/wonday/pdf/MemoryMappedCache.java +1 -1
- package/android/src/main/java/org/wonday/pdf/PDFExporter.java +0 -54
- package/android/src/main/java/org/wonday/pdf/PdfView.java +12 -2
- package/android/src/main/java/org/wonday/pdf/RNPDFJSIPackage.java +50 -0
- package/android/src/main/java/org/wonday/pdf/RNPDFPackage.java +0 -1
- package/fabric/RNPDFPdfNativeComponent.js +4 -0
- package/index.js +148 -23
- package/ios/RNPDFPdf/RNPDFPdfView.h +0 -2
- package/ios/RNPDFPdf/RNPDFPdfView.mm +2 -27
- package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +0 -2
- package/package.json +8 -5
- package/src/PDFJSI.js +29 -4
- package/src/components/AnalyticsPanel.jsx +22 -9
- package/src/managers/AnalyticsManager.js +1 -5
- package/src/managers/BookmarkManager.js +2 -10
- package/src/managers/CacheManager.js +14 -1
- package/src/managers/ExportManager.js +5 -20
- package/src/utils/ErrorHandler.js +0 -11
- package/src/utils/PDFTextExtractor.js +82 -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 +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/src/main/java/org/wonday/pdf/LicenseVerifier.java +0 -311
|
@@ -42,9 +42,7 @@ UIView
|
|
|
42
42
|
@property(nonatomic) BOOL showsHorizontalScrollIndicator;
|
|
43
43
|
@property(nonatomic) BOOL scrollEnabled;
|
|
44
44
|
@property(nonatomic) BOOL enablePaging;
|
|
45
|
-
@property(nonatomic) float scrollVelocity;
|
|
46
45
|
@property(nonatomic) BOOL enableMomentum;
|
|
47
|
-
@property(nonatomic, strong) NSString *decelerationRate;
|
|
48
46
|
@property(nonatomic) BOOL enableRTL;
|
|
49
47
|
@property(nonatomic) BOOL enableAnnotationRendering;
|
|
50
48
|
@property(nonatomic) BOOL enableDoubleTapZoom;
|
|
@@ -196,19 +196,10 @@ using namespace facebook::react;
|
|
|
196
196
|
[updatedPropNames addObject:@"scrollEnabled"];
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
// Scroll control properties (Issue #607)
|
|
200
|
-
if (_scrollVelocity != newProps.scrollVelocity) {
|
|
201
|
-
_scrollVelocity = newProps.scrollVelocity;
|
|
202
|
-
[updatedPropNames addObject:@"scrollVelocity"];
|
|
203
|
-
}
|
|
204
199
|
if (_enableMomentum != newProps.enableMomentum) {
|
|
205
200
|
_enableMomentum = newProps.enableMomentum;
|
|
206
201
|
[updatedPropNames addObject:@"enableMomentum"];
|
|
207
202
|
}
|
|
208
|
-
if (_decelerationRate != RCTNSStringFromStringNilIfEmpty(newProps.decelerationRate)) {
|
|
209
|
-
_decelerationRate = RCTNSStringFromStringNilIfEmpty(newProps.decelerationRate);
|
|
210
|
-
[updatedPropNames addObject:@"decelerationRate"];
|
|
211
|
-
}
|
|
212
203
|
|
|
213
204
|
[super updateProps:props oldProps:oldProps];
|
|
214
205
|
[self didSetProps:updatedPropNames];
|
|
@@ -298,11 +289,7 @@ using namespace facebook::react;
|
|
|
298
289
|
_showsHorizontalScrollIndicator = YES;
|
|
299
290
|
_showsVerticalScrollIndicator = YES;
|
|
300
291
|
_scrollEnabled = YES;
|
|
301
|
-
|
|
302
|
-
// Scroll control properties (Issue #607)
|
|
303
|
-
_scrollVelocity = 1.0f;
|
|
304
292
|
_enableMomentum = YES;
|
|
305
|
-
_decelerationRate = @"normal";
|
|
306
293
|
|
|
307
294
|
// Enhanced properties
|
|
308
295
|
_enableCaching = YES;
|
|
@@ -560,10 +547,9 @@ using namespace facebook::react;
|
|
|
560
547
|
}
|
|
561
548
|
}
|
|
562
549
|
|
|
563
|
-
// Apply
|
|
550
|
+
// Apply momentum property
|
|
564
551
|
if (_pdfDocument && ([changedProps containsObject:@"path"] ||
|
|
565
|
-
[changedProps containsObject:@"enableMomentum"]
|
|
566
|
-
[changedProps containsObject:@"decelerationRate"])) {
|
|
552
|
+
[changedProps containsObject:@"enableMomentum"])) {
|
|
567
553
|
for (UIView *subview in _pdfView.subviews) {
|
|
568
554
|
if ([subview isKindOfClass:[UIScrollView class]]) {
|
|
569
555
|
UIScrollView *scrollView = (UIScrollView *)subview;
|
|
@@ -572,17 +558,6 @@ using namespace facebook::react;
|
|
|
572
558
|
scrollView.bounces = _enableMomentum;
|
|
573
559
|
scrollView.alwaysBounceVertical = _enableMomentum;
|
|
574
560
|
scrollView.alwaysBounceHorizontal = _enableMomentum;
|
|
575
|
-
|
|
576
|
-
// Apply deceleration rate
|
|
577
|
-
if ([_decelerationRate isEqualToString:@"fast"]) {
|
|
578
|
-
scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
|
|
579
|
-
} else if ([_decelerationRate isEqualToString:@"slow"]) {
|
|
580
|
-
scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
|
|
581
|
-
} else {
|
|
582
|
-
scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
NSLog(@"[RNPDFPdf] Applied scroll controls: momentum=%d, deceleration=%@", _enableMomentum, _decelerationRate);
|
|
586
561
|
}
|
|
587
562
|
}
|
|
588
563
|
}
|
|
@@ -43,9 +43,7 @@ RCT_EXPORT_VIEW_PROPERTY(showsHorizontalScrollIndicator, BOOL);
|
|
|
43
43
|
RCT_EXPORT_VIEW_PROPERTY(showsVerticalScrollIndicator, BOOL);
|
|
44
44
|
RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL);
|
|
45
45
|
RCT_EXPORT_VIEW_PROPERTY(enablePaging, BOOL);
|
|
46
|
-
RCT_EXPORT_VIEW_PROPERTY(scrollVelocity, float);
|
|
47
46
|
RCT_EXPORT_VIEW_PROPERTY(enableMomentum, BOOL);
|
|
48
|
-
RCT_EXPORT_VIEW_PROPERTY(decelerationRate, NSString);
|
|
49
47
|
RCT_EXPORT_VIEW_PROPERTY(enableRTL, BOOL);
|
|
50
48
|
RCT_EXPORT_VIEW_PROPERTY(enableAnnotationRendering, BOOL);
|
|
51
49
|
RCT_EXPORT_VIEW_PROPERTY(enableDoubleTapZoom, BOOL);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pdf-jsi",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.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",
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"crypto-js": "4.2.0",
|
|
67
|
-
"deprecated-react-native-prop-types": "^2.3.0"
|
|
67
|
+
"deprecated-react-native-prop-types": "^2.3.0",
|
|
68
|
+
"react-native-pdf-jsi": "^2.2.8"
|
|
68
69
|
},
|
|
69
70
|
"devDependencies": {
|
|
70
71
|
"@babel/core": "^7.20.2",
|
|
@@ -72,10 +73,10 @@
|
|
|
72
73
|
"prop-types": "^15.7.2"
|
|
73
74
|
},
|
|
74
75
|
"peerDependencies": {
|
|
76
|
+
"@react-native-async-storage/async-storage": ">=1.17.0",
|
|
75
77
|
"react": "*",
|
|
76
78
|
"react-native": "*",
|
|
77
|
-
"react-native-blob-util": ">=0.13.7"
|
|
78
|
-
"@react-native-async-storage/async-storage": ">=1.17.0"
|
|
79
|
+
"react-native-blob-util": ">=0.13.7"
|
|
79
80
|
},
|
|
80
81
|
"files": [
|
|
81
82
|
"android/",
|
|
@@ -93,7 +94,9 @@
|
|
|
93
94
|
"PinchZoomView.js",
|
|
94
95
|
"react-native-pdf-jsi.podspec",
|
|
95
96
|
"fabric/",
|
|
96
|
-
"
|
|
97
|
+
"README.md",
|
|
98
|
+
"README_JSI.md",
|
|
99
|
+
"LICENSE"
|
|
97
100
|
],
|
|
98
101
|
"codegenConfig": {
|
|
99
102
|
"name": "rnpdf",
|
package/src/PDFJSI.js
CHANGED
|
@@ -75,18 +75,23 @@ class PDFJSIManager {
|
|
|
75
75
|
this.cacheMetrics = new Map();
|
|
76
76
|
this.initializationPromise = null;
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
// Don't initialize JSI in constructor - it will be initialized lazily when first accessed
|
|
79
|
+
// This prevents hooks from being called before React is ready
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
/**
|
|
82
83
|
* Initialize JSI availability check
|
|
84
|
+
* This is now called lazily when first accessed, not at module load
|
|
83
85
|
*/
|
|
84
86
|
async initializeJSI() {
|
|
85
87
|
if (this.initializationPromise) {
|
|
86
88
|
return this.initializationPromise;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
// Defer initialization to prevent hooks from being called before React is ready
|
|
92
|
+
this.initializationPromise = Promise.resolve().then(() => {
|
|
93
|
+
return this.checkJSIAvailability();
|
|
94
|
+
});
|
|
90
95
|
return this.initializationPromise;
|
|
91
96
|
}
|
|
92
97
|
|
|
@@ -814,8 +819,28 @@ class PDFJSIManager {
|
|
|
814
819
|
}
|
|
815
820
|
}
|
|
816
821
|
|
|
817
|
-
// Create singleton instance
|
|
818
|
-
|
|
822
|
+
// Create singleton instance lazily to prevent initialization before React is ready
|
|
823
|
+
let pdfJSIManagerInstance = null;
|
|
824
|
+
|
|
825
|
+
const getPDFJSIManager = () => {
|
|
826
|
+
if (!pdfJSIManagerInstance) {
|
|
827
|
+
pdfJSIManagerInstance = new PDFJSIManager();
|
|
828
|
+
}
|
|
829
|
+
return pdfJSIManagerInstance;
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
// Export a proxy that lazy-loads the instance
|
|
833
|
+
const pdfJSIManager = new Proxy({}, {
|
|
834
|
+
get(target, prop) {
|
|
835
|
+
const instance = getPDFJSIManager();
|
|
836
|
+
const value = instance[prop];
|
|
837
|
+
// If it's a method, bind it to the instance
|
|
838
|
+
if (typeof value === 'function') {
|
|
839
|
+
return value.bind(instance);
|
|
840
|
+
}
|
|
841
|
+
return value;
|
|
842
|
+
}
|
|
843
|
+
});
|
|
819
844
|
|
|
820
845
|
export default pdfJSIManager;
|
|
821
846
|
|
|
@@ -12,10 +12,23 @@ const AnalyticsPanel = ({
|
|
|
12
12
|
analytics,
|
|
13
13
|
licenseInfo,
|
|
14
14
|
}) => {
|
|
15
|
-
|
|
15
|
+
// Handle null/undefined analytics with defaults
|
|
16
|
+
const safeAnalytics = analytics || {
|
|
17
|
+
timeSpent: 0,
|
|
18
|
+
pagesRead: [],
|
|
19
|
+
totalPages: 0,
|
|
20
|
+
percentage: 0,
|
|
21
|
+
sessions: 0,
|
|
22
|
+
currentPage: 1,
|
|
23
|
+
lastRead: null,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const timeInMinutes = Math.round((safeAnalytics.timeSpent || 0) / 60);
|
|
27
|
+
const pagesReadArray = Array.isArray(safeAnalytics.pagesRead) ? safeAnalytics.pagesRead : [];
|
|
28
|
+
const totalPages = safeAnalytics.totalPages || 0;
|
|
16
29
|
const readingSpeed =
|
|
17
|
-
timeInMinutes > 0 ?
|
|
18
|
-
const remainingPages =
|
|
30
|
+
timeInMinutes > 0 ? pagesReadArray.length / timeInMinutes : 0;
|
|
31
|
+
const remainingPages = totalPages - pagesReadArray.length;
|
|
19
32
|
const estimatedTimeRemaining =
|
|
20
33
|
readingSpeed > 0 ? Math.round(remainingPages / readingSpeed) : 0;
|
|
21
34
|
|
|
@@ -34,13 +47,13 @@ const AnalyticsPanel = ({
|
|
|
34
47
|
<View style={styles.progressSection}>
|
|
35
48
|
<View style={styles.progressRing}>
|
|
36
49
|
<Text style={styles.progressPercent}>
|
|
37
|
-
{
|
|
50
|
+
{safeAnalytics.percentage || 0}%
|
|
38
51
|
</Text>
|
|
39
52
|
<Text style={styles.progressLabel}>Complete</Text>
|
|
40
53
|
</View>
|
|
41
54
|
<View style={styles.progressStats}>
|
|
42
55
|
<Text style={styles.statValue}>
|
|
43
|
-
{
|
|
56
|
+
{pagesReadArray.length}/{totalPages}
|
|
44
57
|
</Text>
|
|
45
58
|
<Text style={styles.statLabel}>Pages Read</Text>
|
|
46
59
|
</View>
|
|
@@ -64,7 +77,7 @@ const AnalyticsPanel = ({
|
|
|
64
77
|
|
|
65
78
|
<View style={styles.statCard}>
|
|
66
79
|
<Text style={styles.statIcon}>🔄</Text>
|
|
67
|
-
<Text style={styles.statCardValue}>{
|
|
80
|
+
<Text style={styles.statCardValue}>{safeAnalytics.sessions || 0}</Text>
|
|
68
81
|
<Text style={styles.statCardLabel}>Sessions</Text>
|
|
69
82
|
</View>
|
|
70
83
|
|
|
@@ -81,11 +94,11 @@ const AnalyticsPanel = ({
|
|
|
81
94
|
<View style={styles.sessionCard}>
|
|
82
95
|
<Text style={styles.sessionTitle}>Current Session</Text>
|
|
83
96
|
<Text style={styles.sessionInfo}>
|
|
84
|
-
Page {
|
|
97
|
+
Page {safeAnalytics.currentPage || 1} of {totalPages}
|
|
85
98
|
</Text>
|
|
86
|
-
{
|
|
99
|
+
{safeAnalytics.lastRead && (
|
|
87
100
|
<Text style={styles.sessionTime}>
|
|
88
|
-
Last read: {new Date(
|
|
101
|
+
Last read: {new Date(safeAnalytics.lastRead).toLocaleTimeString()}
|
|
89
102
|
</Text>
|
|
90
103
|
)}
|
|
91
104
|
</View>
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
* OPTIMIZATION: Memoized analytics for 95% faster repeated calls
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import bookmarkManager from '
|
|
14
|
-
import licenseManager from '../license/LicenseManager';
|
|
13
|
+
import bookmarkManager from './BookmarkManager';
|
|
15
14
|
import MemoizedAnalytics from '../utils/MemoizedAnalytics';
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -28,9 +27,6 @@ export class AnalyticsManager {
|
|
|
28
27
|
* Initialize analytics
|
|
29
28
|
*/
|
|
30
29
|
async initialize() {
|
|
31
|
-
// Check Pro license
|
|
32
|
-
licenseManager.requirePro('Reading Analytics');
|
|
33
|
-
|
|
34
30
|
if (!this.initialized) {
|
|
35
31
|
await bookmarkManager.initialize();
|
|
36
32
|
this.initialized = true;
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
14
|
-
import licenseManager, { ProFeature } from '../license/LicenseManager';
|
|
15
14
|
|
|
16
15
|
const STORAGE_KEY = '@react-native-pdf-jsi/bookmarks';
|
|
17
16
|
const PROGRESS_KEY = '@react-native-pdf-jsi/progress';
|
|
@@ -94,10 +93,7 @@ export class BookmarkManager {
|
|
|
94
93
|
async createBookmark(pdfId, bookmark) {
|
|
95
94
|
await this.initialize();
|
|
96
95
|
|
|
97
|
-
//
|
|
98
|
-
if (bookmark.color && bookmark.color !== '#000000') {
|
|
99
|
-
licenseManager.requirePro('Bookmark Colors');
|
|
100
|
-
}
|
|
96
|
+
// All features enabled by default
|
|
101
97
|
|
|
102
98
|
const newBookmark = {
|
|
103
99
|
id: this.generateId(),
|
|
@@ -255,11 +251,7 @@ export class BookmarkManager {
|
|
|
255
251
|
async updateProgress(pdfId, progressData) {
|
|
256
252
|
await this.initialize();
|
|
257
253
|
|
|
258
|
-
//
|
|
259
|
-
// Advanced analytics require Pro
|
|
260
|
-
if (progressData.timeSpent || progressData.sessions) {
|
|
261
|
-
licenseManager.requirePro('Reading Progress Tracking');
|
|
262
|
-
}
|
|
254
|
+
// All features enabled by default
|
|
263
255
|
|
|
264
256
|
const currentProgress = this.progress.get(pdfId) || {
|
|
265
257
|
pdfId,
|
|
@@ -16,7 +16,20 @@ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
|
16
16
|
const { PDFJSIManager } = NativeModules;
|
|
17
17
|
|
|
18
18
|
// Event emitter for progress updates
|
|
19
|
-
|
|
19
|
+
// Safely create event emitter only if the module supports event listeners
|
|
20
|
+
let eventEmitter = null;
|
|
21
|
+
if (PDFJSIManager) {
|
|
22
|
+
try {
|
|
23
|
+
// Check if NativeEventEmitter is available and the module supports events
|
|
24
|
+
if (typeof NativeEventEmitter !== 'undefined' &&
|
|
25
|
+
(typeof PDFJSIManager.addListener === 'function' || typeof PDFJSIManager.removeListeners === 'function')) {
|
|
26
|
+
eventEmitter = new NativeEventEmitter(PDFJSIManager);
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn('[CacheManager] Failed to create NativeEventEmitter:', error);
|
|
30
|
+
eventEmitter = null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
20
33
|
|
|
21
34
|
class CacheManager {
|
|
22
35
|
constructor() {
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
|
|
14
14
|
import { NativeModules, Platform, Share } from 'react-native';
|
|
15
15
|
import PDFTextExtractor from '../utils/PDFTextExtractor';
|
|
16
|
-
import licenseManager, { ProFeature } from '../license/LicenseManager';
|
|
17
16
|
|
|
18
17
|
const { PDFExporter } = NativeModules;
|
|
19
18
|
|
|
@@ -167,9 +166,7 @@ export class ExportManager {
|
|
|
167
166
|
* @returns {Promise<Array>} Array of image paths
|
|
168
167
|
*/
|
|
169
168
|
async exportToImages(filePath, options = {}) {
|
|
170
|
-
//
|
|
171
|
-
licenseManager.requirePro('Export to Images');
|
|
172
|
-
|
|
169
|
+
// All features enabled by default
|
|
173
170
|
const {
|
|
174
171
|
pages = null, // null = all pages
|
|
175
172
|
format = ExportFormat.JPEG,
|
|
@@ -230,11 +227,7 @@ export class ExportManager {
|
|
|
230
227
|
});
|
|
231
228
|
|
|
232
229
|
try {
|
|
233
|
-
//
|
|
234
|
-
console.log('🔑 [ExportManager] Checking license for Export to Images...');
|
|
235
|
-
licenseManager.requirePro('Export to Images');
|
|
236
|
-
console.log('✅ [ExportManager] License check passed');
|
|
237
|
-
|
|
230
|
+
// All features enabled by default
|
|
238
231
|
if (this.isNativeAvailable) {
|
|
239
232
|
console.log('📱 [ExportManager] Calling native PDFExporter.exportPageToImage...');
|
|
240
233
|
console.log('📱 [ExportManager] Parameters:', {
|
|
@@ -277,9 +270,7 @@ export class ExportManager {
|
|
|
277
270
|
* @returns {Promise<string>} Path to merged PDF
|
|
278
271
|
*/
|
|
279
272
|
async mergePDFs(filePaths, outputPath = null) {
|
|
280
|
-
//
|
|
281
|
-
licenseManager.requirePro('PDF Operations');
|
|
282
|
-
|
|
273
|
+
// All features enabled by default
|
|
283
274
|
console.log(`📤 ExportManager: Merging ${filePaths.length} PDFs...`);
|
|
284
275
|
|
|
285
276
|
try {
|
|
@@ -313,10 +304,7 @@ export class ExportManager {
|
|
|
313
304
|
});
|
|
314
305
|
|
|
315
306
|
try {
|
|
316
|
-
|
|
317
|
-
licenseManager.requirePro('PDF Operations');
|
|
318
|
-
console.log('✅ [ExportManager] License check passed');
|
|
319
|
-
|
|
307
|
+
// All features enabled by default
|
|
320
308
|
if (this.isNativeAvailable) {
|
|
321
309
|
console.log('📱 [ExportManager] Calling native PDFExporter.splitPDF...');
|
|
322
310
|
console.log('📱 [ExportManager] Ranges:', JSON.stringify(ranges));
|
|
@@ -354,10 +342,7 @@ export class ExportManager {
|
|
|
354
342
|
});
|
|
355
343
|
|
|
356
344
|
try {
|
|
357
|
-
|
|
358
|
-
licenseManager.requirePro('PDF Operations');
|
|
359
|
-
console.log('✅ [ExportManager] License check passed');
|
|
360
|
-
|
|
345
|
+
// All features enabled by default
|
|
361
346
|
if (this.isNativeAvailable) {
|
|
362
347
|
// Convert to 0-indexed
|
|
363
348
|
const pageIndices = pages.map(p => p - 1);
|
|
@@ -157,16 +157,6 @@ export const validatePageNumber = (page, totalPages) => {
|
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
159
|
|
|
160
|
-
export const validateLicense = (licenseManager, featureName) => {
|
|
161
|
-
if (!licenseManager.isProActive()) {
|
|
162
|
-
throw new PDFError(
|
|
163
|
-
`${featureName} requires a Pro license`,
|
|
164
|
-
ErrorCodes.LICENSE_REQUIRED,
|
|
165
|
-
{feature: featureName}
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
160
|
export default {
|
|
171
161
|
PDFError,
|
|
172
162
|
ErrorCodes,
|
|
@@ -175,5 +165,4 @@ export default {
|
|
|
175
165
|
withErrorHandling,
|
|
176
166
|
validatePDFPath,
|
|
177
167
|
validatePageNumber,
|
|
178
|
-
validateLicense,
|
|
179
168
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDFTextExtractor - Text Extraction from PDF Files
|
|
3
|
+
*
|
|
4
|
+
* Handles extracting text content from PDF files for export functionality
|
|
5
|
+
*
|
|
6
|
+
* @author Punith M
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* PDFTextExtractor Class
|
|
12
|
+
*/
|
|
13
|
+
class PDFTextExtractor {
|
|
14
|
+
/**
|
|
15
|
+
* Check if text extraction is available
|
|
16
|
+
* @returns {boolean} True if text extraction is available
|
|
17
|
+
*/
|
|
18
|
+
static isTextExtractionAvailable() {
|
|
19
|
+
// For development: Always return true
|
|
20
|
+
// In production, this would check if native modules are available
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Extract text from a specific page
|
|
26
|
+
* @param {string} filePath - Path to PDF file
|
|
27
|
+
* @param {number} pageNumber - Page number (0-indexed)
|
|
28
|
+
* @returns {Promise<string>} Extracted text content
|
|
29
|
+
*/
|
|
30
|
+
static async extractTextFromPage(filePath, pageNumber) {
|
|
31
|
+
// For development: Return placeholder text
|
|
32
|
+
// In production, this would use native modules to extract text
|
|
33
|
+
console.warn(`📄 PDFTextExtractor: Text extraction not fully implemented. Returning placeholder for page ${pageNumber}`);
|
|
34
|
+
return `[Text extraction from page ${pageNumber + 1} not yet implemented]`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Extract text from multiple pages
|
|
39
|
+
* @param {string} filePath - Path to PDF file
|
|
40
|
+
* @param {Array<number>} pageIndices - Array of page indices (0-indexed)
|
|
41
|
+
* @returns {Promise<Object>} Map of page index to extracted text
|
|
42
|
+
*/
|
|
43
|
+
static async extractTextFromPages(filePath, pageIndices) {
|
|
44
|
+
const textMap = {};
|
|
45
|
+
|
|
46
|
+
for (const pageIndex of pageIndices) {
|
|
47
|
+
textMap[pageIndex] = await this.extractTextFromPage(filePath, pageIndex);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return textMap;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extract text from all pages
|
|
55
|
+
* @param {string} filePath - Path to PDF file
|
|
56
|
+
* @returns {Promise<Object>} Map of page index to extracted text
|
|
57
|
+
*/
|
|
58
|
+
static async extractAllText(filePath) {
|
|
59
|
+
// For development: Return placeholder for first few pages
|
|
60
|
+
// In production, this would extract from all pages
|
|
61
|
+
console.warn('📄 PDFTextExtractor: Full text extraction not yet implemented. Returning placeholder data.');
|
|
62
|
+
|
|
63
|
+
// Return placeholder data structure
|
|
64
|
+
return {
|
|
65
|
+
0: '[Text extraction from all pages not yet implemented]',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get page count
|
|
71
|
+
* @param {string} filePath - Path to PDF file
|
|
72
|
+
* @returns {Promise<number>} Number of pages
|
|
73
|
+
*/
|
|
74
|
+
static async getPageCount(filePath) {
|
|
75
|
+
// Placeholder implementation
|
|
76
|
+
// In production, this would use native modules
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default PDFTextExtractor;
|
|
82
|
+
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
File without changes
|