diff --git a/src/lib/components/studio/chat/chat.svelte b/src/lib/components/studio/chat/chat.svelte index b1dc919bc..3d5df39d4 100644 --- a/src/lib/components/studio/chat/chat.svelte +++ b/src/lib/components/studio/chat/chat.svelte @@ -258,7 +258,10 @@ } @media (min-width: 768px) { - margin-block-end: var(--space-7); + margin-block-end: var(--space-4); + margin-inline-start: calc(-1 * var(--space-4)); + border-radius: var(--border-radius-xs); + width: calc(100% + 2 * var(--space-4)); } } diff --git a/src/lib/components/studio/chatWrapper.svelte b/src/lib/components/studio/chatWrapper.svelte new file mode 100644 index 000000000..93ffcf5be --- /dev/null +++ b/src/lib/components/studio/chatWrapper.svelte @@ -0,0 +1,196 @@ + + + + +{#if !$isSmallViewport && ($showChat || isResizing)} + +{/if} + + diff --git a/src/lib/layout/cover.svelte b/src/lib/layout/cover.svelte index f38ba36fb..9024c7483 100644 --- a/src/lib/layout/cover.svelte +++ b/src/lib/layout/cover.svelte @@ -1,17 +1,40 @@ {#if isStudio} + {#if nestedLevel > 4} + {#if (nestedLevel === 6 && paramCount === 2) || nestedLevel === 7} + + {:else if paramCount >= 2} + + {/if} + {/if} + diff --git a/src/lib/layout/coverTitle.svelte b/src/lib/layout/coverTitle.svelte index 3f3b30f06..05b34d6d8 100644 --- a/src/lib/layout/coverTitle.svelte +++ b/src/lib/layout/coverTitle.svelte @@ -14,6 +14,9 @@ {/if} - + diff --git a/src/lib/layout/shellStudio.svelte b/src/lib/layout/shellStudio.svelte index 0a26b6bad..8209900dd 100644 --- a/src/lib/layout/shellStudio.svelte +++ b/src/lib/layout/shellStudio.svelte @@ -16,11 +16,11 @@ import { user } from '$lib/stores/user'; import SidebarProject from '$lib/components/studio/sidebarProject.svelte'; import SidebarOrganization from '$lib/components/studio/sidebarOrganization.svelte'; + import ChatWrapper from '$lib/components/studio/chatWrapper.svelte'; import { BillingPlan } from '$lib/constants.js'; import { isCloud } from '$lib/system.js'; import { tierToPlan } from '$lib/stores/billing.js'; import type { NavbarProject } from '$lib/components/navbar.svelte'; - import Chat from '$lib/components/studio/chat/chat.svelte'; import { IconChevronRight, IconLogoutRight, @@ -35,18 +35,7 @@ import { logout } from '$lib/helpers/logout'; import { Click, trackEvent } from '$lib/actions/analytics'; import { conversation, showChat } from '$lib/stores/chat'; - import { createStreamParser } from '$lib/components/studio/chat/parser'; import { type Snippet } from 'svelte'; - import { sdk } from '$lib/stores/sdk'; - import { filesystem } from '$lib/components/editor/filesystem'; - import { previewFrameRef } from '$routes/(console)/project-[project]/store'; - import { - disableBodySelect, - enabledBodySelect, - getChatWidthFromPrefs, - saveChatWidthToPrefs - } from '$lib/helpers/studioLayout'; - import { synapse } from '$lib/components/studio/synapse.svelte'; let hasProjectSidebar = $state(false); @@ -69,7 +58,9 @@ $effect(() => { isOnEditorPage = - page.url.pathname.includes('studio') && page.url.pathname.includes('artifact'); + page.url.pathname.includes('studio') && + page.url.pathname.includes('artifact') && + 'artifact' in page.params; }); function updateTheme(theme: 'light' | 'dark' | 'auto') { @@ -114,144 +105,6 @@ }; }); }); - - $effect(() => { - if ($isSmallViewport || page.params.artifact) { - showChat.set(true); - } - if (!page.params.artifact) { - showChat.set(false); - } - }); - - let resizer = $state(null); - let resizerLeftPosition = $state( - page.data?.subNavigation ? getChatWidthFromPrefs() + 24 : getChatWidthFromPrefs() - ); - let resizerLeftOffset = $state(page.data?.subNavigation ? 52 : 9); - let chatWidth = $derived(resizerLeftPosition - resizerLeftOffset); - - $effect(() => { - chatWidth = resizerLeftPosition - resizerLeftOffset; - }); - - let isResizing = false; - - function startResize() { - isResizing = true; - window.addEventListener('mousemove', resize); - window.addEventListener('mouseup', stopResize); - window.addEventListener('touchmove', resize); - window.addEventListener('touchend', stopResize); - disableBodySelect(); - - if ($previewFrameRef) { - $previewFrameRef.style.pointerEvents = 'none'; - } - } - - function resize(event: TouchEvent | MouseEvent) { - if (!isResizing) return; - if (resizer) { - resizerLeftPosition = - ('touches' in event ? event.touches[0].clientX : event.clientX) - 60; - const maxSize = page.data?.subNavigation - ? window.innerWidth - 660 - : window.innerWidth - 540; - - const minSize = 320; - if (resizerLeftPosition > maxSize) { - resizerLeftPosition = maxSize; - } else if (resizerLeftPosition < minSize) { - if (resizerLeftPosition < minSize - 100) { - showChat.set(false); - } - - resizerLeftPosition = minSize; - } else if (resizerLeftPosition > minSize && !$showChat) { - showChat.set(true); - } - } - } - - function stopResize() { - if (!$showChat) { - resizerLeftPosition = 500; - } - const saveWidth = page.data?.subNavigation ? resizerLeftPosition - 24 : resizerLeftPosition; - saveChatWidthToPrefs(saveWidth); - - isResizing = false; - window.removeEventListener('mousemove', resize); - window.removeEventListener('mouseup', stopResize); - window.removeEventListener('touchmove', resize); - window.removeEventListener('touchend', stopResize); - enabledBodySelect(); - - if ($previewFrameRef) { - $previewFrameRef.style.pointerEvents = ''; - } - } - - const parser = createStreamParser(); - - async function getConversation(artifactId: string) { - parser.reset(); - const { conversations } = await sdk.forProject.imagine.listConversations(artifactId); - if (conversations.length === 0) { - const convo = sdk.forProject.imagine.createConversation( - artifactId, - `Conversation ${new Date().getTime()}` - ); - conversation.set(convo); - } else { - conversation.set(conversations[0]); - } - } - - $effect(() => { - if (page.params.artifact && $conversation.data?.artifactId !== page.params.artifact) { - getConversation(page.params.artifact); - } - }); - - conversation.subscribe(async (convo) => { - if (!convo.data) return; - const { messages } = await sdk.forProject.imagine.listMessages( - convo.data.artifactId, - convo.data.$id - ); - let t = 0; - for (const message of messages) { - parser.chunk(message.content, message.role === 'assistant' ? 'system' : 'user', { - silent: true - }); - parser.end(); - } - }); - - parser.on('complete', async (action) => { - switch (action.type) { - case 'file': - await synapse.dispatch('fs', { - operation: 'updateFile', - params: { - filepath: action.src, - content: action.content - } - }); - $filesystem = [...$filesystem, action.src]; - break; - case 'shell': - synapse.dispatch('terminal', { - operation: 'createCommand', - params: { - command: action.content + '\n' - } - }); - break; - } - });
@@ -373,9 +226,10 @@ class:project-sidebar={hasProjectSidebar} class:sub-navigation={page.data.subNavigation}> {#if $isSmallViewport} - {#if hasProjectSidebar} - + {#if isOnEditorPage} + {/if} + {#if page.data?.subNavigation} @@ -389,19 +243,8 @@
- {#if hasProjectSidebar} - - {#if $showChat || isResizing} - - {/if} + {#if isOnEditorPage} + {/if} {@const Header = page.data.header} @@ -529,6 +372,12 @@ .studio-wrapper { position: relative; + height: calc(100dvh - 64px); + } + + :global(.studio-wrapper > div) { + height: 100%; + overflow-y: scroll; } .studio-content { @@ -554,33 +403,6 @@ } } - .resizer { - width: 16px; - cursor: col-resize; - margin-inline: 10px; - position: absolute; - height: calc(100vh - 72px); - margin-block-start: calc(-1 * var(--base-8)); - margin-inline-start: 0; - - &::after { - content: ''; - cursor: col-resize; - position: absolute; - height: 100%; - width: 1px; - margin-left: -1px; - left: 8px; - background-color: var(--border-neutral); - opacity: 1; - transition: all 0.3s ease-in-out; - } - - &:hover::after { - width: 2px; - background-color: var(--border-neutral-strong); - } - } .hidden { opacity: 0; } @@ -619,6 +441,7 @@ margin-inline-start: -17px; margin-block-start: 6px; border-top-left-radius: var(--border-radius-m); + border-bottom-left-radius: var(--border-radius-m); height: calc(100% - 65px) !important; border-left-width: 1px; border-top-width: 1px; diff --git a/src/routes/(console)/project-[project]/studio/+layout.ts b/src/routes/(console)/project-[project]/studio/+layout.ts index cfb64b9f6..c3c0e94fd 100644 --- a/src/routes/(console)/project-[project]/studio/+layout.ts +++ b/src/routes/(console)/project-[project]/studio/+layout.ts @@ -11,6 +11,7 @@ import type { Plan } from '$lib/sdk/billing'; export const load: LayoutLoad = async ({ params, depends }) => { depends(Dependencies.ARTIFACTS); + sdk.forProject.project.client.setProject(params.project); try { return { diff --git a/src/routes/(console)/project-[project]/studio/artifact-[artifact]/+layout.svelte b/src/routes/(console)/project-[project]/studio/artifact-[artifact]/+layout.svelte index 26f2e97d2..57313b001 100644 --- a/src/routes/(console)/project-[project]/studio/artifact-[artifact]/+layout.svelte +++ b/src/routes/(console)/project-[project]/studio/artifact-[artifact]/+layout.svelte @@ -172,8 +172,7 @@ {#if !$showChat} { showChat.set(true); }}> @@ -295,10 +294,10 @@ } .terminal-tabs { - background-color: white; + background-color: var(--bgcolor-neutral-primary); padding: var(--space-4) var(--space-4); - margin-inline-start: calc(-1 * var(--space-1)); - width: calc(100% + 1px); + margin-inline-start: calc(-1 * var(--space-1) + 1px); + width: calc(100%); } .divider-wrapper-artifacts {