@messenger-box/tailwind-ui-inbox 10.0.3-alpha.122 → 10.0.3-alpha.124
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/CHANGELOG.md +8 -0
- package/lib/components/AIAgent/AIAgent.d.ts +2 -0
- package/lib/components/AIAgent/AIAgent.d.ts.map +1 -1
- package/lib/components/AIAgent/AIAgent.js +42 -26
- package/lib/components/AIAgent/AIAgent.js.map +1 -1
- package/lib/components/InboxMessage/InputComponent.d.ts +4 -1
- package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -1
- package/lib/components/InboxMessage/InputComponent.js +20 -304
- package/lib/components/InboxMessage/InputComponent.js.map +1 -1
- package/lib/components/InboxMessage/UploadImageButton.js +2 -6
- package/lib/components/InboxMessage/UploadImageButton.js.map +1 -1
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts +1 -0
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.d.ts.map +1 -1
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js +15 -5
- package/lib/components/InboxMessage/message-widgets/ModernMessageGroup.js.map +1 -1
- package/lib/components/ModelConfigPanel.d.ts +10 -0
- package/lib/components/ModelConfigPanel.d.ts.map +1 -1
- package/lib/components/ModelConfigPanel.js +551 -2
- package/lib/components/ModelConfigPanel.js.map +1 -1
- package/lib/components/filler-components/RightSiderBar.d.ts +1 -0
- package/lib/components/filler-components/RightSiderBar.d.ts.map +1 -1
- package/lib/components/filler-components/RightSiderBar.js +174 -140
- package/lib/components/filler-components/RightSiderBar.js.map +1 -1
- package/lib/components/slot-fill/right-sidebar-filler.d.ts.map +1 -1
- package/lib/components/slot-fill/right-sidebar-filler.js.map +1 -1
- package/lib/config/env-config.d.ts +2 -0
- package/lib/config/env-config.d.ts.map +1 -1
- package/lib/config/env-config.js +7 -1
- package/lib/config/env-config.js.map +1 -1
- package/lib/container/AiLandingInput.d.ts.map +1 -1
- package/lib/container/AiLandingInput.js +11 -9
- package/lib/container/AiLandingInput.js.map +1 -1
- package/lib/container/Inbox.js +1 -1
- package/lib/container/Inbox.js.map +1 -1
- package/lib/container/InboxAiMessagesLoader.d.ts +1 -0
- package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -1
- package/lib/container/InboxAiMessagesLoader.js +4 -1
- package/lib/container/InboxAiMessagesLoader.js.map +1 -1
- package/lib/container/InboxContainer.d.ts +1 -0
- package/lib/container/InboxContainer.d.ts.map +1 -1
- package/lib/container/InboxContainer.js +1 -6
- package/lib/container/InboxContainer.js.map +1 -1
- package/lib/container/InboxWithAiLoader.d.ts +2 -0
- package/lib/container/InboxWithAiLoader.d.ts.map +1 -1
- package/lib/container/InboxWithAiLoader.js +8 -3
- package/lib/container/InboxWithAiLoader.js.map +1 -1
- package/lib/container/ServiceInbox.js +1 -1
- package/lib/container/ServiceInbox.js.map +1 -1
- package/lib/container/ThreadMessages.js +1 -1
- package/lib/container/ThreadMessages.js.map +1 -1
- package/lib/container/ThreadMessagesInbox.js +1 -1
- package/lib/container/ThreadMessagesInbox.js.map +1 -1
- package/lib/container/Threads.js +1 -1
- package/lib/container/Threads.js.map +1 -1
- package/lib/module.js +1 -1
- package/lib/module.js.map +1 -1
- package/lib/templates/InboxWithAi.d.ts +1 -0
- package/lib/templates/InboxWithAi.d.ts.map +1 -1
- package/lib/templates/InboxWithAi.js +9 -6
- package/lib/templates/InboxWithAi.js.map +1 -1
- package/lib/templates/InboxWithAi.tsx +7 -3
- package/lib/xstate/index.d.ts +3 -0
- package/lib/xstate/index.d.ts.map +1 -0
- package/lib/xstate/rightSidebar.machine.d.ts +4 -0
- package/lib/xstate/rightSidebar.machine.d.ts.map +1 -0
- package/lib/xstate/rightSidebar.machine.js +174 -0
- package/lib/xstate/rightSidebar.machine.js.map +1 -0
- package/lib/xstate/rightSidebar.types.d.ts +52 -0
- package/lib/xstate/rightSidebar.types.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/components/AIAgent/AIAgent.tsx +35 -21
- package/src/components/InboxMessage/InputComponent.tsx +23 -375
- package/src/components/InboxMessage/UploadImageButton.tsx +4 -4
- package/src/components/InboxMessage/message-widgets/ModernMessageGroup.tsx +17 -0
- package/src/components/ModelConfigPanel.tsx +666 -0
- package/src/components/filler-components/RightSiderBar.tsx +189 -150
- package/src/components/slot-fill/right-sidebar-filler.tsx +1 -0
- package/src/config/env-config.ts +3 -1
- package/src/container/AiLandingInput.tsx +11 -111
- package/src/container/InboxAiMessagesLoader.tsx +13 -2
- package/src/container/InboxContainer.tsx +2 -8
- package/src/container/InboxWithAiLoader.tsx +8 -2
- package/src/templates/InboxWithAi.tsx +7 -3
- package/src/xstate/index.ts +2 -0
- package/src/xstate/rightSidebar.machine.ts +139 -0
- package/src/xstate/rightSidebar.types.ts +55 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { HybridLiveEditor, HybridLiveEditorRef } from '../live-code-editor/hybrid-live-editor';
|
|
3
3
|
import { useOnChatMessageAddedSubscription } from 'common/graphql';
|
|
4
|
-
import { ICreateChannelInput } from 'common';
|
|
4
|
+
import { AiAgentMessageRole, ICreateChannelInput, PostTypeEnum, RoomType } from 'common';
|
|
5
|
+
import { Sandbox } from '@e2b/code-interpreter';
|
|
6
|
+
import { useMachine } from '@xstate/react';
|
|
7
|
+
import { fromPromise } from 'xstate';
|
|
8
|
+
import { rightSidebarMachine } from '../../xstate';
|
|
5
9
|
|
|
6
10
|
type RightSidebarProps = {
|
|
7
11
|
channelId: string;
|
|
@@ -22,6 +26,7 @@ type RightSidebarProps = {
|
|
|
22
26
|
setIsLoading?: (isLoading: boolean) => void;
|
|
23
27
|
handleSendMessage?: (createChannelInput: ICreateChannelInput) => void;
|
|
24
28
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
29
|
+
isMinimized?: boolean;
|
|
25
30
|
isLoading?: boolean;
|
|
26
31
|
[key: string]: any;
|
|
27
32
|
};
|
|
@@ -39,32 +44,49 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
39
44
|
isLoading,
|
|
40
45
|
handleSendMessage,
|
|
41
46
|
handleRecreateSandbox,
|
|
47
|
+
isMinimized,
|
|
42
48
|
} = props;
|
|
43
|
-
|
|
44
49
|
const hybridLiveEditorRef = React.useRef<HybridLiveEditorRef>(null);
|
|
45
50
|
const previewIframeRef = React.useRef<HTMLIFrameElement>(null);
|
|
46
|
-
|
|
47
|
-
// State for subscription data
|
|
51
|
+
const previewIframeContainerRef = React.useRef<HTMLIFrameElement>(null);
|
|
52
|
+
// State for subscription data
|
|
48
53
|
const [subscriptionData, setSubscriptionData] = React.useState<any>(null);
|
|
49
|
-
|
|
50
|
-
const [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
// XState machine for sidebar state
|
|
55
|
+
const [state, send] = useMachine(
|
|
56
|
+
rightSidebarMachine.provide({
|
|
57
|
+
actors: {
|
|
58
|
+
recreateSandbox: fromPromise(async ({ input }) => {
|
|
59
|
+
const { id } = input as { id: string };
|
|
60
|
+
if (handleRecreateSandbox) {
|
|
61
|
+
await handleRecreateSandbox(id);
|
|
62
|
+
}
|
|
63
|
+
return { success: true } as const;
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
{
|
|
68
|
+
input: {
|
|
69
|
+
channelId: channelId || '',
|
|
70
|
+
isMinimized: !!isMinimized,
|
|
71
|
+
windowWidth,
|
|
72
|
+
windowHeight,
|
|
73
|
+
isLoading: !!isLoading,
|
|
74
|
+
activeFragment: null,
|
|
75
|
+
currentFiles: {},
|
|
76
|
+
canvasLayers: [],
|
|
77
|
+
previewStatus: null,
|
|
78
|
+
},
|
|
65
79
|
},
|
|
66
|
-
[setIsLoading],
|
|
67
80
|
);
|
|
81
|
+
const activeFragment = state.context.activeFragment;
|
|
82
|
+
const currentFiles = state.context.currentFiles;
|
|
83
|
+
const canvasLayers = state.context.canvasLayers as any[];
|
|
84
|
+
const previewStatus = state.context.previewStatus as { code?: number; message?: string; status?: string } | null;
|
|
85
|
+
// const [isLoading, setIsLoading] = React.useState(false);
|
|
86
|
+
const { data: chatMessageAddedData } = useOnChatMessageAddedSubscription({
|
|
87
|
+
variables: { channelId: channelId?.toString() || '' },
|
|
88
|
+
skip: !channelId,
|
|
89
|
+
});
|
|
68
90
|
|
|
69
91
|
// Component mount tracking
|
|
70
92
|
const componentId = React.useMemo(
|
|
@@ -131,27 +153,20 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
131
153
|
// Determine if we should show preview or editor based on activeTab
|
|
132
154
|
const isPreviewMode = activeTab === 'preview';
|
|
133
155
|
|
|
134
|
-
const { data: chatMessageAddedData } = useOnChatMessageAddedSubscription({
|
|
135
|
-
variables: { channelId: channelId?.toString() || '' },
|
|
136
|
-
skip: !channelId,
|
|
137
|
-
});
|
|
138
|
-
|
|
139
156
|
// Turn on loader when new data is about to be processed
|
|
140
157
|
React.useEffect(() => {
|
|
141
158
|
if (chatMessageAddedData?.chatMessageAdded || selectedPost) {
|
|
142
|
-
//
|
|
159
|
+
// sync external loader
|
|
160
|
+
// setIsLoading?.(false);
|
|
161
|
+
// send({ type: 'SET_LOADING', isLoading: false });
|
|
143
162
|
}
|
|
144
|
-
}, [chatMessageAddedData, selectedPost]);
|
|
163
|
+
}, [chatMessageAddedData, selectedPost, send, setIsLoading]);
|
|
145
164
|
|
|
146
165
|
// Handle subscription data updates - prefer response update structure like use-ai-messages.ts
|
|
147
166
|
React.useEffect(() => {
|
|
148
167
|
if (chatMessageAddedData?.chatMessageAdded || selectedPost) {
|
|
149
168
|
// Prefer explicitly selected post to ensure UI updates when it changes
|
|
150
169
|
const message = selectedPost || chatMessageAddedData?.chatMessageAdded;
|
|
151
|
-
// console.log('=== SUBSCRIPTION MESSAGE DEBUG ===');
|
|
152
|
-
// console.log('Full message:', JSON.stringify(message, null, 2));
|
|
153
|
-
// console.log('Message props:', message.props);
|
|
154
|
-
// console.log('Message propsConfiguration:', message.propsConfiguration);
|
|
155
170
|
|
|
156
171
|
// Extract strictly from message.propsConfiguration (fragment only)
|
|
157
172
|
let extracted: any = null;
|
|
@@ -178,7 +193,6 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
178
193
|
summary: contents.summary || cfg.summary || frag.summary,
|
|
179
194
|
title: frag.title || contents.title || cfg.title,
|
|
180
195
|
isError: frag.isError,
|
|
181
|
-
syncStatus: frag.syncStatus,
|
|
182
196
|
};
|
|
183
197
|
fragmentSource = 'propsConfiguration.contents.props.fragment';
|
|
184
198
|
}
|
|
@@ -196,7 +210,6 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
196
210
|
summary: contents.summary || cfg.summary || frag.summary,
|
|
197
211
|
title: frag.title || contents.title || cfg.title,
|
|
198
212
|
isError: frag.isError,
|
|
199
|
-
syncStatus: frag.syncStatus,
|
|
200
213
|
};
|
|
201
214
|
fragmentSource = 'propsConfiguration.contents.fragment';
|
|
202
215
|
}
|
|
@@ -214,7 +227,6 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
214
227
|
summary: cfg.summary || frag.summary,
|
|
215
228
|
title: frag.title || cfg.title,
|
|
216
229
|
isError: frag.isError,
|
|
217
|
-
syncStatus: frag.syncStatus,
|
|
218
230
|
};
|
|
219
231
|
fragmentSource = 'propsConfiguration.fragment';
|
|
220
232
|
}
|
|
@@ -235,6 +247,7 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
235
247
|
const fragment = {
|
|
236
248
|
id: message.id,
|
|
237
249
|
sandboxUrl: extracted.sandboxUrl || extracted.url,
|
|
250
|
+
sandboxId: extracted.sandboxId,
|
|
238
251
|
title: extracted.title || 'Generated Code',
|
|
239
252
|
files: extracted.files || {},
|
|
240
253
|
projectId: extracted.projectId,
|
|
@@ -242,7 +255,6 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
242
255
|
canvasLayers: extracted.canvasLayers,
|
|
243
256
|
summary: extracted.summary,
|
|
244
257
|
isError: extracted.isError,
|
|
245
|
-
syncStatus: extracted.syncStatus,
|
|
246
258
|
};
|
|
247
259
|
|
|
248
260
|
// If canvasLayers missing but present in summary, attempt to extract like use-ai-messages
|
|
@@ -260,69 +272,17 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
260
272
|
}
|
|
261
273
|
}
|
|
262
274
|
|
|
263
|
-
console.log('✅ Setting active fragment:', fragment);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
//
|
|
267
|
-
if (fragment.files) {
|
|
268
|
-
console.log('✅ Setting current files:', Object.keys(fragment.files));
|
|
269
|
-
setCurrentFiles(fragment.files);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Update canvas layers if available
|
|
273
|
-
if (fragment.canvasLayers && Array.isArray(fragment.canvasLayers)) {
|
|
274
|
-
console.log('Received canvas layers from AI:', fragment.canvasLayers);
|
|
275
|
-
setCanvasLayers(fragment.canvasLayers);
|
|
276
|
-
} else {
|
|
277
|
-
console.log('No canvas layers found in response');
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// setIsLoading(false);
|
|
275
|
+
console.log('✅ Setting active fragment via XState:', fragment);
|
|
276
|
+
send({ type: 'SET_FRAGMENT', fragment });
|
|
277
|
+
// setIsLoading?.(false);
|
|
278
|
+
//send({ type: 'SET_LOADING', isLoading: false });
|
|
281
279
|
} else {
|
|
282
280
|
console.log('❌ No valid response found in message');
|
|
283
|
-
//
|
|
281
|
+
// setIsLoading?.(false);
|
|
282
|
+
// send({ type: 'SET_LOADING', isLoading: false });
|
|
284
283
|
}
|
|
285
284
|
}
|
|
286
|
-
}, [chatMessageAddedData, selectedPost]);
|
|
287
|
-
|
|
288
|
-
// Probe sandbox URL to detect server-side errors (e.g., 502) before rendering iframe
|
|
289
|
-
React.useEffect(() => {
|
|
290
|
-
const url = activeFragment?.sandboxUrl;
|
|
291
|
-
setPreviewStatus(null);
|
|
292
|
-
if (!url) return;
|
|
293
|
-
|
|
294
|
-
const controller = new AbortController();
|
|
295
|
-
const signal = controller.signal;
|
|
296
|
-
const run = async () => {
|
|
297
|
-
try {
|
|
298
|
-
//setLoading(true);
|
|
299
|
-
// timeout to avoid indefinite loading
|
|
300
|
-
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
301
|
-
const res = await fetch(url, {
|
|
302
|
-
method: 'GET',
|
|
303
|
-
mode: 'cors',
|
|
304
|
-
redirect: 'follow',
|
|
305
|
-
signal,
|
|
306
|
-
});
|
|
307
|
-
clearTimeout(timeoutId);
|
|
308
|
-
console.log('res....', res);
|
|
309
|
-
if (!res.ok) {
|
|
310
|
-
setPreviewStatus({ code: res.status, message: res.statusText });
|
|
311
|
-
if (!sanboxRecreate) setSanboxRecreate(true);
|
|
312
|
-
} else {
|
|
313
|
-
setPreviewStatus(null);
|
|
314
|
-
}
|
|
315
|
-
} catch (e: any) {
|
|
316
|
-
// Network/CORS errors will end up here
|
|
317
|
-
setPreviewStatus({ message: 'Network error' });
|
|
318
|
-
// if(!sanboxRecreate) setSanboxRecreate(true);
|
|
319
|
-
} finally {
|
|
320
|
-
setLoading(false);
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
run();
|
|
324
|
-
return () => controller.abort();
|
|
325
|
-
}, [activeFragment?.sandboxUrl, sanboxRecreate]);
|
|
285
|
+
}, [chatMessageAddedData, selectedPost, send, setIsLoading]);
|
|
326
286
|
|
|
327
287
|
// When switching tabs or when sandbox changes, show loader until ready
|
|
328
288
|
// React.useEffect(() => {
|
|
@@ -351,92 +311,158 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
351
311
|
};
|
|
352
312
|
}, []);
|
|
353
313
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
.
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
314
|
+
React.useEffect(() => {
|
|
315
|
+
const handleVisualEditorMessage = (event: MessageEvent) => {
|
|
316
|
+
// Handle AI changes
|
|
317
|
+
if (event.data.type === 'VISUAL_EDITOR_CHANGES') {
|
|
318
|
+
console.log('visual_editor_changes....', event.data.message);
|
|
319
|
+
|
|
320
|
+
if (handleSendMessage && event.data.message) {
|
|
321
|
+
// Call aiHandleSend directly - this is the handleSend function from AIAgent
|
|
322
|
+
handleSendMessage({
|
|
323
|
+
channelId,
|
|
324
|
+
type: RoomType.Aiassistant,
|
|
325
|
+
postData: {
|
|
326
|
+
// postId: postId,
|
|
327
|
+
type: PostTypeEnum.Aiassistant,
|
|
328
|
+
content: event.data.message,
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
} else {
|
|
332
|
+
console.warn('⚠️ handleSendMessage not available or no message provided');
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
window.addEventListener('message', handleVisualEditorMessage);
|
|
338
|
+
return () => window.removeEventListener('message', handleVisualEditorMessage);
|
|
339
|
+
}, [handleSendMessage, channelId]);
|
|
340
|
+
|
|
341
|
+
const recreateSandboxHandler = React.useCallback(
|
|
342
|
+
async (id: string) => {
|
|
343
|
+
if (id) {
|
|
344
|
+
console.log('recreate sandbox id....', id);
|
|
345
|
+
setIsLoading?.(true);
|
|
346
|
+
send({ type: 'SET_LOADING', isLoading: true });
|
|
347
|
+
try {
|
|
348
|
+
send({ type: 'RECREATE_SANDBOX', id });
|
|
349
|
+
} catch (e: any) {
|
|
350
|
+
console.error('Error recreating sandbox:', e);
|
|
351
|
+
setIsLoading?.(false);
|
|
352
|
+
send({ type: 'SET_LOADING', isLoading: false });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
[send, setIsLoading],
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
// Track if we've already attempted recreate for a given sandbox URL
|
|
360
|
+
const recreateAttemptedByUrlRef = React.useRef<Record<string, boolean>>({});
|
|
361
|
+
|
|
362
|
+
// Probe sandbox URL via XState actor
|
|
363
|
+
React.useEffect(() => {
|
|
364
|
+
const url = activeFragment?.sandboxUrl;
|
|
365
|
+
if (url) {
|
|
366
|
+
send({ type: 'PROBE', url, fragmentId: activeFragment?.id });
|
|
365
367
|
}
|
|
366
|
-
}, [activeFragment?.
|
|
368
|
+
}, [activeFragment?.sandboxUrl, activeFragment?.id, send]);
|
|
369
|
+
|
|
370
|
+
// Prefer using external loading when provided; otherwise fall back to machine state
|
|
371
|
+
const derivedIsLoading = (typeof isLoading === 'boolean' ? isLoading : state.context.isLoading) as boolean;
|
|
367
372
|
|
|
373
|
+
// Sync external loading prop with machine's loading state (no-op if setter not provided)
|
|
368
374
|
React.useEffect(() => {
|
|
369
|
-
|
|
370
|
-
|
|
375
|
+
console.log(
|
|
376
|
+
'isLoading....',
|
|
377
|
+
isLoading,
|
|
378
|
+
' state.context.isLoading',
|
|
379
|
+
state.context.isLoading,
|
|
380
|
+
' previewStatus',
|
|
381
|
+
previewStatus,
|
|
382
|
+
);
|
|
383
|
+
if (!state.context.isLoading) {
|
|
384
|
+
setIsLoading?.(!!state.context.isLoading);
|
|
371
385
|
}
|
|
372
|
-
}, [
|
|
386
|
+
}, [state.context.isLoading, setIsLoading, isLoading]);
|
|
373
387
|
|
|
374
388
|
return (
|
|
375
|
-
<div className="right-sidebar-content h-full flex flex-col">
|
|
376
|
-
<div className="flex-1 overflow-hidden" style={{
|
|
389
|
+
<div ref={previewIframeContainerRef} className="right-sidebar-content h-full flex flex-col">
|
|
390
|
+
<div className="flex-1 overflow-hidden" style={{ minHeight: windowHeight - 140 }}>
|
|
377
391
|
{isPreviewMode ? (
|
|
378
392
|
// Preview Mode - Show sandbox iframe or fallback
|
|
379
393
|
(() => {
|
|
380
394
|
if (activeFragment?.sandboxUrl) {
|
|
381
395
|
return (
|
|
382
396
|
<div
|
|
383
|
-
className="w-full h-full
|
|
397
|
+
className="w-full h-full relative"
|
|
384
398
|
style={{
|
|
385
|
-
|
|
399
|
+
width: isMinimized ? windowWidth * 0.8 + 'px' : '100%',
|
|
400
|
+
height: windowHeight - 140,
|
|
386
401
|
backgroundColor: '#f0f0f0',
|
|
387
|
-
minHeight: 'calc(100vh - 140px)',
|
|
388
|
-
width: '100%',
|
|
389
402
|
}}
|
|
390
403
|
>
|
|
391
404
|
{!previewStatus ? (
|
|
392
405
|
<iframe
|
|
393
406
|
key={activeFragment.sandboxUrl}
|
|
394
407
|
ref={previewIframeRef}
|
|
395
|
-
src={
|
|
396
|
-
className="w-full h-full border border-gray-200 rounded-md bg-white shadow-sm"
|
|
408
|
+
src={activeFragment.sandboxUrl}
|
|
409
|
+
className="w-full w-fit h-full h-fit border border-gray-200 rounded-md bg-white shadow-sm"
|
|
397
410
|
title="Live Preview"
|
|
398
411
|
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-orientation-lock allow-pointer-lock allow-presentation allow-storage-access-by-user-activation allow-top-navigation-by-user-activation"
|
|
399
412
|
loading="lazy"
|
|
400
413
|
onLoad={() => {
|
|
401
414
|
console.log('🎯 Iframe loaded successfully');
|
|
402
|
-
|
|
403
|
-
|
|
415
|
+
setIsLoading?.(false);
|
|
416
|
+
send({ type: 'SET_LOADING', isLoading: false });
|
|
404
417
|
}}
|
|
405
418
|
onError={(e) => {
|
|
406
419
|
console.error('❌ Iframe error:', e);
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
style={{
|
|
410
|
-
// minHeight: '400px'
|
|
411
|
-
minHeight: 'calc(100vh - 140px)',
|
|
420
|
+
setIsLoading?.(false);
|
|
421
|
+
send({ type: 'SET_LOADING', isLoading: false });
|
|
412
422
|
}}
|
|
423
|
+
style={
|
|
424
|
+
{
|
|
425
|
+
// maxHeight: windowHeight - 140,
|
|
426
|
+
// width: isMinimized ? windowWidth * 0.82 + 'px' : '100%',
|
|
427
|
+
//padding: isMinimized ? '10px' : '0px',
|
|
428
|
+
}
|
|
429
|
+
}
|
|
413
430
|
/>
|
|
414
431
|
) : (
|
|
415
|
-
<div className="absolute inset-0 flex items-center justify-center
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<div className="
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
className="
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
432
|
+
<div className="absolute inset-0 bg-white/60 flex items-center justify-center z-20">
|
|
433
|
+
{handleRecreateSandbox && (
|
|
434
|
+
<>
|
|
435
|
+
{derivedIsLoading ? (
|
|
436
|
+
<div className="flex flex-col items-center justify-center gap-2">
|
|
437
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
|
438
|
+
<p className="text-xs text-blue-700">Recreating...</p>
|
|
439
|
+
</div>
|
|
440
|
+
) : (
|
|
441
|
+
<div className="flex flex-col items-center justify-center gap-2">
|
|
442
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
|
443
|
+
<p className="text-sm text-muted-foreground">
|
|
444
|
+
{isLoading ? 'Recreating...' : 'Refresh'}{' '}
|
|
445
|
+
{/* Sandbox is not available. */}
|
|
446
|
+
</p>
|
|
447
|
+
{/* <button
|
|
448
|
+
type="button"
|
|
449
|
+
className="themed-button focus-themed px-3 py-1.5 text-xs"
|
|
450
|
+
onClick={() =>
|
|
451
|
+
recreateSandboxHandler(activeFragment?.id)
|
|
452
|
+
}
|
|
453
|
+
>
|
|
454
|
+
Recreate
|
|
455
|
+
</button> */}
|
|
456
|
+
</div>
|
|
457
|
+
)}
|
|
458
|
+
</>
|
|
459
|
+
)}
|
|
434
460
|
</div>
|
|
435
461
|
)}
|
|
436
462
|
<div className="absolute top-2 right-2 bg-green-100 text-green-800 px-2 py-1 rounded text-xs z-10">
|
|
437
463
|
Live Preview
|
|
438
464
|
</div>
|
|
439
|
-
{
|
|
465
|
+
{derivedIsLoading && (
|
|
440
466
|
<>
|
|
441
467
|
<div className="absolute inset-0 bg-white/60 flex items-center justify-center z-20">
|
|
442
468
|
<div className="animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"></div>
|
|
@@ -450,17 +476,22 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
450
476
|
);
|
|
451
477
|
} else {
|
|
452
478
|
return (
|
|
453
|
-
<div
|
|
479
|
+
<div
|
|
480
|
+
className="h-full flex items-center justify-center text-gray-500 border border-gray-200 rounded-md bg-gray-50 "
|
|
481
|
+
style={{ width: '100%', height: '80vh' }}
|
|
482
|
+
>
|
|
454
483
|
<div className="text-center space-y-3">
|
|
455
484
|
<p className="font-medium">No preview available</p>
|
|
456
485
|
<div className="flex flex-col items-center justify-center space-y-3">
|
|
457
|
-
{
|
|
486
|
+
{derivedIsLoading ? (
|
|
458
487
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
|
|
459
488
|
) : (
|
|
460
489
|
<div className="w-8 h-8 bg-gray-300 rounded-full"></div>
|
|
461
490
|
)}
|
|
462
491
|
<p className="text-sm text-gray-400">
|
|
463
|
-
{
|
|
492
|
+
{derivedIsLoading
|
|
493
|
+
? 'Generating code...'
|
|
494
|
+
: 'Waiting for code generation...'}
|
|
464
495
|
</p>
|
|
465
496
|
</div>
|
|
466
497
|
</div>
|
|
@@ -470,7 +501,14 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
470
501
|
})()
|
|
471
502
|
) : (
|
|
472
503
|
// Code Editor Mode - Show files from subscription or fallback
|
|
473
|
-
<div
|
|
504
|
+
<div
|
|
505
|
+
className="h-full w-full relative"
|
|
506
|
+
style={{
|
|
507
|
+
minHeight: windowHeight - 140,
|
|
508
|
+
height: windowHeight - 140,
|
|
509
|
+
width: isMinimized ? windowWidth * 0.9 + 'px' : '100%',
|
|
510
|
+
}}
|
|
511
|
+
>
|
|
474
512
|
<HybridLiveEditor
|
|
475
513
|
ref={hybridLiveEditorRef}
|
|
476
514
|
projectId={activeFragment?.projectId || channelId}
|
|
@@ -482,9 +520,10 @@ export const RightSidebarFillComponent = (props: RightSidebarProps) => {
|
|
|
482
520
|
readOnly={!activeFragment?.id}
|
|
483
521
|
autoSave={false}
|
|
484
522
|
debounceMs={500}
|
|
523
|
+
//className={`h-full w-[100%] h-[75vh] border-b border-gray-200 rounded-md bg-white shadow-sm overflow-hidden`}
|
|
485
524
|
className="h-full w-full"
|
|
486
525
|
/>
|
|
487
|
-
{
|
|
526
|
+
{derivedIsLoading && (
|
|
488
527
|
<>
|
|
489
528
|
<div className="absolute inset-0 bg-white/60 flex items-center justify-center z-20">
|
|
490
529
|
<div className="animate-spin rounded-full h-12 w-12 border-4 border-blue-500 border-t-transparent"></div>
|
|
@@ -23,6 +23,7 @@ type RightSidebarProps = {
|
|
|
23
23
|
setIsLoading?: (isLoading: boolean) => void;
|
|
24
24
|
handleSendMessage?: (createChannelInput: ICreateChannelInput) => void;
|
|
25
25
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
26
|
+
isMinimized?: boolean;
|
|
26
27
|
isLoading?: boolean;
|
|
27
28
|
[key: string]: any;
|
|
28
29
|
};
|
package/src/config/env-config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cleanEnv, num, str } from 'envalid';
|
|
1
|
+
import { cleanEnv, json, num, str } from 'envalid';
|
|
2
2
|
import { getEnvironment } from '@common-stack/core';
|
|
3
3
|
|
|
4
4
|
const env = getEnvironment();
|
|
@@ -19,4 +19,6 @@ export const config = cleanEnv(env, {
|
|
|
19
19
|
NEWS_API_KEY: str({ default: '' }),
|
|
20
20
|
OPENAI_API_KEY: str({ default: '' }),
|
|
21
21
|
AI_MESSENGER_PATH: str({ default: '/ai-messenger/app' }),
|
|
22
|
+
LAYOUT_SETTINGS: json({ default: {} }),
|
|
23
|
+
APP_NAME: str({ default: 'Messenger Box' }),
|
|
22
24
|
});
|