Kissmanga loading through Cloudflare. A lot of refactoring was needed

This commit is contained in:
len
2016-05-10 15:09:44 +02:00
parent 8da11dbdb9
commit 6e8a41f898
42 changed files with 753 additions and 524 deletions

View File

@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.catalogue
import android.view.View
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl
import eu.kanade.tachiyomi.data.database.models.Manga
import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
@@ -42,20 +41,16 @@ class CatalogueGridHolder(private val view: View, private val adapter: Catalogue
* @param manga the manga to bind.
*/
fun setImage(manga: Manga) {
Glide.clear(view.thumbnail)
if (!manga.thumbnail_url.isNullOrEmpty()) {
val url = manga.thumbnail_url!!
val headers = adapter.fragment.presenter.source.glideHeaders
Glide.with(view.context)
.load(if (headers != null) GlideUrl(url, headers) else url)
.load(manga)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.centerCrop()
.skipMemoryCache(true)
.placeholder(android.R.color.transparent)
.into(view.thumbnail)
} else {
Glide.clear(view.thumbnail)
}
}
}

View File

@@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.catalogue
import android.os.Bundle
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -38,6 +39,11 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
*/
@Inject lateinit var prefs: PreferencesHelper
/**
* Cover cache.
*/
@Inject lateinit var coverCache: CoverCache
/**
* Enabled sources.
*/
@@ -335,6 +341,9 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
*/
fun changeMangaFavorite(manga: Manga) {
manga.favorite = !manga.favorite
if (!manga.favorite) {
coverCache.deleteFromCache(manga.thumbnail_url)
}
db.insertManga(manga).executeAsBlocking()
}

View File

@@ -98,10 +98,9 @@ class LibraryCategoryAdapter(val fragment: LibraryCategoryFragment) :
* @param position the position to bind.
*/
override fun onBindViewHolder(holder: LibraryHolder, position: Int) {
val presenter = (fragment.parentFragment as LibraryFragment).presenter
val manga = getItem(position)
holder.onSetValues(manga, presenter)
holder.onSetValues(manga)
//When user scrolls this bind the correct selection status
holder.itemView.isActivated = isSelected(position)
}

View File

@@ -12,7 +12,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.event.LibraryMangaEvent
import eu.kanade.tachiyomi.ui.library.LibraryMangaEvent
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment
import eu.kanade.tachiyomi.ui.manga.MangaActivity

View File

@@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.event.LibraryMangaEvent
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
import eu.kanade.tachiyomi.ui.category.CategoryActivity
import eu.kanade.tachiyomi.ui.main.MainActivity
@@ -388,7 +387,10 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
* @param mangas the manga list to move.
*/
private fun moveMangasToCategories(mangas: List<Manga>) {
val categories = presenter.categories
// Hide the default category because it has a different behavior than the ones from db.
val categories = presenter.categories.filter { it.id != 0 }
// Get indexes of the common categories to preselect.
val commonCategoriesIndexes = presenter.getCommonCategories(mangas)
.map { categories.indexOf(it) }
.toTypedArray()
@@ -397,7 +399,8 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
.title(R.string.action_move_category)
.items(categories.map { it.name })
.itemsCallbackMultiChoice(commonCategoriesIndexes) { dialog, positions, text ->
presenter.moveMangasToCategories(positions, mangas)
val selectedCategories = positions.map { categories[it] }
presenter.moveMangasToCategories(selectedCategories, mangas)
destroyActionModeIfNeeded()
true
}

View File

@@ -3,10 +3,7 @@ package eu.kanade.tachiyomi.ui.library
import android.view.View
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.signature.StringSignature
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder
import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
@@ -19,8 +16,10 @@ import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
* @param listener a listener to react to single tap and long tap events.
* @constructor creates a new library holder.
*/
class LibraryHolder(private val view: View, private val adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) :
FlexibleViewHolder(view, adapter, listener) {
class LibraryHolder(private val view: View,
private val adapter: LibraryCategoryAdapter,
listener: FlexibleViewHolder.OnListItemClickListener)
: FlexibleViewHolder(view, adapter, listener) {
private var manga: Manga? = null
@@ -29,9 +28,8 @@ class LibraryHolder(private val view: View, private val adapter: LibraryCategory
* holder with the given manga.
*
* @param manga the manga to bind.
* @param presenter the library presenter.
*/
fun onSetValues(manga: Manga, presenter: LibraryPresenter) {
fun onSetValues(manga: Manga) {
this.manga = manga
// Update the title of the manga.
@@ -44,31 +42,13 @@ class LibraryHolder(private val view: View, private val adapter: LibraryCategory
}
// Update the cover.
loadCover(manga, presenter.sourceManager.get(manga.source)!!, presenter.coverCache)
}
/**
* Load the cover of a manga in a image view.
*
* @param manga the manga to bind.
* @param source the source of the manga.
* @param coverCache the cache that stores the cover in the filesystem.
*/
private fun loadCover(manga: Manga, source: Source, coverCache: CoverCache) {
Glide.clear(view.thumbnail)
if (!manga.thumbnail_url.isNullOrEmpty()) {
coverCache.saveOrLoadFromCache(manga.thumbnail_url, source.glideHeaders) {
if (adapter.fragment.isResumed && this.manga == manga) {
Glide.with(view.context)
.load(it)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.signature(StringSignature(it.lastModified().toString()))
.placeholder(android.R.color.transparent)
.into(itemView.thumbnail)
}
}
}
Glide.with(view.context)
.load(manga)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.placeholder(android.R.color.transparent)
.into(view.thumbnail)
}
}

View File

@@ -0,0 +1,11 @@
package eu.kanade.tachiyomi.ui.library
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
class LibraryMangaEvent(val mangas: Map<Int, List<Manga>>) {
fun getMangaForCategory(category: Category): List<Manga>? {
return mangas[category.id]
}
}

View File

@@ -11,10 +11,10 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.event.LibraryMangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.subjects.BehaviorSubject
import java.io.IOException
import java.io.InputStream
@@ -236,26 +236,18 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
* Remove the selected manga from the library.
*/
fun deleteMangas() {
for (manga in selectedMangas) {
manga.favorite = false
}
// Create a set of the list
val mangaToDelete = selectedMangas.toSet()
db.insertMangas(selectedMangas).executeAsBlocking()
}
/**
* Move the given list of manga to categories.
*
* @param positions the indexes of the selected categories.
* @param mangas the list of manga to move.
*/
fun moveMangasToCategories(positions: Array<Int>, mangas: List<Manga>) {
val categoriesToAdd = ArrayList<Category>()
for (index in positions) {
categoriesToAdd.add(categories[index])
}
moveMangasToCategories(categoriesToAdd, mangas)
Observable.from(mangaToDelete)
.subscribeOn(Schedulers.io())
.doOnNext {
it.favorite = false
coverCache.deleteFromCache(it.thumbnail_url)
}
.toList()
.flatMap { db.insertMangas(it).asRxObservable() }
.subscribe()
}
/**

View File

@@ -8,7 +8,7 @@ import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.manga.MangaEvent
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersFragment
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoFragment

View File

@@ -0,0 +1,5 @@
package eu.kanade.tachiyomi.ui.manga
import eu.kanade.tachiyomi.data.database.models.Manga
class MangaEvent(val manga: Manga)

View File

@@ -4,8 +4,8 @@ import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.event.ChapterCountEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.manga.info.ChapterCountEvent
import eu.kanade.tachiyomi.ui.manga.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.SharedData
import rx.Observable

View File

@@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.event.ChapterCountEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.manga.info.ChapterCountEvent
import eu.kanade.tachiyomi.ui.manga.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.SharedData
import rx.Observable

View File

@@ -0,0 +1,16 @@
package eu.kanade.tachiyomi.ui.manga.info
import rx.Observable
import rx.subjects.BehaviorSubject
class ChapterCountEvent() {
private val subject = BehaviorSubject.create<Int>()
val observable: Observable<Int>
get() = subject
fun emit(count: Int) {
subject.onNext(count)
}
}

View File

@@ -6,8 +6,6 @@ import android.os.Bundle
import android.view.*
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.signature.StringSignature
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.source.base.Source
@@ -112,45 +110,19 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
// Set the favorite drawable to the correct one.
setFavoriteDrawable(manga.favorite)
// Initialize CoverCache and Glide headers to retrieve cover information.
val coverCache = presenter.coverCache
val headers = presenter.source.glideHeaders
// Set cover if it wasn't already.
if (manga_cover.drawable == null) {
manga.thumbnail_url?.let { url ->
if (manga.favorite) {
coverCache.saveOrLoadFromCache(url, headers) {
if (isResumed) {
Glide.with(context)
.load(it)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.signature(StringSignature(it.lastModified().toString()))
.into(manga_cover)
if (manga_cover.drawable == null && !manga.thumbnail_url.isNullOrEmpty()) {
Glide.with(context)
.load(manga)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.into(manga_cover)
Glide.with(context)
.load(it)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.signature(StringSignature(it.lastModified().toString()))
.into(backdrop)
}
}
} else {
Glide.with(context)
.load(if (headers != null) GlideUrl(url, headers) else url)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.centerCrop()
.into(manga_cover)
Glide.with(context)
.load(if (headers != null) GlideUrl(url, headers) else url)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.centerCrop()
.into(backdrop)
}
}
Glide.with(context)
.load(manga)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.into(backdrop)
}
}

View File

@@ -6,9 +6,8 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.event.ChapterCountEvent
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.manga.MangaEvent
import eu.kanade.tachiyomi.util.SharedData
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
@@ -116,22 +115,11 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
*/
fun toggleFavorite() {
manga.favorite = !manga.favorite
onMangaFavoriteChange(manga.favorite)
db.insertManga(manga).executeAsBlocking()
refreshManga()
}
/**
* (Removes / Saves) cover depending on favorite status.
*
* @param isFavorite determines if manga is favorite or not.
*/
private fun onMangaFavoriteChange(isFavorite: Boolean) {
if (isFavorite) {
coverCache.save(manga.thumbnail_url, source.glideHeaders)
} else {
if (!manga.favorite) {
coverCache.deleteFromCache(manga.thumbnail_url)
}
db.insertManga(manga).executeAsBlocking()
refreshManga()
}
/**

View File

@@ -7,7 +7,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaSync
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.event.MangaEvent
import eu.kanade.tachiyomi.ui.manga.MangaEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.SharedData
import eu.kanade.tachiyomi.util.toast

View File

@@ -21,7 +21,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.event.ReaderEvent
import eu.kanade.tachiyomi.ui.reader.ReaderEvent
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
import eu.kanade.tachiyomi.ui.base.listener.SimpleAnimationListener
import eu.kanade.tachiyomi.ui.base.listener.SimpleSeekBarListener

View File

@@ -0,0 +1,6 @@
package eu.kanade.tachiyomi.ui.reader
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
class ReaderEvent(val manga: Manga, val chapter: Chapter)

View File

@@ -15,7 +15,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.event.ReaderEvent
import eu.kanade.tachiyomi.ui.reader.ReaderEvent
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.SharedData
import rx.Observable

View File

@@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
@@ -20,6 +21,7 @@ class SettingsActivity : BaseActivity() {
@Inject lateinit var db: DatabaseHelper
@Inject lateinit var sourceManager: SourceManager
@Inject lateinit var syncManager: MangaSyncManager
@Inject lateinit var networkHelper: NetworkHelper
override fun onCreate(savedState: Bundle?) {
setAppTheme()

View File

@@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.ui.setting
import android.os.Bundle
import android.support.v7.preference.Preference
import android.view.View
import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
@@ -16,8 +15,6 @@ import java.util.concurrent.atomic.AtomicInteger
class SettingsAdvancedFragment : SettingsNestedFragment() {
private var clearCacheSubscription: Subscription? = null
companion object {
fun newInstance(resourcePreference: Int, resourceTitle: Int): SettingsNestedFragment {
@@ -27,17 +24,28 @@ class SettingsAdvancedFragment : SettingsNestedFragment() {
}
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
val clearCache = findPreference(getString(R.string.pref_clear_chapter_cache_key))
val clearDatabase = findPreference(getString(R.string.pref_clear_database_key))
private val clearCache by lazy { findPreference(getString(R.string.pref_clear_chapter_cache_key)) }
clearCache.setOnPreferenceClickListener { preference ->
clearChapterCache(preference)
private val clearDatabase by lazy { findPreference(getString(R.string.pref_clear_database_key)) }
private val clearCookies by lazy { findPreference(getString(R.string.pref_clear_cookies_key)) }
private var clearCacheSubscription: Subscription? = null
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
clearCache.setOnPreferenceClickListener {
clearChapterCache()
true
}
clearCache.summary = getString(R.string.used_cache, chapterCache.readableSize)
clearDatabase.setOnPreferenceClickListener { preference ->
clearCookies.setOnPreferenceClickListener {
settingsActivity.networkHelper.cookies.removeAll()
activity.toast(R.string.cookies_cleared)
true
}
clearDatabase.setOnPreferenceClickListener {
clearDatabase()
true
}
@@ -48,7 +56,7 @@ class SettingsAdvancedFragment : SettingsNestedFragment() {
super.onDestroyView()
}
private fun clearChapterCache(preference: Preference) {
private fun clearChapterCache() {
val deletedFiles = AtomicInteger()
val files = chapterCache.cacheDir.listFiles()
@@ -78,7 +86,7 @@ class SettingsAdvancedFragment : SettingsNestedFragment() {
}, {
dialog.dismiss()
activity.toast(getString(R.string.cache_deleted, deletedFiles.get()))
preference.summary = getString(R.string.used_cache, chapterCache.readableSize)
clearCache.summary = getString(R.string.used_cache, chapterCache.readableSize)
})
}
@@ -87,7 +95,10 @@ class SettingsAdvancedFragment : SettingsNestedFragment() {
.content(R.string.clear_database_confirmation)
.positiveText(android.R.string.yes)
.negativeText(android.R.string.no)
.onPositive { dialog, which -> db.deleteMangasNotInLibrary().executeAsBlocking() }
.onPositive { dialog, which ->
db.deleteMangasNotInLibrary().executeAsBlocking()
activity.toast(R.string.clear_database_completed)
}
.show()
}