diff --git a/src/App.vue b/src/App.vue
index f1e7436..d9c66e9 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -188,6 +188,23 @@ onMounted(async () => {
registerShortcuts()
+ // Auto-backup on window close
+ try {
+ const { getCurrentWindow } = await import('@tauri-apps/api/window')
+ const win = getCurrentWindow()
+ win.onCloseRequested(async () => {
+ if (settingsStore.settings.auto_backup === 'true' && settingsStore.settings.backup_path) {
+ try {
+ await invoke('auto_backup', { backupDir: settingsStore.settings.backup_path })
+ } catch (e) {
+ console.error('Auto-backup failed:', e)
+ }
+ }
+ })
+ } catch (e) {
+ console.error('Failed to register close handler:', e)
+ }
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (settingsStore.settings.theme_mode === 'system') applyTheme()
})
diff --git a/src/views/Settings.vue b/src/views/Settings.vue
index 19e103e..76bcc00 100644
--- a/src/views/Settings.vue
+++ b/src/views/Settings.vue
@@ -1198,6 +1198,45 @@
+
+
+
+
Last exported
+
{{ lastExportedFormatted }}
+
+
+
+
+
+
+
+
+
Auto-backup on close
+
Save a backup when the app closes
+
+
+
+
+
+
+
+
Backup directory
+
{{ backupPath || 'Not set' }}
+
+
+
+
+
+
Import Data
@@ -1685,6 +1724,34 @@ watch(showClearDataDialog, (val) => {
}
})
+// Auto-backup state
+const autoBackupEnabled = ref(false)
+const backupPath = ref('')
+const lastExported = ref('')
+
+const lastExportedFormatted = computed(() => {
+ if (!lastExported.value) return ''
+ return new Date(lastExported.value).toLocaleString()
+})
+
+async function toggleAutoBackup() {
+ autoBackupEnabled.value = !autoBackupEnabled.value
+ await settingsStore.updateSetting('auto_backup', autoBackupEnabled.value ? 'true' : 'false')
+}
+
+async function chooseBackupPath() {
+ try {
+ const { open } = await import('@tauri-apps/plugin-dialog')
+ const selected = await open({ directory: true, title: 'Choose backup directory' })
+ if (selected && typeof selected === 'string') {
+ backupPath.value = selected
+ await settingsStore.updateSetting('backup_path', selected)
+ }
+ } catch {
+ // User cancelled
+ }
+}
+
// Import state
const importFormat = ref('toggl')
const importFileContent = ref('')
@@ -2103,6 +2170,10 @@ async function exportData() {
a.download = `zeroclock-export-${new Date().toISOString().split('T')[0]}.json`
a.click()
URL.revokeObjectURL(url)
+
+ const now = new Date().toISOString()
+ await settingsStore.updateSetting('last_exported', now)
+ lastExported.value = now
} catch (error) {
console.error('Failed to export data:', error)
toastStore.error('Failed to export data')
@@ -2158,6 +2229,11 @@ onMounted(async () => {
// Notification settings
persistentNotifications.value = settingsStore.settings.persistent_notifications === 'true'
+ // Auto-backup settings
+ autoBackupEnabled.value = settingsStore.settings.auto_backup === 'true'
+ backupPath.value = settingsStore.settings.backup_path || ''
+ lastExported.value = settingsStore.settings.last_exported || ''
+
// Sound settings
soundEnabled.value = settingsStore.settings.sound_enabled === 'true'
soundMode.value = settingsStore.settings.sound_mode || 'synthesized'