add autoSync in WebDav

This commit is contained in:
little_penguin66 2024-12-22 21:02:39 +08:00 committed by 亢奋猫
parent 0739758469
commit 87c3716f75
7 changed files with 117 additions and 4 deletions

View File

@ -222,6 +222,7 @@
"assistant.added.content": "Assistant added successfully",
"backup.failed": "Backup failed",
"backup.success": "Backup successful",
"backup.start.success": "Backup started",
"chat.completion.paused": "Chat completion paused",
"copied": "Copied!",
"error.enter.api.host": "Please enter your API host first",
@ -363,6 +364,8 @@
"webdav.password": "WebDAV Password",
"webdav.path": "WebDAV Path",
"webdav.path.placeholder": "/backup",
"webdav.autoSync": "Auto Sync",
"webdav.minutes": "Minutes",
"webdav.restore.button": "Restore from WebDAV",
"webdav.title": "WebDAV",
"webdav.user": "WebDAV User"

View File

@ -222,6 +222,7 @@
"assistant.added.content": "Ассистент успешно добавлен",
"backup.failed": "Создание резервной копии не удалось",
"backup.success": "Резервная копия успешно создана",
"backup.start.success": "Создание резервной копии начато",
"chat.completion.paused": "Завершение чата приостановлено",
"copied": "Скопировано!",
"error.enter.api.host": "Пожалуйста, введите ваш API хост",
@ -363,6 +364,8 @@
"webdav.password": "Пароль WebDAV",
"webdav.path": "Путь WebDAV",
"webdav.path.placeholder": "/backup",
"webdav.autoSync": "Автоматическая синхронизация",
"webdav.minutes": "минут",
"webdav.restore.button": "Восстановление с WebDAV",
"webdav.title": "WebDAV",
"webdav.user": "Пользователь WebDAV"

View File

@ -222,6 +222,7 @@
"assistant.added.content": "智能体添加成功",
"backup.failed": "备份失败",
"backup.success": "备份成功",
"backup.start.success": "开始备份",
"chat.completion.paused": "会话已停止",
"copied": "已复制",
"error.enter.api.host": "请输入您的 API 地址",
@ -363,6 +364,8 @@
"webdav.password": "WebDAV 密码",
"webdav.path": "WebDAV 路径",
"webdav.path.placeholder": "/backup",
"webdav.autoSync": "自动同步",
"webdav.minutes": "分钟",
"webdav.restore.button": "从 WebDAV 恢复",
"webdav.title": "WebDAV",
"webdav.user": "WebDAV 用户名"

View File

@ -222,6 +222,7 @@
"assistant.added.content": "智能體添加成功",
"backup.failed": "備份失敗",
"backup.success": "備份成功",
"backup.start.success": "開始備份",
"chat.completion.paused": "聊天完成已暫停",
"copied": "已複製",
"error.enter.api.host": "請先輸入您的 API 主機地址",
@ -363,6 +364,8 @@
"webdav.password": "WebDAV 密碼",
"webdav.path": "WebDAV Path",
"webdav.path.placeholder": "/backup",
"webdav.autoSync": "自動同步",
"webdav.minutes": "分鐘",
"webdav.restore.button": "從 WebDAV 恢復",
"webdav.title": "WebDAV",
"webdav.user": "WebDAV 使用者名稱"

View File

@ -1,15 +1,17 @@
import { FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
import { HStack } from '@renderer/components/Layout'
import { useSettings } from '@renderer/hooks/useSettings'
import { backupToWebdav, restoreFromWebdav } from '@renderer/services/BackupService'
import { backupToWebdav, restoreFromWebdav, startAutoSync, stopAutoSync } from '@renderer/services/BackupService'
import { useAppDispatch } from '@renderer/store'
import {
setWebdavAutoSync,
setWebdavHost as _setWebdavHost,
setWebdavPass as _setWebdavPass,
setWebdavPath as _setWebdavPath,
setWebdavSyncInterval as _setWebdavSyncInterval,
setWebdavUser as _setWebdavUser
} from '@renderer/store/settings'
import { Button, Input } from 'antd'
import { Button, Input, Select, Switch } from 'antd'
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -20,7 +22,9 @@ const WebDavSettings: FC = () => {
webdavHost: webDAVHost,
webdavUser: webDAVUser,
webdavPass: webDAVPass,
webdavPath: webDAVPath
webdavPath: webDAVPath,
webdavAutoSync: webDAVAutoSync,
webdavSyncInterval: webDAVSyncInterval
} = useSettings()
const [webdavHost, setWebdavHost] = useState<string | undefined>(webDAVHost)
@ -28,6 +32,9 @@ const WebDavSettings: FC = () => {
const [webdavPass, setWebdavPass] = useState<string | undefined>(webDAVPass)
const [webdavPath, setWebdavPath] = useState<string | undefined>(webDAVPath)
const [autoSync, setAutoSync] = useState<boolean>(webDAVAutoSync)
const [syncInterval, setSyncInterval] = useState<number>(webDAVSyncInterval)
const [backuping, setBackuping] = useState(false)
const [restoring, setRestoring] = useState(false)
@ -56,6 +63,19 @@ const WebDavSettings: FC = () => {
await restoreFromWebdav()
setRestoring(false)
}
const onToggleAutoSync = (checked: boolean) => {
dispatch(setWebdavAutoSync(checked))
if (checked) {
startAutoSync()
} else {
stopAutoSync()
}
}
const onSyncIntervalChange = (value: number) => {
setSyncInterval(value)
dispatch(_setWebdavSyncInterval(value))
}
return (
<>
@ -106,6 +126,32 @@ const WebDavSettings: FC = () => {
/>
</SettingRow>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.data.webdav.autoSync')}</SettingRowTitle>
<HStack gap="10px" alignItems="center">
<Switch
checked={autoSync}
onChange={(checked) => {
setAutoSync(checked)
onToggleAutoSync(checked)
}}
disabled={!webdavHost}
/>
<Select
value={syncInterval}
onChange={onSyncIntervalChange}
disabled={!webdavHost || !autoSync}
style={{ width: 120 }}>
<Select.Option value={1}>1 {t('settings.data.webdav.minutes')}</Select.Option>
<Select.Option value={5}>5 {t('settings.data.webdav.minutes')}</Select.Option>
<Select.Option value={15}>15 {t('settings.data.webdav.minutes')}</Select.Option>
<Select.Option value={30}>30 {t('settings.data.webdav.minutes')}</Select.Option>
<Select.Option value={60}>60 {t('settings.data.webdav.minutes')}</Select.Option>
<Select.Option value={120}>120 {t('settings.data.webdav.minutes')}</Select.Option>
</Select>
</HStack>
</SettingRow>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
<HStack gap="5px" justifyContent="space-between">

View File

@ -108,6 +108,49 @@ export async function restoreFromWebdav() {
}
}
let syncInterval: NodeJS.Timeout | null = null
export function startAutoSync() {
const { webdavAutoSync, webdavHost, webdavSyncInterval } = store.getState().settings
if (syncInterval) {
stopAutoSync()
}
if (webdavAutoSync && webdavHost) {
console.log('[AutoSync] Starting auto sync with interval:', webdavSyncInterval, 'minutes')
const performBackup = async () => {
try {
console.log('[AutoSync] Performing backup...')
await backupToWebdav()
window.message.success({
content: i18n.t('message.backup.start.success'),
key: 'webdav-sync'
})
} catch (error) {
console.error('[AutoSync] Backup failed:', error)
window.message.error({
content: i18n.t('message.backup.failed'),
key: 'webdav-sync'
})
}
}
performBackup()
syncInterval = setInterval(performBackup, webdavSyncInterval * 60 * 1000)
console.log('[AutoSync] Sync interval set up:', syncInterval)
}
}
export function stopAutoSync() {
if (syncInterval) {
console.log('[AutoSync] Stopping auto sync')
clearInterval(syncInterval)
syncInterval = null
}
}
async function getBackupData() {
return JSON.stringify({
time: new Date().getTime(),

View File

@ -36,6 +36,8 @@ export interface SettingsState {
webdavUser: string
webdavPass: string
webdavPath: string
webdavAutoSync: boolean
webdavSyncInterval: number
translateModelPrompt: string
autoTranslateWithSpace: boolean
enableTopicNaming: boolean
@ -75,6 +77,8 @@ const initialState: SettingsState = {
webdavUser: '',
webdavPass: '',
webdavPath: '/cherry-studio',
webdavAutoSync: false,
webdavSyncInterval: 5,
translateModelPrompt: TRANSLATE_PROMPT,
autoTranslateWithSpace: false,
enableTopicNaming: true,
@ -165,6 +169,12 @@ const settingsSlice = createSlice({
setWebdavPath: (state, action: PayloadAction<string>) => {
state.webdavPath = action.payload
},
setWebdavAutoSync: (state, action: PayloadAction<boolean>) => {
state.webdavAutoSync = action.payload
},
setWebdavSyncInterval: (state, action: PayloadAction<number>) => {
state.webdavSyncInterval = action.payload
},
setCodeShowLineNumbers: (state, action: PayloadAction<boolean>) => {
state.codeShowLineNumbers = action.payload
},
@ -228,6 +238,8 @@ export const {
setWebdavUser,
setWebdavPass,
setWebdavPath,
setWebdavAutoSync,
setWebdavSyncInterval,
setCodeShowLineNumbers,
setCodeCollapsible,
setMathEngine,