99package com.owncloud.android.ui.fragment.contactsbackup
1010
1111import android.Manifest
12- import android.annotation.SuppressLint
1312import android.app.DatePickerDialog
1413import android.app.DatePickerDialog.OnDateSetListener
1514import android.content.Context
1615import android.content.Intent
17- import android.os.AsyncTask
1816import android.os.Bundle
1917import android.view.LayoutInflater
2018import android.view.MenuItem
@@ -24,10 +22,12 @@ import android.widget.CompoundButton
2422import android.widget.DatePicker
2523import android.widget.Toast
2624import androidx.core.app.ActivityCompat
25+ import androidx.lifecycle.lifecycleScope
2726import com.nextcloud.client.account.User
2827import com.nextcloud.client.di.Injectable
2928import com.nextcloud.client.jobs.BackgroundJobManager
3029import com.nextcloud.utils.extensions.getSerializableArgument
30+ import com.nextcloud.utils.extensions.setVisibleIf
3131import com.owncloud.android.R
3232import com.owncloud.android.databinding.BackupFragmentBinding
3333import com.owncloud.android.datamodel.ArbitraryDataProvider
@@ -44,6 +44,9 @@ import com.owncloud.android.utils.PermissionUtil
4444import com.owncloud.android.utils.PermissionUtil.checkSelfPermission
4545import com.owncloud.android.utils.theme.ThemeUtils
4646import com.owncloud.android.utils.theme.ViewThemeUtils
47+ import kotlinx.coroutines.Dispatchers
48+ import kotlinx.coroutines.launch
49+ import kotlinx.coroutines.withContext
4750import third_parties.daveKoeller.AlphanumComparator
4851import java.util.Calendar
4952import java.util.GregorianCalendar
@@ -77,7 +80,7 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
7780 private var showCalendarBackup = true
7881 private var isCalendarBackupEnabled: Boolean
7982 get() = arbitraryDataProvider.getBooleanValue(user, PREFERENCE_CALENDAR_BACKUP_ENABLED )
80- private set(enabled) {
83+ set(enabled) {
8184 arbitraryDataProvider.storeOrUpdateKeyValue(
8285 user.accountName,
8386 PREFERENCE_CALENDAR_BACKUP_ENABLED ,
@@ -87,21 +90,28 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
8790
8891 private var isContactsBackupEnabled: Boolean
8992 get() = arbitraryDataProvider.getBooleanValue(user, PREFERENCE_CONTACTS_BACKUP_ENABLED )
90- private set(enabled) {
93+ set(enabled) {
9194 arbitraryDataProvider.storeOrUpdateKeyValue(
9295 user.accountName,
9396 PREFERENCE_CONTACTS_BACKUP_ENABLED ,
9497 enabled
9598 )
9699 }
97100
101+ private lateinit var contactsBackupFolderPath: String
102+ private lateinit var calendarBackupFolderPath: String
103+
98104 override fun onCreateView (inflater : LayoutInflater , container : ViewGroup ? , savedInstanceState : Bundle ? ): View {
99105 // use grey as fallback for elements where custom theming is not available
100106 if (themeUtils.themingEnabled(context)) {
101107 requireContext().theme.applyStyle(R .style.FallbackThemingTheme , true )
102108 }
103109
104110 binding = BackupFragmentBinding .inflate(inflater, container, false )
111+
112+ contactsBackupFolderPath = getString(R .string.contacts_backup_folder) + OCFile .PATH_SEPARATOR
113+ calendarBackupFolderPath = getString(R .string.calendar_backup_folder) + OCFile .PATH_SEPARATOR
114+
105115 val view: View = binding.root
106116
107117 setHasOptionsMenu(true )
@@ -175,8 +185,9 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
175185 }
176186
177187 private fun setBackupNowButtonVisibility () {
178- binding.backupNow.visibility =
179- if (binding.contacts.isChecked || binding.calendar.isChecked) View .VISIBLE else View .INVISIBLE
188+ binding.run {
189+ backupNow.isEnabled = (contacts.isChecked || calendar.isChecked)
190+ }
180191 }
181192
182193 private fun setOnClickListeners () {
@@ -239,61 +250,73 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
239250 openDate(selectedDate)
240251 }
241252
242- val contactsPreferenceActivity = activity as ContactsPreferenceActivity ?
243- if (contactsPreferenceActivity != null ) {
244- val backupFolderPath = resources.getString(R .string.contacts_backup_folder) + OCFile .PATH_SEPARATOR
245- refreshBackupFolder(
246- backupFolderPath,
247- contactsPreferenceActivity.applicationContext,
248- contactsPreferenceActivity.storageManager
249- )
253+ (activity as ? ContactsPreferenceActivity )?.let {
254+ refreshBackupFolder(it.storageManager)
250255 }
251256 }
252257
253- private fun refreshBackupFolder (
254- backupFolderPath : String ,
255- context : Context ,
256- storageManager : FileDataStorageManager
257- ) {
258- val task: AsyncTask <String , Int , Boolean > =
259- @SuppressLint(" StaticFieldLeak" )
260- object : AsyncTask <String , Int , Boolean >() {
261- @Deprecated(" Deprecated in Java" )
262- override fun doInBackground (vararg path : String ): Boolean {
263- val folder = storageManager.getFileByPath(path[0 ])
264- return if (folder != null ) {
265- val operation = RefreshFolderOperation (
266- folder,
267- System .currentTimeMillis(),
268- false ,
269- false ,
270- storageManager,
271- user,
272- context
273- )
274- val result = operation.execute(user, context)
275- result.isSuccess
276- } else {
277- false
278- }
258+ private fun refreshBackupFolder (storageManager : FileDataStorageManager ) {
259+ lifecycleScope.launch {
260+ val backupFiles = listOf (calendarBackupFolderPath, contactsBackupFolderPath)
261+ .mapNotNull { path -> storageManager.getFileByDecryptedRemotePath(path) }
262+ .flatMap { folder -> fetchBackupFiles(folder, storageManager) }
263+ .toMutableList()
264+ .also {
265+ it.sortWith(AlphanumComparator ())
279266 }
280267
281- @Deprecated(" Deprecated in Java" )
282- override fun onPostExecute (result : Boolean ) {
283- if (result) {
284- val backupFolder = storageManager.getFileByPath(backupFolderPath)
285- val backupFiles = storageManager.getFolderContent(backupFolder, false )
286- backupFiles.sortWith(AlphanumComparator ())
287- if (backupFiles.isEmpty()) {
288- binding.contactsDatepicker.visibility = View .INVISIBLE
289- } else {
290- binding.contactsDatepicker.visibility = View .VISIBLE
291- }
292- }
293- }
268+ withContext(Dispatchers .Main ) {
269+ binding.contactsDatepicker.setVisibleIf(backupFiles.isNotEmpty())
294270 }
271+ }
272+ }
273+
274+ /* *
275+ * Returns backup files from database
276+ */
277+ private fun getBackupFiles (): List <OCFile > {
278+ val contactsPreferenceActivity = activity as ContactsPreferenceActivity ?
279+ val storageManager = contactsPreferenceActivity?.storageManager ? : return listOf ()
280+ val contactsBackupFolder = storageManager.getFileByDecryptedRemotePath(contactsBackupFolderPath)
281+ val calendarBackupFolder = storageManager.getFileByDecryptedRemotePath(calendarBackupFolderPath)
295282
296- task.execute(backupFolderPath)
283+ val backupFiles = storageManager.getFolderContent(contactsBackupFolder, false )
284+ backupFiles.addAll(storageManager.getFolderContent(calendarBackupFolder, false ))
285+ return backupFiles
286+ }
287+
288+ /* *
289+ * Refreshes the folder and returns updated backup files
290+ */
291+ @Suppress(" TooGenericExceptionCaught" )
292+ private suspend fun fetchBackupFiles (folder : OCFile , storageManager : FileDataStorageManager ): List <OCFile > {
293+ return withContext(Dispatchers .IO ) {
294+ try {
295+ val operation = RefreshFolderOperation (
296+ folder,
297+ System .currentTimeMillis(),
298+ false ,
299+ false ,
300+ storageManager,
301+ user,
302+ context
303+ )
304+
305+ @Suppress(" DEPRECATION" )
306+ val result = operation.execute(user, context)
307+
308+ if (result.isSuccess) {
309+ Log_OC .d(TAG , " Backup files fetched" )
310+ storageManager.getFolderContent(folder, false )
311+ } else {
312+ Log_OC .d(TAG , " Backup files cannot be fetched" )
313+ listOf ()
314+ }
315+ } catch (e: Exception ) {
316+ Log_OC .d(TAG , " Exception fetchBackupFiles: $e " )
317+ listOf ()
318+ }
319+ }
297320 }
298321
299322 @Deprecated(" Deprecated in Java" )
@@ -500,14 +523,7 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
500523 return
501524 }
502525
503- val contactsBackupFolderString = getString(R .string.contacts_backup_folder) + OCFile .PATH_SEPARATOR
504- val calendarBackupFolderString = getString(R .string.calendar_backup_folder) + OCFile .PATH_SEPARATOR
505- val storageManager = contactsPreferenceActivity.storageManager
506- val contactsBackupFolder = storageManager.getFileByDecryptedRemotePath(contactsBackupFolderString)
507- val calendarBackupFolder = storageManager.getFileByDecryptedRemotePath(calendarBackupFolderString)
508-
509- val backupFiles = storageManager.getFolderContent(contactsBackupFolder, false )
510- backupFiles.addAll(storageManager.getFolderContent(calendarBackupFolder, false ))
526+ val backupFiles = getBackupFiles().toMutableList()
511527 backupFiles.sortBy { it.modificationTimestamp }
512528
513529 if (backupFiles.isNotEmpty() && backupFiles.last() != null ) {
@@ -570,13 +586,7 @@ class BackupFragment : FileFragment(), OnDateSetListener, Injectable {
570586 }
571587
572588 selectedDate = GregorianCalendar (year, month, dayOfMonth)
573- val contactsBackupFolderString = getString(R .string.contacts_backup_folder) + OCFile .PATH_SEPARATOR
574- val calendarBackupFolderString = getString(R .string.calendar_backup_folder) + OCFile .PATH_SEPARATOR
575- val storageManager = contactsPreferenceActivity.storageManager
576- val contactsBackupFolder = storageManager.getFileByDecryptedRemotePath(contactsBackupFolderString)
577- val calendarBackupFolder = storageManager.getFileByDecryptedRemotePath(calendarBackupFolderString)
578- val backupFiles = storageManager.getFolderContent(contactsBackupFolder, false )
579- backupFiles.addAll(storageManager.getFolderContent(calendarBackupFolder, false ))
589+ val backupFiles = getBackupFiles()
580590
581591 // find file with modification with date and time between 00:00 and 23:59
582592 // if more than one file exists, take oldest
0 commit comments