@adminide-stack/yantra-mobile 12.0.38 → 12.0.39-alpha.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.
Files changed (35) hide show
  1. package/lib/components/NavigationHeader/NavigationHeader.js +6 -2
  2. package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
  3. package/lib/features/templates/buildTemplateCards.js +150 -0
  4. package/lib/features/templates/buildTemplateCards.js.map +1 -0
  5. package/lib/features/templates/buildTemplateCards.ts +203 -0
  6. package/lib/features/templates/index.ts +1 -0
  7. package/lib/hooks/mintSurfaceSystemToken.js +79 -39
  8. package/lib/hooks/mintSurfaceSystemToken.js.map +1 -1
  9. package/lib/hooks/useCdecliAutoConnect.js +1 -1
  10. package/lib/hooks/useCdecliAutoConnect.js.map +1 -1
  11. package/lib/hooks/useMarketplaceTemplateCards.js +32 -0
  12. package/lib/hooks/useMarketplaceTemplateCards.js.map +1 -0
  13. package/lib/hooks/useMarketplaceTemplateGroups.js +32 -0
  14. package/lib/hooks/useMarketplaceTemplateGroups.js.map +1 -0
  15. package/lib/hooks/useObtainSystemToken.js +37 -29
  16. package/lib/hooks/useObtainSystemToken.js.map +1 -1
  17. package/lib/hooks/usePrerequisiteIds.js +62 -21
  18. package/lib/hooks/usePrerequisiteIds.js.map +1 -1
  19. package/lib/screens/Home/HomeScreen.js +164 -50
  20. package/lib/screens/Home/HomeScreen.js.map +1 -1
  21. package/lib/screens/Home/components/BuildTemplatesSection.js +156 -0
  22. package/lib/screens/Home/components/BuildTemplatesSection.js.map +1 -0
  23. package/lib/screens/Home/components/WebBuilderPrewarm.js +83 -0
  24. package/lib/screens/Home/components/WebBuilderPrewarm.js.map +1 -0
  25. package/lib/screens/WebBuilder/WebViewWithNavigation.js +3 -7
  26. package/lib/screens/WebBuilder/WebViewWithNavigation.js.map +1 -1
  27. package/lib/screens/WebBuilder/index.js +146 -36
  28. package/lib/screens/WebBuilder/index.js.map +1 -1
  29. package/lib/screens/WebBuilder/webbuilderBackHandler.js +11 -0
  30. package/lib/screens/WebBuilder/webbuilderBackHandler.js.map +1 -0
  31. package/lib/screens/WebBuilder/webbuilderWarmCache.js +89 -0
  32. package/lib/screens/WebBuilder/webbuilderWarmCache.js.map +1 -0
  33. package/lib/utils/cdecodeUri.js +11 -1
  34. package/lib/utils/cdecodeUri.js.map +1 -1
  35. package/package.json +4 -4
@@ -0,0 +1,156 @@
1
+ import {jsxs,jsx}from'react/jsx-runtime';import {useCallback}from'react';import {useWindowDimensions,Pressable,StyleSheet,View,Image,Text,ActivityIndicator,ScrollView}from'react-native';import {useMarketplaceTemplateCards}from'../../../hooks/useMarketplaceTemplateCards.js';function BuildTemplatesSection({
2
+ enabled,
3
+ group,
4
+ orgName,
5
+ isDark,
6
+ primaryTextColor,
7
+ secondaryTextColor,
8
+ selectedTemplateId = null,
9
+ onUseTemplate
10
+ }) {
11
+ const {
12
+ width
13
+ } = useWindowDimensions();
14
+ const selectedGroup = (group != null ? group : "").trim();
15
+ const {
16
+ cards,
17
+ loading,
18
+ error
19
+ } = useMarketplaceTemplateCards({
20
+ group: selectedGroup,
21
+ orgName,
22
+ enabled: enabled && Boolean(selectedGroup)
23
+ });
24
+ const cardWidth = Math.min(168, Math.max(140, (width - 56) / 2));
25
+ const renderCard = useCallback((item) => {
26
+ var _a;
27
+ const cover = (_a = item.coverImageUrl) == null ? void 0 : _a.trim();
28
+ const selected = selectedTemplateId === item.id;
29
+ return /* @__PURE__ */ jsxs(Pressable, { onPress: () => onUseTemplate(item), style: [styles.card, {
30
+ width: cardWidth,
31
+ backgroundColor: isDark ? "#1e293b" : "#ffffff",
32
+ borderColor: selected ? isDark ? "#818cf8" : "#4338ca" : isDark ? "rgba(148,163,184,0.28)" : "rgba(15,23,42,0.08)",
33
+ borderWidth: selected ? 2 : 1
34
+ }], accessibilityRole: "button", accessibilityState: {
35
+ selected
36
+ }, accessibilityLabel: `${selected ? "Selected" : "Select"} template ${item.title}`, children: [
37
+ /* @__PURE__ */ jsx(View, { style: [styles.cover, {
38
+ backgroundColor: isDark ? "#0f172a" : "#f1f5f9"
39
+ }], children: cover ? /* @__PURE__ */ jsx(Image, { source: {
40
+ uri: cover
41
+ }, style: styles.coverImage, resizeMode: "cover" }) : /* @__PURE__ */ jsx(Text, { style: [styles.coverFallback, {
42
+ color: secondaryTextColor
43
+ }], children: "Yantra" }) }),
44
+ /* @__PURE__ */ jsxs(View, { style: styles.cardBody, children: [
45
+ /* @__PURE__ */ jsx(Text, { style: [styles.cardTitle, {
46
+ color: primaryTextColor
47
+ }], numberOfLines: 2, children: item.title }),
48
+ item.snapshotId ? /* @__PURE__ */ jsx(Text, { style: [styles.cardMeta, {
49
+ color: secondaryTextColor
50
+ }], numberOfLines: 1, children: "Remix ready" }) : null,
51
+ /* @__PURE__ */ jsx(Text, { style: [styles.useLabel, {
52
+ color: isDark ? "#a5b4fc" : "#4338ca"
53
+ }], children: selected ? "Selected" : "Select" })
54
+ ] })
55
+ ] }, item.id);
56
+ }, [cardWidth, isDark, onUseTemplate, primaryTextColor, secondaryTextColor, selectedTemplateId]);
57
+ if (!enabled || !selectedGroup) {
58
+ return null;
59
+ }
60
+ if (loading && cards.length === 0) {
61
+ return /* @__PURE__ */ jsxs(View, { style: styles.statusWrap, children: [
62
+ /* @__PURE__ */ jsx(ActivityIndicator, { color: isDark ? "#a5b4fc" : "#4338ca" }),
63
+ /* @__PURE__ */ jsx(Text, { style: [styles.statusText, {
64
+ color: secondaryTextColor
65
+ }], children: "Loading templates\u2026" })
66
+ ] });
67
+ }
68
+ if (error && cards.length === 0) {
69
+ return /* @__PURE__ */ jsx(View, { style: styles.statusWrap, children: /* @__PURE__ */ jsx(Text, { style: [styles.statusText, {
70
+ color: secondaryTextColor
71
+ }], children: "Couldn\u2019t load templates. Try another group." }) });
72
+ }
73
+ if (cards.length === 0) {
74
+ return /* @__PURE__ */ jsx(View, { style: styles.statusWrap, children: /* @__PURE__ */ jsx(Text, { style: [styles.statusText, {
75
+ color: secondaryTextColor
76
+ }], children: "No remixable templates in this group yet." }) });
77
+ }
78
+ return /* @__PURE__ */ jsxs(View, { style: styles.section, children: [
79
+ /* @__PURE__ */ jsx(Text, { style: [styles.sectionTitle, {
80
+ color: primaryTextColor
81
+ }], children: "Yantra templates" }),
82
+ /* @__PURE__ */ jsx(Text, { style: [styles.sectionHint, {
83
+ color: secondaryTextColor
84
+ }], children: "Select a starter, type your prompt, then send \u2014 message + snapshot go to Web Builder." }),
85
+ /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, contentContainerStyle: styles.listContent, children: cards.map(renderCard) })
86
+ ] });
87
+ }
88
+ const styles = StyleSheet.create({
89
+ section: {
90
+ width: "100%",
91
+ marginTop: 20,
92
+ paddingBottom: 8
93
+ },
94
+ sectionTitle: {
95
+ fontSize: 16,
96
+ fontWeight: "700",
97
+ marginBottom: 4,
98
+ paddingHorizontal: 4
99
+ },
100
+ sectionHint: {
101
+ fontSize: 12,
102
+ lineHeight: 18,
103
+ marginBottom: 12,
104
+ paddingHorizontal: 4
105
+ },
106
+ listContent: {
107
+ paddingHorizontal: 2,
108
+ gap: 12
109
+ },
110
+ card: {
111
+ borderRadius: 14,
112
+ borderWidth: 1,
113
+ overflow: "hidden"
114
+ },
115
+ cover: {
116
+ height: 96,
117
+ alignItems: "center",
118
+ justifyContent: "center"
119
+ },
120
+ coverImage: {
121
+ width: "100%",
122
+ height: "100%"
123
+ },
124
+ coverFallback: {
125
+ fontSize: 13,
126
+ fontWeight: "600"
127
+ },
128
+ cardBody: {
129
+ paddingHorizontal: 10,
130
+ paddingVertical: 10,
131
+ gap: 4
132
+ },
133
+ cardTitle: {
134
+ fontSize: 13,
135
+ fontWeight: "600",
136
+ lineHeight: 18
137
+ },
138
+ cardMeta: {
139
+ fontSize: 11
140
+ },
141
+ useLabel: {
142
+ marginTop: 2,
143
+ fontSize: 12,
144
+ fontWeight: "600"
145
+ },
146
+ statusWrap: {
147
+ marginTop: 20,
148
+ alignItems: "center",
149
+ gap: 8,
150
+ paddingHorizontal: 16
151
+ },
152
+ statusText: {
153
+ fontSize: 13,
154
+ textAlign: "center"
155
+ }
156
+ });export{BuildTemplatesSection,BuildTemplatesSection as default};//# sourceMappingURL=BuildTemplatesSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuildTemplatesSection.js","sources":["../../../../src/screens/Home/components/BuildTemplatesSection.tsx"],"sourcesContent":["import React, { useCallback } from 'react';\nimport {\n ActivityIndicator,\n Image,\n Pressable,\n ScrollView,\n StyleSheet,\n Text,\n View,\n useWindowDimensions,\n} from 'react-native';\nimport type { BuildTemplateCard } from '../../../features/templates/buildTemplateCards';\nimport { useMarketplaceTemplateCards } from '../../../hooks/useMarketplaceTemplateCards';\n\nexport type BuildTemplatesSectionProps = {\n enabled: boolean;\n /** Selected marketplace group key (`codeAssistant`, …). */\n group: string | null;\n orgName?: string | null;\n isDark: boolean;\n primaryTextColor: string;\n secondaryTextColor: string;\n /** Armed card id — submit will send input message + this card's snapshotId. */\n selectedTemplateId?: string | null;\n onUseTemplate: (card: BuildTemplateCard) => void;\n};\n\n/**\n * Yantra template cards for Build mode (web `DefaultFormTemplatesSection` parity).\n * Tap arms the card (`snapshotId`); composer submit sends message + snapshotId.\n */\nexport function BuildTemplatesSection({\n enabled,\n group,\n orgName,\n isDark,\n primaryTextColor,\n secondaryTextColor,\n selectedTemplateId = null,\n onUseTemplate,\n}: BuildTemplatesSectionProps) {\n const { width } = useWindowDimensions();\n const selectedGroup = (group ?? '').trim();\n const { cards, loading, error } = useMarketplaceTemplateCards({\n group: selectedGroup,\n orgName,\n enabled: enabled && Boolean(selectedGroup),\n });\n\n const cardWidth = Math.min(168, Math.max(140, (width - 56) / 2));\n\n const renderCard = useCallback(\n (item: BuildTemplateCard) => {\n const cover = item.coverImageUrl?.trim();\n const selected = selectedTemplateId === item.id;\n return (\n <Pressable\n key={item.id}\n onPress={() => onUseTemplate(item)}\n style={[\n styles.card,\n {\n width: cardWidth,\n backgroundColor: isDark ? '#1e293b' : '#ffffff',\n borderColor: selected\n ? isDark\n ? '#818cf8'\n : '#4338ca'\n : isDark\n ? 'rgba(148,163,184,0.28)'\n : 'rgba(15,23,42,0.08)',\n borderWidth: selected ? 2 : 1,\n },\n ]}\n accessibilityRole=\"button\"\n accessibilityState={{ selected }}\n accessibilityLabel={`${selected ? 'Selected' : 'Select'} template ${item.title}`}\n >\n <View style={[styles.cover, { backgroundColor: isDark ? '#0f172a' : '#f1f5f9' }]}>\n {cover ? (\n <Image source={{ uri: cover }} style={styles.coverImage} resizeMode=\"cover\" />\n ) : (\n <Text style={[styles.coverFallback, { color: secondaryTextColor }]}>Yantra</Text>\n )}\n </View>\n <View style={styles.cardBody}>\n <Text style={[styles.cardTitle, { color: primaryTextColor }]} numberOfLines={2}>\n {item.title}\n </Text>\n {item.snapshotId ? (\n <Text style={[styles.cardMeta, { color: secondaryTextColor }]} numberOfLines={1}>\n Remix ready\n </Text>\n ) : null}\n <Text style={[styles.useLabel, { color: isDark ? '#a5b4fc' : '#4338ca' }]}>\n {selected ? 'Selected' : 'Select'}\n </Text>\n </View>\n </Pressable>\n );\n },\n [cardWidth, isDark, onUseTemplate, primaryTextColor, secondaryTextColor, selectedTemplateId],\n );\n\n if (!enabled || !selectedGroup) {\n return null;\n }\n\n if (loading && cards.length === 0) {\n return (\n <View style={styles.statusWrap}>\n <ActivityIndicator color={isDark ? '#a5b4fc' : '#4338ca'} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>Loading templates…</Text>\n </View>\n );\n }\n\n if (error && cards.length === 0) {\n return (\n <View style={styles.statusWrap}>\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>\n Couldn’t load templates. Try another group.\n </Text>\n </View>\n );\n }\n\n if (cards.length === 0) {\n return (\n <View style={styles.statusWrap}>\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>\n No remixable templates in this group yet.\n </Text>\n </View>\n );\n }\n\n return (\n <View style={styles.section}>\n <Text style={[styles.sectionTitle, { color: primaryTextColor }]}>Yantra templates</Text>\n <Text style={[styles.sectionHint, { color: secondaryTextColor }]}>\n Select a starter, type your prompt, then send — message + snapshot go to Web Builder.\n </Text>\n <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.listContent}>\n {cards.map(renderCard)}\n </ScrollView>\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n section: {\n width: '100%',\n marginTop: 20,\n paddingBottom: 8,\n },\n sectionTitle: {\n fontSize: 16,\n fontWeight: '700',\n marginBottom: 4,\n paddingHorizontal: 4,\n },\n sectionHint: {\n fontSize: 12,\n lineHeight: 18,\n marginBottom: 12,\n paddingHorizontal: 4,\n },\n listContent: {\n paddingHorizontal: 2,\n gap: 12,\n },\n card: {\n borderRadius: 14,\n borderWidth: 1,\n overflow: 'hidden',\n },\n cover: {\n height: 96,\n alignItems: 'center',\n justifyContent: 'center',\n },\n coverImage: {\n width: '100%',\n height: '100%',\n },\n coverFallback: {\n fontSize: 13,\n fontWeight: '600',\n },\n cardBody: {\n paddingHorizontal: 10,\n paddingVertical: 10,\n gap: 4,\n },\n cardTitle: {\n fontSize: 13,\n fontWeight: '600',\n lineHeight: 18,\n },\n cardMeta: {\n fontSize: 11,\n },\n useLabel: {\n marginTop: 2,\n fontSize: 12,\n fontWeight: '600',\n },\n statusWrap: {\n marginTop: 20,\n alignItems: 'center',\n gap: 8,\n paddingHorizontal: 16,\n },\n statusText: {\n fontSize: 13,\n textAlign: 'center',\n },\n});\n\nexport default BuildTemplatesSection;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import {jsx}from'react/jsx-runtime';import {useMemo,useState,useEffect}from'react';import {View,StyleSheet}from'react-native';import {WebView}from'react-native-webview';import {config}from'../../../config/env-config.js';import'../../../bridge/WebViewManager.js';import {WEB_BRIDGE_BOOTSTRAP}from'../../../bridge/webBridgeBootstrap.js';import'@react-native-async-storage/async-storage';import'expo-secure-store';import'@react-navigation/native';import {getPackagerHost,resolveMobileWebUrl}from'../../../bridge/resolveMobileWebUrl.js';import {appendSurfaceAuthParams,buildCdecliTokenInjection}from'../../../hooks/mintSurfaceSystemToken.js';import {useObtainSystemToken}from'../../../hooks/useObtainSystemToken.js';import {getWarmWebBuilderSession,warmWebBuilderSession,webbuilderPreloadUrl}from'../../WebBuilder/webbuilderWarmCache.js';function WebBuilderPrewarm({
2
+ enabled,
3
+ orgName,
4
+ projectId,
5
+ tagId
6
+ }) {
7
+ const {
8
+ obtainSystemToken
9
+ } = useObtainSystemToken(enabled);
10
+ const packagerHost = getPackagerHost();
11
+ const graphqlUrl = useMemo(() => resolveMobileWebUrl(config.GRAPHQL_URL, packagerHost), [packagerHost]);
12
+ const surfaceBase = useMemo(() => resolveMobileWebUrl(config.WEB_BUILDER_URL, packagerHost), [packagerHost]);
13
+ const [token, setToken] = useState(() => {
14
+ var _a, _b;
15
+ return (_b = (_a = getWarmWebBuilderSession()) == null ? void 0 : _a.token) != null ? _b : null;
16
+ });
17
+ const [backend, setBackend] = useState(() => {
18
+ var _a, _b;
19
+ return (_b = (_a = getWarmWebBuilderSession()) == null ? void 0 : _a.backend) != null ? _b : null;
20
+ });
21
+ useEffect(() => {
22
+ if (!enabled) return;
23
+ if (!orgName || !projectId) return;
24
+ let cancelled = false;
25
+ (async () => {
26
+ try {
27
+ const session = await warmWebBuilderSession({
28
+ graphqlUrl,
29
+ orgName,
30
+ projectId,
31
+ tagId,
32
+ obtainSystemToken
33
+ });
34
+ if (cancelled) return;
35
+ setToken(session.token);
36
+ setBackend(session.backend);
37
+ if (__DEV__) {
38
+ console.log("[WebBuilderPrewarm] session ready");
39
+ }
40
+ } catch (err) {
41
+ if (__DEV__) {
42
+ console.warn("[WebBuilderPrewarm] warm failed:", err);
43
+ }
44
+ }
45
+ })();
46
+ return () => {
47
+ cancelled = true;
48
+ };
49
+ }, [enabled, graphqlUrl, obtainSystemToken, orgName, projectId, tagId]);
50
+ const preloadUri = useMemo(() => {
51
+ if (!token || !backend) return null;
52
+ const base = webbuilderPreloadUrl(surfaceBase);
53
+ return appendSurfaceAuthParams(base, token, "mobile-webview-prewarm");
54
+ }, [backend, surfaceBase, token]);
55
+ const injected = useMemo(() => {
56
+ if (!token || !backend) return WEB_BRIDGE_BOOTSTRAP;
57
+ return `${buildCdecliTokenInjection(token, backend, "mobile-webview-prewarm")}
58
+ ${WEB_BRIDGE_BOOTSTRAP}`;
59
+ }, [backend, token]);
60
+ if (!enabled || !preloadUri) return null;
61
+ return /* @__PURE__ */ jsx(View, { style: styles.host, pointerEvents: "none", collapsable: false, children: /* @__PURE__ */ jsx(WebView, { source: {
62
+ uri: preloadUri
63
+ }, style: styles.webview, injectedJavaScriptBeforeContentLoaded: injected, javaScriptEnabled: true, domStorageEnabled: true, sharedCookiesEnabled: true, thirdPartyCookiesEnabled: true, originWhitelist: ["*"], onError: () => {
64
+ }, onHttpError: () => {
65
+ } }) });
66
+ }
67
+ const styles = StyleSheet.create({
68
+ host: {
69
+ position: "absolute",
70
+ width: 1,
71
+ height: 1,
72
+ opacity: 0,
73
+ overflow: "hidden",
74
+ left: 0,
75
+ top: 0,
76
+ zIndex: -1
77
+ },
78
+ webview: {
79
+ width: 1,
80
+ height: 1,
81
+ opacity: 0
82
+ }
83
+ });export{WebBuilderPrewarm};//# sourceMappingURL=WebBuilderPrewarm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebBuilderPrewarm.js","sources":["../../../../src/screens/Home/components/WebBuilderPrewarm.tsx"],"sourcesContent":["/**\n * Off-screen Web Builder warm-up while the user is in Build mode on Home.\n * Mints the system JWT and loads the surface SPA so send → navigate is instant.\n *\n * Receives org/project from Home (do NOT call usePrerequisiteIds here — a second\n * instance can steal the project bootstrap and leave Home without projectId).\n */\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { StyleSheet, View } from 'react-native';\nimport { WebView } from 'react-native-webview';\nimport { config } from '../../../config/env-config';\nimport { getPackagerHost, resolveMobileWebUrl, WEB_BRIDGE_BOOTSTRAP } from '../../../bridge';\nimport { appendSurfaceAuthParams, buildCdecliTokenInjection } from '../../../hooks/mintSurfaceSystemToken';\nimport { useObtainSystemToken } from '../../../hooks/useObtainSystemToken';\nimport {\n getWarmWebBuilderSession,\n warmWebBuilderSession,\n webbuilderPreloadUrl,\n} from '../../WebBuilder/webbuilderWarmCache';\n\ntype Props = {\n /** Only warm while Build mode is active. */\n enabled: boolean;\n orgName?: string | null;\n projectId?: string | null;\n tagId?: string | null;\n};\n\nexport function WebBuilderPrewarm({ enabled, orgName, projectId, tagId }: Props): React.ReactElement | null {\n const { obtainSystemToken } = useObtainSystemToken(enabled);\n const packagerHost = getPackagerHost();\n const graphqlUrl = useMemo(() => resolveMobileWebUrl(config.GRAPHQL_URL, packagerHost), [packagerHost]);\n const surfaceBase = useMemo(() => resolveMobileWebUrl(config.WEB_BUILDER_URL, packagerHost), [packagerHost]);\n\n const [token, setToken] = useState<string | null>(() => getWarmWebBuilderSession()?.token ?? null);\n const [backend, setBackend] = useState<string | null>(() => getWarmWebBuilderSession()?.backend ?? null);\n\n useEffect(() => {\n if (!enabled) return;\n if (!orgName || !projectId) return;\n\n let cancelled = false;\n (async () => {\n try {\n const session = await warmWebBuilderSession({\n graphqlUrl,\n orgName,\n projectId,\n tagId,\n obtainSystemToken,\n });\n if (cancelled) return;\n setToken(session.token);\n setBackend(session.backend);\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.log('[WebBuilderPrewarm] session ready');\n }\n } catch (err) {\n if (__DEV__) {\n // eslint-disable-next-line no-console\n console.warn('[WebBuilderPrewarm] warm failed:', err);\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [enabled, graphqlUrl, obtainSystemToken, orgName, projectId, tagId]);\n\n const preloadUri = useMemo(() => {\n if (!token || !backend) return null;\n const base = webbuilderPreloadUrl(surfaceBase);\n return appendSurfaceAuthParams(base, token, 'mobile-webview-prewarm');\n }, [backend, surfaceBase, token]);\n\n const injected = useMemo(() => {\n if (!token || !backend) return WEB_BRIDGE_BOOTSTRAP;\n return `${buildCdecliTokenInjection(token, backend, 'mobile-webview-prewarm')}\\n${WEB_BRIDGE_BOOTSTRAP}`;\n }, [backend, token]);\n\n if (!enabled || !preloadUri) return null;\n\n return (\n <View style={styles.host} pointerEvents=\"none\" collapsable={false}>\n <WebView\n source={{ uri: preloadUri }}\n style={styles.webview}\n injectedJavaScriptBeforeContentLoaded={injected}\n javaScriptEnabled\n domStorageEnabled\n sharedCookiesEnabled\n thirdPartyCookiesEnabled\n originWhitelist={['*']}\n onError={() => {\n /* prewarm is best-effort */\n }}\n onHttpError={() => {\n /* prewarm is best-effort */\n }}\n />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n host: {\n position: 'absolute',\n width: 1,\n height: 1,\n opacity: 0,\n overflow: 'hidden',\n left: 0,\n top: 0,\n zIndex: -1,\n },\n webview: {\n width: 1,\n height: 1,\n opacity: 0,\n },\n});\n"],"names":[],"mappings":"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"}
@@ -1,13 +1,9 @@
1
- import React from'react';import {BackHandler}from'react-native';import {useFocusEffect}from'@react-navigation/native';function WebViewWithNavigation({
2
- webViewRef,
3
- canGoBack,
1
+ import React from'react';import {BackHandler}from'react-native';import {useFocusEffect}from'@react-navigation/native';import {tryWebBuilderBack}from'./webbuilderBackHandler.js';function WebViewWithNavigation({
4
2
  onGoBack
5
3
  }) {
6
4
  useFocusEffect(React.useCallback(() => {
7
5
  const onBackPress = () => {
8
- var _a;
9
- if (canGoBack) {
10
- (_a = webViewRef.current) == null ? void 0 : _a.goBack();
6
+ if (tryWebBuilderBack()) {
11
7
  return true;
12
8
  }
13
9
  onGoBack();
@@ -15,6 +11,6 @@ import React from'react';import {BackHandler}from'react-native';import {useFocus
15
11
  };
16
12
  const subscription = BackHandler.addEventListener("hardwareBackPress", onBackPress);
17
13
  return () => subscription.remove();
18
- }, [canGoBack, onGoBack, webViewRef]));
14
+ }, [onGoBack]));
19
15
  return null;
20
16
  }export{WebViewWithNavigation};//# sourceMappingURL=WebViewWithNavigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebViewWithNavigation.js","sources":["../../../src/screens/WebBuilder/WebViewWithNavigation.tsx"],"sourcesContent":["import React from 'react';\nimport { BackHandler } from 'react-native';\nimport { useFocusEffect } from '@react-navigation/native';\nimport type { WebView } from 'react-native-webview';\n\n/**\n * Hardware back: WebView history first, then native navigation.\n */\nexport function WebViewWithNavigation({\n webViewRef,\n canGoBack,\n onGoBack,\n}: {\n webViewRef: React.RefObject<WebView | null>;\n canGoBack: boolean;\n onGoBack: () => void;\n}): null {\n useFocusEffect(\n React.useCallback(() => {\n const onBackPress = () => {\n if (canGoBack) {\n webViewRef.current?.goBack();\n return true;\n }\n onGoBack();\n return true;\n };\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);\n return () => subscription.remove();\n }, [canGoBack, onGoBack, webViewRef]),\n );\n\n return null;\n}\n"],"names":[],"mappings":"sHAQO,SAAS,qBAAsB,CAAA;AAAA,EACpC,UAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAIS,EAAA;AACP,EAAe,cAAA,CAAA,KAAA,CAAM,YAAY,MAAM;AACrC,IAAA,MAAM,cAAc,MAAM;AAlB9B,MAAA,IAAA,EAAA;AAmBM,MAAA,IAAI,SAAW,EAAA;AACb,QAAA,CAAA,EAAA,GAAA,UAAA,CAAW,YAAX,IAAoB,GAAA,MAAA,GAAA,EAAA,CAAA,MAAA,EAAA;AACpB,QAAO,OAAA,IAAA;AAAA;AAET,MAAS,QAAA,EAAA;AACT,MAAO,OAAA,IAAA;AAAA,KACT;AACA,IAAA,MAAM,YAAe,GAAA,WAAA,CAAY,gBAAiB,CAAA,mBAAA,EAAqB,WAAW,CAAA;AAClF,IAAO,OAAA,MAAM,aAAa,MAAO,EAAA;AAAA,KAChC,CAAC,SAAA,EAAW,QAAU,EAAA,UAAU,CAAC,CAAC,CAAA;AACrC,EAAO,OAAA,IAAA;AACT"}
1
+ {"version":3,"file":"WebViewWithNavigation.js","sources":["../../../src/screens/WebBuilder/WebViewWithNavigation.tsx"],"sourcesContent":["import React from 'react';\nimport { BackHandler } from 'react-native';\nimport { useFocusEffect } from '@react-navigation/native';\nimport { tryWebBuilderBack } from './webbuilderBackHandler';\n\n/**\n * Hardware back: dismiss in-app preview if open, otherwise leave WebBuilder.\n */\nexport function WebViewWithNavigation({\n onGoBack,\n}: {\n /** Kept for call-site compatibility; SPA history is no longer used. */\n webViewRef?: React.RefObject<unknown>;\n canGoBack?: boolean;\n onGoBack: () => void;\n}): null {\n useFocusEffect(\n React.useCallback(() => {\n const onBackPress = () => {\n // Preview dismiss only (via setWebBuilderBackHandler). SPA history\n // must not trap Android back on this screen.\n if (tryWebBuilderBack()) {\n return true;\n }\n onGoBack();\n return true;\n };\n\n const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);\n return () => subscription.remove();\n }, [onGoBack]),\n );\n\n return null;\n}\n"],"names":[],"mappings":"iLAQO,SAAS,qBAAsB,CAAA;AAAA,EACpC;AACF,CAKS,EAAA;AACP,EAAe,cAAA,CAAA,KAAA,CAAM,YAAY,MAAM;AACrC,IAAA,MAAM,cAAc,MAAM;AAGxB,MAAA,IAAI,mBAAqB,EAAA;AACvB,QAAO,OAAA,IAAA;AAAA;AAET,MAAS,QAAA,EAAA;AACT,MAAO,OAAA,IAAA;AAAA,KACT;AACA,IAAA,MAAM,YAAe,GAAA,WAAA,CAAY,gBAAiB,CAAA,mBAAA,EAAqB,WAAW,CAAA;AAClF,IAAO,OAAA,MAAM,aAAa,MAAO,EAAA;AAAA,GAChC,EAAA,CAAC,QAAQ,CAAC,CAAC,CAAA;AACd,EAAO,OAAA,IAAA;AACT"}
@@ -1,4 +1,4 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import {useRef,useState,useMemo,useEffect,useCallback}from'react';import {useColorScheme,AppState,StyleSheet,View,ActivityIndicator,Text,Pressable,Platform}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {WebView}from'react-native-webview';import {useNavigation,useRoute}from'@react-navigation/native';import {config}from'../../config/env-config.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {WebViewManager}from'../../bridge/WebViewManager.js';import {NativeWebViewBridge}from'../../bridge/NativeWebViewBridge.js';import {WEB_BRIDGE_BOOTSTRAP}from'../../bridge/webBridgeBootstrap.js';import {AuthBridgeHandler}from'../../bridge/handlers/AuthBridgeHandler.js';import {NavigationBridgeHandler}from'../../bridge/handlers/NavigationBridgeHandler.js';import {AnalyticsBridgeHandler}from'../../bridge/handlers/AnalyticsBridgeHandler.js';import {getPackagerHost,resolveMobileWebUrl}from'../../bridge/resolveMobileWebUrl.js';import {appendSurfaceAuthParams,buildCdecliTokenInjection,buildSurfaceGateRecoveryScript}from'../../hooks/mintSurfaceSystemToken.js';import {useObtainSystemToken}from'../../hooks/useObtainSystemToken.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {WebViewWithNavigation}from'./WebViewWithNavigation.js';var __defProp = Object.defineProperty;
1
+ import {jsx,jsxs}from'react/jsx-runtime';import {useRef,useState,useMemo,useEffect,useCallback}from'react';import {useColorScheme,AppState,StyleSheet,View,ActivityIndicator,Text,Pressable,Platform}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {WebView}from'react-native-webview';import {useNavigation,useRoute}from'@react-navigation/native';import {config}from'../../config/env-config.js';import {mobileTokens}from'../../theme/mobileTokens.js';import {WebViewManager}from'../../bridge/WebViewManager.js';import {NativeWebViewBridge}from'../../bridge/NativeWebViewBridge.js';import {WEB_BRIDGE_BOOTSTRAP}from'../../bridge/webBridgeBootstrap.js';import {AuthBridgeHandler}from'../../bridge/handlers/AuthBridgeHandler.js';import {NavigationBridgeHandler}from'../../bridge/handlers/NavigationBridgeHandler.js';import {AnalyticsBridgeHandler}from'../../bridge/handlers/AnalyticsBridgeHandler.js';import {getPackagerHost,resolveMobileWebUrl}from'../../bridge/resolveMobileWebUrl.js';import {appendSurfaceAuthParams,buildCdecliTokenInjection,buildSurfaceGateRecoveryScript}from'../../hooks/mintSurfaceSystemToken.js';import {useObtainSystemToken}from'../../hooks/useObtainSystemToken.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {WebViewWithNavigation}from'./WebViewWithNavigation.js';import {setWebBuilderBackHandler}from'./webbuilderBackHandler.js';import {getWarmWebBuilderSession,warmWebBuilderSession,setWarmWebBuilderSession,clearWarmWebBuilderSession}from'./webbuilderWarmCache.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -21,7 +21,7 @@ function makeHandoffState() {
21
21
  return `mobile-webview-${Date.now().toString(36)}`;
22
22
  }
23
23
  function WebBuilderScreen() {
24
- var _a;
24
+ var _a, _b, _c;
25
25
  const navigation = useNavigation();
26
26
  const route = useRoute();
27
27
  const colorScheme = useColorScheme();
@@ -32,11 +32,19 @@ function WebBuilderScreen() {
32
32
  const [hasError, setHasError] = useState(false);
33
33
  const [errorDetail, setErrorDetail] = useState(null);
34
34
  const [canGoBack, setCanGoBack] = useState(false);
35
+ const previewOpenRef = useRef(false);
35
36
  const [reloadKey, setReloadKey] = useState(0);
36
- const [authToken, setAuthToken] = useState(null);
37
- const [authBackend, setAuthBackend] = useState(null);
37
+ const warm = getWarmWebBuilderSession();
38
+ const [authToken, setAuthToken] = useState(() => {
39
+ var _a2;
40
+ return (_a2 = warm == null ? void 0 : warm.token) != null ? _a2 : null;
41
+ });
42
+ const [authBackend, setAuthBackend] = useState(() => {
43
+ var _a2;
44
+ return (_a2 = warm == null ? void 0 : warm.backend) != null ? _a2 : null;
45
+ });
38
46
  const [authState, setAuthState] = useState(() => makeHandoffState());
39
- const [authReady, setAuthReady] = useState(false);
47
+ const [authReady, setAuthReady] = useState(() => Boolean(warm == null ? void 0 : warm.token));
40
48
  const [authError, setAuthError] = useState(null);
41
49
  const [mintGeneration, setMintGeneration] = useState(0);
42
50
  const {
@@ -45,73 +53,135 @@ function WebBuilderScreen() {
45
53
  tagId
46
54
  } = usePrerequisiteIds();
47
55
  const {
48
- obtainSystemToken,
49
- loading: systemTokenQueryLoading
56
+ obtainSystemToken
50
57
  } = useObtainSystemToken(true);
51
58
  const packagerHost = getPackagerHost();
52
59
  const handoffParams = useMemo(() => {
53
60
  const params = route == null ? void 0 : route.params;
54
- const channelId = typeof (params == null ? void 0 : params.channelId) === "string" ? params.channelId.trim() : "";
55
- const projectIdParam = typeof (params == null ? void 0 : params.projectId) === "string" ? params.projectId.trim() : "";
56
- const message = typeof (params == null ? void 0 : params.message) === "string" ? params.message.trim() : "";
61
+ const read = (key) => {
62
+ const value = params == null ? void 0 : params[key];
63
+ return typeof value === "string" ? value.trim() : "";
64
+ };
65
+ const channelId = read("channelId");
66
+ const projectIdParam = read("projectId");
67
+ const message = read("message");
68
+ const snapshotId = read("snapshotId");
69
+ const templateId = read("templateId");
70
+ const templateTitle = read("templateTitle");
71
+ const seedTemplate = read("seedTemplate");
72
+ const deployUrl = read("deployUrl");
73
+ const previewUrl = read("previewUrl");
57
74
  return {
58
75
  channelId: channelId || null,
59
76
  projectId: projectIdParam || null,
60
- message: message || null
77
+ message: message || null,
78
+ snapshotId: snapshotId || null,
79
+ templateId: templateId || null,
80
+ templateTitle: templateTitle || null,
81
+ seedTemplate: seedTemplate || null,
82
+ deployUrl: deployUrl || null,
83
+ previewUrl: previewUrl || null
61
84
  };
62
85
  }, [route == null ? void 0 : route.params]);
86
+ const routeOrgName = useMemo(() => {
87
+ var _a2;
88
+ const raw = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.orgName;
89
+ return typeof raw === "string" && raw.trim() ? raw.trim() : null;
90
+ }, [route == null ? void 0 : route.params]);
91
+ const effectiveOrgName = orgName || routeOrgName;
92
+ const effectiveProjectId = projectId || handoffParams.projectId;
63
93
  const baseUrl = useMemo(() => {
64
94
  var _a2;
65
95
  const fromParams = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.url;
66
96
  const raw = typeof fromParams === "string" && fromParams.trim() ? fromParams.trim() : config.WEB_BUILDER_URL;
67
97
  const resolved = resolveMobileWebUrl(raw, packagerHost);
68
- if (!handoffParams.channelId && !handoffParams.message) return resolved;
98
+ const stamp = (url) => {
99
+ url.searchParams.set("embed", "mobile");
100
+ const isRemix = Boolean(handoffParams.snapshotId);
101
+ if (!isRemix && handoffParams.channelId) url.searchParams.set("channelId", handoffParams.channelId);
102
+ if (!isRemix && handoffParams.projectId) url.searchParams.set("projectId", handoffParams.projectId);
103
+ if (handoffParams.message) url.searchParams.set("message", handoffParams.message);
104
+ if (handoffParams.snapshotId) url.searchParams.set("snapshotId", handoffParams.snapshotId);
105
+ if (handoffParams.templateId) url.searchParams.set("templateId", handoffParams.templateId);
106
+ if (handoffParams.templateTitle) url.searchParams.set("templateTitle", handoffParams.templateTitle);
107
+ if (handoffParams.seedTemplate) url.searchParams.set("seedTemplate", handoffParams.seedTemplate);
108
+ };
69
109
  try {
70
110
  const url = new URL(resolved);
71
- if (handoffParams.channelId) url.searchParams.set("channelId", handoffParams.channelId);
72
- if (handoffParams.projectId) url.searchParams.set("projectId", handoffParams.projectId);
73
- if (handoffParams.message) url.searchParams.set("message", handoffParams.message);
111
+ stamp(url);
74
112
  return url.toString();
75
113
  } catch (e) {
76
114
  const sep = resolved.includes("?") ? "&" : "?";
77
- const parts = [];
78
- if (handoffParams.channelId) parts.push(`channelId=${encodeURIComponent(handoffParams.channelId)}`);
79
- if (handoffParams.projectId) parts.push(`projectId=${encodeURIComponent(handoffParams.projectId)}`);
115
+ const parts = ["embed=mobile"];
116
+ const isRemix = Boolean(handoffParams.snapshotId);
117
+ if (!isRemix && handoffParams.channelId) {
118
+ parts.push(`channelId=${encodeURIComponent(handoffParams.channelId)}`);
119
+ }
120
+ if (!isRemix && handoffParams.projectId) {
121
+ parts.push(`projectId=${encodeURIComponent(handoffParams.projectId)}`);
122
+ }
80
123
  if (handoffParams.message) parts.push(`message=${encodeURIComponent(handoffParams.message)}`);
81
- return parts.length ? `${resolved}${sep}${parts.join("&")}` : resolved;
124
+ if (handoffParams.snapshotId) parts.push(`snapshotId=${encodeURIComponent(handoffParams.snapshotId)}`);
125
+ if (handoffParams.templateId) parts.push(`templateId=${encodeURIComponent(handoffParams.templateId)}`);
126
+ if (handoffParams.templateTitle) {
127
+ parts.push(`templateTitle=${encodeURIComponent(handoffParams.templateTitle)}`);
128
+ }
129
+ if (handoffParams.seedTemplate) {
130
+ parts.push(`seedTemplate=${encodeURIComponent(handoffParams.seedTemplate)}`);
131
+ }
132
+ return `${resolved}${sep}${parts.join("&")}`;
82
133
  }
83
134
  }, [route == null ? void 0 : route.params, packagerHost, handoffParams]);
84
135
  const graphqlUrl = useMemo(() => resolveMobileWebUrl(config.GRAPHQL_URL, packagerHost), [packagerHost]);
85
136
  useEffect(() => {
86
137
  let cancelled = false;
87
- setAuthReady(false);
88
- setAuthError(null);
89
138
  const handoffState = makeHandoffState();
90
139
  setAuthState(handoffState);
140
+ setAuthError(null);
91
141
  if (__DEV__) {
92
142
  console.log("[WebBuilder] surface=", baseUrl, "graphql=", graphqlUrl);
93
143
  }
94
- if (systemTokenQueryLoading) {
144
+ const cached = getWarmWebBuilderSession();
145
+ if (cached == null ? void 0 : cached.token) {
146
+ setAuthToken(cached.token);
147
+ setAuthBackend(cached.backend || graphqlUrl);
148
+ setAuthReady(true);
95
149
  return () => {
96
150
  cancelled = true;
97
151
  };
98
152
  }
99
153
  (async () => {
100
154
  try {
101
- const token = await obtainSystemToken();
155
+ const session = await warmWebBuilderSession({
156
+ graphqlUrl,
157
+ orgName: effectiveOrgName,
158
+ projectId: effectiveProjectId,
159
+ tagId,
160
+ obtainSystemToken
161
+ });
102
162
  if (cancelled) return;
103
- if (!(token == null ? void 0 : token.trim())) {
104
- throw new Error("Could not obtain system token via Apollo. Ensure org/project are set (same as chat).");
105
- }
163
+ setAuthToken(session.token);
164
+ setAuthBackend(session.backend);
165
+ setWarmWebBuilderSession(session);
166
+ setAuthReady(true);
106
167
  if (__DEV__) {
107
- console.log("[WebBuilder] Apollo system token length=", token.length);
168
+ console.log("[WebBuilder] session ready length=", session.token.length);
108
169
  }
109
- setAuthToken(token.trim());
110
- setAuthBackend(graphqlUrl);
111
- setAuthReady(true);
112
170
  } catch (err) {
113
171
  if (cancelled) return;
172
+ if (!effectiveOrgName || !effectiveProjectId) {
173
+ if (__DEV__) {
174
+ console.log("[WebBuilder] waiting for org/project\u2026");
175
+ }
176
+ return;
177
+ }
114
178
  const message = err instanceof Error ? err.message : "Token mint failed";
179
+ if (/Waiting for org\/project/i.test(message)) {
180
+ if (__DEV__) {
181
+ console.log("[WebBuilder] waiting for org/project\u2026");
182
+ }
183
+ return;
184
+ }
115
185
  console.warn("[WebBuilder] surface token mint failed:", message);
116
186
  setAuthError(message);
117
187
  setAuthToken(null);
@@ -119,10 +189,19 @@ function WebBuilderScreen() {
119
189
  setAuthReady(true);
120
190
  }
121
191
  })();
192
+ const failsafe = setTimeout(() => {
193
+ if (cancelled) return;
194
+ setAuthReady((ready) => {
195
+ if (ready) return ready;
196
+ setAuthError("Timed out preparing Web Builder. Ensure you are signed in with an org, then retry.");
197
+ return true;
198
+ });
199
+ }, 2e4);
122
200
  return () => {
123
201
  cancelled = true;
202
+ clearTimeout(failsafe);
124
203
  };
125
- }, [baseUrl, graphqlUrl, obtainSystemToken, systemTokenQueryLoading, orgName, projectId, tagId, mintGeneration]);
204
+ }, [baseUrl, graphqlUrl, obtainSystemToken, effectiveOrgName, effectiveProjectId, tagId, mintGeneration]);
126
205
  const mfeUrl = useMemo(() => {
127
206
  if (!authToken) return baseUrl;
128
207
  return appendSurfaceAuthParams(baseUrl, authToken, authState);
@@ -167,9 +246,9 @@ function WebBuilderScreen() {
167
246
  }, [authToken, mfeConfig.url, webViewManager]);
168
247
  useEffect(() => {
169
248
  const handleAppStateChange = (nextAppState) => {
170
- var _a2, _b;
249
+ var _a2, _b2;
171
250
  if (nextAppState === "background") {
172
- (_b = (_a2 = webViewRef.current) == null ? void 0 : _a2.clearCache) == null ? void 0 : _b.call(_a2, true);
251
+ (_b2 = (_a2 = webViewRef.current) == null ? void 0 : _a2.clearCache) == null ? void 0 : _b2.call(_a2, true);
173
252
  }
174
253
  };
175
254
  const subscription = AppState.addEventListener("change", handleAppStateChange);
@@ -228,18 +307,30 @@ function WebBuilderScreen() {
228
307
  setIsLoading(false);
229
308
  }, [mfeConfig.url]);
230
309
  const handleMessage = useCallback((event) => {
231
- var _a2;
232
- (_a2 = bridgeRef.current) == null ? void 0 : _a2.handleMessage(event);
310
+ var _a2, _b2;
311
+ try {
312
+ const raw = (_a2 = event == null ? void 0 : event.nativeEvent) == null ? void 0 : _a2.data;
313
+ if (typeof raw === "string" && raw.includes("wb-preview")) {
314
+ const parsed = JSON.parse(raw);
315
+ if ((parsed == null ? void 0 : parsed.type) === "wb-preview") {
316
+ previewOpenRef.current = Boolean(parsed.open);
317
+ }
318
+ }
319
+ } catch (e) {
320
+ }
321
+ (_b2 = bridgeRef.current) == null ? void 0 : _b2.handleMessage(event);
233
322
  }, []);
234
323
  const handleNavigationStateChange = useCallback((navState) => {
235
324
  setCanGoBack(Boolean(navState.canGoBack));
236
325
  }, []);
237
326
  const handleRetry = useCallback(() => {
327
+ clearWarmWebBuilderSession();
238
328
  setHasError(false);
239
329
  setErrorDetail(null);
240
330
  setAuthError(null);
241
331
  setAuthToken(null);
242
332
  setAuthBackend(null);
333
+ setAuthReady(false);
243
334
  setIsLoading(true);
244
335
  setMintGeneration((g) => g + 1);
245
336
  setReloadKey((k) => k + 1);
@@ -247,8 +338,27 @@ function WebBuilderScreen() {
247
338
  const handleNativeGoBack = useCallback(() => {
248
339
  if (navigation.canGoBack()) {
249
340
  navigation.goBack();
341
+ return;
250
342
  }
343
+ navigation.navigate("MainStack.Layout.Home");
251
344
  }, [navigation]);
345
+ useEffect(() => {
346
+ setWebBuilderBackHandler(() => {
347
+ var _a2;
348
+ if (previewOpenRef.current) {
349
+ (_a2 = webViewRef.current) == null ? void 0 : _a2.injectJavaScript(`
350
+ (function () {
351
+ try { window.__yantraWbNativeBack && window.__yantraWbNativeBack(); } catch (e) {}
352
+ })();
353
+ true;
354
+ `);
355
+ previewOpenRef.current = false;
356
+ return true;
357
+ }
358
+ return false;
359
+ });
360
+ return () => setWebBuilderBackHandler(null);
361
+ }, []);
252
362
  const cacheMode = mfeConfig.cachePolicy === "cache-else-load" ? "LOAD_CACHE_ELSE_NETWORK" : "LOAD_DEFAULT";
253
363
  const showAuthSpinner = !authReady;
254
364
  const showAuthFailure = authReady && !authToken;
@@ -292,7 +402,7 @@ function WebBuilderScreen() {
292
402
  uri: mfeConfig.url
293
403
  }, style: styles.webview, onLoadStart: handleLoadStart, onLoadEnd: handleLoadEnd, onError: handleError, onHttpError: handleHttpError, onMessage: handleMessage, onNavigationStateChange: handleNavigationStateChange, injectedJavaScriptBeforeContentLoaded: injectedBeforeContent, injectedJavaScript: reinjectAfterLoad, cacheEnabled: mfeConfig.cachePolicy !== "reload", cacheMode, javaScriptEnabled: true, domStorageEnabled: true, sharedCookiesEnabled: true, thirdPartyCookiesEnabled: true, startInLoadingState: true, scalesPageToFit: true, originWhitelist: ["*"], mixedContentMode: "always", allowsInlineMediaPlayback: false, mediaPlaybackRequiresUserAction: true, setSupportMultipleWindows: false, allowsBackForwardNavigationGestures: true }, Platform.OS === "android" ? {
294
404
  overScrollMode: "never"
295
- } : null), `${reloadKey}-${(_a = authToken == null ? void 0 : authToken.slice(-8)) != null ? _a : "none"}`)
405
+ } : null), `${reloadKey}-${(_a = handoffParams.channelId) != null ? _a : "none"}-${(_b = handoffParams.snapshotId) != null ? _b : "nosnap"}-${(_c = authToken == null ? void 0 : authToken.slice(-8)) != null ? _c : "none"}`)
296
406
  ] });
297
407
  }
298
408
  const styles = StyleSheet.create({