You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
etesync-android/app/src/main/java/com/etesync/syncadapter/ui/CreateCollectionFragment.kt

175 lines
6.6 KiB

/*
* Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package com.etesync.syncadapter.ui
import android.accounts.Account
import android.app.Dialog
import android.app.ProgressDialog
import android.content.ContentResolver
import android.content.Context
import android.os.Bundle
import android.provider.CalendarContract
import androidx.fragment.app.DialogFragment
import androidx.loader.app.LoaderManager
import androidx.loader.content.AsyncTaskLoader
import androidx.loader.content.Loader
import com.etesync.syncadapter.*
import com.etesync.journalmanager.Crypto
import com.etesync.journalmanager.Exceptions
import com.etesync.journalmanager.JournalManager
import com.etesync.syncadapter.model.CollectionInfo
import com.etesync.syncadapter.model.JournalEntity
import com.etesync.syncadapter.model.JournalModel
import com.etesync.syncadapter.utils.TaskProviderHandling
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
class CreateCollectionFragment : DialogFragment(), LoaderManager.LoaderCallbacks<Exception> {
protected lateinit var account: Account
protected lateinit var info: CollectionInfo
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
account = arguments!!.getParcelable(ARG_ACCOUNT)!!
info = arguments!!.getSerializable(ARG_COLLECTION_INFO) as CollectionInfo
loaderManager.initLoader(0, null, this)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val progress = ProgressDialog(context)
progress.setTitle(R.string.create_collection_creating)
progress.setMessage(getString(R.string.please_wait))
progress.isIndeterminate = true
progress.setCanceledOnTouchOutside(false)
isCancelable = false
return progress
}
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Exception> {
return CreateCollectionLoader(context!!, account, info)
}
override fun onLoadFinished(loader: Loader<Exception>, exception: Exception?) {
dismissAllowingStateLoss()
val parent = activity
if (parent != null) {
if (exception != null)
fragmentManager!!.beginTransaction()
.add(ExceptionInfoFragment.newInstance(exception, account), null)
.commitAllowingStateLoss()
else
parent.finish()
}
}
override fun onLoaderReset(loader: Loader<Exception>) {}
protected class CreateCollectionLoader(context: Context, internal val account: Account, internal val info: CollectionInfo) : AsyncTaskLoader<Exception>(context) {
override fun onStartLoading() {
forceLoad()
}
override fun loadInBackground(): Exception? {
try {
val context = context.applicationContext
val data = (context as App).data
// 1. find service ID
val authority = when (info.enumType){
CollectionInfo.Type.ADDRESS_BOOK -> App.addressBooksAuthority
CollectionInfo.Type.CALENDAR -> CalendarContract.AUTHORITY
CollectionInfo.Type.TASKS ->
TaskProviderHandling.getWantedTaskSyncProvider(context)?.authority
else -> null
}
val serviceEntity = JournalModel.Service.fetchOrCreate(data, account.name, info.enumType)
info.serviceID = serviceEntity.id
val settings = AccountSettings(context, account)
val principal = settings.uri?.toHttpUrlOrNull()
val httpClient = HttpClient.Builder(context, settings).build().okHttpClient
val journalManager = JournalManager(httpClient, principal!!)
var uid = info.uid
if (uid == null) {
uid = JournalManager.Journal.genUid()
info.uid = uid
val crypto = Crypto.CryptoManager(info.version, settings.password(), uid)
val journal = JournalManager.Journal(crypto, info.toJson(), uid)
journalManager.create(journal)
val journalEntity = JournalEntity.fetchOrCreate(data, info)
data.upsert(journalEntity)
} else {
val crypto: Crypto.CryptoManager
val journalEntity = JournalEntity.fetch(data, serviceEntity, uid)
if (journalEntity.encryptedKey != null) {
crypto = Crypto.CryptoManager(info.version, settings.keyPair!!, journalEntity.encryptedKey)
} else {
crypto = Crypto.CryptoManager(info.version, settings.password(), uid)
}
val journal = JournalManager.Journal(crypto, info.toJson(), uid)
journalManager.update(journal)
}
authority?.let { requestSync(it) }
} catch (e: IllegalStateException) {
return e
} catch (e: Exceptions.HttpException) {
return e
} catch (e: InvalidAccountException) {
return e
} catch (e: Exceptions.IntegrityException) {
return e
} catch (e: Exceptions.GenericCryptoException) {
return e
} catch (e: Exceptions.AssociateNotAllowedException) {
return e
} catch (e: Exception) {
// Also catch all exceptions
return e
}
return null
}
private fun requestSync(authority: String) {
val extras = Bundle()
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true) // manual sync
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true) // run immediately (don't queue)
ContentResolver.requestSync(account, authority, extras)
}
}
companion object {
private val ARG_ACCOUNT = "account"
private val ARG_COLLECTION_INFO = "collectionInfo"
fun newInstance(account: Account, info: CollectionInfo): CreateCollectionFragment {
val frag = CreateCollectionFragment()
val args = Bundle(2)
args.putParcelable(ARG_ACCOUNT, account)
args.putSerializable(ARG_COLLECTION_INFO, info)
frag.arguments = args
return frag
}
}
}