diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt index d2812d4a6..9a05baf54 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/ChaptersFragment.kt @@ -75,7 +75,10 @@ class ChaptersFragment : BaseFragment(), override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) - inflater.inflate(R.menu.opt_chapters, menu) + // workaround: duplication after screen rotation + if (menu.findItem(R.id.action_reversed) == null) { + inflater.inflate(R.menu.opt_chapters, menu) + } } override fun onPrepareOptionsMenu(menu: Menu) { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index be4b2316d..b6ecb17ea 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -30,8 +30,7 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.base.domain.MangaIntent import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.browser.BrowserActivity -import org.koitharu.kotatsu.browser.cloudflare.CloudFlareDialog -import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException +import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.databinding.ActivityDetailsBinding @@ -87,9 +86,8 @@ class DetailsActivity : BaseActivity(), TabLayoutMediato private fun onError(e: Throwable) { when { - e is CloudFlareProtectedException -> { - CloudFlareDialog.newInstance(e.url) - .show(supportFragmentManager, CloudFlareDialog.TAG) + ExceptionResolver.canResolve(e) -> { + resolveError(e) } viewModel.manga.value == null -> { Toast.makeText(this, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show() @@ -284,6 +282,17 @@ class DetailsActivity : BaseActivity(), TabLayoutMediato } } + private fun resolveError(e: Throwable) { + lifecycleScope.launch { + if (exceptionResolver.resolve(e)) { + viewModel.reload() + } else if (viewModel.manga.value == null) { + Toast.makeText(this@DetailsActivity, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show() + finishAfterTransition() + } + } + } + companion object { fun newIntent(context: Context, manga: Manga): Intent { diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt index a9a758ea6..e3101c734 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.asFlow import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.* import kotlinx.coroutines.plus import org.koitharu.kotatsu.base.domain.MangaDataRepository @@ -29,7 +30,7 @@ import org.koitharu.kotatsu.utils.ext.mapToSet import java.io.IOException class DetailsViewModel( - intent: MangaIntent, + private val intent: MangaIntent, private val historyRepository: HistoryRepository, private val favouritesRepository: FavouritesRepository, private val localMangaRepository: LocalMangaRepository, @@ -38,6 +39,7 @@ class DetailsViewModel( private val settings: AppSettings, ) : BaseViewModel() { + private var loadingJob: Job private val mangaData = MutableStateFlow(intent.manga) private val selectedBranch = MutableStateFlow(null) @@ -109,28 +111,12 @@ class DetailsViewModel( }.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default) init { - launchLoadingJob(Dispatchers.Default) { - var manga = mangaDataRepository.resolveIntent(intent) - ?: throw MangaNotFoundException("Cannot find manga") - mangaData.value = manga - manga = MangaRepository(manga.source).getDetails(manga) - // find default branch - val hist = historyRepository.getOne(manga) - selectedBranch.value = if (hist != null) { - manga.chapters?.find { it.id == hist.chapterId }?.branch - } else { - predictBranch(manga.chapters) - } - mangaData.value = manga - remoteManga.value = runCatching { - if (manga.source == MangaSource.LOCAL) { - val m = localMangaRepository.getRemoteManga(manga) ?: return@runCatching null - MangaRepository(m.source).getDetails(m) - } else { - localMangaRepository.findSavedManga(manga) - } - }.getOrNull() - } + loadingJob = doLoad() + } + + fun reload() { + loadingJob.cancel() + loadingJob = doLoad() } fun deleteLocal(manga: Manga) { @@ -156,6 +142,29 @@ class DetailsViewModel( return remoteManga.value } + private fun doLoad() = launchLoadingJob(Dispatchers.Default) { + var manga = mangaDataRepository.resolveIntent(intent) + ?: throw MangaNotFoundException("Cannot find manga") + mangaData.value = manga + manga = MangaRepository(manga.source).getDetails(manga) + // find default branch + val hist = historyRepository.getOne(manga) + selectedBranch.value = if (hist != null) { + manga.chapters?.find { it.id == hist.chapterId }?.branch + } else { + predictBranch(manga.chapters) + } + mangaData.value = manga + remoteManga.value = runCatching { + if (manga.source == MangaSource.LOCAL) { + val m = localMangaRepository.getRemoteManga(manga) ?: return@runCatching null + MangaRepository(m.source).getDetails(m) + } else { + localMangaRepository.findSavedManga(manga) + } + }.getOrNull() + } + private fun mapChapters( chapters: List, downloadedChapters: List?, diff --git a/app/src/main/res/layout/item_source_config_draggable.xml b/app/src/main/res/layout/item_source_config_draggable.xml index 2e4ae2c57..ffa9a68e5 100644 --- a/app/src/main/res/layout/item_source_config_draggable.xml +++ b/app/src/main/res/layout/item_source_config_draggable.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="?android:listPreferredItemHeightSmall" + android:background="?android:windowBackground" android:gravity="center_vertical" android:orientation="horizontal">