enh/feat: persist folder state

Co-Authored-By: G30 <50341825+silentoplayz@users.noreply.github.com>
This commit is contained in:
Timothy Jaeryang Baek
2025-11-19 01:20:07 -05:00
parent bbd48b3638
commit 7e03637446
2 changed files with 76 additions and 68 deletions

View File

@@ -26,6 +26,7 @@
export let dragAndDrop = true;
let folderElement;
let loaded = false;
let draggedOver = false;
@@ -103,6 +104,13 @@
};
onMount(() => {
const state = localStorage.getItem(`${id}-folder-state`);
if (state !== null) {
open = state === 'true';
}
loaded = true;
if (!dragAndDrop) {
return;
}
@@ -122,70 +130,73 @@
</script>
<div bind:this={folderElement} class="relative {className}">
{#if draggedOver}
<div
class="absolute top-0 left-0 w-full h-full rounded-xs bg-gray-100/50 dark:bg-gray-700/20 bg-opacity-50 dark:bg-opacity-10 z-50 pointer-events-none touch-none"
></div>
{/if}
{#if collapsible}
<Collapsible
bind:open
className="w-full "
buttonClassName="w-full"
onChange={(state) => {
dispatch('change', state);
}}
>
<!-- svelte-ignore a11y-no-static-element-interactions -->
{#if loaded}
{#if draggedOver}
<div
id="sidebar-folder-button"
class=" w-full group rounded-xl relative flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-900 transition {buttonClassName}"
class="absolute top-0 left-0 w-full h-full rounded-xs bg-gray-100/50 dark:bg-gray-700/20 bg-opacity-50 dark:bg-opacity-10 z-50 pointer-events-none touch-none"
></div>
{/if}
{#if collapsible}
<Collapsible
bind:open
className="w-full "
buttonClassName="w-full"
onChange={(state) => {
dispatch('change', state);
localStorage.setItem(`${id}-folder-state`, `${state}`);
}}
>
<button class="w-full py-1.5 pl-2 flex items-center gap-1.5 text-xs font-medium">
{#if chevron}
<div class=" p-[1px]">
{#if open}
<ChevronDown className=" size-3" strokeWidth="2" />
{:else}
<ChevronRight className=" size-3" strokeWidth="2" />
{/if}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
id="sidebar-folder-button"
class=" w-full group rounded-xl 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=" p-[1px]">
{#if open}
<ChevronDown className=" size-3" strokeWidth="2" />
{:else}
<ChevronRight className=" size-3" strokeWidth="2" />
{/if}
</div>
{/if}
<div class="translate-y-[0.5px] {chevron ? '' : 'pl-0.5'}">
{name}
</div>
{/if}
<div class="translate-y-[0.5px] {chevron ? '' : 'pl-0.5'}">
{name}
</div>
</button>
{#if onAdd}
<button
class="absolute z-10 right-2 invisible group-hover:visible self-center flex items-center dark:text-gray-300"
on:pointerup={(e) => {
e.stopPropagation();
}}
on:click={(e) => {
e.stopPropagation();
onAdd();
}}
>
<Tooltip content={onAddLabel}>
<button
class="p-0.5 dark:hover:bg-gray-850 rounded-lg touch-auto"
on:click={(e) => {}}
>
<Plus className=" size-3" strokeWidth="2.5" />
</button>
</Tooltip>
</button>
{/if}
</div>
<div slot="content" class="w-full">
<slot></slot>
</div>
</Collapsible>
{:else}
<slot></slot>
{#if onAdd}
<button
class="absolute z-10 right-2 invisible group-hover:visible self-center flex items-center dark:text-gray-300"
on:pointerup={(e) => {
e.stopPropagation();
}}
on:click={(e) => {
e.stopPropagation();
onAdd();
}}
>
<Tooltip content={onAddLabel}>
<button
class="p-0.5 dark:hover:bg-gray-850 rounded-lg touch-auto"
on:click={(e) => {}}
>
<Plus className=" size-3" strokeWidth="2.5" />
</button>
</Tooltip>
</button>
{/if}
</div>
<div slot="content" class="w-full">
<slot></slot>
</div>
</Collapsible>
{:else}
<slot></slot>
{/if}
{/if}
</div>

View File

@@ -72,8 +72,6 @@
let shiftKey = false;
let selectedChatId = null;
let showPinnedChat = true;
let showCreateChannel = false;
// Pagination variables
@@ -354,7 +352,6 @@
let unsubscribers = [];
onMount(async () => {
showPinnedChat = localStorage?.showPinnedChat ? localStorage.showPinnedChat === 'true' : true;
await showSidebar.set(!$mobile ? localStorage.sidebar === 'true' : false);
unsubscribers = [
@@ -892,6 +889,7 @@
{#if ($models ?? []).length > 0 && ($settings?.pinnedModels ?? []).length > 0}
<Folder
id="sidebar-models"
className="px-2 mt-0.5"
name={$i18n.t('Models')}
chevron={false}
@@ -903,6 +901,7 @@
{#if $config?.features?.enable_channels && ($user?.role === 'admin' || $channels.length > 0)}
<Folder
id="sidebar-channels"
className="px-2 mt-0.5"
name={$i18n.t('Channels')}
chevron={false}
@@ -931,6 +930,7 @@
{#if folders}
<Folder
id="sidebar-folders"
className="px-2 mt-0.5"
name={$i18n.t('Folders')}
chevron={false}
@@ -982,6 +982,7 @@
{/if}
<Folder
id="sidebar-chats"
className="px-2 mt-0.5"
name={$i18n.t('Chats')}
chevron={false}
@@ -1051,12 +1052,8 @@
<div class="mb-1">
<div class="flex flex-col space-y-1 rounded-xl">
<Folder
id="sidebar-pinned-chats"
buttonClassName=" text-gray-500"
bind:open={showPinnedChat}
on:change={(e) => {
localStorage.setItem('showPinnedChat', e.detail);
console.log(e.detail);
}}
on:import={(e) => {
importChatHandler(e.detail, true);
}}