Move tracking to a bottom sheet (#4364)
* Move tracking to a bottom sheet * Give methods better names and remove unnecessary annotation
This commit is contained in:
parent
c34b548a3e
commit
535abcbb8b
@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.databinding.MangaControllerBinding
|
import eu.kanade.tachiyomi.databinding.MangaControllerBinding
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
@ -62,7 +63,9 @@ import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog
|
|||||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaChaptersHeaderAdapter
|
import eu.kanade.tachiyomi.ui.manga.chapter.MangaChaptersHeaderAdapter
|
||||||
import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter
|
import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter
|
||||||
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoHeaderAdapter
|
import eu.kanade.tachiyomi.ui.manga.info.MangaInfoHeaderAdapter
|
||||||
import eu.kanade.tachiyomi.ui.manga.track.TrackController
|
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.track.TrackSearchDialog
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.track.TrackSheet
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||||
@ -160,6 +163,8 @@ class MangaController :
|
|||||||
private var isRefreshingInfo = false
|
private var isRefreshingInfo = false
|
||||||
private var isRefreshingChapters = false
|
private var isRefreshingChapters = false
|
||||||
|
|
||||||
|
private var trackSheet: TrackSheet? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
}
|
}
|
||||||
@ -246,6 +251,8 @@ class MangaController :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackSheet = TrackSheet(this, manga!!)
|
||||||
|
|
||||||
updateFilterIconState()
|
updateFilterIconState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +468,7 @@ class MangaController :
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onTrackingClick() {
|
fun onTrackingClick() {
|
||||||
router.pushController(TrackController(manga).withFadeTransaction())
|
trackSheet?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addToLibrary(manga: Manga) {
|
private fun addToLibrary(manga: Manga) {
|
||||||
@ -1030,6 +1037,35 @@ class MangaController :
|
|||||||
|
|
||||||
// Chapters list - end
|
// Chapters list - end
|
||||||
|
|
||||||
|
// Tracker sheet - start
|
||||||
|
fun onNextTrackers(trackers: List<TrackItem>) {
|
||||||
|
trackSheet?.onNextTrackers(trackers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTrackingRefreshDone() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTrackingRefreshError(error: Throwable) {
|
||||||
|
Timber.e(error)
|
||||||
|
activity?.toast(error.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTrackingSearchResults(results: List<TrackSearch>) {
|
||||||
|
getTrackingSearchDialog()?.onSearchResults(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTrackingSearchResultsError(error: Throwable) {
|
||||||
|
Timber.e(error)
|
||||||
|
activity?.toast(error.message)
|
||||||
|
getTrackingSearchDialog()?.onSearchResultsError()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTrackingSearchDialog(): TrackSearchDialog? {
|
||||||
|
return trackSheet?.getSearchDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracker sheet - end
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val FROM_SOURCE_EXTRA = "from_source"
|
const val FROM_SOURCE_EXTRA = "from_source"
|
||||||
const val MANGA_EXTRA = "manga"
|
const val MANGA_EXTRA = "manga"
|
||||||
|
@ -10,17 +10,20 @@ import eu.kanade.tachiyomi.data.database.models.Category
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.model.toSChapter
|
import eu.kanade.tachiyomi.source.model.toSChapter
|
||||||
import eu.kanade.tachiyomi.source.model.toSManga
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||||
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
import eu.kanade.tachiyomi.util.isLocal
|
import eu.kanade.tachiyomi.util.isLocal
|
||||||
@ -29,9 +32,13 @@ import eu.kanade.tachiyomi.util.lang.withUIContext
|
|||||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
import eu.kanade.tachiyomi.util.prepUpdateCover
|
||||||
import eu.kanade.tachiyomi.util.removeCovers
|
import eu.kanade.tachiyomi.util.removeCovers
|
||||||
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.updateCoverLastModified
|
import eu.kanade.tachiyomi.util.updateCoverLastModified
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.awaitAll
|
||||||
|
import kotlinx.coroutines.supervisorScope
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
@ -86,6 +93,15 @@ class MangaPresenter(
|
|||||||
private var observeDownloadsStatusSubscription: Subscription? = null
|
private var observeDownloadsStatusSubscription: Subscription? = null
|
||||||
private var observeDownloadsPageSubscription: Subscription? = null
|
private var observeDownloadsPageSubscription: Subscription? = null
|
||||||
|
|
||||||
|
private var _trackList: List<TrackItem> = emptyList()
|
||||||
|
val trackList get() = _trackList
|
||||||
|
|
||||||
|
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
|
||||||
|
|
||||||
|
private var trackSubscription: Subscription? = null
|
||||||
|
private var searchJob: Job? = null
|
||||||
|
private var refreshJob: Job? = null
|
||||||
|
|
||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
super.onCreate(savedState)
|
super.onCreate(savedState)
|
||||||
|
|
||||||
@ -134,6 +150,8 @@ class MangaPresenter(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Chapters list - end
|
// Chapters list - end
|
||||||
|
|
||||||
|
fetchTrackers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manga info - start
|
// Manga info - start
|
||||||
@ -645,4 +663,128 @@ class MangaPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Chapters list - end
|
// Chapters list - end
|
||||||
|
|
||||||
|
// Track sheet - start
|
||||||
|
|
||||||
|
private fun fetchTrackers() {
|
||||||
|
trackSubscription?.let { remove(it) }
|
||||||
|
trackSubscription = db.getTracks(manga)
|
||||||
|
.asRxObservable()
|
||||||
|
.map { tracks ->
|
||||||
|
loggedServices.map { service ->
|
||||||
|
TrackItem(tracks.find { it.sync_id == service.id }, service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnNext { _trackList = it }
|
||||||
|
.subscribeLatestCache(MangaController::onNextTrackers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun trackingRefresh() {
|
||||||
|
refreshJob?.cancel()
|
||||||
|
refreshJob = launchIO {
|
||||||
|
supervisorScope {
|
||||||
|
try {
|
||||||
|
trackList
|
||||||
|
.filter { it.track != null }
|
||||||
|
.map {
|
||||||
|
async {
|
||||||
|
val track = it.service.refresh(it.track!!)
|
||||||
|
db.insertTrack(track).executeAsBlocking()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.awaitAll()
|
||||||
|
|
||||||
|
withUIContext { view?.onTrackingRefreshDone() }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
withUIContext { view?.onTrackingRefreshError(e) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun trackingSearch(query: String, service: TrackService) {
|
||||||
|
searchJob?.cancel()
|
||||||
|
searchJob = launchIO {
|
||||||
|
try {
|
||||||
|
val results = service.search(query)
|
||||||
|
withUIContext { view?.onTrackingSearchResults(results) }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
withUIContext { view?.onTrackingSearchResultsError(e) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerTracking(item: Track?, service: TrackService) {
|
||||||
|
if (item != null) {
|
||||||
|
item.manga_id = manga.id!!
|
||||||
|
launchIO {
|
||||||
|
try {
|
||||||
|
service.bind(item)
|
||||||
|
db.insertTrack(item).executeAsBlocking()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
withUIContext { view?.applicationContext?.toast(e.message) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unregisterTracking(service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregisterTracking(service: TrackService) {
|
||||||
|
db.deleteTrackForManga(manga, service).executeAsBlocking()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateRemote(track: Track, service: TrackService) {
|
||||||
|
launchIO {
|
||||||
|
try {
|
||||||
|
service.update(track)
|
||||||
|
db.insertTrack(track).executeAsBlocking()
|
||||||
|
withUIContext { view?.onTrackingRefreshDone() }
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
withUIContext { view?.onTrackingRefreshError(e) }
|
||||||
|
|
||||||
|
// Restart on error to set old values
|
||||||
|
fetchTrackers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTrackerStatus(item: TrackItem, index: Int) {
|
||||||
|
val track = item.track!!
|
||||||
|
track.status = item.service.getStatusList()[index]
|
||||||
|
if (track.status == item.service.getCompletionStatus() && track.total_chapters != 0) {
|
||||||
|
track.last_chapter_read = track.total_chapters
|
||||||
|
}
|
||||||
|
updateRemote(track, item.service)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTrackerScore(item: TrackItem, index: Int) {
|
||||||
|
val track = item.track!!
|
||||||
|
track.score = item.service.indexToScore(index)
|
||||||
|
updateRemote(track, item.service)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTrackerLastChapterRead(item: TrackItem, chapterNumber: Int) {
|
||||||
|
val track = item.track!!
|
||||||
|
track.last_chapter_read = chapterNumber
|
||||||
|
if (track.total_chapters != 0 && track.last_chapter_read == track.total_chapters) {
|
||||||
|
track.status = item.service.getCompletionStatus()
|
||||||
|
}
|
||||||
|
updateRemote(track, item.service)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTrackerStartDate(item: TrackItem, date: Long) {
|
||||||
|
val track = item.track!!
|
||||||
|
track.started_reading_date = date
|
||||||
|
updateRemote(track, item.service)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setTrackerFinishDate(item: TrackItem, date: Long) {
|
||||||
|
val track = item.track!!
|
||||||
|
track.finished_reading_date = date
|
||||||
|
updateRemote(track, item.service)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track sheet - end
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,17 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class SetTrackChaptersDialog<T> : DialogController
|
class SetTrackChaptersDialog<T> : DialogController
|
||||||
where T : Controller, T : SetTrackChaptersDialog.Listener {
|
where T : Controller {
|
||||||
|
|
||||||
private val item: TrackItem
|
private val item: TrackItem
|
||||||
|
|
||||||
constructor(target: T, item: TrackItem) : super(
|
private lateinit var listener: Listener
|
||||||
|
|
||||||
|
constructor(target: T, listener: Listener, item: TrackItem) : super(
|
||||||
bundleOf(KEY_ITEM_TRACK to item.track)
|
bundleOf(KEY_ITEM_TRACK to item.track)
|
||||||
) {
|
) {
|
||||||
targetController = target
|
targetController = target
|
||||||
|
this.listener = listener
|
||||||
this.item = item
|
this.item = item
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +49,7 @@ class SetTrackChaptersDialog<T> : DialogController
|
|||||||
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
val np: NumberPicker = view.findViewById(R.id.chapters_picker)
|
||||||
np.clearFocus()
|
np.clearFocus()
|
||||||
|
|
||||||
(targetController as? Listener)?.setChaptersRead(item, np.value)
|
listener.setChaptersRead(item, np.value)
|
||||||
}
|
}
|
||||||
.negativeButton(android.R.string.cancel)
|
.negativeButton(android.R.string.cancel)
|
||||||
|
|
||||||
|
@ -15,16 +15,19 @@ import uy.kohesive.injekt.api.get
|
|||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
|
||||||
class SetTrackReadingDatesDialog<T> : DialogController
|
class SetTrackReadingDatesDialog<T> : DialogController
|
||||||
where T : Controller, T : SetTrackReadingDatesDialog.Listener {
|
where T : Controller {
|
||||||
|
|
||||||
private val item: TrackItem
|
private val item: TrackItem
|
||||||
|
|
||||||
private val dateToUpdate: ReadingDate
|
private val dateToUpdate: ReadingDate
|
||||||
|
|
||||||
constructor(target: T, dateToUpdate: ReadingDate, item: TrackItem) : super(
|
private lateinit var listener: Listener
|
||||||
|
|
||||||
|
constructor(target: T, listener: Listener, dateToUpdate: ReadingDate, item: TrackItem) : super(
|
||||||
bundleOf(KEY_ITEM_TRACK to item.track)
|
bundleOf(KEY_ITEM_TRACK to item.track)
|
||||||
) {
|
) {
|
||||||
targetController = target
|
targetController = target
|
||||||
|
this.listener = listener
|
||||||
this.item = item
|
this.item = item
|
||||||
this.dateToUpdate = dateToUpdate
|
this.dateToUpdate = dateToUpdate
|
||||||
}
|
}
|
||||||
@ -38,8 +41,6 @@ class SetTrackReadingDatesDialog<T> : DialogController
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val listener = (targetController as? Listener)
|
|
||||||
|
|
||||||
return MaterialDialog(activity!!)
|
return MaterialDialog(activity!!)
|
||||||
.title(
|
.title(
|
||||||
when (dateToUpdate) {
|
when (dateToUpdate) {
|
||||||
|
@ -16,14 +16,17 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class SetTrackScoreDialog<T> : DialogController
|
class SetTrackScoreDialog<T> : DialogController
|
||||||
where T : Controller, T : SetTrackScoreDialog.Listener {
|
where T : Controller {
|
||||||
|
|
||||||
private val item: TrackItem
|
private val item: TrackItem
|
||||||
|
|
||||||
constructor(target: T, item: TrackItem) : super(
|
private lateinit var listener: Listener
|
||||||
|
|
||||||
|
constructor(target: T, listener: Listener, item: TrackItem) : super(
|
||||||
bundleOf(KEY_ITEM_TRACK to item.track)
|
bundleOf(KEY_ITEM_TRACK to item.track)
|
||||||
) {
|
) {
|
||||||
targetController = target
|
targetController = target
|
||||||
|
this.listener = listener
|
||||||
this.item = item
|
this.item = item
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +49,7 @@ class SetTrackScoreDialog<T> : DialogController
|
|||||||
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
val np: NumberPicker = view.findViewById(R.id.score_picker)
|
||||||
np.clearFocus()
|
np.clearFocus()
|
||||||
|
|
||||||
(targetController as? Listener)?.setScore(item, np.value)
|
listener.setScore(item, np.value)
|
||||||
}
|
}
|
||||||
.negativeButton(android.R.string.cancel)
|
.negativeButton(android.R.string.cancel)
|
||||||
|
|
||||||
|
@ -14,14 +14,17 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class SetTrackStatusDialog<T> : DialogController
|
class SetTrackStatusDialog<T> : DialogController
|
||||||
where T : Controller, T : SetTrackStatusDialog.Listener {
|
where T : Controller {
|
||||||
|
|
||||||
private val item: TrackItem
|
private val item: TrackItem
|
||||||
|
|
||||||
constructor(target: T, item: TrackItem) : super(
|
private lateinit var listener: Listener
|
||||||
|
|
||||||
|
constructor(target: T, listener: Listener, item: TrackItem) : super(
|
||||||
bundleOf(KEY_ITEM_TRACK to item.track)
|
bundleOf(KEY_ITEM_TRACK to item.track)
|
||||||
) {
|
) {
|
||||||
targetController = target
|
targetController = target
|
||||||
|
this.listener = listener
|
||||||
this.item = item
|
this.item = item
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +49,7 @@ class SetTrackStatusDialog<T> : DialogController
|
|||||||
initialSelection = selectedIndex,
|
initialSelection = selectedIndex,
|
||||||
waitForPositiveButton = false
|
waitForPositiveButton = false
|
||||||
) { dialog, position, _ ->
|
) { dialog, position, _ ->
|
||||||
(targetController as? Listener)?.setStatus(item, position)
|
listener.setStatus(item, position)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import eu.kanade.tachiyomi.databinding.TrackItemBinding
|
import eu.kanade.tachiyomi.databinding.TrackItemBinding
|
||||||
|
|
||||||
class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHolder>() {
|
class TrackAdapter(listener: OnClickListener) : RecyclerView.Adapter<TrackHolder>() {
|
||||||
|
|
||||||
private lateinit var binding: TrackItemBinding
|
private lateinit var binding: TrackItemBinding
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ class TrackAdapter(controller: TrackController) : RecyclerView.Adapter<TrackHold
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val rowClickListener: OnClickListener = controller
|
val rowClickListener: OnClickListener = listener
|
||||||
|
|
||||||
fun getItem(index: Int): TrackItem? {
|
fun getItem(index: Int): TrackItem? {
|
||||||
return items.getOrNull(index)
|
return items.getOrNull(index)
|
||||||
|
@ -1,200 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.ui.manga.track
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.core.os.bundleOf
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
|
||||||
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import reactivecircus.flowbinding.swiperefreshlayout.refreshes
|
|
||||||
import timber.log.Timber
|
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
class TrackController :
|
|
||||||
NucleusController<TrackControllerBinding, TrackPresenter>,
|
|
||||||
TrackAdapter.OnClickListener,
|
|
||||||
SetTrackStatusDialog.Listener,
|
|
||||||
SetTrackChaptersDialog.Listener,
|
|
||||||
SetTrackScoreDialog.Listener,
|
|
||||||
SetTrackReadingDatesDialog.Listener {
|
|
||||||
|
|
||||||
constructor(manga: Manga?) : super(
|
|
||||||
bundleOf(MANGA_EXTRA to (manga?.id ?: 0))
|
|
||||||
) {
|
|
||||||
this.manga = manga
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(mangaId: Long) : this(
|
|
||||||
Injekt.get<DatabaseHelper>().getManga(mangaId).executeAsBlocking()
|
|
||||||
)
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
constructor(bundle: Bundle) : this(bundle.getLong(MANGA_EXTRA))
|
|
||||||
|
|
||||||
var manga: Manga? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
private var adapter: TrackAdapter? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
// There's no menu, but this avoids a bug when coming from the catalogue, where the menu
|
|
||||||
// disappears if the searchview is expanded
|
|
||||||
setHasOptionsMenu(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
|
||||||
return manga?.title
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPresenter(): TrackPresenter {
|
|
||||||
return TrackPresenter(manga!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
|
||||||
binding = TrackControllerBinding.inflate(inflater)
|
|
||||||
return binding.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View) {
|
|
||||||
super.onViewCreated(view)
|
|
||||||
|
|
||||||
if (manga == null) return
|
|
||||||
|
|
||||||
adapter = TrackAdapter(this)
|
|
||||||
binding.trackRecycler.layoutManager = LinearLayoutManager(view.context)
|
|
||||||
binding.trackRecycler.adapter = adapter
|
|
||||||
binding.swipeRefresh.isEnabled = false
|
|
||||||
binding.swipeRefresh.refreshes()
|
|
||||||
.onEach { presenter.refresh() }
|
|
||||||
.launchIn(viewScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView(view: View) {
|
|
||||||
adapter = null
|
|
||||||
super.onDestroyView(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onNextTrackings(trackings: List<TrackItem>) {
|
|
||||||
val atLeastOneLink = trackings.any { it.track != null }
|
|
||||||
adapter?.items = trackings
|
|
||||||
binding.swipeRefresh.isEnabled = atLeastOneLink
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSearchResults(results: List<TrackSearch>) {
|
|
||||||
getSearchDialog()?.onSearchResults(results)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun onSearchResultsError(error: Throwable) {
|
|
||||||
Timber.e(error)
|
|
||||||
activity?.toast(error.message)
|
|
||||||
getSearchDialog()?.onSearchResultsError()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSearchDialog(): TrackSearchDialog? {
|
|
||||||
return router.getControllerWithTag(TAG_SEARCH_CONTROLLER) as? TrackSearchDialog
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onRefreshDone() {
|
|
||||||
binding.swipeRefresh.isRefreshing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onRefreshError(error: Throwable) {
|
|
||||||
binding.swipeRefresh.isRefreshing = false
|
|
||||||
activity?.toast(error.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLogoClick(position: Int) {
|
|
||||||
val track = adapter?.getItem(position)?.track ?: return
|
|
||||||
|
|
||||||
if (track.tracking_url.isNotBlank()) {
|
|
||||||
activity?.startActivity(Intent(Intent.ACTION_VIEW, track.tracking_url.toUri()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSetClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
TrackSearchDialog(this, item.service).showDialog(router, TAG_SEARCH_CONTROLLER)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTitleLongClick(position: Int) {
|
|
||||||
adapter?.getItem(position)?.track?.title?.let {
|
|
||||||
activity?.copyToClipboard(it, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStatusClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
if (item.track == null) return
|
|
||||||
|
|
||||||
SetTrackStatusDialog(this, item).showDialog(router)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onChaptersClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
if (item.track == null) return
|
|
||||||
|
|
||||||
SetTrackChaptersDialog(this, item).showDialog(router)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScoreClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
if (item.track == null) return
|
|
||||||
|
|
||||||
SetTrackScoreDialog(this, item).showDialog(router)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartDateClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
if (item.track == null) return
|
|
||||||
|
|
||||||
SetTrackReadingDatesDialog(this, SetTrackReadingDatesDialog.ReadingDate.Start, item).showDialog(router)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFinishDateClick(position: Int) {
|
|
||||||
val item = adapter?.getItem(position) ?: return
|
|
||||||
if (item.track == null) return
|
|
||||||
|
|
||||||
SetTrackReadingDatesDialog(this, SetTrackReadingDatesDialog.ReadingDate.Finish, item).showDialog(router)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setStatus(item: TrackItem, selection: Int) {
|
|
||||||
presenter.setStatus(item, selection)
|
|
||||||
binding.swipeRefresh.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setScore(item: TrackItem, score: Int) {
|
|
||||||
presenter.setScore(item, score)
|
|
||||||
binding.swipeRefresh.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setChaptersRead(item: TrackItem, chaptersRead: Int) {
|
|
||||||
presenter.setLastChapterRead(item, chaptersRead)
|
|
||||||
binding.swipeRefresh.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setReadingDate(item: TrackItem, type: SetTrackReadingDatesDialog.ReadingDate, date: Long) {
|
|
||||||
when (type) {
|
|
||||||
SetTrackReadingDatesDialog.ReadingDate.Start -> presenter.setStartDate(item, date)
|
|
||||||
SetTrackReadingDatesDialog.ReadingDate.Finish -> presenter.setFinishDate(item, date)
|
|
||||||
}
|
|
||||||
binding.swipeRefresh.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val MANGA_EXTRA = "manga"
|
|
||||||
const val TAG_SEARCH_CONTROLLER = "track_search_controller"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,164 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.ui.manga.track
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
|
||||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.awaitAll
|
|
||||||
import kotlinx.coroutines.supervisorScope
|
|
||||||
import rx.Subscription
|
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
class TrackPresenter(
|
|
||||||
val manga: Manga,
|
|
||||||
preferences: PreferencesHelper = Injekt.get(),
|
|
||||||
private val db: DatabaseHelper = Injekt.get(),
|
|
||||||
private val trackManager: TrackManager = Injekt.get()
|
|
||||||
) : BasePresenter<TrackController>() {
|
|
||||||
|
|
||||||
private val context = preferences.context
|
|
||||||
|
|
||||||
private var trackList: List<TrackItem> = emptyList()
|
|
||||||
|
|
||||||
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
|
|
||||||
|
|
||||||
private var trackSubscription: Subscription? = null
|
|
||||||
private var searchJob: Job? = null
|
|
||||||
private var refreshJob: Job? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedState: Bundle?) {
|
|
||||||
super.onCreate(savedState)
|
|
||||||
fetchTrackings()
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.doOnNext { trackList = it }
|
|
||||||
.subscribeLatestCache(TrackController::onNextTrackings)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refresh() {
|
|
||||||
refreshJob?.cancel()
|
|
||||||
refreshJob = launchIO {
|
|
||||||
supervisorScope {
|
|
||||||
try {
|
|
||||||
trackList
|
|
||||||
.filter { it.track != null }
|
|
||||||
.map {
|
|
||||||
async {
|
|
||||||
val track = it.service.refresh(it.track!!)
|
|
||||||
db.insertTrack(track).executeAsBlocking()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.awaitAll()
|
|
||||||
|
|
||||||
withUIContext { view?.onRefreshDone() }
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
withUIContext { view?.onRefreshError(e) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun search(query: String, service: TrackService) {
|
|
||||||
searchJob?.cancel()
|
|
||||||
searchJob = launchIO {
|
|
||||||
try {
|
|
||||||
val results = service.search(query)
|
|
||||||
withUIContext { view?.onSearchResults(results) }
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
withUIContext { view?.onSearchResultsError(e) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun registerTracking(item: Track?, service: TrackService) {
|
|
||||||
if (item != null) {
|
|
||||||
item.manga_id = manga.id!!
|
|
||||||
launchIO {
|
|
||||||
try {
|
|
||||||
service.bind(item)
|
|
||||||
db.insertTrack(item).executeAsBlocking()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
withUIContext { context.toast(e.message) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unregisterTracking(service)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unregisterTracking(service: TrackService) {
|
|
||||||
db.deleteTrackForManga(manga, service).executeAsBlocking()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateRemote(track: Track, service: TrackService) {
|
|
||||||
launchIO {
|
|
||||||
try {
|
|
||||||
service.update(track)
|
|
||||||
db.insertTrack(track).executeAsBlocking()
|
|
||||||
withUIContext { view?.onRefreshDone() }
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
withUIContext { view?.onRefreshError(e) }
|
|
||||||
|
|
||||||
// Restart on error to set old values
|
|
||||||
fetchTrackings()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStatus(item: TrackItem, index: Int) {
|
|
||||||
val track = item.track!!
|
|
||||||
track.status = item.service.getStatusList()[index]
|
|
||||||
if (track.status == item.service.getCompletionStatus() && track.total_chapters != 0) {
|
|
||||||
track.last_chapter_read = track.total_chapters
|
|
||||||
}
|
|
||||||
updateRemote(track, item.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setScore(item: TrackItem, index: Int) {
|
|
||||||
val track = item.track!!
|
|
||||||
track.score = item.service.indexToScore(index)
|
|
||||||
updateRemote(track, item.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLastChapterRead(item: TrackItem, chapterNumber: Int) {
|
|
||||||
val track = item.track!!
|
|
||||||
track.last_chapter_read = chapterNumber
|
|
||||||
if (track.total_chapters != 0 && track.last_chapter_read == track.total_chapters) {
|
|
||||||
track.status = item.service.getCompletionStatus()
|
|
||||||
}
|
|
||||||
updateRemote(track, item.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStartDate(item: TrackItem, date: Long) {
|
|
||||||
val track = item.track!!
|
|
||||||
track.started_reading_date = date
|
|
||||||
updateRemote(track, item.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setFinishDate(item: TrackItem, date: Long) {
|
|
||||||
val track = item.track!!
|
|
||||||
track.finished_reading_date = date
|
|
||||||
updateRemote(track, item.service)
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.data.track.TrackService
|
|||||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||||
import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding
|
import eu.kanade.tachiyomi.databinding.TrackSearchDialogBinding
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
@ -36,9 +37,9 @@ class TrackSearchDialog : DialogController {
|
|||||||
private val service: TrackService
|
private val service: TrackService
|
||||||
|
|
||||||
private val trackController
|
private val trackController
|
||||||
get() = targetController as TrackController
|
get() = targetController as MangaController
|
||||||
|
|
||||||
constructor(target: TrackController, service: TrackService) : super(
|
constructor(target: MangaController, service: TrackService) : super(
|
||||||
bundleOf(KEY_SERVICE to service.id)
|
bundleOf(KEY_SERVICE to service.id)
|
||||||
) {
|
) {
|
||||||
targetController = target
|
targetController = target
|
||||||
@ -105,7 +106,7 @@ class TrackSearchDialog : DialogController {
|
|||||||
val binding = binding ?: return
|
val binding = binding ?: return
|
||||||
binding.progress.isVisible = true
|
binding.progress.isVisible = true
|
||||||
binding.trackSearchList.isVisible = false
|
binding.trackSearchList.isVisible = false
|
||||||
trackController.presenter.search(query, service)
|
trackController.presenter.trackingSearch(query, service)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSearchResults(results: List<TrackSearch>) {
|
fun onSearchResults(results: List<TrackSearch>) {
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.manga.track
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.databinding.TrackControllerBinding
|
||||||
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
|
import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog
|
||||||
|
|
||||||
|
class TrackSheet(
|
||||||
|
val controller: MangaController,
|
||||||
|
val manga: Manga
|
||||||
|
) : BaseBottomSheetDialog(controller.activity!!),
|
||||||
|
TrackAdapter.OnClickListener,
|
||||||
|
SetTrackStatusDialog.Listener,
|
||||||
|
SetTrackChaptersDialog.Listener,
|
||||||
|
SetTrackScoreDialog.Listener,
|
||||||
|
SetTrackReadingDatesDialog.Listener {
|
||||||
|
|
||||||
|
private lateinit var binding: TrackControllerBinding
|
||||||
|
|
||||||
|
private lateinit var sheetBehavior: BottomSheetBehavior<*>
|
||||||
|
|
||||||
|
private lateinit var adapter: TrackAdapter
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
binding = TrackControllerBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
adapter = TrackAdapter(this)
|
||||||
|
binding.trackRecycler.layoutManager = LinearLayoutManager(context)
|
||||||
|
binding.trackRecycler.adapter = adapter
|
||||||
|
|
||||||
|
sheetBehavior = BottomSheetBehavior.from(binding.root.parent as ViewGroup)
|
||||||
|
|
||||||
|
adapter.items = controller.presenter.trackList
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
sheetBehavior.skipCollapsed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
super.show()
|
||||||
|
controller.presenter.trackingRefresh()
|
||||||
|
sheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onNextTrackers(trackers: List<TrackItem>) {
|
||||||
|
if (this::adapter.isInitialized) {
|
||||||
|
adapter.items = trackers
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLogoClick(position: Int) {
|
||||||
|
val track = adapter.getItem(position)?.track ?: return
|
||||||
|
|
||||||
|
if (track.tracking_url.isNotBlank()) {
|
||||||
|
controller.activity?.startActivity(Intent(Intent.ACTION_VIEW, track.tracking_url.toUri()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSetClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
TrackSearchDialog(controller, item.service).showDialog(controller.router, TAG_SEARCH_CONTROLLER)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTitleLongClick(position: Int) {
|
||||||
|
adapter.getItem(position)?.track?.title?.let {
|
||||||
|
controller.activity?.copyToClipboard(it, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStatusClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
if (item.track == null) return
|
||||||
|
|
||||||
|
SetTrackStatusDialog(controller, this, item).showDialog(controller.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChaptersClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
if (item.track == null) return
|
||||||
|
|
||||||
|
SetTrackChaptersDialog(controller, this, item).showDialog(controller.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScoreClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
if (item.track == null) return
|
||||||
|
|
||||||
|
SetTrackScoreDialog(controller, this, item).showDialog(controller.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartDateClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
if (item.track == null) return
|
||||||
|
|
||||||
|
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Start, item).showDialog(controller.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinishDateClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) ?: return
|
||||||
|
if (item.track == null) return
|
||||||
|
|
||||||
|
SetTrackReadingDatesDialog(controller, this, SetTrackReadingDatesDialog.ReadingDate.Finish, item).showDialog(controller.router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStatus(item: TrackItem, selection: Int) {
|
||||||
|
controller.presenter.setTrackerStatus(item, selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setChaptersRead(item: TrackItem, chaptersRead: Int) {
|
||||||
|
controller.presenter.setTrackerLastChapterRead(item, chaptersRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setScore(item: TrackItem, score: Int) {
|
||||||
|
controller.presenter.setTrackerScore(item, score)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setReadingDate(item: TrackItem, type: SetTrackReadingDatesDialog.ReadingDate, date: Long) {
|
||||||
|
when (type) {
|
||||||
|
SetTrackReadingDatesDialog.ReadingDate.Start -> controller.presenter.setTrackerStartDate(item, date)
|
||||||
|
SetTrackReadingDatesDialog.ReadingDate.Finish -> controller.presenter.setTrackerFinishDate(item, date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSearchDialog(): TrackSearchDialog? {
|
||||||
|
return controller.router.getControllerWithTag(TAG_SEARCH_CONTROLLER) as? TrackSearchDialog
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val TAG_SEARCH_CONTROLLER = "track_search_controller"
|
||||||
|
}
|
||||||
|
}
|
@ -5,20 +5,12 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/swipe_refresh"
|
android:id="@+id/track_recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:clipToPadding="false"
|
||||||
android:orientation="vertical">
|
tools:listitem="@layout/track_item" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/track_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:listitem="@layout/track_item" />
|
|
||||||
|
|
||||||
</eu.kanade.tachiyomi.widget.ThemedSwipeRefreshLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
Loading…
Reference in New Issue
Block a user