diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 06ca5f352..ed717a06c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -145,6 +145,7 @@ android {
}
}
+/*
testOptions {
managedDevices {
localDevices {
@@ -156,6 +157,7 @@ android {
}
}
}
+*/
namespace = "org.tasks"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 56184212e..74b147687 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -618,7 +618,9 @@
android:taskAffinity=""
android:theme="@style/TranslucentDialog"/>
-
+
+
+
)
+ .fetch(data!!.getSerializableExtra(TagPickerActivityCompose.EXTRA_TASKS) as ArrayList)
.filterNot { it.readOnly },
- data.getParcelableArrayListExtra(TagPickerActivity.EXTRA_PARTIALLY_SELECTED)!!,
- data.getParcelableArrayListExtra(TagPickerActivity.EXTRA_SELECTED)!!
+ data.getParcelableArrayListExtra(TagPickerActivityCompose.EXTRA_PARTIALLY_SELECTED)!!,
+ data.getParcelableArrayListExtra(TagPickerActivityCompose.EXTRA_SELECTED)!!
)
taskDao.touch(modified)
}
@@ -676,7 +673,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
- onBackPressed.isEnabled = true
+ onBackPressed.isEnabled = true
search.setOnQueryTextListener(this)
listViewModel.setSearchQuery("")
if (preferences.isTopAppBar) {
@@ -686,7 +683,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
- onBackPressed.isEnabled = false
+ onBackPressed.isEnabled = false
search.setOnQueryTextListener(null)
listViewModel.setFilter(filter)
listViewModel.setSearchQuery(null)
@@ -727,13 +724,13 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
R.id.edit_tags -> {
lifecycleScope.launch {
val tags = tagDataDao.getTagSelections(selected)
- val intent = Intent(context, TagPickerActivity::class.java)
- intent.putExtra(TagPickerActivity.EXTRA_TASKS, selected)
+ val intent = Intent(context, TagPickerActivityCompose::class.java)
+ intent.putExtra(TagPickerActivityCompose.EXTRA_TASKS, selected)
intent.putParcelableArrayListExtra(
- TagPickerActivity.EXTRA_PARTIALLY_SELECTED,
+ TagPickerActivityCompose.EXTRA_PARTIALLY_SELECTED,
ArrayList(tagDataDao.getByUuid(tags.first!!)))
intent.putParcelableArrayListExtra(
- TagPickerActivity.EXTRA_SELECTED, ArrayList(tagDataDao.getByUuid(tags.second!!)))
+ TagPickerActivityCompose.EXTRA_SELECTED, ArrayList(tagDataDao.getByUuid(tags.second!!)))
startActivityForResult(intent, REQUEST_TAG_TASKS)
}
true
diff --git a/app/src/main/java/com/todoroo/astrid/tags/TagsControlSet.kt b/app/src/main/java/com/todoroo/astrid/tags/TagsControlSet.kt
index e0c91e4d6..65ebf79bc 100644
--- a/app/src/main/java/com/todoroo/astrid/tags/TagsControlSet.kt
+++ b/app/src/main/java/com/todoroo/astrid/tags/TagsControlSet.kt
@@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.update
import org.tasks.R
import org.tasks.compose.collectAsStateLifecycleAware
import org.tasks.compose.edit.TagsRow
-import org.tasks.tags.TagPickerActivity
+import org.tasks.tags.TagPickerActivityCompose
import org.tasks.ui.ChipProvider
import org.tasks.ui.TaskEditControlFragment
import javax.inject.Inject
@@ -21,8 +21,8 @@ class TagsControlSet : TaskEditControlFragment() {
@Inject lateinit var chipProvider: ChipProvider
private fun onRowClick() {
- val intent = Intent(context, TagPickerActivity::class.java)
- intent.putParcelableArrayListExtra(TagPickerActivity.EXTRA_SELECTED, viewModel.selectedTags.value)
+ val intent = Intent(context, TagPickerActivityCompose::class.java)
+ intent.putParcelableArrayListExtra(TagPickerActivityCompose.EXTRA_SELECTED, viewModel.selectedTags.value)
startActivityForResult(intent, REQUEST_TAG_PICKER_ACTIVITY)
}
@@ -48,7 +48,7 @@ class TagsControlSet : TaskEditControlFragment() {
if (requestCode == REQUEST_TAG_PICKER_ACTIVITY) {
if (resultCode == Activity.RESULT_OK && data != null) {
viewModel.selectedTags.value =
- data.getParcelableArrayListExtra(TagPickerActivity.EXTRA_SELECTED)
+ data.getParcelableArrayListExtra(TagPickerActivityCompose.EXTRA_SELECTED)
?: ArrayList()
}
} else {
diff --git a/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt b/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt
index 776c25edb..8fe7a1784 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/TaskDefaults.kt
@@ -31,8 +31,8 @@ import org.tasks.preferences.Preferences
import org.tasks.repeats.BasicRecurrenceDialog
import org.tasks.repeats.BasicRecurrenceDialog.Companion.EXTRA_RRULE
import org.tasks.repeats.RepeatRuleToString
-import org.tasks.tags.TagPickerActivity
-import org.tasks.tags.TagPickerActivity.Companion.EXTRA_SELECTED
+import org.tasks.tags.TagPickerActivityCompose
+import org.tasks.tags.TagPickerActivityCompose.Companion.EXTRA_SELECTED
import javax.inject.Inject
private const val FRAG_TAG_DEFAULT_LIST_SELECTION = "frag_tag_default_list_selection"
@@ -108,7 +108,7 @@ class TaskDefaults : InjectingPreferenceFragment() {
findPreference(R.string.p_default_tags)
.setOnPreferenceClickListener {
lifecycleScope.launch {
- val intent = Intent(context, TagPickerActivity::class.java)
+ val intent = Intent(context, TagPickerActivityCompose::class.java)
.putParcelableArrayListExtra(
EXTRA_SELECTED,
ArrayList(defaultTags())
diff --git a/app/src/main/java/org/tasks/tags/TagPickerActivity.kt b/app/src/main/java/org/tasks/tags/TagPickerActivity.kt
deleted file mode 100644
index 38890da9e..000000000
--- a/app/src/main/java/org/tasks/tags/TagPickerActivity.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.tasks.tags
-
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import android.widget.EditText
-import androidx.activity.viewModels
-import androidx.core.widget.addTextChangedListener
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.DefaultItemAnimator
-import androidx.recyclerview.widget.LinearLayoutManager
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.launch
-import org.tasks.R
-import org.tasks.Strings.isNullOrEmpty
-import org.tasks.billing.Inventory
-import org.tasks.data.TagData
-import org.tasks.databinding.ActivityTagPickerBinding
-import org.tasks.extensions.addBackPressedCallback
-import org.tasks.injection.ThemedInjectingAppCompatActivity
-import org.tasks.themes.ColorProvider
-import org.tasks.themes.Theme
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class TagPickerActivity : ThemedInjectingAppCompatActivity() {
- @Inject lateinit var theme: Theme
- @Inject lateinit var inventory: Inventory
- @Inject lateinit var colorProvider: ColorProvider
-
- private val viewModel: TagPickerViewModel by viewModels()
- private var taskIds: ArrayList? = null
- private lateinit var editText: EditText
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val intent = intent
- taskIds = intent.getSerializableExtra(EXTRA_TASKS) as ArrayList?
- if (savedInstanceState == null) {
- intent.getParcelableArrayListExtra(EXTRA_SELECTED)?.let {
- viewModel.setSelected(
- it,
- intent.getParcelableArrayListExtra(EXTRA_PARTIALLY_SELECTED)
- )
- }
- }
- val binding = ActivityTagPickerBinding.inflate(layoutInflater)
- editText = binding.searchInput.apply {
- addTextChangedListener(
- onTextChanged = { text, _, _, _ -> onSearch(text) }
- )
- }
- setContentView(binding.root)
- val toolbar = binding.toolbar
- toolbar.setNavigationIcon(R.drawable.ic_outline_arrow_back_24px)
- toolbar.setNavigationOnClickListener { onBackPressed() }
- val themeColor = theme.themeColor
- themeColor.applyToNavigationBar(this)
- val recyclerAdapter = TagRecyclerAdapter(this, viewModel, inventory, colorProvider) { tagData, vh ->
- onToggle(tagData, vh)
- }
- val recyclerView = binding.recyclerView
- recyclerView.adapter = recyclerAdapter
- (recyclerView.itemAnimator as DefaultItemAnimator?)!!.supportsChangeAnimations = false
- recyclerView.layoutManager = LinearLayoutManager(this)
- viewModel.observe(this) { recyclerAdapter.submitList(it) }
- editText.setText(viewModel.text)
-
- addBackPressedCallback {
- if (isNullOrEmpty(viewModel.text)) {
- val data = Intent()
- data.putExtra(EXTRA_TASKS, taskIds)
- data.putParcelableArrayListExtra(
- EXTRA_PARTIALLY_SELECTED,
- viewModel.getPartiallySelected()
- )
- data.putParcelableArrayListExtra(EXTRA_SELECTED, viewModel.getSelected())
- setResult(Activity.RESULT_OK, data)
- finish()
- } else {
- clear()
- }
- }
- }
-
- private fun onToggle(tagData: TagData, vh: TagPickerViewHolder) = lifecycleScope.launch {
- val newTag = tagData.id == null
- val newState = viewModel.toggle(tagData, vh.isChecked || newTag)
- vh.updateCheckbox(newState)
- if (newTag) {
- clear()
- }
- }
-
- private fun onSearch(text: CharSequence?) {
- viewModel.search(text?.toString() ?: "")
- }
-
- private fun clear() {
- editText.setText("")
- }
-
- companion object {
- const val EXTRA_SELECTED = "extra_tags"
- const val EXTRA_PARTIALLY_SELECTED = "extra_partial"
- const val EXTRA_TASKS = "extra_tasks"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/tags/TagPickerActivityCompose.kt b/app/src/main/java/org/tasks/tags/TagPickerActivityCompose.kt
new file mode 100644
index 000000000..708d76f79
--- /dev/null
+++ b/app/src/main/java/org/tasks/tags/TagPickerActivityCompose.kt
@@ -0,0 +1,292 @@
+package org.tasks.tags
+
+/*
+ * TagPickerActivityCompose is a replacement for TagPickerActivity reimplemented
+ * using JetPack Compose framework.
+ *
+ * The modification eliminates TagRecycleAdapter.
+ * TriStateCheckbox from Compose is used instead of CheckBoxTriState.
+ * Source code for TagRecycleAdapter and TagPickerActivity were deleted because they became incompatible
+ * with modified TagPickerViewModel, but were not excluded from build due to the hilt logic.
+ *
+ * There is a tag "FeatureReady" in the git commits log which marks the state when the main logic was
+ * already implemented via Compose but but viewModel was modified with backward compatibility so to
+ * switch back to View implementation its enough to find lines like this
+ * //val intent = Intent(context, TagPickerActivity::class.java)
+ * val intent = Intent(context, TagPickerActivityCompose::class.java)
+ * in TaskListFragment.kt and TagsControlSet.kt and move comment mark to another line.
+ */
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.activity.viewModels
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.Icon
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.TextField
+import androidx.compose.material.TextFieldDefaults
+import androidx.compose.material.TriStateCheckbox
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.state.ToggleableState
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewModelScope
+import com.google.android.material.composethemeadapter.MdcTheme
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.launch
+import org.tasks.R
+import org.tasks.Strings
+import org.tasks.billing.Inventory
+import org.tasks.data.TagData
+import org.tasks.extensions.addBackPressedCallback
+import org.tasks.injection.ThemedInjectingAppCompatActivity
+import org.tasks.themes.ColorProvider
+import org.tasks.themes.CustomIcons
+import org.tasks.themes.Theme
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class TagPickerActivityCompose : ThemedInjectingAppCompatActivity() {
+ @Inject lateinit var theme: Theme
+ @Inject lateinit var inventory: Inventory
+ @Inject lateinit var colorProvider: ColorProvider
+
+
+ private val viewModel: TagPickerViewModel by viewModels()
+ private var taskIds: ArrayList? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val intent = intent
+ taskIds = intent.getSerializableExtra(EXTRA_TASKS) as ArrayList?
+ if (savedInstanceState == null) {
+ val selected = intent.getParcelableArrayListExtra(EXTRA_SELECTED)
+ if ( selected != null ) {
+ viewModel.setSelected(
+ selected, intent.getParcelableArrayListExtra(EXTRA_PARTIALLY_SELECTED)
+ )
+ }
+ }
+
+ addBackPressedCallback { handleBackPressed() }
+
+ viewModel.search("")
+
+ setContent {
+ MdcTheme {
+ TagPicker(
+ viewModel,
+ onBackClicked = { handleBackPressed() },
+ getTagIcon = { tagData -> getIcon(tagData) },
+ getTagColor = { tagData -> getColor(tagData) }
+ )
+ } /* setContent */
+ }
+ } /* onCreate */
+
+ private fun handleBackPressed() {
+ if (Strings.isNullOrEmpty(viewModel.searchText.value)) {
+ val data = Intent()
+ data.putExtra(EXTRA_TASKS, taskIds)
+ data.putParcelableArrayListExtra(EXTRA_PARTIALLY_SELECTED, viewModel.getPartiallySelected())
+ data.putParcelableArrayListExtra(EXTRA_SELECTED, viewModel.getSelected())
+ setResult(Activity.RESULT_OK, data)
+ finish()
+ } else {
+ viewModel.search("")
+ }
+ } /* handleBackPressed */
+
+ private fun getColor(tagData: TagData): Color {
+ if (tagData.getColor() != 0) {
+ val themeColor = colorProvider.getThemeColor(tagData.getColor()!!, true)
+ if (inventory.purchasedThemes() || themeColor.isFree) {
+ return Color(themeColor.primaryColor)
+ }
+ }
+ return Color(getColor(R.color.icon_tint_with_alpha))
+ }
+
+ private fun getIcon(tagData: TagData): Int
+ {
+ val iconIndex = tagData.getIcon()
+ var iconResource = R.drawable.ic_outline_label_24px
+ if ( (iconIndex != null) && (iconIndex < 1000 || inventory.hasPro) ) {
+ iconResource = CustomIcons.getIconResId(iconIndex) ?: R.drawable.ic_outline_label_24px
+ }
+ return iconResource
+ }
+
+ /* Copy of the TagPickerActivity's companion object */
+ companion object {
+ const val EXTRA_SELECTED = "extra_tags"
+ const val EXTRA_PARTIALLY_SELECTED = "extra_partial"
+ const val EXTRA_TASKS = "extra_tasks"
+ }
+}
+
+@Composable
+internal fun TagPicker(
+ viewModel: TagPickerViewModel,
+ onBackClicked: () -> Unit,
+ getTagIcon: (TagData) -> Int,
+ getTagColor: (TagData) -> Color
+) {
+ Box ( modifier = Modifier.fillMaxSize() )
+ {
+ Column (modifier = Modifier.padding(horizontal = 12.dp)) {
+ Box( modifier = Modifier.fillMaxWidth() ) {
+ SearchBar(viewModel, onBackClicked)
+ }
+ Box (
+ modifier = Modifier.weight(1f)
+ ) {
+ PickerBox(viewModel, viewModel.tagsList.observeAsState(initial = emptyList()), getTagIcon, getTagColor)
+ }
+ }
+ }
+}
+
+@Composable
+internal fun SearchBar(
+ viewModel: TagPickerViewModel,
+ onBack: () -> Unit
+) {
+ val searchPattern = remember { viewModel.searchText }
+ val invitation = LocalContext.current.getString(R.string.enter_tag_name)
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Icon(
+ ImageVector.vectorResource(id = R.drawable.ic_outline_arrow_back_24px),
+ "Done",
+ modifier = Modifier
+ .padding(6.dp)
+ .clickable { onBack() }
+ )
+
+ TextField(
+ value = searchPattern.value,
+ onValueChange = { viewModel.search(it) },
+ placeholder = { Text(invitation) },
+ colors = TextFieldDefaults.textFieldColors(
+ textColor = MaterialTheme.colors.onBackground,
+ backgroundColor = Color.Transparent,
+ focusedIndicatorColor = Color.Transparent,
+ unfocusedIndicatorColor = Color.Transparent
+ ),
+ modifier = Modifier.padding(start = 6.dp)
+ )
+ }
+} /* SearchBar */
+
+@Composable
+internal fun PickerBox (
+ viewModel: TagPickerViewModel,
+ tags: State>,
+ getTagIcon: (TagData) -> Int = { R.drawable.ic_outline_label_24px },
+ getTagColor: (TagData) -> Color = { Color.Gray }
+) {
+ val onClick: (TagData) -> Unit = {
+ viewModel.viewModelScope.launch {
+ viewModel.toggle(it, viewModel.getState(it) != ToggleableState.On) }
+ }
+
+ val newItem: (String) -> Unit = {
+ viewModel.viewModelScope.launch { viewModel.createNew(it); viewModel.search("") }
+ }
+
+ LazyColumn {
+ if (viewModel.tagToCreate.value != "") {
+ item(key = -1) {
+ val text = LocalContext.current.getString(R.string.new_tag) + " \"${viewModel.tagToCreate.value}\""
+ TagRow(
+ icon = ImageVector.vectorResource(R.drawable.ic_outline_add_24px),
+ iconColor = Color(LocalContext.current.getColor(R.color.icon_tint_with_alpha)),
+ text = text,
+ onClick = { newItem(viewModel.searchText.value) }
+ )
+ }
+ }
+
+ items( tags.value, key = { tag -> tag.id!! } )
+ {
+ val checked = remember { mutableStateOf ( viewModel.getState(it) ) }
+ val clickChecked: () -> Unit = { onClick(it); checked.value = viewModel.getState(it) }
+ TagRow(
+ icon = ImageVector.vectorResource(getTagIcon(it)),
+ iconColor = getTagColor(it),
+ text = it.name!!,
+ onClick = clickChecked
+ ) {
+ TriStateCheckbox(
+ modifier = Modifier.padding(6.dp),
+ state = checked.value,
+ onClick = clickChecked
+ )
+ }
+ }
+ }
+} /* PickerBox */
+
+@Composable
+internal fun TagRow (
+ icon: ImageVector,
+ iconColor: Color,
+ text: String,
+ onClick: () -> Unit,
+ checkBox: @Composable RowScope.() -> Unit = {}
+) {
+ Row(modifier = Modifier.fillMaxWidth().clickable{ onClick() },
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Icon(
+ imageVector = icon,
+ contentDescription = "",
+ modifier = Modifier.padding(6.dp),
+ tint = iconColor
+ )
+ Text(
+ text,
+ modifier = Modifier.weight(1f).padding(horizontal = 24.dp)
+ )
+ checkBox()
+ }
+} /* TagRow */
+
+/*
+internal fun genTestTags(): List
+{
+ var idcc: Long = 1
+ return "alpha beta gamma delta kappa theta alfa1 beta1 gamma1 delta1 kappa1 theta1"
+ .split(" ")
+ .map { name -> TagData(name).also{ it.id = idcc++ } }
+}
+
+@Composable
+@Preview(showBackground = true, backgroundColor = 0xffffff)
+internal fun PickerBoxPreview() {
+ val list = remember { mutableStateOf( genTestTags() ) }
+ PickerBox(list, getTagColor = { Color.Green })
+}
+*/
diff --git a/app/src/main/java/org/tasks/tags/TagPickerViewModel.kt b/app/src/main/java/org/tasks/tags/TagPickerViewModel.kt
index 0f597f915..47f2101d9 100644
--- a/app/src/main/java/org/tasks/tags/TagPickerViewModel.kt
+++ b/app/src/main/java/org/tasks/tags/TagPickerViewModel.kt
@@ -1,12 +1,16 @@
package org.tasks.tags
-import androidx.lifecycle.*
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.state.ToggleableState
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
-import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.TagData
import org.tasks.data.TagDataDao
-import org.tasks.tags.CheckBoxTriStates.State
import javax.inject.Inject
@HiltViewModel
@@ -17,12 +21,22 @@ class TagPickerViewModel @Inject constructor(
private val tags = MutableLiveData>()
private val selected: MutableSet = HashSet()
private val partiallySelected: MutableSet = HashSet()
- var text: String? = null
- private set
+
+ val searchText: State
+ get() = _searchText
+ private val _searchText = mutableStateOf("")
+
+ val tagToCreate: State
+ get() = _tagToCreate
+ private val _tagToCreate = mutableStateOf("")
fun observe(owner: LifecycleOwner, observer: (List) -> Unit) =
tags.observe(owner, observer)
+ /* The property to access selected tags list from the @Composable activity */
+ val tagsList: MutableLiveData>
+ get() = tags
+
fun setSelected(selected: List, partiallySelected: List?) {
this.selected.addAll(selected)
if (partiallySelected != null) {
@@ -35,16 +49,16 @@ class TagPickerViewModel @Inject constructor(
fun getPartiallySelected() = ArrayList(partiallySelected)
fun search(newText: String) {
- if (!newText.equals(text, ignoreCase = true)) {
+ if (newText == "" || !newText.equals(_searchText.value, ignoreCase = true)) {
viewModelScope.launch {
val results = tagDataDao.searchTags(newText)
- onUpdate(results.toMutableList())
+ onUpdate(newText, results.toMutableList())
}
}
- text = newText
+ _searchText.value = newText
}
- private fun onUpdate(results: MutableList) {
+ private fun onUpdate(newText: String, results: MutableList) {
val sorted = results
.sortedWith { l, r ->
val lSelected = selected.contains(l) || partiallySelected.contains(r)
@@ -58,20 +72,21 @@ class TagPickerViewModel @Inject constructor(
}
}
.toMutableList()
- if (!isNullOrEmpty(text) && !results.any { text.equals(it.name, ignoreCase = true) }) {
- sorted.add(0, TagData(text))
- }
+ if ( newText != "" && !results.any {newText.equals(it.name, ignoreCase = true) } )
+ _tagToCreate.value = newText
+ else
+ _tagToCreate.value = ""
tags.value = sorted
}
- fun getState(tagData: TagData): State {
+ fun getState(tagData: TagData): ToggleableState {
if (partiallySelected.contains(tagData)) {
- return State.PARTIALLY_CHECKED
+ return ToggleableState.Indeterminate
}
- return if (selected.contains(tagData)) State.CHECKED else State.UNCHECKED
+ return if (selected.contains(tagData)) ToggleableState.On else ToggleableState.Off
}
- suspend fun toggle(tagData: TagData, checked: Boolean): State {
+ suspend fun toggle(tagData: TagData, checked: Boolean): ToggleableState {
var tagData = tagData
if (tagData.id == null) {
tagData = TagData(tagData.name)
@@ -80,10 +95,17 @@ class TagPickerViewModel @Inject constructor(
partiallySelected.remove(tagData)
return if (checked) {
selected.add(tagData)
- State.CHECKED
+ ToggleableState.On
} else {
selected.remove(tagData)
- State.UNCHECKED
+ ToggleableState.Off
}
}
+
+ suspend fun createNew(name: String) {
+ val tagData = TagData(name)
+ tagDataDao.createNew(tagData)
+ selected.add(tagData)
+ search("")
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/tags/TagRecyclerAdapter.kt b/app/src/main/java/org/tasks/tags/TagRecyclerAdapter.kt
deleted file mode 100644
index 4ea39ac33..000000000
--- a/app/src/main/java/org/tasks/tags/TagRecyclerAdapter.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.tasks.tags
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.recyclerview.widget.AsyncListDiffer
-import androidx.recyclerview.widget.RecyclerView
-import org.tasks.R
-import org.tasks.billing.Inventory
-import org.tasks.data.TagData
-import org.tasks.databinding.RowTagPickerBinding
-import org.tasks.themes.ColorProvider
-import org.tasks.themes.CustomIcons.getIconResId
-
-internal class TagRecyclerAdapter(
- private val context: Context,
- private val viewModel: TagPickerViewModel,
- private val inventory: Inventory,
- private val colorProvider: ColorProvider,
- private val callback: (TagData, TagPickerViewHolder) -> Unit
-) : RecyclerView.Adapter() {
-
- private val differ: AsyncListDiffer = AsyncListDiffer(this, TagDiffCallback())
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
- TagPickerViewHolder(
- context,
- RowTagPickerBinding.inflate(LayoutInflater.from(context), parent, false),
- callback
- )
-
- override fun onBindViewHolder(holder: TagPickerViewHolder, position: Int) {
- val tagData = differ.currentList[position]
- holder.bind(tagData, getColor(tagData), getIcon(tagData), viewModel.getState(tagData))
- }
-
- override fun getItemCount(): Int = differ.currentList.size
-
- private fun getColor(tagData: TagData): Int {
- if (tagData.getColor() != 0) {
- val themeColor = colorProvider.getThemeColor(tagData.getColor()!!, true)
- if (inventory.purchasedThemes() || themeColor.isFree) {
- return themeColor.primaryColor
- }
- }
- return context.getColor(R.color.icon_tint_with_alpha)
- }
-
- private fun getIcon(tagData: TagData): Int? =
- tagData.getIcon()?.takeIf { it < 1000 || inventory.hasPro }?.let { getIconResId(it) }
-
- fun submitList(tagData: List?) {
- differ.submitList(tagData)
- }
-}
\ No newline at end of file