From be15206234ffbb5232ac48f06eaa3a1aabaa4e2f Mon Sep 17 00:00:00 2001 From: beyondkmp Date: Mon, 23 Jun 2025 17:18:46 +0800 Subject: [PATCH] fix: Data config improvement (#7471) * fix: update localization files for data migration warnings and path validation messages * fix: update app data path validation and localization messages for installation path consistency * fix: enhance app data flushing process by adding connection closure and delay in DataSettings component --- src/main/ipc.ts | 10 ++- src/renderer/src/i18n/locales/en-us.json | 5 +- src/renderer/src/i18n/locales/ja-jp.json | 5 +- src/renderer/src/i18n/locales/ru-ru.json | 5 +- src/renderer/src/i18n/locales/zh-cn.json | 5 +- src/renderer/src/i18n/locales/zh-tw.json | 5 +- .../settings/DataSettings/DataSettings.tsx | 73 +++++++++++-------- src/renderer/src/types/index.ts | 1 + 8 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 5e1ac819a9..5f54d64e07 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -1,5 +1,6 @@ import fs from 'node:fs' import { arch } from 'node:os' +import path from 'node:path' import { isMac, isWin } from '@main/constant' import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process' @@ -57,7 +58,8 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { resourcesPath: getResourcePath(), logsPath: log.transports.file.getFile().path, arch: arch(), - isPortable: isWin && 'PORTABLE_EXECUTABLE_DIR' in process.env + isPortable: isWin && 'PORTABLE_EXECUTABLE_DIR' in process.env, + installPath: path.dirname(app.getPath('exe')) })) ipcMain.handle(IpcChannel.App_Proxy, async (_, proxy: string) => { @@ -233,7 +235,13 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { BrowserWindow.getAllWindows().forEach((w) => { w.webContents.session.flushStorageData() w.webContents.session.cookies.flushStore() + + w.webContents.session.closeAllConnections() }) + + session.defaultSession.flushStorageData() + session.defaultSession.cookies.flushStore() + session.defaultSession.closeAllConnections() }) ipcMain.handle(IpcChannel.App_IsNotEmptyDir, async (_, path: string) => { diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index b8bcfb66b2..fefebd6394 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -1091,7 +1091,7 @@ "app_data.copy_data_option": "Copy data, will automatically restart after copying the original directory data to the new directory", "app_data.copy_time_notice": "Copying data may take a while, do not force quit app", "app_data.path_changed_without_copy": "Path changed successfully", - "app_data.copying_warning": "Data copying, do not force quit app", + "app_data.copying_warning": "Data copying, do not force quit app, the app will restart after copied", "app_data.copying": "Copying data to new location...", "app_data.copy_success": "Successfully copied data to new location", "app_data.copy_failed": "Failed to copy data", @@ -1104,8 +1104,9 @@ "app_data.select_error_write_permission": "New path does not have write permission", "app_data.stop_quit_app_reason": "The app is currently migrating data and cannot be exited", "app_data.select_not_empty_dir": "New path is not empty", - "app_data.select_not_empty_dir_content": "New path is not empty, if you select copy, it will overwrite the data in the new path, there is a risk of data loss, continue?", + "app_data.select_not_empty_dir_content": "New path is not empty, it will overwrite the data in the new path, there is a risk of data loss and copy failure, continue?", "app_data.select_error_same_path": "New path is the same as the old path, please select another path", + "app_data.select_error_in_app_path": "New path is the same as the application installation path, please select another path", "app_knowledge": "Knowledge Base Files", "app_knowledge.button.delete": "Delete File", "app_knowledge.remove_all": "Remove Knowledge Base Files", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 430cba8351..612df65d71 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -1089,7 +1089,7 @@ "app_data.copy_data_option": "データをコピーする, 開くと元のディレクトリのデータが新しいディレクトリにコピーされます。", "app_data.copy_time_notice": "データコピーには時間がかかります。アプリを強制終了しないでください。", "app_data.path_changed_without_copy": "パスが変更されました。", - "app_data.copying_warning": "データコピー中、アプリを強制終了しないでください", + "app_data.copying_warning": "データコピー中、アプリを強制終了しないでください。コピーが完了すると、アプリが自動的に再起動します。", "app_data.copying": "新しい場所にデータをコピーしています...", "app_data.copy_success": "データを新しい場所に正常にコピーしました", "app_data.copy_failed": "データのコピーに失敗しました", @@ -1102,8 +1102,9 @@ "app_data.select_error_write_permission": "新しいパスに書き込み権限がありません", "app_data.stop_quit_app_reason": "アプリは現在データを移行しているため、終了できません", "app_data.select_not_empty_dir": "新しいパスは空ではありません", - "app_data.select_not_empty_dir_content": "新しいパスは空ではありません。コピーを選択すると、新しいパスのデータが上書きされます。データが失われるリスクがあります。続行しますか?", + "app_data.select_not_empty_dir_content": "新しいパスは空ではありません。新しいパスのデータが上書きされます。データが失われるリスクがあります。続行しますか?", "app_data.select_error_same_path": "新しいパスは元のパスと同じです。別のパスを選択してください", + "app_data.select_error_in_app_path": "新しいパスはアプリのインストールパスと同じです。別のパスを選択してください", "app_knowledge": "知識ベースファイル", "app_knowledge.button.delete": "ファイルを削除", "app_knowledge.remove_all": "ナレッジベースファイルを削除", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index af26cddf92..ec2ad7785f 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -1089,7 +1089,7 @@ "app_data.copy_data_option": "Копировать данные, будет автоматически перезапущено после копирования данных из исходной директории в новую директорию", "app_data.copy_time_notice": "Копирование данных из исходной директории займет некоторое время, пожалуйста, будьте терпеливы", "app_data.path_changed_without_copy": "Путь изменен успешно", - "app_data.copying_warning": "Копирование данных, нельзя взаимодействовать с приложением, не закрывайте приложение", + "app_data.copying_warning": "Копирование данных, нельзя взаимодействовать с приложением, не закрывайте приложение, приложение будет перезапущено после копирования", "app_data.copying": "Копирование данных в новое место...", "app_data.copy_success": "Данные успешно скопированы в новое место", "app_data.copy_failed": "Не удалось скопировать данные", @@ -1102,7 +1102,8 @@ "app_data.select_error_write_permission": "Новый путь не имеет разрешения на запись", "app_data.stop_quit_app_reason": "Приложение в настоящее время перемещает данные и не может быть закрыто", "app_data.select_not_empty_dir": "Новый путь не пуст", - "app_data.select_not_empty_dir_content": "Новый путь не пуст, если вы выбираете копирование, он перезапишет данные в новом пути, есть риск потери данных, продолжить?", + "app_data.select_not_empty_dir_content": "Новый путь не пуст, он перезапишет данные в новом пути, есть риск потери данных и ошибки копирования, продолжить?", + "app_data.select_error_in_app_path": "Новый путь совпадает с исходным путем, пожалуйста, выберите другой путь", "app_data.select_error_same_path": "Новый путь совпадает с исходным путем, пожалуйста, выберите другой путь", "app_knowledge": "Файлы базы знаний", "app_knowledge.button.delete": "Удалить файл", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index fd393e36ce..8d7c30f323 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -1091,7 +1091,7 @@ "app_data.copy_data_option": "复制数据,会自动重启后将原始目录数据复制到新目录", "app_data.copy_time_notice": "复制数据将需要一些时间,复制期间不要关闭应用", "app_data.path_changed_without_copy": "路径已更改成功", - "app_data.copying_warning": "数据复制中,不要强制退出app", + "app_data.copying_warning": "数据复制中,不要强制退出app, 复制完成后会自动重启应用", "app_data.copying": "正在将数据复制到新位置...", "app_data.copy_success": "已成功复制数据到新位置", "app_data.copy_failed": "复制数据失败", @@ -1104,8 +1104,9 @@ "app_data.select_error_write_permission": "新路径没有写入权限", "app_data.stop_quit_app_reason": "应用目前在迁移数据, 不能退出", "app_data.select_not_empty_dir": "新路径不为空", - "app_data.select_not_empty_dir_content": "新路径不为空,选择复制将覆盖新路径中的数据, 有数据丢失的风险,是否继续?", + "app_data.select_not_empty_dir_content": "新路径不为空,将覆盖新路径中的数据, 有数据丢失和复制失败的风险,是否继续?", "app_data.select_error_same_path": "新路径与旧路径相同,请选择其他路径", + "app_data.select_error_in_app_path": "新路径与应用安装路径相同,请选择其他路径", "app_knowledge": "知识库文件", "app_knowledge.button.delete": "删除文件", "app_knowledge.remove_all": "删除知识库文件", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 995bee24bc..1d23fb540a 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -1091,7 +1091,7 @@ "app_data.copy_data_option": "複製數據, 會自動重啟後將原始目錄數據複製到新目錄", "app_data.copy_time_notice": "複製數據將需要一些時間,複製期間不要關閉應用", "app_data.path_changed_without_copy": "路徑已變更成功", - "app_data.copying_warning": "數據複製中,不要強制退出應用", + "app_data.copying_warning": "數據複製中,不要強制退出應用, 複製完成後會自動重啟應用", "app_data.copying": "正在複製數據到新位置...", "app_data.copy_success": "成功複製數據到新位置", "app_data.copy_failed": "複製數據失敗", @@ -1104,8 +1104,9 @@ "app_data.select_error_write_permission": "新路徑沒有寫入權限", "app_data.stop_quit_app_reason": "應用目前正在遷移數據,不能退出", "app_data.select_not_empty_dir": "新路徑不為空", - "app_data.select_not_empty_dir_content": "新路徑不為空,選擇複製將覆蓋新路徑中的數據, 有數據丟失的風險,是否繼續?", + "app_data.select_not_empty_dir_content": "新路徑不為空,選擇複製將覆蓋新路徑中的數據, 有數據丟失和複製失敗的風險,是否繼續?", "app_data.select_error_same_path": "新路徑與舊路徑相同,請選擇其他路徑", + "app_data.select_error_in_app_path": "新路徑與應用安裝路徑相同,請選擇其他路徑", "app_knowledge": "知識庫文件", "app_knowledge.button.delete": "刪除檔案", "app_knowledge.remove_all": "刪除知識庫檔案", diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 52b1c0bbb7..0038f1947c 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -202,12 +202,18 @@ const DataSettings: FC = () => { return } - // check new app data path is same as old app data path - if (newAppDataPath.startsWith(appInfo!.appDataPath)) { + // check new app data path is not in old app data path + if (newAppDataPath.startsWith(appInfo.appDataPath)) { window.message.error(t('settings.data.app_data.select_error_same_path')) return } + // check new app data path is not in app install path + if (newAppDataPath.startsWith(appInfo.installPath)) { + window.message.error(t('settings.data.app_data.select_error_in_app_path')) + return + } + // check new app data path has write permission const hasWritePermission = await window.api.hasWritePermission(newAppDataPath) if (!hasWritePermission) { @@ -219,25 +225,30 @@ const DataSettings: FC = () => {
{t('settings.data.app_data.migration_title')}
) const migrationClassName = 'migration-modal' - - if (await window.api.isNotEmptyDir(newAppDataPath)) { - const modal = window.modal.confirm({ - title: t('settings.data.app_data.select_not_empty_dir'), - content: t('settings.data.app_data.select_not_empty_dir_content'), - centered: true, - okText: t('common.confirm'), - cancelText: t('common.cancel'), - onOk: () => { - modal.destroy() - // 显示确认对话框 - showMigrationConfirmModal(appInfo.appDataPath, newAppDataPath, migrationTitle, migrationClassName) - } - }) - return - } showMigrationConfirmModal(appInfo.appDataPath, newAppDataPath, migrationTitle, migrationClassName) } + const doubleConfirmModalBeforeCopyData = (newPath: string) => { + window.modal.confirm({ + title: t('settings.data.app_data.select_not_empty_dir'), + content: t('settings.data.app_data.select_not_empty_dir_content'), + centered: true, + okText: t('common.confirm'), + cancelText: t('common.cancel'), + onOk: () => { + window.message.info({ + content: t('settings.data.app_data.restart_notice'), + duration: 2 + }) + setTimeout(() => { + window.api.relaunchApp({ + args: ['--new-data-path=' + newPath] + }) + }, 500) + } + }) + } + // 显示确认迁移的对话框 const showMigrationConfirmModal = async ( originalPath: string, @@ -280,7 +291,7 @@ const DataSettings: FC = () => { ) // 显示确认模态框 - const modal = window.modal.confirm({ + window.modal.confirm({ title, className, width: 'min(600px, 90vw)', @@ -305,11 +316,12 @@ const DataSettings: FC = () => { cancelText: t('common.cancel'), onOk: async () => { try { - // 立即关闭确认对话框 - modal.destroy() - if (shouldCopyData) { - // 如果选择复制数据,显示进度模态框并执行迁移 + if (await window.api.isNotEmptyDir(newPath)) { + doubleConfirmModalBeforeCopyData(newPath) + return + } + window.message.info({ content: t('settings.data.app_data.restart_notice'), duration: 3 @@ -318,12 +330,12 @@ const DataSettings: FC = () => { window.api.relaunchApp({ args: ['--new-data-path=' + newPath] }) - }, 300) - } else { - // 如果不复制数据,直接设置新的应用数据路径 - await window.api.setAppDataPath(newPath) - window.message.success(t('settings.data.app_data.path_changed_without_copy')) + }, 500) + return } + // 如果不复制数据,直接设置新的应用数据路径 + await window.api.setAppDataPath(newPath) + window.message.success(t('settings.data.app_data.path_changed_without_copy')) // 更新应用数据路径 setAppInfo(await window.api.getAppInfo()) @@ -333,7 +345,7 @@ const DataSettings: FC = () => { window.message.success(t('settings.data.app_data.select_success')) window.api.setStopQuitApp(false, '') window.api.relaunchApp() - }, 1000) + }, 500) } catch (error) { window.api.setStopQuitApp(false, '') window.message.error({ @@ -484,6 +496,9 @@ const DataSettings: FC = () => { // flush app data await window.api.flushAppData() + // wait 2 seconds to flush app data + await new Promise((resolve) => setTimeout(resolve, 2000)) + // 开始复制过程 const copyResult = await window.api.copy(originalPath, newPath) diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index e60f374ba7..75e1da19ce 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -387,6 +387,7 @@ export type AppInfo = { logsPath: string arch: string isPortable: boolean + installPath: string } export interface Shortcut {