File size: 2,019 Bytes
1b66f8d
5da61b4
 
 
4a6603b
77c7055
5da61b4
 
4a6603b
2606dde
 
4a6603b
 
1b66f8d
 
3aa8136
 
2606dde
 
 
1b66f8d
 
77c7055
 
 
 
 
 
 
9c038aa
77c7055
 
1b66f8d
 
0714764
b2387f6
9a2f641
0714764
 
b2387f6
3aa8136
4a6603b
 
 
ad6275a
4a6603b
 
1b66f8d
2606dde
 
 
1b66f8d
3aa8136
ad6275a
 
 
 
3aa8136
1b66f8d
 
0714764
b2387f6
0714764
 
1b66f8d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<script lang="ts">
	import type { Message } from "$lib/types/Message";
	import { snapScrollToBottom } from "$lib/actions/snapScrollToBottom";
	import ScrollToBottomBtn from "$lib/components/ScrollToBottomBtn.svelte";
	import { createEventDispatcher, tick } from "svelte";

	import ChatIntroduction from "./ChatIntroduction.svelte";
	import ChatMessage from "./ChatMessage.svelte";
	import { randomUUID } from "$lib/utils/randomUuid";
	import type { Model } from "$lib/types/Model";
	import type { LayoutData } from "../../../routes/$types";

	const dispatch = createEventDispatcher<{ retry: { id: Message["id"]; content: string } }>();

	export let messages: Message[];
	export let loading: boolean;
	export let pending: boolean;
	export let currentModel: Model;
	export let settings: LayoutData["settings"];
	export let models: Model[] | undefined;

	let chatContainer: HTMLElement;

	async function scrollToBottom() {
		await tick();
		chatContainer.scrollTop = chatContainer.scrollHeight;
	}

	// If last message is from user, scroll to bottom
	$: if (messages[messages.length - 1]?.from === "user") {
		scrollToBottom();
	}
</script>

<div
	class="scrollbar-custom mr-1 h-full overflow-y-auto"
	use:snapScrollToBottom={messages.length ? messages : false}
	bind:this={chatContainer}
>
	<div class="mx-auto flex h-full max-w-3xl flex-col gap-5 px-5 pt-6 sm:gap-8 xl:max-w-4xl">
		{#each messages as message, i}
			<ChatMessage
				loading={loading && i === messages.length - 1}
				{message}
				model={currentModel}
				on:retry={() => dispatch("retry", { id: message.id, content: message.content })}
			/>
		{:else}
			{#if models}
				<ChatIntroduction {settings} {models} {currentModel} on:message />
			{/if}
		{/each}
		{#if pending}
			<ChatMessage
				message={{ from: "assistant", content: "", id: randomUUID() }}
				model={currentModel}
			/>
		{/if}
		<div class="h-32 flex-none" />
	</div>
	<ScrollToBottomBtn
		class="bottom-36 right-4 max-md:hidden lg:right-10"
		scrollNode={chatContainer}
	/>
</div>