File size: 3,537 Bytes
cfb0fa4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<script lang="ts">
	import { getContext } from 'svelte';
	import dayjs from 'dayjs';
	import calendar from 'dayjs/plugin/calendar';
	import { WEBUI_API_BASE_URL } from '$lib/constants';
	import Spinner from '$lib/components/common/Spinner.svelte';
	import Loader from '$lib/components/common/Loader.svelte';

	dayjs.extend(calendar);

	const i18n = getContext('i18n');

	export let chatList: Array<{
		id: string;
		title: string;
		updated_at: number;
		user_id?: string;
		user_name?: string;
		time_range?: string;
	}> | null = null;
	export let loading = false;
	export let allLoaded = false;
	export let showUserInfo = false;
	export let shareUrl = false;
	export let emptyMessage = 'No chats found';
	export let onLoadMore: (() => void) | null = null;
	export let onChatClick: ((chatId: string) => void) | null = null;
</script>

<div>
	{#if chatList && chatList.length > 0}
		<div class="flex text-xs font-medium mb-1.5">
			{#if showUserInfo}
				<div class="px-1.5 py-1 w-32">
					{$i18n.t('User')}
				</div>
			{/if}
			<div class="px-1.5 py-1 {showUserInfo ? 'flex-1' : 'basis-3/5'}">
				{$i18n.t('Title')}
			</div>
			<div class="px-1.5 py-1 hidden sm:flex {showUserInfo ? 'w-28' : 'basis-2/5'} justify-end">
				{$i18n.t('Updated at')}
			</div>
		</div>
	{/if}
	<div class="max-h-[22rem] overflow-y-scroll">
		{#if loading && (!chatList || chatList.length === 0)}
			<div class="flex justify-center py-8">
				<Spinner />
			</div>
		{:else if !chatList || chatList.length === 0}
			<div class="text-center text-gray-500 text-sm py-8">
				{$i18n.t(emptyMessage)}
			</div>
		{:else}
			{#each chatList as chat, idx (chat.id)}
				{#if chat.time_range && (idx === 0 || chat.time_range !== chatList[idx - 1]?.time_range)}
					<div
						class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium {idx === 0
							? ''
							: 'pt-5'} pb-2 px-2"
					>
						{$i18n.t(chat.time_range)}
					</div>
				{/if}

				<div
					class="w-full flex items-center rounded-lg text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850"
				>
					{#if showUserInfo && chat.user_id}
						<div class="w-32 shrink-0 flex items-center gap-2">
							<img
								src="{WEBUI_API_BASE_URL}/users/{chat.user_id}/profile/image"
								alt={chat.user_name || 'User'}
								class="size-5 rounded-full object-cover shrink-0"
							/>
							<span class="text-xs text-gray-600 dark:text-gray-400 truncate"
								>{chat.user_name || 'Unknown'}</span
							>
						</div>
					{/if}
					<a
						class={showUserInfo ? 'flex-1' : 'basis-3/5'}
						href={shareUrl ? `/s/${chat.id}` : `/c/${chat.id}`}
						on:click={() => onChatClick?.(chat.id)}
					>
						<div class="text-ellipsis line-clamp-1 w-full">
							{chat.title}
						</div>
					</a>

					<div class="{showUserInfo ? 'w-28' : 'basis-2/5'} flex items-center justify-end">
						<div class="hidden sm:flex text-gray-500 dark:text-gray-400 text-xs">
							{dayjs(chat.updated_at * 1000).calendar(null, {
								sameDay: '[Today] h:mm A',
								lastDay: '[Yesterday] h:mm A',
								lastWeek: 'MMM D',
								sameElse: 'MMM D, YYYY'
							})}
						</div>
					</div>
				</div>
			{/each}

			{#if !allLoaded && onLoadMore}
				<Loader
					on:visible={() => {
						if (!loading) {
							onLoadMore();
						}
					}}
				>
					<div class="w-full flex justify-center py-1 text-xs animate-pulse items-center gap-2">
						<Spinner className="size-4" />
						<div>{$i18n.t('Loading...')}</div>
					</div>
				</Loader>
			{/if}
		{/if}
	</div>
</div>