Skip to content

Commit

Permalink
feat: 970 版本阅读页章评以及楼中楼图片、评论复制
Browse files Browse the repository at this point in the history
Signed-off-by: xihan123 <srxqzxs@vip.qq.com>
  • Loading branch information
xihan123 committed Aug 12, 2023
1 parent 50f8ccb commit 5099804
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ jobs:
message: |
*${{ github.repository }}* new release *${{ steps.outputs.tag_name }}* is available
${{ steps.get_latest_release.outputs.description}}
format: markdown
# format: markdown
document: app/build/outputs/apk/release/*.apk
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ jobs:
token: ${{ secrets.RELEASE_TOKEN }}
release-type: node
package-name: release-please-action
release-as: 2.2.3
release-as: 2.2.4
signoff: "xihan123<srxqzxs@vip.qq.com>"
changelog-types: '[{"type":"types","section":"Types","hidden":false},{"type":"revert","section":"Reverts","hidden":false},{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"improvement","section":"Feature Improvements","hidden":false},{"type":"docs","section":"Docs","hidden":false},{"type":"ci","section":"CI","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]'
155 changes: 132 additions & 23 deletions app/src/main/kotlin/cn/xihan/qdds/ReadPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ fun PackageParam.readerPageChapterReviewPictures(
}

if (enableShowReaderPageChapterSavePictureDialog || enableCopyReaderPageChapterComment) {

val needHookClass = when (versionCode) {
in 868..878 -> "com.qidian.QDReader.ui.viewholder.chaptercomment.list.b0"
884 -> "com.qidian.QDReader.ui.viewholder.chaptercomment.list.y"
Expand All @@ -93,14 +94,22 @@ fun PackageParam.readerPageChapterReviewPictures(
in 958..970 -> "com.qidian.QDReader.ui.viewholder.chaptercomment.list.e0"
else -> null
}
val needHookClass2 = when (versionCode) {
970 -> "com.qidian.QDReader.ui.viewholder.chaptercomment.list.m0"
else -> null
}
val needHookMethod = when (versionCode) {
in 868..878 -> "A"
884 -> "x"
in 890..970 -> "z"
else -> null
}
val needHookMethod2 = when (versionCode) {
970 -> "z"
else -> null
}
if (needHookClass == null || needHookMethod == null) {
"阅读页-章评图片".printlnNotSupportVersion(versionCode)
"阅读页-章评相关复制".printlnNotSupportVersion(versionCode)
} else {
needHookClass.hook {
injectMember {
Expand All @@ -113,37 +122,138 @@ fun PackageParam.readerPageChapterReviewPictures(
if (enableShowReaderPageChapterSavePictureDialog) {
val rawImgUrl =
args[0]?.toJSONString().parseObject().getString("imageDetail")
val p = instance.getParam<ImageView>("p")
if (rawImgUrl == null || p == null) return@afterHook
p.setOnLongClickListener {
p.context.alertDialog {
title = "图片地址"
message = rawImgUrl
positiveButton("复制") {
p.context.copyToClipboard(rawImgUrl)
}
negativeButton("取消") {
it.dismiss()
val imageViews = instance.getViews<ImageView>()
val contexts = instance.getParams<Context>()
if (rawImgUrl == null || imageViews.isEmpty() || contexts.isEmpty()) return@afterHook
imageViews.forEach { s, imageView ->
imageView.setOnLongClickListener {
imageView.context.alertDialog {
title = "图片地址"
message = rawImgUrl
positiveButton("复制") {
imageView.context.copyToClipboard(rawImgUrl)
}
negativeButton("取消") {
it.dismiss()
}
build()
show()
}
build()
show()
true
}
true
}
}

if (enableCopyReaderPageChapterComment) {
val r = instance.getView<TextView>("r") ?: return@afterHook
val v = instance.getParam<Context>("v") ?: return@afterHook
r.setOnLongClickListener {
v.apply {
copyToClipboard(r.text.toString())
toast("已复制到剪贴板")
val messageTextView =
"com.qd.ui.component.widget.textview.MessageTextView".toClass()
val textViews = instance.getViews(messageTextView)
if (textViews.isNotEmpty()) {
textViews.forEach { (s, any) ->
val textView = any as? TextView
textView?.setOnLongClickListener {
textView.context.alertDialog {
title = "评论内容"
message = textView.text.toString()
positiveButton("复制") {
textView.context.copyToClipboard(textView.text.toString())
}
negativeButton("取消") {
it.dismiss()
}
build()
show()
}
true
}

}
}

val textViews2 = instance.getViews<TextView>()

if (textViews2.isNotEmpty()) {
textViews2.forEach { (s, textView) ->
"text: ${textView.text}".loge()
}

}

}

}
}
}

needHookClass2?.hook {
injectMember {
method {
name = needHookMethod2!!
paramCount(2)
returnType = UnitType
}
afterHook {
if (enableShowReaderPageChapterSavePictureDialog) {
val rawImgUrl =
args[0]?.toJSONString().parseObject().getString("imageDetail")
val imageViews = instance.getViews<ImageView>()
val contexts = instance.getParams<Context>()
if (rawImgUrl == null || imageViews.isEmpty() || contexts.isEmpty()) return@afterHook
imageViews.forEach { s, imageView ->
imageView.setOnLongClickListener {
imageView.context.alertDialog {
title = "图片地址"
message = rawImgUrl
positiveButton("复制") {
imageView.context.copyToClipboard(rawImgUrl)
}
negativeButton("取消") {
it.dismiss()
}
build()
show()
}
true
}
false
}
}

if (enableCopyReaderPageChapterComment) {
val messageTextView =
"com.qd.ui.component.widget.textview.MessageTextView".toClass()
val textViews = instance.getViews(messageTextView)
if (textViews.isNotEmpty()) {
textViews.forEach { (s, any) ->
val textView = any as? TextView
textView?.setOnLongClickListener {
textView.context.alertDialog {
title = "评论内容"
message = textView.text.toString()
positiveButton("复制") {
textView.context.copyToClipboard(textView.text.toString())
}
negativeButton("取消") {
it.dismiss()
}
build()
show()
}
true
}

}
}

val textViews2 = instance.getViews<TextView>()

if (textViews2.isNotEmpty()) {
textViews2.forEach { (s, textView) ->
"text: ${textView.text}".loge()
}

}

}
}
}
}
Expand All @@ -152,7 +262,6 @@ fun PackageParam.readerPageChapterReviewPictures(
* com.qidian.QDReader.ui.adapter.reader.ChapterParagraphCommentAdapter.onBindContentItemViewHolder
* b00.A(newParagraphCommentListBean$DataListBean0, this.getMBookInfo());
*/

}

if (enableShowReaderPageChapterSaveAudioDialog && versionCode in 884..970) {
Expand Down
45 changes: 42 additions & 3 deletions app/src/main/kotlin/cn/xihan/qdds/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ import kotlin.system.exitProcess
@Throws(NoSuchFieldException::class, IllegalAccessException::class)
inline fun <reified T : View> Any.getView(name: String): T? = getParam<T>(name)

/**
* 反射所有类型为T的控件 并附带字段名 返回Map
*/
@Throws(NoSuchFieldException::class, IllegalAccessException::class)
inline fun <reified T : View> Any.getViews(): Map<String, T> = getParams<T>()

/**
* 反射所有类型为指定 Class<*>名的控件并附带字段名 返回Map
* @param type 类型
*/
@Throws(NoSuchFieldException::class, IllegalAccessException::class)
fun Any.getViews(type: Class<*>): Map<String, Any> {
val map = mutableMapOf<String, Any>()
val fields = javaClass.declaredFields
for (field in fields) {
if (field.type == type) {
field.isAccessible = true
map[field.name] = field[this] as Any
}
}
return map
}

/**
* 反射获取父类控件
*/
Expand All @@ -73,6 +96,22 @@ inline fun <reified T> Any.getParam(name: String): T? = javaClass.getDeclaredFie
isAccessible = true
}[this] as? T

/**
* 反射获取任何T类型 并附带字段名 返回Map
*/
@Throws(NoSuchFieldException::class, IllegalAccessException::class)
inline fun <reified T> Any.getParams(): Map<String, T> {
val map = mutableMapOf<String, T>()
val fields = javaClass.declaredFields
for (field in fields) {
if (field.type == T::class.java) {
field.isAccessible = true
map[field.name] = field[this] as T
}
}
return map
}

/**
* 反射获取父类任何类型
*/
Expand Down Expand Up @@ -761,7 +800,6 @@ fun PackageParam.findMethodAndPrint(
}
}


fun Array<Any?>.printArgs(): String {
val stringBuilder = StringBuilder()
this.forEachIndexed { index, any ->
Expand Down Expand Up @@ -790,13 +828,14 @@ fun Any?.mToString(): String = when (this) {
/**
* 重定向启动图路径
*/
val splashPath = "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/QDReader/Splash/"
val splashPath =
"${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/QDReader/Splash/"

/**
* 随机返回一个 bitmap
*/
fun randomBitmap(): Bitmap? {
val files = File(splashPath)
val files = File(splashPath)
if (!files.exists()) {
files.mkdirs()
}
Expand Down

0 comments on commit 5099804

Please sign in to comment.