From aa65f9b02c39091afa42712d5ddae1fe5f6ebe85 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 2 Feb 2020 16:31:50 +0200 Subject: [PATCH] Update history repository --- .../koitharu/kotatsu/core/model/MangaInfo.kt | 6 -- .../koitharu/kotatsu/domain/ChapterExtra.kt | 6 ++ .../kotatsu/domain/HistoryRepository.kt | 41 +--------- .../ui/common/list/BaseRecyclerAdapter.kt | 20 +++-- .../kotatsu/ui/common/list/BaseViewHolder.kt | 10 +-- .../kotatsu/ui/details/ChapterHolder.kt | 25 ++++++- .../kotatsu/ui/details/ChaptersAdapter.kt | 19 ++++- .../kotatsu/ui/details/ChaptersFragment.kt | 18 +++-- .../ui/details/MangaDetailsActivity.kt | 15 +++- .../kotatsu/ui/details/MangaDetailsAdapter.kt | 2 +- .../ui/details/MangaDetailsFragment.kt | 55 ++++++++------ .../ui/details/MangaDetailsPresenter.kt | 38 +++++++--- .../kotatsu/ui/details/MangaDetailsView.kt | 7 +- .../kotatsu/ui/main/list/MangaGridHolder.kt | 11 +-- .../kotatsu/ui/main/list/MangaListAdapter.kt | 15 ++-- .../ui/main/list/MangaListDetailsHolder.kt | 18 ++--- .../kotatsu/ui/main/list/MangaListFragment.kt | 14 ++-- .../kotatsu/ui/main/list/MangaListHolder.kt | 13 ++-- .../kotatsu/ui/main/list/MangaListView.kt | 6 +- .../main/list/history/HistoryListPresenter.kt | 8 +- .../main/list/remote/RemoteListPresenter.kt | 2 - .../koitharu/kotatsu/ui/reader/PageHolder.kt | 6 +- .../kotatsu/ui/reader/PagesAdapter.kt | 4 +- .../kotatsu/ui/reader/ReaderActivity.kt | 75 ++++++++++++------- .../kotatsu/ui/reader/ReaderPresenter.kt | 20 +++-- .../koitharu/kotatsu/ui/reader/ReaderState.kt | 20 +++++ .../koitharu/kotatsu/ui/reader/ReaderView.kt | 2 +- app/src/main/res/drawable/bg_badge_accent.xml | 11 +++ ...bg_round_rect.xml => bg_badge_default.xml} | 0 .../main/res/drawable/bg_badge_outline.xml | 13 ++++ .../res/drawable/bg_badge_outline_accent.xml | 13 ++++ app/src/main/res/layout/fragment_details.xml | 8 +- app/src/main/res/layout/item_chapter.xml | 2 +- 33 files changed, 331 insertions(+), 192 deletions(-) delete mode 100644 app/src/main/java/org/koitharu/kotatsu/core/model/MangaInfo.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/domain/ChapterExtra.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt create mode 100644 app/src/main/res/drawable/bg_badge_accent.xml rename app/src/main/res/drawable/{bg_round_rect.xml => bg_badge_default.xml} (100%) create mode 100644 app/src/main/res/drawable/bg_badge_outline.xml create mode 100644 app/src/main/res/drawable/bg_badge_outline_accent.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaInfo.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaInfo.kt deleted file mode 100644 index 3871a462f..000000000 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaInfo.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.koitharu.kotatsu.core.model - -data class MangaInfo ( - val manga: Manga, - val extra: E -) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/ChapterExtra.kt b/app/src/main/java/org/koitharu/kotatsu/domain/ChapterExtra.kt new file mode 100644 index 000000000..bd0d15d15 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/domain/ChapterExtra.kt @@ -0,0 +1,6 @@ +package org.koitharu.kotatsu.domain + +enum class ChapterExtra { + + READ, CURRENT, UNREAD, NEW +} \ No newline at end of file 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 2b094d923..a3ecc59a4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/HistoryRepository.kt @@ -11,44 +11,15 @@ import org.koitharu.kotatsu.core.parser.MangaRepository import java.io.Closeable import java.util.* -class HistoryRepository() : KoinComponent, - MangaRepository, Closeable { +class HistoryRepository() : KoinComponent { private val db: MangaDatabase by inject() - override val sortOrders: Set = setOf(SortOrder.NEWEST, SortOrder.POPULARITY) - - override val isSearchAvailable = false - - override suspend fun getList( - offset: Int, - query: String?, - sortOrder: SortOrder?, - tag: MangaTag? - ): List = getHistory(offset, query, sortOrder, tag).map { x -> x.manga } - - suspend fun getHistory( - offset: Int, - query: String? = null, - sortOrder: SortOrder? = null, - tag: MangaTag? = null - ): List> { + suspend fun getList(offset: Int) : List { val entities = db.historyDao().getAll(offset, 20, "updated_by") - return entities.map { x -> MangaInfo(x.manga.toManga(), x.history.toMangaHistory()) } + return entities.map { it.manga.toManga() } } - override suspend fun getDetails(manga: Manga): Manga { - throw UnsupportedOperationException("History repository does not support getDetails() method") - } - - override suspend fun getPages(chapter: MangaChapter): List { - throw UnsupportedOperationException("History repository does not support getPages() method") - } - - override suspend fun getPageFullUrl(page: MangaPage) = page.url - - override suspend fun getTags() = emptySet() - suspend fun addOrUpdate(manga: Manga, chapterId: Long, page: Int) { val dao = db.historyDao() val entity = HistoryEntity( @@ -66,7 +37,7 @@ class HistoryRepository() : KoinComponent, ) } - suspend fun getHistory(manga: Manga): MangaHistory? { + suspend fun getOne(manga: Manga): MangaHistory? { return db.historyDao().getOneOrNull(manga.id)?.let { MangaHistory( createdAt = Date(it.createdAt), @@ -80,8 +51,4 @@ class HistoryRepository() : KoinComponent, suspend fun clear() { db.historyDao().clear() } - - override fun close() { - db.close() - } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt index 55559eae2..7f1aebd18 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt @@ -5,8 +5,8 @@ import androidx.recyclerview.widget.RecyclerView import org.koin.core.KoinComponent import org.koitharu.kotatsu.utils.ext.replaceWith -abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecyclerItemClickListener? = null) : - RecyclerView.Adapter>(), +abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecyclerItemClickListener? = null) : + RecyclerView.Adapter>(), KoinComponent { private val dataSet = ArrayList() @@ -16,8 +16,9 @@ abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecycle setHasStableIds(true) } - override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { - holder.bind(dataSet[position]) + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + val item = dataSet[position] + holder.bind(item, getExtra(item, position)) } fun getItem(position: Int) = dataSet[position] @@ -64,13 +65,16 @@ abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecycle final override fun getItemCount() = dataSet.size - final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { - return onCreateViewHolder(parent).setOnItemClickListener(onItemClickListener).also(this::onViewHolderCreated) + final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { + return onCreateViewHolder(parent).setOnItemClickListener(onItemClickListener) + .also(this::onViewHolderCreated) } - protected open fun onViewHolderCreated(holder: BaseViewHolder) = Unit + protected abstract fun getExtra(item: T, position: Int): E - protected abstract fun onCreateViewHolder(parent: ViewGroup): BaseViewHolder + protected open fun onViewHolderCreated(holder: BaseViewHolder) = Unit + + protected abstract fun onCreateViewHolder(parent: ViewGroup): BaseViewHolder protected abstract fun onGetItemId(item: T): Long } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt index 321afa285..2f9a25f13 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt @@ -8,7 +8,7 @@ import kotlinx.android.extensions.LayoutContainer import org.koin.core.KoinComponent import org.koitharu.kotatsu.utils.ext.inflate -abstract class BaseViewHolder protected constructor(view: View) : +abstract class BaseViewHolder protected constructor(view: View) : RecyclerView.ViewHolder(view), LayoutContainer, KoinComponent { constructor(parent: ViewGroup, @LayoutRes resId: Int) : this(parent.inflate(resId)) @@ -21,14 +21,14 @@ abstract class BaseViewHolder protected constructor(view: View) : val context get() = itemView.context!! - fun bind(data: T) { + fun bind(data: T, extra: E) { boundData = data - onBind(data) + onBind(data, extra) } fun requireData() = boundData ?: throw IllegalStateException("Calling requireData() before bind()") - fun setOnItemClickListener(listener: OnRecyclerItemClickListener?): BaseViewHolder { + fun setOnItemClickListener(listener: OnRecyclerItemClickListener?): BaseViewHolder { if (listener != null) { itemView.setOnClickListener { listener.onItemClick(boundData ?: return@setOnClickListener, adapterPosition, it) @@ -40,5 +40,5 @@ abstract class BaseViewHolder protected constructor(view: View) : return this } - abstract fun onBind(data: T) + abstract fun onBind(data: T, extra: E) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChapterHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChapterHolder.kt index 84fa9632e..7d766c8cd 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChapterHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChapterHolder.kt @@ -4,12 +4,33 @@ import android.view.ViewGroup import kotlinx.android.synthetic.main.item_chapter.* import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.MangaChapter +import org.koitharu.kotatsu.domain.ChapterExtra import org.koitharu.kotatsu.ui.common.list.BaseViewHolder +import org.koitharu.kotatsu.utils.ext.getThemeColor -class ChapterHolder(parent: ViewGroup) : BaseViewHolder(parent, R.layout.item_chapter) { +class ChapterHolder(parent: ViewGroup) : + BaseViewHolder(parent, R.layout.item_chapter) { - override fun onBind(data: MangaChapter) { + override fun onBind(data: MangaChapter, extra: ChapterExtra) { textView_title.text = data.name textView_number.text = data.number.toString() + when (extra) { + ChapterExtra.UNREAD -> { + textView_number.setBackgroundResource(R.drawable.bg_badge_default) + textView_number.setTextColor(context.getThemeColor(android.R.attr.textColorSecondaryInverse)) + } + ChapterExtra.READ -> { + textView_number.setBackgroundResource(R.drawable.bg_badge_outline) + textView_number.setTextColor(context.getThemeColor(android.R.attr.textColorTertiary)) + } + ChapterExtra.CURRENT -> { + textView_number.setBackgroundResource(R.drawable.bg_badge_outline_accent) + textView_number.setTextColor(context.getThemeColor(R.attr.colorAccent)) + } + ChapterExtra.NEW -> { + textView_number.setBackgroundResource(R.drawable.bg_badge_accent) + textView_number.setTextColor(context.getThemeColor(android.R.attr.textColorPrimaryInverse)) + } + } } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersAdapter.kt index e3924fdef..a3c080489 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/ChaptersAdapter.kt @@ -1,15 +1,32 @@ package org.koitharu.kotatsu.ui.details import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaChapter +import org.koitharu.kotatsu.domain.ChapterExtra import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter +import org.koitharu.kotatsu.ui.common.list.BaseViewHolder import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener class ChaptersAdapter(onItemClickListener: OnRecyclerItemClickListener) : - BaseRecyclerAdapter(onItemClickListener) { + BaseRecyclerAdapter(onItemClickListener) { + + var currentChapterPosition = RecyclerView.NO_POSITION + set(value) { + field = value + notifyDataSetChanged() + } override fun onCreateViewHolder(parent: ViewGroup) = ChapterHolder(parent) override fun onGetItemId(item: MangaChapter) = item.id + + override fun getExtra(item: MangaChapter, position: Int): ChapterExtra = when { + currentChapterPosition == RecyclerView.NO_POSITION -> ChapterExtra.UNREAD + currentChapterPosition == position -> ChapterExtra.CURRENT + currentChapterPosition < position -> ChapterExtra.UNREAD + currentChapterPosition > position -> ChapterExtra.READ + else -> ChapterExtra.UNREAD + } } \ No newline at end of file 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 dde6da6aa..7adc3a0bb 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,9 +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 @@ -21,7 +21,7 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV @Suppress("unused") private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter } - private var data: MangaInfo? = null + private var manga: Manga? = null private lateinit var adapter: ChaptersAdapter @@ -37,9 +37,9 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV recyclerView_chapters.adapter = adapter } - override fun onMangaUpdated(data: MangaInfo) { - this.data = data - adapter.replaceData(data.manga.chapters.orEmpty()) + override fun onMangaUpdated(manga: Manga) { + this.manga = manga + adapter.replaceData(manga.chapters.orEmpty()) } override fun onLoadingStateChanged(isLoading: Boolean) { @@ -50,11 +50,17 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV } + override fun onHistoryChanged(history: MangaHistory?) { + adapter.currentChapterPosition = history?.let { + manga?.chapters?.indexOfFirst { x -> x.id == it.chapterId } + } ?: RecyclerView.NO_POSITION + } + override fun onItemClick(item: MangaChapter, position: Int, view: View) { startActivity( ReaderActivity.newIntent( context ?: return, - data?.manga ?: return, + manga ?: return, item.id ) ) 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 b7905c0ac..ca5a56a05 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 @@ -9,7 +9,6 @@ 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 @@ -25,13 +24,23 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView { tabs.setupWithViewPager(pager) intent?.getParcelableExtra(EXTRA_MANGA)?.let { presenter.loadDetails(it) + presenter.loadHistory(it) } ?: finish() } - override fun onMangaUpdated(data: MangaInfo) { - title = data.manga.title + override fun onResume() { + super.onResume() + intent?.getParcelableExtra(EXTRA_MANGA)?.let { + presenter.loadHistory(it) + } + } + + override fun onMangaUpdated(manga: Manga) { + title = manga.title } + override fun onHistoryChanged(history: MangaHistory?) = Unit + override fun onLoadingStateChanged(isLoading: Boolean) = Unit override fun onError(e: Exception) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsAdapter.kt index 8b885165d..94c018bc3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsAdapter.kt @@ -6,7 +6,7 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import org.koitharu.kotatsu.R -class MangaDetailsAdapter(private val resources: Resources, fm: FragmentManager) : FragmentPagerAdapter(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { +class MangaDetailsAdapter(private val resources: Resources, fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getCount() = 2 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 b5e1b3281..d072e9d10 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 @@ -8,7 +8,6 @@ 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 @@ -19,53 +18,65 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai @Suppress("unused") private val presenter by moxyPresenter { (activity as MangaDetailsActivity).presenter } - 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?.parseAsHtml() - if (data.manga.rating == Manga.NO_RATING) { + private var manga: Manga? = null + private var history: MangaHistory? = null + + override fun onMangaUpdated(manga: Manga) { + this.manga = manga + imageView_cover.load(manga.largeCoverUrl ?: manga.coverUrl) + textView_title.text = manga.title + textView_subtitle.text = manga.localizedTitle + textView_description.text = manga.description?.parseAsHtml() + if (manga.rating == Manga.NO_RATING) { ratingBar.isVisible = false } else { - ratingBar.progress = (ratingBar.max * data.manga.rating).roundToInt() + ratingBar.progress = (ratingBar.max * manga.rating).roundToInt() ratingBar.isVisible = true } - chips_tags.setChips(data.manga.tags) { + chips_tags.setChips(manga.tags) { create( text = it.title, iconRes = R.drawable.ic_chip_tag, tag = it ) } - if (data.manga.chapters.isNullOrEmpty()) { + updateReadButton() + } + + override fun onHistoryChanged(history: MangaHistory?) { + this.history = history + updateReadButton() + } + + override fun onLoadingStateChanged(isLoading: Boolean) { + progressBar.isVisible = isLoading + } + + override fun onError(e: Exception) { + + } + + private fun updateReadButton() { + if (manga?.chapters.isNullOrEmpty()) { button_read.isEnabled = false } else { button_read.isEnabled = true - if (data.extra == null) { + if (history == 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 + manga ?: return@setOnClickListener, + history ) ) } } } - - override fun onLoadingStateChanged(isLoading: Boolean) { - progressBar.isVisible = isLoading - } - - override fun onError(e: Exception) { - - } } \ No newline at end of file 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 8cfb8dc65..7c043f519 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,13 +1,11 @@ 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 @@ -15,24 +13,25 @@ import org.koitharu.kotatsu.ui.common.BasePresenter @InjectViewState class MangaDetailsPresenter : BasePresenter() { + private lateinit var historyRepository: HistoryRepository + private var isLoaded = false - fun loadDetails(manga: Manga) { - if (isLoaded) { + override fun onFirstViewAttach() { + historyRepository = HistoryRepository() + super.onFirstViewAttach() + } + + fun loadDetails(manga: Manga, force: Boolean = false) { + if (!force && isLoaded) { return } - viewState.onMangaUpdated(MangaInfo(manga, null)) + viewState.onMangaUpdated(manga) launch { try { viewState.onLoadingStateChanged(true) 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()) + MangaProviderFactory.create(manga.source).getDetails(manga) } viewState.onMangaUpdated(data) isLoaded = true @@ -46,4 +45,19 @@ class MangaDetailsPresenter : BasePresenter() { } } } + + fun loadHistory(manga: Manga) { + launch { + try { + val history = withContext(Dispatchers.IO) { + historyRepository.getOne(manga) + } + viewState.onHistoryChanged(history) + } catch (e: Exception) { + if (BuildConfig.DEBUG) { + e.printStackTrace() + } + } + } + } } \ No newline at end of file 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 e015ed13a..13a9b290a 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,17 +4,20 @@ 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(data: MangaInfo) + fun onMangaUpdated(manga: Manga) @StateStrategyType(AddToEndSingleStrategy::class) fun onLoadingStateChanged(isLoading: Boolean) @StateStrategyType(OneExecutionStateStrategy::class) fun onError(e: Exception) + + @StateStrategyType(AddToEndSingleStrategy::class) + fun onHistoryChanged(history: MangaHistory?) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaGridHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaGridHolder.kt index 60eda6c6a..0a3a8f740 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaGridHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaGridHolder.kt @@ -5,17 +5,18 @@ import coil.api.load import coil.request.RequestDisposable import kotlinx.android.synthetic.main.item_manga_grid.* import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.Manga +import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.ui.common.list.BaseViewHolder -class MangaGridHolder(parent: ViewGroup) : BaseViewHolder>(parent, R.layout.item_manga_grid) { +class MangaGridHolder(parent: ViewGroup) : BaseViewHolder(parent, R.layout.item_manga_grid) { private var coverRequest: RequestDisposable? = null - override fun onBind(data: MangaInfo) { + override fun onBind(data: Manga, extra: MangaHistory?) { coverRequest?.dispose() - textView_title.text = data.manga.title - coverRequest = imageView_cover.load(data.manga.coverUrl) { + textView_title.text = data.title + coverRequest = imageView_cover.load(data.coverUrl) { crossfade(true) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListAdapter.kt index ea0568cbb..42b3a48bf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListAdapter.kt @@ -1,21 +1,24 @@ package org.koitharu.kotatsu.ui.main.list import android.view.ViewGroup -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.Manga +import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener -class MangaListAdapter(onItemClickListener: OnRecyclerItemClickListener>) : - BaseRecyclerAdapter>(onItemClickListener) { +class MangaListAdapter(onItemClickListener: OnRecyclerItemClickListener) : + BaseRecyclerAdapter(onItemClickListener) { var listMode: ListMode = ListMode.LIST override fun onCreateViewHolder(parent: ViewGroup) = when(listMode) { - ListMode.LIST -> MangaListHolder(parent) - ListMode.DETAILED_LIST -> MangaListDetailsHolder(parent) + ListMode.LIST -> MangaListHolder(parent) + ListMode.DETAILED_LIST -> MangaListDetailsHolder(parent) ListMode.GRID -> MangaGridHolder(parent) } - override fun onGetItemId(item: MangaInfo) = item.manga.id + override fun onGetItemId(item: Manga) = item.id + + override fun getExtra(item: Manga, position: Int): MangaHistory? = null } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListDetailsHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListDetailsHolder.kt index ddf0428b7..7850f40dc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListDetailsHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListDetailsHolder.kt @@ -8,30 +8,30 @@ import coil.request.RequestDisposable import kotlinx.android.synthetic.main.item_manga_list_details.* import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.Manga -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.ui.common.list.BaseViewHolder import org.koitharu.kotatsu.utils.ext.textAndVisible import kotlin.math.roundToInt -class MangaListDetailsHolder(parent: ViewGroup) : BaseViewHolder>(parent, R.layout.item_manga_list_details) { +class MangaListDetailsHolder(parent: ViewGroup) : BaseViewHolder(parent, R.layout.item_manga_list_details) { private var coverRequest: RequestDisposable? = null @SuppressLint("SetTextI18n") - override fun onBind(data: MangaInfo) { + override fun onBind(data: Manga, extra: MangaHistory?) { coverRequest?.dispose() - textView_title.text = data.manga.title - textView_subtitle.textAndVisible = data.manga.localizedTitle - coverRequest = imageView_cover.load(data.manga.coverUrl) { + textView_title.text = data.title + textView_subtitle.textAndVisible = data.localizedTitle + coverRequest = imageView_cover.load(data.coverUrl) { crossfade(true) } - if(data.manga.rating == Manga.NO_RATING) { + if(data.rating == Manga.NO_RATING) { textView_rating.isVisible = false } else { - textView_rating.text = "${(data.manga.rating * 10).roundToInt()}/10" + textView_rating.text = "${(data.rating * 10).roundToInt()}/10" textView_rating.isVisible = true } - textView_tags.text = data.manga.tags.joinToString(", ") { + textView_tags.text = data.tags.joinToString(", ") { it.title } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt index 2378a8ffe..a6e7c4c37 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.fragment_list.* import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.ui.common.BaseFragment import org.koitharu.kotatsu.ui.common.list.OnRecyclerItemClickListener @@ -27,9 +27,9 @@ import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.hasItems abstract class MangaListFragment : BaseFragment(R.layout.fragment_list), MangaListView, - PaginationScrollListener.Callback, OnRecyclerItemClickListener> { + PaginationScrollListener.Callback, OnRecyclerItemClickListener { - private lateinit var adapter: MangaListAdapter + private lateinit var adapter: MangaListAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -73,16 +73,16 @@ abstract class MangaListFragment : BaseFragment(R.layout.fragment_list), Man else -> super.onOptionsItemSelected(item) } - override fun onItemClick(item: MangaInfo, position: Int, view: View) { - startActivity(MangaDetailsActivity.newIntent(context ?: return, item.manga)) + override fun onItemClick(item: Manga, position: Int, view: View) { + startActivity(MangaDetailsActivity.newIntent(context ?: return, item)) } - override fun onListChanged(list: List>) { + override fun onListChanged(list: List) { adapter.replaceData(list) layout_holder.isVisible = list.isEmpty() } - override fun onListAppended(list: List>) { + override fun onListAppended(list: List) { adapter.appendData(list) } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListHolder.kt index 1405fadc9..6e4e7827e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListHolder.kt @@ -5,19 +5,20 @@ import coil.api.load import coil.request.RequestDisposable import kotlinx.android.synthetic.main.item_manga_list.* import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.Manga +import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.ui.common.list.BaseViewHolder import org.koitharu.kotatsu.utils.ext.textAndVisible -class MangaListHolder(parent: ViewGroup) : BaseViewHolder>(parent, R.layout.item_manga_list) { +class MangaListHolder(parent: ViewGroup) : BaseViewHolder(parent, R.layout.item_manga_list) { private var coverRequest: RequestDisposable? = null - override fun onBind(data: MangaInfo) { + override fun onBind(data: Manga, extra: MangaHistory?) { coverRequest?.dispose() - textView_title.text = data.manga.title - textView_subtitle.textAndVisible = data.manga.localizedTitle - coverRequest = imageView_cover.load(data.manga.coverUrl) { + textView_title.text = data.title + textView_subtitle.textAndVisible = data.localizedTitle + coverRequest = imageView_cover.load(data.coverUrl) { crossfade(true) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListView.kt index d13cfe196..939fafc61 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListView.kt @@ -2,15 +2,15 @@ package org.koitharu.kotatsu.ui.main.list import moxy.MvpView import moxy.viewstate.strategy.* -import org.koitharu.kotatsu.core.model.MangaInfo +import org.koitharu.kotatsu.core.model.Manga interface MangaListView : MvpView { @StateStrategyType(AddToEndSingleTagStrategy::class, tag = "content") - fun onListChanged(list: List>) + fun onListChanged(list: List) @StateStrategyType(AddToEndStrategy::class, tag = "content") - fun onListAppended(list: List>) + fun onListAppended(list: List) @StateStrategyType(AddToEndSingleStrategy::class) fun onLoadingChanged(isLoading: Boolean) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListPresenter.kt index 62299dced..4b833674a 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/history/HistoryListPresenter.kt @@ -4,7 +4,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import moxy.InjectViewState -import okhttp3.internal.closeQuietly import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.domain.HistoryRepository @@ -26,7 +25,7 @@ class HistoryListPresenter : BasePresenter>() { viewState.onLoadingChanged(true) try { val list = withContext(Dispatchers.IO) { - repository.getHistory(offset = offset) + repository.getList(offset = offset) } if (offset == 0) { viewState.onListChanged(list) @@ -62,9 +61,4 @@ class HistoryListPresenter : BasePresenter>() { } } } - - override fun onDestroy() { - repository.closeQuietly() - super.onDestroy() - } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/remote/RemoteListPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/remote/RemoteListPresenter.kt index 6085e24b2..844e6af6b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/remote/RemoteListPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/remote/RemoteListPresenter.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import moxy.InjectViewState import org.koitharu.kotatsu.BuildConfig -import org.koitharu.kotatsu.core.model.MangaInfo import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.domain.MangaProviderFactory import org.koitharu.kotatsu.ui.common.BasePresenter @@ -21,7 +20,6 @@ class RemoteListPresenter : BasePresenter>() { val list = withContext(Dispatchers.IO) { MangaProviderFactory.create(source) .getList(offset) - .map { MangaInfo(it, Unit) } } if (offset == 0) { viewState.onListChanged(list) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageHolder.kt index 3a05d6ba5..c0cefa387 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageHolder.kt @@ -11,17 +11,17 @@ import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.ui.common.list.BaseViewHolder import org.koitharu.kotatsu.utils.ext.getDisplayMessage -class PageHolder(parent: ViewGroup, private val loader: PageLoader) : BaseViewHolder(parent, R.layout.item_page), +class PageHolder(parent: ViewGroup, private val loader: PageLoader) : BaseViewHolder(parent, R.layout.item_page), SubsamplingScaleImageView.OnImageEventListener { init { ssiv.setOnImageEventListener(this) button_retry.setOnClickListener { - onBind(boundData ?: return@setOnClickListener) + onBind(boundData ?: return@setOnClickListener, Unit) } } - override fun onBind(data: MangaPage) { + override fun onBind(data: MangaPage, extra: Unit) { layout_error.isVisible = false progressBar.show() ssiv.recycle() diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PagesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PagesAdapter.kt index 5a7bbdb5a..04f395711 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PagesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PagesAdapter.kt @@ -5,9 +5,11 @@ import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter import org.koitharu.kotatsu.ui.common.list.BaseViewHolder -class PagesAdapter(private val loader: PageLoader) : BaseRecyclerAdapter() { +class PagesAdapter(private val loader: PageLoader) : BaseRecyclerAdapter() { override fun onCreateViewHolder(parent: ViewGroup) = PageHolder(parent, loader) override fun onGetItemId(item: MangaPage) = item.id + + override fun getExtra(item: MangaPage, position: Int) = Unit } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt index d3d519f23..d80d50b54 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt @@ -5,11 +5,13 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import android.widget.Toast import androidx.core.view.isVisible import kotlinx.android.synthetic.main.activity_reader.* 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.MangaPage import org.koitharu.kotatsu.ui.common.BaseActivity import org.koitharu.kotatsu.utils.ext.showDialog @@ -18,12 +20,7 @@ class ReaderActivity : BaseActivity(), ReaderView { private val presenter by moxyPresenter { ReaderPresenter() } - private val manga by lazy(LazyThreadSafetyMode.NONE) { - intent.getParcelableExtra(EXTRA_MANGA)!! - } - private val chapterId by lazy(LazyThreadSafetyMode.NONE) { - intent.getLongExtra(EXTRA_CHAPTER_ID, 0L) - } + private lateinit var state: ReaderState private lateinit var loader: PageLoader private lateinit var adapter: PagesAdapter @@ -34,21 +31,24 @@ class ReaderActivity : BaseActivity(), ReaderView { supportActionBar?.setDisplayHomeAsUpEnabled(true) bottomBar.inflateMenu(R.menu.opt_reader_bottom) - val chapter = manga.chapters?.find { x -> x.id == chapterId } - if (chapter == null) { - // TODO - finish() - return - } - title = chapter.name - manga.chapters?.run { - supportActionBar?.subtitle = getString(R.string.chapter_d_of_d, chapter.number, size) + state = savedInstanceState?.getParcelable(EXTRA_STATE) + ?: intent.getParcelableExtra(EXTRA_STATE) + ?: let { + Toast.makeText(this, R.string.error_occurred, Toast.LENGTH_SHORT).show() + finish() + return + } + + title = state.chapter?.name ?: state.manga.title + state.manga.chapters?.run { + supportActionBar?.subtitle = + getString(R.string.chapter_d_of_d, state.chapter?.number ?: 0, size) } loader = PageLoader(this) adapter = PagesAdapter(loader) pager.adapter = adapter - presenter.loadChapter(chapter) + presenter.loadChapter(state) } override fun onDestroy() { @@ -57,7 +57,8 @@ class ReaderActivity : BaseActivity(), ReaderView { } override fun onPause() { - presenter.addToHistory(manga, chapterId, pager.currentItem) + state = state.copy(page = pager.currentItem) + presenter.saveState(state) super.onPause() } @@ -66,16 +67,17 @@ class ReaderActivity : BaseActivity(), ReaderView { return super.onCreateOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) { + override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { R.id.action_chapters -> { - ChaptersDialog.show(supportFragmentManager, manga.chapters.orEmpty()) + ChaptersDialog.show(supportFragmentManager, state.manga.chapters.orEmpty()) true } else -> super.onOptionsItemSelected(item) } - override fun onPagesReady(pages: List) { + override fun onPagesReady(pages: List, index: Int) { adapter.replaceData(pages) + pager.setCurrentItem(index, false) } override fun onLoadingStateChanged(isLoading: Boolean) { @@ -92,11 +94,32 @@ class ReaderActivity : BaseActivity(), ReaderView { companion object { - private const val EXTRA_MANGA = "manga" - private const val EXTRA_CHAPTER_ID = "chapter_id" - - fun newIntent(context: Context, manga: Manga, chapterId: Long) = Intent(context, ReaderActivity::class.java) - .putExtra(EXTRA_MANGA, manga) - .putExtra(EXTRA_CHAPTER_ID, chapterId) + private const val EXTRA_STATE = "state" + + fun newIntent(context: Context, state: ReaderState) = + Intent(context, ReaderActivity::class.java) + .putExtra(EXTRA_STATE, state) + + fun newIntent(context: Context, manga: Manga, chapterId: Long = -1) = newIntent( + context, ReaderState( + manga = manga, + chapterId = if (chapterId == -1L) manga.chapters?.firstOrNull()?.id + ?: -1 else chapterId, + page = 0 + ) + ) + + fun newIntent(context: Context, manga: Manga, history: MangaHistory?) = + if (history == null) { + newIntent(context, manga) + } else { + newIntent( + context, ReaderState( + manga = manga, + chapterId = history.chapterId, + page = history.page + ) + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt index b325b8d87..e4a3b1237 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt @@ -14,14 +14,18 @@ import org.koitharu.kotatsu.ui.common.BasePresenter @InjectViewState class ReaderPresenter : BasePresenter() { - fun loadChapter(chapter: MangaChapter) { + fun loadChapter(state: ReaderState) { launch { viewState.onLoadingStateChanged(isLoading = true) try { val pages = withContext(Dispatchers.IO) { - MangaProviderFactory.create(chapter.source).getPages(chapter) + val repo = MangaProviderFactory.create(state.manga.source) + val chapter = state.chapter ?: repo.getDetails(state.manga).chapters + ?.first { it.id == state.chapterId } + ?: throw RuntimeException("Chapter ${state.chapterId} not found") + repo.getPages(chapter) } - viewState.onPagesReady(pages) + viewState.onPagesReady(pages, state.page) } catch (e: Exception) { if (BuildConfig.DEBUG) { e.printStackTrace() @@ -33,11 +37,13 @@ class ReaderPresenter : BasePresenter() { } } - fun addToHistory(manga: Manga, chapterId: Long, page: Int) { + fun saveState(state: ReaderState) { launch(Dispatchers.IO) { - HistoryRepository().use { - it.addOrUpdate(manga, chapterId, page) - } + HistoryRepository().addOrUpdate( + manga = state.manga, + chapterId = state.chapterId, + page = state.page + ) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt new file mode 100644 index 000000000..cd5f07996 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderState.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.ui.reader + +import android.os.Parcelable +import kotlinx.android.parcel.IgnoredOnParcel +import kotlinx.android.parcel.Parcelize +import org.koitharu.kotatsu.core.model.Manga +import org.koitharu.kotatsu.core.model.MangaChapter + +@Parcelize +data class ReaderState( + val manga: Manga, + val chapterId: Long, + val page: Int +) : Parcelable { + + @IgnoredOnParcel + val chapter: MangaChapter? by lazy { + manga.chapters?.find { it.id == chapterId } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt index cdeebb373..1b9e35e74 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderView.kt @@ -9,7 +9,7 @@ import org.koitharu.kotatsu.core.model.MangaPage interface ReaderView : MvpView { @StateStrategyType(AddToEndSingleStrategy::class) - fun onPagesReady(pages: List) + fun onPagesReady(pages: List, index: Int) @StateStrategyType(AddToEndSingleStrategy::class) fun onLoadingStateChanged(isLoading: Boolean) diff --git a/app/src/main/res/drawable/bg_badge_accent.xml b/app/src/main/res/drawable/bg_badge_accent.xml new file mode 100644 index 000000000..240151434 --- /dev/null +++ b/app/src/main/res/drawable/bg_badge_accent.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_round_rect.xml b/app/src/main/res/drawable/bg_badge_default.xml similarity index 100% rename from app/src/main/res/drawable/bg_round_rect.xml rename to app/src/main/res/drawable/bg_badge_default.xml diff --git a/app/src/main/res/drawable/bg_badge_outline.xml b/app/src/main/res/drawable/bg_badge_outline.xml new file mode 100644 index 000000000..f03c4e593 --- /dev/null +++ b/app/src/main/res/drawable/bg_badge_outline.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_badge_outline_accent.xml b/app/src/main/res/drawable/bg_badge_outline_accent.xml new file mode 100644 index 000000000..d9f9aa2cf --- /dev/null +++ b/app/src/main/res/drawable/bg_badge_outline_accent.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_details.xml b/app/src/main/res/layout/fragment_details.xml index 4f36958a3..05b1119b2 100644 --- a/app/src/main/res/layout/fragment_details.xml +++ b/app/src/main/res/layout/fragment_details.xml @@ -27,25 +27,27 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" + android:maxLines="3" android:layout_marginEnd="8dp" android:textAppearance="@style/TextAppearance.AppCompat.Body2" android:textColor="?android:textColorPrimary" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/imageView_cover" app:layout_constraintTop_toTopOf="parent" - tools:text="@tools:sample/lorem" /> + tools:text="@tools:sample/lorem[20]" /> + tools:text="@tools:sample/lorem[20]" />