187d87595STomasz Sapetaimport { PermissionResponse, PermissionStatus, UnavailabilityError } from 'expo-modules-core';
2ac43a3f3SŁukasz Kosmaty
3ac43a3f3SŁukasz Kosmatyfunction getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream> {
4ac43a3f3SŁukasz Kosmaty  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
5ac43a3f3SŁukasz Kosmaty    return navigator.mediaDevices.getUserMedia(constraints);
6ac43a3f3SŁukasz Kosmaty  }
7ac43a3f3SŁukasz Kosmaty
8ac43a3f3SŁukasz Kosmaty  // Some browsers partially implement mediaDevices. We can't just assign an object
9ac43a3f3SŁukasz Kosmaty  // with getUserMedia as it would overwrite existing properties.
10ac43a3f3SŁukasz Kosmaty  // Here, we will just add the getUserMedia property if it's missing.
11ac43a3f3SŁukasz Kosmaty
12ac43a3f3SŁukasz Kosmaty  // First get ahold of the legacy getUserMedia, if present
13ac43a3f3SŁukasz Kosmaty  const getUserMedia =
14*ab22f034SBartłomiej Bukowski    // TODO: this method is deprecated, migrate to https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
15ac43a3f3SŁukasz Kosmaty    navigator.getUserMedia ||
16*ab22f034SBartłomiej Bukowski    navigator.webkitGetUserMedia ||
17*ab22f034SBartłomiej Bukowski    navigator.mozGetUserMedia ||
18ac43a3f3SŁukasz Kosmaty    function () {
19ac43a3f3SŁukasz Kosmaty      const error: any = new Error('Permission unimplemented');
20ac43a3f3SŁukasz Kosmaty      error.code = 0;
21ac43a3f3SŁukasz Kosmaty      error.name = 'NotAllowedError';
22ac43a3f3SŁukasz Kosmaty      throw error;
23ac43a3f3SŁukasz Kosmaty    };
24ac43a3f3SŁukasz Kosmaty
25ac43a3f3SŁukasz Kosmaty  return new Promise((resolve, reject) => {
26ac43a3f3SŁukasz Kosmaty    getUserMedia.call(navigator, constraints, resolve, reject);
27ac43a3f3SŁukasz Kosmaty  });
28ac43a3f3SŁukasz Kosmaty}
29ac43a3f3SŁukasz Kosmaty
30ac43a3f3SŁukasz Kosmatyfunction handleGetUserMediaError({ message }: { message: string }): PermissionResponse {
31ac43a3f3SŁukasz Kosmaty  // name: NotAllowedError
32ac43a3f3SŁukasz Kosmaty  // code: 0
33ac43a3f3SŁukasz Kosmaty  if (message === 'Permission dismissed') {
34ac43a3f3SŁukasz Kosmaty    return {
35ac43a3f3SŁukasz Kosmaty      status: PermissionStatus.UNDETERMINED,
36ac43a3f3SŁukasz Kosmaty      expires: 'never',
37ac43a3f3SŁukasz Kosmaty      canAskAgain: true,
38ac43a3f3SŁukasz Kosmaty      granted: false,
39ac43a3f3SŁukasz Kosmaty    };
40ac43a3f3SŁukasz Kosmaty  } else {
41ac43a3f3SŁukasz Kosmaty    return {
42ac43a3f3SŁukasz Kosmaty      status: PermissionStatus.DENIED,
43ac43a3f3SŁukasz Kosmaty      expires: 'never',
44ac43a3f3SŁukasz Kosmaty      canAskAgain: true,
45ac43a3f3SŁukasz Kosmaty      granted: false,
46ac43a3f3SŁukasz Kosmaty    };
47ac43a3f3SŁukasz Kosmaty  }
48ac43a3f3SŁukasz Kosmaty}
49ac43a3f3SŁukasz Kosmaty
50ac43a3f3SŁukasz Kosmatyasync function handleRequestPermissionsAsync(): Promise<PermissionResponse> {
51ac43a3f3SŁukasz Kosmaty  try {
52ac43a3f3SŁukasz Kosmaty    await getUserMedia({
53ac43a3f3SŁukasz Kosmaty      video: true,
54ac43a3f3SŁukasz Kosmaty    });
55ac43a3f3SŁukasz Kosmaty    return {
56ac43a3f3SŁukasz Kosmaty      status: PermissionStatus.GRANTED,
57ac43a3f3SŁukasz Kosmaty      expires: 'never',
58ac43a3f3SŁukasz Kosmaty      canAskAgain: true,
59ac43a3f3SŁukasz Kosmaty      granted: true,
60ac43a3f3SŁukasz Kosmaty    };
61ac43a3f3SŁukasz Kosmaty  } catch ({ message }) {
62ac43a3f3SŁukasz Kosmaty    return handleGetUserMediaError({ message });
63ac43a3f3SŁukasz Kosmaty  }
64ac43a3f3SŁukasz Kosmaty}
65ac43a3f3SŁukasz Kosmaty
66ac43a3f3SŁukasz Kosmatyasync function handlePermissionsQueryAsync(): Promise<PermissionResponse> {
67ac43a3f3SŁukasz Kosmaty  if (!navigator?.permissions?.query) {
68ac43a3f3SŁukasz Kosmaty    throw new UnavailabilityError(
69ac43a3f3SŁukasz Kosmaty      'expo-barcode-scanner',
70ac43a3f3SŁukasz Kosmaty      'navigator.permissions API is not available'
71ac43a3f3SŁukasz Kosmaty    );
72ac43a3f3SŁukasz Kosmaty  }
73ac43a3f3SŁukasz Kosmaty
74ac43a3f3SŁukasz Kosmaty  const { state } = await navigator.permissions.query({ name: 'camera' });
75ac43a3f3SŁukasz Kosmaty  switch (state) {
76ac43a3f3SŁukasz Kosmaty    case 'prompt':
77ac43a3f3SŁukasz Kosmaty      return {
78ac43a3f3SŁukasz Kosmaty        status: PermissionStatus.UNDETERMINED,
79ac43a3f3SŁukasz Kosmaty        expires: 'never',
80ac43a3f3SŁukasz Kosmaty        canAskAgain: true,
81ac43a3f3SŁukasz Kosmaty        granted: false,
82ac43a3f3SŁukasz Kosmaty      };
83ac43a3f3SŁukasz Kosmaty    case 'granted':
84ac43a3f3SŁukasz Kosmaty      return {
85ac43a3f3SŁukasz Kosmaty        status: PermissionStatus.GRANTED,
86ac43a3f3SŁukasz Kosmaty        expires: 'never',
87ac43a3f3SŁukasz Kosmaty        canAskAgain: true,
88ac43a3f3SŁukasz Kosmaty        granted: true,
89ac43a3f3SŁukasz Kosmaty      };
90ac43a3f3SŁukasz Kosmaty    case 'denied':
91ac43a3f3SŁukasz Kosmaty      return {
92ac43a3f3SŁukasz Kosmaty        status: PermissionStatus.DENIED,
93ac43a3f3SŁukasz Kosmaty        expires: 'never',
94ac43a3f3SŁukasz Kosmaty        canAskAgain: true,
95ac43a3f3SŁukasz Kosmaty        granted: false,
96ac43a3f3SŁukasz Kosmaty      };
97ac43a3f3SŁukasz Kosmaty  }
98ac43a3f3SŁukasz Kosmaty}
99ac43a3f3SŁukasz Kosmaty
1009ab5f539SEvan Baconexport default {
1019ab5f539SEvan Bacon  get name(): string {
1029ab5f539SEvan Bacon    return 'ExpoBarCodeScannerModule';
1039ab5f539SEvan Bacon  },
104567432c8SEvan Bacon  get BarCodeType() {
105567432c8SEvan Bacon    return {
106567432c8SEvan Bacon      code39mod43: 'code39mod43',
107567432c8SEvan Bacon      code138: 'code138',
108567432c8SEvan Bacon      interleaved2of5: 'interleaved2of5',
109567432c8SEvan Bacon      aztec: 'aztec',
110567432c8SEvan Bacon      ean13: 'ean13',
111567432c8SEvan Bacon      ean8: 'ean8',
112567432c8SEvan Bacon      qr: 'qr',
113567432c8SEvan Bacon      pdf417: 'pdf417',
114567432c8SEvan Bacon      upc_e: 'upc_e',
115567432c8SEvan Bacon      datamatrix: 'datamatrix',
116567432c8SEvan Bacon      code39: 'code39',
117567432c8SEvan Bacon      code93: 'code93',
118567432c8SEvan Bacon      itf14: 'itf14',
119567432c8SEvan Bacon      codabar: 'codabar',
120567432c8SEvan Bacon      code128: 'code128',
121567432c8SEvan Bacon      upc_a: 'upc_a',
122567432c8SEvan Bacon    };
1239ab5f539SEvan Bacon  },
124567432c8SEvan Bacon  get Type() {
1259ab5f539SEvan Bacon    return { front: 'front', back: 'back' };
1269ab5f539SEvan Bacon  },
127ac43a3f3SŁukasz Kosmaty  async requestPermissionsAsync(): Promise<PermissionResponse> {
128ac43a3f3SŁukasz Kosmaty    return handleRequestPermissionsAsync();
129ac43a3f3SŁukasz Kosmaty  },
130ac43a3f3SŁukasz Kosmaty  async getPermissionsAsync(): Promise<PermissionResponse> {
131ac43a3f3SŁukasz Kosmaty    return handlePermissionsQueryAsync();
132ac43a3f3SŁukasz Kosmaty  },
1339ab5f539SEvan Bacon};
134