1import invariant from 'invariant'; 2 3import { NativeURLListener, URLListener } from './Linking.types'; 4 5const listeners: { listener: URLListener; nativeListener: NativeURLListener }[] = []; 6 7export default { 8 addEventListener(type: 'url', listener: URLListener): { remove(): void } { 9 // Do nothing in Node.js environments 10 if (typeof window === 'undefined') { 11 return { remove() {} }; 12 } 13 14 invariant(type === 'url', `Linking.addEventListener(): ${type} is not a valid event`); 15 const nativeListener: NativeURLListener = (nativeEvent) => 16 listener({ url: window.location.href, nativeEvent }); 17 listeners.push({ listener, nativeListener }); 18 window.addEventListener('message', nativeListener, false); 19 return { 20 remove: () => { 21 this.removeEventListener(type, listener); 22 }, 23 }; 24 }, 25 26 removeEventListener(type: 'url', listener: URLListener): void { 27 // Do nothing in Node.js environments 28 if (typeof window === 'undefined') { 29 return; 30 } 31 invariant(type === 'url', `Linking.addEventListener(): ${type} is not a valid event`); 32 const listenerIndex = listeners.findIndex((pair) => pair.listener === listener); 33 invariant( 34 listenerIndex !== -1, 35 'Linking.removeEventListener(): cannot remove an unregistered event listener.' 36 ); 37 const nativeListener = listeners[listenerIndex].nativeListener; 38 window.removeEventListener('message', nativeListener, false); 39 listeners.splice(listenerIndex, 1); 40 }, 41 42 async canOpenURL(): Promise<boolean> { 43 // In reality this should be able to return false for links like `chrome://` on chrome. 44 return true; 45 }, 46 47 async getInitialURL(): Promise<string> { 48 if (typeof window === 'undefined') return ''; 49 return window.location.href; 50 }, 51 52 async openURL(url: string): Promise<void> { 53 if (typeof window !== 'undefined') { 54 // @ts-ignore 55 window.location = new URL(url, window.location).toString(); 56 } 57 }, 58}; 59