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