@adminide-stack/yantra-mobile 12.0.38 → 12.0.39-alpha.2

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 +1 -1
  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 +1 -1
  16. package/lib/hooks/useObtainSystemToken.js.map +1 -1
  17. package/lib/hooks/usePrerequisiteIds.js +29 -2
  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 +4 -1
  26. package/lib/screens/WebBuilder/WebViewWithNavigation.js.map +1 -1
  27. package/lib/screens/WebBuilder/index.js +142 -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 +84 -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,4 +1,4 @@
1
- import React from'react';import {BackHandler}from'react-native';import {useFocusEffect}from'@react-navigation/native';function WebViewWithNavigation({
1
+ import React from'react';import {BackHandler}from'react-native';import {useFocusEffect}from'@react-navigation/native';import {tryWebBuilderBack}from'./webbuilderBackHandler.js';function WebViewWithNavigation({
2
2
  webViewRef,
3
3
  canGoBack,
4
4
  onGoBack
@@ -6,6 +6,9 @@ import React from'react';import {BackHandler}from'react-native';import {useFocus
6
6
  useFocusEffect(React.useCallback(() => {
7
7
  const onBackPress = () => {
8
8
  var _a;
9
+ if (tryWebBuilderBack()) {
10
+ return true;
11
+ }
9
12
  if (canGoBack) {
10
13
  (_a = webViewRef.current) == null ? void 0 : _a.goBack();
11
14
  return true;
@@ -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 type { WebView } from 'react-native-webview';\nimport { tryWebBuilderBack } from './webbuilderBackHandler';\n\n/**\n * Hardware back: WebView history / in-app preview 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 (tryWebBuilderBack()) {\n return true;\n }\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":"iLASO,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;AAnB9B,MAAA,IAAA,EAAA;AAoBM,MAAA,IAAI,mBAAqB,EAAA;AACvB,QAAO,OAAA,IAAA;AAAA;AAET,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,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,72 +53,128 @@ 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";
115
179
  console.warn("[WebBuilder] surface token mint failed:", message);
116
180
  setAuthError(message);
@@ -119,10 +183,19 @@ function WebBuilderScreen() {
119
183
  setAuthReady(true);
120
184
  }
121
185
  })();
186
+ const failsafe = setTimeout(() => {
187
+ if (cancelled) return;
188
+ setAuthReady((ready) => {
189
+ if (ready) return ready;
190
+ setAuthError("Timed out preparing Web Builder. Ensure you are signed in with an org, then retry.");
191
+ return true;
192
+ });
193
+ }, 2e4);
122
194
  return () => {
123
195
  cancelled = true;
196
+ clearTimeout(failsafe);
124
197
  };
125
- }, [baseUrl, graphqlUrl, obtainSystemToken, systemTokenQueryLoading, orgName, projectId, tagId, mintGeneration]);
198
+ }, [baseUrl, graphqlUrl, obtainSystemToken, effectiveOrgName, effectiveProjectId, tagId, mintGeneration]);
126
199
  const mfeUrl = useMemo(() => {
127
200
  if (!authToken) return baseUrl;
128
201
  return appendSurfaceAuthParams(baseUrl, authToken, authState);
@@ -167,9 +240,9 @@ function WebBuilderScreen() {
167
240
  }, [authToken, mfeConfig.url, webViewManager]);
168
241
  useEffect(() => {
169
242
  const handleAppStateChange = (nextAppState) => {
170
- var _a2, _b;
243
+ var _a2, _b2;
171
244
  if (nextAppState === "background") {
172
- (_b = (_a2 = webViewRef.current) == null ? void 0 : _a2.clearCache) == null ? void 0 : _b.call(_a2, true);
245
+ (_b2 = (_a2 = webViewRef.current) == null ? void 0 : _a2.clearCache) == null ? void 0 : _b2.call(_a2, true);
173
246
  }
174
247
  };
175
248
  const subscription = AppState.addEventListener("change", handleAppStateChange);
@@ -228,18 +301,30 @@ function WebBuilderScreen() {
228
301
  setIsLoading(false);
229
302
  }, [mfeConfig.url]);
230
303
  const handleMessage = useCallback((event) => {
231
- var _a2;
232
- (_a2 = bridgeRef.current) == null ? void 0 : _a2.handleMessage(event);
304
+ var _a2, _b2;
305
+ try {
306
+ const raw = (_a2 = event == null ? void 0 : event.nativeEvent) == null ? void 0 : _a2.data;
307
+ if (typeof raw === "string" && raw.includes("wb-preview")) {
308
+ const parsed = JSON.parse(raw);
309
+ if ((parsed == null ? void 0 : parsed.type) === "wb-preview") {
310
+ previewOpenRef.current = Boolean(parsed.open);
311
+ }
312
+ }
313
+ } catch (e) {
314
+ }
315
+ (_b2 = bridgeRef.current) == null ? void 0 : _b2.handleMessage(event);
233
316
  }, []);
234
317
  const handleNavigationStateChange = useCallback((navState) => {
235
318
  setCanGoBack(Boolean(navState.canGoBack));
236
319
  }, []);
237
320
  const handleRetry = useCallback(() => {
321
+ clearWarmWebBuilderSession();
238
322
  setHasError(false);
239
323
  setErrorDetail(null);
240
324
  setAuthError(null);
241
325
  setAuthToken(null);
242
326
  setAuthBackend(null);
327
+ setAuthReady(false);
243
328
  setIsLoading(true);
244
329
  setMintGeneration((g) => g + 1);
245
330
  setReloadKey((k) => k + 1);
@@ -249,6 +334,27 @@ function WebBuilderScreen() {
249
334
  navigation.goBack();
250
335
  }
251
336
  }, [navigation]);
337
+ useEffect(() => {
338
+ setWebBuilderBackHandler(() => {
339
+ var _a2, _b2;
340
+ if (canGoBack) {
341
+ (_a2 = webViewRef.current) == null ? void 0 : _a2.goBack();
342
+ return true;
343
+ }
344
+ if (previewOpenRef.current) {
345
+ (_b2 = webViewRef.current) == null ? void 0 : _b2.injectJavaScript(`
346
+ (function () {
347
+ try { window.__yantraWbNativeBack && window.__yantraWbNativeBack(); } catch (e) {}
348
+ })();
349
+ true;
350
+ `);
351
+ previewOpenRef.current = false;
352
+ return true;
353
+ }
354
+ return false;
355
+ });
356
+ return () => setWebBuilderBackHandler(null);
357
+ }, [canGoBack]);
252
358
  const cacheMode = mfeConfig.cachePolicy === "cache-else-load" ? "LOAD_CACHE_ELSE_NETWORK" : "LOAD_DEFAULT";
253
359
  const showAuthSpinner = !authReady;
254
360
  const showAuthFailure = authReady && !authToken;
@@ -292,7 +398,7 @@ function WebBuilderScreen() {
292
398
  uri: mfeConfig.url
293
399
  }, 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
400
  overScrollMode: "never"
295
- } : null), `${reloadKey}-${(_a = authToken == null ? void 0 : authToken.slice(-8)) != null ? _a : "none"}`)
401
+ } : 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
402
  ] });
297
403
  }
298
404
  const styles = StyleSheet.create({