diff --git a/src/lib/components/layout/Navbar/Menu.svelte b/src/lib/components/layout/Navbar/Menu.svelte
index 85e7b037b..079976dcf 100644
--- a/src/lib/components/layout/Navbar/Menu.svelte
+++ b/src/lib/components/layout/Navbar/Menu.svelte
@@ -103,7 +103,7 @@
diff --git a/src/lib/components/layout/Sidebar/ChatMenu.svelte b/src/lib/components/layout/Sidebar/ChatMenu.svelte
index 28d5c5a42..458e1c895 100644
--- a/src/lib/components/layout/Sidebar/ChatMenu.svelte
+++ b/src/lib/components/layout/Sidebar/ChatMenu.svelte
@@ -3,6 +3,9 @@
import { flyAndScale } from '$lib/utils/transitions';
import { getContext, createEventDispatcher } from 'svelte';
+ import fileSaver from 'file-saver';
+ const { saveAs } = fileSaver;
+
const dispatch = createEventDispatcher();
import Dropdown from '$lib/components/common/Dropdown.svelte';
@@ -15,8 +18,14 @@
import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte';
import Bookmark from '$lib/components/icons/Bookmark.svelte';
import BookmarkSlash from '$lib/components/icons/BookmarkSlash.svelte';
- import { getChatPinnedStatusById, toggleChatPinnedStatusById } from '$lib/apis/chats';
+ import {
+ getChatById,
+ getChatPinnedStatusById,
+ toggleChatPinnedStatusById
+ } from '$lib/apis/chats';
import { chats } from '$lib/stores';
+ import { createMessagesList } from '$lib/utils';
+ import { downloadChatAsPDF } from '$lib/apis/utils';
const i18n = getContext('i18n');
@@ -41,6 +50,71 @@
pinned = await getChatPinnedStatusById(localStorage.token, chatId);
};
+ const getChatAsText = async () => {
+ const chat = await getChatById(localStorage.token, chatId);
+ if (!chat) {
+ return;
+ }
+
+ const history = chat.chat.history;
+ const messages = createMessagesList(history, history.currentId);
+ const chatText = messages.reduce((a, message, i, arr) => {
+ return `${a}### ${message.role.toUpperCase()}\n${message.content}\n\n`;
+ }, '');
+
+ return chatText.trim();
+ };
+
+ const downloadTxt = async () => {
+ const chatText = await getChatAsText();
+
+ let blob = new Blob([chatText], {
+ type: 'text/plain'
+ });
+
+ saveAs(blob, `chat-${chat.chat.title}.txt`);
+ };
+
+ const downloadPdf = async () => {
+ const chat = await getChatById(localStorage.token, chatId);
+ if (!chat) {
+ return;
+ }
+
+ const history = chat.chat.history;
+ const messages = createMessagesList(history, history.currentId);
+ const blob = await downloadChatAsPDF(chat.chat.title, messages);
+
+ // Create a URL for the blob
+ const url = window.URL.createObjectURL(blob);
+
+ // Create a link element to trigger the download
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `chat-${chat.chat.title}.pdf`;
+
+ // Append the link to the body and click it programmatically
+ document.body.appendChild(a);
+ a.click();
+
+ // Remove the link from the body
+ document.body.removeChild(a);
+
+ // Revoke the URL to release memory
+ window.URL.revokeObjectURL(url);
+ };
+
+ const downloadJSONExport = async () => {
+ const chat = await getChatById(localStorage.token, chatId);
+
+ if (chat) {
+ let blob = new Blob([JSON.stringify([chat])], {
+ type: 'application/json'
+ });
+ saveAs(blob, `chat-export-${Date.now()}.json`);
+ }
+ };
+
$: if (show) {
checkPinned();
}
@@ -60,7 +134,7 @@
{$i18n.t('Share')}
+
+
+
+
+ {$i18n.t('Download')}
+
+
+ {
+ downloadJSONExport();
+ }}
+ >
+ {$i18n.t('Export chat (.json)')}
+
+ {
+ downloadTxt();
+ }}
+ >
+ {$i18n.t('Plain text (.txt)')}
+
+
+ {
+ downloadPdf();
+ }}
+ >
+ {$i18n.t('PDF document (.pdf)')}
+
+
+
{