Skip to content

Commit f7b062c

Browse files
committed
Work around for iOS main Camera compatibility issue
1 parent bf7d877 commit f7b062c

File tree

7 files changed

+62
-53
lines changed

7 files changed

+62
-53
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@
104104
"react-native-webview": "^11.17.2",
105105
"react-redux": "^7.2.6",
106106
"react-responsive": "^9.0.0-beta.6",
107-
"release-it": "^14.12.5",
107+
"react-webcam": "^7.0.0",
108+
"release-it": "^14.13.1",
108109
"screenfull": "^5.2.0",
109110
"webrtc-adapter": "^8.1.1",
110111
"yup": "^0.32.11"

packages/camera/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"react-native-canvas": "^0.1.38",
5050
"react-native-svg": "^12.1.1",
5151
"react-responsive": "^9.0.0-beta.6",
52+
"react-webcam": "^7.0.0",
5253
"screenfull": "^5.2.0",
5354
"webrtc-adapter": "^8.1.1"
5455
},

packages/camera/src/components/Camera/index.js

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import PropTypes from 'prop-types';
44

55
import { Text, useWindowDimensions, View } from 'react-native';
66
import { utils } from '@monkvision/toolkit';
7+
import Webcam from 'react-webcam';
78

89
import { findDevices, findBestCandidate, setVideoSource } from './utils';
9-
import getOS from '../../utils/getOS';
1010
import styles from './styles';
1111

1212
const { getSize } = utils.styles;
@@ -20,7 +20,6 @@ const Video = React.forwardRef(
2020

2121
const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
2222
const videoRef = useRef();
23-
const expoCameraRef = useRef();
2423
const windowDimensions = useWindowDimensions();
2524

2625
const [camera, setCamera] = useState({
@@ -29,6 +28,7 @@ const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
2928
height: 0,
3029
ratio: '4:3',
3130
pictureSize: '',
31+
constraints: {},
3232
});
3333

3434
const [loading, setLoading] = useState(false);
@@ -41,9 +41,15 @@ const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
4141
useImperativeHandle(ref, () => ({
4242
async takePicture() {
4343
if (!videoRef.current) { throw new Error('Camera is not ready!'); }
44+
45+
if (utils.getOS() === 'iOS') {
46+
const uri = videoRef.current.getScreenshot();
47+
return { uri };
48+
}
49+
4450
const { width, height, stream } = camera;
4551

46-
if (ImageCapture && getOS() !== 'ios') {
52+
if (ImageCapture && utils.getOS() !== 'iOS') {
4753
const track = stream.getVideoTracks()[0];
4854
const imageCapture = new ImageCapture(track);
4955

@@ -64,7 +70,7 @@ const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
6470
canvas.getContext('2d')
6571
.drawImage(videoRef.current, 0, 0, width, height);
6672

67-
const imageType = utils.getOS() === 'ios' ? 'image/png' : 'image/webp';
73+
const imageType = utils.getOS() === 'iOS' ? 'image/png' : 'image/webp';
6874
const uri = canvas.toDataURL(imageType);
6975

7076
return { uri };
@@ -90,7 +96,9 @@ const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
9096
const devices = await findDevices();
9197
const bestCandidate = await findBestCandidate(devices);
9298

93-
setVideoSource(videoRef.current, bestCandidate.stream);
99+
if (utils.getOS() !== 'iOS') {
100+
setVideoSource(videoRef.current, bestCandidate.stream);
101+
}
94102

95103
setCamera(bestCandidate);
96104
setLoading(false);
@@ -106,13 +114,27 @@ const Camera = ({ children, containerStyle, onCameraReady, title }, ref) => {
106114
accessibilityLabel="Camera container"
107115
style={[styles.container, containerStyle]}
108116
>
109-
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
110-
<Video
111-
autoPlay
112-
playsInline
113-
ref={videoRef}
114-
{...videoSize}
115-
/>
117+
118+
{utils.getOS() === 'iOS' ? (
119+
<Webcam
120+
ref={videoRef}
121+
screenshotQuality={1}
122+
videoConstraints={camera.constraints.video}
123+
audioConstraints={camera.constraints.audio}
124+
minScreenshotHeight={camera.height}
125+
minScreenshotWidth={camera.width}
126+
style={videoSize}
127+
{...videoSize}
128+
/>
129+
) : (
130+
/* eslint-disable-next-line jsx-a11y/media-has-caption */
131+
<Video
132+
autoPlay
133+
playsInline
134+
ref={videoRef}
135+
{...videoSize}
136+
/>
137+
)}
116138
{children}
117139
<Text style={styles.title}>{title}</Text>
118140
</View>

packages/camera/src/components/Camera/utils.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,6 @@ import 'webrtc-adapter';
22
import { utils } from '@monkvision/toolkit';
33

44
export const whitelist = [{
5-
label: '4K(UHD) 4:3',
6-
width: 3840,
7-
height: 2880,
8-
ratio: '4:3',
9-
}, {
10-
label: '4K(UHD) 16:9',
11-
width: 3840,
12-
height: 2160,
13-
ratio: '16:9',
14-
}, {
155
label: 'FHD 4:3',
166
width: 1920,
177
height: 1440,
@@ -41,26 +31,6 @@ export const whitelist = [{
4131
width: 640,
4232
height: 480,
4333
ratio: '4:3',
44-
}, {
45-
label: 'CIF',
46-
width: 352,
47-
height: 288,
48-
ratio: '4:3',
49-
}, {
50-
label: 'QVGA',
51-
width: 320,
52-
height: 240,
53-
ratio: '4:3',
54-
}, {
55-
label: 'QCIF',
56-
width: 176,
57-
height: 144,
58-
ratio: '4:3',
59-
}, {
60-
label: 'QQVGA',
61-
width: 160,
62-
height: 120,
63-
ratio: '4:3',
6434
}];
6535

6636
export function captureImageContext(video, { width, height }) {

packages/camera/src/components/Controls/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ Controls.propTypes = {
8585
onPress: PropTypes.func,
8686
})),
8787
enableComplianceCheck: PropTypes.bool,
88+
loading: PropTypes.bool,
8889
onFinishUploadPicture: PropTypes.func,
8990
onStartUploadPicture: PropTypes.func,
90-
loading: PropTypes.bool,
9191
state: PropTypes.shape({
9292
settings: PropTypes.objectOf(PropTypes.any),
9393
sights: PropTypes.objectOf(PropTypes.any),

src/screens/InspectionCreate/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import React, { useCallback, useState } from 'react';
2-
import { SafeAreaView } from 'react-native';
2+
import { SafeAreaView, StyleSheet } from 'react-native';
33

44
import useScreen from 'screens/InspectionCreate/useScreen';
55

66
import { Capture, Controls, Constants, useUploads } from '@monkvision/camera';
77

8+
const styles = StyleSheet.create({
9+
safeArea: { backgroundColor: '#000' },
10+
});
11+
812
export default () => {
913
const { request, isLoading, requestCount: updateTaskRequestCount, inspectionId } = useScreen();
1014

11-
const [cameraloading, setCameraLoading] = useState();
15+
const [cameraLoading, setCameraLoading] = useState();
1216

1317
// start the damage detection task
1418
const handleSuccess = useCallback(() => { if (updateTaskRequestCount === 0) { request(); } },
@@ -17,7 +21,7 @@ export default () => {
1721
const uploads = useUploads({ sightIds: Constants.defaultSightIds });
1822

1923
const controls = [{
20-
disabled: cameraloading,
24+
disabled: cameraLoading,
2125
...Controls.CaptureButtonProps,
2226

2327
/** --- With custom capture handler ---
@@ -26,12 +30,12 @@ export default () => {
2630
}];
2731

2832
return (
29-
<SafeAreaView>
33+
<SafeAreaView style={styles.safeArea}>
3034
<Capture
3135
sightIds={Constants.defaultSightIds}
3236
inspectionId={inspectionId}
3337
controls={controls}
34-
loading={cameraloading}
38+
loading={cameraLoading}
3539
uploads={uploads}
3640
isSubmitting={isLoading}
3741
enableComplianceCheck

yarn.lock

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11631,6 +11631,11 @@ react-test-renderer@^17.0.2, react-test-renderer@~17.0.1:
1163111631
react-shallow-renderer "^16.13.1"
1163211632
scheduler "^0.20.2"
1163311633

11634+
react-webcam@^7.0.0:
11635+
version "7.0.0"
11636+
resolved "https://registry.yarnpkg.com/react-webcam/-/react-webcam-7.0.0.tgz#11635a771d876d897dc54e642c758c0f6ba4987b"
11637+
integrity sha512-HKFiYyLhSCQCUYilzhgkJlDrUCxN60kB97i5OLSjjJ5HJyVQVkEsp8rAFyZZDiZK2fRauvUmaZHac94U4OhVhg==
11638+
1163411639
1163511640
version "17.0.1"
1163611641
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
@@ -11876,10 +11881,10 @@ release-it@*, release-it@^14.11.5:
1187611881
yaml "1.10.2"
1187711882
yargs-parser "20.2.9"
1187811883

11879-
release-it@^14.12.5:
11880-
version "14.12.5"
11881-
resolved "https://registry.yarnpkg.com/release-it/-/release-it-14.12.5.tgz#aaf9802545717f299e14d1dbf025afa7bf956668"
11882-
integrity sha512-mGFbbX8eEKMOhfjq5mZAgGppT8CME1T+vj6xA5tAPYSCuPpcNEDjqiG1tJfPy/XImZI4uS3U6pNP5KyDpy9etg==
11884+
release-it@^14.13.1:
11885+
version "14.13.1"
11886+
resolved "https://registry.yarnpkg.com/release-it/-/release-it-14.13.1.tgz#d87bb2dc488904ea0d39eddf0b354081c645381f"
11887+
integrity sha512-mrng5bqZDFMr/7oCH3kuflwjKpKki4dUp6yYGxs20scYCvvd8rHAI5pdQOJHwI5BKHAC/pad0UjAEycMWQnEIw==
1188311888
dependencies:
1188411889
"@iarna/toml" "2.2.5"
1188511890
"@octokit/rest" "18.12.0"
@@ -11907,6 +11912,7 @@ release-it@^14.12.5:
1190711912
update-notifier "5.1.0"
1190811913
url-join "4.0.1"
1190911914
uuid "8.3.2"
11915+
wildcard-match "5.1.2"
1191011916
yaml "1.10.2"
1191111917
yargs-parser "20.2.9"
1191211918

@@ -13908,6 +13914,11 @@ widest-line@^3.1.0:
1390813914
dependencies:
1390913915
string-width "^4.0.0"
1391013916

13917+
13918+
version "5.1.2"
13919+
resolved "https://registry.yarnpkg.com/wildcard-match/-/wildcard-match-5.1.2.tgz#66b438001391674d8599b45da051e0bd9f33cd2a"
13920+
integrity sha512-qNXwI591Z88c8bWxp+yjV60Ch4F8Riawe3iGxbzquhy8Xs9m+0+SLFBGb/0yCTIDElawtaImC37fYZ+dr32KqQ==
13921+
1391113922
windows-release@^4.0.0:
1391213923
version "4.0.0"
1391313924
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-4.0.0.tgz#4725ec70217d1bf6e02c7772413b29cdde9ec377"

0 commit comments

Comments
 (0)