UNPKG

react-native-pdf-jsi

Version:

🚀 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 c

412 lines (358 loc) • 13 kB
/** * Copyright (c) 2025-present, Enhanced PDF View with JSI * All rights reserved. * * Enhanced PDF View component that automatically uses JSI when available * Falls back to traditional bridge-based operations when JSI is not available */ import React, { Component } from 'react'; import { Platform, Alert } from 'react-native'; import Pdf from '../index'; import PDFJSI from './PDFJSI'; export default class EnhancedPdfView extends Component { constructor(props) { super(props); this.state = { isJSIAvailable: false, jsiInitialized: false, pdfData: null, renderMode: 'bridge' // 'bridge' or 'jsi' }; this.initializeJSI(); } /** * Initialize JSI availability check */ async initializeJSI() { try { if (Platform.OS === 'android') { const isAvailable = await PDFJSI.checkJSIAvailability(); this.setState({ isJSIAvailable: isAvailable, jsiInitialized: true, renderMode: isAvailable ? 'jsi' : 'bridge' }); if (isAvailable) { console.log('📱 EnhancedPdfView: JSI mode enabled - High performance mode active'); } else { console.log('📱 EnhancedPdfView: Bridge mode - Standard performance mode'); } } else { this.setState({ isJSIAvailable: false, jsiInitialized: true, renderMode: 'bridge' }); console.log('📱 EnhancedPdfView: iOS detected - Using bridge mode'); } } catch (error) { console.error('📱 EnhancedPdfView: Error initializing JSI:', error); this.setState({ isJSIAvailable: false, jsiInitialized: true, renderMode: 'bridge' }); } } /** * Render PDF page using JSI (high-performance) */ async renderPageWithJSI(pageNumber, scale = 1.0) { if (!this.state.isJSIAvailable) { throw new Error('JSI not available'); } try { const { source } = this.props; let base64Data = ''; // Handle different source types if (typeof source === 'string') { // Assume it's a URL or file path base64Data = source; } else if (source && source.uri) { base64Data = source.uri; } else { throw new Error('Invalid PDF source'); } const pdfId = `pdf_${Date.now()}`; const result = await PDFJSI.renderPageDirect(pdfId, pageNumber, scale, base64Data); if (result.success) { return result.data; } else { throw new Error(result.error || 'Failed to render page'); } } catch (error) { console.error('📱 EnhancedPdfView: JSI render error:', error); throw error; } } /** * Get page metrics using JSI */ async getPageMetricsWithJSI(pageNumber) { if (!this.state.isJSIAvailable) { throw new Error('JSI not available'); } try { const pdfId = `pdf_${Date.now()}`; const result = await PDFJSI.getPageMetrics(pdfId, pageNumber); if (result.success) { return result.data; } else { throw new Error(result.error || 'Failed to get page metrics'); } } catch (error) { console.error('📱 EnhancedPdfView: JSI metrics error:', error); throw error; } } /** * Preload pages using JSI */ async preloadPagesWithJSI(startPage, endPage) { if (!this.state.isJSIAvailable) { throw new Error('JSI not available'); } try { const pdfId = `pdf_${Date.now()}`; const success = await PDFJSI.preloadPagesDirect(pdfId, startPage, endPage); if (success) { console.log(`📱 EnhancedPdfView: Preloaded pages ${startPage}-${endPage} via JSI`); } else { throw new Error('Failed to preload pages'); } return success; } catch (error) { console.error('📱 EnhancedPdfView: JSI preload error:', error); throw error; } } /** * Search text using JSI */ async searchTextWithJSI(searchTerm, startPage = 1, endPage = 10) { if (!this.state.isJSIAvailable) { throw new Error('JSI not available'); } try { const pdfId = `pdf_${Date.now()}`; const results = await PDFJSI.searchTextDirect(pdfId, searchTerm, startPage, endPage); console.log(`📱 EnhancedPdfView: Found ${results.length} matches for '${searchTerm}' via JSI`); return results; } catch (error) { console.error('📱 EnhancedPdfView: JSI search error:', error); throw error; } } /** * Get performance metrics */ async getPerformanceMetrics() { try { const pdfId = `pdf_${Date.now()}`; const metrics = await PDFJSI.getPerformanceMetrics(pdfId); return metrics; } catch (error) { console.error('📱 EnhancedPdfView: Error getting performance metrics:', error); return null; } } /** * Get JSI statistics */ async getJSIStats() { try { const stats = await PDFJSI.getJSIStats(); return stats; } catch (error) { console.error('📱 EnhancedPdfView: Error getting JSI stats:', error); return null; } } /** * Clear cache */ async clearCache(cacheType = 'all') { try { const pdfId = `pdf_${Date.now()}`; const success = await PDFJSI.clearCacheDirect(pdfId, cacheType); if (success) { console.log(`📱 EnhancedPdfView: Cache cleared successfully (${cacheType})`); } return success; } catch (error) { console.error('📱 EnhancedPdfView: Error clearing cache:', error); return false; } } /** * Optimize memory */ async optimizeMemory() { try { const pdfId = `pdf_${Date.now()}`; const success = await PDFJSI.optimizeMemory(pdfId); if (success) { console.log('📱 EnhancedPdfView: Memory optimized successfully'); } return success; } catch (error) { console.error('📱 EnhancedPdfView: Error optimizing memory:', error); return false; } } /** * Set render quality */ async setRenderQuality(quality) { try { const pdfId = `pdf_${Date.now()}`; const success = await PDFJSI.setRenderQuality(pdfId, quality); if (success) { console.log(`📱 EnhancedPdfView: Render quality set to ${quality}`); } return success; } catch (error) { console.error('📱 EnhancedPdfView: Error setting render quality:', error); return false; } } /** * Show performance information */ showPerformanceInfo = async () => { try { const stats = await this.getJSIStats(); const metrics = await this.getPerformanceMetrics(); const message = `Render Mode: ${this.state.renderMode.toUpperCase()}\n` + `JSI Available: ${this.state.isJSIAvailable ? 'Yes' : 'No'}\n` + `Performance Level: ${stats?.performanceLevel || 'Standard'}\n` + `Direct Memory Access: ${stats?.directMemoryAccess ? 'Yes' : 'No'}`; Alert.alert('Enhanced PDF Performance', message); } catch (error) { Alert.alert('Performance Info', `Render Mode: ${this.state.renderMode.toUpperCase()}\nJSI Available: ${this.state.isJSIAvailable ? 'Yes' : 'No'}`); } }; /** * Lazy load pages for large PDF files */ lazyLoadPages = async (currentPage, preloadRadius = 3, totalPages = null) => { try { const pdfId = `pdf_${Date.now()}`; const result = await PDFJSI.lazyLoadPages(pdfId, currentPage, preloadRadius, totalPages); if (result.success) { console.log(`📱 EnhancedPdfView: Lazy loaded pages around ${currentPage} via JSI`); } return result; } catch (error) { console.error('📱 EnhancedPdfView: JSI lazy load error:', error); throw error; } }; /** * Progressive loading for large PDF files */ progressiveLoadPages = async (startPage = 1, batchSize = 5, onProgress = null) => { try { const pdfId = `pdf_${Date.now()}`; const result = await PDFJSI.progressiveLoadPages(pdfId, startPage, batchSize, onProgress); console.log(`📱 EnhancedPdfView: Progressive loaded ${result.totalLoaded} pages via JSI`); return result; } catch (error) { console.error('📱 EnhancedPdfView: JSI progressive load error:', error); throw error; } }; /** * Smart caching for frequently accessed pages */ smartCacheFrequentPages = async (frequentPages = []) => { try { const pdfId = `pdf_${Date.now()}`; const result = await PDFJSI.smartCacheFrequentPages(pdfId, frequentPages); console.log(`📱 EnhancedPdfView: Smart cached ${result.successfulCaches}/${result.totalPages} frequent pages via JSI`); return result; } catch (error) { console.error('📱 EnhancedPdfView: JSI smart cache error:', error); throw error; } }; render() { const { isJSIAvailable, jsiInitialized, renderMode } = this.state; // Add JSI-specific props to the PDF component const enhancedProps = { ...this.props, // Add JSI-specific props that can be used by the native component jsiEnabled: isJSIAvailable, renderMode: renderMode, // Add performance tracking props enablePerformanceTracking: true, // Add cache optimization props enableSmartCaching: isJSIAvailable, }; return ( <Pdf {...enhancedProps} ref={this.props.pdfRef} /> ); } } // Export additional utilities export const EnhancedPdfUtils = { /** * Check if JSI is available */ async isJSIAvailable() { try { return await PDFJSI.checkJSIAvailability(); } catch (error) { return false; } }, /** * Get performance benchmark */ async getPerformanceBenchmark() { try { const stats = await PDFJSI.getJSIStats(); const history = PDFJSI.getPerformanceHistory(); return { jsiAvailable: stats?.jsiEnabled || false, performanceLevel: stats?.performanceLevel || 'Standard', directMemoryAccess: stats?.directMemoryAccess || false, bridgeOptimized: stats?.bridgeOptimized || false, operationHistory: history }; } catch (error) { return { jsiAvailable: false, performanceLevel: 'Standard', directMemoryAccess: false, bridgeOptimized: false, operationHistory: [] }; } }, /** * Clear all caches */ async clearAllCaches() { try { const pdfId = `pdf_${Date.now()}`; return await PDFJSI.clearCacheDirect(pdfId, 'all'); } catch (error) { return false; } }, /** * Optimize all memory */ async optimizeAllMemory() { try { const pdfId = `pdf_${Date.now()}`; return await PDFJSI.optimizeMemory(pdfId); } catch (error) { return false; } } };