/ src / components / pages / ProductPage.svelte
ProductPage.svelte
 1  <script lang="ts">
 2      import type { ShelfBasedProductPage } from '@jet-app/app-store/api/models';
 3      import { isFlowAction } from '@jet-app/app-store/api/models';
 4      import type { WebRenderablePage } from '@jet-app/app-store/api/models/web-renderable-page';
 5  
 6      import DefaultPage, {
 7          type DefaultPageRequirements,
 8      } from '~/components/pages/DefaultPage.svelte';
 9      import MarkerShelf from '~/components/jet/shelf/MarkerShelf.svelte';
10      import ProductPageArcadeFooter from '~/components/ProductPageArcadeFooter.svelte';
11      import { getProductPageShelvesWithExpandedMedia } from '~/utils/shelves';
12      import { setAccessibilityLayoutContext } from '~/context/accessibility-layout';
13      import { getJet } from '~/jet';
14      import { isProductPageLinkShelf } from '~/components/jet/shelf/ProductPageLinkShelf.svelte';
15      import { isEulaPageIntent } from '@jet-app/app-store/api/intents/eula-page-intent';
16      export let page: ShelfBasedProductPage & WebRenderablePage;
17  
18      const jet = getJet();
19  
20      $: ({ presentationOptions, webNavigation } = page);
21  
22      $: shelves = getProductPageShelvesWithExpandedMedia(page);
23  
24      let defaultPageRequirements: DefaultPageRequirements;
25  
26      $: defaultPageRequirements = {
27          shelves,
28          presentationOptions,
29          webNavigation,
30      };
31  
32      // Set up accessibility layout context for neighbor shelf detection
33      $: {
34          setAccessibilityLayoutContext({ shelves });
35  
36          /**
37           * We suppport "deep linking" to the product page with the License Agreement modal open by
38           * default, based on the presence of the `lic` query parameter. No other modals support
39           * opening via deep link, which is why there isn't a more robust solution for this use case.
40           * Instead, we are just firing off the click action from the license agreement shelf.
41           */
42          if (page.canonicalURL) {
43              const canonicalUrl = new URL(page.canonicalURL);
44              const hasLic = canonicalUrl.searchParams.has('lic');
45  
46              if (hasLic && shelves) {
47                  const eulaItem = shelves
48                      .find(isProductPageLinkShelf)
49                      ?.items.find(
50                          ({ clickAction }) =>
51                              isFlowAction(clickAction) &&
52                              clickAction.destination &&
53                              isEulaPageIntent(clickAction.destination),
54                      );
55  
56                  if (eulaItem) {
57                      jet.perform(eulaItem.clickAction);
58                  }
59              }
60          }
61      }
62  
63      // TODO: replace with `supportsArcade` from Jet
64      // rdar://143706610 (Support `supportsArcade` attribute)
65      $: supportsArcade =
66          page.lockup.offerDisplayProperties?.offerType === 'arcadeApp';
67  </script>
68  
69  <DefaultPage page={defaultPageRequirements}>
70      <svelte:fragment slot="marker-shelf" let:shelf>
71          <MarkerShelf {shelf} {page} />
72      </svelte:fragment>
73  </DefaultPage>
74  
75  {#if supportsArcade}
76      <ProductPageArcadeFooter />
77  {/if}