@adminide-stack/yantra-mobile 12.0.131 → 12.0.132
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/lib/components/CustomDrawer.js +2 -2
- package/lib/components/CustomDrawer.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +7 -1
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/nativeSurfaceTwin.js +35 -0
- package/lib/features/apps/nativeSurfaceTwin.js.map +1 -0
- package/lib/features/canvas/CanvasBoardsGrid.js +49 -49
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +69 -28
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/audioEditor/AudioWaveform.js +1 -1
- package/lib/features/canvas/designCatalog.js +63 -39
- package/lib/features/canvas/designCatalog.js.map +1 -1
- package/lib/features/canvas/designCategories.js +56 -0
- package/lib/features/canvas/designCategories.js.map +1 -1
- package/lib/features/canvas/generator/DirectorSheet.js +3 -2
- package/lib/features/canvas/generator/DirectorSheet.js.map +1 -1
- package/lib/features/canvas/home/HeroComposer.js +165 -76
- package/lib/features/canvas/home/HeroComposer.js.map +1 -1
- package/lib/features/canvas/home/HeroMonitor.js +75 -46
- package/lib/features/canvas/home/HeroMonitor.js.map +1 -1
- package/lib/features/canvas/home/TemplatesGallery.js +273 -138
- package/lib/features/canvas/home/TemplatesGallery.js.map +1 -1
- package/lib/features/canvas/home/templatesGallerySources.js +221 -0
- package/lib/features/canvas/home/templatesGallerySources.js.map +1 -0
- package/lib/features/canvas/homeWork.js +12 -11
- package/lib/features/canvas/homeWork.js.map +1 -1
- package/lib/features/canvas/lazyEditors.js +51 -0
- package/lib/features/canvas/lazyEditors.js.map +1 -0
- package/lib/features/canvas/rankedCatalogSearch.js +33 -23
- package/lib/features/canvas/rankedCatalogSearch.js.map +1 -1
- package/lib/features/canvas/set/SetViewportWebView.js +1 -1
- package/lib/features/canvas/set/agent/tools.js +1 -1
- package/lib/features/canvas/studioCatalog.js +2 -2
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/templateSearch.js +8 -1
- package/lib/features/canvas/templateSearch.js.map +1 -1
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +1 -1
- package/lib/features/design/DesignEditorExperience.js +103 -29
- package/lib/features/design/DesignEditorExperience.js.map +1 -1
- package/lib/features/design/DesignExperience.js +4 -3
- package/lib/features/design/DesignExperience.js.map +1 -1
- package/lib/features/design/doc/aiDesign.js +1 -1
- package/lib/features/design/doc/aiDesign.js.map +1 -1
- package/lib/features/design/doc/artifacts.js +40 -13
- package/lib/features/design/doc/artifacts.js.map +1 -1
- package/lib/features/design/doc/chart.js +387 -13
- package/lib/features/design/doc/chart.js.map +1 -1
- package/lib/features/design/doc/copyStyle.js +47 -0
- package/lib/features/design/doc/copyStyle.js.map +1 -0
- package/lib/features/design/doc/docOps.js +22 -4
- package/lib/features/design/doc/docOps.js.map +1 -1
- package/lib/features/design/doc/geometry.js +32 -18
- package/lib/features/design/doc/geometry.js.map +1 -1
- package/lib/features/design/doc/newDoc.js +5 -1
- package/lib/features/design/doc/newDoc.js.map +1 -1
- package/lib/features/design/doc/resize.js +101 -0
- package/lib/features/design/doc/resize.js.map +1 -0
- package/lib/features/design/doc/sizes.js +15 -2
- package/lib/features/design/doc/sizes.js.map +1 -1
- package/lib/features/design/editor/ChartDataPanel.js +49 -9
- package/lib/features/design/editor/ChartDataPanel.js.map +1 -1
- package/lib/features/design/editor/CropOverlay.js +1 -1
- package/lib/features/design/editor/DesignCanvas.js +14 -13
- package/lib/features/design/editor/DesignCanvas.js.map +1 -1
- package/lib/features/design/editor/ExportSheet.js +8 -4
- package/lib/features/design/editor/ExportSheet.js.map +1 -1
- package/lib/features/design/editor/LayerTools.js +37 -5
- package/lib/features/design/editor/LayerTools.js.map +1 -1
- package/lib/features/design/editor/Slideshow.js +30 -5
- package/lib/features/design/editor/Slideshow.js.map +1 -1
- package/lib/features/design/editor/useDesignSave.js +21 -36
- package/lib/features/design/editor/useDesignSave.js.map +1 -1
- package/lib/features/design/export/exportDesign.js +3 -1
- package/lib/features/design/export/exportDesign.js.map +1 -1
- package/lib/features/design/home/DesignHome.js +7 -2
- package/lib/features/design/home/DesignHome.js.map +1 -1
- package/lib/features/design/render/DesignPageView.js +1 -1
- package/lib/features/design/render/DesignPageView.js.map +1 -1
- package/lib/features/design/render/PageCapture.js +11 -10
- package/lib/features/design/render/PageCapture.js.map +1 -1
- package/lib/features/design/render/fontRegistry.js +27 -3
- package/lib/features/design/render/fontRegistry.js.map +1 -1
- package/lib/features/design/render/svgParts.js +27 -74
- package/lib/features/design/render/svgParts.js.map +1 -1
- package/lib/features/devices/brands/qnScale.js +7 -2
- package/lib/features/devices/brands/qnScale.js.map +1 -1
- package/lib/features/devices/brands/uuids.js +2 -1
- package/lib/features/devices/brands/uuids.js.map +1 -1
- package/lib/features/devices/devices.js +2 -1
- package/lib/features/devices/devices.js.map +1 -1
- package/lib/features/docs/DocBlockRow.js +1 -1
- package/lib/features/docs/docArtifacts.js +2 -2
- package/lib/features/docs/docArtifacts.js.map +1 -1
- package/lib/features/health/healthSync.js +3 -1
- package/lib/features/health/healthSync.js.map +1 -1
- package/lib/features/health/nativeHealth.js +8 -0
- package/lib/features/health/nativeHealth.js.map +1 -0
- package/lib/features/links/openInApp.js +11 -1
- package/lib/features/links/openInApp.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +135 -28
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +14 -6
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewFrame.js +28 -3
- package/lib/features/webbuilder/components/PreviewFrame.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectChat.js +24 -5
- package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectsScreen.js +18 -2
- package/lib/features/webbuilder/components/ProjectsScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ui.js +20 -6
- package/lib/features/webbuilder/components/ui.js.map +1 -1
- package/lib/features/webbuilder/exportCode.js +52 -0
- package/lib/features/webbuilder/exportCode.js.map +1 -0
- package/lib/features/webbuilder/siteAddress.js +71 -0
- package/lib/features/webbuilder/siteAddress.js.map +1 -0
- package/lib/features/webbuilder/widgetBlocks.js +30 -0
- package/lib/features/webbuilder/widgetBlocks.js.map +1 -0
- package/lib/screens/Chat/index.js +5 -6
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ChatHistory/index.js +3 -2
- package/lib/screens/ChatHistory/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js +20 -4
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/WebBuilderCodePrewarm.js +18 -0
- package/lib/screens/Home/components/WebBuilderCodePrewarm.js.map +1 -0
- package/lib/screens/WebBuilderNative/index.js +1 -1
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/keepAlive.js +112 -0
- package/lib/screens/WebBuilderNative/keepAlive.js.map +1 -0
- package/lib/screens/WebBuilderNative/runningBuilds.js +40 -0
- package/lib/screens/WebBuilderNative/runningBuilds.js.map +1 -0
- package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js +57 -0
- package/lib/screens/WebBuilderNative/useSandboxKeepAlive.js.map +1 -0
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js +73 -14
- package/lib/screens/WebBuilderNative/useWebBuilderGallery.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +143 -34
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js +17 -5
- package/lib/screens/WebBuilderNative/useWebBuilderJobs.js.map +1 -1
- package/lib/screens/WebBuilderNative/versionUndo.js +144 -0
- package/lib/screens/WebBuilderNative/versionUndo.js.map +1 -0
- package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js +1 -0
- package/lib/screens/WebBuilderNative/webbuilderSnapshotKey.js.map +1 -0
- package/lib/screens/WebBuilderNative/webbuilderTransport.js +90 -6
- package/lib/screens/WebBuilderNative/webbuilderTransport.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runningBuilds.js","sources":["../../../src/screens/WebBuilderNative/runningBuilds.ts"],"sourcesContent":["/**\n * The Web Builder turns running on this device, by project: what Projects shows as\n * \"Building…\" so a site started from the studio (or an edit left mid-turn) can be\n * found and opened again (web: the project's tile shows its live run).\n *\n * Module state, not React state: it outlives the Web Builder screen, so leaving and\n * coming back still shows the run. An entry ends when its job settles, when its\n * project is opened and has no work left (see the host), or after the build budget\n * plus grace - a turn the app stopped watching (another site was opened, the screen\n * closed) is the agent's, or the server deadline's, to end.\n */\nimport { useSyncExternalStore } from 'react';\nimport { WEBBUILDER_JOB_BUDGET_MS, WEBBUILDER_JOB_GRACE_MS } from '../../features/webbuilder/buildJob';\n\nexport interface RunningBuild {\n channelId: string;\n /** The workspace it runs in: Projects lists only its own org's runs. */\n org: string;\n /** The site's name, or one made from the ask. */\n title: string;\n /** What the person asked, as their chat bubble shows it - until its post comes back. */\n ask?: string;\n startedAt: number;\n}\n\nconst LIFETIME_MS = WEBBUILDER_JOB_BUDGET_MS + WEBBUILDER_JOB_GRACE_MS;\n\nlet running = new Map<string, RunningBuild>();\nlet snapshot: RunningBuild[] = [];\nconst listeners = new Set<() => void>();\n\nfunction publish(next: Map<string, RunningBuild>): void {\n running = next;\n snapshot = [...next.values()].sort((a, b) => b.startedAt - a.startedAt);\n listeners.forEach((listener) => listener());\n}\n\n/** Drop entries past their lifetime; `now` is injectable for tests. */\nfunction pruned(now = Date.now()): Map<string, RunningBuild> {\n const next = new Map([...running].filter(([, run]) => now - run.startedAt < LIFETIME_MS));\n return next.size === running.size ? running : next;\n}\n\nexport function markBuildRunning(run: RunningBuild): void {\n if (!run.channelId) return;\n const next = new Map(pruned());\n next.set(run.channelId, run);\n publish(next);\n}\n\nexport function markBuildDone(channelId: string | null | undefined, startedBefore = Infinity): void {\n const run = channelId ? running.get(channelId) : undefined;\n // A newer turn on the same site keeps running.\n if (!run || run.startedAt > startedBefore) return;\n const next = new Map(running);\n next.delete(run.channelId);\n publish(next);\n}\n\nexport function runningBuild(channelId: string | null | undefined): RunningBuild | null {\n return (channelId && running.get(channelId)) || null;\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n // Entries expire by time: re-check once a minute while someone is listening.\n const timer = setInterval(() => {\n const next = pruned();\n if (next !== running) publish(next);\n }, 60_000);\n return () => {\n listeners.delete(listener);\n clearInterval(timer);\n };\n}\n\n/** The running builds, newest first. */\nexport function useRunningBuilds(): RunningBuild[] {\n return useSyncExternalStore(\n subscribe,\n () => snapshot,\n () => snapshot,\n );\n}\n\n/** Tests only. */\nexport function resetRunningBuilds(): void {\n publish(new Map());\n}\n"],"names":[],"mappings":"8IAuBA,MAAM,cAAc,wBAA2B,GAAA,uBAAA;AAC/C,IAAI,OAAA,uBAAc,GAA0B,EAAA;AAC5C,IAAI,WAA2B,EAAC;AAChC,MAAM,SAAA,uBAAgB,GAAgB,EAAA;AACtC,SAAS,QAAQ,IAAuC,EAAA;AACtD,EAAU,OAAA,GAAA,IAAA;AACV,EAAA,QAAA,GAAW,CAAC,GAAG,IAAK,CAAA,MAAA,EAAQ,CAAA,CAAE,IAAK,CAAA,CAAC,CAAG,EAAA,CAAA,KAAM,CAAE,CAAA,SAAA,GAAY,EAAE,SAAS,CAAA;AACtE,EAAU,SAAA,CAAA,OAAA,CAAQ,CAAY,QAAA,KAAA,QAAA,EAAU,CAAA;AAC1C;AAGA,SAAS,MAAO,CAAA,GAAA,GAAM,IAAK,CAAA,GAAA,EAAkC,EAAA;AAC3D,EAAA,MAAM,OAAO,IAAI,GAAA,CAAI,CAAC,GAAG,OAAO,CAAE,CAAA,MAAA,CAAO,CAAC,GAAG,GAAG,CAAA,KAAM,MAAM,GAAI,CAAA,SAAA,GAAY,WAAW,CAAC,CAAA;AACxF,EAAA,OAAO,IAAK,CAAA,IAAA,KAAS,OAAQ,CAAA,IAAA,GAAO,OAAU,GAAA,IAAA;AAChD;AACO,SAAS,iBAAiB,GAAyB,EAAA;AACxD,EAAI,IAAA,CAAC,IAAI,SAAW,EAAA;AACpB,EAAA,MAAM,IAAO,GAAA,IAAI,GAAI,CAAA,MAAA,EAAQ,CAAA;AAC7B,EAAK,IAAA,CAAA,GAAA,CAAI,GAAI,CAAA,SAAA,EAAW,GAAG,CAAA;AAC3B,EAAA,OAAA,CAAQ,IAAI,CAAA;AACd;AACgB,SAAA,aAAA,CAAc,SAAsC,EAAA,aAAA,GAAgB,QAAgB,EAAA;AAClG,EAAA,MAAM,GAAM,GAAA,SAAA,GAAY,OAAQ,CAAA,GAAA,CAAI,SAAS,CAAI,GAAA,MAAA;AAEjD,EAAA,IAAI,CAAC,GAAA,IAAO,GAAI,CAAA,SAAA,GAAY,aAAe,EAAA;AAC3C,EAAM,MAAA,IAAA,GAAO,IAAI,GAAA,CAAI,OAAO,CAAA;AAC5B,EAAK,IAAA,CAAA,MAAA,CAAO,IAAI,SAAS,CAAA;AACzB,EAAA,OAAA,CAAQ,IAAI,CAAA;AACd;AAIA,SAAS,UAAU,QAAkC,EAAA;AACnD,EAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AAEtB,EAAM,MAAA,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,MAAM,OAAO,MAAO,EAAA;AACpB,IAAI,IAAA,IAAA,KAAS,OAAS,EAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,KACjC,GAAM,CAAA;AACT,EAAA,OAAO,MAAM;AACX,IAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,IAAA,aAAA,CAAc,KAAK,CAAA;AAAA,GACrB;AACF;AAGO,SAAS,gBAAmC,GAAA;AACjD,EAAA,OAAO,oBAAqB,CAAA,SAAA,EAAW,MAAM,QAAA,EAAU,MAAM,QAAQ,CAAA;AACvE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {useRef,useEffect,useCallback}from'react';import {AppState}from'react-native';import {KeepAliveScheduler,WEBBUILDER_EXTEND_ACTION,KEEPALIVE_EXTEND_MS,KEEPALIVE_TICK_MS}from'./keepAlive.js';function useSandboxKeepAlive(opts) {
|
|
2
|
+
const runRef = useRef(opts.run);
|
|
3
|
+
runRef.current = opts.run;
|
|
4
|
+
const schedulerRef = useRef(null);
|
|
5
|
+
if (!schedulerRef.current) {
|
|
6
|
+
schedulerRef.current = new KeepAliveScheduler({
|
|
7
|
+
now: () => Date.now(),
|
|
8
|
+
extend: async (sandboxId2) => {
|
|
9
|
+
const run = runRef.current;
|
|
10
|
+
if (!run) return {
|
|
11
|
+
successful: false,
|
|
12
|
+
data: {},
|
|
13
|
+
error: "no sandbox access"
|
|
14
|
+
};
|
|
15
|
+
return run(WEBBUILDER_EXTEND_ACTION, {
|
|
16
|
+
sandbox_id: sandboxId2,
|
|
17
|
+
timeoutMs: KEEPALIVE_EXTEND_MS
|
|
18
|
+
}, 9e4);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const sandboxId = String(opts.sandboxId || "").trim();
|
|
23
|
+
const enabled = Boolean(opts.run) && opts.live;
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const s = schedulerRef.current;
|
|
26
|
+
s.setTarget(sandboxId, enabled);
|
|
27
|
+
if (enabled) {
|
|
28
|
+
s.noteActivity();
|
|
29
|
+
s.tick().catch(() => void 0);
|
|
30
|
+
}
|
|
31
|
+
}, [sandboxId, enabled]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const s = schedulerRef.current;
|
|
34
|
+
s.setVisible(AppState.currentState === "active");
|
|
35
|
+
const sub = AppState.addEventListener("change", (state) => {
|
|
36
|
+
s.setVisible(state === "active");
|
|
37
|
+
if (state === "active") {
|
|
38
|
+
s.noteActivity();
|
|
39
|
+
s.tick().catch(() => void 0);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
const timer = setInterval(() => {
|
|
43
|
+
s.tick().catch(() => void 0);
|
|
44
|
+
}, KEEPALIVE_TICK_MS);
|
|
45
|
+
return () => {
|
|
46
|
+
sub.remove();
|
|
47
|
+
clearInterval(timer);
|
|
48
|
+
};
|
|
49
|
+
}, []);
|
|
50
|
+
const noteActivity = useCallback(() => {
|
|
51
|
+
var _a;
|
|
52
|
+
return (_a = schedulerRef.current) == null ? void 0 : _a.noteActivity();
|
|
53
|
+
}, []);
|
|
54
|
+
return {
|
|
55
|
+
noteActivity
|
|
56
|
+
};
|
|
57
|
+
}export{useSandboxKeepAlive};//# sourceMappingURL=useSandboxKeepAlive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSandboxKeepAlive.js","sources":["../../../src/screens/WebBuilderNative/useSandboxKeepAlive.ts"],"sourcesContent":["/**\n * Feeds the keep-alive scheduler (keepAlive.ts) the app's foreground state and the\n * person's activity (web `sandbox/useSandboxKeepAlive.ts`): `WEBBUILDER_EXTEND`\n * every 10 minutes while a build is open, the app is in front and the person did\n * something in the last 15 minutes. Opening a project, sending a turn and\n * returning to the app count as activity (`noteActivity`).\n */\nimport { useCallback, useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport {\n KEEPALIVE_EXTEND_MS,\n KEEPALIVE_TICK_MS,\n KeepAliveScheduler,\n WEBBUILDER_EXTEND_ACTION,\n type ExtendResult,\n} from './keepAlive';\n\nexport function useSandboxKeepAlive(opts: {\n run: ((action: string, params: Record<string, unknown>, timeoutMs: number) => Promise<ExtendResult>) | null;\n sandboxId?: string | null;\n /** A build is open (its preview may be on screen). */\n live: boolean;\n}): { noteActivity: () => void } {\n const runRef = useRef(opts.run);\n runRef.current = opts.run;\n const schedulerRef = useRef<KeepAliveScheduler | null>(null);\n if (!schedulerRef.current) {\n schedulerRef.current = new KeepAliveScheduler({\n now: () => Date.now(),\n extend: async (sandboxId) => {\n const run = runRef.current;\n if (!run) return { successful: false, data: {}, error: 'no sandbox access' };\n return run(WEBBUILDER_EXTEND_ACTION, { sandbox_id: sandboxId, timeoutMs: KEEPALIVE_EXTEND_MS }, 90_000);\n },\n });\n }\n\n const sandboxId = String(opts.sandboxId || '').trim();\n const enabled = Boolean(opts.run) && opts.live;\n\n useEffect(() => {\n const s = schedulerRef.current!;\n s.setTarget(sandboxId, enabled);\n if (enabled) {\n s.noteActivity();\n s.tick().catch(() => undefined);\n }\n }, [sandboxId, enabled]);\n\n useEffect(() => {\n const s = schedulerRef.current!;\n s.setVisible(AppState.currentState === 'active');\n const sub = AppState.addEventListener('change', (state) => {\n s.setVisible(state === 'active');\n if (state === 'active') {\n s.noteActivity();\n s.tick().catch(() => undefined);\n }\n });\n const timer = setInterval(() => {\n s.tick().catch(() => undefined);\n }, KEEPALIVE_TICK_MS);\n return () => {\n sub.remove();\n clearInterval(timer);\n };\n }, []);\n\n const noteActivity = useCallback(() => schedulerRef.current?.noteActivity(), []);\n return { noteActivity };\n}\n"],"names":["sandboxId"],"mappings":"oMAUO,SAAS,oBAAoB,IAOlC,EAAA;AACA,EAAM,MAAA,MAAA,GAAS,MAAO,CAAA,IAAA,CAAK,GAAG,CAAA;AAC9B,EAAA,MAAA,CAAO,UAAU,IAAK,CAAA,GAAA;AACtB,EAAM,MAAA,YAAA,GAAe,OAAkC,IAAI,CAAA;AAC3D,EAAI,IAAA,CAAC,aAAa,OAAS,EAAA;AACzB,IAAa,YAAA,CAAA,OAAA,GAAU,IAAI,kBAAmB,CAAA;AAAA,MAC5C,GAAA,EAAK,MAAM,IAAA,CAAK,GAAI,EAAA;AAAA,MACpB,MAAA,EAAQ,OAAMA,UAAa,KAAA;AACzB,QAAA,MAAM,MAAM,MAAO,CAAA,OAAA;AACnB,QAAI,IAAA,CAAC,KAAY,OAAA;AAAA,UACf,UAAY,EAAA,KAAA;AAAA,UACZ,MAAM,EAAC;AAAA,UACP,KAAO,EAAA;AAAA,SACT;AACA,QAAA,OAAO,IAAI,wBAA0B,EAAA;AAAA,UACnC,UAAYA,EAAAA,UAAAA;AAAA,UACZ,SAAW,EAAA;AAAA,WACV,GAAM,CAAA;AAAA;AACX,KACD,CAAA;AAAA;AAEH,EAAA,MAAM,YAAY,MAAO,CAAA,IAAA,CAAK,SAAa,IAAA,EAAE,EAAE,IAAK,EAAA;AACpD,EAAA,MAAM,OAAU,GAAA,OAAA,CAAQ,IAAK,CAAA,GAAG,KAAK,IAAK,CAAA,IAAA;AAC1C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAI,YAAa,CAAA,OAAA;AACvB,IAAE,CAAA,CAAA,SAAA,CAAU,WAAW,OAAO,CAAA;AAC9B,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,CAAA,CAAE,YAAa,EAAA;AACf,MAAA,CAAA,CAAE,IAAK,EAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAAA;AAChC,GACC,EAAA,CAAC,SAAW,EAAA,OAAO,CAAC,CAAA;AACvB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAI,YAAa,CAAA,OAAA;AACvB,IAAE,CAAA,CAAA,UAAA,CAAW,QAAS,CAAA,YAAA,KAAiB,QAAQ,CAAA;AAC/C,IAAA,MAAM,GAAM,GAAA,QAAA,CAAS,gBAAiB,CAAA,QAAA,EAAU,CAAS,KAAA,KAAA;AACvD,MAAE,CAAA,CAAA,UAAA,CAAW,UAAU,QAAQ,CAAA;AAC/B,MAAA,IAAI,UAAU,QAAU,EAAA;AACtB,QAAA,CAAA,CAAE,YAAa,EAAA;AACf,QAAA,CAAA,CAAE,IAAK,EAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAAA;AAChC,KACD,CAAA;AACD,IAAM,MAAA,KAAA,GAAQ,YAAY,MAAM;AAC9B,MAAA,CAAA,CAAE,IAAK,EAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAAA,OAC7B,iBAAiB,CAAA;AACpB,IAAA,OAAO,MAAM;AACX,MAAA,GAAA,CAAI,MAAO,EAAA;AACX,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,KACrB;AAAA,GACF,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,YAAA,GAAe,YAAY,MAAG;AAlEtC,IAAA,IAAA,EAAA;AAkEyC,IAAA,OAAA,CAAA,EAAA,GAAA,YAAA,CAAa,YAAb,IAAsB,GAAA,MAAA,GAAA,EAAA,CAAA,YAAA,EAAA;AAAA,GAAA,EAAgB,EAAE,CAAA;AAC/E,EAAO,OAAA;AAAA,IACL;AAAA,GACF;AACF"}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
|
-
import {useState,useRef,useEffect,useCallback}from'react';import {useApolloClient}from'@apollo/client/index.js';import AsyncStorage from'@react-native-async-storage/async-storage';import {MessagesDocument,GetChannelsByUserWithLastMessageDocument}from'common/graphql';import {getThreadMessagesQueryVariables,getHistoryChannelsQueryVariables}from'../../hooks/useChatApi.js';import {lastMessageHasCover,projectFromPosts}from'../../features/webbuilder/buildFragments.js';
|
|
1
|
+
import {useState,useRef,useEffect,useCallback}from'react';import {useApolloClient}from'@apollo/client/index.js';import AsyncStorage from'@react-native-async-storage/async-storage';import {MessagesDocument,GetChannelsByUserWithLastMessageDocument}from'common/graphql';import {getThreadMessagesQueryVariables,getHistoryChannelsQueryVariables}from'../../hooks/useChatApi.js';import {lastMessageHasCover,projectFromPosts,isGenericTitle}from'../../features/webbuilder/buildFragments.js';import {WEBBUILDER_PROJECTS_SNAPSHOT_KEY}from'./webbuilderSnapshotKey.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const GALLERY_PAGE_SIZE = 10;
|
|
2
21
|
const MIN_FILL = 8;
|
|
3
22
|
const MAX_PAGES_PER_LOAD = 4;
|
|
4
23
|
const READ_CONCURRENCY = 4;
|
|
5
|
-
const SNAPSHOT_KEY =
|
|
24
|
+
const SNAPSHOT_KEY = WEBBUILDER_PROJECTS_SNAPSHOT_KEY;
|
|
6
25
|
const SNAPSHOT_MAX = 40;
|
|
7
26
|
const memory = /* @__PURE__ */ new Map();
|
|
8
27
|
function sortProjects(list) {
|
|
@@ -13,16 +32,46 @@ function stampOf(channel) {
|
|
|
13
32
|
return String((_b = (_a = channel.updatedAt) != null ? _a : channel.createdAt) != null ? _b : "");
|
|
14
33
|
}
|
|
15
34
|
async function readSnapshot(org) {
|
|
35
|
+
var _a;
|
|
16
36
|
try {
|
|
17
37
|
const raw = await AsyncStorage.getItem(`${SNAPSHOT_KEY}:${org}`);
|
|
18
|
-
const
|
|
19
|
-
|
|
38
|
+
const parsed = raw ? JSON.parse(raw) : {};
|
|
39
|
+
const saved = Array.isArray(parsed) ? {
|
|
40
|
+
projects: parsed
|
|
41
|
+
} : parsed;
|
|
42
|
+
const projects = Array.isArray(saved.projects) ? saved.projects.filter((p) => (p == null ? void 0 : p.channelId) && p.title) : [];
|
|
43
|
+
const known = /* @__PURE__ */ new Map();
|
|
44
|
+
for (const row of Array.isArray(saved.known) ? saved.known : []) {
|
|
45
|
+
if (Array.isArray(row) && typeof row[0] === "string" && typeof row[1] === "string") {
|
|
46
|
+
known.set(row[0], {
|
|
47
|
+
stamp: row[1],
|
|
48
|
+
project: (_a = row[2]) != null ? _a : null
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
projects,
|
|
54
|
+
known
|
|
55
|
+
};
|
|
20
56
|
} catch (e) {
|
|
21
|
-
return
|
|
57
|
+
return {
|
|
58
|
+
projects: [],
|
|
59
|
+
known: /* @__PURE__ */ new Map()
|
|
60
|
+
};
|
|
22
61
|
}
|
|
23
62
|
}
|
|
24
|
-
function writeSnapshot(org, projects) {
|
|
25
|
-
|
|
63
|
+
function writeSnapshot(org, projects, known) {
|
|
64
|
+
const snapshot = {
|
|
65
|
+
projects: projects.slice(0, SNAPSHOT_MAX),
|
|
66
|
+
known: [...known].slice(-300).map(([id, k]) => [id, k.stamp, k.project])
|
|
67
|
+
};
|
|
68
|
+
AsyncStorage.setItem(`${SNAPSHOT_KEY}:${org}`, JSON.stringify(snapshot)).catch(() => void 0);
|
|
69
|
+
}
|
|
70
|
+
function keepKnownName(next, prior) {
|
|
71
|
+
if (!next || !prior || !isGenericTitle(next.title) || isGenericTitle(prior.title)) return next;
|
|
72
|
+
return __spreadProps(__spreadValues({}, next), {
|
|
73
|
+
title: prior.title
|
|
74
|
+
});
|
|
26
75
|
}
|
|
27
76
|
async function eachLimited(items, limit, work) {
|
|
28
77
|
let next = 0;
|
|
@@ -76,14 +125,19 @@ function useWebBuilderGallery(orgName, cdnOrigin) {
|
|
|
76
125
|
projects,
|
|
77
126
|
known: knownRef.current
|
|
78
127
|
});
|
|
79
|
-
if (projects.length) writeSnapshot(orgName, projects);
|
|
128
|
+
if (projects.length) writeSnapshot(orgName, projects, knownRef.current);
|
|
80
129
|
}, [orgName, projects]);
|
|
130
|
+
const hydratedRef = useRef(Promise.resolve());
|
|
81
131
|
useEffect(() => {
|
|
82
132
|
var _a2;
|
|
83
133
|
if (!orgName || ((_a2 = memory.get(orgName)) == null ? void 0 : _a2.projects.length)) return void 0;
|
|
84
134
|
let live = true;
|
|
85
|
-
readSnapshot(orgName).then((saved) => {
|
|
86
|
-
if (live
|
|
135
|
+
hydratedRef.current = readSnapshot(orgName).then((saved) => {
|
|
136
|
+
if (!live) return;
|
|
137
|
+
saved.known.forEach((k, id) => {
|
|
138
|
+
if (!knownRef.current.has(id)) knownRef.current.set(id, k);
|
|
139
|
+
});
|
|
140
|
+
if (saved.projects.length) setProjects((prev) => prev.length ? prev : saved.projects);
|
|
87
141
|
}).catch(() => void 0);
|
|
88
142
|
return () => {
|
|
89
143
|
live = false;
|
|
@@ -95,7 +149,7 @@ function useWebBuilderGallery(orgName, cdnOrigin) {
|
|
|
95
149
|
if (!id) return null;
|
|
96
150
|
if (lastMessageHasCover(channel)) {
|
|
97
151
|
const fromLast = projectFromPosts(channel, [channel.lastMessage], cdnOrigin);
|
|
98
|
-
if (fromLast) return fromLast;
|
|
152
|
+
if (fromLast && !isGenericTitle(fromLast.title)) return fromLast;
|
|
99
153
|
}
|
|
100
154
|
const result = await client.query({
|
|
101
155
|
query: MessagesDocument,
|
|
@@ -114,6 +168,7 @@ function useWebBuilderGallery(orgName, cdnOrigin) {
|
|
|
114
168
|
async (mode) => {
|
|
115
169
|
if (!orgName || busyRef.current) return;
|
|
116
170
|
busyRef.current = true;
|
|
171
|
+
await hydratedRef.current;
|
|
117
172
|
const run = runRef.current + 1;
|
|
118
173
|
runRef.current = run;
|
|
119
174
|
const stale = () => runRef.current !== run;
|
|
@@ -163,19 +218,23 @@ function useWebBuilderGallery(orgName, cdnOrigin) {
|
|
|
163
218
|
skipRef.current += channels.length;
|
|
164
219
|
more = channels.length >= GALLERY_PAGE_SIZE;
|
|
165
220
|
await eachLimited(channels, READ_CONCURRENCY, async (channel) => {
|
|
166
|
-
var _a2;
|
|
221
|
+
var _a2, _b;
|
|
167
222
|
const id = (_a2 = channel.id) != null ? _a2 : "";
|
|
168
223
|
seen.add(id);
|
|
169
224
|
const stamp = stampOf(channel);
|
|
170
225
|
const prior = known.get(id);
|
|
171
|
-
|
|
226
|
+
const unnamed = Boolean((prior == null ? void 0 : prior.project) && isGenericTitle(prior.project.title));
|
|
227
|
+
if (prior && prior.stamp === stamp && !unnamed) {
|
|
172
228
|
if (prior.project) tally.found += 1;
|
|
173
229
|
return;
|
|
174
230
|
}
|
|
175
|
-
const
|
|
231
|
+
const quick = channel.lastMessage ? keepKnownName(projectFromPosts(channel, [channel.lastMessage], cdnOrigin), prior == null ? void 0 : prior.project) : null;
|
|
232
|
+
if (quick) put(quick, id);
|
|
233
|
+
const read = await projectFor(channel, "network-only").catch(() => {
|
|
176
234
|
var _a3;
|
|
177
235
|
return (_a3 = prior == null ? void 0 : prior.project) != null ? _a3 : null;
|
|
178
236
|
});
|
|
237
|
+
const project = keepKnownName(read, (_b = prior == null ? void 0 : prior.project) != null ? _b : quick);
|
|
179
238
|
known.set(id, {
|
|
180
239
|
stamp,
|
|
181
240
|
project
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebBuilderGallery.js","sources":["../../../src/screens/WebBuilderNative/useWebBuilderGallery.ts"],"sourcesContent":["/**\n * Projects - the web surface's gallery hydrate, on the host, made fast.\n *\n * Same rule as the web (`realServices` gallery load): page the person's AI\n * assistant chats 10 at a time, newest first, and keep a chat only if its posts\n * hold a build. What makes it quick on a phone:\n *\n * - The last list paints at once: kept in memory across visits and on disk for a\n * cold start (per workspace).\n * - Reads go through the Apollo cache first. The app's type policies\n * (`graphql/typePolicies.ts`) keep `channelsByUser` as one merged list per\n * workspace and `messages` per channel, so a cached page is complete and\n * paints without the network.\n * - The refresh re-reads a chat's thread only when the chat changed\n * (`updatedAt`); an unchanged chat keeps the project it already gave. A typical\n * refresh is one list request, not one per chat.\n * - Thread reads run a few at a time and each project appears as soon as it is\n * known, newest first.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useApolloClient, type ApolloClient, type FetchPolicy } from '@apollo/client';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { GetChannelsByUserWithLastMessageDocument, MessagesDocument } from 'common/graphql';\nimport { getHistoryChannelsQueryVariables, getThreadMessagesQueryVariables } from '../../hooks/useChatApi';\nimport { lastMessageHasCover, projectFromPosts, type ChannelLike } from '../../features/webbuilder/buildFragments';\nimport type { WebBuilderProject } from '../../features/webbuilder/types';\n\n/** The web gallery's page size (`GALLERY_PAGE_SIZE`). */\nexport const GALLERY_PAGE_SIZE = 10;\n/** Keep paging (up to this many pages per load) while pages yield too few projects to fill the screen. */\nconst MIN_FILL = 8;\nconst MAX_PAGES_PER_LOAD = 4;\n/** Thread reads in flight at once: enough to be quick, few enough to keep the app responsive. */\nconst READ_CONCURRENCY = 4;\nconst SNAPSHOT_KEY = 'yantra.webbuilder.projects.v1';\nconst SNAPSHOT_MAX = 40;\n\ntype Loose = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n/** What a chat last gave: its project (or none) at the `updatedAt` it was read for. */\ninterface Known {\n stamp: string;\n project: WebBuilderProject | null;\n}\n\n/** Per-workspace memory: survives leaving and reopening Web Builder in one app run. */\nconst memory = new Map<string, { projects: WebBuilderProject[]; known: Map<string, Known> }>();\n\nexport interface WebBuilderGallery {\n projects: WebBuilderProject[];\n loading: boolean;\n loadingMore: boolean;\n hasMore: boolean;\n error: string | null;\n refresh: () => void;\n loadMore: () => void;\n /** Put (or update) one site - the open one, as its posts change. */\n upsert: (project: WebBuilderProject) => void;\n}\n\nfunction sortProjects(list: Iterable<WebBuilderProject>): WebBuilderProject[] {\n return [...list].sort((a, b) => b.updatedAt - a.updatedAt);\n}\n\nfunction stampOf(channel: ChannelLike): string {\n return String(channel.updatedAt ?? channel.createdAt ?? '');\n}\n\nasync function readSnapshot(org: string): Promise<WebBuilderProject[]> {\n try {\n const raw = await AsyncStorage.getItem(`${SNAPSHOT_KEY}:${org}`);\n const list = raw ? (JSON.parse(raw) as WebBuilderProject[]) : [];\n return Array.isArray(list) ? list.filter((p) => p?.channelId && p.title) : [];\n } catch {\n return [];\n }\n}\n\nfunction writeSnapshot(org: string, projects: WebBuilderProject[]): void {\n AsyncStorage.setItem(`${SNAPSHOT_KEY}:${org}`, JSON.stringify(projects.slice(0, SNAPSHOT_MAX))).catch(\n () => undefined,\n );\n}\n\n/** Runs `work` over `items`, at most `limit` at a time. */\nasync function eachLimited<T>(items: T[], limit: number, work: (item: T) => Promise<void>): Promise<void> {\n let next = 0;\n const lane = async (): Promise<void> => {\n while (next < items.length) {\n const item = items[next];\n next += 1;\n // eslint-disable-next-line no-await-in-loop -- one lane works through its share in order\n await work(item);\n }\n };\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, lane));\n}\n\nasync function readChannels(\n client: ApolloClient<object>,\n orgName: string,\n skip: number,\n fetchPolicy: FetchPolicy,\n): Promise<ChannelLike[]> {\n const result = await client.query({\n query: GetChannelsByUserWithLastMessageDocument,\n variables: getHistoryChannelsQueryVariables(orgName, { limit: GALLERY_PAGE_SIZE, skip }),\n fetchPolicy,\n errorPolicy: 'all',\n // Same slot as chat history: the type policy merges both into one list.\n context: { cacheKey: 'chat-history-channels-list' },\n });\n return (((result.data as Loose)?.channelsByUser ?? []) as ChannelLike[]).filter((c) => c?.id);\n}\n\nexport function useWebBuilderGallery(orgName: string, cdnOrigin: string): WebBuilderGallery {\n const client = useApolloClient();\n const remembered = orgName ? memory.get(orgName) : undefined;\n const [projects, setProjects] = useState<WebBuilderProject[]>(() => remembered?.projects ?? []);\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const skipRef = useRef(0);\n const busyRef = useRef(false);\n const runRef = useRef(0);\n const knownRef = useRef<Map<string, Known>>(remembered?.known ?? new Map());\n\n // Keep memory and the disk snapshot in step with what is shown.\n useEffect(() => {\n if (!orgName) return;\n memory.set(orgName, { projects, known: knownRef.current });\n if (projects.length) writeSnapshot(orgName, projects);\n }, [orgName, projects]);\n\n // A cold start paints the last list from disk while the cache and network catch up.\n useEffect(() => {\n if (!orgName || memory.get(orgName)?.projects.length) return undefined;\n let live = true;\n readSnapshot(orgName)\n .then((saved) => {\n if (live && saved.length) setProjects((prev) => (prev.length ? prev : saved));\n })\n .catch(() => undefined);\n return () => {\n live = false;\n };\n }, [orgName]);\n\n const projectFor = useCallback(\n async (channel: ChannelLike, fetchPolicy: FetchPolicy): Promise<WebBuilderProject | null> => {\n const id = channel.id ?? '';\n if (!id) return null;\n // The web skips the thread read when the last post already has the screenshot.\n if (lastMessageHasCover(channel)) {\n const fromLast = projectFromPosts(channel, [channel.lastMessage], cdnOrigin);\n if (fromLast) return fromLast;\n }\n const result = await client.query({\n query: MessagesDocument,\n variables: getThreadMessagesQueryVariables(id),\n fetchPolicy,\n errorPolicy: 'all',\n context: { cacheKey: `messages-list:${id}` },\n });\n const posts = ((result.data as Loose)?.messages?.data ?? []) as unknown[];\n const withLast = channel.lastMessage ? [...posts, channel.lastMessage] : posts;\n return projectFromPosts(channel, withLast, cdnOrigin);\n },\n [client, cdnOrigin],\n );\n\n const load = useCallback(\n async (mode: 'reset' | 'more') => {\n if (!orgName || busyRef.current) return;\n busyRef.current = true;\n const run = runRef.current + 1;\n runRef.current = run;\n const stale = () => runRef.current !== run;\n const known = knownRef.current;\n const seen = new Set<string>();\n const put = (project: WebBuilderProject | null, channelId: string) => {\n if (stale()) return;\n setProjects((prev) => {\n const byId = new Map(prev.map((p) => [p.channelId, p]));\n if (project) byId.set(channelId, project);\n else byId.delete(channelId);\n return sortProjects(byId.values());\n });\n };\n\n if (mode === 'reset') {\n skipRef.current = 0;\n setLoading(projects.length === 0);\n } else {\n setLoadingMore(true);\n }\n setError(null);\n\n try {\n // 1. From the cache: instant when the type policies already hold the list.\n if (mode === 'reset') {\n const cached = await readChannels(client, orgName, 0, 'cache-only').catch(() => []);\n await eachLimited(cached, READ_CONCURRENCY, async (channel) => {\n const id = channel.id ?? '';\n if (known.has(id)) return;\n const project = await projectFor(channel, 'cache-only').catch(() => null);\n if (project) {\n known.set(id, { stamp: stampOf(channel), project });\n put(project, id);\n }\n });\n if (!stale() && projects.length === 0 && known.size) setLoading(false);\n }\n\n // 2. From the network: the list, then only the threads that changed.\n let more = false;\n const tally = { found: 0 };\n for (let page = 0; page < MAX_PAGES_PER_LOAD; page += 1) {\n // eslint-disable-next-line no-await-in-loop -- pages are sequential by design\n const channels = await readChannels(client, orgName, skipRef.current, 'network-only');\n if (stale()) return;\n skipRef.current += channels.length;\n more = channels.length >= GALLERY_PAGE_SIZE;\n // eslint-disable-next-line no-await-in-loop\n await eachLimited(channels, READ_CONCURRENCY, async (channel) => {\n const id = channel.id ?? '';\n seen.add(id);\n const stamp = stampOf(channel);\n const prior = known.get(id);\n if (prior && prior.stamp === stamp) {\n if (prior.project) tally.found += 1;\n return;\n }\n const project = await projectFor(channel, 'network-only').catch(() => prior?.project ?? null);\n known.set(id, { stamp, project });\n if (project) tally.found += 1;\n put(project, id);\n });\n if (!more || tally.found >= MIN_FILL) break;\n }\n if (stale()) return;\n if (mode === 'reset') {\n // A chat no longer in the first pages (deleted, moved) drops off the list.\n setProjects((prev) =>\n prev.filter((p) => seen.has(p.channelId) || p.updatedAt > Date.now() - 60_000),\n );\n }\n setHasMore(more);\n } catch (err) {\n console.warn('[WebBuilderNative] could not load projects:', err);\n if (!stale()) setError('Check your connection and try again.');\n } finally {\n busyRef.current = false;\n if (!stale()) {\n setLoading(false);\n setLoadingMore(false);\n }\n }\n },\n // `projects.length` only steers the first spinner; reading it stale is harmless.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, orgName, projectFor],\n );\n\n useEffect(() => {\n load('reset').catch(() => undefined);\n }, [load]);\n\n const refresh = useCallback(() => {\n busyRef.current = false;\n load('reset').catch(() => undefined);\n }, [load]);\n const loadMore = useCallback(() => {\n if (hasMore) load('more').catch(() => undefined);\n }, [hasMore, load]);\n\n const upsert = useCallback((project: WebBuilderProject) => {\n setProjects((prev) => {\n const existing = prev.find((p) => p.channelId === project.channelId);\n if (\n existing &&\n existing.title === project.title &&\n existing.coverUrl === project.coverUrl &&\n existing.liveUrl === project.liveUrl &&\n existing.updatedAt === project.updatedAt\n ) {\n return prev;\n }\n return sortProjects([project, ...prev.filter((p) => p.channelId !== project.channelId)]);\n });\n }, []);\n\n return { projects, loading, loadingMore, hasMore, error, refresh, loadMore, upsert };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useWebBuilderGallery.js","sources":["../../../src/screens/WebBuilderNative/useWebBuilderGallery.ts"],"sourcesContent":["/**\n * Projects - the web surface's gallery hydrate, on the host, made fast.\n *\n * Same rule as the web (`realServices` gallery load): page the person's AI\n * assistant chats 10 at a time, newest first, and keep a chat only if its posts\n * hold a build. What makes it quick on a phone:\n *\n * - The last list paints at once: kept in memory across visits and on disk for a\n * cold start (per workspace).\n * - Reads go through the Apollo cache first. The app's type policies\n * (`graphql/typePolicies.ts`) keep `channelsByUser` as one merged list per\n * workspace and `messages` per channel, so a cached page is complete and\n * paints without the network.\n * - The refresh re-reads a chat's thread only when the chat changed\n * (`updatedAt`); an unchanged chat keeps the project it already gave. What each\n * chat gave (a project, or none for a plain chat) is saved with the list, so a\n * cold start re-reads only the chats that changed, not every chat again.\n * - A changed chat shows at once from its last post when that is a build; its\n * thread read then fills in the cover and the name. Thread reads run a few at a\n * time and each project appears as soon as it is known, newest first.\n * - A name, once known, is kept: a read that only yields the placeholder\n * (\"Generated Page\") never replaces it.\n */\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useApolloClient, type ApolloClient, type FetchPolicy } from '@apollo/client';\nimport AsyncStorage from '@react-native-async-storage/async-storage';\nimport { GetChannelsByUserWithLastMessageDocument, MessagesDocument } from 'common/graphql';\nimport { getHistoryChannelsQueryVariables, getThreadMessagesQueryVariables } from '../../hooks/useChatApi';\nimport {\n isGenericTitle,\n lastMessageHasCover,\n projectFromPosts,\n type ChannelLike,\n} from '../../features/webbuilder/buildFragments';\nimport type { WebBuilderProject } from '../../features/webbuilder/types';\nimport { WEBBUILDER_PROJECTS_SNAPSHOT_KEY } from './webbuilderSnapshotKey';\n\n/** The web gallery's page size (`GALLERY_PAGE_SIZE`). */\nexport const GALLERY_PAGE_SIZE = 10;\n/** Keep paging (up to this many pages per load) while pages yield too few projects to fill the screen. */\nconst MIN_FILL = 8;\nconst MAX_PAGES_PER_LOAD = 4;\n/** Thread reads in flight at once: enough to be quick, few enough to keep the app responsive. */\nconst READ_CONCURRENCY = 4;\nconst SNAPSHOT_KEY = WEBBUILDER_PROJECTS_SNAPSHOT_KEY;\nconst SNAPSHOT_MAX = 40;\n/** Chats remembered with their stamp (plain chats included: each would otherwise be re-read). */\nconst KNOWN_MAX = 300;\n\ntype Loose = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n/** What a chat last gave: its project (or none) at the `updatedAt` it was read for. */\ninterface Known {\n stamp: string;\n project: WebBuilderProject | null;\n}\n\n/** Per-workspace memory: survives leaving and reopening Web Builder in one app run. */\nconst memory = new Map<string, { projects: WebBuilderProject[]; known: Map<string, Known> }>();\n\nexport interface WebBuilderGallery {\n projects: WebBuilderProject[];\n loading: boolean;\n loadingMore: boolean;\n hasMore: boolean;\n error: string | null;\n refresh: () => void;\n loadMore: () => void;\n /** Put (or update) one site - the open one, as its posts change. */\n upsert: (project: WebBuilderProject) => void;\n}\n\nfunction sortProjects(list: Iterable<WebBuilderProject>): WebBuilderProject[] {\n return [...list].sort((a, b) => b.updatedAt - a.updatedAt);\n}\n\nfunction stampOf(channel: ChannelLike): string {\n return String(channel.updatedAt ?? channel.createdAt ?? '');\n}\n\ninterface Snapshot {\n projects: WebBuilderProject[];\n /** `[channelId, stamp, project | null]`: what each chat gave at the `updatedAt` it was read for. */\n known: Array<[string, string, WebBuilderProject | null]>;\n}\n\nasync function readSnapshot(org: string): Promise<{ projects: WebBuilderProject[]; known: Map<string, Known> }> {\n try {\n const raw = await AsyncStorage.getItem(`${SNAPSHOT_KEY}:${org}`);\n const parsed = raw ? (JSON.parse(raw) as Partial<Snapshot> | WebBuilderProject[]) : {};\n // An older snapshot is the bare projects list.\n const saved: Partial<Snapshot> = Array.isArray(parsed) ? { projects: parsed } : parsed;\n const projects = Array.isArray(saved.projects) ? saved.projects.filter((p) => p?.channelId && p.title) : [];\n const known = new Map<string, Known>();\n for (const row of Array.isArray(saved.known) ? saved.known : []) {\n if (Array.isArray(row) && typeof row[0] === 'string' && typeof row[1] === 'string') {\n known.set(row[0], { stamp: row[1], project: row[2] ?? null });\n }\n }\n return { projects, known };\n } catch {\n return { projects: [], known: new Map() };\n }\n}\n\nfunction writeSnapshot(org: string, projects: WebBuilderProject[], known: Map<string, Known>): void {\n const snapshot: Snapshot = {\n projects: projects.slice(0, SNAPSHOT_MAX),\n known: [...known].slice(-KNOWN_MAX).map(([id, k]) => [id, k.stamp, k.project]),\n };\n AsyncStorage.setItem(`${SNAPSHOT_KEY}:${org}`, JSON.stringify(snapshot)).catch(() => undefined);\n}\n\n/** A read that only found the placeholder name keeps the name the site already had. */\nfunction keepKnownName(next: WebBuilderProject | null, prior: WebBuilderProject | null | undefined) {\n if (!next || !prior || !isGenericTitle(next.title) || isGenericTitle(prior.title)) return next;\n return { ...next, title: prior.title };\n}\n\n/** Runs `work` over `items`, at most `limit` at a time. */\nasync function eachLimited<T>(items: T[], limit: number, work: (item: T) => Promise<void>): Promise<void> {\n let next = 0;\n const lane = async (): Promise<void> => {\n while (next < items.length) {\n const item = items[next];\n next += 1;\n // eslint-disable-next-line no-await-in-loop -- one lane works through its share in order\n await work(item);\n }\n };\n await Promise.all(Array.from({ length: Math.min(limit, items.length) }, lane));\n}\n\nasync function readChannels(\n client: ApolloClient<object>,\n orgName: string,\n skip: number,\n fetchPolicy: FetchPolicy,\n): Promise<ChannelLike[]> {\n const result = await client.query({\n query: GetChannelsByUserWithLastMessageDocument,\n variables: getHistoryChannelsQueryVariables(orgName, { limit: GALLERY_PAGE_SIZE, skip }),\n fetchPolicy,\n errorPolicy: 'all',\n // Same slot as chat history: the type policy merges both into one list.\n context: { cacheKey: 'chat-history-channels-list' },\n });\n return (((result.data as Loose)?.channelsByUser ?? []) as ChannelLike[]).filter((c) => c?.id);\n}\n\nexport function useWebBuilderGallery(orgName: string, cdnOrigin: string): WebBuilderGallery {\n const client = useApolloClient();\n const remembered = orgName ? memory.get(orgName) : undefined;\n const [projects, setProjects] = useState<WebBuilderProject[]>(() => remembered?.projects ?? []);\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const skipRef = useRef(0);\n const busyRef = useRef(false);\n const runRef = useRef(0);\n const knownRef = useRef<Map<string, Known>>(remembered?.known ?? new Map());\n\n // Keep memory and the disk snapshot in step with what is shown.\n useEffect(() => {\n if (!orgName) return;\n memory.set(orgName, { projects, known: knownRef.current });\n if (projects.length) writeSnapshot(orgName, projects, knownRef.current);\n }, [orgName, projects]);\n\n // A cold start paints the last list from disk, and takes what each chat gave with it,\n // so the first load re-reads only the chats that changed since (it waits for this).\n const hydratedRef = useRef<Promise<void>>(Promise.resolve());\n useEffect(() => {\n if (!orgName || memory.get(orgName)?.projects.length) return undefined;\n let live = true;\n hydratedRef.current = readSnapshot(orgName)\n .then((saved) => {\n if (!live) return;\n saved.known.forEach((k, id) => {\n if (!knownRef.current.has(id)) knownRef.current.set(id, k);\n });\n if (saved.projects.length) setProjects((prev) => (prev.length ? prev : saved.projects));\n })\n .catch(() => undefined);\n return () => {\n live = false;\n };\n }, [orgName]);\n\n const projectFor = useCallback(\n async (channel: ChannelLike, fetchPolicy: FetchPolicy): Promise<WebBuilderProject | null> => {\n const id = channel.id ?? '';\n if (!id) return null;\n // The web skips the thread read when the last post already has the screenshot.\n // Only with a real name: the last post alone has no brief to name the site from.\n if (lastMessageHasCover(channel)) {\n const fromLast = projectFromPosts(channel, [channel.lastMessage], cdnOrigin);\n if (fromLast && !isGenericTitle(fromLast.title)) return fromLast;\n }\n const result = await client.query({\n query: MessagesDocument,\n variables: getThreadMessagesQueryVariables(id),\n fetchPolicy,\n errorPolicy: 'all',\n context: { cacheKey: `messages-list:${id}` },\n });\n const posts = ((result.data as Loose)?.messages?.data ?? []) as unknown[];\n const withLast = channel.lastMessage ? [...posts, channel.lastMessage] : posts;\n return projectFromPosts(channel, withLast, cdnOrigin);\n },\n [client, cdnOrigin],\n );\n\n const load = useCallback(\n async (mode: 'reset' | 'more') => {\n if (!orgName || busyRef.current) return;\n busyRef.current = true;\n await hydratedRef.current;\n const run = runRef.current + 1;\n runRef.current = run;\n const stale = () => runRef.current !== run;\n const known = knownRef.current;\n const seen = new Set<string>();\n const put = (project: WebBuilderProject | null, channelId: string) => {\n if (stale()) return;\n setProjects((prev) => {\n const byId = new Map(prev.map((p) => [p.channelId, p]));\n if (project) byId.set(channelId, project);\n else byId.delete(channelId);\n return sortProjects(byId.values());\n });\n };\n\n if (mode === 'reset') {\n skipRef.current = 0;\n setLoading(projects.length === 0);\n } else {\n setLoadingMore(true);\n }\n setError(null);\n\n try {\n // 1. From the cache: instant when the type policies already hold the list.\n if (mode === 'reset') {\n const cached = await readChannels(client, orgName, 0, 'cache-only').catch(() => []);\n await eachLimited(cached, READ_CONCURRENCY, async (channel) => {\n const id = channel.id ?? '';\n if (known.has(id)) return;\n const project = await projectFor(channel, 'cache-only').catch(() => null);\n if (project) {\n known.set(id, { stamp: stampOf(channel), project });\n put(project, id);\n }\n });\n if (!stale() && projects.length === 0 && known.size) setLoading(false);\n }\n\n // 2. From the network: the list, then only the threads that changed.\n let more = false;\n const tally = { found: 0 };\n for (let page = 0; page < MAX_PAGES_PER_LOAD; page += 1) {\n // eslint-disable-next-line no-await-in-loop -- pages are sequential by design\n const channels = await readChannels(client, orgName, skipRef.current, 'network-only');\n if (stale()) return;\n skipRef.current += channels.length;\n more = channels.length >= GALLERY_PAGE_SIZE;\n // eslint-disable-next-line no-await-in-loop\n await eachLimited(channels, READ_CONCURRENCY, async (channel) => {\n const id = channel.id ?? '';\n seen.add(id);\n const stamp = stampOf(channel);\n const prior = known.get(id);\n // Unchanged: keep what it gave - unless that is still the placeholder name.\n const unnamed = Boolean(prior?.project && isGenericTitle(prior.project.title));\n if (prior && prior.stamp === stamp && !unnamed) {\n if (prior.project) tally.found += 1;\n return;\n }\n // Show it now from its last post when that is a build; the read fills in the rest.\n const quick = channel.lastMessage\n ? keepKnownName(projectFromPosts(channel, [channel.lastMessage], cdnOrigin), prior?.project)\n : null;\n if (quick) put(quick, id);\n const read = await projectFor(channel, 'network-only').catch(() => prior?.project ?? null);\n const project = keepKnownName(read, prior?.project ?? quick);\n known.set(id, { stamp, project });\n if (project) tally.found += 1;\n put(project, id);\n });\n if (!more || tally.found >= MIN_FILL) break;\n }\n if (stale()) return;\n if (mode === 'reset') {\n // A chat no longer in the first pages (deleted, moved) drops off the list.\n setProjects((prev) =>\n prev.filter((p) => seen.has(p.channelId) || p.updatedAt > Date.now() - 60_000),\n );\n }\n setHasMore(more);\n } catch (err) {\n console.warn('[WebBuilderNative] could not load projects:', err);\n if (!stale()) setError('Check your connection and try again.');\n } finally {\n busyRef.current = false;\n if (!stale()) {\n setLoading(false);\n setLoadingMore(false);\n }\n }\n },\n // `projects.length` only steers the first spinner; reading it stale is harmless.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, orgName, projectFor],\n );\n\n useEffect(() => {\n load('reset').catch(() => undefined);\n }, [load]);\n\n const refresh = useCallback(() => {\n busyRef.current = false;\n load('reset').catch(() => undefined);\n }, [load]);\n const loadMore = useCallback(() => {\n if (hasMore) load('more').catch(() => undefined);\n }, [hasMore, load]);\n\n const upsert = useCallback((project: WebBuilderProject) => {\n setProjects((prev) => {\n const existing = prev.find((p) => p.channelId === project.channelId);\n if (\n existing &&\n existing.title === project.title &&\n existing.coverUrl === project.coverUrl &&\n existing.liveUrl === project.liveUrl &&\n existing.updatedAt === project.updatedAt\n ) {\n return prev;\n }\n return sortProjects([project, ...prev.filter((p) => p.channelId !== project.channelId)]);\n });\n }, []);\n\n return { projects, loading, loadingMore, hasMore, error, refresh, loadMore, upsert };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {useRef,useState,useMemo,useEffect,useCallback}from'react';import {useAiCodeDeployToCloudflareMutation}from'common/graphql';import {v4}from'uuid';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useHostChatChannel}from'../../hooks/useHostChatChannel.js';import {config}from'../../config/env-config.js';import {useChatMessages}from'../../hooks/useChatApi.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {useCanvasSession}from'../../features/canvas/useCanvasSession.js';import {tokenClaims}from'../../features/canvas/sessionIdentity.js';import {buildsFromPosts,hasWorkflowPosts,projectFromPosts,turnState,pendingWork,transcriptFromPosts,stripAgentNote,displayAgentText}from'../../features/webbuilder/buildFragments.js';import {WEBBUILDER_CHAT_SKILL,buildTriggerParams,templateRemixNote,newObjectId}from'../../features/webbuilder/workflow.js';import {useWebBuilderGallery}from'./useWebBuilderGallery.js';import {agentEditNote,agentPublishMessage}from'../../features/webbuilder/webbuilderPrompts.js';import {useCodeAssistantCatalog}from'./useCodeAssistantCatalog.js';import {uploadAttachment,triggerBuild,createSandboxRouter,directSandboxRun,restoreSandbox}from'./webbuilderTransport.js';import {useSandboxProxyApi}from'./sandboxProxyApi.js';import {useRestoredSandboxes,applyRestored}from'./useRestoredSandboxes.js';import {useWebBuilderJobs}from'./useWebBuilderJobs.js';var __defProp = Object.defineProperty;
|
|
1
|
+
import {useRef,useState,useMemo,useEffect,useCallback}from'react';import {useAiCodeDeployToCloudflareMutation}from'common/graphql';import {v4}from'uuid';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useHostChatChannel}from'../../hooks/useHostChatChannel.js';import {config}from'../../config/env-config.js';import {useChatMessages}from'../../hooks/useChatApi.js';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {useCanvasSession}from'../../features/canvas/useCanvasSession.js';import {tokenClaims}from'../../features/canvas/sessionIdentity.js';import {buildsFromPosts,hasWorkflowPosts,projectFromPosts,turnState,pendingWork,transcriptFromPosts,stripAgentNote,displayAgentText}from'../../features/webbuilder/buildFragments.js';import {WEBBUILDER_CHAT_SKILL,buildTriggerParams,templateRemixNote,newObjectId}from'../../features/webbuilder/workflow.js';import {useWebBuilderGallery}from'./useWebBuilderGallery.js';import {agentEditNote,agentPublishMessage}from'../../features/webbuilder/webbuilderPrompts.js';import {useCodeAssistantCatalog}from'./useCodeAssistantCatalog.js';import {uploadAttachment,triggerBuild,createSandboxRouter,directSandboxRun,restoreSandbox}from'./webbuilderTransport.js';import {useSandboxProxyApi}from'./sandboxProxyApi.js';import {useSandboxKeepAlive}from'./useSandboxKeepAlive.js';import {pendingAskUser}from'../../features/chat/askUser.js';import {useRunningBuilds,markBuildDone}from'./runningBuilds.js';import {undoLastChange,redoChange}from'./versionUndo.js';import {WEBBUILDER_EXPORT_ZIP_ACTION,exportZipParams,exportZipUrl}from'../../features/webbuilder/exportCode.js';import {useRestoredSandboxes,applyRestored}from'./useRestoredSandboxes.js';import {useWebBuilderJobs}from'./useWebBuilderJobs.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -29,7 +29,7 @@ function failureText(error) {
|
|
|
29
29
|
return "The build didn't start. Try again.";
|
|
30
30
|
}
|
|
31
31
|
function useWebBuilderHost(routeOrg) {
|
|
32
|
-
var _a, _b, _c, _d;
|
|
32
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
33
33
|
const {
|
|
34
34
|
orgName,
|
|
35
35
|
projectId: appProjectId
|
|
@@ -95,7 +95,7 @@ function useWebBuilderHost(routeOrg) {
|
|
|
95
95
|
const chat = useChatStream(agentChannelId, chatRouting);
|
|
96
96
|
const agentLane = activeChannelId !== null && (agentChannels.current.has(activeChannelId) || posts.length > 0 && !hasWorkflowPosts(posts));
|
|
97
97
|
const agentBusy = agentLane && (chat.isLoading || chat.isStreaming);
|
|
98
|
-
const jobs = useWebBuilderJobs();
|
|
98
|
+
const jobs = useWebBuilderJobs(effectiveOrg);
|
|
99
99
|
const agentJob = useRef(null);
|
|
100
100
|
const sendAgentTurn = useCallback((channelId, text, files, task) => {
|
|
101
101
|
const ready = unsavedAgentChannels.current.has(channelId) ? ensureChannel() : Promise.resolve();
|
|
@@ -246,7 +246,7 @@ function useWebBuilderHost(routeOrg) {
|
|
|
246
246
|
return () => clearInterval(timer);
|
|
247
247
|
}, [turn, refetch, jobs]);
|
|
248
248
|
const runTurn = useCallback(async (opts) => {
|
|
249
|
-
var _a2, _b2, _c2, _d2,
|
|
249
|
+
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
250
250
|
const {
|
|
251
251
|
current
|
|
252
252
|
} = tokenRef;
|
|
@@ -290,7 +290,7 @@ function useWebBuilderHost(routeOrg) {
|
|
|
290
290
|
channelId: opts.channelId,
|
|
291
291
|
projectId: opts.projectId,
|
|
292
292
|
ask: opts.text,
|
|
293
|
-
siteTitle: (
|
|
293
|
+
siteTitle: (_e2 = (_d2 = opts.edit) == null ? void 0 : _d2.title) != null ? _e2 : null,
|
|
294
294
|
mode,
|
|
295
295
|
lane: "workflow",
|
|
296
296
|
startedAt: startedAt2
|
|
@@ -304,7 +304,7 @@ function useWebBuilderHost(routeOrg) {
|
|
|
304
304
|
});
|
|
305
305
|
const outcome = await triggerBuild(current, indexUrl, built.params);
|
|
306
306
|
if (!outcome.ok) {
|
|
307
|
-
const reason = (
|
|
307
|
+
const reason = (_f2 = outcome.error) != null ? _f2 : "";
|
|
308
308
|
console.warn("[WebBuilderNative] trigger failed:", reason);
|
|
309
309
|
if (outcome.auth) session.retry();
|
|
310
310
|
setTurn(null);
|
|
@@ -373,11 +373,50 @@ ${templateRemixNote(request.template)}` : request.text,
|
|
|
373
373
|
const running = Boolean(turn && turn.channelId === activeChannelId);
|
|
374
374
|
const startedAt = (_c = turn == null ? void 0 : turn.startedAt) != null ? _c : 0;
|
|
375
375
|
const progress = (_d = state == null ? void 0 : state.progress) != null ? _d : null;
|
|
376
|
+
const runningBuilds = useRunningBuilds();
|
|
377
|
+
const openRun = (_e = runningBuilds.find((r) => r.channelId === activeChannelId)) != null ? _e : null;
|
|
378
|
+
const openRunState = useMemo(() => openRun && posts.length ? turnState(posts, openRun.startedAt) : null, [openRun, posts]);
|
|
379
|
+
const watchingLive = agentBusy || running;
|
|
380
|
+
useEffect(() => {
|
|
381
|
+
if (!openRun || !openRunState || watchingLive || openRunState.status === "running") return;
|
|
382
|
+
markBuildDone(openRun.channelId, openRun.startedAt);
|
|
383
|
+
}, [openRun, openRunState, watchingLive]);
|
|
384
|
+
const openRunPending = openRun !== null && !watchingLive && (!openRunState || openRunState.status === "running");
|
|
385
|
+
useEffect(() => {
|
|
386
|
+
if (!openRun || watchingLive) return void 0;
|
|
387
|
+
const timer = setInterval(() => refetch().catch(() => void 0), POLL_MS);
|
|
388
|
+
return () => clearInterval(timer);
|
|
389
|
+
}, [openRun, watchingLive, refetch]);
|
|
390
|
+
const shownProjects = useMemo(() => {
|
|
391
|
+
const runs = runningBuilds.filter((r) => !r.org || !effectiveOrg || r.org === effectiveOrg);
|
|
392
|
+
if (!runs.length) return projects;
|
|
393
|
+
const ids = new Set(runs.map((r) => r.channelId));
|
|
394
|
+
const rows = projects.map((p) => ids.has(p.channelId) ? __spreadProps(__spreadValues({}, p), {
|
|
395
|
+
building: true
|
|
396
|
+
}) : p);
|
|
397
|
+
for (const run of runs) {
|
|
398
|
+
if (!projects.some((p) => p.channelId === run.channelId)) {
|
|
399
|
+
rows.push({
|
|
400
|
+
channelId: run.channelId,
|
|
401
|
+
title: run.title,
|
|
402
|
+
updatedAt: run.startedAt,
|
|
403
|
+
building: true
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return rows.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
408
|
+
}, [projects, runningBuilds, effectiveOrg]);
|
|
376
409
|
const building = useMemo(() => {
|
|
377
410
|
if (agentBusy) return {
|
|
378
411
|
statusText: "Building with the agent\u2026",
|
|
379
412
|
startedAt: startedAt || Date.now()
|
|
380
413
|
};
|
|
414
|
+
if (!running && work !== "creating" && openRun && openRunPending) {
|
|
415
|
+
return {
|
|
416
|
+
statusText: (openRunState == null ? void 0 : openRunState.progress) || "Building your site\u2026",
|
|
417
|
+
startedAt: openRun.startedAt
|
|
418
|
+
};
|
|
419
|
+
}
|
|
381
420
|
if (!running && work !== "creating") return null;
|
|
382
421
|
let fallback = "Starting your build\u2026";
|
|
383
422
|
if ((turn == null ? void 0 : turn.mode) === "edit") fallback = "Updating your app\u2026";
|
|
@@ -386,13 +425,13 @@ ${templateRemixNote(request.template)}` : request.text,
|
|
|
386
425
|
statusText: progress || fallback,
|
|
387
426
|
startedAt: startedAt || Date.now()
|
|
388
427
|
};
|
|
389
|
-
}, [agentBusy, running, work, turn == null ? void 0 : turn.mode, progress, startedAt]);
|
|
428
|
+
}, [agentBusy, running, work, turn == null ? void 0 : turn.mode, progress, startedAt, openRun, openRunState, openRunPending]);
|
|
390
429
|
const messages = useMemo(() => {
|
|
391
430
|
const rows = transcriptFromPosts(posts).map((m) => ({
|
|
392
431
|
id: m.id,
|
|
393
432
|
role: m.role,
|
|
394
433
|
content: m.role === "user" ? stripAgentNote(m.content) : displayAgentText(m.content)
|
|
395
|
-
}));
|
|
434
|
+
})).filter((m) => m.role === "user" || m.content.trim());
|
|
396
435
|
const pending = running && (turn == null ? void 0 : turn.text) ? turn.text.replace(/^build\s*me\s*:\s*/i, "") : "";
|
|
397
436
|
if (pending && !rows.some((m) => m.role === "user" && pending.startsWith(m.content))) {
|
|
398
437
|
rows.push({
|
|
@@ -449,42 +488,73 @@ ${agentEditNote(target)}` : "";
|
|
|
449
488
|
// The template note is for the agent; the person sees what they typed.
|
|
450
489
|
content: m.role === "user" ? stripAgentNote(m.content).replace(/^build\s*me\s*:\s*/i, "") : displayAgentText(m.content),
|
|
451
490
|
attachments: m.attachments
|
|
452
|
-
})), [chat.messages]);
|
|
491
|
+
})).filter((m) => m.role === "user" || m.content.trim()), [chat.messages]);
|
|
492
|
+
const withOpenRun = useCallback((rows) => {
|
|
493
|
+
if (!openRunPending || !(openRun == null ? void 0 : openRun.ask)) return rows;
|
|
494
|
+
const {
|
|
495
|
+
ask
|
|
496
|
+
} = openRun;
|
|
497
|
+
if (rows.some((m) => m.role === "user" && (m.content.startsWith(ask) || ask.startsWith(m.content)))) {
|
|
498
|
+
return rows;
|
|
499
|
+
}
|
|
500
|
+
return [...rows, {
|
|
501
|
+
id: `run-${openRun.startedAt}`,
|
|
502
|
+
role: "user",
|
|
503
|
+
content: ask
|
|
504
|
+
}];
|
|
505
|
+
}, [openRunPending, openRun]);
|
|
506
|
+
const openRunStreaming = openRunPending ? (openRunState == null ? void 0 : openRunState.progress) || "Building your site\u2026" : null;
|
|
507
|
+
const pendingAsk = useMemo(() => pendingAskUser(agentLane && chat.messages.length ? chat.messages : transcriptFromPosts(posts).map((m) => ({
|
|
508
|
+
role: m.role,
|
|
509
|
+
content: m.content
|
|
510
|
+
}))), [agentLane, chat.messages, posts]);
|
|
453
511
|
const hostChat = useMemo(() => agentLane ? {
|
|
454
|
-
messages: agentMessages,
|
|
455
|
-
streaming: chat.response ? displayAgentText(chat.response) :
|
|
456
|
-
busy: agentBusy,
|
|
512
|
+
messages: withOpenRun(agentMessages.length ? agentMessages : messages),
|
|
513
|
+
streaming: chat.response ? displayAgentText(chat.response) : openRunStreaming,
|
|
514
|
+
busy: agentBusy || openRunPending,
|
|
457
515
|
error: chat.error,
|
|
458
516
|
connected: cdecli.channelConnected,
|
|
517
|
+
ask: pendingAsk,
|
|
459
518
|
send
|
|
460
519
|
} : {
|
|
461
|
-
messages,
|
|
462
|
-
streaming: running ? progress || (building == null ? void 0 : building.statusText) || "Working on it\u2026" :
|
|
463
|
-
busy: running,
|
|
520
|
+
messages: withOpenRun(messages),
|
|
521
|
+
streaming: running ? progress || (building == null ? void 0 : building.statusText) || "Working on it\u2026" : openRunStreaming,
|
|
522
|
+
busy: running || openRunPending,
|
|
464
523
|
error: turnError || (session.ready ? session.error : null),
|
|
465
524
|
connected: Boolean(token),
|
|
525
|
+
ask: pendingAsk,
|
|
466
526
|
send
|
|
467
|
-
}, [agentLane, agentMessages, chat.response, agentBusy, chat.error, cdecli.channelConnected, messages, running, progress, building == null ? void 0 : building.statusText, turnError, session.ready, session.error, token, send]);
|
|
527
|
+
}, [agentLane, agentMessages, pendingAsk, withOpenRun, openRunStreaming, openRunPending, chat.response, agentBusy, chat.error, cdecli.channelConnected, messages, running, progress, building == null ? void 0 : building.statusText, turnError, session.ready, session.error, token, send]);
|
|
468
528
|
const sandboxApi = useSandboxProxyApi();
|
|
529
|
+
const sandboxCall = useMemo(() => createSandboxRouter({
|
|
530
|
+
channelId: activeChannelId,
|
|
531
|
+
proxy: sandboxApi.proxy,
|
|
532
|
+
direct: token && indexUrl ? directSandboxRun(token, indexUrl) : async () => ({
|
|
533
|
+
successful: false,
|
|
534
|
+
error: "Not signed in to the build service."
|
|
535
|
+
}),
|
|
536
|
+
proxyMissing: sandboxApi.proxyMissing
|
|
537
|
+
}), [activeChannelId, token, indexUrl, sandboxApi]);
|
|
538
|
+
const keepAlive = useSandboxKeepAlive({
|
|
539
|
+
run: token || activeChannelId ? sandboxCall : null,
|
|
540
|
+
sandboxId: (_f = builds[0]) == null ? void 0 : _f.sandboxId,
|
|
541
|
+
live: activeChannelId !== null && Boolean((_g = builds[0]) == null ? void 0 : _g.sandboxId)
|
|
542
|
+
});
|
|
543
|
+
const {
|
|
544
|
+
noteActivity
|
|
545
|
+
} = keepAlive;
|
|
546
|
+
useEffect(() => {
|
|
547
|
+
if (activeChannelId) noteActivity();
|
|
548
|
+
}, [activeChannelId, posts.length, chat.messages.length, noteActivity]);
|
|
469
549
|
const resumePreview = useCallback(async (build) => {
|
|
470
|
-
const {
|
|
471
|
-
current
|
|
472
|
-
} = tokenRef;
|
|
473
550
|
const channelId = activeChannelId;
|
|
474
|
-
if (!build.sandboxId || !current && !channelId) return "failed";
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
proxy: sandboxApi.proxy,
|
|
478
|
-
direct: current && indexUrl ? directSandboxRun(current, indexUrl) : async () => ({
|
|
479
|
-
successful: false,
|
|
480
|
-
error: "Not signed in to the build service."
|
|
481
|
-
}),
|
|
482
|
-
proxyMissing: sandboxApi.proxyMissing
|
|
483
|
-
});
|
|
484
|
-
const result = await restoreSandbox(call, {
|
|
551
|
+
if (!build.sandboxId || !tokenRef.current && !channelId) return "failed";
|
|
552
|
+
noteActivity();
|
|
553
|
+
const result = await restoreSandbox(sandboxCall, {
|
|
485
554
|
sandboxId: build.sandboxId,
|
|
486
555
|
snapshotId: build.snapshotId,
|
|
487
|
-
templateId: build.templateId
|
|
556
|
+
templateId: build.templateId,
|
|
557
|
+
previewUrl: build.previewUrl
|
|
488
558
|
});
|
|
489
559
|
if (result.outcome === "ok" && result.sandboxId && result.previewUrl) {
|
|
490
560
|
rememberRestored(build.key, result.sandboxId, result.previewUrl);
|
|
@@ -506,7 +576,43 @@ ${agentEditNote(target)}` : "";
|
|
|
506
576
|
}
|
|
507
577
|
}
|
|
508
578
|
return result.outcome;
|
|
509
|
-
}, [activeChannelId,
|
|
579
|
+
}, [activeChannelId, sandboxCall, noteActivity, sandboxApi, rememberRestored, activeProject, upsertProject]);
|
|
580
|
+
const redoFor = useRef(/* @__PURE__ */ new Map());
|
|
581
|
+
const undo = useCallback(async (build) => {
|
|
582
|
+
if (!build.sandboxId) return {
|
|
583
|
+
ok: false,
|
|
584
|
+
message: "There is nothing to undo yet."
|
|
585
|
+
};
|
|
586
|
+
noteActivity();
|
|
587
|
+
const outcome = await undoLastChange(sandboxCall, build.sandboxId);
|
|
588
|
+
if (outcome.redo) redoFor.current.set(build.key, outcome.redo);
|
|
589
|
+
else redoFor.current.delete(build.key);
|
|
590
|
+
return {
|
|
591
|
+
ok: outcome.ok,
|
|
592
|
+
message: outcome.message,
|
|
593
|
+
canRedo: Boolean(outcome.redo),
|
|
594
|
+
askAgent: Boolean(outcome.listFailed) && build.origin === "agent"
|
|
595
|
+
};
|
|
596
|
+
}, [sandboxCall, noteActivity]);
|
|
597
|
+
const redo = useCallback(async (build) => {
|
|
598
|
+
const version = redoFor.current.get(build.key);
|
|
599
|
+
if (!build.sandboxId || !version) return {
|
|
600
|
+
ok: false,
|
|
601
|
+
message: "There is nothing to redo."
|
|
602
|
+
};
|
|
603
|
+
const outcome = await redoChange(sandboxCall, build.sandboxId, version);
|
|
604
|
+
if (outcome.ok) redoFor.current.delete(build.key);
|
|
605
|
+
return {
|
|
606
|
+
ok: outcome.ok,
|
|
607
|
+
message: outcome.message
|
|
608
|
+
};
|
|
609
|
+
}, [sandboxCall]);
|
|
610
|
+
const downloadCode = useCallback(async (build) => {
|
|
611
|
+
if (!build.sandboxId) return null;
|
|
612
|
+
noteActivity();
|
|
613
|
+
const result = await sandboxCall(WEBBUILDER_EXPORT_ZIP_ACTION, exportZipParams(build.sandboxId, build.title), 10 * 60 * 1e3).catch(() => null);
|
|
614
|
+
return exportZipUrl(result);
|
|
615
|
+
}, [sandboxCall, noteActivity]);
|
|
510
616
|
const [deployToCloudflare] = useAiCodeDeployToCloudflareMutation({});
|
|
511
617
|
const publish = useCallback(async (build, projectName) => {
|
|
512
618
|
var _a2;
|
|
@@ -552,7 +658,7 @@ ${agentEditNote(target)}` : "";
|
|
|
552
658
|
startBlocked = session.ready && session.error ? session.error : "Connecting to Web Builder\u2026";
|
|
553
659
|
}
|
|
554
660
|
return {
|
|
555
|
-
projects,
|
|
661
|
+
projects: shownProjects,
|
|
556
662
|
projectsLoading: gallery.loading,
|
|
557
663
|
projectsError: gallery.error,
|
|
558
664
|
projectsHasMore: gallery.hasMore,
|
|
@@ -574,6 +680,9 @@ ${agentEditNote(target)}` : "";
|
|
|
574
680
|
publishing: work === "publishing",
|
|
575
681
|
hostChat,
|
|
576
682
|
publish,
|
|
577
|
-
resumePreview
|
|
683
|
+
resumePreview,
|
|
684
|
+
undo,
|
|
685
|
+
redo,
|
|
686
|
+
downloadCode
|
|
578
687
|
};
|
|
579
688
|
}export{useWebBuilderHost};//# sourceMappingURL=useWebBuilderHost.js.map
|