@cometchat/chat-uikit-react-native
Version:
Ready-to-use Chat UI Components for React Native
144 lines (130 loc) • 4.52 kB
text/typescript
import {
Alert,
Linking,
NativeModules,
PermissionsAndroid,
Platform,
} from 'react-native';
import { localize } from '../resources/CometChatLocalize/CometChatLocalize';
import { anyObject } from './TypeUtils';
const { FileManager } = NativeModules;
let instance: PermissionUtilIOS;
const permissionStatus = {
'Not Determined': 0,
'Restricted': 1,
'Denied': 2,
'Authorized': 3,
'Unknown': -1,
} as const;
const permissionStatusAndroid = {
granted: 3,
denied: 2,
never_ask_again: 2,
} as any;
const permissibleResources = ['camera', 'mic'] as const;
const permissionMapAndroid: any = {
camera: PermissionsAndroid.PERMISSIONS.CAMERA,
mic: PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
};
type TPermissibleResources = (typeof permissibleResources)[number];
type ValueOf<T> = T[keyof T];
type TPermissionStatus = ValueOf<typeof permissionStatus>;
const permissionStore: any = {
camera: permissionStatus.Unknown,
mic: permissionStatus.Unknown,
};
class PermissionUtilIOS {
status = permissionStatus;
constructor() {
if (instance) {
throw new Error('New instance cannot be created!!');
}
instance = this;
}
async init() {
try {
if (Platform.OS === "ios") {
const res: Record<TPermissibleResources, TPermissionStatus> =
await FileManager.checkResourcesPermission(['mic', 'camera']);
for (const resourceType in res) {
permissionStore[resourceType as TPermissibleResources] =
res[resourceType as TPermissibleResources];
}
permissionStore.camera = res.camera;
permissionStore.mic = res.mic;
} else if (Platform.OS === "android") {
for (const resourceType of permissibleResources) {
const isGranted = await PermissionsAndroid.check(permissionMapAndroid[resourceType]);
permissionStore[resourceType] = isGranted ? permissionStatus.Authorized : permissionStatus['Not Determined'];
}
}
return true;
} catch (error: any) {
return false;
}
}
async get(resources: TPermissibleResources[]) {
return resources.map((resource) => {
if (!permissibleResources.includes(resource)) {
throw new Error('Invalid resource type');
}
return permissionStore[resource];
});
}
async request(resources: TPermissibleResources[]) {
for (const resource of resources) {
if (!permissibleResources.includes(resource)) {
throw new Error('Invalid resource type');
}
}
if (Platform.OS === 'ios') {
const res: Record<TPermissibleResources, TPermissionStatus> =
await FileManager.requestResourcesPermission(resources);
for (const resourceType in res) {
permissionStore[resourceType as TPermissibleResources] =
res[resourceType as TPermissibleResources];
}
} else if (Platform.OS === 'android') {
const res: any = await PermissionsAndroid.requestMultiple(resources.map(item => permissionMapAndroid[item]));
const permissionMapAndroidRevert: anyObject = {};
for (const resource in permissionMapAndroid) {
permissionMapAndroidRevert[permissionMapAndroid[resource]] = resource;
}
for (const androidResource in res) {
permissionStore[permissionMapAndroidRevert[androidResource]] =
permissionStatusAndroid[res[androidResource]];
}
}
}
async startResourceBasedTask(resources: TPermissibleResources[]) {
const resourcePermStatuses = await this.get(resources);
let allResourcesAllowed = true;
for (let i = 0; i < resourcePermStatuses.length; i++) {
const resourcePermStatus = resourcePermStatuses[i];
if (resourcePermStatus === this.status['Not Determined'] || (Platform.OS === "android" && resourcePermStatuses[i] === this.status.Denied)) {
await this.request([resources[i]]);
[resourcePermStatuses[i]] = await this.get([resources[i]]);
}
if (resourcePermStatuses[i] === this.status.Denied) {
allResourcesAllowed = false;
}
}
if (allResourcesAllowed === false) {
Alert.alert('', localize('CAMERA_PERMISSION'), [
{
style: 'cancel',
text: localize('CANCEL'),
},
{
style: 'default',
text: localize('SETTINGS'),
onPress: () => {
Linking.openSettings();
},
},
]);
}
return allResourcesAllowed;
}
}
export const permissionUtil = Object.freeze(new PermissionUtilIOS());