Skip to content

Commit

Permalink
Merged enricoros#158
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros authored and Britt committed Oct 17, 2023
1 parent aed2df4 commit c1ee215
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 34 deletions.
3 changes: 2 additions & 1 deletion src/apps/chat/components/applayout/ChatDrawerItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export function ChatDrawerItems(props: {

const hasChats = conversationIDs.length > 0;
const singleChat = conversationIDs.length === 1;
const softMaxReached = conversationIDs.length >= 50;

const closeDrawerMenu = () => setLayoutDrawerAnchor(null);

Expand Down Expand Up @@ -124,7 +125,7 @@ export function ChatDrawerItems(props: {
isActive={conversationId === props.conversationId}
isSingle={singleChat}
showSymbols={showSymbols}
maxChatMessages={(experimentalLabs || maxReached) ? maxChatMessages : 0}
maxChatMessages={(experimentalLabs || softMaxReached) ? maxChatMessages : 0}
conversationActivate={handleConversationActivate}
conversationDelete={handleConversationDelete}
/>)}
Expand Down
1 change: 0 additions & 1 deletion src/apps/chat/components/applayout/ChatMenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import FileDownloadIcon from '@mui/icons-material/FileDownload';
import ForkRightIcon from '@mui/icons-material/ForkRight';
import SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest';

import { useChatStore } from '~/common/state/store-chats';
import { setLayoutMenuAnchor } from '~/common/layout/store-applayout';
import { useUIPreferencesStore } from '~/common/state/store-ui';

Expand Down
61 changes: 29 additions & 32 deletions src/common/state/store-chats.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { create } from 'zustand';
import { devtools, persist, createJSONStorage, StateStorage } from 'zustand/middleware';
import { get, set, del } from 'idb-keyval'
import { createJSONStorage, devtools, persist } from 'zustand/middleware';
import { v4 as uuidv4 } from 'uuid';

import { DLLMId } from '~/modules/llms/llm.types';
import { useModelsStore } from '~/modules/llms/store-llms';

import { countModelTokens } from '../util/token-counter';
import { defaultSystemPurposeId, SystemPurposeId } from '../../data';
import { idbStateStorage } from '../util/idbUtils';


/**
Expand Down Expand Up @@ -104,38 +104,9 @@ export function createDEphemeral(title: string, initialText: string): DEphemeral
};
}

const storage: StateStorage = {
getItem: async (name: string): Promise<string | null> => {
return (await get(name)) || null
},
setItem: async (name: string, value: string): Promise<void> => {
await set(name, value)
},
removeItem: async (name: string): Promise<void> => {
await del(name)
},
}

function _migrateLocalStorageToIndexedDB(state: ChatStore) {
const key = "app-chats"
const value = localStorage.getItem(key);

// Check if migration has already been done
if (!value) return state;

// Mark migration as done
localStorage.removeItem(key);

// Migrate data to IndexedDB
const localStorageState = JSON.parse(value)?.state;

state.conversations = localStorageState?.conversations;
state.activeConversationId = localStorageState?.activeConversationId;
}

/// Conversations Store


export interface ChatStore {
conversations: DConversation[];
activeConversationId: string | null;
Expand Down Expand Up @@ -434,7 +405,7 @@ export const useChatStore = create<ChatStore>()(devtools(
// - 2: [2023-04-10] multi-chat version - invalidating data to be sure
// - 3: [2023-08-30] switch to IndexedDB
version: 3,
storage: createJSONStorage(() => storage),
storage: createJSONStorage(() => idbStateStorage),

// omit the transient property from the persisted state
partialize: (state) => ({
Expand All @@ -450,7 +421,9 @@ export const useChatStore = create<ChatStore>()(devtools(

onRehydrateStorage: () => (state) => {
if (state) {
// one-time: move localStorage data (version: 2) to the 'state'
_migrateLocalStorageToIndexedDB(state);

// if nothing is selected, select the first conversation
if (!state.activeConversationId && state.conversations.length)
state.activeConversationId = state.conversations[0].id;
Expand All @@ -473,6 +446,30 @@ export const useChatStore = create<ChatStore>()(devtools(
}),
);

/**
* Migrate data from localStorage (version=2) to IndexedDB (version=3+)
* This is a one-time migration, and should be removed in the future
*/
function _migrateLocalStorageToIndexedDB(state: ChatStore) {
const key = 'app-chats';
const value = localStorage.getItem(key);

// Check if migration has already been done
if (!value) return;

// Migrate data to IndexedDB
try {
const localStorageState = JSON.parse(value)?.state;

// Mark migration as done
localStorage.removeItem(key);

state.conversations = localStorageState?.conversations ?? [];
state.activeConversationId = localStorageState?.activeConversationId ?? null;
} catch (e) {
console.error('Failed to migrate localStorage to IndexedDB', e);
}
}

/**
* Convenience function to count the tokens in a DMessage object
Expand Down
14 changes: 14 additions & 0 deletions src/common/util/idbUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { StateStorage } from 'zustand/middleware';
import { del, get, set } from 'idb-keyval';

export const idbStateStorage: StateStorage = {
getItem: async (name: string): Promise<string | null> => {
return (await get(name)) || null;
},
setItem: async (name: string, value: string): Promise<void> => {
await set(name, value);
},
removeItem: async (name: string): Promise<void> => {
await del(name);
},
};

0 comments on commit c1ee215

Please sign in to comment.