Refactor addToFavorites()

This commit is contained in:
FooIbar authored and tarsin committed 2023-07-03 07:16:44 +08:00
1 parent 861c05db44
commit 1473f6326d
6 files changed
+128 -136

No files matched your search

@@ -238,8 +238,8 @@ object EhEngine {
suspend fun addFavorites(
gid: Long,
token: String?,
dstCat: Int,
note: String?,
dstCat: Int = -1,
note: String? = null,
) {
val catStr: String = when (dstCat) {
-1 -> "favdel"
@@ -450,6 +450,6 @@ object EhEngine {
}
suspend fun addFavoritesRange(gidTokenArray: Array<Pair<Long, String>>, dstCat: Int) {
gidTokenArray.forEach { (gid, token) -> addFavorites(gid, token, dstCat, null) }
gidTokenArray.forEach { (gid, token) -> addFavorites(gid, token, dstCat) }
}
}
@@ -201,9 +201,7 @@ object GalleryDetailParser {
gd.isFavorited = false
if (gdf != null) {
val favoriteName = gdf.text().trim()
if (favoriteName == "Add to Favorites") {
gd.favoriteName = null
} else {
if (favoriteName != "Add to Favorites") {
gd.isFavorited = true
gd.favoriteName = gdf.text().trim()
PATTERN_FAVORITE_SLOT.find(body)?.run {
@@ -17,14 +17,12 @@ package com.hippo.ehviewer.client.parser
import android.util.Log
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.client.exception.ParseException
import com.hippo.ehviewer.util.ExceptionUtils
import com.hippo.ehviewer.yorozuya.toIntOrDefault
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import splitties.init.appCtx
import java.util.regex.Pattern
object GalleryListParser {
@@ -96,7 +94,6 @@ object GalleryListParser {
runCatching { parseGalleryInfo(it.toString()) }.onFailure { it.printStackTrace() }.getOrNull()?.apply {
if (favoriteSlot == -2 && EhDB.containLocalFavorites(gid)) {
favoriteSlot = -1
favoriteName = appCtx.getString(R.string.local_favorites)
}
generateSLang()
}
@@ -25,6 +25,7 @@ import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.DriveFileMove
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.HeartBroken
import androidx.compose.material.icons.filled.MenuBook
import androidx.compose.material3.Text
@@ -51,13 +52,11 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.lang.launchNow
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.tarsin.coroutines.runSuspendCatching
import rikka.core.util.ContextUtils.requireActivity
import splitties.init.appCtx
import kotlin.coroutines.resume
object CommonOperations {
fun startDownload(activity: MainActivity?, galleryInfo: GalleryInfo, forceDefault: Boolean) {
@@ -191,64 +190,82 @@ suspend fun keepNoMediaFileStatus() {
}
}
suspend fun Context.addToFavorites(galleryInfo: GalleryInfo, select: Boolean = false) {
val slot = Settings.defaultFavSlot
val localFav = getString(R.string.local_favorites)
val items = Settings.favCat.toMutableList().apply { add(0, localFav) }
suspend fun doAddToFavorites(slot: Int, newFavoriteName: String?) {
when (slot) {
-1 -> {
suspend fun DialogState.addToFavorites(galleryInfo: GalleryInfo): Boolean {
val localFaved = EhDB.containLocalFavorites(galleryInfo.gid)
val localFav = if (localFaved) {
Icons.Default.Favorite
} else {
Icons.Default.FavoriteBorder
} to appCtx.getString(R.string.local_favorites)
val items = Settings.favCat.mapIndexed { index, name ->
if (galleryInfo.favoriteSlot == index) {
Icons.Default.Favorite
} else {
Icons.Default.FavoriteBorder
} to name
}.toTypedArray()
val slot = showSelectItemWithIcon(localFav, *items, title = R.string.add_favorites_dialog_title) - 1
val newFavoriteName = Settings.favCat.getOrNull(slot)
return doAddToFavorites(galleryInfo, slot, newFavoriteName)
}
private suspend fun doAddToFavorites(
galleryInfo: GalleryInfo,
slot: Int = -2,
newFavoriteName: String? = null,
note: String? = null,
localFaved: Boolean = false,
): Boolean {
val add = when (slot) {
-2 -> {
EhDB.removeLocalFavorites(galleryInfo.gid)
if (galleryInfo.favoriteSlot >= 0) {
EhEngine.addFavorites(galleryInfo.gid, galleryInfo.token)
}
false
}
-1 -> {
if (localFaved) {
EhDB.removeLocalFavorites(galleryInfo.gid)
} else {
EhDB.putLocalFavorites(galleryInfo)
}
!localFaved
}
in 0..9 -> {
EhEngine.addFavorites(galleryInfo.gid, galleryInfo.token, slot, "")
}
else -> {
throw EhException("Invalid favslot!")
in 0..9 -> {
if (galleryInfo.favoriteSlot == slot) {
EhEngine.addFavorites(galleryInfo.gid, galleryInfo.token)
false
} else {
EhEngine.addFavorites(galleryInfo.gid, galleryInfo.token, slot, note)
true
}
}
galleryInfo.favoriteName = newFavoriteName
galleryInfo.favoriteSlot = slot
else -> throw EhException("Invalid favorite slot!")
}
if (add) {
if (slot != -1 || galleryInfo.favoriteSlot == -2) { // Cloud favorites have priority
galleryInfo.favoriteSlot = slot
galleryInfo.favoriteName = newFavoriteName
withUIContext {
FavouriteStatusRouter.modifyFavourites(galleryInfo.gid, slot)
}
}
} else if (slot != -1 || galleryInfo.favoriteSlot == -1) {
val newSlot = if (slot >= 0 && localFaved) -1 else -2
galleryInfo.favoriteSlot = newSlot
galleryInfo.favoriteName = null
withUIContext {
FavouriteStatusRouter.modifyFavourites(galleryInfo.gid, slot)
}
}
if (!select && slot >= -1 && slot <= 9) {
val newFavoriteName = if (slot >= 0) items[slot + 1] else null
doAddToFavorites(slot, newFavoriteName)
} else {
val (slot1, checked) = withUIContext {
suspendCancellableCoroutine { cont ->
ListCheckBoxDialogBuilder(
this@addToFavorites,
items,
{ b, _, position -> cont.resume(position - 1 to b.isChecked) },
getString(R.string.remember_favorite_collection),
false,
).setTitle(R.string.add_favorites_dialog_title).setOnCancelListener { cont.cancel() }.show()
}
}
val newFavoriteName = if (slot1 in 0..9) items[slot1 + 1] else null
doAddToFavorites(slot1, newFavoriteName)
if (checked) {
Settings.defaultFavSlot = slot1
} else {
Settings.defaultFavSlot = -2
FavouriteStatusRouter.modifyFavourites(galleryInfo.gid, newSlot)
}
}
return add
}
suspend fun removeFromFavorites(galleryInfo: GalleryInfo) {
EhDB.removeLocalFavorites(galleryInfo.gid)
EhEngine.addFavorites(galleryInfo.gid, galleryInfo.token, -1, "")
galleryInfo.favoriteName = null
galleryInfo.favoriteSlot = -2
withUIContext {
FavouriteStatusRouter.modifyFavourites(galleryInfo.gid, -2)
}
}
suspend fun removeFromFavorites(galleryInfo: GalleryInfo) = doAddToFavorites(galleryInfo)
fun Context.navToReader(info: GalleryInfo, page: Int = -1) {
val intent = Intent(this, ReaderActivity::class.java)
@@ -287,6 +304,7 @@ suspend fun DialogState.doGalleryInfoAction(info: GalleryInfo, context: Context)
CommonOperations.startDownload(this@with, info, false)
}
}
2 -> if (favourite) {
runSuspendCatching {
removeFromFavorites(info)
@@ -302,6 +320,7 @@ suspend fun DialogState.doGalleryInfoAction(info: GalleryInfo, context: Context)
showTip(R.string.add_to_favorite_failure, BaseScene.LENGTH_LONG)
}
}
3 -> showMoveDownloadLabel(info)
}
true
@@ -150,10 +150,10 @@ import com.hippo.ehviewer.ui.main.GalleryDetailHeaderCard
import com.hippo.ehviewer.ui.main.GalleryTags
import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.openBrowser
import com.hippo.ehviewer.ui.removeFromFavorites
import com.hippo.ehviewer.ui.scene.GalleryListScene.Companion.toStartArgs
import com.hippo.ehviewer.ui.setMD3Content
import com.hippo.ehviewer.ui.tools.CrystalCard
import com.hippo.ehviewer.ui.tools.DialogState
import com.hippo.ehviewer.ui.tools.FilledTertiaryIconButton
import com.hippo.ehviewer.ui.tools.FilledTertiaryIconToggleButton
import com.hippo.ehviewer.ui.tools.GalleryDetailRating
@@ -168,6 +168,8 @@ import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.HttpUrl.Companion.toHttpUrl
import splitties.systemservices.downloadManager
@@ -209,7 +211,7 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
private var mArchiveFormParamOr: String? = null
private var mArchiveList: List<ArchiveParser.Archive>? = null
private var mCurrentFunds: HomeParser.Funds? = null
private var mModifyingFavorites = false
private var favoritesLock = Mutex()
@StringRes
private fun getRatingText(rating: Float): Int {
@@ -277,6 +279,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
private val category: Int
get() = composeBindingGD?.category ?: composeBindingGI?.category ?: -1
private val dialogState = DialogState()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
@@ -396,6 +400,7 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
(requireActivity() as MainActivity).mShareUrl = galleryDetailUrl
return ComposeView(requireContext()).apply {
setMD3Content {
dialogState.Handler()
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
Scaffold(
topBar = {
@@ -872,37 +877,26 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
private fun modifyFavourite() {
val galleryDetail = composeBindingGD ?: return
lifecycleScope.launchIO {
if (!mModifyingFavorites) {
favoritesLock.withLock {
var remove = false
val containLocalFavorites = EhDB.containLocalFavorites(galleryDetail.gid)
if (containLocalFavorites || galleryDetail.isFavorited) {
mModifyingFavorites = true
runCatching {
removeFromFavorites(galleryDetail)
runCatching {
remove = !dialogState.addToFavorites(galleryDetail)
if (remove) {
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT)
onModifyFavoritesSuccess(true)
}.onFailure {
if (it !is CancellationException) {
showTip(R.string.remove_from_favorite_failure, LENGTH_LONG)
}
}
mModifyingFavorites = false
remove = true
}
if (!remove) {
mModifyingFavorites = true
runCatching {
requireContext().addToFavorites(galleryDetail)
} else {
showTip(R.string.add_to_favorite_success, LENGTH_SHORT)
withUIContext {
onModifyFavoritesSuccess(false)
}
}.onFailure {
if (it !is CancellationException) {
}
withUIContext {
onModifyFavoritesSuccess()
}
}.onFailure {
if (it !is CancellationException) {
if (remove) {
showTip(R.string.remove_from_favorite_failure, LENGTH_LONG)
} else {
showTip(R.string.add_to_favorite_failure, LENGTH_LONG)
}
}
mModifyingFavorites = false
}
withUIContext {
// Update UI
@@ -1245,47 +1239,6 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
.show()
}
private fun modifyFavouriteLongClick() {
lifecycleScope.launchIO {
if (composeBindingGD != null && !mModifyingFavorites) {
var remove = false
if (EhDB.containLocalFavorites(composeBindingGD!!.gid) || composeBindingGD!!.isFavorited) {
mModifyingFavorites = true
runCatching {
removeFromFavorites(composeBindingGD!!)
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT)
onModifyFavoritesSuccess(true)
}.onFailure {
if (it !is CancellationException) {
showTip(R.string.remove_from_favorite_failure, LENGTH_LONG)
}
}
mModifyingFavorites = false
remove = true
}
if (!remove) {
mModifyingFavorites = true
runCatching {
requireContext().addToFavorites(composeBindingGD!!, true)
showTip(R.string.add_to_favorite_success, LENGTH_SHORT)
withUIContext {
onModifyFavoritesSuccess(false)
}
}.onFailure {
if (it !is CancellationException) {
showTip(R.string.add_to_favorite_failure, LENGTH_LONG)
}
}
mModifyingFavorites = false
}
withUIContext {
// Update UI
updateFavoriteDrawable()
}
}
}
}
private fun updateDownloadText() {
downloadButtonText = when (mDownloadState) {
DownloadInfo.STATE_INVALID -> getString(R.string.download)
@@ -1339,9 +1292,9 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener {
override fun onRenameLabel(from: String, to: String) {}
override fun onUpdateLabels() {}
private fun onModifyFavoritesSuccess(addOrRemove: Boolean) {
private fun onModifyFavoritesSuccess() {
if (composeBindingGD != null) {
composeBindingGD!!.isFavorited = !addOrRemove && composeBindingGD!!.favoriteName != null
composeBindingGD!!.isFavorited = composeBindingGD!!.favoriteName != null
updateFavoriteDrawable()
}
}
@@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Icon
@@ -164,13 +166,36 @@ class DialogState {
): Int = showNoButton {
Column {
Text(text = title, modifier = Modifier.padding(horizontal = 16.dp).padding(top = 16.dp), style = MaterialTheme.typography.titleMedium)
items.forEachIndexed { index, (icon, text) ->
Row(
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = icon, contentDescription = null, modifier = Modifier.padding(16.dp), tint = AlertDialogDefaults.iconContentColor)
Text(text = stringResource(id = text), style = MaterialTheme.typography.titleMedium)
LazyColumn {
itemsIndexed(items) { index, (icon, text) ->
Row(
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = icon, contentDescription = null, modifier = Modifier.padding(16.dp), tint = AlertDialogDefaults.iconContentColor)
Text(text = stringResource(id = text), style = MaterialTheme.typography.titleMedium)
}
}
}
Spacer(modifier = Modifier.size(8.dp))
}
}
suspend fun showSelectItemWithIcon(
vararg items: Pair<ImageVector, String>,
@StringRes title: Int,
): Int = showNoButton {
Column {
Text(text = stringResource(id = title), modifier = Modifier.padding(horizontal = 16.dp).padding(top = 16.dp), style = MaterialTheme.typography.titleMedium)
LazyColumn {
itemsIndexed(items) { index, (icon, text) ->
Row(
modifier = Modifier.clickable { dismissWith(index) }.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = icon, contentDescription = null, modifier = Modifier.padding(16.dp), tint = AlertDialogDefaults.iconContentColor)
Text(text = text, style = MaterialTheme.typography.titleMedium)
}
}
}
Spacer(modifier = Modifier.size(8.dp))