Import: implement import in etebase.

pull/131/head
Tom Hacohen 4 years ago
parent c24936ff7e
commit 712346c7ae

@ -0,0 +1,79 @@
package com.etesync.syncadapter.ui.etebase
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.commit
import com.etesync.syncadapter.CachedCollection
import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.R
import com.etesync.syncadapter.ui.BaseActivity
import com.etesync.syncadapter.ui.importlocal.ImportFragment
import com.etesync.syncadapter.ui.importlocal.LocalCalendarImportFragment
import com.etesync.syncadapter.ui.importlocal.LocalContactImportFragment
class ImportCollectionFragment : Fragment() {
private val model: AccountViewModel by activityViewModels()
private val collectionModel: CollectionViewModel by activityViewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val ret = inflater.inflate(R.layout.import_actions_list, container, false)
setHasOptionsMenu(true)
if (savedInstanceState == null) {
collectionModel.observe(this) {
(activity as? BaseActivity?)?.supportActionBar?.setTitle(R.string.import_dialog_title)
if (container != null) {
initUi(inflater, ret, it)
}
}
}
return ret
}
private fun initUi(inflater: LayoutInflater, v: View, cachedCollection: CachedCollection) {
val accountHolder = model.value!!
var card = v.findViewById<View>(R.id.import_file)
var img = card.findViewById<View>(R.id.action_icon) as ImageView
var text = card.findViewById<View>(R.id.action_text) as TextView
img.setImageResource(R.drawable.ic_file_white)
text.setText(R.string.import_button_file)
card.setOnClickListener {
parentFragmentManager.commit {
add(ImportFragment.newInstance(accountHolder.account, cachedCollection), null)
}
}
card = v.findViewById(R.id.import_account)
img = card.findViewById<View>(R.id.action_icon) as ImageView
text = card.findViewById<View>(R.id.action_text) as TextView
img.setImageResource(R.drawable.ic_account_circle_white)
text.setText(R.string.import_button_local)
card.setOnClickListener {
if (cachedCollection.meta.collectionType == Constants.ETEBASE_TYPE_CALENDAR) {
parentFragmentManager.commit {
replace(R.id.fragment_container, LocalCalendarImportFragment(accountHolder.account, cachedCollection.col.uid))
addToBackStack(null)
}
} else if (cachedCollection.meta.collectionType == Constants.ETEBASE_TYPE_ADDRESS_BOOK) {
parentFragmentManager.commit {
replace(R.id.fragment_container, LocalContactImportFragment(accountHolder.account, cachedCollection.col.uid))
addToBackStack(null)
}
}
// FIXME: should be in the fragments once we kill legacy
(activity as? BaseActivity?)?.supportActionBar?.setTitle(R.string.import_select_account)
}
if (collectionModel.value!!.meta.collectionType == Constants.ETEBASE_TYPE_TASKS) {
card.visibility = View.GONE
}
}
}

@ -5,7 +5,6 @@ import android.graphics.Color.parseColor
import android.os.Bundle
import android.view.*
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@ -15,7 +14,6 @@ import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.R
import com.etesync.syncadapter.resource.LocalCalendar
import com.etesync.syncadapter.ui.BaseActivity
import com.etesync.syncadapter.ui.EditCollectionActivity
import com.etesync.syncadapter.ui.WebViewActivity
import com.etesync.syncadapter.utils.HintManager
import com.etesync.syncadapter.utils.ShowcaseBuilder
@ -143,7 +141,19 @@ class ViewCollectionFragment : Fragment() {
dialog.show()
} }
R.id.on_import -> {
Toast.makeText(context, "Import", Toast.LENGTH_LONG).show()
if (cachedCollection.col.accessLevel != "ro") {
parentFragmentManager.commit {
replace(R.id.fragment_container, ImportCollectionFragment())
addToBackStack(null)
}
} else {
val dialog = AlertDialog.Builder(requireContext())
.setIcon(R.drawable.ic_info_dark)
.setTitle(R.string.not_allowed_title)
.setMessage(R.string.edit_owner_only_anon)
.setPositiveButton(android.R.string.yes) { _, _ -> }.create()
dialog.show()
}
}
}
return super.onOptionsItemSelected(item)

@ -14,7 +14,7 @@ import com.etesync.syncadapter.R
import com.etesync.syncadapter.model.CollectionInfo
import com.etesync.syncadapter.ui.BaseActivity
class ImportActivity : BaseActivity(), SelectImportMethod, ResultFragment.OnImportCallback, DialogInterface {
class ImportActivity : BaseActivity(), SelectImportMethod, DialogInterface {
private lateinit var account: Account
protected lateinit var info: CollectionInfo
@ -83,13 +83,6 @@ class ImportActivity : BaseActivity(), SelectImportMethod, ResultFragment.OnImpo
return super.onKeyDown(keyCode, event)
}
override fun onImportResult(importResult: ResultFragment.ImportResult) {
val fragment = ResultFragment.newInstance(importResult)
supportFragmentManager.beginTransaction()
.add(fragment, "importResult")
.commitAllowingStateLoss()
}
override fun cancel() {
finish()
}

@ -14,12 +14,13 @@ import android.os.Bundle
import android.provider.CalendarContract
import android.provider.ContactsContract
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.commit
import at.bitfire.ical4android.*
import at.bitfire.vcard4android.BatchOperation
import at.bitfire.vcard4android.Contact
import at.bitfire.vcard4android.ContactsStorageException
import com.etesync.syncadapter.Constants.KEY_ACCOUNT
import com.etesync.syncadapter.Constants.KEY_COLLECTION_INFO
import com.etesync.syncadapter.CachedCollection
import com.etesync.syncadapter.Constants.*
import com.etesync.syncadapter.R
import com.etesync.syncadapter.log.Logger
import com.etesync.syncadapter.model.CollectionInfo
@ -34,19 +35,14 @@ import java.io.InputStream
import java.io.InputStreamReader
class ImportFragment : DialogFragment() {
class ImportFragment(private val account: Account, private val uid: String, private val enumType: CollectionInfo.Type) : DialogFragment() {
private lateinit var account: Account
private lateinit var info: CollectionInfo
private var inputStream: InputStream? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isCancelable = false
retainInstance = true
account = arguments!!.getParcelable(KEY_ACCOUNT)!!
info = arguments!!.getSerializable(KEY_COLLECTION_INFO) as CollectionInfo
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
@ -56,7 +52,7 @@ class ImportFragment : DialogFragment() {
} else {
val data = ImportResult()
data.e = Exception(getString(R.string.import_permission_required))
(activity as ResultFragment.OnImportCallback).onImportResult(data)
onImportResult(data)
dismissAllowingStateLoss()
}
@ -117,7 +113,7 @@ class ImportFragment : DialogFragment() {
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.action = Intent.ACTION_GET_CONTENT
when (info.enumType) {
when (enumType) {
CollectionInfo.Type.CALENDAR -> intent.type = "text/calendar"
CollectionInfo.Type.TASKS -> intent.type = "text/calendar"
CollectionInfo.Type.ADDRESS_BOOK -> intent.type = "text/x-vcard"
@ -131,7 +127,7 @@ class ImportFragment : DialogFragment() {
val data = ImportResult()
data.e = Exception("Failed to open file chooser.\nPlease install one.")
(activity as ResultFragment.OnImportCallback).onImportResult(data)
onImportResult(data)
dismissAllowingStateLoss()
}
@ -145,7 +141,7 @@ class ImportFragment : DialogFragment() {
if (data != null) {
// Get the URI of the selected file
val uri = data.data!!
Logger.log.info("Starting import into ${info.uid} from file ${uri}")
Logger.log.info("Starting import into ${uid} from file ${uri}")
try {
inputStream = activity!!.contentResolver.openInputStream(uri)
@ -156,7 +152,7 @@ class ImportFragment : DialogFragment() {
val importResult = ImportResult()
importResult.e = e
(activity as ResultFragment.OnImportCallback).onImportResult(importResult)
onImportResult(importResult)
dismissAllowingStateLoss()
}
@ -171,7 +167,7 @@ class ImportFragment : DialogFragment() {
}
fun loadFinished(data: ImportResult) {
(activity as ResultFragment.OnImportCallback).onImportResult(data)
onImportResult(data)
Logger.log.info("Finished import")
@ -216,7 +212,7 @@ class ImportFragment : DialogFragment() {
val context = context!!
val importReader = InputStreamReader(inputStream)
if (info.enumType == CollectionInfo.Type.CALENDAR) {
if (enumType == CollectionInfo.Type.CALENDAR) {
val events = Event.eventsFromReader(importReader, null)
importReader.close()
@ -238,7 +234,7 @@ class ImportFragment : DialogFragment() {
val localCalendar: LocalCalendar?
try {
localCalendar = LocalCalendar.findByName(account, provider, LocalCalendar.Factory, info.uid!!)
localCalendar = LocalCalendar.findByName(account, provider, LocalCalendar.Factory, uid!!)
if (localCalendar == null) {
throw FileNotFoundException("Failed to load local resource.")
}
@ -269,7 +265,7 @@ class ImportFragment : DialogFragment() {
entryProcessed()
}
} else if (info.enumType == CollectionInfo.Type.TASKS) {
} else if (enumType == CollectionInfo.Type.TASKS) {
val tasks = Task.tasksFromReader(importReader)
importReader.close()
@ -296,7 +292,7 @@ class ImportFragment : DialogFragment() {
provider?.let {
val localTaskList: LocalTaskList?
try {
localTaskList = LocalTaskList.findByName(account, it, LocalTaskList.Factory, info.uid!!)
localTaskList = LocalTaskList.findByName(account, it, LocalTaskList.Factory, uid!!)
if (localTaskList == null) {
throw FileNotFoundException("Failed to load local resource.")
}
@ -324,7 +320,7 @@ class ImportFragment : DialogFragment() {
entryProcessed()
}
}
} else if (info.enumType == CollectionInfo.Type.ADDRESS_BOOK) {
} else if (enumType == CollectionInfo.Type.ADDRESS_BOOK) {
val uidToLocalId = HashMap<String?, Long>()
val downloader = ContactsSyncManager.ResourceDownloader(context)
val contacts = Contact.fromReader(importReader, downloader)
@ -345,7 +341,7 @@ class ImportFragment : DialogFragment() {
return result
}
val localAddressBook = LocalAddressBook.findByUid(context, provider, account, info.uid!!)
val localAddressBook = LocalAddressBook.findByUid(context, provider, account, uid!!)
if (localAddressBook == null) {
throw FileNotFoundException("Failed to load local address book.")
}
@ -423,18 +419,30 @@ class ImportFragment : DialogFragment() {
}
}
fun onImportResult(importResult: ImportResult) {
val fragment = ResultFragment.newInstance(importResult)
parentFragmentManager.commit(true) {
add(fragment, "importResult")
}
}
companion object {
private val REQUEST_CODE = 6384 // onActivityResult request
private val TAG_PROGRESS_MAX = "progressMax"
fun newInstance(account: Account, info: CollectionInfo): ImportFragment {
val frag = ImportFragment()
val args = Bundle(1)
args.putParcelable(KEY_ACCOUNT, account)
args.putSerializable(KEY_COLLECTION_INFO, info)
frag.arguments = args
return frag
return ImportFragment(account, info.uid!!, info.enumType!!)
}
fun newInstance(account: Account, cachedCollection: CachedCollection): ImportFragment {
val enumType = when (cachedCollection.meta.collectionType) {
ETEBASE_TYPE_CALENDAR -> CollectionInfo.Type.CALENDAR
ETEBASE_TYPE_TASKS -> CollectionInfo.Type.TASKS
ETEBASE_TYPE_ADDRESS_BOOK -> CollectionInfo.Type.ADDRESS_BOOK
else -> throw Exception("Got unsupported collection type")
}
return ImportFragment(account, cachedCollection.col.uid, enumType)
}
}
}

@ -14,9 +14,8 @@ import android.widget.ExpandableListView
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.ListFragment
import androidx.fragment.app.commit
import at.bitfire.ical4android.CalendarStorageException
import com.etesync.syncadapter.Constants.KEY_ACCOUNT
import com.etesync.syncadapter.Constants.KEY_COLLECTION_INFO
import com.etesync.syncadapter.R
import com.etesync.syncadapter.log.Logger
import com.etesync.syncadapter.model.CollectionInfo
@ -24,17 +23,10 @@ import com.etesync.syncadapter.resource.LocalCalendar
import com.etesync.syncadapter.resource.LocalEvent
class LocalCalendarImportFragment : ListFragment() {
private lateinit var account: Account
private lateinit var info: CollectionInfo
class LocalCalendarImportFragment(private val account: Account, private val uid: String) : ListFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
account = arguments!!.getParcelable(KEY_ACCOUNT)!!
info = arguments!!.getSerializable(KEY_COLLECTION_INFO) as CollectionInfo
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -200,7 +192,7 @@ class LocalCalendarImportFragment : ListFragment() {
if (progressDialog.isShowing && !activity.isDestroyed) {
progressDialog.dismiss()
}
(activity as ResultFragment.OnImportCallback).onImportResult(result)
onImportResult(result)
}
private fun importEvents(fromCalendar: LocalCalendar): ResultFragment.ImportResult {
@ -208,7 +200,7 @@ class LocalCalendarImportFragment : ListFragment() {
try {
val localCalendar = LocalCalendar.findByName(account,
context!!.contentResolver.acquireContentProviderClient(CalendarContract.CONTENT_URI)!!,
LocalCalendar.Factory, info!!.uid!!)
LocalCalendar.Factory, uid)
val localEvents = fromCalendar.findAll()
val total = localEvents.size
progressDialog.max = total
@ -248,15 +240,17 @@ class LocalCalendarImportFragment : ListFragment() {
}
}
fun onImportResult(importResult: ResultFragment.ImportResult) {
val fragment = ResultFragment.newInstance(importResult)
parentFragmentManager.commit(true) {
add(fragment, "importResult")
}
}
companion object {
fun newInstance(account: Account, info: CollectionInfo): LocalCalendarImportFragment {
val frag = LocalCalendarImportFragment()
val args = Bundle(1)
args.putParcelable(KEY_ACCOUNT, account)
args.putSerializable(KEY_COLLECTION_INFO, info)
frag.arguments = args
return frag
return LocalCalendarImportFragment(account, info.uid!!)
}
}
}

@ -18,6 +18,7 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import at.bitfire.vcard4android.ContactsStorageException
@ -32,18 +33,12 @@ import com.etesync.syncadapter.resource.LocalGroup
import java.util.*
class LocalContactImportFragment : Fragment() {
private lateinit var account: Account
private lateinit var info: CollectionInfo
class LocalContactImportFragment(private val account: Account, private val uid: String) : Fragment() {
private var recyclerView: RecyclerView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
account = arguments!!.getParcelable(KEY_ACCOUNT)
info = arguments!!.getSerializable(KEY_COLLECTION_INFO) as CollectionInfo
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -134,7 +129,7 @@ class LocalContactImportFragment : Fragment() {
if (progressDialog.isShowing && !activity.isDestroyed) {
progressDialog.dismiss()
}
(activity as ResultFragment.OnImportCallback).onImportResult(result)
onImportResult(result)
}
private fun importContacts(localAddressBook: LocalAddressBook): ResultFragment.ImportResult {
@ -142,7 +137,7 @@ class LocalContactImportFragment : Fragment() {
try {
val addressBook = LocalAddressBook.findByUid(context!!,
context!!.contentResolver.acquireContentProviderClient(ContactsContract.RawContacts.CONTENT_URI)!!,
account, info.uid!!)!!
account, uid)!!
val localContacts = localAddressBook.findAllContacts()
val localGroups = localAddressBook.findAllGroups()
val oldIdToNewId = HashMap<Long, Long>()
@ -214,6 +209,13 @@ class LocalContactImportFragment : Fragment() {
}
}
fun onImportResult(importResult: ResultFragment.ImportResult) {
val fragment = ResultFragment.newInstance(importResult)
parentFragmentManager.commit(true) {
add(fragment, "importResult")
}
}
class ImportContactAdapter
/**
* Initialize the dataset of the Adapter.
@ -316,13 +318,7 @@ class LocalContactImportFragment : Fragment() {
companion object {
fun newInstance(account: Account, info: CollectionInfo): LocalContactImportFragment {
val frag = LocalContactImportFragment()
val args = Bundle(1)
args.putParcelable(KEY_ACCOUNT, account)
args.putSerializable(KEY_COLLECTION_INFO, info)
frag.arguments = args
return frag
return LocalContactImportFragment(account, info.uid!!)
}
}
}

@ -72,10 +72,6 @@ class ResultFragment : DialogFragment() {
}
}
interface OnImportCallback {
fun onImportResult(importResult: ImportResult)
}
companion object {
private val KEY_RESULT = "result"

Loading…
Cancel
Save