@thatkid02/react-native-pdf-viewer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +20 -0
  2. package/PdfViewer.podspec +28 -0
  3. package/README.md +290 -0
  4. package/android/CMakeLists.txt +24 -0
  5. package/android/build.gradle +121 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  8. package/android/src/main/java/com/margelo/nitro/pdfviewer/HybridPdfViewer.kt +169 -0
  9. package/android/src/main/java/com/margelo/nitro/pdfviewer/PdfViewer.kt +996 -0
  10. package/android/src/main/java/com/margelo/nitro/pdfviewer/PdfViewerPackage.kt +26 -0
  11. package/ios/PdfViewer.swift +696 -0
  12. package/lib/module/PdfViewer.nitro.js +4 -0
  13. package/lib/module/PdfViewer.nitro.js.map +1 -0
  14. package/lib/module/index.js +13 -0
  15. package/lib/module/index.js.map +1 -0
  16. package/lib/module/package.json +1 -0
  17. package/lib/typescript/package.json +1 -0
  18. package/lib/typescript/src/PdfViewer.nitro.d.ts +67 -0
  19. package/lib/typescript/src/PdfViewer.nitro.d.ts.map +1 -0
  20. package/lib/typescript/src/index.d.ts +8 -0
  21. package/lib/typescript/src/index.d.ts.map +1 -0
  22. package/nitro.json +17 -0
  23. package/nitrogen/generated/android/c++/JErrorEvent.hpp +57 -0
  24. package/nitrogen/generated/android/c++/JFunc_void_ErrorEvent.hpp +77 -0
  25. package/nitrogen/generated/android/c++/JFunc_void_LoadCompleteEvent.hpp +76 -0
  26. package/nitrogen/generated/android/c++/JFunc_void_LoadingChangeEvent.hpp +76 -0
  27. package/nitrogen/generated/android/c++/JFunc_void_PageChangeEvent.hpp +76 -0
  28. package/nitrogen/generated/android/c++/JFunc_void_ScaleChangeEvent.hpp +76 -0
  29. package/nitrogen/generated/android/c++/JFunc_void_ThumbnailGeneratedEvent.hpp +77 -0
  30. package/nitrogen/generated/android/c++/JHybridPdfViewerSpec.cpp +273 -0
  31. package/nitrogen/generated/android/c++/JHybridPdfViewerSpec.hpp +94 -0
  32. package/nitrogen/generated/android/c++/JLoadCompleteEvent.hpp +61 -0
  33. package/nitrogen/generated/android/c++/JLoadingChangeEvent.hpp +53 -0
  34. package/nitrogen/generated/android/c++/JPageChangeEvent.hpp +57 -0
  35. package/nitrogen/generated/android/c++/JScaleChangeEvent.hpp +53 -0
  36. package/nitrogen/generated/android/c++/JThumbnailGeneratedEvent.hpp +57 -0
  37. package/nitrogen/generated/android/c++/views/JHybridPdfViewerStateUpdater.cpp +108 -0
  38. package/nitrogen/generated/android/c++/views/JHybridPdfViewerStateUpdater.hpp +49 -0
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/ErrorEvent.kt +32 -0
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_ErrorEvent.kt +81 -0
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_LoadCompleteEvent.kt +81 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_LoadingChangeEvent.kt +81 -0
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_PageChangeEvent.kt +81 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_ScaleChangeEvent.kt +81 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/Func_void_ThumbnailGeneratedEvent.kt +81 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/HybridPdfViewerSpec.kt +195 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/LoadCompleteEvent.kt +35 -0
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/LoadingChangeEvent.kt +29 -0
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/PageChangeEvent.kt +32 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/ScaleChangeEvent.kt +29 -0
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/ThumbnailGeneratedEvent.kt +32 -0
  52. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/pdfviewerOnLoad.kt +35 -0
  53. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/views/HybridPdfViewerManager.kt +50 -0
  54. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pdfviewer/views/HybridPdfViewerStateUpdater.kt +23 -0
  55. package/nitrogen/generated/android/pdfviewer+autolinking.cmake +83 -0
  56. package/nitrogen/generated/android/pdfviewer+autolinking.gradle +27 -0
  57. package/nitrogen/generated/android/pdfviewerOnLoad.cpp +58 -0
  58. package/nitrogen/generated/android/pdfviewerOnLoad.hpp +25 -0
  59. package/nitrogen/generated/ios/PdfViewer+autolinking.rb +60 -0
  60. package/nitrogen/generated/ios/PdfViewer-Swift-Cxx-Bridge.cpp +80 -0
  61. package/nitrogen/generated/ios/PdfViewer-Swift-Cxx-Bridge.hpp +339 -0
  62. package/nitrogen/generated/ios/PdfViewer-Swift-Cxx-Umbrella.hpp +64 -0
  63. package/nitrogen/generated/ios/PdfViewerAutolinking.mm +33 -0
  64. package/nitrogen/generated/ios/PdfViewerAutolinking.swift +25 -0
  65. package/nitrogen/generated/ios/c++/HybridPdfViewerSpecSwift.cpp +11 -0
  66. package/nitrogen/generated/ios/c++/HybridPdfViewerSpecSwift.hpp +205 -0
  67. package/nitrogen/generated/ios/c++/views/HybridPdfViewerComponent.mm +161 -0
  68. package/nitrogen/generated/ios/swift/ErrorEvent.swift +46 -0
  69. package/nitrogen/generated/ios/swift/Func_void_ErrorEvent.swift +47 -0
  70. package/nitrogen/generated/ios/swift/Func_void_LoadCompleteEvent.swift +47 -0
  71. package/nitrogen/generated/ios/swift/Func_void_LoadingChangeEvent.swift +47 -0
  72. package/nitrogen/generated/ios/swift/Func_void_PageChangeEvent.swift +47 -0
  73. package/nitrogen/generated/ios/swift/Func_void_ScaleChangeEvent.swift +47 -0
  74. package/nitrogen/generated/ios/swift/Func_void_ThumbnailGeneratedEvent.swift +47 -0
  75. package/nitrogen/generated/ios/swift/HybridPdfViewerSpec.swift +65 -0
  76. package/nitrogen/generated/ios/swift/HybridPdfViewerSpec_cxx.swift +500 -0
  77. package/nitrogen/generated/ios/swift/LoadCompleteEvent.swift +57 -0
  78. package/nitrogen/generated/ios/swift/LoadingChangeEvent.swift +35 -0
  79. package/nitrogen/generated/ios/swift/PageChangeEvent.swift +46 -0
  80. package/nitrogen/generated/ios/swift/ScaleChangeEvent.swift +35 -0
  81. package/nitrogen/generated/ios/swift/ThumbnailGeneratedEvent.swift +46 -0
  82. package/nitrogen/generated/shared/c++/ErrorEvent.hpp +71 -0
  83. package/nitrogen/generated/shared/c++/HybridPdfViewerSpec.cpp +52 -0
  84. package/nitrogen/generated/shared/c++/HybridPdfViewerSpec.hpp +111 -0
  85. package/nitrogen/generated/shared/c++/LoadCompleteEvent.hpp +75 -0
  86. package/nitrogen/generated/shared/c++/LoadingChangeEvent.hpp +67 -0
  87. package/nitrogen/generated/shared/c++/PageChangeEvent.hpp +71 -0
  88. package/nitrogen/generated/shared/c++/ScaleChangeEvent.hpp +67 -0
  89. package/nitrogen/generated/shared/c++/ThumbnailGeneratedEvent.hpp +71 -0
  90. package/nitrogen/generated/shared/c++/views/HybridPdfViewerComponent.cpp +243 -0
  91. package/nitrogen/generated/shared/c++/views/HybridPdfViewerComponent.hpp +127 -0
  92. package/nitrogen/generated/shared/json/PdfViewerConfig.json +23 -0
  93. package/package.json +175 -0
  94. package/src/PdfViewer.nitro.ts +97 -0
  95. package/src/index.tsx +27 -0
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 thatkid02
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "PdfViewer"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/thatkid02/react-native-pdf-viewer.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = [
17
+ "ios/**/*.{h,m,mm,swift}",
18
+ "cpp/**/*.{hpp,cpp}",
19
+ ]
20
+
21
+ s.dependency 'React-jsi'
22
+ s.dependency 'React-callinvoker'
23
+
24
+ load 'nitrogen/generated/ios/PdfViewer+autolinking.rb'
25
+ add_nitrogen_files(s)
26
+
27
+ install_modules_dependencies(s)
28
+ end
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ # react-native-pdf-viewer
2
+
3
+ High-performance PDF viewer for React Native, built with [Nitro Modules](https://nitro.margelo.com/) for native rendering performance.
4
+
5
+ ## Features
6
+
7
+ ✅ **High-performance PDF rendering** with native APIs (PDFKit on iOS, PdfRenderer on Android)
8
+ ✅ **Pinch-to-zoom and pan gestures** - Smooth, native gesture handling
9
+ ✅ **Thumbnail generation** for page previews
10
+ ✅ **Local and remote PDF support** (file://, http://, https://)
11
+ ✅ **Page navigation** with events
12
+ ✅ **TypeScript support** - Full type safety
13
+ ✅ **Memory efficient** - Virtualizes pages, only renders visible content
14
+ ✅ **iOS-specific layouts** - Horizontal scroll and paging modes
15
+
16
+ ## Platform Support
17
+
18
+ | Feature | Android | iOS | Notes |
19
+ |---------|---------|-----|-------|
20
+ | Local Files (file://) | ✅ | ✅ | |
21
+ | Remote URLs (http/https) | ✅ | ✅ | Prefer HTTPS in production |
22
+ | Zoom Controls | ✅(2 scale) | ✅ | |
23
+ | Page Navigation | ✅ | ✅ | |
24
+ | Horizontal Scroll | ❌ | ✅ | iOS only |
25
+ | Paging Mode | ❌ | ✅ | iOS only |
26
+ | Thumbnail Generation | ✅ | ✅ | Async on both platforms |
27
+
28
+ ## Installation
29
+
30
+ ```sh
31
+ npm install react-native-pdf-viewer react-native-nitro-modules
32
+ ```
33
+
34
+ > `react-native-nitro-modules` is required as this library relies on [Nitro Modules](https://nitro.margelo.com/).
35
+
36
+ ## Usage
37
+
38
+ ### Basic Example
39
+
40
+ ```tsx
41
+ import { PdfViewerView } from 'react-native-pdf-viewer';
42
+
43
+ export default function App() {
44
+ return (
45
+ <PdfViewerView
46
+ source="https://example.com/document.pdf"
47
+ style={{ flex: 1 }}
48
+ onLoadComplete={(event) => {
49
+ console.log('PDF loaded:', event.pageCount, 'pages');
50
+ }}
51
+ onError={(event) => {
52
+ console.error('PDF error:', event.message);
53
+ }}
54
+ />
55
+ );
56
+ }
57
+ ```
58
+
59
+ ### Advanced Example with All Features
60
+
61
+ ```tsx
62
+ import React, { useRef } from 'react';
63
+ import { View, Button, StyleSheet } from 'react-native';
64
+ import { PdfViewerView, type PdfViewer } from 'react-native-pdf-viewer';
65
+
66
+ export default function AdvancedPdfViewer() {
67
+ const pdfRef = useRef<PdfViewer>(null);
68
+
69
+ const handleLoadComplete = (event) => {
70
+ console.log(`PDF loaded: ${event.pageCount} pages`);
71
+ console.log(`Page size: ${event.pageWidth}x${event.pageHeight}`);
72
+
73
+ // Generate thumbnails for all pages
74
+ pdfRef.current?.generateAllThumbnails();
75
+ };
76
+
77
+ const handlePageChange = (event) => {
78
+ console.log(`Current page: ${event.page + 1} of ${event.pageCount}`);
79
+ };
80
+
81
+ const handleScaleChange = (event) => {
82
+ console.log(`Zoom scale: ${event.scale}`);
83
+ };
84
+
85
+ const handleThumbnailGenerated = (event) => {
86
+ console.log(`Thumbnail for page ${event.page}: ${event.uri}`);
87
+ };
88
+
89
+ const goToPage = (page: number) => {
90
+ pdfRef.current?.goToPage(page);
91
+ };
92
+
93
+ const zoomIn = () => {
94
+ pdfRef.current?.setScale(2.0);
95
+ };
96
+
97
+ return (
98
+ <View style={styles.container}>
99
+ <PdfViewerView
100
+ ref={pdfRef}
101
+ source="https://example.com/document.pdf"
102
+ style={styles.pdf}
103
+ // Layout options
104
+ spacing={16}
105
+ enableZoom={true}
106
+ minScale={0.5}
107
+ maxScale={5.0}
108
+ // iOS-only options
109
+ horizontal={false} // iOS only
110
+ enablePaging={false} // iOS only
111
+ // Loading indicator
112
+ showsActivityIndicator={true}
113
+ // Event handlers
114
+ onLoadComplete={handleLoadComplete}
115
+ onPageChange={handlePageChange}
116
+ onScaleChange={handleScaleChange}
117
+ onThumbnailGenerated={handleThumbnailGenerated}
118
+ onError={(event) => console.error(event.message)}
119
+ onLoadingChange={(event) => console.log('Loading:', event.isLoading)}
120
+ />
121
+
122
+ <View style={styles.controls}>
123
+ <Button title="Go to Page 5" onPress={() => goToPage(4)} />
124
+ <Button title="Zoom In" onPress={zoomIn} />
125
+ </View>
126
+ </View>
127
+ );
128
+ }
129
+
130
+ const styles = StyleSheet.create({
131
+ container: {
132
+ flex: 1,
133
+ },
134
+ pdf: {
135
+ flex: 1,
136
+ },
137
+ controls: {
138
+ flexDirection: 'row',
139
+ justifyContent: 'space-around',
140
+ padding: 16,
141
+ },
142
+ });
143
+ ```
144
+
145
+ ### Loading Local Files
146
+
147
+ ```tsx
148
+ <PdfViewerView
149
+ source="file:///path/to/document.pdf"
150
+ style={{ flex: 1 }}
151
+ />
152
+ ```
153
+
154
+ ### iOS-Specific Features
155
+
156
+ ```tsx
157
+ // Horizontal scrolling (iOS only)
158
+ <PdfViewerView
159
+ source="https://example.com/document.pdf"
160
+ horizontal={true}
161
+ style={{ flex: 1 }}
162
+ />
163
+
164
+ // Paging mode with swipe transitions (iOS only)
165
+ <PdfViewerView
166
+ source="https://example.com/document.pdf"
167
+ enablePaging={true}
168
+ style={{ flex: 1 }}
169
+ />
170
+ ```
171
+
172
+ ## API Reference
173
+
174
+ ### Props
175
+
176
+ | Prop | Type | Default | Description |
177
+ |------|------|---------|-------------|
178
+ | `source` | `string` | - | PDF source URI (file://, http://, https://) |
179
+ | `spacing` | `number` | `8` | Space between pages in pixels |
180
+ | `enableZoom` | `boolean` | `true` | Enable pinch-to-zoom gestures |
181
+ | `minScale` | `number` | `0.5` | Minimum zoom scale |
182
+ | `maxScale` | `number` | `4.0` | Maximum zoom scale |
183
+ | `showsActivityIndicator` | `boolean` | `true` | Show loading indicator |
184
+ | `horizontal` | `boolean` | `false` | Horizontal scroll (iOS only) |
185
+ | `enablePaging` | `boolean` | `false` | Enable paging mode (iOS only) |
186
+ | `onLoadComplete` | `(event) => void` | - | Called when PDF loads |
187
+ | `onPageChange` | `(event) => void` | - | Called when page changes |
188
+ | `onScaleChange` | `(event) => void` | - | Called when zoom changes |
189
+ | `onError` | `(event) => void` | - | Called on error |
190
+ | `onThumbnailGenerated` | `(event) => void` | - | Called when thumbnail is ready |
191
+ | `onLoadingChange` | `(event) => void` | - | Called when loading state changes |
192
+
193
+ ### Methods
194
+
195
+ Access methods via ref:
196
+
197
+ ```tsx
198
+ const pdfRef = useRef<PdfViewer>(null);
199
+
200
+ // Navigate to specific page (0-indexed)
201
+ pdfRef.current?.goToPage(pageIndex);
202
+
203
+ // Set zoom scale
204
+ pdfRef.current?.setScale(2.0);
205
+
206
+ // Generate thumbnail for specific page
207
+ pdfRef.current?.generateThumbnail(pageIndex);
208
+
209
+ // Generate thumbnails for all pages
210
+ pdfRef.current?.generateAllThumbnails();
211
+ ```
212
+
213
+ ### Events
214
+
215
+ #### LoadCompleteEvent
216
+ ```typescript
217
+ {
218
+ pageCount: number; // Total number of pages
219
+ pageWidth: number; // Width of first page
220
+ pageHeight: number; // Height of first page
221
+ }
222
+ ```
223
+
224
+ #### PageChangeEvent
225
+ ```typescript
226
+ {
227
+ page: number; // Current page index (0-based)
228
+ pageCount: number; // Total pages
229
+ }
230
+ ```
231
+
232
+ #### ScaleChangeEvent
233
+ ```typescript
234
+ {
235
+ scale: number; // Current zoom scale
236
+ }
237
+ ```
238
+
239
+ #### ErrorEvent
240
+ ```typescript
241
+ {
242
+ message: string; // Error description
243
+ code: string; // Error code (e.g., "FILE_NOT_FOUND")
244
+ }
245
+ ```
246
+
247
+ #### ThumbnailGeneratedEvent
248
+ ```typescript
249
+ {
250
+ page: number; // Page index
251
+ uri: string; // File URI of thumbnail image
252
+ }
253
+ ```
254
+
255
+ ## Performance
256
+
257
+ - **Memory efficient**: Virtualizes pages, only renders visible content
258
+ - **Smooth scrolling**: 60 FPS on most devices
259
+ - **Large PDFs**: Tested with 500+ page documents
260
+ - **Smart caching**: Automatic memory management with LRU cache
261
+
262
+ ## Troubleshooting
263
+
264
+ ### PDF fails to load from URL
265
+
266
+ Ensure the URL is accessible and returns a valid PDF. For production apps, always use HTTPS URLs for security.
267
+
268
+ ### Out of memory errors on large PDFs
269
+
270
+ The library automatically manages memory, but for very large documents at high zoom levels:
271
+ - Limit `maxScale` to reduce memory usage
272
+ - The Android implementation dynamically reduces quality at high zoom levels
273
+
274
+ ### iOS horizontal/paging mode not working
275
+
276
+ These features are iOS-only. On Android, the viewer always uses vertical scrolling.
277
+
278
+ ## Contributing
279
+
280
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
281
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
282
+ - [Code of conduct](CODE_OF_CONDUCT.md)
283
+
284
+ ## License
285
+
286
+ MIT
287
+
288
+ ---
289
+
290
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -0,0 +1,24 @@
1
+ project(pdfviewer)
2
+ cmake_minimum_required(VERSION 3.9.0)
3
+
4
+ set(PACKAGE_NAME pdfviewer)
5
+ set(CMAKE_VERBOSE_MAKEFILE ON)
6
+ set(CMAKE_CXX_STANDARD 20)
7
+
8
+ # Define C++ library and add all sources
9
+ add_library(${PACKAGE_NAME} SHARED src/main/cpp/cpp-adapter.cpp)
10
+
11
+ # Add Nitrogen specs :)
12
+ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/pdfviewer+autolinking.cmake)
13
+
14
+ # Set up local includes
15
+ include_directories("src/main/cpp" "../cpp")
16
+
17
+ find_library(LOG_LIB log)
18
+
19
+ # Link all libraries together
20
+ target_link_libraries(
21
+ ${PACKAGE_NAME}
22
+ ${LOG_LIB}
23
+ android # <-- Android core
24
+ )
@@ -0,0 +1,121 @@
1
+ buildscript {
2
+ ext.PdfViewer = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36,
6
+ targetSdkVersion: 36,
7
+ ndkVersion: "27.1.12297006"
8
+ ]
9
+
10
+ ext.getExtOrDefault = { prop ->
11
+ if (rootProject.ext.has(prop)) {
12
+ return rootProject.ext.get(prop)
13
+ }
14
+
15
+ return PdfViewer[prop]
16
+ }
17
+
18
+ repositories {
19
+ google()
20
+ mavenCentral()
21
+ }
22
+
23
+ dependencies {
24
+ classpath "com.android.tools.build:gradle:8.7.2"
25
+ // noinspection DifferentKotlinGradleVersion
26
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
27
+ }
28
+ }
29
+
30
+ def reactNativeArchitectures() {
31
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
32
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
33
+ }
34
+
35
+ apply plugin: "com.android.library"
36
+ apply plugin: "kotlin-android"
37
+ apply from: '../nitrogen/generated/android/pdfviewer+autolinking.gradle'
38
+
39
+ apply plugin: "com.facebook.react"
40
+
41
+ android {
42
+ namespace "com.margelo.nitro.pdfviewer"
43
+
44
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
45
+ ndkVersion getExtOrDefault("ndkVersion")
46
+
47
+ defaultConfig {
48
+ minSdkVersion getExtOrDefault("minSdkVersion")
49
+ targetSdkVersion getExtOrDefault("targetSdkVersion")
50
+
51
+ externalNativeBuild {
52
+ cmake {
53
+ cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
54
+ arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
55
+ abiFilters (*reactNativeArchitectures())
56
+
57
+ buildTypes {
58
+ debug {
59
+ cppFlags "-O1 -g"
60
+ }
61
+ release {
62
+ cppFlags "-O2"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ externalNativeBuild {
70
+ cmake {
71
+ path "CMakeLists.txt"
72
+ }
73
+ }
74
+
75
+ packagingOptions {
76
+ excludes = [
77
+ "META-INF",
78
+ "META-INF/**",
79
+ "**/libc++_shared.so",
80
+ "**/libfbjni.so",
81
+ "**/libjsi.so",
82
+ "**/libfolly_json.so",
83
+ "**/libfolly_runtime.so",
84
+ "**/libglog.so",
85
+ "**/libhermes.so",
86
+ "**/libhermes-executor-debug.so",
87
+ "**/libhermes_executor.so",
88
+ "**/libreactnative.so",
89
+ "**/libreactnativejni.so",
90
+ "**/libturbomodulejsijni.so",
91
+ "**/libreact_nativemodule_core.so",
92
+ "**/libjscexecutor.so"
93
+ ]
94
+ }
95
+
96
+ buildFeatures {
97
+ buildConfig true
98
+ prefab true
99
+ }
100
+
101
+ buildTypes {
102
+ release {
103
+ minifyEnabled false
104
+ }
105
+ }
106
+
107
+ lint {
108
+ disable "GradleCompatible"
109
+ }
110
+
111
+ compileOptions {
112
+ sourceCompatibility JavaVersion.VERSION_1_8
113
+ targetCompatibility JavaVersion.VERSION_1_8
114
+ }
115
+ }
116
+
117
+ dependencies {
118
+ implementation "com.facebook.react:react-android"
119
+ implementation project(":react-native-nitro-modules")
120
+ implementation "androidx.recyclerview:recyclerview:1.3.2"
121
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,6 @@
1
+ #include <jni.h>
2
+ #include "pdfviewerOnLoad.hpp"
3
+
4
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
5
+ return margelo::nitro::pdfviewer::initialize(vm);
6
+ }
@@ -0,0 +1,169 @@
1
+ package com.margelo.nitro.pdfviewer
2
+
3
+ import android.view.View
4
+ import androidx.annotation.Keep
5
+ import com.facebook.proguard.annotations.DoNotStrip
6
+ import com.facebook.react.uimanager.ThemedReactContext
7
+
8
+ /**
9
+ * HybridPdfViewer that extends the Nitrogen-generated HybridPdfViewerSpec.
10
+ * This wraps DocumentViewer and connects it to the Nitro interface.
11
+ */
12
+ @DoNotStrip
13
+ @Keep
14
+ class HybridPdfViewer(private val reactContext: ThemedReactContext) : HybridPdfViewerSpec() {
15
+
16
+ companion object {
17
+ private const val TAG = "HybridPdfViewer"
18
+
19
+ init {
20
+ if (BuildConfig.DEBUG) {
21
+ android.util.Log.d(TAG, "HybridPdfViewer class initializing...")
22
+ }
23
+ // Load native library before HybridPdfViewerSpec is initialized
24
+ pdfviewerOnLoad.initializeNative()
25
+ if (BuildConfig.DEBUG) {
26
+ android.util.Log.d(TAG, "Native library loaded successfully")
27
+ }
28
+ }
29
+ }
30
+
31
+ private val documentViewer = PdfViewer(reactContext)
32
+
33
+ init {
34
+ if (BuildConfig.DEBUG) {
35
+ android.util.Log.d(TAG, "HybridPdfViewer instance created")
36
+ }
37
+ }
38
+
39
+ override val view: View
40
+ get() = documentViewer
41
+
42
+ // Connect DocumentViewer callbacks to Nitro callbacks
43
+ init {
44
+ documentViewer.onLoadCompleteCallback = { pageCount, pageWidth, pageHeight ->
45
+ onLoadComplete?.invoke(LoadCompleteEvent(
46
+ pageCount = pageCount.toDouble(),
47
+ pageWidth = pageWidth.toDouble(),
48
+ pageHeight = pageHeight.toDouble()
49
+ ))
50
+ }
51
+
52
+ documentViewer.onPageChangeCallback = { page, pageCount ->
53
+ onPageChange?.invoke(PageChangeEvent(
54
+ page = page.toDouble(),
55
+ pageCount = pageCount.toDouble()
56
+ ))
57
+ }
58
+
59
+ documentViewer.onScaleChangeCallback = { scale ->
60
+ onScaleChange?.invoke(ScaleChangeEvent(
61
+ scale = scale.toDouble()
62
+ ))
63
+ }
64
+
65
+ documentViewer.onErrorCallback = { message, code ->
66
+ onError?.invoke(ErrorEvent(
67
+ message = message,
68
+ code = code
69
+ ))
70
+ }
71
+
72
+ documentViewer.onThumbnailGeneratedCallback = { page, uri ->
73
+ onThumbnailGenerated?.invoke(ThumbnailGeneratedEvent(
74
+ page = page.toDouble(),
75
+ uri = uri
76
+ ))
77
+ }
78
+
79
+ documentViewer.onLoadingChangeCallback = { isLoading ->
80
+ onLoadingChange?.invoke(LoadingChangeEvent(
81
+ isLoading = isLoading
82
+ ))
83
+ }
84
+ }
85
+
86
+ // MARK: - Nitro Properties
87
+
88
+ override var source: String? = null
89
+ set(value) {
90
+ if (BuildConfig.DEBUG) {
91
+ android.util.Log.d("HybridPdfViewer", "Setting source: $value")
92
+ }
93
+ field = value
94
+ documentViewer.sourceUri = value
95
+ }
96
+
97
+ // Note: horizontal and enablePaging are iOS-only features, but we keep them
98
+ // here to match the interface. They have no effect on Android.
99
+ override var horizontal: Boolean? = null
100
+ set(value) {
101
+ field = value
102
+ // No-op on Android - always uses vertical scroll
103
+ }
104
+
105
+ override var enablePaging: Boolean? = null
106
+ set(value) {
107
+ field = value
108
+ // No-op on Android - paging not supported
109
+ }
110
+
111
+ override var spacing: Double? = null
112
+ set(value) {
113
+ field = value
114
+ value?.let { documentViewer.spacing = it.toFloat() }
115
+ }
116
+
117
+ override var enableZoom: Boolean? = null
118
+ set(value) {
119
+ field = value
120
+ value?.let { documentViewer.enableZoom = it }
121
+ }
122
+
123
+ override var minScale: Double? = null
124
+ set(value) {
125
+ field = value
126
+ value?.let { documentViewer.minScale = it.toFloat() }
127
+ }
128
+
129
+ override var maxScale: Double? = null
130
+ set(value) {
131
+ field = value
132
+ value?.let { documentViewer.maxScale = it.toFloat() }
133
+ }
134
+
135
+ override var showsActivityIndicator: Boolean? = null
136
+ set(value) {
137
+ field = value
138
+ value?.let { documentViewer.showsActivityIndicator = it }
139
+ }
140
+
141
+ // Event callbacks - these are set by Nitro
142
+ override var onLoadComplete: ((event: LoadCompleteEvent) -> Unit)? = null
143
+ override var onPageChange: ((event: PageChangeEvent) -> Unit)? = null
144
+ override var onScaleChange: ((event: ScaleChangeEvent) -> Unit)? = null
145
+ override var onError: ((event: ErrorEvent) -> Unit)? = null
146
+ override var onThumbnailGenerated: ((event: ThumbnailGeneratedEvent) -> Unit)? = null
147
+ override var onLoadingChange: ((event: LoadingChangeEvent) -> Unit)? = null
148
+
149
+ // MARK: - Nitro Methods
150
+
151
+ override fun goToPage(page: Double) {
152
+ documentViewer.goToPage(page.toInt())
153
+ }
154
+
155
+ override fun setScale(scale: Double) {
156
+ documentViewer.setScale(scale.toFloat())
157
+ }
158
+
159
+ override fun generateThumbnail(page: Double) {
160
+ if (BuildConfig.DEBUG) {
161
+ android.util.Log.d("HybridPdfViewer", "generateThumbnail called for page: $page")
162
+ }
163
+ documentViewer.generateThumbnail(page.toInt())
164
+ }
165
+
166
+ override fun generateAllThumbnails() {
167
+ documentViewer.generateAllThumbnails()
168
+ }
169
+ }