diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6f8850ec5..a95d2a781 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,6 +53,10 @@ android:label="@string/error_occurred" android:theme="@android:style/Theme.DeviceDefault.Dialog" android:windowSoftInputMode="stateAlwaysHidden" /> + Unit): Builder { delegate.setPositiveButton(textId) { dialog, _ -> listener(dialog, view.inputEdit.text?.toString().orEmpty()) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt index 1f1b26467..fd0f868fe 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt @@ -13,7 +13,7 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.ui.common.BaseFragment -import org.koitharu.kotatsu.ui.main.list.favourites.categories.FavouriteCategoriesDialog +import org.koitharu.kotatsu.ui.main.list.favourites.categories.select.FavouriteCategoriesDialog import org.koitharu.kotatsu.ui.reader.ReaderActivity import org.koitharu.kotatsu.ui.search.MangaSearchSheet import org.koitharu.kotatsu.utils.ext.addChips diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt index 3b82bc2ba..b61836f3b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt @@ -6,11 +6,11 @@ import android.view.MenuItem import kotlinx.android.synthetic.main.fragment_list.* import moxy.ktx.moxyPresenter import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.ui.main.list.MangaListFragment import org.koitharu.kotatsu.ui.main.list.MangaListView +import org.koitharu.kotatsu.ui.main.list.favourites.categories.CategoriesActivity -class FavouritesListFragment : MangaListFragment(), MangaListView{ +class FavouritesListFragment : MangaListFragment(), MangaListView { private val presenter by moxyPresenter(factory = ::FavouritesListPresenter) @@ -19,12 +19,17 @@ class FavouritesListFragment : MangaListFragment(), MangaListView{ } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { -// inflater.inflate(R.menu.opt_history, menu) + inflater.inflate(R.menu.opt_favourites, menu) super.onCreateOptionsMenu(menu, inflater) } - override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) { - + override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { + R.id.action_categories -> { + context?.let { + startActivity(CategoriesActivity.newIntent(it)) + } + true + } else -> super.onOptionsItemSelected(item) } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt new file mode 100644 index 000000000..df06e5490 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt @@ -0,0 +1,111 @@ +package org.koitharu.kotatsu.ui.main.list.favourites.categories + +import android.content.Context +import android.content.Intent +import android.content.res.ColorStateList +import android.graphics.Color +import android.os.Bundle +import android.text.InputType +import android.view.View +import androidx.appcompat.app.AlertDialog +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.snackbar.Snackbar +import kotlinx.android.synthetic.main.activity_categories.* +import moxy.ktx.moxyPresenter +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.ui.common.BaseActivity +import org.koitharu.kotatsu.ui.common.dialog.TextInputDialog +import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener +import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.utils.ext.showPopupMenu + +class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener, + FavouriteCategoriesView, View.OnClickListener { + + private val presenter by moxyPresenter(factory = ::FavouriteCategoriesPresenter) + + private lateinit var adapter: CategoriesAdapter + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_categories) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + fab_add.imageTintList = ColorStateList.valueOf(Color.WHITE) + adapter = CategoriesAdapter(this) + recyclerView.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL)) + recyclerView.adapter = adapter + fab_add.setOnClickListener(this) + } + + override fun onClick(v: View) { + when (v.id) { + R.id.fab_add -> createCategory() + } + } + + override fun onItemClick(item: FavouriteCategory, position: Int, view: View) { + view.showPopupMenu(R.menu.popup_category) { + when (it.itemId) { + R.id.action_remove -> deleteCategory(item) + R.id.action_rename -> renameCategory(item) + } + true + } + } + + override fun onCategoriesChanged(categories: List) { + adapter.replaceData(categories) + textView_holder.isVisible = categories.isEmpty() + } + + override fun onCheckedCategoriesChanged(checkedIds: Set) = Unit + + override fun onError(e: Throwable) { + Snackbar.make(recyclerView, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG) + .show() + } + + private fun deleteCategory(category: FavouriteCategory) { + AlertDialog.Builder(this) + .setMessage(getString(R.string.category_delete_confirm, category.title)) + .setTitle(R.string.remove_category) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.remove) { _, _ -> + presenter.deleteCategory(category.id) + }.create() + .show() + } + + private fun renameCategory(category: FavouriteCategory) { + TextInputDialog.Builder(this) + .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) + .setPositiveButton(R.string.rename) { _, name -> + presenter.renameCategory(category.id, name) + }.create() + .show() + } + + private fun createCategory() { + TextInputDialog.Builder(this) + .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) + .setPositiveButton(R.string.add) { _, name -> + presenter.createCategory(name) + }.create() + .show() + } + + companion object { + + fun newIntent(context: Context) = Intent(context, CategoriesActivity::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesAdapter.kt index cdc26408f..4bc90bc3e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesAdapter.kt @@ -1,46 +1,17 @@ package org.koitharu.kotatsu.ui.main.list.favourites.categories -import android.util.SparseBooleanArray import android.view.ViewGroup -import android.widget.Checkable -import androidx.core.util.set import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter -import org.koitharu.kotatsu.ui.common.list.BaseViewHolder +import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener +import org.koitharu.kotatsu.ui.main.list.favourites.categories.select.CategoryCheckableHolder -class CategoriesAdapter(private val listener: OnCategoryCheckListener) : - BaseRecyclerAdapter() { +class CategoriesAdapter(onItemClickListener: OnRecyclerItemClickListener? = null) : + BaseRecyclerAdapter(onItemClickListener) { - private val checkedIds = SparseBooleanArray() - - fun setCheckedIds(ids: Iterable) { - checkedIds.clear() - ids.forEach { - checkedIds[it] = true - } - notifyDataSetChanged() - } - - override fun getExtra(item: FavouriteCategory, position: Int) = - checkedIds.get(item.id.toInt(), false) - - override fun onCreateViewHolder(parent: ViewGroup) = - CategoryHolder( - parent - ) + override fun onCreateViewHolder(parent: ViewGroup) = CategoryHolder(parent) override fun onGetItemId(item: FavouriteCategory) = item.id - override fun onViewHolderCreated(holder: BaseViewHolder) { - super.onViewHolderCreated(holder) - holder.itemView.setOnClickListener { - if (it !is Checkable) return@setOnClickListener - it.toggle() - if (it.isChecked) { - listener.onCategoryChecked(holder.requireData()) - } else { - listener.onCategoryUnchecked(holder.requireData()) - } - } - } + override fun getExtra(item: FavouriteCategory, position: Int) = Unit } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoryHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoryHolder.kt index 9716b880a..3b2d16fe4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoryHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoryHolder.kt @@ -1,16 +1,15 @@ package org.koitharu.kotatsu.ui.main.list.favourites.categories import android.view.ViewGroup -import kotlinx.android.synthetic.main.item_category_checkable.* +import kotlinx.android.synthetic.main.item_category.* import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.ui.common.list.BaseViewHolder class CategoryHolder(parent: ViewGroup) : - BaseViewHolder(parent, R.layout.item_category_checkable) { + BaseViewHolder(parent, R.layout.item_category) { - override fun onBind(data: FavouriteCategory, extra: Boolean) { - checkedTextView.text = data.title - checkedTextView.isChecked = extra + override fun onBind(data: FavouriteCategory, extra: Unit) { + textView.text = data.title } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesPresenter.kt index 41794cffb..3db757fbf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesPresenter.kt @@ -70,6 +70,40 @@ class FavouriteCategoriesPresenter : BasePresenter() { } } + fun renameCategory(id: Long, name: String) { + presenterScope.launch { + try { + val categories = withContext(Dispatchers.IO) { + repository.renameCategory(id, name) + repository.getAllCategories() + } + viewState.onCategoriesChanged(categories) + } catch (e: Exception) { + if (BuildConfig.DEBUG) { + e.printStackTrace() + } + viewState.onError(e) + } + } + } + + fun deleteCategory(id: Long) { + presenterScope.launch { + try { + val categories = withContext(Dispatchers.IO) { + repository.removeCategory(id) + repository.getAllCategories() + } + viewState.onCategoriesChanged(categories) + } catch (e: Exception) { + if (BuildConfig.DEBUG) { + e.printStackTrace() + } + viewState.onError(e) + } + } + } + fun addToCategory(manga: Manga, categoryId: Long) { presenterScope.launch { try { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoriesSelectAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoriesSelectAdapter.kt new file mode 100644 index 000000000..676e53cd7 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoriesSelectAdapter.kt @@ -0,0 +1,46 @@ +package org.koitharu.kotatsu.ui.main.list.favourites.categories.select + +import android.util.SparseBooleanArray +import android.view.ViewGroup +import android.widget.Checkable +import androidx.core.util.set +import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter +import org.koitharu.kotatsu.ui.common.list.BaseViewHolder + +class CategoriesSelectAdapter(private val listener: OnCategoryCheckListener) : + BaseRecyclerAdapter() { + + private val checkedIds = SparseBooleanArray() + + fun setCheckedIds(ids: Iterable) { + checkedIds.clear() + ids.forEach { + checkedIds[it] = true + } + notifyDataSetChanged() + } + + override fun getExtra(item: FavouriteCategory, position: Int) = + checkedIds.get(item.id.toInt(), false) + + override fun onCreateViewHolder(parent: ViewGroup) = + CategoryCheckableHolder( + parent + ) + + override fun onGetItemId(item: FavouriteCategory) = item.id + + override fun onViewHolderCreated(holder: BaseViewHolder) { + super.onViewHolderCreated(holder) + holder.itemView.setOnClickListener { + if (it !is Checkable) return@setOnClickListener + it.toggle() + if (it.isChecked) { + listener.onCategoryChecked(holder.requireData()) + } else { + listener.onCategoryUnchecked(holder.requireData()) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoryCheckableHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoryCheckableHolder.kt new file mode 100644 index 000000000..7069870ea --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/CategoryCheckableHolder.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.ui.main.list.favourites.categories.select + +import android.view.ViewGroup +import kotlinx.android.synthetic.main.item_category_checkable.* +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.FavouriteCategory +import org.koitharu.kotatsu.ui.common.list.BaseViewHolder + +class CategoryCheckableHolder(parent: ViewGroup) : + BaseViewHolder(parent, R.layout.item_category_checkable) { + + override fun onBind(data: FavouriteCategory, extra: Boolean) { + checkedTextView.text = data.title + checkedTextView.isChecked = extra + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesDialog.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/FavouriteCategoriesDialog.kt similarity index 86% rename from app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesDialog.kt rename to app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/FavouriteCategoriesDialog.kt index e7ccee533..666f3c880 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/FavouriteCategoriesDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/FavouriteCategoriesDialog.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.ui.main.list.favourites.categories +package org.koitharu.kotatsu.ui.main.list.favourites.categories.select import android.os.Bundle import android.text.InputType @@ -12,6 +12,8 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.ui.common.BaseBottomSheet import org.koitharu.kotatsu.ui.common.dialog.TextInputDialog +import org.koitharu.kotatsu.ui.main.list.favourites.categories.FavouriteCategoriesPresenter +import org.koitharu.kotatsu.ui.main.list.favourites.categories.FavouriteCategoriesView import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.withArgs @@ -23,11 +25,13 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ private val manga get() = arguments?.getParcelable(ARG_MANGA) - private var adapter: CategoriesAdapter? = null + private var adapter: CategoriesSelectAdapter? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - adapter = CategoriesAdapter(this) + adapter = + CategoriesSelectAdapter( + this) recyclerView_categories.adapter = adapter textView_add.setOnClickListener { createCategory() @@ -79,8 +83,10 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ private const val ARG_MANGA = "manga" private const val TAG = "FavouriteCategoriesDialog" - fun show(fm: FragmentManager, manga: Manga) = FavouriteCategoriesDialog().withArgs(1) { + fun show(fm: FragmentManager, manga: Manga) = FavouriteCategoriesDialog() + .withArgs(1) { putParcelable(ARG_MANGA, manga) - }.show(fm, TAG) + }.show(fm, + TAG) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/OnCategoryCheckListener.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/OnCategoryCheckListener.kt similarity index 73% rename from app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/OnCategoryCheckListener.kt rename to app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/OnCategoryCheckListener.kt index a3403c323..ea55b245b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/OnCategoryCheckListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/select/OnCategoryCheckListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.ui.main.list.favourites.categories +package org.koitharu.kotatsu.ui.main.list.favourites.categories.select import org.koitharu.kotatsu.core.model.FavouriteCategory diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListFragment.kt index 3849565bf..55ed04fac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListFragment.kt @@ -48,7 +48,7 @@ class HistoryListFragment : MangaListFragment(), MangaListView() { } override fun setUpEmptyListHolder() { - textView_holder.setText(R.string.no_saved_manga) + textView_holder.setText(R.string.text_local_holder) textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) } diff --git a/app/src/main/res/layout/activity_categories.xml b/app/src/main/res/layout/activity_categories.xml new file mode 100644 index 000000000..7f20d872b --- /dev/null +++ b/app/src/main/res/layout/activity_categories.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_category.xml b/app/src/main/res/layout/item_category.xml new file mode 100644 index 000000000..c0739d7cc --- /dev/null +++ b/app/src/main/res/layout/item_category.xml @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/app/src/main/res/menu/opt_favourites.xml b/app/src/main/res/menu/opt_favourites.xml new file mode 100644 index 000000000..627c0bf85 --- /dev/null +++ b/app/src/main/res/menu/opt_favourites.xml @@ -0,0 +1,12 @@ + + + + + + \ 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 new file mode 100644 index 000000000..92dd0a0e9 --- /dev/null +++ b/app/src/main/res/menu/popup_category.xml @@ -0,0 +1,13 @@ + + + + + + + + \ 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 e693594c5..cd0b772f8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -23,7 +23,7 @@ История пуста Читать Добавить закладку - У Вас пока нет избранной манги + Добавьте интересующую Вас мангу в избренное, чтобы не потерять её Добавить в избранное Создать категорию Добавить @@ -122,4 +122,12 @@ Звук уведомления Световая индикация Вибросигнал + Категории избранного + Категории… + Переименовать + Вы уверены, что хотите удалить категорию \"%s\"? \nВся манга из данной категории будет утеряна. + Удалить категорию + Категории помогают упорядочивать избранную мангу. Нажмите «+», чтобы создать категорию + Здесь будет оборажаться манга, которую Вы читаете. Вы можете найти, что почитать, в боковом меню + У Вас пока нет сохранённой манги. Вы можете сохранить мангу из онлайн каталога или импортировать из файла \ 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 ebbb437a8..29b58168a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -123,4 +123,12 @@ Notification sound Light indicator Vibration + Favourites categories + Categories… + Rename + Do you really want to remove category \"%s\" from your favourites? \nAll containing manga will be lost. + Remove category + You can use categories to organize your favourite manga. Press «+» to create a category + Manga you are reading will be displayed here. You can find what to read in side menu + You have not any saved manga yet. You can save it from online sources or import from file \ No newline at end of file