Browse Source

refac: folders

Timothy Jaeryang Baek 4 weeks ago
parent
commit
3ec1efb6e0

+ 14 - 10
src/lib/components/chat/Messages/CodeBlock.svelte

@@ -432,15 +432,17 @@
 			{/if}
 		{:else}
 			<div
-				class="sticky {stickyButtonsClassName} left-0 right-0 py-2 pr-3 flex items-center justify-between w-full z-10 text-xs text-black dark:text-white"
+				class="absolute left-0 right-0 py-2.5 pr-3 text-text-300 pl-4.5 text-xs font-medium dark:text-white"
 			>
-				<div class="text-text-300 pl-4.5 text-xs font-medium dark:text-white">
-					{lang}
-				</div>
+				{lang}
+			</div>
 
+			<div
+				class="sticky {stickyButtonsClassName} left-0 right-0 py-2 pr-3 flex items-center justify-end w-full z-10 text-xs text-black dark:text-white"
+			>
 				<div class="flex items-center gap-0.5">
 					<button
-						class="flex gap-1 items-center bg-none border-none transition rounded-md px-1.5 py-0.5"
+						class="flex gap-1 items-center bg-none border-none transition rounded-md px-1.5 py-0.5 bg-white dark:bg-black"
 						on:click={collapseCodeBlock}
 					>
 						<div class=" -translate-y-[0.5px]">
@@ -454,12 +456,14 @@
 
 					{#if ($config?.features?.enable_code_execution ?? true) && (lang.toLowerCase() === 'python' || lang.toLowerCase() === 'py' || (lang === '' && checkPythonCode(code)))}
 						{#if executing}
-							<div class="run-code-button bg-none border-none p-0.5 cursor-not-allowed">
+							<div
+								class="run-code-button bg-none border-none p-0.5 cursor-not-allowed bg-white dark:bg-black"
+							>
 								{$i18n.t('Running')}
 							</div>
 						{:else if run}
 							<button
-								class="flex gap-1 items-center run-code-button bg-none border-none transition rounded-md px-1.5 py-0.5"
+								class="flex gap-1 items-center run-code-button bg-none border-none transition rounded-md px-1.5 py-0.5 bg-white dark:bg-black"
 								on:click={async () => {
 									code = _code;
 									await tick();
@@ -475,7 +479,7 @@
 
 					{#if save}
 						<button
-							class="save-code-button bg-none border-none transition rounded-md px-1.5 py-0.5"
+							class="save-code-button bg-none border-none transition rounded-md px-1.5 py-0.5 bg-white dark:bg-black"
 							on:click={saveCode}
 						>
 							{saved ? $i18n.t('Saved') : $i18n.t('Save')}
@@ -483,13 +487,13 @@
 					{/if}
 
 					<button
-						class="copy-code-button bg-none border-none transition rounded-md px-1.5 py-0.5"
+						class="copy-code-button bg-none border-none transition rounded-md px-1.5 py-0.5 bg-white dark:bg-black"
 						on:click={copyCode}>{copied ? $i18n.t('Copied') : $i18n.t('Copy')}</button
 					>
 
 					{#if preview && ['html', 'svg'].includes(lang)}
 						<button
-							class="flex gap-1 items-center run-code-button bg-none border-none transition rounded-md px-1.5 py-0.5"
+							class="flex gap-1 items-center run-code-button bg-none border-none transition rounded-md px-1.5 py-0.5 bg-white dark:bg-black"
 							on:click={previewCode}
 						>
 							<div>

+ 1 - 1
src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte

@@ -109,7 +109,7 @@
 				{save}
 				{preview}
 				edit={editCodeBlock}
-				stickyButtonsClassName={topPadding ? 'top-6' : 'top-0'}
+				stickyButtonsClassName={topPadding ? 'top-7' : 'top-0'}
 				onSave={(value) => {
 					onSave({
 						raw: token.raw,

+ 1 - 1
src/lib/components/chat/Navbar.svelte

@@ -72,7 +72,7 @@
 <nav class="sticky top-0 z-30 w-full py-1 -mb-8 flex flex-col items-center drag-region">
 	<div class="flex items-center w-full pl-1.5 pr-1">
 		<div
-			class=" bg-linear-to-b via-40% from-white via-white to-transparent dark:from-gray-900 dark:via-gray-900 dark:to-transparent pointer-events-none absolute inset-0 -bottom-7 z-[-1]"
+			class=" bg-linear-to-b via-40% to-97% from-white via-white to-transparent dark:from-gray-900 dark:via-gray-900 dark:to-transparent pointer-events-none absolute inset-0 -bottom-7 z-[-1]"
 		></div>
 
 		<div class=" flex max-w-full w-full mx-auto px-1.5 md:px-2 pt-0.5 bg-transparent">

+ 8 - 7
src/lib/components/common/Folder.svelte

@@ -16,14 +16,15 @@
 	export let name = '';
 	export let collapsible = true;
 
+	export let className = '';
+	export let buttonClassName = 'text-gray-600 dark:text-gray-400';
+
 	export let chevron = true;
 	export let onAddLabel: string = '';
 	export let onAdd: null | Function = null;
 
 	export let dragAndDrop = true;
 
-	export let className = '';
-
 	let folderElement;
 
 	let draggedOver = false;
@@ -138,20 +139,20 @@
 		>
 			<!-- svelte-ignore a11y-no-static-element-interactions -->
 			<div
-				class="w-full group rounded-lg relative flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-900 text-gray-500 dark:text-gray-500 transition"
+				class="w-full group rounded-lg relative flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-900 transition {buttonClassName}"
 			>
 				<button class="w-full py-1.5 pl-2 flex items-center gap-1.5 text-xs font-medium">
 					{#if chevron}
-						<div class="text-gray-300 dark:text-gray-600 p-[1px]">
+						<div class=" p-[1px]">
 							{#if open}
-								<ChevronDown className=" size-3.5" strokeWidth="2.5" />
+								<ChevronDown className=" size-3" strokeWidth="2" />
 							{:else}
-								<ChevronRight className=" size-3.5" strokeWidth="2.5" />
+								<ChevronRight className=" size-3" strokeWidth="2" />
 							{/if}
 						</div>
 					{/if}
 
-					<div class="translate-y-[0.5px]">
+					<div class="translate-y-[0.5px] {chevron ? '' : 'pl-1'}">
 						{name}
 					</div>
 				</button>

+ 104 - 102
src/lib/components/layout/Sidebar.svelte

@@ -871,14 +871,42 @@
 					</Folder>
 				{/if}
 
+				{#if folders}
+					<Folder
+						className="px-2 mt-0.5"
+						name={$i18n.t('Folders')}
+						chevron={false}
+						dragAndDrop={false}
+						onAdd={() => {
+							showCreateFolderModal = true;
+						}}
+						onAddLabel={$i18n.t('New Folder')}
+					>
+						<Folders
+							{folders}
+							{shiftKey}
+							onDelete={(folderId) => {
+								selectedFolder.set(null);
+								initChatList();
+							}}
+							on:update={() => {
+								initChatList();
+							}}
+							on:import={(e) => {
+								const { folderId, items } = e.detail;
+								importChatHandler(items, false, folderId);
+							}}
+							on:change={async () => {
+								initChatList();
+							}}
+						/>
+					</Folder>
+				{/if}
+
 				<Folder
 					className="px-2 mt-0.5"
 					name={$i18n.t('Chats')}
 					chevron={false}
-					onAdd={() => {
-						showCreateFolderModal = true;
-					}}
-					onAddLabel={$i18n.t('New Folder')}
 					on:change={async (e) => {
 						selectedFolder.set(null);
 						await goto('/');
@@ -940,115 +968,89 @@
 						}
 					}}
 				>
-					{#if folders || $pinnedChats.length > 0}
+					{#if $pinnedChats.length > 0}
 						<div class="mb-1">
-							{#if folders}
-								<Folders
-									{folders}
-									{shiftKey}
-									onDelete={(folderId) => {
-										selectedFolder.set(null);
-										initChatList();
-									}}
-									on:update={() => {
-										initChatList();
+							<div class="flex flex-col space-y-1 rounded-xl">
+								<Folder
+									buttonClassName=" text-gray-500"
+									bind:open={showPinnedChat}
+									on:change={(e) => {
+										localStorage.setItem('showPinnedChat', e.detail);
+										console.log(e.detail);
 									}}
 									on:import={(e) => {
-										const { folderId, items } = e.detail;
-										importChatHandler(items, false, folderId);
-									}}
-									on:change={async () => {
-										initChatList();
+										importChatHandler(e.detail, true);
 									}}
-								/>
-							{/if}
+									on:drop={async (e) => {
+										const { type, id, item } = e.detail;
+
+										if (type === 'chat') {
+											let chat = await getChatById(localStorage.token, id).catch((error) => {
+												return null;
+											});
+											if (!chat && item) {
+												chat = await importChat(
+													localStorage.token,
+													item.chat,
+													item?.meta ?? {},
+													false,
+													null,
+													item?.created_at ?? null,
+													item?.updated_at ?? null
+												);
+											}
 
-							{#if $pinnedChats.length > 0}
-								<div class="flex flex-col space-y-1 rounded-xl">
-									<Folder
-										className=""
-										bind:open={showPinnedChat}
-										on:change={(e) => {
-											localStorage.setItem('showPinnedChat', e.detail);
-											console.log(e.detail);
-										}}
-										on:import={(e) => {
-											importChatHandler(e.detail, true);
-										}}
-										on:drop={async (e) => {
-											const { type, id, item } = e.detail;
-
-											if (type === 'chat') {
-												let chat = await getChatById(localStorage.token, id).catch((error) => {
-													return null;
-												});
-												if (!chat && item) {
-													chat = await importChat(
+											if (chat) {
+												console.log(chat);
+												if (chat.folder_id) {
+													const res = await updateChatFolderIdById(
 														localStorage.token,
-														item.chat,
-														item?.meta ?? {},
-														false,
-														null,
-														item?.created_at ?? null,
-														item?.updated_at ?? null
-													);
+														chat.id,
+														null
+													).catch((error) => {
+														toast.error(`${error}`);
+														return null;
+													});
 												}
 
-												if (chat) {
-													console.log(chat);
-													if (chat.folder_id) {
-														const res = await updateChatFolderIdById(
-															localStorage.token,
-															chat.id,
-															null
-														).catch((error) => {
-															toast.error(`${error}`);
-															return null;
-														});
-													}
-
-													if (!chat.pinned) {
-														const res = await toggleChatPinnedStatusById(
-															localStorage.token,
-															chat.id
-														);
-													}
-
-													initChatList();
+												if (!chat.pinned) {
+													const res = await toggleChatPinnedStatusById(localStorage.token, chat.id);
 												}
+
+												initChatList();
 											}
-										}}
-										name={$i18n.t('Pinned')}
+										}
+									}}
+									name={$i18n.t('Pinned')}
+								>
+									<div
+										class="ml-3 pl-1 mt-[1px] flex flex-col overflow-y-auto scrollbar-hidden border-s border-gray-100 dark:border-gray-900 text-gray-900 dark:text-gray-200"
 									>
-										<div
-											class="ml-3 pl-1 mt-[1px] flex flex-col overflow-y-auto scrollbar-hidden border-s border-gray-100 dark:border-gray-900"
-										>
-											{#each $pinnedChats as chat, idx (`pinned-chat-${chat?.id ?? idx}`)}
-												<ChatItem
-													className=""
-													id={chat.id}
-													title={chat.title}
-													{shiftKey}
-													selected={selectedChatId === chat.id}
-													on:select={() => {
-														selectedChatId = chat.id;
-													}}
-													on:unselect={() => {
-														selectedChatId = null;
-													}}
-													on:change={async () => {
-														initChatList();
-													}}
-													on:tag={(e) => {
-														const { type, name } = e.detail;
-														tagEventHandler(type, name, chat.id);
-													}}
-												/>
-											{/each}
-										</div>
-									</Folder>
-								</div>
-							{/if}
+										{#each $pinnedChats as chat, idx (`pinned-chat-${chat?.id ?? idx}`)}
+											<ChatItem
+												className=""
+												id={chat.id}
+												title={chat.title}
+												{shiftKey}
+												selected={selectedChatId === chat.id}
+												on:select={() => {
+													selectedChatId = chat.id;
+												}}
+												on:unselect={() => {
+													selectedChatId = null;
+												}}
+												on:change={async () => {
+													initChatList();
+												}}
+												on:tag={(e) => {
+													const { type, name } = e.detail;
+													tagEventHandler(type, name, chat.id);
+												}}
+											/>
+										{/each}
+									</div>
+								</Folder>
+							</div>
 						</div>
 					{/if}
 

+ 6 - 6
src/lib/components/layout/Sidebar/RecursiveFolder.svelte

@@ -464,7 +464,7 @@
 				}}
 			>
 				<button
-					class="text-gray-500 dark:text-gray-500 transition-all p-[3px] hover:bg-gray-200 dark:hover:bg-gray-850 rounded-lg"
+					class="text-gray-500 dark:text-gray-500 transition-all p-1 hover:bg-gray-200 dark:hover:bg-gray-850 rounded-lg"
 					on:click={(e) => {
 						e.stopPropagation();
 						open = !open;
@@ -472,22 +472,22 @@
 				>
 					{#if folders[folderId]?.meta?.icon}
 						<div class="flex group-hover:hidden transition-all">
-							<Emoji className="size-4" shortCode={folders[folderId].meta.icon} />
+							<Emoji className="size-3.5" shortCode={folders[folderId].meta.icon} />
 						</div>
 
 						<div class="hidden group-hover:flex transition-all p-[1px]">
 							{#if open}
-								<ChevronDown className=" size-3.5" strokeWidth="2.5" />
+								<ChevronDown className=" size-3" strokeWidth="2.5" />
 							{:else}
-								<ChevronRight className=" size-3.5" strokeWidth="2.5" />
+								<ChevronRight className=" size-3" strokeWidth="2.5" />
 							{/if}
 						</div>
 					{:else}
 						<div class="p-[1px]">
 							{#if open}
-								<ChevronDown className=" size-3.5" strokeWidth="2.5" />
+								<ChevronDown className=" size-3" strokeWidth="2.5" />
 							{:else}
-								<ChevronRight className=" size-3.5" strokeWidth="2.5" />
+								<ChevronRight className=" size-3" strokeWidth="2.5" />
 							{/if}
 						</div>
 					{/if}