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