Skip to content

Instantly share code, notes, and snippets.

@sayurimizuguchi
Created October 9, 2022 02:21
Show Gist options
  • Save sayurimizuguchi/b0e80127c8ae86a0fd7487f07ea7608a to your computer and use it in GitHub Desktop.
Save sayurimizuguchi/b0e80127c8ae86a0fd7487f07ea7608a to your computer and use it in GitHub Desktop.
React Native Permission - Photo Library example (support for Android and iOS)
import { useEffect, useState } from 'react';
import { Platform, Alert, AppState, AppStateStatus, Linking } from 'react-native';
import { check, PERMISSIONS, RESULTS, request } from 'react-native-permissions';
import useTranslation from './useTranslation';
interface IPhotoLibraryRequestState {
isRequesting: boolean;
resolve: (val: boolean) => void;
}
const initialState: IPhotoLibraryRequestState = {
isRequesting: false,
resolve: () => {},
};
type ResultType = 'unavailable' | 'blocked' | 'denied' | 'granted' | 'limited';
export default () => {
const { t } = useTranslation(['common', 'hooks']);
const [appState, setAppState] = useState<AppStateStatus>('active');
const [requestState, setRequestState] = useState<IPhotoLibraryRequestState>(initialState);
const [result, setResult] = useState<ResultType>(RESULTS.UNAVAILABLE);
const [isGranted, setIsGranted] = useState<boolean>(false);
const permission = Platform.select({
ios: PERMISSIONS.IOS.PHOTO_LIBRARY,
android: PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
default: PERMISSIONS.IOS.PHOTO_LIBRARY,
});
const resolvePromise = (val: boolean) => {
setIsGranted(val);
requestState.resolve(val);
setRequestState(initialState);
};
const updateAppState = async (currentAppState: AppStateStatus) => {
setAppState(currentAppState);
};
const checkPermission = async () => {
const response = await check(permission);
if (result === response) {
resolvePromise(result === RESULTS.GRANTED);
} else {
setResult(response);
}
};
useEffect(() => {
AppState.addEventListener('change', updateAppState);
checkPermission();
return () => AppState.removeEventListener('change', updateAppState);
}, []);
useEffect(() => {
if (appState !== 'active') return;
checkPermission();
}, [appState]);
useEffect(() => {
if (!requestState.isRequesting) return;
if (result === RESULTS.GRANTED) {
resolvePromise(result === RESULTS.GRANTED);
} else {
WarningAlert();
}
}, [result]);
useEffect(() => {
if (!requestState.isRequesting) return;
(async () => {
switch (result) {
case RESULTS.UNAVAILABLE:
resolvePromise(false);
break;
case RESULTS.DENIED:
request(permission);
break;
case RESULTS.BLOCKED:
case RESULTS.LIMITED:
WarningAlert();
return;
case RESULTS.GRANTED:
resolvePromise(true);
break;
}
})();
}, [requestState]);
const WarningAlert = () =>
Alert.alert(
t('hooks:usePhotoLibraryPermission.alert.title'),
t('hooks:usePhotoLibraryPermission.alert.body'),
[
{
text: t('common:close'),
onPress: () => resolvePromise(false),
},
{
text: t('common:openSettings'),
onPress: () => Linking.openSettings(),
},
],
);
const handleRequest = (): Promise<boolean> =>
new Promise(resolve => {
setRequestState({
isRequesting: true,
resolve,
});
});
return {
isGranted,
request: handleRequest,
isRequesting: requestState.isRequesting,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment