Pressing on category name in library allows managing of it

Can rename, set download new chapters, or include in global update
This commit is contained in:
Jay 2020-04-16 20:41:07 -04:00
parent 877cb43043
commit 6bdbf59041
24 changed files with 254 additions and 213 deletions

View File

@ -10,12 +10,11 @@ import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.category.CategoryPresenter.Companion.CREATE_CATEGORY_ORDER
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForController
import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.snack
import kotlinx.android.synthetic.main.categories_controller.*
@ -24,9 +23,7 @@ import kotlinx.android.synthetic.main.categories_controller.*
*/
class CategoryController(bundle: Bundle? = null) : BaseController(bundle),
FlexibleAdapter.OnItemClickListener,
CategoryAdapter.CategoryItemListener,
CategoryCreateDialog.Listener,
CategoryRenameDialog.Listener {
CategoryAdapter.CategoryItemListener {
/**
* Adapter containing category items.
@ -67,7 +64,7 @@ class CategoryController(bundle: Bundle? = null) : BaseController(bundle),
*/
override fun onViewCreated(view: View) {
super.onViewCreated(view)
view.applyWindowInsetsForController()
scrollViewWith(recycler, padBottom = true)
adapter = CategoryAdapter(this@CategoryController)
recycler.layoutManager = LinearLayoutManager(view.context)
@ -175,34 +172,6 @@ class CategoryController(bundle: Bundle? = null) : BaseController(bundle),
snack = null
}
/**
* Show a dialog to let the user change the category name.
*
* @param category The category to be edited.
*/
private fun editCategory(category: Category) {
CategoryRenameDialog(this, category).showDialog(router)
}
/**
* Renames the given category with the given name.
*
* @param category The category to rename.
* @param name The new name of the category.
*/
override fun renameCategory(category: Category, name: String) {
presenter.renameCategory(category, name)
}
/**
* Creates a new category with the given name.
*
* @param name The name of the new category.
*/
override fun createCategory(name: String) {
presenter.createCategory(name)
}
/**
* Called from the presenter when a category with the given name already exists.
*/

View File

@ -1,40 +0,0 @@
package eu.kanade.tachiyomi.ui.category
import android.app.Dialog
import android.os.Bundle
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.input
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.base.controller.DialogController
/**
* Dialog to create a new category for the library.
*/
class CategoryCreateDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
where T : Controller, T : CategoryCreateDialog.Listener {
constructor(target: T) : this() {
targetController = target
}
/**
* Called when creating the dialog for this controller.
*
* @param savedViewState The saved state of this dialog.
* @return a new dialog instance.
*/
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
return MaterialDialog(activity!!)
.title(R.string.add_category)
.positiveButton(android.R.string.ok)
.negativeButton(android.R.string.cancel)
.input(hintRes = R.string.name) { _, input ->
(targetController as? Listener)?.createCategory(input.toString())
}
}
interface Listener {
fun createCategory(name: String)
}
}

View File

@ -71,7 +71,6 @@ class CategoryPresenter(
cat.order = categories.map { it.order + 1 }.max() ?: 0
// Insert into database.
cat.mangaSort = 'a'
db.insertCategory(cat).executeAsBlocking()
val cats = db.getCategories().executeAsBlocking()

View File

@ -1,84 +0,0 @@
package eu.kanade.tachiyomi.ui.category
import android.app.Dialog
import android.os.Bundle
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.input
import com.bluelinelabs.conductor.Controller
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.ui.base.controller.DialogController
/**
* Dialog to rename an existing category of the library.
*/
class CategoryRenameDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
where T : Controller, T : CategoryRenameDialog.Listener {
private var category: Category? = null
/**
* Name of the new category. Value updated with each input from the user.
*/
private var currentName = ""
constructor(target: T, category: Category) : this() {
targetController = target
this.category = category
currentName = category.name
}
/**
* Called when creating the dialog for this controller.
*
* @param savedViewState The saved state of this dialog.
* @return a new dialog instance.
*/
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
return MaterialDialog(activity!!)
.title(R.string.rename_category)
.negativeButton(android.R.string.cancel)
.input(hintRes = R.string.name, prefill = currentName) { _, input ->
currentName = input.toString()
}
.positiveButton(android.R.string.ok) { onPositive() }
}
/**
* Called to save this Controller's state in the event that its host Activity is destroyed.
*
* @param outState The Bundle into which data should be saved
*/
override fun onSaveInstanceState(outState: Bundle) {
outState.putSerializable(CATEGORY_KEY, category)
super.onSaveInstanceState(outState)
}
/**
* Restores data that was saved in the [onSaveInstanceState] method.
*
* @param savedInstanceState The bundle that has data to be restored
*/
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
category = savedInstanceState.getSerializable(CATEGORY_KEY) as? Category
}
/**
* Called when the positive button of the dialog is clicked.
*/
private fun onPositive() {
val target = targetController as? Listener ?: return
val category = category ?: return
target.renameCategory(category, currentName)
}
interface Listener {
fun renameCategory(category: Category, name: String)
}
private companion object {
const val CATEGORY_KEY = "CategoryRenameDialog.category"
}
}

View File

@ -0,0 +1,134 @@
package eu.kanade.tachiyomi.ui.category
import android.app.Dialog
import android.os.Bundle
import android.view.View
import android.widget.CompoundButton
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.f2prateek.rx.preferences.Preference
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.library.LibraryController
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.edit_manga_dialog.view.title
import kotlinx.android.synthetic.main.manga_category_dialog.view.*
import uy.kohesive.injekt.injectLazy
class ManageCategoryDialog(bundle: Bundle? = null) :
DialogController(bundle) {
constructor(libraryController: LibraryController, category: Category) : this() {
this.libraryController = libraryController
this.category = category
}
private lateinit var libraryController: LibraryController
private lateinit var category: Category
private var dialogView: View? = null
private val preferences by injectLazy<PreferencesHelper>()
private val db by injectLazy<DatabaseHelper>()
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
val dialog = MaterialDialog(activity!!).apply {
title(R.string.manage_category)
customView(viewRes = R.layout.manga_category_dialog)
negativeButton(android.R.string.cancel)
positiveButton(R.string.save) { onPositiveButtonClick() }
}
dialogView = dialog.view
onViewCreated(dialog.view)
return dialog
}
private fun onPositiveButtonClick() {
val view = dialogView ?: return
val text = view.title.text.toString()
val categoryExists = categoryExists(text)
if (text.isNotBlank() && !categoryExists && !text.equals(category.name, true)) {
category.name = text
db.insertCategory(category).executeAsBlocking()
libraryController.presenter.getLibrary()
} else if (categoryExists) {
activity?.toast(R.string.category_with_name_exists)
}
if (!updatePref(preferences.downloadNewCategories(), view.download_new)) {
preferences.downloadNew().set(false)
} else {
preferences.downloadNew().set(true)
}
if (preferences.libraryUpdateInterval().getOrDefault() > 0 &&
!updatePref(preferences.libraryUpdateCategories(), view.include_global)) {
preferences.libraryUpdateInterval().set(0)
LibraryUpdateJob.cancelTask()
}
}
/**
* Returns true if a category with the given name already exists.
*/
private fun categoryExists(name: String): Boolean {
return db.getCategories().executeAsBlocking().any {
it.name.equals(name, true) && category.id != it.id
}
}
fun onViewCreated(view: View) {
view.edit_categories.setOnClickListener {
router.popCurrentController()
router.pushController(CategoryController().withFadeTransaction())
}
view.title.hint = category.name
view.title.append(category.name)
val downloadNew = preferences.downloadNew().getOrDefault()
setCheckbox(view.download_new,
preferences.downloadNewCategories(),
true)
if (downloadNew && preferences.downloadNewCategories().getOrDefault().isEmpty())
view.download_new.gone()
else if (!downloadNew)
view.download_new.visible()
view.download_new.isChecked =
preferences.downloadNew().getOrDefault() && view.download_new.isChecked
setCheckbox(
view.include_global,
preferences.libraryUpdateCategories(),
preferences.libraryUpdateInterval().getOrDefault() > 0
)
}
/** Update a pref based on checkbox, and return if the pref is not empty */
private fun updatePref(categories: Preference<Set<String>>, box: CompoundButton): Boolean {
val categoryId = category.id ?: return true
val updateCategories = categories.getOrDefault().toMutableSet()
if (box.isChecked) {
updateCategories.add(categoryId.toString())
} else {
updateCategories.remove(categoryId.toString())
}
categories.set(updateCategories)
return updateCategories.isNotEmpty()
}
private fun setCheckbox(
box: CompoundButton,
categories: Preference<Set<String>>,
shouldShow: Boolean
) {
val updateCategories = categories.getOrDefault()
box.visibleIf(updateCategories.isNotEmpty() && shouldShow)
if (updateCategories.isNotEmpty() && shouldShow) box.isChecked =
updateCategories.any { category.id == it.toIntOrNull() }
}
}

View File

@ -38,7 +38,7 @@ class DownloadHolder(private val view: View, val adapter: DownloadAdapter) :
chapter_title.text = download.chapter.name
// Update the manga title
manga_full_title.text = download.manga.title
title.text = download.manga.title
// Update the progress bar and the number of downloaded pages
val pages = download.pages

View File

@ -273,5 +273,6 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
fun selectAll(position: Int)
fun allSelected(position: Int): Boolean
fun toggleCategoryVisibility(position: Int)
fun manageCategory(position: Int)
}
}

View File

@ -46,6 +46,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.category.ManageCategoryDialog
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity
@ -156,7 +157,7 @@ class LibraryController(
if (order != null && order != activeCategory && lastItem == null) {
preferences.lastUsedCategory().set(order)
activeCategory = order
if (presenter.categories.size > 1 && dy != 0 && abs(dy) > 75) {
if (presenter.categories.size > 1 && dy != 0) {
val headerItem = getHeader() ?: return
val view = fast_scroller.getChildAt(0) ?: return
val index = adapter.headerItems.indexOf(headerItem)
@ -809,6 +810,11 @@ class LibraryController(
presenter.toggleCategoryVisibility(catId)
}
override fun manageCategory(position: Int) {
val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return
ManageCategoryDialog(this, category).showDialog(router)
}
override fun sortCategory(catId: Int, sortBy: Int) {
presenter.sortCategory(catId, sortBy)
}

View File

@ -95,6 +95,7 @@ class LibraryHeaderItem(
marginEnd = (if (padEnd && adapter.recyclerView.paddingEnd == 0) 12 else 2).dpToPx
}
updateButton.setOnClickListener { addCategoryToUpdate() }
sectionText.setOnClickListener { adapter.libraryListener.manageCategory(adapterPosition) }
sectionText.setOnLongClickListener {
adapter.libraryListener.toggleCategoryVisibility(adapterPosition)
true

View File

@ -71,8 +71,8 @@ class EditMangaDialog : DialogController {
if (isLocal) {
if (manga.title != manga.url)
view.manga_full_title.append(manga.title)
view.manga_full_title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
view.title.append(manga.title)
view.title.hint = "${resources?.getString(R.string.title)}: ${manga.url}"
view.manga_author.append(manga.author ?: "")
view.manga_artist.append(manga.artist ?: "")
view.manga_description.append(manga.description ?: "")
@ -103,7 +103,7 @@ class EditMangaDialog : DialogController {
}
private fun onPositiveButtonClick() {
infoController.presenter.updateManga(dialogView?.manga_full_title?.text.toString(),
infoController.presenter.updateManga(dialogView?.title?.text.toString(),
dialogView?.manga_author?.text.toString(), dialogView?.manga_artist?.text.toString(),
customCoverUri, dialogView?.manga_description?.text.toString(),
dialogView?.manga_genres_tags?.tags)

View File

@ -69,8 +69,8 @@ class MangaHeaderHolder(
adapter.delegate.favoriteManga(true)
true
}
manga_full_title.setOnLongClickListener {
adapter.delegate.copyToClipboard(manga_full_title.text.toString(), R.string.title)
title.setOnLongClickListener {
adapter.delegate.copyToClipboard(title.text.toString(), R.string.title)
true
}
manga_author.setOnLongClickListener {
@ -114,7 +114,7 @@ class MangaHeaderHolder(
@SuppressLint("SetTextI18n")
fun bind(item: MangaHeaderItem, manga: Manga) {
val presenter = adapter.delegate.mangaPresenter()
manga_full_title.text = manga.title
title.text = manga.title
if (manga.genre.isNullOrBlank().not()) manga_genres_tags.setTags(
manga.genre?.split(", ")?.map(String::trim)

View File

@ -14,8 +14,7 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
import eu.kanade.tachiyomi.util.system.await
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForController
import eu.kanade.tachiyomi.util.view.scrollViewWith
import kotlinx.android.synthetic.main.migration_controller.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -54,13 +53,12 @@ class MigrationController : NucleusController<MigrationPresenter>(),
override fun onViewCreated(view: View) {
super.onViewCreated(view)
view.applyWindowInsetsForController()
scrollViewWith(migration_recycler, padBottom = true)
adapter = FlexibleAdapter(null, this)
migration_recycler.layoutManager =
androidx.recyclerview.widget.LinearLayoutManager(view.context)
migration_recycler.adapter = adapter
migration_recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
}
override fun onDestroyView(view: View) {

View File

@ -56,7 +56,7 @@ class RecentChapterHolder(private val view: View, private val adapter: RecentCha
chapter_title.text = item.chapter.name
// Set manga title
manga_full_title.text = item.manga.title
title.text = item.manga.title
if (front_view.translationX == 0f) {
read.setImageDrawable(
@ -80,10 +80,10 @@ class RecentChapterHolder(private val view: View, private val adapter: RecentCha
// Check if chapter is read and set correct color
if (item.chapter.read) {
chapter_title.setTextColor(readColor)
manga_full_title.setTextColor(readColor)
title.setTextColor(readColor)
} else {
chapter_title.setTextColor(unreadColor)
manga_full_title.setTextColor(unreadColor)
title.setTextColor(unreadColor)
}
// Set chapter status

View File

@ -48,7 +48,7 @@ class RecentlyReadHolder(
val (manga, chapter, history) = item
// Set manga title
manga_full_title.text = manga.title
title.text = manga.title
// Set source + chapter title
val formattedNumber = adapter.decimalFormat.format(chapter.chapter_number.toDouble())

View File

@ -63,16 +63,6 @@ class SettingsLibraryController : SettingsController() {
preferenceCategory {
titleRes = R.string.updates
intListPreference(activity) {
key = Keys.updateOnRefresh
titleRes = R.string.categories_on_manual
entriesRes = arrayOf(
R.string.first_category, R.string.categories_in_global_update
)
entryRange = 0..1
defaultValue = -1
}
intListPreference(activity) {
key = Keys.libraryUpdateInterval
titleRes = R.string.library_update_frequency
@ -136,13 +126,6 @@ class SettingsLibraryController : SettingsController() {
summaryRes = R.string.select_order_to_update
}
switchPreference {
key = Keys.refreshCoversToo
titleRes = R.string.auto_refresh_covers
summaryRes = R.string.auto_refresh_covers_summary
defaultValue = true
}
multiSelectListPreferenceMat(activity) {
key = Keys.libraryUpdateCategories
titleRes = R.string.categories_to_include_in_global_update
@ -160,6 +143,23 @@ class SettingsLibraryController : SettingsController() {
else selectedCategories.joinToString { it.name }
}
}
intListPreference(activity) {
key = Keys.updateOnRefresh
titleRes = R.string.categories_on_manual
entriesRes = arrayOf(
R.string.first_category, R.string.categories_in_global_update
)
entryRange = 0..1
defaultValue = -1
}
switchPreference {
key = Keys.refreshCoversToo
titleRes = R.string.auto_refresh_covers
summaryRes = R.string.auto_refresh_covers_summary
defaultValue = true
}
}
if (preferences.skipPreMigration().getOrDefault() || preferences.migrationSources().getOrDefault().isNotEmpty()) {
preferenceCategory {

View File

@ -4,7 +4,6 @@
android:id="@+id/cat_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:clipToPadding="false"
android:orientation="vertical">

View File

@ -62,7 +62,7 @@
app:srcCompat="@drawable/ic_reorder_grey_24dp" />
<TextView
android:id="@+id/manga_full_title"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
@ -86,8 +86,8 @@
android:textAppearance="@style/TextAppearance.Regular.Caption"
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
android:layout_marginEnd="16dp"
app:layout_constraintStart_toStartOf="@+id/manga_full_title"
app:layout_constraintTop_toBottomOf="@+id/manga_full_title"
app:layout_constraintStart_toStartOf="@+id/title"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Chapter Title" />
<ProgressBar
@ -106,13 +106,13 @@
android:id="@+id/download_progress_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/manga_full_title"
android:layout_toEndOf="@id/title"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Regular.Caption.Hint"
app:layout_constraintBottom_toBottomOf="@+id/manga_full_title"
app:layout_constraintBottom_toBottomOf="@+id/title"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toStartOf="@+id/migration_menu"
app:layout_constraintTop_toTopOf="@+id/manga_full_title"
app:layout_constraintTop_toTopOf="@+id/title"
tools:text="(0/10)" />
<ImageView

View File

@ -23,7 +23,7 @@
</FrameLayout>
<EditText
android:id="@+id/manga_full_title"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/title"

View File

@ -29,10 +29,14 @@
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:paddingStart="4dp"
android:layout_marginStart="4dp"
android:paddingEnd="4dp"
android:paddingTop="4dp"
android:layout_marginTop="28dp"
android:background="@drawable/square_ripple"
android:layout_marginBottom="10dp"
android:paddingBottom="4dp"
android:layout_marginBottom="6dp"
android:ellipsize="end"
android:gravity="center|start"
android:inputType="none"

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/title"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:inputType="text"
android:maxLines="1"/>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/download_new"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/download_new_chapters" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/include_global"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/include_in_global_update" />
<com.google.android.material.button.MaterialButton
android:id="@+id/edit_categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Theme.Widget.Button.TextButton"
android:text="@string/edit_categories"/>
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_marginTop="6dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:textColor="?android:attr/textColorHint"
android:text="@string/tip_long_press_category"/>
</LinearLayout>

View File

@ -82,7 +82,7 @@
<TextView
android:id="@+id/manga_full_title"
android:id="@+id/title"
style="@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -110,8 +110,8 @@
android:textColor="?android:attr/textColorSecondary"
android:textIsSelectable="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/manga_full_title"
app:layout_constraintTop_toBottomOf="@+id/manga_full_title" />
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView
android:id="@+id/manga_status"
@ -121,7 +121,7 @@
android:layout_marginTop="4dp"
android:text="@string/unknown_status"
android:textIsSelectable="false"
app:layout_constraintStart_toStartOf="@id/manga_full_title"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@+id/manga_author" />
<com.google.android.material.textview.MaterialTextView
@ -134,7 +134,7 @@
android:maxLines="1"
android:textIsSelectable="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/manga_full_title"
app:layout_constraintStart_toStartOf="@id/title"
app:layout_constraintTop_toBottomOf="@id/manga_status"
tools:text="Mangadex (EN)" />

View File

@ -44,7 +44,7 @@
tools:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/manga_full_title"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@ -70,7 +70,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/download_button"
app:layout_constraintStart_toEndOf="@+id/manga_cover"
app:layout_constraintTop_toBottomOf="@+id/manga_full_title"
app:layout_constraintTop_toBottomOf="@+id/title"
tools:text="Chapter title" />
<include

View File

@ -28,7 +28,7 @@
android:padding="16dp">
<TextView
android:id="@+id/manga_full_title"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
@ -38,7 +38,7 @@
android:id="@+id/manga_source"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/manga_full_title"
android:layout_below="@id/title"
android:textAppearance="@style/TextAppearance.Medium.Body2" />
<TextView

View File

@ -78,6 +78,7 @@
<string name="already_in_category">Manga already in category</string>
<string name="add_category">Add category</string>
<string name="edit_categories">Edit categories</string>
<string name="manage_category">Manage category</string>
<string name="rename_category">Rename category</string>
<string name="move_to_categories">Move to categories</string>
<string name="hide_categories">Hide categories</string>
@ -85,8 +86,10 @@
<item quantity="one">%d category</item>
<item quantity="other">%d categories</item>
</plurals>
<string name="category_with_name_exists">A category with this name already exists!</string>
<string name="category_with_name_exists">A category with that name already exists!</string>
<string name="category_deleted">Category deleted</string>
<string name="tip_long_press_category">Tip: Press and hold a category\'s name to collapse
section</string>
<!-- Updates -->
<string name="update">Update</string>
@ -163,6 +166,7 @@
<string name="use_last_saved_migration_preferences">Use last saved pre-migration preferences
and sources to mass migrate</string>
<string name="categories_to_include_in_global_update">Categories to include in global update</string>
<string name="include_in_global_update">Include in global update</string>
<string name="auto_refresh_covers">Automatically refresh covers</string>
<string name="auto_refresh_covers_summary">Refresh covers in library as well
when updating library (overwrites local covers)</string>