forked from XiaoMo/ChatGPT-Next-Web
feat: migrate state from v1 to v2
This commit is contained in:
parent
401c1364be
commit
30040a0366
@ -1,7 +1,10 @@
|
||||
import React from "react";
|
||||
import { IconButton } from "./button";
|
||||
import GithubIcon from "../icons/github.svg";
|
||||
import { ISSUE_URL } from "../constant";
|
||||
import ResetIcon from "../icons/reload.svg";
|
||||
import { ISSUE_URL, StoreKey } from "../constant";
|
||||
import Locale from "../locales";
|
||||
import { downloadAs } from "../utils";
|
||||
|
||||
interface IErrorBoundaryState {
|
||||
hasError: boolean;
|
||||
@ -20,6 +23,25 @@ export class ErrorBoundary extends React.Component<any, IErrorBoundaryState> {
|
||||
this.setState({ hasError: true, error, info });
|
||||
}
|
||||
|
||||
clearAndSaveData() {
|
||||
const snapshot: Record<string, any> = {};
|
||||
Object.values(StoreKey).forEach((key) => {
|
||||
snapshot[key] = localStorage.getItem(key);
|
||||
|
||||
if (snapshot[key]) {
|
||||
try {
|
||||
snapshot[key] = JSON.parse(snapshot[key]);
|
||||
} catch {}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
downloadAs(JSON.stringify(snapshot), "chatgpt-next-web-snapshot.json");
|
||||
} catch {}
|
||||
|
||||
localStorage.clear();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
// Render error message
|
||||
@ -31,6 +53,7 @@ export class ErrorBoundary extends React.Component<any, IErrorBoundaryState> {
|
||||
<code>{this.state.info?.componentStack}</code>
|
||||
</pre>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||||
<a href={ISSUE_URL} className="report">
|
||||
<IconButton
|
||||
text="Report This Error"
|
||||
@ -38,6 +61,15 @@ export class ErrorBoundary extends React.Component<any, IErrorBoundaryState> {
|
||||
bordered
|
||||
/>
|
||||
</a>
|
||||
<IconButton
|
||||
icon={<ResetIcon />}
|
||||
text="Clear All Data"
|
||||
onClick={() =>
|
||||
confirm(Locale.Store.ConfirmClearAll) && this.clearAndSaveData()
|
||||
}
|
||||
bordered
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -24,6 +24,15 @@ export enum FileName {
|
||||
Prompts = "prompts.json",
|
||||
}
|
||||
|
||||
export enum StoreKey {
|
||||
Chat = "chat-next-web-store",
|
||||
Access = "access-control",
|
||||
Config = "app-config",
|
||||
Mask = "mask-store",
|
||||
Prompt = "prompt-store",
|
||||
Update = "chat-update",
|
||||
}
|
||||
|
||||
export const MAX_SIDEBAR_WIDTH = 500;
|
||||
export const MIN_SIDEBAR_WIDTH = 230;
|
||||
export const NARROW_SIDEBAR_WIDTH = 100;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { StoreKey } from "../constant";
|
||||
|
||||
export interface AccessControlStore {
|
||||
accessCode: string;
|
||||
@ -14,8 +15,6 @@ export interface AccessControlStore {
|
||||
fetch: () => void;
|
||||
}
|
||||
|
||||
export const ACCESS_KEY = "access-control";
|
||||
|
||||
let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
|
||||
|
||||
export const useAccessStore = create<AccessControlStore>()(
|
||||
@ -62,7 +61,7 @@ export const useAccessStore = create<AccessControlStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: ACCESS_KEY,
|
||||
name: StoreKey.Access,
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
|
@ -13,6 +13,7 @@ import Locale from "../locales";
|
||||
import { showToast } from "../components/ui-lib";
|
||||
import { DEFAULT_CONFIG, ModelConfig, ModelType, useAppConfig } from "./config";
|
||||
import { createEmptyMask, Mask } from "./mask";
|
||||
import { StoreKey } from "../constant";
|
||||
|
||||
export type Message = ChatCompletionResponseMessage & {
|
||||
date: string;
|
||||
@ -109,8 +110,6 @@ function countMessages(msgs: Message[]) {
|
||||
return msgs.reduce((pre, cur) => pre + cur.content.length, 0);
|
||||
}
|
||||
|
||||
const LOCAL_KEY = "chat-next-web-store";
|
||||
|
||||
export const useChatStore = create<ChatStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
@ -489,16 +488,29 @@ export const useChatStore = create<ChatStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: LOCAL_KEY,
|
||||
name: StoreKey.Chat,
|
||||
version: 2,
|
||||
migrate(persistedState, version) {
|
||||
const state = persistedState as ChatStore;
|
||||
const state = persistedState as any;
|
||||
const newState = JSON.parse(JSON.stringify(state)) as ChatStore;
|
||||
|
||||
if (version < 2) {
|
||||
state.sessions.forEach((s) => (s.mask = createEmptyMask()));
|
||||
newState.globalId = 0;
|
||||
newState.sessions = [];
|
||||
|
||||
const oldSessions = state.sessions;
|
||||
for (const oldSession of oldSessions) {
|
||||
const newSession = createEmptySession();
|
||||
newSession.topic = oldSession.topic;
|
||||
newSession.messages = [...oldSession.messages];
|
||||
newSession.mask.modelConfig.sendMemory = true;
|
||||
newSession.mask.modelConfig.historyMessageCount = 4;
|
||||
newSession.mask.modelConfig.compressMessageLengthThreshold = 1000;
|
||||
newState.sessions.push(newSession);
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
return newState;
|
||||
},
|
||||
},
|
||||
),
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { StoreKey } from "../constant";
|
||||
|
||||
export enum SubmitKey {
|
||||
Enter = "Enter",
|
||||
@ -112,8 +113,6 @@ export const ModalConfigValidator = {
|
||||
},
|
||||
};
|
||||
|
||||
const CONFIG_KEY = "app-config";
|
||||
|
||||
export const useAppConfig = create<ChatConfigStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
@ -130,7 +129,18 @@ export const useAppConfig = create<ChatConfigStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: CONFIG_KEY,
|
||||
name: StoreKey.Config,
|
||||
version: 2,
|
||||
migrate(persistedState, version) {
|
||||
if (version === 2) return persistedState as any;
|
||||
|
||||
const state = persistedState as ChatConfig;
|
||||
state.modelConfig.sendMemory = true;
|
||||
state.modelConfig.historyMessageCount = 4;
|
||||
state.modelConfig.compressMessageLengthThreshold = 1000;
|
||||
|
||||
return state;
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -4,8 +4,7 @@ import { BUILTIN_MASKS } from "../masks";
|
||||
import { getLang, Lang } from "../locales";
|
||||
import { DEFAULT_TOPIC, Message } from "./chat";
|
||||
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
||||
|
||||
export const MASK_KEY = "mask-store";
|
||||
import { StoreKey } from "../constant";
|
||||
|
||||
export type Mask = {
|
||||
id: number;
|
||||
@ -93,7 +92,7 @@ export const useMaskStore = create<MaskStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: MASK_KEY,
|
||||
name: StoreKey.Mask,
|
||||
version: 2,
|
||||
},
|
||||
),
|
||||
|
@ -2,6 +2,7 @@ import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import Fuse from "fuse.js";
|
||||
import { getLang } from "../locales";
|
||||
import { StoreKey } from "../constant";
|
||||
|
||||
export interface Prompt {
|
||||
id?: number;
|
||||
@ -23,8 +24,6 @@ export interface PromptStore {
|
||||
updateUserPrompts: (id: number, updater: (prompt: Prompt) => void) => void;
|
||||
}
|
||||
|
||||
export const PROMPT_KEY = "prompt-store";
|
||||
|
||||
export const SearchService = {
|
||||
ready: false,
|
||||
builtinEngine: new Fuse<Prompt>([], { keys: ["title"] }),
|
||||
@ -123,7 +122,7 @@ export const usePromptStore = create<PromptStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: PROMPT_KEY,
|
||||
name: StoreKey.Prompt,
|
||||
version: 1,
|
||||
onRehydrateStorage(state) {
|
||||
const PROMPT_URL = "./prompts.json";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { FETCH_COMMIT_URL, FETCH_TAG_URL } from "../constant";
|
||||
import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant";
|
||||
import { requestUsage } from "../requests";
|
||||
|
||||
export interface UpdateStore {
|
||||
@ -16,8 +16,6 @@ export interface UpdateStore {
|
||||
updateUsage: (force?: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
export const UPDATE_KEY = "chat-update";
|
||||
|
||||
function queryMeta(key: string, defaultValue?: string): string {
|
||||
let ret: string;
|
||||
if (document) {
|
||||
@ -84,7 +82,7 @@ export const useUpdateStore = create<UpdateStore>()(
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: UPDATE_KEY,
|
||||
name: StoreKey.Update,
|
||||
version: 1,
|
||||
},
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user