summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.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/app-promotions/app-event.js
init commit
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.js243
1 files changed, 243 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.js b/node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.js
new file mode 100644
index 0000000..94eb7fe
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/app-promotions/app-event.js
@@ -0,0 +1,243 @@
+import { isNothing, isSome } from "@jet/environment";
+import * as models from "../../api/models";
+import * as serverData from "../../foundation/json-parsing/server-data";
+import * as mediaAttributes from "../../foundation/media/attributes";
+import * as mediaRelationship from "../../foundation/media/relationships";
+import * as color from "../../foundation/util/color-util";
+import * as dateUtil from "../../foundation/util/date-util";
+import * as appPromotionCommon from "./app-promotions-common";
+/**
+ * Creates an app event object or a Date, if the event should not yet be shown, from the given data.
+ * @param data The data blob
+ * @param parentAppData The related parent app of this app event. If not provided will be derived from `data`.
+ * @param hideLockupWhenNotInstalled Whether to hide the lockup chin when the app is installed
+ * @param includeClickAction Whether to generate a click action for the app event
+ * @param offerEnvironment The preferred environment for the offer
+ * @param offerStyle The preferred style of the offer
+ * @param includeCrossLinkTitles Whether the cross link titles will be displayed when the app is installed
+ * @param allowMissingParentApp Whether to still create the app event if the parent app is missing
+ * @param baseMetricsOptions The base metrics options
+ * @param allowEndedEvents Whether events in the past are allowed
+ * @param includeLockupClickAction Whether to include the click action for the lockup
+ * @param isArcadePage Whether or not this is presented on the Arcade page
+ * @param allowUnpublishedAppEventPreviews Whether or not to allow app event previews
+ * @returns an AppEvent, or a Date if the event's `promotionStartDate` is in the future.
+ */
+export function appEventOrPromotionStartDateFromData(objectGraph, data, parentAppData, hideLockupWhenNotInstalled, includeClickAction, offerEnvironment, offerStyle, includeCrossLinkTitles, baseMetricsOptions, allowEndedEvents, includeLockupClickAction, editorialKind, isArcadePage, allowUnpublishedAppEventPreviews) {
+ var _a, _b, _c;
+ if (data.type !== "app-events") {
+ return null;
+ }
+ const promotionStartDateString = mediaAttributes.attributeAsString(data, "promotionStartDate");
+ if (isNothing(promotionStartDateString) || promotionStartDateString.length === 0) {
+ return null;
+ }
+ const promotionStartDate = new Date(promotionStartDateString);
+ if (isNothing(promotionStartDate)) {
+ return null;
+ }
+ const todayDate = new Date();
+ const isFutureDate = promotionStartDate.getTime() > todayDate.getTime();
+ if (isFutureDate && !allowUnpublishedAppEventPreviews) {
+ return promotionStartDate;
+ }
+ // Artwork / video
+ const moduleArtwork = appPromotionCommon.artworkFromData(objectGraph, data, "lockupArtwork");
+ const moduleVideo = appPromotionCommon.videoFromData(objectGraph, data, "lockupVideo", false, false);
+ if (isNothing(moduleArtwork) && serverData.isNullOrEmpty(moduleVideo)) {
+ return null;
+ }
+ const selectedArtwork = (_a = moduleVideo === null || moduleVideo === void 0 ? void 0 : moduleVideo.preview) !== null && _a !== void 0 ? _a : moduleArtwork;
+ const isArtworkDark = color.isDarkColor(selectedArtwork === null || selectedArtwork === void 0 ? void 0 : selectedArtwork.backgroundColor);
+ const mediaOverlayStyle = isArtworkDark ? "dark" : "light";
+ const includeBorderInDarkMode = color.isDarkColor(selectedArtwork === null || selectedArtwork === void 0 ? void 0 : selectedArtwork.backgroundColor, 10);
+ // Other required fields
+ const title = mediaAttributes.attributeAsString(data, "name");
+ let kind = mediaAttributes.attributeAsString(data, "kind");
+ if (serverData.isDefinedNonNullNonEmpty(editorialKind)) {
+ kind = editorialKind;
+ }
+ const startDateString = mediaAttributes.attributeAsString(data, "startDate");
+ if (isNothing(title) ||
+ title.length === 0 ||
+ isNothing(kind) ||
+ kind.length === 0 ||
+ isNothing(startDateString) ||
+ startDateString.length === 0) {
+ return null;
+ }
+ const startDate = new Date(startDateString);
+ if (isNothing(startDate)) {
+ return null;
+ }
+ // Description
+ const detail = (_b = mediaAttributes.attributeAsString(data, "description.standard")) !== null && _b !== void 0 ? _b : "";
+ // Lockup
+ const resolvedParentAppData = parentAppData !== null && parentAppData !== void 0 ? parentAppData : mediaRelationship.relationshipData(objectGraph, data, "app");
+ let lockup = null;
+ if (isSome(resolvedParentAppData)) {
+ lockup = appPromotionCommon.lockupFromData(objectGraph, data, resolvedParentAppData, title, offerEnvironment, offerStyle, includeCrossLinkTitles, baseMetricsOptions, includeLockupClickAction, null, isArcadePage, true);
+ }
+ if (isNothing(lockup)) {
+ objectGraph.console.warn(`Parent app for event ${data.id} is missing, returning null.`);
+ return null;
+ }
+ // Requirements
+ const requirements = mediaAttributes.attributeAsString(data, "requirement");
+ // Supplementary optional fields
+ const subtitle = mediaAttributes.attributeAsString(data, "subtitle");
+ const endDateString = mediaAttributes.attributeAsString(data, "endDate");
+ let endDate;
+ if (isSome(endDateString) && endDateString.length > 0) {
+ endDate = new Date(endDateString);
+ }
+ const hasEventEnded = endDate !== undefined && endDate.getTime() <= todayDate.getTime();
+ if (hasEventEnded && !allowEndedEvents) {
+ return null;
+ }
+ // Formatted dates
+ const badgeKindString = (_c = mediaAttributes.attributeAsString(data, "badgeKind")) !== null && _c !== void 0 ? _c : undefined;
+ const badgeKind = badgeKindFromString(badgeKindString, startDate, endDate);
+ const formattedDates = formattedDatesWithKind(objectGraph, badgeKind, startDate, endDate);
+ const appEvent = new models.AppEvent(data.id, moduleArtwork !== null && moduleArtwork !== void 0 ? moduleArtwork : undefined, moduleVideo !== null && moduleVideo !== void 0 ? moduleVideo : undefined, title, subtitle !== null && subtitle !== void 0 ? subtitle : undefined, detail, startDate, endDate, badgeKind, kind, requirements !== null && requirements !== void 0 ? requirements : undefined, lockup, hideLockupWhenNotInstalled, formattedDates, mediaOverlayStyle, includeBorderInDarkMode);
+ // Notifications
+ if (serverData.isDefinedNonNull(resolvedParentAppData)) {
+ const clickOptions = {
+ ...baseMetricsOptions,
+ id: resolvedParentAppData.id,
+ inAppEventId: data.id,
+ relatedSubjectIds: [resolvedParentAppData.id],
+ };
+ appEvent.notificationConfig = appPromotionCommon.notificationConfigFromData(objectGraph, data, appEvent, clickOptions, true);
+ }
+ // Click action
+ if (includeClickAction && serverData.isDefinedNonNull(resolvedParentAppData)) {
+ appEvent.clickAction = appPromotionCommon.detailPageClickActionFromData(objectGraph, data, resolvedParentAppData, appEvent, baseMetricsOptions, includeLockupClickAction);
+ }
+ return appEvent;
+}
+/**
+ * Determines the badge kind from the given string.
+ * @param badgeKindString The raw badge kind string
+ * @param startDate The start date of the app event
+ * @param endDate The end date of the app event, if any
+ * @returns An AppEventBadgeKind
+ */
+export function badgeKindFromString(badgeKindString, startDate, endDate) {
+ let badgeKind = (badgeKindString !== null && badgeKindString !== void 0 ? badgeKindString : models.AppEventBadgeKind.live);
+ if (badgeKind === models.AppEventBadgeKind.live && serverData.isDefinedNonNull(endDate)) {
+ // If the event is longer than 6 hours, override with "happening now" so that
+ // the blinking red live dot is less prevalent.
+ const difference = endDate.getTime() - startDate.getTime();
+ const sixHoursDifference = 1000 * 60 * 60 * 6;
+ if (difference > sixHoursDifference) {
+ badgeKind = models.AppEventBadgeKind.happening;
+ }
+ }
+ return badgeKind;
+}
+/**
+ * Generates a list of all the possible date variants for a given app event. The native
+ * client will look at this list and determine which variant to display, based
+ * on the current time. The reason for sending down all variants is that the client will
+ * continue to update the display as time progresses, so it's feasible that the client will
+ * cross over from date variant to the next (eg. TOMORROW 12:00 PM -> TODAY 12:00 PM).
+ * @param badgeKind The kind of badge used
+ * @param startDate The start date of the app event
+ * @param endDate The end date of the app event, if any
+ */
+export function formattedDatesWithKind(objectGraph, badgeKind, startDate, endDate) {
+ const formattedDates = [];
+ const startMidnight = dateUtil.convertLocalDateToLocalMidnight(startDate);
+ if (isNothing(startMidnight)) {
+ // This is only possible if `startDate` is "nothing", which means we can't proceed to create formatted dates anyway.
+ return [];
+ }
+ // Event starts 7+ days from now
+ // Example: JAN 15
+ const introductionDateFormat = objectGraph.loc.string("AppEvents.FormattedDate.SevenDaysOrMore.DateFormat");
+ const introductionText = objectGraph.loc.uppercased(objectGraph.loc.formatDate(introductionDateFormat, startDate));
+ const introductionFormattedDate = new models.AppEventFormattedDate(false, undefined, introductionText !== null && introductionText !== void 0 ? introductionText : undefined, undefined, undefined);
+ formattedDates.push(introductionFormattedDate);
+ // Event starts 2-6 days from now
+ // Example: FRI 12:00 PM
+ const sixDaysPrior = new Date(startMidnight);
+ sixDaysPrior.setDate(sixDaysPrior.getDate() - 6);
+ const sixDaysPriorDateFormat = objectGraph.loc.string("AppEvents.FormattedDate.SixDaysOrLess.DateFormat");
+ const sixDaysPriorText = objectGraph.loc.formatDate(sixDaysPriorDateFormat, startDate);
+ const sixDaysPriorTextUppercased = objectGraph.loc.uppercased(sixDaysPriorText);
+ const sixDaysPriorFormattedDate = new models.AppEventFormattedDate(false, sixDaysPrior, sixDaysPriorTextUppercased !== null && sixDaysPriorTextUppercased !== void 0 ? sixDaysPriorTextUppercased : undefined, undefined, undefined);
+ formattedDates.push(sixDaysPriorFormattedDate);
+ // Event starts tomorrow
+ // Example: TOMORROW 12:00 PM
+ const oneDayPrior = new Date(startMidnight);
+ oneDayPrior.setDate(oneDayPrior.getDate() - 1);
+ const tomorrowSentence = objectGraph.loc.string("AppEvents.FormattedDate.Tomorrow");
+ const tomorrowText = objectGraph.loc.formatDateInSentence(tomorrowSentence, "j:mm", startDate);
+ const tomorrowTextUppercased = objectGraph.loc.uppercased(tomorrowText);
+ const tomorrowFormattedDate = new models.AppEventFormattedDate(false, oneDayPrior, tomorrowTextUppercased !== null && tomorrowTextUppercased !== void 0 ? tomorrowTextUppercased : undefined, undefined, undefined);
+ formattedDates.push(tomorrowFormattedDate);
+ // Event starts today
+ // If the event starts within 1 hour of midnight, we don't need to show this case
+ // as it will be superceded by the 1 hour countdown
+ // Example: TODAY 12:00 PM, TONIGHT 7:00 PM
+ if (startDate.getHours() > 1 || (startDate.getHours() === 1 && startDate.getMinutes() > 0)) {
+ let todaySentence;
+ if (startDate.getHours() >= 19) {
+ todaySentence = objectGraph.loc.string("AppEvents.FormattedDate.Tonight");
+ }
+ else {
+ todaySentence = objectGraph.loc.string("AppEvents.FormattedDate.Today");
+ }
+ const todayText = objectGraph.loc.formatDateInSentence(todaySentence, "j:mm", startDate);
+ const todayTextUppercased = objectGraph.loc.uppercased(todayText);
+ const todayFormattedDate = new models.AppEventFormattedDate(false, startMidnight !== null && startMidnight !== void 0 ? startMidnight : undefined, todayTextUppercased !== null && todayTextUppercased !== void 0 ? todayTextUppercased : undefined, undefined, undefined);
+ formattedDates.push(todayFormattedDate);
+ }
+ // Event is starting in 1 hour or less
+ // Example: STARTS IN 59 MIN / AVAILABLE IN 59 MIN
+ const oneHourPrior = new Date(startDate);
+ oneHourPrior.setHours(oneHourPrior.getHours() - 1);
+ let countdownStringKey;
+ switch (badgeKind) {
+ case models.AppEventBadgeKind.available:
+ countdownStringKey = "AppEvents.FormattedDate.AvailableIn.MinutesCountdown";
+ break;
+ case models.AppEventBadgeKind.happening:
+ case models.AppEventBadgeKind.live:
+ default:
+ countdownStringKey = "AppEvents.FormattedDate.StartsIn.MinutesCountdown";
+ break;
+ }
+ const oneHourPriorFormattedDate = new models.AppEventFormattedDate(false, oneHourPrior, undefined, startDate, countdownStringKey);
+ formattedDates.push(oneHourPriorFormattedDate);
+ // Event is happening now
+ // Example: LIVE, HAPPENING NOW, NOW AVAILABLE
+ let liveText;
+ let showLiveIndicator;
+ switch (badgeKind) {
+ case models.AppEventBadgeKind.available:
+ liveText = objectGraph.loc.string("AppEvents.FormattedDate.NowAvailable");
+ showLiveIndicator = false;
+ break;
+ case models.AppEventBadgeKind.happening:
+ liveText = objectGraph.loc.string("AppEvents.FormattedDate.HappeningNow");
+ showLiveIndicator = false;
+ break;
+ case models.AppEventBadgeKind.live:
+ default:
+ liveText = objectGraph.loc.string("AppEvents.FormattedDate.Live");
+ showLiveIndicator = true;
+ break;
+ }
+ const liveFormattedDate = new models.AppEventFormattedDate(showLiveIndicator, startDate, liveText, undefined, undefined);
+ formattedDates.push(liveFormattedDate);
+ // Event has ended
+ // Example: EVENT ENDED
+ if (endDate !== null) {
+ const eventEndedFormattedDate = new models.AppEventFormattedDate(false, endDate, objectGraph.loc.string("AppEvents.FormattedDate.EventEnded"), undefined, undefined);
+ formattedDates.push(eventEndedFormattedDate);
+ }
+ return formattedDates;
+}
+//# sourceMappingURL=app-event.js.map \ No newline at end of file