diff --git a/app/components/settings.tsx b/app/components/settings.tsx
index 367784c5acf..d8ef6fab656 100644
--- a/app/components/settings.tsx
+++ b/app/components/settings.tsx
@@ -48,7 +48,11 @@ import Locale, {
changeLang,
getLang,
} from "../locales";
-import { copyToClipboard } from "../utils";
+import {
+ copyToClipboard,
+ downloadAs,
+ readFromFile,
+} from "../utils";
import Link from "next/link";
import {
Azure,
@@ -569,6 +573,154 @@ function SyncConfigModal(props: { onClose?: () => void }) {
);
}
+/**
+ * Manage Local Data
+ * Author : @H0llyW00dzZ
+ * WIP
+ **/
+
+function LocalDataModal(props: { onClose?: () => void }) {
+ const syncStore = useSyncStore();
+ const [showLocalData, setShowLocalData] = useState(false);
+ const [exporting, setExporting] = useState(false);
+ const chatStore = useChatStore();
+ const promptStore = usePromptStore();
+ const maskStore = useMaskStore();
+ const stateOverview = useMemo(() => {
+ const sessions = chatStore.sessions;
+ const messageCount = sessions.reduce((p, c) => p + c.messages.length, 0);
+
+ return {
+ chat: sessions.length,
+ message: messageCount,
+ prompt: Object.keys(promptStore.prompts).length,
+ mask: Object.keys(maskStore.masks).length,
+ };
+ }, [chatStore.sessions, maskStore.masks, promptStore.prompts]);
+
+ const handleExportChat = async () => {
+ if (exporting) return;
+ setExporting(true);
+ const currentDate = new Date();
+ const sessions = chatStore.sessions;
+ const totalMessageCount = sessions.reduce((count, session) => count + session.messages.length, 0);
+ const datePart = getClientConfig()?.isApp
+ ? `${currentDate.toLocaleDateString().replace(/\//g, '_')} ${currentDate.toLocaleTimeString().replace(/:/g, '_')}`
+ : `${currentDate.toLocaleString().replace(/:/g, '_')}`;
+ const formattedMessageCount = Locale.ChatItem.ChatItemCount(totalMessageCount);
+ const fileName = `(${formattedMessageCount})-${datePart}.json`;
+ await downloadAs(sessions, fileName);
+ setExporting(false);
+ };
+ const handleImportChat = async () => {
+ if (exporting) return;
+ setExporting(true);
+ try {
+ const rawContent = await readFromFile(); // Read the file content using the appropriate function
+
+ const importedData = JSON.parse(rawContent);
+ // Process the imported chat data and update the chat store
+ chatStore.newSession(importedData.sessions);
+ } catch (e) {
+ showToast(Locale.Settings.Sync.ImportFailed);
+ console.error(e);
+ }
+ setExporting(false);
+ };
+
+ return (
+
+
props.onClose?.()}
+ actions={[
+ ,
+ }
+ bordered
+ text={Locale.UI.Confirm}
+ />,
+ ]}
+ >
+
+
+
+ }
+ text={Locale.UI.Export}
+ onClick={handleExportChat}
+ />
+ }
+ text={Locale.UI.Import}
+ onClick={handleImportChat}
+ />
+ }
+ text={Locale.Settings.Danger.Clear.Action}
+ onClick={async () => {
+ if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
+ chatStore.clearChatData();
+ }
+ }}
+ />
+
+
+
+
+ }
+ text={Locale.UI.Export}
+ onClick={() => {
+ showToast(Locale.WIP);
+ }}
+ />
+ }
+ text={Locale.UI.Import}
+ onClick={() => {
+ showToast(Locale.WIP);
+ }}
+ />
+
+
+
+
+ }
+ text={Locale.UI.Export}
+ onClick={() => {
+ showToast(Locale.WIP);
+ }}
+ />
+ }
+ text={Locale.UI.Import}
+ onClick={() => {
+ showToast(Locale.WIP);
+ }}
+ />
+
+
+
+ {showLocalData && (
+ setShowLocalData(false)} />
+ )}
+
+
+ );
+}
function SyncItems() {
const syncStore = useSyncStore();
@@ -580,6 +732,7 @@ function SyncItems() {
}, [syncStore]);
const [showSyncConfigModal, setShowSyncConfigModal] = useState(false);
+ const [showLocalData, setShowLocalData] = useState(false);
const stateOverview = useMemo(() => {
const sessions = chatStore.sessions;
@@ -637,6 +790,13 @@ function SyncItems() {
subTitle={Locale.Settings.Sync.Overview(stateOverview)}
>
+ }
+ text={Locale.UI.Manage}
+ onClick={() => {
+ setShowLocalData(true);
+ }}
+ />
}
text={Locale.UI.Export}
@@ -658,6 +818,10 @@ function SyncItems() {
{showSyncConfigModal && (
setShowSyncConfigModal(false)} />
)}
+
+ {showLocalData && (
+ setShowLocalData(false)} />
+ )}
>
);
}
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index 7378f05fbcf..19974231b23 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -287,6 +287,23 @@ const cn = {
Overview: (overview: any) => {
return `${overview.chat} 次对话,${overview.message} 条消息,${overview.prompt} 条提示词,${overview.mask} 个面具`;
},
+ Description: {
+ Chat: (overview: any) => {
+ const title = "次对话";
+ const description = `${overview.chat} 次对话,, ${overview.message} 条消息`;
+ return { title, description };
+ },
+ Prompt: (overview: any) => {
+ const title = "条提示词";
+ const description = `${overview.prompt} 条提示词`;
+ return { title, description };
+ },
+ Masks: (overview: any) => {
+ const title = "个面具";
+ const description = `${overview.mask} 个面具`;
+ return { title, description };
+ },
+ },
ImportFailed: "导入失败",
},
Mask: {
@@ -530,6 +547,7 @@ const cn = {
Import: "导入",
Sync: "同步",
Config: "配置",
+ Manage: "管理",
},
Exporter: {
Model: "模型",
diff --git a/app/locales/en.ts b/app/locales/en.ts
index 8714c5bcb79..1df0dc08c50 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -292,6 +292,23 @@ const en: LocaleType = {
Overview: (overview: any) => {
return `${overview.chat} chats,${overview.message} messages,${overview.prompt} prompts,${overview.mask} masks`;
},
+ Description: {
+ Chat: (overview: any) => {
+ const title = "Chats";
+ const description = `${overview.chat} chats, ${overview.message} messages`;
+ return { title, description };
+ },
+ Prompt: (overview: any) => {
+ const title = "Prompts";
+ const description = `${overview.prompt} prompts`;
+ return { title, description };
+ },
+ Masks: (overview: any) => {
+ const title = "Masks";
+ const description = `${overview.mask} masks`;
+ return { title, description };
+ },
+ },
ImportFailed: "Failed to import from file",
},
Mask: {
@@ -533,6 +550,7 @@ const en: LocaleType = {
Import: "Import",
Sync: "Sync",
Config: "Config",
+ Manage: "Manage",
},
Exporter: {
Model: "Model",
diff --git a/app/locales/id.ts b/app/locales/id.ts
index ce8fb986aff..9352294dcee 100644
--- a/app/locales/id.ts
+++ b/app/locales/id.ts
@@ -263,6 +263,28 @@ const id: PartialLocaleType = {
},
},
},
+ LocalState: "Data Lokal",
+ Overview: (overview: any) => {
+ return `${overview.chat} percakapan, ${overview.message} pesan, ${overview.prompt} prompt, ${overview.mask} masks`;
+ },
+ Description: {
+ Chat: (overview: any) => {
+ const title = "Percakapan";
+ const description = `${overview.chat} percakapan, ${overview.message} pesan`;
+ return { title, description };
+ },
+ Prompt: (overview: any) => {
+ const title = "Prompts";
+ const description = `${overview.prompt} Prompts`;
+ return { title, description };
+ },
+ Masks: (overview: any) => {
+ const title = "Masks";
+ const description = `${overview.mask} masks`;
+ return { title, description };
+ },
+ },
+ ImportFailed: "Gagal mengimpor dari file",
},
SendKey: "Kirim",
Theme: "Tema",
@@ -456,6 +478,7 @@ const id: PartialLocaleType = {
Close: "Tutup",
Create: "Buat",
Edit: "Edit",
+ Manage: "Kelola",
},
Exporter: {
Model: "Model",
diff --git a/app/store/chat.ts b/app/store/chat.ts
index c38054ad8ce..f4003f6fae3 100644
--- a/app/store/chat.ts
+++ b/app/store/chat.ts
@@ -583,6 +583,13 @@ export const useChatStore = createPersistStore(
set(() => ({ sessions }));
},
+ clearChatData() {
+ set(() => ({
+ sessions: [createEmptySession()],
+ currentSessionIndex: 0,
+ }));
+ },
+
clearAllData() {
localStorage.clear();
location.reload();