mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-05-19 20:20:16 +09:00
大幅优化同步
This commit is contained in:
parent
88f8ca822f
commit
3bc977cebd
@ -83,7 +83,12 @@ export class GeminiProApi implements LLMApi {
|
|||||||
}
|
}
|
||||||
const messages = _messages.map((v) => {
|
const messages = _messages.map((v) => {
|
||||||
let parts: any[] = [{ text: getMessageTextContent(v) }];
|
let parts: any[] = [{ text: getMessageTextContent(v) }];
|
||||||
if (isVisionModel(options.config.model, accessStore.visionModels)) {
|
if (
|
||||||
|
isVisionModel(
|
||||||
|
options.config.model,
|
||||||
|
useAccessStore.getState().visionModels,
|
||||||
|
)
|
||||||
|
) {
|
||||||
const images = getMessageImages(v);
|
const images = getMessageImages(v);
|
||||||
if (images.length > 0) {
|
if (images.length > 0) {
|
||||||
multimodal = true;
|
multimodal = true;
|
||||||
|
@ -1167,6 +1167,7 @@ function _Chat() {
|
|||||||
|
|
||||||
const onDelete = (msgId: string) => {
|
const onDelete = (msgId: string) => {
|
||||||
deleteMessage(msgId);
|
deleteMessage(msgId);
|
||||||
|
syncStore.upload();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onResend = (message: ChatMessage) => {
|
const onResend = (message: ChatMessage) => {
|
||||||
|
@ -28,6 +28,7 @@ import { AuthPage } from "./auth";
|
|||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
import { type ClientApi, getClientApi } from "../client/api";
|
import { type ClientApi, getClientApi } from "../client/api";
|
||||||
import { useAccessStore } from "../store";
|
import { useAccessStore } from "../store";
|
||||||
|
import { useSyncStore } from "../store/sync";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
export function Loading(props: { noLogo?: boolean }) {
|
export function Loading(props: { noLogo?: boolean }) {
|
||||||
@ -239,6 +240,8 @@ export function Home() {
|
|||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useSyncStore.getState().download();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Router>
|
<Router>
|
||||||
|
@ -534,7 +534,22 @@ function SyncItems() {
|
|||||||
text={Locale.UI.Overwrite}
|
text={Locale.UI.Overwrite}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
await syncStore.overwrite();
|
await syncStore.upload();
|
||||||
|
showToast(Locale.Settings.Sync.Success);
|
||||||
|
} catch (e) {
|
||||||
|
showToast(Locale.Settings.Sync.Fail);
|
||||||
|
console.error("[Sync]", e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{couldSync && (
|
||||||
|
<IconButton
|
||||||
|
icon={<DownloadIcon />}
|
||||||
|
text={Locale.UI.Overwrite}
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
await syncStore.download();
|
||||||
showToast(Locale.Settings.Sync.Success);
|
showToast(Locale.Settings.Sync.Success);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showToast(Locale.Settings.Sync.Fail);
|
showToast(Locale.Settings.Sync.Fail);
|
||||||
@ -1408,7 +1423,10 @@ export function Settings() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
aria={Locale.UI.Close}
|
aria={Locale.UI.Close}
|
||||||
icon={<CloseIcon />}
|
icon={<CloseIcon />}
|
||||||
onClick={() => navigate(Path.Home)}
|
onClick={() => {
|
||||||
|
navigate(Path.Home);
|
||||||
|
useSyncStore.getState().sync();
|
||||||
|
}}
|
||||||
bordered
|
bordered
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,6 +29,7 @@ import { ModelConfig, ModelType, useAppConfig } from "./config";
|
|||||||
import { useAccessStore } from "./access";
|
import { useAccessStore } from "./access";
|
||||||
import { collectModelsWithDefaultModel } from "../utils/model";
|
import { collectModelsWithDefaultModel } from "../utils/model";
|
||||||
import { createEmptyMask, Mask } from "./mask";
|
import { createEmptyMask, Mask } from "./mask";
|
||||||
|
import { useSyncStore } from "./sync";
|
||||||
|
|
||||||
const localStorage = safeLocalStorage();
|
const localStorage = safeLocalStorage();
|
||||||
|
|
||||||
@ -226,6 +227,8 @@ export const useChatStore = createPersistStore(
|
|||||||
currentSessionIndex: 0,
|
currentSessionIndex: 0,
|
||||||
sessions: [newSession, ...state.sessions],
|
sessions: [newSession, ...state.sessions],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
},
|
},
|
||||||
|
|
||||||
clearSessions() {
|
clearSessions() {
|
||||||
@ -233,6 +236,8 @@ export const useChatStore = createPersistStore(
|
|||||||
sessions: [createEmptySession()],
|
sessions: [createEmptySession()],
|
||||||
currentSessionIndex: 0,
|
currentSessionIndex: 0,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
},
|
},
|
||||||
|
|
||||||
selectSession(index: number) {
|
selectSession(index: number) {
|
||||||
@ -264,6 +269,8 @@ export const useChatStore = createPersistStore(
|
|||||||
sessions: newSessions,
|
sessions: newSessions,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
},
|
},
|
||||||
|
|
||||||
newSession(mask?: Mask) {
|
newSession(mask?: Mask) {
|
||||||
@ -327,6 +334,8 @@ export const useChatStore = createPersistStore(
|
|||||||
sessions,
|
sessions,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
|
|
||||||
showToast(
|
showToast(
|
||||||
Locale.Home.DeleteToast,
|
Locale.Home.DeleteToast,
|
||||||
{
|
{
|
||||||
@ -433,6 +442,8 @@ export const useChatStore = createPersistStore(
|
|||||||
get().onNewMessage(botMessage, session);
|
get().onNewMessage(botMessage, session);
|
||||||
}
|
}
|
||||||
ChatControllerPool.remove(session.id, botMessage.id);
|
ChatControllerPool.remove(session.id, botMessage.id);
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
},
|
},
|
||||||
onBeforeTool(tool: ChatMessageTool) {
|
onBeforeTool(tool: ChatMessageTool) {
|
||||||
(botMessage.tools = botMessage?.tools || []).push(tool);
|
(botMessage.tools = botMessage?.tools || []).push(tool);
|
||||||
@ -727,8 +738,10 @@ export const useChatStore = createPersistStore(
|
|||||||
console.log("[Memory] ", message);
|
console.log("[Memory] ", message);
|
||||||
get().updateTargetSession(session, (session) => {
|
get().updateTargetSession(session, (session) => {
|
||||||
session.lastSummarizeIndex = lastSummarizeIndex;
|
session.lastSummarizeIndex = lastSummarizeIndex;
|
||||||
session.memoryPrompt = message; // Update the memory prompt for stored it in local storage
|
session.memoryPrompt = message;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useSyncStore.getState().upload();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError(err) {
|
onError(err) {
|
||||||
|
@ -22,6 +22,12 @@ export interface WebDavConfig {
|
|||||||
const isApp = !!getClientConfig()?.isApp;
|
const isApp = !!getClientConfig()?.isApp;
|
||||||
export type SyncStore = GetStoreState<typeof useSyncStore>;
|
export type SyncStore = GetStoreState<typeof useSyncStore>;
|
||||||
|
|
||||||
|
export enum SyncAction {
|
||||||
|
SYNC = "SYNC",
|
||||||
|
UPLOAD = "UPLOAD",
|
||||||
|
DOWNLOAD = "DOWNLOAD",
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_SYNC_STATE = {
|
const DEFAULT_SYNC_STATE = {
|
||||||
provider: ProviderType.WebDAV,
|
provider: ProviderType.WebDAV,
|
||||||
useProxy: true,
|
useProxy: true,
|
||||||
@ -88,41 +94,75 @@ export const useSyncStore = createPersistStore(
|
|||||||
return client;
|
return client;
|
||||||
},
|
},
|
||||||
|
|
||||||
async sync(overwrite = false) {
|
async sync(action: SyncAction = SyncAction.SYNC) {
|
||||||
|
if (!(await this.hasAccount())) {
|
||||||
|
console.log("[Sync] No account found, skipping sync.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const localState = getLocalAppState();
|
const localState = getLocalAppState();
|
||||||
const provider = get().provider;
|
const provider = get().provider;
|
||||||
const config = get()[provider];
|
const config = get()[provider];
|
||||||
const client = this.getClient();
|
const client = this.getClient();
|
||||||
|
|
||||||
try {
|
if (action === SyncAction.SYNC) {
|
||||||
const remoteState = await client.get(config.username);
|
console.log("[Sync] Syncing state", config.username);
|
||||||
if (!remoteState || remoteState === "") {
|
try {
|
||||||
await client.set(config.username, JSON.stringify(localState));
|
const remoteState = await client.get(config.username);
|
||||||
console.log(
|
if (!remoteState || remoteState === "") {
|
||||||
"[Sync] Remote state is empty, using local state instead.",
|
await client.set(config.username, JSON.stringify(localState));
|
||||||
);
|
console.log(
|
||||||
return;
|
"[Sync] Remote state is empty, using local state instead.",
|
||||||
} else {
|
);
|
||||||
if (!overwrite) {
|
return;
|
||||||
|
} else {
|
||||||
const parsedRemoteState = JSON.parse(
|
const parsedRemoteState = JSON.parse(
|
||||||
await client.get(config.username),
|
await client.get(config.username),
|
||||||
) as AppState;
|
) as AppState;
|
||||||
mergeAppState(localState, parsedRemoteState);
|
mergeAppState(localState, parsedRemoteState);
|
||||||
setLocalAppState(localState);
|
setLocalAppState(localState);
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("[Sync] failed to get remote state", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
await client.set(config.username, JSON.stringify(localState));
|
||||||
|
} else if (action === SyncAction.UPLOAD) {
|
||||||
|
console.log("[Sync] Uploading state", localState);
|
||||||
|
await client.set(config.username, JSON.stringify(localState));
|
||||||
|
} else if (action === SyncAction.DOWNLOAD) {
|
||||||
|
console.log("[Sync] Downloading state", config.username);
|
||||||
|
const remoteState = await client.get(config.username);
|
||||||
|
if (!remoteState || remoteState === "") {
|
||||||
|
console.log(
|
||||||
|
"[Sync] Remote state is empty, using local state instead.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const parsedRemoteState = JSON.parse(remoteState) as AppState;
|
||||||
|
setLocalAppState(parsedRemoteState);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.log("[Sync] failed to get remote state", e);
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.set(config.username, JSON.stringify(localState));
|
|
||||||
|
|
||||||
this.markSyncTime();
|
this.markSyncTime();
|
||||||
},
|
},
|
||||||
|
|
||||||
async overwrite() {
|
async download() {
|
||||||
await this.sync(true);
|
await this.sync(SyncAction.DOWNLOAD);
|
||||||
|
},
|
||||||
|
|
||||||
|
async upload() {
|
||||||
|
await this.sync(SyncAction.UPLOAD);
|
||||||
|
},
|
||||||
|
|
||||||
|
async hasAccount() {
|
||||||
|
const provider = get().provider;
|
||||||
|
const config = get()[provider] as any;
|
||||||
|
console.log("[Sync] hasAccount", provider, config);
|
||||||
|
// console.log("[Sync] hasAccount", !!(provider === ProviderType.WebDAV ? config.username && config.password : config.username && config.apiKey));
|
||||||
|
return provider === ProviderType.WebDAV
|
||||||
|
? config.username && config.password
|
||||||
|
: config.username && config.apiKey;
|
||||||
},
|
},
|
||||||
|
|
||||||
async check() {
|
async check() {
|
||||||
|
Loading…
Reference in New Issue
Block a user