summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.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/arcade/render-arcade-see-all-games-page.js
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.js227
1 files changed, 227 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.js b/node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.js
new file mode 100644
index 0000000..f1d39e0
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/arcade/render-arcade-see-all-games-page.js
@@ -0,0 +1,227 @@
+import * as validation from "@jet/environment/json/validation";
+import { Shelf, Trailers, Video, } from "../../api/models";
+import { metricsFromMediaApiObject, } from "../../foundation/media/data-structure";
+import { hasAttributes } from "../../foundation/media/attributes";
+import { isDefinedNonNullNonEmpty, isNullOrEmpty } from "../../foundation/json-parsing/server-data";
+import { Parameters, Path, Protocol } from "../../foundation/network/url-constants";
+import { URL } from "../../foundation/network/urls";
+import * as lockups from "../../common/lockups/lockups";
+import * as metricsHelpersImpressions from "../../common/metrics/helpers/impressions";
+import * as videoDefaults from "../../common/constants/video-constants";
+import * as content from "../../common/content/content";
+import { newLocationTracker, nextPosition, popLocation, pushContentLocation, } from "../metrics/helpers/location";
+export function createArcadeSeeAllGamesPaginationToken(_objectGraph, requestDescriptor, pageInformation) {
+ const locationTracker = newLocationTracker();
+ const paginationUrl = URL.fromComponents(Protocol.internal, null, `/${Path.arcadeSeeAllGames}/${Path.arcadeSeeAllGamesLoadMore}`).build();
+ const paginationToken = {
+ url: paginationUrl,
+ metricsPageInformation: pageInformation,
+ metricsLocationTracker: locationTracker,
+ remainingGroups: [],
+ lastShelfIndex: 0,
+ isCompactMode: requestDescriptor.isCompactMode,
+ };
+ return paginationToken;
+}
+export function createShelves(objectGraph, groups, paginationToken) {
+ return validation.context("createShelves", () => {
+ const shelves = [];
+ if (groups.length === 0) {
+ return shelves;
+ }
+ let shouldStartPagination = false;
+ for (const group of groups) {
+ // Start pagination if we hit a group who's first item has not been hydrated
+ shouldStartPagination = shouldStartPagination || !hasAttributes(group.data[0]);
+ if (shouldStartPagination) {
+ paginationToken.remainingGroups.push(group);
+ }
+ else {
+ const shelfToken = {
+ index: paginationToken.lastShelfIndex,
+ title: shelfTitleForGroup(objectGraph, group),
+ contentType: shelfContentTypeForMode(objectGraph, paginationToken.isCompactMode),
+ shouldFilter: false,
+ remainingContent: group.data,
+ groupKind: group.kind,
+ isCompactMode: paginationToken.isCompactMode,
+ hasExistingContent: false,
+ isFirstRender: true,
+ metricsPageInformation: paginationToken.metricsPageInformation,
+ metricsLocationTracker: paginationToken.metricsLocationTracker,
+ };
+ const shelf = createShelf(objectGraph, shelfToken);
+ shelves.push(shelf);
+ paginationToken.lastShelfIndex++;
+ }
+ }
+ return shelves;
+ });
+}
+const defaultRowsPerColumn = 3;
+export function createShelf(objectGraph, shelfToken) {
+ const shelfItems = [];
+ const shelf = new Shelf(shelfToken.contentType);
+ shelf.title = shelfToken.title;
+ shelf.presentationHints = { showSupplementaryText: false };
+ if (objectGraph.client.isVision) {
+ shelf.isHorizontal =
+ (shelfToken.groupKind === "comingSoonGrouping" && !shelfToken.isCompactMode) ||
+ shelfToken.groupKind === "category";
+ shelf.presentationHints = {
+ ...shelf.presentationHints,
+ isSAGComingSoon: true,
+ };
+ }
+ else {
+ shelf.isHorizontal = shelfToken.groupKind === "comingSoonGrouping" || shelfToken.groupKind === "category";
+ }
+ const shelfMetricsOptions = {
+ id: `${shelfToken.index}`,
+ kind: null,
+ softwareType: null,
+ targetType: "swoosh",
+ title: shelf.title,
+ pageInformation: shelfToken.metricsPageInformation,
+ locationTracker: shelfToken.metricsLocationTracker,
+ idType: "sequential",
+ };
+ /// add impression fields
+ metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfMetricsOptions);
+ pushContentLocation(objectGraph, shelfMetricsOptions, shelf.title);
+ while (isDefinedNonNullNonEmpty(shelfToken.remainingContent) && hasAttributes(shelfToken.remainingContent[0])) {
+ const lockupData = shelfToken.remainingContent.shift();
+ const lockupOptions = {
+ metricsOptions: {
+ pageInformation: shelfToken.metricsPageInformation,
+ locationTracker: shelfToken.metricsLocationTracker,
+ recoMetricsData: metricsFromMediaApiObject(lockupData),
+ },
+ artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */,
+ canDisplayArcadeOfferButton: content.shelfContentTypeCanDisplayArcadeOfferButtons(objectGraph, shelfToken.contentType),
+ shouldHideArcadeHeader: objectGraph.featureFlags.isEnabled("hide_arcade_header_on_arcade_tab"),
+ isContainedInPreorderExclusiveShelf: shelfToken.groupKind === "comingSoonGrouping",
+ };
+ const cropCode = objectGraph.client.isVision ? "sr" : null;
+ const lockup = lockups.mixedMediaLockupFromData(objectGraph, lockupData, lockupOptions, videoDefaults.defaultVideoConfiguration(objectGraph), null, cropCode);
+ const lockupHasVideos = ensureLockupHasVideos(objectGraph, lockup, lockupData);
+ if (!lockupHasVideos) {
+ continue;
+ }
+ lockup.editorialTagline = null;
+ lockup.developerTagline = null;
+ shelfItems.push(lockup);
+ nextPosition(shelfToken.metricsLocationTracker);
+ }
+ shelf.mergeWhenFetched = shelfToken.hasExistingContent;
+ shelfToken.hasExistingContent = shelfToken.hasExistingContent || shelfItems.length > 0;
+ shelf.items = shelfItems;
+ if (isDefinedNonNullNonEmpty(shelfToken.remainingContent)) {
+ shelf.url = shelfUrlForToken(shelfToken);
+ }
+ else if (objectGraph.client.deviceType !== "tv" &&
+ shelfToken.isCompactMode &&
+ shelf.items.length < defaultRowsPerColumn) {
+ shelf.rowsPerColumn = shelf.items.length;
+ }
+ popLocation(shelfToken.metricsLocationTracker);
+ return shelf;
+}
+function shelfContentTypeForMode(objectGraph, isCompactMode) {
+ if (isCompactMode) {
+ return "smallLockup";
+ }
+ else if (objectGraph.client.isTV) {
+ return "mixedMediaLockup";
+ }
+ else {
+ return "appTrailerLockup";
+ }
+}
+function shelfTitleForGroup(objectGraph, group) {
+ let shelfTitle;
+ let dateComponents = null;
+ let groupDateForTitle = null;
+ let sentence;
+ // rdar://104719340 (Arcade See All Games section has a missing name)
+ // Temporary(?) work around for MAPI sometimes not returning a group.name
+ if ((!group.name || group.name.length === 0) && group.kind !== "comingSoonGrouping") {
+ return "";
+ }
+ switch (group.kind) {
+ case "releaseDateByDay":
+ dateComponents = group.name.split("-");
+ groupDateForTitle = new Date(parseInt(dateComponents[0]), parseInt(dateComponents[1]) - 1, parseInt(dateComponents[2]));
+ sentence = objectGraph.loc.string("ALL_GAMES_SECTION_TITLE_RELEASE_DATE_SENTENCE");
+ shelfTitle = objectGraph.loc.formatDateInSentence(sentence, "MMMM d, y", groupDateForTitle);
+ break;
+ case "lastUpdatedByDay":
+ dateComponents = group.name.split("-");
+ groupDateForTitle = new Date(parseInt(dateComponents[0]), parseInt(dateComponents[1]) - 1, parseInt(dateComponents[2]));
+ sentence = objectGraph.loc.string("ALL_GAMES_SECTION_TITLE_LAST_UPDATED_SENTENCE");
+ shelfTitle = objectGraph.loc.formatDateInSentence(sentence, "MMMM d, y", groupDateForTitle);
+ break;
+ case "comingSoonGrouping":
+ shelfTitle = objectGraph.loc.string("Arcade.SeeAllGames.ComingSoonShelf.Title");
+ break;
+ default:
+ shelfTitle = group.name;
+ break;
+ }
+ return shelfTitle;
+}
+function shelfUrlForToken(shelfToken) {
+ if (isNullOrEmpty(shelfToken.remainingContent)) {
+ return null;
+ }
+ return `${Protocol.internal}:/${Path.arcadeSeeAllGames}/${Path.shelf}/?${Parameters.token}=${encodeURIComponent(JSON.stringify(shelfToken))}`;
+}
+// region Fallback Data
+function ensureLockupHasVideos(objectGraph, lockup, lockupData) {
+ // In visionOS, the bin-compat apps usually have trailer from iPad which using 4:3 video
+ // But SAG lockup preferred 16:9 video, so even we already have lockup.trailers, we still want to override it
+ // with the editorial splash video `splashVideo16x9`.
+ // If there is no editorial splash video found, we fallback to the current `lockup.trailers` or create a dump video.
+ if (isNullOrEmpty(lockup.trailers) || objectGraph.client.isVision) {
+ const uberVideo = content.editorialSplashVideoFromData(objectGraph, lockupData);
+ if (isDefinedNonNullNonEmpty(uberVideo)) {
+ const uberTrailer = new Trailers();
+ uberVideo.playbackControls = videoDefaults.standardControls(objectGraph);
+ uberVideo.autoPlayPlaybackControls = videoDefaults.autoPlayControls(objectGraph);
+ uberVideo.canPlayFullScreen = true;
+ uberTrailer.videos = [uberVideo];
+ lockup.trailers = [uberTrailer];
+ }
+ }
+ if (isNullOrEmpty(lockup.trailers)) {
+ /**
+ * <rdar://problem/55328972> See All Games: Bring back screenshots
+ * In the very rare case that an arcade game has absolutely no videos,
+ * that means no app trailer, no editorial video in any form. We're going to create a fake
+ * video that uses the first screenshot as a preview frame. This allows us to
+ * use the same AppTrailersLockup and get uniform sizing for lockups.
+ */
+ addFakeVideoToMixedMediaLockup(lockup);
+ }
+ return isDefinedNonNullNonEmpty(lockup.trailers);
+}
+const fakeVideoURL = "x-as3-internal:/today/test";
+function addFakeVideoToMixedMediaLockup(lockup) {
+ const screenshots = lockup.screenshots[0];
+ if (isNullOrEmpty(screenshots)) {
+ return;
+ }
+ const firstScreenshot = screenshots.artwork[0];
+ const fakeVideo = new Video(fakeVideoURL, firstScreenshot, {
+ allowsAutoPlay: false,
+ looping: false,
+ canPlayFullScreen: false,
+ autoPlayPlaybackControls: {},
+ playbackControls: {},
+ });
+ const fakeTrailers = new Trailers();
+ fakeTrailers.videos = [fakeVideo];
+ lockup.trailers = [fakeTrailers];
+}
+// endregion
+//# sourceMappingURL=render-arcade-see-all-games-page.js.map \ No newline at end of file