Skip to content

Commit bbc8a26

Browse files
author
Jon Tzeng
committed
Fix camera permissions race condition
1 parent 5b69950 commit bbc8a26

3 files changed

Lines changed: 22 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- fixed: ramps: Various Infinite UI/UX issues
1313
- fixed: Search keyboard not dismissing when submitting search
1414
- fixed: Auto-correct not disabled for search input
15+
- fixed: Inaccurate camera permissions detection
1516
- fixed: In-app review for iOS 18+
1617

1718
## 4.41.1 (2025-12-29)

src/components/modals/ScanModal.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { sprintf } from 'sprintf-js'
1717
import { useLayout } from '../../hooks/useLayout'
1818
import { lstrings } from '../../locales/strings'
1919
import { config } from '../../theme/appConfig'
20-
import { useSelector } from '../../types/reactRedux'
20+
import { useDispatch, useSelector } from '../../types/reactRedux'
2121
import { triggerHaptic } from '../../util/haptic'
2222
import { logActivity } from '../../util/logger'
2323
import { ModalButtons } from '../buttons/ModalButtons'
@@ -62,6 +62,7 @@ export const ScanModal: React.FC<Props> = props => {
6262
scanModalTitle
6363
} = props
6464

65+
const dispatch = useDispatch()
6566
const theme = useTheme()
6667
const styles = getStyles(theme)
6768

@@ -87,13 +88,13 @@ export const ScanModal: React.FC<Props> = props => {
8788
// Mount effects
8889
React.useEffect(() => {
8990
setScanEnabled(true)
90-
checkAndRequestPermission('camera').catch((error: unknown) => {
91+
dispatch(checkAndRequestPermission('camera')).catch((error: unknown) => {
9192
showError(error)
9293
})
9394
return () => {
9495
setScanEnabled(false)
9596
}
96-
}, [])
97+
}, [dispatch])
9798

9899
const handleBarCodeRead = (codes: Code[]): void => {
99100
setScanEnabled(false)

src/components/services/PermissionsManager.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,24 @@ export async function requestContactsPermission(
8787
}
8888

8989
/**
90-
* Checks permission and attempts to request permissions (only if checked
91-
* permission was 'denied')
90+
* Checks permission and requests when denied, then syncs Redux with the
91+
* resulting status.
9292
*/
93-
export async function checkAndRequestPermission(
94-
data: Permission
95-
): Promise<PermissionStatus> {
96-
const status: PermissionStatus = await check(permissionNames[data])
93+
export const checkAndRequestPermission =
94+
(permission: Permission): ThunkAction<Promise<PermissionStatus>> =>
95+
async dispatch => {
96+
let status: PermissionStatus = await check(permissionNames[permission])
9797

98-
if (status === 'denied') return await request(permissionNames[data])
99-
else return status
100-
}
98+
if (status === 'denied') {
99+
status = await request(permissionNames[permission])
100+
}
101+
102+
dispatch({
103+
type: 'PERMISSIONS/UPDATE',
104+
data: { [permission]: status }
105+
})
106+
return status
107+
}
101108

102109
export const checkIfDenied = (status: PermissionStatus) =>
103110
status === 'blocked' || status === 'denied' || status === 'unavailable'
@@ -126,7 +133,7 @@ export async function requestPermissionOnSettings(
126133

127134
// User first time check. If mandatory, it needs to be checked if denied or accepted
128135
if (status === 'denied') {
129-
const result = await checkAndRequestPermission(data)
136+
const result = await request(permissionNames[data])
130137
return mandatory && checkIfDenied(result)
131138
}
132139

0 commit comments

Comments
 (0)