mirror of
https://github.com/etesync/android
synced 2025-01-10 15:51:08 +00:00
EditCollection: add a fragment to edit collection.
This commit is contained in:
parent
63a8bf91a9
commit
be22beb7f9
@ -5,6 +5,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
@ -34,9 +35,9 @@ class CollectionActivity() : BaseActivity() {
|
|||||||
model.observe(this) {
|
model.observe(this) {
|
||||||
itemsModel.loadItems(it)
|
itemsModel.loadItems(it)
|
||||||
}
|
}
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.commit {
|
||||||
.add(R.id.fragment_container, ViewCollectionFragment())
|
replace(R.id.fragment_container, ViewCollectionFragment())
|
||||||
.commit()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
@ -69,6 +70,7 @@ class AccountCollectionViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
uiThread {
|
uiThread {
|
||||||
collection.value = AccountCollectionHolder(
|
collection.value = AccountCollectionHolder(
|
||||||
|
account,
|
||||||
etebaseLocalCache,
|
etebaseLocalCache,
|
||||||
etebase,
|
etebase,
|
||||||
colMgr,
|
colMgr,
|
||||||
@ -80,9 +82,12 @@ class AccountCollectionViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun observe(owner: LifecycleOwner, observer: (AccountCollectionHolder) -> Unit) =
|
fun observe(owner: LifecycleOwner, observer: (AccountCollectionHolder) -> Unit) =
|
||||||
collection.observe(owner, observer)
|
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() {
|
class ItemsViewModel : ViewModel() {
|
||||||
private val cachedItems = MutableLiveData<List<CachedItem>>()
|
private val cachedItems = MutableLiveData<List<CachedItem>>()
|
||||||
@ -100,4 +105,19 @@ class ItemsViewModel : ViewModel() {
|
|||||||
|
|
||||||
fun observe(owner: LifecycleOwner, observer: (List<CachedItem>) -> Unit) =
|
fun observe(owner: LifecycleOwner, observer: (List<CachedItem>) -> Unit) =
|
||||||
cachedItems.observe(owner, observer)
|
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.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import com.etesync.syncadapter.Constants
|
import com.etesync.syncadapter.Constants
|
||||||
import com.etesync.syncadapter.R
|
import com.etesync.syncadapter.R
|
||||||
import com.etesync.syncadapter.resource.LocalCalendar
|
import com.etesync.syncadapter.resource.LocalCalendar
|
||||||
@ -26,15 +27,14 @@ class ViewCollectionFragment : Fragment() {
|
|||||||
private val itemsModel: ItemsViewModel by activityViewModels()
|
private val itemsModel: ItemsViewModel by activityViewModels()
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
val ret = super.onCreateView(inflater, container, savedInstanceState)
|
val ret = inflater.inflate(R.layout.view_collection_fragment, container, false)
|
||||||
|
|
||||||
inflater.inflate(R.layout.view_collection_fragment, container)
|
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
model.observe(this) {
|
model.observe(this) {
|
||||||
|
(activity as? BaseActivity?)?.supportActionBar?.title = it.cachedCollection.meta.name
|
||||||
if (container != null) {
|
if (container != null) {
|
||||||
initUi(inflater, container, it)
|
initUi(inflater, ret, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,15 +42,7 @@ class ViewCollectionFragment : Fragment() {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttach(context: Context) {
|
private fun initUi(inflater: LayoutInflater, container: View, collectionHolder: AccountCollectionHolder) {
|
||||||
super.onAttach(context)
|
|
||||||
|
|
||||||
model.observe(this) {
|
|
||||||
(activity as? BaseActivity?)?.supportActionBar?.title = it.cachedCollection.meta.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initUi(inflater: LayoutInflater, container: ViewGroup, collectionHolder: AccountCollectionHolder) {
|
|
||||||
val title = container.findViewById<TextView>(R.id.display_name)
|
val title = container.findViewById<TextView>(R.id.display_name)
|
||||||
if (!HintManager.getHintSeen(requireContext(), HINT_IMPORT)) {
|
if (!HintManager.getHintSeen(requireContext(), HINT_IMPORT)) {
|
||||||
val tourGuide = ShowcaseBuilder.getBuilder(requireActivity())
|
val tourGuide = ShowcaseBuilder.getBuilder(requireActivity())
|
||||||
@ -119,7 +111,10 @@ class ViewCollectionFragment : Fragment() {
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.on_edit -> {
|
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 -> {
|
R.id.on_manage_members -> {
|
||||||
Toast.makeText(context, "Manage", Toast.LENGTH_LONG).show()
|
Toast.makeText(context, "Manage", Toast.LENGTH_LONG).show()
|
||||||
|
25
app/src/main/res/menu/fragment_edit_collection.xml
Normal file
25
app/src/main/res/menu/fragment_edit_collection.xml
Normal file
@ -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…
Reference in New Issue
Block a user