diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt index 24ad5443e..fd7ff3f26 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/HistoryDao.kt @@ -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 + @Query("SELECT * FROM history WHERE manga_id = :id") + abstract suspend fun getOneOrNull(id: Long): HistoryEntity? + @Query("DELETE FROM history") abstract suspend fun clear() diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt index cacc6a872..7b530bd2d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt @@ -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() } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersFragment.kt index 55ab25a29..dde6da6aa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersFragment.kt @@ -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? = 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) { + 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 + ) + ) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt index 0acc41cdb..b7905c0ac 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt @@ -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) { + title = data.manga.title } override fun onLoadingStateChanged(isLoading: Boolean) = Unit diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt index 1f1f70116..9a3a0298b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsFragment.kt @@ -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) { + 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) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsPresenter.kt index 8898b2ce1..8cfb8dc65 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsPresenter.kt @@ -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() { 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) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsView.kt index 060936af4..e015ed13a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsView.kt @@ -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) @StateStrategyType(AddToEndSingleStrategy::class) fun onLoadingStateChanged(isLoading: Boolean) diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 2fd4b74fb..438931b62 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,17 +1,20 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_play.xml b/app/src/main/res/drawable/ic_play.xml new file mode 100644 index 000000000..8c3442fac --- /dev/null +++ b/app/src/main/res/drawable/ic_play.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_read.xml b/app/src/main/res/drawable/ic_read.xml new file mode 100644 index 000000000..3829a78f3 --- /dev/null +++ b/app/src/main/res/drawable/ic_read.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout/fragment_details.xml b/app/src/main/res/layout/fragment_details.xml index 7f5037b8e..4f36958a3 100644 --- a/app/src/main/res/layout/fragment_details.xml +++ b/app/src/main/res/layout/fragment_details.xml @@ -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" /> + + + app:constraint_referenced_ids="imageView_cover, button_read" /> + + Clear history Nothing found History is empty + Read + Continue \ No newline at end of file