import { isSome, isNothing } from "@jet/environment/types/optional"; import { FlowAction, GenericPage, Shelf } from "../../api/models"; import { attributeAsNumber, attributeAsString } from "../../foundation/media/attributes"; import { dataFromDataContainer } from "../../foundation/media/data-structure"; import { asNumber, isDefinedNonNull, isDefinedNonNullNonEmpty, isNull, } from "../../foundation/json-parsing/server-data"; import { hasRelationship, relationship } from "../../foundation/media/relationships"; import { URL } from "../../foundation/network/urls"; import { appStoreIdentifier } from "../../foundation/wrappers/client"; import { createArtworkForResource } from "../content/artwork/artwork"; import { addMetricsEventsToPageWithInformation, metricsPageInformationFromMediaApiResponse, } from "../metrics/helpers/page"; import { newPageRefreshControllerFromResponse, pageRefreshPolicyForController, } from "../refresh/page-refresh-controller"; import { metricsData } from "../personalization/on-device-personalization"; import { impressionEventsFromData } from "../personalization/on-device-impression-demotion"; import { combinedRecoMetricsDataFromMetricsData } from "../metrics/helpers/util"; import { newLocationTracker } from "../metrics/helpers/location"; import { flattenMediaApiGroupingData, insertInitialShelvesIntoGroupingParseContext, shelfForFooterButtons, shelfForTermsAndConditions, shelfForUnifiedMessage, } from "./grouping-common"; import { addBatchGroupsToPage } from "./shelf-batching"; import { nameFromGroupingData } from "../lockups/lockups"; // The key that contains the impression data for the grouping page fetched as an additional request. export const GroupingImpressionAdditionalDataKey = "amdImpressionData"; export function groupingParseContextFromDataContainer(objectGraph, data, additionalPageRequirements) { const mediaApiGroupingData = dataFromDataContainer(objectGraph, data); if (isNothing(mediaApiGroupingData)) { return null; } const metricsPageInformation = metricsPageInformationFromMediaApiResponse(objectGraph, "Genre", mediaApiGroupingData.id, data); const onDevicePersonalizationMetricsData = metricsData(objectGraph); metricsPageInformation.recoMetricsData = combinedRecoMetricsDataFromMetricsData(metricsPageInformation.recoMetricsData, null, onDevicePersonalizationMetricsData); return { shelves: [], metricsPageInformation: metricsPageInformation, metricsLocationTracker: newLocationTracker(), pageGenreAdamId: attributeAsString(mediaApiGroupingData, "id"), pageGenreId: null, hasAuthenticatedUser: isDefinedNonNull(objectGraph.user.dsid), refreshController: newPageRefreshControllerFromResponse(data), recoImpressionData: impressionEventsFromData(objectGraph, additionalPageRequirements === null || additionalPageRequirements === void 0 ? void 0 : additionalPageRequirements[GroupingImpressionAdditionalDataKey]), }; } export function flattenedGroupingFromDataContainer(objectGraph, data) { const mediaApiGroupingData = dataFromDataContainer(objectGraph, data); if (!mediaApiGroupingData) { return null; } if (!hasRelationship(mediaApiGroupingData, "tabs")) { return null; } return flattenMediaApiGroupingData(objectGraph, mediaApiGroupingData); } // TODO: Once 18E is in we need to get the genreId from the chart URL export function genreIdFromChartURL(chartURLString) { if (isNull(chartURLString)) { return null; } const chartURL = URL.from(chartURLString); return asNumber(chartURL.query, "genre"); } function groupingPageTitleForData(objectGraph, groupingData, genreId) { var _a; let pageTitle = null; switch (genreId) { case 36 /* GenreIds.Apps */: if (objectGraph.host.clientIdentifier === appStoreIdentifier && !objectGraph.client.isWatch) { if (objectGraph.client.isMac) { pageTitle = macDiscoverPageTitleForData(objectGraph, groupingData); } else { pageTitle = objectGraph.loc.string("GROUPING_APPS"); } } else { if (objectGraph.client.isTV) { pageTitle = objectGraph.loc.string("GROUPING_APPS"); } else if (objectGraph.client.isWeb) { pageTitle = ((_a = objectGraph.activeIntent) === null || _a === void 0 ? void 0 : _a.previewPlatform) === "mac" ? macDiscoverPageTitleForData(objectGraph, groupingData) : objectGraph.loc.string("GROUPING_APPS"); } else { pageTitle = objectGraph.loc.string("GROUPING_APP_STORE", "App Store"); } } break; case 39 /* GenreIds.Discover */: pageTitle = objectGraph.loc.string("GROUPING_DISCOVER"); break; default: pageTitle = nameFromGroupingData(objectGraph, groupingData); break; } return pageTitle; } /** * Create a shelf for header buttons, e.g. "Search". * * @return Shelf configured to display header buttons. */ function shelfForHeaderButtons(objectGraph) { const shelf = new Shelf("action"); const items = []; const searchFlowAction = new FlowAction("search"); searchFlowAction.title = objectGraph.loc.string("SEARCH", "Search"); searchFlowAction.artwork = createArtworkForResource(objectGraph, "systemimage://magnifyingglass"); items.push(searchFlowAction); shelf.items = items; return shelf; } /** * Returns the page title for the Discover tab on macOS * * @param objectGraph * @param {Data} groupingData MAPI data blob describing the grouping * @return Page title string */ function macDiscoverPageTitleForData(objectGraph, groupingData) { const tabs = relationship(groupingData, "tabs"); if (isDefinedNonNull(tabs) && isDefinedNonNull(tabs.data)) { for (const tabData of tabs.data) { const tabName = attributeAsString(tabData, "name"); const featuredContentId = attributeAsNumber(tabData, "editorialElementKind"); const token = attributeAsString(tabData, "token"); if (isSome(tabName) && tabName.length > 0 && isDefinedNonNull(featuredContentId) && isDefinedNonNullNonEmpty(token) && token === "macOS" && featuredContentId === 414 /* FeaturedContentID.AppStore_TabRoot */) { return tabName; } } } return objectGraph.loc.string("GROUPING_DISCOVER"); } /** * Insert the unified message shelves into the arcade page * * @param objectGraph The App Store dependency graph * @param page The generic page to insert shelves into * @param genreId The genre Id of the generic page, e.g. Apps or Games */ function insertUnifiedMessageShelves(objectGraph, page, genreId) { if (page.shelves.length <= 0) { return; } // Insert Unified message shelves. These are hidden by default and act as 'placeholder' locations // for the marketing teams to target with inline banners or bubble tip messages switch (genreId) { case 36 /* GenreIds.Apps */: page.shelves.splice(0, 0, shelfForUnifiedMessage(objectGraph, "appsPageHeader")); page.shelves.splice(6, 0, shelfForUnifiedMessage(objectGraph, "appsPageMid")); page.shelves.push(shelfForUnifiedMessage(objectGraph, "appsPageFooter")); break; case 6014 /* GenreIds.Games */: page.shelves.splice(0, 0, shelfForUnifiedMessage(objectGraph, "gamesPageHeader")); page.shelves.splice(6, 0, shelfForUnifiedMessage(objectGraph, "gamesPageMid")); page.shelves.push(shelfForUnifiedMessage(objectGraph, "gamesPageFooter")); break; default: break; } } export function groupingPageFromFlattenedGrouping(objectGraph, flattenedGrouping, groupingParseContext) { groupingParseContext.pageGenreId = attributeAsNumber(flattenedGrouping.originalGroupingData, "genre") || genreIdFromChartURL(attributeAsString(flattenedGrouping.originalGroupingData, "chartUrl")); // Construct the shelves insertInitialShelvesIntoGroupingParseContext(objectGraph, flattenedGrouping, groupingParseContext); if (objectGraph.client.isWatch) { // Remove title of first shelf with cards if needed. if (groupingParseContext.shelves.length > 0 && groupingParseContext.shelves[0].contentType === "todayCard") { groupingParseContext.shelves[0].title = undefined; } // Prepend Header Buttons if (objectGraph.client.deviceType !== "watch") { const headerButtonShelf = shelfForHeaderButtons(objectGraph); groupingParseContext.shelves.unshift(headerButtonShelf); } } // TODO: Add for ATV // Append Footer Buttons if (objectGraph.client.deviceType !== "tv" && objectGraph.client.deviceType !== "web") { const footerButtonShelf = shelfForFooterButtons(objectGraph, groupingParseContext.metricsPageInformation, groupingParseContext.metricsLocationTracker); if (footerButtonShelf) { groupingParseContext.shelves.push(footerButtonShelf); } } // TODO: Add for ATV // Append T&C if (objectGraph.client.deviceType !== "watch" && objectGraph.client.deviceType !== "tv") { const url = objectGraph.bag.termsAndConditionsURL; if (!isNull(url)) { const termsAndConditionsShelf = shelfForTermsAndConditions(objectGraph, url); groupingParseContext.shelves.push(termsAndConditionsShelf); } } // Determine the title const pageTitle = groupingPageTitleForData(objectGraph, flattenedGrouping.originalGroupingData, groupingParseContext.pageGenreId); // Build the page const page = new GenericPage(groupingParseContext.shelves); switch (objectGraph.client.deviceType) { case "tv": page.title = pageTitle; break; case "watch": page.title = pageTitle; page.presentationOptions = ["prefersLargeTitleWhenRoot"]; break; case "web": page.title = pageTitle; page.presentationOptions = ["prefersLargeTitleWhenRoot"]; const firstShelfType = page.shelves[0].contentType; if (["heroCarousel", "editorialCard", "largeStoryCard"].includes(firstShelfType)) { page.presentationOptions.push("prefersOverlayedPageHeader"); } break; default: page.title = pageTitle; if ((groupingParseContext.pageGenreId === 39 /* GenreIds.Discover */ || (groupingParseContext.pageGenreId === 36 /* GenreIds.Apps */ && objectGraph.client.isMac)) && !objectGraph.client.isIconArtworkCapable) { page.presentationOptions = ["prefersRevealNavigationBarOnMouseOver"]; } else { page.presentationOptions = ["prefersLargeTitleWhenRoot"]; } break; } if (objectGraph.client.isiOS) { if (groupingParseContext.shelves[0].contentType === "mediaPageHeader") { page.presentationOptions.push("prefersNonStandardBackButton"); page.presentationOptions.push("prefersHiddenPageTitle"); page.presentationOptions.push("prefersOverlayedPageHeader"); } } page.pageRefreshPolicy = pageRefreshPolicyForController(objectGraph, groupingParseContext === null || groupingParseContext === void 0 ? void 0 : groupingParseContext.refreshController); addMetricsEventsToPageWithInformation(objectGraph, page, groupingParseContext.metricsPageInformation); // Add unified message shelves if (objectGraph.client.isiOS) { insertUnifiedMessageShelves(objectGraph, page, groupingParseContext.pageGenreId); } addBatchGroupsToPage(page); return page; } //# sourceMappingURL=render-grouping-page.js.map