Download badge
This commit is contained in:
parent
ca30fd6088
commit
d0567de4e6
@ -18,6 +18,8 @@ interface Manga : SManga {
|
||||
|
||||
var unread: Int
|
||||
|
||||
var downloadTotal: Int
|
||||
|
||||
var category: Int
|
||||
|
||||
fun setChapterOrder(order: Int) {
|
||||
|
@ -34,6 +34,8 @@ class MangaImpl : Manga {
|
||||
|
||||
@Transient override var unread: Int = 0
|
||||
|
||||
@Transient override var downloadTotal: Int = 0
|
||||
|
||||
@Transient override var category: Int = 0
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
@ -105,6 +105,8 @@ object PreferenceKeys {
|
||||
|
||||
const val defaultCategory = "default_category"
|
||||
|
||||
const val downloadBadge = "pref_display_download_badge"
|
||||
|
||||
fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId"
|
||||
|
||||
fun sourcePassword(sourceId: Long) = "pref_source_password_$sourceId"
|
||||
|
@ -141,6 +141,8 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun libraryAsList() = rxPrefs.getBoolean(Keys.libraryAsList, false)
|
||||
|
||||
fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false)
|
||||
|
||||
fun filterDownloaded() = rxPrefs.getBoolean(Keys.filterDownloaded, false)
|
||||
|
||||
fun filterUnread() = rxPrefs.getBoolean(Keys.filterUnread, false)
|
||||
|
@ -196,6 +196,7 @@ class LibraryController(
|
||||
is LibraryNavigationView.FilterGroup -> onFilterChanged()
|
||||
is LibraryNavigationView.SortGroup -> onSortChanged()
|
||||
is LibraryNavigationView.DisplayGroup -> reattachAdapter()
|
||||
is LibraryNavigationView.BadgeGroup -> onDownloadBadgeChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,6 +286,10 @@ class LibraryController(
|
||||
(activity as? AppCompatActivity)?.supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun onDownloadBadgeChanged(){
|
||||
presenter.requestDownloadBadgesUpdate()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the sorting mode is changed.
|
||||
*/
|
||||
|
@ -5,7 +5,12 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
|
||||
@ -19,7 +24,9 @@ import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
|
||||
class LibraryGridHolder(
|
||||
private val view: View,
|
||||
private val adapter: FlexibleAdapter<*>
|
||||
|
||||
) : LibraryHolder(view, adapter) {
|
||||
private val preferences: PreferencesHelper = Injekt.get()
|
||||
|
||||
/**
|
||||
* Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this
|
||||
@ -36,6 +43,15 @@ class LibraryGridHolder(
|
||||
visibility = if (manga.unread > 0) View.VISIBLE else View.GONE
|
||||
text = manga.unread.toString()
|
||||
}
|
||||
// Update the download count and its visibility.
|
||||
with(view.download_text) {
|
||||
visibility = if (manga.downloadTotal > 0 && preferences.downloadBadge().getOrDefault()) View.VISIBLE else View.GONE
|
||||
text = manga.downloadTotal.toString()
|
||||
}
|
||||
//set local visibility if its local manga
|
||||
with(view.local_text){
|
||||
visibility = if(manga.source == LocalSource.ID) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// Update the cover.
|
||||
GlideApp.with(view.context).clear(view.thumbnail)
|
||||
|
@ -5,7 +5,12 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import kotlinx.android.synthetic.main.catalogue_list_item.view.*
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
|
||||
@ -21,6 +26,7 @@ class LibraryListHolder(
|
||||
private val view: View,
|
||||
private val adapter: FlexibleAdapter<*>
|
||||
) : LibraryHolder(view, adapter) {
|
||||
private val preferences: PreferencesHelper = Injekt.get()
|
||||
|
||||
/**
|
||||
* Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this
|
||||
@ -37,6 +43,15 @@ class LibraryListHolder(
|
||||
visibility = if (manga.unread > 0) View.VISIBLE else View.GONE
|
||||
text = manga.unread.toString()
|
||||
}
|
||||
// Update the download count and its visibility.
|
||||
with(itemView.download_text) {
|
||||
visibility = if (manga.downloadTotal > 0 && preferences.downloadBadge().getOrDefault()) View.VISIBLE else View.GONE
|
||||
text = manga.downloadTotal.toString()
|
||||
}
|
||||
//show local text badge if local manga
|
||||
with(itemView.local_text) {
|
||||
visibility = if (manga.source == LocalSource.ID) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// Create thumbnail onclick to simulate long click
|
||||
itemView.thumbnail.setOnClickListener {
|
||||
@ -55,4 +70,4 @@ class LibraryListHolder(
|
||||
.into(itemView.thumbnail)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A
|
||||
/**
|
||||
* List of groups shown in the view.
|
||||
*/
|
||||
private val groups = listOf(FilterGroup(), SortGroup(), DisplayGroup())
|
||||
private val groups = listOf(FilterGroup(), SortGroup(), DisplayGroup(), BadgeGroup())
|
||||
|
||||
/**
|
||||
* Adapter instance.
|
||||
@ -166,6 +166,23 @@ class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: A
|
||||
|
||||
}
|
||||
|
||||
inner class BadgeGroup : Group {
|
||||
private val downloadBadge = Item.CheckboxGroup(R.string.action_display_download_badge, this)
|
||||
override val header = null
|
||||
override val footer= null
|
||||
override val items = listOf(downloadBadge)
|
||||
override fun initModels() {
|
||||
downloadBadge.checked = preferences.downloadBadge().getOrDefault()
|
||||
}
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
item as Item.CheckboxGroup
|
||||
item.checked = !item.checked
|
||||
preferences.downloadBadge().set((item.checked))
|
||||
adapter.notifyItemChanged(item)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display group, to show the library as a list or a grid.
|
||||
*/
|
||||
|
@ -53,6 +53,11 @@ class LibraryPresenter(
|
||||
*/
|
||||
private val filterTriggerRelay = BehaviorRelay.create(Unit)
|
||||
|
||||
/**
|
||||
* Relay used to apply the UI update to the last emission of the library.
|
||||
*/
|
||||
private val downloadTriggerRelay = BehaviorRelay.create(Unit)
|
||||
|
||||
/**
|
||||
* Relay used to apply the selected sorting method to the last emission of the library.
|
||||
*/
|
||||
@ -76,6 +81,8 @@ class LibraryPresenter(
|
||||
librarySubscription = getLibraryObservable()
|
||||
.combineLatest(filterTriggerRelay.observeOn(Schedulers.io()),
|
||||
{ lib, _ -> Pair(lib.first, applyFilters(lib.second)) })
|
||||
.combineLatest(downloadTriggerRelay.observeOn(Schedulers.io()),
|
||||
{ lib, _ -> Pair(lib.first, addDownloadTotal(lib.second)) })
|
||||
.combineLatest(sortTriggerRelay.observeOn(Schedulers.io()),
|
||||
{ lib, _ -> Pair(lib.first, applySort(lib.second)) })
|
||||
.map { Pair(it.first, it.second.mapValues { it.value.map(::LibraryItem) }) }
|
||||
@ -141,6 +148,48 @@ class LibraryPresenter(
|
||||
return map.mapValues { entry -> entry.value.filter(filterFn) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Downloaded chapter count to manga
|
||||
*
|
||||
* @param map the map to filter.
|
||||
*/
|
||||
private fun addDownloadTotal(map: Map<Int, List<Manga>>): Map<Int, List<Manga>> {
|
||||
// Cached list of downloaded manga directories given a source id.
|
||||
if (preferences.downloadBadge().getOrDefault()) {
|
||||
val mangaDirsForSource = mutableMapOf<Long, Map<String?, UniFile>>()
|
||||
|
||||
// Cached list of downloaded chapter directories for a manga.
|
||||
val chapterDirectories = mutableMapOf<Long, Int>()
|
||||
|
||||
for ((key, mangaList) in map) {
|
||||
for (manga in mangaList) {
|
||||
manga.downloadTotal = getDownloadedCountFromDirectory(manga, mangaDirsForSource, chapterDirectories)
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
//Get count of downloaded chapters for a manga
|
||||
fun getDownloadedCountFromDirectory(manga: Manga, mangaDirsForSource: MutableMap<Long, Map<String?, UniFile>>, chapterDirectories: MutableMap<Long, Int>): Int {
|
||||
val source = sourceManager.get(manga.source) ?: return 0;
|
||||
// Get the directories for the source of the manga.
|
||||
val dirsForSource = mangaDirsForSource.getOrPut(source.id) {
|
||||
val sourceDir = downloadManager.findSourceDir(source)
|
||||
sourceDir?.listFiles()?.associateBy { it.name }.orEmpty()
|
||||
}
|
||||
val mangaDirName = downloadManager.getMangaDirName(manga)
|
||||
val mangaDir = dirsForSource[mangaDirName] ?: return 0
|
||||
|
||||
chapterDirectories.getOrPut(manga.id!!) {
|
||||
if (mangaDir.listFiles()?.isNotEmpty() ?: false) {
|
||||
return mangaDir.listFiles()!!.size
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies library sorting to the given map of manga.
|
||||
*
|
||||
@ -236,6 +285,13 @@ class LibraryPresenter(
|
||||
filterTriggerRelay.call(Unit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the library to have download badges added.
|
||||
*/
|
||||
fun requestDownloadBadgesUpdate() {
|
||||
downloadTriggerRelay.call(Unit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the library to be sorted.
|
||||
*/
|
||||
|
@ -29,17 +29,63 @@
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@drawable/gradient_shape"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/unread_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorAccent"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:visibility="gone"/>
|
||||
tools:layout_editor_absoluteY="7dp"
|
||||
tools:layout_editor_absoluteX="7dp">
|
||||
<TextView
|
||||
android:id="@+id/unread_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorAccentDark"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="120"
|
||||
app:layout_constraintLeft_toRightOf="@+id/download_text"
|
||||
android:layout_marginLeft="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="4dp"/>
|
||||
<TextView
|
||||
android:id="@+id/download_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/md_red_500"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="120"
|
||||
app:layout_constraintLeft_toRightOf="@+id/local_text"
|
||||
android:layout_marginLeft="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="4dp"/>
|
||||
<TextView
|
||||
android:id="@+id/local_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/md_teal_500"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:text="@string/local_source_badge"
|
||||
android:layout_marginLeft="4dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="4dp"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<eu.kanade.tachiyomi.widget.PTSansTextView
|
||||
android:id="@+id/title"
|
||||
|
@ -1,56 +1,112 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||
android:background="?attr/selectable_list_drawable">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingLeft="@dimen/material_component_lists_icon_left_padding"
|
||||
android:paddingRight="0dp"
|
||||
android:paddingStart="@dimen/material_component_lists_icon_left_padding"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:background="?attr/selectable_list_drawable"
|
||||
tools:layout_editor_absoluteY="25dp"
|
||||
tools:layout_editor_absoluteX="0dp">
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||
android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:src="@mipmap/ic_launcher"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_marginLeft="8dp"/>
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/material_component_lists_text_left_padding"
|
||||
android:paddingStart="@dimen/material_component_lists_text_left_padding"
|
||||
android:paddingRight="@dimen/material_component_lists_right_padding"
|
||||
android:paddingEnd="@dimen/material_component_lists_right_padding">
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
tools:text="Manga title"
|
||||
android:layout_marginStart="8dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintLeft_toRightOf="@+id/thumbnail"
|
||||
android:layout_marginLeft="8dp"
|
||||
app:layout_constraintRight_toLeftOf="@+id/local_text"
|
||||
android:layout_marginRight="8dp"
|
||||
app:layout_constraintVertical_bias="0.523"
|
||||
app:layout_constraintHorizontal_bias="0.007"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/unread_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Hint"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="@color/colorAccentLight"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.Regular.Caption.Hint"
|
||||
android:visibility="gone"
|
||||
tools:text="22"/>
|
||||
tools:text="130"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
app:layout_constraintRight_toRightOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_toLeftOf="@id/unread_text"
|
||||
android:layout_toStartOf="@id/unread_text"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/download_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/md_red_500"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toStartOf="@+id/unread_text"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
tools:text="Manga title"/>
|
||||
android:visibility="gone"
|
||||
tools:text="122"
|
||||
tools:visibility="visible"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintRight_toLeftOf="@+id/unread_text"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
<TextView
|
||||
android:id="@+id/local_text"
|
||||
style="@style/TextAppearance.Regular.Caption.Light"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/md_teal_500"
|
||||
android:paddingBottom="1dp"
|
||||
android:paddingLeft="3dp"
|
||||
android:paddingRight="3dp"
|
||||
android:paddingTop="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:maxLines="1"
|
||||
android:text="@string/local_source_badge"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintRight_toLeftOf="@+id/download_text"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</FrameLayout>
|
@ -78,4 +78,6 @@
|
||||
|
||||
<color name="md_red_500">#F44336</color>
|
||||
|
||||
<color name="md_teal_500">#009688</color>
|
||||
|
||||
</resources>
|
@ -21,6 +21,7 @@
|
||||
<string name="label_selected">Selected: %1$d</string>
|
||||
<string name="label_backup">Backup</string>
|
||||
|
||||
|
||||
<!-- Actions -->
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="action_filter">Filter</string>
|
||||
@ -74,6 +75,7 @@
|
||||
<string name="action_display">Display</string>
|
||||
<string name="action_display_grid">Grid</string>
|
||||
<string name="action_display_list">List</string>
|
||||
<string name="action_display_download_badge">Download Badges</string>
|
||||
<string name="action_set_filter">Set filter</string>
|
||||
<string name="action_cancel">Cancel</string>
|
||||
<string name="action_sort">Sort</string>
|
||||
@ -270,6 +272,7 @@
|
||||
<!-- Library fragment -->
|
||||
<string name="library_search_hint">Title or author…</string>
|
||||
<string name="updating_category">Updating category</string>
|
||||
<string name="local_source_badge">Local</string>
|
||||
<string name="confirm_delete_manga">Are you sure you want to remove selected manga?</string>
|
||||
<string name="also_delete_chapters">Also delete downloaded chapters</string>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user