import * as validation from "@jet/environment/json/validation"; import { unsafeUnwrapOptional as unwrap } from "@jet/environment/types/optional"; import { Shelf, TopChartSegment } from "../../api/models"; import * as serverData from "../../foundation/json-parsing/server-data"; import { Path, Protocol } from "../../foundation/network/url-constants"; import { addMetricsEventsToPageWithInformation, metricsPageInformationFromMediaApiResponse, } from "../metrics/helpers/page"; import { newLocationTracker, nextPosition } from "../metrics/helpers/location"; import { lockupFromData } from "../lockups/lockups"; import { shouldFilter } from "../filtering"; import { createMediaPageToken } from "../builders/pagination"; /** * Creates short and long display names for the top chart segment, * using server data unless client has overrides in `locKeys.json`. * * @param objectGraph The dependency graph for the App Store. * @param segmentData The top charts segment API object. * @param context The context of the chart, e.g. Apps or Games. * @returns Short and long display names for the top chart segment. */ function namesFromSegmentData(objectGraph, segmentData, context) { const chart = serverData.asString(segmentData, "chart"); // For the web client, regardless of whether the context is Apps or Games, we show "Free" or "Paid". if (objectGraph.client.isWeb) { return chart === "top-free" /* TopChartType.TopFree */ ? { shortName: objectGraph.loc.string("TopCharts.Free.ShortName"), longName: objectGraph.loc.string("TopCharts.Free.LongName"), } : { shortName: objectGraph.loc.string("TopCharts.Paid.ShortName"), longName: objectGraph.loc.string("TopCharts.Paid.LongName"), }; } // Use server provided names, unless we are in the Games tab or web client. let shortName = serverData.asString(segmentData, "shortName"); let longName = serverData.asString(segmentData, "name"); if (context !== 2 /* CategoryListContext.Games */) { return { shortName: unwrap(shortName), longName: unwrap(longName) }; } // Override server names with client names, e.g. from "Top Free/Paid iPad Apps" to "Top Free/Paid iPad Games" / "Top Free/Paid Vision Pro Games" as needed. const isPad = objectGraph.client.isPad; const isVision = objectGraph.client.isVision; switch (chart) { case "top-free" /* TopChartType.TopFree */: if (isPad) { shortName = objectGraph.loc.string("TopCharts.iPadGames.Free.ShortName"); // Free longName = objectGraph.loc.string("TopCharts.iPadGames.Free.LongName"); // Top Free iPad Games } else if (isVision) { shortName = objectGraph.loc.string("TopCharts.VisionGames.Free.ShortName"); // Free longName = objectGraph.loc.string("TopCharts.VisionGames.Free.LongName"); // Top Free Apple Vision Games } else { shortName = objectGraph.loc.string("TopCharts.Games.Free.ShortName"); // Free Games longName = objectGraph.loc.string("TopCharts.Games.Free.LongName"); // Top Free Games } break; case "top-paid" /* TopChartType.TopPaid */: if (isPad) { shortName = objectGraph.loc.string("TopCharts.iPadGames.Paid.ShortName"); // Paid longName = objectGraph.loc.string("TopCharts.iPadGames.Paid.LongName"); // Top Paid iPad Games } else if (isVision) { shortName = objectGraph.loc.string("TopCharts.VisionGames.Paid.ShortName"); // Paid longName = objectGraph.loc.string("TopCharts.VisionGames.Paid.LongName"); // Top Paid Apple Vision Games } else { shortName = objectGraph.loc.string("TopCharts.Games.Paid.ShortName"); // Paid Games longName = objectGraph.loc.string("TopCharts.Games.Paid.LongName"); // Top Paid Games } break; default: break; } return { shortName: unwrap(shortName), longName: unwrap(longName) }; } /** * Create a lockup from an api chart item. * @param index The index of the lockup in the chart. * @param data The mediaAPI chart item. * @returns A `Lockup` object. */ function lockupFromApiChartItem(objectGraph, index, data, metricsPageInformation, locationTracker) { return validation.context("lockupFromApiChartItem", () => { return lockupFromData(objectGraph, data, { ordinal: objectGraph.loc.decimal(index + 1), metricsOptions: { pageInformation: metricsPageInformation, locationTracker: locationTracker, }, artworkUseCase: 1 /* ArtworkUseCase.LockupIconSmall */, }); }); } /** * Creates a top chart segment model object from a top chart segment API object. * * @param objectGraph The dependency graph for the App Store. * @param segmentData The top chart segment API object. * @param response The top charts API object containing all segments. * @param genreId The genre of the chart, e.g. Developer Tools or Board. * @param context The context of the chart, e.g. Apps or Games. * @returns A new top chart segment model object. */ export function segmentFromData(objectGraph, segmentData, response, genreId, context) { return validation.context("segmentFromData", () => { const { shortName, longName } = namesFromSegmentData(objectGraph, segmentData, context); const chart = serverData.asString(segmentData, "chart"); const pageDetails = `${chart} ${longName}`; const pageInformation = metricsPageInformationFromMediaApiResponse(objectGraph, "TopChartsPage", genreId, response, pageDetails); const locationTracker = newLocationTracker(); const items = []; let ordinal = 0; const missingIds = []; for (const data of segmentData.data) { const lockup = lockupFromApiChartItem(objectGraph, ordinal, data, pageInformation, locationTracker); if (lockup) { // Filter only if segment has attributes if (shouldFilter(objectGraph, data, 68606 /* Filter.Charts */)) { continue; } items.push(lockup); nextPosition(locationTracker); ordinal++; } else { missingIds.push(data); } } const shelves = []; /// always generate a shelf else we don't load more items when we have none const shelf = new Shelf("smallLockup"); shelf.items = items; if (objectGraph.featureFlags.isEnabled("shelves_2_0_top_charts") || objectGraph.client.isiOS || objectGraph.client.isTV) { shelf.title = longName; } shelves.push(shelf); const segment = new TopChartSegment(shortName, longName, chart, shelves); // On Vision, include a URL for pagination - we don't use a specific Top Charts view, so we need the // `GenericPageMoreIntent` to be able to find this controller for loading new content. // This can be removed once visionOS adopts `TopChartsPageMoreIntent`. const paginationUrl = objectGraph.client.isVision ? `${Protocol.internal}:/TopChartsBuilder/${Path.lookup}` : undefined; const token = createMediaPageToken(objectGraph, missingIds, paginationUrl, segmentData.next, pageInformation, locationTracker); token.metricsPageInformation = pageInformation; token.metricsLocationTracker = locationTracker; token.highestOrdinal = ordinal; segment.nextPage = token; addMetricsEventsToPageWithInformation(objectGraph, segment, pageInformation); return segment; }); } //# sourceMappingURL=charts-page-model.js.map