summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/web-navigation
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet-app/app-store/tmp/src/common/web-navigation
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/web-navigation')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/flow-action-presentation.js79
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/inject-web-navigation.js32
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/landing-page-links-by-platform.js62
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-intent-controllers.js155
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-utils.js139
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-selection.js115
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/search-results-platform-selection.js28
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/web-navigation/web-navigation.js28
8 files changed, 638 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/flow-action-presentation.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/flow-action-presentation.js
new file mode 100644
index 0000000..41b5bb9
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/flow-action-presentation.js
@@ -0,0 +1,79 @@
+import { isSystemImage } from "../../api/models";
+import { asString } from "../../foundation/json-parsing/server-data";
+import { createArtworkForSystemImage } from "../content/artwork/artwork";
+import * as metricsHelpersClicks from "../metrics/helpers/clicks";
+import * as metricsHelpersLocation from "../metrics/helpers/location";
+/**
+ * Creates a {@linkcode PrepareAction} that sets the link's text and icon
+ */
+function createWebNavigationFlowActionConfiguration(id) {
+ return (objectGraph, action) => {
+ const tab = objectGraph.bag.tabsStandard.find((t) => t.id === id);
+ const imageIdentifier = asString(tab, "image-identifier");
+ const artwork = isSystemImage(imageIdentifier)
+ ? createArtworkForSystemImage(objectGraph, imageIdentifier)
+ : null;
+ action.title = asString(tab, "title");
+ action.artwork = artwork;
+ if (objectGraph.client.isWeb) {
+ metricsHelpersClicks.addClickEventToAction(objectGraph, action, {
+ targetType: "link",
+ id: id,
+ pageInformation: undefined,
+ locationTracker: metricsHelpersLocation.newLocationTracker(),
+ });
+ }
+ };
+}
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Apps" landing page
+ */
+export const appLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("apps");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Apps & Games" landing page
+ */
+export const appAndGamesLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("apps-and-games");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Arcade" landing page
+ */
+export const arcadeLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("arcade");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Discover" landing page
+ */
+export const discoverLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("discover");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Games" landing page
+ */
+export const gamesLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("games");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Create" landing page
+ *
+ * Note: `create` refers to the specific "Create" landing page, rather than this being
+ * a function that creates landing page presentations
+ */
+export const createLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("create");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Work" landing page
+ */
+export const workLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("work");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Play" landing page
+ */
+export const playLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("play");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Develop" landing page
+ */
+export const developLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("develop");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Categories" landing page
+ */
+export const categoriesLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("categories");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Today" landing page
+ */
+export const todayLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("today");
+/**
+ * {@linkcode PrepareAction} that presents a link to the "Apps & Games" landing page
+ */
+export const searchLandingPageFlowActionPresentation = createWebNavigationFlowActionConfiguration("search");
+//# sourceMappingURL=flow-action-presentation.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/inject-web-navigation.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/inject-web-navigation.js
new file mode 100644
index 0000000..b882c17
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/inject-web-navigation.js
@@ -0,0 +1,32 @@
+import { createWebNavigation, setActivePlatform } from "./web-navigation";
+/**
+ * The "default" {@linkcode PreviewPlatform} that should be used for the navigation state in cases
+ * where an explicit value is not provided
+ */
+const FALLBACK_PREVIEW_PLATFORM = "iphone";
+/**
+ * Inject the `WebNavigation` into a page model
+ *
+ * @param objectGraph
+ * @param page the page to inject the navigation into
+ * @param platform the `PreviewPlatform` to render navigation links for
+ * @returns the web navigation shelf, in case further mutation is required
+ */
+export function injectWebNavigation(objectGraph, page, platform) {
+ const webNavigation = createWebNavigation(objectGraph, platform !== null && platform !== void 0 ? platform : FALLBACK_PREVIEW_PLATFORM);
+ if (page.title) {
+ webNavigation.title = page.title;
+ }
+ page.webNavigation = webNavigation;
+ return webNavigation;
+}
+/**
+ * Sets the `WebNavigation` contained by {@linkcode page} to reflect {@linkcode platform}
+ * as the active platform. Landing pages links will also be made active based on {@linkcode intent}
+ */
+export function updateWebNavigation(objectGraph, page, platform, intent) {
+ if (page.webNavigation) {
+ setActivePlatform(objectGraph, page.webNavigation, platform, intent);
+ }
+}
+//# sourceMappingURL=inject-web-navigation.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/landing-page-links-by-platform.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/landing-page-links-by-platform.js
new file mode 100644
index 0000000..02aad6c
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/landing-page-links-by-platform.js
@@ -0,0 +1,62 @@
+import { isPreviewPlatform } from "../../api/models/preview-platform";
+import { getLocale } from "../locale";
+import { landingPageIntentsAreEquivalent, } from "./platform-landing-page-utils";
+import { iPadTodayPageController, iPadAppsController, iPadArcadeController, iPadGamesController, iPadSearchLandingController, iPhoneTodayPageController, iPhoneAppsController, iPhoneGamesController, iPhoneArcadeController, iPhoneSearchLandingController, MacDiscoverController, MacArcadeController, MacCreateController, MacWorkController, MacPlayController, MacDevelopController, MacCategoriesController, MacSearchLandingController, TVAppsController, TVArcadeController, TVDiscoverController, TVGamesController, TVSearchLandingController, VisionAppsAndGamesController, VisionArcadeController, VisionSearchLandingController, WatchDiscoverController, WatchSearchLandingController, } from "./platform-landing-page-intent-controllers";
+const ARCADE_CONTROLLERS = new Set([
+ iPadArcadeController,
+ iPhoneArcadeController,
+ MacArcadeController,
+ TVArcadeController,
+ VisionArcadeController,
+]);
+export function createLandingPageLinks(objectGraph, platform, intent) {
+ if (!platform || !isPreviewPlatform(platform)) {
+ return [];
+ }
+ // NOTE: this map cannot be defined at the module level, for risk of creating
+ // a circular dependency between module-level declarations that will break the build
+ // tools used by the "web" client
+ const landingPageControllers = {
+ ipad: [
+ iPadTodayPageController,
+ iPadGamesController,
+ iPadAppsController,
+ iPadArcadeController,
+ iPadSearchLandingController,
+ ],
+ iphone: [
+ iPhoneTodayPageController,
+ iPhoneGamesController,
+ iPhoneAppsController,
+ iPhoneArcadeController,
+ iPhoneSearchLandingController,
+ ],
+ mac: [
+ MacDiscoverController,
+ MacArcadeController,
+ MacCreateController,
+ MacWorkController,
+ MacPlayController,
+ MacDevelopController,
+ MacCategoriesController,
+ MacSearchLandingController,
+ ],
+ tv: [TVDiscoverController, TVGamesController, TVAppsController, TVArcadeController, TVSearchLandingController],
+ vision: [VisionAppsAndGamesController, VisionArcadeController, VisionSearchLandingController],
+ watch: [WatchDiscoverController, WatchSearchLandingController],
+ };
+ const locale = getLocale(objectGraph);
+ const isArcadeEnabled = objectGraph.bag.isArcadeEnabled;
+ return landingPageControllers[platform]
+ .filter((landingPageController) => {
+ // Rejects Arcade controllers if not supported and let's all other controllers pass
+ const isArcadeController = ARCADE_CONTROLLERS.has(landingPageController);
+ return isArcadeEnabled || !isArcadeController;
+ })
+ .map((controller) => controller.buildAction(locale, objectGraph))
+ .map((action) => ({
+ action,
+ isActive: landingPageIntentsAreEquivalent(intent, action.destination),
+ }));
+}
+//# sourceMappingURL=landing-page-links-by-platform.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-intent-controllers.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-intent-controllers.js
new file mode 100644
index 0000000..d19d46b
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-intent-controllers.js
@@ -0,0 +1,155 @@
+// This module, despite exporting `IntentController` definitions, lives inside of
+// `src/common` because these controllers need to be import-able by other "common"
+// code in order to directly call their `buildIntent` method
+//
+// The "web" client expects all exports from this module to be `IntentController` instances
+import { defineLandingPageController, definePlatformRootRedirectController, defineRootRedirectController, } from "./platform-landing-page-utils";
+import { makeEditorialPageIntentByName } from "../../api/intents/editorial/editorial-page-intent";
+import { makeGroupingPageIntentByName } from "../../api/intents/grouping-page-intent";
+import { makeRoutableTodayPageIntent } from "../../api/intents/routable-today-page-intent";
+import { makeArcadeGroupingPageIntent } from "../../api/intents/arcade-grouping-page-intent";
+import { appLandingPageFlowActionPresentation, appAndGamesLandingPageFlowActionPresentation, arcadeLandingPageFlowActionPresentation, discoverLandingPageFlowActionPresentation, gamesLandingPageFlowActionPresentation, createLandingPageFlowActionPresentation, workLandingPageFlowActionPresentation, playLandingPageFlowActionPresentation, todayLandingPageFlowActionPresentation, developLandingPageFlowActionPresentation, categoriesLandingPageFlowActionPresentation, searchLandingPageFlowActionPresentation, } from "./flow-action-presentation";
+import { makeSearchLandingPageIntent } from "../../api/intents/search/search-landing-page-intent";
+// Ensures that the root URL (e.g. apps.apple.com) redirects to the iPhone Today page
+export const RootRedirectController = defineRootRedirectController((locale) => iPhoneTodayPageController.buildIntent(locale));
+/// MARK: Vision Pro Landing Pages
+export const VisionRootRedirectController = definePlatformRootRedirectController("/vision", (locale) => VisionAppsAndGamesController.buildIntent(locale));
+export const VisionAppsAndGamesController = defineLandingPageController("/vision/apps-and-games", (locale) => makeEditorialPageIntentByName({
+ ...locale,
+ platform: "vision",
+ name: "apps-and-games",
+}), appAndGamesLandingPageFlowActionPresentation);
+export const VisionArcadeController = defineLandingPageController("/vision/arcade", (locale) => makeEditorialPageIntentByName({
+ ...locale,
+ platform: "vision",
+ name: "arcade-subscriber",
+}), arcadeLandingPageFlowActionPresentation);
+export const VisionSearchLandingController = defineLandingPageController("/vision/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "vision",
+}), searchLandingPageFlowActionPresentation);
+/// MARK: Mac Landing Pages
+export const MacRootRedirectController = definePlatformRootRedirectController("/mac", (locale) => MacDiscoverController.buildIntent(locale));
+export const MacDiscoverController = defineLandingPageController("/mac/discover", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "apps",
+}), discoverLandingPageFlowActionPresentation);
+export const MacArcadeController = defineLandingPageController("/mac/arcade", (locale) => makeArcadeGroupingPageIntent({
+ ...locale,
+ platform: "mac",
+}), arcadeLandingPageFlowActionPresentation);
+export const MacCreateController = defineLandingPageController("/mac/create", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "create",
+}), createLandingPageFlowActionPresentation);
+export const MacWorkController = defineLandingPageController("/mac/work", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "work",
+}), workLandingPageFlowActionPresentation);
+export const MacPlayController = defineLandingPageController("/mac/play", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "play",
+}), playLandingPageFlowActionPresentation);
+export const MacDevelopController = defineLandingPageController("/mac/develop", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "develop",
+}), developLandingPageFlowActionPresentation);
+export const MacCategoriesController = defineLandingPageController("/mac/categories", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "mac",
+ name: "categories",
+}), categoriesLandingPageFlowActionPresentation);
+export const MacSearchLandingController = defineLandingPageController("/mac/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "mac",
+}), searchLandingPageFlowActionPresentation);
+/// MARK: iPhone Landing Pages
+export const iPhoneRootRedirectController = definePlatformRootRedirectController("/iphone", (locale) => iPhoneTodayPageController.buildIntent(locale));
+export const iPhoneTodayPageController = defineLandingPageController("/iphone/today", (locale) => makeRoutableTodayPageIntent({
+ ...locale,
+ platform: "iphone",
+}), todayLandingPageFlowActionPresentation);
+export const iPhoneAppsController = defineLandingPageController("/iphone/apps", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "iphone",
+ name: "apps",
+}), appLandingPageFlowActionPresentation);
+export const iPhoneGamesController = defineLandingPageController("/iphone/games", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "iphone",
+ name: "games",
+}), gamesLandingPageFlowActionPresentation);
+export const iPhoneArcadeController = defineLandingPageController("/iphone/arcade", (locale) => makeArcadeGroupingPageIntent({
+ ...locale,
+ platform: "iphone",
+}), arcadeLandingPageFlowActionPresentation);
+export const iPhoneSearchLandingController = defineLandingPageController("/iphone/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "iphone",
+}), searchLandingPageFlowActionPresentation);
+/// MARK: iPad Landing Pages
+export const iPadRootRedirectController = definePlatformRootRedirectController("/ipad", (locale) => iPadTodayPageController.buildIntent(locale));
+export const iPadTodayPageController = defineLandingPageController("/ipad/today", (locale) => makeRoutableTodayPageIntent({
+ ...locale,
+ platform: "ipad",
+}), todayLandingPageFlowActionPresentation);
+export const iPadGamesController = defineLandingPageController("/ipad/games", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "ipad",
+ name: "games",
+}), gamesLandingPageFlowActionPresentation);
+export const iPadAppsController = defineLandingPageController("/ipad/apps", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "ipad",
+ name: "apps",
+}), appLandingPageFlowActionPresentation);
+export const iPadArcadeController = defineLandingPageController("/ipad/arcade", (locale) => makeArcadeGroupingPageIntent({
+ ...locale,
+ platform: "ipad",
+}), arcadeLandingPageFlowActionPresentation);
+export const iPadSearchLandingController = defineLandingPageController("/ipad/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "ipad",
+}), searchLandingPageFlowActionPresentation);
+/// MARK: Watch Landing Pages
+export const WatchRootRedirectController = definePlatformRootRedirectController("/watch", (locale) => WatchDiscoverController.buildIntent(locale));
+export const WatchDiscoverController = defineLandingPageController("/watch/apps-and-games", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "watch",
+ name: "apps",
+}), appAndGamesLandingPageFlowActionPresentation);
+export const WatchSearchLandingController = defineLandingPageController("/watch/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "watch",
+}), searchLandingPageFlowActionPresentation);
+/// MARK: TV Landing Pages
+export const TVRootRedirectController = definePlatformRootRedirectController("/tv", (locale) => TVDiscoverController.buildIntent(locale));
+export const TVDiscoverController = defineLandingPageController("/tv/discover", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "tv",
+ name: "discover",
+}), discoverLandingPageFlowActionPresentation);
+export const TVGamesController = defineLandingPageController("/tv/games", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "tv",
+ name: "games",
+}), gamesLandingPageFlowActionPresentation);
+export const TVAppsController = defineLandingPageController("/tv/apps", (locale) => makeGroupingPageIntentByName({
+ ...locale,
+ platform: "tv",
+ name: "apps",
+}), appLandingPageFlowActionPresentation);
+export const TVArcadeController = defineLandingPageController("/tv/arcade", (locale) => makeArcadeGroupingPageIntent({
+ ...locale,
+ platform: "tv",
+}), arcadeLandingPageFlowActionPresentation);
+export const TVSearchLandingController = defineLandingPageController("/tv/search", (locale) => makeSearchLandingPageIntent({
+ ...locale,
+ platform: "tv",
+}), searchLandingPageFlowActionPresentation);
+//# sourceMappingURL=platform-landing-page-intent-controllers.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-utils.js
new file mode 100644
index 0000000..c408425
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-landing-page-utils.js
@@ -0,0 +1,139 @@
+import { isNothing, unwrapOptional as unwrap } from "@jet/environment/types/optional";
+import { FlowAction } from "../../api/models";
+import { generateRoutes } from "../util/generate-routes";
+import { updateWebNavigation } from "./inject-web-navigation";
+/**
+ * Determine if the two {@linkcode LandingPageIntent} arguments are equivalent
+ */
+export function landingPageIntentsAreEquivalent(activeIntent, navLinkIntent) {
+ if (isNothing(activeIntent) || isNothing(navLinkIntent)) {
+ return false;
+ }
+ for (const key of ["$kind", "storefront", "language"]) {
+ if (activeIntent[key] !== navLinkIntent[key]) {
+ return false;
+ }
+ }
+ return true;
+}
+/**
+ * Dynamically create an {@linkcode IntentController} for a platform "landing page"
+ *
+ * A "landing page" is a vanity URL within a specific platform that loads some other
+ * page under-the-hood; the "canonical URL" for the "landing page" should reflect this
+ * vanity URL, rather than the real canonical URL for the underlying Media API entity.
+ *
+ * @param url the vanity URL for the landing page
+ * @param intentFactory a function that produces the underlying `Intent` for the data backing the landing page
+ * @param prepareAction a function that can be used to provide additional configuration of the `FlowAction` for a landing page
+ */
+export function defineLandingPageController(url, intentFactory, prepareAction) {
+ const intentKind = `LandingPage_${url.substring(1)}_Intent`;
+ const { routes, makeCanonicalUrl } = generateRoutes((locale) => ({
+ ...locale,
+ $kind: intentKind,
+ }), url, [], {
+ exclusions: [
+ {
+ query: ["term"],
+ },
+ ],
+ });
+ return {
+ $intentKind: intentKind,
+ routes,
+ async perform(landingPageIntent, objectGraph) {
+ var _a;
+ const pageIntent = intentFactory({
+ storefront: landingPageIntent.storefront,
+ language: landingPageIntent.language,
+ });
+ const viewModel = await objectGraph.dispatcher.dispatch(pageIntent, objectGraph);
+ if (viewModel) {
+ // Override the default canonical URL to use the vanity URL instead; this ensures
+ // that the navigation mechanics of the "web" client respect the vanity URL, which the
+ // Media API would not know about when providing it's own value for this property
+ // @ts-expect-error TypeScript can't know that `landingPageIntent` satisfies the requirements of
+ // `makeCanonicalUrl`, but this will be safe at runtime because all we actually require
+ // from the intent is the locale information
+ viewModel.canonicalURL = makeCanonicalUrl(objectGraph, landingPageIntent);
+ (_a = objectGraph.seo) === null || _a === void 0 ? void 0 : _a.updateCanonicalURL(viewModel, viewModel.canonicalURL);
+ // If the web navigation has already been injected, the active state of the "tabs" will be incorrect
+ // since non-"landing pages" never have display active landing page links. We need to update the
+ // navigation shelf, if it exists, based on the `landingPageIntent`
+ updateWebNavigation(objectGraph, viewModel, unwrap(pageIntent.platform), landingPageIntent);
+ }
+ return viewModel;
+ },
+ buildIntent(locale) {
+ return {
+ ...locale,
+ $kind: intentKind,
+ };
+ },
+ buildAction(locale, objectGraph) {
+ const intent = this.buildIntent(locale);
+ return this.actionFor(intent, objectGraph, {});
+ },
+ actionFor(landingPageIntent, objectGraph) {
+ const action = new FlowAction("page");
+ action.destination = landingPageIntent;
+ // @ts-expect-error TypeScript can't know that `landingPageIntent` satisfies the requirements of
+ // `makeCanonicalUrl`, but this will be safe at runtime because all we actually require
+ // from the intent is the locale information
+ action.pageUrl = makeCanonicalUrl(objectGraph, landingPageIntent);
+ prepareAction === null || prepareAction === void 0 ? void 0 : prepareAction(objectGraph, action);
+ return action;
+ },
+ };
+}
+/**
+ * Dynamically create an {@linkcode IntentController} that redirects from the platform root
+ * to the default landing page
+ *
+ * @param url the URL for the platform to redirect for
+ * @param intentFactory a function that produces the `Intent` for the `LandingPageController` that should be delegated to
+ */
+export function definePlatformRootRedirectController(url, intentFactory) {
+ const intentKind = `PlatformRootRedirect_${url.substring(1)}_Intent`;
+ const { routes } = generateRoutes((locale) => ({
+ ...locale,
+ $kind: intentKind,
+ }), url);
+ return {
+ $intentKind: intentKind,
+ routes,
+ async perform(landingPageIntent, objectGraph) {
+ const pageIntent = intentFactory({
+ storefront: landingPageIntent.storefront,
+ language: landingPageIntent.language,
+ });
+ return await objectGraph.dispatcher.dispatch(pageIntent, objectGraph);
+ },
+ };
+}
+/**
+ * Dynamically create an {@linkcode IntentController} that redirects from the root
+ * to the default landing page
+ *
+ * @param intentFactory a function that produces the `Intent` for the `LandingPageController` that should be delegated to
+ */
+export function defineRootRedirectController(intentFactory) {
+ const intentKind = `RootRedirect_Intent`;
+ const { routes } = generateRoutes((locale) => ({
+ ...locale,
+ $kind: intentKind,
+ }), "/");
+ return {
+ $intentKind: intentKind,
+ routes,
+ async perform(landingPageIntent, objectGraph) {
+ const pageIntent = intentFactory({
+ storefront: landingPageIntent.storefront,
+ language: landingPageIntent.language,
+ });
+ return await objectGraph.dispatcher.dispatch(pageIntent, objectGraph);
+ },
+ };
+}
+//# sourceMappingURL=platform-landing-page-utils.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-selection.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-selection.js
new file mode 100644
index 0000000..b583859
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/platform-selection.js
@@ -0,0 +1,115 @@
+import { allPreviewPlatforms } from "../../api/models/preview-platform";
+import { iPadTodayPageController, WatchDiscoverController, VisionAppsAndGamesController, MacDiscoverController, iPhoneTodayPageController, TVDiscoverController, } from "./platform-landing-page-intent-controllers";
+import { unreachable } from "../../foundation/util/errors";
+import { getLocale } from "../locale";
+import { createArtworkForSystemImage } from "../content/artwork/artwork";
+import * as metricsHelpersClicks from "../metrics/helpers/clicks";
+import { newLocationTracker } from "../metrics/helpers/location";
+function makeiPhonePlatformSelector(objectGraph, isActive) {
+ const action = iPhoneTodayPageController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.Phone");
+ action.artwork = createArtworkForSystemImage(objectGraph, "iphone.gen2");
+ return {
+ action,
+ isActive,
+ };
+}
+function makeiPadPlatformSelector(objectGraph, isActive) {
+ const action = iPadTodayPageController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.Pad");
+ action.artwork = createArtworkForSystemImage(objectGraph, "ipad.gen2.landscape");
+ return {
+ action,
+ isActive,
+ };
+}
+function makeMacPlatformSelector(objectGraph, isActive) {
+ const action = MacDiscoverController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.Mac");
+ action.artwork = createArtworkForSystemImage(objectGraph, "macbook.gen2");
+ return {
+ action,
+ isActive,
+ };
+}
+function makeVisionPlatformSelector(objectGraph, isActive) {
+ const action = VisionAppsAndGamesController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.Vision");
+ action.artwork = createArtworkForSystemImage(objectGraph, "visionpro");
+ return {
+ action,
+ isActive,
+ };
+}
+function makeWatchPlatformSelector(objectGraph, isActive) {
+ const action = WatchDiscoverController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.Watch");
+ action.artwork = createArtworkForSystemImage(objectGraph, "applewatch");
+ return {
+ action,
+ isActive,
+ };
+}
+function makeTVPlatformSelector(objectGraph, isActive) {
+ const action = TVDiscoverController.buildAction(getLocale(objectGraph), objectGraph);
+ action.title = objectGraph.loc.string("Web.Navigation.Platform.TV");
+ action.artwork = createArtworkForSystemImage(objectGraph, "tv");
+ return {
+ action,
+ isActive,
+ };
+}
+function makePlatformSelector(objectGraph, platform, activePlatform) {
+ let selector;
+ switch (platform) {
+ case "iphone": {
+ selector = makeiPhonePlatformSelector(objectGraph, activePlatform === "iphone");
+ break;
+ }
+ case "ipad": {
+ selector = makeiPadPlatformSelector(objectGraph, activePlatform === "ipad");
+ break;
+ }
+ case "mac": {
+ selector = makeMacPlatformSelector(objectGraph, activePlatform === "mac");
+ break;
+ }
+ case "vision": {
+ selector = makeVisionPlatformSelector(objectGraph, activePlatform === "vision");
+ break;
+ }
+ case "watch": {
+ selector = makeWatchPlatformSelector(objectGraph, activePlatform === "watch");
+ break;
+ }
+ case "tv": {
+ selector = makeTVPlatformSelector(objectGraph, activePlatform === "tv");
+ break;
+ }
+ default:
+ unreachable(platform);
+ }
+ if (objectGraph.client.isWeb) {
+ metricsHelpersClicks.addClickEventToAction(objectGraph, selector.action, {
+ id: platform,
+ actionType: "navigate",
+ locationTracker: newLocationTracker(),
+ pageInformation: undefined,
+ }, false, "link");
+ }
+ return selector;
+}
+/**
+ *
+ * @param objectGraph
+ * @param activePlatform the active platform; navigation links to it will be presented with an "active" style
+ * @returns
+ */
+export function createPlatformSelectors(objectGraph, activePlatform) {
+ const isVisionSupported = objectGraph.bag.enableVisionPlatform;
+ return (allPreviewPlatforms
+ // Rejects vision if its not supported and let's all other platforms pass
+ .filter((platform) => isVisionSupported || platform !== "vision")
+ .map((platform) => makePlatformSelector(objectGraph, platform, activePlatform)));
+}
+//# sourceMappingURL=platform-selection.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/search-results-platform-selection.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/search-results-platform-selection.js
new file mode 100644
index 0000000..00993f8
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/search-results-platform-selection.js
@@ -0,0 +1,28 @@
+import { allPreviewPlatforms } from "../../api/models/preview-platform";
+import { makeCanonicalSearchResultsPageUrl } from "../search/search-page-url";
+function replaceDestinationIntent(objectGraph, action, intent, platform) {
+ const updatedIntent = {
+ ...intent,
+ platform,
+ };
+ action.destination = updatedIntent;
+ action.pageUrl = makeCanonicalSearchResultsPageUrl(objectGraph, updatedIntent);
+}
+/**
+ * Replaces each of the "platform selector" actions with one that navigates to the
+ * {@linkcode searchResultsPageIntent} in each platform
+ *
+ * This is necessary because the existing platform selector, which normally takes
+ * the user to a platform landing page, instead takes the user to the search results
+ * page within the selected platform
+ */
+export function replacePlatformSelectorDestinationWithSearchResults(objectGraph, webNavigation, searchResultsPageIntent) {
+ const isVisionSupported = objectGraph.bag.enableVisionPlatform;
+ allPreviewPlatforms
+ // Rejects vision if its not supported and let's all other platforms pass
+ .filter((platform) => isVisionSupported || platform !== "vision")
+ .forEach((platform, index) => {
+ replaceDestinationIntent(objectGraph, webNavigation.platforms[index].action, searchResultsPageIntent, platform);
+ });
+}
+//# sourceMappingURL=search-results-platform-selection.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/web-navigation.js b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/web-navigation.js
new file mode 100644
index 0000000..13b7f6d
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/web-navigation/web-navigation.js
@@ -0,0 +1,28 @@
+import { createPlatformSelectors } from "./platform-selection";
+import { createLandingPageLinks } from "./landing-page-links-by-platform";
+import { makeWebSearchAction } from "../search/web-search-action";
+/**
+ * Create a {@linkcode WebNavigation} based on the active {@linkcode Intent}
+ */
+export function createWebNavigation(objectGraph, platform) {
+ const webNavigation = {
+ platforms: [],
+ tabs: [],
+ searchAction: makeWebSearchAction(objectGraph, platform),
+ };
+ setActivePlatform(objectGraph, webNavigation, platform);
+ return webNavigation;
+}
+/**
+ * Updates a {@linkcode WebNavigation} to reflect:
+ *
+ * 1. the platform specified by {@linkcode platform}
+ * 2. the "active landing page" specified by {@linkcode intent}
+ */
+export function setActivePlatform(objectGraph, shelf, platform, intent) {
+ shelf.platforms = createPlatformSelectors(objectGraph, platform);
+ const searchActionDestination = shelf.searchAction.destination;
+ shelf.tabs = createLandingPageLinks(objectGraph, platform, intent);
+ searchActionDestination.platform = platform;
+}
+//# sourceMappingURL=web-navigation.js.map \ No newline at end of file