import { isSome } from "@jet/environment"; import * as validation from "@jet/environment/json/validation"; import { MediumAdLockupWithScreenshotsBackground, CondensedAdLockupWithIconBackground, TodayCardMediaSingleLockup, TodayCardMediaMediumLockupWithScreenshots, TodayCardMediaMediumLockupWithAlignedRegion, MediumAdLockupWithAlignedRegionBackground, } from "../../../api/models"; import { asString, isDefinedNonNull, isNull } from "../../../foundation/json-parsing/server-data"; import { isColorEqualToColor } from "../../../foundation/util/color-util"; import { todayAdStyle } from "../../ads/ad-common"; import { recordLockupFromDataFailed } from "../../ads/ad-incident-recorder"; import { iconFromData } from "../../content/content"; import { getTemplateTypeForMediumAdFromLockupWithCustomCreative, getTemplateTypeForMediumAdFromLockupWithScreenshots, isCppDeeplinkEnabledForAdvert, performAdOverridesForCard, } from "../../lockups/ad-lockups"; import * as lockups from "../../lockups/lockups"; import * as metricsHelpersImpressions from "../../metrics/helpers/impressions"; import { productVariantDataForData } from "../../product-page/product-page-variants"; import { popTodayCardLocation, pushTodayCardLocation } from "../today-card-util"; import { createTodayBaseCard } from "./today-base-card-builder"; import { getSelectedCustomCreativeId } from "../../search/custom-creative"; /** * Create TodayCard displaying an ad fetched from Ad platforms * * @param objectGraph The dependency graph for the App Store * @param adData The media api data to build the ad card from * @param adIncidentRecorder The incident recorder for the ad, for when an issues arises * @param cardConfig The configuration for the card * @param context The parse context for the over all today page * @returns The newly created TodayCard, using the full bleed image media. */ export function createTodayAdCard(objectGraph, adData, adIncidentRecorder, cardConfig, context) { return validation.context("createTodayAdCard", () => { var _a, _b, _c, _d; if (isNull(adData)) { return null; // No task for the position } const adCard = createTodayBaseCard(objectGraph, adData, cardConfig, context); pushTodayCardLocation(objectGraph, adData, cardConfig, context, asString(adData.attributes.name)); const metricsOptions = metricsHelpersImpressions.impressionOptions(objectGraph, adData, asString(adData.attributes.name), { targetType: "todayCard", pageInformation: context.pageInformation, locationTracker: context.locationTracker, isAdvert: true, rowIndex: cardConfig.currentRowIndex, displayStyle: cardConfig.metricsDisplayStyle, }); const productVariantData = productVariantDataForData(objectGraph, adData); metricsOptions.productVariantData = productVariantData; metricsOptions.adSlotOverride = context.parsedCardCount; metricsOptions.kind = "adItem"; const clickOptions = metricsOptions; // Set up iAdInfo metricsOptions.pageInformation.iAdInfo.apply(objectGraph, adData); // Configure the action let clientIdentifierOverride; if (isDefinedNonNull(cardConfig)) { clientIdentifierOverride = cardConfig.clientIdentifierOverride; } const customCreativeId = getSelectedCustomCreativeId(adData); const isCustomCreative = isSome(customCreativeId); adCard.style = "dark"; switch (todayAdStyle(objectGraph)) { case "singleLockup": // Hardcode the condensed ad template type. This is not dependent on media count. (_a = metricsOptions.pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.setTemplateType("APPLOCKUP"); break; case "mediumLockup": if (isCustomCreative) { (_b = metricsOptions.pageInformation.iAdInfo) === null || _b === void 0 ? void 0 : _b.setTemplateType(getTemplateTypeForMediumAdFromLockupWithCustomCreative()); } break; default: break; } let lockup = createAdCardLockup(objectGraph, adData, cardConfig, context); if (isNull(lockup)) { recordLockupFromDataFailed(objectGraph, adIncidentRecorder, adData); popTodayCardLocation(context); // Configure impressions metricsHelpersImpressions.addImpressionsFieldsToTodayCard(objectGraph, adCard, metricsOptions, null, null, false, false); return null; } if (objectGraph.props.enabled("advertSlotReporting")) { (_c = lockup.searchAdOpportunity) === null || _c === void 0 ? void 0 : _c.setTemplateType("APPLOCKUP"); } else { (_d = lockup.searchAd) === null || _d === void 0 ? void 0 : _d.setTemplateType("APPLOCKUP"); } switch (todayAdStyle(objectGraph)) { case "singleLockup": const condensedAdLockupWithIconBackground = new CondensedAdLockupWithIconBackground(lockup, lockup.icon); adCard.media = new TodayCardMediaSingleLockup(condensedAdLockupWithIconBackground); adCard.media.impressionMetrics = lockup.impressionMetrics; break; case "mediumLockup": if (preprocessor.CARRY_BUILD || preprocessor.DEBUG_BUILD) { if (isCustomCreative && objectGraph.featureFlags.isEnabled("aligned_region_artwork_2025A")) { adCard.media = createMediumLockupWithAlignedRegion(objectGraph, lockup, adData, metricsOptions.pageInformation); // After the media is created, we need to recreate the lockup to ensure all instrumentation // has the updated template type, which is derived from the final set of media in // `createMediumLockupWithAlignedRegion`. lockup = createAdCardLockup(objectGraph, adData, cardConfig, context); // Preserve SearchAd metadata lockup.searchAdOpportunity = adCard.media.mediumAdLockupWithAlignedRegionBackground.lockup.searchAdOpportunity; lockup.searchAd = adCard.media.mediumAdLockupWithAlignedRegionBackground.lockup.searchAd; // The new lockup with the correct metrics should be set on the media. adCard.media.mediumAdLockupWithAlignedRegionBackground.lockup = lockup; adCard.media.impressionMetrics = lockup.impressionMetrics; break; } else { adCard.media = createMediumScreenshotsCardMedia(adCard, objectGraph, lockup, adData, cardConfig, context, metricsOptions); } } else { adCard.media = createMediumScreenshotsCardMedia(adCard, objectGraph, lockup, adData, cardConfig, context, metricsOptions); } break; default: return null; } popTodayCardLocation(context); // CPP deeplinks used for ads have a requirement to not be used when targeting criteria is too narrow. const isCppDeeplinkingEnabled = isCppDeeplinkEnabledForAdvert(adData); // It's important the click action is created after the template type is set, to ensure it's in the metrics. adCard.clickAction = lockups.actionFromData(objectGraph, adData, clickOptions, clientIdentifierOverride, undefined, isCppDeeplinkingEnabled); performAdOverridesForCard(objectGraph, adData, adCard, metricsOptions); // Configure impressions metricsHelpersImpressions.addImpressionsFieldsToTodayCard(objectGraph, adCard, metricsOptions, null, null, false, false); return adCard; }); } function createMediumScreenshotsCardMedia(adCard, objectGraph, lockup, adData, cardConfig, context, metricsOptions) { adCard.media = createMediumLockupWithScreenshots(objectGraph, lockup, objectGraph.bag.todayAdMediumLockupScreenshotAnimationEnabled, metricsOptions.pageInformation, adData); // After the media is created, we need to recreate the lockup to ensure all instrumentation // has the updated template type, which is derived from the final set of media in // `createMediumLockupWithScreenshots`. lockup = createAdCardLockup(objectGraph, adData, cardConfig, context); if (isNull(lockup)) { return null; } // Preserve SearchAd metadata lockup.searchAdOpportunity = adCard.media.mediumAdLockupWithScreenshotsBackground.lockup.searchAdOpportunity; lockup.searchAd = adCard.media.mediumAdLockupWithScreenshotsBackground.lockup.searchAd; // The new lockup with the correct metrics should be set on the media. adCard.media.mediumAdLockupWithScreenshotsBackground.lockup = lockup; adCard.media.impressionMetrics = lockup.impressionMetrics; return adCard.media; } function createAdCardLockup(objectGraph, data, cardConfig, context) { const offerEnvironment = "ad"; const offerStyle = "transparent"; return lockups.mixedMediaAdLockupFromData(objectGraph, data, { offerEnvironment: offerEnvironment, offerStyle: offerStyle, metricsOptions: { pageInformation: context.pageInformation, locationTracker: context.locationTracker, isAdvert: true, adSlotOverride: context.parsedCardCount, disableFastImpressionsForAds: true, }, clientIdentifierOverride: cardConfig.clientIdentifierOverride, crossLinkSubtitle: cardConfig.crossLinkSubtitle, artworkUseCase: 1 /* ArtworkUseCase.LockupIconSmall */, canDisplayArcadeOfferButton: cardConfig.canDisplayArcadeOfferButton, }, { allowsAutoPlay: true, looping: true, canPlayFullScreen: false, playbackControls: {}, }, null, false); } function createMediumLockupWithAlignedRegion(objectGraph, lockup, adData, pageInformation) { var _a, _b, _c; const alignedRegionArtwork = lockup.alignedRegionArtwork; const templateString = getTemplateTypeForMediumAdFromLockupWithCustomCreative(); (_a = pageInformation === null || pageInformation === void 0 ? void 0 : pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.setTemplateType(templateString); if (objectGraph.props.enabled("advertSlotReporting")) { (_b = lockup.searchAdOpportunity) === null || _b === void 0 ? void 0 : _b.setTemplateType(templateString); } else { (_c = lockup.searchAd) === null || _c === void 0 ? void 0 : _c.setTemplateType(templateString); } const mediumContainer = new MediumAdLockupWithAlignedRegionBackground(lockup, alignedRegionArtwork); return new TodayCardMediaMediumLockupWithAlignedRegion(mediumContainer); } /** * Creates the media for a medium Today ad, with the appropriate media. * Also applies information about the created media template to a provided MetricsPageInformation. * @param objectGraph The object graph. * @param lockup The lockup for the app. * @param isAnimated Whether the card background should be animated. * @param pageInformation A MetricsPageInformation to apply the created template metrics information to. * @param adData The data for the ad. * @returns A `TodayCardMediumLockupWithScreenshots` with the correct media to be displayed. */ function createMediumLockupWithScreenshots(objectGraph, lockup, isAnimated, pageInformation, adData) { var _a, _b, _c; // Grab the first of the platform screenshots and trailers - the ones the ad will display. const platformScreenshots = lockup.screenshots[0]; const templateString = getTemplateTypeForMediumAdFromLockupWithScreenshots(platformScreenshots); (_a = pageInformation.iAdInfo) === null || _a === void 0 ? void 0 : _a.setTemplateType(templateString); if (objectGraph.props.enabled("advertSlotReporting")) { (_b = lockup.searchAdOpportunity) === null || _b === void 0 ? void 0 : _b.setTemplateType(templateString); } else { (_c = lockup.searchAd) === null || _c === void 0 ? void 0 : _c.setTemplateType(templateString); } const iconData = iconFromData(objectGraph, adData, { useCase: 0 /* ArtworkUseCase.Default */, withJoeColorPlaceholder: true, overrideTextColorKey: "textColor2", }); let backgroundColor = iconData.backgroundColor; let secondaryTextColor = iconData.textColor; const rgbWhite = { type: "rgb", red: 1, green: 1, blue: 1, }; // If `backgroundColor` is white, use `secondaryTextColor` as the "primary" color. // Otherwise, if `secondaryTextColor` is white, remove it and use only `backgroundColor`. // Native code has a fallback state where only `backgroundColor` is provided, so if // either color is white, we prefer the single non-white color. if (isColorEqualToColor(rgbWhite, backgroundColor)) { backgroundColor = secondaryTextColor; secondaryTextColor = undefined; } else if (isColorEqualToColor(rgbWhite, secondaryTextColor)) { secondaryTextColor = undefined; } const mediumContainer = new MediumAdLockupWithScreenshotsBackground(lockup, [platformScreenshots], isAnimated, secondaryTextColor, backgroundColor, 8); return new TodayCardMediaMediumLockupWithScreenshots(mediumContainer); } //# sourceMappingURL=today-ad-card-builder.js.map