mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 15:49:29 +08:00
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
This commit is contained in:
parent
aee8fe6196
commit
be15206234
@ -1,5 +1,6 @@
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import { arch } from 'node:os'
|
import { arch } from 'node:os'
|
||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
import { isMac, isWin } from '@main/constant'
|
import { isMac, isWin } from '@main/constant'
|
||||||
import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process'
|
import { getBinaryPath, isBinaryExists, runInstallScript } from '@main/utils/process'
|
||||||
@ -57,7 +58,8 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
|||||||
resourcesPath: getResourcePath(),
|
resourcesPath: getResourcePath(),
|
||||||
logsPath: log.transports.file.getFile().path,
|
logsPath: log.transports.file.getFile().path,
|
||||||
arch: arch(),
|
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) => {
|
ipcMain.handle(IpcChannel.App_Proxy, async (_, proxy: string) => {
|
||||||
@ -233,7 +235,13 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
|||||||
BrowserWindow.getAllWindows().forEach((w) => {
|
BrowserWindow.getAllWindows().forEach((w) => {
|
||||||
w.webContents.session.flushStorageData()
|
w.webContents.session.flushStorageData()
|
||||||
w.webContents.session.cookies.flushStore()
|
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) => {
|
ipcMain.handle(IpcChannel.App_IsNotEmptyDir, async (_, path: string) => {
|
||||||
|
|||||||
@ -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_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.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.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.copying": "Copying data to new location...",
|
||||||
"app_data.copy_success": "Successfully copied data to new location",
|
"app_data.copy_success": "Successfully copied data to new location",
|
||||||
"app_data.copy_failed": "Failed to copy data",
|
"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.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.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": "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_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": "Knowledge Base Files",
|
||||||
"app_knowledge.button.delete": "Delete File",
|
"app_knowledge.button.delete": "Delete File",
|
||||||
"app_knowledge.remove_all": "Remove Knowledge Base Files",
|
"app_knowledge.remove_all": "Remove Knowledge Base Files",
|
||||||
|
|||||||
@ -1089,7 +1089,7 @@
|
|||||||
"app_data.copy_data_option": "データをコピーする, 開くと元のディレクトリのデータが新しいディレクトリにコピーされます。",
|
"app_data.copy_data_option": "データをコピーする, 開くと元のディレクトリのデータが新しいディレクトリにコピーされます。",
|
||||||
"app_data.copy_time_notice": "データコピーには時間がかかります。アプリを強制終了しないでください。",
|
"app_data.copy_time_notice": "データコピーには時間がかかります。アプリを強制終了しないでください。",
|
||||||
"app_data.path_changed_without_copy": "パスが変更されました。",
|
"app_data.path_changed_without_copy": "パスが変更されました。",
|
||||||
"app_data.copying_warning": "データコピー中、アプリを強制終了しないでください",
|
"app_data.copying_warning": "データコピー中、アプリを強制終了しないでください。コピーが完了すると、アプリが自動的に再起動します。",
|
||||||
"app_data.copying": "新しい場所にデータをコピーしています...",
|
"app_data.copying": "新しい場所にデータをコピーしています...",
|
||||||
"app_data.copy_success": "データを新しい場所に正常にコピーしました",
|
"app_data.copy_success": "データを新しい場所に正常にコピーしました",
|
||||||
"app_data.copy_failed": "データのコピーに失敗しました",
|
"app_data.copy_failed": "データのコピーに失敗しました",
|
||||||
@ -1102,8 +1102,9 @@
|
|||||||
"app_data.select_error_write_permission": "新しいパスに書き込み権限がありません",
|
"app_data.select_error_write_permission": "新しいパスに書き込み権限がありません",
|
||||||
"app_data.stop_quit_app_reason": "アプリは現在データを移行しているため、終了できません",
|
"app_data.stop_quit_app_reason": "アプリは現在データを移行しているため、終了できません",
|
||||||
"app_data.select_not_empty_dir": "新しいパスは空ではありません",
|
"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_same_path": "新しいパスは元のパスと同じです。別のパスを選択してください",
|
||||||
|
"app_data.select_error_in_app_path": "新しいパスはアプリのインストールパスと同じです。別のパスを選択してください",
|
||||||
"app_knowledge": "知識ベースファイル",
|
"app_knowledge": "知識ベースファイル",
|
||||||
"app_knowledge.button.delete": "ファイルを削除",
|
"app_knowledge.button.delete": "ファイルを削除",
|
||||||
"app_knowledge.remove_all": "ナレッジベースファイルを削除",
|
"app_knowledge.remove_all": "ナレッジベースファイルを削除",
|
||||||
|
|||||||
@ -1089,7 +1089,7 @@
|
|||||||
"app_data.copy_data_option": "Копировать данные, будет автоматически перезапущено после копирования данных из исходной директории в новую директорию",
|
"app_data.copy_data_option": "Копировать данные, будет автоматически перезапущено после копирования данных из исходной директории в новую директорию",
|
||||||
"app_data.copy_time_notice": "Копирование данных из исходной директории займет некоторое время, пожалуйста, будьте терпеливы",
|
"app_data.copy_time_notice": "Копирование данных из исходной директории займет некоторое время, пожалуйста, будьте терпеливы",
|
||||||
"app_data.path_changed_without_copy": "Путь изменен успешно",
|
"app_data.path_changed_without_copy": "Путь изменен успешно",
|
||||||
"app_data.copying_warning": "Копирование данных, нельзя взаимодействовать с приложением, не закрывайте приложение",
|
"app_data.copying_warning": "Копирование данных, нельзя взаимодействовать с приложением, не закрывайте приложение, приложение будет перезапущено после копирования",
|
||||||
"app_data.copying": "Копирование данных в новое место...",
|
"app_data.copying": "Копирование данных в новое место...",
|
||||||
"app_data.copy_success": "Данные успешно скопированы в новое место",
|
"app_data.copy_success": "Данные успешно скопированы в новое место",
|
||||||
"app_data.copy_failed": "Не удалось скопировать данные",
|
"app_data.copy_failed": "Не удалось скопировать данные",
|
||||||
@ -1102,7 +1102,8 @@
|
|||||||
"app_data.select_error_write_permission": "Новый путь не имеет разрешения на запись",
|
"app_data.select_error_write_permission": "Новый путь не имеет разрешения на запись",
|
||||||
"app_data.stop_quit_app_reason": "Приложение в настоящее время перемещает данные и не может быть закрыто",
|
"app_data.stop_quit_app_reason": "Приложение в настоящее время перемещает данные и не может быть закрыто",
|
||||||
"app_data.select_not_empty_dir": "Новый путь не пуст",
|
"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_data.select_error_same_path": "Новый путь совпадает с исходным путем, пожалуйста, выберите другой путь",
|
||||||
"app_knowledge": "Файлы базы знаний",
|
"app_knowledge": "Файлы базы знаний",
|
||||||
"app_knowledge.button.delete": "Удалить файл",
|
"app_knowledge.button.delete": "Удалить файл",
|
||||||
|
|||||||
@ -1091,7 +1091,7 @@
|
|||||||
"app_data.copy_data_option": "复制数据,会自动重启后将原始目录数据复制到新目录",
|
"app_data.copy_data_option": "复制数据,会自动重启后将原始目录数据复制到新目录",
|
||||||
"app_data.copy_time_notice": "复制数据将需要一些时间,复制期间不要关闭应用",
|
"app_data.copy_time_notice": "复制数据将需要一些时间,复制期间不要关闭应用",
|
||||||
"app_data.path_changed_without_copy": "路径已更改成功",
|
"app_data.path_changed_without_copy": "路径已更改成功",
|
||||||
"app_data.copying_warning": "数据复制中,不要强制退出app",
|
"app_data.copying_warning": "数据复制中,不要强制退出app, 复制完成后会自动重启应用",
|
||||||
"app_data.copying": "正在将数据复制到新位置...",
|
"app_data.copying": "正在将数据复制到新位置...",
|
||||||
"app_data.copy_success": "已成功复制数据到新位置",
|
"app_data.copy_success": "已成功复制数据到新位置",
|
||||||
"app_data.copy_failed": "复制数据失败",
|
"app_data.copy_failed": "复制数据失败",
|
||||||
@ -1104,8 +1104,9 @@
|
|||||||
"app_data.select_error_write_permission": "新路径没有写入权限",
|
"app_data.select_error_write_permission": "新路径没有写入权限",
|
||||||
"app_data.stop_quit_app_reason": "应用目前在迁移数据, 不能退出",
|
"app_data.stop_quit_app_reason": "应用目前在迁移数据, 不能退出",
|
||||||
"app_data.select_not_empty_dir": "新路径不为空",
|
"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_same_path": "新路径与旧路径相同,请选择其他路径",
|
||||||
|
"app_data.select_error_in_app_path": "新路径与应用安装路径相同,请选择其他路径",
|
||||||
"app_knowledge": "知识库文件",
|
"app_knowledge": "知识库文件",
|
||||||
"app_knowledge.button.delete": "删除文件",
|
"app_knowledge.button.delete": "删除文件",
|
||||||
"app_knowledge.remove_all": "删除知识库文件",
|
"app_knowledge.remove_all": "删除知识库文件",
|
||||||
|
|||||||
@ -1091,7 +1091,7 @@
|
|||||||
"app_data.copy_data_option": "複製數據, 會自動重啟後將原始目錄數據複製到新目錄",
|
"app_data.copy_data_option": "複製數據, 會自動重啟後將原始目錄數據複製到新目錄",
|
||||||
"app_data.copy_time_notice": "複製數據將需要一些時間,複製期間不要關閉應用",
|
"app_data.copy_time_notice": "複製數據將需要一些時間,複製期間不要關閉應用",
|
||||||
"app_data.path_changed_without_copy": "路徑已變更成功",
|
"app_data.path_changed_without_copy": "路徑已變更成功",
|
||||||
"app_data.copying_warning": "數據複製中,不要強制退出應用",
|
"app_data.copying_warning": "數據複製中,不要強制退出應用, 複製完成後會自動重啟應用",
|
||||||
"app_data.copying": "正在複製數據到新位置...",
|
"app_data.copying": "正在複製數據到新位置...",
|
||||||
"app_data.copy_success": "成功複製數據到新位置",
|
"app_data.copy_success": "成功複製數據到新位置",
|
||||||
"app_data.copy_failed": "複製數據失敗",
|
"app_data.copy_failed": "複製數據失敗",
|
||||||
@ -1104,8 +1104,9 @@
|
|||||||
"app_data.select_error_write_permission": "新路徑沒有寫入權限",
|
"app_data.select_error_write_permission": "新路徑沒有寫入權限",
|
||||||
"app_data.stop_quit_app_reason": "應用目前正在遷移數據,不能退出",
|
"app_data.stop_quit_app_reason": "應用目前正在遷移數據,不能退出",
|
||||||
"app_data.select_not_empty_dir": "新路徑不為空",
|
"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_same_path": "新路徑與舊路徑相同,請選擇其他路徑",
|
||||||
|
"app_data.select_error_in_app_path": "新路徑與應用安裝路徑相同,請選擇其他路徑",
|
||||||
"app_knowledge": "知識庫文件",
|
"app_knowledge": "知識庫文件",
|
||||||
"app_knowledge.button.delete": "刪除檔案",
|
"app_knowledge.button.delete": "刪除檔案",
|
||||||
"app_knowledge.remove_all": "刪除知識庫檔案",
|
"app_knowledge.remove_all": "刪除知識庫檔案",
|
||||||
|
|||||||
@ -202,12 +202,18 @@ const DataSettings: FC = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check new app data path is same as old app data path
|
// check new app data path is not in old app data path
|
||||||
if (newAppDataPath.startsWith(appInfo!.appDataPath)) {
|
if (newAppDataPath.startsWith(appInfo.appDataPath)) {
|
||||||
window.message.error(t('settings.data.app_data.select_error_same_path'))
|
window.message.error(t('settings.data.app_data.select_error_same_path'))
|
||||||
return
|
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
|
// check new app data path has write permission
|
||||||
const hasWritePermission = await window.api.hasWritePermission(newAppDataPath)
|
const hasWritePermission = await window.api.hasWritePermission(newAppDataPath)
|
||||||
if (!hasWritePermission) {
|
if (!hasWritePermission) {
|
||||||
@ -219,25 +225,30 @@ const DataSettings: FC = () => {
|
|||||||
<div style={{ fontSize: '18px', fontWeight: 'bold' }}>{t('settings.data.app_data.migration_title')}</div>
|
<div style={{ fontSize: '18px', fontWeight: 'bold' }}>{t('settings.data.app_data.migration_title')}</div>
|
||||||
)
|
)
|
||||||
const migrationClassName = 'migration-modal'
|
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)
|
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 (
|
const showMigrationConfirmModal = async (
|
||||||
originalPath: string,
|
originalPath: string,
|
||||||
@ -280,7 +291,7 @@ const DataSettings: FC = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 显示确认模态框
|
// 显示确认模态框
|
||||||
const modal = window.modal.confirm({
|
window.modal.confirm({
|
||||||
title,
|
title,
|
||||||
className,
|
className,
|
||||||
width: 'min(600px, 90vw)',
|
width: 'min(600px, 90vw)',
|
||||||
@ -305,11 +316,12 @@ const DataSettings: FC = () => {
|
|||||||
cancelText: t('common.cancel'),
|
cancelText: t('common.cancel'),
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
// 立即关闭确认对话框
|
|
||||||
modal.destroy()
|
|
||||||
|
|
||||||
if (shouldCopyData) {
|
if (shouldCopyData) {
|
||||||
// 如果选择复制数据,显示进度模态框并执行迁移
|
if (await window.api.isNotEmptyDir(newPath)) {
|
||||||
|
doubleConfirmModalBeforeCopyData(newPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
window.message.info({
|
window.message.info({
|
||||||
content: t('settings.data.app_data.restart_notice'),
|
content: t('settings.data.app_data.restart_notice'),
|
||||||
duration: 3
|
duration: 3
|
||||||
@ -318,12 +330,12 @@ const DataSettings: FC = () => {
|
|||||||
window.api.relaunchApp({
|
window.api.relaunchApp({
|
||||||
args: ['--new-data-path=' + newPath]
|
args: ['--new-data-path=' + newPath]
|
||||||
})
|
})
|
||||||
}, 300)
|
}, 500)
|
||||||
} else {
|
return
|
||||||
// 如果不复制数据,直接设置新的应用数据路径
|
|
||||||
await window.api.setAppDataPath(newPath)
|
|
||||||
window.message.success(t('settings.data.app_data.path_changed_without_copy'))
|
|
||||||
}
|
}
|
||||||
|
// 如果不复制数据,直接设置新的应用数据路径
|
||||||
|
await window.api.setAppDataPath(newPath)
|
||||||
|
window.message.success(t('settings.data.app_data.path_changed_without_copy'))
|
||||||
|
|
||||||
// 更新应用数据路径
|
// 更新应用数据路径
|
||||||
setAppInfo(await window.api.getAppInfo())
|
setAppInfo(await window.api.getAppInfo())
|
||||||
@ -333,7 +345,7 @@ const DataSettings: FC = () => {
|
|||||||
window.message.success(t('settings.data.app_data.select_success'))
|
window.message.success(t('settings.data.app_data.select_success'))
|
||||||
window.api.setStopQuitApp(false, '')
|
window.api.setStopQuitApp(false, '')
|
||||||
window.api.relaunchApp()
|
window.api.relaunchApp()
|
||||||
}, 1000)
|
}, 500)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.api.setStopQuitApp(false, '')
|
window.api.setStopQuitApp(false, '')
|
||||||
window.message.error({
|
window.message.error({
|
||||||
@ -484,6 +496,9 @@ const DataSettings: FC = () => {
|
|||||||
// flush app data
|
// flush app data
|
||||||
await window.api.flushAppData()
|
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)
|
const copyResult = await window.api.copy(originalPath, newPath)
|
||||||
|
|
||||||
|
|||||||
@ -387,6 +387,7 @@ export type AppInfo = {
|
|||||||
logsPath: string
|
logsPath: string
|
||||||
arch: string
|
arch: string
|
||||||
isPortable: boolean
|
isPortable: boolean
|
||||||
|
installPath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Shortcut {
|
export interface Shortcut {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user