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) 60 ?.then(resolveOnce) 61 ?.catch(reject); 62 }); 63 } 64 return convertPermissionStatus(status); 65 } else if (typeof navigator !== 'undefined' && navigator?.permissions?.query) { 66 // TODO(Bacon): Support `push` in the future when it's stable. 67 const query = await navigator.permissions.query({ name: 'notifications' }); 68 return convertPermissionStatus(query.state); 69 } 70 // Platforms like iOS Safari don't support Notifications so return denied. 71 return convertPermissionStatus('denied'); 72} 73 74export default { 75 addListener: () => {}, 76 removeListeners: () => {}, 77 async getPermissionsAsync(): Promise<NotificationPermissionsStatus> { 78 return resolvePermissionAsync({ shouldAsk: false }); 79 }, 80 async requestPermissionsAsync( 81 request: NativeNotificationPermissionsRequest 82 ): Promise<NotificationPermissionsStatus> { 83 return resolvePermissionAsync({ shouldAsk: true }); 84 }, 85} as NotificationPermissionsModule; 86