mirror of
https://github.com/etesync/android
synced 2025-07-07 15:18:16 +00:00
175 lines
6.6 KiB
Kotlin
175 lines
6.6 KiB
Kotlin
/*
|
||
* 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
|
||
}
|
||
}
|
||
|
||
}
|