Compare commits

...
13 Commits
Author SHA1 Message Date
tarsin ce823e9b20 Release 1.8.6.2
Releases / Build (push) Has been cancelled
2023-02-20 19:06:59 +08:00
FooIbar 0caa5b1a3b Fix 509 detection false positive 2023-02-20 19:06:13 +08:00
FooIbar 9edea5d584 Clean up unfinished download files 2023-02-20 18:48:49 +08:00
FooIbar 9a773aeb39 Workaround for del tag parsing in comments 2023-02-20 18:48:40 +08:00
FooIbar 9fd3196bb1 Use initializer instead of getter for coroutineContext 2023-02-20 18:48:34 +08:00
FooIbar 7580572874 Temporarily disable vpn bypass on login 2023-02-20 18:48:27 +08:00
tarsin 06acc620f4 Resolve #842 2023-02-20 18:48:19 +08:00
FooIbar 367358d277 Resolve #789 2023-02-20 18:48:13 +08:00
tarsin d61df599e8 Release 1.8.6.1
Releases / Build (push) Has been cancelled
2023-02-18 10:38:33 +08:00
tarsin 989a0a01c1 Fix quicksearch progress 2023-02-18 10:37:57 +08:00
tarsin 12108645e9 Fix a stupid memleak 2023-02-18 10:37:45 +08:00
FooIbar 4910ec194d Fix search keyword in tag mode 2023-02-18 10:37:29 +08:00
FooIbar f730f43945 Fix comment last edited time parsing 2023-02-18 10:37:14 +08:00
10 changed files with 121 additions and 105 deletions

No files matched your search

+2 -2
View File
@@ -34,8 +34,8 @@ android {
applicationId = "moe.tarsin.ehviewer" applicationId = "moe.tarsin.ehviewer"
minSdk = 28 minSdk = 28
targetSdk = 33 targetSdk = 33
versionCode = 180032 versionCode = 180034
versionName = "1.8.6.0" versionName = "1.8.6.2"
resourceConfigurations.addAll( resourceConfigurations.addAll(
listOf( listOf(
"zh", "zh",
+1 -1
View File
@@ -36,7 +36,7 @@
<activity <activity
android:name=".ui.login.LoginActivity" android:name=".ui.login.LoginActivity"
android:exported="false" android:exported="false"
android:theme="@style/AppTheme" android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"/> android:windowSoftInputMode="adjustResize"/>
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.MainActivity"
@@ -91,7 +91,8 @@ object GalleryDetailParser {
// Error info // Error info
PATTERN_ERROR.find(body)?.run { throw EhException(groupValues[1]) } PATTERN_ERROR.find(body)?.run { throw EhException(groupValues[1]) }
val galleryDetail = GalleryDetail() val galleryDetail = GalleryDetail()
val document = Jsoup.parse(body) // Temporary workaround, see https://github.com/jhy/jsoup/issues/1850
val document = Jsoup.parse(body.replace("del>", "s>"))
parseDetail(galleryDetail, document, body) parseDetail(galleryDetail, document, body)
galleryDetail.tags = parseTagGroups(document) galleryDetail.tags = parseTagGroups(document)
galleryDetail.comments = parseComments(document) galleryDetail.comments = parseComments(document)
@@ -376,15 +377,15 @@ object GalleryDetailParser {
} }
// time // time
val c3 = JsoupUtils.getElementByClass(element, "c3") val c3 = JsoupUtils.getElementByClass(element, "c3")
var temp = c3!!.ownText() val temp = c3!!.ownText()
if (temp.endsWith(':')) { val time = if (temp.endsWith(':')) {
temp = temp.substring("Posted on ".length, temp.length - " by:".length)
// user // user
comment.user = c3.child(0).text() comment.user = c3.child(0).text()
temp.substring("Posted on ".length, temp.length - " by:".length)
} else { } else {
temp = temp.substring("Posted on ".length) temp.substring("Posted on ".length)
} }
comment.time = Instant.from(WEB_COMMENT_DATE_FORMAT.parse(temp)).toEpochMilli() comment.time = Instant.from(WEB_COMMENT_DATE_FORMAT.parse(time)).toEpochMilli()
// comment // comment
val c6 = JsoupUtils.getElementByClass(element, "c6") val c6 = JsoupUtils.getElementByClass(element, "c6")
// fix underline support // fix underline support
@@ -407,7 +408,7 @@ object GalleryDetailParser {
val e = c8.children().first() val e = c8.children().first()
if (e != null) { if (e != null) {
comment.lastEdited = comment.lastEdited =
Instant.from(WEB_COMMENT_DATE_FORMAT.parse(temp)).toEpochMilli() Instant.from(WEB_COMMENT_DATE_FORMAT.parse(e.text())).toEpochMilli()
} }
} }
comment comment
@@ -36,6 +36,7 @@ import com.hippo.yorozuya.FileUtils
import com.hippo.yorozuya.MathUtils import com.hippo.yorozuya.MathUtils
import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import moe.tarsin.coroutines.runSuspendCatching
import okhttp3.executeAsync import okhttp3.executeAsync
import okio.buffer import okio.buffer
import java.io.File import java.io.File
@@ -194,7 +195,7 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
return receivedSize return receivedSize
} }
findDownloadFileForIndex(index, extension)?.runCatching { findDownloadFileForIndex(index, extension)?.runSuspendCatching {
openOutputStream().use { outputStream -> openOutputStream().use { outputStream ->
(outputStream as FileOutputStream).channel.use { return doSave(it) == length } (outputStream as FileOutputStream).channel.use { return doSave(it) == length }
} }
@@ -208,7 +209,7 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
val key = EhCacheKeyFactory.getImageKey(mGid, index) val key = EhCacheKeyFactory.getImageKey(mGid, index)
val editor = sCache.edit(key) ?: return false val editor = sCache.edit(key) ?: return false
var received: Long = 0 var received: Long = 0
runCatching { runSuspendCatching {
editor.metadata.toFile().writeText(extension) editor.metadata.toFile().writeText(extension)
editor.data.toFile().outputStream().use { outputStream -> editor.data.toFile().outputStream().use { outputStream ->
outputStream.channel.use { received = doSave(it) } outputStream.channel.use { received = doSave(it) }
@@ -365,7 +365,7 @@ public final class SpiderQueen implements Runnable {
request(index, false); request(index, false);
} }
private int getPageState(int index) { public int getPageState(int index) {
synchronized (mPageStateLock) { synchronized (mPageStateLock) {
if (mPageStateArray != null && index >= 0 && index < mPageStateArray.length) { if (mPageStateArray != null && index >= 0 && index < mPageStateArray.length) {
return mPageStateArray[index]; return mPageStateArray[index];
@@ -12,9 +12,10 @@ import com.hippo.ehviewer.spider.SpiderQueen.NETWORK_ERROR
import com.hippo.ehviewer.spider.SpiderQueen.PTOKEN_FAILED_MESSAGE import com.hippo.ehviewer.spider.SpiderQueen.PTOKEN_FAILED_MESSAGE
import com.hippo.ehviewer.spider.SpiderQueen.STATE_FAILED import com.hippo.ehviewer.spider.SpiderQueen.STATE_FAILED
import com.hippo.ehviewer.spider.SpiderQueen.STATE_FINISHED import com.hippo.ehviewer.spider.SpiderQueen.STATE_FINISHED
import com.hippo.ehviewer.spider.SpiderQueen.STATE_DOWNLOADING
import com.hippo.image.Image.Companion.decode import com.hippo.image.Image.Companion.decode
import com.hippo.util.ExceptionUtils import com.hippo.util.ExceptionUtils
import com.hippo.yorozuya.StringUtils import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -27,7 +28,6 @@ import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.sync.withPermit
import moe.tarsin.coroutines.runSuspendCatching import moe.tarsin.coroutines.runSuspendCatching
import kotlin.coroutines.CoroutineContext
class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope { class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
private val spiderDen private val spiderDen
@@ -42,8 +42,7 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
private var isDownloadMode = false private var isDownloadMode = false
private val size private val size
get() = queen.size() get() = queen.size()
override val coroutineContext: CoroutineContext override val coroutineContext = Dispatchers.IO + Job()
get() = Dispatchers.IO + Job()
fun cancelDecode(index: Int) { fun cancelDecode(index: Int) {
decoder.cancel(index) decoder.cancel(index)
@@ -80,6 +79,15 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
mSemaphore.withPermit { mSemaphore.withPermit {
doInJob(index, force) doInJob(index, force)
} }
}.apply {
invokeOnCompletion {
if (queen.getPageState(index) == STATE_DOWNLOADING) {
Log.d(DEBUG_TAG, "Download image cancelled $index")
launchNonCancellable {
spiderDen.remove(index)
}
}
}
} }
} }
} }
@@ -100,7 +108,7 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
?: queen.getPTokenFromInternet(index) ?: queen.getPTokenFromInternet(index)
?: queen.getPTokenFromMultiPageViewer(index) ?: queen.getPTokenFromMultiPageViewer(index)
} }
queen.updatePageState(index, SpiderQueen.STATE_DOWNLOADING) queen.updatePageState(index, STATE_DOWNLOADING)
if (!force && index in spiderDen) { if (!force && index in spiderDen) {
return queen.updatePageState(index, STATE_FINISHED) return queen.updatePageState(index, STATE_FINISHED)
} }
@@ -149,7 +157,7 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
} }
runSuspendCatching { runSuspendCatching {
getGalleryPage(pageUrl, spiderInfo.gid, spiderInfo.token).also { getGalleryPage(pageUrl, spiderInfo.gid, spiderInfo.token).also {
if (StringUtils.endsWith(it.imageUrl, URL_509_SUFFIX_ARRAY)) { if (check509(it.imageUrl)) {
// Get 509 // Get 509
queen.notifyGet509(index) queen.notifyGet509(index)
error = ERROR_509 error = ERROR_509
@@ -200,7 +208,7 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
localShowKey, localShowKey,
previousPToken previousPToken
).also { ).also {
if (StringUtils.endsWith(it.imageUrl, URL_509_SUFFIX_ARRAY)) { if (check509(it.imageUrl)) {
// Get 509 // Get 509
queen.notifyGet509(index) queen.notifyGet509(index)
error = ERROR_509 error = ERROR_509
@@ -270,6 +278,7 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
}.onFailure { }.onFailure {
it.printStackTrace() it.printStackTrace()
error = NETWORK_ERROR error = NETWORK_ERROR
forceHtml = true
} }
Log.d(DEBUG_TAG, "End download image $index") Log.d(DEBUG_TAG, "End download image $index")
} }
@@ -278,10 +287,13 @@ class SpiderQueenWorker(private val queen: SpiderQueen) : CoroutineScope {
} }
companion object { companion object {
private val URL_509_SUFFIX_ARRAY = arrayOf( private val URL_509_ARRAY = arrayOf(
"/509.gif", "https://ehgt.org/g/509.gif",
"/509s.gif" "https://ehgt.org/g/509s.gif",
"https://exhentai.org/img/509.gif",
"https://exhentai.org/img/509s.gif"
) )
private fun check509(url: String) = url in URL_509_ARRAY
private const val DEBUG_TAG = "SpiderQueenWorker" private const val DEBUG_TAG = "SpiderQueenWorker"
} }
@@ -89,8 +89,8 @@ import java.io.OutputStream
class MainActivity : EhActivity() { class MainActivity : EhActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController private lateinit var navController: NavController
private lateinit var connectivityManager: ConnectivityManager private val connectivityManager by lazy { getSystemService<ConnectivityManager>()!! }
private val availableNetworks: MutableList<Network> = mutableListOf() private val availableNetworks = mutableListOf<Network>()
private fun saveImageToTempFile(uri: Uri): File? { private fun saveImageToTempFile(uri: Uri): File? {
val src = ImageDecoder.createSource(contentResolver, uri) val src = ImageDecoder.createSource(contentResolver, uri)
@@ -223,7 +223,6 @@ class MainActivity : EhActivity() {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
connectivityManager = getSystemService()!!
if (Settings.getDF() && Settings.getBypassVpn()) { if (Settings.getDF() && Settings.getBypassVpn()) {
bypassVpn() bypassVpn()
} }
@@ -233,13 +232,7 @@ class MainActivity : EhActivity() {
val navHostFragment = val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
navController = navHostFragment.navController navController = navHostFragment.navController
if (EhUtils.needSignedIn()) { if (!EhUtils.needSignedIn()) setNavGraph()
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
setNavGraph()
}.launch(Intent(this, LoginActivity::class.java))
} else {
setNavGraph()
}
binding.drawView.addDrawerListener(mDrawerOnBackPressedCallback) binding.drawView.addDrawerListener(mDrawerOnBackPressedCallback)
binding.navView.setupWithNavController(navController) binding.navView.setupWithNavController(navController)
@@ -371,7 +364,19 @@ class MainActivity : EhActivity() {
} }
} }
private val loginLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (availableNetworks.isNotEmpty()) {
connectivityManager.bindProcessToNetwork(availableNetworks.last())
}
setNavGraph()
}
override fun onResume() { override fun onResume() {
if (EhUtils.needSignedIn()) {
connectivityManager.bindProcessToNetwork(null)
loginLauncher.launch(Intent(this, LoginActivity::class.java))
}
super.onResume() super.onResume()
lifecycleScope.launch { lifecycleScope.launch {
delay(100) delay(100)
@@ -74,7 +74,9 @@ import com.hippo.ehviewer.client.EhRequest
import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.GalleryInfo import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.client.data.ListUrlBuilder import com.hippo.ehviewer.client.data.ListUrlBuilder
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_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_TOPLIST
import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_WHATS_HOT import com.hippo.ehviewer.client.data.ListUrlBuilder.Companion.MODE_WHATS_HOT
import com.hippo.ehviewer.client.exception.EhException import com.hippo.ehviewer.client.exception.EhException
@@ -98,13 +100,14 @@ import com.hippo.widget.FabLayout
import com.hippo.widget.FabLayout.OnClickFabListener import com.hippo.widget.FabLayout.OnClickFabListener
import com.hippo.widget.FabLayout.OnExpandListener import com.hippo.widget.FabLayout.OnExpandListener
import com.hippo.yorozuya.AnimationUtils import com.hippo.yorozuya.AnimationUtils
import com.hippo.yorozuya.MathUtils
import com.hippo.yorozuya.SimpleAnimatorListener import com.hippo.yorozuya.SimpleAnimatorListener
import com.hippo.yorozuya.StringUtils import com.hippo.yorozuya.StringUtils
import com.hippo.yorozuya.ViewUtils import com.hippo.yorozuya.ViewUtils
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlinx.coroutines.delay
import rikka.core.res.resolveColor import rikka.core.res.resolveColor
import java.io.File import java.io.File
import java.time.LocalDateTime import java.time.LocalDateTime
@@ -216,6 +219,13 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
else -> throw IllegalStateException("Wrong KEY_ACTION:${args?.getString(KEY_ACTION)} when handle args!") else -> throw IllegalStateException("Wrong KEY_ACTION:${args?.getString(KEY_ACTION)} when handle args!")
} }
val goto = args?.getString(KEY_GOTO)
goto?.let {
lifecycleScope.launchUI {
delay(100)
mHelper?.goTo(it, true)
}
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -288,25 +298,6 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}) })
} }
private fun wrapTagKeyword(keyword: String?): String {
var keyword = keyword
keyword = keyword!!.trim { it <= ' ' }
val index1 = keyword.indexOf(':')
if (index1 == -1 || index1 >= keyword.length - 1) {
// Can't find :, or : is the last char
return keyword
}
if (keyword[index1 + 1] == '"') {
// The char after : is ", the word must be quoted
return keyword
}
val index2 = keyword.indexOf(' ')
return if (index2 <= index1) {
// Can't find space, or space is before :
keyword
} else keyword.substring(0, index1 + 1) + "\"" + keyword.substring(index1 + 1) + "$\""
}
// Update search bar title, drawer checked item // Update search bar title, drawer checked item
private fun onUpdateUrlBuilder() { private fun onUpdateUrlBuilder() {
_binding ?: return _binding ?: return
@@ -332,8 +323,8 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
// Update search edit text // Update search edit text
if (!mIsTopList) { if (!mIsTopList) {
if (mode == ListUrlBuilder.MODE_TAG) { if (mode == MODE_TAG) {
keyword = wrapTagKeyword(keyword) keyword = wrapTagKeyword(keyword!!)
} }
setSearchBarText(keyword) setSearchBarText(keyword)
} }
@@ -547,7 +538,8 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
qsDrawerAdapter.setHasStableIds(true) qsDrawerAdapter.setHasStableIds(true)
drawerBinding.recyclerViewDrawer.adapter = qsDrawerAdapter drawerBinding.recyclerViewDrawer.adapter = qsDrawerAdapter
if (!mIsTopList) { if (!mIsTopList) {
val itemTouchHelper = ItemTouchHelper(GalleryListQSItemTouchHelperCallback(qsDrawerAdapter)) val itemTouchHelper =
ItemTouchHelper(GalleryListQSItemTouchHelperCallback(qsDrawerAdapter))
itemTouchHelper.attachToRecyclerView(drawerBinding.recyclerViewDrawer) itemTouchHelper.attachToRecyclerView(drawerBinding.recyclerViewDrawer)
drawerBinding.tip.visibility = View.VISIBLE drawerBinding.tip.visibility = View.VISIBLE
drawerBinding.recyclerViewDrawer.visibility = View.GONE drawerBinding.recyclerViewDrawer.visibility = View.GONE
@@ -995,7 +987,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
val oldMode = mUrlBuilder.mode val oldMode = mUrlBuilder.mode
// If it's MODE_SUBSCRIPTION, keep it // If it's MODE_SUBSCRIPTION, keep it
val newMode = val newMode =
if (oldMode == MODE_SUBSCRIPTION) MODE_SUBSCRIPTION else ListUrlBuilder.MODE_NORMAL if (oldMode == MODE_SUBSCRIPTION) MODE_SUBSCRIPTION else MODE_NORMAL
mUrlBuilder.reset() mUrlBuilder.reset()
mUrlBuilder.mode = newMode mUrlBuilder.mode = newMode
mUrlBuilder.keyword = query mUrlBuilder.keyword = query
@@ -1155,8 +1147,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
val goto = if (i != -1) q.name!!.substring(i + 1) else null val goto = if (i != -1) q.name!!.substring(i + 1) else null
val args = ListUrlBuilder().apply { val args = ListUrlBuilder().apply {
set(q) set(q)
setIndex(goto) }.toStartArgs().apply { putString(KEY_GOTO, goto) }
}.toStartArgs()
navigate(R.id.galleryListScene, args, true) navigate(R.id.galleryListScene, args, true)
setState(STATE_NORMAL) setState(STATE_NORMAL)
closeDrawer(GravityCompat.END) closeDrawer(GravityCompat.END)
@@ -1431,6 +1422,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
companion object { companion object {
const val KEY_ACTION = "action" const val KEY_ACTION = "action"
const val KEY_GOTO = "goto"
const val ACTION_HOMEPAGE = "action_homepage" const val ACTION_HOMEPAGE = "action_homepage"
const val ACTION_SUBSCRIPTION = "action_subscription" const val ACTION_SUBSCRIPTION = "action_subscription"
const val ACTION_WHATS_HOT = "action_whats_hot" const val ACTION_WHATS_HOT = "action_whats_hot"
@@ -1444,38 +1436,6 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
private const val STATE_SEARCH = 2 private const val STATE_SEARCH = 2
private const val STATE_SEARCH_SHOW_LIST = 3 private const val STATE_SEARCH_SHOW_LIST = 3
private const val ANIMATE_TIME = 300L private const val ANIMATE_TIME = 300L
private fun getSuitableTitleForUrlBuilder(
resources: Resources, urlBuilder: ListUrlBuilder, appName: Boolean
): String? {
val keyword = urlBuilder.keyword
val category = urlBuilder.category
return if (ListUrlBuilder.MODE_NORMAL == urlBuilder.mode && EhUtils.NONE == category &&
TextUtils.isEmpty(keyword) && urlBuilder.advanceSearch == -1 && urlBuilder.minRating == -1 && urlBuilder.pageFrom == -1 && urlBuilder.pageTo == -1
) {
resources.getString(if (appName) R.string.app_name else R.string.homepage)
} else if (MODE_SUBSCRIPTION == urlBuilder.mode && EhUtils.NONE == category &&
TextUtils.isEmpty(keyword) && urlBuilder.advanceSearch == -1 && urlBuilder.minRating == -1 && urlBuilder.pageFrom == -1 && urlBuilder.pageTo == -1
) {
resources.getString(R.string.subscription)
} else if (MODE_WHATS_HOT == urlBuilder.mode) {
resources.getString(R.string.whats_hot)
} else if (MODE_TOPLIST == urlBuilder.mode) {
when (urlBuilder.keyword) {
"11" -> resources.getString(R.string.toplist_alltime)
"12" -> resources.getString(R.string.toplist_pastyear)
"13" -> resources.getString(R.string.toplist_pastmonth)
"15" -> resources.getString(R.string.toplist_yesterday)
else -> null
}
} else if (!TextUtils.isEmpty(keyword)) {
keyword
} else if (MathUtils.hammingWeight(category) == 1) {
EhUtils.getCategory(category)
} else {
null
}
}
fun ListUrlBuilder.toStartArgs(): Bundle { fun ListUrlBuilder.toStartArgs(): Bundle {
val args = Bundle() val args = Bundle()
args.putString(KEY_ACTION, ACTION_LIST_URL_BUILDER) args.putString(KEY_ACTION, ACTION_LIST_URL_BUILDER)
@@ -1483,4 +1443,40 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
return args return args
} }
} }
}
private fun getSuitableTitleForUrlBuilder(
resources: Resources, urlBuilder: ListUrlBuilder, appName: Boolean
): String? {
val keyword = urlBuilder.keyword
val category = urlBuilder.category
val mode = urlBuilder.mode
return if (mode == MODE_WHATS_HOT) {
resources.getString(R.string.whats_hot)
} else if (!keyword.isNullOrEmpty()) {
when (mode) {
MODE_TOPLIST -> {
when (keyword) {
"11" -> resources.getString(R.string.toplist_alltime)
"12" -> resources.getString(R.string.toplist_pastyear)
"13" -> resources.getString(R.string.toplist_pastmonth)
"15" -> resources.getString(R.string.toplist_yesterday)
else -> null
}
}
MODE_TAG -> wrapTagKeyword(keyword)
else -> keyword
}
} else if (category == EhUtils.NONE && urlBuilder.advanceSearch == -1) {
when (mode) {
MODE_NORMAL -> resources.getString(if (appName) R.string.app_name else R.string.homepage)
MODE_SUBSCRIPTION -> resources.getString(R.string.subscription)
else -> null
}
} else if (category.countOneBits() == 1) {
EhUtils.getCategory(category)
} else {
null
}
} }
@@ -127,6 +127,7 @@ abstract class SearchBarScene : BaseScene(), ToolBarScene {
fun setSearchBarText(text: String?) { fun setSearchBarText(text: String?) {
binding.toolbar.text = text binding.toolbar.text = text
binding.searchview.setText(text)
} }
fun setEditTextHint(hint: String?) { fun setEditTextHint(hint: String?) {
@@ -168,18 +169,6 @@ abstract class SearchBarScene : BaseScene(), ToolBarScene {
mAllowEmptySearch = allowEmptySearch mAllowEmptySearch = allowEmptySearch
} }
private fun wrapTagKeyword(keyword: String): String {
return if (keyword.endsWith(':')) {
keyword
} else if (keyword.contains(' ')) {
val tag = keyword.substringAfter(':')
val prefix = keyword.dropLast(tag.length)
"$prefix\"$tag$\" "
} else {
"$keyword$ "
}
}
interface SuggestionProvider { interface SuggestionProvider {
fun providerSuggestions(text: String): List<Suggestion>? fun providerSuggestions(text: String): List<Suggestion>?
@@ -268,7 +257,7 @@ abstract class SearchBarScene : BaseScene(), ToolBarScene {
edittext.let { edittext.let {
val keywords = it.text.toString().substringBeforeLast(' ', "") val keywords = it.text.toString().substringBeforeLast(' ', "")
val keyword = wrapTagKeyword(mKeyword) val keyword = wrapTagKeyword(mKeyword)
val newKeywords = if (keywords.isNotEmpty()) "$keywords $keyword" else keyword val newKeywords = if (keywords.isNotEmpty()) "$keywords $keyword " else "$keyword "
it.setText(newKeywords) it.setText(newKeywords)
it.setSelection(newKeywords.length) it.setSelection(newKeywords.length)
} }
@@ -370,3 +359,15 @@ abstract class SearchBarScene : BaseScene(), ToolBarScene {
} }
} }
} }
fun wrapTagKeyword(keyword: String): String {
return if (keyword.endsWith(':')) {
keyword
} else if (keyword.contains(' ')) {
val tag = keyword.substringAfter(':')
val prefix = keyword.dropLast(tag.length)
"$prefix\"$tag$\""
} else {
"$keyword$"
}
}
+1 -1
View File
@@ -56,8 +56,8 @@ class Image private constructor(private val src: CloseableSource) {
(mObtainedDrawable as? AnimatedImageDrawable)?.stop() (mObtainedDrawable as? AnimatedImageDrawable)?.stop()
(mObtainedDrawable as? BitmapDrawable)?.bitmap?.recycle() (mObtainedDrawable as? BitmapDrawable)?.bitmap?.recycle()
mObtainedDrawable?.callback = null mObtainedDrawable?.callback = null
mObtainedDrawable = null
(mObtainedDrawable as? AnimatedImageDrawable)?.let { src.close() } (mObtainedDrawable as? AnimatedImageDrawable)?.let { src.close() }
mObtainedDrawable = null
} }
companion object { companion object {