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