From bce557cc2dc767628bed6aac87301a1be7c5431b Mon Sep 17 00:00:00 2001 From: rxliuli Date: Tue, 4 Nov 2025 05:03:50 +0800 Subject: init commit --- .../@jet-app/app-store/tmp/src/common/sharing.js | 428 +++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 node_modules/@jet-app/app-store/tmp/src/common/sharing.js (limited to 'node_modules/@jet-app/app-store/tmp/src/common/sharing.js') diff --git a/node_modules/@jet-app/app-store/tmp/src/common/sharing.js b/node_modules/@jet-app/app-store/tmp/src/common/sharing.js new file mode 100644 index 0000000..65c73b5 --- /dev/null +++ b/node_modules/@jet-app/app-store/tmp/src/common/sharing.js @@ -0,0 +1,428 @@ +// +// sharing.ts +// AppStoreKit +// +// Created by Sam Vafaee on 6/16/17. +// Copyright (c) 2016 Apple Inc. All rights reserved. +// +import { isNothing, isSome } from "@jet/environment"; +import * as validation from "@jet/environment/json/validation"; +import * as models from "../api/models"; +import * as serverData from "../foundation/json-parsing/server-data"; +import * as mediaAttributes from "../foundation/media/attributes"; +import { Parameters, ShareURLParameters } from "../foundation/network/url-constants"; +import * as urls from "../foundation/network/urls"; +import * as dateUtil from "../foundation/util/date-util"; +import * as client from "../foundation/wrappers/client"; +import * as contentArtwork from "./content/artwork/artwork"; +import * as contentAttributes from "./content/attributes"; +import * as content from "./content/content"; +import * as metricsHelpersClicks from "./metrics/helpers/clicks"; +import * as offers from "./offers/offers"; +import { productVariantDataForData, productVariantIDForVariantData } from "./product-page/product-page-variants"; +import { cardDisplayStyleFromData, editorialArtKeyPathForCardDisplayStyle, todayCardArtworkFromArtworkData, todayCardHeroArtForData, } from "./today/today-card-util"; +import { HeroMediaDisplayContext } from "./today/today-types"; +import { dataHasDeviceFamily, dataOnlyHasDeviceFamily } from "./content/device-family"; +// region Data helpers +export function adamIdForShareSheetGiftActivityFromProductData(objectGraph, data) { + if (!objectGraph.bag.isContentGiftingEnabled) { + return null; + } + if (serverData.isNull(data)) { + return null; + } + const offer = offers.offerDataFromData(objectGraph, data); + if (serverData.isNull(offer)) { + return null; + } + // Disable gifting for pre-orders + const isPreorder = mediaAttributes.attributeAsBoolean(data, "isPreorder"); + if (isPreorder) { + return null; + } + const price = serverData.asNumber(offer, "price"); + if (price > 0) { + return data.id; + } + return null; +} +/** + * Return the url for sharing for given product + * @param objectGraph Dependency soup + * @param data Apps Resource data for product + */ +function shareUrlForProductData(objectGraph, data, urlKey) { + const rawUrl = mediaAttributes.attributeAsString(data, urlKey); + if (serverData.isNullOrEmpty(rawUrl)) { + return null; + } + const url = new urls.URL(rawUrl); + // Add client specifier to url so apps are shown in the same client they were shared from + let clientSpecifier = null; + const clientIdentifier = objectGraph.host.clientIdentifier; + switch (clientIdentifier) { + case client.messagesIdentifier: + clientSpecifier = "messages"; + break; + case client.watchIdentifier: + clientSpecifier = "watch"; + break; + default: + break; + } + if (clientSpecifier) { + url.param(ShareURLParameters.clientSpecifier, clientSpecifier); + } + // Custom product page variant id must be added to `url` for MAPI resource caching constraints. + const productVariantData = productVariantDataForData(objectGraph, data); + const productVariantID = productVariantIDForVariantData(productVariantData); + if (serverData.isDefinedNonNull(productVariantID)) { + url.param(Parameters.productVariantID, productVariantID); + } + return url.toString(); +} +function notesMetadataFromProductData(objectGraph, data) { + return validation.context("notesMetadataFromProductData", () => { + var _a; + if (serverData.isNull(data)) { + return null; + } + const itemName = mediaAttributes.attributeAsString(data, "name"); + // Require name + if (isNothing(itemName) || itemName.length === 0) { + return null; + } + const url = shareUrlForProductData(objectGraph, data, "url"); + const developer = mediaAttributes.attributeAsString(data, "artistName"); + const category = mediaAttributes.attributeAsString(data, "genreNames.0"); + const fileSize = (_a = content.combinedFileSizeFromData(objectGraph, data)) === null || _a === void 0 ? void 0 : _a.fileSizeByDevice; + let mediaType; + switch (data.type) { + case "apps": { + mediaType = "app"; + break; + } + case "app-bundles": { + mediaType = "bundle"; + break; + } + case "in-apps": { + mediaType = "iap"; + break; + } + default: { + mediaType = null; + } + } + return new models.ShareSheetNotesMetadata(itemName, url, developer, category, fileSize, mediaType); + }); +} +function copyLinkShareSheetActivityForURL(objectGraph, url, title) { + if (serverData.isNullOrEmpty(url)) { + return null; + } + const copyTextAction = new models.CopyTextAction(url); + copyTextAction.title = title !== null && title !== void 0 ? title : objectGraph.loc.string("ShareSheet.CopyLink.Title"); + copyTextAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://link"); + const copyLinkActionActivity = new models.ShareSheetActivity("com.apple.AppStore.copyLinkActivity", copyTextAction); + return copyLinkActionActivity; +} +function openInGameCenterShareSheetActivityForURL(url, title) { + if (serverData.isNullOrEmpty(url)) { + return undefined; + } + const openURLAction = new models.ExternalUrlAction(url); + openURLAction.title = title; + const activity = new models.ShareSheetActivity("com.apple.AppStore.openInGameCenterActivity", openURLAction); + return activity; +} +// endregion +// region Article +export function shareSheetDataForArticle(objectGraph, text, url, shortUrl, articleArtwork, data) { + // Sharing is currently not supported on watchOS. + if (serverData.isNull(data) || objectGraph.client.isWatch) { + return null; + } + return validation.context("shareSheetDataForArticle", () => { + let artwork = articleArtwork; + if (isNothing(artwork) && isSome(data)) { + artwork = shareSheetArtForData(objectGraph, data); + } + const subtitle = objectGraph.loc.string("ShareSheet.Story.Subtitle"); + const articleMetadata = new models.ShareSheetArticleMetadata(data.id, text, subtitle, artwork); + return new models.ShareSheetData(articleMetadata, url, shortUrl); + }); +} +/** + * Determines the artwork to use in share sheets. + * @param {Data} data The data from which to retrieve the artwork. + * @returns {Artwork} The artwork suitable for display in the share sheet. + */ +export function shareSheetArtForData(objectGraph, data) { + const cardDisplayStyle = cardDisplayStyleFromData(data); + if (!objectGraph.client.isVision && !preprocessor.GAMES_TARGET) { + const heroArt = todayCardHeroArtForData(objectGraph, data, HeroMediaDisplayContext.Article, cardDisplayStyle); + if (serverData.isDefinedNonNull(heroArt)) { + return heroArt; + } + } + let cropCode; + if (objectGraph.client.isVision) { + cropCode = "SCS.ApDPCS01"; + } + const artKeyPath = editorialArtKeyPathForCardDisplayStyle(objectGraph, cardDisplayStyle); + return todayCardArtworkFromArtworkData(objectGraph, mediaAttributes.attributeAsDictionary(data, artKeyPath), cropCode); +} +export function shareSheetActivitiesForArticle(objectGraph, shareUrl, todayCardPreviewUrl, storyID) { + const shareSheetActivities = []; + if ((shareUrl === null || shareUrl === void 0 ? void 0 : shareUrl.length) > 0) { + const copyLinkActivity = copyLinkShareSheetActivityForURL(objectGraph, shareUrl); + if (serverData.isDefinedNonNull(copyLinkActivity)) { + shareSheetActivities.push(copyLinkActivity); + } + } + if ((todayCardPreviewUrl === null || todayCardPreviewUrl === void 0 ? void 0 : todayCardPreviewUrl.length) > 0) { + const copyCardPreviewLinkActivity = copyLinkShareSheetActivityForURL(objectGraph, todayCardPreviewUrl, "Copy Card Preview Link"); + if (serverData.isDefinedNonNull(copyCardPreviewLinkActivity)) { + shareSheetActivities.push(copyCardPreviewLinkActivity); + } + } + if (isSome(storyID)) { + let activity; + if (objectGraph.featureFlags.isGSEUIEnabled("de7bbd8e") && + objectGraph.featureFlags.isEnabled("open_in_story_share_sheet")) { + activity = openInGameCenterShareSheetActivityForURL(`games:///story/id${storyID}`, objectGraph.loc.string("ShareSheet.OpenInGameCenter.Title")); + } + if (serverData.isDefinedNonNull(activity)) { + shareSheetActivities.push(activity); + } + } + return shareSheetActivities; +} +// endregion +// region App Events +export function shareSheetDataForAppEvent(objectGraph, text, subtitle, url, shortUrl, appEventArtwork) { + return validation.context("shareSheetDataForAppEvent", () => { + const artwork = appEventArtwork; + const appEventMetadata = new models.ShareSheetAppEventMetadata(text, subtitle, artwork); + return new models.ShareSheetData(appEventMetadata, url, shortUrl); + }); +} +export function shareSheetActivitiesForAppEvent(objectGraph, appEvent, shareUrl) { + var _a; + const shareSheetActivities = []; + // Copy link action + if ((shareUrl === null || shareUrl === void 0 ? void 0 : shareUrl.length) > 0) { + const copyLinkActivity = copyLinkShareSheetActivityForURL(objectGraph, shareUrl); + if (serverData.isDefinedNonNull) { + shareSheetActivities.push(copyLinkActivity); + } + } + // If the event has already started, remove the option to create a calendar event + if (appEvent.startDate.getTime() <= Date.now()) { + return shareSheetActivities; + } + // Creating events is not supported in the product page extension + if (objectGraph.host.clientIdentifier === client.productPageExtensionIdentifier) { + return shareSheetActivities; + } + // Not authorized action + const notAuthorizedAction = new models.AlertAction("default"); + notAuthorizedAction.title = objectGraph.loc.string("APP_EVENTS_CALENDAR_NOT_AUTHORIZED_TITLE"); + notAuthorizedAction.message = objectGraph.loc.string("APP_EVENTS_CALENDAR_NOT_AUTHORIZED_DETAIL"); + notAuthorizedAction.isCancelable = true; + notAuthorizedAction.buttonTitles = [objectGraph.loc.string("ACTION_SETTINGS")]; + // NOTE: This URL only works on iOS. If this feature is expanded beyond iOS, this code will need to be split per-platform. + notAuthorizedAction.buttonActions = [new models.ExternalUrlAction("prefs:root=Privacy&path=CALENDARS", true)]; + let isAllDay = false; + if (serverData.isDefinedNonNull(appEvent.endDate)) { + // If the start and end date are > 6 hours apart, and spans over multiple days, then mark as all-day + const startMidnight = dateUtil.convertLocalDateToLocalMidnight(appEvent.startDate); + const endMidnight = dateUtil.convertLocalDateToLocalMidnight(appEvent.endDate); + const difference = appEvent.endDate.getTime() - appEvent.startDate.getTime(); + const sixHoursDifference = 1000 * 60 * 60 * 6; + if (endMidnight.getTime() > startMidnight.getTime() && difference > sixHoursDifference) { + isAllDay = true; + } + // If the start and end date are on the same day, and the event runs for 23 hours & 59 mins + // then mark as all-day. This effectively ignores the seconds portion as calendar ignores + // this anyway. + const fullDayDifference = 1000 * 60 * 60 * 23 + 1000 * 60 * 59; + if (startMidnight.getTime() === endMidnight.getTime() && difference >= fullDayDifference) { + isAllDay = true; + } + } + // Create calendar event activity + const createCalendarEventAction = new models.CreateCalendarEventAction(appEvent.startDate, appEvent.endDate, isAllDay, appEvent.title, (_a = appEvent.lockup) === null || _a === void 0 ? void 0 : _a.title, appEvent.detail, shareUrl, notAuthorizedAction, "free"); + createCalendarEventAction.title = objectGraph.loc.string("SHARE_SHEET_ADD_TO_CALENDAR"); + createCalendarEventAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://calendar.circle"); + const createCalendarEventActivity = new models.ShareSheetActivity("com.apple.AppStore.createCalendarEventActivity", createCalendarEventAction); + // Create Calendar Event should be at the beginning. + shareSheetActivities.unshift(createCalendarEventActivity); + return shareSheetActivities; +} +// endregion +// region Products +export function shareSheetDataForProductFromProductData(objectGraph, data, clientIdentifierOverride) { + return validation.context("shareSheetDataForProductFromProductData", () => { + // Sharing is currently not supported on watchOS or the web client. + if (serverData.isNull(data) || objectGraph.client.isWatch || objectGraph.client.isWeb) { + return null; + } + // required attributes + const url = shareUrlForProductData(objectGraph, data, "url"); + const title = mediaAttributes.attributeAsString(data, "name"); + const developerName = mediaAttributes.attributeAsString(data, "artistName"); + const adamId = data.id; + const storeFrontIdentifier = objectGraph.client.storefrontIdentifier; + // Sanity check + if (!url || !title || !developerName || !adamId) { + return null; + } + // optional attributes + const shortUrl = shareUrlForProductData(objectGraph, data, "shortUrl"); + let artwork = null; + let notesMetadata = null; + const screenshots = content.screenshotsFromData(objectGraph, data, 4 /* content.ArtworkUseCase.LockupScreenshots */); + const videos = content.videoPreviewsFromData(objectGraph, data); + const subtitle = contentAttributes.contentAttributeAsString(objectGraph, data, "subtitle") || developerName; + const genreName = null; + const isMessagesOnlyApp = false; + const messagesAppIcon = null; + // Platform + let platform; + const isMacOnlyApp = dataOnlyHasDeviceFamily(objectGraph, data, "mac"); + const isMacApp = dataHasDeviceFamily(objectGraph, data, "mac"); + if (isMacOnlyApp || (objectGraph.client.isMac && isMacApp)) { + platform = "Mac"; + } + else { + platform = "iOS"; + } + // Add product info + if (serverData.isDefinedNonNull(data) && mediaAttributes.attributeAsString(data, "url")) { + artwork = content.iconFromData(objectGraph, data, { + useCase: 1 /* content.ArtworkUseCase.LockupIconSmall */, + }, clientIdentifierOverride); + notesMetadata = notesMetadataFromProductData(objectGraph, data); + } + const productMetadata = new models.ShareSheetProductMetadata(adamId, storeFrontIdentifier, title, platform, artwork, screenshots, videos, isMessagesOnlyApp, subtitle, genreName, messagesAppIcon, notesMetadata); + return new models.ShareSheetData(productMetadata, url, shortUrl); + }); +} +export function shareProductActionFromData(objectGraph, data, metricsPageInformation, metricsLocationTracker, clientIdentifierOverride) { + return validation.context(`shareActionFromData: ${data.type}`, () => { + var _a; + const id = data.id; + switch (objectGraph.client.deviceType) { + case "mac": { + const shareSheetData = shareSheetDataForProductFromProductData(objectGraph, data); + // Share action + if (shareSheetData) { + const shareAction = new models.ShareSheetAction(shareSheetData, []); + metricsHelpersClicks.addClickEventToAction(objectGraph, shareAction, { + targetType: "button", + id: id, + actionType: "share", + pageInformation: metricsPageInformation, + locationTracker: metricsLocationTracker, + }); + return shareAction; + } + break; + } + case "phone": + case "pad": + case "vision": { + const shareSheetData = shareSheetDataForProductFromProductData(objectGraph, data, clientIdentifierOverride); + const shareSheetActivities = []; + // Copy link action + if (((_a = shareSheetData === null || shareSheetData === void 0 ? void 0 : shareSheetData.url) === null || _a === void 0 ? void 0 : _a.length) > 0) { + const copyLinkActivity = copyLinkShareSheetActivityForURL(objectGraph, shareSheetData.url); + if (serverData.isDefinedNonNull) { + shareSheetActivities.push(copyLinkActivity); + } + } + // Gift action + const giftAdamId = adamIdForShareSheetGiftActivityFromProductData(objectGraph, data); + if (giftAdamId) { + const giftAction = new models.FlowAction("finance"); + giftAction.presentationContext = "presentModal"; + giftAction.title = objectGraph.loc.string("SHARE_GIFT_APP"); + giftAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://app.gift"); + giftAction.pageUrl = `gift/${giftAdamId}`; + metricsHelpersClicks.addClickEventToAction(objectGraph, giftAction, { + targetType: "button", + id: id, + actionType: "gift", + actionContext: "shareSheet", + pageInformation: metricsPageInformation, + locationTracker: metricsLocationTracker, + }); + const giftActionActivity = new models.ShareSheetActivity("com.apple.AppStore.giftActivity", giftAction); + shareSheetActivities.push(giftActionActivity); + } + if (shareSheetData) { + // Share action + const shareSheetStyle = "expanded"; + const shareAction = new models.ShareSheetAction(shareSheetData, shareSheetActivities, shareSheetStyle); + shareAction.title = objectGraph.loc.string("SHARE_APP"); + shareAction.artwork = contentArtwork.createArtworkForResource(objectGraph, "systemimage://square.and.arrow.up"); + metricsHelpersClicks.addClickEventToAction(objectGraph, shareAction, { + targetType: "button", + id: id, + actionType: "share", + actionContext: "shareSheet", + pageInformation: metricsPageInformation, + locationTracker: metricsLocationTracker, + }); + return shareAction; + } + else if (shareSheetActivities.length > 0) { + // Map ActionActivity[] to Action[] as we're not dealing with a share sheet + const sheetActions = shareSheetActivities.map((activity) => activity.action); + // Create action sheet instead of share sheet + const sheetAction = new models.SheetAction(sheetActions); + sheetAction.isCancelable = true; + sheetAction.isCustom = true; + metricsHelpersClicks.addClickEventToAction(objectGraph, sheetAction, { + targetType: "button", + id: id, + actionType: "actionSheet", + pageInformation: metricsPageInformation, + locationTracker: metricsLocationTracker, + }); + return sheetAction; + } + break; + } + default: { + // These device types do not support sharing, so we don't create any share actions. + break; + } + } + return null; + }); +} +// region Generic Pages +export function shareSheetDataForGenericPage(objectGraph, text, url, subtitle, shortUrl, artwork) { + return validation.context("shareSheetDataForGenericPage", () => { + if (serverData.isNullOrEmpty(url)) { + return null; + } + const metadata = new models.ShareSheetGenericMetadata(text, subtitle, artwork !== null && artwork !== void 0 ? artwork : undefined); + return new models.ShareSheetData(metadata, url, shortUrl); + }); +} +export function shareSheetActivitiesForGenericPage(objectGraph, shareUrl) { + const shareSheetActivities = []; + if ((shareUrl === null || shareUrl === void 0 ? void 0 : shareUrl.length) > 0) { + const copyLinkActivity = copyLinkShareSheetActivityForURL(objectGraph, shareUrl); + if (serverData.isDefinedNonNull) { + shareSheetActivities.push(copyLinkActivity); + } + } + return shareSheetActivities; +} +// endregion +//# sourceMappingURL=sharing.js.map \ No newline at end of file -- cgit v1.2.3