/* * 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.content.Context import android.content.DialogInterface import android.content.Intent import android.os.AsyncTask import android.os.Bundle import android.provider.CalendarContract import android.provider.ContactsContract import android.view.Gravity import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.TextView import androidx.appcompat.app.AlertDialog import at.bitfire.ical4android.CalendarStorageException import at.bitfire.ical4android.TaskProvider import at.bitfire.vcard4android.ContactsStorageException import com.etesync.syncadapter.App import com.etesync.syncadapter.Constants import com.etesync.syncadapter.R import com.etesync.syncadapter.model.CollectionInfo import com.etesync.syncadapter.model.EntryEntity import com.etesync.syncadapter.model.JournalEntity import com.etesync.syncadapter.resource.LocalAddressBook import com.etesync.syncadapter.resource.LocalCalendar import com.etesync.syncadapter.resource.LocalTaskList import com.etesync.syncadapter.ui.importlocal.ImportActivity import com.etesync.syncadapter.ui.journalviewer.ListEntriesFragment import com.etesync.syncadapter.utils.HintManager import com.etesync.syncadapter.utils.ShowcaseBuilder import com.etesync.syncadapter.utils.TaskProviderHandling import com.google.android.material.floatingactionbutton.FloatingActionButton import tourguide.tourguide.ToolTip import java.io.FileNotFoundException import java.util.* class ViewCollectionActivity : BaseActivity(), Refreshable { private lateinit var account: Account private var journalEntity: JournalEntity? = null protected lateinit var info: CollectionInfo private var isOwner: Boolean = false override fun refresh() { val data = (applicationContext as App).data journalEntity = JournalEntity.fetch(data, info.getServiceEntity(data), info.uid) if (journalEntity == null || journalEntity!!.isDeleted) { finish() return } info = journalEntity!!.info isOwner = journalEntity!!.isOwner(account.name) val colorSquare = findViewById(R.id.color) when (info.enumType) { CollectionInfo.Type.CALENDAR -> { colorSquare.setBackgroundColor(info.color ?: LocalCalendar.defaultColor) } CollectionInfo.Type.TASKS -> { colorSquare.setBackgroundColor(info.color ?: LocalCalendar.defaultColor) val tasksNotShowing = findViewById(R.id.tasks_not_showing) tasksNotShowing.visibility = View.VISIBLE } CollectionInfo.Type.ADDRESS_BOOK -> { colorSquare.visibility = View.GONE } null -> { } } LoadCountTask().execute() val title = findViewById(R.id.display_name) as TextView title.text = info.displayName val desc = findViewById(R.id.description) as TextView desc.text = info.description val owner = findViewById(R.id.owner) as TextView if (isOwner) { owner.visibility = View.GONE } else { owner.visibility = View.VISIBLE owner.text = getString(R.string.account_owner, journalEntity!!.owner) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.view_collection_activity) supportActionBar!!.setDisplayHomeAsUpEnabled(true) account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!! info = intent.extras!!.getSerializable(EXTRA_COLLECTION_INFO) as CollectionInfo if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .add(R.id.list_entries_container, ListEntriesFragment.newInstance(account, info)) .commit() } refresh() val title = findViewById(R.id.display_name) as TextView if (!HintManager.getHintSeen(this, HINT_IMPORT)) { val tourGuide = ShowcaseBuilder.getBuilder(this) .setToolTip(ToolTip().setTitle(getString(R.string.tourguide_title)).setDescription(getString(R.string.account_showcase_import)).setGravity(Gravity.BOTTOM)) .setPointer(null) tourGuide.mOverlay.setHoleRadius(0) tourGuide.playOn(title) HintManager.setHintSeen(this, HINT_IMPORT, true) } val fab = findViewById(R.id.fab) fab.setOnClickListener { AlertDialog.Builder(this) .setIcon(R.drawable.ic_info_dark) .setTitle(R.string.use_native_apps_title) .setMessage(R.string.use_native_apps_body) .setNegativeButton(R.string.navigation_drawer_guide, { _: DialogInterface, _: Int -> WebViewActivity.openUrl(this, Constants.helpUri) }) .setPositiveButton(android.R.string.yes) { _, _ -> }.show() } } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.activity_view_collection, menu) return true } override fun onResume() { super.onResume() refresh() } fun onEditCollection(item: MenuItem) { if (isOwner) { startActivity(EditCollectionActivity.newIntent(this, account, info)) } else { val dialog = AlertDialog.Builder(this) .setIcon(R.drawable.ic_info_dark) .setTitle(R.string.not_allowed_title) .setMessage(getString(R.string.edit_owner_only, journalEntity!!.owner)) .setPositiveButton(android.R.string.yes) { _, _ -> }.create() dialog.show() } } fun onImport(item: MenuItem) { startActivity(ImportActivity.newIntent(this@ViewCollectionActivity, account, info)) } fun onManageMembers(item: MenuItem) { if (info.version < 2) { val dialog = AlertDialog.Builder(this) .setIcon(R.drawable.ic_info_dark) .setTitle(R.string.not_allowed_title) .setMessage(R.string.members_old_journals_not_allowed) .setPositiveButton(android.R.string.yes) { _, _ -> }.create() dialog.show() } else if (isOwner) { startActivity(CollectionMembersActivity.newIntent(this, account, info)) } else { val dialog = AlertDialog.Builder(this) .setIcon(R.drawable.ic_info_dark) .setTitle(R.string.not_allowed_title) .setMessage(getString(R.string.members_owner_only, journalEntity!!.owner)) .setPositiveButton(android.R.string.yes) { _, _ -> }.create() dialog.show() } } private inner class LoadCountTask : AsyncTask() { private var entryCount: Int = 0 override fun doInBackground(vararg aVoids: Void): Long? { val data = (applicationContext as App).data val journalEntity = JournalEntity.fetch(data, info.getServiceEntity(data), info.uid) entryCount = data.count(EntryEntity::class.java).where(EntryEntity.JOURNAL.eq(journalEntity)).get().value() var count: Long = -1 when (info.enumType) { CollectionInfo.Type.CALENDAR -> { try { val providerClient = contentResolver.acquireContentProviderClient(CalendarContract.CONTENT_URI) if (providerClient == null) { return null } val resource = LocalCalendar.findByName(account, providerClient, LocalCalendar.Factory, info.uid!!) providerClient.release() if (resource == null) { return null } count = resource.count() } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: CalendarStorageException) { e.printStackTrace() } } CollectionInfo.Type.TASKS -> { try { val providerClient = TaskProviderHandling.getWantedTaskSyncProvider(this@ViewCollectionActivity)?.let { TaskProvider.acquire(this@ViewCollectionActivity, it) } if (providerClient == null) { return null } val resource = LocalTaskList.findByName(account, providerClient, LocalTaskList.Factory, info.uid!!) if (resource == null) { return null } count = resource.count() } catch (e: ContactsStorageException) { e.printStackTrace() } } CollectionInfo.Type.ADDRESS_BOOK -> { try { val providerClient = contentResolver.acquireContentProviderClient(ContactsContract.Contacts.CONTENT_URI) if (providerClient == null) { return null } val resource = LocalAddressBook.findByUid(this@ViewCollectionActivity, providerClient, account, info.uid!!) providerClient.release() if (resource == null) { return null } count = resource.count() } catch (e: ContactsStorageException) { e.printStackTrace() } } null -> { } } return count } override fun onPostExecute(result: Long?) { val stats = findViewById(R.id.stats) as TextView findViewById(R.id.progressBar).visibility = View.GONE if (result == null) { stats.text = "Stats loading error." } else { when (info.enumType) { CollectionInfo.Type.CALENDAR -> { stats.text = String.format(Locale.getDefault(), "Events: %d, Journal entries: %d", result, entryCount) } CollectionInfo.Type.TASKS -> { stats.text = String.format(Locale.getDefault(), "Tasks: %d, Journal entries: %d", result, entryCount) } CollectionInfo.Type.ADDRESS_BOOK -> { stats.text = String.format(Locale.getDefault(), "Contacts: %d, Journal Entries: %d", result, entryCount) } null -> { } } } } } companion object { private val HINT_IMPORT = "Import" val EXTRA_ACCOUNT = "account" val EXTRA_COLLECTION_INFO = "collectionInfo" fun newIntent(context: Context, account: Account, info: CollectionInfo): Intent { val intent = Intent(context, ViewCollectionActivity::class.java) intent.putExtra(ViewCollectionActivity.EXTRA_ACCOUNT, account) intent.putExtra(ViewCollectionActivity.EXTRA_COLLECTION_INFO, info) return intent } } }