Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 86 additions & 12 deletions packages/camera/src/components/Capture/capture.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { utils } from '@monkvision/toolkit';
import { useMonitoring, MonitoringStatus, SentryTransaction, SentryOperation, SentryTag } from '@monkvision/corejs';
import PropTypes from 'prop-types';
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
import React, { forwardRef, useCallback, useEffect, useRef, useImperativeHandle, useMemo, useState } from 'react';

import { useTranslation } from 'react-i18next';
import { ActivityIndicator, Platform, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
Expand Down Expand Up @@ -122,9 +123,6 @@ const Capture = forwardRef(({
onPictureTaken,
onWarningMessage,
onReady,
onRetakeAll,
onRetakeNeeded,
onSkipRetake,
onStartUploadPicture,
onFinishUploadPicture,
orientationBlockerProps,
Expand Down Expand Up @@ -156,7 +154,9 @@ const Capture = forwardRef(({
});
const [endTour, setEndTour] = useState(false);
const { height, width } = useWindowDimensions();
const { errorHandler, measurePerformance } = useMonitoring();

const captureTourTransRef = useRef({});
const { camera, ref } = combinedRefs.current;
const { current } = sights.state;
const portraitMediaQuery = useMediaQuery({ query: '(orientation: portrait)' });
Expand Down Expand Up @@ -244,14 +244,25 @@ const Capture = forwardRef(({

const checkComplianceParams = { compliance, inspectionId, sightId: current.id };
const checkComplianceAsync = useCheckComplianceAsync(checkComplianceParams);
const handleCaptureTourFinish = useCallback(() => {
/**
* finish 'capture tour' transaction successfully
* this function will be triggered when 'capture tour' ends
*/
if (!enableComplianceCheck) {
utils.log(['[Event] Capture-Tour sentry transaction finishes']);
captureTourTransRef.current.transaction.finish();
}
onCaptureTourFinish();
}, []);
const startUploadAsyncParams = {
inspectionId,
sights,
uploads,
task,
mapTasksToSights,
enableCarCoverage,
onFinish: onCaptureTourFinish,
onFinish: handleCaptureTourFinish,
onPictureUploaded,
onWarningMessage,
endTour,
Expand Down Expand Up @@ -348,6 +359,9 @@ const Capture = forwardRef(({
if (typeof onCloseEarly === 'function') {
onCloseEarly();
}
// finish 'capture tour' transaction unsuccessfully
utils.log(['[Event] Capture-Tour sentry transaction cancels']);
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
setEndTour(true);
}, [setEndTour]);

Expand Down Expand Up @@ -377,14 +391,80 @@ const Capture = forwardRef(({
handleCloseCaptureEarly();
}, [setCloseEarlyModalState, handleCloseCaptureEarly]);

const handleComplianceCheckFinish = useCallback(() => {
/**
* finish 'capture tour' transaction successfully
* this function will be triggered only when
* enableComplianceCheck = true and UploadCenter component is rendered
*/
utils.log(['[Event] Capture-Tour sentry transaction finishes']);
captureTourTransRef.current.transaction.finish();
onComplianceCheckFinish();
}, []);

const onRetakeAll = useCallback(() => {
captureTourTransRef.current.hasRetakeCalled = true;
captureTourTransRef.current.transaction.setTag(SentryTag.IS_RETAKE, 1);
}, []);

const onSkipRetake = useCallback(() => {
captureTourTransRef.current.transaction.setTag(SentryTag.IS_SKIP, 1);
}, []);

const onRetakeNeeded = useCallback(({ retakesNeeded = 0 }) => {
if (!captureTourTransRef.current.hasRetakeCalled) {
const { transaction } = captureTourTransRef.current;
const percentOfNonCompliancePics = ((100 * retakesNeeded) / states.sights.state.ids.length);
transaction.setTag(SentryTag.RETAKEN_PICTURES, retakesNeeded);
transaction.setTag(SentryTag.PERCENT_OF_NON_COMPLIANCE_PICS, percentOfNonCompliancePics);
}
}, []);

// END HANDLERS //
// EFFECTS //

useEffect(() => {
/**
* create a new transaction with operation name 'Capture Tour' to measure tour performance
*/
utils.log(['[Event] Capture-Tour sentry transaction starts']);
const transaction = measurePerformance(
SentryTransaction.PICTURE_PROCESSING,
SentryOperation.CAPTURE_TOUR,
);
// set tags to identify a transation and relate with an inspection
transaction.setTag(SentryTag.TASK, task);
transaction.setTag(SentryTag.INSPECTION_ID, inspectionId);
transaction.setTag(SentryTag.IS_SKIP, 0);
transaction.setTag(SentryTag.IS_RETAKE, 0);
transaction.setTag(SentryTag.TAKEN_PICTURES, 0);
transaction.setTag(SentryTag.RETAKEN_PICTURES, 0);
captureTourTransRef.current = {
transaction,
takenPictures: 0,
hasRetakeCalled: false,
};
}, []);

useEffect(() => {
try {
/**
* add takenPictures tag in "Capture Tour" transaction for a tour
*/
const takenPicturesLen = Object.values(states.sights.state.takenPictures).length;
const refObj = captureTourTransRef.current;
if (takenPicturesLen
&& refObj.transaction
&& !refObj.hasRetakeCalled
&& takenPicturesLen !== refObj.takenPictures
) {
refObj.takenPictures = takenPicturesLen;
refObj.transaction.setTag(SentryTag.TAKEN_PICTURES, takenPicturesLen);
}
onChange(states, api);
} catch (err) {
log([`Error in \`<Capture />\` \`onChange()\`: ${err}`], 'error');
errorHandler(err);
throw err;
}
}, [api, onChange, states]);
Expand Down Expand Up @@ -483,7 +563,7 @@ const Capture = forwardRef(({
<UploadCenter
{...states}
isSubmitting={isSubmitting}
onComplianceCheckFinish={onComplianceCheckFinish}
onComplianceCheckFinish={handleComplianceCheckFinish}
onComplianceCheckStart={onComplianceCheckStart}
onRetakeAll={onRetakeAll}
onSkipRetake={onSkipRetake}
Expand Down Expand Up @@ -676,11 +756,8 @@ Capture.propTypes = {
onPictureTaken: PropTypes.func,
onPictureUploaded: PropTypes.func,
onReady: PropTypes.func,
onRetakeAll: PropTypes.func,
onRetakeNeeded: PropTypes.func,
onSettingsChange: PropTypes.func,
onSightsChange: PropTypes.func,
onSkipRetake: PropTypes.func,
onStartUploadPicture: PropTypes.func,
onUploadsChange: PropTypes.func,
onWarningMessage: PropTypes.func,
Expand Down Expand Up @@ -789,16 +866,13 @@ Capture.defaultProps = {
onComplianceChange: () => {},
onSettingsChange: () => {},
onSightsChange: () => {},
onSkipRetake: () => {},
onUploadsChange: () => {},
onComplianceCheckFinish: () => {},
onComplianceCheckStart: () => {},
onFinishUploadPicture: () => {},
onWarningMessage: () => {},
onReady: () => {},
onStartUploadPicture: () => {},
onRetakeAll: () => {},
onRetakeNeeded: () => {},
orientationBlockerProps: null,
primaryColor: '#FFF',
resolutionOptions: undefined,
Expand Down
85 changes: 12 additions & 73 deletions src/screens/InspectionCapture/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useTheme } from 'react-native-paper';
import { Alert, Platform, View } from 'react-native';

import { Capture, Controls } from '@monkvision/camera';
import monk, { useMonitoring, MonitoringStatus, SentryTransaction, SentryOperation, SentryTag } from '@monkvision/corejs';
import monk, { useMonitoring } from '@monkvision/corejs';
import { utils } from '@monkvision/toolkit';

import * as names from 'screens/names';
Expand All @@ -23,15 +23,14 @@ export default function InspectionCapture() {
const dispatch = useDispatch();
const { t } = useTranslation();
const { colors } = useTheme();
const { errorHandler, measurePerformance } = useMonitoring();
const { errorHandler } = useMonitoring();

const { inspectionId, sightIds, taskName, vehicleType, selectedMode } = route.params;

const [isFocused, setFocused] = useState(false);
const [success, setSuccess] = useState(false);
const [cameraLoading, setCameraLoading] = useState(false);
const { setShowMessage, Notice } = useSnackbar();
const captureTourTransRef = useRef({});
const { isFullscreen, requestFullscreen } = useFullscreen();

const handleNavigate = useCallback((confirm = false) => {
Expand All @@ -40,11 +39,6 @@ export default function InspectionCapture() {
// eslint-disable-next-line no-alert
const ok = window.confirm(t('capture.quit.title'));
if (ok) {
/**
* cancel 'Capture Tour' transaction and navigate back to landing page
*/
utils.log(['[Click]', 'User suddenly quit the inspection']);
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
navigation.navigate(names.LANDING, { inspectionId });
}
}
Expand All @@ -58,11 +52,6 @@ export default function InspectionCapture() {
}, {
text: t('capture.quit.ok'),
onPress: () => {
/**
* cancel 'Capture Tour' transaction and navigate back to landing page
*/
utils.log(['[Click]', 'User suddenly quit the inspection']);
captureTourTransRef.current.transaction.finish(MonitoringStatus.CANCELLED);
navigation.navigate(names.LANDING, { inspectionId });
},
}],
Expand Down Expand Up @@ -103,10 +92,9 @@ export default function InspectionCapture() {
setCameraLoading(false);

/**
* finish 'capture tour' transaction and navigate back to landing page
* navigate back to landing page
*/
utils.log(['[Event] Back to landing page with photo taken']);
captureTourTransRef.current.transaction.finish();
handleNavigate();
} catch (err) {
errorHandler(err);
Expand All @@ -116,20 +104,6 @@ export default function InspectionCapture() {
}, [dispatch, handleNavigate, inspectionId, success, taskName, isFocused]);

const handleChange = useCallback((state) => {
/**
* add takenPictures tag in "Capture Tour" transaction for a tour
*/
const takenPicturesLen = Object.values(state.sights.state.takenPictures).length;
const refObj = captureTourTransRef.current;
if (takenPicturesLen
&& refObj.transaction
&& !refObj.hasRetakeCalled
&& takenPicturesLen !== refObj.takenPictures
) {
refObj.takenPictures = takenPicturesLen;
refObj.transaction.setTag(SentryTag.TAKEN_PICTURES, takenPicturesLen);
}
//
if (!success && isFocused && !enableComplianceCheck) {
try {
const { takenPictures, tour } = state.sights.state;
Expand Down Expand Up @@ -160,8 +134,6 @@ export default function InspectionCapture() {
}
} catch (err) {
errorHandler(err);
// eslint-disable-next-line no-console
console.error(err);
throw err;
}
}
Expand All @@ -179,49 +151,19 @@ export default function InspectionCapture() {
{ disabled: cameraLoading, ...Controls.AddDamageButtonProps },
{ disabled: cameraLoading, ...Controls.CaptureButtonProps },
],
{ disabled: cameraLoading, onPress: () => handleNavigate(true), ...Controls.GoBackButtonProps },
{
...Controls.CloseEarlyButtonProps,
confirm: true,
confirmationMessage: {
en: 'Your inspection is not complete, are you sure you want to stop it ?',
fr: 'Votre inspection n\'est pas complète, êtes-vous sûr(e) de vouloir l\'arrêter ?',
},
disabled: cameraLoading,
},
];

const onRetakeAll = useCallback(() => {
captureTourTransRef.current.hasRetakeCalled = true;
captureTourTransRef.current.transaction.setTag(SentryTag.IS_RETAKE, 1);
}, []);
const onSkipRetake = useCallback(() => {
captureTourTransRef.current.transaction.setTag(SentryTag.IS_SKIP, 1);
}, []);
const onRetakeNeeded = useCallback(({ retakesNeeded = 0 }) => {
if (!captureTourTransRef.current.hasRetakeCalled) {
const { transaction } = captureTourTransRef.current;
const percentOfNonCompliancePics = ((100 * retakesNeeded) / sightIds.length);
transaction.setTag(SentryTag.RETAKEN_PICTURES, retakesNeeded);
transaction.setTag(SentryTag.PERCENT_OF_NON_COMPLIANCE_PICS, percentOfNonCompliancePics);
}
}, []);

useEffect(() => { if (success) { handleSuccess(); } }, [handleSuccess, success]);

useEffect(() => {
/**
* create a new transaction with operation name 'Capture Tour' to measure tour performance
*/
const transaction = measurePerformance(
SentryTransaction.PICTURE_PROCESSING,
SentryOperation.CAPTURE_TOUR,
);
// set tags to identify a transation and relate with an inspection
transaction.setTag(SentryTag.TASK, taskName);
transaction.setTag(SentryTag.INSPECTION_ID, inspectionId);
transaction.setTag(SentryTag.IS_SKIP, 0);
transaction.setTag(SentryTag.IS_RETAKE, 0);
transaction.setTag(SentryTag.TAKEN_PICTURES, 0);
transaction.setTag(SentryTag.RETAKEN_PICTURES, 0);
captureTourTransRef.current = {
transaction,
takenPictures: 0,
hasRetakeCalled: false,
};
}, []);

useFocusEffect(() => {
setFocused(true);
return () => setFocused(false);
Expand All @@ -243,9 +185,6 @@ export default function InspectionCapture() {
onFinishUploadPicture={() => setCameraLoading(false)}
onWarningMessage={(message) => setShowMessage(message)}
onChange={handleChange}
onRetakeAll={onRetakeAll}
onSkipRetake={onSkipRetake}
onRetakeNeeded={onRetakeNeeded}
enableCarCoverage
enableComplianceCheck={enableComplianceCheck}
onComplianceCheckFinish={() => setSuccess(true)}
Expand Down