EditCollection: add a fragment to edit collection.

pull/131/head
Tom Hacohen 4 years ago
parent 63a8bf91a9
commit be22beb7f9

@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.fragment.app.commit
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -34,9 +35,9 @@ class CollectionActivity() : BaseActivity() {
model.observe(this) {
itemsModel.loadItems(it)
}
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, ViewCollectionFragment())
.commit()
supportFragmentManager.commit {
replace(R.id.fragment_container, ViewCollectionFragment())
}
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
@ -69,6 +70,7 @@ class AccountCollectionViewModel : ViewModel() {
}
uiThread {
collection.value = AccountCollectionHolder(
account,
etebaseLocalCache,
etebase,
colMgr,
@ -80,9 +82,12 @@ class AccountCollectionViewModel : ViewModel() {
fun observe(owner: LifecycleOwner, observer: (AccountCollectionHolder) -> Unit) =
collection.observe(owner, observer)
val value: AccountCollectionHolder?
get() = collection.value
}
data class AccountCollectionHolder(val etebaseLocalCache: EtebaseLocalCache, val etebase: com.etebase.client.Account, val colMgr: CollectionManager, val cachedCollection: CachedCollection)
data class AccountCollectionHolder(val account: Account, val etebaseLocalCache: EtebaseLocalCache, val etebase: com.etebase.client.Account, val colMgr: CollectionManager, val cachedCollection: CachedCollection)
class ItemsViewModel : ViewModel() {
private val cachedItems = MutableLiveData<List<CachedItem>>()
@ -100,4 +105,19 @@ class ItemsViewModel : ViewModel() {
fun observe(owner: LifecycleOwner, observer: (List<CachedItem>) -> Unit) =
cachedItems.observe(owner, observer)
val value: List<CachedItem>?
get() = cachedItems.value
}
class LoadingViewModel : ViewModel() {
private val loading = MutableLiveData<Boolean>()
fun setLoading(value: Boolean) {
loading.value = value
}
fun observe(owner: LifecycleOwner, observer: (Boolean) -> Unit) =
loading.observe(owner, observer)
}

@ -0,0 +1,235 @@
package com.etesync.syncadapter.ui.etebase
import android.graphics.Color.parseColor
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.TextUtils
import android.view.*
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.etebase.client.Collection
import com.etebase.client.exceptions.EtebaseException
import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.R
import com.etesync.syncadapter.resource.LocalCalendar
import com.etesync.syncadapter.ui.BaseActivity
import org.apache.commons.lang3.StringUtils
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import yuku.ambilwarna.AmbilWarnaDialog
import java.lang.String
class EditCollectionFragment() : Fragment() {
private val model: AccountCollectionViewModel by activityViewModels()
private val loadingModel: LoadingViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val ret = inflater.inflate(R.layout.activity_create_collection, container, false)
setHasOptionsMenu(true)
if (savedInstanceState == null) {
model.observe(this) {
updateTitle(it)
if (container != null) {
initUi(inflater, ret, it)
}
}
}
return ret
}
fun updateTitle(accountCollectionHolder: AccountCollectionHolder) {
accountCollectionHolder.let {
val new = false
var titleId: Int = R.string.create_calendar
if (new) {
when (it.cachedCollection.meta.collectionType) {
Constants.ETEBASE_TYPE_CALENDAR -> {
titleId = R.string.create_calendar
}
Constants.ETEBASE_TYPE_TASKS -> {
titleId = R.string.create_tasklist
}
Constants.ETEBASE_TYPE_ADDRESS_BOOK -> {
titleId = R.string.create_addressbook
}
}
} else {
titleId = R.string.edit_collection
}
(activity as? BaseActivity?)?.supportActionBar?.setTitle(titleId)
}
}
private fun initUi(inflater: LayoutInflater, v: View, collectionHolder: AccountCollectionHolder) {
val title = v.findViewById<EditText>(R.id.display_name)
val desc = v.findViewById<EditText>(R.id.description)
val meta = collectionHolder.cachedCollection.meta
title.setText(meta.name)
desc.setText(meta.description)
val colorSquare = v.findViewById<View>(R.id.color)
when (collectionHolder.cachedCollection.meta.collectionType) {
Constants.ETEBASE_TYPE_CALENDAR -> {
title.setHint(R.string.create_calendar_display_name_hint)
val color = if (!meta.color.isNullOrBlank()) parseColor(meta.color) else LocalCalendar.defaultColor
colorSquare.setBackgroundColor(color)
colorSquare.setOnClickListener {
AmbilWarnaDialog(context, (colorSquare.background as ColorDrawable).color, true, object : AmbilWarnaDialog.OnAmbilWarnaListener {
override fun onCancel(dialog: AmbilWarnaDialog) {}
override fun onOk(dialog: AmbilWarnaDialog, color: Int) {
colorSquare.setBackgroundColor(color)
}
}).show()
}
}
Constants.ETEBASE_TYPE_TASKS -> {
title.setHint(R.string.create_tasklist_display_name_hint)
val color = if (!meta.color.isNullOrBlank()) parseColor(meta.color) else LocalCalendar.defaultColor
colorSquare.setBackgroundColor(color)
colorSquare.setOnClickListener {
AmbilWarnaDialog(context, (colorSquare.background as ColorDrawable).color, true, object : AmbilWarnaDialog.OnAmbilWarnaListener {
override fun onCancel(dialog: AmbilWarnaDialog) {}
override fun onOk(dialog: AmbilWarnaDialog, color: Int) {
colorSquare.setBackgroundColor(color)
}
}).show()
}
}
Constants.ETEBASE_TYPE_ADDRESS_BOOK -> {
title.setHint(R.string.create_addressbook_display_name_hint)
val colorGroup = v.findViewById<View>(R.id.color_group)
colorGroup.visibility = View.GONE
}
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.fragment_edit_collection, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.on_delete -> {
deleteColection()
}
R.id.on_save -> {
saveCollection()
}
}
return super.onOptionsItemSelected(item)
}
private fun deleteColection() {
val meta = model.value!!.cachedCollection.meta
val name = meta.name
AlertDialog.Builder(requireContext())
.setTitle(R.string.delete_collection_confirm_title)
.setMessage(getString(R.string.delete_collection_confirm_warning, name))
.setPositiveButton(android.R.string.yes) { dialog, _ ->
doDeleteCollection()
dialog.dismiss()
}
.setNegativeButton(android.R.string.no) { _, _ -> }
.show()
}
private fun doDeleteCollection() {
loadingModel.setLoading(true)
doAsync {
try {
val col = model.value!!.cachedCollection.col
col.delete()
uploadCollection(col)
activity?.finish()
} catch (e: EtebaseException) {
uiThread {
AlertDialog.Builder(requireContext())
.setIcon(R.drawable.ic_info_dark)
.setTitle(R.string.exception)
.setMessage(e.localizedMessage)
.setPositiveButton(android.R.string.yes) { _, _ -> }.show()
}
} finally {
uiThread {
loadingModel.setLoading(false)
}
}
}
}
private fun saveCollection() {
var ok = true
val meta = model.value!!.cachedCollection.meta
val v = requireView()
var edit = v.findViewById<EditText>(R.id.display_name)
meta.name = edit.text.toString()
if (TextUtils.isEmpty(meta.name)) {
edit.error = getString(R.string.create_collection_display_name_required)
ok = false
}
edit = v.findViewById<EditText>(R.id.description)
meta.description = StringUtils.trimToNull(edit.text.toString())
if (ok) {
when (meta.collectionType) {
Constants.ETEBASE_TYPE_CALENDAR, Constants.ETEBASE_TYPE_TASKS -> {
val view = v.findViewById<View>(R.id.color)
val color = (view.background as ColorDrawable).color
meta.color = String.format("#%06X", 0xFFFFFF and color)
}
Constants.ETEBASE_TYPE_ADDRESS_BOOK -> {
}
}
loadingModel.setLoading(true)
doAsync {
try {
val col = model.value!!.cachedCollection.col
col.meta = meta
uploadCollection(col)
parentFragmentManager.popBackStack()
} catch (e: EtebaseException) {
uiThread {
AlertDialog.Builder(requireContext())
.setIcon(R.drawable.ic_info_dark)
.setTitle(R.string.exception)
.setMessage(e.localizedMessage)
.setPositiveButton(android.R.string.yes) { _, _ -> }.show()
}
} finally {
uiThread {
loadingModel.setLoading(false)
}
}
}
}
}
private fun uploadCollection(col: Collection) {
val accountHolder = model.value!!
val etebaseLocalCache = accountHolder.etebaseLocalCache
val colMgr = accountHolder.colMgr
colMgr.upload(col)
synchronized(etebaseLocalCache) {
etebaseLocalCache.collectionSet(colMgr, col)
}
model.loadCollection(requireContext(), accountHolder.account, col.uid)
}
}

@ -10,6 +10,7 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.commit
import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.R
import com.etesync.syncadapter.resource.LocalCalendar
@ -26,15 +27,14 @@ class ViewCollectionFragment : Fragment() {
private val itemsModel: ItemsViewModel by activityViewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val ret = super.onCreateView(inflater, container, savedInstanceState)
inflater.inflate(R.layout.view_collection_fragment, container)
val ret = inflater.inflate(R.layout.view_collection_fragment, container, false)
setHasOptionsMenu(true)
if (savedInstanceState == null) {
model.observe(this) {
(activity as? BaseActivity?)?.supportActionBar?.title = it.cachedCollection.meta.name
if (container != null) {
initUi(inflater, container, it)
initUi(inflater, ret, it)
}
}
}
@ -42,15 +42,7 @@ class ViewCollectionFragment : Fragment() {
return ret
}
override fun onAttach(context: Context) {
super.onAttach(context)
model.observe(this) {
(activity as? BaseActivity?)?.supportActionBar?.title = it.cachedCollection.meta.name
}
}
private fun initUi(inflater: LayoutInflater, container: ViewGroup, collectionHolder: AccountCollectionHolder) {
private fun initUi(inflater: LayoutInflater, container: View, collectionHolder: AccountCollectionHolder) {
val title = container.findViewById<TextView>(R.id.display_name)
if (!HintManager.getHintSeen(requireContext(), HINT_IMPORT)) {
val tourGuide = ShowcaseBuilder.getBuilder(requireActivity())
@ -119,7 +111,10 @@ class ViewCollectionFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.on_edit -> {
Toast.makeText(context, "Edit", Toast.LENGTH_LONG).show()
parentFragmentManager.commit {
replace(R.id.fragment_container, EditCollectionFragment())
addToBackStack(EditCollectionFragment::class.java.name)
}
}
R.id.on_manage_members -> {
Toast.makeText(context, "Manage", Toast.LENGTH_LONG).show()

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ 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
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/on_delete"
android:icon="@drawable/ic_delete_dark"
android:title="@string/delete_collection"
app:showAsAction="always" />
<item
android:id="@+id/on_save"
android:icon="@drawable/ic_save_dark"
android:title="@string/create_collection_create"
app:showAsAction="always" />
</menu>
Loading…
Cancel
Save