react-native-pdf-jsi 4.0.0 → 4.1.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.
|
@@ -144,7 +144,6 @@ public class PdfManager extends SimpleViewManager<PdfView> implements RNPDFPdfVi
|
|
|
144
144
|
// NOOP on Android
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
@Override
|
|
148
147
|
public void setEnableMomentum(PdfView view, boolean value) {
|
|
149
148
|
// NOOP on Android - momentum scrolling is handled automatically by Android's ScrollView
|
|
150
149
|
}
|
|
@@ -179,8 +178,9 @@ public class PdfManager extends SimpleViewManager<PdfView> implements RNPDFPdfVi
|
|
|
179
178
|
@Override
|
|
180
179
|
public void onAfterUpdateTransaction(PdfView pdfView) {
|
|
181
180
|
super.onAfterUpdateTransaction(pdfView);
|
|
182
|
-
//
|
|
183
|
-
//
|
|
181
|
+
// Call drawPdf() to ensure PDF loads initially and when path changes
|
|
182
|
+
// The drawPdf() method internally checks if reload is needed to prevent unnecessary reloads
|
|
183
|
+
pdfView.drawPdf();
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
}
|
|
@@ -20,6 +20,8 @@ import android.net.Uri;
|
|
|
20
20
|
import android.util.AttributeSet;
|
|
21
21
|
import android.view.MotionEvent;
|
|
22
22
|
import android.graphics.Canvas;
|
|
23
|
+
import android.os.Handler;
|
|
24
|
+
import android.os.Looper;
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
import com.facebook.react.uimanager.ThemedReactContext;
|
|
@@ -85,6 +87,8 @@ public class PdfView extends PDFView implements OnPageChangeListener,OnLoadCompl
|
|
|
85
87
|
private boolean needsReload = true;
|
|
86
88
|
private String lastLoadedPath = null;
|
|
87
89
|
private float lastPageHeight = 0;
|
|
90
|
+
private boolean loadCompleteDispatched = false;
|
|
91
|
+
private int lastKnownPageCount = 0;
|
|
88
92
|
|
|
89
93
|
// used to store the parameters for `super.onSizeChanged`
|
|
90
94
|
private int oldW = 0;
|
|
@@ -100,6 +104,17 @@ public class PdfView extends PDFView implements OnPageChangeListener,OnLoadCompl
|
|
|
100
104
|
page = page+1;
|
|
101
105
|
this.page = page;
|
|
102
106
|
showLog(format("%s %s / %s", path, page, numberOfPages));
|
|
107
|
+
|
|
108
|
+
// Store page count when we get it (useful for loadComplete dispatch)
|
|
109
|
+
if (numberOfPages > 0 && lastKnownPageCount == 0) {
|
|
110
|
+
lastKnownPageCount = numberOfPages;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Note: We don't dispatch loadComplete from onPageChanged anymore because:
|
|
114
|
+
// 1. The PDF library's onLoad callback should call loadComplete() directly
|
|
115
|
+
// 2. If it doesn't, we've already fixed it in loadComplete() with delayed dispatch
|
|
116
|
+
// 3. This prevents duplicate loadComplete events
|
|
117
|
+
// The delayed dispatch in loadComplete() ensures React component is ready
|
|
103
118
|
|
|
104
119
|
WritableMap event = Arguments.createMap();
|
|
105
120
|
event.putString("message", "pageChanged|"+page+"|"+numberOfPages);
|
|
@@ -145,27 +160,75 @@ public class PdfView extends PDFView implements OnPageChangeListener,OnLoadCompl
|
|
|
145
160
|
|
|
146
161
|
@Override
|
|
147
162
|
public void loadComplete(int numberOfPages) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
163
|
+
// Prevent duplicate calls - if already dispatched, skip
|
|
164
|
+
if (loadCompleteDispatched) {
|
|
165
|
+
showLog("loadComplete: Already dispatched, skipping duplicate call");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
showLog("loadComplete called with " + numberOfPages + " pages, loadCompleteDispatched=" + loadCompleteDispatched);
|
|
169
|
+
// Store the page count for later use
|
|
170
|
+
lastKnownPageCount = numberOfPages;
|
|
171
|
+
|
|
172
|
+
float width = 0;
|
|
173
|
+
float height = 0;
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
SizeF pageSize = getPageSize(0);
|
|
177
|
+
if (pageSize != null) {
|
|
178
|
+
width = pageSize.getWidth();
|
|
179
|
+
height = pageSize.getHeight();
|
|
180
|
+
}
|
|
181
|
+
} catch (Exception e) {
|
|
182
|
+
showLog("Error getting page size in loadComplete: " + e.getMessage());
|
|
183
|
+
// Continue with default values to ensure event is dispatched
|
|
184
|
+
}
|
|
151
185
|
|
|
152
|
-
|
|
186
|
+
try {
|
|
187
|
+
this.zoomTo(this.scale);
|
|
188
|
+
} catch (Exception e) {
|
|
189
|
+
showLog("Error setting zoom in loadComplete: " + e.getMessage());
|
|
190
|
+
// Continue even if zoom fails
|
|
191
|
+
}
|
|
192
|
+
|
|
153
193
|
WritableMap event = Arguments.createMap();
|
|
154
194
|
|
|
155
195
|
//create a new json Object for the TableOfContents
|
|
156
196
|
Gson gson = new Gson();
|
|
197
|
+
String tableOfContents = "";
|
|
198
|
+
try {
|
|
199
|
+
tableOfContents = gson.toJson(this.getTableOfContents());
|
|
200
|
+
} catch (Exception e) {
|
|
201
|
+
showLog("Error serializing table of contents: " + e.getMessage());
|
|
202
|
+
// Continue with empty table of contents
|
|
203
|
+
}
|
|
204
|
+
|
|
157
205
|
// Include path in loadComplete message for reliable access in JS
|
|
158
206
|
String pathValue = this.path != null ? this.path : "";
|
|
159
|
-
event.putString("message", "loadComplete|"+numberOfPages+"|"+width+"|"+height+"|"+pathValue+"|"+
|
|
207
|
+
event.putString("message", "loadComplete|"+numberOfPages+"|"+width+"|"+height+"|"+pathValue+"|"+tableOfContents);
|
|
160
208
|
|
|
161
209
|
ThemedReactContext context = (ThemedReactContext) getContext();
|
|
162
|
-
EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, getId());
|
|
210
|
+
final EventDispatcher dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, getId());
|
|
163
211
|
int surfaceId = UIManagerHelper.getSurfaceId(this);
|
|
164
212
|
|
|
165
|
-
TopChangeEvent tce = new TopChangeEvent(surfaceId, getId(), event);
|
|
213
|
+
final TopChangeEvent tce = new TopChangeEvent(surfaceId, getId(), event);
|
|
166
214
|
|
|
167
215
|
if (dispatcher != null) {
|
|
168
|
-
|
|
216
|
+
showLog("loadComplete: Dispatching event with message: " + event.getString("message"));
|
|
217
|
+
// Post to next frame to ensure React component is ready to receive events
|
|
218
|
+
// This fixes timing issues where event is dispatched before component is mounted
|
|
219
|
+
final PdfView self = this;
|
|
220
|
+
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
|
221
|
+
@Override
|
|
222
|
+
public void run() {
|
|
223
|
+
if (dispatcher != null) {
|
|
224
|
+
dispatcher.dispatchEvent(tce);
|
|
225
|
+
self.loadCompleteDispatched = true;
|
|
226
|
+
showLog("loadComplete: Event dispatched successfully (delayed)");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
showLog("EventDispatcher is null, cannot dispatch loadComplete event");
|
|
169
232
|
}
|
|
170
233
|
// ReactContext reactContext = (ReactContext)this.getContext();
|
|
171
234
|
// reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
|
|
@@ -296,6 +359,11 @@ public class PdfView extends PDFView implements OnPageChangeListener,OnLoadCompl
|
|
|
296
359
|
if (this.page > 0 && !this.isRecycled()) {
|
|
297
360
|
this.jumpTo(this.page - 1, false);
|
|
298
361
|
}
|
|
362
|
+
// If PDF is already loaded but loadComplete event hasn't been dispatched yet, dispatch it now
|
|
363
|
+
if (!loadCompleteDispatched && !this.isRecycled() && lastKnownPageCount > 0) {
|
|
364
|
+
showLog("drawPdf: PDF already loaded but loadComplete not dispatched, dispatching now with " + lastKnownPageCount + " pages");
|
|
365
|
+
loadComplete(lastKnownPageCount);
|
|
366
|
+
}
|
|
299
367
|
return;
|
|
300
368
|
}
|
|
301
369
|
showLog(format("drawPdf path:%s %s", this.path, this.page));
|
|
@@ -367,6 +435,9 @@ public class PdfView extends PDFView implements OnPageChangeListener,OnLoadCompl
|
|
|
367
435
|
// Path changed - need to reload document
|
|
368
436
|
needsReload = true;
|
|
369
437
|
this.path = path;
|
|
438
|
+
// Reset flags when path changes
|
|
439
|
+
loadCompleteDispatched = false;
|
|
440
|
+
lastKnownPageCount = 0;
|
|
370
441
|
}
|
|
371
442
|
|
|
372
443
|
// page start from 1
|
package/index.js
CHANGED
|
@@ -547,9 +547,14 @@ export default class Pdf extends Component {
|
|
|
547
547
|
_onChange = (event) => {
|
|
548
548
|
|
|
549
549
|
let message = event.nativeEvent.message.split('|');
|
|
550
|
-
|
|
550
|
+
if (__DEV__) {
|
|
551
|
+
console.log("📥 [Pdf] onChange received:", message[0], "full message:", event.nativeEvent.message);
|
|
552
|
+
}
|
|
551
553
|
if (message.length > 0) {
|
|
552
554
|
if (message[0] === 'loadComplete') {
|
|
555
|
+
if (__DEV__) {
|
|
556
|
+
console.log("📥 [Pdf] Processing loadComplete event");
|
|
557
|
+
}
|
|
553
558
|
let tableContents;
|
|
554
559
|
let filePath;
|
|
555
560
|
|
|
@@ -670,9 +670,31 @@ using namespace facebook::react;
|
|
|
670
670
|
PDFPage *page = [_pdfDocument pageAtIndex:_pdfDocument.pageCount-1];
|
|
671
671
|
CGSize pageSize = [_pdfView rowSizeForPage:page];
|
|
672
672
|
NSString *jsonString = [self getTableContents];
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
673
|
+
|
|
674
|
+
// Include path in loadComplete message for consistency with Android and reliable path access in JS
|
|
675
|
+
// Format: loadComplete|numberOfPages|width|height|path|tableContents
|
|
676
|
+
NSString *pathValue = @"";
|
|
677
|
+
if (_path != nil && _path.length > 0) {
|
|
678
|
+
pathValue = _path;
|
|
679
|
+
} else if (_pdfDocument.documentURL != nil) {
|
|
680
|
+
// Fallback: try to get path from document URL
|
|
681
|
+
pathValue = _pdfDocument.documentURL.path;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Debug logging to verify path is being included (using RCTLog so it shows in all builds)
|
|
685
|
+
RCTLogInfo(@"🔍 [iOS] loadComplete: numberOfPages=%lu, width=%f, height=%f, path='%@', pathLength=%lu",
|
|
686
|
+
numberOfPages, pageSize.width, pageSize.height, pathValue, (unsigned long)pathValue.length);
|
|
687
|
+
|
|
688
|
+
// Ensure path is always included in message (even if empty) for consistent parsing
|
|
689
|
+
// Format: loadComplete|numberOfPages|width|height|path|tableContents
|
|
690
|
+
// Use explicit format to ensure path segment is always present
|
|
691
|
+
NSString *message = [NSString stringWithFormat:@"loadComplete|%lu|%f|%f|%@|%@",
|
|
692
|
+
numberOfPages, pageSize.width, pageSize.height,
|
|
693
|
+
(pathValue != nil ? pathValue : @""), jsonString];
|
|
694
|
+
|
|
695
|
+
RCTLogInfo(@"🔍 [iOS] loadComplete message: %@", message);
|
|
696
|
+
|
|
697
|
+
[self notifyOnChangeWithMessage:message];
|
|
676
698
|
}
|
|
677
699
|
|
|
678
700
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-pdf-jsi",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.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",
|