T4B_Chat/utilities/permissionUtils.ts

280 lines
6.2 KiB
TypeScript

import { Platform, Alert } from 'react-native';
import messaging, { AuthorizationStatus } from '@react-native-firebase/messaging';
import { request, PERMISSIONS, RESULTS, Permission } from 'react-native-permissions';
export interface PermissionResult {
granted: boolean;
status: string;
needsRequest: boolean;
platform: string;
androidVersion?: number;
}
/**
* Check if the device requires explicit notification permission request
* Android 13+ (API 33+) requires POST_NOTIFICATIONS permission
* Older Android versions don't need explicit permission for notifications
*/
export function needsNotificationPermission(): boolean {
if (Platform.OS === 'ios') {
return true; // iOS always requires permission
}
if (Platform.OS === 'android') {
// Android 13+ (API level 33+) requires POST_NOTIFICATIONS permission
return Platform.Version >= 33;
}
return false;
}
/**
* Get the appropriate notification permission constant based on platform
*/
export function getNotificationPermission(): Permission | null {
if (Platform.OS === 'android') {
//@ts-ignore
return 'android.permission.POST_NOTIFICATIONS';
}
// iOS uses Firebase messaging permission, not react-native-permissions
return null;
}
/**
* Request notification permission for Android 13+
* Returns permission status information
*/
export async function requestNotificationPermission(): Promise<PermissionResult> {
if (Platform.OS === 'ios') {
// iOS uses Firebase messaging permission
try {
const authStatus = await messaging().requestPermission();
const granted = authStatus === AuthorizationStatus.AUTHORIZED ||
authStatus === AuthorizationStatus.PROVISIONAL;
return {
granted,
status: AuthorizationStatus[authStatus],
needsRequest: true,
platform: 'ios'
};
} catch (error) {
return {
granted: false,
status: 'ERROR',
needsRequest: true,
platform: 'ios'
};
}
}
if (Platform.OS === 'android') {
const androidVersion = Platform.Version as number;
const permission = getNotificationPermission();
if (!permission) {
// Older Android versions don't need explicit permission
return {
granted: true,
status: 'GRANTED',
needsRequest: false,
platform: 'android',
androidVersion
};
}
try {
const result = await request(permission);
return {
granted: result === RESULTS.GRANTED,
status: result,
needsRequest: true,
platform: 'android',
androidVersion
};
} catch (error) {
return {
granted: false,
status: 'ERROR',
needsRequest: true,
platform: 'android',
androidVersion
};
}
}
return {
granted: false,
status: 'UNSUPPORTED',
needsRequest: false,
platform: 'unknown'
};
}
/**
* Check current notification permission status
*/
export async function checkNotificationPermission(): Promise<PermissionResult> {
if (Platform.OS === 'ios') {
try {
const authStatus = await messaging().hasPermission();
const granted = authStatus === AuthorizationStatus.AUTHORIZED ||
authStatus === AuthorizationStatus.PROVISIONAL;
return {
granted,
status: AuthorizationStatus[authStatus],
needsRequest: !granted,
platform: 'ios'
};
} catch (error) {
return {
granted: false,
status: 'ERROR',
needsRequest: true,
platform: 'ios'
};
}
}
if (Platform.OS === 'android') {
const androidVersion = Platform.Version as number;
const permission = getNotificationPermission();
if (!permission) {
// Older Android versions - assume granted
return {
granted: true,
status: 'GRANTED',
needsRequest: false,
platform: 'android',
androidVersion
};
}
try {
const { check } = require('react-native-permissions');
const result = await check(permission);
return {
granted: result === RESULTS.GRANTED,
status: result,
needsRequest: result !== RESULTS.GRANTED,
platform: 'android',
androidVersion
};
} catch (error) {
return {
granted: false,
status: 'ERROR',
needsRequest: true,
platform: 'android',
androidVersion
};
}
}
return {
granted: false,
status: 'UNSUPPORTED',
needsRequest: false,
platform: 'unknown'
};
}
/**
* Show permission explanation dialog for Android
*/
export function showPermissionExplanation(): Promise<boolean> {
return new Promise((resolve) => {
Alert.alert(
'Notification Permission',
'This app needs notification permission to send you chat messages and updates. You can change this later in your device settings.',
[
{
text: 'Cancel',
style: 'cancel',
onPress: () => resolve(false),
},
{
text: 'Allow',
onPress: () => resolve(true),
},
]
);
});
}
/**
* Show settings redirect dialog when permission is denied
*/
export function showSettingsDialog(): void {
Alert.alert(
'Permission Required',
'Notification permission is required for this app to work properly. Please enable it in your device settings.',
[
{
text: 'Cancel',
style: 'cancel',
},
{
text: 'Open Settings',
onPress: () => {
// You can use react-native-permissions to open settings
// Linking.openSettings();
},
},
]
);
}
/**
* Debug function to test permission flow
* Call this from your app to see detailed permission information
*/
export async function debugPermissionFlow(): Promise<void> {
const permission = getNotificationPermission();
const currentStatus = await checkNotificationPermission();
if (!currentStatus.granted && currentStatus.needsRequest) {
const requestResult = await requestNotificationPermission();
;
}
console.log('🔧 === END DEBUG ===');
}