280 lines
6.2 KiB
TypeScript
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 ===');
|
|
}
|