Option to read in incognito mode instantly

pull/370/head
Koitharu 3 years ago
parent 67bbd3e6d3
commit 96d6f8d8e6
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -15,8 +15,8 @@ android {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 33
versionCode 541 versionCode 542
versionName '5.1-a1' versionName '5.1-b1'
generatedDensities = [] generatedDensities = []
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

@ -5,8 +5,6 @@ import androidx.lifecycle.Observer
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.reverseAsync import org.koitharu.kotatsu.base.domain.reverseAsync
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
import org.koitharu.kotatsu.utils.ext.findActivity
class ReversibleActionObserver( class ReversibleActionObserver(
private val snackbarHost: View, private val snackbarHost: View,
@ -22,9 +20,6 @@ class ReversibleActionObserver(
if (handle != null) { if (handle != null) {
snackbar.setAction(R.string.undo) { handle.reverseAsync() } snackbar.setAction(R.string.undo) { handle.reverseAsync() }
} }
(snackbarHost.context.findActivity() as? BottomNavOwner)?.let {
snackbar.anchorView = it.bottomNav
}
snackbar.show() snackbar.show()
} }
} }

@ -7,6 +7,7 @@ import android.transition.Slide
import android.transition.TransitionManager import android.transition.TransitionManager
import android.view.Gravity import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.AccelerateDecelerateInterpolator
@ -42,6 +43,7 @@ import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.ReaderState import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.utils.ViewBadge import org.koitharu.kotatsu.utils.ViewBadge
import org.koitharu.kotatsu.utils.ext.getDisplayMessage import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat import org.koitharu.kotatsu.utils.ext.setNavigationBarTransparentCompat
import org.koitharu.kotatsu.utils.ext.textAndVisible import org.koitharu.kotatsu.utils.ext.textAndVisible
import javax.inject.Inject import javax.inject.Inject
@ -51,7 +53,7 @@ class DetailsActivity :
BaseActivity<ActivityDetailsBinding>(), BaseActivity<ActivityDetailsBinding>(),
View.OnClickListener, View.OnClickListener,
BottomSheetHeaderBar.OnExpansionChangeListener, BottomSheetHeaderBar.OnExpansionChangeListener,
NoModalBottomSheetOwner { NoModalBottomSheetOwner, View.OnLongClickListener, PopupMenu.OnMenuItemClickListener {
override val bsHeader: BottomSheetHeaderBar? override val bsHeader: BottomSheetHeaderBar?
get() = binding.headerChapters get() = binding.headerChapters
@ -72,6 +74,7 @@ class DetailsActivity :
setDisplayShowTitleEnabled(false) setDisplayShowTitleEnabled(false)
} }
binding.buttonRead.setOnClickListener(this) binding.buttonRead.setOnClickListener(this)
binding.buttonRead.setOnLongClickListener(this)
binding.buttonDropdown.setOnClickListener(this) binding.buttonDropdown.setOnClickListener(this)
viewBadge = ViewBadge(binding.buttonRead, this) viewBadge = ViewBadge(binding.buttonRead, this)
@ -134,25 +137,32 @@ class DetailsActivity :
} }
override fun onClick(v: View) { override fun onClick(v: View) {
val manga = viewModel.manga.value ?: return
when (v.id) { when (v.id) {
R.id.button_read -> openReader(isIncognitoMode = false)
R.id.button_dropdown -> showBranchPopupMenu()
}
}
override fun onLongClick(v: View): Boolean = when (v.id) {
R.id.button_read -> { R.id.button_read -> {
val chapterId = viewModel.historyInfo.value?.history?.chapterId val menu = PopupMenu(v.context, v)
if (chapterId != null && manga.chapters?.none { x -> x.id == chapterId } == true) { menu.inflate(R.menu.popup_read)
showChapterMissingDialog(chapterId) menu.setOnMenuItemClickListener(this)
} else { menu.setForceShowIcon(true)
startActivity( menu.show()
ReaderActivity.newIntent( true
context = this,
manga = manga,
branch = viewModel.selectedBranchValue,
),
)
} }
else -> false
} }
R.id.button_dropdown -> showBranchPopupMenu() override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_incognito -> {
openReader(isIncognitoMode = true)
true
} }
else -> false
} }
override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) { override fun onExpansionStateChanged(headerBar: BottomSheetHeaderBar, isExpanded: Boolean) {
@ -258,13 +268,22 @@ class DetailsActivity :
menu.show() menu.show()
} }
private fun resolveError(e: Throwable) { private fun openReader(isIncognitoMode: Boolean) {
lifecycleScope.launch { val manga = viewModel.manga.value ?: return
if (exceptionResolver.resolve(e)) { val chapterId = viewModel.historyInfo.value?.history?.chapterId
viewModel.reload() if (chapterId != null && manga.chapters?.none { x -> x.id == chapterId } == true) {
} else if (viewModel.manga.value == null) { showChapterMissingDialog(chapterId)
Toast.makeText(this@DetailsActivity, e.getDisplayMessage(resources), Toast.LENGTH_LONG).show() } else {
finishAfterTransition() startActivity(
ReaderActivity.newIntent(
context = this,
manga = manga,
branch = viewModel.selectedBranchValue,
isIncognitoMode = isIncognitoMode,
),
)
if (isIncognitoMode) {
Toast.makeText(this, R.string.incognito_mode, Toast.LENGTH_SHORT).show()
} }
} }
} }

@ -407,10 +407,11 @@ class ReaderActivity :
.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true)) .putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
} }
fun newIntent(context: Context, manga: Manga, branch: String?): Intent { fun newIntent(context: Context, manga: Manga, branch: String?, isIncognitoMode: Boolean): Intent {
return Intent(context, ReaderActivity::class.java) return Intent(context, ReaderActivity::class.java)
.putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true)) .putExtra(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = true))
.putExtra(EXTRA_BRANCH, branch) .putExtra(EXTRA_BRANCH, branch)
.putExtra(EXTRA_INCOGNITO, isIncognitoMode)
} }
fun newIntent(context: Context, manga: Manga, state: ReaderState?): Intent { fun newIntent(context: Context, manga: Manga, state: ReaderState?): Intent {

@ -14,11 +14,10 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.toManga
import org.koitharu.kotatsu.core.db.entity.toMangaTags
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
import org.koitharu.kotatsu.favourites.data.toFavouriteCategory import org.koitharu.kotatsu.favourites.data.toFavouriteCategory
import org.koitharu.kotatsu.favourites.data.toMangaList
import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.local.data.LocalManga import org.koitharu.kotatsu.local.data.LocalManga
import org.koitharu.kotatsu.local.data.LocalStorageChanges import org.koitharu.kotatsu.local.data.LocalStorageChanges
@ -93,7 +92,7 @@ class ShelfRepository @Inject constructor(
categories.map { cat -> categories.map { cat ->
val category = cat.toFavouriteCategory() val category = cat.toFavouriteCategory()
db.favouritesDao.observeAll(category.id, category.order) db.favouritesDao.observeAll(category.id, category.order)
.map { category to it.map { x -> x.manga.toManga(x.tags.toMangaTags()) } } .map { category to it.toMangaList() }
}, },
) { array -> array.toMap() } ) { array -> array.toMap() }
} }

@ -162,7 +162,7 @@ class ShelfViewModel @Inject constructor(
sections: List<ShelfSection>, sections: List<ShelfSection>,
isNetworkAvailable: Boolean, isNetworkAvailable: Boolean,
): List<ListModel> { ): List<ListModel> {
val result = ArrayList<ListModel>(content.favourites.keys.size + 3) val result = ArrayList<ListModel>(content.favourites.keys.size + sections.size)
if (isNetworkAvailable) { if (isNetworkAvailable) {
for (section in sections) { for (section in sections) {
when (section) { when (section) {

@ -91,7 +91,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:clickable="true" android:clickable="true"
app:layout_insetEdge="bottom"
app:menu="@menu/nav_bottom" app:menu="@menu/nav_bottom"
tools:ignore="KeyboardInaccessibleWidget" /> tools:ignore="KeyboardInaccessibleWidget" />

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_incognito"
android:icon="@drawable/ic_incognito"
android:title="@string/incognito_mode" />
</menu>
Loading…
Cancel
Save