react-native-optimized-pdf 1.0.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/.eslintrc.js ADDED
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['@react-native-community'],
4
+ parser: '@typescript-eslint/parser',
5
+ plugins: ['@typescript-eslint'],
6
+ rules: {
7
+ 'react-hooks/exhaustive-deps': 'warn',
8
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
9
+ 'react-native/no-inline-styles': 'off',
10
+ },
11
+ };
package/.prettierrc.js ADDED
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ arrowParens: 'always',
3
+ bracketSameLine: false,
4
+ bracketSpacing: true,
5
+ singleQuote: true,
6
+ trailingComma: 'all',
7
+ semi: true,
8
+ tabWidth: 2,
9
+ printWidth: 100,
10
+ };
package/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - Modular architecture with separated concerns
13
+ - `PdfCacheService` for advanced cache management
14
+ - `PdfNavigationControls` as standalone component
15
+ - `PdfLoadingOverlay` and `PdfErrorOverlay` components
16
+ - `showNavigationControls` prop to hide/show built-in controls
17
+ - `onPageChange` callback for page change events
18
+ - Comprehensive TypeScript types in `/src/types`
19
+ - JSDoc comments for better IDE support
20
+ - Cache utility methods (clearCache, clearAllCache, getCacheSize)
21
+ - Accessibility labels for navigation controls
22
+
23
+ ### Changed
24
+
25
+ - Refactored component structure for better maintainability
26
+ - Improved error handling and messaging
27
+ - Better TypeScript type exports
28
+ - Enhanced documentation with more examples
29
+ - Cleaner imports using ES6 modules consistently
30
+
31
+ ### Fixed
32
+
33
+ - Memory leaks in useEffect cleanup
34
+ - Proper file:// protocol handling
35
+ - Cache validation logic
@@ -0,0 +1,91 @@
1
+ # Contributing to React Native Optimized PDF
2
+
3
+ Thank you for considering contributing to this project! Here are some guidelines to help you get started.
4
+
5
+ ## Development Setup
6
+
7
+ 1. Clone the repository
8
+
9
+ ```bash
10
+ git clone https://github.com/yourusername/react-native-optimized-pdf.git
11
+ cd react-native-optimized-pdf
12
+ ```
13
+
14
+ 2. Install dependencies
15
+
16
+ ```bash
17
+ yarn install
18
+ ```
19
+
20
+ 3. Install pods (iOS)
21
+
22
+ ```bash
23
+ cd ios && pod install
24
+ ```
25
+
26
+ ## Project Structure
27
+
28
+ ```
29
+ react-native-optimized-pdf/
30
+ ├── src/
31
+ │ ├── components/ # Reusable UI components
32
+ │ │ ├── PdfNavigationControls.tsx
33
+ │ │ └── PdfOverlays.tsx
34
+ │ ├── services/ # Business logic and utilities
35
+ │ │ └── pdfCache.ts
36
+ │ ├── types/ # TypeScript type definitions
37
+ │ │ └── index.ts
38
+ │ ├── constants.ts # App constants
39
+ │ ├── OptimizedPdfView.tsx # Main component
40
+ │ └── index.ts # Public exports
41
+ ├── ios/ # Native iOS implementation
42
+ ├── index.ts # Package entry point
43
+ └── index.d.ts # TypeScript declarations
44
+ ```
45
+
46
+ ## Code Style
47
+
48
+ - Use TypeScript for all new code
49
+ - Follow the existing code style (use Prettier and ESLint)
50
+ - Add JSDoc comments for public APIs
51
+ - Write meaningful commit messages
52
+
53
+ ## Testing
54
+
55
+ Before submitting a PR:
56
+
57
+ 1. Test on a real iOS device or simulator
58
+ 2. Verify TypeScript types compile without errors
59
+ 3. Check that all exports work correctly
60
+ 4. Test with various PDF sources (local, remote, large files)
61
+
62
+ ## Pull Request Process
63
+
64
+ 1. Fork the repository
65
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
66
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
67
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
68
+ 5. Open a Pull Request
69
+
70
+ ## Reporting Issues
71
+
72
+ When reporting issues, please include:
73
+
74
+ - React Native version
75
+ - iOS version
76
+ - Device/simulator information
77
+ - Steps to reproduce
78
+ - Expected vs actual behavior
79
+ - Error messages or logs
80
+
81
+ ## Feature Requests
82
+
83
+ We welcome feature requests! Please open an issue and describe:
84
+
85
+ - The use case
86
+ - Why this would be useful
87
+ - Any implementation ideas
88
+
89
+ ## License
90
+
91
+ By contributing, you agree that your contributions will be licensed under the MIT License.
package/README.md ADDED
@@ -0,0 +1,302 @@
1
+ # React Native Optimized PDF
2
+
3
+ High-performance PDF viewer for React Native with optimized memory usage. Uses CATiledLayer on iOS and PdfRenderer on Android for smooth rendering with automatic caching.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Optimized memory usage** with CATiledLayer (iOS) and PdfRenderer (Android)
8
+ - 📦 **Automatic caching** with configurable expiration
9
+ - 📱 **Smooth zoom and scroll** with customizable maximum zoom
10
+ - 🎯 **Built-in page navigation** with optional custom controls
11
+ - 📊 **Comprehensive event callbacks** for load, error, and page events
12
+ - 🎨 **High-quality rendering** with antialiasing support
13
+ - 📈 **Download progress tracking** for remote PDFs
14
+ - ⚡ **TypeScript support** with full type definitions
15
+ - 🔧 **Modular architecture** with exportable utilities
16
+ - 🤖 **Cross-platform** support for iOS and Android
17
+ - 🔒 **Password-protected PDF** support
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install react-native-optimized-pdf
23
+ # or
24
+ yarn add react-native-optimized-pdf
25
+ ```
26
+
27
+ ### iOS Setup
28
+
29
+ ```bash
30
+ cd ios && pod install
31
+ ```
32
+
33
+ ### Android Setup
34
+
35
+ No additional setup required! The module will be automatically linked.
36
+
37
+ ## Usage
38
+
39
+ ### Basic Example
40
+
41
+ ```tsx
42
+ import OptimizedPdfView from 'react-native-optimized-pdf';
43
+
44
+ function App() {
45
+ return (
46
+ <OptimizedPdfView source={{ uri: 'https://example.com/sample.pdf' }} style={{ flex: 1 }} />
47
+ );
48
+ }
49
+ ```
50
+
51
+ ### Advanced Example with All Options
52
+
53
+ ```tsx
54
+ import OptimizedPdfView from 'react-native-optimized-pdf';
55
+
56
+ function App() {
57
+ return (
58
+ <OptimizedPdfView
59
+ source={{
60
+ uri: 'https://example.com/sample.pdf',
61
+ cache: true,
62
+ cacheFileName: 'my-custom-file.pdf',
63
+ expiration: 86400, // 24 hours in seconds
64
+ headers: {
65
+ Authorization: 'Bearer token',
66
+ },
67
+ }}
68
+ maximumZoom={5}
69
+ enableAntialiasing={true}
70
+ showNavigationControls={true}
71
+ style={{ flex: 1 }}
72
+ onLoadComplete={(page, dimensions) => {
73
+ console.log(`Loaded page ${page}`, dimensions);
74
+ }}
75
+ onPageCount={(count) => {
76
+ console.log(`Total pages: ${count}`);
77
+ }}
78
+ onPageChange={(page) => {
79
+ console.log(`Changed to page ${page}`);
80
+ }}
81
+ onError={(error) => {
82
+ console.error('PDF Error:', error.nativeEvent.message);
83
+ }}
84
+ />
85
+ );
86
+ }
87
+ ```
88
+
89
+ ### Password Protected PDF
90
+
91
+ ```tsx
92
+ import OptimizedPdfView from 'react-native-optimized-pdf';
93
+ import { useState } from 'react';
94
+
95
+ function App() {
96
+ const [password, setPassword] = useState('');
97
+ const [showPasswordPrompt, setShowPasswordPrompt] = useState(false);
98
+
99
+ return (
100
+ <>
101
+ <OptimizedPdfView
102
+ source={{ uri: 'https://example.com/protected.pdf' }}
103
+ password={password}
104
+ onPasswordRequired={() => {
105
+ setShowPasswordPrompt(true);
106
+ }}
107
+ onError={(error) => {
108
+ if (error.nativeEvent.message.includes('Invalid password')) {
109
+ alert('Wrong password, please try again');
110
+ }
111
+ }}
112
+ style={{ flex: 1 }}
113
+ />
114
+ {/* Your password input modal */}
115
+ </>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ### Custom Navigation Controls
121
+
122
+ ```tsx
123
+ import OptimizedPdfView from 'react-native-optimized-pdf';
124
+ import { useState } from 'react';
125
+ import { View, Text } from 'react-native';
126
+
127
+ function App() {
128
+ const [currentPage, setCurrentPage] = useState(0);
129
+ const [totalPages, setTotalPages] = useState(1);
130
+
131
+ return (
132
+ <View style={{ flex: 1 }}>
133
+ <OptimizedPdfView
134
+ source={{ uri: 'https://example.com/sample.pdf' }}
135
+ showNavigationControls={false}
136
+ onPageCount={setTotalPages}
137
+ onPageChange={setCurrentPage}
138
+ style={{ flex: 1 }}
139
+ />
140
+
141
+ {/* Your custom navigation UI */}
142
+ <Text>
143
+ Page {currentPage + 1} of {totalPages}
144
+ </Text>
145
+ </View>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ### Using Cache Service Directly
151
+
152
+ ```tsx
153
+ import { PdfCacheService } from 'react-native-optimized-pdf';
154
+
155
+ // Clear specific cache
156
+ await PdfCacheService.clearCache({ uri: 'https://example.com/file.pdf' });
157
+
158
+ // Clear all cached PDFs
159
+ await PdfCacheService.clearAllCache();
160
+
161
+ // Get cache size in bytes
162
+ const size = await PdfCacheService.getCacheSize();
163
+ console.log(`Cache size: ${size / 1024 / 1024} MB`);
164
+
165
+ // Check if cache is valid
166
+ const isValid = await PdfCacheService.isCacheValid({
167
+ uri: 'https://example.com/file.pdf',
168
+ expiration: 3600,
169
+ });
170
+ ```
171
+
172
+ ## API Reference
173
+
174
+ ### OptimizedPdfView Props
175
+
176
+ | Prop | Type | Default | Description |
177
+ | ------------------------ | ------------------------------------------------------- | ------------ | -------------------------------------- |
178
+ | `source` | `PdfSource` | **required** | PDF source configuration |
179
+ | `password` | `string` | - | Password for encrypted PDF files |
180
+ | `maximumZoom` | `number` | `3` | Maximum zoom level |
181
+ | `enableAntialiasing` | `boolean` | `true` | Enable antialiasing for better quality |
182
+ | `showNavigationControls` | `boolean` | `true` | Show built-in navigation controls |
183
+ | `style` | `ViewStyle` | - | Container style |
184
+ | `onLoadComplete` | `(page: number, dimensions: PdfPageDimensions) => void` | - | Called when PDF loads |
185
+ | `onPageCount` | `(count: number) => void` | - | Called when page count is available |
186
+ | `onPageChange` | `(page: number) => void` | - | Called when page changes |
187
+ | `onError` | `(error: PdfErrorEvent) => void` | - | Called on error |
188
+ | `onPasswordRequired` | `() => void` | - | Called when PDF requires a password |
189
+
190
+ ### PdfSource
191
+
192
+ | Property | Type | Default | Description |
193
+ | --------------- | ------------------------ | ------------ | ------------------------------------------------------------ |
194
+ | `uri` | `string` | **required** | PDF file URI (remote URL or local path) |
195
+ | `cache` | `boolean` | `true` | Enable local caching |
196
+ | `cacheFileName` | `string` | MD5 of URI | Custom filename for cached file |
197
+ | `expiration` | `number` | - | Cache expiration in seconds (0 or undefined = no expiration) |
198
+ | `headers` | `Record<string, string>` | - | HTTP headers for download |
199
+
200
+ ### PdfCacheService
201
+
202
+ Static methods for managing PDF cache:
203
+
204
+ - `getCacheFilePath(source: PdfSource): string` - Get local cache path
205
+ - `isCacheValid(source: PdfSource): Promise<boolean>` - Check if cache is valid
206
+ - `downloadPdf(source: PdfSource, onProgress?: (percent: number) => void): Promise<string>` - Download and cache PDF
207
+ - `clearCache(source: PdfSource): Promise<void>` - Clear specific cached file
208
+ - `clearAllCache(): Promise<void>` - Clear all cached PDFs
209
+ - `getCacheSize(): Promise<number>` - Get total cache size in bytes
210
+
211
+ ## Components
212
+
213
+ ### PdfNavigationControls
214
+
215
+ Reusable navigation controls component:
216
+
217
+ ```tsx
218
+ import { PdfNavigationControls } from 'react-native-optimized-pdf';
219
+
220
+ <PdfNavigationControls
221
+ currentPage={0}
222
+ totalPages={10}
223
+ onNextPage={() => {}}
224
+ onPrevPage={() => {}}
225
+ onPageChange={(page) => {}}
226
+ />;
227
+ ```
228
+
229
+ ### PdfLoadingOverlay
230
+
231
+ Loading state component with progress:
232
+
233
+ ```tsx
234
+ import { PdfLoadingOverlay } from 'react-native-optimized-pdf';
235
+
236
+ <PdfLoadingOverlay progress={75} />;
237
+ ```
238
+
239
+ ### PdfErrorOverlay
240
+
241
+ Error state component:
242
+
243
+ ```tsx
244
+ import { PdfErrorOverlay } from 'react-native-optimized-pdf';
245
+
246
+ <PdfErrorOverlay error="Failed to load PDF" />;
247
+ ```
248
+
249
+ ## Platform Support
250
+
251
+ | Platform | Supported | Min Version |
252
+ | -------- | --------- | ----------- |
253
+ | iOS | ✅ Yes | iOS 12.0+ |
254
+ | Android | ✅ Yes | API 24+ |
255
+
256
+ ## Performance Tips
257
+
258
+ 1. **Enable caching** for remote PDFs to avoid re-downloading
259
+ 2. **Set cache expiration** for frequently updated documents
260
+ 3. **Use custom cache filenames** for better cache management
261
+ 4. **Monitor cache size** and clear old files periodically
262
+ 5. **Adjust maximum zoom** based on your needs (lower = better performance)
263
+ 6. **Hide navigation controls** if implementing custom UI
264
+
265
+ ## Troubleshooting
266
+
267
+ ### PDF not loading
268
+
269
+ - Check that the URI is accessible
270
+ - Verify network permissions for remote URLs
271
+ - Check console for error messages
272
+ - Ensure file format is valid PDF
273
+
274
+ ### High memory usage
275
+
276
+ - Reduce `maximumZoom` value
277
+ - Clear cache periodically
278
+ - Use smaller PDF files when possible
279
+
280
+ ### Cache not working
281
+
282
+ - Verify write permissions
283
+ - Check available storage space
284
+ - Ensure `cache` is not set to `false`
285
+
286
+ ### Password protected PDF not opening
287
+
288
+ - Use `onPasswordRequired` callback to prompt user for password
289
+ - Pass the password via the `password` prop
290
+ - Check for "Invalid password" in error message to show retry prompt
291
+
292
+ ## License
293
+
294
+ MIT
295
+
296
+ ## Contributing
297
+
298
+ Contributions are welcome! Please open an issue or submit a pull request.
299
+
300
+ ## Author
301
+
302
+ Created with ❤️ for the React Native community
@@ -0,0 +1,21 @@
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 = "ReactNativeOptimizedPdf"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.description = <<-DESC
10
+ High-performance PDF viewer for React Native
11
+ DESC
12
+ s.homepage = "https://github.com/your-username/react-native-optimized-pdf"
13
+ s.license = "MIT"
14
+ s.author = { "Your Name" => "your-email@example.com" }
15
+ s.platform = :ios, "12.0"
16
+ s.source = { :git => "https://github.com/your-username/react-native-optimized-pdf.git", :tag => "#{s.version}" }
17
+ s.source_files = "ios/*.{swift,h,m}"
18
+ s.requires_arc = true
19
+ s.swift_version = "5.0"
20
+ s.dependency "React-Core"
21
+ end
@@ -0,0 +1,57 @@
1
+ buildscript {
2
+ ext.safeExtGet = {prop, fallback ->
3
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
4
+ }
5
+ repositories {
6
+ google()
7
+ mavenCentral()
8
+ }
9
+ dependencies {
10
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', '1.9.0')}")
11
+ }
12
+ }
13
+
14
+ apply plugin: 'com.android.library'
15
+ apply plugin: 'kotlin-android'
16
+
17
+ android {
18
+ namespace "com.reactnativeoptimizedpdf"
19
+ compileSdkVersion safeExtGet('compileSdkVersion', 36)
20
+
21
+ defaultConfig {
22
+ minSdkVersion safeExtGet('minSdkVersion', 24)
23
+ targetSdkVersion safeExtGet('targetSdkVersion', 36)
24
+ }
25
+
26
+ buildTypes {
27
+ release {
28
+ minifyEnabled false
29
+ }
30
+ }
31
+
32
+ compileOptions {
33
+ sourceCompatibility JavaVersion.VERSION_17
34
+ targetCompatibility JavaVersion.VERSION_17
35
+ }
36
+
37
+ kotlinOptions {
38
+ jvmTarget = '17'
39
+ }
40
+
41
+ sourceSets {
42
+ main {
43
+ java.srcDirs = ['src/main/kotlin']
44
+ }
45
+ }
46
+ }
47
+
48
+ repositories {
49
+ google()
50
+ mavenCentral()
51
+ }
52
+
53
+ dependencies {
54
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:${safeExtGet('kotlinVersion', '1.9.0')}"
55
+ implementation "com.facebook.react:react-android:+"
56
+ implementation "com.tom-roush:pdfbox-android:2.0.27.0"
57
+ }
@@ -0,0 +1,10 @@
1
+ # React Native Optimized PDF - ProGuard Rules
2
+
3
+ # Keep the native view classes
4
+ -keep class com.reactnativeoptimizedpdf.** { *; }
5
+
6
+ # Keep React Native classes
7
+ -keep class com.facebook.react.** { *; }
8
+
9
+ # Keep PDF Renderer
10
+ -keep class android.graphics.pdf.** { *; }
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.reactnativeoptimizedpdf">
3
+ </manifest>