Skip to content

Commit

Permalink
♻️ refactor: refactor the setting storage from localStorage to indexe…
Browse files Browse the repository at this point in the history
…dDB (#1180)

* 🚧 wip: add user schema

* ♻️ refactor: refactor the copy with new api

* ♻️ refactor: refactor a preference slice

* ♻️ refactor: refactor the settings store

* ✅ test: fix test

* 🎨 chore: clean code

* 🎨 chore: clean code

* 🎨 chore: clean code

* 🎨 chore: clean code

* 🐛 fix: fix update default agent

* 🐛 fix: fix update default agent
  • Loading branch information
arvinxx committed Jan 30, 2024
1 parent b72f842 commit 615e796
Show file tree
Hide file tree
Showing 66 changed files with 1,395 additions and 662 deletions.
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,12 @@
"antd-style": "^3",
"brotli-wasm": "^2",
"chroma-js": "^2",
"copy-to-clipboard": "^3",
"dayjs": "^1",
"dexie": "^3",
"fast-deep-equal": "^3",
"gpt-tokenizer": "^2",
"i18next": "^23",
"i18next-browser-languagedetector": "^7",
"i18next-resources-for-ts": "^1",
"i18next-resources-to-backend": "^1",
"idb-keyval": "^6",
"immer": "^10",
Expand All @@ -111,7 +109,6 @@
"react-dom": "^18",
"react-hotkeys-hook": "^4",
"react-i18next": "^14",
"react-intersection-observer": "^9",
"react-layout-kit": "^1",
"react-lazy-load": "^4",
"react-virtuoso": "^4.6.2",
Expand Down
4 changes: 3 additions & 1 deletion src/app/api/config/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export const runtime = 'edge';
export const GET = async () => {
const { CUSTOM_MODELS } = getServerConfig();

const config: GlobalServerConfig = { customModelName: CUSTOM_MODELS };
const config: GlobalServerConfig = {
customModelName: CUSTOM_MODELS,
};

return new Response(JSON.stringify(config));
};
3 changes: 2 additions & 1 deletion src/app/chat/(mobile)/features/SessionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { memo } from 'react';

import { MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
import { useGlobalStore } from '@/store/global';
import { commonSelectors } from '@/store/global/selectors';
import { useSessionStore } from '@/store/session';

export const useStyles = createStyles(({ css, token }) => ({
Expand All @@ -21,7 +22,7 @@ export const useStyles = createStyles(({ css, token }) => ({
const Header = memo(() => {
const [createSession] = useSessionStore((s) => [s.createSession]);
const router = useRouter();
const avatar = useGlobalStore((st) => st.settings.avatar);
const avatar = useGlobalStore(commonSelectors.userAvatar);
return (
<MobileNavBar
center={<Logo type={'text'} />}
Expand Down
3 changes: 2 additions & 1 deletion src/app/chat/features/ChatHeader/ShareButton/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Flexbox } from 'react-layout-kit';
import { FORM_STYLE } from '@/const/layoutTokens';
import { useChatStore } from '@/store/chat';
import { useGlobalStore } from '@/store/global';
import { commonSelectors } from '@/store/global/selectors';

import Preview from './Preview';
import { FieldType, ImageType } from './type';
Expand Down Expand Up @@ -48,7 +49,7 @@ const ShareModal = memo<ModalProps>(({ onCancel, open }) => {
const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
const [tab, setTab] = useState<Tab>(Tab.Screenshot);
const { t } = useTranslation('chat');
const avatar = useGlobalStore((s) => s.settings.avatar);
const avatar = useGlobalStore(commonSelectors.userAvatar);
const [shareLoading, shareToShareGPT] = useChatStore((s) => [s.shareLoading, s.shareToShareGPT]);
const { loading, onDownload, title } = useScreenshot(fieldValue.imageType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Flexbox } from 'react-layout-kit';
import { AGENTS_INDEX_GITHUB_ISSUE } from '@/const/url';
import AgentInfo from '@/features/AgentInfo';
import { useGlobalStore } from '@/store/global';
import { settingsSelectors } from '@/store/global/selectors';
import { useSessionStore } from '@/store/session';
import { agentSelectors } from '@/store/session/selectors';

Expand All @@ -20,7 +21,7 @@ const SubmitAgentModal = memo<ModalProps>(({ open, onCancel }) => {
const systemRole = useSessionStore(agentSelectors.currentAgentSystemRole);
const theme = useTheme();
const meta = useSessionStore(agentSelectors.currentAgentMeta, isEqual);
const language = useGlobalStore((s) => s.settings.language);
const language = useGlobalStore((s) => settingsSelectors.currentSettings(s).language);

const isMetaPass = Boolean(
meta && meta.title && meta.description && (meta.tags as string[])?.length > 0 && meta.avatar,
Expand Down
3 changes: 2 additions & 1 deletion src/app/settings/(mobile)/mobile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CURRENT_VERSION } from '@/const/version';
import AvatarWithUpload from '@/features/AvatarWithUpload';
import { useGlobalStore, useSwitchSideBarOnInit } from '@/store/global';
import { SidebarTabKey } from '@/store/global/initialState';
import { commonSelectors } from '@/store/global/selectors';

import List from '../../features/SideBar/List';
import AvatarBanner from '../features/AvatarBanner';
Expand All @@ -28,7 +29,7 @@ const useStyles = createStyles(({ css, token }) => ({

const Setting = memo(() => {
useSwitchSideBarOnInit(SidebarTabKey.Setting);
const avatar = useGlobalStore((s) => s.settings.avatar);
const avatar = useGlobalStore(commonSelectors.userAvatar);
const { styles } = useStyles();

return (
Expand Down
17 changes: 14 additions & 3 deletions src/app/settings/common/Common.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Form, type ItemGroup, SelectWithImg, SliderWithInput } from '@lobehub/ui';
import { Form as AntForm, App, Button, Input, Select } from 'antd';
import isEqual from 'fast-deep-equal';
import { debounce } from 'lodash-es';
import { AppWindow, Monitor, Moon, Palette, Sun } from 'lucide-react';
import { memo, useCallback } from 'react';
import { memo, useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';

import { FORM_STYLE } from '@/const/layoutTokens';
Expand Down Expand Up @@ -222,12 +221,24 @@ const Common = memo<SettingsCommonProps>(({ showAccessCodeConfig }) => {
title: t('settingSystem.title'),
};

useEffect(() => {
const unsubscribe = useGlobalStore.subscribe(
(s) => s.settings,
(settings) => {
form.setFieldsValue(settings);
},
);
return () => {
unsubscribe();
};
}, []);

return (
<Form
form={form}
initialValues={settings}
items={[theme, system]}
onValuesChange={debounce(setSettings, 100)}
onValuesChange={setSettings}
{...FORM_STYLE}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {
import { memo } from 'react';

import { useGlobalStore } from '@/store/global';
import { settingsSelectors } from '@/store/global/selectors';

const ThemeSwatchesNeutral = memo(() => {
const [neutralColor, setSettings] = useGlobalStore((s) => [
s.settings.neutralColor,
settingsSelectors.currentSettings(s).neutralColor,
s.setSettings,
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {
import { memo } from 'react';

import { useGlobalStore } from '@/store/global';
import { settingsSelectors } from '@/store/global/selectors';

const ThemeSwatchesPrimary = memo(() => {
const [primaryColor, setSettings] = useGlobalStore((s) => [
s.settings.primaryColor,
settingsSelectors.currentSettings(s).primaryColor,
s.setSettings,
]);

Expand Down
27 changes: 17 additions & 10 deletions src/app/settings/llm/LLM/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { Form as AntForm, AutoComplete, Input, Switch } from 'antd';
import { createStyles } from 'antd-style';
import { debounce } from 'lodash-es';
import { Webhook } from 'lucide-react';
import { memo } from 'react';
import { memo, useEffect } from 'react';
import { useTranslation } from 'react-i18next';

import { FORM_STYLE } from '@/const/layoutTokens';
import { useEffectAfterGlobalHydrated, useGlobalStore } from '@/store/global';
import { settingsSelectors } from '@/store/global/selectors';
import { useGlobalStore } from '@/store/global';
import { modelProviderSelectors } from '@/store/global/selectors';

import Checker from './Checker';

Expand All @@ -35,16 +35,23 @@ const LLM = memo(() => {
const { t } = useTranslation('setting');
const [form] = AntForm.useForm();
const { styles } = useStyles();
const [setSettings] = useGlobalStore((s) => [s.setSettings]);
const [useAzure, setSettings] = useGlobalStore((s) => [
modelProviderSelectors.enableAzure(s),
s.setSettings,
]);

useEffectAfterGlobalHydrated((store) => {
const settings = settingsSelectors.currentSettings(store.getState());

form.setFieldsValue(settings);
useEffect(() => {
const unsubscribe = useGlobalStore.subscribe(
(s) => s.settings,
(settings) => {
form.setFieldsValue(settings);
},
);
return () => {
unsubscribe();
};
}, []);

const useAzure = useGlobalStore((s) => s.settings.languageModel.openAI.useAzure);

const openAI: ItemGroup = {
children: [
{
Expand Down
1 change: 0 additions & 1 deletion src/const/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
} from '@/types/settings';

export const DEFAULT_BASE_SETTINGS: GlobalBaseSettings = {
avatar: '',
fontSize: 14,
language: 'auto',
password: '',
Expand Down
43 changes: 41 additions & 2 deletions src/database/core/db.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import Dexie, { Transaction } from 'dexie';

import { DBModel, LOBE_CHAT_LOCAL_DB_NAME } from '@/database/core/types/db';
import { DB_File } from '@/database/schemas/files';
import { DB_Message } from '@/database/schemas/message';
import { DB_Plugin } from '@/database/schemas/plugin';
import { DB_Session } from '@/database/schemas/session';
import { DB_SessionGroup } from '@/database/schemas/sessionGroup';
import { DB_Topic } from '@/database/schemas/topic';
import { DB_User } from '@/database/schemas/user';

import { dbSchemaV1, dbSchemaV2, dbSchemaV3, dbSchemaV4 } from './schemas';
import { migrateSettingsToUser } from './migrations/migrateSettingsToUser';
import { dbSchemaV1, dbSchemaV2, dbSchemaV3, dbSchemaV4, dbSchemaV5 } from './schemas';
import { DBModel, LOBE_CHAT_LOCAL_DB_NAME } from './types/db';

interface LobeDBSchemaMap {
files: DB_File;
Expand All @@ -17,6 +19,7 @@ interface LobeDBSchemaMap {
sessionGroups: DB_SessionGroup;
sessions: DB_Session;
topics: DB_Topic;
users: DB_User;
}

// Define a local DB
Expand All @@ -27,6 +30,7 @@ export class LocalDB extends Dexie {
public topics: LobeDBTable<'topics'>;
public plugins: LobeDBTable<'plugins'>;
public sessionGroups: LobeDBTable<'sessionGroups'>;
public users: LobeDBTable<'users'>;

constructor() {
super(LOBE_CHAT_LOCAL_DB_NAME);
Expand All @@ -37,12 +41,17 @@ export class LocalDB extends Dexie {
.stores(dbSchemaV4)
.upgrade((trans) => this.upgradeToV4(trans));

this.version(5)
.stores(dbSchemaV5)
.upgrade((trans) => this.upgradeToV5(trans));

this.files = this.table('files');
this.sessions = this.table('sessions');
this.messages = this.table('messages');
this.topics = this.table('topics');
this.plugins = this.table('plugins');
this.sessionGroups = this.table('sessionGroups');
this.users = this.table('users');
}

/**
Expand All @@ -59,6 +68,36 @@ export class LocalDB extends Dexie {
session.group = 'default';
});
};

/**
* 2024.01.29
* settings from localStorage to indexedDB
*/
upgradeToV5 = async (trans: Transaction) => {
const users = trans.table('users');

// if no user, create one
if ((await users.count()) === 0) {
const data = localStorage.getItem('LOBE_SETTINGS');

if (data) {
let json;

try {
json = JSON.parse(data);
} catch {
/* empty */
}

if (!json?.state?.settings) return;

const settings = json.state.settings;

const user = migrateSettingsToUser(settings);
await users.add(user);
}
}
};
}

export const LocalDBInstance = new LocalDB();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"avatar": "",
"defaultAgent": {
"config": {
"autoCreateTopicThreshold": 2,
"displayMode": "chat",
"enableAutoCreateTopic": true,
"historyCount": 1,
"model": "gpt-3.5-turbo-1106",
"params": {
"frequency_penalty": 0,
"presence_penalty": 0,
"temperature": 0.7,
"top_p": 0.7
},
"plugins": ["website-crawler"],
"systemRole": "",
"tts": {
"showAllLocaleVoice": false,
"sttLocale": "auto",
"ttsService": "openai",
"voice": { "openai": "alloy" }
},
"enableHistoryCount": true
},
"meta": {}
},
"fontSize": 14,
"language": "auto",
"languageModel": {
"openAI": {
"OPENAI_API_KEY": "dfdf",
"models": [
"gpt-3.5-turbo",
"gpt-3.5-turbo-1106",
"gpt-3.5-turbo-16k",
"gpt-4",
"gpt-4-32k",
"gpt-4-1106-preview",
"gpt-4-vision-preview"
],
"customModelName": "+glm-4,+glm-4v",
"endpoint": "sdaddsd"
},
"zhipu": { "ZHIPU_API_KEY": "", "enabled": false }
},
"password": "",
"themeMode": "auto",
"tool": { "dalle": { "autoGenerate": false } },
"tts": {
"openAI": { "sttModel": "whisper-1", "ttsModel": "tts-1" },
"sttAutoStop": true,
"sttServer": "openai"
}
}
Loading

0 comments on commit 615e796

Please sign in to comment.