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.
Files changed (37) hide show
  1. package/README.md +106 -7
  2. package/android/src/main/java/org/wonday/pdf/FileManager.java +2 -0
  3. package/android/src/main/java/org/wonday/pdf/MemoryMappedCache.java +1 -1
  4. package/android/src/main/java/org/wonday/pdf/PDFExporter.java +0 -54
  5. package/android/src/main/java/org/wonday/pdf/PdfView.java +12 -2
  6. package/android/src/main/java/org/wonday/pdf/RNPDFJSIPackage.java +50 -0
  7. package/android/src/main/java/org/wonday/pdf/RNPDFPackage.java +0 -1
  8. package/fabric/RNPDFPdfNativeComponent.js +4 -0
  9. package/index.js +148 -23
  10. package/ios/RNPDFPdf/RNPDFPdfView.h +0 -2
  11. package/ios/RNPDFPdf/RNPDFPdfView.mm +2 -27
  12. package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +0 -2
  13. package/package.json +8 -5
  14. package/src/PDFJSI.js +29 -4
  15. package/src/components/AnalyticsPanel.jsx +22 -9
  16. package/src/managers/AnalyticsManager.js +1 -5
  17. package/src/managers/BookmarkManager.js +2 -10
  18. package/src/managers/CacheManager.js +14 -1
  19. package/src/managers/ExportManager.js +5 -20
  20. package/src/utils/ErrorHandler.js +0 -11
  21. package/src/utils/PDFTextExtractor.js +82 -0
  22. package/android/.gradle/5.6.1/fileChanges/last-build.bin +0 -0
  23. package/android/.gradle/5.6.1/fileHashes/fileHashes.lock +0 -0
  24. package/android/.gradle/5.6.1/gc.properties +0 -0
  25. package/android/.gradle/8.5/checksums/checksums.lock +0 -0
  26. package/android/.gradle/8.5/checksums/md5-checksums.bin +0 -0
  27. package/android/.gradle/8.5/checksums/sha1-checksums.bin +0 -0
  28. package/android/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock +0 -0
  29. package/android/.gradle/8.5/dependencies-accessors/gc.properties +0 -0
  30. package/android/.gradle/8.5/executionHistory/executionHistory.lock +0 -0
  31. package/android/.gradle/8.5/fileChanges/last-build.bin +0 -0
  32. package/android/.gradle/8.5/fileHashes/fileHashes.lock +0 -0
  33. package/android/.gradle/8.5/gc.properties +0 -0
  34. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  35. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  36. package/android/.gradle/vcs-1/gc.properties +0 -0
  37. 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 scroll control properties (Issue #607)
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.0",
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
- "README_JSI.md"
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
- this.initializeJSI();
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
- this.initializationPromise = this.checkJSIAvailability();
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
- const pdfJSIManager = new PDFJSIManager();
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
- const timeInMinutes = Math.round(analytics.timeSpent / 60);
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 ? analytics.pagesRead.length / timeInMinutes : 0;
18
- const remainingPages = analytics.totalPages - analytics.pagesRead.length;
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
- {analytics.percentage}%
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
- {analytics.pagesRead.length}/{analytics.totalPages}
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}>{analytics.sessions}</Text>
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 {analytics.currentPage} of {analytics.totalPages}
97
+ Page {safeAnalytics.currentPage || 1} of {totalPages}
85
98
  </Text>
86
- {analytics.lastRead && (
99
+ {safeAnalytics.lastRead && (
87
100
  <Text style={styles.sessionTime}>
88
- Last read: {new Date(analytics.lastRead).toLocaleTimeString()}
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 '../bookmarks/BookmarkManager';
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
- // Check if using Pro features (colors)
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
- // Basic progress tracking is free
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
- const eventEmitter = PDFJSIManager ? new NativeEventEmitter(PDFJSIManager) : null;
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
- // ⚠️ PRO FEATURE - Requires license
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
- // ⚠️ PRO FEATURE - Requires license
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
- // ⚠️ PRO FEATURE - Requires license
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
- console.log('🔑 [ExportManager] Checking license for PDF Operations...');
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
- console.log('🔑 [ExportManager] Checking license for PDF Operations...');
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
+
File without changes
File without changes
@@ -1,2 +0,0 @@
1
- #Thu Oct 02 20:04:14 IST 2025
2
- gradle.version=8.5
File without changes