UNPKG

react-native-screenguard

Version:

A Native screenshot blocking library for React-Native developer, with background customizable after captured. Screenshot detector are also supported.

223 lines (219 loc) 9.12 kB
import { NativeEventEmitter, Platform, TurboModuleRegistry } from 'react-native'; import * as ScreenGuardConstants from './constant'; const NativeScreenGuard = TurboModuleRegistry.get('ScreenGuard'); const NativeSGScreenshot = TurboModuleRegistry.get('SGScreenshot'); const NativeSGScreenRecord = TurboModuleRegistry.get('SGScreenRecord'); var screenShotEmitter = new NativeEventEmitter(NativeSGScreenshot); var screenshotSubscription = null; var screenRecordingSubscription = null; var screenRecordingEmitter = new NativeEventEmitter(NativeSGScreenRecord); export default { /** * activate screenshot blocking with a color effect (iOS 13+, Android 8+) * @param data ScreenGuardColorData object * @version v0.0.2+ */ async register(data) { let { backgroundColor = ScreenGuardConstants.BLACK_COLOR, timeAfterResume = ScreenGuardConstants.TIME_DELAYED, } = data; let currentColor = backgroundColor.trim().length === 0 || !backgroundColor.trim().startsWith('#') || ScreenGuardConstants.REGEX.test(backgroundColor.trim().substring(1)) ? ScreenGuardConstants.BLACK_COLOR : data.backgroundColor; try { await NativeScreenGuard?.activateShield({ backgroundColor: currentColor, timeAfterResume, }); } catch (error) { console.error('Error register:', error); } }, /** * (Android only) activate screenshot and screen record blocking without * any effect (blur, image, color) on Android (Android 5+) * @version v1.0.0+ */ async registerWithoutEffect() { if (Platform.OS === 'android') { await NativeScreenGuard?.activateShieldWithoutEffect(); } }, /** * Activate screenshot blocking with a blur effect after captured (iOS 13+, Android 8+) * @param data ScreenGuardBlurDataObject data object * @version v0.1.2+ */ async registerWithBlurView(data) { const { radius = ScreenGuardConstants.RADIUS_DEFAULT, timeAfterResume = ScreenGuardConstants.TIME_DELAYED, } = data; if (typeof radius !== 'number') { throw new Error('radius must be a number and bigger than 1'); } if (radius < 1) { throw new Error('radius must bigger than 1!'); } if (radius >= 1 && radius < 15) { console.warn('Consider a radius value bigger than 15, as content still very clear and easy to read!'); } if (radius > 50) { console.warn('Consider a radius value in between 15 and 50, as blur contents may vanish inside the view!'); } if (Platform.OS === 'android' && timeAfterResume > 3000) { console.warn('Consider a number in between 1000 and 3000 for better user experience!'); } if (Platform.OS === 'android' && (timeAfterResume < 0 || isNaN(timeAfterResume))) { throw new Error('timeAfterResume must be > 0!'); } try { await NativeScreenGuard?.activateShieldWithBlurView({ radius, timeAfterResume, }); } catch (error) { console.error('Error registerWithBlurView:', error); } }, /** * activate with an Image uri (iOS 13+, Android 8+) * @param data ScreenGuardImageDataObject data object, * @version v1.0.2+ */ async registerWithImage(data) { let { source, width, height, top, left, bottom, right, backgroundColor = ScreenGuardConstants.BLACK_COLOR, alignment, timeAfterResume = ScreenGuardConstants.TIME_DELAYED, defaultSource, } = data; let newDefaultSource = null; if (typeof source === 'object' && 'uri' in source) { if (source.uri.length === 0) { throw new Error('uri must not be empty!'); } if (width < 1 || isNaN(width)) { throw new Error('width of image must bigger than 0!'); } if (height < 1 || isNaN(height)) { throw new Error('height of image must bigger than 0!'); } if (!ScreenGuardConstants.IMAGE_REGEX.test(source.uri)) { console.warn('Looks like the uri is not an image uri. Try to provide a correct image uri for better result!'); } } else if (typeof source === 'number') { source = { uri: ScreenGuardConstants.resolveAssetSource(data.source) }; } if (defaultSource == null) { console.warn('Consider adding a default source to display image that cannot be loaded from uri!'); newDefaultSource = { uri: ScreenGuardConstants.resolveAssetSource(require('../images/screenshot_blocking.webp')), }; } else { newDefaultSource = { uri: ScreenGuardConstants.resolveAssetSource(data.source), }; } if (alignment != null && (alignment > 8 || alignment < 0 || isNaN(alignment))) { throw new Error('alignment must be in range from 0 -> 8 only, values: \n topLeft: 0; \n topCenter: 1; \n topRight: 2; \n centerLeft: 3; \n Center: 4; \n centerRight: 5; \n bottomLeft: 6; \n bottomCenter: 7;\n bottomRight: 8; \n If you want to center the image, leave null instead!'); } if (alignment == null && ((top == null && left == null && bottom == null && right == null) || Platform.OS === 'android')) { alignment = ScreenGuardConstants.Alignment.center; } try { await NativeScreenGuard?.activateShieldWithImage({ source, defaultSource: newDefaultSource, width, height, top, left, bottom, right, alignment, backgroundColor, timeAfterResume, }); } catch (error) { console.error('Error registerWithImage:', error); } }, /** * Deactivate screenguard * Clear all screen protector and event listening * @version v0.0.2+ */ async unregister() { try { await NativeScreenGuard?.deactivateShield(); } catch (error) { console.error('Error unregister:', error); } }, /** * Screenshot event listener * Register for screenshot event listener * @param getScreenShotPath if true, callback will return a ScreenGuardScreenShotPathDataObject containing info of an image after captured, null otherwise. Default = false * @param callback callback after a screenshot has been triggered. * @version v0.3.6+ */ registerScreenshotEventListener(getScreenShotPath, callback) { NativeSGScreenshot?.registerScreenshotEventListener(getScreenShotPath); const _onScreenCapture = (res) => { callback(res); }; screenshotSubscription = screenShotEmitter?.addListener(ScreenGuardConstants.SCREENSHOT_EVT, _onScreenCapture); return () => this.removeScreenshotEventListener(); }, /** * Screen recording event listener (iOS only) * Register for screen recording event listener * @version v0.3.6+ */ registerScreenRecordingEventListener(getScreenRecordStatus, callback) { if (Platform.OS === 'android') { console.warn('Screen recording event listener is only available on iOS!'); return; } NativeSGScreenRecord?.registerScreenRecordingEventListener(getScreenRecordStatus ?? false); const _onScreenRecording = (res) => { callback(res); }; screenRecordingSubscription = screenRecordingEmitter?.addListener(ScreenGuardConstants.SCREEN_RECORDING_EVT, _onScreenRecording); return () => this.removeRecordingEventListener(); }, /** * Remove screen recording event listener * @version v1.0.8+ */ removeRecordingEventListener() { if (Platform.OS === 'android') { console.warn('Screen recording event listener is only available on iOS!'); return; } NativeSGScreenRecord?.removeScreenRecordingEventListener(); // screenRecordingEmitter?.removeAllListeners( // ScreenGuardConstants.SCREEN_RECORDING_EVT // ); if (screenRecordingSubscription != null) { screenRecordingSubscription.remove(); screenRecordingSubscription = null; } }, /** * Remove screenshot event listener * @version v1.0.8+ */ removeScreenshotEventListener() { NativeSGScreenshot?.removeScreenshotEventListener(); // screenShotEmitter?.removeAllListeners(ScreenGuardConstants.SCREENSHOT_EVT); if (screenshotSubscription != null) { screenshotSubscription.remove(); screenshotSubscription = null; } }, }; export { ScreenGuardConstants };