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/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.js | 243 |
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 |
