import SessionRecorderNative, { type MaskingOptions, } from '../native/SessionRecorderNative' import { logger } from '../utils' export interface ScreenRecordingConfig { /** Whether screen masking is enabled */ enabled: boolean /** Whether to mask text inputs (UITextField, UITextView, React Native text components) */ maskTextInputs?: boolean /** Whether to mask images (UIImageView, React Native Image components) */ maskImages?: boolean /** Whether to mask buttons (UIButton) */ maskButtons?: boolean /** Whether to mask labels (UILabel) */ maskLabels?: boolean /** Whether to mask web views (WKWebView) */ maskWebViews?: boolean /** Whether to mask sandboxed views (system views that don't belong to current process) */ maskSandboxedViews?: boolean } export class ScreenRecordingService { private config: ScreenRecordingConfig private isAvailable: boolean = false constructor( config: ScreenRecordingConfig = { enabled: true, maskTextInputs: true, maskImages: false, maskButtons: false, maskLabels: false, maskWebViews: false, maskSandboxedViews: false, }, ) { this.config = config this.checkAvailability() } /** * Check if the native masking module is available */ private checkAvailability(): void { try { // Try to access the native module to check if it's available if ( SessionRecorderNative && typeof SessionRecorderNative.captureAndMask === 'function' ) { this.isAvailable = true logger.info( 'ScreenRecordingService', 'Screen masking native module is available', ) } else { this.isAvailable = false logger.warn( 'ScreenRecordingService', 'Screen masking native module is not available - auto-linking may still be in progress', ) } } catch (error) { this.isAvailable = false logger.error( 'ScreenRecordingService', 'Error checking screen masking availability:', error, ) } } /** * Capture screen with masking applied */ async captureMaskedScreen(options: MaskingOptions): Promise { if (!this.isAvailable || !this.config.enabled) { logger.warn( 'ScreenRecordingService', 'Screen masking is not available or disabled', ) return null } try { const maskingOptions: MaskingOptions = { ...this.config, ...options, } const maskedImageBase64 = await SessionRecorderNative.captureAndMaskWithOptions(maskingOptions) return maskedImageBase64 } catch (error) { logger.error( 'ScreenRecordingService', 'Failed to capture masked screen:', error, ) return null } } /** * Capture screen with basic masking (no custom options) */ async captureMaskedScreenBasic(): Promise { if (!this.isAvailable || !this.config.enabled) { logger.warn( 'ScreenRecordingService', 'Screen masking is not available or disabled', ) return null } try { const maskedImageBase64 = await SessionRecorderNative.captureAndMask() return maskedImageBase64 } catch (error) { logger.error( 'ScreenRecordingService', 'Failed to capture masked screen (basic):', error, ) return null } } /** * Update the masking configuration */ updateConfig(config: Partial): void { this.config = { ...this.config, ...config } logger.info( 'ScreenRecordingService', 'Screen masking configuration updated', ) } /** * Check if screen masking is available */ isScreenRecordingAvailable(): boolean { return this.isAvailable && this.config.enabled } /** * Get the current configuration */ getConfig(): ScreenRecordingConfig { return { ...this.config } } } // Create a singleton instance export const screenRecordingService = new ScreenRecordingService()