import { TodayCardDisplayStyle } from "./../../today/today-types"; /** * Builder for SearchLockupCollection. */ import { SearchLockupCollection } from "../../../api/models"; import { isDefinedNonNullNonEmpty, isNullOrEmpty } from "../../../foundation/json-parsing/server-data"; import { attributeAsArrayOrEmpty, attributeAsString } from "../../../foundation/media/attributes"; import { relationshipCollection } from "../../../foundation/media/relationships"; import { createArtworkForResource } from "../../content/artwork/artwork"; import { notesFromData } from "../../content/content"; import { currentEditorialCollectionTreatment, } from "../../../foundation/experimentation/search-results-experiments"; import { actionFromData, lockupsFromData } from "../../lockups/lockups"; import { addImpressionFields, impressionOptions } from "../../metrics/helpers/impressions"; import { popLocation, pushContentLocation } from "../../metrics/helpers/location"; import { cardDisplayStyleFromData } from "../../today/today-card-util"; import { editorialSearchResultTagline } from "./search-content-common"; /** * Whether or not a given result data should be rendered as `SearchLockupCollection` model. * Semantically, every `collection` should be rendered as a lockup collection, but collections are currently backed by many different types of articles. * @param resultData Data from results endpoint. * @param searchResponseMetadata Meta blob from initial search request. */ export function resultDataShouldRenderLockupCollection(objectGraph, resultData, searchResponseMetadata) { // Filter supported platforms if (!(objectGraph.host.isiOS || objectGraph.host.isVision)) { return false; } if (currentEditorialCollectionTreatment(objectGraph, searchResponseMetadata) !== 1 /* EditorialCollectionExperimentType.Swoosh */) { return false; } switch (resultData.type) { case "groupings": // Groupings can only be rendered if `contentIds` is present const collectionAdamIds = attributeAsArrayOrEmpty(resultData, "contentIds"); return isDefinedNonNullNonEmpty(collectionAdamIds); case "rooms": case "multirooms": // Rooms, and multirooms always render as collection. return true; case "editorial-items": // Some subtypes of editorial items render as collection. const cardDisplayStyle = cardDisplayStyleFromData(resultData); switch (cardDisplayStyle) { case TodayCardDisplayStyle.List: case TodayCardDisplayStyle.NumberedList: case TodayCardDisplayStyle.Grid: case TodayCardDisplayStyle.River: return true; default: return false; } default: return false; } } /** * Create a `SearchLockupCollection` from search results. * @param resultData Data from results endpoint. * @param lockupOptions Options for lockups shared throughout search results page. * @param metricsOptions Metrics context. */ export function lockupCollectionFromResultData(objectGraph, resultData, metricsOptions) { // Text const heading = lockupCollectionHeadingFromResultData(objectGraph, resultData); const headingArtwork = lockupCollectionHeadingArtworkFromResultData(objectGraph, resultData); const title = lockupCollectionTitleFromResultData(objectGraph, resultData); // Metrics for impression + location const lockupCollectionMetrics = impressionOptions(objectGraph, resultData, title, { targetType: "card", pageInformation: metricsOptions.pageInformation, locationTracker: metricsOptions.locationTracker, }); pushContentLocation(objectGraph, lockupCollectionMetrics, title); // Click Action ("See All") const clickMetrics = { actionType: "navigate", targetType: "button", pageInformation: metricsOptions.pageInformation, locationTracker: metricsOptions.locationTracker, id: "See All", idType: "sequential", }; const seeAllAction = actionFromData(objectGraph, resultData, clickMetrics, objectGraph.host.clientIdentifier); seeAllAction.title = objectGraph.loc.string("ACTION_SEE_ALL"); // Lockups const listOptions = { lockupOptions: { metricsOptions: { pageInformation: metricsOptions.pageInformation, locationTracker: metricsOptions.locationTracker, targetType: "lockup", }, skipDefaultClickAction: objectGraph.client.isVision, artworkUseCase: 8 /* ArtworkUseCase.SearchIcon */, hideCompatibilityBadge: objectGraph.client.isVision, }, filter: 128 /* Filter.UnsupportedPlatform */, }; let lockupData = relationshipCollection(resultData, "card-contents"); if (isNullOrEmpty(lockupData)) { lockupData = relationshipCollection(resultData, "top-apps"); } const items = lockupsFromData(objectGraph, lockupData, listOptions); popLocation(metricsOptions.locationTracker); // Lockup Collection const lockupCollection = new SearchLockupCollection(heading, title, items, seeAllAction, headingArtwork); addImpressionFields(objectGraph, lockupCollection, lockupCollectionMetrics); if (isNullOrEmpty(items)) { return null; } return lockupCollection; } // endregion // region Heading /** * Returns the title for given editorial results search results data. * @param resultData The result data to get a title for. */ function lockupCollectionTitleFromResultData(objectGraph, resultData) { const resultType = resultData.type; switch (resultType) { case "developers": return attributeAsString(resultData, "name"); default: return notesFromData(objectGraph, resultData, "name"); } } /** * Returns the heading for given editorial results search results data. * This builds on `editorialSearchResultTagline` with some additional search-specific logic * @param resultData The result data to get a heading for. */ function lockupCollectionHeadingFromResultData(objectGraph, resultData) { const resultType = resultData.type; if (resultType === "developers") { return objectGraph.loc.string("EDITORIAL_SEARCH_RESULT_TYPE_DEVELOPER_TITLE_CASE"); } const editorialTagline = editorialSearchResultTagline(objectGraph, resultData); if (isDefinedNonNullNonEmpty(editorialTagline)) { return editorialTagline; } if (objectGraph.client.isVision) { return objectGraph.loc.string("EDITORIAL_SEARCH_RESULT_TYPE_COLLECTION_TITLE_CASE"); } else { return objectGraph.loc.string("Search.EditorialSearchResultType.Heading.Collection"); } } /** * Returns the heading artwork to use for a given editorial search results data. * @param resultData The result data to get heading artwork for. */ function lockupCollectionHeadingArtworkFromResultData(objectGraph, resultData) { if (!objectGraph.client.isVision) { return null; } const resultType = resultData.type; let imageName; switch (resultType) { case "developers": imageName = "person.crop.square"; break; default: imageName = "appstore"; break; } return createArtworkForResource(objectGraph, `systemimage://${imageName}`); } // endregion //# sourceMappingURL=search-lockup-collection.js.map