1import { PermissionStatus, Platform } from 'expo-modules-core'; 2 3import { 4 NativeNotificationPermissionsRequest, 5 NotificationPermissionsStatus, 6} from './NotificationPermissions.types'; 7import { NotificationPermissionsModule } from './NotificationPermissionsModule.types'; 8 9function convertPermissionStatus( 10 status?: NotificationPermission | 'prompt' 11): NotificationPermissionsStatus { 12 switch (status) { 13 case 'granted': 14 return { 15 status: PermissionStatus.GRANTED, 16 expires: 'never', 17 canAskAgain: false, 18 granted: true, 19 }; 20 case 'denied': 21 return { 22 status: PermissionStatus.DENIED, 23 expires: 'never', 24 canAskAgain: false, 25 granted: false, 26 }; 27 default: 28 return { 29 status: PermissionStatus.UNDETERMINED, 30 expires: 'never', 31 canAskAgain: true, 32 granted: false, 33 }; 34 } 35} 36 37async function resolvePermissionAsync({ 38 shouldAsk, 39}: { 40 shouldAsk: boolean; 41}): Promise<NotificationPermissionsStatus> { 42 if (!Platform.isDOMAvailable) { 43 return convertPermissionStatus('denied'); 44 } 45 46 const { Notification = {} } = window as any; 47 if (typeof Notification.requestPermission !== 'undefined') { 48 let status = Notification.permission; 49 if (shouldAsk) { 50 status = await new Promise((resolve, reject) => { 51 let resolved = false; 52 function resolveOnce(status: string) { 53 if (!resolved) { 54 resolved = true; 55 resolve(status); 56 } 57 } 58 // Some browsers require a callback argument and some return a Promise 59 Notification.requestPermission(resolveOnce)?.then(resolveOnce)?.catch(reject); 60 }); 61 } 62 return convertPermissionStatus(status); 63 } else if (typeof navigator !== 'undefined' && navigator?.permissions?.query) { 64 // TODO(Bacon): Support `push` in the future when it's stable. 65 const query = await navigator.permissions.query({ name: 'notifications' }); 66 return convertPermissionStatus(query.state); 67 } 68 // Platforms like iOS Safari don't support Notifications so return denied. 69 return convertPermissionStatus('denied'); 70} 71 72export default { 73 addListener: () => {}, 74 removeListeners: () => {}, 75 async getPermissionsAsync(): Promise<NotificationPermissionsStatus> { 76 return resolvePermissionAsync({ shouldAsk: false }); 77 }, 78 async requestPermissionsAsync( 79 request: NativeNotificationPermissionsRequest 80 ): Promise<NotificationPermissionsStatus> { 81 return resolvePermissionAsync({ shouldAsk: true }); 82 }, 83} as NotificationPermissionsModule; 84