diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt index f2db6cb49..cbc9656f0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/BookmarksFragment.kt @@ -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() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt index 8803fa2d7..62d431639 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/os/ShortcutsUpdater.kt @@ -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(), ) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt index 6d8745f84..463a16ec5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Android.kt @@ -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(",") diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index 576aa88c9..d1b6aa21d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -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), ) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 487c843a9..1de67398f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -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() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 5cf4dc756..8272c3b2e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -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), ) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt index 34a5f8332..faa310f6b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoSheet.kt @@ -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) } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt index 2675851ae..e72e050fa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt @@ -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 { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index a49bb4dfa..021f4d83a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -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)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt index a46c13ca7..395cd5b63 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -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) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index afc354213..c33f1b076 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -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) - } } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt index 5bd2e8531..3a260db4f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ReaderViewModel.kt @@ -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) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt index e2a9a82e4..293928fb5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/BaseReaderFragment.kt @@ -17,9 +17,13 @@ abstract class BaseReaderFragment : BaseFragment() { protected val viewModel by activityViewModels() 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(KEY_STATE) + readerAdapter = onCreateAdapter() viewModel.content.observe(viewLifecycleOwner) { onPagesChanged(it.pages, restoredState ?: it.state) @@ -34,6 +38,7 @@ abstract class BaseReaderFragment : BaseFragment() { override fun onDestroyView() { stateToSave = getCurrentState() + readerAdapter = null super.onDestroyView() } @@ -45,6 +50,10 @@ abstract class BaseReaderFragment : BaseFragment() { 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 : BaseFragment() { abstract fun getCurrentState(): ReaderState? - protected abstract fun onPagesChanged(pages: List, pendingState: ReaderState?) + protected abstract fun onCreateAdapter(): BaseReaderAdapter<*> + + protected abstract suspend fun onPagesChanged(pages: List, pendingState: ReaderState?) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt index ce228d578..beed525cd 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/reversed/ReversedReaderFragment.kt @@ -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 @Inject lateinit var pageLoader: PageLoader - private var pagerAdapter: ReversedPagesAdapter? = null - override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, @@ -42,15 +42,8 @@ class ReversedReaderFragment : BaseReaderFragment 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 } 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 } } - override fun onPagesChanged(pages: List, pendingState: ReaderState?) { + override suspend fun onPagesChanged(pages: List, 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 } private fun reversed(position: Int): Int { - return ((pagerAdapter?.itemCount ?: 0) - position - 1).coerceAtLeast(0) + return ((readerAdapter?.itemCount ?: 0) - position - 1).coerceAtLeast(0) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt index c08199d24..a9c656113 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PagerReaderFragment.kt @@ -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() @Inject lateinit var pageLoader: PageLoader - private var pagesAdapter: PagesAdapter? = null - override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, @@ -41,15 +41,8 @@ class PagerReaderFragment : BaseReaderFragment() 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() } override fun onDestroyView() { - pagesAdapter = null requireViewBinding().pager.adapter = null super.onDestroyView() } - override fun onPagesChanged(pages: List, pendingState: ReaderState?) { - viewLifecycleScope.launch { - val items = async { - pagesAdapter?.setItems(pages) + override suspend fun onPagesChanged(pages: List, 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) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt index e98d90c94..78836411a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt @@ -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() 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() 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() } override fun onDestroyView() { - webtoonAdapter = null requireViewBinding().recyclerView.adapter = null super.onDestroyView() } - override fun onPagesChanged(pages: List, 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, 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() } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt index a5aa7ac9c..2886c1a43 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsSheet.kt @@ -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() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt index 36a1125fc..3871a0cfc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/MultiSearchActivity.kt @@ -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)) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index 8d203ac8e..f4b6a24fa 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -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, ),