Linting fixes
This commit is contained in:
@@ -35,10 +35,12 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaController : RxController<MangaControllerBinding>, TabbedController {
|
||||
|
||||
constructor(manga: Manga?, fromSource: Boolean = false) : super(Bundle().apply {
|
||||
putLong(MANGA_EXTRA, manga?.id ?: 0)
|
||||
putBoolean(FROM_SOURCE_EXTRA, fromSource)
|
||||
}) {
|
||||
constructor(manga: Manga?, fromSource: Boolean = false) : super(
|
||||
Bundle().apply {
|
||||
putLong(MANGA_EXTRA, manga?.id ?: 0)
|
||||
putBoolean(FROM_SOURCE_EXTRA, fromSource)
|
||||
}
|
||||
) {
|
||||
this.manga = manga
|
||||
if (manga != null) {
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source)
|
||||
@@ -46,7 +48,8 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
|
||||
}
|
||||
|
||||
constructor(mangaId: Long) : this(
|
||||
Injekt.get<DatabaseHelper>().getManga(mangaId).executeAsBlocking())
|
||||
Injekt.get<DatabaseHelper>().getManga(mangaId).executeAsBlocking()
|
||||
)
|
||||
|
||||
@Suppress("unused")
|
||||
constructor(bundle: Bundle) : this(bundle.getLong(MANGA_EXTRA))
|
||||
@@ -87,8 +90,9 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
|
||||
binding.mangaPager.offscreenPageLimit = 3
|
||||
binding.mangaPager.adapter = adapter
|
||||
|
||||
if (!fromSource)
|
||||
if (!fromSource) {
|
||||
binding.mangaPager.currentItem = CHAPTERS_CONTROLLER
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
@@ -130,9 +134,11 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
|
||||
|
||||
private fun setTrackingIconInternal(visible: Boolean) {
|
||||
val tab = activity?.tabs?.getTabAt(TRACK_CONTROLLER) ?: return
|
||||
val drawable = if (visible)
|
||||
val drawable = if (visible) {
|
||||
VectorDrawableCompat.create(resources!!, R.drawable.ic_done_white_18dp, null)
|
||||
else null
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
tab.icon = drawable
|
||||
}
|
||||
@@ -142,10 +148,11 @@ class MangaController : RxController<MangaControllerBinding>, TabbedController {
|
||||
private val tabCount = if (Injekt.get<TrackManager>().hasLoggedServices()) 3 else 2
|
||||
|
||||
private val tabTitles = listOf(
|
||||
R.string.manga_detail_tab,
|
||||
R.string.manga_chapters_tab,
|
||||
R.string.manga_tracking_tab)
|
||||
.map { resources!!.getString(it) }
|
||||
R.string.manga_detail_tab,
|
||||
R.string.manga_chapters_tab,
|
||||
R.string.manga_tracking_tab
|
||||
)
|
||||
.map { resources!!.getString(it) }
|
||||
|
||||
override fun getCount(): Int {
|
||||
return tabCount
|
||||
|
||||
@@ -10,8 +10,9 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) : AbstractFlexibleItem<ChapterHolder>(),
|
||||
Chapter by chapter {
|
||||
class ChapterItem(val chapter: Chapter, val manga: Manga) :
|
||||
AbstractFlexibleItem<ChapterHolder>(),
|
||||
Chapter by chapter {
|
||||
|
||||
private var _status: Int = 0
|
||||
|
||||
|
||||
@@ -26,8 +26,11 @@ class ChaptersAdapter(
|
||||
|
||||
val bookmarkedColor = context.getResourceColor(R.attr.colorAccent)
|
||||
|
||||
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
|
||||
.apply { decimalSeparator = '.' })
|
||||
val decimalFormat = DecimalFormat(
|
||||
"#.###",
|
||||
DecimalFormatSymbols()
|
||||
.apply { decimalSeparator = '.' }
|
||||
)
|
||||
|
||||
val dateFormat: DateFormat = preferences.dateFormat().getOrDefault()
|
||||
|
||||
|
||||
@@ -39,12 +39,13 @@ import reactivecircus.flowbinding.android.view.clicks
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import timber.log.Timber
|
||||
|
||||
class ChaptersController : NucleusController<ChaptersControllerBinding, ChaptersPresenter>(),
|
||||
ActionMode.Callback,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
DownloadCustomChaptersDialog.Listener,
|
||||
DeleteChaptersDialog.Listener {
|
||||
class ChaptersController :
|
||||
NucleusController<ChaptersControllerBinding, ChaptersPresenter>(),
|
||||
ActionMode.Callback,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
DownloadCustomChaptersDialog.Listener,
|
||||
DeleteChaptersDialog.Listener {
|
||||
|
||||
/**
|
||||
* Adapter containing a list of chapters.
|
||||
@@ -168,11 +169,13 @@ class ChaptersController : NucleusController<ChaptersControllerBinding, Chapters
|
||||
menuFilterEmpty.isVisible = filterSet
|
||||
|
||||
// Disable unread filter option if read filter is enabled.
|
||||
if (presenter.onlyRead())
|
||||
if (presenter.onlyRead()) {
|
||||
menuFilterUnread.isEnabled = false
|
||||
}
|
||||
// Disable read filter option if unread filter is enabled.
|
||||
if (presenter.onlyUnread())
|
||||
if (presenter.onlyUnread()) {
|
||||
menuFilterRead.isEnabled = false
|
||||
}
|
||||
|
||||
// Display mode submenu
|
||||
if (presenter.manga.displayMode == Manga.DISPLAY_NAME) {
|
||||
@@ -320,10 +323,12 @@ class ChaptersController : NucleusController<ChaptersControllerBinding, Chapters
|
||||
createActionModeIfNeeded()
|
||||
when {
|
||||
lastClickPosition == -1 -> setSelection(position)
|
||||
lastClickPosition > position -> for (i in position until lastClickPosition)
|
||||
setSelection(i)
|
||||
lastClickPosition < position -> for (i in lastClickPosition + 1..position)
|
||||
setSelection(i)
|
||||
lastClickPosition > position ->
|
||||
for (i in position until lastClickPosition)
|
||||
setSelection(i)
|
||||
lastClickPosition < position ->
|
||||
for (i in lastClickPosition + 1..position)
|
||||
setSelection(i)
|
||||
else -> setSelection(position)
|
||||
}
|
||||
lastClickPosition = position
|
||||
@@ -364,8 +369,8 @@ class ChaptersController : NucleusController<ChaptersControllerBinding, Chapters
|
||||
if (actionMode == null) {
|
||||
actionMode = (activity as? AppCompatActivity)?.startSupportActionMode(this)
|
||||
binding.actionToolbar.show(
|
||||
actionMode!!,
|
||||
R.menu.chapter_selection
|
||||
actionMode!!,
|
||||
R.menu.chapter_selection
|
||||
) { onActionItemClicked(actionMode!!, it!!) }
|
||||
}
|
||||
}
|
||||
@@ -526,9 +531,9 @@ class ChaptersController : NucleusController<ChaptersControllerBinding, Chapters
|
||||
}
|
||||
|
||||
private fun getUnreadChaptersSorted() = presenter.chapters
|
||||
.filter { !it.read && it.status == Download.NOT_DOWNLOADED }
|
||||
.distinctBy { it.name }
|
||||
.sortedByDescending { it.source_order }
|
||||
.filter { !it.read && it.status == Download.NOT_DOWNLOADED }
|
||||
.distinctBy { it.name }
|
||||
.sortedByDescending { it.source_order }
|
||||
|
||||
private fun downloadChapters(choice: Int) {
|
||||
val chaptersToDownload = when (choice) {
|
||||
|
||||
@@ -43,7 +43,7 @@ class ChaptersPresenter(
|
||||
* Subject of list of chapters to allow updating the view without going to DB.
|
||||
*/
|
||||
val chaptersRelay: PublishRelay<List<ChapterItem>>
|
||||
by lazy { PublishRelay.create<List<ChapterItem>>() }
|
||||
by lazy { PublishRelay.create<List<ChapterItem>>() }
|
||||
|
||||
/**
|
||||
* Whether the chapter list has been requested to the source.
|
||||
@@ -66,12 +66,13 @@ class ChaptersPresenter(
|
||||
|
||||
// Prepare the relay.
|
||||
chaptersRelay.flatMap { applyChapterFilters(it) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(ChaptersController::onNextChapters) { _, error -> Timber.e(error) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(ChaptersController::onNextChapters) { _, error -> Timber.e(error) }
|
||||
|
||||
// Add the subscription that retrieves the chapters from the database, keeps subscribed to
|
||||
// changes, and sends the list of chapters to the relay.
|
||||
add(db.getChapters(manga).asRxObservable()
|
||||
add(
|
||||
db.getChapters(manga).asRxObservable()
|
||||
.map { chapters ->
|
||||
// Convert every chapter to a model.
|
||||
chapters.map { it.toModel() }
|
||||
@@ -86,18 +87,19 @@ class ChaptersPresenter(
|
||||
// Listen for download status changes
|
||||
observeDownloads()
|
||||
}
|
||||
.subscribe { chaptersRelay.call(it) })
|
||||
.subscribe { chaptersRelay.call(it) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun observeDownloads() {
|
||||
observeDownloadsSubscription?.let { remove(it) }
|
||||
observeDownloadsSubscription = downloadManager.queue.getStatusObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.filter { download -> download.manga.id == manga.id }
|
||||
.doOnNext { onDownloadStatusChange(it) }
|
||||
.subscribeLatestCache(ChaptersController::onChapterStatusChange) { _, error ->
|
||||
Timber.e(error)
|
||||
}
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.filter { download -> download.manga.id == manga.id }
|
||||
.doOnNext { onDownloadStatusChange(it) }
|
||||
.subscribeLatestCache(ChaptersController::onChapterStatusChange) { _, error ->
|
||||
Timber.e(error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,12 +140,15 @@ class ChaptersPresenter(
|
||||
|
||||
if (!fetchChaptersSubscription.isNullOrUnsubscribed()) return
|
||||
fetchChaptersSubscription = Observable.defer { source.fetchChapterList(manga) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { syncChaptersWithSource(db, it, manga, source) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst({ view, _ ->
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { syncChaptersWithSource(db, it, manga, source) }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst(
|
||||
{ view, _ ->
|
||||
view.onFetchChaptersDone()
|
||||
}, ChaptersController::onFetchChaptersError)
|
||||
},
|
||||
ChaptersController::onFetchChaptersError
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,8 +205,9 @@ class ChaptersPresenter(
|
||||
}
|
||||
|
||||
// Force UI update if downloaded filter active and download finished.
|
||||
if (onlyDownloaded() && download.status == Download.DOWNLOADED)
|
||||
if (onlyDownloaded() && download.status == Download.DOWNLOADED) {
|
||||
refreshChapters()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,16 +224,16 @@ class ChaptersPresenter(
|
||||
*/
|
||||
fun markChaptersRead(selectedChapters: List<ChapterItem>, read: Boolean) {
|
||||
Observable.from(selectedChapters)
|
||||
.doOnNext { chapter ->
|
||||
chapter.read = read
|
||||
if (!read) {
|
||||
chapter.last_page_read = 0
|
||||
}
|
||||
.doOnNext { chapter ->
|
||||
chapter.read = read
|
||||
if (!read) {
|
||||
chapter.last_page_read = 0
|
||||
}
|
||||
.toList()
|
||||
.flatMap { db.updateChaptersProgress(it).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
}
|
||||
.toList()
|
||||
.flatMap { db.updateChaptersProgress(it).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,13 +250,13 @@ class ChaptersPresenter(
|
||||
*/
|
||||
fun bookmarkChapters(selectedChapters: List<ChapterItem>, bookmarked: Boolean) {
|
||||
Observable.from(selectedChapters)
|
||||
.doOnNext { chapter ->
|
||||
chapter.bookmark = bookmarked
|
||||
}
|
||||
.toList()
|
||||
.flatMap { db.updateChaptersProgress(it).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
.doOnNext { chapter ->
|
||||
chapter.bookmark = bookmarked
|
||||
}
|
||||
.toList()
|
||||
.flatMap { db.updateChaptersProgress(it).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,13 +265,16 @@ class ChaptersPresenter(
|
||||
*/
|
||||
fun deleteChapters(chapters: List<ChapterItem>) {
|
||||
Observable.just(chapters)
|
||||
.doOnNext { deleteChaptersInternal(chapters) }
|
||||
.doOnNext { if (onlyDownloaded()) refreshChapters() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst({ view, _ ->
|
||||
.doOnNext { deleteChaptersInternal(chapters) }
|
||||
.doOnNext { if (onlyDownloaded()) refreshChapters() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst(
|
||||
{ view, _ ->
|
||||
view.onChaptersDeleted(chapters)
|
||||
}, ChaptersController::onChaptersDeletedError)
|
||||
},
|
||||
ChaptersController::onChaptersDeletedError
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,11 +16,11 @@ class DeleteChaptersDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.message(R.string.confirm_delete_chapters)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
(targetController as? Listener)?.deleteChapters()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.message(R.string.confirm_delete_chapters)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
(targetController as? Listener)?.deleteChapters()
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
||||
+12
-10
@@ -24,10 +24,12 @@ class DownloadCustomChaptersDialog<T> : DialogController
|
||||
* Initialize dialog.
|
||||
* @param maxChapters maximal number of chapters that user can download.
|
||||
*/
|
||||
constructor(target: T, maxChapters: Int) : super(Bundle().apply {
|
||||
// Add maximum number of chapters to download value to bundle.
|
||||
putInt(KEY_ITEM_MAX, maxChapters)
|
||||
}) {
|
||||
constructor(target: T, maxChapters: Int) : super(
|
||||
Bundle().apply {
|
||||
// Add maximum number of chapters to download value to bundle.
|
||||
putInt(KEY_ITEM_MAX, maxChapters)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.maxChapters = maxChapters
|
||||
}
|
||||
@@ -57,12 +59,12 @@ class DownloadCustomChaptersDialog<T> : DialogController
|
||||
// Build dialog.
|
||||
// when positive dialog is pressed call custom listener.
|
||||
return MaterialDialog(activity)
|
||||
.title(R.string.custom_download)
|
||||
.customView(view = view, scrollable = true)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
(targetController as? Listener)?.downloadCustomChapters(view.amount)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.title(R.string.custom_download)
|
||||
.customView(view = view, scrollable = true)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
(targetController as? Listener)?.downloadCustomChapters(view.amount)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
||||
@@ -31,7 +31,7 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||
import eu.kanade.tachiyomi.ui.source.browse.BrowseSourceController
|
||||
import eu.kanade.tachiyomi.ui.source.global_search.GlobalSearchController
|
||||
import eu.kanade.tachiyomi.ui.source.globalsearch.GlobalSearchController
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.lang.truncateCenter
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
@@ -217,12 +217,14 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
}
|
||||
|
||||
// Update status TextView.
|
||||
binding.mangaStatus.setText(when (manga.status) {
|
||||
SManga.ONGOING -> R.string.ongoing
|
||||
SManga.COMPLETED -> R.string.completed
|
||||
SManga.LICENSED -> R.string.licensed
|
||||
else -> R.string.unknown
|
||||
})
|
||||
binding.mangaStatus.setText(
|
||||
when (manga.status) {
|
||||
SManga.ONGOING -> R.string.ongoing
|
||||
SManga.COMPLETED -> R.string.completed
|
||||
SManga.LICENSED -> R.string.licensed
|
||||
else -> R.string.unknown
|
||||
}
|
||||
)
|
||||
|
||||
// Set the favorite drawable to the correct one.
|
||||
setFavoriteButtonState(manga.favorite)
|
||||
@@ -233,16 +235,16 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
val mangaThumbnail = manga.toMangaThumbnail()
|
||||
|
||||
GlideApp.with(view.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(binding.mangaCover)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(binding.mangaCover)
|
||||
|
||||
GlideApp.with(view.context)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(binding.backdrop)
|
||||
.load(mangaThumbnail)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(binding.backdrop)
|
||||
}
|
||||
|
||||
// Manga info section
|
||||
@@ -291,23 +293,26 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
val isExpanded = binding.mangaInfoToggle.text == context.getString(R.string.manga_info_collapse)
|
||||
|
||||
binding.mangaInfoToggle.text =
|
||||
if (isExpanded)
|
||||
if (isExpanded) {
|
||||
context.getString(R.string.manga_info_expand)
|
||||
else
|
||||
} else {
|
||||
context.getString(R.string.manga_info_collapse)
|
||||
}
|
||||
|
||||
with(binding.mangaSummary) {
|
||||
maxLines =
|
||||
if (isExpanded)
|
||||
if (isExpanded) {
|
||||
3
|
||||
else
|
||||
} else {
|
||||
Int.MAX_VALUE
|
||||
}
|
||||
|
||||
ellipsize =
|
||||
if (isExpanded)
|
||||
if (isExpanded) {
|
||||
TextUtils.TruncateAt.END
|
||||
else
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
binding.mangaGenresTagsCompact.visibleIf { isExpanded }
|
||||
@@ -447,7 +452,7 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
}.toTypedArray()
|
||||
|
||||
ChangeMangaCategoriesDialog(this, listOf(manga), categories, preselected)
|
||||
.showDialog(router)
|
||||
.showDialog(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,7 +468,7 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
}.toTypedArray()
|
||||
|
||||
ChangeMangaCategoriesDialog(this, listOf(manga), categories, preselected)
|
||||
.showDialog(router)
|
||||
.showDialog(router)
|
||||
}
|
||||
|
||||
override fun updateCategoriesForMangas(mangas: List<Manga>, categories: List<Category>) {
|
||||
@@ -492,8 +497,10 @@ class MangaInfoController(private val fromSource: Boolean = false) :
|
||||
val clipboard = activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, content))
|
||||
|
||||
activity.toast(view.context.getString(R.string.copied_to_clipboard, content.truncateCenter(20)),
|
||||
Toast.LENGTH_SHORT)
|
||||
activity.toast(
|
||||
view.context.getString(R.string.copied_to_clipboard, content.truncateCenter(20)),
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,8 +48,8 @@ class MangaInfoPresenter(
|
||||
|
||||
// Update favorite status
|
||||
mangaFavoriteRelay.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { setFavorite(it) }
|
||||
.apply { add(this) }
|
||||
.subscribe { setFavorite(it) }
|
||||
.apply { add(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ class MangaInfoPresenter(
|
||||
fun sendMangaToView() {
|
||||
viewMangaSubscription?.let { remove(it) }
|
||||
viewMangaSubscription = Observable.just(manga)
|
||||
.subscribeLatestCache({ view, manga -> view.onNextManga(manga, source) })
|
||||
.subscribeLatestCache({ view, manga -> view.onNextManga(manga, source) })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,18 +67,21 @@ class MangaInfoPresenter(
|
||||
fun fetchMangaFromSource() {
|
||||
if (!fetchMangaSubscription.isNullOrUnsubscribed()) return
|
||||
fetchMangaSubscription = Observable.defer { source.fetchMangaDetails(manga) }
|
||||
.map { networkManga ->
|
||||
manga.copyFrom(networkManga)
|
||||
manga.initialized = true
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
manga
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext { sendMangaToView() }
|
||||
.subscribeFirst({ view, _ ->
|
||||
.map { networkManga ->
|
||||
manga.copyFrom(networkManga)
|
||||
manga.initialized = true
|
||||
db.insertManga(manga).executeAsBlocking()
|
||||
manga
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext { sendMangaToView() }
|
||||
.subscribeFirst(
|
||||
{ view, _ ->
|
||||
view.onFetchMangaDone()
|
||||
}, MangaInfoController::onFetchMangaError)
|
||||
},
|
||||
MangaInfoController::onFetchMangaError
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,9 +19,11 @@ class SetTrackChaptersDialog<T> : DialogController
|
||||
|
||||
private val item: TrackItem
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
constructor(target: T, item: TrackItem) : super(
|
||||
Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.item = item
|
||||
}
|
||||
@@ -37,17 +39,17 @@ class SetTrackChaptersDialog<T> : DialogController
|
||||
val item = item
|
||||
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(R.string.chapters)
|
||||
.customView(R.layout.track_chapters_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
np.clearFocus()
|
||||
.title(R.string.chapters)
|
||||
.customView(R.layout.track_chapters_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
np.clearFocus()
|
||||
|
||||
(targetController as? Listener)?.setChaptersRead(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
(targetController as? Listener)?.setChaptersRead(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
val view = dialog.getCustomView()
|
||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||
|
||||
+16
-11
@@ -20,9 +20,11 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
||||
|
||||
private val dateToUpdate: ReadingDate
|
||||
|
||||
constructor(target: T, dateToUpdate: ReadingDate, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(SetTrackReadingDatesDialog.KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
constructor(target: T, dateToUpdate: ReadingDate, item: TrackItem) : super(
|
||||
Bundle().apply {
|
||||
putSerializable(SetTrackReadingDatesDialog.KEY_ITEM_TRACK, item.track)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.item = item
|
||||
this.dateToUpdate = dateToUpdate
|
||||
@@ -40,16 +42,18 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
||||
val listener = (targetController as? Listener)
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(when (dateToUpdate) {
|
||||
.title(
|
||||
when (dateToUpdate) {
|
||||
ReadingDate.Start -> R.string.track_started_reading_date
|
||||
ReadingDate.Finish -> R.string.track_finished_reading_date
|
||||
})
|
||||
.datePicker(currentDate = getCurrentDate()) { _, date ->
|
||||
listener?.setReadingDate(item, dateToUpdate, date.timeInMillis)
|
||||
}
|
||||
.neutralButton(R.string.action_remove) {
|
||||
listener?.setReadingDate(item, dateToUpdate, 0L)
|
||||
}
|
||||
)
|
||||
.datePicker(currentDate = getCurrentDate()) { _, date ->
|
||||
listener?.setReadingDate(item, dateToUpdate, date.timeInMillis)
|
||||
}
|
||||
.neutralButton(R.string.action_remove) {
|
||||
listener?.setReadingDate(item, dateToUpdate, 0L)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentDate(): Calendar {
|
||||
@@ -60,8 +64,9 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
||||
ReadingDate.Start -> it.started_reading_date
|
||||
ReadingDate.Finish -> it.finished_reading_date
|
||||
}
|
||||
if (date != 0L)
|
||||
if (date != 0L) {
|
||||
timeInMillis = date
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,11 @@ class SetTrackScoreDialog<T> : DialogController
|
||||
|
||||
private val item: TrackItem
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
constructor(target: T, item: TrackItem) : super(
|
||||
Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.item = item
|
||||
}
|
||||
@@ -37,17 +39,17 @@ class SetTrackScoreDialog<T> : DialogController
|
||||
val item = item
|
||||
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.title(R.string.score)
|
||||
.customView(R.layout.track_score_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
np.clearFocus()
|
||||
.title(R.string.score)
|
||||
.customView(R.layout.track_score_dialog, dialogWrapContent = false)
|
||||
.positiveButton(android.R.string.ok) { dialog ->
|
||||
val view = dialog.getCustomView()
|
||||
// Remove focus to update selected number
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
np.clearFocus()
|
||||
|
||||
(targetController as? Listener)?.setScore(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
(targetController as? Listener)?.setScore(item, np.value)
|
||||
}
|
||||
.negativeButton(android.R.string.cancel)
|
||||
|
||||
val view = dialog.getCustomView()
|
||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||
|
||||
@@ -17,9 +17,11 @@ class SetTrackStatusDialog<T> : DialogController
|
||||
|
||||
private val item: TrackItem
|
||||
|
||||
constructor(target: T, item: TrackItem) : super(Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}) {
|
||||
constructor(target: T, item: TrackItem) : super(
|
||||
Bundle().apply {
|
||||
putSerializable(KEY_ITEM_TRACK, item.track)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.item = item
|
||||
}
|
||||
@@ -38,16 +40,16 @@ class SetTrackStatusDialog<T> : DialogController
|
||||
val selectedIndex = statusList.indexOf(item.track?.status)
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(R.string.status)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.listItemsSingleChoice(
|
||||
items = statusString,
|
||||
initialSelection = selectedIndex,
|
||||
waitForPositiveButton = false
|
||||
) { dialog, position, _ ->
|
||||
(targetController as? Listener)?.setStatus(item, position)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.title(R.string.status)
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.listItemsSingleChoice(
|
||||
items = statusString,
|
||||
initialSelection = selectedIndex,
|
||||
waitForPositiveButton = false
|
||||
) { dialog, position, _ ->
|
||||
(targetController as? Listener)?.setStatus(item, position)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
||||
@@ -17,12 +17,13 @@ import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
||||
import timber.log.Timber
|
||||
|
||||
class TrackController : NucleusController<TrackControllerBinding, TrackPresenter>(),
|
||||
TrackAdapter.OnClickListener,
|
||||
SetTrackStatusDialog.Listener,
|
||||
SetTrackChaptersDialog.Listener,
|
||||
SetTrackScoreDialog.Listener,
|
||||
SetTrackReadingDatesDialog.Listener {
|
||||
class TrackController :
|
||||
NucleusController<TrackControllerBinding, TrackPresenter>(),
|
||||
TrackAdapter.OnClickListener,
|
||||
SetTrackStatusDialog.Listener,
|
||||
SetTrackChaptersDialog.Listener,
|
||||
SetTrackScoreDialog.Listener,
|
||||
SetTrackReadingDatesDialog.Listener {
|
||||
|
||||
private var adapter: TrackAdapter? = null
|
||||
|
||||
|
||||
@@ -56,15 +56,15 @@ class TrackHolder(view: View, adapter: TrackAdapter) : BaseViewHolder(view) {
|
||||
if (track != null) {
|
||||
track_title.text = track.title
|
||||
track_chapters.text = "${track.last_chapter_read}/" +
|
||||
if (track.total_chapters > 0) track.total_chapters else "-"
|
||||
if (track.total_chapters > 0) track.total_chapters else "-"
|
||||
track_status.text = item.service.getStatus(track.status)
|
||||
track_score.text = if (track.score == 0f) "-" else item.service.displayScore(track)
|
||||
|
||||
if (item.service.supportsReadingDates) {
|
||||
track_start_date.text =
|
||||
if (track.started_reading_date != 0L) dateFormat.format(track.started_reading_date) else "-"
|
||||
if (track.started_reading_date != 0L) dateFormat.format(track.started_reading_date) else "-"
|
||||
track_finish_date.text =
|
||||
if (track.finished_reading_date != 0L) dateFormat.format(track.finished_reading_date) else "-"
|
||||
if (track.finished_reading_date != 0L) dateFormat.format(track.finished_reading_date) else "-"
|
||||
} else {
|
||||
bottom_divider.gone()
|
||||
vert_divider_3.gone()
|
||||
|
||||
@@ -43,52 +43,60 @@ class TrackPresenter(
|
||||
fun fetchTrackings() {
|
||||
trackSubscription?.let { remove(it) }
|
||||
trackSubscription = db.getTracks(manga)
|
||||
.asRxObservable()
|
||||
.map { tracks ->
|
||||
loggedServices.map { service ->
|
||||
TrackItem(tracks.find { it.sync_id == service.id }, service)
|
||||
}
|
||||
.asRxObservable()
|
||||
.map { tracks ->
|
||||
loggedServices.map { service ->
|
||||
TrackItem(tracks.find { it.sync_id == service.id }, service)
|
||||
}
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext { trackList = it }
|
||||
.subscribeLatestCache(TrackController::onNextTrackings)
|
||||
}
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext { trackList = it }
|
||||
.subscribeLatestCache(TrackController::onNextTrackings)
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
refreshSubscription?.let { remove(it) }
|
||||
refreshSubscription = Observable.from(trackList)
|
||||
.filter { it.track != null }
|
||||
.concatMap { item ->
|
||||
item.service.refresh(item.track!!)
|
||||
.flatMap { db.insertTrack(it).asRxObservable() }
|
||||
.map { item }
|
||||
.onErrorReturn { item }
|
||||
}
|
||||
.toList()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst({ view, _ -> view.onRefreshDone() },
|
||||
TrackController::onRefreshError)
|
||||
.filter { it.track != null }
|
||||
.concatMap { item ->
|
||||
item.service.refresh(item.track!!)
|
||||
.flatMap { db.insertTrack(it).asRxObservable() }
|
||||
.map { item }
|
||||
.onErrorReturn { item }
|
||||
}
|
||||
.toList()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst(
|
||||
{ view, _ -> view.onRefreshDone() },
|
||||
TrackController::onRefreshError
|
||||
)
|
||||
}
|
||||
|
||||
fun search(query: String, service: TrackService) {
|
||||
searchSubscription?.let { remove(it) }
|
||||
searchSubscription = service.search(query)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(TrackController::onSearchResults,
|
||||
TrackController::onSearchResultsError)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(
|
||||
TrackController::onSearchResults,
|
||||
TrackController::onSearchResultsError
|
||||
)
|
||||
}
|
||||
|
||||
fun registerTracking(item: Track?, service: TrackService) {
|
||||
if (item != null) {
|
||||
item.manga_id = manga.id!!
|
||||
add(service.bind(item)
|
||||
add(
|
||||
service.bind(item)
|
||||
.flatMap { db.insertTrack(item).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ },
|
||||
{ error -> context.toast(error.message) }))
|
||||
.subscribe(
|
||||
{ },
|
||||
{ error -> context.toast(error.message) }
|
||||
)
|
||||
)
|
||||
} else {
|
||||
unregisterTracking(service)
|
||||
}
|
||||
@@ -100,16 +108,18 @@ class TrackPresenter(
|
||||
|
||||
private fun updateRemote(track: Track, service: TrackService) {
|
||||
service.update(track)
|
||||
.flatMap { db.insertTrack(track).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst({ view, _ -> view.onRefreshDone() },
|
||||
{ view, error ->
|
||||
view.onRefreshError(error)
|
||||
.flatMap { db.insertTrack(track).asRxObservable() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeFirst(
|
||||
{ view, _ -> view.onRefreshDone() },
|
||||
{ view, error ->
|
||||
view.onRefreshError(error)
|
||||
|
||||
// Restart on error to set old values
|
||||
fetchTrackings()
|
||||
})
|
||||
// Restart on error to set old values
|
||||
fetchTrackings()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun setStatus(item: TrackItem, index: Int) {
|
||||
|
||||
@@ -56,10 +56,10 @@ class TrackSearchAdapter(context: Context) :
|
||||
GlideApp.with(view.context).clear(view.track_search_cover)
|
||||
if (!track.cover_url.isEmpty()) {
|
||||
GlideApp.with(view.context)
|
||||
.load(track.cover_url)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(view.track_search_cover)
|
||||
.load(track.cover_url)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerCrop()
|
||||
.into(view.track_search_cover)
|
||||
}
|
||||
|
||||
if (track.publishing_status.isBlank()) {
|
||||
|
||||
@@ -40,9 +40,11 @@ class TrackSearchDialog : DialogController {
|
||||
private val trackController
|
||||
get() = targetController as TrackController
|
||||
|
||||
constructor(target: TrackController, service: TrackService) : super(Bundle().apply {
|
||||
putInt(KEY_SERVICE, service.id)
|
||||
}) {
|
||||
constructor(target: TrackController, service: TrackService) : super(
|
||||
Bundle().apply {
|
||||
putInt(KEY_SERVICE, service.id)
|
||||
}
|
||||
) {
|
||||
targetController = target
|
||||
this.service = service
|
||||
}
|
||||
@@ -54,10 +56,10 @@ class TrackSearchDialog : DialogController {
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
val dialog = MaterialDialog(activity!!)
|
||||
.customView(R.layout.track_search_dialog)
|
||||
.positiveButton(android.R.string.ok) { onPositiveButtonClick() }
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.neutralButton(R.string.action_remove) { onRemoveButtonClick() }
|
||||
.customView(R.layout.track_search_dialog)
|
||||
.positiveButton(android.R.string.ok) { onPositiveButtonClick() }
|
||||
.negativeButton(android.R.string.cancel)
|
||||
.neutralButton(R.string.action_remove) { onRemoveButtonClick() }
|
||||
|
||||
dialogView = dialog.view
|
||||
onViewCreated(dialog.view, savedViewState)
|
||||
|
||||
Reference in New Issue
Block a user