File size: 2,490 Bytes
8aab1a5
98051f8
 
 
5d291ff
ef7aeda
01b06a3
 
5d291ff
 
0c6af63
8aab1a5
 
949cae0
 
5d291ff
01b06a3
 
c202241
 
770735d
8aab1a5
770735d
8aab1a5
feb88db
0c6af63
 
feb88db
 
 
 
 
 
4a396c5
feb88db
 
770735d
 
 
 
 
 
 
 
 
 
 
8aab1a5
 
45dbaaf
6a0861b
0c6af63
45dbaaf
 
5d291ff
949cae0
770735d
 
 
 
 
 
 
 
 
 
8aab1a5
c202241
8aab1a5
949cae0
f16c630
 
 
0c6af63
f16c630
949cae0
0c6af63
8aab1a5
45dbaaf
6a0861b
45dbaaf
 
8aab1a5
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<script lang="ts">
	import type { Message } from "$lib/types/Message";
	import { snapScrollToBottom } from "$lib/actions/snapScrollToBottom";
	import ScrollToBottomBtn from "$lib/components/ScrollToBottomBtn.svelte";
	import { tick } from "svelte";
	import { randomUUID } from "$lib/utils/randomUuid";
	import type { Model } from "$lib/types/Model";
	import type { LayoutData } from "../../../routes/$types";
	import ChatIntroduction from "./ChatIntroduction.svelte";
	import ChatMessage from "./ChatMessage.svelte";
	import type { WebSearchMessage } from "$lib/types/WebSearch";

	export let messages: Message[];
	export let loading: boolean;
	export let pending: boolean;
	export let isAuthor: boolean;
	export let currentModel: Model;
	export let settings: LayoutData["settings"];
	export let models: Model[];
	export let readOnly: boolean;
	export let searches: Record<string, WebSearchMessage[]>;

	let webSearchArray: Array<WebSearchMessage[] | undefined> = [];
	let chatContainer: HTMLElement;

	export let webSearchMessages: WebSearchMessage[] = [];

	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();
	}

	$: messages,
		(webSearchArray = messages.map((message, idx) => {
			if (message.webSearchId) {
				return searches[message.webSearchId] ?? [];
			} else if (idx === messages.length - 1) {
				return webSearchMessages;
			} else {
				return [];
			}
		}));
</script>

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