diff options
| author | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
|---|---|---|
| committer | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
| commit | bce557cc2dc767628bed6aac87301a1be7c5431b (patch) | |
| tree | b51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet-app/app-store/tmp/src/common/editorial-pages | |
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/editorial-pages')
40 files changed, 3868 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-action-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-action-util.js new file mode 100644 index 0000000..9c50926 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-action-util.js @@ -0,0 +1,58 @@ +import * as lockups from "../lockups/lockups"; +import { CollectionShelfDisplayStyle } from "./editorial-page-types"; +/** + * For a given piece of MAPI data create the primary clickAction for the component with this data + * @param objectGraph + * @param data + * @param shelfToken + */ +export function createPrimaryActionForComponentFromData(objectGraph, data, shelfToken, baseClickOptions) { + const clickOptions = createClickOptionsFromData(objectGraph, data, shelfToken, baseClickOptions); + const primaryAction = lockups.actionFromData(objectGraph, data, clickOptions, shelfToken.clientIdentifierOverride); + return primaryAction; +} +function createClickOptionsFromData(objectGraph, data, shelfToken, baseClickOptions) { + const targetType = clickTargetForCollectionDisplayStyle(objectGraph, shelfToken.collectionDisplayStyle); + const clickOptions = { + ...shelfToken.metricsImpressionOptions, + ...baseClickOptions, + id: data.id, + targetType: targetType, + }; + return clickOptions; +} +export function clickTargetForCollectionDisplayStyle(objectGraph, displayStyle) { + switch (displayStyle) { + case CollectionShelfDisplayStyle.Hero: + return "hero"; + case CollectionShelfDisplayStyle.TextOnly: + return "textOnly"; + case CollectionShelfDisplayStyle.TextWithArtwork: + return "textWithArtwork"; + case CollectionShelfDisplayStyle.BrickSmall: + return "brickSmall"; + case CollectionShelfDisplayStyle.BrickMedium: + return "brickMedium"; + case CollectionShelfDisplayStyle.BrickLarge: + return "brickLarge"; + case CollectionShelfDisplayStyle.EditorialLockupMedium: + case CollectionShelfDisplayStyle.EditorialLockupMediumVariant: + return "editorialLockupMedium"; + case CollectionShelfDisplayStyle.EditorialLockupLarge: + case CollectionShelfDisplayStyle.EditorialLockupLargeVariant: + return "editorialLockupLarge"; + case CollectionShelfDisplayStyle.LockupSmall: + return "lockupSmall"; + case CollectionShelfDisplayStyle.LockupLarge: + return "lockupLarge"; + case CollectionShelfDisplayStyle.StorySmall: + return "storySmall"; + case CollectionShelfDisplayStyle.StoryMedium: + return "storyMedium"; + case CollectionShelfDisplayStyle.BreakoutLarge: + return "largeBreakout"; + default: + return "lockup"; + } +} +//# sourceMappingURL=editorial-action-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-data-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-data-util.js new file mode 100644 index 0000000..041bde4 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-data-util.js @@ -0,0 +1,173 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../foundation/media/attributes"; +import * as mediaRelationship from "../../foundation/media/relationships"; +import * as content from "../content/content"; +import { EditorialShelfType } from "./editorial-page-types"; +/** + * Take the remaining content fromt he shelfToken if this is not the first render, otherwise + * use the initial data. + * + * @param objectGraph + * @param shelfToken + */ +export function extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken) { + if (!shelfToken.isFirstRender) { + return serverData.isDefinedNonNullNonEmpty(shelfToken.remainingItems) ? shelfToken.remainingItems : []; + } + const initialShelfContent = mediaRelationship.relationshipCollection(shelfToken.data, "contents"); + return serverData.isDefinedNonNullNonEmpty(initialShelfContent) ? initialShelfContent : []; +} +/** + * Find the related product data from some MAPI data that was programmed on an editorial page. + * + * @param objectGraph + * @param data + * @returns the product MAPI data from the correct relationship or the data itself if the supplied data is already a product + */ +export function extractProductData(objectGraph, data) { + let productData = null; + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + productData = + mediaRelationship.relationshipData(objectGraph, data, "primary-content") || + mediaRelationship.relationshipData(objectGraph, data, "card-contents") || + mediaRelationship.relationshipData(objectGraph, data, "contents") || + mediaRelationship.relationshipData(objectGraph, data, "app"); + break; + case "apps": + case "in-apps": + case "app-bundles": + productData = data; + break; + default: + break; + } + return productData; +} +/** + * Find the related collection of product data from some MAPI data that was programmed on an editorial page. + * + * @param objectGraph + * @param data + * @returns collection of related content for in the relationship of the supplied MAPI data + */ +export function extractCollectionData(objectGraph, data) { + let collectionData = null; + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + collectionData = + mediaRelationship.relationshipCollection(data, "primary-contents", true) || + mediaRelationship.relationshipCollection(data, "card-contents", true) || + mediaRelationship.relationshipCollection(data, "contents", true); + break; + case "tags": + collectionData = serverData.asArray(data.meta, "associations.apps.data"); + break; + default: + collectionData = null; + } + return collectionData; +} +/** + * Find the related editorial card used for determining override information + * + * @param objectGraph + * @param data + * @returns The editorial-card data object to use for overrides + */ +export function extractEditorialCardData(objectGraph, data) { + if (serverData.isNullOrEmpty(data)) { + return null; + } + const editorialCardsData = serverData.asArrayOrEmpty(data.meta, "associations.editorial-cards.data"); + if (serverData.isNullOrEmpty(editorialCardsData)) { + return null; + } + return editorialCardsData[0]; +} +/** + * Find the related editorial client params from this data object + * + * @param objectGraph + * @param data + * @returns The EditorialClientParams data object to use for this component + */ +export function extractEditorialClientParams(objectGraph, data) { + const baseEditorialClientParams = mediaAttributes.attributeAsDictionary(data, "editorialClientParams", {}); + const editorialCardData = extractEditorialCardData(objectGraph, data); + const cardEditorialClientParams = mediaAttributes.attributeAsDictionary(editorialCardData, "editorialClientParams", {}); + return serverData.asInterface({ + ...baseEditorialClientParams, + ...cardEditorialClientParams, + }); +} +/** + * Use the client params to create the display options for this component + * + * @param clientParams + * @returns The editorialDisplayOptions data object to use for this component + */ +export function editorialDisplayOptionsFromClientParams(clientParams) { + return { + showAppIcon: serverData.asBooleanWithDefault(clientParams.showAppIcon, false), + suppressLockup: serverData.asBooleanWithDefault(clientParams.suppressLockup, false), + useGeneratedBackground: serverData.asBooleanWithDefault(clientParams.useGeneratedBackground, false), + useMaterialBlur: serverData.asBooleanWithDefault(clientParams.useMaterialBlur, true), + useTextProtectionColor: serverData.asBooleanWithDefault(clientParams.useTextProtectionColor, false), + }; +} +/** + * Get the primary content for this MAPI data object, depending on the type it is. If the data + * does not have any attributes this method will return null, since we'll need to fetch it. + * @param objectGraph + * @param data + */ +export function extractHydratedPrimaryContentData(objectGraph, data) { + if (!mediaAttributes.hasAttributes(data)) { + return null; + } + let primaryData; + switch (data.type) { + case "editorial-items": + primaryData = content.primaryContentForData(objectGraph, data); + break; + default: + primaryData = data; + break; + } + if (!mediaAttributes.hasAttributes(primaryData)) { + return null; + } + return primaryData; +} +/** + * Method to check whether we need the primary content relationship for a piece of content + * to be rendered + * + * @param objectGraph + * @param data The MAPI date we're checking for + */ +export function requiresPrimaryContent(objectGraph, data) { + const linkData = mediaAttributes.attributeAsDictionary(data, "link"); + const isLinkAction = serverData.isDefinedNonNullNonEmpty(linkData); + const isStoryAction = mediaAttributes.attributeAsBooleanOrFalse(data, "isCanvasAvailable"); + return !isLinkAction && !isStoryAction; +} +/** + * Extracts the collection shelf display style, for any collection / recommendation shelf + * @param objectGraph Current object graph + * @param shelfData The input shelf data + * @returns The collection shelf display style, if any + */ +export function collectionShelfDisplayStyleFromShelfData(objectGraph, shelfData) { + const shelfType = shelfData.type; + if (shelfType !== EditorialShelfType.Collection && shelfType !== EditorialShelfType.Recommendations) { + return null; + } + return mediaAttributes.attributeAsString(shelfData, "displayStyle"); +} +//# sourceMappingURL=editorial-data-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-media-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-media-util.js new file mode 100644 index 0000000..218f74f --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-media-util.js @@ -0,0 +1,511 @@ +import { isNothing, isSome } from "@jet/environment/types/optional"; +import * as models from "../../api/models"; +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../foundation/media/attributes"; +import * as mediaPlatformAttributes from "../../foundation/media/platform-attributes"; +import * as videoDefaults from "../constants/video-constants"; +import * as contentAttributes from "../content/attributes"; +import * as content from "../content/content"; +import * as editorialDataUtil from "./editorial-data-util"; +import * as color from "../../foundation/util/color-util"; +/** + * The flavors for editorial art that can be used + */ +export var EditorialMediaFlavor; +(function (EditorialMediaFlavor) { + EditorialMediaFlavor["StoryCenteredMotion16x9"] = "storyCenteredMotion16x9"; + EditorialMediaFlavor["StoryCenteredStatic16x9"] = "storyCenteredStatic16x9"; + EditorialMediaFlavor["StoryDetailMotion3x4"] = "storyDetailMotion3x4"; + EditorialMediaFlavor["StoryDetailStatic3x4"] = "storyDetailStatic3x4"; + EditorialMediaFlavor["HeroMotion16x9"] = "heroMotion16x9"; + EditorialMediaFlavor["HeroStatic16x9"] = "heroStatic16x9"; + EditorialMediaFlavor["HeroMotionRTL16x9"] = "heroMotionRTL16x9"; + EditorialMediaFlavor["HeroStaticRTL16x9"] = "heroStaticRTL16x9"; + EditorialMediaFlavor["LargeBreakoutMotion16x9"] = "largeBreakoutMotion16x9"; + EditorialMediaFlavor["LargeBreakoutStatic16x9"] = "largeBreakoutStatic16x9"; + EditorialMediaFlavor["LargeBreakoutRTLMotion16x9"] = "largeBreakoutRTLMotion16x9"; + EditorialMediaFlavor["LargeBreakoutRTLStatic16x9"] = "largeBreakoutRTLStatic16x9"; + EditorialMediaFlavor["StoryCardMotion3x4"] = "storyCardMotion3x4"; + EditorialMediaFlavor["StoryCardStatic3x4"] = "storyCardStatic3x4"; + EditorialMediaFlavor["StorySearchStatic16x9"] = "storySearchStatic16x9"; + EditorialMediaFlavor["SubscriptionHero"] = "subscriptionHero"; + EditorialMediaFlavor["UniversalAMotion16x9"] = "universalAMotion16x9"; + EditorialMediaFlavor["UniversalAStatic16x9"] = "universalAStatic16x9"; + EditorialMediaFlavor["BrickStatic16x9"] = "brickStatic16x9"; + EditorialMediaFlavor["BrickStaticRTL16x9"] = "brickStaticRTL16x9"; + EditorialMediaFlavor["SearchCategoryBrick"] = "searchCategoryBrick"; +})(EditorialMediaFlavor || (EditorialMediaFlavor = {})); +/** + * The different locations for where editorial art is displayed + */ +export var EditorialMediaPlacement; +(function (EditorialMediaPlacement) { + EditorialMediaPlacement["Hero"] = "hero"; + EditorialMediaPlacement["LargeBreakout"] = "largeBreakout"; + EditorialMediaPlacement["StoryCard"] = "storyCard"; + EditorialMediaPlacement["StoryDetail"] = "storyDetail"; + EditorialMediaPlacement["StoryDetailLandscape"] = "storyDetailLandscape"; + EditorialMediaPlacement["Search"] = "search"; + EditorialMediaPlacement["Brick"] = "brick"; + EditorialMediaPlacement["EditorialLockup"] = "editorialLockup"; + EditorialMediaPlacement["EditorialPage"] = "editorialPage"; +})(EditorialMediaPlacement || (EditorialMediaPlacement = {})); +/** + * The mapping between the various placements and the preferred flavor for that location + */ +const preferredEditorialMediaFlavorMap = { + hero: [ + EditorialMediaFlavor.HeroMotion16x9, + EditorialMediaFlavor.HeroStatic16x9, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + largeBreakout: [ + EditorialMediaFlavor.LargeBreakoutMotion16x9, + EditorialMediaFlavor.LargeBreakoutStatic16x9, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyCard: [ + EditorialMediaFlavor.StoryCardMotion3x4, + EditorialMediaFlavor.StoryCardStatic3x4, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyDetail: [ + EditorialMediaFlavor.StoryDetailMotion3x4, + EditorialMediaFlavor.StoryDetailStatic3x4, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyDetailLandscape: [ + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + EditorialMediaFlavor.StoryDetailMotion3x4, + EditorialMediaFlavor.StoryDetailStatic3x4, + ], + search: [ + EditorialMediaFlavor.StorySearchStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + brick: [ + EditorialMediaFlavor.BrickStatic16x9, + EditorialMediaFlavor.HeroStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + EditorialMediaFlavor.SearchCategoryBrick, + ], + editorialLockup: [EditorialMediaFlavor.SubscriptionHero], + editorialPage: [ + EditorialMediaFlavor.StoryCardStatic3x4, + EditorialMediaFlavor.HeroStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.SubscriptionHero, + ], +}; +/** + * The mapping between the various placements and the preferred flavor for that location, for RTL flavors + */ +const preferredEditorialMediaRTLFlavorMap = { + hero: [ + EditorialMediaFlavor.HeroMotionRTL16x9, + EditorialMediaFlavor.HeroStaticRTL16x9, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + largeBreakout: [ + EditorialMediaFlavor.LargeBreakoutRTLMotion16x9, + EditorialMediaFlavor.LargeBreakoutRTLStatic16x9, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyCard: [ + EditorialMediaFlavor.StoryCardMotion3x4, + EditorialMediaFlavor.StoryCardStatic3x4, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyDetail: [ + EditorialMediaFlavor.StoryDetailMotion3x4, + EditorialMediaFlavor.StoryDetailStatic3x4, + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + storyDetailLandscape: [ + EditorialMediaFlavor.StoryCenteredMotion16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAMotion16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + EditorialMediaFlavor.StoryDetailMotion3x4, + EditorialMediaFlavor.StoryDetailStatic3x4, + ], + search: [ + EditorialMediaFlavor.StorySearchStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + ], + brick: [ + EditorialMediaFlavor.BrickStaticRTL16x9, + EditorialMediaFlavor.HeroStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.UniversalAStatic16x9, + EditorialMediaFlavor.SearchCategoryBrick, + ], + editorialLockup: [EditorialMediaFlavor.SubscriptionHero], + editorialPage: [ + EditorialMediaFlavor.StoryCardStatic3x4, + EditorialMediaFlavor.HeroStatic16x9, + EditorialMediaFlavor.StoryCenteredStatic16x9, + EditorialMediaFlavor.SubscriptionHero, + ], +}; +/** + * Create the best suitable editorial artwork / video for the given placement, including the additional data that might be + * needed about this artwork + * + * @param objectGraph + * @param data + * @param placement + */ +export function editorialMediaDataForPlacement(objectGraph, data, placement) { + const editorialCardData = editorialDataUtil.extractEditorialCardData(objectGraph, data); + const preferredEditorialMediaFlavors = preferredEditorialMediaFlavorMap[placement]; + const editorialMediaData = editorialMediaDataForPlacementAndFlavors(objectGraph, data, editorialCardData, placement, preferredEditorialMediaFlavors, false); + const preferredEditorialMediaRTLFlavors = preferredEditorialMediaRTLFlavorMap[placement]; + const rtlEditorialMediaData = editorialMediaDataForPlacementAndFlavors(objectGraph, data, editorialCardData, placement, preferredEditorialMediaRTLFlavors, true); + editorialMediaData.rtlArtwork = rtlEditorialMediaData.rtlArtwork; + editorialMediaData.rtlArtworkData = rtlEditorialMediaData.rtlArtworkData; + editorialMediaData.rtlVideo = rtlEditorialMediaData.rtlVideo; + editorialMediaData.rtlBackgroundColor = rtlEditorialMediaData.rtlBackgroundColor; + editorialMediaData.rtlTextColorOverride = rtlEditorialMediaData.rtlTextColorOverride; + return editorialMediaData; +} +/** + * Creates the `EditorialMediaData` object for a specific placement and flavors. + * + * Note: This will only populate either the LTR properties or the RTL properties on the `EditorialMediaData` + * object, never both. Which ones are populated is based on the `isRTL` flag. + * + * @param objectGraph Current object graph + * @param data The data blob for the main item + * @param editorialCardData The data blob for the editorial card + * @param placement The placement for the media + * @param flavors The flavor candidates for the media + * @param isRTL Whether the placement is for RTL media + * @returns A built `EditorialMediaData` object + */ +function editorialMediaDataForPlacementAndFlavors(objectGraph, data, editorialCardData, placement, flavors, isRTL) { + let editorialMediaData = {}; + for (const flavor of flavors) { + // Check the editorial card first for override media + if (serverData.isDefinedNonNull(editorialCardData)) { + editorialMediaData = + editorialVideoFromDataForFlavor(objectGraph, editorialCardData, placement, flavor, isRTL) || + editorialArtworkFromDataForFlavor(objectGraph, editorialCardData, placement, flavor, isRTL); + if (serverData.isDefinedNonNullNonEmpty(editorialMediaData)) { + break; + } + } + // If no override found, then check the main data + editorialMediaData = + editorialVideoFromDataForFlavor(objectGraph, data, placement, flavor, isRTL) || + editorialArtworkFromDataForFlavor(objectGraph, data, placement, flavor, isRTL); + if (serverData.isDefinedNonNullNonEmpty(editorialMediaData)) { + break; + } + } + if (isNothing(editorialMediaData)) { + editorialMediaData = {}; + } + return editorialMediaData; +} +/** + * Create the best suitable editorial artwork for the given flavor, including the additional data that might be + * needed about this artwork, returns null if there is no editorial artwork for this flavor + * + * @param objectGraph + * @param data + * @param placement + * @param flavor + * @param isRTL + */ +function editorialArtworkFromDataForFlavor(objectGraph, data, placement, flavor, isRTL) { + let editorialArtwork = null; + let editorialArtworkData = null; + let editorialArtworkBackgroundColor = null; + const editorialArtworkPath = `editorialArtwork.${flavor}`; + const attributePlatform = contentAttributes.bestAttributePlatformFromData(objectGraph, data); + if (serverData.isNull(attributePlatform)) { + return null; + } + editorialArtworkData = + mediaAttributes.attributeAsDictionary(data, editorialArtworkPath) || + mediaPlatformAttributes.platformAttributeAsDictionary(data, attributePlatform, editorialArtworkPath); + if (!serverData.isDefinedNonNullNonEmpty(editorialArtworkData)) { + return null; + } + editorialArtwork = content.artworkFromApiArtwork(objectGraph, editorialArtworkData, { + withJoeColorPlaceholder: true, + useCase: artworkUseCaseForPlacement(placement), + cropCode: cropCodeForPlacementAndFlavor(placement, flavor, isRTL), + }); + if (serverData.isNull(editorialArtwork)) { + return null; + } + editorialArtworkBackgroundColor = editorialArtwork.backgroundColor; + const textColorOverride = editorialTextColorOverride(objectGraph, editorialArtworkData, editorialArtwork); + if (isRTL) { + return { + rtlArtwork: editorialArtwork, + rtlArtworkData: editorialArtworkData, + rtlBackgroundColor: editorialArtworkBackgroundColor, + rtlTextColorOverride: textColorOverride, + }; + } + else { + return { + artwork: editorialArtwork, + artworkData: editorialArtworkData, + backgroundColor: editorialArtworkBackgroundColor, + textColorOverride: textColorOverride, + }; + } +} +/** + * Create the best suitable editorial artwork for the given flavor, including the additional data that might be + * needed about this artwork, returns null if there is no editorial artwork for this flavor + * + * @param objectGraph + * @param data + * @param placement + * @param flavor + */ +function editorialVideoFromDataForFlavor(objectGraph, data, placement, flavor, isRTL) { + let editorialVideo = null; + let previewFrameArtwork = null; + let editorialVideoData = null; + let editorialVideoBackgroundColor = null; + const editorialVideoPath = `editorialVideo.${flavor}`; + const attributePlatform = contentAttributes.bestAttributePlatformFromData(objectGraph, data); + if (isNothing(attributePlatform)) { + return null; + } + editorialVideoData = + mediaAttributes.attributeAsDictionary(data, editorialVideoPath) || + mediaPlatformAttributes.platformAttributeAsDictionary(data, attributePlatform, editorialVideoPath); + if (serverData.isNullOrEmpty(editorialVideoData)) { + return null; + } + const previewFrameData = serverData.asDictionary(editorialVideoData, "previewFrame"); + if (serverData.isDefinedNonNullNonEmpty(previewFrameData)) { + previewFrameArtwork = content.artworkFromApiArtwork(objectGraph, previewFrameData, { + withJoeColorPlaceholder: true, + useCase: artworkUseCaseForPlacement(placement), + cropCode: "sr", + }); + } + if (serverData.isDefinedNonNullNonEmpty(previewFrameArtwork)) { + previewFrameArtwork.crop = "sr"; + editorialVideoBackgroundColor = previewFrameArtwork.backgroundColor; + } + const videoUrl = serverData.asString(editorialVideoData, "video"); + if (serverData.isDefinedNonNullNonEmpty(previewFrameArtwork) && isSome(videoUrl) && videoUrl.length > 0) { + editorialVideo = new models.Video(videoUrl, previewFrameArtwork, { + canPlayFullScreen: false, + allowsAutoPlay: true, + looping: true, + playbackControls: videoPlaybackControls(objectGraph, placement), + autoPlayPlaybackControls: {}, + }); + editorialVideo.editorialMediaFlavor = flavor; + editorialVideo.editorialMediaPlacement = placement; + } + if (isNothing(previewFrameData) || isNothing(previewFrameArtwork)) { + return null; + } + const textColorOverride = editorialTextColorOverride(objectGraph, previewFrameData, previewFrameArtwork); + if (isRTL) { + return { + rtlVideo: editorialVideo, + rtlArtwork: previewFrameArtwork, + rtlArtworkData: previewFrameData, + rtlBackgroundColor: editorialVideoBackgroundColor, + rtlTextColorOverride: textColorOverride, + }; + } + else { + return { + video: editorialVideo, + artwork: previewFrameArtwork, + artworkData: previewFrameData, + backgroundColor: editorialVideoBackgroundColor, + textColorOverride: textColorOverride, + }; + } +} +/** + * Determine the correct artwork use case for each placement + * @param placement + */ +function artworkUseCaseForPlacement(placement) { + switch (placement) { + case EditorialMediaPlacement.Hero: + return 19 /* content.ArtworkUseCase.GroupingHero */; + case EditorialMediaPlacement.LargeBreakout: + return 6 /* content.ArtworkUseCase.ArcadeLargeBreakout */; + case EditorialMediaPlacement.StoryCard: + return 15 /* content.ArtworkUseCase.TodayCardMedia */; + case EditorialMediaPlacement.StoryDetail: + case EditorialMediaPlacement.StoryDetailLandscape: + return 13 /* content.ArtworkUseCase.ArticleImage */; + case EditorialMediaPlacement.Search: + return 9 /* content.ArtworkUseCase.SearchEditorialResult */; + default: + return 0 /* content.ArtworkUseCase.Default */; + } +} +/** + * Determine the correct crop code to use for artwork at a given flavor + * @param placement + * @param flavor + * @param isRTL + */ +function cropCodeForPlacementAndFlavor(placement, flavor, isRTL) { + switch (placement) { + case EditorialMediaPlacement.Hero: + switch (flavor) { + case EditorialMediaFlavor.HeroStatic16x9: + if (!isRTL) { + return "gd"; + } + break; + case EditorialMediaFlavor.HeroStaticRTL16x9: + if (isRTL) { + return "gg"; + } + break; + case EditorialMediaFlavor.StoryCenteredStatic16x9: + return isRTL ? "gh" : "ge"; + case EditorialMediaFlavor.UniversalAStatic16x9: + return isRTL ? "gj" : "gi"; + default: + break; + } + break; + case EditorialMediaPlacement.LargeBreakout: + switch (flavor) { + case EditorialMediaFlavor.StoryCenteredStatic16x9: + return isRTL ? "gk" : "gf"; + case EditorialMediaFlavor.UniversalAStatic16x9: + return isRTL ? "gl" : "gm"; + default: + break; + } + break; + case EditorialMediaPlacement.StoryCard: + case EditorialMediaPlacement.StoryDetail: + case EditorialMediaPlacement.StoryDetailLandscape: + case EditorialMediaPlacement.Search: + switch (flavor) { + case EditorialMediaFlavor.UniversalAStatic16x9: + return "gn"; + default: + break; + } + break; + case EditorialMediaPlacement.Brick: + switch (flavor) { + case EditorialMediaFlavor.SearchCategoryBrick: + return "SCB.ApSCBL01"; + default: + break; + } + break; + default: + break; + } + return "sr"; +} +/** + * Determines whether a given piece of editorial media is considered dark, light, or unknown. + * @param objectGraph Current object graph + * @param mediaData The data for the editorial media + * @param isRTL Whether the media to check is for RTL + * @returns True if the media is considered to be dark, false if considered light, or undefined if unknown. + */ +export function isMediaDark(objectGraph, editorialMediaData, isRTL = false) { + if (isNothing(editorialMediaData)) { + return null; + } + const textColorOverride = isRTL + ? editorialMediaData.rtlTextColorOverride + : editorialMediaData.textColorOverride; + const backgroundColor = isRTL + ? editorialMediaData.rtlBackgroundColor + : editorialMediaData.backgroundColor; + if (isSome(textColorOverride)) { + // Custom text colors can either be white or black. If the custom color is white, we set the + // media as dark, which will implicitly use white text. The behaviour is reversed for black text. + return color.isColorEqualToColor(textColorOverride, color.white); + } + else if (isSome(backgroundColor)) { + // If no custom text color is set, use the media background color to determine the darkness. + return color.isDarkColor(backgroundColor); + } + return null; +} +/** + * Determines if an editorially set custom text color should be used. + * @param objectGraph Current object graph + * @param artworkData The data that represents the editorial artwork + * @param artwork The parsed editorial artwork + * @returns True if the component should respect an editorial color + */ +function editorialTextColorOverride(objectGraph, artworkData, artwork) { + const textColor = artwork === null || artwork === void 0 ? void 0 : artwork.textColor; + if (isNothing(textColor)) { + return null; + } + const useCustomTextColor = serverData.asBooleanOrFalse(artworkData, "useCustomTextColor"); + const customTextColorIsValid = color.isColorEqualToColor(textColor, color.black) || color.isColorEqualToColor(textColor, color.white); + if (useCustomTextColor && customTextColorIsValid) { + return textColor; + } + return null; +} +/** + * Determines the video playback controls for a given placement. + * @param objectGraph Current object graph + * @param placement The placement for the view containing the video + * @returns The video playback controls + */ +function videoPlaybackControls(objectGraph, placement) { + switch (placement) { + case EditorialMediaPlacement.Hero: + case EditorialMediaPlacement.StoryDetail: + case EditorialMediaPlacement.StoryDetailLandscape: + return videoDefaults.noControls(objectGraph); + default: + return videoDefaults.standardControls(objectGraph); + } +} +//# sourceMappingURL=editorial-media-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-component-media-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-component-media-util.js new file mode 100644 index 0000000..9a39901 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-component-media-util.js @@ -0,0 +1,76 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as lockups from "../lockups/lockups"; +import * as editorialDataUtil from "./editorial-data-util"; +import * as editorialMediaUtil from "./editorial-media-util"; +/** + * Get the editorial artwork / video data for a component on an editorial page + * @param objectGraph + * @param data + * @param collectionDisplayStyle + */ +export function editorialMediaDataFromData(objectGraph, data, collectionDisplayStyle) { + switch (collectionDisplayStyle) { + case "EditorialLockupMedium": + case "EditorialLockupLarge": + case "EditorialLockupMediumVariant": + case "EditorialLockupLargeVariant": + return editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, data, editorialMediaUtil.EditorialMediaPlacement.EditorialLockup); + case "BrickSmall": + case "BrickMedium": + case "BrickLarge": + return editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, data, editorialMediaUtil.EditorialMediaPlacement.Brick); + case "StoryMedium": + case "StorySmall": + return editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, data, editorialMediaUtil.EditorialMediaPlacement.StoryCard); + case "Hero": + return editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, data, editorialMediaUtil.EditorialMediaPlacement.Hero); + case "BreakoutLarge": + return editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, data, editorialMediaUtil.EditorialMediaPlacement.LargeBreakout); + default: + return {}; + } +} +/** + * Get the app icons to display when there is no editorial artwork / video + * @param objectGraph + * @param data + * @param lockupOptions + */ +export function editorialFallbackAppIconsFromData(objectGraph, data, lockupOptions) { + const collectionLockups = editorialCollectionAppsFromData(objectGraph, data, { lockupOptions: lockupOptions }); + if (serverData.isNullOrEmpty(collectionLockups)) { + return undefined; + } + return collectionLockups === null || collectionLockups === void 0 ? void 0 : collectionLockups.map((lockup) => { + return lockup.icon; + }); +} +/** + * Get lockup to be displayed on an editorial component + * @param objectGraph + * @param data + * @param lockupOptions + */ +export function editorialAppLockupFromData(objectGraph, data, lockupOptions) { + const productData = editorialDataUtil.extractProductData(objectGraph, data); + if (serverData.isNullOrEmpty(productData)) { + return null; + } + const appLockup = lockups.lockupFromData(objectGraph, productData, lockupOptions); + return appLockup; +} +/** + * Get the lockups from the collection this data is pointing to for a component on an editorial page + * @param objectGraph + * @param data + * @param lockupOptions + */ +export function editorialCollectionAppsFromData(objectGraph, data, lockupOptions) { + const collectionData = editorialDataUtil.extractCollectionData(objectGraph, data); + if (serverData.isNullOrEmpty(collectionData)) { + return null; + } + const collectionApps = lockups.lockupsFromData(objectGraph, collectionData, lockupOptions); + return collectionApps; +} +//# sourceMappingURL=editorial-page-component-media-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-controller-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-controller-util.js new file mode 100644 index 0000000..db81f0d --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-controller-util.js @@ -0,0 +1,209 @@ +import { isNothing } from "@jet/environment"; +import * as editorialMediaUtil from "./editorial-media-util"; +import * as mediaAttributes from "../../foundation/media/attributes"; +import * as mediaDataFetching from "../../foundation/media/data-fetching"; +import * as mediaDataStructure from "../../foundation/media/data-structure"; +import * as mediaRelationship from "../../foundation/media/relationships"; +import * as metricsHelpersLocation from "../../common/metrics/helpers/location"; +import * as metricsHelpersPage from "../../common/metrics/helpers/page"; +import * as metricsHelpersUtil from "../../common/metrics/helpers/util"; +import * as models from "../../api/models"; +import * as onDevicePersonalization from "../../common/personalization/on-device-personalization"; +import * as refresh from "../../common/refresh/page-refresh-controller"; +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as sharing from "../../common/sharing"; +import * as shelfBatching from "../../common/grouping/shelf-batching"; +import { createBaseShelfToken } from "./editorial-page-shelf-token"; +import { buildEditorialShelf } from "./editorial-page-shelf-builder"; +import { buildArcadeLockup } from "./editorial-page-shelf-builder/editorial-page-arcade-lockup-builder"; +import { shelfForTermsAndConditions } from "../grouping/grouping-common"; +import { EditorialShelfType } from "./editorial-page-types"; +/** + * Returns the number of shelves to hydrate on first load + */ +export function pageSparseCount(objectGraph) { + if (objectGraph.client.isWeb) { + // Returning `null` will avoid `Request` from setting the count at all + return null; + } + else { + return 5; + } +} +/** + * Returns the number of hydrated items in the hydrated shelves + */ +export function pageSparseLimit(objectGraph) { + return 12; +} +/** + * Modify request for a items fetched for grouping shelf items. (i.e. individual IDs). + * This should be ideally be in grouping builder's `prepareRequest`, but that would change how url-driven requests are configured. + * @param objectGraph + * @param request Request to modify. + */ +export function prepareMAPIRequest(objectGraph, request) { + const baseAttributes = ["editorialArtwork", "editorialVideo", "editorialClientParams"]; + const editorialItemsAttributes = [ + ...baseAttributes, + "showExpectedReleaseDate", + "expectedReleaseDateDisplayFormat", + "enrichedEditorialNotes", + "shortEditorialNotes", + ]; + const editorialPagesAttributes = [...baseAttributes, "enrichedEditorialNotes"]; + const contentAttributes = [ + ...baseAttributes, + "minimumOSVersion", + "screenshotsByType", + "videoPreviewsByType", + "expectedReleaseDateDisplayFormat", + "isAppleWatchSupported", + "minimumOSVersion", + "compatibilityControllerRequirement", + ]; + if (objectGraph.appleSilicon.isSupportEnabled) { + contentAttributes.push("macRequiredCapabilities"); + } + if (objectGraph.client.isMac) { + contentAttributes.push("hasMacIPAPackage"); + } + if (objectGraph.client.isVision) { + request.addingRelationshipLimit("editorial-shelves-collection:contents", 100); + } + if (objectGraph.client.isWeb) { + request.addingRelationshipLimit("editorial-shelves-collection:contents", 20); + } + const appsAttributes = [...contentAttributes]; + const features = ["personalization", "supportsCustomTextColor"]; + request + .includingAgeRestrictions() + .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph)) + .enablingFeatures(features) + .includingRelationshipsForUpsell(true) + .includingScopedAttributes("editorial-items", editorialItemsAttributes) + .includingScopedAttributes("editorial-pages", editorialPagesAttributes) + .includingScopedAttributes("apps", appsAttributes); +} +export function shareSheetActionFromData(objectGraph, editorialPageData) { + var _a; + const url = mediaAttributes.attributeAsString(editorialPageData, "url"); + const title = mediaAttributes.attributeAsString(editorialPageData, "editorialNotes.name"); + if (serverData.isNull(url) || serverData.isNull(title)) { + return null; + } + const subtitle = objectGraph.loc.string("SHARE_EDITORIAL_PAGE_SUBTITLE"); + const artwork = (_a = editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, editorialPageData, editorialMediaUtil.EditorialMediaPlacement.EditorialPage)) === null || _a === void 0 ? void 0 : _a.artwork; + // Create share sheet model (bail out if unable to do so) + const shareData = sharing.shareSheetDataForGenericPage(objectGraph, title, url, subtitle, null, artwork); + if (isNothing(shareData)) { + return null; + } + const activities = sharing.shareSheetActivitiesForGenericPage(objectGraph, url); + return new models.ShareSheetAction(shareData, activities); +} +export async function renderPage(objectGraph, data, parameters) { + var _a, _b; + const editorialPageData = mediaDataStructure.dataFromDataContainer(objectGraph, data); + if (!serverData.isDefinedNonNullNonEmpty(editorialPageData)) { + return null; + } + const canvasData = mediaRelationship.relationshipCollection(editorialPageData, "canvas"); + if (!serverData.isDefinedNonNullNonEmpty(canvasData)) { + return null; + } + let pageType = "Editorial"; + const typeFromServer = serverData.asString(editorialPageData, "type"); + if (typeFromServer === "tags") { + pageType = "TagRoom"; + } + const metricsPageInformation = metricsHelpersPage.metricsPageInformationFromMediaApiResponse(objectGraph, pageType, editorialPageData.id, data); + const metricsLocationTracker = metricsHelpersLocation.newLocationTracker(); + const onDevicePersonalizationMetricsData = onDevicePersonalization.metricsData(objectGraph); + metricsPageInformation.recoMetricsData = metricsHelpersUtil.combinedRecoMetricsDataFromMetricsData(metricsPageInformation.recoMetricsData, null, onDevicePersonalizationMetricsData); + const pageRefreshController = refresh.newPageRefreshControllerFromResponse(data); + const { isArcadePage } = parameters; + const shelves = []; + let pageData = null; + let arcadeLockup = null; + if (serverData.isDefinedNonNull(editorialPageData.attributes)) { + pageData = { + id: editorialPageData.id, + type: editorialPageData.type, + attributes: editorialPageData.attributes, + relationships: editorialPageData.relationships, + meta: editorialPageData.meta, + }; + } + else { + return null; + } + let hasUpsellbreakout = false; + for (const shelfData of canvasData) { + const shelfIndex = shelves.length; + const shelfToken = createBaseShelfToken(objectGraph, pageData.id, shelfData, isArcadePage, shelfIndex, metricsPageInformation, metricsLocationTracker); + const shelf = buildEditorialShelf(objectGraph, pageData, shelfToken); + if (serverData.isNull(shelf)) { + continue; + } + if (shelves.length === 0) { + const existingPresentationHints = shelf.presentationHints; + shelf.presentationHints = { + ...existingPresentationHints, + isFirstShelf: true, + }; + } + if (shelfToken.type === EditorialShelfType.Upsell) { + hasUpsellbreakout = true; + } + if (shelf.contentType === "upsellBreakout") { + arcadeLockup = buildArcadeLockup(objectGraph, shelfToken); + } + shelves.push(shelf); + } + const page = isArcadePage ? new models.ArcadePage(shelves) : new models.GenericPage(shelves); + page.title = hasUpsellbreakout + ? null + : (_a = mediaAttributes.attributeAsString(editorialPageData, "editorialNotes.name")) !== null && _a !== void 0 ? _a : mediaAttributes.attributeAsString(editorialPageData, "name"); + page.canonicalURL = mediaAttributes.attributeAsString(editorialPageData, "url"); + page.shareAction = shareSheetActionFromData(objectGraph, editorialPageData); + page.pageRefreshPolicy = refresh.pageRefreshPolicyForController(objectGraph, pageRefreshController); + // Create the ArcadeLockup for Arcade's sticky header + if (isArcadePage && serverData.isDefinedNonNull(arcadeLockup)) { + page.subscriptionLockup = arcadeLockup; + } + if (isArcadePage) { + metricsPageInformation.isCrossfireReferralCandidate = true; + } + metricsHelpersPage.addMetricsEventsToPageWithInformation(objectGraph, page, metricsPageInformation); + if (objectGraph.client.isVision) { + page.presentationOptions.push("prefersRevealingPageTitleWhenNotRoot"); + } + const isLastShelfSeeAllGames = ((_b = shelves[shelves.length - 1]) === null || _b === void 0 ? void 0 : _b.contentType) === "arcadeFooter"; + if (objectGraph.client.deviceType !== "watch" && + objectGraph.client.deviceType !== "tv" && + !isLastShelfSeeAllGames) { + const url = objectGraph.bag.termsAndConditionsURL; + if (!serverData.isNull(url)) { + const termsAndConditionsShelf = shelfForTermsAndConditions(objectGraph, url); + shelves.push(termsAndConditionsShelf); + } + } + if (shelves.length > 0) { + const isLargeHeroBreakout = shelves[0].contentType === "largeHeroBreakout"; + const isUpsell = shelves[0].contentType === "upsellBreakout"; + const isHeroCarousel = shelves[0].contentType === "heroCarousel"; + const isMediaPageHeader = shelves[0].contentType === "mediaPageHeader"; + const shouldOverlayPageHeader = isLargeHeroBreakout || isUpsell || isHeroCarousel || isMediaPageHeader; + if (shouldOverlayPageHeader && !preprocessor.GAMES_TARGET) { + page.presentationOptions.push("prefersOverlayedPageHeader"); + } + if (isMediaPageHeader) { + page.presentationOptions.push("prefersNonStandardBackButton"); + page.presentationOptions.push("prefersHiddenPageTitle"); + } + } + shelfBatching.addBatchGroupsToPage(page); + return page; +} +//# sourceMappingURL=editorial-page-controller-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-editorial-copy-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-editorial-copy-util.js new file mode 100644 index 0000000..7e8da86 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-editorial-copy-util.js @@ -0,0 +1,247 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../foundation/media/attributes"; +import * as mediaPlatformAttributes from "../../foundation/media/platform-attributes"; +import * as contentAttributes from "../content/attributes"; +import * as editorialDataUtil from "./editorial-data-util"; +/** + * Get the text that should be displayed as the badge (some times referred to as caption) for + * an editorial component + * @param objectGraph + * @param data + * @param collectionDisplayStyle + */ +export function editorialBadgeFromData(objectGraph, data, collectionDisplayStyle) { + let editorialBadge = null; + let editorialBadgeOverride = null; + let editorialBadgePaths = []; + // Check the editorial card first for override content + const editorialCardData = editorialDataUtil.extractEditorialCardData(objectGraph, data); + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + editorialBadgePaths = ["enrichedEditorialNotes.badge", "editorialNotes.badge", "label"]; + editorialBadge = findFirstMatchingString(objectGraph, data, editorialBadgePaths, false); + editorialBadgeOverride = findFirstMatchingString(objectGraph, editorialCardData, editorialBadgePaths, false); + break; + case "apps": + case "in-apps": + case "app-bundles": + editorialBadgePaths = ["editorialNotes.badge"]; + editorialBadge = findFirstMatchingString(objectGraph, data, editorialBadgePaths, true); + editorialBadgeOverride = findFirstMatchingString(objectGraph, editorialCardData, editorialBadgePaths, true); + break; + default: + break; + } + const badge = serverData.isDefinedNonNull(editorialBadgeOverride) ? editorialBadgeOverride : editorialBadge; + if (serverData.isNullOrEmpty(badge)) { + return null; + } + return badge; +} +/** + * Get the text that should be displayed as the title for + * an editorial component + * @param objectGraph + * @param data + * @param collectionDisplayStyle + */ +export function editorialTitleFromData(objectGraph, data, collectionDisplayStyle) { + let editorialTitle = null; + let editorialTitlePaths = []; + switch (collectionDisplayStyle) { + case "EditorialLockupMediumVariant": + case "EditorialLockupLargeVariant": + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + editorialTitlePaths = ["enrichedEditorialNotes.name", "editorialNotes.name"]; + editorialTitle = attributeAsString(data, editorialTitlePaths); + break; + case "apps": + case "in-apps": + case "app-bundles": + editorialTitlePaths = ["editorialNotes.tagline"]; + editorialTitle = findFirstMatchingString(objectGraph, data, editorialTitlePaths, true); + break; + default: + break; + } + break; + default: + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + editorialTitlePaths = ["enrichedEditorialNotes.name", "editorialNotes.name"]; + editorialTitle = findFirstMatchingString(objectGraph, data, editorialTitlePaths, false); + break; + case "tags": + case "apps": + case "in-apps": + case "app-bundles": + editorialTitlePaths = ["name"]; + editorialTitle = findFirstMatchingString(objectGraph, data, editorialTitlePaths, false); + break; + default: + break; + } + } + // Check the editorial card first for override content + const editorialCardData = editorialDataUtil.extractEditorialCardData(objectGraph, data); + const editorialTitleOverride = findFirstMatchingString(objectGraph, editorialCardData, editorialTitlePaths, false); + const title = serverData.isDefinedNonNull(editorialTitleOverride) ? editorialTitleOverride : editorialTitle; + if (serverData.isNullOrEmpty(title)) { + return null; + } + return title; +} +/** + * Get the text that should be displayed as the description for + * an editorial component + * @param objectGraph + * @param data + */ +export function editorialDescriptionFromData(objectGraph, data, preferHeroDescription = false) { + let editorialDescription = null; + let editorialDescriptionPaths = []; + switch (data.type) { + case "editorial-items": + if (preferHeroDescription) { + editorialDescriptionPaths = ["enrichedEditorialNotes.tagline", "editorialNotes.tagline"]; + } + else { + const ignoreShortNotes = mediaAttributes.attributeAsBooleanOrFalse(data, "ignoreITunesShortNotes"); + if (!ignoreShortNotes) { + editorialDescriptionPaths = ["enrichedEditorialNotes.short", "editorialNotes.short"]; + } + } + editorialDescription = findFirstMatchingString(objectGraph, data, editorialDescriptionPaths, false); + break; + case "editorial-pages": + case "editorial-shelves-header": + editorialDescriptionPaths = ["enrichedEditorialNotes.tagline", "editorialNotes.tagline"]; + editorialDescription = findFirstMatchingString(objectGraph, data, editorialDescriptionPaths, false); + break; + case "apps": + case "in-apps": + case "app-bundles": + editorialDescriptionPaths = ["editorialNotes.tagline"]; + editorialDescription = findFirstMatchingString(objectGraph, data, editorialDescriptionPaths, true); + break; + default: + break; + } + // Check the editorial card first for override content + const editorialCardData = editorialDataUtil.extractEditorialCardData(objectGraph, data); + const editorialDescriptionOverride = findFirstMatchingString(objectGraph, editorialCardData, editorialDescriptionPaths, false); + const description = serverData.isDefinedNonNull(editorialDescriptionOverride) + ? editorialDescriptionOverride + : editorialDescription; + if (serverData.isNullOrEmpty(description)) { + return null; + } + return description; +} +/** + * Get the text that should be displayed as the call to action on a button for + * an editorial component + * @param objectGraph + * @param data + */ +export function editorialCallToActionFromData(objectGraph, data) { + let editorialCallToAction = null; + let editorialCallToActionPaths = []; + switch (data.type) { + case "editorial-items": + case "editorial-pages": + case "editorial-shelves-header": + editorialCallToActionPaths = ["enrichedEditorialNotes.callToAction", "editorialNotes.callToAction"]; + editorialCallToAction = findFirstMatchingString(objectGraph, data, editorialCallToActionPaths, false); + break; + case "apps": + case "in-apps": + case "app-bundles": + editorialCallToActionPaths = ["enrichedEditorialNotes.callToAction", "editorialNotes.callToAction"]; + editorialCallToAction = findFirstMatchingString(objectGraph, data, editorialCallToActionPaths, true); + break; + default: + break; + } + // Check the editorial card first for override content + const editorialCardData = editorialDataUtil.extractEditorialCardData(objectGraph, data); + const editorialCallToActionOverride = findFirstMatchingString(objectGraph, editorialCardData, editorialCallToActionPaths, false); + let callToAction = null; + if ((editorialCallToActionOverride === null || editorialCallToActionOverride === void 0 ? void 0 : editorialCallToActionOverride.length) > 0) { + callToAction = editorialCallToActionOverride; + } + else if (serverData.isDefinedNonNullNonEmpty(editorialCallToAction)) { + callToAction = editorialCallToAction; + } + else { + if (preprocessor.GAMES_TARGET) { + callToAction = objectGraph.loc.string("Card.Collection.ActionButton.Title"); + } + else { + callToAction = objectGraph.loc.string("HERO_CAROUSEL_OVERLAY_BUTTON_TITLE_VIEW"); + } + } + return callToAction; +} +// region Debug Helpers +/** + * Retrieve the specified attribute from the data as a string. + * + * @param data The data from which to retrieve the attribute. + * @param attributePath The object path for the attribute. + * @returns {string} The attribute value as a string. + */ +function attributeAsString(data, attributePath) { + if (serverData.isNullOrEmpty(data)) { + return null; + } + return mediaAttributes.attributeAsString(data, attributePath); +} +/** + * Retrieve the specified attribute from the data as a string. Returning the path if null or missing + * + * If the attribute lives under the platform-specific attributes, then a platform may be provided to properly call in to + * the nested structure. + * @param data The data from which to retrieve the attribute. + * @param platform The platform to look up + * @param attributePath The object path for the attribute. + * @returns {string} The attribute value as a string. + */ +export function platformAttributeAsString(data, platform, attributePath) { + if (serverData.isNullOrEmpty(data)) { + return null; + } + return mediaPlatformAttributes.platformAttributeAsString(data, platform, attributePath); +} +/** + * Retrieve the specified attribute from the data as a string. Trying to find the best match for the given paths. + * @param objectGraph The object graph to use lookups + * @param mediaApiData The media data to use to query for the string + * @param stringPaths The different paths to try to find the string + * @param usePlatformAttributes Whether to check the platform attributes or not + * @returns The first matching string or null if none found + */ +function findFirstMatchingString(objectGraph, mediaApiData, stringPaths, usePlatformAttributes) { + if (serverData.isNullOrEmpty(mediaApiData)) { + return null; + } + const attributePlatform = contentAttributes.bestAttributePlatformFromData(objectGraph, mediaApiData); + for (const path of stringPaths) { + const matchingString = usePlatformAttributes + ? platformAttributeAsString(mediaApiData, attributePlatform, path) + : attributeAsString(mediaApiData, path); + if (serverData.isDefinedNonNullNonEmpty(matchingString)) { + return matchingString; + } + } + return null; +} +// endregion +//# sourceMappingURL=editorial-page-editorial-copy-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-hero-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-hero-util.js new file mode 100644 index 0000000..7ecca30 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-hero-util.js @@ -0,0 +1,88 @@ +import { isSome } from "@jet/environment/types/optional"; +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 content from "../content/content"; +import * as heroCarouselOverlayCommon from "../grouping/hero/hero-carousel-overlay-common"; +import { deepLinkUrlFromData } from "../linking/external-deep-link"; +import * as lockups from "../lockups/lockups"; +import * as metricsHelpersImpressions from "../metrics/helpers/impressions"; +import * as editorialComponentMediaUtil from "./editorial-page-component-media-util"; +import * as editorialCopyUtil from "./editorial-page-editorial-copy-util"; +import * as editorialOverlayContentUtil from "./editorial-page-overlay-content-util"; +import { CollectionShelfDisplayStyle } from "./editorial-page-types"; +// region Overlay +export function heroOverlayFromData(objectGraph, data, shelfToken, editorialClientParams) { + const heroCarouselItemOverlay = new models.HeroCarouselItemOverlay(); + heroCarouselItemOverlay.overlayType = heroCarouselOverlayCommon.overlayTypeFromData(objectGraph, data); + heroCarouselItemOverlay.displayOptions = { + horizontalPlacement: "leading", + textAlignment: "leading", + isOverDarkContent: heroCarouselOverlayCommon.overlayIsOverDarkContent(objectGraph, data), + }; + heroCarouselItemOverlay.badgeText = editorialCopyUtil.editorialBadgeFromData(objectGraph, data, CollectionShelfDisplayStyle.Hero); + heroCarouselItemOverlay.titleText = editorialCopyUtil.editorialTitleFromData(objectGraph, data, CollectionShelfDisplayStyle.Hero); + if (!editorialClientParams.suppressTagline) { + heroCarouselItemOverlay.descriptionText = editorialCopyUtil.editorialDescriptionFromData(objectGraph, data, true); + } + heroCarouselItemOverlay.callToActionText = editorialCopyUtil.editorialCallToActionFromData(objectGraph, data); + heroCarouselItemOverlay.buttonTitle = heroCarouselOverlayCommon.overlayButtonTitleFromData(objectGraph, data); + const lockupOptions = { + metricsOptions: { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + targetType: "lockupSmall", + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data), + }, + metricsClickOptions: { + id: data.id, + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + actionDetails: { + franchise: heroCarouselItemOverlay.badgeText, + }, + }, + artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + offerEnvironment: "dark", + canDisplayArcadeOfferButton: content.shelfDisplayStyleCanDisplayArcadeOfferButtons(objectGraph, shelfToken.collectionDisplayStyle), + isContainedInPreorderExclusiveShelf: false, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, data), + }; + const appLockup = editorialComponentMediaUtil.editorialAppLockupFromData(objectGraph, data, lockupOptions); + const overlayContent = editorialOverlayContentUtil.extractOverlayContent(objectGraph, data, lockupOptions); + heroCarouselItemOverlay.lockup = overlayContent.lockup; + heroCarouselItemOverlay.collectionIcons = overlayContent.collectionIcons; + // If this EI can and should show the expected release date of an arcade app, override the badge. + const fallbackLabel = mediaAttributes.attributeAsString(data, "label"); + // For hero items the design is to use editorial labels instead of "Apple Arcade" so we replace that text here + if (serverData.isDefinedNonNullNonEmpty(fallbackLabel) && serverData.isDefinedNonNull(appLockup)) { + appLockup.heading = fallbackLabel; + } + const suppressLockup = isSome(editorialClientParams.suppressLockup) && editorialClientParams.suppressLockup; + if (serverData.isDefinedNonNullNonEmpty(heroCarouselItemOverlay.lockup) && !suppressLockup) { + heroCarouselItemOverlay.clickAction = heroCarouselItemOverlay.lockup.clickAction; + heroCarouselItemOverlay.impressionMetrics = heroCarouselItemOverlay.lockup.impressionMetrics; + } + else { + const heroCarouselItemOverlayMetricsOptions = { + targetType: "hero", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(data), + }; + const heroCarouselOverlayItemClickOptions = { + ...heroCarouselItemOverlayMetricsOptions, + id: data.id, + actionDetails: { + franchise: heroCarouselItemOverlay.badgeText, + }, + }; + heroCarouselItemOverlay.clickAction = lockups.editorialItemActionFromData(objectGraph, data, heroCarouselOverlayItemClickOptions, shelfToken.clientIdentifierOverride); + const heroCarouselItemOverlayImpressionsOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, heroCarouselItemOverlay.titleText, heroCarouselItemOverlayMetricsOptions); + metricsHelpersImpressions.addImpressionFields(objectGraph, heroCarouselItemOverlay, heroCarouselItemOverlayImpressionsOptions); + } + return heroCarouselItemOverlay; +} +// endregion +//# sourceMappingURL=editorial-page-hero-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-intent-controller-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-intent-controller-utils.js new file mode 100644 index 0000000..e3c2690 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-intent-controller-utils.js @@ -0,0 +1,5 @@ +import { generateRoutes } from "../util/generate-routes"; +import { makeEditorialPageIntentByID } from "../../api/intents/editorial/editorial-page-intent"; +const { routes: editorialPageRoutes, makeCanonicalUrl: makeEditorialPageURL } = generateRoutes(makeEditorialPageIntentByID, "/{platform}/editorial/{id}"); +export { editorialPageRoutes, makeEditorialPageURL }; +//# sourceMappingURL=editorial-page-intent-controller-utils.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-lockup-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-lockup-utils.js new file mode 100644 index 0000000..35e1cf9 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-lockup-utils.js @@ -0,0 +1,91 @@ +// region Lockup Creation +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaDataStructure from "../../foundation/media/data-structure"; +import * as content from "../content/content"; +import * as adLockups from "../lockups/ad-lockups"; +import * as lockups from "../lockups/lockups"; +import { clickTargetForCollectionDisplayStyle } from "./editorial-action-util"; +import { CollectionShelfFilterOverride } from "./editorial-page-types"; +import { isNothing } from "@jet/environment/types/optional"; +// region Lockup Creation +/** + * Create a lockup for shelfContents to display within an editorial page shelf + * @param objectGraph + * @param lockupData shelfContents to create lockup for. + * @param shelfToken Shelf shelfToken + * @param itemPosition The position of the item in the shelf + * @param collectionDisplayStyle The collection display style + */ +export function lockupFromData(objectGraph, lockupData, shelfToken, itemPosition, collectionDisplayStyle) { + if (serverData.isNullOrEmpty(lockupData)) { + return null; + } + // Set the ordinal + let ordinalString; + if (shelfToken.showOrdinals) { + ordinalString = objectGraph.loc.decimal(shelfToken.ordinalIndex); + } + let offerStyle = null; + if (serverData.isDefinedNonNull(shelfToken.shelfBackground) && + (shelfToken.shelfBackground.type === "color" || shelfToken.shelfBackground.type === "interactive")) { + offerStyle = "white"; + } + let clientIdentifierOverride; + if (serverData.isDefinedNonNullNonEmpty(shelfToken)) { + clientIdentifierOverride = shelfToken.clientIdentifierOverride; + } + const contentMetricsOptions = { + ...shelfToken.metricsImpressionOptions, + id: lockupData.id, + idType: "its_id", + }; + // Create the lockup + const lockupOptions = { + ordinal: ordinalString, + metricsOptions: { + ...contentMetricsOptions, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(lockupData), + isAdvert: adLockups.isAdvert(objectGraph, lockupData), + targetType: clickTargetForCollectionDisplayStyle(objectGraph, collectionDisplayStyle), + }, + clientIdentifierOverride: clientIdentifierOverride, + artworkUseCase: 0 /* content.ArtworkUseCase.Default */, + offerStyle: offerStyle, + canDisplayArcadeOfferButton: content.shelfDisplayStyleCanDisplayArcadeOfferButtons(objectGraph, collectionDisplayStyle), + isContainedInPreorderExclusiveShelf: shelfToken.filterOverrides.includes(CollectionShelfFilterOverride.ShowOnlyPreorder), + }; + let lockup; + switch (collectionDisplayStyle) { + case "EditorialLockupMediumVariant": + case "EditorialLockupMedium": + case "EditorialLockupLargeVariant": + case "EditorialLockupLarge": + lockupOptions.offerEnvironment = "light"; + lockup = lockups.imageLockupFromData(objectGraph, lockupData, lockupOptions, collectionDisplayStyle); + break; + case "Poster": + lockup = lockups.posterLockupFromData(objectGraph, lockupData, lockupOptions); + break; + default: + lockup = lockups.lockupFromData(objectGraph, lockupData, lockupOptions); + } + if (serverData.isNull(lockup) || !lockup.isValid()) { + return null; + } + lockup.id = lockupIdentifier(shelfToken, itemPosition, lockup.adamId); + return lockup; +} +/** + * @param shelfToken The shelf token + * @param itemPosition The position of the item in the shelf + * @param adamId The adamID associated with the lockup + * @returns A string for uniquely identifying the lockup in this shelf + */ +function lockupIdentifier(shelfToken, itemPosition, adamId) { + if (isNothing(adamId)) { + return null; + } + return `${shelfToken.id}_${itemPosition}_${adamId}`; +} +// endregion +//# sourceMappingURL=editorial-page-lockup-utils.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-media-api-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-media-api-utils.js new file mode 100644 index 0000000..42e838a --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-media-api-utils.js @@ -0,0 +1,39 @@ +import * as editorialPageControllerUtil from "./editorial-page-controller-util"; +import { Request as MediaAPIRequest, defaultAdditionalPlatformsForClient } from "../../foundation/media/data-fetching"; +import { Parameters } from "../../foundation/network/url-constants"; +import { shouldFetchCustomAttributes } from "../product-page/product-page-variants"; +import { isEditorialPageIntentByName, } from "../../api/intents/editorial/editorial-page-intent"; +import { setPreviewPlatform } from "../preview-platform"; +export function makeEditorialPageRequest(objectGraph, intent) { + const mediaApiRequest = makeBaseMediaAPIRequest(objectGraph, intent); + if (isEditorialPageIntentByName(intent)) { + mediaApiRequest.addingQuery(Parameters.name, intent.name); + } + else { + mediaApiRequest.withIdOfType(intent.id, "editorial-pages"); + } + prepareMediaAPIRequest(objectGraph, mediaApiRequest); + setPreviewPlatform(objectGraph, mediaApiRequest); + return mediaApiRequest; +} +function makeBaseMediaAPIRequest(objectGraph, locale) { + return new MediaAPIRequest(objectGraph, `/v1/editorial/${locale.storefront}`).forType("editorial-pages"); +} +function prepareMediaAPIRequest(objectGraph, mediaApiRequest) { + mediaApiRequest.includingAdditionalPlatforms(defaultAdditionalPlatformsForClient(objectGraph)); + mediaApiRequest.usingCustomAttributes(shouldFetchCustomAttributes(objectGraph)); + // <rdar://53420717> For performance reasons, we limit shelves to 3 items on watchOS. + if (objectGraph.client.isWatch) { + mediaApiRequest.addingRelationshipLimit("contents", 3); + } + mediaApiRequest + .includingAgeRestrictions() + .includingScopedRelationships("editorial-shelves", ["contents"]) + .includingScopedRelationships("editorial-pages", ["primary-contents"]) + .includingRelationships(["canvas"]) + .withSparseCount(editorialPageControllerUtil.pageSparseCount(objectGraph)) + .withSparseLimit(editorialPageControllerUtil.pageSparseLimit(objectGraph)) + .includingAssociateKeys("editorial-shelves-collection:contents", ["editorial-cards"]); + editorialPageControllerUtil.prepareMAPIRequest(objectGraph, mediaApiRequest); +} +//# sourceMappingURL=editorial-page-media-api-utils.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-overlay-content-util.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-overlay-content-util.js new file mode 100644 index 0000000..f76d85a --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-overlay-content-util.js @@ -0,0 +1,20 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import { popLocation, pushBasicLocation } from "../metrics/helpers/location"; +import * as editorialComponentMediaUtil from "./editorial-page-component-media-util"; +export function extractOverlayContent(objectGraph, itemData, lockupOptions) { + const overlayContent = {}; + pushBasicLocation(objectGraph, lockupOptions.metricsOptions, "collectionIcons"); + const collectionIcons = editorialComponentMediaUtil.editorialFallbackAppIconsFromData(objectGraph, itemData, lockupOptions); + popLocation(lockupOptions.metricsOptions.locationTracker); + const appLockup = editorialComponentMediaUtil.editorialAppLockupFromData(objectGraph, itemData, lockupOptions); + if (serverData.isDefinedNonNullNonEmpty(collectionIcons) && + (collectionIcons.length > 1 || serverData.isNullOrEmpty(appLockup))) { + overlayContent.collectionIcons = collectionIcons; + } + else if (serverData.isDefinedNonNull(appLockup)) { + overlayContent.lockup = appLockup; + overlayContent.collectionIcons = [appLockup.icon]; + } + return overlayContent; +} +//# sourceMappingURL=editorial-page-overlay-content-util.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-lockup-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-lockup-builder.js new file mode 100644 index 0000000..edb539c --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-lockup-builder.js @@ -0,0 +1,17 @@ +import * as models from "../../../api/models"; +import * as serverData from "../../../foundation/json-parsing/server-data"; +import * as arcadeCommon from "../../arcade/arcade-common"; +import * as lockups from "../../lockups/lockups"; +export function buildArcadeLockup(objectGraph, upsellBreakoutShelfToken) { + const metricsOptions = { + pageInformation: upsellBreakoutShelfToken.metricsPageInformation, + locationTracker: upsellBreakoutShelfToken.metricsLocationTracker, + }; + const upsellData = arcadeCommon.upsellFromRelationshipOf(objectGraph, upsellBreakoutShelfToken.data); + if (serverData.isNullOrEmpty(upsellData)) { + return null; + } + const arcadeLockup = lockups.arcadeLockupFromData(objectGraph, upsellData, metricsOptions, models.marketingItemContextFromString("arcadeTabHeader"), "colored", objectGraph.client.isMac ? "arcade" : "navigationBar"); + return arcadeLockup; +} +//# sourceMappingURL=editorial-page-arcade-lockup-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-see-all-games-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-see-all-games-shelf-builder.js new file mode 100644 index 0000000..a197c19 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-arcade-see-all-games-shelf-builder.js @@ -0,0 +1,71 @@ +import * as arcadeCommon from "../../arcade/arcade-common"; +import * as color from "../../../foundation/util/color-util"; +import * as content from "../../content/content"; +import * as editorialDataUtil from "../editorial-data-util"; +import * as metricsHelpersImpressions from "../../metrics/helpers/impressions"; +import * as metricsHelpersLocation from "../../metrics/helpers/location"; +import * as models from "../../../api/models"; +import * as serverData from "../../../foundation/json-parsing/server-data"; +import * as gamesComponentBuilder from "../../../gameservicesui/src/editorial-page/editorial-component-builder"; +export function buildArcadeSeeAllGamesShelf(objectGraph, shelfToken) { + const footer = new models.ArcadeFooter(); + const shelf = new models.Shelf("arcadeFooter"); + shelf.items = [footer]; + const impressionOptions = { + targetType: "arcadeSeeAllGamesFooter", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + title: objectGraph.loc.string("Arcade.SeeAllGames.Button.Title"), + id: shelfToken.id, + kind: "footer", + softwareType: "Arcade", + }; + metricsHelpersImpressions.addImpressionFields(objectGraph, footer, impressionOptions); + metricsHelpersLocation.pushContentLocation(objectGraph, impressionOptions, impressionOptions.title); + if (preprocessor.GAMES_TARGET) { + footer.buttonAction = gamesComponentBuilder.makeArcadeSeeAllAction(objectGraph); + } + else { + footer.buttonAction = arcadeCommon.seeAllArcadeGamesPageFlowAction(objectGraph, "releaseDate", shelfToken.metricsPageInformation, shelfToken.metricsLocationTracker); + } + const buttonImpressionOptions = { + targetType: "button", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + title: footer.buttonAction.title, + id: "SeeAllGames", + kind: "button", + softwareType: "Arcade", + }; + metricsHelpersImpressions.addImpressionFields(objectGraph, footer.buttonAction, buttonImpressionOptions); + metricsHelpersLocation.popLocation(impressionOptions.locationTracker); + const termsAndConditionsUrl = objectGraph.bag.termsAndConditionsURL; + const shouldAddTermsAndConditions = !serverData.isNull(termsAndConditionsUrl) && objectGraph.client.deviceType !== "tv"; + if (shouldAddTermsAndConditions) { + const termsAndConditionTitle = objectGraph.loc.string("TermsAndConditions.Title"); + const urlAction = new models.ExternalUrlAction(termsAndConditionsUrl); + const footnote = new models.Footnote(termsAndConditionTitle); + footnote.clickAction = urlAction; + footnote.presentationStyle = ["hasChevron", "textLightensOnHighlight", "hasSeparator"]; + footer.footnote = footnote; + } + shelf.background = { + type: "color", + color: color.named("placeholderBackground"), + }; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + if (serverData.isDefinedNonNullNonEmpty(shelfContents)) { + const metricsOptions = { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + }; + footer.icons = content.impressionableAppIconsFromDataCollection(objectGraph, shelfContents, metricsOptions, { + useCase: 2 /* content.ArtworkUseCase.LockupIconMedium */, + }); + } + else { + footer.icons = []; + } + return shelf; +} +//# sourceMappingURL=editorial-page-arcade-see-all-games-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-chart-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-chart-shelf-builder.js new file mode 100644 index 0000000..58e6862 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-chart-shelf-builder.js @@ -0,0 +1,106 @@ +import { isNothing, isSome } from "@jet/environment"; +import * as models from "../../../api/models"; +import { attributeAsString } from "../../../foundation/media/attributes"; +import { chartUrlFromData } from "../../content/content"; +import { addClickEventToSeeAllAction } from "../../metrics/helpers/clicks"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../placeholders/placeholders"; +import { CollectionShelfLayoutDirection } from "../editorial-page-types"; +import { createShelfTokenUrlIfNecessary } from "./editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common"; +import { buildLockupChartShelf, buildLockupSmallShelf, } from "./editorial-page-collection-shelf-builder/editorial-page-lockup-collection-shelf-builder"; +import { viewChartListActionWithGames } from "../../../gameservicesui/src/intent-controllers/page/charts-list-page-intent-controller"; +import * as editorialDataUtil from "../editorial-data-util"; +import { makeGamesFromCollection } from "../../../gameservicesui/src/models/cards/collection-card"; +export function buildChartShelf(objectGraph, shelfToken) { + var _a; + shelfToken.showOrdinals = true; + let shelf; + if (preprocessor.GAMES_TARGET) { + shelf = buildLockupChartShelf(objectGraph, shelfToken); + } + else { + /// Currently the charts shelf doesn't return a `displayStyle`, we only support LockupSmall. + shelf = buildLockupSmallShelf(objectGraph, shelfToken, false, CollectionShelfLayoutDirection.Horizontal); + } + if (isNothing(shelf)) { + return undefined; + } + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + if (preprocessor.GAMES_TARGET) { + if (isSome(shelf.header)) { + shelf.header.titleAction = (_a = chartPageSeeAllActionForGames(objectGraph, shelfToken)) !== null && _a !== void 0 ? _a : undefined; + } + else { + shelf.seeAllAction = chartPageSeeAllActionForGames(objectGraph, shelfToken); + } + shelf.id = `shelf_${shelfToken.id}`; + } + else { + replaceShelfSeeAllAction(objectGraph, shelf, chartPageSeeAllAction(objectGraph, shelfToken)); + } + return shelf; +} +function chartPageSeeAllActionForGames(objectGraph, shelfToken) { + var _a; + const gamesData = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + const games = makeGamesFromCollection(objectGraph, gamesData, {}, {}); + const genre = attributeAsString(shelfToken.data, "genre"); + const chart = attributeAsString(shelfToken.data, "chart"); + if (isSome(games) && isSome(genre) && isSome(chart)) { + const chartUrl = chartUrlFromData(objectGraph, genre, chart); + return viewChartListActionWithGames(games, shelfToken.title, (_a = shelfToken.subtitle) !== null && _a !== void 0 ? _a : "", chartUrl, shelfToken.data.id, // TODO: provide real `reco_id` rdar://133659618 ([Play Now Feed] Use metrics.meta.reco_id from shelf meta in metrics) + objectGraph); + } + return null; +} +function chartPageSeeAllAction(objectGraph, shelfToken) { + const genre = attributeAsString(shelfToken.data, "genre"); + const chart = attributeAsString(shelfToken.data, "chart"); + const action = new models.FlowAction("page"); + action.pageUrl = chartUrlFromData(objectGraph, genre, chart); + action.title = objectGraph.loc.string("ACTION_SEE_ALL"); + action.referrerUrl = shelfToken.metricsPageInformation.pageUrl; + addClickEventToSeeAllAction(objectGraph, action, action.pageUrl, { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + }); + return action; +} +/** + * Update the shelf header to use the provided seeAll action. + * @param objectGraph The App Store object graph used to check feature flags + * @param shelfHeader The shelf header to update + * @param seeAllAction The "See All" action to apply + */ +export function replaceShelfHeaderSeeAllAction(objectGraph, shelfHeader, seeAllAction) { + if (objectGraph.featureFlags.isEnabled("shelf_header")) { + // Modern headers make title tappable with a chevron (>). + shelfHeader.titleAction = seeAllAction; + } + else { + // Legacy headers show "See All" textual button on trailing edge. + shelfHeader.accessoryAction = seeAllAction; + } +} +/** + * Update the shelf header to use the provided seeAll action. + * @param objectGraph The App Store object graph used to check feature flags + * @param shelf The shelf whose header needs updating + * @param seeAllAction The see all action to apply + */ +export function replaceShelfSeeAllAction(objectGraph, shelf, seeAllAction) { + if (objectGraph.featureFlags.isEnabled("shelf_header")) { + if (isSome(shelf.header)) { + replaceShelfHeaderSeeAllAction(objectGraph, shelf.header, seeAllAction); + } + else { + shelf.header = { + titleAction: seeAllAction, + }; + } + } + else { + shelf.seeAllAction = seeAllAction; + } +} +//# sourceMappingURL=editorial-page-chart-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-breakout-large-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-breakout-large-collection-shelf-builder.js new file mode 100644 index 0000000..093336d --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-breakout-large-collection-shelf-builder.js @@ -0,0 +1,94 @@ +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 metricsHelpersImpressions from "../../../metrics/helpers/impressions"; +import * as editorialActionUtil from "../../editorial-action-util"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialComponentMediaUtil from "../../editorial-page-component-media-util"; +import * as editorialCopyUtil from "../../editorial-page-editorial-copy-util"; +import * as editorialOverlayContentUtil from "../../editorial-page-overlay-content-util"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import { deepLinkUrlFromData } from "../../../linking/external-deep-link"; +import { isMediaDark } from "../../editorial-media-util"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +export function buildBreakoutLargeShelf(objectGraph, shelfToken) { + const items = []; + const shelf = new models.Shelf("largeHeroBreakout"); + shelf.isHorizontal = mediaAttributes.attributeAsString(shelfToken.data, "layoutDirection") === "Horizontal"; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + const primaryItemData = editorialDataUtil.extractHydratedPrimaryContentData(objectGraph, itemData); + if ((editorialDataUtil.requiresPrimaryContent(objectGraph, itemData) && + !mediaAttributes.hasAttributes(primaryItemData)) || + shouldDefer(shelfToken)) { + shelfToken.isDeferring = true; + shelfToken.remainingItems.push(itemData); + continue; + } + const metricsOptions = { + targetType: "largeBreakout", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData), + }; + const editorialClientParams = editorialDataUtil.extractEditorialClientParams(objectGraph, itemData); + const hideEditorialMedia = serverData.asBooleanOrFalse(editorialClientParams.hideEditorialMedia); + const mediaData = !hideEditorialMedia + ? editorialComponentMediaUtil.editorialMediaDataFromData(objectGraph, itemData, shelfToken.collectionDisplayStyle) + : null; + const lockupOptions = { + metricsOptions, + clientIdentifierOverride: shelfToken.clientIdentifierOverride, + artworkUseCase: 0 /* content.ArtworkUseCase.Default */, + offerEnvironment: "lightOverArtwork", + canDisplayArcadeOfferButton: true, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, itemData), + }; + const overlayContent = editorialOverlayContentUtil.extractOverlayContent(objectGraph, itemData, lockupOptions); + if (serverData.isNullOrEmpty(mediaData) && serverData.isNullOrEmpty(overlayContent.collectionIcons)) { + continue; + } + const badgeText = editorialCopyUtil.editorialBadgeFromData(objectGraph, itemData, shelfToken.collectionDisplayStyle); + const badgeType = serverData.isDefinedNonNull(badgeText) + ? { type: "text", title: badgeText } + : { type: "none", title: null }; + const largeBreakoutDetails = new models.BreakoutDetails(editorialCopyUtil.editorialTitleFromData(objectGraph, itemData, shelfToken.collectionDisplayStyle), editorialCopyUtil.editorialDescriptionFromData(objectGraph, itemData, true), badgeType, null); + const largeBreakout = new models.LargeHeroBreakout(largeBreakoutDetails, { position: "leading", wantsBlur: true }, null, mediaData === null || mediaData === void 0 ? void 0 : mediaData.artwork, mediaData === null || mediaData === void 0 ? void 0 : mediaData.video, overlayContent.collectionIcons, mediaData === null || mediaData === void 0 ? void 0 : mediaData.backgroundColor); + largeBreakout.rtlArtwork = mediaData === null || mediaData === void 0 ? void 0 : mediaData.rtlArtwork; + largeBreakout.rtlVideo = mediaData === null || mediaData === void 0 ? void 0 : mediaData.rtlVideo; + largeBreakout.rtlBackgroundColor = mediaData === null || mediaData === void 0 ? void 0 : mediaData.rtlBackgroundColor; + // Configure impressions + const contentMetricsOptions = { + ...metricsOptions, + id: itemData.id, + idType: "its_contentId", + }; + const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, itemData, largeBreakout.details.title, contentMetricsOptions); + metricsHelpersImpressions.addImpressionFields(objectGraph, largeBreakout, impressionOptions); + const breakoutAction = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken); + if (serverData.isDefinedNonNull(breakoutAction)) { + breakoutAction.title = editorialCopyUtil.editorialCallToActionFromData(objectGraph, itemData); + } + largeBreakout.details.callToActionButtonAction = breakoutAction; + largeBreakout.clickAction = breakoutAction; + largeBreakout.editorialDisplayOptions = + editorialDataUtil.editorialDisplayOptionsFromClientParams(editorialClientParams); + largeBreakout.lockup = overlayContent.lockup; + largeBreakout.isMediaDark = isMediaDark(objectGraph, mediaData); + largeBreakout.isRTLMediaDark = isMediaDark(objectGraph, mediaData, true); + items.push(largeBreakout); + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + shelf.items = items; + shelf.rowsPerColumn = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount"); + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + return shelf; +} +//# sourceMappingURL=editorial-page-breakout-large-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-brick-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-brick-collection-shelf-builder.js new file mode 100644 index 0000000..cefe63e --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-brick-collection-shelf-builder.js @@ -0,0 +1,146 @@ +import { isNothing, isSome } from "@jet/environment/types/optional"; +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 content from "../../../content/content"; +import * as metricsHelpersImpressions from "../../../metrics/helpers/impressions"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import * as editorialActionUtil from "../../editorial-action-util"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialMediaUtil from "../../editorial-page-component-media-util"; +import * as editorialCopyUtil from "../../editorial-page-editorial-copy-util"; +import { CollectionShelfDisplayStyle } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import { deepLinkUrlFromData } from "../../../linking/external-deep-link"; +import { isMediaDark } from "../../editorial-media-util"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +import { convertToShelfModel, makeShelfId, } from "../../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import { createSmallBrickFromData } from "../../../../gameservicesui/src/models/cards/small-brick"; +export function buildBrickSmallShelf(objectGraph, shelfToken) { + return buildBrickShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.BrickSmall, "smallBrick"); +} +export function buildBrickMediumShelf(objectGraph, shelfToken) { + return buildBrickShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.BrickMedium, "brick"); +} +export function buildBrickLargeShelf(objectGraph, shelfToken) { + return buildBrickShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.BrickLarge, "largeBrick"); +} +// region Brick Creation +function buildBrickShelf(objectGraph, shelfToken, displayStyle, brickComponentType) { + const items = []; + const shelf = new models.Shelf(brickComponentType); + shelf.isHorizontal = mediaAttributes.attributeAsString(shelfToken.data, "layoutDirection") === "Horizontal"; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + const metricsOptions = { + ...shelfToken.metricsImpressionOptions, + targetType: editorialActionUtil.clickTargetForCollectionDisplayStyle(objectGraph, displayStyle), + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData), + }; + if (!itemData.attributes || shouldDefer(shelfToken)) { + shelfToken.remainingItems.push(itemData); + shelfToken.isDeferring = true; + continue; + } + if (preprocessor.GAMES_TARGET && displayStyle === CollectionShelfDisplayStyle.BrickSmall) { + const clickAction = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken); + const smallBrick = createSmallBrickFromData(objectGraph, itemData, makeShelfId(shelfToken), clickAction, {}, {}, true); + if (isNothing(smallBrick)) { + continue; + } + items.push(convertToShelfModel(smallBrick)); + } + else { + const brick = buildBrick(objectGraph, itemData, shelfToken.collectionDisplayStyle, metricsOptions, metricsOptions, shelfToken.clientIdentifierOverride); + brick.clickAction = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken); + if (!brick.isValid()) { + continue; + } + items.push(brick); + } + metricsHelpersLocation.nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + } + if (serverData.isDefinedNonNull(shelfToken.presentationHints)) { + shelf.presentationHints = shelfToken.presentationHints; + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + shelf.items = items; + shelf.rowsPerColumn = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount"); + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + return shelf; +} +/** + * Creates a Brick from the input data. + * Note: the clickAction will need to be assigned post-creation. + * + * @param objectGraph Current object graph + * @param data The data for the Brick + * @param collectionDisplayStyle The desired display style for the brick + * @param metricsOptions Metrics options for impressions + * @param lockupMetricsOptions Metrics options for the collection icon lockups + * @param clientIdentifierOverride Any preferred client identifier override + * @returns A built Brick object + */ +export function buildBrick(objectGraph, data, collectionDisplayStyle, metricsOptions, lockupMetricsOptions, clientIdentifierOverride) { + const brick = new models.Brick(); + const editorialClientParams = editorialDataUtil.extractEditorialClientParams(objectGraph, data); + const hideEditorialMedia = serverData.asBooleanOrFalse(editorialClientParams.hideEditorialMedia); + if (!hideEditorialMedia) { + const editorialMediaData = editorialMediaUtil.editorialMediaDataFromData(objectGraph, data, collectionDisplayStyle); + if (isSome(editorialMediaData === null || editorialMediaData === void 0 ? void 0 : editorialMediaData.artwork)) { + brick.artworks = [editorialMediaData.artwork]; + brick.isMediaDark = isMediaDark(objectGraph, editorialMediaData); + } + if (isSome(editorialMediaData === null || editorialMediaData === void 0 ? void 0 : editorialMediaData.rtlArtwork)) { + brick.rtlArtwork = editorialMediaData === null || editorialMediaData === void 0 ? void 0 : editorialMediaData.rtlArtwork; + brick.isRTLMediaDark = isMediaDark(objectGraph, editorialMediaData, true); + } + } + const lockupOptions = { + metricsOptions: lockupMetricsOptions, + clientIdentifierOverride: clientIdentifierOverride, + artworkUseCase: 0 /* content.ArtworkUseCase.Default */, + canDisplayArcadeOfferButton: true, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, data), + }; + metricsHelpersLocation.pushBasicLocation(objectGraph, lockupOptions.metricsOptions, "collectionIcons"); + brick.collectionIcons = editorialMediaUtil.editorialFallbackAppIconsFromData(objectGraph, data, lockupOptions); + metricsHelpersLocation.popLocation(lockupOptions.metricsOptions.locationTracker); + if (serverData.isNullOrEmpty(brick.collectionIcons)) { + const primaryAppIcon = content.iconFromData(objectGraph, data, { + useCase: 0 /* content.ArtworkUseCase.Default */, + }); + if (serverData.isDefinedNonNullNonEmpty(primaryAppIcon)) { + brick.collectionIcons = [primaryAppIcon]; + } + } + brick.caption = editorialCopyUtil.editorialBadgeFromData(objectGraph, data, collectionDisplayStyle); + brick.title = editorialCopyUtil.editorialTitleFromData(objectGraph, data, collectionDisplayStyle); + brick.subtitle = editorialCopyUtil.editorialDescriptionFromData(objectGraph, data); + brick.accessibilityLabel = brick.title; + brick.editorialDisplayOptions = editorialDataUtil.editorialDisplayOptionsFromClientParams(editorialClientParams); + // Configure impressions + const metricsIdType = serverData.isDefinedNonNullNonEmpty(brick.artworks) + ? "its_contentId" + : "collection_id"; + const contentMetricsOptions = { + ...metricsOptions, + id: data.id, + idType: metricsIdType, + }; + const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, data, brick.title, contentMetricsOptions); + metricsHelpersImpressions.addImpressionFields(objectGraph, brick, impressionOptions); + // Safe area + brick.artworkSafeArea = models.ChartOrCategorySafeArea.defaultTileArtworkSafeArea; + brick.textSafeArea = models.ChartOrCategorySafeArea.defaultTileTextSafeArea; + return brick; +} +// endregion +//# sourceMappingURL=editorial-page-brick-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common.js new file mode 100644 index 0000000..5af39c4 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common.js @@ -0,0 +1,248 @@ +import { buildEditorialShelf } from ".."; +import * as models from "../../../../api/models"; +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import { Parameters, Path, Protocol } from "../../../../foundation/network/url-constants"; +import * as urls from "../../../../foundation/network/urls"; +import * as mediaUrlMapping from "../../../builders/url-mapping"; +import * as metricsHelpersClicks from "../../../metrics/helpers/clicks"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import { createLocationTrackerCopy, setCurrentPosition } from "../../../metrics/helpers/location"; +import * as placeholders from "../../../placeholders/placeholders"; +import { createBaseShelfToken } from "../../editorial-page-shelf-token"; +import { collectionDisplayStyleOverride, CollectionShelfDisplayStyle, CollectionShelfFilterOverride, EditorialShelfType, } from "../../editorial-page-types"; +import { isNothing, isSome } from "@jet/environment"; +import * as gamesComponentBuilder from "../../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import { makeEditorialShelfCollectionPageIntent } from "../../../../api/intents/editorial/editorial-shelf-collection-page-intent"; +import { makeEditorialShelfCollectionPageURL } from "../../editorial-shelf-collection-page-utils"; +import { getLocale } from "../../../locale"; +import { getPlatform } from "../../../preview-platform"; +import { collectionShelfDisplayStyleFromShelfData } from "../../editorial-data-util"; +// region Shelf Tokens +/** + * Whether we should defer building the rest of a shelf given a shelf token + * @param token + */ +export function shouldDefer(token) { + return token && token.isDeferring && token.isFirstRender; +} +// endregion +// region Shelf Urls +/** + * Configure `url` on a standard editorial page shelf if it needs to fetch more content. + * @param objectGraph + * @param shelf The shelf we'll be adding the url to + * @param shelfToken Token to encode in URL for subsequent fetch. + */ +export function createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken) { + if (serverData.isNullOrEmpty(shelfToken)) { + return null; + } + if (objectGraph.client.isWeb) { + return null; + } + const shouldAddFirstRenderUrl = shelfToken.remainingItems.length || shelfToken.recommendationsHref || shelfToken.onDeviceRecommendationsUseCase; + if (shouldAddFirstRenderUrl && shelfToken.isFirstRender) { + return editorialPageShelfUrl(shelfToken); + } + else { + return null; + } +} +/** + * Updates a shelf URL based on the provided token. + * @param objectGraph Current object graph + * @param shelf Shelf to add url to. + * @param token Token to encode in the url. + */ +function updateShelfTokenUrlWithNewShelfToken(objectGraph, shelf, shelfToken) { + const originalShelfUrl = urls.URL.from(shelf.url); + const updatedUrl = urls.URL.from(createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken)); + // Add missing query params to the updated URL from the original. + for (const key of Object.keys(originalShelfUrl.query)) { + if (serverData.isNull(updatedUrl.query[key])) { + updatedUrl.query[key] = originalShelfUrl.query[key]; + } + } + // Finally, update the shelf's URL. + shelf.url = updatedUrl.build(); +} +/** + * Stores the impression metrics for a placeholder shelf in the shelf token. + * @param objectGraph Current object graph + * @param shelf The shelf + * @param shelfToken The shelf token + */ +export function storePlaceholderShelfImpressionMetrics(objectGraph, shelf, shelfToken) { + if (isNothing(shelf.url) || isNothing(shelf.impressionMetrics) || !shelfToken.showingPlaceholders) { + return; + } + const originalShelfUrlString = shelf.url; + try { + // Extract the token from the URL. + // Note: Although we have access to the shelfToken here, we do not know that + // the url was constructed from token in its current state. To be safe, + // if not efficient, we reverse engineer the URL to get the token. + const originalShelfUrl = urls.URL.from(originalShelfUrlString); + const encodedToken = originalShelfUrl.query[Parameters.token]; + const shelfTokenFromUrl = JSON.parse(decodeURIComponent(encodedToken)); + // Modify the token to include the impressions metrics. + shelfTokenFromUrl.originalPlaceholderShelfImpressionMetrics = shelf.impressionMetrics; + updateShelfTokenUrlWithNewShelfToken(objectGraph, shelf, shelfTokenFromUrl); + } + catch { + shelf.url = originalShelfUrlString; + } +} +/** + * // Merge the original impression metrics with the newly created impression metrics. + * @param objectGraph Current object graph + * @param shelf The hydrated shelf + * @param shelfToken The shelf token + */ +export function mergeShelfImpressionMetricsWithPlaceholders(objectGraph, shelf, shelfToken) { + if (serverData.isNullOrEmpty(shelfToken.originalPlaceholderShelfImpressionMetrics)) { + return; + } + // If the `shelf.impressionMetrics` is null, we just defer to the original metrics. + if (serverData.isNull(shelf.impressionMetrics)) { + shelf.impressionMetrics = shelfToken.originalPlaceholderShelfImpressionMetrics; + } + else { + for (const key in shelfToken.originalPlaceholderShelfImpressionMetrics.fields) { + if (Object.prototype.hasOwnProperty.call(shelfToken.originalPlaceholderShelfImpressionMetrics.fields, key)) { + shelf.impressionMetrics.fields[key] = shelfToken.originalPlaceholderShelfImpressionMetrics.fields[key]; + } + } + } +} +/** + * Configure `url` on a standard editorial page shelf if it needs to fetch more content. + * @param objectGraph + * @param shelf The shelf we'll be adding the url to + * @param shelfToken Token to encode in URL for subsequent fetch. + */ +export function createShelfSeeAllActionIfNecessary(objectGraph, shelf, shelfToken) { + if (serverData.isNullOrEmpty(shelfToken) || serverData.isNullOrEmpty(shelf)) { + return null; + } + if (shouldShowSeeAll(shelfToken)) { + const action = new models.FlowAction("page"); + // The web client makes a separate request for See All pages, so we don't sidepack for web. + if (!placeholders.isPlaceholderShelf(shelf) && !objectGraph.client.isWeb) { + const contentShelfId = `shelf_${shelfToken.id}`; + action.pageData = createSeeAllPage(objectGraph, shelfToken, shelf.contentType, contentShelfId, isSome(shelfToken.recommendationsHref)); + } + const additionalPageUrlQueryParams = {}; + if (shelfToken.type === EditorialShelfType.Recommendations) { + additionalPageUrlQueryParams[Parameters.editorialPageId] = shelfToken.pageId; + } + if (objectGraph.client.isWeb) { + const destinationIntent = makeEditorialShelfCollectionPageIntent({ + ...getLocale(objectGraph), + ...getPlatform(objectGraph), + id: shelfToken.id, + }); + action.destination = destinationIntent; + action.pageUrl = makeEditorialShelfCollectionPageURL(objectGraph, destinationIntent); + } + else { + action.pageUrl = mediaUrlMapping.hrefToRoutableUrl(objectGraph, shelfToken.data.href, additionalPageUrlQueryParams); + } + action.title = objectGraph.loc.string("ACTION_SEE_ALL"); + action.referrerUrl = shelfToken.metricsPageInformation.pageUrl; + // This can be called after we've gone through and added items to a shelf, meaning the locationPosition + // would have been incremented to the number of shelf items, the see all should always have a position of + // 0 so we reset it here and use that, without mucking with the active location tracker. + const resetLocationTracker = createLocationTrackerCopy(shelfToken.metricsLocationTracker); + setCurrentPosition(resetLocationTracker, 0); + metricsHelpersClicks.addClickEventToSeeAllAction(objectGraph, action, shelfToken.seeAllUrl, { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: resetLocationTracker, + }); + return action; + } + else { + return null; + } +} +/** + * Determine whether lockup shelves should show "See All" on given platforms. + * + * @param shelfToken Token to encode in URL for subsequent fetch. + * @return Whether or not a lockup shelf with given properties should have a "See All" action. + */ +export function shouldShowSeeAll(shelfToken) { + if (shelfToken.isSeeAll) { + return false; + } + switch (shelfToken.collectionDisplayStyle) { + case CollectionShelfDisplayStyle.BreakoutLarge: + case CollectionShelfDisplayStyle.Poster: + return false; + default: + break; + } + // On all other platforms, we always to attach "See All", except AppStore_ComingSoon, + // which should not because the see all page won't drop lockups whose pre-order has + // been released (which the AppStore_ComingSoon swoosh will). + // + // The Games app is able to show the see all irrespective of the preorder flag. + return (!shelfToken.filterOverrides.includes(CollectionShelfFilterOverride.ShowOnlyPreorder) || + preprocessor.GAMES_TARGET); +} +/** + * Returns the URL schema for editorial page shelves that may need to fetch additional content. + * Editorial-Page-Related builders can extend on this scheme if needed, e.g. query param on Continue Playing shelves. + * @param shelfToken Token to encode in URL for subsequent fetch. + * @param parseContext + */ +export function editorialPageShelfUrl(shelfToken) { + const shelfUrl = new urls.URL() + .set("protocol", Protocol.internal) + .append("pathname", Path.editorialPage) + .append("pathname", Path.shelf) + .param(Parameters.token, encodeURIComponent(JSON.stringify(shelfToken))); + return shelfUrl.build(); +} +/** + * Creates a page that can be used for side-packing see all pages into a room. + * + * @param objectGraph + * @param {EditorialPageShelfToken} shelfToken The shelf token used to build the original shelf + * @param {ShelfContentType} preferredShelfContentType The content type to use for the page + * @param {string} parentShelfId The ID of the parent shelf that the contains the sidepack items + * @returns {GenericPage} A GenericPage which will use the parentShelfItems from the see all to render the initial room + */ +export function createSeeAllPage(objectGraph, shelfToken, preferredShelfContentType, parentShelfId, isComplete) { + // Create a new shelf token with a new location tracker in order to get accurate metrics for the items in the shelf. + const newLocationTracker = metricsHelpersLocation.newLocationTracker(); + const collectionDisplayStyle = collectionShelfDisplayStyleFromShelfData(objectGraph, shelfToken.data); + const newToken = createBaseShelfToken(objectGraph, shelfToken.pageId, shelfToken.data, shelfToken.isArcadePage, shelfToken.shelfIndex, shelfToken.metricsPageInformation, newLocationTracker, true, collectionDisplayStyleOverride(collectionDisplayStyle)); + const contentShelf = buildEditorialShelf(objectGraph, undefined, newToken); + if (contentShelf === null) { + return null; + } + contentShelf.title = null; + contentShelf.eyebrow = null; + contentShelf.isHorizontal = false; + contentShelf.id = parentShelfId; + let pageHeader; + if (preprocessor.GAMES_TARGET) { + pageHeader = gamesComponentBuilder.makeGamesPageHeader(shelfToken, shelfToken.title, contentShelf.items, shelfToken.subtitle); + } + else { + pageHeader = new models.PageHeader(null, shelfToken.title, null); + } + const headerShelf = new models.Shelf("pageHeader"); + headerShelf.id = "shelf_page_header"; + headerShelf.items = [pageHeader]; + const shelves = [headerShelf, contentShelf]; + const page = new models.GenericPage(shelves); + page.isIncomplete = !(isComplete !== null && isComplete !== void 0 ? isComplete : false); + if (isNothing(page.pageMetrics.pageFields)) { + page.pageMetrics.pageFields = {}; + } + return page; +} +// endregion +//# sourceMappingURL=editorial-page-collection-shelf-common.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-hero-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-hero-collection-shelf-builder.js new file mode 100644 index 0000000..adc7087 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-hero-collection-shelf-builder.js @@ -0,0 +1,137 @@ +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 { shallowCopyOf } from "../../../../foundation/util/objects"; +import * as breakoutsCommon from "../../../arcade/breakouts-common"; +import * as contentAttributes from "../../../content/attributes"; +import * as metricsHelpersImpressions from "../../../metrics/helpers/impressions"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import * as article from "../../../today/article"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialMediaUtil from "../../editorial-media-util"; +import { editorialTitleFromData } from "../../editorial-page-editorial-copy-util"; +import { heroOverlayFromData } from "../../editorial-page-hero-util"; +import * as editorialOverlayContentUtil from "../../editorial-page-overlay-content-util"; +import { CollectionShelfDisplayStyle } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +export function buildHeroShelf(objectGraph, shelfToken) { + if (shelfToken.shelfIndex !== 0) { + return null; + } + const shelf = new models.Shelf("heroCarousel"); + const heroCarousel = new models.HeroCarousel(); + heroCarousel.autoScrollConfiguration = heroAutoscrollConfiguration(objectGraph); + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + const primaryItemData = editorialDataUtil.extractHydratedPrimaryContentData(objectGraph, itemData); + if ((editorialDataUtil.requiresPrimaryContent(objectGraph, itemData) && + !mediaAttributes.hasAttributes(primaryItemData)) || + shouldDefer(shelfToken)) { + shelfToken.isDeferring = true; + shelfToken.remainingItems.push(itemData); + continue; + } + const heroCarouselItemMetricsOptions = { + ...shelfToken.metricsImpressionOptions, + idType: "its_contentId", + targetType: "hero", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData), + }; + const heroMediaData = editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, itemData, editorialMediaUtil.EditorialMediaPlacement.Hero); + const lockupOptions = { + metricsOptions: heroCarouselItemMetricsOptions, + clientIdentifierOverride: shelfToken.clientIdentifierOverride, + artworkUseCase: 0 /* content.ArtworkUseCase.Default */, + offerEnvironment: "lightOverArtwork", + canDisplayArcadeOfferButton: true, + }; + const overlayContent = editorialOverlayContentUtil.extractOverlayContent(objectGraph, itemData, lockupOptions); + const heroCarouselItem = new models.HeroCarouselItem(); + const productData = article.productDataFromArticle(objectGraph, itemData); + const metricsTitle = editorialTitleFromData(objectGraph, itemData, CollectionShelfDisplayStyle.Hero); + const heroCarouselItemImpressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, itemData, metricsTitle, heroCarouselItemMetricsOptions); + heroCarouselItemImpressionOptions.isPreorder = contentAttributes.contentAttributeAsBooleanOrFalse(objectGraph, productData, "isPreorder"); + metricsHelpersImpressions.addImpressionFields(objectGraph, heroCarouselItem, heroCarouselItemImpressionOptions); + // Push the heroCarouselItem here so that the click action has the item 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 + // actiono + // <rdar://problem/60883269> Metrics: Arcade: Container values requested in Location field + metricsHelpersLocation.pushContentLocation(objectGraph, heroCarouselItemImpressionOptions, metricsTitle); + const editorialClientParams = editorialDataUtil.extractEditorialClientParams(objectGraph, itemData); + const hideEditorialMedia = serverData.asBooleanOrFalse(editorialClientParams.hideEditorialMedia); + heroCarouselItem.overlay = heroOverlayFromData(objectGraph, itemData, shelfToken, editorialClientParams); + heroCarouselItem.collectionIcons = overlayContent.collectionIcons; + heroCarouselItem.editorialDisplayOptions = + editorialDataUtil.editorialDisplayOptionsFromClientParams(editorialClientParams); + populateHeroCarouselItemMedia(objectGraph, heroCarouselItem, hideEditorialMedia, heroMediaData, false); + if (heroCarouselItem.isValid()) { + heroCarousel.items.push(heroCarouselItem); + } + const rtlHeroCarouselItem = shallowCopyOf(heroCarouselItem); + populateHeroCarouselItemMedia(objectGraph, rtlHeroCarouselItem, hideEditorialMedia, heroMediaData, true); + if (rtlHeroCarouselItem.isValid()) { + heroCarousel.rtlItems.push(rtlHeroCarouselItem); + } + metricsHelpersLocation.popLocation(heroCarouselItemImpressionOptions.locationTracker); + metricsHelpersLocation.nextPosition(heroCarouselItemImpressionOptions.locationTracker); + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.isHorizontal = false; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + shelf.items = [heroCarousel]; + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + return shelf; +} +/** + * Populates the media properties of a `HeroCarouselItem`. + * @param objectGraph Current object graph + * @param heroCarouselItem The item to populate + * @param hideEditorialMedia Whether to hide editorial media + * @param heroMediaData The `EditorialMediaData` to derive the media properties from + * @param isRTL Whether this item will be used in an RTL layout + */ +function populateHeroCarouselItemMedia(objectGraph, heroCarouselItem, hideEditorialMedia, heroMediaData, isRTL) { + if (!hideEditorialMedia) { + const backgroundColor = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlBackgroundColor : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.backgroundColor; + heroCarouselItem.backgroundColor = backgroundColor; + const artworkData = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlArtworkData : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.artworkData; + if (!objectGraph.client.isMac || objectGraph.props.isNotEnabled("macOSArcadeHeaderUpdates")) { + heroCarouselItem.titleEffect = breakoutsCommon.titleEffectFromArtwork(objectGraph, artworkData); + } + const artwork = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlArtwork : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.artwork; + heroCarouselItem.artwork = artwork; + const video = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlVideo : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.video; + heroCarouselItem.video = video; + } + heroCarouselItem.isMediaDark = editorialMediaUtil.isMediaDark(objectGraph, heroMediaData, isRTL); +} +/** + * Generates the auto scroll configuration for the hero carousel + * @param objectGraph Current object graph + * @returns Built auto scroll configuration + */ +export function heroAutoscrollConfiguration(objectGraph) { + return { + isAutoScrollEnabled: objectGraph.bag.heroCarouselAutoScrollDuration > 0.0, + autoScrollInterval: objectGraph.bag.heroCarouselAutoScrollDuration, + }; +} +/** + * Decorates the input shelf metrics options with shelf specific fields. + * @param objectGraph Current object graph + * @param shelfMetricsOptions Base shelf metrics options + * @returns Decorated shelf metrics options + */ +export function decorateHeroShelfMetricsOptions(objectGraph, shelfMetricsOptions) { + shelfMetricsOptions.title = "heroCarousel"; + const autoScrollConfiguration = heroAutoscrollConfiguration(objectGraph); + shelfMetricsOptions.autoAdvanceInterval = autoScrollConfiguration.autoScrollInterval; +} +//# sourceMappingURL=editorial-page-hero-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-lockup-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-lockup-collection-shelf-builder.js new file mode 100644 index 0000000..12525c4 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-lockup-collection-shelf-builder.js @@ -0,0 +1,193 @@ +import { isSome } from "@jet/environment"; +import * as models from "../../../../api/models"; +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../../../foundation/media/attributes"; +import * as filtering from "../../../filtering"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +import * as editorialDataUtil from "../../editorial-data-util"; +import { lockupFromData } from "../../editorial-page-lockup-utils"; +import { CollectionShelfDisplayStyle, CollectionShelfFilterOverride, collectionShelfLayoutDirection, CollectionShelfLayoutDirection, displayLimitForCollectionShelf, } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import * as gamesComponentBuilder from "../../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import * as charts from "../../../../gameservicesui/src/utility/charts"; +import { arcadeColor } from "../../../arcade/arcade-common"; +import { artworkTemplateForBundleImage, createArtworkForResource } from "../../../content/artwork/artwork"; +export function buildEditorialLockupHierarchicalPortrait(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupHierarchicalPortrait, "mediumImageLockup", true, CollectionShelfLayoutDirection.Vertical); +} +export function buildEditorialLockupHierarchicalRows(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupHierarchicalRows, "mediumImageLockup", true, CollectionShelfLayoutDirection.Vertical); +} +export function buildEditorialLockupMediumShelf(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupMedium, "mediumImageLockup"); +} +export function buildEditorialLockupMediumVariantShelf(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupMediumVariant, "mediumImageLockup"); +} +export function buildEditorialLockupLargeShelf(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupLarge, "largeImageLockup"); +} +export function buildEditorialLockupLargeVariantShelf(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.EditorialLockupLargeVariant, "largeImageLockup"); +} +export function buildLockupChartShelf(objectGraph, shelfToken) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.Charts, shelfToken.isSeeAll ? "smallLockup" : "mediumImageLockup", true, CollectionShelfLayoutDirection.Vertical); +} +export function buildLockupMedium(objectGraph, shelfToken) { + shelfToken.metricsImpressionOptions.shouldOmitImpressionIndex = true; + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.LockupMedium, "mediumLockup"); +} +export function buildLockupSmallShelf(objectGraph, shelfToken, insertPlaceholdersIfRequired = true, overrideShelfLayoutDirection) { + if (objectGraph.featureFlags.isEnabled("force_display_lockup_ordinals")) { + // For 2023F Charts testing before server is ready. Can be removed in the 2024A timeline. + shelfToken.showOrdinals = true; + } + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.LockupSmall, "smallLockup", insertPlaceholdersIfRequired, overrideShelfLayoutDirection); +} +export function buildLockupLargeShelf(objectGraph, shelfToken, insertPlaceholdersIfRequired = true) { + return buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.LockupLarge, "largeLockup", insertPlaceholdersIfRequired); +} +export function buildEditorialLockupPosterShelf(objectGraph, shelfToken) { + const shelf = buildLockupShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.Poster, "posterLockup"); + if (isSome(shelf)) { + shelf.horizontalScrollTargetBehavior = models.ShelfHorizontalScrollTargetBehavior.CenterAligned; + } + return shelf; +} +// region Lockup Creation +function buildLockupShelf(objectGraph, shelfToken, displayStyle, lockupComponentType, insertPlaceholdersIfRequired = true, overrideShelfLayoutDirection) { + const items = []; + const shelf = new models.Shelf(lockupComponentType); + const layoutDirection = overrideShelfLayoutDirection !== null && overrideShelfLayoutDirection !== void 0 ? overrideShelfLayoutDirection : collectionShelfLayoutDirection(shelfToken); + shelf.isHorizontal = layoutDirection === CollectionShelfLayoutDirection.Horizontal; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + const displayLimit = displayLimitForCollectionShelf(displayStyle, layoutDirection, shelfToken); + for (const [index, itemData] of shelfContents.entries()) { + // If we encounter a type of app-events, this means they have been incorrectly programmed, + // and we should throw the shelf away. + if (itemData.type === "app-events") { + return null; + } + if (serverData.isNull(itemData.attributes) || shouldDefer(shelfToken)) { + shelfToken.isDeferring = true; + shelfToken.remainingItems.push(itemData); + continue; + } + // Filter out unwanted content + if (filtering.shouldFilter(objectGraph, itemData, 80894 /* filtering.Filter.All */)) { + continue; + } + let lockup = null; + if (preprocessor.GAMES_TARGET && gamesComponentBuilder.shouldUseChartCard(displayStyle, shelfToken)) { + lockup = gamesComponentBuilder.makeChartCard(objectGraph, itemData, shelfToken, index, "Editorial"); + } + else if (preprocessor.GAMES_TARGET && gamesComponentBuilder.shouldUseMediaCard(displayStyle)) { + lockup = gamesComponentBuilder.makeEditorialMediaCard(objectGraph, itemData, "Card", shelfToken, "Editorial"); + } + else if (preprocessor.GAMES_TARGET && gamesComponentBuilder.shouldUseGameLockup(displayStyle)) { + lockup = gamesComponentBuilder.makeGameLockupShelfModel(objectGraph, itemData, shelfToken); + } + else { + lockup = lockupFromData(objectGraph, itemData, shelfToken, items.length, displayStyle); + } + if (lockup) { + items.push(lockup); + metricsHelpersLocation.nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + shelfToken.ordinalIndex++; + if (items.length === displayLimit) { + break; + } + } + } + if (displayStyle === CollectionShelfDisplayStyle.EditorialLockupMediumVariant || + displayStyle === CollectionShelfDisplayStyle.EditorialLockupLargeVariant) { + if (serverData.isNull(shelf.presentationHints)) { + shelf.presentationHints = { showSupplementaryText: true }; + } + else { + shelf.presentationHints = { + ...shelf.presentationHints, + showSupplementaryText: true, + }; + } + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + // Hydrate Games data if the eyebrow has not already been populated from the shelf token. + if (preprocessor.GAMES_TARGET && shelf.eyebrow == null && shelf.eyebrowArtwork == null) { + populateGamesHeaderContent(shelf, shelfToken, objectGraph); + } + if (preprocessor.GAMES_TARGET && + gamesComponentBuilder.shouldUseComponentGrid(displayStyle, layoutDirection, shelfToken)) { + const item = gamesComponentBuilder.makeComponentGrid(objectGraph, items, shelfToken, displayStyle); + shelf.items = isSome(item) ? [item] : []; + } + else { + shelf.items = items; + } + shelf.rowsPerColumn = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount"); + shelf.shouldFilterApps = !shelfToken.filterOverrides.includes(CollectionShelfFilterOverride.ShowInstalled); + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + if (insertPlaceholdersIfRequired) { + let placeholderDisplayLimit = displayLimit; + if (isSome(displayLimit) && + displayLimit > 4 && + (displayStyle === CollectionShelfDisplayStyle.Charts || + displayStyle === CollectionShelfDisplayStyle.EditorialLockupMedium)) { + // TODO: Remove this override when this radar is complete: rdar://148395979 ([EditorialPage] Placeholders for Charts and 4UP are not rendering as a ComponentGrid) + placeholderDisplayLimit = 4; + } + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken, placeholderDisplayLimit); + } + return shelf; +} +/** + * Hydrates game related header data + * + * Note that both the header and non header fields should be hydrated, since header + * preference can be switched off. In this case we will not have the capacity to color the Arcade eyebrow + */ +function populateGamesHeaderContent(shelf, shelfToken, objectGraph) { + switch (serverData.asString(shelfToken.data.attributes, "chart")) { + case "combined-game-center" /* TopChartType.CombinedGameCenter */: + const gameCenterEyebrow = charts.makeChartsTopSubtitle("game-center", objectGraph); + const gameCenterEyebrowArtwork = createArtworkForResource(objectGraph, artworkTemplateForBundleImage("ProductCapabilityGameCenter")); + shelf.eyebrow = gameCenterEyebrow; + shelf.eyebrowArtwork = gameCenterEyebrowArtwork; + shelf.header = { + eyebrow: gameCenterEyebrow, + eyebrowArtwork: gameCenterEyebrowArtwork, + eyebrowArtworkSize: 14, + title: shelfToken.title, + subtitle: shelfToken.subtitle, + }; + break; + case "top-arcade" /* TopChartType.TopArcade */: + const color = arcadeColor; + const arcadeEyebrow = charts.makeChartsTopSubtitle("arcade", objectGraph); + shelf.eyebrow = arcadeEyebrow; + shelf.header = { + eyebrow: arcadeEyebrow, + title: shelfToken.title, + subtitle: shelfToken.subtitle, + configuration: { + eyebrowColor: { + type: "rgb", + red: color.red, + green: color.green, + blue: color.blue, + }, + }, + }; + break; + default: + break; + } +} +// endregion +//# sourceMappingURL=editorial-page-lockup-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-collection-shelf-builder.js new file mode 100644 index 0000000..3e78c25 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-collection-shelf-builder.js @@ -0,0 +1,70 @@ +import * as models from "../../../../api/models"; +import { isNull } from "../../../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../../../foundation/media/attributes"; +import * as mediaDataStructure from "../../../../foundation/media/data-structure"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +import { clickTargetForCollectionDisplayStyle } from "../../editorial-action-util"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialMediaUtil from "../../editorial-media-util"; +import { CollectionShelfDisplayStyle, collectionShelfLayoutDirection } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import { buildStoryCard } from "./editorial-page-story-card-utils"; +import * as gamesComponentBuilder from "../../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import { isSome } from "@jet/environment/types/optional"; +export function buildSmallStoryCardShelf(objectGraph, shelfToken) { + return buildStoryCardShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.StorySmall, "smallStoryCard"); +} +export function buildMediumStoryCardShelf(objectGraph, shelfToken) { + return buildStoryCardShelf(objectGraph, shelfToken, CollectionShelfDisplayStyle.StoryMedium, "mediumStoryCard"); +} +function buildStoryCardShelf(objectGraph, shelfToken, displayStyle, storyComponentType) { + const items = []; + const shelf = new models.Shelf(storyComponentType); + const layoutDirection = collectionShelfLayoutDirection(shelfToken); + shelf.isHorizontal = layoutDirection === "Horizontal"; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + const metricsOptions = { + ...shelfToken.metricsImpressionOptions, + targetType: clickTargetForCollectionDisplayStyle(objectGraph, displayStyle), + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData), + }; + if (!mediaAttributes.hasAttributes(itemData) || shouldDefer(shelfToken)) { + shelfToken.remainingItems.push(itemData); + shelfToken.isDeferring = true; + continue; + } + let storyCard = null; + if (preprocessor.GAMES_TARGET && gamesComponentBuilder.shouldUseMediaCard(displayStyle)) { + storyCard = gamesComponentBuilder.makeEditorialMediaCard(objectGraph, itemData, "Card", shelfToken, "Editorial"); + } + else { + storyCard = buildStoryCard(objectGraph, itemData, editorialMediaUtil.EditorialMediaPlacement.StoryCard, metricsOptions, shelfToken.collectionDisplayStyle, true, shelfToken); + } + if (isNull(storyCard)) { + continue; + } + items.push(storyCard); + metricsHelpersLocation.nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + if (preprocessor.GAMES_TARGET && + gamesComponentBuilder.shouldUseComponentGrid(displayStyle, layoutDirection, shelfToken)) { + const item = gamesComponentBuilder.makeComponentGrid(objectGraph, items, shelfToken, displayStyle); + shelf.items = isSome(item) ? [item] : []; + } + else { + shelf.items = items; + } + shelf.rowsPerColumn = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount"); + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + return shelf; +} +//# sourceMappingURL=editorial-page-story-card-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-utils.js new file mode 100644 index 0000000..ff85e3d --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-story-card-utils.js @@ -0,0 +1,128 @@ +import * as models from "../../../../api/models"; +import * as content from "../../../content/content"; +import * as mediaDataStructure from "../../../../foundation/media/data-structure"; +import * as metricsHelpersImpressions from "../../../metrics/helpers/impressions"; +import * as editorialCopyUtil from "../../editorial-page-editorial-copy-util"; +import * as editorialOverlayContentUtil from "../../editorial-page-overlay-content-util"; +import { asBooleanOrFalse, isDefinedNonNull, isDefinedNonNullNonEmpty, } from "../../../../foundation/json-parsing/server-data"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialActionUtil from "../../editorial-action-util"; +import * as editorialMediaUtil from "../../editorial-media-util"; +import * as mediaAttributes from "../../../../foundation/media/attributes"; +import { deepLinkUrlFromData } from "../../../linking/external-deep-link"; +import { shouldFilter } from "../../../filtering"; +import { mixedMediaItemFromEditorialData } from "../../../../gameservicesui/src/common/mixed-media-item-editorial-artwork"; +/** + * Build an `EditorialStoryCard` from the provided data. + * @param objectGraph The object graph. + * @param itemData Data for the card item being created. + * @param mediaPlacement The placement within which the card is being created for media. + * @param metricsOptions A set of metrics options. + * @param collectionDisplayStyle The collection display style for the shelf this is in. + * @param allowSuppressLockup Whether any lockup can be suppressed + * @param shelfToken A shelf token, if being presented within a shelf. If not, it's being used in another context. + * @returns The built editorial story card. + */ +export function buildStoryCard(objectGraph, itemData, mediaPlacement, metricsOptions, collectionDisplayStyle, allowSuppressLockup, shelfToken) { + var _a, _b; + const editorialClientParams = editorialDataUtil.extractEditorialClientParams(objectGraph, itemData); + const storyCard = new models.EditorialStoryCard(); + storyCard.title = editorialCopyUtil.editorialTitleFromData(objectGraph, itemData, collectionDisplayStyle); + if (!editorialClientParams.suppressShort) { + storyCard.description = editorialCopyUtil.editorialDescriptionFromData(objectGraph, itemData); + } + const hideEditorialMedia = asBooleanOrFalse(editorialClientParams.hideEditorialMedia); + if (!hideEditorialMedia) { + const mediaData = editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, itemData, mediaPlacement); + storyCard.artwork = mediaData === null || mediaData === void 0 ? void 0 : mediaData.artwork; + storyCard.video = mediaData === null || mediaData === void 0 ? void 0 : mediaData.video; + storyCard.isMediaDark = (_a = editorialMediaUtil.isMediaDark(objectGraph, mediaData)) !== null && _a !== void 0 ? _a : undefined; + if (mediaPlacement === editorialMediaUtil.EditorialMediaPlacement.StoryDetail) { + if (preprocessor.GAMES_TARGET) { + storyCard.mixedMediaItem = mixedMediaItemFromEditorialData(objectGraph, itemData, "DetailStory"); + } + const landscapeMediaData = editorialMediaUtil.editorialMediaDataForPlacement(objectGraph, itemData, editorialMediaUtil.EditorialMediaPlacement.StoryDetailLandscape); + storyCard.landscapeArtwork = landscapeMediaData === null || landscapeMediaData === void 0 ? void 0 : landscapeMediaData.artwork; + storyCard.landscapeVideo = landscapeMediaData === null || landscapeMediaData === void 0 ? void 0 : landscapeMediaData.video; + storyCard.isLandscapeMediaDark = + (_b = editorialMediaUtil.isMediaDark(objectGraph, landscapeMediaData)) !== null && _b !== void 0 ? _b : undefined; + } + } + const lockupOptions = { + metricsOptions: { + pageInformation: metricsOptions.pageInformation, + locationTracker: metricsOptions.locationTracker, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(itemData), + }, + artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + offerEnvironment: editorialClientParams.useMaterialBlur ? "light" : "lightOverArtwork", + canDisplayArcadeOfferButton: content.shelfDisplayStyleCanDisplayArcadeOfferButtons(objectGraph, collectionDisplayStyle), + isContainedInPreorderExclusiveShelf: false, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, itemData), + useJoeColorIconPlaceholder: preprocessor.GAMES_TARGET, + }; + const overlayContent = editorialOverlayContentUtil.extractOverlayContent(objectGraph, itemData, lockupOptions); + const suppressLockup = allowSuppressLockup && asBooleanOrFalse(editorialClientParams.suppressLockup); + if (!suppressLockup) { + storyCard.lockup = overlayContent.lockup; + } + // For Arcade app that is preorder and bincompat, we should override the badge to always display "COMING SOON" in upper cased. + const lockupData = editorialDataUtil.extractProductData(objectGraph, itemData); + const isPreorder = mediaAttributes.attributeAsBooleanOrFalse(lockupData, "isPreorder"); + const isArcadeLockup = content.isArcadeSupported(objectGraph, lockupData); + const supportsVisionOSCompatibleIOSBinary = content.supportsVisionOSCompatibleIOSBinaryFromData(objectGraph, lockupData); + // If there is lockup data, and we're not suppressing the lockup, check the data is valid for this platform. + // If this is for a story detail page, ignore these checks so that the artwork card is still presented as expected. + if (isDefinedNonNullNonEmpty(lockupData) && + !suppressLockup && + shouldFilter(objectGraph, lockupData, 80894 /* Filter.All */) && + mediaPlacement !== editorialMediaUtil.EditorialMediaPlacement.StoryDetail) { + return null; + } + let badgeText; + if (isPreorder && isArcadeLockup && supportsVisionOSCompatibleIOSBinary) { + badgeText = objectGraph.loc.string("ARCADE_PREORDER_COMING_SOON"); + } + else { + badgeText = editorialCopyUtil.editorialBadgeFromData(objectGraph, itemData, collectionDisplayStyle); + } + if (objectGraph.client.isVision && badgeText === objectGraph.loc.string("APPLE_ARCADE")) { + storyCard.badge = { + type: "arcadeWordmark", + }; + } + else { + storyCard.badge = { + type: "text", + title: badgeText, + }; + } + storyCard.collectionIcons = overlayContent.collectionIcons; + if (isDefinedNonNull(shelfToken)) { + const baseClickOptions = { + id: itemData.id, + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + actionDetails: { + franchise: storyCard.badge.title, + }, + idType: "editorial_id", + }; + storyCard.clickAction = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken, baseClickOptions); + } + storyCard.editorialDisplayOptions = + editorialDataUtil.editorialDisplayOptionsFromClientParams(editorialClientParams); + // Configure impressions + const contentMetricsOptions = { + ...metricsOptions, + id: itemData.id, + idType: "editorial_id", + }; + const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, itemData, storyCard.title, contentMetricsOptions); + metricsHelpersImpressions.addImpressionFields(objectGraph, storyCard, impressionOptions); + if (!storyCard.isValid()) { + return null; + } + return storyCard; +} +//# sourceMappingURL=editorial-page-story-card-utils.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-only-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-only-collection-shelf-builder.js new file mode 100644 index 0000000..3f9f2b7 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-only-collection-shelf-builder.js @@ -0,0 +1,54 @@ +import * as models from "../../../../api/models"; +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../../../foundation/media/attributes"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import * as editorialActionUtil from "../../editorial-action-util"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialCopyUtil from "../../editorial-page-editorial-copy-util"; +import { CollectionShelfLayoutDirection } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import * as metricsHelpersImpressions from "../../../metrics/helpers/impressions"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +export function buildTextOnlyShelf(objectGraph, shelfToken) { + var _a; + const items = []; + const shelf = new models.Shelf("action"); + shelf.isHorizontal = + mediaAttributes.attributeAsString(shelfToken.data, "layoutDirection") === + CollectionShelfLayoutDirection.Horizontal; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + if (serverData.isNull(itemData.attributes) || shouldDefer(shelfToken)) { + shelfToken.isDeferring = true; + shelfToken.remainingItems.push(itemData); + continue; + } + const action = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken); + action.title = editorialCopyUtil.editorialTitleFromData(objectGraph, itemData, shelfToken.collectionDisplayStyle); + // Configure impressions + const contentMetricsOptions = { + ...shelfToken.metricsImpressionOptions, + id: itemData.id, + idType: "editorial_id", + targetType: "textOnly", + }; + const impressionOptions = metricsHelpersImpressions.impressionOptions(objectGraph, itemData, action.title, contentMetricsOptions); + metricsHelpersImpressions.addImpressionFields(objectGraph, action, impressionOptions); + if (action.isValid()) { + items.push(action); + metricsHelpersLocation.nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + } + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + shelf.items = items; + shelf.rowsPerColumn = (_a = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount")) !== null && _a !== void 0 ? _a : 1; + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + return shelf; +} +//# sourceMappingURL=editorial-page-text-only-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-with-artwork-collection-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-with-artwork-collection-shelf-builder.js new file mode 100644 index 0000000..7587b49 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-text-with-artwork-collection-shelf-builder.js @@ -0,0 +1,66 @@ +import * as models from "../../../../api/models"; +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../../../foundation/media/attributes"; +import * as content from "../../../content/content"; +import * as metricsHelpersLocation from "../../../metrics/helpers/location"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../../placeholders/placeholders"; +import * as editorialActionUtil from "../../editorial-action-util"; +import * as editorialDataUtil from "../../editorial-data-util"; +import * as editorialCopyUtil from "../../editorial-page-editorial-copy-util"; +import { CollectionShelfLayoutDirection } from "../../editorial-page-types"; +import { createShelfTokenUrlIfNecessary, shouldDefer } from "./editorial-page-collection-shelf-common"; +import * as gamesComponentBuilder from "../../../../gameservicesui/src/editorial-page/editorial-component-builder"; +export function buildTextWithArtworkShelf(objectGraph, shelfToken) { + var _a; + const items = []; + const shelf = new models.Shelf("action"); + shelf.isHorizontal = + mediaAttributes.attributeAsString(shelfToken.data, "layoutDirection") === + CollectionShelfLayoutDirection.Horizontal; + const shelfContents = editorialDataUtil.extractRemainingItemsOrInitialShelfContents(objectGraph, shelfToken); + for (const itemData of shelfContents) { + if (serverData.isNull(itemData.attributes) || shouldDefer(shelfToken)) { + shelfToken.isDeferring = true; + shelfToken.remainingItems.push(itemData); + continue; + } + const action = editorialActionUtil.createPrimaryActionForComponentFromData(objectGraph, itemData, shelfToken); + action.title = editorialCopyUtil.editorialTitleFromData(objectGraph, itemData, shelfToken.collectionDisplayStyle); + let artwork; + if (preprocessor.GAMES_TARGET) { + const editorialArtwork = mediaAttributes.attributeAsDictionary(itemData, "editorialArtwork"); + artwork = serverData.asDictionary(editorialArtwork, "contentIconTrimmed"); + } + else { + artwork = mediaAttributes.attributeAsDictionary(itemData, "artwork"); + } + if (serverData.isDefinedNonNullNonEmpty(artwork)) { + action.artwork = content.artworkFromApiArtwork(objectGraph, artwork, { + allowingTransparency: true, + useCase: 20 /* content.ArtworkUseCase.CategoryIcon */, + }); + } + if (action.isValid()) { + items.push(action); + metricsHelpersLocation.nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + } + } + // We don't need this in our incomplete shelf URL, so we'll preemptively remove it. + delete shelfToken.maxItemCount; + shelf.eyebrow = shelfToken.eyebrow; + shelf.eyebrowArtwork = shelfToken.eyebrowArtwork; + shelf.title = shelfToken.title; + shelf.subtitle = shelfToken.subtitle; + if (preprocessor.GAMES_TARGET) { + shelf.items = [gamesComponentBuilder.makeRibbonBar(objectGraph, items)]; + shelf.contentType = "ribbonBar"; + } + else { + shelf.items = items; + } + shelf.rowsPerColumn = (_a = mediaAttributes.attributeAsNumber(shelfToken.data, "rowCount")) !== null && _a !== void 0 ? _a : 1; + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + return shelf; +} +//# sourceMappingURL=editorial-page-text-with-artwork-collection-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/index.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/index.js new file mode 100644 index 0000000..ae02877 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-collection-shelf-builder/index.js @@ -0,0 +1,113 @@ +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import { attributeAsString } from "../../../../foundation/media/attributes"; +import { CollectionShelfDisplayStyle } from "../../editorial-page-types"; +import { buildBreakoutLargeShelf } from "./editorial-page-breakout-large-collection-shelf-builder"; +import { buildBrickLargeShelf, buildBrickMediumShelf, buildBrickSmallShelf, } from "./editorial-page-brick-collection-shelf-builder"; +import { createShelfSeeAllActionIfNecessary } from "./editorial-page-collection-shelf-common"; +import { buildHeroShelf } from "./editorial-page-hero-collection-shelf-builder"; +import { buildEditorialLockupLargeShelf, buildEditorialLockupLargeVariantShelf, buildEditorialLockupMediumShelf, buildEditorialLockupMediumVariantShelf, buildLockupLargeShelf, buildLockupSmallShelf, buildEditorialLockupPosterShelf, buildEditorialLockupHierarchicalRows, buildEditorialLockupHierarchicalPortrait, buildLockupMedium, } from "./editorial-page-lockup-collection-shelf-builder"; +import { buildMediumStoryCardShelf, buildSmallStoryCardShelf, } from "./editorial-page-story-card-collection-shelf-builder"; +import { buildTextOnlyShelf } from "./editorial-page-text-only-collection-shelf-builder"; +import { buildTextWithArtworkShelf } from "./editorial-page-text-with-artwork-collection-shelf-builder"; +import { collectionShelfDisplayStyleFromShelfData } from "../../editorial-data-util"; +import * as gamesHeroShelfBuilder from "../../../../gameservicesui/src/editorial-page/editorial-page-hero-collection-shelf-builder"; +import { isSome } from "@jet/environment"; +export function buildCollectionShelf(objectGraph, shelfToken) { + let collectionDisplayStyle = attributeAsString(shelfToken.data, "displayStyle"); + if (preprocessor.GAMES_TARGET) { + // A way to override display style as design wants to see large cards in "See all" rooms. + const shelfTokenStyle = shelfToken.collectionDisplayStyle; + if (isSome(shelfTokenStyle) && shelfTokenStyle !== collectionDisplayStyle) { + collectionDisplayStyle = shelfToken.collectionDisplayStyle; + } + } + if (serverData.isNullOrEmpty(collectionDisplayStyle)) { + return null; + } + let shelf = null; + switch (collectionDisplayStyle) { + case CollectionShelfDisplayStyle.Hero: + if (preprocessor.GAMES_TARGET) { + shelf = gamesHeroShelfBuilder.buildHeroShelf(objectGraph, shelfToken); + } + else { + shelf = buildHeroShelf(objectGraph, shelfToken); + } + break; + case CollectionShelfDisplayStyle.TextOnly: + shelf = buildTextOnlyShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.TextWithArtwork: + shelf = buildTextWithArtworkShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.BrickSmall: + shelf = buildBrickSmallShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.BrickMedium: + shelf = buildBrickMediumShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.BrickLarge: + shelf = buildBrickLargeShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupHierarchicalPortrait: + shelf = buildEditorialLockupHierarchicalPortrait(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupHierarchicalRows: + shelf = buildEditorialLockupHierarchicalRows(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupMedium: + shelf = buildEditorialLockupMediumShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupMediumVariant: + shelf = buildEditorialLockupMediumVariantShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupLarge: + shelf = buildEditorialLockupLargeShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupLargeVariant: + shelf = buildEditorialLockupLargeVariantShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.LockupMedium: + shelf = buildLockupMedium(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.Poster: + shelf = buildEditorialLockupPosterShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.StorySmall: + shelf = buildSmallStoryCardShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.StoryMedium: + shelf = buildMediumStoryCardShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.LockupSmall: + shelf = buildLockupSmallShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.LockupLarge: + shelf = buildLockupLargeShelf(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.BreakoutLarge: + shelf = buildBreakoutLargeShelf(objectGraph, shelfToken); + break; + default: + break; + } + if (serverData.isDefinedNonNullNonEmpty(shelf)) { + shelf.seeAllAction = createShelfSeeAllActionIfNecessary(objectGraph, shelf, shelfToken); + shelf.id = `shelf_${shelfToken.id}`; + } + return shelf; +} +/** + * Decorates the input shelf metrics options with shelf specific fields. + * @param objectGraph Current object graph + * @param shelfMetricsOptions Base shelf metrics options + * @returns Decorated shelf metrics options + */ +export function decorateCollectionShelfMetricsOptions(objectGraph, shelfData, shelfMetricsOptions) { + const collectionDisplayStyle = collectionShelfDisplayStyleFromShelfData(objectGraph, shelfData); + if (serverData.isNullOrEmpty(collectionDisplayStyle)) { + return; + } + shelfMetricsOptions.displayStyle = collectionDisplayStyle; +} +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-engagement-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-engagement-shelf-builder.js new file mode 100644 index 0000000..76756a7 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-engagement-shelf-builder.js @@ -0,0 +1,4 @@ +export function buildEngagementShelf(objectGraph, shelfToken) { + return null; +} +//# sourceMappingURL=editorial-page-engagement-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-game-center-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-game-center-shelf-builder.js new file mode 100644 index 0000000..7de4145 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-game-center-shelf-builder.js @@ -0,0 +1,4 @@ +export function buildGameCenterShelf(objectGraph, shelfToken) { + return null; +} +//# sourceMappingURL=editorial-page-game-center-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-header-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-header-shelf-builder.js new file mode 100644 index 0000000..0f3a98f --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-header-shelf-builder.js @@ -0,0 +1,157 @@ +import { attributeAsString } from "@apple-media-services/media-api"; +import { isSome } from "@jet/environment/types/optional"; +import * as models from "../../../api/models"; +import { asBooleanOrFalse, isDefinedNonNullNonEmpty } from "../../../foundation/json-parsing/server-data"; +import { attributeAsDictionary } from "../../../foundation/media/attributes"; +import { metricsFromMediaApiObject } from "../../../foundation/media/data-structure"; +import * as color from "../../../foundation/util/color-util"; +import { shallowCopyOf } from "../../../foundation/util/objects"; +import * as gamesComponentBuilder from "../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import * as content from "../../content/content"; +import { deepLinkUrlFromData } from "../../linking/external-deep-link"; +import { popLocation, pushBasicLocation } from "../../metrics/helpers/location"; +import { areAppTagsEnabled } from "../../util/app-tags-util"; +import { editorialDisplayOptionsFromClientParams, extractEditorialClientParams } from "../editorial-data-util"; +import { editorialMediaDataForPlacement, EditorialMediaPlacement, isMediaDark, } from "../editorial-media-util"; +import * as editorialComponentMediaUtil from "../editorial-page-component-media-util"; +import { heroOverlayFromData } from "../editorial-page-hero-util"; +import * as metricsHelpersImpressions from "../../metrics/helpers/impressions"; +/** + * Build a header shelf for the editorial page, if present. + * @param objectGraph The App Store object graph. + * @param pageData The data for the editorial page. + * @param shelfToken The shelf token. + * @returns A Shelf, if the data is available. + */ +export function buildHeaderShelf(objectGraph, pageData, shelfToken) { + var _a, _b, _c; + const shouldUseShelfData = isDefinedNonNullNonEmpty(attributeAsDictionary(shelfToken.data, "editorialNotes")); + const headerData = shouldUseShelfData ? shelfToken.data : pageData; + if (!headerData) { + return null; + } + if (preprocessor.GAMES_TARGET) { + return gamesComponentBuilder.makeGamesPageHeaderFromData(objectGraph, headerData, shelfToken); + } + const editorialArtworkData = isDefinedNonNullNonEmpty(attributeAsDictionary(headerData, "editorialArtwork")); + if (editorialArtworkData) { + const pageHeader = new models.HeroCarousel(); + const pageHeaderCarouselItem = new models.HeroCarouselItem(); + const editorialClientParams = extractEditorialClientParams(objectGraph, headerData); + const pageHeaderCarouselItemOverlay = heroOverlayFromData(objectGraph, headerData, shelfToken, editorialClientParams); + pageHeaderCarouselItemOverlay.overlayType = "text"; + pageHeaderCarouselItemOverlay.callToActionText = null; + pageHeaderCarouselItem.clickAction = null; + pageHeaderCarouselItemOverlay.collectionIcons = null; + pageHeaderCarouselItemOverlay.lockup = null; + pageHeaderCarouselItemOverlay.callToActionText = null; + pageHeaderCarouselItem.overlay = pageHeaderCarouselItemOverlay; + const lockupOptions = { + artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + offerStyle: "transparent", + offerEnvironment: "dark", + canDisplayArcadeOfferButton: content.shelfDisplayStyleCanDisplayArcadeOfferButtons(objectGraph, shelfToken.collectionDisplayStyle), + isContainedInPreorderExclusiveShelf: false, + metricsOptions: { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: metricsFromMediaApiObject(headerData), + }, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, headerData), + }; + pushBasicLocation(objectGraph, lockupOptions.metricsOptions, "collectionIcons"); + const collectionIcons = editorialComponentMediaUtil.editorialFallbackAppIconsFromData(objectGraph, headerData, lockupOptions); + popLocation(lockupOptions.metricsOptions.locationTracker); + pageHeaderCarouselItem.collectionIcons = collectionIcons; + const heroMediaData = editorialMediaDataForPlacement(objectGraph, headerData, EditorialMediaPlacement.Hero); + const hideEditorialMedia = asBooleanOrFalse(editorialClientParams.hideEditorialMedia); + populatePageHeaderCarouselItemMedia(objectGraph, pageHeaderCarouselItem, hideEditorialMedia, heroMediaData, false); + pageHeaderCarouselItem.editorialDisplayOptions = editorialDisplayOptionsFromClientParams(editorialClientParams); + pageHeader.items = [pageHeaderCarouselItem]; + const rtlPageHeaderCarouselItem = shallowCopyOf(pageHeaderCarouselItem); + populatePageHeaderCarouselItemMedia(objectGraph, rtlPageHeaderCarouselItem, hideEditorialMedia, heroMediaData, true); + pageHeader.rtlItems = [rtlPageHeaderCarouselItem]; + const shelf = new models.Shelf("heroCarousel"); + shelf.items = [pageHeader]; + return shelf; + } + else { + const editorialName = attributeAsString(headerData, "name"); + if (isDefinedNonNullNonEmpty(editorialName) && areAppTagsEnabled(objectGraph, null)) { + const shelf = new models.Shelf("mediaPageHeader"); + shelf.id = "mediaPageHeader"; + const editorialBadge = (_a = attributeAsString(headerData, "editorialNotes.badge")) !== null && _a !== void 0 ? _a : null; + const lockupOptions = { + artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + offerStyle: "transparent", + offerEnvironment: "dark", + canDisplayArcadeOfferButton: content.shelfDisplayStyleCanDisplayArcadeOfferButtons(objectGraph, shelfToken.collectionDisplayStyle), + isContainedInPreorderExclusiveShelf: false, + metricsOptions: { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: metricsFromMediaApiObject(headerData), + }, + externalDeepLinkUrl: deepLinkUrlFromData(objectGraph, headerData), + useJoeColorIconPlaceholder: true, + joeColorPlaceholderSelectionLogic: content.bestJoeColorPlaceholderSelectionLogic, + }; + let collectionIcons = (_b = editorialComponentMediaUtil.editorialFallbackAppIconsFromData(objectGraph, shelfToken.data, lockupOptions)) !== null && _b !== void 0 ? _b : undefined; + let backgroundColor; + if (isSome(collectionIcons) && (collectionIcons === null || collectionIcons === void 0 ? void 0 : collectionIcons.length) >= 3) { + collectionIcons = collectionIcons.slice(0, 3); + const collectionIconBackgroundColor = collectionIcons[0].backgroundColor; + if (isSome(collectionIconBackgroundColor) && (collectionIconBackgroundColor === null || collectionIconBackgroundColor === void 0 ? void 0 : collectionIconBackgroundColor.type) === "rgb") { + backgroundColor = content.closestTagBackgroundColorForIcon(collectionIconBackgroundColor); + } + const isArtworkDark = color.isDarkColor(backgroundColor); + const editorialClientParams = extractEditorialClientParams(objectGraph, shelfToken.data); + const mediaPageHeader = new models.MediaPageHeader(editorialBadge, editorialName, null, undefined, undefined, collectionIcons, false, backgroundColor !== null && backgroundColor !== void 0 ? backgroundColor : undefined, convertHintToIconCollectionStyle((_c = editorialClientParams.fallbackDisplayStyleHint) !== null && _c !== void 0 ? _c : "one", collectionIcons === null || collectionIcons === void 0 ? void 0 : collectionIcons.length), isArtworkDark ? "dark" : "light"); + // Configure impressions + const metricsOptions = { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + recoMetricsData: metricsFromMediaApiObject(headerData), + }; + const impressionOptions = metricsHelpersImpressions.impressionOptionsForTagHeader(objectGraph, headerData, editorialName, metricsOptions); + metricsHelpersImpressions.addImpressionFieldsToTagRoomHeader(objectGraph, mediaPageHeader, impressionOptions); + shelf.items = [mediaPageHeader]; + return shelf; + } + else { + return null; + } + } + else { + return null; + } + } +} +function convertHintToIconCollectionStyle(hint, artworkCount) { + if (artworkCount === 2) { + return "TwoUp"; + } + else { + switch (hint) { + case "one": + return "ThreeUp"; + case "two": + return "Fan"; + case "three": + return "Asymmetrical"; + default: + return "ThreeUp"; + } + } +} +function populatePageHeaderCarouselItemMedia(objectGraph, pageHeaderCarouselItem, hideEditorialMedia, heroMediaData, isRTL) { + if (!hideEditorialMedia) { + pageHeaderCarouselItem.backgroundColor = isRTL + ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlBackgroundColor + : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.backgroundColor; + pageHeaderCarouselItem.artwork = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlArtwork : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.artwork; + pageHeaderCarouselItem.video = isRTL ? heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.rtlVideo : heroMediaData === null || heroMediaData === void 0 ? void 0 : heroMediaData.video; + } + pageHeaderCarouselItem.isMediaDark = isMediaDark(objectGraph, heroMediaData, isRTL); +} +//# sourceMappingURL=editorial-page-header-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-image-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-image-shelf-builder.js new file mode 100644 index 0000000..44ce98e --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-image-shelf-builder.js @@ -0,0 +1,4 @@ +export function buildImageShelf(objectGraph, shelfToken) { + return null; +} +//# sourceMappingURL=editorial-page-image-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/editorial-page-quick-links-marker-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/editorial-page-quick-links-marker-shelf-builder.js new file mode 100644 index 0000000..0f3b482 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/editorial-page-quick-links-marker-shelf-builder.js @@ -0,0 +1,71 @@ +import { isSome } from "@jet/environment/types/optional"; +import * as models from "../../../../api/models"; +import * as artworkBuilder from "../../../content/artwork/artwork"; +import * as metricsHelpersClicks from "../../../metrics/helpers/clicks"; +export function buildQuickLinksShelf(objectGraph, shelfToken) { + if (objectGraph.user && objectGraph.user.isManagedAppleID) { + return null; + } + // Watch App Store does not support titled button stacks, + // and has different footer buttons. + if (objectGraph.client.isWatch) { + const shelf = new models.Shelf("action"); + const items = []; + const accountFlowAction = new models.FlowAction("account"); + accountFlowAction.title = objectGraph.loc.string("ACCOUNT", "Account"); + accountFlowAction.artwork = artworkBuilder.createArtworkForResource(objectGraph, "systemimage://person.crop.circle"); + const accountFlowClickOptions = { + targetType: "button", + id: "account", + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + }; + metricsHelpersClicks.addClickEventToAction(objectGraph, accountFlowAction, accountFlowClickOptions); + items.push(accountFlowAction); + shelf.items = items; + return shelf; + } + else { + const items = []; + if (isSome(objectGraph.bag.aboutAppStoreUrl)) { + const aboutAppStoreAction = new models.ExternalUrlAction(objectGraph.bag.aboutAppStoreUrl); + aboutAppStoreAction.title = objectGraph.loc.string("QuickLinks.AboutTheAppStore.Title"); + items.push(aboutAppStoreAction); + } + if (isSome(objectGraph.bag.aboutInAppPurchasesEditorialItemId)) { + const aboutIAPsFlowAction = new models.FlowAction("article"); + aboutIAPsFlowAction.title = objectGraph.loc.string("QuickLinks.AboutInAppPurchases.Title"); + aboutIAPsFlowAction.pageUrl = `https://apps.apple.com/story/id${objectGraph.bag.aboutInAppPurchasesEditorialItemId}`; + items.push(aboutIAPsFlowAction); + } + if (isSome(objectGraph.bag.reportProblemUrl)) { + const reportProblemAction = new models.ExternalUrlAction(objectGraph.bag.reportProblemUrl); + reportProblemAction.title = objectGraph.loc.string("REPORT_A_PROBLEM", "Report a Problem"); + items.push(reportProblemAction); + } + if (isSome(objectGraph.bag.requestARefundUrl)) { + const requestRefundAction = new models.ExternalUrlAction(objectGraph.bag.requestARefundUrl); + requestRefundAction.title = objectGraph.loc.string("QuickLinks.RequestARefund.Title"); + items.push(requestRefundAction); + } + if (isSome(objectGraph.bag.changePaymentMethodUrl)) { + const changePaymentMethodAction = new models.ExternalUrlAction(objectGraph.bag.changePaymentMethodUrl); + changePaymentMethodAction.title = objectGraph.loc.string("QuickLinks.ChangePaymentMethod.Title"); + items.push(changePaymentMethodAction); + } + if (isSome(objectGraph.bag.aboutFrenchAppStoreEditorialItemId)) { + const aboutFrenchAppStoreFlowAction = new models.FlowAction("article"); + aboutFrenchAppStoreFlowAction.title = objectGraph.loc.string("QuickLinks.AboutFrenchAppStore.Title"); + aboutFrenchAppStoreFlowAction.pageUrl = `https://apps.apple.com/story/id${objectGraph.bag.aboutFrenchAppStoreEditorialItemId}`; + items.push(aboutFrenchAppStoreFlowAction); + } + const shelf = new models.Shelf("action"); + shelf.title = objectGraph.loc.string("QuickLinks.Title"); + shelf.items = items; + shelf.isHorizontal = true; + shelf.rowsPerColumn = 1; + shelfToken.metricsImpressionOptions.title = shelf.title; + return shelf; + } +} +//# sourceMappingURL=editorial-page-quick-links-marker-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/index.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/index.js new file mode 100644 index 0000000..6392f23 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-marker-shelf-builder/index.js @@ -0,0 +1,20 @@ +import * as serverData from "../../../../foundation/json-parsing/server-data"; +import { attributeAsString } from "../../../../foundation/media/attributes"; +import { MarkerShelfKind } from "../../editorial-page-types"; +import { buildQuickLinksShelf } from "./editorial-page-quick-links-marker-shelf-builder"; +export function buildMarkerShelf(objectGraph, shelfToken) { + const markerKind = attributeAsString(shelfToken.data, "kind"); + if (serverData.isNullOrEmpty(markerKind)) { + return null; + } + let shelf = null; + switch (markerKind) { + case MarkerShelfKind.QuickLinks: + shelf = buildQuickLinksShelf(objectGraph, shelfToken); + break; + default: + break; + } + return shelf; +} +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-recommendations-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-recommendations-shelf-builder.js new file mode 100644 index 0000000..828d652 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-recommendations-shelf-builder.js @@ -0,0 +1,77 @@ +import { isNothing, isSome } from "@jet/environment"; +import * as models from "../../../api/models"; +import { isDefinedNonNullNonEmpty } from "../../../foundation/json-parsing/server-data"; +import { attributeAsBooleanOrFalse, attributeAsString } from "../../../foundation/media/attributes"; +import { Request } from "../../../foundation/media/data-fetching"; +import { relationshipCollection } from "../../../foundation/media/relationships"; +import { buildURLFromRequest } from "../../../foundation/media/url-builder"; +import { Parameters } from "../../../foundation/network/url-constants"; +import { insertPlaceholdersIntoShelfIfRequired } from "../../placeholders/placeholders"; +import { CollectionShelfDisplayStyle } from "../editorial-page-types"; +import { createShelfSeeAllActionIfNecessary, createShelfTokenUrlIfNecessary, } from "./editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common"; +import { buildEditorialLockupHierarchicalPortrait, buildEditorialLockupLargeShelf, buildLockupLargeShelf, buildLockupSmallShelf, } from "./editorial-page-collection-shelf-builder/editorial-page-lockup-collection-shelf-builder"; +export function buildRecommendationsShelf(objectGraph, shelfToken) { + let collectionDisplayStyle = attributeAsString(shelfToken.data, "displayStyle"); + if (preprocessor.GAMES_TARGET) { + // A way to override display style as design wants to see large cards in "See all" rooms. + const shelfTokenStyle = shelfToken.collectionDisplayStyle; + if (isSome(shelfTokenStyle) && shelfTokenStyle !== collectionDisplayStyle) { + collectionDisplayStyle = shelfToken.collectionDisplayStyle; + } + } + let shelf = null; + switch (collectionDisplayStyle) { + case CollectionShelfDisplayStyle.LockupSmall: + shelf = buildLockupSmallShelf(objectGraph, shelfToken, false); + break; + case CollectionShelfDisplayStyle.LockupLarge: + shelf = buildLockupLargeShelf(objectGraph, shelfToken, false); + break; + case CollectionShelfDisplayStyle.EditorialLockupHierarchicalPortrait: + shelf = buildEditorialLockupHierarchicalPortrait(objectGraph, shelfToken); + break; + case CollectionShelfDisplayStyle.EditorialLockupLarge: + shelf = buildEditorialLockupLargeShelf(objectGraph, shelfToken); + break; + default: + shelf = shelfToken.isFirstRender ? makeHiddenShelf() : null; + break; + } + if (isNothing(shelf)) { + return null; + } + shelf.id = `shelf_${shelfToken.id}`; + addRecommendationsHrefIfNecessary(objectGraph, shelfToken); + shelf.url = createShelfTokenUrlIfNecessary(objectGraph, shelf, shelfToken); + insertPlaceholdersIntoShelfIfRequired(objectGraph, shelf, shelfToken); + shelf.seeAllAction = createShelfSeeAllActionIfNecessary(objectGraph, shelf, shelfToken); + return shelf; +} +/** + * Add the recommendations href for out of band reqeusts if necessary + * @param shelfToken The shelf token to add the href to + */ +function addRecommendationsHrefIfNecessary(objectGraph, shelfToken) { + const hasRecommendedContents = isDefinedNonNullNonEmpty(relationshipCollection(shelfToken.data, "contents")) || + isDefinedNonNullNonEmpty(shelfToken.remainingItems); + const isPersonalizationAvailable = attributeAsBooleanOrFalse(shelfToken.data, "isPersonalizationAvailable"); + const baseHref = shelfToken.data.href; + const shouldAddHref = isPersonalizationAvailable && !hasRecommendedContents && isDefinedNonNullNonEmpty(baseHref); + if (!shouldAddHref) { + return; + } + const recommendationsRequest = new Request(objectGraph, shelfToken.data.href) + .addingQuery(Parameters.editorialPageId, shelfToken.pageId) + .includingRelationships(["contents"]); + const recommendationsUrl = buildURLFromRequest(objectGraph, recommendationsRequest); + shelfToken.recommendationsHref = recommendationsUrl.toString(); +} +/** + * Creates a hidden shelf for when we're performing a secondary fetch and need to hide a shelf that returns null + */ +function makeHiddenShelf() { + const hiddenShelf = new models.Shelf("placeholder"); + hiddenShelf.isHidden = true; + return hiddenShelf; +} +//# sourceMappingURL=editorial-page-recommendations-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-tag-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-tag-shelf-builder.js new file mode 100644 index 0000000..9378611 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-tag-shelf-builder.js @@ -0,0 +1,4 @@ +export function buildTagShelf(objectGraph, shelfToken) { + return null; +} +//# sourceMappingURL=editorial-page-tag-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-text-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-text-shelf-builder.js new file mode 100644 index 0000000..3b8fd26 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-text-shelf-builder.js @@ -0,0 +1,19 @@ +import * as models from "../../../api/models"; +import { isNothing } from "@jet/environment"; +import { makeShelfId } from "../../../gameservicesui/src/editorial-page/editorial-component-builder"; +import * as mediaAPI from "@apple-media-services/media-api"; +export function buildTextShelf(objectGraph, shelfToken) { + if (!preprocessor.GAMES_TARGET) { + return null; + } + const shelf = new models.Shelf("paragraph"); + shelf.id = makeShelfId(shelfToken).toString(); + const editorialCopy = mediaAPI.attributeAsString(shelfToken.data, "editorialCopy"); + if (isNothing(editorialCopy)) { + return null; + } + const paragraph = new models.Paragraph(editorialCopy, "text/x-apple-as3-nqml", "article"); + shelf.items = [paragraph]; + return shelf; +} +//# sourceMappingURL=editorial-page-text-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-upsell-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-upsell-shelf-builder.js new file mode 100644 index 0000000..deb0ac9 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-upsell-shelf-builder.js @@ -0,0 +1,31 @@ +import * as models from "../../../api/models"; +import * as serverData from "../../../foundation/json-parsing/server-data"; +import * as arcadeCommon from "../../arcade/arcade-common"; +import * as arcadeUpsell from "../../arcade/arcade-upsell"; +import * as metricsHelpersLocation from "../../metrics/helpers/location"; +import * as metricsHelpersUtil from "../../metrics/helpers/util"; +import { makeGamesPageUpsellHeaderFromData } from "../../../gameservicesui/src/editorial-page/editorial-component-builder"; +export function buildUpsellShelf(objectGraph, shelfToken) { + if (preprocessor.GAMES_TARGET) { + return makeGamesPageUpsellHeaderFromData(objectGraph, shelfToken); + } + const upsellData = arcadeCommon.upsellFromRelationshipOf(objectGraph, shelfToken.data); + if (serverData.isNullOrEmpty(upsellData)) { + return null; + } + const marketingItemData = upsellData.marketingItemData; + if (serverData.isNullOrEmpty(marketingItemData) || serverData.isNullOrEmpty(marketingItemData.attributes)) { + return null; + } + const metricsOptions = { + pageInformation: shelfToken.metricsPageInformation, + locationTracker: shelfToken.metricsLocationTracker, + mercuryMetricsData: metricsHelpersUtil.marketingItemTopLevelBaseFieldsFromData(objectGraph, marketingItemData), + }; + const upsellBreakout = arcadeUpsell.createUpsellBreakout(objectGraph, marketingItemData, metricsOptions); + metricsHelpersLocation.nextPosition(shelfToken.metricsLocationTracker); + const shelf = new models.Shelf("upsellBreakout"); + shelf.items = [upsellBreakout]; + return shelf; +} +//# sourceMappingURL=editorial-page-upsell-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-video-clip-shelf-builder.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-video-clip-shelf-builder.js new file mode 100644 index 0000000..b5548db --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/editorial-page-video-clip-shelf-builder.js @@ -0,0 +1,4 @@ +export function buildVideoClipShelf(objectGraph, shelfToken) { + return null; +} +//# sourceMappingURL=editorial-page-video-clip-shelf-builder.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/index.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/index.js new file mode 100644 index 0000000..59dbabe --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-builder/index.js @@ -0,0 +1,83 @@ +import { isNullOrEmpty } from "../../../foundation/json-parsing/server-data"; +import { EditorialShelfType } from "../editorial-page-types"; +import { buildChartShelf } from "./editorial-page-chart-shelf-builder"; +import { buildCollectionShelf } from "./editorial-page-collection-shelf-builder"; +import { buildEngagementShelf } from "./editorial-page-engagement-shelf-builder"; +import { buildGameCenterShelf } from "./editorial-page-game-center-shelf-builder"; +import { buildHeaderShelf } from "./editorial-page-header-shelf-builder"; +import { buildImageShelf } from "./editorial-page-image-shelf-builder"; +import { buildMarkerShelf } from "./editorial-page-marker-shelf-builder"; +import { buildArcadeSeeAllGamesShelf } from "./editorial-page-arcade-see-all-games-shelf-builder"; +import { buildRecommendationsShelf } from "./editorial-page-recommendations-shelf-builder"; +import { buildTagShelf } from "./editorial-page-tag-shelf-builder"; +import { buildTextShelf } from "./editorial-page-text-shelf-builder"; +import { buildUpsellShelf } from "./editorial-page-upsell-shelf-builder"; +import { buildVideoClipShelf } from "./editorial-page-video-clip-shelf-builder"; +import { nextPosition, popLocation, pushContentLocation } from "../../metrics/helpers/location"; +import { addImpressionFields } from "../../metrics/helpers/impressions"; +import { storePlaceholderShelfImpressionMetrics } from "./editorial-page-collection-shelf-builder/editorial-page-collection-shelf-common"; +import { isSome } from "@jet/environment/types/optional"; +export function buildEditorialShelf(objectGraph, pageData, shelfToken) { + let shelf = null; + if (shelfToken.isFirstRender) { + pushContentLocation(objectGraph, shelfToken.metricsImpressionOptions, shelfToken.title); + } + switch (shelfToken.type) { + case EditorialShelfType.ArcadeSeeAllGames: + shelf = buildArcadeSeeAllGamesShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Collection: + shelf = buildCollectionShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Chart: + shelf = buildChartShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Tag: + shelf = buildTagShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Engagement: + shelf = buildEngagementShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Text: + shelf = buildTextShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Image: + shelf = buildImageShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.VideoClip: + shelf = buildVideoClipShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Header: + shelf = buildHeaderShelf(objectGraph, pageData, shelfToken); + break; + case EditorialShelfType.Recommendations: + shelf = buildRecommendationsShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.GameCenter: + shelf = buildGameCenterShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Upsell: + shelf = buildUpsellShelf(objectGraph, shelfToken); + break; + case EditorialShelfType.Marker: + shelf = buildMarkerShelf(objectGraph, shelfToken); + break; + default: + break; + } + if (isNullOrEmpty(shelf === null || shelf === void 0 ? void 0 : shelf.items) && isNullOrEmpty(shelf === null || shelf === void 0 ? void 0 : shelf.url)) { + shelf = null; + } + if (shelfToken.isFirstRender) { + popLocation(shelfToken.metricsImpressionOptions.locationTracker); + } + addImpressionFields(objectGraph, shelf, shelfToken.metricsImpressionOptions); + if (shelfToken.isFirstRender) { + nextPosition(shelfToken.metricsImpressionOptions.locationTracker); + } + if (isSome(shelf)) { + storePlaceholderShelfImpressionMetrics(objectGraph, shelf, shelfToken); + } + return shelf; +} +//# sourceMappingURL=index.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-metrics.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-metrics.js new file mode 100644 index 0000000..e1f18ed --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-metrics.js @@ -0,0 +1,51 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaDataStructure from "../../foundation/media/data-structure"; +import { collectionShelfDisplayStyleFromShelfData } from "./editorial-data-util"; +import { decorateCollectionShelfMetricsOptions } from "./editorial-page-shelf-builder/editorial-page-collection-shelf-builder"; +import { decorateHeroShelfMetricsOptions } from "./editorial-page-shelf-builder/editorial-page-collection-shelf-builder/editorial-page-hero-collection-shelf-builder"; +import { CollectionShelfDisplayStyle, EditorialShelfType } from "./editorial-page-types"; +/** + * Creates the shelf metrics options for a given shelf data item. + * @param objectGraph Current object graph + * @param shelfData The data for the shelf + * @param title The metrics title for the shelf + * @param metricsPageInformation Current metrics page information + * @param metricsLocationTracker Current metrics location tracker + * @returns Built shelf metrics options + */ +export function buildShelfMetricsOptions(objectGraph, shelfData, title, metricsPageInformation, metricsLocationTracker) { + const shelfType = shelfData.type; + const collectionDisplayStyle = collectionShelfDisplayStyleFromShelfData(objectGraph, shelfData); + const shelfMetricsOptions = { + id: serverData.asString(shelfData, "id"), + kind: null, + softwareType: null, + targetType: "swoosh", + title: title, + pageInformation: metricsPageInformation, + locationTracker: metricsLocationTracker, + idType: "shelf_id", + shelfType: shelfType, + recoMetricsData: mediaDataStructure.metricsFromMediaApiObject(shelfData), + canonicalId: serverData.asString(shelfData.meta, "canonicalId"), + }; + switch (shelfType) { + case EditorialShelfType.Collection: + decorateCollectionShelfMetricsOptions(objectGraph, shelfData, shelfMetricsOptions); + switch (collectionDisplayStyle) { + case CollectionShelfDisplayStyle.Hero: + decorateHeroShelfMetricsOptions(objectGraph, shelfMetricsOptions); + break; + default: + break; + } + break; + case EditorialShelfType.Recommendations: + decorateCollectionShelfMetricsOptions(objectGraph, shelfData, shelfMetricsOptions); + break; + default: + break; + } + return shelfMetricsOptions; +} +//# sourceMappingURL=editorial-page-shelf-metrics.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-token.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-token.js new file mode 100644 index 0000000..6857cdb --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-shelf-token.js @@ -0,0 +1,120 @@ +import * as serverData from "../../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../../foundation/media/attributes"; +import * as mediaRelationship from "../../foundation/media/relationships"; +import * as content from "../content/content"; +import { recoMetricsDataForFCData } from "../grouping/shelf-controllers/grouping-shelf-controller-common"; +import { collectionShelfDisplayStyleFromShelfData, extractEditorialClientParams } from "./editorial-data-util"; +import { buildShelfMetricsOptions } from "./editorial-page-shelf-metrics"; +import { GameCenterShelfClientFilter, } from "./editorial-page-types"; +import { isSome } from "@jet/environment"; +/** + * Create the base shelf token to start parsing an editorial page shelf. This will create a new shelf token with the + * base metrics options + * + * @param objectGraph The App Store dependency graph for making native calls and viewing properties + * @param pageId The id of the editorial page this shelf is on. + * @param shelfData The media api data for this specific shelf + * @param isArcadePage Whether this shelf is on the arcade page or not + * @param shelfIndex The index of this shelf on the page, at the time of building + * @param metricsPageInformation The metrics page information for the editorial page + * @param metricsLocationTracker The location tracker for building metrics location information + * @param isSeeAll Whether the shelf is being built as a shelf for a sidepacked See All page. + * @param collectionDisplayStyleOverride A way to override collection display style that is coming from mediaAPI. + */ +export function createBaseShelfToken(objectGraph, pageId, shelfData, isArcadePage, shelfIndex, metricsPageInformation, metricsLocationTracker, isSeeAll = false, collectionDisplayStyle = null) { + const shelfToken = { + id: serverData.asString(shelfData, "id"), + type: shelfData.type, + collectionDisplayStyle: collectionDisplayStyle !== null && collectionDisplayStyle !== void 0 ? collectionDisplayStyle : collectionShelfDisplayStyleFromShelfData(objectGraph, shelfData), + filterOverrides: mediaAttributes.attributeAsArrayOrEmpty(shelfData, "filterOverrides"), + pageId: pageId, + data: shelfData, + presentationHints: {}, + clientIdentifierOverride: null, + isFirstRender: true, + shouldFilter: true, + gamesFilter: gamesFilterFromShelfData(shelfData), + hasExistingContent: false, + title: null, + subtitle: null, + eyebrow: null, + titleArtwork: null, + remainingItems: [], + metricsImpressionOptions: null, + metricsPageInformation: metricsPageInformation, + metricsLocationTracker: metricsLocationTracker, + recoMetricsData: recoMetricsDataForFCData(objectGraph, shelfData), + isDeferring: false, + showOrdinals: false, + ordinalIndex: 1, + isSearchLandingPage: false, + isArcadePage: isArcadePage, + shelfIndex: shelfIndex, + isSeeAll: isSeeAll, + }; + applyBaseShelfTokenTitleValues(objectGraph, shelfData, shelfToken); + return shelfToken; +} +/** + * Apply the values for the title, subtitle, and eyebrow to the shelf token, as well as the impressionOptions + * + * @param objectGraph The App Store dependency graph for making native calls and viewing properties + * @param shelfData The media api data for this specific shelf + * @param shelfToken The shelf token to apply the title values to + */ +export function applyBaseShelfTokenTitleValues(objectGraph, shelfData, shelfToken) { + let title = mediaAttributes.attributeAsString(shelfData, "editorialNotes.name"); + let subtitle = mediaAttributes.attributeAsString(shelfData, "editorialNotes.tagline"); + let eyebrow = mediaAttributes.attributeAsString(shelfData, "editorialNotes.badge"); + let titleArtwork = null; + // 'Similar To' Personalised Shelf + // Check if personalised shelf has a badge-content, if it's got valid content, and the clients support eyebrows and title artwork: + // - Reco shelf title becomes the eyebrow + // - Featured App in badge-content becomes the shelf title, and we add the icon as title artwork + // - No subtitle should be shown + // - Flag to use the eyebrown name for metrics + let wantsEyebrowNameForMetrics = false; + const badgeContent = mediaRelationship.relationshipData(objectGraph, shelfData, "badge-content"); + if (serverData.isDefinedNonNullNonEmpty(badgeContent)) { + eyebrow = objectGraph.loc.uppercased(mediaAttributes.attributeAsString(shelfData, "editorialNotes.name")); + title = mediaAttributes.attributeAsString(badgeContent, "editorialNotes.name"); + titleArtwork = content.iconFromData(objectGraph, badgeContent, { + useCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + }); + subtitle = null; + wantsEyebrowNameForMetrics = true; + } + if (preprocessor.GAMES_TARGET) { + const editorialClientParams = extractEditorialClientParams(objectGraph, shelfData); + // This flag hides the whole shelf header content altogether + if (isSome(editorialClientParams) && editorialClientParams.suppressName) { + title = null; + subtitle = null; + eyebrow = null; + titleArtwork = null; + } + } + const shelfMetricsOptionsTitle = wantsEyebrowNameForMetrics ? eyebrow : title; + const shelfMetricsOptions = buildShelfMetricsOptions(objectGraph, shelfData, shelfMetricsOptionsTitle, shelfToken.metricsPageInformation, shelfToken.metricsLocationTracker); + shelfToken.title = title; + shelfToken.subtitle = subtitle; + shelfToken.eyebrow = eyebrow; + shelfToken.titleArtwork = titleArtwork; + shelfToken.metricsImpressionOptions = shelfMetricsOptions; +} +function gamesFilterFromShelfData(shelfData) { + const clientFilter = mediaAttributes.attributeAsString(shelfData, "clientFilter"); + let gamesFilter = null; + switch (clientFilter) { + case GameCenterShelfClientFilter.ArcadeGames: + gamesFilter = "arcade"; + break; + case GameCenterShelfClientFilter.AllGames: + gamesFilter = "all"; + break; + default: + break; + } + return gamesFilter; +} +//# sourceMappingURL=editorial-page-shelf-token.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-types.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-types.js new file mode 100644 index 0000000..22daf5f --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-page-types.js @@ -0,0 +1,139 @@ +import { isNothing } from "@jet/environment"; +import * as mediaAttributes from "../../foundation/media/attributes"; +export var EditorialShelfType; +(function (EditorialShelfType) { + EditorialShelfType["ArcadeSeeAllGames"] = "editorial-shelves-arcade-see-all-games"; + EditorialShelfType["Collection"] = "editorial-shelves-collection"; + EditorialShelfType["Chart"] = "editorial-shelves-chart"; + EditorialShelfType["Tag"] = "editorial-shelves-tag"; + EditorialShelfType["Engagement"] = "editorial-shelves-engagement"; + EditorialShelfType["Text"] = "editorial-shelves-text"; + EditorialShelfType["Image"] = "editorial-shelves-image"; + EditorialShelfType["VideoClip"] = "editorial-shelves-video-clip"; + EditorialShelfType["Header"] = "editorial-shelves-header"; + EditorialShelfType["Recommendations"] = "editorial-shelves-recommendation"; + EditorialShelfType["GameCenter"] = "editorial-shelves-game-center"; + EditorialShelfType["Upsell"] = "editorial-shelves-upsell"; + EditorialShelfType["Marker"] = "editorial-shelves-marker"; +})(EditorialShelfType || (EditorialShelfType = {})); +export var CollectionShelfDisplayStyle; +(function (CollectionShelfDisplayStyle) { + CollectionShelfDisplayStyle["Hero"] = "Hero"; + CollectionShelfDisplayStyle["TextOnly"] = "TextOnly"; + CollectionShelfDisplayStyle["TextWithArtwork"] = "TextWithArtwork"; + CollectionShelfDisplayStyle["BrickSmall"] = "BrickSmall"; + CollectionShelfDisplayStyle["BrickMedium"] = "BrickMedium"; + CollectionShelfDisplayStyle["BrickLarge"] = "BrickLarge"; + CollectionShelfDisplayStyle["Charts"] = "Charts"; + CollectionShelfDisplayStyle["EditorialLockupHierarchicalPortrait"] = "EditorialLockupHierarchicalPortrait"; + CollectionShelfDisplayStyle["EditorialLockupHierarchicalRows"] = "EditorialLockupHierarchicalRows"; + CollectionShelfDisplayStyle["EditorialLockupMedium"] = "EditorialLockupMedium"; + CollectionShelfDisplayStyle["EditorialLockupMediumVariant"] = "EditorialLockupMediumVariant"; + CollectionShelfDisplayStyle["EditorialLockupLarge"] = "EditorialLockupLarge"; + CollectionShelfDisplayStyle["EditorialLockupLargeVariant"] = "EditorialLockupLargeVariant"; + CollectionShelfDisplayStyle["LockupMedium"] = "LockupMedium"; + CollectionShelfDisplayStyle["Lockup4Up"] = "Lockup4Up"; + CollectionShelfDisplayStyle["Poster"] = "Poster"; + CollectionShelfDisplayStyle["StorySmall"] = "StorySmall"; + CollectionShelfDisplayStyle["StoryMedium"] = "StoryMedium"; + CollectionShelfDisplayStyle["LockupSmall"] = "LockupSmall"; + CollectionShelfDisplayStyle["LockupLarge"] = "LockupLarge"; + CollectionShelfDisplayStyle["BreakoutLarge"] = "BreakoutLarge"; +})(CollectionShelfDisplayStyle || (CollectionShelfDisplayStyle = {})); +/** + * Returns the limit for a collection shelf to display in a non-See All page. + * @param {CollectionShelfDisplayStyle} displayStyle Collection shelf display style. + * @returns {number | undefined} Number of items to display. + */ +export function displayLimitForCollectionShelf(displayStyle, layoutDirection, shelfToken) { + if (!preprocessor.GAMES_TARGET || shelfToken.isSeeAll) { + return undefined; + } + switch (displayStyle) { + case CollectionShelfDisplayStyle.EditorialLockupLarge: + // "2 Cards" style https://quip-apple.com/qjjZAy4x977f + return layoutDirection === "Condensed" ? 2 : undefined; + case CollectionShelfDisplayStyle.EditorialLockupHierarchicalPortrait: + // "3 Cards" style https://quip-apple.com/qjjZAy4x977f + return 3; + case CollectionShelfDisplayStyle.EditorialLockupMedium: + // "4 Cards (4up)" style https://quip-apple.com/qjjZAy4x977f + return layoutDirection === "Condensed" ? 4 : undefined; + case CollectionShelfDisplayStyle.EditorialLockupHierarchicalRows: + // "4 Cards (Hierarchical)" style https://quip-apple.com/qjjZAy4x977f + return 4; + case CollectionShelfDisplayStyle.Charts: + // "4 Cards (Charts)" style https://quip-apple.com/qjjZAy4x977f + return 6; + case CollectionShelfDisplayStyle.LockupSmall: + // "6 Rows" style https://quip-apple.com/qjjZAy4x977f + return layoutDirection === "Condensed" ? 9 : undefined; + default: + return undefined; + } +} +/** + * Returns the display style override for See All pages. + * @param {CollectionShelfDisplayStyle} displayStyle Collection shelf display style. + * @returns {number | undefined} Number of items to display. + */ +export function collectionDisplayStyleOverride(displayStyle) { + if (!preprocessor.GAMES_TARGET || isNothing(displayStyle)) { + return null; + } + switch (displayStyle) { + // These shelves should maintain their display style in See All pages. + case CollectionShelfDisplayStyle.BrickSmall: + case CollectionShelfDisplayStyle.LockupMedium: + return displayStyle; + // All other shelves will display in EditorialLockupLarge display style in See All pages. + default: + return CollectionShelfDisplayStyle.EditorialLockupLarge; + } +} +export var MarkerShelfKind; +(function (MarkerShelfKind) { + MarkerShelfKind["QuickLinks"] = "QuickLinks"; +})(MarkerShelfKind || (MarkerShelfKind = {})); +export var CollectionShelfLayoutDirection; +(function (CollectionShelfLayoutDirection) { + CollectionShelfLayoutDirection["Vertical"] = "Vertical"; + CollectionShelfLayoutDirection["Horizontal"] = "Horizontal"; + CollectionShelfLayoutDirection["Condensed"] = "Condensed"; +})(CollectionShelfLayoutDirection || (CollectionShelfLayoutDirection = {})); +export function collectionShelfLayoutDirection(shelfToken) { + const layoutDirection = mediaAttributes.attributeAsString(shelfToken.data, "layoutDirection"); + if (layoutDirection === CollectionShelfLayoutDirection.Horizontal) { + return CollectionShelfLayoutDirection.Horizontal; + } + if (layoutDirection === CollectionShelfLayoutDirection.Condensed) { + return CollectionShelfLayoutDirection.Condensed; + } + // Make default one as vertical for backward compatibility when code used to check `=== "Horizontal"`. + return CollectionShelfLayoutDirection.Vertical; +} +export var CollectionShelfFilterOverride; +(function (CollectionShelfFilterOverride) { + CollectionShelfFilterOverride["ShowInstalled"] = "ShowInstalled"; + CollectionShelfFilterOverride["ShowAllPlatforms"] = "ShowAllPlatforms"; + CollectionShelfFilterOverride["ShowOnlyPreorder"] = "ShowOnlyPreorder"; +})(CollectionShelfFilterOverride || (CollectionShelfFilterOverride = {})); +export var GameCenterShelfClientFilter; +(function (GameCenterShelfClientFilter) { + GameCenterShelfClientFilter["AllGames"] = "AllGames"; + GameCenterShelfClientFilter["ArcadeGames"] = "ArcadeGames"; +})(GameCenterShelfClientFilter || (GameCenterShelfClientFilter = {})); +export var GameCenterShelfKind; +(function (GameCenterShelfKind) { + GameCenterShelfKind["FriendsArePlaying"] = "FriendsArePlaying"; + GameCenterShelfKind["ContinuePlaying"] = "ContinuePlaying"; +})(GameCenterShelfKind || (GameCenterShelfKind = {})); +export var UpsellShelfPlacement; +(function (UpsellShelfPlacement) { + UpsellShelfPlacement["ArcadeTabHeader"] = "ArcadeTabHeader"; +})(UpsellShelfPlacement || (UpsellShelfPlacement = {})); +export var UpsellShelfServiceType; +(function (UpsellShelfServiceType) { + UpsellShelfServiceType["Arcade"] = "Arcade"; +})(UpsellShelfServiceType || (UpsellShelfServiceType = {})); +//# sourceMappingURL=editorial-page-types.js.map
\ No newline at end of file diff --git a/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-shelf-collection-page-utils.js b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-shelf-collection-page-utils.js new file mode 100644 index 0000000..6544691 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/editorial-pages/editorial-shelf-collection-page-utils.js @@ -0,0 +1,120 @@ +import { isSome, unwrapOptional as unwrap } from "@jet/environment/types/optional"; +import { GenericPage, Shelf, PageHeader } from "../../api/models"; +import { makeEditorialShelfCollectionPageIntent, } from "../../api/intents/editorial/editorial-shelf-collection-page-intent"; +import { Request, defaultAdditionalPlatformsForClient } from "../../foundation/media/data-fetching"; +import { dataFromDataContainer } from "../../foundation/media/data-structure"; +import { attributeAsString } from "../../foundation/media/attributes"; +import { isDefinedNonNullNonEmpty } from "../../foundation/json-parsing/server-data"; +import { metricsPageInformationFromMediaApiResponse, addMetricsEventsToPageWithInformation, } from "../../common/metrics/helpers/page"; +import { newLocationTracker } from "../../common/metrics/helpers/location"; +import { createBaseShelfToken } from "../../common/editorial-pages/editorial-page-shelf-token"; +import { buildEditorialShelf } from "../../common/editorial-pages/editorial-page-shelf-builder"; +import { newPageRefreshControllerFromResponse, pageRefreshPolicyForController, } from "../../common/refresh/page-refresh-controller"; +import { shouldFetchCustomAttributes } from "../product-page/product-page-variants"; +import { prepareMAPIRequest } from "./editorial-page-controller-util"; +import { generateRoutes } from "../util/generate-routes"; +import { setPreviewPlatform } from "../preview-platform"; +import { makeGamesPageHeader } from "../../gameservicesui/src/editorial-page/editorial-component-builder"; +import { collectionShelfDisplayStyleFromShelfData } from "./editorial-data-util"; +import { collectionDisplayStyleOverride } from "./editorial-page-types"; +import { shouldUsePrerenderedIconArtwork } from "../content/content"; +// MARK: - `EditorialShelfCollectionPageIntentController` URL Building +const { routes: routesWithoutPlatformSegment, makeCanonicalUrl: makeCanonicalUrlWithoutPlatformSegment } = generateRoutes(makeEditorialShelfCollectionPageIntent, "/collections/{id}"); +const { routes: routesWithPlatformSegment, makeCanonicalUrl: makeCanonicalUrlWithPlatformSegment } = generateRoutes(makeEditorialShelfCollectionPageIntent, "/{platform}/collections/{id}"); +export function editorialShelfCollectionPageRoutes(objectGraph) { + return [...routesWithoutPlatformSegment(objectGraph), ...routesWithPlatformSegment(objectGraph)]; +} +export function makeEditorialShelfCollectionPageURL(objectGraph, intent) { + if (intent.platform) { + return makeCanonicalUrlWithPlatformSegment(objectGraph, intent); + } + else { + return makeCanonicalUrlWithoutPlatformSegment(objectGraph, intent); + } +} +// MARK: - Media API Request Building +export function defaultRequestAttributes(objectGraph) { + const attributes = [ + "editorialArtwork", + "editorialVideo", + "isAppleWatchSupported", + "requiredCapabilities", + "expectedReleaseDateDisplayFormat", + "showExpectedReleaseDate", + "badge-content", + "compatibilityControllerRequirement", + ]; + if (objectGraph.appleSilicon.isSupportEnabled) { + attributes.push("macRequiredCapabilities"); + } + if (objectGraph.client.isMac) { + attributes.push("hasMacIPAPackage"); + } + if (objectGraph.bag.enableUpdatedAgeRatings) { + attributes.push("ageRating"); + } + if (shouldUsePrerenderedIconArtwork(objectGraph)) { + attributes.push("iconArtwork"); + } + return attributes; +} +/** + * Creates a {@linkcode Request} to fetch a single `editorial-shelves-collection` item by {@linkcode id} + */ +export function makeEditorialShelfCollectionPageRequest(objectGraph, intent) { + const request = new Request(objectGraph, `/v1/editorial/${intent.storefront}`).withIdOfType(intent.id, "editorial-shelves-collection"); + request + .includingAgeRestrictions() + .includingAdditionalPlatforms(defaultAdditionalPlatformsForClient(objectGraph)) + .includingAttributes(defaultRequestAttributes(objectGraph)) + .usingCustomAttributes(shouldFetchCustomAttributes(objectGraph)); + if (objectGraph.client.isWatch) { + request.addingRelationshipLimit("contents", 3); + } + request + .includingRelationships(["contents"]) + .includingScopedRelationships("editorial-pages", ["primary-contents"]) + .includingAssociateKeys("editorial-shelves-collection:contents", ["editorial-cards"]); + prepareMAPIRequest(objectGraph, request); + setPreviewPlatform(objectGraph, request); + return request; +} +// MARK: - Editorial Shelves Collection Page Rendering +export function renderEditorialShelfCollectionPage(objectGraph, data) { + var _a; + const shelfData = dataFromDataContainer(objectGraph, data); + if (!isDefinedNonNullNonEmpty(shelfData)) { + return null; + } + const metricsPageInformation = metricsPageInformationFromMediaApiResponse(objectGraph, "Room", shelfData.id, data); + const metricsPageLocationTracker = newLocationTracker(); + const pageRefreshController = newPageRefreshControllerFromResponse(data); + const collectionDisplayStyle = collectionShelfDisplayStyleFromShelfData(objectGraph, shelfData); + const shelfToken = createBaseShelfToken(objectGraph, undefined, shelfData, false, 0, metricsPageInformation, metricsPageLocationTracker, preprocessor.GAMES_TARGET, collectionDisplayStyleOverride(collectionDisplayStyle)); + const shelves = []; + const shelf = unwrap(buildEditorialShelf(objectGraph, undefined, shelfToken)); + shelf.title = null; + shelf.eyebrow = null; + shelf.isHorizontal = false; + const headerTitle = attributeAsString(shelfData, "editorialNotes.name"); + if (isSome(headerTitle)) { + // There must be a title to create a pageHeader. + const headerShelf = new Shelf("pageHeader"); + headerShelf.id = "shelf_page_header"; + let pageHeader; + if (preprocessor.GAMES_TARGET) { + pageHeader = makeGamesPageHeader(shelfToken, headerTitle, shelf.items, (_a = attributeAsString(shelfData, "editorialNotes.tagline")) !== null && _a !== void 0 ? _a : undefined); + } + else { + pageHeader = new PageHeader(null, headerTitle, attributeAsString(shelfData, "editorialNotes.tagline")); + } + headerShelf.items = [pageHeader]; + shelves.push(headerShelf); + } + shelves.push(shelf); + const page = new GenericPage(shelves); + page.pageRefreshPolicy = pageRefreshPolicyForController(objectGraph, pageRefreshController); + addMetricsEventsToPageWithInformation(objectGraph, page, metricsPageInformation); + return page; +} +//# sourceMappingURL=editorial-shelf-collection-page-utils.js.map
\ No newline at end of file |
