Skip to content

Commit

Permalink
Merge pull request #28619 from zoontek/fix-camera-permission-prompt
Browse files Browse the repository at this point in the history
Fix Android camera permission prompt
  • Loading branch information
Julesssss authored Oct 11, 2023
2 parents 7b52fa5 + 60e0254 commit 012538a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 69 deletions.
31 changes: 18 additions & 13 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,29 @@
# This value is used by $RNMapboxMaps
$RNMapboxMapsImpl = 'mapbox'

# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
def node_require(script)
# Resolve script with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end

node_require('react-native/scripts/react_native_pods.rb')
node_require('react-native-permissions/scripts/setup.rb')

# Our min supported iOS version is higher than the default (min_ios_version_supported) to support libraires such as Airship
platform :ios, 13
prepare_react_native_project!

setup_permissions([
'Camera',
'LocationAccuracy',
'LocationAlways',
'LocationWhenInUse'
])

# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
Expand Down Expand Up @@ -51,8 +63,6 @@ pre_install do |installer|
end

target 'NewExpensify' do
permissions_path = '../node_modules/react-native-permissions/ios'

project 'NewExpensify',
'DebugDevelopment' => :debug,
'DebugAdHoc' => :debug,
Expand All @@ -61,11 +71,6 @@ target 'NewExpensify' do
'ReleaseAdHoc' => :release,
'ReleaseProduction' => :release

pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy"
pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
pod 'Permission-Camera', :path => "#{permissions_path}/Camera"

config = use_native_modules!

# Flags change depending on the env values.
Expand Down
30 changes: 3 additions & 27 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,6 @@ PODS:
- Onfido (= 27.4.0)
- React
- OpenSSL-Universal (1.1.1100)
- Permission-Camera (3.6.1):
- RNPermissions
- Permission-LocationAccuracy (3.6.1):
- RNPermissions
- Permission-LocationAlways (3.6.1):
- RNPermissions
- Permission-LocationWhenInUse (3.6.1):
- RNPermissions
- Plaid (4.1.0)
- PromisesObjC (2.2.0)
- RCT-Folly (2021.07.22.00):
Expand Down Expand Up @@ -781,7 +773,7 @@ PODS:
- React
- React-Core
- Turf
- RNPermissions (3.6.1):
- RNPermissions (3.9.3):
- React-Core
- RNReactNativeHapticFeedback (1.14.0):
- React-Core
Expand Down Expand Up @@ -867,10 +859,6 @@ DEPENDENCIES:
- lottie-react-native (from `../node_modules/lottie-react-native`)
- "onfido-react-native-sdk (from `../node_modules/@onfido/react-native-sdk`)"
- OpenSSL-Universal (= 1.1.1100)
- Permission-Camera (from `../node_modules/react-native-permissions/ios/Camera`)
- Permission-LocationAccuracy (from `../node_modules/react-native-permissions/ios/LocationAccuracy`)
- Permission-LocationAlways (from `../node_modules/react-native-permissions/ios/LocationAlways`)
- Permission-LocationWhenInUse (from `../node_modules/react-native-permissions/ios/LocationWhenInUse`)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
Expand Down Expand Up @@ -1018,14 +1006,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/lottie-react-native"
onfido-react-native-sdk:
:path: "../node_modules/@onfido/react-native-sdk"
Permission-Camera:
:path: "../node_modules/react-native-permissions/ios/Camera"
Permission-LocationAccuracy:
:path: "../node_modules/react-native-permissions/ios/LocationAccuracy"
Permission-LocationAlways:
:path: "../node_modules/react-native-permissions/ios/LocationAlways"
Permission-LocationWhenInUse:
:path: "../node_modules/react-native-permissions/ios/LocationWhenInUse"
RCT-Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
RCTRequired:
Expand Down Expand Up @@ -1227,10 +1207,6 @@ SPEC CHECKSUMS:
Onfido: e36f284b865adcf99d9c905590a64ac09d4a576b
onfido-react-native-sdk: 4ecde1a97435dcff9f00a878e3f8d1eb14fabbdc
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
Permission-Camera: bf6791b17c7f614b6826019fcfdcc286d3a107f6
Permission-LocationAccuracy: 76df17de5c6b8bc2eee34e61ee92cdd7a864c73d
Permission-LocationAlways: 8d99b025c9f73c696e0cdb367e42525f2e9a26f2
Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4
Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2
PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
Expand Down Expand Up @@ -1302,7 +1278,7 @@ SPEC CHECKSUMS:
RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0
RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81
rnmapbox-maps: 6f638ec002aa6e906a6f766d69cd45f968d98e64
RNPermissions: dcdb7b99796bbeda6975a6e79ad519c41b251b1c
RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa
RNReactNativeHapticFeedback: 1e3efeca9628ff9876ee7cdd9edec1b336913f8c
RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87
RNScreens: d037903436160a4b039d32606668350d2a808806
Expand All @@ -1315,6 +1291,6 @@ SPEC CHECKSUMS:
Yoga: 3efc43e0d48686ce2e8c60f99d4e6bd349aff981
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

PODFILE CHECKSUM: 2daf34c870819a933f3fefe426801d54b2ff2a14
PODFILE CHECKSUM: ff769666b7221c15936ebc5576a8c8e467dc6879

COCOAPODS: 1.12.1
11 changes: 7 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
"react-native-pager-view": "^6.2.0",
"react-native-pdf": "^6.7.1",
"react-native-performance": "^5.1.0",
"react-native-permissions": "^3.0.1",
"react-native-permissions": "^3.9.3",
"react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2",
"react-native-plaid-link-sdk": "^10.0.0",
"react-native-qrcode-svg": "^6.2.0",
Expand Down
57 changes: 33 additions & 24 deletions src/pages/iou/ReceiptSelector/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})

const camera = useRef(null);
const [flash, setFlash] = useState(false);
const [permissions, setPermissions] = useState('granted');
const isAndroidBlockedPermissionRef = useRef(false);
const appState = useRef(AppState.currentState);
const [cameraPermissionStatus, setCameraPermissionStatus] = useState(undefined);

const iouType = lodashGet(route, 'params.iouType', '');
const pageIndex = lodashGet(route, 'params.pageIndex', 1);
Expand All @@ -105,16 +103,23 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})

const CameraComponent = isInTabNavigator ? TabNavigationAwareCamera : NavigationAwareCamera;

// We want to listen to if the app has come back from background and refresh the permissions status to show camera when permissions were granted
useEffect(() => {
const subscription = AppState.addEventListener('change', (nextAppState) => {
if (appState.current.match(/inactive|background/) && nextAppState === 'active') {
CameraPermission.getCameraPermissionStatus().then((permissionStatus) => {
setPermissions(permissionStatus);
});
const refreshCameraPermissionStatus = () => {
CameraPermission.getCameraPermissionStatus()
.then(setCameraPermissionStatus)
.catch(() => setCameraPermissionStatus(RESULTS.UNAVAILABLE));
};

// Check initial camera permission status
refreshCameraPermissionStatus();

// Refresh permission status when app gain focus
const subscription = AppState.addEventListener('change', (appState) => {
if (appState !== 'active') {
return;
}

appState.current = nextAppState;
refreshCameraPermissionStatus();
});

return () => {
Expand Down Expand Up @@ -154,14 +159,17 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
const askForPermissions = () => {
// There's no way we can check for the BLOCKED status without requesting the permission first
// https://github.com/zoontek/react-native-permissions/blob/a836e114ce3a180b2b23916292c79841a267d828/README.md?plain=1#L670
if (permissions === RESULTS.BLOCKED || isAndroidBlockedPermissionRef.current) {
Linking.openSettings();
} else if (permissions === RESULTS.DENIED) {
CameraPermission.requestCameraPermission().then((permissionStatus) => {
setPermissions(permissionStatus);
isAndroidBlockedPermissionRef.current = permissionStatus === RESULTS.BLOCKED;
CameraPermission.requestCameraPermission()
.then((status) => {
setCameraPermissionStatus(status);

if (status === RESULTS.BLOCKED) {
showPermissionsAlert();
}
})
.catch(() => {
setCameraPermissionStatus(RESULTS.UNAVAILABLE);
});
}
};

/**
Expand Down Expand Up @@ -230,13 +238,14 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
});
}, [flash, iouType, iou, report, translate, transactionID, route.path]);

CameraPermission.getCameraPermissionStatus().then((permissionStatus) => {
setPermissions(permissionStatus);
});
// Wait for camera permission status to render
if (cameraPermissionStatus == null) {
return null;
}

return (
<View style={styles.flex1}>
{permissions !== RESULTS.GRANTED && (
{cameraPermissionStatus !== RESULTS.GRANTED && (
<View style={[styles.cameraView, styles.permissionView]}>
<Hand
width={CONST.RECEIPT.HAND_ICON_WIDTH}
Expand All @@ -255,7 +264,7 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
/>
</View>
)}
{permissions === RESULTS.GRANTED && device == null && (
{cameraPermissionStatus === RESULTS.GRANTED && device == null && (
<View style={[styles.cameraView]}>
<ActivityIndicator
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
Expand All @@ -264,7 +273,7 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
/>
</View>
)}
{permissions === RESULTS.GRANTED && device != null && (
{cameraPermissionStatus === RESULTS.GRANTED && device != null && (
<CameraComponent
ref={camera}
device={device}
Expand Down Expand Up @@ -322,7 +331,7 @@ function ReceiptSelector({route, report, iou, transactionID, isInTabNavigator})
accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON}
accessibilityLabel={translate('receipt.flash')}
style={[styles.alignItemsEnd]}
disabled={permissions !== RESULTS.GRANTED}
disabled={cameraPermissionStatus !== RESULTS.GRANTED}
onPress={() => setFlash((prevFlash) => !prevFlash)}
>
<Icon
Expand Down

0 comments on commit 012538a

Please sign in to comment.