diff --git a/app/src/main/kotlin/cn/xihan/qdds/AdvManage.kt b/app/src/main/kotlin/cn/xihan/qdds/AdvManage.kt index 8b9f9f5..17a9c3f 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/AdvManage.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/AdvManage.kt @@ -1,9 +1,7 @@ package cn.xihan.qdds import android.view.View -import android.widget.ImageView import android.widget.LinearLayout -import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.type.android.ContextClass import com.highcapable.yukihookapi.hook.type.android.ViewClass @@ -11,8 +9,6 @@ import com.highcapable.yukihookapi.hook.type.java.BooleanType import com.highcapable.yukihookapi.hook.type.java.ListClass import com.highcapable.yukihookapi.hook.type.java.StringClass import com.highcapable.yukihookapi.hook.type.java.UnitType -import okhttp3.internal.connection.ConnectInterceptor -import okhttp3.internal.connection.ConnectInterceptor.intercept /** * @项目名 : QDReadHook @@ -23,30 +19,32 @@ import okhttp3.internal.connection.ConnectInterceptor.intercept /** * 广告相关配置 */ -fun PackageParam.advOption(versionCode: Int, optionValueSet: Set) { - optionValueSet.forEach { - when (it) { - 0 -> disableAd(versionCode) - 1 -> disableUpdate(versionCode) - 2 -> disableDailyReadAd(versionCode) - 3 -> disableBookshelfActivityPopup(versionCode) - 4 -> disableBookshelfFloatWindow(versionCode) - 5 -> disableBottomNavigationCenterAd(versionCode) - 6 -> disableAccountCenterAd(versionCode) - 7 -> disableReadPageFloatAd(versionCode) - 8 -> disableReadPageRewardTheater(versionCode) - 15 -> hideReadPageBottom(versionCode) - 17 -> disableReadPageNewestPageWindowBannerAd(versionCode) +fun PackageParam.advOption(versionCode: Int, configurations: List) { + if (configurations.isEmpty()) return + configurations.filter { it.selected }.takeIf { it.isNotEmpty() }?.forEach { selected -> + when (selected.title) { + "GDT(TX)广告" -> disableAd(versionCode) + "检查更新" -> disableUpdate(versionCode) + "主页-每日阅读广告" -> disableDailyReadAd(versionCode) + "主页-书架活动弹框" -> disableBookshelfActivityPopup(versionCode) + "主页-书架浮窗活动" -> disableBookshelfFloatWindow(versionCode) + "主页-书架底部导航栏广告" -> disableBottomNavigationCenterAd(versionCode) + "我-中间广告" -> disableAccountCenterAd(versionCode) + "阅读页-浮窗广告" -> disableReadPageFloatAd(versionCode) + "阅读页-打赏小剧场" -> disableReadPageRewardTheater(versionCode) + "阅读页-章末底部月票打赏红包" -> hideReadPageBottom(versionCode) + "阅读页-最后一页-弹框广告" -> disableReadPageNewestPageWindowBannerAd(versionCode) } } + disableReadPageChapterEnd( versionCode, - disableAll = HookEntry.isEnableAdvOption(9), - disableBookRecommend = HookEntry.isEnableAdvOption(10), - disableBookComment = HookEntry.isEnableAdvOption(11), - disableChapterEndWelfare = HookEntry.isEnableAdvOption(12), - disableChapterEndRewardAd = HookEntry.isEnableAdvOption(13), - disableVoteTicketSpecialLine = HookEntry.isEnableAdvOption(14) + disableAll = configurations.isSelectedByTitle("阅读页-章末一刀切"), + disableBookRecommend = configurations.isSelectedByTitle("阅读页-章末新人推书"), + disableBookComment = configurations.isSelectedByTitle("阅读页-章末本章说"), + disableChapterEndWelfare = configurations.isSelectedByTitle("阅读页-章末福利"), + disableChapterEndRewardAd = configurations.isSelectedByTitle("阅读页-章末广告"), + disableVoteTicketSpecialLine = configurations.isSelectedByTitle("阅读页-章末求票") ) } @@ -88,9 +86,7 @@ fun PackageParam.disableBookshelfActivityPopup(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.clear() - result = list + result = result.safeCast>()?.also { it.clear() } } } } @@ -133,19 +129,13 @@ fun PackageParam.disableBookshelfFloatWindow(versionCode: Int) { param(View::class.java) } afterHook { - val imgAdIconClose = instance.getView( - "imgAdIconClose" - ) - imgAdIconClose?.visibility = View.GONE - val layoutImgAdIcon = instance.getView( - "layoutImgAdIcon" - ) - layoutImgAdIcon?.visibility = View.GONE - - val imgBookShelfActivityIcon = instance.getView( - "imgBookShelfActivityIcon" - ) - imgBookShelfActivityIcon?.visibility = View.GONE + instance.getViews( + *arrayOf( + "imgAdIconClose", + "layoutImgAdIcon", + "imgBookShelfActivityIcon" + ).toPairs() + ).hideViews() } } } @@ -173,10 +163,9 @@ fun PackageParam.disableBookshelfFloatWindow(versionCode: Int) { param(View::class.java) } afterHook { - val layoutImgAdIcon = instance.getView( + instance.getView( "layoutImgAdIcon" - ) - layoutImgAdIcon?.visibility = View.GONE + )?.setVisibilityIfNotEqual() } } @@ -217,10 +206,9 @@ fun PackageParam.disableBookshelfFloatWindow(versionCode: Int) { param(ViewClass) } afterHook { - val layoutImgAdIcon = instance.getView( + instance.getView( "layoutImgAdIcon" - ) - layoutImgAdIcon?.visibility = View.GONE + )?.setVisibilityIfNotEqual() } } @@ -613,29 +601,29 @@ fun PackageParam.disableUpdate(versionCode: Int) { /** * 也可全局搜索 "UpgradeCommon"、"checkUpdate:" */ - val methodMap = mapOf( - "needHookClass" to when (versionCode) { - in 758..788 -> "com.qidian.QDReader.util.z4" - in 792..796 -> "com.qidian.QDReader.util.i5" - in 800..834 -> "com.qidian.QDReader.util.l5" - in 842..878 -> "com.qidian.QDReader.util.m5" - 884 -> "com.qidian.QDReader.util.k5" - in 890..900 -> "com.qidian.QDReader.util.l5" - in 906..970 -> "com.qidian.QDReader.util.m5" - in 980..994 -> "com.qidian.QDReader.util.k5" - else -> null - }, - "needHookMethod" to when (versionCode) { - in 758..878 -> "b" - in 884..994 -> "judian" - else -> null - }, - "needHookMethod2" to when (versionCode) { - in 758..878 -> "a" - in 884..994 -> "search" - else -> null - } - ) + val methodMap = mapOf( + "needHookClass" to when (versionCode) { + in 758..788 -> "com.qidian.QDReader.util.z4" + in 792..796 -> "com.qidian.QDReader.util.i5" + in 800..834 -> "com.qidian.QDReader.util.l5" + in 842..878 -> "com.qidian.QDReader.util.m5" + 884 -> "com.qidian.QDReader.util.k5" + in 890..900 -> "com.qidian.QDReader.util.l5" + in 906..970 -> "com.qidian.QDReader.util.m5" + in 980..994 -> "com.qidian.QDReader.util.k5" + else -> null + }, + "needHookMethod" to when (versionCode) { + in 758..878 -> "b" + in 884..994 -> "judian" + else -> null + }, + "needHookMethod2" to when (versionCode) { + in 758..878 -> "a" + in 884..994 -> "search" + else -> null + } + ) methodMap["needHookClass"]?.hook { injectMember { diff --git a/app/src/main/kotlin/cn/xihan/qdds/Dialogs.kt b/app/src/main/kotlin/cn/xihan/qdds/Dialogs.kt index 4be8532..0c28306 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/Dialogs.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/Dialogs.kt @@ -119,7 +119,9 @@ inline fun AlertBuilder<*>.singleChoiceItems( checkItem: CharSequence, crossinline onItemSelected: (DialogInterface, Int) -> Unit ) = - singleChoiceItems(items.map { it.toString() }, items.indexOfFirst { it == checkItem }) { dialog, which -> + singleChoiceItems( + items.map { it.toString() }, + items.indexOfFirst { it == checkItem }) { dialog, which -> onItemSelected(dialog, which) } @@ -128,7 +130,9 @@ inline fun AlertBuilder<*>.singleChoiceItems( checkItem: T, crossinline onItemSelected: (DialogInterface, T, Int) -> Unit ) = - singleChoiceItems(items.map { it.toString() }, items.indexOfFirst { it == checkItem }) { dialog, which -> + singleChoiceItems( + items.map { it.toString() }, + items.indexOfFirst { it == checkItem }) { dialog, which -> onItemSelected(dialog, items[which], which) } @@ -219,7 +223,10 @@ interface AlertBuilder { onClicked: (dialog: DialogInterface) -> Unit, ) - fun items(items: List, onItemSelected: (dialog: DialogInterface, index: Int) -> Unit) + fun items( + items: List, + onItemSelected: (dialog: DialogInterface, index: Int) -> Unit + ) fun singleChoiceItems( items: List, @@ -335,7 +342,11 @@ abstract class AlertDialogBuilder : AlertBuilder { } } - override fun singleChoiceItems(items: List, checkedIndex: Int, onItemSelected: (DialogInterface, Int) -> Unit) { + override fun singleChoiceItems( + items: List, + checkedIndex: Int, + onItemSelected: (DialogInterface, Int) -> Unit + ) { builder.setSingleChoiceItems(items.toTypedArray(), checkedIndex) { dialog, which -> onItemSelected(dialog, which) } diff --git a/app/src/main/kotlin/cn/xihan/qdds/HookEntry.kt b/app/src/main/kotlin/cn/xihan/qdds/HookEntry.kt index f6ff371..05946b7 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/HookEntry.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/HookEntry.kt @@ -33,7 +33,6 @@ import com.highcapable.yukihookapi.hook.type.java.LongType import com.highcapable.yukihookapi.hook.type.java.StringClass import com.highcapable.yukihookapi.hook.type.java.UnitType import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit -import de.robv.android.xposed.XposedHelpers import org.json.JSONArray import org.json.JSONObject import java.util.concurrent.CopyOnWriteArrayList @@ -236,51 +235,6 @@ class HookEntry : IYukiHookXposedInit { */ -// findMethodAndPrint("kc.search") -// -// findMethodAndPrint("kc.cihai") - - -// findMethodAndPrint("com.qidian.QDReader.ui.widget.maintab.PagerSlidingTabStrip", true) - - /* - findClass("com.qidian.QDReader.ui.widget.maintab.PagerSlidingTabStrip").hook { - injectMember { - method { - name = "x" - paramCount(3) - returnType = UnitType - } - intercept() - } - } - - */ - - /* - findClass("com.qidian.QDReader.ui.activity.MainGroupActivity").hook { - injectMember { - method { - name = "checkOpenView" - param(IntentClass) - returnType = UnitType - } - intercept() - /* - beforeHook { - val intent = args[0] as? Intent ?: return@beforeHook - val i = intent.getIntExtra("MainScreen", -1) - if (i == 0 || i == -1) return@beforeHook - intent.extras?.putInt("MainScreen", 0) - args(0).set(intent) - } - - */ - } - } - - */ - } } @@ -352,17 +306,11 @@ class HookEntry : IYukiHookXposedInit { customReadBackgroundPath(versionCode) } - if (optionEntity.advOption.advOptionSelectedList.isNotEmpty()) { - advOption(versionCode, optionEntity.advOption.advOptionSelectedList) - } + advOption(versionCode, optionEntity.advOption.configurations) interceptOption(versionCode, optionEntity.interceptOption.configurations) - if ((optionEntity.viewHideOption.homeOption.configurations.any { it.selected })) { - homeOption( - versionCode, optionEntity.viewHideOption.homeOption.configurations - ) - } + homeOption(versionCode, optionEntity.viewHideOption.homeOption.configurations) if (optionEntity.viewHideOption.homeOption.enableCaptureBottomNavigation) { hideBottomNavigation(versionCode) @@ -414,34 +362,34 @@ class HookEntry : IYukiHookXposedInit { } if (optionEntity.viewHideOption.bookDetailOptions.enableHideBookDetail) { - bookDetailHide(versionCode) + bookDetailHide( + versionCode = versionCode, + isNeedHideCqzs = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("出圈指数"), + isNeedHideRybq = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("荣誉标签"), + isNeedHideQqGroups = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("QQ群"), + isNeedHideSyq = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("书友圈"), + isNeedHideSyb = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("书友榜"), + isNeedHideYpjz = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("月票金主"), + isNeedHideCenterAd = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("本书看点|中心广告"), + isNeedHideFloatAd = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("浮窗广告"), + isNeedHideBookRecommend = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("同类作品推荐"), + isNeedHideBookRecommend2 = optionEntity.viewHideOption.bookDetailOptions.configurations.isSelectedByTitle("看过此书的人还看过") + ) } if (optionEntity.viewHideOption.bookLastPageOptions.enableHideBookLastPage) { readBookLastPage( versionCode = versionCode, - shieldAlsoRead = isEnableShieldOption(16), - shieldSimilarRecommend = isEnableShieldOption(17), - shieldRecommendation = isEnableShieldOption(18), - hideCircle = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[0].title - ), - hideAlsoRead = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[1].title - ), - hideRecommendation = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[2].title - ), - hideSimilarRecommend = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[3].title - ), - hideBookList = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[4].title - ), - hideTryRead = optionEntity.viewHideOption.bookLastPageOptions.configurations.isEnabled( - optionEntity.viewHideOption.bookLastPageOptions.configurations[5].title - ), - hideAdView = isEnableAdvOption(16) + shieldAlsoRead = optionEntity.shieldOption.configurations.isSelectedByTitle("阅读-最后一页-看过此书的人还看过"), + shieldSimilarRecommend = optionEntity.shieldOption.configurations.isSelectedByTitle("阅读-最后一页-同类作品推荐"), + shieldRecommendation = optionEntity.shieldOption.configurations.isSelectedByTitle("阅读-最后一页-推荐"), + hideCircle = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("书友圈"), + hideAlsoRead = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("看过此书的人还看过"), + hideRecommendation = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("推荐"), + hideSimilarRecommend = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("同类作品推荐"), + hideBookList = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("收录此书的书单"), + hideTryRead = optionEntity.viewHideOption.bookLastPageOptions.configurations.isSelectedByTitle("试读"), + hideAdView = optionEntity.advOption.configurations.isSelectedByTitle("阅读页-最后一页-中间广告") ) } @@ -471,9 +419,7 @@ class HookEntry : IYukiHookXposedInit { isEnableCustomSplash = optionEntity.splashOption.enableCustomSplash ) - if (optionEntity.shieldOption.shieldOptionValueSet.isNotEmpty()) { - shieldOption(versionCode, optionEntity.shieldOption.shieldOptionValueSet) - } + shieldOption(versionCode, optionEntity.shieldOption.configurations) if (optionEntity.shieldOption.enableQuickShieldDialog) { quickShield(versionCode) @@ -488,10 +434,10 @@ class HookEntry : IYukiHookXposedInit { } afterHook { safeRun { - val readMoreSetting = - instance.getView("readMoreSetting") + val readMoreSetting = instance.getView("readMoreSetting") // 获取 readMoreSetting 子控件 - val readMoreSettingChild = readMoreSetting?.getChildAt(0) as? TextView + val readMoreSettingChild = + readMoreSetting?.getChildAt(0).safeCast() readMoreSettingChild?.text = "阅读设置/模块设置(长按)" readMoreSetting?.setOnLongClickListener { @@ -553,19 +499,6 @@ class HookEntry : IYukiHookXposedInit { optionEntity.shieldOption.bookTypeList } - /** - * 判断是否启用了屏蔽配置的选项 - * @param optionValue 选项的值 - */ - fun isEnableShieldOption(optionValue: Int) = - optionValue in optionEntity.shieldOption.shieldOptionValueSet - - /** - * 判断是否启用了广告配置的选项 - */ - fun isEnableAdvOption(optionValue: Int) = - optionValue in optionEntity.advOption.advOptionSelectedList - /** * 判断是否需要屏蔽 * @param bookName 书名-可空 @@ -573,68 +506,68 @@ class HookEntry : IYukiHookXposedInit { * @param bookType 书类型-可空 */ fun isNeedShield( - bookName: String? = null, - authorName: String? = null, - bookType: Set? = null, + bookName: String? = null, authorName: String? = null, bookType: Set? = null ): Boolean {/* if (BuildConfig.DEBUG) { - loggerE(msg = "bookName: $bookName\nauthorName:$authorName\nbookType:$bookType") + "bookName: $bookName\nauthorName:$authorName\nbookType:$bookType".loge() } */ - if (bookNameList.isNotEmpty()) { - if (!bookName.isNullOrBlank() && bookNameList.any { it in bookName }) { - return true - } - } - if (authorList.isNotEmpty()) { - if (!authorName.isNullOrBlank() && authorList.any { authorName == it }) { - return true + + bookNameList.takeIf { it.isNotEmpty() }?.let { bookNameList -> + bookName.takeUnless { it.isNullOrBlank() }?.let { bookName -> + if (bookNameList.any { it in bookName }) { + return true + } } } - if (bookTypeList.isNotEmpty() && !bookType.isNullOrEmpty()) { - if (optionEntity.shieldOption.enableBookTypeEnhancedBlocking) { - if (bookType.isNotEmpty() && bookType.any { bookTypeList.any { it1 -> it1 in it } }) { + + authorList.takeIf { it.isNotEmpty() }?.let { list -> + authorName.takeUnless { it.isNullOrBlank() }?.let { authorName -> + if (authorName in authorList) { return true } - } else { - if (bookType.isNotEmpty() && bookType.any { it in bookTypeList }) { - return true + } + } + + bookTypeList.takeIf { it.isNotEmpty() }?.let { list -> + bookType.takeUnless { it.isNullOrEmpty() }?.let { type -> + val bookTypes = type.filter { it.isNotBlank() || it.length > 1 }.toSet() + bookTypes.takeIf { it.isNotEmpty() }?.let { types -> + if (optionEntity.shieldOption.enableBookTypeEnhancedBlocking) { + if (types.any { list.any { it1 -> it1 in it } }) { + return true + } + } else { + if (types.any { it in list }) { + return true + } + } } } } + return false } - /** - * 解析关键词组 - * @param it 关键词组 - */ - fun parseKeyWordOption(it: String = ""): MutableSet = - it.split(";").filter { it.isNotBlank() }.map { it.replace(Regex(pattern = "\\s+"), "") } - .toMutableSet() - /** * 解析需要屏蔽的书籍列表 */ fun parseNeedShieldList(list: MutableList<*>): List<*> { val iterator = list.iterator() while (iterator.hasNext()) { - runCatching { - val item = iterator.next().toJSONString() - val jb = item.parseObject() - val bookName = jb.getString("BookName") ?: jb.getString("bookName") - ?: jb.getString("itemName") ?: jb.getString("ItemName") - val authorName = jb.getString("AuthorName") ?: jb.getString("authorName") - val categoryName = jb.getString("CategoryName") ?: jb.getString("categoryName") - val subCategoryName = - jb.getString("SubCategoryName") ?: jb.getString("subCategoryName") - ?: jb.getString("itemSubName") ?: jb.getString("ItemSubName") - val tagName = jb.getString("TagName") ?: jb.getString("tagName") - val array = - jb.getJSONArray("AuthorTags") ?: jb.getJSONArray("tags") ?: jb.getJSONArray( - "Tags" - ) ?: jb.getJSONArray("tagList") - val tip = jb.getString("Tip") ?: jb.getString("tip") + safeRun { + val jb = iterator.next().toJSONString().parseObject() + val bookName = + jb.getStringWithFallback("bookName") ?: jb.getStringWithFallback("itemName") + val authorName = jb.getStringWithFallback("authorName") + val categoryName = jb.getStringWithFallback("categoryName") + val subCategoryName = jb.getStringWithFallback("subCategoryName") + ?: jb.getStringWithFallback("itemSubName") + val tagName = jb.getStringWithFallback("tagName") + val array = jb.getJSONArrayWithFallback("AuthorTags") + ?: jb.getJSONArrayWithFallback("tags") + ?: jb.getJSONArrayWithFallback("tagList") + val tip = jb.getStringWithFallback("tip") val bookTypeArray = mutableSetOf() if (categoryName != null) { bookTypeArray += categoryName @@ -652,11 +585,7 @@ class HookEntry : IYukiHookXposedInit { for (i in array.indices) { val tag = array.getString(i) if ("{" in tag) { - val tags = tag.parseObject() - tags?.getString("tagName")?.let { - bookTypeArray += it - } - tags?.getString("TagName")?.let { + tag.parseObject()?.getStringWithFallback("tagName")?.let { bookTypeArray += it } } else { @@ -680,40 +609,41 @@ class HookEntry : IYukiHookXposedInit { fun parseNeedShieldComicList(list: MutableList<*>): List<*> { val iterator = list.iterator() while (iterator.hasNext()) { - val item = iterator.next().toJSONString() - val jb = item.parseObject() - val comicName = jb.getString("ComicName") ?: jb.getString("comicName") - val authorName = jb.getString("AuthorName") ?: jb.getString("authorName") - ?: jb.getString("Author") - val categoryName = jb.getString("CategoryName") ?: jb.getString("categoryName") - val subCategoryName = - jb.getString("SubCategoryName") ?: jb.getString("subCategoryName") - val tagName = jb.getString("TagName") ?: jb.getString("tagName") - val extraTag = jb.getString("ExtraTag") ?: jb.getString("extraTag") - val array = jb.getJSONArray("AuthorTags") ?: jb.getJSONArray("tags") - ?: jb.getJSONArray("Tags") ?: jb.getJSONArray("tagList") - val bookTypeArray = mutableSetOf() - if (categoryName != null) { - bookTypeArray += categoryName - } - if (subCategoryName != null) { - bookTypeArray += subCategoryName - } - if (tagName != null) { - bookTypeArray += tagName - } - if (extraTag != null) { - bookTypeArray += extraTag - } - if (!array.isNullOrEmpty()) { - for (i in array.indices) { - array.getString(i)?.let { - bookTypeArray += it + safeRun { + val jb = iterator.next().toJSONString().parseObject() + val comicName = jb.getStringWithFallback("comicName") + val authorName = + jb.getStringWithFallback("authorName") ?: jb.getStringWithFallback("Author") + val categoryName = jb.getStringWithFallback("categoryName") + val subCategoryName = jb.getStringWithFallback("subCategoryName") + val tagName = jb.getStringWithFallback("tagName") + val extraTag = jb.getStringWithFallback("extraTag") + val array = jb.getJSONArrayWithFallback("authorTags") + ?: jb.getJSONArrayWithFallback("tags") + ?: jb.getJSONArrayWithFallback("tagList") + val bookTypeArray = mutableSetOf() + if (categoryName != null) { + bookTypeArray += categoryName + } + if (subCategoryName != null) { + bookTypeArray += subCategoryName + } + if (tagName != null) { + bookTypeArray += tagName + } + if (extraTag != null) { + bookTypeArray += extraTag + } + if (!array.isNullOrEmpty()) { + for (i in array.indices) { + array.getString(i)?.let { + bookTypeArray += it + } } } - } - if (isNeedShield(comicName, authorName, bookTypeArray)) { - iterator.remove() + if (isNeedShield(comicName, authorName, bookTypeArray)) { + iterator.remove() + } } } return list @@ -739,7 +669,7 @@ class HookEntry : IYukiHookXposedInit { optionEntity.viewHideOption.selectedOption.selectedTitleConfigurations.filter { it.selected && it.title in type.values } - return needShieldTitleList.map { type.filterValues { it1 -> it1 == it.title }.keys.first() } + return needShieldTitleList.mapNotNull { type.filterValues { it1 -> it1 == it.title }.keys.firstOrNull() } } /** @@ -754,7 +684,6 @@ class HookEntry : IYukiHookXposedInit { bookName.isNotBlank() -> { optionEntity.shieldOption.bookNameList += bookName } - authorName.isNotBlank() -> { optionEntity.shieldOption.authorList += authorName } @@ -863,7 +792,7 @@ fun PackageParam.newAutoSignIn(versionCode: Int) { afterHook { result?.let { val c = it.getParam("c") - c?.visibility = View.GONE + c?.setVisibilityIfNotEqual() val e = it.getParam("e") e?.let { it1 -> val binding = it1.getParam("binding") @@ -930,8 +859,7 @@ fun PackageParam.newAutoSignIn(versionCode: Int) { val qDUIButtons = binding.getViews("com.qd.ui.component.widget.QDUIButton".toClass()) qDUIButtons.filter { button -> - button.getViews() - .any { textView -> textView.text == "签到" } + button.getViews().any { textView -> textView.text == "签到" } }.forEach { button -> (button as View).performClick() } @@ -979,31 +907,27 @@ fun PackageParam.newOldLayout( 970 -> "o4.search\$search" 980 -> "com.qidian.QDReader.component.abtest.ABTestConfigHelper\$search" else -> null - }, - "needHookNewUserAccountMethod" to when (versionCode) { + }, "needHookNewUserAccountMethod" to when (versionCode) { 868 -> "n" 872 -> "m" 878 -> "o" 884 -> "m" 890 -> "n" else -> null - }, - "needHookBookStoreV2Method" to when (versionCode) { + }, "needHookBookStoreV2Method" to when (versionCode) { 872 -> "d" 878 -> "e" 884 -> "b" in 890..900 -> "c" else -> null - }, - "needHookMethod" to when (versionCode) { + }, "needHookMethod" to when (versionCode) { in 827..850 -> "b" in 868..872 -> "c" 878 -> "d" 884 -> "a" in 890..900 -> "b" else -> null - }, - "needHookGDTGameMethod" to when (versionCode) { + }, "needHookGDTGameMethod" to when (versionCode) { in 896..900 -> "U" in 906..916 -> "W" 924 -> "Y" @@ -1222,15 +1146,14 @@ fun PackageParam.unlockMemberBackground(versionCode: Int) { returnType = UnitType } afterHook { - val list = args[0] as? MutableList<*> + val list = args[0].safeCast>() list?.forEach { it?.let { if (it.javaClass.name == "com.qidian.QDReader.repository.dal.store.ReaderThemeEntity") { val themeType = it.getParam("themeType") if (themeType == 102L) { it.setParams( - "themeType" to 101L, - "haveStatus" to 1 + "themeType" to 101L, "haveStatus" to 1 ) } } @@ -1259,7 +1182,7 @@ fun PackageParam.freeAdReward(versionCode: Int) { returnType = "java.lang.ClassLoader".toClass() } afterHook { - val classLoader = result as? ClassLoader + val classLoader = result.safeCast() classLoader?.let { /** * com.qq.e.comm.plugin.tangramrewardvideo.g.K() : void @@ -1502,8 +1425,7 @@ fun PackageParam.ignoreFreeSubscribeLimit(versionCode: Int) { 950 -> "com.qidian.QDReader.component.bll.manager.b1" in 958..994 -> "com.qidian.QDReader.component.bll.manager.d1" else -> null - }, - "needHookMethod" to when (versionCode) { + }, "needHookMethod" to when (versionCode) { in 854..878 -> "n0" in 884..890 -> "k0" in 896..924 -> "l0" @@ -1530,7 +1452,7 @@ fun PackageParam.ignoreFreeSubscribeLimit(versionCode: Int) { returnType = IntType } beforeHook { - val jb = args[1] as? JSONObject + val jb = args[1].safeCast() safeRun { jb?.optJSONObject("Data")?.put("IsFreeLimit", -1) args(1).set(jb) @@ -1587,9 +1509,7 @@ fun PackageParam.exportEmoji(versionCode: Int) { else -> null } if (topBarId != null) { - val topBar = XposedHelpers.callMethod( - context, "findViewById", topBarId - ) as? RelativeLayout + val topBar = context.findViewById(topBarId) if (topBar != null) { val layoutParams = RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, @@ -1788,8 +1708,7 @@ fun PackageParam.receiveReadingCreditsAutomatically(versionCode: Int) { afterHook { val bubbleViewMap = instance.getParam>("bubbleViewMap") bubbleViewMap?.values?.forEach { view -> - val readTimeBubbleView = view as? LinearLayout - readTimeBubbleView?.postRandomDelay { performClick() } + view.safeCast()?.postRandomDelay { performClick() } } } } @@ -1806,13 +1725,12 @@ fun PackageParam.receiveReadingCreditsAutomatically(versionCode: Int) { returnType = IntType } afterHook { - val list = args[1] as? List<*> - if (list.isNullOrEmpty()) { - return@afterHook - } + args[1].safeCast>() ?: return@afterHook + val pBarTagContainerId = when (versionCode) { 970 -> 0x7F091391 980 -> 0x7F0913D0 + 994 -> 0x7F0913F6 else -> null } if (pBarTagContainerId == null) { @@ -1823,7 +1741,7 @@ fun PackageParam.receiveReadingCreditsAutomatically(versionCode: Int) { name = "_\$_findCachedViewById" paramCount(1) returnType = ViewClass - }.get(instance).call(pBarTagContainerId) as? FrameLayout + }.get(instance).call(pBarTagContainerId).safeCast() view?.let { val count = it.childCount @@ -1849,7 +1767,7 @@ fun PackageParam.receiveReadingCreditsAutomatically(versionCode: Int) { returnType = UnitType } afterHook { - val button = args[0] as? LinearLayout ?: return@afterHook + val button = args[0].safeCast() ?: return@afterHook button.current { val text = method { name = "getText" @@ -1880,7 +1798,7 @@ fun PackageParam.receiveReadingCreditsAutomatically(versionCode: Int) { name = "getQdButtonBottom" emptyParam() returnType = "com.qd.ui.component.widget.QDUIButton".toClass() - }.get(instance).call() as? LinearLayout ?: return@afterHook + }.get(instance).call().safeCast() ?: return@afterHook button.current { val text = method { @@ -1937,10 +1855,8 @@ fun PackageParam.postToShowImageUrl(versionCode: Int) { val lists = instance.getParamList>().takeUnless { it.isEmpty() } ?.filterNot { it[0] is String } lists?.firstOrNull()?.let { urlList -> - urlList.mapNotNull { it?.getParam("mAccessUrl") } - .let { accessUrls -> - instance.getViews() - .firstNotNullOfOrNull { it.context } + urlList.mapNotNull { it?.getParam("mAccessUrl") }.let { accessUrls -> + instance.getViews().firstNotNullOfOrNull { it.context } ?.showUrlListDialog(accessUrls) } } diff --git a/app/src/main/kotlin/cn/xihan/qdds/MainActivity.kt b/app/src/main/kotlin/cn/xihan/qdds/MainActivity.kt index b2af4fc..2f71c10 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/MainActivity.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/MainActivity.kt @@ -212,7 +212,7 @@ class MainActivity : ModuleAppCompatActivity() { ) { Text( - "需要存储以及安装未知应用权限\n存储权限:用来管理位于外部存储的配置文件\n安装未知应用权限:Android 11及以上读取其他应用版本号需要此权限", + "需要存储以及安装未知应用权限\n存储权限:用来管理位于外部存储的配置文件\n安装未知应用权限:Android 11及以上读取其他应用版本号", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center, fontWeight = FontWeight.Bold @@ -1392,7 +1392,6 @@ fun PurifyScreen( TextSetting(title = "拦截设置列表", modifier = Modifier.padding(4.dp), onClick = { context.multiChoiceSelector(HookEntry.optionEntity.interceptOption.configurations) }) - } Card( @@ -2021,7 +2020,7 @@ fun AboutScreen( TextSetting(title = "重置模块配置文件", subTitle = "", onClick = { writeOptionFile(OptionEntity()) context.toast("重置成功,即将重启应用") - (context as? Activity)?.restartApplication() + context.safeCast()?.restartApplication() }) TextSetting(title = "打赏", subTitle = "", onClick = { diff --git a/app/src/main/kotlin/cn/xihan/qdds/Option.kt b/app/src/main/kotlin/cn/xihan/qdds/Option.kt index 660dbfb..d2ac017 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/Option.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/Option.kt @@ -3,7 +3,6 @@ package cn.xihan.qdds import android.os.Environment import androidx.annotation.Keep import androidx.compose.runtime.Immutable -import com.highcapable.yukihookapi.hook.log.loggerE import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString @@ -55,33 +54,31 @@ data class OptionEntity( ) { /** * 广告配置 - * @param advOptionList 广告配置列表 - * @param advOptionSelectedList 广告配置选中列表 + * @param configurations 广告配置列表 */ @Keep @Serializable data class AdvOption( - @SerialName("advOptionList") var advOptionList: List = listOf( - "GDT(TX)广告", - "检查更新", - "主页-每日阅读广告", - "主页-书架活动弹框", - "主页-书架浮窗活动", - "主页-书架底部导航栏广告", - "我-中间广告", - "阅读页-浮窗广告", - "阅读页-打赏小剧场", - "阅读页-章末一刀切", - "阅读页-章末新人推书", - "阅读页-章末本章说", - "阅读页-章末福利", - "阅读页-章末广告", - "阅读页-章末求票", - "阅读页-章末底部月票打赏红包", - "阅读页-最后一页-中间广告", - "阅读页-最后一页-弹框广告", - ), - @SerialName("advOptionSelectedList") var advOptionSelectedList: MutableSet = mutableSetOf(), + @SerialName("configurations") var configurations: MutableList = mutableListOf( + SelectedModel("GDT(TX)广告"), + SelectedModel("检查更新"), + SelectedModel("主页-每日阅读广告"), + SelectedModel("主页-书架活动弹框"), + SelectedModel("主页-书架浮窗活动"), + SelectedModel("主页-书架底部导航栏广告"), + SelectedModel("我-中间广告"), + SelectedModel("阅读页-浮窗广告"), + SelectedModel("阅读页-打赏小剧场"), + SelectedModel("阅读页-章末一刀切"), + SelectedModel("阅读页-章末新人推书"), + SelectedModel("阅读页-章末本章说"), + SelectedModel("阅读页-章末福利"), + SelectedModel("阅读页-章末广告"), + SelectedModel("阅读页-章末求票"), + SelectedModel("阅读页-章末底部月票打赏红包"), + SelectedModel("阅读页-最后一页-中间广告"), + SelectedModel("阅读页-最后一页-弹框广告") + ) ) /** @@ -126,7 +123,7 @@ data class OptionEntity( /** * 屏蔽配置 * @param enableQuickShieldDialog 启用快速屏蔽弹窗 - * @param shieldOptionValueSet 屏蔽配置值集合 + * @param configurations 屏蔽配置值集合 * @param authorList 屏蔽作者集合 * @param bookTypeList 屏蔽书类集合 * @param bookNameList 屏蔽书名集合 @@ -139,7 +136,28 @@ data class OptionEntity( @SerialName("authorList") var authorList: MutableSet = mutableSetOf(), @SerialName("bookNameList") var bookNameList: MutableSet = mutableSetOf(), @SerialName("bookTypeList") var bookTypeList: Set = emptySet(), - @SerialName("shieldOptionValueSet") var shieldOptionValueSet: MutableSet = mutableSetOf(), + @SerialName("configurations") var configurations: MutableList = mutableListOf( + SelectedModel("搜索-发现(热词)"), + SelectedModel("搜索-热门作品榜"), + SelectedModel("搜索-人气标签榜"), + SelectedModel("搜索-为你推荐"), + SelectedModel("精选-主页面"), + SelectedModel("精选-分类"), + SelectedModel("精选-分类-全部作品"), + SelectedModel("精选-免费-免费推荐"), + SelectedModel("精选-免费-新书入库"), + SelectedModel("精选-畅销精选、主编力荐等更多"), + SelectedModel("精选-新书强推、三江推荐"), + SelectedModel("精选-排行榜"), + SelectedModel("精选-新书"), + SelectedModel("每日导读"), + SelectedModel("精选-漫画"), + SelectedModel("精选-漫画-其他"), + SelectedModel("阅读-最后一页-看过此书的人还看过"), + SelectedModel("阅读-最后一页-同类作品推荐"), + SelectedModel("阅读-最后一页-推荐"), + SelectedModel("分类-小编力荐、本周强推等更多") + ), @SerialName("enableBookTypeEnhancedBlocking") var enableBookTypeEnhancedBlocking: Boolean = false, ) @@ -279,7 +297,7 @@ data class OptionEntity( @Keep @Serializable data class InterceptOption( - @SerialName("configurations") var configurations: List = listOf( + @SerialName("configurations") var configurations: MutableList = mutableListOf( SelectedModel("隐私政策更新弹框"), SelectedModel("同意隐私政策弹框"), SelectedModel("WebSocket"), @@ -299,9 +317,13 @@ data class OptionEntity( SelectedModel("异步子崩溃任务|com.qidian.QDReader.start.AsyncChildCrashTask"), SelectedModel("异步子点播上传任务|com.qidian.QDReader.start.AsyncChildVODUploadTask"), SelectedModel("异步子青少年和网络回调任务|com.qidian.QDReader.start.AsyncChildTeenagerAndNetCallbackTask"), + SelectedModel("异步主下载Sdk任务|com.qidian.QDReader.start.AsyncMainDownloadSdkTask"), + SelectedModel("异步子自动跟踪器初始化任务|com.qidian.QDReader.start.AsyncChildAutoTrackerInitTask"), + SelectedModel("异步子表情符号任务|com.qidian.QDReader.start.AsyncChildEmojiTask"), SelectedModel("同步推送任务|com.qidian.QDReader.start.SyncPushTask"), SelectedModel("同步Bugly-APM任务|com.qidian.QDReader.start.SyncBuglyApmTask"), - SelectedModel("同步挂钩通道任务|com.qidian.QDReader.start.SyncHookChannelTask") + SelectedModel("同步挂钩通道任务|com.qidian.QDReader.start.SyncHookChannelTask"), + SelectedModel("同步正确任务|com.qidian.QDReader.start.SyncRightlyTask") ) ) @@ -336,18 +358,20 @@ data class OptionEntity( * 主页配置 * @param enableCaptureBottomNavigation 启用截取底部导航栏 * @param configurations 主页配置列表 + * @param bottomNavigationConfigurations 底部导航栏配置 */ @Keep @Serializable data class HomeOption( @SerialName("enableCaptureBottomNavigation") var enableCaptureBottomNavigation: Boolean = false, - @SerialName("homeConfigurations") var configurations: MutableList = mutableListOf( + @SerialName("configurations") var configurations: MutableList = mutableListOf( SelectedModel("主页顶部宝箱提示"), SelectedModel("主页顶部战力提示"), SelectedModel("书架每日导读"), SelectedModel("书架去找书"), SelectedModel("主页底部导航栏红点") ), + @SerialName("bottomNavigationConfigurations") var bottomNavigationConfigurations: MutableList = mutableListOf() ) /** @@ -419,7 +443,7 @@ data class OptionEntity( @Immutable data class BookDetailOptions( @SerialName("enableHideBookDetail") var enableHideBookDetail: Boolean = false, - @SerialName("configurations") var configurations: List = listOf( + @SerialName("configurations") var configurations: MutableList = mutableListOf( SelectedModel(title = "出圈指数"), SelectedModel(title = "荣誉标签"), SelectedModel(title = "QQ群"), @@ -547,9 +571,8 @@ data class OptionEntity( @Serializable data class HideWelfareOption( @SerialName("enableHideWelfare") var enableHideWelfare: Boolean = false, - @SerialName("configurations") var configurations: List = listOf( - SelectedModel("内部浏览器右上角菜单", true), - SelectedModel("我的", false) + @SerialName("configurations") var configurations: MutableList = mutableListOf( + SelectedModel("内部浏览器右上角菜单", true), SelectedModel("我的", false) ), @SerialName("remoteCHideWelfareList") var remoteCHideWelfareList: MutableSet = mutableSetOf( "https://raw.githubusercontent.com/xihan123/AGE-API/master/details/HideWelfareList.json" @@ -579,7 +602,7 @@ data class OptionEntity( *读取配置文件模型 */ fun readOptionEntity(): OptionEntity { - val file = readOptionFile() ?: return defaultOptionEntity() + val file = readOptionFile() ?: return defaultOptionEntity return try { if (file.readText().isNotEmpty()) { try { @@ -589,65 +612,47 @@ fun readOptionEntity(): OptionEntity { } kJson.decodeFromString(file.readText()).apply { val newOptionEntity = OptionEntity() - val advOptionConfigurations = advOption.advOptionList.toMutableList() - val newAdvOptionConfigurations = newOptionEntity.advOption.advOptionList - if (advOptionConfigurations.size != newAdvOptionConfigurations.size) { - advOption.advOptionList = - advOptionConfigurations.updateStringListOptionEntity( - newAdvOptionConfigurations - ) - } - val interceptConfigurations = interceptOption.configurations.toMutableList() - val newConfiguration = newOptionEntity.interceptOption.configurations - - if (newConfiguration.isNotEmpty() && interceptConfigurations.isNotEmpty()) { - interceptOption.configurations = interceptConfigurations.deleteSelectedOption(newConfiguration) - } - if (interceptConfigurations.size != newConfiguration.size) { - interceptOption.configurations = - interceptConfigurations.updateSelectedListOptionEntity(newConfiguration) - } - val viewHideOptionConfigurations = - viewHideOption.homeOption.configurations + val newAdvOptionConfigurations = newOptionEntity.advOption.configurations + val newInterceptConfigurations = newOptionEntity.interceptOption.configurations val newViewHideOptionConfigurations = newOptionEntity.viewHideOption.homeOption.configurations - if (viewHideOptionConfigurations.size != newViewHideOptionConfigurations.size) { - viewHideOption.homeOption.configurations = - viewHideOptionConfigurations.updateSelectedListOptionEntity( - newViewHideOptionConfigurations - ) - } - val bookDetailOptionConfigurations = - viewHideOption.bookDetailOptions.configurations.toMutableList() val newBookDetailOptionConfigurations = newOptionEntity.viewHideOption.bookDetailOptions.configurations - if (bookDetailOptionConfigurations.size != newBookDetailOptionConfigurations.size) { - viewHideOption.bookDetailOptions.configurations = - bookDetailOptionConfigurations.updateSelectedListOptionEntity( - newBookDetailOptionConfigurations - ) - } - val hideWelfareOptionConfigurations = - hideBenefitsOption.configurations.toMutableList() val newHideWelfareOptionConfigurations = newOptionEntity.hideBenefitsOption.configurations - if (hideWelfareOptionConfigurations.size != newHideWelfareOptionConfigurations.size) { - hideBenefitsOption.configurations = - hideWelfareOptionConfigurations.updateSelectedListOptionEntity( - newHideWelfareOptionConfigurations - ) - } + + advOption.configurations = + advOption.configurations.updateSelectedListOptionEntity( + newAdvOptionConfigurations + ) + interceptOption.configurations = + interceptOption.configurations.updateSelectedListOptionEntity( + newInterceptConfigurations + ) + + viewHideOption.homeOption.configurations = + viewHideOption.homeOption.configurations.updateSelectedListOptionEntity( + newViewHideOptionConfigurations + ) + viewHideOption.bookDetailOptions.configurations = + viewHideOption.bookDetailOptions.configurations.updateSelectedListOptionEntity( + newBookDetailOptionConfigurations + ) + hideBenefitsOption.configurations = + hideBenefitsOption.configurations.updateSelectedListOptionEntity( + newHideWelfareOptionConfigurations + ) } } catch (e: Exception) { - loggerE(msg = "readOptionFile: ${e.message}") - defaultOptionEntity() + "readOptionFile: ${e.message}".loge() + defaultOptionEntity } } else { - defaultOptionEntity() + defaultOptionEntity } } catch (e: Exception) { - loggerE(msg = "readOptionEntity: ${e.message}") - defaultOptionEntity() + "readOptionEntity: ${e.message}".loge() + defaultOptionEntity } } @@ -673,46 +678,42 @@ fun readOptionFile(): File? = try { } if (!downloadFile.exists()) { downloadFile.createNewFile() - downloadFile.writeText(Json.encodeToString(defaultOptionEntity())) + downloadFile.writeText(Json.encodeToString(defaultOptionEntity)) } downloadFile } catch (e: Throwable) { - loggerE(msg = "readOptionFile: ${e.message}") + "readOptionFile: ${e.message}".loge() null } /** * 写入配置文件 */ -fun writeOptionFile(optionEntity: OptionEntity): Boolean = - try { - readOptionFile()?.writeText(Json.encodeToString(optionEntity)) - true - } catch (e: Exception) { - loggerE(msg = "writeOptionFile: ${e.message}") - false - } +fun writeOptionFile(optionEntity: OptionEntity): Boolean = try { + readOptionFile()?.writeText(Json.encodeToString(optionEntity)) + true +} catch (e: Exception) { + "writeOptionFile: ${e.message}".loge() + false +} /** * 返回一个默认的配置模型 */ -fun defaultOptionEntity(): OptionEntity = OptionEntity( - mainOption = OptionEntity.MainOption( - packageName = "com.qidian.QDReader", - enableAutoSign = true, - enableLocalCard = true - ), - advOption = OptionEntity.AdvOption( - advOptionSelectedList = mutableSetOf(1, 2, 3, 4, 5, 6, 7), - ), - viewHideOption = OptionEntity.ViewHideOption( - enableDisableQSNModeDialog = true, - accountOption = OptionEntity.ViewHideOption.AccountOption( - enableHideAccount = true, - enableHideAccountRightTopRedDot = true +val defaultOptionEntity by lazy { + OptionEntity( + mainOption = OptionEntity.MainOption( + packageName = "com.qidian.QDReader", enableAutoSign = true, enableLocalCard = true + ), viewHideOption = OptionEntity.ViewHideOption( + enableDisableQSNModeDialog = true, + accountOption = OptionEntity.ViewHideOption.AccountOption( + enableHideAccount = true, enableHideAccountRightTopRedDot = true + ) ) ) -) +} + +val defaultSelectedList by lazy { mutableListOf() } /** * 更新配置 diff --git a/app/src/main/kotlin/cn/xihan/qdds/ReadPage.kt b/app/src/main/kotlin/cn/xihan/qdds/ReadPage.kt index 2c10cca..086573f 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/ReadPage.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/ReadPage.kt @@ -157,7 +157,7 @@ fun PackageParam.readerPageChapterReviewPictures( val textViews = instance.getViews(messageTextView) if (textViews.isNotEmpty()) { textViews.forEach { any -> - val textView = any as? TextView + val textView = any.safeCast() textView?.setOnLongClickListener { textView.context.alertDialog { title = "评论内容" @@ -220,7 +220,7 @@ fun PackageParam.readerPageChapterReviewPictures( val textViews = instance.getViews(messageTextView) if (textViews.isNotEmpty()) { textViews.forEach { any -> - val textView = any as? TextView + val textView = any.safeCast() textView?.setOnLongClickListener { textView.context.alertDialog { title = "评论内容" @@ -323,7 +323,7 @@ fun PackageParam.readTimeDouble( paramCount(2) } afterHook { - val list = result as? MutableList<*> + val list = result.safeCast>() if (list.isNullOrEmpty()) return@afterHook list.forEach { item -> item?.let { diff --git a/app/src/main/kotlin/cn/xihan/qdds/ReplaceRule.kt b/app/src/main/kotlin/cn/xihan/qdds/ReplaceRule.kt index 538e1d6..7f70f2a 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/ReplaceRule.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/ReplaceRule.kt @@ -24,11 +24,10 @@ fun PackageParam.enableReplace(versionCode: Int) { returnType = StringClass } afterHook { - val mResult = result as? String - mResult?.let { + result.safeCast()?.let { if (HookEntry.optionEntity.replaceRuleOption.replaceRuleList.isNotEmpty()) { result = - mResult.replaceByReplaceRuleList(HookEntry.optionEntity.replaceRuleOption.replaceRuleList) + it.replaceByReplaceRuleList(HookEntry.optionEntity.replaceRuleOption.replaceRuleList) } } //loggerE(msg = "restoreShufflingText: ${result as? String}") diff --git a/app/src/main/kotlin/cn/xihan/qdds/Shield.kt b/app/src/main/kotlin/cn/xihan/qdds/Shield.kt index c9c62b6..73c7154 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/Shield.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/Shield.kt @@ -2,6 +2,7 @@ package cn.xihan.qdds import android.app.Activity import android.content.Context +import android.widget.RelativeLayout import android.widget.TextView import cn.xihan.qdds.HookEntry.Companion.isNeedShield import cn.xihan.qdds.HookEntry.Companion.parseNeedShieldList @@ -91,9 +92,8 @@ fun PackageParam.shieldDailyReading( } afterHook { - val list = result as? ArrayList<*> - list?.let { - result = parseNeedShieldList(list) + result.safeCast>()?.let { + result = parseNeedShieldList(it) } } } @@ -153,8 +153,7 @@ fun PackageParam.shieldCategory(versionCode: Int) { ) } beforeHook { - val list = args[3] as? MutableList<*> - list?.let { + args[3].safeCast>()?.let { safeRun { args(3).set(parseNeedShieldList(it)) } @@ -176,8 +175,7 @@ fun PackageParam.shieldCategory(versionCode: Int) { ) } beforeHook { - val list = args[3] as? MutableList<*> - list?.let { + args[3].safeCast>()?.let { safeRun { args(3).set(parseNeedShieldList(it)) } @@ -197,8 +195,7 @@ fun PackageParam.shieldCategory(versionCode: Int) { returnType = UnitType } beforeHook { - val b = args[1] as? MutableList<*> - b?.let { + args[1].safeCast>()?.let { safeRun { args(1).set(parseNeedShieldList(it)) } @@ -269,10 +266,9 @@ fun PackageParam.shieldCategory(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.let { + result.safeCast>()?.let { safeRun { - result = parseNeedShieldList(list) + result = parseNeedShieldList(it) } } } @@ -453,8 +449,7 @@ fun PackageParam.shieldNewBook(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.let { + result.safeCast>()?.let { parseNeedShieldList(it) } } @@ -564,8 +559,7 @@ fun PackageParam.shieldNewBook(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.let { + result.safeCast>()?.let { parseNeedShieldList(it) } } @@ -692,13 +686,11 @@ fun PackageParam.shieldNewBookAndRecommend(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.let { + result.safeCast>()?.let { safeRun { val iterator = it.iterator() while (iterator.hasNext()) { - val item = iterator.next().toJSONString() - val json = item.parseObject() + val json = iterator.next().toJSONString().parseObject() val jb = json.getJSONObject("BookStoreItem") if (jb != null) { val authorName = jb.getString("AuthorName") @@ -738,8 +730,7 @@ fun PackageParam.shieldNewBookAndRecommend(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.let { + result.safeCast>()?.let { safeRun { val iterator = it.iterator() while (iterator.hasNext()) { @@ -808,8 +799,7 @@ fun PackageParam.shieldNewBookAndRecommend(versionCode: Int) { returnType = UnitType } beforeHook { - val list = args[0] as? MutableList<*> - list?.let { + args[0].safeCast>()?.let { safeRun { val iterator = it.iterator() while (iterator.hasNext()) { @@ -927,8 +917,7 @@ fun PackageParam.shieldCategoryAllBook(versionCode: Int) { returnType = UnitType } beforeHook { - val b = args[1] as? MutableList<*> - b?.let { + args[1].safeCast>()?.let { safeRun { args(1).set(parseNeedShieldList(it)) } @@ -947,8 +936,7 @@ fun PackageParam.shieldCategoryAllBook(versionCode: Int) { returnType = UnitType } beforeHook { - val b = args[1] as? MutableList<*> - b?.let { + args[1].safeCast>()?.let { safeRun { args(1).set(parseNeedShieldList(it)) } @@ -980,9 +968,8 @@ fun PackageParam.shieldCategoryBookListReborn(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? ArrayList<*> - list?.let { - result = parseNeedShieldList(list) + result.safeCast>()?.let { + result = parseNeedShieldList(it) } } } @@ -1007,9 +994,7 @@ fun PackageParam.shieldSearchFind(versionCode: Int) { returnType = ListClass } afterHook { - val list = result as? MutableList<*> - list?.clear() - result = list + result = result.safeCast>()?.clear() } } } @@ -1068,8 +1053,7 @@ fun PackageParam.shieldSearch( name = needHookMethod } beforeHook { - val list = args[0] as? MutableList<*> - list?.let { + args[0].safeCast>()?.let { safeRun { args(0).set(parseNeedShieldList(it)) } @@ -1148,8 +1132,7 @@ fun PackageParam.shieldSearchRecommend(versionCode: Int) { param(ListClass) } beforeHook { - val list = args[0] as? MutableList<*> - list?.clear() + args[0].safeCast>()?.clear() } } } @@ -1173,9 +1156,8 @@ fun PackageParam.shieldComic(versionCode: Int) { returnType = ArrayListClass } afterHook { - val list = result as? ArrayList<*> - list?.let { - result = HookEntry.parseNeedShieldComicList(list) + result.safeCast>()?.let { + result = HookEntry.parseNeedShieldComicList(it) } } } @@ -1280,16 +1262,8 @@ fun PackageParam.quickShield(versionCode: Int) { returnType = UnitType } afterHook { - val tvBookName = XposedHelpers.callMethod( - instance, - "findViewById", - tvBookNameId - ) as? TextView - val tvAuthorName = XposedHelpers.callMethod( - instance, - "findViewById", - tvAuthorNameId - ) as? TextView + val tvBookName = instance.findViewById(tvBookNameId) + val tvAuthorName = instance.findViewById(tvAuthorNameId) // "tvBookName: ${tvBookName?.text}\ntvAuthorName: ${tvAuthorName?.text}".loge() tvBookName?.setOnLongClickListener { instance().apply { diff --git a/app/src/main/kotlin/cn/xihan/qdds/Splash.kt b/app/src/main/kotlin/cn/xihan/qdds/Splash.kt index 3d25d1c..0e7c995 100644 --- a/app/src/main/kotlin/cn/xihan/qdds/Splash.kt +++ b/app/src/main/kotlin/cn/xihan/qdds/Splash.kt @@ -1,10 +1,6 @@ package cn.xihan.qdds import android.view.View -import android.widget.Button -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.RelativeLayout import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.type.android.BundleClass @@ -112,15 +108,11 @@ fun PackageParam.enableCustomSplash( returnType = UnitType } afterHook { - val btnSkip = instance.getView