Reader refactoring
This commit is contained in:
@@ -95,8 +95,11 @@ class BookmarksFragment :
|
||||
|
||||
override fun onItemClick(item: Bookmark, view: View) {
|
||||
if (selectionController?.onItemClick(item.manga, item.pageId) != true) {
|
||||
val intent = ReaderActivity.newIntent(view.context, item)
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
|
||||
val intent = ReaderActivity.IntentBuilder(view.context)
|
||||
.bookmark(item)
|
||||
.incognito(true)
|
||||
.build()
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view))
|
||||
Toast.makeText(view.context, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ import org.koitharu.kotatsu.core.db.TABLE_HISTORY
|
||||
import org.koitharu.kotatsu.core.parser.MangaDataRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.getDrawableOrThrow
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.koitharu.kotatsu.core.util.ext.processLifecycleScope
|
||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -142,8 +142,9 @@ class ShortcutsUpdater @Inject constructor(
|
||||
.setLongLabel(manga.title)
|
||||
.setIcon(icon)
|
||||
.setIntent(
|
||||
ReaderActivity.newIntent(context, manga.id)
|
||||
.setAction(ReaderActivity.ACTION_MANGA_READ),
|
||||
ReaderActivity.IntentBuilder(context)
|
||||
.mangaId(manga.id)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import android.database.SQLException
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.view.ViewPropertyAnimator
|
||||
@@ -43,7 +44,6 @@ import org.jsoup.internal.StringUtil.StringJoiner
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
import kotlin.math.roundToLong
|
||||
@@ -148,13 +148,17 @@ val Context.ramAvailable: Long
|
||||
return result.availMem
|
||||
}
|
||||
|
||||
fun scaleUpActivityOptionsOf(view: View): ActivityOptions = ActivityOptions.makeScaleUpAnimation(
|
||||
view,
|
||||
0,
|
||||
0,
|
||||
view.width,
|
||||
view.height,
|
||||
)
|
||||
fun scaleUpActivityOptionsOf(view: View): Bundle? = if (view.context.isAnimationsEnabled) {
|
||||
ActivityOptions.makeScaleUpAnimation(
|
||||
view,
|
||||
0,
|
||||
0,
|
||||
view.width,
|
||||
view.height,
|
||||
).toBundle()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
fun Resources.getLocalesConfig(): LocaleListCompat {
|
||||
val tagsList = StringJoiner(",")
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.koitharu.kotatsu.details.ui.adapter.ChaptersSelectionDecoration
|
||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||
import org.koitharu.kotatsu.local.ui.LocalChaptersRemoveService
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -79,12 +79,11 @@ class ChaptersFragment :
|
||||
return
|
||||
}
|
||||
startActivity(
|
||||
ReaderActivity.newIntent(
|
||||
context = view.context,
|
||||
manga = viewModel.manga.value ?: return,
|
||||
state = ReaderState(item.chapter.id, 0, 0),
|
||||
),
|
||||
scaleUpActivityOptionsOf(view).toBundle(),
|
||||
IntentBuilder(view.context)
|
||||
.manga(viewModel.manga.value ?: return)
|
||||
.state(ReaderState(item.chapter.id, 0, 0))
|
||||
.build(),
|
||||
scaleUpActivityOptionsOf(view),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ import org.koitharu.kotatsu.details.ui.model.MangaBranch
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver
|
||||
import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
@@ -301,12 +301,11 @@ class DetailsActivity :
|
||||
snackbar.show()
|
||||
} else {
|
||||
startActivity(
|
||||
ReaderActivity.newIntent(
|
||||
context = this,
|
||||
manga = manga,
|
||||
branch = viewModel.selectedBranchValue,
|
||||
isIncognitoMode = isIncognitoMode,
|
||||
),
|
||||
IntentBuilder(this)
|
||||
.manga(manga)
|
||||
.branch(viewModel.selectedBranchValue)
|
||||
.incognito(isIncognitoMode)
|
||||
.build(),
|
||||
)
|
||||
if (isIncognitoMode) {
|
||||
Toast.makeText(this, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -96,8 +96,8 @@ class DetailsFragment :
|
||||
|
||||
override fun onItemClick(item: Bookmark, view: View) {
|
||||
startActivity(
|
||||
ReaderActivity.newIntent(view.context, item),
|
||||
scaleUpActivityOptionsOf(view).toBundle(),
|
||||
ReaderActivity.IntentBuilder(view.context).bookmark(item).incognito(true).build(),
|
||||
scaleUpActivityOptionsOf(view),
|
||||
)
|
||||
Toast.makeText(view.context, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
@@ -257,7 +257,7 @@ class DetailsFragment :
|
||||
manga.largeCoverUrl.ifNullOrEmpty { manga.coverUrl },
|
||||
manga.source,
|
||||
),
|
||||
scaleUpActivityOptionsOf(v).toBundle(),
|
||||
scaleUpActivityOptionsOf(v),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ class ScrobblingInfoSheet :
|
||||
R.id.imageView_cover -> {
|
||||
val coverUrl = viewModel.scrobblingInfo.value.getOrNull(scrobblerIndex)?.coverUrl ?: return
|
||||
val options = scaleUpActivityOptionsOf(v)
|
||||
startActivity(ImageActivity.newIntent(v.context, coverUrl, null), options.toBundle())
|
||||
startActivity(ImageActivity.newIntent(v.context, coverUrl, null), options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ class FavouriteCategoriesActivity :
|
||||
}
|
||||
val intent = FavouritesActivity.newIntent(this, item)
|
||||
val options = scaleUpActivityOptionsOf(view)
|
||||
startActivity(intent, options.toBundle())
|
||||
startActivity(intent, options)
|
||||
}
|
||||
|
||||
override fun onItemLongClick(item: FavouriteCategory, view: View): Boolean {
|
||||
|
||||
@@ -55,7 +55,7 @@ import org.koitharu.kotatsu.main.ui.MainActivity
|
||||
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -148,8 +148,8 @@ abstract class MangaListFragment :
|
||||
|
||||
override fun onReadClick(manga: Manga, view: View) {
|
||||
if (selectionController?.onItemClick(manga.id) != true) {
|
||||
val intent = ReaderActivity.newIntent(context ?: return, manga)
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
|
||||
val intent = IntentBuilder(view.context).manga(manga).build()
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||
import org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity
|
||||
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionFragment
|
||||
@@ -259,9 +259,9 @@ class MainActivity :
|
||||
private fun onOpenReader(manga: Manga) {
|
||||
val fab = viewBinding.fab ?: viewBinding.navRail?.headerView
|
||||
val options = fab?.let {
|
||||
scaleUpActivityOptionsOf(it).toBundle()
|
||||
scaleUpActivityOptionsOf(it)
|
||||
}
|
||||
startActivity(ReaderActivity.newIntent(this, manga), options)
|
||||
startActivity(IntentBuilder(this).manga(manga).build(), options)
|
||||
}
|
||||
|
||||
private fun onCountersChanged(counters: SparseIntArray) {
|
||||
|
||||
@@ -398,6 +398,44 @@ class ReaderActivity :
|
||||
}
|
||||
}
|
||||
|
||||
class IntentBuilder(context: Context) {
|
||||
|
||||
private val intent = Intent(context, ReaderActivity::class.java)
|
||||
.setAction(ACTION_MANGA_READ)
|
||||
|
||||
fun manga(manga: Manga) = apply {
|
||||
intent.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
|
||||
}
|
||||
|
||||
fun mangaId(mangaId: Long) = apply {
|
||||
intent.putExtra(MangaIntent.KEY_ID, mangaId)
|
||||
}
|
||||
|
||||
fun incognito(incognito: Boolean) = apply {
|
||||
intent.putExtra(EXTRA_INCOGNITO, incognito)
|
||||
}
|
||||
|
||||
fun branch(branch: String?) = apply {
|
||||
intent.putExtra(EXTRA_BRANCH, branch)
|
||||
}
|
||||
|
||||
fun state(state: ReaderState?) = apply {
|
||||
intent.putExtra(EXTRA_STATE, state)
|
||||
}
|
||||
|
||||
fun bookmark(bookmark: Bookmark) = manga(
|
||||
bookmark.manga,
|
||||
).state(
|
||||
ReaderState(
|
||||
chapterId = bookmark.chapterId,
|
||||
page = bookmark.page,
|
||||
scroll = bookmark.scroll,
|
||||
),
|
||||
)
|
||||
|
||||
fun build() = intent
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val ACTION_MANGA_READ = "${BuildConfig.APPLICATION_ID}.action.READ_MANGA"
|
||||
@@ -405,38 +443,5 @@ class ReaderActivity :
|
||||
const val EXTRA_BRANCH = "branch"
|
||||
const val EXTRA_INCOGNITO = "incognito"
|
||||
private const val TOAST_DURATION = 1500L
|
||||
|
||||
fun newIntent(context: Context, manga: Manga): Intent {
|
||||
return Intent(context, ReaderActivity::class.java)
|
||||
.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
|
||||
}
|
||||
|
||||
fun newIntent(context: Context, manga: Manga, branch: String?, isIncognitoMode: Boolean): Intent {
|
||||
return Intent(context, ReaderActivity::class.java)
|
||||
.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
|
||||
.putExtra(EXTRA_BRANCH, branch)
|
||||
.putExtra(EXTRA_INCOGNITO, isIncognitoMode)
|
||||
}
|
||||
|
||||
fun newIntent(context: Context, manga: Manga, state: ReaderState?): Intent {
|
||||
return Intent(context, ReaderActivity::class.java)
|
||||
.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
|
||||
.putExtra(EXTRA_STATE, state)
|
||||
}
|
||||
|
||||
fun newIntent(context: Context, bookmark: Bookmark): Intent {
|
||||
val state = ReaderState(
|
||||
chapterId = bookmark.chapterId,
|
||||
page = bookmark.page,
|
||||
scroll = bookmark.scroll,
|
||||
)
|
||||
return newIntent(context, bookmark.manga, state)
|
||||
.putExtra(EXTRA_INCOGNITO, true)
|
||||
}
|
||||
|
||||
fun newIntent(context: Context, mangaId: Long): Intent {
|
||||
return Intent(context, ReaderActivity::class.java)
|
||||
.putExtra(MangaIntent.KEY_ID, mangaId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,8 +312,10 @@ class ReaderViewModel @Inject constructor(
|
||||
|
||||
private fun loadImpl() {
|
||||
loadingJob = launchLoadingJob(Dispatchers.Default) {
|
||||
var manga =
|
||||
DoubleManga(dataRepository.resolveIntent(intent) ?: throw NotFoundException("Cannot find manga", ""))
|
||||
var manga = DoubleManga(
|
||||
dataRepository.resolveIntent(intent)
|
||||
?: throw NotFoundException("Cannot find manga", ""),
|
||||
)
|
||||
mangaData.value = manga
|
||||
manga = doubleMangaLoadUseCase(intent)
|
||||
chaptersLoader.init(manga)
|
||||
|
||||
@@ -17,9 +17,13 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>() {
|
||||
protected val viewModel by activityViewModels<ReaderViewModel>()
|
||||
private var stateToSave: ReaderState? = null
|
||||
|
||||
protected var readerAdapter: BaseReaderAdapter<*>? = null
|
||||
private set
|
||||
|
||||
override fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
var restoredState = savedInstanceState?.getParcelableCompat<ReaderState>(KEY_STATE)
|
||||
readerAdapter = onCreateAdapter()
|
||||
|
||||
viewModel.content.observe(viewLifecycleOwner) {
|
||||
onPagesChanged(it.pages, restoredState ?: it.state)
|
||||
@@ -34,6 +38,7 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>() {
|
||||
|
||||
override fun onDestroyView() {
|
||||
stateToSave = getCurrentState()
|
||||
readerAdapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@@ -45,6 +50,10 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>() {
|
||||
outState.putParcelable(KEY_STATE, stateToSave)
|
||||
}
|
||||
|
||||
protected fun requireAdapter() = checkNotNull(readerAdapter) {
|
||||
"Adapter was not created or already destroyed"
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) = Unit
|
||||
|
||||
abstract fun switchPageBy(delta: Int)
|
||||
@@ -55,5 +64,7 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>() {
|
||||
|
||||
abstract fun getCurrentState(): ReaderState?
|
||||
|
||||
protected abstract fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?)
|
||||
protected abstract fun onCreateAdapter(): BaseReaderAdapter<*>
|
||||
|
||||
protected abstract suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?)
|
||||
}
|
||||
|
||||
@@ -4,16 +4,18 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.recyclerView
|
||||
import org.koitharu.kotatsu.core.util.ext.resetTransformations
|
||||
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
@@ -33,8 +35,6 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
@Inject
|
||||
lateinit var pageLoader: PageLoader
|
||||
|
||||
private var pagerAdapter: ReversedPagesAdapter? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -42,15 +42,8 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
|
||||
override fun onViewBindingCreated(binding: FragmentReaderStandardBinding, savedInstanceState: Bundle?) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
pagerAdapter = ReversedPagesAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
with(binding.pager) {
|
||||
adapter = pagerAdapter
|
||||
adapter = readerAdapter
|
||||
offscreenPageLimit = 2
|
||||
doOnPageChanged(::notifyPageChanged)
|
||||
}
|
||||
@@ -67,11 +60,18 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
pagerAdapter = null
|
||||
requireViewBinding().pager.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onCreateAdapter() = ReversedPagesAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
|
||||
override fun switchPageBy(delta: Int) {
|
||||
with(requireViewBinding().pager) {
|
||||
setCurrentItem(currentItem - delta, context.isAnimationsEnabled)
|
||||
@@ -87,24 +87,26 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
||||
val reversedPages = pages.asReversed()
|
||||
viewLifecycleScope.launch {
|
||||
val items = async {
|
||||
pagerAdapter?.setItems(reversedPages)
|
||||
val items = async {
|
||||
requireAdapter().setItems(reversedPages)
|
||||
yield()
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = reversedPages.indexOfLast {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = reversedPages.indexOfLast {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
items.await() ?: return@launch
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
}
|
||||
items.await()
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
} else {
|
||||
items.await()
|
||||
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
items.await()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +125,6 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
}
|
||||
|
||||
private fun reversed(position: Int): Int {
|
||||
return ((pagerAdapter?.itemCount ?: 0) - position - 1).coerceAtLeast(0)
|
||||
return ((readerAdapter?.itemCount ?: 0) - position - 1).coerceAtLeast(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,18 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.recyclerView
|
||||
import org.koitharu.kotatsu.core.util.ext.resetTransformations
|
||||
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderStandardBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
@@ -32,8 +34,6 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>()
|
||||
@Inject
|
||||
lateinit var pageLoader: PageLoader
|
||||
|
||||
private var pagesAdapter: PagesAdapter? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -41,15 +41,8 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>()
|
||||
|
||||
override fun onViewBindingCreated(binding: FragmentReaderStandardBinding, savedInstanceState: Bundle?) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
pagesAdapter = PagesAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
with(binding.pager) {
|
||||
adapter = pagesAdapter
|
||||
adapter = readerAdapter
|
||||
offscreenPageLimit = 2
|
||||
doOnPageChanged(::notifyPageChanged)
|
||||
}
|
||||
@@ -66,31 +59,40 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
pagesAdapter = null
|
||||
requireViewBinding().pager.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
|
||||
viewLifecycleScope.launch {
|
||||
val items = async {
|
||||
pagesAdapter?.setItems(pages)
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
||||
val items = async {
|
||||
requireAdapter().setItems(pages)
|
||||
yield()
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
items.await() ?: return@launch
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
}
|
||||
items.await()
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
} else {
|
||||
items.await()
|
||||
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
items.await()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateAdapter() = PagesAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
|
||||
override fun switchPageBy(delta: Int) {
|
||||
with(requireViewBinding().pager) {
|
||||
setCurrentItem(currentItem + delta, context.isAnimationsEnabled)
|
||||
|
||||
@@ -4,15 +4,17 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.util.ext.findCenterViewPosition
|
||||
import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.databinding.FragmentReaderWebtoonBinding
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
@@ -31,7 +33,6 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
lateinit var pageLoader: PageLoader
|
||||
|
||||
private val scrollInterpolator = AccelerateDecelerateInterpolator()
|
||||
private var webtoonAdapter: WebtoonAdapter? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
@@ -40,16 +41,9 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
|
||||
override fun onViewBindingCreated(binding: FragmentReaderWebtoonBinding, savedInstanceState: Bundle?) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
webtoonAdapter = WebtoonAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
with(binding.recyclerView) {
|
||||
setHasFixedSize(true)
|
||||
adapter = webtoonAdapter
|
||||
adapter = readerAdapter
|
||||
addOnPageScrollListener(PageScrollListener())
|
||||
}
|
||||
|
||||
@@ -59,32 +53,43 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
webtoonAdapter = null
|
||||
requireViewBinding().recyclerView.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) {
|
||||
viewLifecycleScope.launch {
|
||||
val setItems = async { webtoonAdapter?.setItems(pages) }
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
setItems.await() ?: return@launch
|
||||
if (position != -1) {
|
||||
with(requireViewBinding().recyclerView) {
|
||||
firstVisibleItemPosition = position
|
||||
post {
|
||||
(findViewHolderForAdapterPosition(position) as? WebtoonHolder)
|
||||
?.restoreScroll(pendingState.scroll)
|
||||
}
|
||||
}
|
||||
notifyPageChanged(position)
|
||||
}
|
||||
} else {
|
||||
setItems.await()
|
||||
override fun onCreateAdapter() = WebtoonAdapter(
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
loader = pageLoader,
|
||||
settings = viewModel.readerSettings,
|
||||
networkState = networkState,
|
||||
exceptionResolver = exceptionResolver,
|
||||
)
|
||||
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
||||
val setItems = async {
|
||||
requireAdapter().setItems(pages)
|
||||
yield()
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
setItems.await()
|
||||
if (position != -1) {
|
||||
with(requireViewBinding().recyclerView) {
|
||||
firstVisibleItemPosition = position
|
||||
post {
|
||||
(findViewHolderForAdapterPosition(position) as? WebtoonHolder)
|
||||
?.restoreScroll(pendingState.scroll)
|
||||
}
|
||||
}
|
||||
notifyPageChanged(position)
|
||||
} else {
|
||||
Snackbar.make(requireView(), R.string.not_found_404, Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
setItems.await()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.koitharu.kotatsu.databinding.SheetPagesBinding
|
||||
import org.koitharu.kotatsu.list.ui.MangaListSpanResolver
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderState
|
||||
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
|
||||
import javax.inject.Inject
|
||||
@@ -101,8 +101,8 @@ class PagesThumbnailsSheet :
|
||||
listener.onPageSelected(item.page)
|
||||
} else {
|
||||
val state = ReaderState(item.page.chapterId, item.page.index, 0)
|
||||
val intent = ReaderActivity.newIntent(view.context, viewModel.manga, state)
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
|
||||
val intent = IntentBuilder(view.context).manga(viewModel.manga).state(state).build()
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view))
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||
import org.koitharu.kotatsu.search.ui.SearchActivity
|
||||
import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter
|
||||
@@ -117,8 +117,8 @@ class MultiSearchActivity :
|
||||
|
||||
override fun onReadClick(manga: Manga, view: View) {
|
||||
if (!selectionController.onItemClick(manga.id)) {
|
||||
val intent = ReaderActivity.newIntent(this, manga)
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
|
||||
val intent = IntentBuilder(this).manga(manga).build()
|
||||
startActivity(intent, scaleUpActivityOptionsOf(view))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.almostEquals
|
||||
import org.koitharu.kotatsu.core.util.ext.asArrayList
|
||||
import org.koitharu.kotatsu.core.util.ext.flatten
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import org.koitharu.kotatsu.core.util.ext.sanitize
|
||||
import org.koitharu.kotatsu.core.util.ext.takeMostFrequent
|
||||
import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull
|
||||
@@ -53,11 +54,10 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.suggestions.domain.MangaSuggestion
|
||||
import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository
|
||||
import org.koitharu.kotatsu.suggestions.domain.TagsBlacklist
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.pow
|
||||
import kotlin.random.Random
|
||||
@@ -263,7 +263,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
PendingIntentCompat.getActivity(
|
||||
applicationContext,
|
||||
id + 2,
|
||||
ReaderActivity.newIntent(applicationContext, manga),
|
||||
IntentBuilder(applicationContext).manga(manga).build(),
|
||||
0,
|
||||
false,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user