UNPKG

@b8safe/react-native-safe

Version:
324 lines (319 loc) 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _reactNativeSkia = require("@shopify/react-native-skia"); var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeWorkletsCore = require("react-native-worklets-core"); var _index = require("../index.js"); var _reactNativeReanimated = require("react-native-reanimated"); var _reactNativeVisionCamera = require("react-native-vision-camera"); var _PopIcon = _interopRequireDefault(require("../illustrations/icons/PopIcon.js")); var _ConnectionIcon = _interopRequireDefault(require("../illustrations/icons/ConnectionIcon.js")); var _styles = _interopRequireDefault(require("./styles.js")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const plugin = _reactNativeVisionCamera.VisionCameraProxy.initFrameProcessorPlugin('b8SafeProcessor', {}); const { width, height } = _reactNative.Dimensions.get('screen'); const CameraScreen = ({ hash, type, title, goBack, onError, children, onMessage, onSuccess, onFinishCall, titleStyle = { fontSize: 15, color: '#FFF' }, showConnectionStatus = true, messageTextStyle = { textAlign: 'center', fontSize: 19, color: '#FFF' } }) => { const { pc, stop, start, connected, datachannel, addDataChannelFunction, removeDataChannelFunction, changeStreamResolution } = (0, _index.useB8SafeService)() ?? {}; const layout = (0, _react.useRef)({ width: 0, height: 0, x: 0, y: 0 }); const { hasPermission, requestPermission } = (0, _reactNativeVisionCamera.useCameraPermission)(); let isMultiCamera = false; const cameraRef = (0, _react.useRef)(null); const [message, setMessage] = (0, _react.useState)(`Posicione ${type === 'front' ? 'a frente' : 'o verso'} do documento na moldura acima`); const renderHud = canvas => { const _width = layout.current.width; const _height = layout.current.height; const paint = _reactNativeSkia.Skia.Paint(); const color = _reactNativeSkia.Skia.Color(new Float32Array([0, 0, 0, 0.8])); paint.setColor(color); canvas.drawRect({ x: 0, y: 0, width: _width, height: _height }, paint); const transparentPaint = _reactNativeSkia.Skia.Paint(); transparentPaint.setColor(_reactNativeSkia.Skia.Color(new Float32Array([0, 0, 0, 0.8]))); transparentPaint.setBlendMode(_reactNativeSkia.BlendMode.Clear); const marginLeft = _width * 0.1; const marginTop = _height * 0.22; const w = _width * 0.8; const h = w * 1.3082; const _1 = { x: 30, y: 30 }; const _2 = { x: 30, y: 30 }; const _3 = { x: 30, y: 30 }; const _4 = { x: 30, y: 30 }; canvas.drawRRect({ topLeft: _1, topRight: _2, bottomRight: _3, bottomLeft: _4, rect: { x: marginLeft, y: marginTop, width: w, height: h } }, transparentPaint); }; const picture = (0, _reactNativeReanimated.useSharedValue)((0, _reactNativeSkia.createPicture)(renderHud)); const handleLayout = event => { if (children != null) return; layout.current = event.nativeEvent.layout; picture.value = (0, _reactNativeSkia.createPicture)(renderHud); }; const checkPermission = () => { if (!hasPermission) requestPermission(); setTimeout(() => { // setCameraReady(width); }, 500); }; const finishCall = data => { pc?.getSenders().forEach(sender => { sender.replaceTrack(null); }); if (onFinishCall != null) onFinishCall(data); if (data.success) { onSuccess != null && onSuccess(data); } else { stop?.(); onError != null && onError(data); } }; const upgradeResolution = data => { // console.log('upgradeResolution', data); changeStreamResolution?.(data); }; const _onMessage = data => { if (children != null) setMessage(data.message); if (onMessage != null) onMessage(data); }; const resolutionMultiplier = (0, _reactNativeWorkletsCore.useSharedValue)(0.1); //Usar 0.1 como default const currentRequestPhoto = (0, _reactNativeWorkletsCore.useSharedValue)(false); const lastFrameSent = (0, _reactNativeWorkletsCore.useSharedValue)(false); const requestStillPhoto = data => { currentRequestPhoto.value = data.requestId; if (typeof data.resolutionMultiplier === 'string') data.resolutionMultiplier = parseFloat(data.resolutionMultiplier); if (!isNaN(data.resolutionMultiplier)) { // console.log('requestStillPhoto setting received resolutionMultiplier as '+data.resolutionMultiplier); resolutionMultiplier.value = Number(data.resolutionMultiplier); } else { // console.log('requestStillPhoto setting default resolutionMultiplier as 0.1'); resolutionMultiplier.value = 0.1; } }; (0, _react.useEffect)(() => { if (hash !== '') start?.(hash, 'back'); addDataChannelFunction?.('onMessage', _onMessage); addDataChannelFunction?.('finishCall', finishCall); addDataChannelFunction?.('requestStillPhoto', requestStillPhoto); addDataChannelFunction?.('upgradeResolution', upgradeResolution); checkPermission(); return () => { removeDataChannelFunction?.('onMessage'); removeDataChannelFunction?.('finishCall'); removeDataChannelFunction?.('requestStillPhoto'); removeDataChannelFunction?.('upgradeResolution'); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const videoHeight = width * 16 / 9; const verticalSpace = (height - videoHeight) / 2; const breakString = (str, size) => { size = size ?? 60000; const breakStr = []; while (str.length > 0) { breakStr.push(str.substring(0, size)); str = str.substring(size, str.length); } return breakStr; }; const sendImageToServer = _reactNativeWorkletsCore.Worklets.createRunOnJS(base64Img => { if (currentRequestPhoto.value === lastFrameSent.value) return; // console.log('sendImageToServer:', base64Img.slice(0, 32), datachannel?.current?.readyState); if (datachannel?.readyState === 'open') { lastFrameSent.value = currentRequestPhoto.value; // const b64Len = base64Img.length; const parts = breakString(base64Img); const frameId = currentRequestPhoto.value; parts.forEach((item, index) => { const str = `${frameId}|${index}|${item}`; // if(index == 0) console.log(`${frameId}|${index}|${item}`); //console.log(str.substring(0, 30)); datachannel.send(str); }); const str = `${frameId}|-1|${parts.length}`; // console.log(str); datachannel.send(str); } }); let device; const cameraDevices = _reactNativeVisionCamera.Camera.getAvailableCameraDevices(); if (cameraDevices.length > 0) { const firstCameraDevice = cameraDevices[0]; // Você pode escolher qualquer câmera da lista, porem o ideal é a da posição [0] pois ela é a camera principal do dispositivo if (firstCameraDevice?.isMultiCam) { isMultiCamera = true; device = (0, _reactNativeVisionCamera.getCameraDevice)(cameraDevices, 'back', { physicalDevices: ['ultra-wide-angle-camera', 'wide-angle-camera', 'telephoto-camera'] }); } else { device = (0, _reactNativeVisionCamera.getCameraDevice)(cameraDevices, 'back'); } } else { console.warn('Nenhuma câmera disponível.'); } const frameProcessor = (0, _reactNativeVisionCamera.useFrameProcessor)(frame => { 'worklet'; (0, _reactNativeVisionCamera.runAtTargetFps)(4, () => { 'worklet'; if (currentRequestPhoto.value === false || currentRequestPhoto.value === lastFrameSent.value) { //Previne processamento se não estamos solicitando frames // console.log('prevented frame processing - resolutionMultiplier: '+resolutionMultiplier); return; } // console.log('frame will be processed - resolutionMultiplier: '+resolutionMultiplier); const base64String = plugin?.call(frame, { resolutionMultiplier: resolutionMultiplier.value }); // console.log('base64String', base64String.substring(0, 64)); sendImageToServer(base64String); }); }, [resolutionMultiplier, currentRequestPhoto, lastFrameSent, sendImageToServer]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.default.flex1, children: [device != null && hasPermission ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeVisionCamera.Camera, { style: _styles.default.cameraContainer, ref: cameraRef, frameProcessor: frameProcessor, zoom: isMultiCamera === true ? 2 : 0, isActive: true, focusable: true, device: device }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.absoluteFill }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.absoluteFill, onLayout: handleLayout, children: children != null ? children : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNativeSkia.Canvas, { style: _styles.default.cameraMask, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.Picture, { picture: picture }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.Rect, { x: 0, y: 0, width: width, height: verticalSpace + 70, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.LinearGradient, { start: (0, _reactNativeSkia.vec)(0, verticalSpace), end: (0, _reactNativeSkia.vec)(0, verticalSpace + 70), colors: ['rgb(0,0,0)', 'rgba(0,0,0,0)'] }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.Rect, { x: 0, y: verticalSpace + videoHeight - 70, width: width, height: verticalSpace + 70, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeSkia.LinearGradient, { start: (0, _reactNativeSkia.vec)(0, verticalSpace + videoHeight - 70), end: (0, _reactNativeSkia.vec)(0, verticalSpace + videoHeight), colors: ['rgba(0,0,0,0)', 'rgb(0,0,0)'] }) })] }) }), children != null ? null : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.default.cameraMaskContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: _styles.default.header, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.headerTitle, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: titleStyle, children: title ?? '' }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: _styles.default.padding30, onPress: goBack, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_PopIcon.default, { width: 20, height: 20, strokeWidth: 16, stroke: "#FFF" }) })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.flex1 }), message !== '' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.footer, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: messageTextStyle, children: message }) }) : null, showConnectionStatus ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: _styles.default.connectionStatusContainer, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConnectionIcon.default, { connected: connected }) }) : null] })] }); }; var _default = exports.default = CameraScreen; //# sourceMappingURL=Camera.js.map