// // breakouts-common.ts // AppStoreKit // // Created by Jonathan Ellenbogen on 11/19/19. // Copyright (c) 2016 Apple Inc. All rights reserved. // import { isNothing } 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 platformAttributes from "../../foundation/media/platform-attributes"; import * as mediaRelationship from "../../foundation/media/relationships"; import * as color from "../../foundation/util/color-util"; import { pageRouter } from "../builders/routing"; import * as contentAttributes from "../content/attributes"; import * as heroCommon from "../grouping/hero/hero-common"; import * as offers from "../offers/offers"; import * as productPageUtil from "../product-page/product-page-util"; import { makeProductPageIntent } from "../../api/intents/product-page-intent"; import { makeRoutableArticlePageIntent } from "../../api/intents/routable-article-page-intent"; import { getLocale } from "../locale"; import { makeRoutableArticlePageCanonicalUrl } from "../today/routable-article-page-url-utils"; import { getPlatform } from "../preview-platform"; export function detailBackgroundStyleFromData(objectGraph, breakoutData, supportsMaterial = true, isFirstShelf, isUpsell) { const heroVideoData = heroCommon.heroVideoFromData(objectGraph, breakoutData); const heroArtworkData = heroCommon.heroArtworkFromData(objectGraph, breakoutData); const backgroundColor = heroVideoData.backgroundColor || heroArtworkData.backgroundColor; const detailPosition = detailPositionFromData(objectGraph, breakoutData, isFirstShelf, isUpsell); const displayBreakoutMaterial = breakoutData.type === "marketing-items" ? serverData.asBooleanOrFalse(templateParametersFromData(objectGraph, breakoutData), "displayMaterial") : mediaAttributes.attributeAsBooleanOrFalse(breakoutData, "displayBreakoutMaterial"); const shouldUseMaterialBackground = displayBreakoutMaterial || (objectGraph.client.isTV && detailPosition === "center"); if (shouldUseMaterialBackground && supportsMaterial) { return "material"; } else { return detailBackgroundStyleFromColor(objectGraph, backgroundColor); } } export function detailBackgroundStyleFromColor(objectGraph, backgroundColor) { if (!backgroundColor) { return "dark"; } return color.isDarkColor(backgroundColor, 50) ? "dark" : "light"; } export function detailPositionFromData(objectGraph, data, isFirstShelf, isUpsell) { // Upsells always position the details in the center. if (objectGraph.client.isPhone || isUpsell) { return "center"; } if (objectGraph.client.isTV) { return isFirstShelf ? "center" : "leading"; } const breakoutDetailsString = data.type === "marketing-items" ? serverData.asString(templateParametersFromData(objectGraph, data), "textPosition") : mediaAttributes.attributeAsString(data, "breakoutTextAlignment"); if (isNothing(breakoutDetailsString) || breakoutDetailsString.length === 0) { return objectGraph.client.isMac ? "center" : "leading"; } switch (breakoutDetailsString.toLowerCase()) { case "left": return "leading"; case "center": return "center"; case "right": return "trailing"; default: return "leading"; } } /** * The text alignment to use for a particular detail position on large breakouts * @param position The positioning of the details within the breakout. */ export function detailTextAlignmentForDetailPosition(objectGraph, position, breakoutData, isUpsell = false) { const isTV = objectGraph.client.isTV; switch (position) { case "leading": return isTV ? "center" : "leading"; case "trailing": return isTV ? "center" : "leading"; case "center": if (isUpsell && !isTV) { return "center"; } else if (isTV) { return "leading"; } else { return breakoutData.type === "marketing-items" ? "center" : textAlignmentFromData(objectGraph, breakoutData); } default: return "leading"; } } function textAlignmentFromData(objectGraph, data) { var _a; const breakoutTextAlignmentString = (_a = mediaAttributes.attributeAsString(data, "breakoutTextAlignment")) !== null && _a !== void 0 ? _a : ""; switch (breakoutTextAlignmentString.toLowerCase()) { case "left": return "leading"; case "center": return "center"; case "right": return "trailing"; default: return objectGraph.client.isMac ? "center" : "leading"; } } export function templateParametersFromData(objectGraph, data) { if (data.type !== "marketing-items") { return null; } return mediaAttributes.attributeAsDictionary(data, "display.templateParameters"); } export function artworkDictionaryFromData(objectGraph, data) { switch (data.type) { case "editorial-items": return mediaAttributes.attributeAsDictionary(data, "editorialArtwork"); case "marketing-items": return mediaAttributes.attributeAsDictionary(data, "marketingArtwork"); default: const attributePlatform = contentAttributes.bestAttributePlatformFromData(objectGraph, data); return platformAttributes.platformAttributeAsDictionary(data, attributePlatform, "editorialArtwork"); } } export function videoDictionaryFromData(objectGraph, data) { switch (data.type) { case "editorial-items": return mediaAttributes.attributeAsDictionary(data, "editorialVideo"); case "marketing-items": return mediaAttributes.attributeAsDictionary(data, "marketingVideo"); default: if (preprocessor.GAMES_TARGET) { return mediaAttributes.attributeAsDictionary(data, "editorialVideo"); } else { const attributePlatform = contentAttributes.bestAttributePlatformFromData(objectGraph, data); return platformAttributes.platformAttributeAsDictionary(data, attributePlatform, "marketingVideo"); } } } export function callToActionLabelFromData(objectGraph, data) { switch (data.type) { case "marketing-items": const offerData = offers.offerDataFromMarketingItem(objectGraph, data); return serverData.asString(offerData, "callToActionLabel"); default: return mediaAttributes.attributeAsString(data, "breakoutCallToActionLabel"); } } 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; } export function wantsBlur(objectGraph, backgroundStyle, isInHeroPosition) { return backgroundStyle !== "material" && isInHeroPosition; } /** * The action to use when displaying a breakout's call to action button * @param data The breakout node data from MAPI */ export function actionFromData(objectGraph, data) { const linkData = mediaAttributes.attributeAsDictionary(data, "link"); const isLinkAction = serverData.isDefinedNonNullNonEmpty(linkData); const isProductAction = mediaAttributes.attributeAsString(data, "kind") === "App"; const isStoryAction = mediaAttributes.attributeAsBooleanOrFalse(data, "isCanvasAvailable"); const primaryContent = mediaRelationship.relationshipData(objectGraph, data, "primary-content"); if (!isLinkAction && !isStoryAction && !mediaAttributes.hasAttributes(primaryContent)) { return null; } let actionUrl = null; if (isLinkAction) { actionUrl = serverData.asString(linkData, "url"); } else if (isStoryAction) { actionUrl = mediaAttributes.attributeAsString(data, "url"); } else { actionUrl = mediaAttributes.attributeAsString(primaryContent, "url"); } if (serverData.isNull(actionUrl)) { return null; } let action = null; if (isLinkAction && serverData.asString(linkData, "target") === "external") { const externalUrlAction = new models.ExternalUrlAction(actionUrl); action = externalUrlAction; } else if (objectGraph.isAvailable(pageRouter)) { const flowPage = objectGraph.required(pageRouter).fetchFlowPage(actionUrl); const flowAction = new models.FlowAction(flowPage); flowAction.pageUrl = actionUrl; if (flowPage === "product") { flowAction.pageData = productPageUtil.createProductPageSidePackFromResponse(objectGraph, primaryContent); } action = flowAction; } else if (objectGraph.client.isWeb && isStoryAction) { const routableArticlePageIntent = makeRoutableArticlePageIntent({ ...getLocale(objectGraph), ...getPlatform(objectGraph), id: data.id, }); const flowAction = new models.FlowAction("article"); flowAction.title = mediaAttributes.attributeAsString(data, "breakoutCallToActionLabel"); flowAction.pageUrl = makeRoutableArticlePageCanonicalUrl(objectGraph, routableArticlePageIntent); flowAction.destination = routableArticlePageIntent; action = flowAction; } else if (objectGraph.client.isWeb && isProductAction) { const flowAction = new models.FlowAction("product"); flowAction.title = mediaAttributes.attributeAsString(data, "breakoutCallToActionLabel"); flowAction.pageUrl = actionUrl; flowAction.destination = makeProductPageIntent({ ...getLocale(objectGraph), ...getPlatform(objectGraph), id: primaryContent.id, }); action = flowAction; } if (action) { action.title = callToActionLabelFromData(objectGraph, data); } return action; } export function titleEffectFromArtwork(objectGraph, editorialArtworkData, isUpsell = false) { if (serverData.isNullOrEmpty(editorialArtworkData)) { return null; } let titleEffect = null; const white = color.named("white"); const black = color.named("black"); const backgroundColor = color.fromHex(serverData.asString(editorialArtworkData, "bgColor")); const gradientColors = serverData .asArrayOrEmpty(editorialArtworkData, "textGradient") .map((hexColor) => { return color.fromHex(hexColor); }); const backgroundStyle = detailBackgroundStyleFromColor(objectGraph, backgroundColor); const hasGradient = gradientColors.length === 2; if (hasGradient) { titleEffect = new models.TitleEffect("horizontalGradient"); const startColor = gradientColors[0]; const endColor = gradientColors[1]; titleEffect.gradientStartColor = color.dynamicWith(startColor, startColor); titleEffect.gradientEndColor = color.dynamicWith(endColor, endColor); titleEffect.filter = "plusLight"; if (!isUpsell) { titleEffect.accessoryColor = titleEffect.gradientEndColor; } } else { titleEffect = new models.TitleEffect("color"); titleEffect.color = backgroundStyle === "dark" ? white : black; if (!isUpsell) { titleEffect.accessoryColor = titleEffect.color; } titleEffect.isFallbackStyle = true; } // The accessory on tvOS should always be white resulting in a dark accessory. if (objectGraph.client.isTV) { titleEffect.accessoryColor = white; } return titleEffect; } //# sourceMappingURL=breakouts-common.js.map