diff options
| author | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
|---|---|---|
| committer | rxliuli <rxliuli@gmail.com> | 2025-11-04 05:03:50 +0800 |
| commit | bce557cc2dc767628bed6aac87301a1be7c5431b (patch) | |
| tree | b51a051228d01fe3306cd7626d4a96768aadb944 /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.js | 227 |
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 |
