From df9f2f4ed465d1e3df1cec47e7d55f81e8c47157 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 27 Aug 2020 18:05:44 +0300 Subject: [PATCH] Collection member listing. --- .../ui/etebase/CollectionMembersFragment.kt | 63 ++++++++ .../etebase/CollectionMembersListFragment.kt | 145 ++++++++++++++++++ .../ui/etebase/ViewCollectionFragment.kt | 15 +- .../etebase_view_collection_members.xml | 56 +++++++ 4 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt create mode 100644 app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersListFragment.kt create mode 100644 app/src/main/res/layout/etebase_view_collection_members.xml diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt new file mode 100644 index 00000000..013515a7 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt @@ -0,0 +1,63 @@ +package com.etesync.syncadapter.ui.etebase + +import android.graphics.Color.parseColor +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import com.etesync.syncadapter.CachedCollection +import com.etesync.syncadapter.Constants +import com.etesync.syncadapter.R +import com.etesync.syncadapter.resource.LocalCalendar +import com.etesync.syncadapter.ui.BaseActivity + +class CollectionMembersFragment : Fragment() { + private val collectionModel: CollectionViewModel by activityViewModels() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val ret = inflater.inflate(R.layout.etebase_view_collection_members, container, false) + + if (savedInstanceState == null) { + collectionModel.observe(this) { + (activity as? BaseActivity?)?.supportActionBar?.setTitle(R.string.collection_members_title) + if (container != null) { + initUi(inflater, ret, it) + } + } + } + + return ret + } + + private fun initUi(inflater: LayoutInflater, v: View, cachedCollection: CachedCollection) { + v.findViewById(R.id.add_member).setOnClickListener { + + } + + val meta = cachedCollection.meta + val colorSquare = v.findViewById(R.id.color) + val color = if (!meta.color.isNullOrBlank()) parseColor(meta.color) else LocalCalendar.defaultColor + when (meta.collectionType) { + Constants.ETEBASE_TYPE_CALENDAR -> { + colorSquare.setBackgroundColor(color) + } + Constants.ETEBASE_TYPE_TASKS -> { + colorSquare.setBackgroundColor(color) + } + Constants.ETEBASE_TYPE_ADDRESS_BOOK -> { + colorSquare.visibility = View.GONE + } + } + + val title = v.findViewById(R.id.display_name) as TextView + title.text = meta.name + + val desc = v.findViewById(R.id.description) as TextView + desc.text = meta.description + + v.findViewById(R.id.progressBar).visibility = View.GONE + } +} \ No newline at end of file diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersListFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersListFragment.kt new file mode 100644 index 00000000..b986c6d7 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersListFragment.kt @@ -0,0 +1,145 @@ +package com.etesync.syncadapter.ui.etebase + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.TextView +import androidx.fragment.app.ListFragment +import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.observe +import com.etebase.client.CollectionMember +import com.etebase.client.FetchOptions +import com.etesync.syncadapter.CachedCollection +import com.etesync.syncadapter.R +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread +import java.util.* +import java.util.concurrent.Future + +class CollectionMembersListFragment : ListFragment(), AdapterView.OnItemClickListener { + private val model: AccountViewModel by activityViewModels() + private val collectionModel: CollectionViewModel by activityViewModels() + private val membersModel: LoadMembersViewModel by viewModels() + + private var emptyTextView: TextView? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.collection_members_list, container, false) + + //This is instead of setEmptyText() function because of Google bug + //See: https://code.google.com/p/android/issues/detail?id=21742 + emptyTextView = view.findViewById(android.R.id.empty) + return view + } + + private fun setListAdapterMembers(members: List) { + val context = context + if (context != null) { + val listAdapter = MembersListAdapter(context) + setListAdapter(listAdapter) + + listAdapter.addAll(members) + + emptyTextView!!.setText(R.string.collection_members_list_empty) + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + model.observe(this) { + collectionModel.observe(this) { cachedCollection -> + membersModel.loadMembers(it, cachedCollection) + } + } + + membersModel.observe(this) { + setListAdapterMembers(it) + } + + listView.onItemClickListener = this + } + + override fun onDestroyView() { + super.onDestroyView() + + membersModel.cancelLoad() + } + + override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) { + val member = listAdapter?.getItem(position) as CollectionMember + + /* + AlertDialog.Builder(requireActivity()) + .setIcon(R.drawable.ic_info_dark) + .setTitle(R.string.collection_members_remove_title) + .setMessage(getString(R.string.collection_members_remove, member.user)) + .setPositiveButton(android.R.string.yes) { dialog, which -> + val frag = RemoveMemberFragment.newInstance(account, info, member.user!!) + frag.show(requireFragmentManager(), null) + } + .setNegativeButton(android.R.string.no) { dialog, which -> }.show() + */ + } + + internal inner class MembersListAdapter(context: Context) : ArrayAdapter(context, R.layout.collection_members_list_item) { + + override fun getView(position: Int, _v: View?, parent: ViewGroup): View { + var v = _v + if (v == null) + v = LayoutInflater.from(context).inflate(R.layout.collection_members_list_item, parent, false) + + val member = getItem(position) + + val tv = v!!.findViewById(R.id.title) as TextView + tv.text = member!!.username + + // FIXME: Also mark admins + val readOnly = v.findViewById(R.id.read_only) + readOnly.visibility = if (member.accessLevel == "ro") View.VISIBLE else View.GONE + + return v + } + } +} + +class LoadMembersViewModel : ViewModel() { + private val members = MutableLiveData>() + private var asyncTask: Future? = null + + fun loadMembers(accountCollectionHolder: AccountHolder, cachedCollection: CachedCollection) { + asyncTask = doAsync { + val ret = LinkedList() + val col = cachedCollection.col + val memberManager = accountCollectionHolder.colMgr.getMemberManager(col) + var iterator: String? = null + var done = false + while (!done) { + val chunk = memberManager.list(FetchOptions().iterator(iterator).limit(30)) + iterator = chunk.stoken + done = chunk.isDone + + ret.addAll(chunk.data) + } + + uiThread { + members.value = ret + } + } + } + + fun cancelLoad() { + asyncTask?.cancel(true) + } + + fun observe(owner: LifecycleOwner, observer: (List) -> Unit) = + members.observe(owner, observer) +} \ No newline at end of file diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt index eb27eb59..48ffcca6 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt @@ -129,8 +129,19 @@ class ViewCollectionFragment : Fragment() { } } R.id.on_manage_members -> { - Toast.makeText(context, "Manage", Toast.LENGTH_LONG).show() - } + if (cachedCollection.col.accessLevel == "adm") { + parentFragmentManager.commit { + replace(R.id.fragment_container, CollectionMembersFragment()) + 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() + } } R.id.on_import -> { Toast.makeText(context, "Import", Toast.LENGTH_LONG).show() } diff --git a/app/src/main/res/layout/etebase_view_collection_members.xml b/app/src/main/res/layout/etebase_view_collection_members.xml new file mode 100644 index 00000000..7b3758f2 --- /dev/null +++ b/app/src/main/res/layout/etebase_view_collection_members.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + +