Update details activity

This commit is contained in:
Admin
2020-02-02 13:15:47 +02:00
parent 6eea278b4d
commit ef32c49310
13 changed files with 154 additions and 45 deletions

View File

@@ -16,6 +16,9 @@ abstract class HistoryDao {
@Query("SELECT * FROM history ORDER BY :orderBy LIMIT :limit OFFSET :offset")
abstract suspend fun getAll(offset: Int, limit: Int, orderBy: String): List<HistoryWithManga>
@Query("SELECT * FROM history WHERE manga_id = :id")
abstract suspend fun getOneOrNull(id: Long): HistoryEntity?
@Query("DELETE FROM history")
abstract suspend fun clear()

View File

@@ -8,6 +8,7 @@ import org.koitharu.kotatsu.core.db.entity.HistoryWithManga
import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.model.*
import java.io.Closeable
import java.util.*
class HistoryRepository() : KoinComponent, MangaRepository, Closeable {
@@ -61,6 +62,17 @@ class HistoryRepository() : KoinComponent, MangaRepository, Closeable {
)
}
suspend fun getHistory(manga: Manga): MangaHistory? {
return db.historyDao().getOneOrNull(manga.id)?.let {
MangaHistory(
createdAt = Date(it.createdAt),
updatedAt = Date(it.updatedAt),
chapterId = it.chapterId,
page = it.page
)
}
}
suspend fun clear() {
db.historyDao().clear()
}

View File

@@ -8,8 +8,9 @@ import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_chapters.*
import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaInfo
import org.koitharu.kotatsu.ui.common.BaseFragment
import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener
import org.koitharu.kotatsu.ui.reader.ReaderActivity
@@ -20,20 +21,25 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV
@Suppress("unused")
private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter }
private var manga: Manga? = null
private var data: MangaInfo<MangaHistory?>? = null
private lateinit var adapter: ChaptersAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = ChaptersAdapter(this)
recyclerView_chapters.addItemDecoration(DividerItemDecoration(view.context, RecyclerView.VERTICAL))
recyclerView_chapters.addItemDecoration(
DividerItemDecoration(
view.context,
RecyclerView.VERTICAL
)
)
recyclerView_chapters.adapter = adapter
}
override fun onMangaUpdated(manga: Manga) {
this.manga = manga
adapter.replaceData(manga.chapters.orEmpty())
override fun onMangaUpdated(data: MangaInfo<MangaHistory?>) {
this.data = data
adapter.replaceData(data.manga.chapters.orEmpty())
}
override fun onLoadingStateChanged(isLoading: Boolean) {
@@ -45,10 +51,12 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV
}
override fun onItemClick(item: MangaChapter, position: Int, view: View) {
startActivity(ReaderActivity.newIntent(
context ?: return,
manga ?: return,
item.id
))
startActivity(
ReaderActivity.newIntent(
context ?: return,
data?.manga ?: return,
item.id
)
)
}
}

View File

@@ -8,6 +8,8 @@ import kotlinx.android.synthetic.main.activity_details.*
import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaInfo
import org.koitharu.kotatsu.ui.common.BaseActivity
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
@@ -26,8 +28,8 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
} ?: finish()
}
override fun onMangaUpdated(manga: Manga) {
title = manga.title
override fun onMangaUpdated(data: MangaInfo<MangaHistory?>) {
title = data.manga.title
}
override fun onLoadingStateChanged(isLoading: Boolean) = Unit

View File

@@ -6,7 +6,10 @@ import kotlinx.android.synthetic.main.fragment_details.*
import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaInfo
import org.koitharu.kotatsu.ui.common.BaseFragment
import org.koitharu.kotatsu.ui.reader.ReaderActivity
import org.koitharu.kotatsu.utils.ext.setChips
import kotlin.math.roundToInt
@@ -15,24 +18,46 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
@Suppress("unused")
private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter }
override fun onMangaUpdated(manga: Manga) {
imageView_cover.load(manga.largeCoverUrl ?: manga.coverUrl)
textView_title.text = manga.title
textView_subtitle.text = manga.localizedTitle
textView_description.text = manga.description
if (manga.rating == Manga.NO_RATING) {
override fun onMangaUpdated(data: MangaInfo<MangaHistory?>) {
imageView_cover.load(data.manga.largeCoverUrl ?: data.manga.coverUrl)
textView_title.text = data.manga.title
textView_subtitle.text = data.manga.localizedTitle
textView_description.text = data.manga.description
if (data.manga.rating == Manga.NO_RATING) {
ratingBar.isVisible = false
} else {
ratingBar.progress = (ratingBar.max * manga.rating).roundToInt()
ratingBar.progress = (ratingBar.max * data.manga.rating).roundToInt()
ratingBar.isVisible = true
}
chips_tags.setChips(manga.tags) {
chips_tags.setChips(data.manga.tags) {
create(
text = it.title,
iconRes = R.drawable.ic_chip_tag,
tag = it
)
}
if (data.manga.chapters.isNullOrEmpty()) {
button_read.isEnabled = false
} else {
button_read.isEnabled = true
if (data.extra == null) {
button_read.setText(R.string.read)
button_read.setIconResource(R.drawable.ic_read)
} else {
button_read.setText(R.string.continue_)
button_read.setIconResource(R.drawable.ic_play)
}
val chapterId = data.extra?.chapterId ?: data.manga.chapters.first().id
button_read.setOnClickListener {
startActivity(
ReaderActivity.newIntent(
context ?: return@setOnClickListener,
data.manga,
chapterId
)
)
}
}
}
override fun onLoadingStateChanged(isLoading: Boolean) {

View File

@@ -1,11 +1,14 @@
package org.koitharu.kotatsu.ui.details
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import moxy.InjectViewState
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaInfo
import org.koitharu.kotatsu.domain.HistoryRepository
import org.koitharu.kotatsu.domain.MangaProviderFactory
import org.koitharu.kotatsu.ui.common.BasePresenter
@@ -18,14 +21,20 @@ class MangaDetailsPresenter : BasePresenter<MangaDetailsView>() {
if (isLoaded) {
return
}
viewState.onMangaUpdated(manga)
viewState.onMangaUpdated(MangaInfo(manga, null))
launch {
try {
viewState.onLoadingStateChanged(true)
val details = withContext(Dispatchers.IO) {
MangaProviderFactory.create(manga.source).getDetails(manga)
val data = withContext(Dispatchers.IO) {
val details = async {
MangaProviderFactory.create(manga.source).getDetails(manga)
}
val history = async {
HistoryRepository().use { it.getHistory(manga) }
}
MangaInfo(details.await(), history.await())
}
viewState.onMangaUpdated(details)
viewState.onMangaUpdated(data)
isLoaded = true
} catch (e: Exception) {
if (BuildConfig.DEBUG) {

View File

@@ -4,12 +4,13 @@ import moxy.MvpView
import moxy.viewstate.strategy.AddToEndSingleStrategy
import moxy.viewstate.strategy.OneExecutionStateStrategy
import moxy.viewstate.strategy.StateStrategyType
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaInfo
interface MangaDetailsView : MvpView {
@StateStrategyType(AddToEndSingleStrategy::class)
fun onMangaUpdated(manga: Manga)
fun onMangaUpdated(data: MangaInfo<MangaHistory?>)
@StateStrategyType(AddToEndSingleStrategy::class)
fun onLoadingStateChanged(isLoading: Boolean)

View File

@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#0D47A1">
<group android:scaleX="0.40188664"
android:scaleY="0.40188664"
android:translateX="32.90095"
android:translateY="18.7272">
<group android:translateY="139.39206">
<path android:pathData="M83.796875,-0L105.6875,-0L60.765625,-55.828125L103.09375,-101L82.078125,-101L32.25,-49.1875L32.25,-101L13.53125,-101L13.53125,-0L32.25,-0L32.25,-25.8125L48.234375,-42.265625L83.796875,-0Z"
android:fillColor="#0D47A1"/>
</group>
</group>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:tint="#0D47A1"
android:viewportWidth="108"
android:viewportHeight="108">
<group
android:scaleX="0.40188664"
android:scaleY="0.40188664"
android:translateX="32.90095"
android:translateY="18.7272">
<group android:translateY="139.39206">
<path
android:fillColor="#0D47A1"
android:pathData="M83.796875,-0L105.6875,-0L60.765625,-55.828125L103.09375,-101L82.078125,-101L32.25,-49.1875L32.25,-101L13.53125,-101L13.53125,-0L32.25,-0L32.25,-25.8125L48.234375,-42.265625L83.796875,-0Z" />
</group>
</group>
</vector>

View File

@@ -0,0 +1,11 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M10,8.64L15.27,12 10,15.36V8.64M8,5v14l11,-7L8,5z" />
</vector>

View File

@@ -0,0 +1,11 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M12,9c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,3c1.1,0 2,0.9 2,2s-0.9,2 -2,2 -2,-0.9 -2,-2 0.9,-2 2,-2zM12,11.55C9.64,9.35 6.48,8 3,8v11c3.48,0 6.64,1.35 9,3.55 2.36,-2.19 5.52,-3.55 9,-3.55L21,8c-3.48,0 -6.64,1.35 -9,3.55zM19,17.13c-2.53,0.34 -4.93,1.3 -7,2.82 -2.06,-1.52 -4.47,-2.49 -7,-2.83v-6.95c2.1,0.38 4.05,1.35 5.64,2.83L12,14.28l1.36,-1.27c1.59,-1.48 3.54,-2.45 5.64,-2.83v6.95z" />
</vector>

View File

@@ -55,16 +55,31 @@
android:layout_marginTop="10dp"
android:isIndicator="true"
android:max="100"
tools:progress="70"
app:layout_constraintStart_toStartOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/textView_subtitle" />
app:layout_constraintTop_toBottomOf="@id/textView_subtitle"
tools:progress="70" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/read"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:icon="@drawable/ic_read"
app:iconPadding="12dp"
android:enabled="false"
android:layout_marginEnd="4dp"
app:layout_constraintBottom_toBottomOf="@id/imageView_cover"
app:layout_constraintEnd_toEndOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/ratingBar"
app:layout_constraintVertical_bias="1" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="imageView_cover, textView_subtitle, ratingBar" />
app:constraint_referenced_ids="imageView_cover, button_read" />
<com.google.android.material.chip.ChipGroup
android:id="@+id/chips_tags"

View File

@@ -4,6 +4,13 @@
android:layout_width="match_parent"
android:layout_height="92dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground"
android:layout_alignParentStart="true"
android:layout_centerVertical="true" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"

View File

@@ -22,4 +22,6 @@
<string name="clear_history">Clear history</string>
<string name="nothing_found">Nothing found</string>
<string name="history_is_empty">History is empty</string>
<string name="read">Read</string>
<string name="continue_">Continue</string>
</resources>