@b8safe/react-native-safe
Version:
Package for native integration of B8Safe SDK
324 lines (319 loc) • 12.8 kB
JavaScript
;
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