mirror of
https://github.com/etesync/android
synced 2025-01-10 15:51:08 +00:00
Import: implement import in etebase.
This commit is contained in:
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…
Reference in New Issue
Block a user