Show related manga
This commit is contained in:
@@ -30,6 +30,7 @@ android {
|
|||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||||
|
freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
@@ -71,7 +72,7 @@ dependencies {
|
|||||||
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
|
implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
implementation 'androidx.work:work-runtime-ktx:2.4.0-beta01'
|
implementation 'androidx.work:work-runtime-ktx:2.4.0-beta01'
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
implementation 'com.google.android.material:material:1.3.0-alpha01'
|
||||||
|
|
||||||
implementation 'androidx.room:room-runtime:2.2.5'
|
implementation 'androidx.room:room-runtime:2.2.5'
|
||||||
implementation 'androidx.room:room-ktx:2.2.5'
|
implementation 'androidx.room:room-ktx:2.2.5'
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView,
|
|||||||
tab.text = when (position) {
|
tab.text = when (position) {
|
||||||
0 -> getString(R.string.details)
|
0 -> getString(R.string.details)
|
||||||
1 -> getString(R.string.chapters)
|
1 -> getString(R.string.chapters)
|
||||||
|
2 -> getString(R.string.related)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ import androidx.viewpager2.adapter.FragmentStateAdapter
|
|||||||
|
|
||||||
class MangaDetailsAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
|
class MangaDetailsAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
|
||||||
|
|
||||||
override fun getItemCount() = 2
|
override fun getItemCount() = 3
|
||||||
|
|
||||||
override fun createFragment(position: Int): Fragment = when(position) {
|
override fun createFragment(position: Int): Fragment = when(position) {
|
||||||
0 -> MangaDetailsFragment()
|
0 -> MangaDetailsFragment()
|
||||||
1 -> ChaptersFragment()
|
1 -> ChaptersFragment()
|
||||||
|
2 -> RelatedMangaFragment()
|
||||||
else -> throw IndexOutOfBoundsException("No fragment for position $position")
|
else -> throw IndexOutOfBoundsException("No fragment for position $position")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.ui.details
|
|||||||
|
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import moxy.InjectViewState
|
import moxy.InjectViewState
|
||||||
@@ -13,6 +14,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
|||||||
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
||||||
import org.koitharu.kotatsu.domain.MangaDataRepository
|
import org.koitharu.kotatsu.domain.MangaDataRepository
|
||||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||||
|
import org.koitharu.kotatsu.domain.MangaSearchRepository
|
||||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||||
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
||||||
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||||
@@ -30,6 +32,7 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
|
|||||||
private lateinit var historyRepository: HistoryRepository
|
private lateinit var historyRepository: HistoryRepository
|
||||||
private lateinit var favouritesRepository: FavouritesRepository
|
private lateinit var favouritesRepository: FavouritesRepository
|
||||||
private lateinit var trackingRepository: TrackingRepository
|
private lateinit var trackingRepository: TrackingRepository
|
||||||
|
private lateinit var searchRepository: MangaSearchRepository
|
||||||
|
|
||||||
private var manga: Manga? = null
|
private var manga: Manga? = null
|
||||||
|
|
||||||
@@ -37,6 +40,7 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
|
|||||||
historyRepository = HistoryRepository()
|
historyRepository = HistoryRepository()
|
||||||
favouritesRepository = FavouritesRepository()
|
favouritesRepository = FavouritesRepository()
|
||||||
trackingRepository = TrackingRepository()
|
trackingRepository = TrackingRepository()
|
||||||
|
searchRepository = MangaSearchRepository()
|
||||||
super.onFirstViewAttach()
|
super.onFirstViewAttach()
|
||||||
HistoryRepository.subscribe(this)
|
HistoryRepository.subscribe(this)
|
||||||
FavouritesRepository.subscribe(this)
|
FavouritesRepository.subscribe(this)
|
||||||
@@ -147,6 +151,38 @@ class MangaDetailsPresenter private constructor() : BasePresenter<MangaDetailsVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadRelated() {
|
||||||
|
val manga = this.manga ?: return
|
||||||
|
presenterScope.launch {
|
||||||
|
viewState.onLoadingStateChanged(isLoading = true)
|
||||||
|
var isFirstCall = true
|
||||||
|
searchRepository.globalSearch(manga.title)
|
||||||
|
.map { list ->
|
||||||
|
list.filter { x -> x.id != manga.id }
|
||||||
|
}.filterNot { x -> x.isEmpty() }
|
||||||
|
.flowOn(Dispatchers.IO)
|
||||||
|
.catch { e ->
|
||||||
|
if (e is IOException) {
|
||||||
|
viewState.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onEmpty {
|
||||||
|
viewState.onListChanged(emptyList())
|
||||||
|
viewState.onLoadingStateChanged(isLoading = false)
|
||||||
|
}.onCompletion {
|
||||||
|
viewState.onListAppended(emptyList())
|
||||||
|
}.collect {
|
||||||
|
if (isFirstCall) {
|
||||||
|
isFirstCall = false
|
||||||
|
viewState.onListChanged(it)
|
||||||
|
viewState.onLoadingStateChanged(isLoading = false)
|
||||||
|
} else {
|
||||||
|
viewState.onListAppended(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onHistoryChanged() {
|
override fun onHistoryChanged() {
|
||||||
loadHistory(manga ?: return)
|
loadHistory(manga ?: return)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package org.koitharu.kotatsu.ui.details
|
package org.koitharu.kotatsu.ui.details
|
||||||
|
|
||||||
|
import moxy.viewstate.strategy.AddToEndSingleTagStrategy
|
||||||
|
import moxy.viewstate.strategy.AddToEndStrategy
|
||||||
|
import moxy.viewstate.strategy.StateStrategyType
|
||||||
import moxy.viewstate.strategy.alias.AddToEndSingle
|
import moxy.viewstate.strategy.alias.AddToEndSingle
|
||||||
import moxy.viewstate.strategy.alias.SingleState
|
import moxy.viewstate.strategy.alias.SingleState
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
@@ -23,4 +26,13 @@ interface MangaDetailsView : BaseMvpView {
|
|||||||
|
|
||||||
@AddToEndSingle
|
@AddToEndSingle
|
||||||
fun onNewChaptersChanged(newChapters: Int)
|
fun onNewChaptersChanged(newChapters: Int)
|
||||||
|
|
||||||
|
@StateStrategyType(AddToEndSingleTagStrategy::class, tag = "content")
|
||||||
|
fun onListChanged(list: List<Manga>) = Unit
|
||||||
|
|
||||||
|
@StateStrategyType(AddToEndStrategy::class, tag = "content")
|
||||||
|
fun onListAppended(list: List<Manga>) = Unit
|
||||||
|
|
||||||
|
@StateStrategyType(AddToEndSingleTagStrategy::class, tag = "content")
|
||||||
|
fun onListError(e: Throwable) = Unit
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.details
|
||||||
|
|
||||||
|
import moxy.ktx.moxyPresenter
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import org.koitharu.kotatsu.core.model.Manga
|
||||||
|
import org.koitharu.kotatsu.core.model.MangaHistory
|
||||||
|
import org.koitharu.kotatsu.ui.list.MangaListFragment
|
||||||
|
|
||||||
|
class RelatedMangaFragment : MangaListFragment<Unit>(), MangaDetailsView {
|
||||||
|
|
||||||
|
private val presenter by moxyPresenter(factory = MangaDetailsPresenter.Companion::getInstance)
|
||||||
|
|
||||||
|
override fun onRequestMoreItems(offset: Int) {
|
||||||
|
if (offset == 0) {
|
||||||
|
presenter.loadRelated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMangaUpdated(manga: Manga) = Unit
|
||||||
|
|
||||||
|
override fun onHistoryChanged(history: MangaHistory?) = Unit
|
||||||
|
|
||||||
|
override fun onFavouriteChanged(categories: List<FavouriteCategory>) = Unit
|
||||||
|
|
||||||
|
override fun onMangaRemoved(manga: Manga) = Unit
|
||||||
|
|
||||||
|
override fun onNewChaptersChanged(newChapters: Int) = Unit
|
||||||
|
|
||||||
|
override fun onListChanged(list: List<Manga>) = super<MangaListFragment>.onListChanged(list)
|
||||||
|
|
||||||
|
override fun onListAppended(list: List<Manga>) = super<MangaListFragment>.onListAppended(list)
|
||||||
|
|
||||||
|
override fun onListError(e: Throwable) = super<MangaListFragment>.onListError(e)
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ class GlobalSearchPresenter : BasePresenter<MangaListView<Unit>>() {
|
|||||||
super.onFirstViewAttach()
|
super.onFirstViewAttach()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
|
||||||
fun startSearch(query: String) {
|
fun startSearch(query: String) {
|
||||||
presenterScope.launch {
|
presenterScope.launch {
|
||||||
viewState.onLoadingStateChanged(isLoading = true)
|
viewState.onLoadingStateChanged(isLoading = true)
|
||||||
|
|||||||
@@ -134,6 +134,7 @@
|
|||||||
<string name="favourites_category_empty">В этой категории ничего нет</string>
|
<string name="favourites_category_empty">В этой категории ничего нет</string>
|
||||||
<string name="read_later">Прочитать позже</string>
|
<string name="read_later">Прочитать позже</string>
|
||||||
<string name="updates">Обновления</string>
|
<string name="updates">Обновления</string>
|
||||||
<string name="text_feed_holder">Here you will see manga updates</string>
|
<string name="text_feed_holder">Здесь будут отображаться обновления манги, которую Вы читаете</string>
|
||||||
<string name="search_results">Результаты поиска</string>
|
<string name="search_results">Результаты поиска</string>
|
||||||
|
<string name="related">Похожие</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -135,6 +135,7 @@
|
|||||||
<string name="favourites_category_empty">This category is empty</string>
|
<string name="favourites_category_empty">This category is empty</string>
|
||||||
<string name="read_later">Read later</string>
|
<string name="read_later">Read later</string>
|
||||||
<string name="updates">Updates</string>
|
<string name="updates">Updates</string>
|
||||||
<string name="text_feed_holder">Here you will see manga updates</string>
|
<string name="text_feed_holder">Here you will see the new chapters of the manga you are reading</string>
|
||||||
<string name="search_results">Search results</string>
|
<string name="search_results">Search results</string>
|
||||||
|
<string name="related">Related</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user