summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js b/node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js
new file mode 100644
index 0000000..c93843b
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/top-charts-common.js
@@ -0,0 +1,212 @@
+/**
+ * Common for top-charts.
+ * Incrementally migrate `top-charts-controller` builder logic here.
+ */
+import { isSome, isNothing } from "@jet/environment/types/optional";
+import * as categories from "../common/categories";
+import { isDefinedNonNullNonEmpty } from "../foundation/json-parsing/server-data";
+import { attributeAsString } from "../foundation/media/attributes";
+import { fetchData } from "../foundation/media/network";
+import { Parameters } from "../foundation/network/url-constants";
+import { URL } from "../foundation/network/urls";
+import * as client from "../foundation/wrappers/client";
+import { mediaApiChartRequestForGenre } from "./builders/url-mapping";
+// region API - URLs
+/**
+ * Given a chart type, lookup the most appropriate chart to show next to it using
+ * fallback mapping logic, e.g. `top-paid` for `top-free` and visa versa.
+ *
+ * MAINTAINERS NOTE: This is typically driven by Editorial's programming but this can be used as a fallback.
+ *
+ * @param objectGraph The App Store object graph.
+ * @param chartType The type of chart to lookup a sibling for, e.g. `top-free`.
+ * @returns The sibling of the provided chart type, e.g. `top-paid`.
+ */
+export function lookupFallbackSiblingChart(objectGraph, chartType) {
+ // Vision currently doesn't support sibling charts - don't attempt to find one.
+ if (isNothing(chartType) || objectGraph.client.isVision) {
+ return undefined;
+ }
+ switch (chartType) {
+ case "top-free" /* TopChartType.TopFree */:
+ return "top-paid" /* TopChartType.TopPaid */;
+ case "top-paid" /* TopChartType.TopPaid */:
+ return "top-free" /* TopChartType.TopFree */;
+ /*
+ ** MAINTAINERS NOTE **
+ We don't want to show "Top Apps" / "Paid Apps" for extensions, trending, or emerging,
+ so don't map these together until we can confirm the desired UX we want for this.
+
+ case TopChartType.TopFreeSafariExtensions:
+ return TopChartType.TopPaidSafariExtensions;
+ case TopChartType.TopPaidSafariExtensions:
+ return TopChartType.TopFreeSafariExtensions;
+ case TopChartType.TopFreeTrending:
+ return TopChartType.TopPaidTrending;
+ case TopChartType.TopPaidTrending:
+ return TopChartType.TopFreeTrending;
+ case TopChartType.TopFreeEmerging:
+ return TopChartType.TopPaidEmerging;
+ case TopChartType.TopPaidEmerging:
+ return TopChartType.TopFreeEmerging;
+ */
+ default:
+ return undefined;
+ }
+}
+/**
+ * Creates a charts parameter value for an invidual chart shelf's see all flow action URL, which may show multiple charts.
+ *
+ * ** MAINTAINERS NOTE **
+ * This function guarantees the selected chart is always included in charts.
+ * This helps make the user experience more resilient to either unexpected editorial programming or client JS programmer error.
+ * For example, if provided chart set is missing the selected chart or is missing any siblings, we lookup hardcoded fallback
+ * mappings, e.g. `top-paid` for `top-free`.
+ *
+ * @param objectGraph The App Store object graph.
+ * @param selectedChartType The selected chart, e.g. `top-free`.
+ * @param chartSet The collection fo charts to be shown as sibligs, e.g. `top-free` and `top-paid` in a segmented control
+ * @returns Value for charts URL query paramater.
+ */
+function makeChartsParameterValue(objectGraph, selectedChartType, chartSet) {
+ var _a;
+ const hasMultipleCharts = (_a = (chartSet === null || chartSet === void 0 ? void 0 : chartSet.editorialCharts.length) > 1) !== null && _a !== void 0 ? _a : false;
+ const charts = chartSet === null || chartSet === void 0 ? void 0 : chartSet.editorialCharts.map((chart) => chart.type.toString()).join(",");
+ // use editorially programmed chart set if defined with multiple charts, including the selection.
+ if (isSome(charts) && charts.includes(selectedChartType) && hasMultipleCharts) {
+ return charts;
+ }
+ // otherwise, lookup hardcoded fallback sibling if available, e.g. `top-paid` for `top-free`.
+ const siblingChartType = lookupFallbackSiblingChart(objectGraph, selectedChartType);
+ if (siblingChartType === undefined) {
+ return selectedChartType; // no sibling found, show just the single selected chart
+ }
+ return [selectedChartType, siblingChartType].join(","); // show harcoded pair of charts
+}
+/**
+ * Construct the URL for a single chart shelf "See All", that might be part of an editorial chart set.
+ * @param objectGraph The App Store object graph.
+ * @param chartData The media API data for the chart shelf, e.g. `top-paid`.
+ * @param chartSet The set of charts shown when tapping "See All", e.g. `top-free` and `top-paid`.
+ */
+export function makeSeeAllUrlFromMediaApiData(objectGraph, chartData, chartSet) {
+ const baseUrl = attributeAsString(chartData, "chartHref");
+ const chartSeeAllUrl = new URL(baseUrl);
+ /**
+ * The selected chart to show, e.g. `top-free`.
+ */
+ const selectedChart = attributeAsString(chartData, "chart");
+ if (isDefinedNonNullNonEmpty(selectedChart)) {
+ chartSeeAllUrl.param(Parameters.chart, selectedChart);
+ }
+ /**
+ * The collection of charts to show, e.g. `top-free` and `top-paid`.
+ * This is needed since a chart sets are vended down as a single fcKind item with children that is divided into multiple shelves.
+ * Tapping "See All" on a chart shelf, should show a top charts page with all `charts` provided and `chart` selected.
+ */
+ const charts = makeChartsParameterValue(objectGraph, selectedChart, chartSet);
+ if (isDefinedNonNullNonEmpty(charts)) {
+ chartSeeAllUrl.param(Parameters.charts, charts);
+ }
+ return chartSeeAllUrl.toString();
+}
+/**
+ * Returns whether or not given chart page URL charts parameter is for safari extensions.
+ * Charts for safari extensions must be handled as a special case since they don't have an associated specific genre.
+ *
+ * @param url The URL to check if it is Safari Extension charts.
+ */
+function isSafariExtensionCharts(charts) {
+ return (isDefinedNonNullNonEmpty(charts) &&
+ (charts.indexOf("top-free-safari-extensions" /* TopChartType.TopFreeSafariExtensions */) !== -1 ||
+ charts.indexOf("top-paid-safari-extensions" /* TopChartType.TopPaidSafariExtensions */) !== -1));
+}
+// endregion API
+// region MAPI Requests
+/**
+ * Fetch the top-level structural data for top charts.
+ *
+ * @param objectGraph The App Store object graph.
+ * @param genreId The genre to fetch charts for, e.g. Apps or Games.
+ * @param charts The specific charts in this genre.
+ */
+export async function fetchTopChartsData(objectGraph, genreId, charts, ages = null) {
+ // Request
+ const topChartsRequest = mediaApiChartRequestForGenre(objectGraph, genreId, charts, ages);
+ // Pagination + Sparse limits
+ topChartsRequest.withLimit(200);
+ if (objectGraph.client.isMac || objectGraph.client.isWeb) {
+ topChartsRequest.withSparseLimit(25);
+ }
+ topChartsRequest.enablingFeature("newChartsElements");
+ return await fetchData(objectGraph, topChartsRequest);
+}
+/**
+ * Fetch the categories data promise accompanying given `chartUrl`.
+ *
+ * @param objectGraph Object graph
+ * @param charts The charts to fetch categories data for, e.g. `top-free,top-paid`
+ * @param genreId The genre for chart to fetch categories data for, e.g. Apps or Games
+ */
+export async function fetchCategoriesDataForPlatform(objectGraph, charts, genreId) {
+ let categoriesRequestPromise;
+ /**
+ * No categories filter on:
+ * - All tvOS charts
+ * - All Messages AppStore charts
+ * - Safari Extension Charts (Genre-less Genre)
+ */
+ if (objectGraph.client.isTV ||
+ objectGraph.host.clientIdentifier === client.messagesIdentifier ||
+ isSafariExtensionCharts(charts)) {
+ categoriesRequestPromise = Promise.resolve({});
+ }
+ else {
+ const categoriesRequest = categories.createRequest(objectGraph, genreId);
+ categoriesRequestPromise = fetchData(objectGraph, categoriesRequest).catch(() => undefined);
+ }
+ return await categoriesRequestPromise;
+}
+// endregion
+// region Page Title
+/**
+ * Return the top charts page title to use for a collection of top chart segments.
+ *
+ * @param objectGraph Object graph
+ * @param segments The segments to derive page title for
+ */
+export function topChartsPageTitleForSegments(objectGraph, segments) {
+ const everySegmentIsTrending = segments.every((seg) => isTrendingChartType(seg.chart));
+ if (everySegmentIsTrending) {
+ return objectGraph.loc.string("PAGE_TITLE_TRENDING_CHARTS");
+ }
+ const everySegmentIsEmerging = segments.every((seg) => isEmergingChartType(seg.chart));
+ if (everySegmentIsEmerging) {
+ return objectGraph.loc.string("PAGE_TITLE_EMERGING_CHARTS");
+ }
+ return objectGraph.loc.string("PAGE_TITLE_TOP_CHARTS");
+}
+// endregion
+// region Top Charts Type
+/// Whether or not given chart type is trending chart type
+function isTrendingChartType(chart) {
+ switch (chart) {
+ case "top-trending-free" /* TopChartType.TopFreeTrending */:
+ case "top-trending-paid" /* TopChartType.TopPaidTrending */:
+ return true;
+ default:
+ return false;
+ }
+}
+/// Whether or not given chart type is emerging chart type
+function isEmergingChartType(chart) {
+ switch (chart) {
+ case "top-emerging-free" /* TopChartType.TopFreeEmerging */:
+ case "top-emerging-paid" /* TopChartType.TopPaidEmerging */:
+ return true;
+ default:
+ return false;
+ }
+}
+// endregion
+//# sourceMappingURL=top-charts-common.js.map \ No newline at end of file