/ src / components / decorators / HlsJSDecorator.svelte
HlsJSDecorator.svelte
 1  <script lang="ts" context="module">
 2      // This store is used to keep track of in-flight requests, ensuring that we don't attempt
 3      // to load the same src (which is stored in the Map key) multiple times.
 4      const inFlightRequests = new Map<string, Promise<void>>();
 5  </script>
 6  
 7  <script lang="ts">
 8      import { onMount } from 'svelte';
 9      import { generateHLSJSURL } from '~/config/hlsjs';
10      import { generateRTCJSURL } from '~/config/rtcjs';
11  
12      export let version: string | undefined = undefined;
13  
14      let hlsjsSourceURL = generateHLSJSURL(version).toString();
15      let rtcjsSourceURL = generateRTCJSURL(version).toString();
16  
17      function loadScript(src: string): Promise<void> {
18          // If we have an in-flight request for this `src`, return it.
19          const inFlightRequest = inFlightRequests.get(src);
20          if (inFlightRequest) {
21              return inFlightRequest;
22          }
23  
24          const promise = new Promise<void>(function (resolve, reject) {
25              const scriptElement = document.createElement('script');
26              scriptElement.src = src;
27              scriptElement.onload = () => resolve();
28              scriptElement.onerror = () => {
29                  // If a script fails to load due to a network blip, we remove it from the store,
30                  // so that the next attempt in an `onMount` will try to load the `src` again.
31                  inFlightRequests.delete(src);
32                  reject();
33              };
34  
35              document.head.appendChild(scriptElement);
36          });
37  
38          // Add the given `src` to the store so we can keep track of in-flight requests.
39          inFlightRequests.set(src, promise);
40  
41          return promise;
42      }
43  
44      let loading: Promise<[void, void]> | undefined;
45  
46      onMount(() => {
47          loading = Promise.all([
48              window.Hls ?? loadScript(hlsjsSourceURL),
49              window.rtc ?? loadScript(rtcjsSourceURL),
50          ]);
51      });
52  </script>
53  
54  {#if loading}
55      {#await loading}
56          <slot name="loading-component" />
57      {:then}
58          <slot HLS={window.Hls} RTC={window.rtc} />
59      {:catch}
60          <div>
61              <p>
62                  Failed to load HLS.js {version} from
63                  <a href={hlsjsSourceURL}>{hlsjsSourceURL}</a>
64              </p>
65          </div>
66      {/await}
67  {/if}