Skip to content

Commit fd030cc

Browse files
committed
Re-create backups correctly when backup folder changes
1 parent 7764800 commit fd030cc

2 files changed

Lines changed: 62 additions & 16 deletions

File tree

app/src/main/java/com/philkes/notallyx/NotallyXApplication.kt

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import com.philkes.notallyx.presentation.viewmodel.preference.Theme
2121
import com.philkes.notallyx.presentation.widget.WidgetProvider
2222
import com.philkes.notallyx.utils.backup.AUTO_BACKUP_WORK_NAME
2323
import com.philkes.notallyx.utils.backup.autoBackupOnSave
24+
import com.philkes.notallyx.utils.backup.autoBackupOnSaveFileExists
2425
import com.philkes.notallyx.utils.backup.cancelAutoBackup
2526
import com.philkes.notallyx.utils.backup.containsNonCancelled
27+
import com.philkes.notallyx.utils.backup.createBackup
2628
import com.philkes.notallyx.utils.backup.deleteModifiedNoteBackup
2729
import com.philkes.notallyx.utils.backup.isEqualTo
2830
import com.philkes.notallyx.utils.backup.modifiedNoteBackupExists
@@ -31,6 +33,7 @@ import com.philkes.notallyx.utils.backup.updateAutoBackup
3133
import com.philkes.notallyx.utils.observeOnce
3234
import com.philkes.notallyx.utils.security.UnlockReceiver
3335
import java.util.concurrent.TimeUnit
36+
import kotlinx.coroutines.CoroutineScope
3437
import kotlinx.coroutines.Dispatchers
3538
import kotlinx.coroutines.MainScope
3639
import kotlinx.coroutines.launch
@@ -79,7 +82,9 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
7982
backupFolderBefore,
8083
backupFolder,
8184
preferences.periodicBackups.value.periodInDays.toLong(),
85+
execute = true,
8286
)
87+
checkUpdateAutoBackupOnSave(backupFolderBefore, backupFolder)
8388
}
8489
preferences.periodicBackups.observeForever { value ->
8590
val backupFolder = preferences.backupsFolder.value
@@ -117,14 +122,12 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
117122
previousBackupPassword != backupPassword)
118123
) {
119124
deleteModifiedNoteBackup(backupPath)
120-
MainScope().launch {
121-
withContext(Dispatchers.IO) {
122-
autoBackupOnSave(
123-
backupPath,
124-
savedNote = null,
125-
password = backupPassword,
126-
)
127-
}
125+
runOnIODispatcher {
126+
autoBackupOnSave(
127+
backupPath,
128+
savedNote = null,
129+
password = backupPassword,
130+
)
128131
}
129132
}
130133
}
@@ -136,6 +139,7 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
136139
backupFolderBefore: String?,
137140
backupFolder: String,
138141
periodInDays: Long,
142+
execute: Boolean = false,
139143
) {
140144
val workManager = getWorkManagerSafe() ?: return
141145
workManager.getWorkInfosForUniqueWorkLiveData(AUTO_BACKUP_WORK_NAME).observeOnce { workInfos
@@ -150,10 +154,30 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
150154
(backupFolderBefore != null && backupFolderBefore != backupFolder)
151155
) {
152156
workManager.scheduleAutoBackup(this, periodInDays)
157+
if (execute) {
158+
runOnIODispatcher { createBackup() }
159+
}
153160
} else if (
154161
workInfos.first().periodicityInfo?.isEqualTo(periodInDays, TimeUnit.DAYS) == false
155162
) {
156163
workManager.updateAutoBackup(workInfos, periodInDays)
164+
if (execute) {
165+
runOnIODispatcher { createBackup() }
166+
}
167+
}
168+
}
169+
}
170+
171+
private fun checkUpdateAutoBackupOnSave(backupFolderBefore: String?, backupFolder: String) {
172+
if (preferences.backupOnSave.value) {
173+
if (backupFolderBefore == null && !autoBackupOnSaveFileExists(backupFolder)) {
174+
runOnIODispatcher {
175+
autoBackupOnSave(backupFolder, preferences.backupPassword.value, null)
176+
}
177+
}
178+
} else if (backupFolderBefore != backupFolder) {
179+
runOnIODispatcher {
180+
autoBackupOnSave(backupFolder, preferences.backupPassword.value, null)
157181
}
158182
}
159183
}
@@ -167,10 +191,8 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
167191
}
168192
}
169193

170-
companion object {
171-
private fun isTestRunner(): Boolean {
172-
return Build.FINGERPRINT.equals("robolectric", ignoreCase = true)
173-
}
194+
private fun <T> runOnIODispatcher(block: suspend CoroutineScope.() -> T) {
195+
MainScope().launch { withContext(Dispatchers.IO, block) }
174196
}
175197

176198
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
@@ -188,4 +210,10 @@ class NotallyXApplication : Application(), Application.ActivityLifecycleCallback
188210
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
189211

190212
override fun onActivityDestroyed(activity: Activity) {}
213+
214+
companion object {
215+
private fun isTestRunner(): Boolean {
216+
return Build.FINGERPRINT.equals("robolectric", ignoreCase = true)
217+
}
218+
}
191219
}

app/src/main/java/com/philkes/notallyx/utils/backup/ExportExtensions.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ fun ContextWrapper.createBackup(): Result {
161161
return Result.success()
162162
}
163163

164+
fun ContextWrapper.autoBackupOnSaveFileExists(backupPath: String): Boolean {
165+
val backupFolderFile = DocumentFile.fromTreeUri(this, backupPath.toUri())
166+
return backupFolderFile?.let {
167+
val autoBackupFile = it.findFile("$ON_SAVE_BACKUP_FILE.zip")
168+
autoBackupFile == null || !autoBackupFile.exists()
169+
} ?: false
170+
}
171+
164172
fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedNote: BaseNote?) {
165173
val folder =
166174
requireBackupFolder(
@@ -171,14 +179,24 @@ fun ContextWrapper.autoBackupOnSave(backupPath: String, password: String, savedN
171179
logToFile(TAG, folder, "$NOTALLYX_BACKUP_LOGS_FILE.txt", msg = msg, throwable = throwable)
172180
}
173181
try {
182+
var changedNote = savedNote
174183
var backupFile = folder.findFile("$ON_SAVE_BACKUP_FILE.zip")
175-
if (savedNote == null || backupFile == null || !backupFile.exists()) {
176-
backupFile = folder.createFileSafe(MIME_TYPE_ZIP, ON_SAVE_BACKUP_FILE, ".zip")
177-
exportAsZip(backupFile!!.uri, password = password)
184+
backupFile =
185+
if (backupFile == null || !backupFile.exists()) {
186+
if (savedNote != null) {
187+
log("Re-creating full backup since auto backup ZIP unexpectedly does not exist")
188+
changedNote = null
189+
}
190+
folder.createFileSafe(MIME_TYPE_ZIP, ON_SAVE_BACKUP_FILE, ".zip")
191+
} else backupFile
192+
if (changedNote == null) {
193+
// Export all notes
194+
exportAsZip(backupFile.uri, password = password)
178195
} else {
196+
// Only add changed note to existing backup ZIP
179197
val (_, file) = copyDatabase()
180198
val files =
181-
with(savedNote) {
199+
with(changedNote) {
182200
images.map {
183201
BackupFile(
184202
SUBFOLDER_IMAGES,

0 commit comments

Comments
 (0)