import * as models from "../../../api/models"; import * as serverData from "../../../foundation/json-parsing/server-data"; import * as mediaAttributes from "../../../foundation/media/attributes"; import * as mediaDataStructure from "../../../foundation/media/data-structure"; import * as mediaRelationship from "../../../foundation/media/relationships"; import * as breakoutsCommon from "../../arcade/breakouts-common"; import * as contentAttributes from "../../content/attributes"; import * as content from "../../content/content"; import * as flowPreview from "../../content/flow-preview"; import * as metricsHelpersClicks from "../../metrics/helpers/clicks"; import * as metricsHelpersImpressions from "../../metrics/helpers/impressions"; import * as metricsHelpersLocation from "../../metrics/helpers/location"; import * as article from "../../today/article"; import * as heroCommon from "../hero/hero-common"; import { GroupingShelfController } from "./grouping-shelf-controller"; import * as groupingShelfControllerCommon from "./grouping-shelf-controller-common"; export class GroupingLargeBreakoutShelfController extends GroupingShelfController { // region Constructors constructor(builderClass = null) { super(builderClass || "GroupingLargeBreakoutShelfController"); this.supportedFeaturedContentIds = new Set([480 /* groupingTypes.FeaturedContentID.AppStore_Breakout */]); } // endregion // region GroupingShelfController _supports(objectGraph, mediaApiData, featuredContentId, nativeGroupingShelfId) { if (!super._supports(objectGraph, mediaApiData, featuredContentId, nativeGroupingShelfId)) { return false; } const breakoutStyle = mediaAttributes.attributeAsString(mediaApiData, "displayStyle"); return breakoutStyle === "large"; } // endregion // region Shelf Creation Prerequisites /** * For a given mediaApiData extract the actual shelfContents array needed to render this shelf * * @param mediaApiData The outer shelfContents object containing the shelf contents */ initialShelfDataFromGroupingMediaApiData(objectGraph, mediaApiData) { return { shelfContents: mediaRelationship.relationshipCollection(mediaApiData, "contents") }; } /** * For a given url that this controller handles, we should return a promise that will result in the `ShelfData` * needed to render this shelf * * @param objectGraph The App Store dependency graph * @param shelfUrl The url that this controller handled on a secondary fetch * @param parameters The extracted parameters from the shelf url */ async secondaryShelfDataForShelfUrl(objectGraph, shelfUrl, shelfToken, parameters) { return await GroupingShelfController.secondaryGroupingShelfDataForShelfUrl(objectGraph, shelfUrl, shelfToken, parameters); } /** * For a given mediaApiData create an updated shelf token that contains all the additional data for this specific shelf type * * @param objectGraph The App Store dependency graph * @param baseShelfToken The base grouping shelf token created by the grouping-controller * @param mediaApiData The outer data object containing the FC properties and data * @param groupingParseContext The parse context for the grouping page so far */ shelfTokenFromBaseTokenAndMediaApiData(objectGraph, mediaApiData, baseShelfToken, groupingParseContext) { return baseShelfToken; } // endregion // region Metrics shouldImpressShelf() { return false; } // endregion // region Shelf Creation isInHeroPosition() { return false; } /** * * @param objectGraph The App Store dependency graph * @param shelfToken The shelf shelfToken for this current shelf creation request * @param shelfData The media api shelfContents array for this shelf * @param groupingParseContext The parse context used to generate the grouping page on the initial page load, * this will be missing when this controller renders a secondary or incomplete shelf fetch. */ _createShelf(objectGraph, shelfToken, shelfData, groupingParseContext) { const isFirstShelf = serverData.isDefinedNonNullNonEmpty(groupingParseContext) && serverData.isNullOrEmpty(groupingParseContext.pageTitleEffect) && groupingParseContext.shelves.length === 0; const trimmedShelfContents = serverData.isDefinedNonNullNonEmpty(shelfData.shelfContents) ? [shelfData.shelfContents[0]] : []; const items = []; for (const data of trimmedShelfContents) { if (serverData.isNull(data.attributes) || groupingShelfControllerCommon.shouldDefer(shelfToken)) { shelfToken.isDeferring = true; shelfToken.remainingItems.push(data); continue; } const metricsOptions = { targetType: this.isInHeroPosition() ? "heroBreakout" : "largeBreakout", pageInformation: shelfToken.metricsPageInformation, locationTracker: shelfToken.metricsLocationTracker, recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data), }; const heroVideoData = heroCommon.heroVideoFromData(objectGraph, data); const heroArtworkData = heroCommon.heroArtworkFromData(objectGraph, data); const titleEffectArtwork = heroVideoData.artworkData || heroArtworkData.artworkData; const largeHeroBreakout = GroupingLargeBreakoutShelfController.createLargeBreakout(objectGraph, data, shelfToken, this.isInHeroPosition(), isFirstShelf, metricsOptions); if (serverData.isNullOrEmpty(largeHeroBreakout)) { continue; } items.push(largeHeroBreakout); if (isFirstShelf) { groupingParseContext.pageTitleEffect = breakoutsCommon.titleEffectFromArtwork(objectGraph, titleEffectArtwork); } } const shelf = new models.Shelf("largeHeroBreakout"); shelf.isHorizontal = false; shelf.items = items; shelf.url = groupingShelfControllerCommon.createShelfTokenUrlIfNecessaryForShelf(objectGraph, shelf, shelfToken); if (groupingParseContext.shelves.length === 0) { shelf.presentationHints = { isFirstShelf: true }; } return shelf; } static createLargeBreakout(objectGraph, data, shelfToken, isHeroPosition, isFirstShelf, metricsOptions) { const primaryContent = content.primaryContentForData(objectGraph, data); if (breakoutsCommon.requiresPrimaryContent(objectGraph, data) && !mediaAttributes.hasAttributes(primaryContent)) { shelfToken.isDeferring = true; shelfToken.remainingItems.push(data); shelfToken.relationshipToFetch = "primary-content"; return null; } const heroVideoData = heroCommon.heroVideoFromData(objectGraph, data); const heroArtworkData = heroCommon.heroArtworkFromData(objectGraph, data); if (serverData.isNullOrEmpty(heroVideoData.video) && serverData.isNullOrEmpty(heroArtworkData.artwork)) { return null; } const backgroundColor = heroVideoData.backgroundColor || heroArtworkData.backgroundColor; const heading = isHeroPosition ? null : mediaAttributes.attributeAsString(data, "breakoutBadge"); // If this EI can and should show the expected release date of an app, override the badge. let badgeTitle; const fallbackLabel = mediaAttributes.attributeAsString(data, "label"); if (contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, data, "showExpectedReleaseDate")) { badgeTitle = objectGraph.loc.uppercased(content.dynamicPreorderDateFromData(objectGraph, primaryContent, fallbackLabel)); } else { badgeTitle = fallbackLabel; } let badge = { type: "none" }; if ((badgeTitle === null || badgeTitle === void 0 ? void 0 : badgeTitle.length) > 0) { badge = { type: "text", title: badgeTitle, }; } const title = content.editorialNotesFromData(objectGraph, data, "name") || contentAttributes.contentAttributeAsString(objectGraph, primaryContent, "name"); const description = content.editorialNotesFromData(objectGraph, data, "short") || contentAttributes.contentAttributeAsString(objectGraph, primaryContent, "tagline"); const backgroundStyle = breakoutsCommon.detailBackgroundStyleFromData(objectGraph, data, true, isFirstShelf, false); const detailPosition = breakoutsCommon.detailPositionFromData(objectGraph, data, isFirstShelf, false); const details = new models.BreakoutDetails(title, description, badge, null, backgroundStyle, breakoutsCommon.detailTextAlignmentForDetailPosition(objectGraph, detailPosition, data)); const largeHeroBreakout = new models.LargeHeroBreakout(details, { position: detailPosition || "leading", }, heading, heroArtworkData.artwork, heroVideoData.video, null, backgroundColor); const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, largeHeroBreakout.details.title, metricsOptions); const productData = article.productDataFromArticle(objectGraph, data); const isPreorder = contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, productData, "isPreorder"); impressionOptions.isPreorder = isPreorder; metricsHelpersImpressions.addImpressionFields(objectGraph, largeHeroBreakout, impressionOptions); // Push the breakout here so that the click action has the breakout in its location // but we do not want to add it to the overall location tracker, so pop it right after adding it to the button // action // Metrics: Arcade: Container values requested in Location field metricsHelpersLocation.pushContentLocation(objectGraph, impressionOptions, largeHeroBreakout.details.title); const breakoutAction = breakoutsCommon.actionFromData(objectGraph, data); const breakoutClickOptions = { pageInformation: shelfToken.metricsPageInformation, locationTracker: shelfToken.metricsLocationTracker, recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data), targetType: "button", id: data.id, }; metricsHelpersClicks.addClickEventToAction(objectGraph, breakoutAction, breakoutClickOptions); largeHeroBreakout.details.callToActionButtonAction = breakoutAction; largeHeroBreakout.clickAction = breakoutAction; metricsHelpersLocation.popLocation(metricsOptions.locationTracker); // Set flow preview actions largeHeroBreakout.flowPreviewActionsConfiguration = flowPreview.flowPreviewActionsConfigurationForProductFromData(objectGraph, data, true, shelfToken.clientIdentifierOverride, breakoutAction, metricsOptions, breakoutClickOptions); return largeHeroBreakout; } } //# sourceMappingURL=grouping-large-breakout-shelf-controller.js.map