Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Feat UI/UX Page [Settings] Managing local data #72

Merged
merged 7 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 165 additions & 1 deletion app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -569,6 +573,154 @@ function SyncConfigModal(props: { onClose?: () => void }) {
</div>
);
}
/**
* 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 (
<div className="modal-mask">
<Modal
title={Locale.Settings.Sync.LocalState}
onClose={() => props.onClose?.()}
actions={[
<CheckButton key="check" />,
<IconButton
key="confirm"
onClick={props.onClose}
icon={<ConfirmIcon />}
bordered
text={Locale.UI.Confirm}
/>,
]}
>
<List>
<ListItem
title={Locale.Settings.Sync.Description.Chat(stateOverview).title}
subTitle={Locale.Settings.Sync.Description.Chat(stateOverview).description}
>
<div style={{ display: "flex" }}>
<IconButton
icon={<UploadIcon />}
text={Locale.UI.Export}
onClick={handleExportChat}
/>
<IconButton
icon={<DownloadIcon />}
text={Locale.UI.Import}
onClick={handleImportChat}
/>
<IconButton
icon={<ClearIcon />}
text={Locale.Settings.Danger.Clear.Action}
onClick={async () => {
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
chatStore.clearChatData();
}
}}
/>
</div>
</ListItem>
<ListItem
title={Locale.Settings.Sync.Description.Masks(stateOverview).title}
subTitle={Locale.Settings.Sync.Description.Masks(stateOverview).description}
>
<div style={{ display: "flex" }}>
<IconButton
icon={<UploadIcon />}
text={Locale.UI.Export}
onClick={() => {
showToast(Locale.WIP);
}}
/>
<IconButton
icon={<DownloadIcon />}
text={Locale.UI.Import}
onClick={() => {
showToast(Locale.WIP);
}}
/>
</div>
</ListItem>
<ListItem
title={Locale.Settings.Sync.Description.Prompt(stateOverview).title}
subTitle={Locale.Settings.Sync.Description.Prompt(stateOverview).description}
>
<div style={{ display: "flex" }}>
<IconButton
icon={<UploadIcon />}
text={Locale.UI.Export}
onClick={() => {
showToast(Locale.WIP);
}}
/>
<IconButton
icon={<DownloadIcon />}
text={Locale.UI.Import}
onClick={() => {
showToast(Locale.WIP);
}}
/>
</div>
</ListItem>
</List>
{showLocalData && (
<LocalDataModal onClose={() => setShowLocalData(false)} />
)}
</Modal>
</div>
);
}

function SyncItems() {
const syncStore = useSyncStore();
Expand All @@ -580,6 +732,7 @@ function SyncItems() {
}, [syncStore]);

const [showSyncConfigModal, setShowSyncConfigModal] = useState(false);
const [showLocalData, setShowLocalData] = useState(false);

const stateOverview = useMemo(() => {
const sessions = chatStore.sessions;
Expand Down Expand Up @@ -637,6 +790,13 @@ function SyncItems() {
subTitle={Locale.Settings.Sync.Overview(stateOverview)}
>
<div style={{ display: "flex" }}>
<IconButton
icon={<EditIcon />}
text={Locale.UI.Manage}
onClick={() => {
setShowLocalData(true);
}}
/>
<IconButton
icon={<UploadIcon />}
text={Locale.UI.Export}
Expand All @@ -658,6 +818,10 @@ function SyncItems() {
{showSyncConfigModal && (
<SyncConfigModal onClose={() => setShowSyncConfigModal(false)} />
)}

{showLocalData && (
<LocalDataModal onClose={() => setShowLocalData(false)} />
)}
</>
);
}
Expand Down
18 changes: 18 additions & 0 deletions app/locales/cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -530,6 +547,7 @@ const cn = {
Import: "导入",
Sync: "同步",
Config: "配置",
Manage: "管理",
},
Exporter: {
Model: "模型",
Expand Down
18 changes: 18 additions & 0 deletions app/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -533,6 +550,7 @@ const en: LocaleType = {
Import: "Import",
Sync: "Sync",
Config: "Config",
Manage: "Manage",
},
Exporter: {
Model: "Model",
Expand Down
23 changes: 23 additions & 0 deletions app/locales/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -456,6 +478,7 @@ const id: PartialLocaleType = {
Close: "Tutup",
Create: "Buat",
Edit: "Edit",
Manage: "Kelola",
},
Exporter: {
Model: "Model",
Expand Down
7 changes: 7 additions & 0 deletions app/store/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,13 @@ export const useChatStore = createPersistStore(
set(() => ({ sessions }));
},

clearChatData() {
set(() => ({
sessions: [createEmptySession()],
currentSessionIndex: 0,
}));
},

clearAllData() {
localStorage.clear();
location.reload();
Expand Down