From 4cbdd563e805a7a70fcc0754ad283eb45f79d4dd Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Thu, 2 Jan 2025 18:29:36 +0800 Subject: [PATCH] feat: add translations and file management features --- src/renderer/src/i18n/locales/en-us.json | 7 +- src/renderer/src/i18n/locales/ja-jp.json | 7 +- src/renderer/src/i18n/locales/ru-ru.json | 7 +- src/renderer/src/i18n/locales/zh-cn.json | 7 +- src/renderer/src/i18n/locales/zh-tw.json | 7 +- src/renderer/src/pages/files/FilesPage.tsx | 105 +++++++++++++++++++-- src/renderer/src/services/FileManager.ts | 27 +++++- 7 files changed, 150 insertions(+), 17 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 232b5d06..feb079fa 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -184,7 +184,12 @@ "open": "Open", "size": "Size", "text": "Text", - "title": "Files" + "title": "Files", + "edit": "Edit", + "delete": "Delete", + "delete.title": "Delete File", + "delete.content": "Deleting a file will delete its reference from all messages. Are you sure you want to delete this file?", + "delete.paintings.warning": "Image contains this file, deletion is not possible" }, "history": { "continue_chat": "Continue Chatting", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 5570313f..e3303a80 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -184,7 +184,12 @@ "open": "開く", "size": "サイズ", "text": "テキスト", - "title": "ファイル" + "title": "ファイル", + "edit": "編集", + "delete": "削除", + "delete.title": "ファイルを削除", + "delete.content": "ファイルを削除すると、ファイルがすべてのメッセージで参照されることを削除します。このファイルを削除してもよろしいですか?", + "delete.paintings.warning": "画像に含まれているため、削除できません" }, "history": { "continue_chat": "チャットを続ける", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 3f758652..8f4fa371 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -184,7 +184,12 @@ "open": "Открыть", "size": "Размер", "text": "Текст", - "title": "Файлы" + "title": "Файлы", + "edit": "Редактировать", + "delete": "Удалить", + "delete.title": "Удалить файл", + "delete.content": "Удаление файла удалит его из всех сообщений, вы уверены, что хотите удалить этот файл?", + "delete.paintings.warning": "В изображениях содержится этот файл, удаление невозможно" }, "history": { "continue_chat": "Продолжить чат", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 4073cc95..c7b6fb40 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -185,7 +185,12 @@ "open": "打开", "size": "大小", "text": "文本", - "title": "文件" + "title": "文件", + "edit": "编辑", + "delete": "删除", + "delete.title": "删除文件", + "delete.content": "删除文件会删除文件在所有消息中的引用,确定要删除此文件吗?", + "delete.paintings.warning": "绘图中包含该图片,暂时无法删除" }, "history": { "continue_chat": "继续聊天", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 87b51b32..dbb2ad93 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -184,7 +184,12 @@ "open": "打開", "size": "大小", "text": "文本", - "title": "檔案" + "title": "檔案", + "edit": "編輯", + "delete": "刪除", + "delete.title": "刪除檔案", + "delete.content": "刪除檔案會刪除檔案在所有消息中的引用,確定要刪除此檔案嗎?", + "delete.paintings.warning": "繪圖中包含該圖片,暫時無法刪除" }, "history": { "continue_chat": "繼續聊天", diff --git a/src/renderer/src/pages/files/FilesPage.tsx b/src/renderer/src/pages/files/FilesPage.tsx index 79dbd9d1..89fcc089 100644 --- a/src/renderer/src/pages/files/FilesPage.tsx +++ b/src/renderer/src/pages/files/FilesPage.tsx @@ -1,11 +1,21 @@ -import { FileImageOutlined, FilePdfOutlined, FileTextOutlined } from '@ant-design/icons' +import { + DeleteOutlined, + EditOutlined, + EllipsisOutlined, + FileImageOutlined, + FilePdfOutlined, + FileTextOutlined +} from '@ant-design/icons' import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar' +import TextEditPopup from '@renderer/components/Popups/TextEditPopup' import Scrollbar from '@renderer/components/Scrollbar' import db from '@renderer/databases' import FileManager from '@renderer/services/FileManager' +import store from '@renderer/store' import { FileType, FileTypes } from '@renderer/types' import { formatFileSize } from '@renderer/utils' -import { Col, Image, Menu, Row, Spin, Table } from 'antd' +import type { MenuProps } from 'antd' +import { Button, Col, Dropdown, Image, Menu, Row, Spin, Table } from 'antd' import dayjs from 'dayjs' import { useLiveQuery } from 'dexie-react-hooks' import { FC, useState } from 'react' @@ -23,14 +33,88 @@ const FilesPage: FC = () => { return db.files.where('type').equals(fileType).sortBy('count') }, [fileType]) + const handleDelete = async (fileId: string) => { + const file = await FileManager.getFile(fileId) + + const paintings = await store.getState().paintings.paintings + const paintingsFiles = paintings.flatMap((p) => p.files) + + if (paintingsFiles.some((p) => p.id === fileId)) { + window.modal.warning({ content: t('files.delete.paintings.warning'), centered: true }) + return + } + + if (file) { + await FileManager.deleteFile(fileId, true) + } + + const topics = await db.topics + .filter((topic) => topic.messages.some((message) => message.files?.some((f) => f.id === fileId))) + .toArray() + + if (topics.length > 0) { + for (const topic of topics) { + const updatedMessages = topic.messages.map((message) => ({ + ...message, + files: message.files?.filter((f) => f.id !== fileId) + })) + await db.topics.update(topic.id, { messages: updatedMessages }) + } + } + } + + const handleRename = async (fileId: string) => { + const file = await FileManager.getFile(fileId) + if (file) { + const newName = await TextEditPopup.show({ text: file.origin_name }) + if (newName) { + FileManager.updateFile({ ...file, origin_name: newName }) + } + } + } + + const getActionMenu = (fileId: string): MenuProps['items'] => [ + { + key: 'rename', + icon: , + label: t('files.edit'), + onClick: () => handleRename(fileId) + }, + { + key: 'delete', + icon: , + label: t('files.delete'), + danger: true, + onClick: () => { + window.modal.confirm({ + title: t('files.delete.title'), + content: t('files.delete.content'), + centered: true, + okButtonProps: { danger: true }, + onOk: () => handleDelete(fileId) + }) + } + } + ] + const dataSource = files?.map((file) => { return { key: file.id, - file: {file.origin_name}, + file: ( + window.api.file.openPath(file.path)}> + {file.origin_name} + + ), size: formatFileSize(file), + size_bytes: file.size, count: file.count, created_at: dayjs(file.created_at).format('MM-DD HH:mm'), - actions: {t('files.open')} + created_at_unix: dayjs(file.created_at).unix(), + actions: ( + +