diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bba1d89b0..13f5cecbf 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -53,7 +53,8 @@
-
+ android:label="@string/manga_shelf"
+ android:theme="@style/Theme.Kotatsu.DialogWhenLarge">
@@ -95,9 +97,13 @@
android:windowSoftInputMode="adjustResize" />
-
+ android:theme="@style/Theme.Kotatsu.DialogWhenLarge" />
+
+
MangaCategoriesViewModel(manga.get(), get())
}
+ viewModel { params -> FavouritesCategoryEditViewModel(params[0], get(), get()) }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt
index 65d429706..d0ada21da 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/data/FavouriteCategoriesDao.kt
@@ -6,6 +6,9 @@ import kotlinx.coroutines.flow.Flow
@Dao
abstract class FavouriteCategoriesDao {
+ @Query("SELECT * FROM favourite_categories WHERE category_id = :id")
+ abstract suspend fun find(id: Int): FavouriteCategoryEntity
+
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
abstract suspend fun findAll(): List
@@ -27,6 +30,9 @@ abstract class FavouriteCategoriesDao {
@Query("UPDATE favourite_categories SET title = :title WHERE category_id = :id")
abstract suspend fun updateTitle(id: Long, title: String)
+ @Query("UPDATE favourite_categories SET title = :title, `order` = :order, `track` = :tracker WHERE category_id = :id")
+ abstract suspend fun update(id: Long, title: String, order: String, tracker: Boolean)
+
@Query("UPDATE favourite_categories SET `order` = :order WHERE category_id = :id")
abstract suspend fun updateOrder(id: Long, order: String)
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt
index 35a362e95..6e995696b 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt
@@ -52,6 +52,11 @@ class FavouritesRepository(
}.distinctUntilChanged()
}
+ fun observeCategory(id: Long): Flow {
+ return db.favouriteCategoriesDao.observe(id)
+ .map { it.toFavouriteCategory() }
+ }
+
fun observeCategories(mangaId: Long): Flow> {
return db.favouritesDao.observe(mangaId).map { entity ->
entity?.categories?.map { it.toFavouriteCategory() }.orEmpty()
@@ -62,6 +67,29 @@ class FavouritesRepository(
return db.favouritesDao.observeIds(mangaId).map { it.toSet() }
}
+ suspend fun getCategory(id: Long): FavouriteCategory {
+ return db.favouriteCategoriesDao.find(id.toInt()).toFavouriteCategory()
+ }
+
+ suspend fun createCategory(title: String, sortOrder: SortOrder, isTrackerEnabled: Boolean): FavouriteCategory {
+ val entity = FavouriteCategoryEntity(
+ title = title,
+ createdAt = System.currentTimeMillis(),
+ sortKey = db.favouriteCategoriesDao.getNextSortKey(),
+ categoryId = 0,
+ order = sortOrder.name,
+ track = isTrackerEnabled,
+ )
+ val id = db.favouriteCategoriesDao.insert(entity)
+ val category = entity.toFavouriteCategory(id)
+ channels.createChannel(category)
+ return category
+ }
+
+ suspend fun updateCategory(id: Long, title: String, sortOrder: SortOrder, isTrackerEnabled: Boolean) {
+ db.favouriteCategoriesDao.update(id, title, sortOrder.name, isTrackerEnabled)
+ }
+
suspend fun addCategory(title: String): FavouriteCategory {
val entity = FavouriteCategoryEntity(
title = title,
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesContainerFragment.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesContainerFragment.kt
index 45cbba17a..61fae0369 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesContainerFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/FavouritesContainerFragment.kt
@@ -16,12 +16,12 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseFragment
import org.koitharu.kotatsu.base.ui.util.ActionModeListener
import org.koitharu.kotatsu.core.model.FavouriteCategory
-import org.koitharu.kotatsu.core.ui.titleRes
import org.koitharu.kotatsu.databinding.FragmentFavouritesBinding
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesEditDelegate
import org.koitharu.kotatsu.favourites.ui.categories.FavouritesCategoriesViewModel
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel
+import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.main.ui.AppBarOwner
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.measureHeight
@@ -134,28 +134,6 @@ class FavouritesContainerFragment :
viewModel.deleteCategory(category.id)
}
- override fun onRenameCategory(category: FavouriteCategory, newName: String) {
- viewModel.renameCategory(category.id, newName)
- }
-
- override fun onCreateCategory(name: String) {
- viewModel.createCategory(name)
- }
-
- private fun createOrderSubmenu(menu: Menu, category: FavouriteCategory) {
- val submenu = menu.findItem(R.id.action_order)?.subMenu ?: return
- for ((i, item) in CategoriesActivity.SORT_ORDERS.withIndex()) {
- val menuItem = submenu.add(R.id.group_order, Menu.NONE, i, item.titleRes)
- menuItem.isCheckable = true
- menuItem.isChecked = item == category.order
- }
- submenu.setGroupCheckable(R.id.group_order, true, true)
- menu.findItem(R.id.action_tracking)?.run {
- isVisible = viewModel.isFavouritesTrackerEnabled
- isChecked = category.isTrackingEnabled
- }
- }
-
private fun TabLayout.setTabsEnabled(enabled: Boolean) {
val tabStrip = getChildAt(0) as? ViewGroup ?: return
for (tab in tabStrip.children) {
@@ -166,19 +144,11 @@ class FavouritesContainerFragment :
private fun showCategoryMenu(tabView: View, category: FavouriteCategory) {
val menu = PopupMenu(tabView.context, tabView)
menu.inflate(R.menu.popup_category)
- createOrderSubmenu(menu.menu, category)
menu.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_remove -> editDelegate.deleteCategory(category)
- R.id.action_rename -> editDelegate.renameCategory(category)
- R.id.action_create -> editDelegate.createCategory()
- R.id.action_tracking -> viewModel.setCategoryTracking(category.id, !category.isTrackingEnabled)
- R.id.action_order -> return@setOnMenuItemClickListener false
- else -> {
- val order = CategoriesActivity.SORT_ORDERS.getOrNull(it.order)
- ?: return@setOnMenuItemClickListener false
- viewModel.setCategoryOrder(category.id, order)
- }
+ R.id.action_edit -> FavouritesCategoryEditActivity.newIntent(tabView.context, category.id)
+ else -> return@setOnMenuItemClickListener false
}
true
}
@@ -190,7 +160,7 @@ class FavouritesContainerFragment :
menu.inflate(R.menu.popup_category_all)
menu.setOnMenuItemClickListener {
when (it.itemId) {
- R.id.action_create -> editDelegate.createCategory()
+ R.id.action_create -> FavouritesCategoryEditActivity.newIntent(requireContext())
R.id.action_hide -> viewModel.setAllCategoriesVisible(false)
}
true
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt
index d2615c826..80fd2a137 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesActivity.kt
@@ -3,7 +3,6 @@ package org.koitharu.kotatsu.favourites.ui.categories
import android.content.Context
import android.content.Intent
import android.os.Bundle
-import android.view.Menu
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
@@ -19,9 +18,9 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.model.FavouriteCategory
-import org.koitharu.kotatsu.core.ui.titleRes
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel
+import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.measureHeight
@@ -57,24 +56,17 @@ class CategoriesActivity :
override fun onClick(v: View) {
when (v.id) {
- R.id.fab_add -> editDelegate.createCategory()
+ R.id.fab_add -> startActivity(FavouritesCategoryEditActivity.newIntent(this))
}
}
override fun onItemClick(item: FavouriteCategory, view: View) {
val menu = PopupMenu(view.context, view)
menu.inflate(R.menu.popup_category)
- prepareCategoryMenu(menu.menu, item)
menu.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.action_remove -> editDelegate.deleteCategory(item)
- R.id.action_rename -> editDelegate.renameCategory(item)
- R.id.action_tracking -> viewModel.setCategoryTracking(item.id, !item.isTrackingEnabled)
- R.id.action_order -> return@setOnMenuItemClickListener false
- else -> {
- val order = SORT_ORDERS.getOrNull(menuItem.order) ?: return@setOnMenuItemClickListener false
- viewModel.setCategoryOrder(item.id, order)
- }
+ R.id.action_edit -> startActivity(FavouritesCategoryEditActivity.newIntent(this, item.id))
}
true
}
@@ -118,33 +110,6 @@ class CategoriesActivity :
viewModel.deleteCategory(category.id)
}
- override fun onRenameCategory(category: FavouriteCategory, newName: String) {
- viewModel.renameCategory(category.id, newName)
- }
-
- override fun onCreateCategory(name: String) {
- viewModel.createCategory(name)
- }
-
- private fun prepareCategoryMenu(menu: Menu, category: FavouriteCategory) {
- val submenu = menu.findItem(R.id.action_order)?.subMenu ?: return
- for ((i, item) in SORT_ORDERS.withIndex()) {
- val menuItem = submenu.add(
- R.id.group_order,
- Menu.NONE,
- i,
- item.titleRes
- )
- menuItem.isCheckable = true
- menuItem.isChecked = item == category.order
- }
- submenu.setGroupCheckable(R.id.group_order, true, true)
- menu.findItem(R.id.action_tracking)?.run {
- isVisible = viewModel.isFavouritesTrackerEnabled
- isChecked = category.isTrackingEnabled
- }
- }
-
private inner class ReorderHelperCallback : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.DOWN or ItemTouchHelper.UP, 0
) {
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesEditDelegate.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesEditDelegate.kt
index 603a70ee3..f7a98c078 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesEditDelegate.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/CategoriesEditDelegate.kt
@@ -1,15 +1,10 @@
package org.koitharu.kotatsu.favourites.ui.categories
import android.content.Context
-import android.text.InputType
-import android.widget.Toast
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.koitharu.kotatsu.R
-import org.koitharu.kotatsu.base.ui.dialog.TextInputDialog
import org.koitharu.kotatsu.core.model.FavouriteCategory
-private const val MAX_TITLE_LENGTH = 24
-
class CategoriesEditDelegate(
private val context: Context,
private val callback: CategoriesEditCallback
@@ -26,49 +21,8 @@ class CategoriesEditDelegate(
.show()
}
- fun renameCategory(category: FavouriteCategory) {
- TextInputDialog.Builder(context)
- .setTitle(R.string.rename)
- .setText(category.title)
- .setHint(R.string.enter_category_name)
- .setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
- .setNegativeButton(android.R.string.cancel)
- .setMaxLength(MAX_TITLE_LENGTH, false)
- .setPositiveButton(R.string.rename) { _, name ->
- val trimmed = name.trim()
- if (trimmed.isEmpty()) {
- Toast.makeText(context, R.string.error_empty_name, Toast.LENGTH_SHORT).show()
- } else {
- callback.onRenameCategory(category, name)
- }
- }.create()
- .show()
- }
-
- fun createCategory() {
- TextInputDialog.Builder(context)
- .setTitle(R.string.add_new_category)
- .setHint(R.string.enter_category_name)
- .setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
- .setNegativeButton(android.R.string.cancel)
- .setMaxLength(MAX_TITLE_LENGTH, false)
- .setPositiveButton(R.string.add) { _, name ->
- val trimmed = name.trim()
- if (trimmed.isEmpty()) {
- Toast.makeText(context, R.string.error_empty_name, Toast.LENGTH_SHORT).show()
- } else {
- callback.onCreateCategory(trimmed)
- }
- }.create()
- .show()
- }
-
interface CategoriesEditCallback {
fun onDeleteCategory(category: FavouriteCategory)
-
- fun onRenameCategory(category: FavouriteCategory, newName: String)
-
- fun onCreateCategory(name: String)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt
index 9e84a9d89..31c1e11de 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt
@@ -1,7 +1,6 @@
package org.koitharu.kotatsu.favourites.ui.categories
import androidx.lifecycle.viewModelScope
-import java.util.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
@@ -10,8 +9,8 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoryListModel
-import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
+import java.util.*
class FavouritesCategoriesViewModel(
private val repository: FavouritesRepository,
@@ -34,39 +33,12 @@ class FavouritesCategoriesViewModel(
mapCategories(list, showAll, showAll)
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
- val isFavouritesTrackerEnabled: Boolean
- get() = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources
-
- fun createCategory(name: String) {
- launchJob {
- repository.addCategory(name)
- }
- }
-
- fun renameCategory(id: Long, name: String) {
- launchJob {
- repository.renameCategory(id, name)
- }
- }
-
fun deleteCategory(id: Long) {
launchJob {
repository.removeCategory(id)
}
}
- fun setCategoryOrder(id: Long, order: SortOrder) {
- launchJob {
- repository.setCategoryOrder(id, order)
- }
- }
-
- fun setCategoryTracking(id: Long, isEnabled: Boolean) {
- launchJob {
- repository.setCategoryTracking(id, isEnabled)
- }
- }
-
fun setAllCategoriesVisible(isVisible: Boolean) {
settings.isAllFavouritesVisible = isVisible
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt
new file mode 100644
index 000000000..27239c0dc
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt
@@ -0,0 +1,147 @@
+package org.koitharu.kotatsu.favourites.ui.categories.edit
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.core.graphics.Insets
+import androidx.core.view.isVisible
+import androidx.core.view.updatePadding
+import org.koin.androidx.viewmodel.ext.android.viewModel
+import org.koin.core.parameter.parametersOf
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.base.ui.BaseActivity
+import org.koitharu.kotatsu.core.model.FavouriteCategory
+import org.koitharu.kotatsu.core.ui.titleRes
+import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding
+import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
+import org.koitharu.kotatsu.parsers.model.SortOrder
+import org.koitharu.kotatsu.utils.ext.getDisplayMessage
+
+class FavouritesCategoryEditActivity : BaseActivity(), AdapterView.OnItemClickListener {
+
+ private val viewModel by viewModel {
+ parametersOf(intent.getLongExtra(EXTRA_ID, NO_ID))
+ }
+ private var selectedSortOrder: SortOrder? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(ActivityCategoryEditBinding.inflate(layoutInflater))
+ supportActionBar?.run {
+ setDisplayHomeAsUpEnabled(true)
+ setHomeAsUpIndicator(com.google.android.material.R.drawable.abc_ic_clear_material)
+ }
+ initSortSpinner()
+
+ viewModel.onSaved.observe(this) { finishAfterTransition() }
+ viewModel.category.observe(this, ::onCategoryChanged)
+ viewModel.isLoading.observe(this, ::onLoadingStateChanged)
+ viewModel.onError.observe(this, ::onError)
+ viewModel.isTrackerEnabled.observe(this) {
+ binding.switchTracker.isVisible = it
+ }
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putSerializable(KEY_SORT_ORDER, selectedSortOrder)
+ }
+
+ override fun onRestoreInstanceState(savedInstanceState: Bundle) {
+ super.onRestoreInstanceState(savedInstanceState)
+ val order = savedInstanceState.getSerializable(KEY_SORT_ORDER)
+ if (order != null && order is SortOrder) {
+ selectedSortOrder = order
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ menuInflater.inflate(R.menu.opt_config, menu)
+ menu.findItem(R.id.action_done)?.setTitle(R.string.save)
+ return super.onCreateOptionsMenu(menu)
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
+ R.id.action_done -> {
+ viewModel.save(
+ title = binding.editName.text?.toString().orEmpty(),
+ sortOrder = getSelectedSortOrder(),
+ isTrackerEnabled = binding.switchTracker.isChecked,
+ )
+ true
+ }
+ else -> super.onOptionsItemSelected(item)
+ }
+
+ override fun onWindowInsetsChanged(insets: Insets) {
+ binding.scrollView.updatePadding(
+ left = insets.left,
+ right = insets.right,
+ bottom = insets.bottom,
+ )
+ binding.toolbar.updatePadding(
+ top = insets.top,
+ )
+ }
+
+ override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+ selectedSortOrder = CategoriesActivity.SORT_ORDERS.getOrNull(position)
+ }
+
+ private fun onCategoryChanged(category: FavouriteCategory?) {
+ setTitle(if (category == null) R.string.create_category else R.string.edit_category)
+ if (selectedSortOrder != null) {
+ return
+ }
+ binding.editName.setText(category?.title)
+ selectedSortOrder = category?.order
+ val sortText = getString((category?.order ?: SortOrder.NEWEST).titleRes)
+ binding.editSort.setText(sortText, false)
+ binding.switchTracker.isChecked = category?.isTrackingEnabled ?: true
+ }
+
+ private fun onError(e: Throwable) {
+ binding.textViewError.text = e.getDisplayMessage(resources)
+ binding.textViewError.isVisible = true
+ }
+
+ private fun onLoadingStateChanged(isLoading: Boolean) {
+ binding.editSort.isEnabled = !isLoading
+ binding.editName.isEnabled = !isLoading
+ binding.switchTracker.isEnabled = !isLoading
+ if (isLoading) {
+ binding.textViewError.isVisible = false
+ }
+ }
+
+ private fun initSortSpinner() {
+ val entries = CategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) }
+ val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, entries)
+ binding.editSort.setAdapter(adapter)
+ binding.editSort.onItemClickListener = this
+ }
+
+ private fun getSelectedSortOrder(): SortOrder {
+ selectedSortOrder?.let { return it }
+ val entries = CategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) }
+ val index = entries.indexOf(binding.editSort.text.toString())
+ return CategoriesActivity.SORT_ORDERS.getOrNull(index) ?: SortOrder.NEWEST
+ }
+
+ companion object {
+
+ private const val EXTRA_ID = "id"
+ private const val KEY_SORT_ORDER = "sort"
+ private const val NO_ID = -1L
+
+ fun newIntent(context: Context, id: Long = NO_ID): Intent {
+ return Intent(context, FavouritesCategoryEditActivity::class.java)
+ .putExtra(EXTRA_ID, id)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt
new file mode 100644
index 000000000..78446dd14
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt
@@ -0,0 +1,53 @@
+package org.koitharu.kotatsu.favourites.ui.categories.edit
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.liveData
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Dispatchers
+import org.koitharu.kotatsu.base.ui.BaseViewModel
+import org.koitharu.kotatsu.core.model.FavouriteCategory
+import org.koitharu.kotatsu.core.prefs.AppSettings
+import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
+import org.koitharu.kotatsu.parsers.model.SortOrder
+import org.koitharu.kotatsu.utils.SingleLiveEvent
+
+private const val NO_ID = -1L
+
+class FavouritesCategoryEditViewModel(
+ private val categoryId: Long,
+ private val repository: FavouritesRepository,
+ private val settings: AppSettings,
+) : BaseViewModel() {
+
+ val onSaved = SingleLiveEvent()
+ val category = MutableLiveData()
+
+ val isTrackerEnabled = liveData(viewModelScope.coroutineContext + Dispatchers.Default) {
+ emit(settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources)
+ }
+
+ init {
+ launchLoadingJob {
+ category.value = if (categoryId != NO_ID) {
+ repository.getCategory(categoryId)
+ } else {
+ null
+ }
+ }
+ }
+
+ fun save(
+ title: String,
+ sortOrder: SortOrder,
+ isTrackerEnabled: Boolean,
+ ) {
+ launchLoadingJob {
+ if (categoryId == NO_ID) {
+ repository.createCategory(title, sortOrder, isTrackerEnabled)
+ } else {
+ repository.updateCategory(categoryId, title, sortOrder, isTrackerEnabled)
+ }
+ onSaved.call(Unit)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesDialog.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesDialog.kt
index 43eec185e..95f733006 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesDialog.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/FavouriteCategoriesDialog.kt
@@ -17,6 +17,7 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.databinding.DialogFavoriteCategoriesBinding
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesEditDelegate
+import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity
import org.koitharu.kotatsu.favourites.ui.categories.select.adapter.MangaCategoriesAdapter
import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem
import org.koitharu.kotatsu.parsers.model.Manga
@@ -34,9 +35,6 @@ class FavouriteCategoriesDialog :
}
private var adapter: MangaCategoriesAdapter? = null
- private val editDelegate by lazy(LazyThreadSafetyMode.NONE) {
- CategoriesEditDelegate(requireContext(), this@FavouriteCategoriesDialog)
- }
override fun onInflateView(
inflater: LayoutInflater,
@@ -61,7 +59,7 @@ class FavouriteCategoriesDialog :
override fun onMenuItemClick(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_create -> {
- editDelegate.createCategory()
+ FavouritesCategoryEditActivity.newIntent(requireContext())
true
}
else -> false
@@ -74,12 +72,6 @@ class FavouriteCategoriesDialog :
override fun onDeleteCategory(category: FavouriteCategory) = Unit
- override fun onRenameCategory(category: FavouriteCategory, newName: String) = Unit
-
- override fun onCreateCategory(name: String) {
- viewModel.createCategory(name)
- }
-
private fun onContentChanged(categories: List) {
adapter?.items = categories
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt
index 84f9cf8f9..b9f906549 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/categories/select/MangaCategoriesViewModel.kt
@@ -38,12 +38,6 @@ class MangaCategoriesViewModel(
}
}
- fun createCategory(name: String) {
- launchJob(Dispatchers.Default) {
- favouritesRepository.addCategory(name)
- }
- }
-
private fun observeCategoriesIds() = if (manga.size == 1) {
// Fast path
favouritesRepository.observeCategoriesIds(manga[0].id)
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt
index f2748622c..8d4b9e419 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt
@@ -1,11 +1,17 @@
package org.koitharu.kotatsu.favourites.ui.list
+import android.os.Bundle
import android.view.Menu
+import android.view.MenuInflater
import android.view.MenuItem
+import android.view.View
import androidx.appcompat.view.ActionMode
+import androidx.core.view.iterator
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.ui.titleRes
+import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
import org.koitharu.kotatsu.list.ui.MangaListFragment
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.utils.ext.withArgs
@@ -17,12 +23,54 @@ class FavouritesListFragment : MangaListFragment() {
}
private val categoryId: Long
- get() = arguments?.getLong(ARG_CATEGORY_ID) ?: 0L
+ get() = arguments?.getLong(ARG_CATEGORY_ID) ?: NO_ID
override val isSwipeRefreshEnabled = false
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ viewModel.sortOrder.observe(viewLifecycleOwner) { activity?.invalidateOptionsMenu() }
+ }
+
override fun onScrolledToEnd() = Unit
+ override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+ super.onCreateOptionsMenu(menu, inflater)
+ if (categoryId != NO_ID) {
+ inflater.inflate(R.menu.opt_favourites_list, menu)
+ menu.findItem(R.id.action_order)?.subMenu?.let { submenu ->
+ for ((i, item) in CategoriesActivity.SORT_ORDERS.withIndex()) {
+ val menuItem = submenu.add(R.id.group_order, Menu.NONE, i, item.titleRes)
+ menuItem.isCheckable = true
+ }
+ submenu.setGroupCheckable(R.id.group_order, true, true)
+ }
+ }
+ }
+
+ override fun onPrepareOptionsMenu(menu: Menu) {
+ super.onPrepareOptionsMenu(menu)
+ menu.findItem(R.id.action_order)?.subMenu?.let { submenu ->
+ val selectedOrder = viewModel.sortOrder.value
+ for (item in submenu) {
+ val order = CategoriesActivity.SORT_ORDERS.getOrNull(item.order)
+ item.isChecked = order == selectedOrder
+ }
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return when {
+ item.itemId == R.id.action_order -> false
+ item.groupId == R.id.group_order -> {
+ val order = CategoriesActivity.SORT_ORDERS.getOrNull(item.order) ?: return false
+ viewModel.setSortOrder(order)
+ true
+ }
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.mode_favourites, menu)
return super.onCreateActionMode(mode, menu)
@@ -48,6 +96,7 @@ class FavouritesListFragment : MangaListFragment() {
companion object {
+ const val NO_ID = 0L
private const val ARG_CATEGORY_ID = "category_id"
fun newInstance(categoryId: Long) = FavouritesListFragment().withArgs(1) {
diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt
index 476fa6fb1..06d5bee3d 100644
--- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt
@@ -1,12 +1,16 @@
package org.koitharu.kotatsu.favourites.ui.list
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
+import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID
import org.koitharu.kotatsu.list.domain.CountersProvider
import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.EmptyState
@@ -24,8 +28,16 @@ class FavouritesListViewModel(
settings: AppSettings,
) : MangaListViewModel(settings), CountersProvider {
+ var sortOrder: LiveData = if (categoryId == NO_ID) {
+ MutableLiveData(null)
+ } else {
+ repository.observeCategory(categoryId)
+ .map { it.order }
+ .asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
+ }
+
override val content = combine(
- if (categoryId == 0L) {
+ if (categoryId == NO_ID) {
repository.observeAll(SortOrder.NEWEST)
} else {
repository.observeAll(categoryId)
@@ -37,7 +49,7 @@ class FavouritesListViewModel(
EmptyState(
icon = R.drawable.ic_heart_outline,
textPrimary = R.string.text_empty_holder_primary,
- textSecondary = if (categoryId == 0L) {
+ textSecondary = if (categoryId == NO_ID) {
R.string.you_have_not_favourites_yet
} else {
R.string.favourites_category_empty
@@ -60,7 +72,7 @@ class FavouritesListViewModel(
return
}
launchJob {
- if (categoryId == 0L) {
+ if (categoryId == NO_ID) {
repository.removeFromFavourites(ids)
} else {
repository.removeFromCategory(categoryId, ids)
@@ -68,6 +80,15 @@ class FavouritesListViewModel(
}
}
+ fun setSortOrder(order: SortOrder) {
+ if (categoryId == NO_ID) {
+ return
+ }
+ launchJob {
+ repository.setCategoryOrder(categoryId, order)
+ }
+ }
+
override suspend fun getCounter(mangaId: Long): Int {
return trackingRepository.getNewChaptersCount(mangaId)
}
diff --git a/app/src/main/res/layout-w720dp-land/activity_main.xml b/app/src/main/res/layout-w720dp-land/activity_main.xml
index ee362d397..a442269b3 100644
--- a/app/src/main/res/layout-w720dp-land/activity_main.xml
+++ b/app/src/main/res/layout-w720dp-land/activity_main.xml
@@ -62,6 +62,7 @@
android:layout_height="match_parent"
android:background="@null"
android:drawablePadding="16dp"
+ android:layout_marginEnd="4dp"
android:gravity="center_vertical"
android:hint="@string/search_manga"
android:imeOptions="actionSearch"
diff --git a/app/src/main/res/layout/activity_category_edit.xml b/app/src/main/res/layout/activity_category_edit.xml
new file mode 100644
index 000000000..e453df674
--- /dev/null
+++ b/app/src/main/res/layout/activity_category_edit.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 43361b15b..6314cf7ef 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -51,7 +51,7 @@
style="@style/Widget.Kotatsu.SearchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginEnd="2dp"
+ android:layout_marginEnd="4dp"
android:background="@null"
android:gravity="center_vertical"
android:hint="@string/search_manga"
diff --git a/app/src/main/res/menu/opt_favourites_list.xml b/app/src/main/res/menu/opt_favourites_list.xml
new file mode 100644
index 000000000..269569df7
--- /dev/null
+++ b/app/src/main/res/menu/opt_favourites_list.xml
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/popup_category.xml b/app/src/main/res/menu/popup_category.xml
index ee78b4b80..50c1313be 100644
--- a/app/src/main/res/menu/popup_category.xml
+++ b/app/src/main/res/menu/popup_category.xml
@@ -7,25 +7,7 @@
android:title="@string/remove" />
-
- -
-
-
-
-
-
-
-
-
-
+ android:id="@+id/action_edit"
+ android:title="@string/edit" />
\ No newline at end of file
diff --git a/app/src/main/res/values-large/themes.xml b/app/src/main/res/values-large/themes.xml
new file mode 100644
index 000000000..56e1ed965
--- /dev/null
+++ b/app/src/main/res/values-large/themes.xml
@@ -0,0 +1,34 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 87da7d5d0..012bf4aee 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -281,4 +281,7 @@
Вы будете получать уведомления об обновлении манги, которую Вы читаете
Вы не будете получать уведомления, но новые главы будут отображаться в списке
Включить уведомления
+ Название
+ Изменить
+ Изменить категорию
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 083717035..2bc68e061 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -284,4 +284,7 @@
You will receive notifications about updates of manga you are reading
You will not receive notifications but new chapters will be highlighted in the lists
Enable notifications
+ Name
+ Edit
+ Edit category
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index b63927f74..b16f50044 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -119,6 +119,8 @@
+
+
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 12ccac10f..f6addbe8f 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -71,7 +71,8 @@
- @style/Widget.Kotatsu.RecyclerView
- @style/Widget.Kotatsu.ListItemTextView
-
+
+ - @style/TextAppearance.Kotatsu.Menu
- ?attr/textAppearanceBodyLarge
- @style/TextAppearance.Kotatsu.Preference.Secondary
@@ -80,6 +81,8 @@
+
+