1<script lang="ts">
  2	import { ChatMessage } from '$lib/components/app';
  3	import { chatStore } from '$lib/stores/chat.svelte';
  4	import { conversationsStore, activeConversation } from '$lib/stores/conversations.svelte';
  5	import { config } from '$lib/stores/settings.svelte';
  6	import { getMessageSiblings } from '$lib/utils';
  7
  8	interface Props {
  9		class?: string;
 10		messages?: DatabaseMessage[];
 11		onUserAction?: () => void;
 12	}
 13
 14	let { class: className, messages = [], onUserAction }: Props = $props();
 15
 16	let allConversationMessages = $state<DatabaseMessage[]>([]);
 17	const currentConfig = config();
 18
 19	function refreshAllMessages() {
 20		const conversation = activeConversation();
 21
 22		if (conversation) {
 23			conversationsStore.getConversationMessages(conversation.id).then((messages) => {
 24				allConversationMessages = messages;
 25			});
 26		} else {
 27			allConversationMessages = [];
 28		}
 29	}
 30
 31	// Single effect that tracks both conversation and message changes
 32	$effect(() => {
 33		const conversation = activeConversation();
 34
 35		if (conversation) {
 36			refreshAllMessages();
 37		}
 38	});
 39
 40	let displayMessages = $derived.by(() => {
 41		if (!messages.length) {
 42			return [];
 43		}
 44
 45		// Filter out system messages if showSystemMessage is false
 46		const filteredMessages = currentConfig.showSystemMessage
 47			? messages
 48			: messages.filter((msg) => msg.type !== 'system');
 49
 50		return filteredMessages.map((message) => {
 51			const siblingInfo = getMessageSiblings(allConversationMessages, message.id);
 52
 53			return {
 54				message,
 55				siblingInfo: siblingInfo || {
 56					message,
 57					siblingIds: [message.id],
 58					currentIndex: 0,
 59					totalSiblings: 1
 60				}
 61			};
 62		});
 63	});
 64
 65	async function handleNavigateToSibling(siblingId: string) {
 66		await conversationsStore.navigateToSibling(siblingId);
 67	}
 68
 69	async function handleEditWithBranching(
 70		message: DatabaseMessage,
 71		newContent: string,
 72		newExtras?: DatabaseMessageExtra[]
 73	) {
 74		onUserAction?.();
 75
 76		await chatStore.editMessageWithBranching(message.id, newContent, newExtras);
 77
 78		refreshAllMessages();
 79	}
 80
 81	async function handleEditWithReplacement(
 82		message: DatabaseMessage,
 83		newContent: string,
 84		shouldBranch: boolean
 85	) {
 86		onUserAction?.();
 87
 88		await chatStore.editAssistantMessage(message.id, newContent, shouldBranch);
 89
 90		refreshAllMessages();
 91	}
 92
 93	async function handleRegenerateWithBranching(message: DatabaseMessage, modelOverride?: string) {
 94		onUserAction?.();
 95
 96		await chatStore.regenerateMessageWithBranching(message.id, modelOverride);
 97
 98		refreshAllMessages();
 99	}
100
101	async function handleContinueAssistantMessage(message: DatabaseMessage) {
102		onUserAction?.();
103
104		await chatStore.continueAssistantMessage(message.id);
105
106		refreshAllMessages();
107	}
108
109	async function handleEditUserMessagePreserveResponses(
110		message: DatabaseMessage,
111		newContent: string,
112		newExtras?: DatabaseMessageExtra[]
113	) {
114		onUserAction?.();
115
116		await chatStore.editUserMessagePreserveResponses(message.id, newContent, newExtras);
117
118		refreshAllMessages();
119	}
120
121	async function handleDeleteMessage(message: DatabaseMessage) {
122		await chatStore.deleteMessage(message.id);
123
124		refreshAllMessages();
125	}
126</script>
127
128<div class="flex h-full flex-col space-y-10 pt-16 md:pt-24 {className}" style="height: auto; ">
129	{#each displayMessages as { message, siblingInfo } (message.id)}
130		<ChatMessage
131			class="mx-auto w-full max-w-[48rem]"
132			{message}
133			{siblingInfo}
134			onDelete={handleDeleteMessage}
135			onNavigateToSibling={handleNavigateToSibling}
136			onEditWithBranching={handleEditWithBranching}
137			onEditWithReplacement={handleEditWithReplacement}
138			onEditUserMessagePreserveResponses={handleEditUserMessagePreserveResponses}
139			onRegenerateWithBranching={handleRegenerateWithBranching}
140			onContinueAssistantMessage={handleContinueAssistantMessage}
141		/>
142	{/each}
143</div>