summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/top-charts/top-charts-page.js
blob: 0f242795def8db7100317a4501375f8b1a9aa0d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { FetchTimingMetricsBuilder } from "@jet/environment/metrics/fetch-timing-metrics-builder";
import * as validation from "@jet/environment/json/validation";
import * as models from "../../api/models";
import * as mediaUrlMapping from "../../common/builders/url-mapping";
import * as categories from "../../common/categories";
import * as topChartsCommon from "../../common/top-charts-common";
import * as serverData from "../../foundation/json-parsing/server-data";
import { isSome } from "@jet/environment/types/optional";
import { makeChartsPageIntent } from "../../api/intents/charts-page-intent";
import { segmentFromData } from "../../common/charts/charts-page-model";
import { makeChartsPageURL } from "../../common/charts/charts-page-url";
import { getLocale } from "../../common/locale";
import { getPlatform } from "../../common/preview-platform";
import * as mediaDataStructure from "../../foundation/media/data-structure";
import * as mediaUrlBuilder from "../../foundation/media/url-builder";
import * as urls from "../../foundation/network/urls";
export async function fetchAndRenderTopChartPage(objectGraph, genreId, charts, selectedChart, ages) {
    if (serverData.isNullOrEmpty(charts)) {
        const siblingChart = topChartsCommon.lookupFallbackSiblingChart(objectGraph, selectedChart);
        if (siblingChart !== undefined) {
            charts = `${selectedChart},${siblingChart}`; // charts not provided, use hardcoded sibling along with selected chart
        }
        else {
            charts = selectedChart; // charts not provided, use selected chart
        }
    }
    else if (!charts.includes(selectedChart)) {
        charts += `,${selectedChart}`; // charts missing selected chart, so inject it.
    }
    // Request
    // Note: `FetchTimingMetricsBuilder` API currently only supports instrumenting a single primary network call.
    // We will choose to use the network metrics data from the top charts call.
    const fetchTimingMetricsBuilder = new FetchTimingMetricsBuilder();
    const modifiedObjectGraph = objectGraph.addingFetchTimingMetricsBuilder(fetchTimingMetricsBuilder);
    const topChartsPromise = topChartsCommon.fetchTopChartsData(modifiedObjectGraph, genreId, charts, ages);
    let categoriesRequestPromise;
    // Vision currently doesn't support displaying categories on the Charts page.
    if (!objectGraph.client.isVision) {
        categoriesRequestPromise = topChartsCommon.fetchCategoriesDataForPlatform(objectGraph, charts, genreId);
    }
    // Response
    return await Promise.all([topChartsPromise, categoriesRequestPromise]).then(([topChartsResponse, categoriesResponse]) => {
        return fetchTimingMetricsBuilder.measureModelConstruction(() => {
            const categoriesList = categories.categoryListFromApiResponse(objectGraph, categoriesResponse);
            const context = serverData.isNull(categoriesList)
                ? categories.createContextFromGenre(genreId)
                : categories.createContextFromList(categoriesList);
            return topChartsPageFromApiResponse(modifiedObjectGraph, topChartsResponse, genreId, categoriesList, selectedChart, context);
        });
    });
}
/**
 * Creates a Top Charts Page model object from a server data structure.
 *
 * @param objectGraph The object graph for the App Store.
 * @param response The server response to parse.
 * @param genreId The genre identifier of the genre to which this page belongs.
 * @param categoriesList The list of categories for top charts picker.
 * @param selectedChart The selected chart, typically shown in a segemented control.
 * @param context  The context of the charts, .e.g. All, Apps, or Games.
 * @returns A top charts page model object.
 */
export function topChartsPageFromApiResponse(objectGraph, response, genreId, categoriesList, selectedChart, context) {
    return validation.context("topChartsPageFromApiResponse", () => {
        var _a;
        // Categories
        const topChartsCategories = [];
        if (isSome(categoriesList)) {
            for (const categoryListItem of categoriesList.categories) {
                if (isSome(categoryListItem.genreId)) {
                    topChartsCategories.push(convertCategoryToTopChartsCategory(objectGraph, categoryListItem));
                }
            }
        }
        // Construct the segments and sort by chart name to prevent the order from changing
        const rawSegments = mediaDataStructure.chartResultsFromServerResponse(response);
        const segments = rawSegments
            .map((segment) => {
            return segmentFromData(objectGraph, segment, response, genreId, context);
        })
            .sort((a, b) => {
            return a.chart.localeCompare(b.chart);
        });
        const segmentHref = serverData.asString(rawSegments, "0.href");
        const segmentURL = new urls.URL(segmentHref);
        const segmentGenreId = (_a = segmentURL.query["genre"]) !== null && _a !== void 0 ? _a : genreId;
        const ages = segmentURL.query["ages"];
        const selectedCategory = findCategoryInTree(segmentGenreId, ages, topChartsCategories);
        const title = topChartsCommon.topChartsPageTitleForSegments(objectGraph, segments);
        // Build Page
        const topChartsPage = new models.TopChartsPage(segmentGenreId, selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.ageBandId, title, segments, selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.name, topChartsCategories);
        // The "web" client needs a `FlowAction` defined on each category and segment to perform navigation
        if (objectGraph.client.isWeb) {
            for (const category of topChartsCategories) {
                const destination = makeChartsPageIntent({
                    ...getLocale(objectGraph),
                    ...getPlatform(objectGraph),
                    genreId: category.genreId,
                    chart: selectedChart,
                    ageBandId: category.ageBandId,
                });
                const pageUrl = makeChartsPageURL(objectGraph, destination);
                const action = new models.FlowAction("topCharts");
                action.destination = destination;
                action.pageUrl = pageUrl;
                category.chartSelectAction = action;
            }
            for (const segment of segments) {
                const destination = makeChartsPageIntent({
                    ...getLocale(objectGraph),
                    ...getPlatform(objectGraph),
                    genreId,
                    chart: segment.chart,
                    ageBandId: selectedCategory === null || selectedCategory === void 0 ? void 0 : selectedCategory.ageBandId,
                });
                const pageUrl = makeChartsPageURL(objectGraph, destination);
                const action = new models.FlowAction("topCharts");
                action.destination = destination;
                action.pageUrl = pageUrl;
                segment.segmentSelectAction = action;
            }
        }
        // Find selected chart segment
        const selectedIndex = segments.findIndex((segment) => segment.chart === selectedChart);
        if (selectedIndex >= 0) {
            topChartsPage.initialSegmentIndex = selectedIndex;
        }
        // Decorate the final page model with network performance metrics.
        const fetchTimingMetricsBuilder = objectGraph.fetchTimingMetricsBuilder;
        if (isSome(fetchTimingMetricsBuilder)) {
            fetchTimingMetricsBuilder.decorate(topChartsPage);
        }
        return topChartsPage;
    });
}
export function convertCategoryToTopChartsCategory(objectGraph, category) {
    const topChartsPageRequest = mediaUrlMapping.mediaApiChartsRequest(objectGraph, category.genreId, category.ageBandId);
    const children = category.children.map((child) => convertCategoryToTopChartsCategory(objectGraph, child));
    return new models.TopChartCategory(category, mediaUrlBuilder.buildURLFromRequest(objectGraph, topChartsPageRequest).toString(), children);
}
/**
 * Recursively search through a category list to find a matching genre/age
 * @param genreId The genreId to search for
 * @param ageBandId The age band to include when searching for selected genre
 * @param categoryList The array of categories to search recursively through
 * @returns A found category, or null if not found.
 */
function findCategoryInTree(genreId, ageBandId, categoryList) {
    for (const category of categoryList) {
        if ((ageBandId && category.ageBandId === ageBandId) ||
            (!ageBandId && !category.ageBandId && category.genreId === genreId)) {
            return category;
        }
        const result = findCategoryInTree(genreId, ageBandId, category.children);
        if (result) {
            return result;
        }
    }
    return null;
}
//# sourceMappingURL=top-charts-page.js.map