summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/charts
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/charts
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/charts')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/charts/charts-hub.js39
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-model.js156
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-url.js12
3 files changed, 207 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-hub.js b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-hub.js
new file mode 100644
index 0000000..7c2da09
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-hub.js
@@ -0,0 +1,39 @@
+import { ChartsHubChart, ChartsHubPage, FlowAction } from "../../api/models";
+import { makeChartsPageIntent } from "../../api/intents/charts-page-intent";
+import { makeChartsPageURL } from "./charts-page-url";
+import { getLocale } from "../locale";
+import { getPlatform } from "../preview-platform";
+function seeAllActionForChart(objectGraph, chart) {
+ const selectedChart = chart.segments[chart.initialSegmentIndex].chart;
+ const seeAllAction = new FlowAction("topCharts");
+ const destinationIntent = makeChartsPageIntent({
+ ...getLocale(objectGraph),
+ ...getPlatform(objectGraph),
+ genreId: chart.genreId,
+ chart: selectedChart,
+ });
+ seeAllAction.destination = destinationIntent;
+ seeAllAction.pageUrl = makeChartsPageURL(objectGraph, destinationIntent);
+ return seeAllAction;
+}
+/**
+ * Create a {@linkcode TopChart} from a {@linkcode TopChartsPage} without any of the
+ * page-level properties defined
+ */
+function topChartFromPage(objectGraph, page, title) {
+ const chart = new ChartsHubChart(page.genreId, page.ageBandId, title, page.segments, page.categoriesButtonTitle, page.categories);
+ chart.initialSegmentIndex = page.initialSegmentIndex;
+ chart.seeAllAction = seeAllActionForChart(objectGraph, chart);
+ return chart;
+}
+/**
+ * Render a {@linkcode ChartsHubPage} from constituent {@linkcode TopChartsPage}s
+ */
+export function renderChartsHub(objectGraph, appsPage, gamesPage) {
+ const appsCharts = topChartFromPage(objectGraph, appsPage, objectGraph.loc.string("TopCharts.Hub.Apps.Title"));
+ const gamesCharts = topChartFromPage(objectGraph, gamesPage, objectGraph.loc.string("TopCharts.Hub.Games.Title"));
+ const hubPage = new ChartsHubPage([appsCharts, gamesCharts]);
+ hubPage.title = objectGraph.loc.string("TopCharts.Hub.Title");
+ return hubPage;
+}
+//# sourceMappingURL=charts-hub.js.map \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-model.js b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-model.js
new file mode 100644
index 0000000..cbbecf3
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-model.js
@@ -0,0 +1,156 @@
+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 \ No newline at end of file
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-url.js b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-url.js
new file mode 100644
index 0000000..2ecc0e2
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/charts/charts-page-url.js
@@ -0,0 +1,12 @@
+import { makeChartsPageIntent } from "../../api/intents/charts-page-intent";
+import { makeChartsHubPageIntent } from "../../api/intents/charts-hub-page-intent";
+import { generateRoutes } from "../util/generate-routes";
+/// MARK: Charts Detail Page Routing
+const { routes: chartsPageRoutes, makeCanonicalUrl: makeChartsPageURL } = generateRoutes(makeChartsPageIntent, "/{platform}/charts/{genreId}", [], {
+ optionalQuery: ["chart", "ageBandId"],
+});
+export { chartsPageRoutes, makeChartsPageURL };
+/// MARK: Charts Hub Page Routing
+const { routes: chartsHubPageRoutes, makeCanonicalUrl: makeChartsHubPageURL } = generateRoutes(makeChartsHubPageIntent, "/{platform}/charts");
+export { chartsHubPageRoutes, makeChartsHubPageURL };
+//# sourceMappingURL=charts-page-url.js.map \ No newline at end of file