feat: Automatic plaintext backup option in Preferences > Backups will backup your notes and tags into plaintext, unencrypted folders on your computer. In addition, automatic encrypted text backups preference management has moved from the top-level menu in the desktop app to Preferences > Backups. (#2322)

This commit is contained in:
Mo
2023-05-02 11:05:10 -05:00
committed by GitHub
parent 3df23cdb5c
commit 7e3db49322
76 changed files with 1526 additions and 1013 deletions

View File

@@ -14,6 +14,8 @@ import {
DesktopDeviceInterface,
WebApplicationInterface,
WebAppEvent,
BackupServiceInterface,
DesktopWatchedDirectoriesChanges,
} from '@standardnotes/snjs'
export class DesktopManager
@@ -27,10 +29,34 @@ export class DesktopManager
dataLoaded = false
lastSearchedText?: string
constructor(application: WebApplicationInterface, private device: DesktopDeviceInterface) {
private textBackupsInterval: ReturnType<typeof setInterval> | undefined
private needsInitialTextBackup = false
constructor(
application: WebApplicationInterface,
private device: DesktopDeviceInterface,
private backups: BackupServiceInterface,
) {
super(application, new InternalEventBus())
}
async handleWatchedDirectoriesChanges(changes: DesktopWatchedDirectoriesChanges): Promise<void> {
void this.backups.importWatchedDirectoryChanges(changes)
}
beginTextBackupsTimer() {
if (this.textBackupsInterval) {
clearInterval(this.textBackupsInterval)
}
this.needsInitialTextBackup = true
const hoursInterval = 12
const seconds = hoursInterval * 60 * 60
const milliseconds = seconds * 1000
this.textBackupsInterval = setInterval(this.saveDesktopBackup, milliseconds)
}
get webApplication() {
return this.application as WebApplicationInterface
}
@@ -44,14 +70,35 @@ export class DesktopManager
super.onAppEvent(eventName).catch(console.error)
if (eventName === ApplicationEvent.LocalDataLoaded) {
this.dataLoaded = true
this.device.onInitialDataLoad()
if (this.backups.isTextBackupsEnabled()) {
this.beginTextBackupsTimer()
}
} else if (eventName === ApplicationEvent.MajorDataChange) {
this.device.onMajorDataChange()
void this.saveDesktopBackup()
}
}
saveBackup() {
this.device.onMajorDataChange()
async saveDesktopBackup() {
this.webApplication.notifyWebEvent(WebAppEvent.BeganBackupDownload)
const data = await this.getBackupFile()
if (data) {
await this.webApplication.fileBackups?.saveTextBackupData(data)
this.webApplication.notifyWebEvent(WebAppEvent.EndedBackupDownload, { success: true })
}
}
private async getBackupFile(): Promise<string | undefined> {
const encrypted = this.application.hasProtectionSources()
const data = encrypted
? await this.application.createEncryptedBackupFileForAutomatedDesktopBackups()
: await this.application.createDecryptedBackupFile()
if (data) {
return JSON.stringify(data, null, 2)
}
return undefined
}
getExtServerHost(): string {
@@ -111,6 +158,11 @@ export class DesktopManager
windowLostFocus(): void {
this.webApplication.notifyWebEvent(WebAppEvent.WindowDidBlur)
if (this.needsInitialTextBackup) {
this.needsInitialTextBackup = false
void this.saveDesktopBackup()
}
}
async onComponentInstallationComplete(componentData: DecryptedTransferPayload<ComponentContent>) {
@@ -136,25 +188,4 @@ export class DesktopManager
observer.callback(updatedComponent as SNComponent)
}
}
async requestBackupFile(): Promise<string | undefined> {
const encrypted = this.application.hasProtectionSources()
const data = encrypted
? await this.application.createEncryptedBackupFileForAutomatedDesktopBackups()
: await this.application.createDecryptedBackupFile()
if (data) {
return JSON.stringify(data, null, 2)
}
return undefined
}
didBeginBackup() {
this.webApplication.notifyWebEvent(WebAppEvent.BeganBackupDownload)
}
didFinishBackup(success: boolean) {
this.webApplication.notifyWebEvent(WebAppEvent.EndedBackupDownload, { success })
}
}