From 2e3914221319917a9f8e3d4b7c18c6810796748e Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Mon, 20 Nov 2023 21:04:03 +0530 Subject: [PATCH] fix: issue with camera permissions when clicking the camera picker (#2315) * fix: issue with camera permissions when clicking the camera picker * fix: open settings logic * feat: show alert before opening settings --- .../expo-package/src/handlers/takePhoto.ts | 5 ++--- .../native-package/src/handlers/takePhoto.ts | 22 +++++++++---------- .../components/AttachmentSelectionBar.tsx | 14 +++++++++++- package/src/i18n/en.json | 5 ++++- package/src/i18n/es.json | 5 ++++- package/src/i18n/fr.json | 5 ++++- package/src/i18n/he.json | 5 ++++- package/src/i18n/hi.json | 5 ++++- package/src/i18n/it.json | 5 ++++- package/src/i18n/ja.json | 5 ++++- package/src/i18n/ko.json | 5 ++++- package/src/i18n/nl.json | 5 ++++- package/src/i18n/ru.json | 5 ++++- package/src/i18n/tr.json | 5 ++++- package/src/native.ts | 6 ++++- 15 files changed, 75 insertions(+), 27 deletions(-) diff --git a/package/expo-package/src/handlers/takePhoto.ts b/package/expo-package/src/handlers/takePhoto.ts index 6259636ac8..b30d351ef5 100644 --- a/package/expo-package/src/handlers/takePhoto.ts +++ b/package/expo-package/src/handlers/takePhoto.ts @@ -1,4 +1,4 @@ -import { Image, Linking, Platform } from 'react-native'; +import { Image, Platform } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; @@ -17,8 +17,7 @@ export const takePhoto = async ({ compressImageQuality = 1 }) => { const response = await ImagePicker.requestCameraPermissionsAsync(); permissionGranted = response.granted; } else { - Linking.openSettings(); - return { cancelled: true }; + return { askToOpenSettings: true, cancelled: true }; } } diff --git a/package/native-package/src/handlers/takePhoto.ts b/package/native-package/src/handlers/takePhoto.ts index 72d02acd0e..344b215291 100644 --- a/package/native-package/src/handlers/takePhoto.ts +++ b/package/native-package/src/handlers/takePhoto.ts @@ -1,8 +1,6 @@ -import { AppState, Image, Linking, PermissionsAndroid, Platform } from 'react-native'; +import { AppState, Image, PermissionsAndroid, Platform } from 'react-native'; import ImagePicker from 'react-native-image-crop-picker'; -let hadDeniedAndroidPermission = false; - export const takePhoto = async ({ compressImageQuality = Platform.OS === 'ios' ? 0.8 : 1 }) => { if (Platform.OS === 'android') { const cameraPermissions = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.CAMERA); @@ -11,13 +9,9 @@ export const takePhoto = async ({ compressImageQuality = Platform.OS === 'ios' ? PermissionsAndroid.PERMISSIONS.CAMERA, ); if (androidPermissionStatus === PermissionsAndroid.RESULTS.DENIED) { - hadDeniedAndroidPermission = true; return { cancelled: true }; } else if (androidPermissionStatus === PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) { - if (!hadDeniedAndroidPermission) { - Linking.openSettings(); - } - return { cancelled: true }; + return { askToOpenSettings: true, cancelled: true }; } } } @@ -62,9 +56,15 @@ export const takePhoto = async ({ compressImageQuality = Platform.OS === 'ios' ? }; } } catch (e: unknown) { - // on iOS: if it was in inactive state, then the user had just denied the permissions - if (Platform.OS === 'ios' && AppState.currentState === 'active') { - await Linking.openSettings(); + if (e instanceof Error) { + // on iOS: if it was in inactive state, then the user had just denied the permissions + if (Platform.OS === 'ios' && AppState.currentState === 'active') { + const cameraPermissionDeniedMsg = 'User did not grant camera permission.'; + // Open settings when the user did not allow camera permissions + if (e.message === cameraPermissionDeniedMsg) { + return { askToOpenSettings: true, cancelled: true }; + } + } } } diff --git a/package/src/components/AttachmentPicker/components/AttachmentSelectionBar.tsx b/package/src/components/AttachmentPicker/components/AttachmentSelectionBar.tsx index 8501b8cb10..c1568af526 100644 --- a/package/src/components/AttachmentPicker/components/AttachmentSelectionBar.tsx +++ b/package/src/components/AttachmentPicker/components/AttachmentSelectionBar.tsx @@ -1,9 +1,10 @@ import React from 'react'; -import { StyleSheet, TouchableOpacity, View } from 'react-native'; +import { Alert, Linking, StyleSheet, TouchableOpacity, View } from 'react-native'; import { useAttachmentPickerContext } from '../../../contexts/attachmentPickerContext/AttachmentPickerContext'; import { useMessageInputContext } from '../../../contexts/messageInputContext/MessageInputContext'; import { useTheme } from '../../../contexts/themeContext/ThemeContext'; +import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext'; import { takePhoto } from '../../../native'; @@ -29,6 +30,7 @@ export const AttachmentSelectionBar: React.FC = () => { setSelectedImages, setSelectedPicker, } = useAttachmentPickerContext(); + const { t } = useTranslationContext(); const { compressImageQuality, hasFilePicker, imageUploads, pickFile } = useMessageInputContext(); @@ -57,6 +59,16 @@ export const AttachmentSelectionBar: React.FC = () => { setSelectedPicker(undefined); closePicker(); const photo = await takePhoto({ compressImageQuality }); + if (photo.askToOpenSettings) { + Alert.alert( + t('Allow camera access in device settings'), + t('Device camera is used to take photos or videos.'), + [ + { style: 'cancel', text: t('Cancel') }, + { onPress: () => Linking.openSettings(), style: 'default', text: t('Open Settings') }, + ], + ); + } if (!photo.cancelled) { setSelectedImages((images) => [...images, photo]); } diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index 212cfff0d3..99fcacd7c7 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Attachment...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.", "Let's start chatting!": "Let's start chatting!", - "How about sending your first message to a friend?": "How about sending your first message to a friend?" + "How about sending your first message to a friend?": "How about sending your first message to a friend?", + "Allow camera access in device settings": "Allow camera access in device settings", + "Device camera is used to take photos or videos.": "Device camera is used to take photos or videos.", + "Open Settings": "Open Settings" } diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index ca42b9754a..dc099a3f87 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Adjunto...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "El archivo supera el tamaño máximo permitido. Por favor, selecciona un archivo menor a {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.", "Let's start chatting!": "¡Empecemos a charlar!", - "How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?" + "How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?", + "Allow camera access in device settings": "Permitir el acceso a la cámara en la configuración del dispositivo", + "Device camera is used to take photos or videos.": "La cámara del dispositivo se utiliza para tomar fotografías o vídeos.", + "Open Settings": "Configuración abierta" } diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 676565342c..22ed265d7b 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Pièce jointe...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Taille maximale de téléchargement de fichier atteinte. Veuillez télécharger un fichier inférieur à {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} Mo.", "Let's start chatting!": "Commençons à discuter !", - "How about sending your first message to a friend?": "Et si vous envoyiez votre premier message à un ami ?" + "How about sending your first message to a friend?": "Et si vous envoyiez votre premier message à un ami ?", + "Allow camera access in device settings": "Autoriser l'accès à la caméra dans les paramètres de l'appareil", + "Device camera is used to take photos or videos.": "L'appareil photo de l'appareil est utilisé pour prendre des photos ou des vidéos.", + "Open Settings": "Ouvrir les paramètres" } diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index 4c98660cd6..7f949c7380 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 קובץ מצורף...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "הגעת למגבלת העלאת גודל הקובץ המקסימלית. אנא העלה קובץ מתחת ל-{{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB", "Let's start chatting!": "בואו נתחיל לשוחח!", - "How about sending your first message to a friend?": "מה דעתך לשלוח את ההודעה הראשונה שלך לחבר?" + "How about sending your first message to a friend?": "מה דעתך לשלוח את ההודעה הראשונה שלך לחבר?", + "Allow camera access in device settings": "אפשר גישה למצלמה בהגדרות המכשיר", + "Device camera is used to take photos or videos.": "מצלמת המכשיר משמשת לצילום תמונות או סרטונים.", + "Open Settings": "פתח את ההגדרות" } diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 02e01c61a7..25abc3d34b 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 अटैचमेंट...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "अधिकतम फ़ाइल आकार अपलोड सीमा पूरी हो गई। कृपया {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} एमबी से नीचे की फ़ाइल अपलोड करें।", "Let's start chatting!": "आइए चैट करना शुरू करें!", - "How about sending your first message to a friend?": "किसी मित्र को अपना पहला संदेश भेजने के बारे में क्या ख़याल है?" + "How about sending your first message to a friend?": "किसी मित्र को अपना पहला संदेश भेजने के बारे में क्या ख़याल है?", + "Allow camera access in device settings": "डिवाइस सेटिंग्स में कैमरा एक्सेस की अनुमति दें", + "Device camera is used to take photos or videos.": "डिवाइस कैमरे का उपयोग फ़ोटो या वीडियो लेने के लिए किया जाता है।", + "Open Settings": "सेटिंग्स खोलें" } diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index ece4490731..43abf8611e 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Allegato...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "È stato raggiunto il limite massimo di caricamento delle dimensioni del file. Carica un file inferiore a {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.", "Let's start chatting!": "Iniziamo a chattare!", - "How about sending your first message to a friend?": "Che ne dici di inviare il tuo primo messaggio ad un amico?" + "How about sending your first message to a friend?": "Che ne dici di inviare il tuo primo messaggio ad un amico?", + "Allow camera access in device settings": "Consenti l'accesso alla fotocamera nelle impostazioni del dispositivo", + "Device camera is used to take photos or videos.": "La fotocamera del dispositivo viene utilizzata per scattare foto o video.", + "Open Settings": "Apri Impostazioni" } diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index ba17b73fbe..1b24e20471 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -73,5 +73,8 @@ "File type not supported": "サポートされていないファイルです", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "最大ファイル サイズのアップロード制限に達しました。 {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB 以下のファイルをアップロードしてください", "Let's start chatting!": "チャットを始めましょう!", - "How about sending your first message to a friend?": "初めてのメッセージを友達に送ってみてはいかがでしょうか?" + "How about sending your first message to a friend?": "初めてのメッセージを友達に送ってみてはいかがでしょうか?", + "Allow camera access in device settings": "デバイス設定でカメラへのアクセスを許可する", + "Device camera is used to take photos or videos.": "デバイスのカメラは写真やビデオの撮影に使用されます。", + "Open Settings": "設定を開く" } diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index 983bf34104..7451b0a1bc 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -72,5 +72,8 @@ "Not supported": "지원하지 않습니다", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "최대 파일 크기 업로드 제한에 도달했습니다. {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}}MB 미만의 파일을 업로드하세요.", "Let's start chatting!": "채팅을 시작합시다!", - "How about sending your first message to a friend?": "친구에게 첫 번째 메시지를 보내는 것은 어떻습니까?" + "How about sending your first message to a friend?": "친구에게 첫 번째 메시지를 보내는 것은 어떻습니까?", + "Allow camera access in device settings": "기기 설정에서 카메라 액세스를 허용하세요.", + "Device camera is used to take photos or videos.": "기기 카메라는 사진이나 동영상을 촬영하는 데 사용됩니다.", + "Open Settings": "설정 열기" } diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index a4078d6280..6e21fc3880 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Bijlage...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maximale uploadlimiet voor bestandsgrootte bereikt. Upload een bestand van minder dan {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.", "Let's start chatting!": "Laten we beginnen met chatten!", - "How about sending your first message to a friend?": "Wat dacht je ervan om je eerste bericht naar een vriend te sturen?" + "How about sending your first message to a friend?": "Wat dacht je ervan om je eerste bericht naar een vriend te sturen?", + "Allow camera access in device settings": "Sta cameratoegang toe in de apparaatinstellingen", + "Device camera is used to take photos or videos.": "De camera van het apparaat wordt gebruikt om foto's of video's te maken.", + "Open Settings": "Open instellingen" } diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index fd2eadbe06..0d953978a5 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Вложение...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Достигнут предел максимального размера файла для загрузки. Загрузите файл размером менее {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} МБ.", "Let's start chatting!": "Давайте начнем общаться!", - "How about sending your first message to a friend?": "Как насчет отправки первого сообщения другу?" + "How about sending your first message to a friend?": "Как насчет отправки первого сообщения другу?", + "Allow camera access in device settings": "Разрешите доступ к камере в настройках устройства.", + "Device camera is used to take photos or videos.": "Камера устройства используется для съемки фотографий или видео.", + "Open Settings": "Открыть настройки" } diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index 15e64f5b0d..37cf6c3694 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -70,5 +70,8 @@ "🏙 Attachment...": "🏙 Ek...", "Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "Maksimum dosya boyutu yükleme sınırına ulaşıldı. Lütfen {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB'ın altında bir dosya yükleyin.", "Let's start chatting!": "Haydi sohbete başlayalım!", - "How about sending your first message to a friend?": "İlk mesajınızı bir arkadaşınıza göndermeye ne dersiniz?" + "How about sending your first message to a friend?": "İlk mesajınızı bir arkadaşınıza göndermeye ne dersiniz?", + "Allow camera access in device settings": "Cihaz ayarlarında kamera erişimine izin ver", + "Device camera is used to take photos or videos.": "Cihaz kamerası fotoğraf veya video çekmek için kullanılır.", + "Open Settings": "Ayarları aç" } diff --git a/package/src/native.ts b/package/src/native.ts index ad48d5354a..5b9693bef2 100644 --- a/package/src/native.ts +++ b/package/src/native.ts @@ -87,8 +87,12 @@ type Photo = | (Omit & { cancelled: false; source: 'camera'; + askToOpenSettings?: boolean; }) - | { cancelled: true }; + | { + cancelled: true; + askToOpenSettings?: boolean; + }; type TakePhoto = (options: { compressImageQuality?: number }) => Promise | never; export let takePhoto: TakePhoto = fail;