优化
This commit is contained in:
@@ -21,8 +21,8 @@ import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.help.globalExecutor
|
||||
import io.legado.app.model.webBook.WebBook
|
||||
import io.legado.app.ui.book.manga.entities.MangaChapter
|
||||
import io.legado.app.ui.book.manga.entities.MangaContent
|
||||
import io.legado.app.ui.book.manga.entities.MangaContentData
|
||||
import io.legado.app.ui.book.manga.entities.MangaPage
|
||||
import io.legado.app.ui.book.manga.entities.ReaderLoading
|
||||
import io.legado.app.utils.mapIndexed
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -67,7 +67,6 @@ object ReadManga : CoroutineScope by MainScope() {
|
||||
var rateLimiter = ConcurrentRateLimiter(null)
|
||||
val mangaContents get() = buildContentList()
|
||||
val hasNextChapter get() = durChapterIndex < simulatedChapterSize - 1
|
||||
val mSeekParPos = mutableMapOf<Int, MutableMap<Int, Int>>()
|
||||
|
||||
fun resetData(book: Book) {
|
||||
ReadManga.book = book
|
||||
@@ -260,14 +259,18 @@ object ReadManga : CoroutineScope by MainScope() {
|
||||
/**
|
||||
* 加载下一章
|
||||
*/
|
||||
fun moveToNextChapter(startLoad: () -> Unit): Boolean {
|
||||
fun moveToNextChapter(toFirst: Boolean = false): Boolean {
|
||||
if (durChapterIndex < simulatedChapterSize - 1) {
|
||||
if (toFirst) {
|
||||
mCallback?.showLoading()
|
||||
durChapterPos = 0
|
||||
}
|
||||
durChapterIndex++
|
||||
prevMangaChapter = curMangaChapter
|
||||
curMangaChapter = nextMangaChapter
|
||||
nextMangaChapter = null
|
||||
if (curMangaChapter == null) {
|
||||
startLoad.invoke()
|
||||
mCallback?.startLoad()
|
||||
loadContent(durChapterIndex)
|
||||
} else {
|
||||
mCallback?.upContent()
|
||||
@@ -283,8 +286,12 @@ object ReadManga : CoroutineScope by MainScope() {
|
||||
}
|
||||
}
|
||||
|
||||
fun moveToPrevChapter(): Boolean {
|
||||
fun moveToPrevChapter(toFirst: Boolean = false): Boolean {
|
||||
if (durChapterIndex > 0) {
|
||||
if (toFirst) {
|
||||
mCallback?.showLoading()
|
||||
durChapterPos = 0
|
||||
}
|
||||
durChapterIndex--
|
||||
nextMangaChapter = curMangaChapter
|
||||
curMangaChapter = prevMangaChapter
|
||||
@@ -561,8 +568,8 @@ object ReadManga : CoroutineScope by MainScope() {
|
||||
private suspend fun getManageChapter(chapter: BookChapter, content: String): MangaChapter {
|
||||
val list = BookHelp.flowImages(chapter, content)
|
||||
.distinctUntilChanged().mapIndexed { index, src ->
|
||||
MangaContent(
|
||||
mChapterIndex = chapter.index,
|
||||
MangaPage(
|
||||
chapterIndex = chapter.index,
|
||||
chapterSize = chapterSize,
|
||||
mImageUrl = src,
|
||||
index = index,
|
||||
@@ -577,43 +584,18 @@ object ReadManga : CoroutineScope by MainScope() {
|
||||
}
|
||||
|
||||
val contentList = mutableListOf<Any>()
|
||||
contentList.add(ReaderLoading(chapter.index, "阅读 ${chapter.title}"))
|
||||
contentList.add(ReaderLoading(chapter.index, -1, "阅读 ${chapter.title}"))
|
||||
contentList.addAll(list)
|
||||
contentList.add(ReaderLoading(chapter.index, "已读完 ${chapter.title}"))
|
||||
contentList.add(ReaderLoading(chapter.index, imageCount, "已读完 ${chapter.title}"))
|
||||
|
||||
return MangaChapter(chapter, contentList, imageCount)
|
||||
}
|
||||
|
||||
fun recordMangaPosition(dataList: MutableList<Any>) {
|
||||
Coroutine.async {
|
||||
var globalPosition = 0
|
||||
val mangaList = mutableListOf<MangaContent>()
|
||||
dataList.forEach {
|
||||
if (it is MangaContent) {
|
||||
mangaList.add(it)
|
||||
}
|
||||
}
|
||||
dataList.groupBy { if (it is MangaContent) it.mChapterIndex else (it as ReaderLoading).mChapterIndex }
|
||||
.forEach { (chapterIndex, items) ->
|
||||
val itemMap = mutableMapOf<Int, Int>()
|
||||
for (i in items.indices) {
|
||||
val item = items[i]
|
||||
if (item is MangaContent) {
|
||||
itemMap[item.index] = globalPosition++
|
||||
} else {
|
||||
globalPosition++
|
||||
}
|
||||
}
|
||||
mSeekParPos[chapterIndex] = itemMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface Callback {
|
||||
fun upContent()
|
||||
fun loadFail(msg: String)
|
||||
fun sureNewProgress(progress: BookProgress)
|
||||
fun showLoading()
|
||||
fun startLoad()
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,8 @@ import io.legado.app.ui.book.manga.config.MangaColorFilterConfig
|
||||
import io.legado.app.ui.book.manga.config.MangaColorFilterDialog
|
||||
import io.legado.app.ui.book.manga.config.MangaFooterConfig
|
||||
import io.legado.app.ui.book.manga.config.MangaFooterSettingDialog
|
||||
import io.legado.app.ui.book.manga.entities.MangaContent
|
||||
import io.legado.app.ui.book.manga.entities.BaseMangaPage
|
||||
import io.legado.app.ui.book.manga.entities.MangaPage
|
||||
import io.legado.app.ui.book.manga.recyclerview.MangaAdapter
|
||||
import io.legado.app.ui.book.read.MangaMenu
|
||||
import io.legado.app.ui.book.read.ReadBookActivity.Companion.RESULT_DELETED
|
||||
@@ -56,6 +57,8 @@ import io.legado.app.ui.widget.recycler.LoadMoreView
|
||||
import io.legado.app.utils.GSON
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.StartActivityContract
|
||||
import io.legado.app.utils.fastBinarySearch
|
||||
import io.legado.app.utils.findCenterViewPosition
|
||||
import io.legado.app.utils.fromJsonObject
|
||||
import io.legado.app.utils.getCompatColor
|
||||
import io.legado.app.utils.gone
|
||||
@@ -187,13 +190,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
override fun observeLiveBus() {
|
||||
observeEvent<MangaFooterConfig>(EventBus.UP_MANGA_CONFIG) {
|
||||
mMangaFooterConfig = it
|
||||
upInfoBar(
|
||||
ReadManga.durChapterIndex,
|
||||
ReadManga.chapterSize,
|
||||
ReadManga.durChapterPos,
|
||||
ReadManga.durChapterImageCount,
|
||||
ReadManga.curMangaChapter?.chapter?.title ?: ""
|
||||
)
|
||||
val item = mAdapter.getItem(binding.mRecyclerManga.findCenterViewPosition())
|
||||
upInfoBar(item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,26 +213,18 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
disableMangaScaling(AppConfig.disableMangaScale)
|
||||
setPreScrollListener { _, _, _, position ->
|
||||
if (mAdapter.isNotEmpty()) {
|
||||
val content = mAdapter.getItem(position)
|
||||
if (content is MangaContent) {
|
||||
if (ReadManga.durChapterIndex < content.mChapterIndex) {
|
||||
ReadManga.moveToNextChapter {
|
||||
loadMoreView.startLoad()
|
||||
}
|
||||
} else if (ReadManga.durChapterIndex > content.mChapterIndex) {
|
||||
val item = mAdapter.getItem(position)
|
||||
if (item is MangaPage) {
|
||||
if (ReadManga.durChapterIndex < item.chapterIndex) {
|
||||
ReadManga.moveToNextChapter()
|
||||
} else if (ReadManga.durChapterIndex > item.chapterIndex) {
|
||||
ReadManga.moveToPrevChapter()
|
||||
} else {
|
||||
ReadManga.durChapterPos = content.index
|
||||
ReadManga.durChapterPos = item.index
|
||||
ReadManga.curPageChanged()
|
||||
}
|
||||
binding.mangaMenu.upSeekBar(content.index, content.imageCount)
|
||||
upInfoBar(
|
||||
content.mChapterIndex,
|
||||
content.chapterSize,
|
||||
content.index,
|
||||
content.imageCount,
|
||||
content.mChapterName
|
||||
)
|
||||
binding.mangaMenu.upSeekBar(item.index, item.imageCount)
|
||||
upInfoBar(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,16 +269,9 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
val nextFinish = data.nextFinish
|
||||
mAdapter.submitList(list) {
|
||||
binding.mangaMenu.upSeekBar(ReadManga.durChapterPos, ReadManga.durChapterImageCount)
|
||||
ReadManga.recordMangaPosition(mAdapter.getCurrentList())
|
||||
if (loadingViewVisible && curFinish) {
|
||||
binding.infobar.isVisible = true
|
||||
upInfoBar(
|
||||
ReadManga.durChapterIndex,
|
||||
ReadManga.chapterSize,
|
||||
ReadManga.durChapterPos,
|
||||
ReadManga.durChapterImageCount,
|
||||
ReadManga.curMangaChapter!!.chapter.title
|
||||
)
|
||||
upInfoBar(list[pos])
|
||||
binding.mRecyclerManga.scrollToPosition(pos)
|
||||
binding.flLoading.isGone = true
|
||||
loadMoreView.visible()
|
||||
@@ -307,13 +290,15 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
}
|
||||
}
|
||||
|
||||
private fun upInfoBar(
|
||||
chapterIndex: Int,
|
||||
chapterSize: Int,
|
||||
chapterPos: Int,
|
||||
chapterImageCount: Int,
|
||||
chapterName: String,
|
||||
) {
|
||||
private fun upInfoBar(page: Any?) {
|
||||
if (page !is MangaPage) {
|
||||
return
|
||||
}
|
||||
val chapterIndex = page.index
|
||||
val chapterSize = page.chapterSize
|
||||
val chapterPos = page.index
|
||||
val imageCount = page.imageCount
|
||||
val chapterName = page.mChapterName
|
||||
mMangaFooterConfig.run {
|
||||
mLabelBuilder.clear()
|
||||
binding.infobar.isGone = hideFooter
|
||||
@@ -327,7 +312,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
if (!hidePageNumberLabel) {
|
||||
mLabelBuilder.append(getString(R.string.manga_check_page_number))
|
||||
}
|
||||
mLabelBuilder.append("${chapterPos + 1}/${chapterImageCount}").append(" ")
|
||||
mLabelBuilder.append("${chapterPos + 1}/${imageCount}").append(" ")
|
||||
}
|
||||
|
||||
if (!hideChapter) {
|
||||
@@ -341,16 +326,16 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
if (!hideProgressRatioLabel) {
|
||||
mLabelBuilder.append(getString(R.string.manga_check_progress))
|
||||
}
|
||||
val percent = if (chapterSize == 0 || chapterImageCount == 0 && chapterIndex == 0) {
|
||||
val percent = if (chapterSize == 0 || imageCount == 0 && chapterIndex == 0) {
|
||||
"0.0%"
|
||||
} else if (chapterImageCount == 0) {
|
||||
} else if (imageCount == 0) {
|
||||
df.format((chapterIndex + 1.0f) / chapterSize.toDouble())
|
||||
} else {
|
||||
var percent =
|
||||
df.format(
|
||||
chapterIndex * 1.0f / chapterSize + 1.0f / chapterSize * (chapterPos + 1) / chapterImageCount.toDouble()
|
||||
chapterIndex * 1.0f / chapterSize + 1.0f / chapterSize * (chapterPos + 1) / imageCount.toDouble()
|
||||
)
|
||||
if (percent == "100.0%" && (chapterIndex + 1 != chapterSize || chapterPos + 1 != chapterImageCount)) {
|
||||
if (percent == "100.0%" && (chapterIndex + 1 != chapterSize || chapterPos + 1 != imageCount)) {
|
||||
percent = "99.9%"
|
||||
}
|
||||
percent
|
||||
@@ -432,6 +417,12 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
}
|
||||
}
|
||||
|
||||
override fun startLoad() {
|
||||
lifecycleScope.launch {
|
||||
loadMoreView.startLoad()
|
||||
}
|
||||
}
|
||||
|
||||
override val oldBook: Book?
|
||||
get() = ReadManga.book
|
||||
|
||||
@@ -540,10 +531,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
if (item.isChecked) LinearLayoutManager.HORIZONTAL else LinearLayoutManager.VERTICAL
|
||||
singlePagerScroller(item.isChecked)
|
||||
mAdapter.isHorizontal = item.isChecked
|
||||
mAdapter.notifyItemRangeChanged(
|
||||
ReadManga.durChapterPos.minus(2),
|
||||
mAdapter.getCurrentList().size
|
||||
)
|
||||
mAdapter.notifyItemRangeChanged(0, mAdapter.itemCount)
|
||||
}
|
||||
|
||||
R.id.menu_manga_color_filter -> {
|
||||
@@ -567,12 +555,6 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
toggleSystemBar(menuIsVisible)
|
||||
}
|
||||
|
||||
override fun moveToTargetIndex(isNext: Boolean) {
|
||||
var targetIndex =
|
||||
if (isNext) ReadManga.durChapterIndex + 1 else ReadManga.durChapterIndex - 1
|
||||
viewModel.openChapter(if (isNext) targetIndex else targetIndex, 0)
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
val keyCode = event.keyCode
|
||||
val action = event.action
|
||||
@@ -756,10 +738,27 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
|
||||
window.decorView.postInvalidate()
|
||||
}
|
||||
|
||||
override fun seekValue(pos: Int) {
|
||||
val mangaIndex = ReadManga.mSeekParPos[ReadManga.durChapterIndex]
|
||||
if (mangaIndex != null && mangaIndex[pos] != null) {
|
||||
binding.mRecyclerManga.scrollToPosition(mangaIndex[pos]!!)
|
||||
override fun skipToPage(pos: Int) {
|
||||
val durChapterIndex = ReadManga.durChapterIndex
|
||||
val pos = mAdapter.getItems().fastBinarySearch {
|
||||
val chapterIndex: Int
|
||||
val pageIndex: Int
|
||||
if (it is BaseMangaPage) {
|
||||
chapterIndex = it.chapterIndex
|
||||
pageIndex = it.index
|
||||
} else {
|
||||
error("unknown item type")
|
||||
}
|
||||
val delta = chapterIndex - durChapterIndex
|
||||
if (delta != 0) {
|
||||
delta
|
||||
} else {
|
||||
pageIndex - pos
|
||||
}
|
||||
}
|
||||
if (pos > -1) {
|
||||
binding.mRecyclerManga.scrollToPosition(pos)
|
||||
upInfoBar(mAdapter.getItem(pos))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package io.legado.app.ui.book.manga.entities
|
||||
|
||||
interface BaseMangaPage {
|
||||
val chapterIndex: Int
|
||||
val index: Int
|
||||
}
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
package io.legado.app.ui.book.manga.entities
|
||||
|
||||
data class MangaContent(
|
||||
val mChapterIndex: Int = 0,//总章节位置
|
||||
data class MangaPage(
|
||||
override val chapterIndex: Int = 0,//总章节位置
|
||||
val chapterSize: Int,//总章节数量
|
||||
val mImageUrl: String = "",//当前URL
|
||||
val index: Int = 0,//当前章节位置
|
||||
override val index: Int = 0,//当前章节位置
|
||||
var imageCount: Int = 0,//当前章节内容总数
|
||||
val mChapterName: String = "",//章节名称
|
||||
)
|
||||
) : BaseMangaPage
|
||||
@@ -1,7 +1,8 @@
|
||||
package io.legado.app.ui.book.manga.entities
|
||||
|
||||
data class ReaderLoading(
|
||||
val mChapterIndex: Int = 0,
|
||||
override val chapterIndex: Int = 0,
|
||||
override val index: Int = 0,
|
||||
val mMessage: String? = null,
|
||||
var mLoading: Boolean = false,
|
||||
)
|
||||
) : BaseMangaPage
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import io.legado.app.help.glide.progress.ProgressManager
|
||||
import io.legado.app.model.BookCover
|
||||
import io.legado.app.model.ReadManga
|
||||
import io.legado.app.ui.book.manga.config.MangaColorFilterConfig
|
||||
import io.legado.app.ui.book.manga.entities.MangaContent
|
||||
import io.legado.app.ui.book.manga.entities.MangaPage
|
||||
import io.legado.app.ui.book.manga.entities.ReaderLoading
|
||||
import io.legado.app.utils.getCompatDrawable
|
||||
import java.util.Collections
|
||||
@@ -49,7 +49,7 @@ class MangaAdapter(private val context: Context) :
|
||||
override fun areItemsTheSame(oldItem: Any, newItem: Any): Boolean {
|
||||
return if (oldItem is ReaderLoading && newItem is ReaderLoading) {
|
||||
newItem.mMessage == oldItem.mMessage
|
||||
} else if (oldItem is MangaContent && newItem is MangaContent) {
|
||||
} else if (oldItem is MangaPage && newItem is MangaPage) {
|
||||
oldItem.mImageUrl == newItem.mImageUrl
|
||||
} else false
|
||||
}
|
||||
@@ -57,7 +57,7 @@ class MangaAdapter(private val context: Context) :
|
||||
override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean {
|
||||
return if (oldItem is ReaderLoading && newItem is ReaderLoading) {
|
||||
oldItem == newItem
|
||||
} else if (oldItem is MangaContent && newItem is MangaContent) {
|
||||
} else if (oldItem is MangaPage && newItem is MangaPage) {
|
||||
oldItem == newItem
|
||||
} else false
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class MangaAdapter(private val context: Context) :
|
||||
|
||||
fun getItem(@IntRange(from = 0) position: Int) = mDiffer.currentList.getOrNull(position)
|
||||
|
||||
fun getCurrentList() = mDiffer.currentList
|
||||
fun getItems() = mDiffer.currentList
|
||||
|
||||
fun isEmpty() = mDiffer.currentList.isEmpty()
|
||||
|
||||
@@ -91,7 +91,7 @@ class MangaAdapter(private val context: Context) :
|
||||
)
|
||||
binding.retry.setOnClickListener {
|
||||
val item = mDiffer.currentList[layoutPosition]
|
||||
if (item is MangaContent) {
|
||||
if (item is MangaPage) {
|
||||
loadImageWithRetry(
|
||||
item.mImageUrl, isHorizontal, item.imageCount == 1
|
||||
)
|
||||
@@ -99,7 +99,7 @@ class MangaAdapter(private val context: Context) :
|
||||
}
|
||||
}
|
||||
|
||||
fun onBind(item: MangaContent) {
|
||||
fun onBind(item: MangaPage) {
|
||||
setImageColorFilter()
|
||||
loadImageWithRetry(item.mImageUrl, isHorizontal, item.imageCount == 1)
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class MangaAdapter(private val context: Context) :
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when {
|
||||
isFooter(position) -> TYPE_FOOTER_VIEW + position - getActualItemCount()
|
||||
getItem(position) is MangaContent -> CONTENT_VIEW
|
||||
getItem(position) is MangaPage -> CONTENT_VIEW
|
||||
getItem(position) is ReaderLoading -> LOADING_VIEW
|
||||
else -> error("Unknown view type!")
|
||||
}
|
||||
@@ -182,7 +182,7 @@ class MangaAdapter(private val context: Context) :
|
||||
|
||||
override fun onBindViewHolder(vh: RecyclerView.ViewHolder, position: Int) {
|
||||
when (vh) {
|
||||
is PageViewHolder -> vh.onBind(getItem(position) as MangaContent)
|
||||
is PageViewHolder -> vh.onBind(getItem(position) as MangaPage)
|
||||
is PageMoreViewHolder -> vh.onBind(getItem(position) as ReaderLoading)
|
||||
}
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class MangaAdapter(private val context: Context) :
|
||||
/**
|
||||
* 除去header和footer
|
||||
*/
|
||||
fun getActualItemCount() = getCurrentList().size
|
||||
fun getActualItemCount() = getItems().size
|
||||
|
||||
@Synchronized
|
||||
fun removeFooterView(footer: ((parent: ViewGroup) -> ViewBinding)) {
|
||||
@@ -216,13 +216,13 @@ class MangaAdapter(private val context: Context) :
|
||||
}
|
||||
|
||||
override fun getPreloadItems(position: Int): MutableList<Any> {
|
||||
if (getCurrentList().isEmpty()) return Collections.emptyList()
|
||||
if (position >= getCurrentList().size) return Collections.emptyList()
|
||||
return getCurrentList().subList(position, position + 1)
|
||||
if (getItems().isEmpty()) return Collections.emptyList()
|
||||
if (position >= getItems().size) return Collections.emptyList()
|
||||
return getItems().subList(position, position + 1)
|
||||
}
|
||||
|
||||
override fun getPreloadRequestBuilder(item: Any): RequestBuilder<*>? {
|
||||
if (item is MangaContent) {
|
||||
if (item is MangaPage) {
|
||||
return BookCover.loadManga(
|
||||
context,
|
||||
item.mImageUrl,
|
||||
|
||||
@@ -236,15 +236,15 @@ class MangaMenu @JvmOverloads constructor(
|
||||
tvChapterUrl.setOnLongClickListener(chapterViewLongClickListener)
|
||||
|
||||
tvNext.setOnClickListener {
|
||||
callBack.moveToTargetIndex(true)
|
||||
ReadManga.moveToNextChapter(true)
|
||||
}
|
||||
tvPre.setOnClickListener {
|
||||
callBack.moveToTargetIndex(false)
|
||||
ReadManga.moveToPrevChapter(true)
|
||||
}
|
||||
|
||||
seekReadPage.setOnSeekBarChangeListener(object : SeekBarChangeListener {
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
callBack.seekValue(seekBar.progress)
|
||||
callBack.skipToPage(seekBar.progress)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -259,8 +259,7 @@ class MangaMenu @JvmOverloads constructor(
|
||||
interface CallBack {
|
||||
fun openBookInfoActivity()
|
||||
fun upSystemUiVisibility(menuIsVisible: Boolean)
|
||||
fun moveToTargetIndex(isNext: Boolean)
|
||||
fun seekValue(pos: Int)
|
||||
fun skipToPage(pos: Int)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user