Skip to content

Commit 54f1570

Browse files
committed
wip
1 parent c42d5f7 commit 54f1570

File tree

6 files changed

+191
-43
lines changed

6 files changed

+191
-43
lines changed

src/lib/components/chat/AssistantIntroduction.svelte

+5-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@
124124
</div>
125125
</div>
126126

127-
<div class="absolute right-3 top-3 md:right-4 md:top-4">
127+
<div
128+
class="absolute right-3 top-3 md:right-4 md:top-4"
129+
class:hidden={$page.data.embeddedAssistantId}
130+
>
128131
<div class="flex flex-row items-center gap-1">
129132
<button
130133
class="flex h-7 items-center gap-1.5 rounded-full border bg-white px-2.5 py-1 text-gray-800 shadow-sm hover:shadow-inner dark:border-gray-700 dark:bg-gray-700 dark:text-gray-300/90 dark:hover:bg-gray-800 max-sm:px-1.5 md:text-sm"
@@ -161,6 +164,7 @@
161164
goto(`${base}/`);
162165
}}
163166
class="absolute -bottom-6 right-2 inline-flex items-center justify-center text-xs text-gray-600 underline hover:brightness-50 dark:text-gray-400 dark:hover:brightness-110"
167+
class:hidden={$page.data.embeddedAssistantId}
164168
>
165169
<CarbonRenew class="mr-1.5 text-xxs" /> Reset to default model
166170
</button>

src/lib/components/chat/ChatWindow.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@
241241
<div
242242
class="mx-auto flex h-full max-w-3xl flex-col gap-6 px-5 pt-6 sm:gap-8 xl:max-w-4xl xl:pt-10"
243243
>
244-
{#if $page.data?.assistant && !!messages.length}
244+
{#if $page.data?.assistant && !!messages.length && !$page.data.embeddedAssistantId}
245245
<a
246246
class="mx-auto flex items-center gap-1.5 rounded-full border border-gray-100 bg-gray-50 py-1 pl-1 pr-3 text-sm text-gray-800 hover:bg-gray-100 dark:border-gray-800 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
247247
href="{base}/settings/assistants/{$page.data.assistant._id}"
@@ -263,7 +263,7 @@
263263

264264
{$page.data.assistant.name}
265265
</a>
266-
{:else if preprompt && preprompt != currentModel.preprompt}
266+
{:else if preprompt && preprompt != currentModel.preprompt && !$page.data.embeddedAssistantId}
267267
<SystemPromptModal preprompt={preprompt ?? ""} />
268268
{/if}
269269

@@ -448,6 +448,7 @@
448448
</form>
449449
<div
450450
class="mt-2 flex justify-between self-stretch px-1 text-xs text-gray-400/90 max-md:mb-2 max-sm:gap-2"
451+
class:hidden={$page.data.embeddedAssistantId}
451452
>
452453
<p>
453454
Model:

src/routes/+layout.server.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { toolFromConfigs } from "$lib/server/tools";
1212
import { MetricsServer } from "$lib/server/metrics";
1313
import type { ToolFront, ToolInputFile } from "$lib/types/Tool";
1414

15-
export const load: LayoutServerLoad = async ({ locals, depends, request }) => {
15+
export const load: LayoutServerLoad = async ({ locals, depends, request, url }) => {
1616
depends(UrlDependency.ConversationList);
1717

1818
const settings = await collections.settings.findOne(authCondition(locals));
@@ -127,6 +127,8 @@ export const load: LayoutServerLoad = async ({ locals, depends, request }) => {
127127
}))
128128
);
129129

130+
console.log("we here", url.searchParams.get("embeddedAssistantId"));
131+
130132
return {
131133
conversations: conversations.map((conv) => {
132134
if (settings?.hideEmojiOnSidebar) {
@@ -244,5 +246,6 @@ export const load: LayoutServerLoad = async ({ locals, depends, request }) => {
244246
loginRequired,
245247
loginEnabled: requiresUser,
246248
guestMode: requiresUser && messagesBeforeLogin > 0,
249+
embeddedAssistantId: url.searchParams.get("embeddedAssistantId"),
247250
};
248251
};

src/routes/+layout.svelte

+55-39
Original file line numberDiff line numberDiff line change
@@ -203,49 +203,65 @@
203203
{#if envPublic.PUBLIC_APPLE_APP_ID}
204204
<meta name="apple-itunes-app" content={`app-id=${envPublic.PUBLIC_APPLE_APP_ID}`} />
205205
{/if}
206+
<!-- TODO: remove -->
207+
{#if !$page.data.embeddedAssistantId}
208+
<script src="http://localhost:5173/chat/api/assistant/5/embed-snippet" defer></script>
209+
{/if}
206210
</svelte:head>
207211

208212
{#if !$settings.ethicsModalAccepted && $page.url.pathname !== `${base}/privacy` && PUBLIC_APP_DISCLAIMER === "1"}
209213
<DisclaimerModal />
210214
{/if}
211215

212-
<ExpandNavigation
213-
isCollapsed={isNavCollapsed}
214-
on:click={() => (isNavCollapsed = !isNavCollapsed)}
215-
classNames="absolute inset-y-0 z-10 my-auto {!isNavCollapsed
216-
? 'left-[280px]'
217-
: 'left-0'} *:transition-transform"
218-
/>
219-
220-
<div
221-
class="grid h-full w-screen grid-cols-1 grid-rows-[auto,1fr] overflow-hidden text-smd {!isNavCollapsed
222-
? 'md:grid-cols-[280px,1fr]'
223-
: 'md:grid-cols-[0px,1fr]'} transition-[300ms] [transition-property:grid-template-columns] dark:text-gray-300 md:grid-rows-[1fr]"
224-
>
225-
<MobileNav isOpen={isNavOpen} on:toggle={(ev) => (isNavOpen = ev.detail)} title={mobileNavTitle}>
226-
<NavMenu
227-
conversations={data.conversations}
228-
user={data.user}
229-
canLogin={data.user === undefined && data.loginEnabled}
230-
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
231-
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
232-
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
233-
/>
234-
</MobileNav>
235-
<nav
236-
class=" grid max-h-screen grid-cols-1 grid-rows-[auto,1fr,auto] overflow-hidden *:w-[280px] max-md:hidden"
216+
{#if !$page.data.embeddedAssistantId}
217+
<ExpandNavigation
218+
isCollapsed={isNavCollapsed}
219+
on:click={() => (isNavCollapsed = !isNavCollapsed)}
220+
classNames="absolute inset-y-0 z-10 my-auto {!isNavCollapsed
221+
? 'left-[280px]'
222+
: 'left-0'} *:transition-transform"
223+
/>
224+
225+
<div
226+
class="grid h-full w-screen grid-cols-1 grid-rows-[auto,1fr] overflow-hidden text-smd {!isNavCollapsed
227+
? 'md:grid-cols-[280px,1fr]'
228+
: 'md:grid-cols-[0px,1fr]'} transition-[300ms] [transition-property:grid-template-columns] dark:text-gray-300 md:grid-rows-[1fr]"
237229
>
238-
<NavMenu
239-
conversations={data.conversations}
240-
user={data.user}
241-
canLogin={data.user === undefined && data.loginEnabled}
242-
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
243-
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
244-
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
245-
/>
246-
</nav>
247-
{#if currentError}
248-
<Toast message={currentError} />
249-
{/if}
250-
<slot />
251-
</div>
230+
<MobileNav
231+
isOpen={isNavOpen}
232+
on:toggle={(ev) => (isNavOpen = ev.detail)}
233+
title={mobileNavTitle}
234+
>
235+
<NavMenu
236+
conversations={data.conversations}
237+
user={data.user}
238+
canLogin={data.user === undefined && data.loginEnabled}
239+
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
240+
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
241+
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
242+
/>
243+
</MobileNav>
244+
<nav
245+
class=" grid max-h-screen grid-cols-1 grid-rows-[auto,1fr,auto] overflow-hidden *:w-[280px] max-md:hidden"
246+
>
247+
<NavMenu
248+
conversations={data.conversations}
249+
user={data.user}
250+
canLogin={data.user === undefined && data.loginEnabled}
251+
on:shareConversation={(ev) => shareConversation(ev.detail.id, ev.detail.title)}
252+
on:deleteConversation={(ev) => deleteConversation(ev.detail)}
253+
on:editConversationTitle={(ev) => editConversationTitle(ev.detail.id, ev.detail.title)}
254+
/>
255+
</nav>
256+
{#if currentError}
257+
<Toast message={currentError} />
258+
{/if}
259+
<slot />
260+
</div>
261+
{:else}
262+
<div
263+
class="grid h-full w-screen grid-cols-1 grid-rows-[auto,1fr] overflow-hidden text-smd dark:text-gray-300"
264+
>
265+
<slot />
266+
</div>
267+
{/if}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
export async function GET() {
2+
const script = `(function() {
3+
function resizeIframeToContentSize(iframe) {
4+
if (iframe.contentWindow) {
5+
const maxHeight = window.innerHeight * 0.8; // 80% of window height
6+
const contentHeight = iframe.contentWindow.document.body.scrollHeight;
7+
console.log("contentHeight", contentHeight);
8+
iframe.style.height = Math.min(contentHeight, maxHeight) + "px";
9+
}
10+
}
11+
12+
document.addEventListener('DOMContentLoaded', function() {
13+
const button = document.createElement('button');
14+
button.className = 'fixed bottom-5 right-5 z-50 px-1.5 py-1 bg-blue-500 text-white rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center focus:outline-none';
15+
16+
const img = document.createElement('img');
17+
img.src = 'https://huggingface.co/chat/huggingchat/logo.svg';
18+
img.alt = 'HuggingChat Logo';
19+
img.className = 'size-4 mr-0.5';
20+
21+
const text = document.createTextNode('Chat');
22+
23+
button.appendChild(img);
24+
button.appendChild(text);
25+
26+
const modal = document.createElement('div');
27+
modal.className = 'hidden fixed inset-0 z-[1001] overflow-auto bg-black bg-opacity-50';
28+
29+
const modalContent = document.createElement('div');
30+
modalContent.className = 'bg-transparent mx-auto my-[5%] max-w-2xl rounded';
31+
32+
const closeButton = document.createElement('span');
33+
closeButton.innerHTML = '&times;';
34+
closeButton.className = 'text-gray-500 float-right text-2xl font-bold cursor-pointer hover:text-gray-700';
35+
36+
const iframe = document.createElement('iframe');
37+
iframe.className = 'w-full rounded-xl';
38+
iframe.style.height = '500px'; // Set an initial height
39+
iframe.src = \`http://localhost:5173/chat/assistant/66f40815222227d57241a145/embedded\`;
40+
41+
iframe.onload = function() {
42+
const iframeWindow = this.contentWindow;
43+
iframeWindow.parent = {
44+
resizeIframeToContentSize: resizeIframeToContentSize.bind(null, iframe)
45+
};
46+
47+
const script = iframeWindow.document.createElement('script');
48+
script.textContent = \`
49+
this.container = this.frameElement.contentWindow.document.body;
50+
this.lastScrollHeight = 0;
51+
52+
this.watch = () => {
53+
cancelAnimationFrame(this.watcher);
54+
55+
if (this.lastScrollHeight !== container.scrollHeight) {
56+
parent.resizeIframeToContentSize();
57+
}
58+
this.lastScrollHeight = container.scrollHeight;
59+
this.watcher = requestAnimationFrame(this.watch);
60+
};
61+
this.watcher = window.requestAnimationFrame(this.watch);
62+
\`;
63+
iframeWindow.document.body.appendChild(script);
64+
};
65+
66+
modalContent.appendChild(closeButton);
67+
modalContent.appendChild(iframe);
68+
modal.appendChild(modalContent);
69+
70+
function closeModal() {
71+
modal.classList.add('hidden');
72+
}
73+
74+
button.onclick = function() {
75+
modal.classList.remove('hidden');
76+
resizeIframeToContentSize(iframe); // Resize on opening to ensure correct initial size
77+
};
78+
79+
closeButton.onclick = closeModal;
80+
81+
window.onclick = function(event) {
82+
if (event.target == modal) {
83+
closeModal();
84+
}
85+
};
86+
87+
document.addEventListener('keydown', function(event) {
88+
if (event.key === 'Escape') {
89+
closeModal();
90+
}
91+
});
92+
93+
// Add resize event listener to adjust iframe height when window is resized
94+
window.addEventListener('resize', function() {
95+
if (!modal.classList.contains('hidden')) {
96+
resizeIframeToContentSize(iframe);
97+
}
98+
});
99+
100+
document.body.appendChild(button);
101+
document.body.appendChild(modal);
102+
});
103+
})();
104+
`;
105+
106+
return new Response(script, {
107+
headers: {
108+
"Content-Type": "application/javascript",
109+
"Access-Control-Allow-Origin": "*",
110+
},
111+
});
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { base } from "$app/paths";
2+
import { redirect } from "@sveltejs/kit";
3+
4+
export async function load() {
5+
const queryParams = new URLSearchParams({
6+
embeddedAssistantId: "value1",
7+
});
8+
9+
const redirectUrl = `${base}/?${queryParams.toString()}`;
10+
11+
redirect(302, redirectUrl);
12+
}

0 commit comments

Comments
 (0)