this repo has no description
1import * as validation from "@jet/environment/json/validation";
2import * as models from "../../api/models";
3import * as serverData from "../../foundation/json-parsing/server-data";
4import * as mediaAttributes from "../../foundation/media/attributes";
5import * as mediaDataStructure from "../../foundation/media/data-structure";
6import * as mediaRelationship from "../../foundation/media/relationships";
7import { Path, Protocol } from "../../foundation/network/url-constants";
8import * as client from "../../foundation/wrappers/client";
9import { watchosDeveloperRelationshipKey } from "./developer-request";
10import * as content from "../content/content";
11import * as lockups from "../lockups/lockups";
12import * as metricsHelpersClicks from "../metrics/helpers/clicks";
13import * as metricsHelpersImpressions from "../metrics/helpers/impressions";
14import * as metricsHelpersLocation from "../metrics/helpers/location";
15import * as metricsHelpersPage from "../metrics/helpers/page";
16import * as room from "../room/room-common";
17export class DeveloperRoomToken extends room.RoomPageToken {
18}
19/// Ordering of shelves for macOS developer page per Relationship key.
20/// @seealso mediaUrlMapping.macOSDeveloperRelationshipKeys
21const macosDeveloperRelationshipOrder = [
22 "latest-release-app",
23 "arcade-apps",
24 "app-bundles",
25 "mac-apps",
26 "mac-os-compatible-ios-apps",
27];
28/// Ordering of shelves for iOS developer page per Relationship key.
29/// @seealso mediaUrlMapping.iosDeveloperRelationshipKeys
30const iosDeveloperRelationshipOrder = [
31 "latest-release-app",
32 "arcade-apps",
33 "system-apps",
34 "app-bundles",
35 "ios-apps",
36 "imessage-apps",
37 "watch-apps",
38 "atv-apps",
39];
40/// The threshold for when to show the see all button.
41const seeAllThreshold = 8;
42/// Ordering of shelves for macOS developer page per Relationship key.
43/// @seealso mediaUrlMapping.macOSDeveloperRelationshipKeys
44const visionOSDeveloperRelationshipOrder = [
45 "latest-release-app",
46 "xros-apps",
47 "arcade-apps",
48 "ios-apps",
49];
50/// Ordering of shelves for the web developer page per Relationship key.
51/// @seealso mediaUrlMapping.macOSDeveloperRelationshipKeys
52const webDeveloperRelationshipOrder = [
53 "latest-release-app",
54 "system-apps",
55 "app-bundles",
56 "ios-apps",
57 "mac-apps",
58 "arcade-apps",
59 "xros-apps",
60 "atv-apps",
61 "watch-apps",
62 "imessage-apps",
63];
64export class DeveloperPageShelfToken {
65}
66export function developerPageFromResponse(objectGraph, response) {
67 return validation.context("developerPageFromResponse", () => {
68 const developerData = response.data.length ? response.data[0] : null;
69 if (!developerData) {
70 return null;
71 }
72 const metricsPageInformation = metricsHelpersPage.metricsPageInformationFromMediaApiResponse(objectGraph, "Artist", developerData.id, response);
73 const locationTracker = metricsHelpersLocation.newLocationTracker();
74 const shelves = shelvesForDeveloperData(objectGraph, developerData, metricsPageInformation, locationTracker);
75 // A single shelf should be vertical
76 if (shelves.length === 1) {
77 shelves[0].isHorizontal = false;
78 }
79 // Add developer description
80 const itunesNotes = content.notesFromData(objectGraph, developerData, "standard");
81 if (itunesNotes) {
82 const paragraph = new models.Paragraph(itunesNotes, "text/x-apple-as3-nqml");
83 const shelf = new models.Shelf("paragraph");
84 shelf.items = [paragraph];
85 shelves.unshift(shelf);
86 }
87 // Create the page
88 const page = new models.GenericPage(shelves);
89 page.title = mediaAttributes.attributeAsString(developerData, "name");
90 if (objectGraph.client.deviceType !== "watch") {
91 page.presentationOptions = ["prefersLargeTitle"];
92 }
93 page.canonicalURL = mediaAttributes.attributeAsString(developerData, "url");
94 // Setup metrics
95 metricsHelpersPage.addMetricsEventsToPageWithInformation(objectGraph, page, metricsPageInformation);
96 // Add the uber
97 const uber = mediaAttributes.attributeAsDictionary(developerData, "editorialArtwork.bannerUber");
98 if (uber && !objectGraph.client.isVision) {
99 const uberArtwork = content.artworkFromApiArtwork(objectGraph, uber, {
100 cropCode: "sr",
101 useCase: 21 /* content.ArtworkUseCase.Uber */,
102 });
103 page.uber = uberArtwork;
104 if (objectGraph.client.isiOS || objectGraph.client.isWeb) {
105 const uberShelf = new models.Shelf("uber");
106 const uberModel = new models.Uber("above");
107 uberModel.artwork = uberArtwork;
108 uberShelf.items = [uberModel];
109 uberModel.title = page.title;
110 shelves.unshift(uberShelf);
111 page.presentationOptions.push("prefersNonStandardBackButton");
112 if (!objectGraph.client.isWeb) {
113 page.presentationOptions.push("prefersOverlayedPageHeader");
114 }
115 }
116 }
117 return page;
118 });
119}
120function shelvesForDeveloperData(objectGraph, data, metricsPageInformation, locationTracker) {
121 switch (objectGraph.client.deviceType) {
122 case "mac":
123 return macosShelvesForDeveloperData(objectGraph, data, metricsPageInformation, locationTracker);
124 case "watch":
125 return flatShelvesForDeveloperData(objectGraph, "smallLockup", data, watchosDeveloperRelationshipKey, objectGraph.loc.string("DEVELOPER_WATCH"), metricsPageInformation, locationTracker);
126 case "vision":
127 return orderedShelvesForDeveloperData(objectGraph, data, visionOSDeveloperRelationshipOrder, metricsPageInformation, locationTracker);
128 case "web":
129 return orderedShelvesForDeveloperData(objectGraph, data, webDeveloperRelationshipOrder, metricsPageInformation, locationTracker);
130 default:
131 return orderedShelvesForDeveloperData(objectGraph, data, iosDeveloperRelationshipOrder, metricsPageInformation, locationTracker);
132 }
133}
134/**
135 * Returns the iOS shelf title for a given relationship.
136 * @param relationshipKey The relationship key.
137 * @param developerData Media API data for the developer page.
138 * @returns The localized shelf title.
139 */
140function iosShelfTitle(objectGraph, relationshipKey, developerData) {
141 switch (relationshipKey) {
142 case "latest-release-app":
143 return objectGraph.loc.string("DEVELOPER_LATEST_RELEASE");
144 case "system-apps":
145 return objectGraph.loc.string("DEVELOPER_SYSTEM_APPS");
146 case "imessage-apps":
147 return objectGraph.loc.string("DEVELOPER_IMESSAGE");
148 case "watch-apps":
149 return objectGraph.loc.string("DEVELOPER_WATCH");
150 case "atv-apps":
151 return objectGraph.loc.string("DEVELOPER_TV");
152 case "app-bundles":
153 return objectGraph.loc.string("DEVELOPER_BUNDLES");
154 case "xros-apps":
155 return objectGraph.loc.string("DEVELOPER_VISION");
156 case "ios-apps":
157 const hasApps = mediaAttributes.attributeAsBooleanOrFalse(developerData, "hasApps");
158 const hasGames = mediaAttributes.attributeAsBooleanOrFalse(developerData, "hasGames");
159 if (hasApps && hasGames) {
160 return objectGraph.loc.string("DEVELOPER_APPS_AND_GAMES");
161 }
162 else if (hasGames) {
163 return objectGraph.loc.string("DEVELOPER_GAMES");
164 }
165 else {
166 return objectGraph.loc.string("DEVELOPER_APPS");
167 }
168 case "arcade-apps":
169 return objectGraph.loc.string("DEVELOPER_APPLE_ARCADE");
170 default:
171 return null;
172 }
173}
174/**
175 * Returns the web shelf title for a given relationship.
176 * @param relationshipKey The relationship key.
177 * @param developerData Media API data for the developer page.
178 * @returns The localized shelf title.
179 */
180function webShelfTitle(objectGraph, relationshipKey, developerData) {
181 switch (relationshipKey) {
182 case "latest-release-app":
183 return objectGraph.loc.string("DEVELOPER_LATEST_RELEASE");
184 case "system-apps":
185 return objectGraph.loc.string("DEVELOPER_SYSTEM_APPS");
186 case "imessage-apps":
187 return objectGraph.loc.string("DEVELOPER_IMESSAGE");
188 case "watch-apps":
189 return objectGraph.loc.string("DEVELOPER_WATCH");
190 case "atv-apps":
191 return objectGraph.loc.string("DEVELOPER_TV");
192 case "app-bundles":
193 return objectGraph.loc.string("DEVELOPER_BUNDLES");
194 case "xros-apps":
195 return objectGraph.loc.string("DEVELOPER_VISION");
196 case "ios-apps":
197 return objectGraph.loc.string("DEVELOPER_PHONE_PAD_APPS");
198 case "arcade-apps":
199 return objectGraph.loc.string("DEVELOPER_APPLE_ARCADE");
200 case "mac-apps":
201 return objectGraph.loc.string("DEVELOPER_MAC_APPS");
202 case "mac-os-compatible-ios-apps":
203 return objectGraph.loc.string("DEVELOPER_PHONE_PAD_APPS");
204 default:
205 return null;
206 }
207}
208function orderedShelvesForDeveloperData(objectGraph, developerData, developerRelationshipOrdering, metricsPageInformation, locationTracker) {
209 var _a, _b;
210 if (objectGraph.host.isiOS) {
211 // Filter duplicate Arcade apps on iOS
212 filterDuplicateApps(developerData, "arcade-apps", ["ios-apps", "atv-apps"]);
213 }
214 let shelfContentType;
215 let artworkUseCase;
216 switch (objectGraph.client.deviceType) {
217 case "tv":
218 shelfContentType = "mediumLockup";
219 artworkUseCase = 2 /* content.ArtworkUseCase.LockupIconMedium */;
220 break;
221 case "web":
222 shelfContentType = "mediumLockup";
223 artworkUseCase = 2 /* content.ArtworkUseCase.LockupIconMedium */;
224 break;
225 default:
226 shelfContentType = "smallLockup";
227 artworkUseCase = 1 /* content.ArtworkUseCase.LockupIconSmall */;
228 break;
229 }
230 let shelfCount = 0;
231 const shelves = [];
232 for (const relationship of developerRelationshipOrdering) {
233 const dataContainer = mediaRelationship.relationship(developerData, relationship);
234 const sectionData = serverData.asArrayOrEmpty(dataContainer, "data");
235 const contentCount = sectionData.length;
236 if (contentCount === 0) {
237 continue;
238 }
239 // Skip the latest release shelf if there are no items
240 // Note: This typically happens on the Apple developer page
241 // if the latest release is a system app that you're not eligible for
242 if (relationship === "latest-release-app" && contentCount === 0) {
243 continue;
244 }
245 // Setup some content specific options
246 let clientIdentifier;
247 if (relationship === "imessage-apps") {
248 clientIdentifier = client.messagesIdentifier;
249 }
250 else if (relationship === "watch-apps") {
251 clientIdentifier = client.watchIdentifier;
252 }
253 else if (relationship === "atv-apps") {
254 clientIdentifier = client.tvIdentifier;
255 }
256 else {
257 clientIdentifier = client.appStoreIdentifier;
258 }
259 // Determine the title
260 let shelfTitle;
261 if (objectGraph.client.isWeb) {
262 shelfTitle = webShelfTitle(objectGraph, relationship, developerData);
263 }
264 else {
265 shelfTitle = iosShelfTitle(objectGraph, relationship, developerData);
266 }
267 // Create a metrics context
268 metricsHelpersLocation.pushContentLocation(objectGraph, {
269 pageInformation: metricsPageInformation,
270 locationTracker: locationTracker,
271 idType: "sequential",
272 id: `${shelfCount}`,
273 targetType: "swoosh",
274 }, shelfTitle);
275 // Create the shelf
276 const listOptions = {
277 lockupOptions: {
278 metricsOptions: {
279 pageInformation: metricsPageInformation,
280 locationTracker: locationTracker,
281 },
282 clientIdentifierOverride: clientIdentifier,
283 artworkUseCase: artworkUseCase,
284 },
285 filter: 76532 /* filtering.Filter.DeveloperPage */,
286 };
287 // Determine the ids we need to load
288 const remainingData = sectionData.filter((data) => {
289 return serverData.isNullOrEmpty(data.attributes);
290 });
291 // Vision doesn't support See All on developer page shelves currently.
292 const shouldShowSeeAll = (((_a = dataContainer.next) === null || _a === void 0 ? void 0 : _a.length) > 0 || contentCount >= seeAllThreshold) &&
293 !(objectGraph.client.isVision || objectGraph.client.isWeb);
294 const shelf = shelfForData(objectGraph, shelfTitle, developerData.id, sectionData, relationship, shelfContentType, listOptions, metricsPageInformation, locationTracker, dataContainer.href, shouldShowSeeAll);
295 // Ensure we're not too high
296 const itemCount = shelf.items.length + remainingData.length;
297 if (objectGraph.client.isVision) {
298 if (itemCount < 5) {
299 shelf.rowsPerColumn = 1;
300 }
301 else if (itemCount < 10) {
302 shelf.rowsPerColumn = 2;
303 }
304 else {
305 shelf.rowsPerColumn = 3;
306 }
307 }
308 else if (objectGraph.client.isWeb) {
309 shelf.rowsPerColumn = itemCount > 3 ? 2 : 1;
310 }
311 else if (itemCount < 3) {
312 shelf.rowsPerColumn = itemCount;
313 }
314 // Add metrics before serializing token for url
315 const shelfMetricsOptions = {
316 id: null,
317 kind: null,
318 softwareType: null,
319 targetType: "swoosh",
320 title: shelf.title,
321 pageInformation: metricsPageInformation,
322 locationTracker: locationTracker,
323 idType: null,
324 };
325 metricsHelpersLocation.popLocation(locationTracker);
326 metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfMetricsOptions);
327 metricsHelpersLocation.nextPosition(locationTracker);
328 if (remainingData.length) {
329 const token = new DeveloperPageShelfToken();
330 token.title = shelfTitle;
331 token.developerId = developerData.id;
332 token.contentType = shelfContentType;
333 token.remainingData = remainingData;
334 token.lockupListOptions = listOptions;
335 token.relationship = relationship;
336 token.roomUrl = dataContainer.href;
337 token.shouldShowSeeAll = shouldShowSeeAll;
338 token.hasExistingContent = serverData.isDefinedNonNullNonEmpty(shelf.items);
339 shelf.url =
340 `${Protocol.internal}:/${Path.developer}/${Path.shelf}/` + encodeURIComponent(JSON.stringify(token));
341 }
342 // Don't add the shelf if there are no items in it, and there is no more content to fetch.
343 if (shelf.items.length > 0 || ((_b = shelf.url) === null || _b === void 0 ? void 0 : _b.length) > 0) {
344 shelves.push(shelf);
345 shelfCount++;
346 }
347 }
348 return shelves;
349}
350/**
351 * Returns the macOS shelf title for a given relationship.
352 * @param relationshipKey The relationship key.
353 * @param developerData Media API data for the developer page.
354 * @returns The localized shelf title.
355 */
356function macosShelfTitle(objectGraph, relationshipKey, developerData) {
357 switch (relationshipKey) {
358 case "latest-release-app":
359 return objectGraph.loc.string("DEVELOPER_LATEST_RELEASE");
360 case "app-bundles":
361 return objectGraph.loc.string("DEVELOPER_BUNDLES");
362 case "mac-apps":
363 if (objectGraph.appleSilicon.isSupportEnabled) {
364 return objectGraph.loc.string("DEVELOPER_MAC_APPS");
365 }
366 else {
367 const hasApps = mediaAttributes.attributeAsBooleanOrFalse(developerData, "hasApps");
368 const hasGames = mediaAttributes.attributeAsBooleanOrFalse(developerData, "hasGames");
369 if (hasApps && hasGames) {
370 return objectGraph.loc.string("DEVELOPER_APPS_AND_GAMES");
371 }
372 else if (hasGames) {
373 return objectGraph.loc.string("DEVELOPER_GAMES");
374 }
375 else {
376 return objectGraph.loc.string("DEVELOPER_APPS");
377 }
378 }
379 case "mac-os-compatible-ios-apps":
380 return objectGraph.loc.string("DEVELOPER_PHONE_PAD_APPS");
381 case "arcade-apps":
382 return objectGraph.loc.string("DEVELOPER_APPLE_ARCADE");
383 default:
384 return null;
385 }
386}
387function macosShelvesForDeveloperData(objectGraph, developerData, metricsPageInformation, locationTracker) {
388 var _a;
389 // Filter duplicate apps
390 if (objectGraph.appleSilicon.isSupportEnabled) {
391 filterDuplicateApps(developerData, "arcade-apps", ["mac-apps", "mac-os-compatible-ios-apps"]);
392 filterDuplicateApps(developerData, "mac-apps", ["mac-os-compatible-ios-apps"]);
393 }
394 else {
395 filterDuplicateApps(developerData, "arcade-apps", ["mac-apps"]);
396 }
397 const shelfContentType = "smallLockup";
398 const artworkUseCase = 1 /* content.ArtworkUseCase.LockupIconSmall */;
399 let shelfCount = 0;
400 const shelves = [];
401 for (const relationship of macosDeveloperRelationshipOrder) {
402 const dataContainer = mediaRelationship.relationship(developerData, relationship);
403 const sectionData = serverData.asArrayOrEmpty(dataContainer, "data");
404 const contentCount = sectionData.length;
405 if (contentCount === 0) {
406 continue;
407 }
408 // Skip the latest release shelf if there are no items
409 // Note: This typically happens on the Apple developer page
410 // if the latest release is a system app that you're not eligible for
411 if (relationship === "latest-release-app" && contentCount === 0) {
412 continue;
413 }
414 // Determine the title
415 const shelfTitle = macosShelfTitle(objectGraph, relationship, developerData);
416 // Create a metrics context
417 metricsHelpersLocation.pushContentLocation(objectGraph, {
418 pageInformation: metricsPageInformation,
419 locationTracker: locationTracker,
420 idType: "sequential",
421 id: `${shelfCount}`,
422 targetType: "swoosh",
423 }, shelfTitle);
424 // Create the shelf
425 const listOptions = {
426 lockupOptions: {
427 metricsOptions: {
428 pageInformation: metricsPageInformation,
429 locationTracker: locationTracker,
430 },
431 artworkUseCase: artworkUseCase,
432 },
433 filter: 76532 /* filtering.Filter.DeveloperPage */,
434 };
435 // Determine the ids we need to load
436 const remainingData = sectionData.filter((data) => {
437 return serverData.isNullOrEmpty(data.attributes);
438 });
439 const shouldShowSeeAll = ((_a = dataContainer.next) === null || _a === void 0 ? void 0 : _a.length) > 0 || contentCount >= seeAllThreshold;
440 const shelf = shelfForData(objectGraph, shelfTitle, developerData.id, sectionData, relationship, shelfContentType, listOptions, metricsPageInformation, locationTracker, dataContainer.href, shouldShowSeeAll);
441 // Ensure we're not too high
442 const itemCount = shelf.items.length + remainingData.length;
443 if (itemCount < 3) {
444 shelf.rowsPerColumn = itemCount;
445 }
446 // Add metrics before serializing token for url
447 const shelfMetricsOptions = {
448 id: null,
449 kind: null,
450 softwareType: null,
451 targetType: "swoosh",
452 title: shelf.title,
453 pageInformation: metricsPageInformation,
454 locationTracker: locationTracker,
455 idType: null,
456 };
457 metricsHelpersLocation.popLocation(locationTracker);
458 metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfMetricsOptions);
459 metricsHelpersLocation.nextPosition(locationTracker);
460 if (remainingData.length) {
461 const token = new DeveloperPageShelfToken();
462 token.title = shelfTitle;
463 token.developerId = developerData.id;
464 token.contentType = "smallLockup";
465 token.remainingData = remainingData;
466 token.lockupListOptions = listOptions;
467 token.relationship = relationship;
468 token.roomUrl = dataContainer.href;
469 token.shouldShowSeeAll = shouldShowSeeAll;
470 token.hasExistingContent = serverData.isDefinedNonNullNonEmpty(shelf.items);
471 shelf.url =
472 `${Protocol.internal}:/${Path.developer}/${Path.shelf}/` + encodeURIComponent(JSON.stringify(token));
473 }
474 // Don't add the shelf if there are no items in it
475 if (shelf.items.length > 0) {
476 shelves.push(shelf);
477 shelfCount++;
478 }
479 }
480 return shelves;
481}
482/**
483 * Creates a list of apps for the given relationship type.
484 */
485function flatShelvesForDeveloperData(objectGraph, contentType, developerData, relationshipType, shelfTitle, metricsPageInformation, locationTracker) {
486 const dataCollection = mediaRelationship.relationshipCollection(developerData, relationshipType);
487 const listOptions = {
488 lockupOptions: {
489 metricsOptions: {
490 pageInformation: metricsPageInformation,
491 locationTracker: locationTracker,
492 },
493 artworkUseCase: 1 /* content.ArtworkUseCase.LockupIconSmall */,
494 },
495 filter: 76532 /* filtering.Filter.DeveloperPage */,
496 };
497 // Create a metrics context
498 metricsHelpersLocation.pushContentLocation(objectGraph, {
499 pageInformation: metricsPageInformation,
500 locationTracker: locationTracker,
501 idType: "sequential",
502 id: `0`,
503 targetType: "swoosh",
504 }, shelfTitle);
505 const shelf = shelfForData(objectGraph, shelfTitle, developerData.id, dataCollection, relationshipType, contentType, listOptions, metricsPageInformation, locationTracker, null, false);
506 // Determine the ids we need to load
507 const remainingData = dataCollection.filter((data) => {
508 return serverData.isNullOrEmpty(data.attributes);
509 });
510 // Add metrics before serializing token for url
511 const shelfMetricsOptions = {
512 id: null,
513 kind: null,
514 softwareType: null,
515 targetType: "swoosh",
516 title: shelfTitle,
517 pageInformation: metricsPageInformation,
518 locationTracker: locationTracker,
519 idType: null,
520 };
521 metricsHelpersLocation.popLocation(locationTracker);
522 metricsHelpersImpressions.addImpressionFields(objectGraph, shelf, shelfMetricsOptions);
523 metricsHelpersLocation.nextPosition(locationTracker);
524 if (remainingData.length) {
525 const token = new DeveloperPageShelfToken();
526 token.title = shelfTitle;
527 token.developerId = developerData.id;
528 token.contentType = contentType;
529 token.remainingData = remainingData;
530 token.lockupListOptions = listOptions;
531 token.hasExistingContent = serverData.isDefinedNonNullNonEmpty(shelf.items);
532 shelf.url =
533 `${Protocol.internal}:/${Path.developer}/${Path.shelf}/` + encodeURIComponent(JSON.stringify(token));
534 }
535 return [shelf];
536}
537export function shelfForData(objectGraph, title, developerId, dataArray, developerRelationship, contentType, listOptions, pageInformation, locationTracker, roomUrl, includeSeeAll) {
538 const shelf = new models.Shelf(contentType);
539 shelf.title = title;
540 switch (contentType) {
541 case "screenshotsLockup":
542 shelf.items = lockups.screenshotsLockupsFromData(objectGraph, dataArray, listOptions);
543 shelf.isHorizontal = false;
544 shelf.presentationHints = { showSupplementaryText: false };
545 break;
546 case "smallLockup":
547 default:
548 shelf.items = lockups.lockupsFromData(objectGraph, dataArray, listOptions);
549 shelf.isHorizontal = objectGraph.client.deviceType !== "watch";
550 break;
551 }
552 if (includeSeeAll) {
553 // Create token for the see all room
554 const roomToken = new DeveloperRoomToken();
555 roomToken.title = title;
556 roomToken.url = roomUrl;
557 roomToken.developerId = developerId;
558 roomToken.relationshipId = developerRelationship;
559 roomToken.clientIdentifierOverride = listOptions.lockupOptions.clientIdentifierOverride;
560 const seeAllAction = new models.FlowAction("page");
561 seeAllAction.pageUrl = developerRoomUrlWithToken(objectGraph, roomToken);
562 seeAllAction.title = objectGraph.loc.string("ACTION_SEE_ALL");
563 seeAllAction.pageData = room.seeAllPage(objectGraph, title);
564 metricsHelpersClicks.addClickEventToSeeAllAction(objectGraph, seeAllAction, seeAllAction.pageUrl, {
565 pageInformation,
566 locationTracker,
567 });
568 shelf.seeAllAction = seeAllAction;
569 }
570 return shelf;
571}
572/**
573 * Determines the URL to use for the developer room page.
574 * @param {string} token The token to use.
575 * @returns {string} The string to use for the developer room page.
576 */
577function developerRoomUrlWithToken(objectGraph, token) {
578 if (!serverData.isDefinedNonNull(token)) {
579 return null;
580 }
581 return `${Protocol.internal}:/${Path.developer}/${Path.room}/` + encodeURIComponent(JSON.stringify(token));
582}
583/**
584 * Prune duplicate entries for apps that can appear in other shelves by modifying `developerData` in place.
585 * For example if `arcade-apps` relation contains id `12345`, we want to prune `12345` from shelves like "Games" and "Apple TV"
586 */
587function filterDuplicateApps(developerData, authoritativeRelationshipKey, filteredRelationshipKeys) {
588 const arcadeRelationship = mediaRelationship.relationship(developerData, authoritativeRelationshipKey);
589 if (serverData.isNull(arcadeRelationship)) {
590 return; // No arcade relationship
591 }
592 const arcadeApps = mediaDataStructure.dataCollectionFromDataContainer(arcadeRelationship);
593 if (serverData.isNull(arcadeApps)) {
594 return; // No arcade relationship data
595 }
596 // IDs to filter from other shelves since they are in arcade shelf
597 const arcadeAppIds = arcadeApps.map((app) => app.id);
598 for (const relationshipKeyToFilter of filteredRelationshipKeys) {
599 const relationshipToFilter = mediaRelationship.relationship(developerData, relationshipKeyToFilter);
600 if (serverData.isNull(relationshipToFilter)) {
601 continue; // Skip if relationship didn't exist
602 }
603 const relationshipDataToFilter = mediaDataStructure.dataCollectionFromDataContainer(relationshipToFilter);
604 if (serverData.isNull(relationshipToFilter)) {
605 continue; // Skip if relationship had no `data`
606 }
607 // Overwrite with filtered data
608 developerData.relationships[relationshipKeyToFilter].data = relationshipDataToFilter.filter((data) => !arcadeAppIds.includes(data.id));
609 }
610}
611//# sourceMappingURL=developer-common.js.map