diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhUrl.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhUrl.kt index 5c1002c88..46673168f 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhUrl.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhUrl.kt @@ -139,19 +139,21 @@ object EhUrl { fun getTagDefinitionUrl(tag: String) = "https://ehwiki.org/wiki/" + tag.replace(' ', '_') } -inline fun ehUrl(path: String?, builder: ParametersBuilder.() -> Unit) = ehUrl( +inline fun ehUrl(path: String?, host: String = EhUrl.domain, builder: ParametersBuilder.() -> Unit) = ehUrl( path = if (path.isNullOrBlank()) emptyList() else listOf(path), + host = host, parameters = Parameters.build(builder), ) -inline fun ehUrl(path: List, builder: ParametersBuilder.() -> Unit) = ehUrl( +inline fun ehUrl(path: List, host: String = EhUrl.domain, builder: ParametersBuilder.() -> Unit) = ehUrl( path = path, + host = host, parameters = Parameters.build(builder), ) -fun ehUrl(path: List, parameters: Parameters = Parameters.Empty) = URLBuilder( +fun ehUrl(path: List, host: String = EhUrl.domain, parameters: Parameters = Parameters.Empty) = URLBuilder( protocol = URLProtocol.HTTPS, - host = EhUrl.domain, + host = host, pathSegments = path, parameters = parameters, ) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/data/ListUrlBuilder.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/data/ListUrlBuilder.kt index 2b2310839..2b62d7477 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/client/data/ListUrlBuilder.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/client/data/ListUrlBuilder.kt @@ -25,7 +25,6 @@ import com.hippo.ehviewer.client.addQueryParameterIfNotBlank import com.hippo.ehviewer.client.ehUrl import com.hippo.ehviewer.dao.QuickSearch import com.hippo.ehviewer.ui.main.AdvanceTable -import com.hippo.ehviewer.util.encodeUTF8 import com.hippo.ehviewer.util.toIntOrDefault import java.io.UnsupportedEncodingException import java.net.URLDecoder @@ -39,6 +38,7 @@ data class ListUrlBuilder( var mNext: String? = null, // Reset to null after initial loading var mJumpTo: String? = null, + private var mRange: Int = 0, var category: Int = EhUtils.NONE, private var mKeyword: String? = null, var hash: String? = null, @@ -51,15 +51,23 @@ data class ListUrlBuilder( var isOnlySearchCovers: Boolean = false, ) : Parcelable { - fun setIndex(index: String?, isNext: Boolean = true) { - mNext = index?.takeIf { isNext } - mPrev = index?.takeUnless { isNext } + fun setIndex(index: String, isNext: Boolean = true) { + mNext = index.takeIf { isNext } + mPrev = index.takeUnless { isNext } + mRange = 0 } fun setJumpTo(jumpTo: Int) { mJumpTo = jumpTo.takeUnless { it == 0 }?.toString() } + fun setRange(range: Int) { + mRange = range + mPrev = null + mNext = null + mJumpTo = null + } + var keyword: String? get() = if (MODE_UPLOADER == mode) "uploader:$mKeyword" else mKeyword set(keyword) { @@ -270,6 +278,7 @@ data class ListUrlBuilder( addQueryParameterIfNotBlank("prev", mPrev) addQueryParameterIfNotBlank("next", mNext) addQueryParameterIfNotBlank("seek", mJumpTo) + addQueryParameterIfNotBlank("range", mRange.takeIf { it > 0 }?.toString()) // Advance search if (advanceSearch > 0 || minRating > 0 || pageFrom > 0 || pageTo > 0) { addQueryParameter("advsearch", "1") @@ -306,55 +315,25 @@ data class ListUrlBuilder( ) } } - }.toString() + }.buildString() - MODE_UPLOADER -> { - buildString { - append(EhUrl.host) - mKeyword?.let { - append("uploader/").append(encodeUTF8(it)) - } - mPrev?.let { - append("?prev=").append(it) - } - mNext?.let { - append("?next=").append(it) - } - mJumpTo?.let { - append("&seek=").append(it) - } - } - } - - MODE_TAG -> { - buildString { - append(EhUrl.host) - mKeyword?.let { - append("tag/").append(encodeUTF8(it)) - } - mPrev?.let { - append("?prev=").append(it) - } - mNext?.let { - append("?next=").append(it) - } - mJumpTo?.let { - append("&seek=").append(it) - } - } + MODE_UPLOADER, MODE_TAG -> { + val path = if (mode == MODE_UPLOADER) "uploader" else "tag" + ehUrl(listOf(path, requireNotNull(mKeyword))) { + addQueryParameterIfNotBlank("prev", mPrev) + addQueryParameterIfNotBlank("next", mNext) + addQueryParameterIfNotBlank("seek", mJumpTo) + addQueryParameterIfNotBlank("range", mRange.takeIf { it > 0 }?.toString()) + }.buildString() } MODE_WHATS_HOT -> EhUrl.popularUrl MODE_IMAGE_SEARCH -> EhUrl.imageSearchUrl MODE_TOPLIST -> { - buildString { - append(EhUrl.HOST_E) - append("toplist.php?tl=") - append(mKeyword!!) - mJumpTo?.let { - append("&p=").append(it) - } - } + ehUrl("toplist.php", EhUrl.DOMAIN_E) { + addQueryParameter("tl", requireNotNull(mKeyword)) + addQueryParameterIfNotBlank("p", mJumpTo) + }.buildString() } else -> throw IllegalStateException("Unexpected value: $mode") diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt index 44f0ce896..9a7262fd0 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/GalleryListScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.material.icons.automirrored.filled.Help import androidx.compose.material.icons.automirrored.filled.LastPage import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Refresh +import androidx.compose.material.icons.filled.Shuffle import androidx.compose.material.icons.outlined.Bookmarks import androidx.compose.material3.ElevatedCard import androidx.compose.material3.HorizontalDivider @@ -103,6 +104,7 @@ import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_NORMAL import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_SUBSCRIPTION import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_TAG import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_TOPLIST +import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_UPLOADER import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_WHATS_HOT import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser import com.hippo.ehviewer.client.parser.GalleryPageUrlParser @@ -144,6 +146,7 @@ import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withUIContext import java.io.File import kotlin.math.roundToInt +import kotlin.random.Random import kotlinx.coroutines.delay import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onEach @@ -718,7 +721,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) { }, refreshState = refreshState, onRefresh = { - urlBuilder.setIndex(null) + urlBuilder.setRange(0) data.refresh() }, onLoading = { searchBarOffsetY = 0 }, @@ -743,9 +746,14 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) { onExpandChanged = { expanded = it }, autoCancel = true, ) { + if (urlBuilder.mode in arrayOf(MODE_NORMAL, MODE_UPLOADER, MODE_TAG)) { + onClick(Icons.Default.Shuffle) { + urlBuilder.setRange(Random.nextInt(100)) + data.refresh() + } + } onClick(Icons.Default.Refresh) { - urlBuilder.setIndex(null) - urlBuilder.mJumpTo = null + urlBuilder.setRange(0) data.refresh() } if (urlBuilder.mode != MODE_WHATS_HOT) { @@ -774,7 +782,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) { } onClick(Icons.AutoMirrored.Default.LastPage) { if (isTopList) { - urlBuilder.mJumpTo = "${TOPLIST_PAGES - 1}" + urlBuilder.setJumpTo(TOPLIST_PAGES - 1) data.refresh() } else { urlBuilder.setIndex("1", false) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/util/URLEncoderCompat.kt b/app/src/main/kotlin/com/hippo/ehviewer/util/URLEncoderCompat.kt deleted file mode 100644 index b169ebb19..000000000 --- a/app/src/main/kotlin/com/hippo/ehviewer/util/URLEncoderCompat.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.hippo.ehviewer.util - -import android.os.Build -import java.net.URLEncoder -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets - -fun encode(s: String, charset: Charset): String { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - URLEncoder.encode(s, charset) - } else { - URLEncoder.encode(s, charset.name()) - } -} - -fun encodeUTF8(s: String): String { - return encode(s, StandardCharsets.UTF_8) -}