Download badge

This commit is contained in:
inorichi
2017-10-21 17:08:49 +02:00
parent ca30fd6088
commit d0567de4e6
13 changed files with 269 additions and 45 deletions

View File

@ -18,6 +18,8 @@ interface Manga : SManga {
var unread: Int
var downloadTotal: Int
var category: Int
fun setChapterOrder(order: Int) {

View File

@ -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 {

View File

@ -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"

View File

@ -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)

View File

@ -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.
*/

View File

@ -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)

View File

@ -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)
}
}
}

View File

@ -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.
*/

View File

@ -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.
*/