@xapps-platform/marketplace-ui 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/MarketplaceApp.d.ts.map +1 -1
- package/dist/index.css +119 -0
- package/dist/index.css.map +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1144 -190
- package/dist/index.js.map +4 -4
- package/dist/marketplace.css +141 -0
- package/dist/pages/CatalogPage.d.ts.map +1 -1
- package/dist/pages/XappDetailPage.d.ts +3 -1
- package/dist/pages/XappDetailPage.d.ts.map +1 -1
- package/dist/pages/installationPolicy.test.d.ts +2 -0
- package/dist/pages/installationPolicy.test.d.ts.map +1 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -978,6 +978,14 @@ function getDefaultWidgetId(x) {
|
|
|
978
978
|
const pick = def || widgets[0];
|
|
979
979
|
return readFirstString(asRecord(pick).id) || null;
|
|
980
980
|
}
|
|
981
|
+
function getDefaultWidgetName(x, locale) {
|
|
982
|
+
const rawWidgets = asRecord(x.manifest).widgets;
|
|
983
|
+
const widgets = Array.isArray(rawWidgets) ? rawWidgets : null;
|
|
984
|
+
if (!widgets || widgets.length === 0) return null;
|
|
985
|
+
const def = widgets.find((w) => asRecord(w).default === true);
|
|
986
|
+
const pick = asRecord(def || widgets[0]);
|
|
987
|
+
return resolveMarketplaceText(pick.title, locale) || readFirstString(pick.name, pick.id) || null;
|
|
988
|
+
}
|
|
981
989
|
function buildCatalogFilterStorageKey(input) {
|
|
982
990
|
const mode = input.isEmbedded ? "embed" : "portal";
|
|
983
991
|
const scope = input.singleXappMode && input.xappId ? `xapp:${input.xappId}` : "catalog";
|
|
@@ -1011,6 +1019,11 @@ function CatalogPage() {
|
|
|
1011
1019
|
const canMutate = host.canMutate ? host.canMutate() : true;
|
|
1012
1020
|
const addAppLabel = env?.copy?.addAppLabel || "Add app";
|
|
1013
1021
|
const removeAppLabel = env?.copy?.removeAppLabel || "Remove app";
|
|
1022
|
+
const openAppLabel = env?.copy?.openAppLabel || t("xapp.open_app", void 0, "Open app");
|
|
1023
|
+
const installationPolicyResolved = env?.installationPolicyResolved !== false;
|
|
1024
|
+
const mutationControlsReady = installationPolicyResolved || !host.subjectId || !canMutate;
|
|
1025
|
+
const autoUpdateMode = mutationControlsReady && (env?.installationPolicy ?? host.installationPolicy)?.update_mode === "auto_update_compatible" && Boolean(host.subjectId);
|
|
1026
|
+
const autoAvailableMode = mutationControlsReady && (env?.installationPolicy ?? host.installationPolicy)?.mode === "auto_available" && Boolean(host.subjectId);
|
|
1014
1027
|
const loc = useLocation();
|
|
1015
1028
|
const token = useQueryToken();
|
|
1016
1029
|
const tokenSearch = buildTokenSearch(token, loc.search);
|
|
@@ -1075,6 +1088,14 @@ function CatalogPage() {
|
|
|
1075
1088
|
setInstalledOnly(Boolean(stored?.addedOnly));
|
|
1076
1089
|
setSelectedTag(typeof stored?.selectedTag === "string" ? stored.selectedTag : defaultTag);
|
|
1077
1090
|
}, [defaultTag, storageKey]);
|
|
1091
|
+
useEffect3(() => {
|
|
1092
|
+
if (!autoAvailableMode || !installedOnly) return;
|
|
1093
|
+
setInstalledOnly(false);
|
|
1094
|
+
writeStoredCatalogFilters(storageKey, {
|
|
1095
|
+
addedOnly: false,
|
|
1096
|
+
selectedTag: selectedTag || ""
|
|
1097
|
+
});
|
|
1098
|
+
}, [autoAvailableMode, installedOnly, selectedTag, storageKey]);
|
|
1078
1099
|
useEffect3(() => {
|
|
1079
1100
|
const restrictedTags = env?.tags ?? [];
|
|
1080
1101
|
if (selectedTag && restrictedTags.length > 0 && !restrictedTags.includes(selectedTag)) {
|
|
@@ -1192,7 +1213,7 @@ function CatalogPage() {
|
|
|
1192
1213
|
}
|
|
1193
1214
|
)
|
|
1194
1215
|
] }),
|
|
1195
|
-
/* @__PURE__ */ jsxs3("label", { className: "mx-checkbox-label", children: [
|
|
1216
|
+
mutationControlsReady && !autoAvailableMode ? /* @__PURE__ */ jsxs3("label", { className: "mx-checkbox-label", children: [
|
|
1196
1217
|
/* @__PURE__ */ jsx6(
|
|
1197
1218
|
"input",
|
|
1198
1219
|
{
|
|
@@ -1210,7 +1231,7 @@ function CatalogPage() {
|
|
|
1210
1231
|
}
|
|
1211
1232
|
),
|
|
1212
1233
|
/* @__PURE__ */ jsx6("span", { className: "mx-label mx-label-inline", children: t("common.added_only", void 0, "Added only") })
|
|
1213
|
-
] })
|
|
1234
|
+
] }) : null
|
|
1214
1235
|
] }) }),
|
|
1215
1236
|
busy && items.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "mx-grid", "aria-busy": "true", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs3("div", { className: "mx-skeleton-card", children: [
|
|
1216
1237
|
/* @__PURE__ */ jsx6("div", { className: "mx-skeleton-card-image" }),
|
|
@@ -1240,7 +1261,7 @@ function CatalogPage() {
|
|
|
1240
1261
|
/* @__PURE__ */ jsx6("div", { className: "mx-grid", children: filtered.length === 0 && !busy ? /* @__PURE__ */ jsxs3("div", { className: "mx-empty-catalog", children: [
|
|
1241
1262
|
/* @__PURE__ */ jsx6("div", { className: "mx-empty-catalog-icon", children: "\u2315" }),
|
|
1242
1263
|
/* @__PURE__ */ jsx6("div", { className: "mx-empty-catalog-title", children: t("catalog.no_apps_found", void 0, "No apps found") }),
|
|
1243
|
-
/* @__PURE__ */ jsx6("div", { className: "mx-empty-catalog-desc", children: installedOnly && items.length > 0 ? t(
|
|
1264
|
+
/* @__PURE__ */ jsx6("div", { className: "mx-empty-catalog-desc", children: !autoAvailableMode && installedOnly && items.length > 0 ? t(
|
|
1244
1265
|
"catalog.empty_added_only",
|
|
1245
1266
|
void 0,
|
|
1246
1267
|
"No apps are installed for the current subject yet. Turn off Added only to browse the full catalog."
|
|
@@ -1260,7 +1281,9 @@ function CatalogPage() {
|
|
|
1260
1281
|
const image = typeof manifest.image === "string" ? manifest.image : "https://picsum.photos/seed/" + x.slug + "/560/320";
|
|
1261
1282
|
const inst = installationsByXappId[String(x.id)];
|
|
1262
1283
|
const installed = Boolean(inst);
|
|
1284
|
+
const updateAvailable = Boolean(inst?.updateAvailable);
|
|
1263
1285
|
const defaultWidgetId = getDefaultWidgetId(x);
|
|
1286
|
+
const defaultWidgetName = getDefaultWidgetName(x, locale) || t("common.widget", void 0, "Widget");
|
|
1264
1287
|
const xTerms = asRecord(manifest.terms);
|
|
1265
1288
|
const requiresTerms = Boolean(
|
|
1266
1289
|
Object.keys(xTerms).length > 0 || typeof xTerms.text === "string" && xTerms.text.trim() || typeof xTerms.url === "string" && xTerms.url.trim()
|
|
@@ -1293,7 +1316,7 @@ function CatalogPage() {
|
|
|
1293
1316
|
)
|
|
1294
1317
|
] }) : /* @__PURE__ */ jsx6("div", { className: "mx-card-publisher", children: t("common.catalog_app", void 0, "Catalog app") }),
|
|
1295
1318
|
/* @__PURE__ */ jsxs3("div", { className: "mx-card-badges", children: [
|
|
1296
|
-
installed && /* @__PURE__ */ jsxs3("span", { className: "mx-card-installed-badge", children: [
|
|
1319
|
+
!autoAvailableMode && installed && /* @__PURE__ */ jsxs3("span", { className: "mx-card-installed-badge", children: [
|
|
1297
1320
|
/* @__PURE__ */ jsx6("span", { className: "mx-card-installed-badge-dot" }),
|
|
1298
1321
|
t("common.added", void 0, "Added")
|
|
1299
1322
|
] }),
|
|
@@ -1317,7 +1340,7 @@ function CatalogPage() {
|
|
|
1317
1340
|
children: t("catalog.view_details", void 0, "View details")
|
|
1318
1341
|
}
|
|
1319
1342
|
),
|
|
1320
|
-
canMutate && (!installed ? /* @__PURE__ */ jsx6(
|
|
1343
|
+
canMutate && mutationControlsReady && (!installed ? /* @__PURE__ */ jsx6(
|
|
1321
1344
|
"button",
|
|
1322
1345
|
{
|
|
1323
1346
|
className: "mx-btn mx-btn-primary mx-btn-sm",
|
|
@@ -1331,12 +1354,50 @@ function CatalogPage() {
|
|
|
1331
1354
|
host.requestInstall({
|
|
1332
1355
|
xappId: String(x.id),
|
|
1333
1356
|
defaultWidgetId,
|
|
1357
|
+
xappTitle: title,
|
|
1358
|
+
widgetName: defaultWidgetName,
|
|
1359
|
+
openAfterInstall: autoAvailableMode && Boolean(defaultWidgetId),
|
|
1334
1360
|
subjectId: host.subjectId ?? null
|
|
1335
1361
|
});
|
|
1336
1362
|
},
|
|
1337
|
-
children: addAppLabel
|
|
1363
|
+
children: autoAvailableMode ? openAppLabel : addAppLabel
|
|
1364
|
+
}
|
|
1365
|
+
) : autoAvailableMode ? /* @__PURE__ */ jsx6(
|
|
1366
|
+
"button",
|
|
1367
|
+
{
|
|
1368
|
+
className: "mx-btn mx-btn-primary mx-btn-sm",
|
|
1369
|
+
onClick: (e) => {
|
|
1370
|
+
e.preventDefault();
|
|
1371
|
+
e.stopPropagation();
|
|
1372
|
+
if (!defaultWidgetId || !inst?.installationId) {
|
|
1373
|
+
navigate(detailTo);
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
if (updateAvailable && host.requestUpdate && autoUpdateMode) {
|
|
1377
|
+
host.requestUpdate({
|
|
1378
|
+
installationId: inst.installationId,
|
|
1379
|
+
xappId: String(x.id),
|
|
1380
|
+
widgetId: defaultWidgetId,
|
|
1381
|
+
xappTitle: title,
|
|
1382
|
+
widgetName: defaultWidgetName
|
|
1383
|
+
});
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
if (updateAvailable) {
|
|
1387
|
+
navigate(detailTo);
|
|
1388
|
+
return;
|
|
1389
|
+
}
|
|
1390
|
+
host.openWidget({
|
|
1391
|
+
installationId: inst.installationId,
|
|
1392
|
+
widgetId: defaultWidgetId,
|
|
1393
|
+
xappId: String(x.id),
|
|
1394
|
+
xappTitle: title,
|
|
1395
|
+
widgetName: t("common.widget", void 0, "Widget")
|
|
1396
|
+
});
|
|
1397
|
+
},
|
|
1398
|
+
children: openAppLabel
|
|
1338
1399
|
}
|
|
1339
|
-
) : /* @__PURE__ */ jsx6(
|
|
1400
|
+
) : !autoAvailableMode ? /* @__PURE__ */ jsx6(
|
|
1340
1401
|
"button",
|
|
1341
1402
|
{
|
|
1342
1403
|
className: "mx-btn mx-btn-outline mx-btn-sm mx-btn-danger-text",
|
|
@@ -1354,7 +1415,7 @@ function CatalogPage() {
|
|
|
1354
1415
|
},
|
|
1355
1416
|
children: removeAppLabel
|
|
1356
1417
|
}
|
|
1357
|
-
))
|
|
1418
|
+
) : null)
|
|
1358
1419
|
] })
|
|
1359
1420
|
] }, x.id);
|
|
1360
1421
|
}) })
|
|
@@ -4242,6 +4303,365 @@ function RequestsPage() {
|
|
|
4242
4303
|
import { useEffect as useEffect9, useMemo as useMemo8, useRef, useState as useState7 } from "react";
|
|
4243
4304
|
import { Link as Link9, useLocation as useLocation7, useNavigate as useNavigate3, useParams as useParams2 } from "react-router-dom";
|
|
4244
4305
|
|
|
4306
|
+
// ../browser-host/src/xms.ts
|
|
4307
|
+
function readString4(value) {
|
|
4308
|
+
return String(value ?? "").trim();
|
|
4309
|
+
}
|
|
4310
|
+
function readNumber(value, fallback = 0) {
|
|
4311
|
+
const parsed = Number(value);
|
|
4312
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
4313
|
+
}
|
|
4314
|
+
function readLower(value) {
|
|
4315
|
+
return readString4(value).toLowerCase();
|
|
4316
|
+
}
|
|
4317
|
+
function readBoolean(value, fallback = false) {
|
|
4318
|
+
return typeof value === "boolean" ? value : fallback;
|
|
4319
|
+
}
|
|
4320
|
+
function readLocalizedText(value, fallback = "") {
|
|
4321
|
+
if (typeof value === "string") {
|
|
4322
|
+
return readString4(value) || fallback;
|
|
4323
|
+
}
|
|
4324
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
4325
|
+
return fallback;
|
|
4326
|
+
}
|
|
4327
|
+
const record = value;
|
|
4328
|
+
return readString4(record.en) || readString4(record.ro) || Object.values(record).map((item) => readString4(item)).find(Boolean) || fallback;
|
|
4329
|
+
}
|
|
4330
|
+
function formatStateLabel(value, fallback = "\u2014") {
|
|
4331
|
+
const raw = readString4(value);
|
|
4332
|
+
if (!raw) return fallback;
|
|
4333
|
+
return raw.replace(/_/g, " ");
|
|
4334
|
+
}
|
|
4335
|
+
function listXappMonetizationPaywalls(items) {
|
|
4336
|
+
return (Array.isArray(items) ? items : []).filter((item) => item && typeof item === "object" && !Array.isArray(item)).map((item) => item);
|
|
4337
|
+
}
|
|
4338
|
+
function buildPaywallPlacementCandidates(value) {
|
|
4339
|
+
const raw = readLower(value);
|
|
4340
|
+
if (!raw) return [];
|
|
4341
|
+
const out = /* @__PURE__ */ new Set([raw]);
|
|
4342
|
+
if (raw === "paywall" || raw === "default_paywall") {
|
|
4343
|
+
out.add("paywall");
|
|
4344
|
+
out.add("default_paywall");
|
|
4345
|
+
}
|
|
4346
|
+
if (raw === "feature_paywall" || raw === "feature_gate") {
|
|
4347
|
+
out.add("feature_paywall");
|
|
4348
|
+
out.add("feature_gate");
|
|
4349
|
+
}
|
|
4350
|
+
if (raw === "upgrade" || raw === "upgrade_paywall") {
|
|
4351
|
+
out.add("upgrade");
|
|
4352
|
+
out.add("upgrade_paywall");
|
|
4353
|
+
}
|
|
4354
|
+
if (raw === "retention" || raw === "retention_paywall") {
|
|
4355
|
+
out.add("retention");
|
|
4356
|
+
out.add("retention_paywall");
|
|
4357
|
+
}
|
|
4358
|
+
if (raw === "checkout" || raw === "checkout_entry") {
|
|
4359
|
+
out.add("checkout");
|
|
4360
|
+
out.add("checkout_entry");
|
|
4361
|
+
}
|
|
4362
|
+
return Array.from(out);
|
|
4363
|
+
}
|
|
4364
|
+
function selectXappMonetizationPaywall(input) {
|
|
4365
|
+
const paywalls = listXappMonetizationPaywalls(input.paywalls);
|
|
4366
|
+
const slug = readLower(input.slug);
|
|
4367
|
+
const placement = readLower(input.placement);
|
|
4368
|
+
if (slug) {
|
|
4369
|
+
const matched = paywalls.find((item) => readLower(item.slug) === slug);
|
|
4370
|
+
if (matched) return matched;
|
|
4371
|
+
}
|
|
4372
|
+
if (placement) {
|
|
4373
|
+
const candidates = buildPaywallPlacementCandidates(placement);
|
|
4374
|
+
const matched = paywalls.find((item) => candidates.includes(readLower(item.placement)));
|
|
4375
|
+
if (matched) return matched;
|
|
4376
|
+
}
|
|
4377
|
+
return paywalls[0] || null;
|
|
4378
|
+
}
|
|
4379
|
+
function flattenXappMonetizationPaywallPackages(paywall) {
|
|
4380
|
+
const record = paywall && typeof paywall === "object" && !Array.isArray(paywall) ? paywall : {};
|
|
4381
|
+
const out = [];
|
|
4382
|
+
for (const pkg of Array.isArray(record.packages) ? record.packages : []) {
|
|
4383
|
+
const packageRecord = pkg && typeof pkg === "object" && !Array.isArray(pkg) ? pkg : {};
|
|
4384
|
+
const price = Array.isArray(packageRecord.prices) ? packageRecord.prices[0] || null : null;
|
|
4385
|
+
out.push({
|
|
4386
|
+
offeringId: readString4(packageRecord.offering_id),
|
|
4387
|
+
offeringSlug: readString4(packageRecord.offering_slug),
|
|
4388
|
+
offeringTitle: readString4(packageRecord.offering_slug) || "Offering",
|
|
4389
|
+
offeringPlacement: readString4(packageRecord.offering_placement) || null,
|
|
4390
|
+
packageId: readString4(packageRecord.id),
|
|
4391
|
+
packageSlug: readString4(packageRecord.slug),
|
|
4392
|
+
packageTitle: readString4(packageRecord.slug) || "Package",
|
|
4393
|
+
packageKind: readString4(packageRecord.package_kind) || "standard",
|
|
4394
|
+
productId: readString4(packageRecord.product?.id),
|
|
4395
|
+
productSlug: readString4(packageRecord.product?.slug),
|
|
4396
|
+
productFamily: readString4(
|
|
4397
|
+
packageRecord.product?.product_family
|
|
4398
|
+
),
|
|
4399
|
+
priceId: readString4(price?.id),
|
|
4400
|
+
amount: readString4(price?.amount),
|
|
4401
|
+
currency: readString4(price?.currency),
|
|
4402
|
+
billingPeriod: readString4(price?.billing_period) || null,
|
|
4403
|
+
purchasePolicy: readProjectedPurchasePolicy(packageRecord.purchase_policy),
|
|
4404
|
+
metadata: packageRecord.metadata && typeof packageRecord.metadata === "object" ? packageRecord.metadata : {}
|
|
4405
|
+
});
|
|
4406
|
+
}
|
|
4407
|
+
return out.filter((item) => item.offeringId && item.packageId && item.priceId);
|
|
4408
|
+
}
|
|
4409
|
+
function formatPlacementLabel(value, fallback = "General placement") {
|
|
4410
|
+
const raw = readString4(value);
|
|
4411
|
+
if (!raw) return fallback;
|
|
4412
|
+
return raw.replace(/[_-]+/g, " ");
|
|
4413
|
+
}
|
|
4414
|
+
function readPackageCredits(item) {
|
|
4415
|
+
const metadata = item.metadata && typeof item.metadata === "object" && !Array.isArray(item.metadata) ? item.metadata : {};
|
|
4416
|
+
const direct = readNumber(item.credits ?? metadata.credits, -1);
|
|
4417
|
+
if (direct > 0) return direct;
|
|
4418
|
+
const included = readNumber(metadata.included_credits, -1);
|
|
4419
|
+
if (included > 0) return included;
|
|
4420
|
+
return 0;
|
|
4421
|
+
}
|
|
4422
|
+
function buildMonetizationOfferingPresentation(input) {
|
|
4423
|
+
const record = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
4424
|
+
const offeringLabel = readString4(record.offeringTitle) || formatStateLabel(record.offeringSlug, "Offering");
|
|
4425
|
+
const placementRaw = readLower(record.offeringPlacement);
|
|
4426
|
+
const placementLabel = formatPlacementLabel(record.offeringPlacement);
|
|
4427
|
+
let summary = "General offering surface for this xapp.";
|
|
4428
|
+
if (placementRaw.includes("feature") && placementRaw.includes("paywall")) {
|
|
4429
|
+
summary = "Feature-paywall placement for gated in-app flows.";
|
|
4430
|
+
} else if (placementRaw.includes("paywall")) {
|
|
4431
|
+
summary = "Default paywall placement for monetized upgrade prompts.";
|
|
4432
|
+
} else if (placementRaw.includes("checkout")) {
|
|
4433
|
+
summary = "Direct checkout placement for purchase-driven flows.";
|
|
4434
|
+
} else if (placementRaw.includes("upgrade")) {
|
|
4435
|
+
summary = "Upgrade-oriented placement for membership and package switching.";
|
|
4436
|
+
}
|
|
4437
|
+
return {
|
|
4438
|
+
offeringLabel,
|
|
4439
|
+
placementLabel,
|
|
4440
|
+
summary
|
|
4441
|
+
};
|
|
4442
|
+
}
|
|
4443
|
+
function buildMonetizationPaywallPresentation(input) {
|
|
4444
|
+
const record = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
4445
|
+
const paywallLabel = readLocalizedText(record.title, formatStateLabel(record.slug, "Paywall")) || "Paywall";
|
|
4446
|
+
const placementLabel = formatPlacementLabel(record.placement);
|
|
4447
|
+
const packages = flattenXappMonetizationPaywallPackages(record);
|
|
4448
|
+
const defaultPackageRef = readString4(record.default_package_ref);
|
|
4449
|
+
const defaultPackage = packages.find((item) => readString4(item.packageSlug) === defaultPackageRef) || packages[0] || null;
|
|
4450
|
+
const summary = readLocalizedText(record.description) || (placementLabel === "General placement" ? "Presentation surface for monetized package selection." : `${placementLabel} surface for monetized package selection.`);
|
|
4451
|
+
return {
|
|
4452
|
+
paywallLabel,
|
|
4453
|
+
placementLabel,
|
|
4454
|
+
summary,
|
|
4455
|
+
defaultPackageLabel: defaultPackage ? readString4(defaultPackage.packageTitle) : "",
|
|
4456
|
+
packageCountLabel: `${packages.length} package${packages.length === 1 ? "" : "s"}`
|
|
4457
|
+
};
|
|
4458
|
+
}
|
|
4459
|
+
function buildMonetizationPaywallRenderModel(input) {
|
|
4460
|
+
const record = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
4461
|
+
const presentation = buildMonetizationPaywallPresentation(record);
|
|
4462
|
+
const defaultPackageRef = readString4(record.default_package_ref);
|
|
4463
|
+
const packages = flattenXappMonetizationPaywallPackages(record).map((item) => {
|
|
4464
|
+
const packagePresentation = buildMonetizationPackagePresentation(item);
|
|
4465
|
+
return {
|
|
4466
|
+
packageId: readString4(item.packageId),
|
|
4467
|
+
packageSlug: readString4(item.packageSlug),
|
|
4468
|
+
packageTitle: readString4(item.packageTitle) || "Package",
|
|
4469
|
+
productId: readString4(item.productId),
|
|
4470
|
+
productSlug: readString4(item.productSlug),
|
|
4471
|
+
productFamily: readString4(item.productFamily),
|
|
4472
|
+
metadata: item.metadata && typeof item.metadata === "object" && !Array.isArray(item.metadata) ? item.metadata : {},
|
|
4473
|
+
description: readString4(item.description) || packagePresentation.summary,
|
|
4474
|
+
fitLabel: packagePresentation.fitLabel,
|
|
4475
|
+
moneyLabel: packagePresentation.moneyLabel,
|
|
4476
|
+
offeringLabel: packagePresentation.offeringLabel,
|
|
4477
|
+
placementLabel: packagePresentation.placementLabel,
|
|
4478
|
+
signals: packagePresentation.signals,
|
|
4479
|
+
isDefault: Boolean(defaultPackageRef) && readString4(item.packageSlug) === defaultPackageRef
|
|
4480
|
+
};
|
|
4481
|
+
});
|
|
4482
|
+
const badges = [presentation.placementLabel, presentation.packageCountLabel];
|
|
4483
|
+
if (presentation.defaultPackageLabel) {
|
|
4484
|
+
badges.push(`default ${presentation.defaultPackageLabel}`);
|
|
4485
|
+
}
|
|
4486
|
+
return {
|
|
4487
|
+
...presentation,
|
|
4488
|
+
badges,
|
|
4489
|
+
packages
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
function buildMonetizationPackagePresentation(input) {
|
|
4493
|
+
const item = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
4494
|
+
const packageKind = readString4(item.packageKind);
|
|
4495
|
+
const packageSlug = readLower(item.packageSlug);
|
|
4496
|
+
const metadata = item.metadata && typeof item.metadata === "object" && !Array.isArray(item.metadata) ? item.metadata : {};
|
|
4497
|
+
const credits = readPackageCredits(item);
|
|
4498
|
+
const moneyLabel = normalizeMoneyLabel(item);
|
|
4499
|
+
const offeringPresentation = buildMonetizationOfferingPresentation(item);
|
|
4500
|
+
let fitLabel = "General upgrade";
|
|
4501
|
+
let summary = "Useful as a general monetization upgrade for this creator scope.";
|
|
4502
|
+
if (packageKind === "one_time_unlock") {
|
|
4503
|
+
fitLabel = "Durable unlock";
|
|
4504
|
+
summary = "Best when the feature mainly needs current access without ongoing membership.";
|
|
4505
|
+
} else if (packageKind === "subscription") {
|
|
4506
|
+
fitLabel = "Recurring membership";
|
|
4507
|
+
summary = "Best when the feature depends on ongoing membership coverage.";
|
|
4508
|
+
} else if (packageKind === "credit_pack") {
|
|
4509
|
+
fitLabel = "Credit top-up";
|
|
4510
|
+
summary = "Best when the feature spends credits for each advanced action.";
|
|
4511
|
+
} else if (packageSlug.includes("hybrid")) {
|
|
4512
|
+
fitLabel = "Hybrid upgrade";
|
|
4513
|
+
summary = "Blends access coverage with bundled credits for mixed workflows.";
|
|
4514
|
+
}
|
|
4515
|
+
const signals = [];
|
|
4516
|
+
if (readString4(metadata.badge)) {
|
|
4517
|
+
signals.push(readString4(metadata.badge));
|
|
4518
|
+
}
|
|
4519
|
+
if (credits > 0) {
|
|
4520
|
+
signals.push(`${credits} credits`);
|
|
4521
|
+
}
|
|
4522
|
+
if (readString4(item.billingPeriod)) {
|
|
4523
|
+
signals.push(`billed ${readString4(item.billingPeriod)}`);
|
|
4524
|
+
}
|
|
4525
|
+
if (offeringPresentation.offeringLabel) {
|
|
4526
|
+
signals.push(offeringPresentation.offeringLabel);
|
|
4527
|
+
}
|
|
4528
|
+
if (offeringPresentation.placementLabel && offeringPresentation.placementLabel !== "General placement") {
|
|
4529
|
+
signals.push(offeringPresentation.placementLabel);
|
|
4530
|
+
}
|
|
4531
|
+
return {
|
|
4532
|
+
fitLabel,
|
|
4533
|
+
summary,
|
|
4534
|
+
signals,
|
|
4535
|
+
moneyLabel,
|
|
4536
|
+
offeringLabel: offeringPresentation.offeringLabel,
|
|
4537
|
+
placementLabel: offeringPresentation.placementLabel,
|
|
4538
|
+
offeringSummary: offeringPresentation.summary
|
|
4539
|
+
};
|
|
4540
|
+
}
|
|
4541
|
+
function collectPackageOwnershipCandidates(item) {
|
|
4542
|
+
const metadata = item.metadata && typeof item.metadata === "object" && !Array.isArray(item.metadata) ? item.metadata : {};
|
|
4543
|
+
return [
|
|
4544
|
+
readLower(item.productSlug),
|
|
4545
|
+
readLower(item.packageSlug),
|
|
4546
|
+
readLower(metadata.tier),
|
|
4547
|
+
readLower(metadata.access_tier)
|
|
4548
|
+
].filter(Boolean);
|
|
4549
|
+
}
|
|
4550
|
+
function hasActiveRecurringSubscription(currentSubscription) {
|
|
4551
|
+
const record = currentSubscription && typeof currentSubscription === "object" && !Array.isArray(currentSubscription) ? currentSubscription : {};
|
|
4552
|
+
const status = readLower(record.status);
|
|
4553
|
+
if (!status || status === "expired") return false;
|
|
4554
|
+
const expiredAt = readString4(record.expired_at);
|
|
4555
|
+
if (!expiredAt) return true;
|
|
4556
|
+
const expiresAtMs = Date.parse(expiredAt);
|
|
4557
|
+
return Number.isNaN(expiresAtMs) || expiresAtMs > Date.now();
|
|
4558
|
+
}
|
|
4559
|
+
function hasCurrentOwnedEntitlement(entitlement) {
|
|
4560
|
+
const status = readLower(entitlement.status);
|
|
4561
|
+
if (status !== "active" && status !== "grace_period") return false;
|
|
4562
|
+
const expiresAt = readString4(entitlement.expires_at);
|
|
4563
|
+
if (!expiresAt) return true;
|
|
4564
|
+
const expiresAtMs = Date.parse(expiresAt);
|
|
4565
|
+
return Number.isNaN(expiresAtMs) || expiresAtMs > Date.now();
|
|
4566
|
+
}
|
|
4567
|
+
function readProjectedPurchasePolicy(value) {
|
|
4568
|
+
const record = value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
4569
|
+
if (!record) return null;
|
|
4570
|
+
const status = readLower(record.status);
|
|
4571
|
+
const transitionKind = readLower(record.transition_kind ?? record.transitionKind);
|
|
4572
|
+
if (!status || !transitionKind) return null;
|
|
4573
|
+
return {
|
|
4574
|
+
canPurchase: readBoolean(record.can_purchase ?? record.canPurchase, true),
|
|
4575
|
+
status: status === "current_recurring_plan" || status === "owned_additive_unlock" ? status : "available",
|
|
4576
|
+
transitionKind: transitionKind === "start_recurring" || transitionKind === "replace_recurring" || transitionKind === "buy_additive_unlock" || transitionKind === "buy_credit_pack" || transitionKind === "activate_hybrid" ? transitionKind : "none",
|
|
4577
|
+
reason: readString4(record.reason) || null
|
|
4578
|
+
};
|
|
4579
|
+
}
|
|
4580
|
+
function resolveMonetizationPackagePurchasePolicy(input) {
|
|
4581
|
+
const item = input.item && typeof input.item === "object" ? input.item : {};
|
|
4582
|
+
const projectedPolicy = readProjectedPurchasePolicy(item.purchasePolicy ?? item.purchase_policy);
|
|
4583
|
+
if (projectedPolicy) return projectedPolicy;
|
|
4584
|
+
const currentSubscription = input.currentSubscription && typeof input.currentSubscription === "object" && !Array.isArray(input.currentSubscription) ? input.currentSubscription : {};
|
|
4585
|
+
const additiveEntitlements = Array.isArray(input.additiveEntitlements) ? input.additiveEntitlements : [];
|
|
4586
|
+
const productFamily = readLower(item.productFamily);
|
|
4587
|
+
const packageKind = readLower(item.packageKind);
|
|
4588
|
+
const productId = readLower(item.productId);
|
|
4589
|
+
const currentSubscriptionProductId = readLower(currentSubscription.product_id);
|
|
4590
|
+
const ownershipCandidates = new Set(collectPackageOwnershipCandidates(item));
|
|
4591
|
+
const ownedAdditiveUnlock = additiveEntitlements.some((entry) => {
|
|
4592
|
+
const entitlement = entry && typeof entry === "object" && !Array.isArray(entry) ? entry : {};
|
|
4593
|
+
if (!hasCurrentOwnedEntitlement(entitlement)) return false;
|
|
4594
|
+
const entitlementProductId = readLower(entitlement.product_id);
|
|
4595
|
+
if (productId && entitlementProductId && productId === entitlementProductId) return true;
|
|
4596
|
+
const candidateValues = [
|
|
4597
|
+
readLower(entitlement.product_slug),
|
|
4598
|
+
readLower(entitlement.tier)
|
|
4599
|
+
].filter(Boolean);
|
|
4600
|
+
return candidateValues.some((value) => ownershipCandidates.has(value));
|
|
4601
|
+
});
|
|
4602
|
+
if (hasActiveRecurringSubscription(currentSubscription) && productId && currentSubscriptionProductId && productId === currentSubscriptionProductId) {
|
|
4603
|
+
return {
|
|
4604
|
+
canPurchase: false,
|
|
4605
|
+
status: "current_recurring_plan",
|
|
4606
|
+
transitionKind: "none",
|
|
4607
|
+
reason: "current_recurring_plan"
|
|
4608
|
+
};
|
|
4609
|
+
}
|
|
4610
|
+
if ((productFamily === "one_time_unlock" || packageKind === "one_time_unlock") && ownedAdditiveUnlock) {
|
|
4611
|
+
return {
|
|
4612
|
+
canPurchase: false,
|
|
4613
|
+
status: "owned_additive_unlock",
|
|
4614
|
+
transitionKind: "none",
|
|
4615
|
+
reason: "owned_additive_unlock"
|
|
4616
|
+
};
|
|
4617
|
+
}
|
|
4618
|
+
if (productFamily === "credit_pack" || packageKind === "credit_pack") {
|
|
4619
|
+
return {
|
|
4620
|
+
canPurchase: true,
|
|
4621
|
+
status: "available",
|
|
4622
|
+
transitionKind: "buy_credit_pack",
|
|
4623
|
+
reason: null
|
|
4624
|
+
};
|
|
4625
|
+
}
|
|
4626
|
+
if (productFamily === "one_time_unlock" || packageKind === "one_time_unlock") {
|
|
4627
|
+
return {
|
|
4628
|
+
canPurchase: true,
|
|
4629
|
+
status: "available",
|
|
4630
|
+
transitionKind: "buy_additive_unlock",
|
|
4631
|
+
reason: null
|
|
4632
|
+
};
|
|
4633
|
+
}
|
|
4634
|
+
if (productFamily === "subscription_plan" || packageKind === "subscription") {
|
|
4635
|
+
return {
|
|
4636
|
+
canPurchase: true,
|
|
4637
|
+
status: "available",
|
|
4638
|
+
transitionKind: hasActiveRecurringSubscription(currentSubscription) ? "replace_recurring" : "start_recurring",
|
|
4639
|
+
reason: null
|
|
4640
|
+
};
|
|
4641
|
+
}
|
|
4642
|
+
if (productFamily === "hybrid_plan") {
|
|
4643
|
+
return {
|
|
4644
|
+
canPurchase: true,
|
|
4645
|
+
status: "available",
|
|
4646
|
+
transitionKind: "activate_hybrid",
|
|
4647
|
+
reason: null
|
|
4648
|
+
};
|
|
4649
|
+
}
|
|
4650
|
+
return {
|
|
4651
|
+
canPurchase: true,
|
|
4652
|
+
status: "available",
|
|
4653
|
+
transitionKind: "none",
|
|
4654
|
+
reason: null
|
|
4655
|
+
};
|
|
4656
|
+
}
|
|
4657
|
+
function normalizeMoneyLabel(item) {
|
|
4658
|
+
const amount = readString4(item.amount);
|
|
4659
|
+
const currency = readString4(item.currency);
|
|
4660
|
+
const billingPeriod = readString4(item.billingPeriod);
|
|
4661
|
+
if (!amount && !currency) return "Price unavailable";
|
|
4662
|
+
return `${amount} ${currency}${billingPeriod ? ` / ${billingPeriod}` : ""}`.trim();
|
|
4663
|
+
}
|
|
4664
|
+
|
|
4245
4665
|
// src/utils/monetizationAccess.ts
|
|
4246
4666
|
function asRecord5(value) {
|
|
4247
4667
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
@@ -4310,17 +4730,49 @@ function asRecord6(value) {
|
|
|
4310
4730
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
4311
4731
|
return value;
|
|
4312
4732
|
}
|
|
4313
|
-
function
|
|
4733
|
+
function readString5(value) {
|
|
4314
4734
|
return typeof value === "string" ? value.trim() : "";
|
|
4315
4735
|
}
|
|
4316
|
-
function
|
|
4736
|
+
function readBoolean2(value, fallback) {
|
|
4317
4737
|
return typeof value === "boolean" ? value : fallback;
|
|
4318
4738
|
}
|
|
4319
|
-
function
|
|
4739
|
+
function readNumber2(value) {
|
|
4320
4740
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
4321
4741
|
}
|
|
4742
|
+
function buildMonetizationCheckoutReturnUrl(input) {
|
|
4743
|
+
const url = new URL(input.currentHref, window.location.href);
|
|
4744
|
+
url.searchParams.set("focus", "plans");
|
|
4745
|
+
url.searchParams.set("xapps_monetization_intent_id", input.intentId);
|
|
4746
|
+
if (input.packageSlug) {
|
|
4747
|
+
url.searchParams.set("paywallPackage", input.packageSlug);
|
|
4748
|
+
}
|
|
4749
|
+
return url.toString();
|
|
4750
|
+
}
|
|
4751
|
+
function navigateToHostedCheckout(url) {
|
|
4752
|
+
const target = String(url || "").trim();
|
|
4753
|
+
if (!target) return;
|
|
4754
|
+
try {
|
|
4755
|
+
if (typeof window !== "undefined" && window.top && window.top !== window) {
|
|
4756
|
+
window.top.location.assign(target);
|
|
4757
|
+
return;
|
|
4758
|
+
}
|
|
4759
|
+
} catch {
|
|
4760
|
+
}
|
|
4761
|
+
window.location.assign(target);
|
|
4762
|
+
}
|
|
4763
|
+
function stripMonetizationCheckoutReturnParams(search) {
|
|
4764
|
+
const next = new URLSearchParams(search);
|
|
4765
|
+
const keysToDelete = [];
|
|
4766
|
+
for (const key of next.keys()) {
|
|
4767
|
+
if (key.startsWith("xapps_payment_")) keysToDelete.push(key);
|
|
4768
|
+
}
|
|
4769
|
+
keysToDelete.push("xapps_monetization_intent_id");
|
|
4770
|
+
for (const key of keysToDelete) next.delete(key);
|
|
4771
|
+
const rendered = next.toString();
|
|
4772
|
+
return rendered ? `?${rendered}` : "";
|
|
4773
|
+
}
|
|
4322
4774
|
function formatDateTime2(value, locale) {
|
|
4323
|
-
const raw =
|
|
4775
|
+
const raw = readString5(value);
|
|
4324
4776
|
if (!raw) return "";
|
|
4325
4777
|
const parsed = new Date(raw);
|
|
4326
4778
|
if (Number.isNaN(parsed.getTime())) return raw;
|
|
@@ -4339,28 +4791,28 @@ function formatDateTime2(value, locale) {
|
|
|
4339
4791
|
function normalizeUsageCreditSummary(value) {
|
|
4340
4792
|
const summary = asRecord6(value);
|
|
4341
4793
|
if (!summary) return null;
|
|
4342
|
-
const availableCount =
|
|
4343
|
-
const availableSessionBackedCount =
|
|
4344
|
-
const availableLedgerOnlyCount =
|
|
4345
|
-
const reservedCount =
|
|
4346
|
-
const reservedActiveCount =
|
|
4347
|
-
const reservedStaleCount =
|
|
4348
|
-
const consumedCount =
|
|
4794
|
+
const availableCount = readNumber2(summary.available_count) ?? 0;
|
|
4795
|
+
const availableSessionBackedCount = readNumber2(summary.available_session_backed_count) ?? 0;
|
|
4796
|
+
const availableLedgerOnlyCount = readNumber2(summary.available_ledger_only_count) ?? 0;
|
|
4797
|
+
const reservedCount = readNumber2(summary.reserved_count) ?? 0;
|
|
4798
|
+
const reservedActiveCount = readNumber2(summary.reserved_active_count) ?? reservedCount;
|
|
4799
|
+
const reservedStaleCount = readNumber2(summary.reserved_stale_count) ?? 0;
|
|
4800
|
+
const consumedCount = readNumber2(summary.consumed_count) ?? 0;
|
|
4349
4801
|
const byToolRaw = Array.isArray(summary.by_tool) ? summary.by_tool : [];
|
|
4350
4802
|
const byTool = byToolRaw.map((entry) => {
|
|
4351
4803
|
const record = asRecord6(entry);
|
|
4352
4804
|
if (!record) return null;
|
|
4353
|
-
const toolName =
|
|
4805
|
+
const toolName = readString5(record.tool_name);
|
|
4354
4806
|
if (!toolName) return null;
|
|
4355
4807
|
return {
|
|
4356
4808
|
tool_name: toolName,
|
|
4357
|
-
available_count:
|
|
4358
|
-
available_session_backed_count:
|
|
4359
|
-
available_ledger_only_count:
|
|
4360
|
-
reserved_count:
|
|
4361
|
-
reserved_active_count:
|
|
4362
|
-
reserved_stale_count:
|
|
4363
|
-
consumed_count:
|
|
4809
|
+
available_count: readNumber2(record.available_count) ?? 0,
|
|
4810
|
+
available_session_backed_count: readNumber2(record.available_session_backed_count) ?? 0,
|
|
4811
|
+
available_ledger_only_count: readNumber2(record.available_ledger_only_count) ?? 0,
|
|
4812
|
+
reserved_count: readNumber2(record.reserved_count) ?? 0,
|
|
4813
|
+
reserved_active_count: readNumber2(record.reserved_active_count) ?? readNumber2(record.reserved_count) ?? 0,
|
|
4814
|
+
reserved_stale_count: readNumber2(record.reserved_stale_count) ?? 0,
|
|
4815
|
+
consumed_count: readNumber2(record.consumed_count) ?? 0
|
|
4364
4816
|
};
|
|
4365
4817
|
}).filter((entry) => Boolean(entry)).filter(
|
|
4366
4818
|
(entry) => entry.available_count > 0 || entry.available_ledger_only_count > 0 || entry.reserved_active_count > 0 || entry.reserved_stale_count > 0
|
|
@@ -4376,14 +4828,14 @@ function normalizeUsageCreditSummary(value) {
|
|
|
4376
4828
|
reserved_active_count: reservedActiveCount,
|
|
4377
4829
|
reserved_stale_count: reservedStaleCount,
|
|
4378
4830
|
consumed_count: consumedCount,
|
|
4379
|
-
updated_at:
|
|
4831
|
+
updated_at: readString5(summary.updated_at) || null,
|
|
4380
4832
|
by_tool: byTool
|
|
4381
4833
|
};
|
|
4382
4834
|
}
|
|
4383
4835
|
function normalizeGuardPolicyKind(policy) {
|
|
4384
4836
|
if (policy === "all" || policy === "any") return policy;
|
|
4385
4837
|
const policyObj = asRecord6(policy);
|
|
4386
|
-
const mode =
|
|
4838
|
+
const mode = readString5(policyObj?.mode);
|
|
4387
4839
|
return mode === "any" ? "any" : "all";
|
|
4388
4840
|
}
|
|
4389
4841
|
function defaultBlockingForTrigger(trigger) {
|
|
@@ -4392,6 +4844,47 @@ function defaultBlockingForTrigger(trigger) {
|
|
|
4392
4844
|
function humanizeSlug(slug) {
|
|
4393
4845
|
return String(slug || "").trim().replace(/[_-]+/g, " ").replace(/\s+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
4394
4846
|
}
|
|
4847
|
+
function buildMonetizationHookSummaryItems(manifest) {
|
|
4848
|
+
const monetization = asRecord6(manifest?.monetization);
|
|
4849
|
+
const hooks = asRecord6(monetization?.hooks);
|
|
4850
|
+
const afterPaymentCompleted = asRecord6(
|
|
4851
|
+
hooks?.after_payment_completed ?? hooks?.afterPaymentCompleted
|
|
4852
|
+
);
|
|
4853
|
+
if (!afterPaymentCompleted || readBoolean2(afterPaymentCompleted.enabled, true) === false) {
|
|
4854
|
+
return [];
|
|
4855
|
+
}
|
|
4856
|
+
const baseItems = [];
|
|
4857
|
+
const defaultInvoiceRef = readString5(
|
|
4858
|
+
afterPaymentCompleted.invoice_ref ?? afterPaymentCompleted.invoiceRef
|
|
4859
|
+
);
|
|
4860
|
+
baseItems.push({
|
|
4861
|
+
slug: "xms_after_payment_completed",
|
|
4862
|
+
label: defaultInvoiceRef ? `XMS payment completed \xB7 ${defaultInvoiceRef}` : "XMS payment completed",
|
|
4863
|
+
trigger: "after:payment_completed",
|
|
4864
|
+
headless: true,
|
|
4865
|
+
blocking: false,
|
|
4866
|
+
order: null,
|
|
4867
|
+
policyKind: "all"
|
|
4868
|
+
});
|
|
4869
|
+
const byPaymentGuardRef = asRecord6(
|
|
4870
|
+
afterPaymentCompleted.by_payment_guard_ref ?? afterPaymentCompleted.byPaymentGuardRef
|
|
4871
|
+
);
|
|
4872
|
+
for (const [paymentGuardRef, rawValue] of Object.entries(byPaymentGuardRef ?? {})) {
|
|
4873
|
+
const config = asRecord6(rawValue);
|
|
4874
|
+
if (!config || readBoolean2(config.enabled, true) === false) continue;
|
|
4875
|
+
const invoiceRef = readString5(config.invoice_ref ?? config.invoiceRef);
|
|
4876
|
+
baseItems.push({
|
|
4877
|
+
slug: `xms_after_payment_completed_${paymentGuardRef}`,
|
|
4878
|
+
label: invoiceRef ? `XMS payment completed \xB7 ${paymentGuardRef} \xB7 ${invoiceRef}` : `XMS payment completed \xB7 ${paymentGuardRef}`,
|
|
4879
|
+
trigger: "after:payment_completed",
|
|
4880
|
+
headless: true,
|
|
4881
|
+
blocking: false,
|
|
4882
|
+
order: null,
|
|
4883
|
+
policyKind: "all"
|
|
4884
|
+
});
|
|
4885
|
+
}
|
|
4886
|
+
return baseItems;
|
|
4887
|
+
}
|
|
4395
4888
|
function humanizeTrigger(trigger, translate) {
|
|
4396
4889
|
const normalized = String(trigger || "").trim().toLowerCase();
|
|
4397
4890
|
if (normalized === "before:tool_run") {
|
|
@@ -4413,6 +4906,12 @@ function describeGuardChain(policyKind, translate) {
|
|
|
4413
4906
|
return policyKind === "any" ? translate("xapp.policy_any", void 0, "Any one satisfies") : translate("xapp.policy_all", void 0, "All steps apply");
|
|
4414
4907
|
}
|
|
4415
4908
|
function XappDetailPage() {
|
|
4909
|
+
return /* @__PURE__ */ jsx14(XappDetailPageContent, {});
|
|
4910
|
+
}
|
|
4911
|
+
function XappPlansPage() {
|
|
4912
|
+
return /* @__PURE__ */ jsx14(XappDetailPageContent, { renderMode: "plans_only" });
|
|
4913
|
+
}
|
|
4914
|
+
function XappDetailPageContent(props) {
|
|
4416
4915
|
const { client, host, env } = useMarketplace();
|
|
4417
4916
|
const { locale, t } = useMarketplaceI18n();
|
|
4418
4917
|
const { xappId } = useParams2();
|
|
@@ -4420,14 +4919,30 @@ function XappDetailPage() {
|
|
|
4420
4919
|
const token = useQueryToken7();
|
|
4421
4920
|
const action = useQueryAction();
|
|
4422
4921
|
const queryToolName = useQueryToolName();
|
|
4922
|
+
const routeQuery = useMemo8(() => new URLSearchParams(loc.search), [loc.search]);
|
|
4923
|
+
const routeSource = String(routeQuery.get("from") || "").trim().toLowerCase();
|
|
4924
|
+
const focusedSection = String(routeQuery.get("focus") || "").trim().toLowerCase();
|
|
4925
|
+
const requestedPaywallSlug = String(routeQuery.get("paywall") || "").trim().toLowerCase();
|
|
4926
|
+
const selectedPaywallPackageSlug = String(routeQuery.get("paywallPackage") || "").trim().toLowerCase();
|
|
4927
|
+
const paymentReturnStatus = String(routeQuery.get("xapps_payment_status") || "").trim().toLowerCase();
|
|
4928
|
+
const paymentReturnSessionId = String(routeQuery.get("xapps_payment_session_id") || "").trim();
|
|
4929
|
+
const paymentReturnIntentId = String(routeQuery.get("xapps_monetization_intent_id") || "").trim();
|
|
4423
4930
|
const tokenSearch = buildTokenSearch(token, loc.search);
|
|
4424
4931
|
const navigate = useNavigate3();
|
|
4425
4932
|
const autoOpenedWidgetKeyRef = useRef("");
|
|
4933
|
+
const plansSectionRef = useRef(null);
|
|
4426
4934
|
const canMutate = host.canMutate ? host.canMutate() : true;
|
|
4935
|
+
const renderMode = props?.renderMode === "plans_only" ? "plans_only" : "full";
|
|
4936
|
+
const plansOnlyMode = renderMode === "plans_only";
|
|
4937
|
+
const widgetHostedPlansMode = plansOnlyMode && routeSource === "widget";
|
|
4427
4938
|
const addAppLabel = env?.copy?.addAppLabel || t("xapp.add_to_workspace", void 0, "Add to workspace");
|
|
4428
4939
|
const removeAppLabel = env?.copy?.removeAppLabel || t("xapp.remove_from_workspace", void 0, "Remove from workspace");
|
|
4429
4940
|
const updateAppLabel = env?.copy?.updateAppLabel || t("xapp.update_app", void 0, "Update app");
|
|
4430
4941
|
const openAppLabel = env?.copy?.openAppLabel || t("xapp.open_app", void 0, "Open app");
|
|
4942
|
+
const hasSubject = Boolean(host.subjectId);
|
|
4943
|
+
const installationPolicyResolved = env?.installationPolicyResolved !== false;
|
|
4944
|
+
const mutationControlsReady = installationPolicyResolved || !hasSubject || !canMutate;
|
|
4945
|
+
const installationPolicy = env?.installationPolicy ?? host.installationPolicy ?? null;
|
|
4431
4946
|
const [data, setData] = useState7(null);
|
|
4432
4947
|
const [monetization, setMonetization] = useState7(null);
|
|
4433
4948
|
const [error, setError] = useState7(null);
|
|
@@ -4436,13 +4951,24 @@ function XappDetailPage() {
|
|
|
4436
4951
|
const [termsOpen, setTermsOpen] = useState7(false);
|
|
4437
4952
|
const [termsAccepted, setTermsAccepted] = useState7(false);
|
|
4438
4953
|
const [termsAction, setTermsAction] = useState7("none");
|
|
4954
|
+
const [termsWidgetId, setTermsWidgetId] = useState7(null);
|
|
4955
|
+
const [termsWidgetName, setTermsWidgetName] = useState7(null);
|
|
4439
4956
|
const [removeConfirmOpen, setRemoveConfirmOpen] = useState7(false);
|
|
4440
4957
|
const [guardSummaryOpen, setGuardSummaryOpen] = useState7(false);
|
|
4441
|
-
const
|
|
4958
|
+
const [checkoutBusyPackageSlug, setCheckoutBusyPackageSlug] = useState7("");
|
|
4959
|
+
const [checkoutError, setCheckoutError] = useState7(null);
|
|
4960
|
+
const [checkoutNotice, setCheckoutNotice] = useState7(null);
|
|
4961
|
+
const checkoutFinalizeKeyRef = useRef("");
|
|
4442
4962
|
const installationsByXappId = hasSubject ? host.getInstallationsByXappId() : {};
|
|
4443
|
-
const
|
|
4963
|
+
const routeInstallationId = String(routeQuery.get("installationId") || "").trim();
|
|
4964
|
+
const installation = xappId && installationsByXappId[String(xappId)] ? installationsByXappId[String(xappId)] : xappId && routeInstallationId ? {
|
|
4965
|
+
installationId: routeInstallationId,
|
|
4966
|
+
xappId: String(xappId)
|
|
4967
|
+
} : null;
|
|
4444
4968
|
const updateAvailable = Boolean(installation?.updateAvailable);
|
|
4445
|
-
const
|
|
4969
|
+
const autoAvailableMode = mutationControlsReady && installationPolicy?.mode === "auto_available" && Boolean(hasSubject) && canMutate;
|
|
4970
|
+
const autoUpdateMode = mutationControlsReady && installationPolicy?.update_mode === "auto_update_compatible" && Boolean(hasSubject) && canMutate;
|
|
4971
|
+
const widgetsEnabled = Boolean(hasSubject) && (Boolean(installation) || autoAvailableMode) && (!updateAvailable || autoUpdateMode);
|
|
4446
4972
|
const isEmbedded = window.location.pathname.startsWith("/embed");
|
|
4447
4973
|
const singleXappMode = env?.singleXappMode;
|
|
4448
4974
|
async function refresh() {
|
|
@@ -4455,7 +4981,7 @@ function XappDetailPage() {
|
|
|
4455
4981
|
});
|
|
4456
4982
|
setData(asRecord6(res));
|
|
4457
4983
|
} catch (e) {
|
|
4458
|
-
setError(
|
|
4984
|
+
setError(readString5(asRecord6(e)?.message) || String(e));
|
|
4459
4985
|
} finally {
|
|
4460
4986
|
setBusy(false);
|
|
4461
4987
|
}
|
|
@@ -4499,7 +5025,10 @@ function XappDetailPage() {
|
|
|
4499
5025
|
let cancelled = false;
|
|
4500
5026
|
void (async () => {
|
|
4501
5027
|
try {
|
|
4502
|
-
const next = await client.getMyXappMonetization(currentXappId
|
|
5028
|
+
const next = await client.getMyXappMonetization(currentXappId, {
|
|
5029
|
+
installationId: installation?.installationId ?? null,
|
|
5030
|
+
locale
|
|
5031
|
+
});
|
|
4503
5032
|
if (!cancelled) {
|
|
4504
5033
|
setMonetization(next);
|
|
4505
5034
|
}
|
|
@@ -4512,23 +5041,23 @@ function XappDetailPage() {
|
|
|
4512
5041
|
return () => {
|
|
4513
5042
|
cancelled = true;
|
|
4514
5043
|
};
|
|
4515
|
-
}, [client, host.subjectId, xappId]);
|
|
5044
|
+
}, [client, host.subjectId, installation?.installationId, xappId]);
|
|
4516
5045
|
const manifest = asRecord6(data?.manifest);
|
|
4517
5046
|
const xappRecord = asRecord6(data?.xapp);
|
|
4518
5047
|
const versionRecord = asRecord6(data?.version);
|
|
4519
5048
|
const publisherRecord = asRecord6(xappRecord?.publisher);
|
|
4520
|
-
const title = resolveMarketplaceText(manifest?.title, locale) ||
|
|
4521
|
-
const description = resolveMarketplaceText(manifest?.description, locale) ||
|
|
4522
|
-
const imageUrl =
|
|
5049
|
+
const title = resolveMarketplaceText(manifest?.title, locale) || readString5(xappRecord?.name) || t("xapp.kicker_default", void 0, "Xapp");
|
|
5050
|
+
const description = resolveMarketplaceText(manifest?.description, locale) || readString5(xappRecord?.description) || "";
|
|
5051
|
+
const imageUrl = readString5(manifest?.image) || "https://picsum.photos/seed/xapps-detail/840/360";
|
|
4523
5052
|
const widgets = Array.isArray(data?.widgets) ? data.widgets.filter((widget) => Boolean(asRecord6(widget))) : [];
|
|
4524
5053
|
const defaultWidget = useMemo8(() => {
|
|
4525
|
-
const def = widgets.find((w) =>
|
|
5054
|
+
const def = widgets.find((w) => readBoolean2(w.default, false));
|
|
4526
5055
|
return def || widgets[0] || null;
|
|
4527
5056
|
}, [widgets]);
|
|
4528
5057
|
const requestedWidget = useMemo8(() => {
|
|
4529
|
-
const desiredToolName =
|
|
5058
|
+
const desiredToolName = readString5(queryToolName);
|
|
4530
5059
|
if (!desiredToolName) return defaultWidget;
|
|
4531
|
-
return widgets.find((widget) =>
|
|
5060
|
+
return widgets.find((widget) => readString5(widget.bind_tool_name) === desiredToolName) || defaultWidget;
|
|
4532
5061
|
}, [defaultWidget, queryToolName, widgets]);
|
|
4533
5062
|
const backTo = {
|
|
4534
5063
|
pathname: isEmbedded ? "/embed/catalog" : "..",
|
|
@@ -4536,55 +5065,126 @@ function XappDetailPage() {
|
|
|
4536
5065
|
};
|
|
4537
5066
|
const terms = asRecord6(manifest?.terms);
|
|
4538
5067
|
const termsTitle = resolveMarketplaceText(terms?.title, locale) || t("xapp.terms_title", void 0, "Terms & Conditions");
|
|
4539
|
-
const termsText = resolveMarketplaceText(terms?.text, locale) ||
|
|
4540
|
-
const termsUrl =
|
|
5068
|
+
const termsText = resolveMarketplaceText(terms?.text, locale) || readString5(terms?.text);
|
|
5069
|
+
const termsUrl = readString5(terms?.url);
|
|
4541
5070
|
const hasTermsContent = Boolean(termsText || termsUrl);
|
|
4542
5071
|
const requiresTerms = Boolean(terms || action === "install" || action === "update");
|
|
5072
|
+
function requestInstallForWidget(widgetId, widgetName = null, acceptedTerms = false, openAfterInstall = false) {
|
|
5073
|
+
host.requestInstall({
|
|
5074
|
+
xappId: String(xappId ?? ""),
|
|
5075
|
+
defaultWidgetId: widgetId,
|
|
5076
|
+
xappTitle: String(title),
|
|
5077
|
+
widgetName,
|
|
5078
|
+
openAfterInstall,
|
|
5079
|
+
subjectId: host.subjectId ?? null,
|
|
5080
|
+
...acceptedTerms ? { termsAccepted: true } : {}
|
|
5081
|
+
});
|
|
5082
|
+
}
|
|
5083
|
+
function requestUpdateForWidget(widgetId, acceptedTerms = false) {
|
|
5084
|
+
if (!installation?.installationId || !host.requestUpdate) return;
|
|
5085
|
+
const activeWidget = widgetId && Array.isArray(widgets) ? widgets.find((entry) => readString5(entry.id) === widgetId) || null : null;
|
|
5086
|
+
host.requestUpdate({
|
|
5087
|
+
installationId: installation.installationId,
|
|
5088
|
+
xappId: String(xappId ?? ""),
|
|
5089
|
+
widgetId,
|
|
5090
|
+
xappTitle: String(title),
|
|
5091
|
+
widgetName: resolveMarketplaceText(activeWidget?.title, locale) || readString5(activeWidget?.name) || null,
|
|
5092
|
+
...acceptedTerms ? { termsAccepted: true } : {}
|
|
5093
|
+
});
|
|
5094
|
+
}
|
|
5095
|
+
function openInstalledWidget(widgetId, widgetName, toolName) {
|
|
5096
|
+
if (!installation) return;
|
|
5097
|
+
if (env?.embedMode) {
|
|
5098
|
+
navigate({
|
|
5099
|
+
pathname: isEmbedded ? `/widget/${encodeURIComponent(installation.installationId)}/${encodeURIComponent(widgetId)}` : `/marketplace/widget/${encodeURIComponent(installation.installationId)}/${encodeURIComponent(widgetId)}`,
|
|
5100
|
+
search: tokenSearch
|
|
5101
|
+
});
|
|
5102
|
+
return;
|
|
5103
|
+
}
|
|
5104
|
+
host.openWidget({
|
|
5105
|
+
installationId: installation.installationId,
|
|
5106
|
+
widgetId,
|
|
5107
|
+
xappId: String(xappId ?? ""),
|
|
5108
|
+
xappTitle: String(title),
|
|
5109
|
+
widgetName,
|
|
5110
|
+
toolName
|
|
5111
|
+
});
|
|
5112
|
+
}
|
|
5113
|
+
function launchWidgetForSubject(widgetId, widgetName, toolName) {
|
|
5114
|
+
if (!hasSubject || !widgetId) return;
|
|
5115
|
+
if (!installation) {
|
|
5116
|
+
if (requiresTerms) {
|
|
5117
|
+
setTermsAccepted(false);
|
|
5118
|
+
setTermsAction("install");
|
|
5119
|
+
setTermsWidgetId(widgetId);
|
|
5120
|
+
setTermsWidgetName(widgetName);
|
|
5121
|
+
setTermsOpen(true);
|
|
5122
|
+
return;
|
|
5123
|
+
}
|
|
5124
|
+
requestInstallForWidget(widgetId, widgetName, false, true);
|
|
5125
|
+
return;
|
|
5126
|
+
}
|
|
5127
|
+
if (updateAvailable) {
|
|
5128
|
+
if (autoUpdateMode && host.requestUpdate) {
|
|
5129
|
+
if (requiresTerms) {
|
|
5130
|
+
setTermsAccepted(false);
|
|
5131
|
+
setTermsAction("update");
|
|
5132
|
+
setTermsWidgetId(widgetId);
|
|
5133
|
+
setTermsWidgetName(widgetName);
|
|
5134
|
+
setTermsOpen(true);
|
|
5135
|
+
return;
|
|
5136
|
+
}
|
|
5137
|
+
requestUpdateForWidget(widgetId);
|
|
5138
|
+
}
|
|
5139
|
+
return;
|
|
5140
|
+
}
|
|
5141
|
+
openInstalledWidget(widgetId, widgetName, toolName);
|
|
5142
|
+
}
|
|
4543
5143
|
useEffect9(() => {
|
|
4544
5144
|
if (action === "install") {
|
|
4545
5145
|
setTermsAccepted(false);
|
|
4546
5146
|
setTermsAction("install");
|
|
5147
|
+
setTermsWidgetId(readString5(defaultWidget?.id) || null);
|
|
5148
|
+
setTermsWidgetName(resolveMarketplaceText(defaultWidget?.title, locale) || null);
|
|
4547
5149
|
setTermsOpen(true);
|
|
4548
5150
|
return;
|
|
4549
5151
|
}
|
|
4550
5152
|
if (action === "update" && installation) {
|
|
4551
5153
|
setTermsAccepted(false);
|
|
4552
5154
|
setTermsAction("update");
|
|
5155
|
+
setTermsWidgetId(null);
|
|
5156
|
+
setTermsWidgetName(null);
|
|
4553
5157
|
setTermsOpen(true);
|
|
4554
5158
|
}
|
|
4555
|
-
}, [action, installation]);
|
|
5159
|
+
}, [action, defaultWidget, installation, locale]);
|
|
4556
5160
|
useEffect9(() => {
|
|
4557
5161
|
if (action !== "open-widget") return;
|
|
4558
5162
|
if (env?.embedMode) return;
|
|
4559
|
-
if (!
|
|
5163
|
+
if (!requestedWidget || !widgetsEnabled) return;
|
|
4560
5164
|
const widget = requestedWidget;
|
|
4561
|
-
const widgetId =
|
|
5165
|
+
const widgetId = readString5(widget?.id);
|
|
4562
5166
|
if (!widgetId) return;
|
|
4563
5167
|
const key = [
|
|
4564
5168
|
String(xappId ?? ""),
|
|
4565
|
-
installation
|
|
5169
|
+
installation?.installationId || "auto",
|
|
4566
5170
|
widgetId,
|
|
4567
|
-
|
|
5171
|
+
readString5(queryToolName)
|
|
4568
5172
|
].join(":");
|
|
4569
5173
|
if (autoOpenedWidgetKeyRef.current === key) return;
|
|
4570
5174
|
autoOpenedWidgetKeyRef.current = key;
|
|
4571
|
-
|
|
4572
|
-
installationId: installation.installationId,
|
|
5175
|
+
launchWidgetForSubject(
|
|
4573
5176
|
widgetId,
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
toolName: readString4(widget?.bind_tool_name)
|
|
4578
|
-
});
|
|
5177
|
+
resolveMarketplaceText(widget?.title, locale) || readString5(widget?.widget_name) || readString5(widget?.name) || t("common.widget", void 0, "Widget"),
|
|
5178
|
+
readString5(widget?.bind_tool_name)
|
|
5179
|
+
);
|
|
4579
5180
|
}, [
|
|
4580
5181
|
action,
|
|
4581
5182
|
env?.embedMode,
|
|
4582
|
-
host,
|
|
4583
5183
|
installation,
|
|
5184
|
+
launchWidgetForSubject,
|
|
4584
5185
|
locale,
|
|
4585
5186
|
queryToolName,
|
|
4586
5187
|
requestedWidget,
|
|
4587
|
-
title,
|
|
4588
5188
|
widgetsEnabled,
|
|
4589
5189
|
xappId
|
|
4590
5190
|
]);
|
|
@@ -4618,8 +5218,8 @@ function XappDetailPage() {
|
|
|
4618
5218
|
}
|
|
4619
5219
|
return t("activity.requests_title", void 0, "Requests");
|
|
4620
5220
|
}
|
|
4621
|
-
const publisherSlug =
|
|
4622
|
-
const publisherName =
|
|
5221
|
+
const publisherSlug = readString5(publisherRecord?.slug);
|
|
5222
|
+
const publisherName = readString5(publisherRecord?.name) || publisherSlug;
|
|
4623
5223
|
const publisherTo = publisherSlug ? {
|
|
4624
5224
|
pathname: isEmbedded ? `/publishers/${encodeURIComponent(publisherSlug)}` : `/marketplace/publishers/${encodeURIComponent(publisherSlug)}`,
|
|
4625
5225
|
search: tokenSearch
|
|
@@ -4627,28 +5227,31 @@ function XappDetailPage() {
|
|
|
4627
5227
|
const guardSummary = useMemo8(() => {
|
|
4628
5228
|
const guardsRaw = Array.isArray(manifest?.guards) ? manifest.guards : [];
|
|
4629
5229
|
const policyMap = asRecord6(manifest?.guards_policy) ?? {};
|
|
4630
|
-
const
|
|
5230
|
+
const guardItems = guardsRaw.map((raw) => {
|
|
4631
5231
|
const guard = asRecord6(raw);
|
|
4632
5232
|
if (!guard) return null;
|
|
4633
|
-
const trigger =
|
|
4634
|
-
const slug =
|
|
5233
|
+
const trigger = readString5(guard.trigger);
|
|
5234
|
+
const slug = readString5(guard.slug);
|
|
4635
5235
|
if (!trigger || !slug) return null;
|
|
4636
5236
|
const policyKind = normalizeGuardPolicyKind(policyMap[trigger]);
|
|
4637
5237
|
return {
|
|
4638
5238
|
slug,
|
|
4639
5239
|
trigger,
|
|
4640
|
-
headless:
|
|
4641
|
-
blocking:
|
|
4642
|
-
order:
|
|
5240
|
+
headless: readBoolean2(guard.headless, true),
|
|
5241
|
+
blocking: readBoolean2(guard.blocking, defaultBlockingForTrigger(trigger)),
|
|
5242
|
+
order: readNumber2(guard.order),
|
|
4643
5243
|
policyKind
|
|
4644
5244
|
};
|
|
4645
|
-
}).filter((item) => Boolean(item))
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
5245
|
+
}).filter((item) => Boolean(item));
|
|
5246
|
+
const items = [...guardItems, ...buildMonetizationHookSummaryItems(manifest)].sort(
|
|
5247
|
+
(a, b) => {
|
|
5248
|
+
const orderA = a.order ?? Number.MAX_SAFE_INTEGER;
|
|
5249
|
+
const orderB = b.order ?? Number.MAX_SAFE_INTEGER;
|
|
5250
|
+
if (orderA !== orderB) return orderA - orderB;
|
|
5251
|
+
if (a.trigger !== b.trigger) return a.trigger.localeCompare(b.trigger);
|
|
5252
|
+
return a.slug.localeCompare(b.slug);
|
|
5253
|
+
}
|
|
5254
|
+
);
|
|
4652
5255
|
const byTrigger = /* @__PURE__ */ new Map();
|
|
4653
5256
|
for (const item of items) {
|
|
4654
5257
|
const existing = byTrigger.get(item.trigger) ?? [];
|
|
@@ -4662,15 +5265,259 @@ function XappDetailPage() {
|
|
|
4662
5265
|
[data?.usage_credit_summary]
|
|
4663
5266
|
);
|
|
4664
5267
|
const monetizationAccessProjection = monetization?.access_projection ?? null;
|
|
5268
|
+
const monetizationPaywalls = useMemo8(
|
|
5269
|
+
() => listXappMonetizationPaywalls(monetization?.paywalls),
|
|
5270
|
+
[monetization?.paywalls]
|
|
5271
|
+
);
|
|
5272
|
+
const selectedPaywall = useMemo8(
|
|
5273
|
+
() => monetizationPaywalls.find(
|
|
5274
|
+
(item) => readString5(asRecord6(item)?.slug).trim().toLowerCase() === requestedPaywallSlug
|
|
5275
|
+
) || selectXappMonetizationPaywall({
|
|
5276
|
+
paywalls: monetizationPaywalls,
|
|
5277
|
+
placement: "default_paywall"
|
|
5278
|
+
}) || selectXappMonetizationPaywall({
|
|
5279
|
+
paywalls: monetizationPaywalls,
|
|
5280
|
+
placement: "paywall"
|
|
5281
|
+
}) || monetizationPaywalls[0] || null,
|
|
5282
|
+
[monetizationPaywalls, requestedPaywallSlug]
|
|
5283
|
+
);
|
|
5284
|
+
const selectedPaywallRenderModel = useMemo8(
|
|
5285
|
+
() => selectedPaywall ? buildMonetizationPaywallRenderModel(selectedPaywall) : null,
|
|
5286
|
+
[selectedPaywall]
|
|
5287
|
+
);
|
|
5288
|
+
const selectedPaywallPackageRecords = useMemo8(
|
|
5289
|
+
() => selectedPaywall ? flattenXappMonetizationPaywallPackages(selectedPaywall) : [],
|
|
5290
|
+
[selectedPaywall]
|
|
5291
|
+
);
|
|
5292
|
+
useEffect9(() => {
|
|
5293
|
+
if (focusedSection !== "plans" || !plansSectionRef.current) return;
|
|
5294
|
+
if (typeof plansSectionRef.current.scrollIntoView === "function") {
|
|
5295
|
+
plansSectionRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
5296
|
+
}
|
|
5297
|
+
}, [focusedSection]);
|
|
5298
|
+
useEffect9(() => {
|
|
5299
|
+
const currentXappId = String(xappId ?? "").trim();
|
|
5300
|
+
if (!currentXappId || !paymentReturnIntentId || !paymentReturnStatus) return;
|
|
5301
|
+
const handledKey = [
|
|
5302
|
+
currentXappId,
|
|
5303
|
+
paymentReturnIntentId,
|
|
5304
|
+
paymentReturnSessionId,
|
|
5305
|
+
paymentReturnStatus
|
|
5306
|
+
].join(":");
|
|
5307
|
+
if (checkoutFinalizeKeyRef.current === handledKey) return;
|
|
5308
|
+
checkoutFinalizeKeyRef.current = handledKey;
|
|
5309
|
+
const clearReturnParams = () => {
|
|
5310
|
+
const nextSearch = stripMonetizationCheckoutReturnParams(loc.search);
|
|
5311
|
+
void navigate(
|
|
5312
|
+
{
|
|
5313
|
+
pathname: loc.pathname,
|
|
5314
|
+
search: nextSearch
|
|
5315
|
+
},
|
|
5316
|
+
{ replace: true }
|
|
5317
|
+
);
|
|
5318
|
+
};
|
|
5319
|
+
if (paymentReturnStatus === "cancelled" || paymentReturnStatus === "canceled") {
|
|
5320
|
+
setCheckoutError(null);
|
|
5321
|
+
setCheckoutNotice(
|
|
5322
|
+
t("xapp.checkout_cancelled", void 0, "Checkout was cancelled before completion.")
|
|
5323
|
+
);
|
|
5324
|
+
clearReturnParams();
|
|
5325
|
+
return;
|
|
5326
|
+
}
|
|
5327
|
+
if (paymentReturnStatus === "failed") {
|
|
5328
|
+
setCheckoutNotice(null);
|
|
5329
|
+
setCheckoutError(
|
|
5330
|
+
t("xapp.checkout_failed", void 0, "Payment failed before access could be issued.")
|
|
5331
|
+
);
|
|
5332
|
+
clearReturnParams();
|
|
5333
|
+
return;
|
|
5334
|
+
}
|
|
5335
|
+
if (paymentReturnStatus !== "paid" || typeof client.finalizeMyXappPurchasePaymentSession !== "function") {
|
|
5336
|
+
return;
|
|
5337
|
+
}
|
|
5338
|
+
let cancelled = false;
|
|
5339
|
+
setCheckoutNotice(
|
|
5340
|
+
t("xapp.checkout_finalizing", void 0, "Finalizing payment and refreshing access...")
|
|
5341
|
+
);
|
|
5342
|
+
setCheckoutError(null);
|
|
5343
|
+
void (async () => {
|
|
5344
|
+
try {
|
|
5345
|
+
await client.finalizeMyXappPurchasePaymentSession({
|
|
5346
|
+
xappId: currentXappId,
|
|
5347
|
+
intentId: paymentReturnIntentId
|
|
5348
|
+
});
|
|
5349
|
+
if (typeof client.getMyXappMonetization === "function") {
|
|
5350
|
+
const next = await client.getMyXappMonetization(currentXappId, {
|
|
5351
|
+
installationId: installation?.installationId ?? null,
|
|
5352
|
+
locale
|
|
5353
|
+
});
|
|
5354
|
+
if (!cancelled) setMonetization(next);
|
|
5355
|
+
}
|
|
5356
|
+
if (!cancelled) {
|
|
5357
|
+
setCheckoutNotice(
|
|
5358
|
+
t("xapp.checkout_finalized", void 0, "Payment completed and access was refreshed.")
|
|
5359
|
+
);
|
|
5360
|
+
clearReturnParams();
|
|
5361
|
+
}
|
|
5362
|
+
} catch (error2) {
|
|
5363
|
+
if (cancelled) return;
|
|
5364
|
+
const message = readString5(asRecord6(error2)?.message) || (error2 instanceof Error ? error2.message : "") || t(
|
|
5365
|
+
"xapp.checkout_finalize_failed",
|
|
5366
|
+
void 0,
|
|
5367
|
+
"Payment returned, but access refresh did not complete yet."
|
|
5368
|
+
);
|
|
5369
|
+
setCheckoutNotice(null);
|
|
5370
|
+
setCheckoutError(message);
|
|
5371
|
+
}
|
|
5372
|
+
})();
|
|
5373
|
+
return () => {
|
|
5374
|
+
cancelled = true;
|
|
5375
|
+
};
|
|
5376
|
+
}, [
|
|
5377
|
+
client,
|
|
5378
|
+
installation?.installationId,
|
|
5379
|
+
locale,
|
|
5380
|
+
loc.pathname,
|
|
5381
|
+
loc.search,
|
|
5382
|
+
navigate,
|
|
5383
|
+
paymentReturnIntentId,
|
|
5384
|
+
paymentReturnSessionId,
|
|
5385
|
+
paymentReturnStatus,
|
|
5386
|
+
t,
|
|
5387
|
+
xappId
|
|
5388
|
+
]);
|
|
5389
|
+
async function finalizeCurrentUserCheckoutIntent(currentXappId, intentId) {
|
|
5390
|
+
if (typeof client.finalizeMyXappPurchasePaymentSession !== "function") {
|
|
5391
|
+
throw new Error(
|
|
5392
|
+
t(
|
|
5393
|
+
"xapp.checkout_finalize_unavailable",
|
|
5394
|
+
void 0,
|
|
5395
|
+
"Access refresh is not available for this checkout flow."
|
|
5396
|
+
)
|
|
5397
|
+
);
|
|
5398
|
+
}
|
|
5399
|
+
setCheckoutNotice(
|
|
5400
|
+
t("xapp.checkout_finalizing", void 0, "Finalizing payment and refreshing access...")
|
|
5401
|
+
);
|
|
5402
|
+
setCheckoutError(null);
|
|
5403
|
+
await client.finalizeMyXappPurchasePaymentSession({
|
|
5404
|
+
xappId: currentXappId,
|
|
5405
|
+
intentId
|
|
5406
|
+
});
|
|
5407
|
+
if (typeof client.getMyXappMonetization === "function") {
|
|
5408
|
+
const next = await client.getMyXappMonetization(currentXappId, {
|
|
5409
|
+
installationId: installation?.installationId ?? null,
|
|
5410
|
+
locale
|
|
5411
|
+
});
|
|
5412
|
+
setMonetization(next);
|
|
5413
|
+
}
|
|
5414
|
+
setCheckoutNotice(
|
|
5415
|
+
t("xapp.checkout_finalized", void 0, "Payment completed and access was refreshed.")
|
|
5416
|
+
);
|
|
5417
|
+
}
|
|
5418
|
+
async function startPackageCheckout(packageSlug) {
|
|
5419
|
+
const normalizedSlug = packageSlug.trim().toLowerCase();
|
|
5420
|
+
if (!xappId || typeof client.prepareMyXappPurchaseIntent !== "function" || typeof client.createMyXappPurchasePaymentSession !== "function" || !normalizedSlug) {
|
|
5421
|
+
return;
|
|
5422
|
+
}
|
|
5423
|
+
const pkg = selectedPaywallPackageRecords.find(
|
|
5424
|
+
(item) => readString5(item.packageSlug).trim().toLowerCase() === normalizedSlug
|
|
5425
|
+
);
|
|
5426
|
+
if (pkg) {
|
|
5427
|
+
const purchasePolicy = getPackagePurchasePolicy(pkg);
|
|
5428
|
+
if (!purchasePolicy.canPurchase) {
|
|
5429
|
+
setCheckoutError(
|
|
5430
|
+
purchasePolicy.status === "owned_additive_unlock" ? t(
|
|
5431
|
+
"xapp.checkout_owned_unlock_blocked",
|
|
5432
|
+
void 0,
|
|
5433
|
+
"This add-on unlock is already owned for the current monetization scope."
|
|
5434
|
+
) : t(
|
|
5435
|
+
"xapp.checkout_current_plan_blocked",
|
|
5436
|
+
void 0,
|
|
5437
|
+
"This plan is already active for the current monetization scope."
|
|
5438
|
+
)
|
|
5439
|
+
);
|
|
5440
|
+
return;
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
const offeringId = readString5(pkg?.offeringId);
|
|
5444
|
+
const packageId = readString5(pkg?.packageId);
|
|
5445
|
+
const priceId = readString5(pkg?.priceId);
|
|
5446
|
+
if (!offeringId || !packageId || !priceId) {
|
|
5447
|
+
setCheckoutError(
|
|
5448
|
+
t(
|
|
5449
|
+
"xapp.checkout_package_missing",
|
|
5450
|
+
void 0,
|
|
5451
|
+
"This package is missing purchase metadata in the published paywall."
|
|
5452
|
+
)
|
|
5453
|
+
);
|
|
5454
|
+
return;
|
|
5455
|
+
}
|
|
5456
|
+
setCheckoutBusyPackageSlug(normalizedSlug);
|
|
5457
|
+
setCheckoutError(null);
|
|
5458
|
+
setCheckoutNotice(null);
|
|
5459
|
+
try {
|
|
5460
|
+
const prepared = await client.prepareMyXappPurchaseIntent({
|
|
5461
|
+
xappId: String(xappId),
|
|
5462
|
+
offeringId,
|
|
5463
|
+
packageId,
|
|
5464
|
+
priceId,
|
|
5465
|
+
installationId: installation?.installationId ?? null
|
|
5466
|
+
});
|
|
5467
|
+
const returnUrl = buildMonetizationCheckoutReturnUrl({
|
|
5468
|
+
currentHref: window.location.href,
|
|
5469
|
+
intentId: String(prepared.prepared_intent.purchase_intent_id || ""),
|
|
5470
|
+
packageSlug: normalizedSlug
|
|
5471
|
+
});
|
|
5472
|
+
const payment = await client.createMyXappPurchasePaymentSession({
|
|
5473
|
+
xappId: String(xappId),
|
|
5474
|
+
intentId: String(prepared.prepared_intent.purchase_intent_id || ""),
|
|
5475
|
+
returnUrl,
|
|
5476
|
+
cancelUrl: returnUrl,
|
|
5477
|
+
xappsResume: returnUrl,
|
|
5478
|
+
locale
|
|
5479
|
+
});
|
|
5480
|
+
const paymentPageUrl = readString5(payment.payment_page_url);
|
|
5481
|
+
const paymentStatus = readString5(payment.payment_session?.status).trim().toLowerCase();
|
|
5482
|
+
if (!paymentPageUrl && (paymentStatus === "paid" || paymentStatus === "completed")) {
|
|
5483
|
+
await finalizeCurrentUserCheckoutIntent(
|
|
5484
|
+
String(xappId),
|
|
5485
|
+
String(prepared.prepared_intent.purchase_intent_id || "")
|
|
5486
|
+
);
|
|
5487
|
+
return;
|
|
5488
|
+
}
|
|
5489
|
+
if (!paymentPageUrl) {
|
|
5490
|
+
throw new Error(
|
|
5491
|
+
t(
|
|
5492
|
+
"xapp.checkout_page_missing",
|
|
5493
|
+
void 0,
|
|
5494
|
+
"Payment page is not available for this package."
|
|
5495
|
+
)
|
|
5496
|
+
);
|
|
5497
|
+
}
|
|
5498
|
+
navigateToHostedCheckout(paymentPageUrl);
|
|
5499
|
+
} catch (error2) {
|
|
5500
|
+
const message = readString5(asRecord6(error2)?.message) || (error2 instanceof Error ? error2.message : "") || t("xapp.checkout_start_failed", void 0, "Unable to start checkout for this package.");
|
|
5501
|
+
setCheckoutError(message);
|
|
5502
|
+
} finally {
|
|
5503
|
+
setCheckoutBusyPackageSlug("");
|
|
5504
|
+
}
|
|
5505
|
+
}
|
|
4665
5506
|
const hasCatalogMonetization = hasMarketplaceCatalogMonetization(manifest);
|
|
4666
5507
|
const monetizationAccess = asRecord6(monetization?.access_projection);
|
|
4667
5508
|
const monetizationSubscription = asRecord6(monetization?.current_subscription);
|
|
5509
|
+
const additiveEntitlements = Array.isArray(monetization?.additive_entitlements) ? monetization.additive_entitlements.map((item) => asRecord6(item)).filter((item) => item ? Object.keys(item).length > 0 : false) : [];
|
|
5510
|
+
const activeAdditiveEntitlements = additiveEntitlements.filter((item) => {
|
|
5511
|
+
const status = readString5(item.status).trim().toLowerCase();
|
|
5512
|
+
return status === "active" || status === "grace_period";
|
|
5513
|
+
});
|
|
5514
|
+
const additiveUnlockLabels = activeAdditiveEntitlements.map((item) => readString5(item.tier) || readString5(item.product_slug)).filter(Boolean);
|
|
4668
5515
|
const overduePolicy = asRecord6(monetizationSubscription?.overdue_policy);
|
|
4669
|
-
const currentTier =
|
|
4670
|
-
const balanceState =
|
|
4671
|
-
const subscriptionStatus =
|
|
5516
|
+
const currentTier = readString5(monetizationSubscription?.tier) || readString5(monetizationAccess?.tier);
|
|
5517
|
+
const balanceState = readString5(monetizationAccess?.balance_state);
|
|
5518
|
+
const subscriptionStatus = readString5(monetizationSubscription?.status);
|
|
4672
5519
|
const subscriptionCoverage = typeof overduePolicy?.has_current_access === "boolean" ? overduePolicy.has_current_access ? t("xapp.subscription_coverage_active", void 0, "Still covered") : t("xapp.subscription_coverage_inactive", void 0, "Not covered") : null;
|
|
4673
|
-
const subscriptionReasonKey =
|
|
5520
|
+
const subscriptionReasonKey = readString5(overduePolicy?.effective_status_reason);
|
|
4674
5521
|
const subscriptionReason = subscriptionReasonKey === "grace_covered_past_due" ? t(
|
|
4675
5522
|
"xapp.subscription_reason_grace_covered_past_due",
|
|
4676
5523
|
void 0,
|
|
@@ -4688,17 +5535,154 @@ function XappDetailPage() {
|
|
|
4688
5535
|
const expiryBoundaryAt = formatDateTime2(overduePolicy?.expiry_boundary_at, locale);
|
|
4689
5536
|
const renewsAt = formatDateTime2(monetizationSubscription?.renews_at, locale);
|
|
4690
5537
|
const expiresAt = formatDateTime2(monetizationSubscription?.expired_at, locale) || formatDateTime2(monetizationSubscription?.current_period_ends_at, locale);
|
|
4691
|
-
const creditsRemaining =
|
|
5538
|
+
const creditsRemaining = readString5(monetizationAccess?.credits_remaining);
|
|
4692
5539
|
const accessState = resolveMarketplaceDefaultAccessState({
|
|
4693
5540
|
projection: monetizationAccessProjection,
|
|
4694
5541
|
hasCatalogMonetization,
|
|
4695
5542
|
availableLabel: t("xapp.access_state_available", void 0, "available")
|
|
4696
5543
|
});
|
|
4697
5544
|
const hasMonetizationState = Boolean(
|
|
4698
|
-
currentTier || accessState || subscriptionStatus || subscriptionCoverage || subscriptionReason || overdueSince || expiryBoundaryAt || renewsAt || expiresAt || creditsRemaining
|
|
5545
|
+
currentTier || accessState || subscriptionStatus || subscriptionCoverage || subscriptionReason || overdueSince || expiryBoundaryAt || renewsAt || expiresAt || creditsRemaining || additiveUnlockLabels.length > 0
|
|
4699
5546
|
);
|
|
4700
|
-
const manifestScreenshots = Array.isArray(manifest?.screenshots) ? manifest.screenshots.map((shot) =>
|
|
4701
|
-
const manifestTags = Array.isArray(manifest?.tags) ? manifest.tags.map((tag) =>
|
|
5547
|
+
const manifestScreenshots = Array.isArray(manifest?.screenshots) ? manifest.screenshots.map((shot) => readString5(shot)).filter(Boolean) : [];
|
|
5548
|
+
const manifestTags = Array.isArray(manifest?.tags) ? manifest.tags.map((tag) => readString5(tag)).filter(Boolean) : [];
|
|
5549
|
+
function getPackagePurchasePolicy(item) {
|
|
5550
|
+
return resolveMonetizationPackagePurchasePolicy({
|
|
5551
|
+
item,
|
|
5552
|
+
currentSubscription: monetizationSubscription,
|
|
5553
|
+
additiveEntitlements: activeAdditiveEntitlements
|
|
5554
|
+
});
|
|
5555
|
+
}
|
|
5556
|
+
const currentAccessCard = hasMonetizationState ? /* @__PURE__ */ jsxs10("div", { className: "mx-sidebar-card", children: [
|
|
5557
|
+
/* @__PURE__ */ jsx14("h3", { className: "mx-section-title mx-detail-sidebar-title", children: t("xapp.current_access_title", void 0, "Current Access") }),
|
|
5558
|
+
currentTier ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5559
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.current_plan_label", void 0, "Current plan") }),
|
|
5560
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: currentTier })
|
|
5561
|
+
] }) : null,
|
|
5562
|
+
accessState ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5563
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.access_state_label", void 0, "Access state") }),
|
|
5564
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: accessState })
|
|
5565
|
+
] }) : null,
|
|
5566
|
+
subscriptionStatus ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5567
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_status_label", void 0, "Subscription status") }),
|
|
5568
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionStatus })
|
|
5569
|
+
] }) : null,
|
|
5570
|
+
subscriptionCoverage ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5571
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_coverage_label", void 0, "Coverage") }),
|
|
5572
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionCoverage })
|
|
5573
|
+
] }) : null,
|
|
5574
|
+
subscriptionReason ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item mx-meta-item-top", children: [
|
|
5575
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_reason_label", void 0, "Status reason") }),
|
|
5576
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionReason })
|
|
5577
|
+
] }) : null,
|
|
5578
|
+
overdueSince ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5579
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_overdue_since_label", void 0, "Overdue since") }),
|
|
5580
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: overdueSince })
|
|
5581
|
+
] }) : null,
|
|
5582
|
+
expiryBoundaryAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5583
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_expiry_boundary_label", void 0, "Expiry boundary") }),
|
|
5584
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: expiryBoundaryAt })
|
|
5585
|
+
] }) : null,
|
|
5586
|
+
renewsAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5587
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.renews_at_label", void 0, "Renews at") }),
|
|
5588
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: renewsAt })
|
|
5589
|
+
] }) : null,
|
|
5590
|
+
expiresAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5591
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.expires_at_label", void 0, "Expires at") }),
|
|
5592
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: expiresAt })
|
|
5593
|
+
] }) : null,
|
|
5594
|
+
creditsRemaining ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5595
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.credits_remaining_label", void 0, "Credits remaining") }),
|
|
5596
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: creditsRemaining })
|
|
5597
|
+
] }) : null,
|
|
5598
|
+
additiveUnlockLabels.length > 0 ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item mx-meta-item-top", children: [
|
|
5599
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.add_on_unlocks_label", void 0, "Add-on unlocks") }),
|
|
5600
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-meta-value mx-meta-stack-sm", children: additiveUnlockLabels.map((label) => /* @__PURE__ */ jsx14("div", { children: label }, label)) })
|
|
5601
|
+
] }) : null
|
|
5602
|
+
] }) : null;
|
|
5603
|
+
const plansCard = selectedPaywallRenderModel ? /* @__PURE__ */ jsxs10("div", { className: "mx-sidebar-card", ref: plansSectionRef, children: [
|
|
5604
|
+
/* @__PURE__ */ jsx14("h3", { className: "mx-section-title mx-detail-sidebar-title", children: t("xapp.plan_options_title", void 0, "Plans") }),
|
|
5605
|
+
/* @__PURE__ */ jsxs10("div", { className: "mx-paywall-card-head", children: [
|
|
5606
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-title", children: selectedPaywallRenderModel.paywallLabel }),
|
|
5607
|
+
selectedPaywallRenderModel.summary ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-summary", children: selectedPaywallRenderModel.summary }) : null
|
|
5608
|
+
] }),
|
|
5609
|
+
selectedPaywallRenderModel.badges.length > 0 ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-badges", children: selectedPaywallRenderModel.badges.map((badge) => /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-badge", children: badge }, badge)) }) : null,
|
|
5610
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-packages", children: selectedPaywallRenderModel.packages.map((item) => {
|
|
5611
|
+
const normalizedPackageSlug = item.packageSlug.trim().toLowerCase();
|
|
5612
|
+
const purchasePolicy = getPackagePurchasePolicy(item);
|
|
5613
|
+
const isCurrentPackage = purchasePolicy.status === "current_recurring_plan";
|
|
5614
|
+
const isOwnedAdditive = purchasePolicy.status === "owned_additive_unlock";
|
|
5615
|
+
const isAdditiveCompanion = purchasePolicy.transitionKind === "buy_additive_unlock" && subscriptionStatus === "active";
|
|
5616
|
+
return /* @__PURE__ */ jsxs10(
|
|
5617
|
+
"div",
|
|
5618
|
+
{
|
|
5619
|
+
className: `mx-paywall-card-package ${item.isDefault ? "is-default" : ""} ${selectedPaywallPackageSlug && normalizedPackageSlug === selectedPaywallPackageSlug ? "is-selected" : ""}`,
|
|
5620
|
+
children: [
|
|
5621
|
+
/* @__PURE__ */ jsxs10("div", { className: "mx-paywall-card-package-head", children: [
|
|
5622
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
5623
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-package-title", children: item.packageTitle }),
|
|
5624
|
+
item.description ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-package-description", children: item.description }) : null
|
|
5625
|
+
] }),
|
|
5626
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-money", children: item.moneyLabel })
|
|
5627
|
+
] }),
|
|
5628
|
+
/* @__PURE__ */ jsxs10("div", { className: "mx-paywall-card-package-meta", children: [
|
|
5629
|
+
/* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-fit", children: item.fitLabel }),
|
|
5630
|
+
selectedPaywallPackageSlug && normalizedPackageSlug === selectedPaywallPackageSlug ? /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-default", children: t("xapp.selected_label", void 0, "Selected") }) : null,
|
|
5631
|
+
isOwnedAdditive ? /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-default", children: t("xapp.owned_unlock_label", void 0, "Owned unlock") }) : null,
|
|
5632
|
+
isCurrentPackage && !isOwnedAdditive ? /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-default", children: t("xapp.current_plan_label", void 0, "Current plan") }) : null,
|
|
5633
|
+
isAdditiveCompanion ? /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-default", children: t("xapp.additive_unlock_label", void 0, "Add-on with membership") }) : null,
|
|
5634
|
+
item.isDefault ? /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-package-default", children: t("xapp.default_label", void 0, "Default") }) : null
|
|
5635
|
+
] }),
|
|
5636
|
+
item.signals.length > 0 ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-signals", children: item.signals.map((signal) => /* @__PURE__ */ jsx14("span", { className: "mx-paywall-card-signal", children: signal }, signal)) }) : null,
|
|
5637
|
+
isAdditiveCompanion ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-summary", children: t(
|
|
5638
|
+
"xapp.additive_unlock_message",
|
|
5639
|
+
void 0,
|
|
5640
|
+
"This one-time unlock is additive. It adds access on top of the active recurring membership instead of replacing it."
|
|
5641
|
+
) }) : null,
|
|
5642
|
+
typeof client.prepareMyXappPurchaseIntent === "function" && typeof client.createMyXappPurchasePaymentSession === "function" && canMutate ? /* @__PURE__ */ jsx14(
|
|
5643
|
+
"button",
|
|
5644
|
+
{
|
|
5645
|
+
className: "mx-btn mx-btn-secondary",
|
|
5646
|
+
disabled: !purchasePolicy.canPurchase || checkoutBusyPackageSlug === normalizedPackageSlug,
|
|
5647
|
+
onClick: () => void startPackageCheckout(item.packageSlug),
|
|
5648
|
+
children: isOwnedAdditive ? t("xapp.owned_unlock_active", void 0, "Owned unlock active") : isCurrentPackage ? t("xapp.current_plan_active", void 0, "Current plan active") : checkoutBusyPackageSlug === normalizedPackageSlug ? t("xapp.checkout_starting", void 0, "Starting checkout...") : isAdditiveCompanion ? t("xapp.additive_unlock_action", void 0, "Purchase add-on unlock") : t("xapp.checkout_action", void 0, "Continue to checkout")
|
|
5649
|
+
}
|
|
5650
|
+
) : null
|
|
5651
|
+
]
|
|
5652
|
+
},
|
|
5653
|
+
item.packageId || item.packageSlug
|
|
5654
|
+
);
|
|
5655
|
+
}) }),
|
|
5656
|
+
checkoutNotice ? /* @__PURE__ */ jsx14("div", { className: "mx-paywall-card-summary", children: checkoutNotice }) : null,
|
|
5657
|
+
checkoutError ? /* @__PURE__ */ jsx14("div", { className: "mx-payment-lock-error", children: checkoutError }) : null
|
|
5658
|
+
] }) : null;
|
|
5659
|
+
if (plansOnlyMode) {
|
|
5660
|
+
return /* @__PURE__ */ jsxs10("div", { className: `mx-detail-container ${isEmbedded ? "is-embedded" : ""}`, children: [
|
|
5661
|
+
error && /* @__PURE__ */ jsx14("div", { className: "mx-detail-error", children: error }),
|
|
5662
|
+
busy && !data ? /* @__PURE__ */ jsx14("div", { className: "mx-sidebar-card mx-detail-empty", "aria-busy": "true", children: t("common.loading", void 0, "Loading...") }) : /* @__PURE__ */ jsxs10("div", { className: `mx-plans-route ${widgetHostedPlansMode ? "is-widget-hosted" : ""}`, children: [
|
|
5663
|
+
!widgetHostedPlansMode ? /* @__PURE__ */ jsxs10("div", { className: "mx-plans-route-header", children: [
|
|
5664
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-plans-route-title", children: t("xapp.plan_options_title", void 0, "Plans") }),
|
|
5665
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-plans-route-subtitle", children: title ? t(
|
|
5666
|
+
"xapp.plans_route_subtitle",
|
|
5667
|
+
{ title },
|
|
5668
|
+
`Current access and published plans for ${title}.`
|
|
5669
|
+
) : t(
|
|
5670
|
+
"xapp.plans_route_subtitle_default",
|
|
5671
|
+
void 0,
|
|
5672
|
+
"Current access and published plans for this app."
|
|
5673
|
+
) })
|
|
5674
|
+
] }) : null,
|
|
5675
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-plans-route-grid", children: /* @__PURE__ */ jsxs10("div", { className: "mx-plans-route-main", children: [
|
|
5676
|
+
currentAccessCard,
|
|
5677
|
+
plansCard || /* @__PURE__ */ jsx14("div", { className: "mx-sidebar-card mx-detail-empty", children: t(
|
|
5678
|
+
"xapp.no_plans_available",
|
|
5679
|
+
void 0,
|
|
5680
|
+
"No published plans are currently available."
|
|
5681
|
+
) })
|
|
5682
|
+
] }) })
|
|
5683
|
+
] })
|
|
5684
|
+
] });
|
|
5685
|
+
}
|
|
4702
5686
|
return /* @__PURE__ */ jsxs10("div", { className: `mx-detail-container ${isEmbedded ? "is-embedded" : ""}`, children: [
|
|
4703
5687
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-topbar", children: [
|
|
4704
5688
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-topbar-left", children: [
|
|
@@ -4778,15 +5762,15 @@ function XappDetailPage() {
|
|
|
4778
5762
|
description ? /* @__PURE__ */ jsx14("p", { className: "mx-detail-subtitle", children: description }) : null,
|
|
4779
5763
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-meta-row", children: [
|
|
4780
5764
|
/* @__PURE__ */ jsx14("div", { className: "mx-card-slug", children: xappId }),
|
|
4781
|
-
|
|
5765
|
+
readString5(versionRecord?.version) && /* @__PURE__ */ jsxs10("div", { className: "mx-card-version mx-detail-version-pill", children: [
|
|
4782
5766
|
"v",
|
|
4783
|
-
|
|
5767
|
+
readString5(versionRecord?.version)
|
|
4784
5768
|
] }),
|
|
4785
5769
|
updateAvailable ? /* @__PURE__ */ jsx14("div", { className: "mx-detail-update-pill", children: t("xapp.update_available", void 0, "Update available") }) : null
|
|
4786
5770
|
] })
|
|
4787
5771
|
] }),
|
|
4788
|
-
/* @__PURE__ */ jsx14("div", { className: "mx-detail-actions", children: canMutate ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
|
|
4789
|
-
installation && updateAvailable && host.requestUpdate ? /* @__PURE__ */ jsx14(
|
|
5772
|
+
/* @__PURE__ */ jsx14("div", { className: "mx-detail-actions", children: canMutate && mutationControlsReady ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
|
|
5773
|
+
installation && updateAvailable && host.requestUpdate && installationPolicy?.update_mode !== "auto_update_compatible" ? /* @__PURE__ */ jsx14(
|
|
4790
5774
|
"button",
|
|
4791
5775
|
{
|
|
4792
5776
|
className: "mx-btn mx-btn-primary",
|
|
@@ -4795,14 +5779,13 @@ function XappDetailPage() {
|
|
|
4795
5779
|
if (requiresTerms) {
|
|
4796
5780
|
setTermsAccepted(false);
|
|
4797
5781
|
setTermsAction("update");
|
|
5782
|
+
setTermsWidgetId(null);
|
|
5783
|
+
setTermsWidgetName(null);
|
|
4798
5784
|
setTermsOpen(true);
|
|
4799
5785
|
return;
|
|
4800
5786
|
}
|
|
4801
5787
|
if (!installation.installationId) return;
|
|
4802
|
-
|
|
4803
|
-
installationId: installation.installationId,
|
|
4804
|
-
xappId: String(xappId ?? "")
|
|
4805
|
-
});
|
|
5788
|
+
requestUpdateForWidget(null);
|
|
4806
5789
|
},
|
|
4807
5790
|
children: updateAppLabel
|
|
4808
5791
|
}
|
|
@@ -4816,18 +5799,23 @@ function XappDetailPage() {
|
|
|
4816
5799
|
if (requiresTerms) {
|
|
4817
5800
|
setTermsAccepted(false);
|
|
4818
5801
|
setTermsAction("install");
|
|
5802
|
+
setTermsWidgetId(readString5(defaultWidget?.id) || null);
|
|
5803
|
+
setTermsWidgetName(
|
|
5804
|
+
resolveMarketplaceText(defaultWidget?.title, locale) || null
|
|
5805
|
+
);
|
|
4819
5806
|
setTermsOpen(true);
|
|
4820
5807
|
return;
|
|
4821
5808
|
}
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
5809
|
+
requestInstallForWidget(
|
|
5810
|
+
readString5(defaultWidget?.id) || null,
|
|
5811
|
+
resolveMarketplaceText(defaultWidget?.title, locale) || null,
|
|
5812
|
+
false,
|
|
5813
|
+
autoAvailableMode
|
|
5814
|
+
);
|
|
4827
5815
|
},
|
|
4828
|
-
children: addAppLabel
|
|
5816
|
+
children: autoAvailableMode ? openAppLabel : addAppLabel
|
|
4829
5817
|
}
|
|
4830
|
-
) : /* @__PURE__ */ jsx14(
|
|
5818
|
+
) : !autoAvailableMode ? /* @__PURE__ */ jsx14(
|
|
4831
5819
|
"button",
|
|
4832
5820
|
{
|
|
4833
5821
|
className: "mx-btn mx-btn-outline",
|
|
@@ -4839,7 +5827,7 @@ function XappDetailPage() {
|
|
|
4839
5827
|
},
|
|
4840
5828
|
children: removeAppLabel
|
|
4841
5829
|
}
|
|
4842
|
-
)
|
|
5830
|
+
) : null
|
|
4843
5831
|
] }) : null })
|
|
4844
5832
|
] }),
|
|
4845
5833
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-grid", children: [
|
|
@@ -4850,11 +5838,19 @@ function XappDetailPage() {
|
|
|
4850
5838
|
] }),
|
|
4851
5839
|
/* @__PURE__ */ jsxs10("section", { className: "mx-detail-section mx-detail-section-widgets", children: [
|
|
4852
5840
|
/* @__PURE__ */ jsx14("h2", { className: "mx-section-title", children: t("xapp.available_views_title", void 0, "Available Views") }),
|
|
4853
|
-
!widgetsEnabled ? /* @__PURE__ */ jsx14("div", { className: "mx-sidebar-card mx-detail-empty", children: !installation ? t(
|
|
5841
|
+
!widgetsEnabled ? /* @__PURE__ */ jsx14("div", { className: "mx-sidebar-card mx-detail-empty", children: !installation ? autoAvailableMode ? t(
|
|
5842
|
+
"xapp.open_to_access_views",
|
|
5843
|
+
void 0,
|
|
5844
|
+
"Open this app to start and install it automatically for your workspace."
|
|
5845
|
+
) : t(
|
|
4854
5846
|
"xapp.add_to_access_views",
|
|
4855
5847
|
void 0,
|
|
4856
5848
|
"Add this app to your workspace to access its available views."
|
|
4857
|
-
) : updateAvailable ? t(
|
|
5849
|
+
) : updateAvailable ? autoUpdateMode ? t(
|
|
5850
|
+
"xapp.update_to_access_views_auto",
|
|
5851
|
+
void 0,
|
|
5852
|
+
"Open a view to update the app automatically for your workspace."
|
|
5853
|
+
) : t(
|
|
4858
5854
|
"xapp.update_to_access_views",
|
|
4859
5855
|
void 0,
|
|
4860
5856
|
"An update is available. Please update the app to access its available views."
|
|
@@ -4867,9 +5863,9 @@ function XappDetailPage() {
|
|
|
4867
5863
|
void 0,
|
|
4868
5864
|
"No app views are currently available."
|
|
4869
5865
|
) }) : /* @__PURE__ */ jsx14("div", { className: "mx-detail-widget-list", children: widgets.map((w, idx) => {
|
|
4870
|
-
const name = resolveMarketplaceText(w.title, locale) ||
|
|
5866
|
+
const name = resolveMarketplaceText(w.title, locale) || readString5(w.widget_name) || readString5(w.name) || readString5(w.id) || t("common.widget", void 0, "Widget");
|
|
4871
5867
|
const disabled = !widgetsEnabled;
|
|
4872
|
-
const isDefault =
|
|
5868
|
+
const isDefault = readBoolean2(w.default, false) || idx === 0 && !widgets.some((ww) => readBoolean2(ww.default, false));
|
|
4873
5869
|
const widgetType = String(w.type || "").toLowerCase();
|
|
4874
5870
|
return /* @__PURE__ */ jsxs10(
|
|
4875
5871
|
"button",
|
|
@@ -4877,24 +5873,10 @@ function XappDetailPage() {
|
|
|
4877
5873
|
disabled,
|
|
4878
5874
|
className: `mx-detail-widget-card ${disabled ? "is-disabled" : ""} ${isDefault ? "is-default" : ""}`,
|
|
4879
5875
|
onClick: () => {
|
|
4880
|
-
if (!
|
|
4881
|
-
const widgetId =
|
|
5876
|
+
if (!widgetsEnabled) return;
|
|
5877
|
+
const widgetId = readString5(w.id);
|
|
4882
5878
|
if (!widgetId) return;
|
|
4883
|
-
|
|
4884
|
-
navigate({
|
|
4885
|
-
pathname: isEmbedded ? `/widget/${encodeURIComponent(installation.installationId)}/${encodeURIComponent(widgetId)}` : `/marketplace/widget/${encodeURIComponent(installation.installationId)}/${encodeURIComponent(widgetId)}`,
|
|
4886
|
-
search: tokenSearch
|
|
4887
|
-
});
|
|
4888
|
-
return;
|
|
4889
|
-
}
|
|
4890
|
-
host.openWidget({
|
|
4891
|
-
installationId: installation.installationId,
|
|
4892
|
-
widgetId,
|
|
4893
|
-
xappId: String(xappId ?? ""),
|
|
4894
|
-
xappTitle: String(title),
|
|
4895
|
-
widgetName: name,
|
|
4896
|
-
toolName: readString4(w.bind_tool_name)
|
|
4897
|
-
});
|
|
5879
|
+
launchWidgetForSubject(widgetId, name, readString5(w.bind_tool_name));
|
|
4898
5880
|
},
|
|
4899
5881
|
children: [
|
|
4900
5882
|
/* @__PURE__ */ jsx14("div", { className: "mx-detail-widget-icon", children: widgetType === "read" ? /* @__PURE__ */ jsxs10(
|
|
@@ -4929,7 +5911,7 @@ function XappDetailPage() {
|
|
|
4929
5911
|
) }),
|
|
4930
5912
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-widget-body", children: [
|
|
4931
5913
|
/* @__PURE__ */ jsx14("div", { className: "mx-detail-widget-name", children: name }),
|
|
4932
|
-
|
|
5914
|
+
readString5(w.bind_tool_name) && /* @__PURE__ */ jsx14("div", { className: "mx-detail-widget-tool", children: readString5(w.bind_tool_name) }),
|
|
4933
5915
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-widget-badges", children: [
|
|
4934
5916
|
isDefault && /* @__PURE__ */ jsx14("span", { className: "mx-detail-widget-badge is-primary", children: t("xapp.widget_primary", void 0, "Primary") }),
|
|
4935
5917
|
widgetType && /* @__PURE__ */ jsx14("span", { className: "mx-detail-widget-badge", children: widgetType })
|
|
@@ -5062,7 +6044,14 @@ function XappDetailPage() {
|
|
|
5062
6044
|
children: [
|
|
5063
6045
|
/* @__PURE__ */ jsxs10("div", { className: "mx-guard-row-left", children: [
|
|
5064
6046
|
guard.order !== null ? /* @__PURE__ */ jsx14("span", { className: "mx-guard-row-order", children: guard.order }) : /* @__PURE__ */ jsx14("span", { className: "mx-guard-row-order", children: guardIdx + 1 }),
|
|
5065
|
-
/* @__PURE__ */ jsx14(
|
|
6047
|
+
/* @__PURE__ */ jsx14(
|
|
6048
|
+
"span",
|
|
6049
|
+
{
|
|
6050
|
+
className: "mx-guard-row-name",
|
|
6051
|
+
title: guard.label || guard.slug,
|
|
6052
|
+
children: guard.label ? guard.label : humanizeSlug(guard.slug)
|
|
6053
|
+
}
|
|
6054
|
+
)
|
|
5066
6055
|
] }),
|
|
5067
6056
|
/* @__PURE__ */ jsxs10("div", { className: "mx-guard-row-right", children: [
|
|
5068
6057
|
/* @__PURE__ */ jsxs10(
|
|
@@ -5145,49 +6134,7 @@ function XappDetailPage() {
|
|
|
5145
6134
|
] })
|
|
5146
6135
|
] }),
|
|
5147
6136
|
/* @__PURE__ */ jsxs10("aside", { className: "mx-detail-sidebar", children: [
|
|
5148
|
-
|
|
5149
|
-
/* @__PURE__ */ jsx14("h3", { className: "mx-section-title mx-detail-sidebar-title", children: t("xapp.current_access_title", void 0, "Current Access") }),
|
|
5150
|
-
currentTier ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5151
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.current_plan_label", void 0, "Current plan") }),
|
|
5152
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: currentTier })
|
|
5153
|
-
] }) : null,
|
|
5154
|
-
accessState ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5155
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.access_state_label", void 0, "Access state") }),
|
|
5156
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: accessState })
|
|
5157
|
-
] }) : null,
|
|
5158
|
-
subscriptionStatus ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5159
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_status_label", void 0, "Subscription status") }),
|
|
5160
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionStatus })
|
|
5161
|
-
] }) : null,
|
|
5162
|
-
subscriptionCoverage ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5163
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_coverage_label", void 0, "Coverage") }),
|
|
5164
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionCoverage })
|
|
5165
|
-
] }) : null,
|
|
5166
|
-
subscriptionReason ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item mx-meta-item-top", children: [
|
|
5167
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_reason_label", void 0, "Status reason") }),
|
|
5168
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: subscriptionReason })
|
|
5169
|
-
] }) : null,
|
|
5170
|
-
overdueSince ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5171
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_overdue_since_label", void 0, "Overdue since") }),
|
|
5172
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: overdueSince })
|
|
5173
|
-
] }) : null,
|
|
5174
|
-
expiryBoundaryAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5175
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.subscription_expiry_boundary_label", void 0, "Expiry boundary") }),
|
|
5176
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: expiryBoundaryAt })
|
|
5177
|
-
] }) : null,
|
|
5178
|
-
renewsAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5179
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.renews_at_label", void 0, "Renews at") }),
|
|
5180
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: renewsAt })
|
|
5181
|
-
] }) : null,
|
|
5182
|
-
expiresAt ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5183
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.expires_at_label", void 0, "Expires at") }),
|
|
5184
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: expiresAt })
|
|
5185
|
-
] }) : null,
|
|
5186
|
-
creditsRemaining ? /* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
5187
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-label", children: t("xapp.credits_remaining_label", void 0, "Credits remaining") }),
|
|
5188
|
-
/* @__PURE__ */ jsx14("span", { className: "mx-meta-value", children: creditsRemaining })
|
|
5189
|
-
] }) : null
|
|
5190
|
-
] }) : null,
|
|
6137
|
+
currentAccessCard,
|
|
5191
6138
|
usageCreditSummary ? /* @__PURE__ */ jsxs10("div", { className: "mx-sidebar-card", children: [
|
|
5192
6139
|
/* @__PURE__ */ jsx14("h3", { className: "mx-section-title mx-detail-sidebar-title", children: t("xapp.usage_credits_title", void 0, "Usage Credits") }),
|
|
5193
6140
|
/* @__PURE__ */ jsxs10("div", { className: "mx-meta-item", children: [
|
|
@@ -5248,26 +6195,19 @@ function XappDetailPage() {
|
|
|
5248
6195
|
] }, tool.tool_name)) })
|
|
5249
6196
|
] }) : null
|
|
5250
6197
|
] }) : null,
|
|
5251
|
-
|
|
6198
|
+
plansCard,
|
|
6199
|
+
defaultWidget && hasSubject && (installation || autoAvailableMode) && /* @__PURE__ */ jsx14(
|
|
5252
6200
|
"button",
|
|
5253
6201
|
{
|
|
5254
6202
|
className: "mx-btn mx-btn-primary mx-detail-primary-cta",
|
|
5255
6203
|
onClick: () => {
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
host.openWidget({
|
|
5264
|
-
installationId: installation.installationId,
|
|
5265
|
-
widgetId: readString4(defaultWidget.id),
|
|
5266
|
-
xappId: String(xappId ?? ""),
|
|
5267
|
-
xappTitle: String(title),
|
|
5268
|
-
widgetName: resolveMarketplaceText(defaultWidget?.title, locale) || readString4(defaultWidget?.widget_name) || readString4(defaultWidget?.name) || t("common.widget", void 0, "Widget"),
|
|
5269
|
-
toolName: readString4(defaultWidget?.bind_tool_name)
|
|
5270
|
-
});
|
|
6204
|
+
const widgetId = readString5(defaultWidget.id);
|
|
6205
|
+
if (!widgetId) return;
|
|
6206
|
+
launchWidgetForSubject(
|
|
6207
|
+
widgetId,
|
|
6208
|
+
resolveMarketplaceText(defaultWidget?.title, locale) || readString5(defaultWidget?.widget_name) || readString5(defaultWidget?.name) || t("common.widget", void 0, "Widget"),
|
|
6209
|
+
readString5(defaultWidget?.bind_tool_name)
|
|
6210
|
+
);
|
|
5271
6211
|
},
|
|
5272
6212
|
children: openAppLabel
|
|
5273
6213
|
}
|
|
@@ -5448,21 +6388,35 @@ function XappDetailPage() {
|
|
|
5448
6388
|
] })
|
|
5449
6389
|
] }),
|
|
5450
6390
|
/* @__PURE__ */ jsxs10("div", { className: "mx-detail-modal-actions", children: [
|
|
5451
|
-
/* @__PURE__ */ jsx14(
|
|
6391
|
+
/* @__PURE__ */ jsx14(
|
|
6392
|
+
"button",
|
|
6393
|
+
{
|
|
6394
|
+
className: "mx-btn mx-btn-outline",
|
|
6395
|
+
onClick: () => {
|
|
6396
|
+
setTermsOpen(false);
|
|
6397
|
+
setTermsAction("none");
|
|
6398
|
+
setTermsWidgetId(null);
|
|
6399
|
+
setTermsWidgetName(null);
|
|
6400
|
+
},
|
|
6401
|
+
children: t("common.cancel", void 0, "Cancel")
|
|
6402
|
+
}
|
|
6403
|
+
),
|
|
5452
6404
|
termsAction === "install" ? /* @__PURE__ */ jsx14(
|
|
5453
6405
|
"button",
|
|
5454
6406
|
{
|
|
5455
6407
|
className: "mx-btn mx-btn-primary",
|
|
5456
6408
|
disabled: !termsAccepted,
|
|
5457
6409
|
onClick: () => {
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
6410
|
+
requestInstallForWidget(
|
|
6411
|
+
termsWidgetId ?? readString5(defaultWidget?.id) ?? null,
|
|
6412
|
+
termsWidgetName || resolveMarketplaceText(defaultWidget?.title, locale) || null,
|
|
6413
|
+
true,
|
|
6414
|
+
autoAvailableMode
|
|
6415
|
+
);
|
|
5464
6416
|
setTermsOpen(false);
|
|
5465
6417
|
setTermsAction("none");
|
|
6418
|
+
setTermsWidgetId(null);
|
|
6419
|
+
setTermsWidgetName(null);
|
|
5466
6420
|
},
|
|
5467
6421
|
children: t("xapp.accept_add_app", void 0, "Accept & Add app")
|
|
5468
6422
|
}
|
|
@@ -5473,13 +6427,11 @@ function XappDetailPage() {
|
|
|
5473
6427
|
disabled: !termsAccepted || !installation,
|
|
5474
6428
|
onClick: () => {
|
|
5475
6429
|
if (!installation) return;
|
|
5476
|
-
|
|
5477
|
-
installationId: installation.installationId,
|
|
5478
|
-
xappId: String(xappId ?? ""),
|
|
5479
|
-
termsAccepted: true
|
|
5480
|
-
});
|
|
6430
|
+
requestUpdateForWidget(termsWidgetId, true);
|
|
5481
6431
|
setTermsOpen(false);
|
|
5482
6432
|
setTermsAction("none");
|
|
6433
|
+
setTermsWidgetId(null);
|
|
6434
|
+
setTermsWidgetName(null);
|
|
5483
6435
|
},
|
|
5484
6436
|
children: t("xapp.accept_update", void 0, "Accept & Update")
|
|
5485
6437
|
}
|
|
@@ -6741,6 +7693,7 @@ function MarketplaceApp() {
|
|
|
6741
7693
|
/* @__PURE__ */ jsx18(Route, { path: "publishers", element: /* @__PURE__ */ jsx18(PublishersPage, {}) }),
|
|
6742
7694
|
/* @__PURE__ */ jsx18(Route, { path: "publishers/:publisherSlug", element: /* @__PURE__ */ jsx18(PublisherDetailPage, {}) }),
|
|
6743
7695
|
/* @__PURE__ */ jsx18(Route, { path: "xapps/:xappId", element: /* @__PURE__ */ jsx18(XappDetailPage, {}) }),
|
|
7696
|
+
/* @__PURE__ */ jsx18(Route, { path: "xapps/:xappId/plans", element: /* @__PURE__ */ jsx18(XappPlansPage, {}) }),
|
|
6744
7697
|
/* @__PURE__ */ jsx18(Route, { path: "requests", element: /* @__PURE__ */ jsx18(RequestsPage, {}) }),
|
|
6745
7698
|
/* @__PURE__ */ jsx18(Route, { path: "payments", element: /* @__PURE__ */ jsx18(PaymentsPage, {}) }),
|
|
6746
7699
|
/* @__PURE__ */ jsx18(Route, { path: "invoices", element: /* @__PURE__ */ jsx18(InvoicesPage, {}) }),
|
|
@@ -6761,6 +7714,7 @@ export {
|
|
|
6761
7714
|
RequestsPage,
|
|
6762
7715
|
WidgetView,
|
|
6763
7716
|
XappDetailPage,
|
|
7717
|
+
XappPlansPage,
|
|
6764
7718
|
resolveMarketplaceText,
|
|
6765
7719
|
resolvePaymentLockStateFromGuardSummary,
|
|
6766
7720
|
useMarketplace,
|