commit
b6485fab8b
@ -0,0 +1,32 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project version="4"> |
||||
<component name="WizardSettings"> |
||||
<option name="children"> |
||||
<map> |
||||
<entry key="vectorWizard"> |
||||
<value> |
||||
<PersistentState> |
||||
<option name="children"> |
||||
<map> |
||||
<entry key="vectorAssetStep"> |
||||
<value> |
||||
<PersistentState> |
||||
<option name="values"> |
||||
<map> |
||||
<entry key="assetSourceType" value="FILE" /> |
||||
<entry key="outputName" value="ic_cloud_download" /> |
||||
<entry key="sourceFile" value="F:\SVG图标\cloud.svg" /> |
||||
</map> |
||||
</option> |
||||
</PersistentState> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</PersistentState> |
||||
</value> |
||||
</entry> |
||||
</map> |
||||
</option> |
||||
</component> |
||||
</project> |
@ -1,9 +1,5 @@ |
||||
* 1、修复阅读界面概率性闪退的问题 |
||||
* 2、关于界面新增插件加载结果 |
||||
* 3、修复书源订阅失败的问题 |
||||
* 4、修复字体下载失败的问题 |
||||
* 5、\[设置-缓存设置\]新增清除广告文件 |
||||
* 6、修复检查更新失败的问题 |
||||
* 7、修复获取更新链接失败的问题 |
||||
* 8、更新订阅书源链接 |
||||
* 9、修复其他已知bug |
||||
* 1、[书籍详情界面]取消书籍简介展开时最大行数限制 |
||||
* 2、修复从数据库中读取章节时部分数据项缺失的bug |
||||
* 3、目录列表添加更新时间显示 |
||||
* 4、更新部分书源接口 |
||||
* 5、修复插件加载bug |
@ -0,0 +1,496 @@ |
||||
/* |
||||
* This file is part of FYReader. |
||||
* FYReader is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* FYReader is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
* |
||||
* Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
*/ |
||||
|
||||
package xyz.fycz.myreader.model.third3.analyzeRule |
||||
|
||||
import android.util.Base64 |
||||
import cn.hutool.crypto.digest.DigestUtil |
||||
import cn.hutool.crypto.digest.HMac |
||||
import cn.hutool.crypto.symmetric.SymmetricCrypto |
||||
import xyz.fycz.myreader.util.utils.MD5Utils |
||||
|
||||
/** |
||||
* js加解密扩展类, 在js中通过java变量调用 |
||||
* 添加方法,请更新文档/legado/app/src/main/assets/help/JsHelp.md |
||||
*/ |
||||
interface JsEncodeUtils { |
||||
|
||||
fun md5Encode(str: String): String { |
||||
return MD5Utils.md5Encode(str) |
||||
} |
||||
|
||||
fun md5Encode16(str: String): String { |
||||
return MD5Utils.md5Encode16(str) |
||||
} |
||||
|
||||
|
||||
//******************对称加密解密************************// |
||||
|
||||
/** |
||||
* 在js中这样使用 |
||||
* java.createSymmetricCrypto(transformation, key, iv).decrypt(data) |
||||
* java.createSymmetricCrypto(transformation, key, iv).decryptStr(data) |
||||
|
||||
* java.createSymmetricCrypto(transformation, key, iv).encrypt(data) |
||||
* java.createSymmetricCrypto(transformation, key, iv).encryptBase64(data) |
||||
* java.createSymmetricCrypto(transformation, key, iv).encryptHex(data) |
||||
*/ |
||||
|
||||
/* 调用SymmetricCrypto key为null时使用随机密钥*/ |
||||
fun createSymmetricCrypto( |
||||
transformation: String, |
||||
key: ByteArray?, |
||||
iv: ByteArray? |
||||
): SymmetricCrypto { |
||||
val symmetricCrypto = SymmetricCrypto(transformation, key) |
||||
return if (iv != null && iv.isNotEmpty()) symmetricCrypto.setIv(iv) else symmetricCrypto |
||||
} |
||||
|
||||
fun createSymmetricCrypto( |
||||
transformation: String, |
||||
key: ByteArray |
||||
): SymmetricCrypto { |
||||
return createSymmetricCrypto(transformation, key, null) |
||||
} |
||||
|
||||
fun createSymmetricCrypto( |
||||
transformation: String, |
||||
key: String |
||||
): SymmetricCrypto { |
||||
return createSymmetricCrypto(transformation, key, null) |
||||
} |
||||
|
||||
fun createSymmetricCrypto( |
||||
transformation: String, |
||||
key: String, |
||||
iv: String? |
||||
): SymmetricCrypto { |
||||
return createSymmetricCrypto( |
||||
transformation, key.encodeToByteArray(), iv?.encodeToByteArray() |
||||
) |
||||
} |
||||
|
||||
//******************对称加密解密old************************// |
||||
|
||||
/////AES |
||||
/** |
||||
* AES 解码为 ByteArray |
||||
* @param str 传入的AES加密的数据 |
||||
* @param key AES 解密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(str)") |
||||
) |
||||
fun aesDecodeToByteArray( |
||||
str: String, key: String, transformation: String, iv: String |
||||
): ByteArray? { |
||||
return createSymmetricCrypto(transformation, key, iv).decrypt(str) |
||||
} |
||||
|
||||
/** |
||||
* AES 解码为 String |
||||
* @param str 传入的AES加密的数据 |
||||
* @param key AES 解密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(str)") |
||||
) |
||||
fun aesDecodeToString( |
||||
str: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).decryptStr(str) |
||||
} |
||||
|
||||
/** |
||||
* AES解码为String,算法参数经过Base64加密 |
||||
* |
||||
* @param data 加密的字符串 |
||||
* @param key Base64后的密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv Base64后的加盐 |
||||
* @return 解密后的字符串 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun aesDecodeArgsBase64Str( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto( |
||||
"AES/${mode}/${padding}", |
||||
Base64.decode(key, Base64.NO_WRAP), |
||||
Base64.decode(iv, Base64.NO_WRAP) |
||||
).decryptStr(data) |
||||
} |
||||
|
||||
/** |
||||
* 已经base64的AES 解码为 ByteArray |
||||
* @param str 传入的AES Base64加密的数据 |
||||
* @param key AES 解密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(str)") |
||||
) |
||||
fun aesBase64DecodeToByteArray( |
||||
str: String, key: String, transformation: String, iv: String |
||||
): ByteArray? { |
||||
return createSymmetricCrypto(transformation, key, iv).decrypt(str) |
||||
} |
||||
|
||||
/** |
||||
* 已经base64的AES 解码为 String |
||||
* @param str 传入的AES Base64加密的数据 |
||||
* @param key AES 解密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(str)") |
||||
) |
||||
fun aesBase64DecodeToString( |
||||
str: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).decryptStr(str) |
||||
} |
||||
|
||||
/** |
||||
* 加密aes为ByteArray |
||||
* @param data 传入的原始数据 |
||||
* @param key AES加密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decrypt(data)") |
||||
) |
||||
fun aesEncodeToByteArray( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): ByteArray? { |
||||
return createSymmetricCrypto(transformation, key, iv).decrypt(data) |
||||
} |
||||
|
||||
/** |
||||
* 加密aes为String |
||||
* @param data 传入的原始数据 |
||||
* @param key AES加密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun aesEncodeToString( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).decryptStr(data) |
||||
} |
||||
|
||||
/** |
||||
* 加密aes后Base64化的ByteArray |
||||
* @param data 传入的原始数据 |
||||
* @param key AES加密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data).toByteArray()") |
||||
) |
||||
fun aesEncodeToBase64ByteArray( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): ByteArray? { |
||||
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data).toByteArray() |
||||
} |
||||
|
||||
/** |
||||
* 加密aes后Base64化的String |
||||
* @param data 传入的原始数据 |
||||
* @param key AES加密的key |
||||
* @param transformation AES加密的方式 |
||||
* @param iv ECB模式的偏移向量 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)") |
||||
) |
||||
fun aesEncodeToBase64String( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data) |
||||
} |
||||
|
||||
|
||||
/** |
||||
* AES加密并转为Base64,算法参数经过Base64加密 |
||||
* |
||||
* @param data 被加密的字符串 |
||||
* @param key Base64后的密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv Base64后的加盐 |
||||
* @return 加密后的Base64 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)") |
||||
) |
||||
fun aesEncodeArgsBase64Str( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto("AES/${mode}/${padding}", key, iv).encryptBase64(data) |
||||
} |
||||
|
||||
/////DES |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun desDecodeToString( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).decryptStr(data) |
||||
} |
||||
|
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun desBase64DecodeToString( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).decryptStr(data) |
||||
} |
||||
|
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encrypt(data)") |
||||
) |
||||
fun desEncodeToString( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return String(createSymmetricCrypto(transformation, key, iv).encrypt(data)) |
||||
} |
||||
|
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)") |
||||
) |
||||
fun desEncodeToBase64String( |
||||
data: String, key: String, transformation: String, iv: String |
||||
): String? { |
||||
return createSymmetricCrypto(transformation, key, iv).encryptBase64(data) |
||||
} |
||||
|
||||
//////3DES |
||||
/** |
||||
* 3DES解密 |
||||
* |
||||
* @param data 加密的字符串 |
||||
* @param key 密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv 加盐 |
||||
* @return 解密后的字符串 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun tripleDESDecodeStr( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto("DESede/${mode}/${padding}", key, iv).decryptStr(data) |
||||
} |
||||
|
||||
/** |
||||
* 3DES解密,算法参数经过Base64加密 |
||||
* |
||||
* @param data 加密的字符串 |
||||
* @param key Base64后的密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv Base64后的加盐 |
||||
* @return 解密后的字符串 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).decryptStr(data)") |
||||
) |
||||
fun tripleDESDecodeArgsBase64Str( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto( |
||||
"DESede/${mode}/${padding}", |
||||
Base64.decode(key, Base64.NO_WRAP), |
||||
iv.encodeToByteArray() |
||||
).decryptStr(data) |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 3DES加密并转为Base64 |
||||
* |
||||
* @param data 被加密的字符串 |
||||
* @param key 密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv 加盐 |
||||
* @return 加密后的Base64 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)") |
||||
) |
||||
fun tripleDESEncodeBase64Str( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto("DESede/${mode}/${padding}", key, iv) |
||||
.encryptBase64(data) |
||||
} |
||||
|
||||
/** |
||||
* 3DES加密并转为Base64,算法参数经过Base64加密 |
||||
* |
||||
* @param data 被加密的字符串 |
||||
* @param key Base64后的密钥 |
||||
* @param mode 模式 |
||||
* @param padding 补码方式 |
||||
* @param iv Base64后的加盐 |
||||
* @return 加密后的Base64 |
||||
*/ |
||||
@Deprecated( |
||||
"过于繁琐弃用", |
||||
ReplaceWith("createSymmetricCrypto(transformation, key, iv).encryptBase64(data)") |
||||
) |
||||
fun tripleDESEncodeArgsBase64Str( |
||||
data: String, |
||||
key: String, |
||||
mode: String, |
||||
padding: String, |
||||
iv: String |
||||
): String? { |
||||
return createSymmetricCrypto( |
||||
"DESede/${mode}/${padding}", |
||||
Base64.decode(key, Base64.NO_WRAP), |
||||
iv.encodeToByteArray() |
||||
).encryptBase64(data) |
||||
} |
||||
|
||||
//******************消息摘要/散列消息鉴别码************************// |
||||
|
||||
/** |
||||
* 生成摘要,并转为16进制字符串 |
||||
* |
||||
* @param data 被摘要数据 |
||||
* @param algorithm 签名算法 |
||||
* @return 16进制字符串 |
||||
*/ |
||||
fun digestHex( |
||||
data: String, |
||||
algorithm: String, |
||||
): String { |
||||
return DigestUtil.digester(algorithm).digestHex(data) |
||||
} |
||||
|
||||
/** |
||||
* 生成摘要,并转为Base64字符串 |
||||
* |
||||
* @param data 被摘要数据 |
||||
* @param algorithm 签名算法 |
||||
* @return Base64字符串 |
||||
*/ |
||||
fun digestBase64Str( |
||||
data: String, |
||||
algorithm: String, |
||||
): String { |
||||
return Base64.encodeToString(DigestUtil.digester(algorithm).digest(data), Base64.NO_WRAP) |
||||
} |
||||
|
||||
/** |
||||
* 生成散列消息鉴别码,并转为16进制字符串 |
||||
* |
||||
* @param data 被摘要数据 |
||||
* @param algorithm 签名算法 |
||||
* @param key 密钥 |
||||
* @return 16进制字符串 |
||||
*/ |
||||
@Suppress("FunctionName") |
||||
fun HMacHex( |
||||
data: String, |
||||
algorithm: String, |
||||
key: String |
||||
): String { |
||||
return HMac(algorithm, key.toByteArray()).digestHex(data) |
||||
} |
||||
|
||||
/** |
||||
* 生成散列消息鉴别码,并转为Base64字符串 |
||||
* |
||||
* @param data 被摘要数据 |
||||
* @param algorithm 签名算法 |
||||
* @param key 密钥 |
||||
* @return Base64字符串 |
||||
*/ |
||||
@Suppress("FunctionName") |
||||
fun HMacBase64( |
||||
data: String, |
||||
algorithm: String, |
||||
key: String |
||||
): String { |
||||
return Base64.encodeToString( |
||||
HMac(algorithm, key.toByteArray()).digest(data), |
||||
Base64.NO_WRAP |
||||
) |
||||
} |
||||
|
||||
|
||||
} |
Before Width: | Height: | Size: 246 B |
Before Width: | Height: | Size: 246 B |
@ -0,0 +1,33 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- |
||||
~ This file is part of FYReader. |
||||
~ FYReader is free software: you can redistribute it and/or modify |
||||
~ it under the terms of the GNU General Public License as published by |
||||
~ the Free Software Foundation, either version 3 of the License, or |
||||
~ (at your option) any later version. |
||||
~ |
||||
~ FYReader is distributed in the hope that it will be useful, |
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
~ GNU General Public License for more details. |
||||
~ |
||||
~ You should have received a copy of the GNU General Public License |
||||
~ along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
~ |
||||
~ Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
--> |
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:height="48dp" |
||||
android:width="48dp" |
||||
android:viewportWidth="48" |
||||
android:viewportHeight="48"> |
||||
<path |
||||
android:fillColor="#FFFFFFFF" |
||||
android:pathData="M22.5,40.3180195 L22.5,26.5 C22.5,19.5964406 28.0964406,14 35,14 C41.0751322,14 46,18.9248678 46,25 C46,31.0751322 41.0751322,36 35,36 L28.5,36 L28.5,33 L35,33 C39.418278,33 43,29.418278 43,25 C43,20.581722 39.418278,17 35,17 C29.7532949,17 25.5,21.2532949 25.5,26.5 L25.5,40.3180195 L27.9393398,37.8786797 L30.0606602,40 L24,46.0606602 L17.9393398,40 L20.0606602,37.8786797 L22.5,40.3180195 Z" |
||||
android:strokeWidth="1.0" /> |
||||
<path |
||||
android:fillColor="#FFFFFFFF" |
||||
android:pathData="M33.8258342,11.0485401 C32.0120952,7.45657788 28.2870652,5 24,5 C18.0506258,5 13.1836471,9.7309997 13.0050811,15.6619804 L12.9676728,16.9044801 L11.7398391,17.098463 C7.8813734,17.7080539 5,21.0505922 5,25 C5,29.418278 8.581722,33 13,33 L19.5,33 L19.5,36 L13,36 C6.92486775,36 2,31.0751322 2,25 C2,19.9793459 5.38459981,15.6735816 10.0917391,14.3885641 C10.8920106,7.40161656 16.8277534,2 24,2 C30.0211876,2 35.1709114,5.80695411 37.1422625,11.1628739 C36.443846,11.0556302 35.7284196,11 35,11 C34.6045681,11 34.2129653,11.0163942 33.8258342,11.0485401 L33.8258342,11.0485401 Z" |
||||
android:strokeWidth="1.0" /> |
||||
</vector> |
@ -1,25 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- |
||||
~ This file is part of FYReader. |
||||
~ FYReader is free software: you can redistribute it and/or modify |
||||
~ it under the terms of the GNU General Public License as published by |
||||
~ the Free Software Foundation, either version 3 of the License, or |
||||
~ (at your option) any later version. |
||||
~ |
||||
~ FYReader is distributed in the hope that it will be useful, |
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
~ GNU General Public License for more details. |
||||
~ |
||||
~ You should have received a copy of the GNU General Public License |
||||
~ along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
~ |
||||
~ Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
--> |
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<!-- 没有焦点时字体颜色 --> |
||||
<item |
||||
android:state_selected="false" |
||||
android:drawable="@drawable/ic_item_category_download"/> |
||||
</selector> |
@ -1,25 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- |
||||
~ This file is part of FYReader. |
||||
~ FYReader is free software: you can redistribute it and/or modify |
||||
~ it under the terms of the GNU General Public License as published by |
||||
~ the Free Software Foundation, either version 3 of the License, or |
||||
~ (at your option) any later version. |
||||
~ |
||||
~ FYReader is distributed in the hope that it will be useful, |
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
~ GNU General Public License for more details. |
||||
~ |
||||
~ You should have received a copy of the GNU General Public License |
||||
~ along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
~ |
||||
~ Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
--> |
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<!-- 没有焦点时字体颜色 --> |
||||
<item |
||||
android:state_selected="false" |
||||
android:drawable="@drawable/ic_item_category_normal"/> |
||||
</selector> |
@ -0,0 +1,79 @@ |
||||
<?xml version="1.0" encoding="utf-8"?><!-- |
||||
~ This file is part of FYReader. |
||||
~ FYReader is free software: you can redistribute it and/or modify |
||||
~ it under the terms of the GNU General Public License as published by |
||||
~ the Free Software Foundation, either version 3 of the License, or |
||||
~ (at your option) any later version. |
||||
~ |
||||
~ FYReader is distributed in the hope that it will be useful, |
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
~ GNU General Public License for more details. |
||||
~ |
||||
~ You should have received a copy of the GNU General Public License |
||||
~ along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
~ |
||||
~ Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
--> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:background="?android:attr/selectableItemBackground" |
||||
android:orientation="vertical"> |
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout |
||||
android:id="@+id/tv_chapter_item" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:padding="13dp"> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_chapter_title" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:singleLine="true" |
||||
android:textColor="@color/textSecondary" |
||||
android:textSize="15sp" |
||||
app:layout_constraintBottom_toTopOf="@id/tv_tag" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toLeftOf="@+id/iv_icon" |
||||
app:layout_constraintTop_toTopOf="parent" /> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_tag" |
||||
android:layout_marginTop="2dp" |
||||
android:layout_width="0dp" |
||||
android:layout_height="wrap_content" |
||||
android:singleLine="true" |
||||
android:textColor="@color/textAssist" |
||||
android:textSize="@dimen/text_default_size" |
||||
android:visibility="gone" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintLeft_toLeftOf="parent" |
||||
app:layout_constraintRight_toLeftOf="@+id/iv_icon" |
||||
app:layout_constraintTop_toBottomOf="@+id/tv_chapter_title" /> |
||||
|
||||
<ImageView |
||||
android:id="@+id/iv_icon" |
||||
android:layout_width="24dp" |
||||
android:layout_height="24dp" |
||||
android:contentDescription="@string/success" |
||||
android:padding="3.5dp" |
||||
android:src="@drawable/ic_cloud_download" |
||||
android:visibility="invisible" |
||||
app:layout_constraintBottom_toBottomOf="parent" |
||||
app:layout_constraintRight_toRightOf="parent" |
||||
app:layout_constraintTop_toTopOf="parent" |
||||
app:tint="@color/textAssist" /> |
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout> |
||||
<View |
||||
android:id="@+id/v_line" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="0.5dp" |
||||
android:layout_gravity="bottom" |
||||
android:background="@color/colorDivider" |
||||
android:layerType="software" /> |
||||
</LinearLayout> |
@ -1,46 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- |
||||
~ This file is part of FYReader. |
||||
~ FYReader is free software: you can redistribute it and/or modify |
||||
~ it under the terms of the GNU General Public License as published by |
||||
~ the Free Software Foundation, either version 3 of the License, or |
||||
~ (at your option) any later version. |
||||
~ |
||||
~ FYReader is distributed in the hope that it will be useful, |
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
~ GNU General Public License for more details. |
||||
~ |
||||
~ You should have received a copy of the GNU General Public License |
||||
~ along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
~ |
||||
~ Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
--> |
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:orientation="vertical"> |
||||
|
||||
<TextView |
||||
android:id="@+id/tv_chapter_title" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:singleLine="true" |
||||
android:drawableLeft="@drawable/selector_category_unload" |
||||
android:textColor="@color/textSecondary" |
||||
android:text="chapter" |
||||
android:drawablePadding="10dp" |
||||
android:padding="13dp" |
||||
android:textSize="15sp" /> |
||||
|
||||
<View |
||||
android:id="@+id/v_line" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="0.5dp" |
||||
android:layout_gravity="bottom" |
||||
android:layout_marginLeft="12dp" |
||||
android:layout_marginRight="12dp" |
||||
android:background="@color/colorDivider" |
||||
android:layerType="software" /> |
||||
</LinearLayout> |
@ -0,0 +1,92 @@ |
||||
/* |
||||
* This file is part of FYReader. |
||||
* FYReader is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* FYReader is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with FYReader. If not, see <https://www.gnu.org/licenses/>. |
||||
* |
||||
* Copyright (C) 2020 - 2022 fengyuecanzhu |
||||
*/ |
||||
|
||||
package xyz.fycz.dynamic.fix |
||||
|
||||
import android.widget.TextView |
||||
import androidx.viewbinding.ViewBinding |
||||
import me.fycz.maple.MapleBridge |
||||
import me.fycz.maple.MapleUtils |
||||
import me.fycz.maple.MethodReplacement |
||||
import xyz.fycz.myreader.greendao.DbManager |
||||
import xyz.fycz.myreader.greendao.entity.Chapter |
||||
import xyz.fycz.myreader.greendao.gen.ChapterDao |
||||
import xyz.fycz.myreader.greendao.service.ChapterService |
||||
import xyz.fycz.myreader.ui.activity.BookDetailedActivity |
||||
|
||||
/** |
||||
* @author fengyue |
||||
* @date 2022/8/11 16:44 |
||||
*/ |
||||
@AppFix( |
||||
[243, 244, 245, 246, 250], |
||||
["[书籍详情界面]取消书籍简介展开时最大行数限制(无法显示完全)", |
||||
"修复从数据库中读取章节时部分数据项缺失的bug"], |
||||
"2022-08-11" |
||||
) |
||||
class App250Fix : AppFixHandle { |
||||
override fun onFix(key: String): BooleanArray { |
||||
return handleFix( |
||||
key, |
||||
"showMoreDesc" to { fxShowMoreDesc() }, |
||||
"findBookAllChapterByBookId" to { fxFindBookAllChapterByBookId() }, |
||||
) |
||||
} |
||||
|
||||
private fun fxFindBookAllChapterByBookId() { |
||||
MapleUtils.findAndHookMethod( |
||||
ChapterService::class.java, |
||||
"findBookAllChapterByBookId", |
||||
String::class.java, |
||||
object : MethodReplacement() { |
||||
override fun replaceHookedMethod(param: MapleBridge.MethodHookParam): Any { |
||||
val bookId = param.args[0] as String? |
||||
if (bookId.isNullOrBlank()) { |
||||
return emptyList<Chapter>() |
||||
} |
||||
return DbManager.getDaoSession().chapterDao |
||||
.queryBuilder() |
||||
.where(ChapterDao.Properties.BookId.eq(bookId)) |
||||
.orderAsc(ChapterDao.Properties.Number) |
||||
.list() |
||||
} |
||||
} |
||||
) |
||||
} |
||||
|
||||
fun fxShowMoreDesc() { |
||||
MapleUtils.findAndHookMethod( |
||||
BookDetailedActivity::class.java, |
||||
"showMoreDesc", |
||||
object : MethodReplacement() { |
||||
override fun replaceHookedMethod(param: MapleBridge.MethodHookParam) { |
||||
val binding = |
||||
MapleUtils.getObjectField(param.thisObject, "binding") as ViewBinding |
||||
val icBinding = MapleUtils.getObjectField(binding, "ic") as ViewBinding |
||||
val bookDetailTvDesc = |
||||
MapleUtils.getObjectField(icBinding, "bookDetailTvDesc") as TextView |
||||
if (bookDetailTvDesc.maxLines == 5) { |
||||
bookDetailTvDesc.maxLines = Int.MAX_VALUE |
||||
} else { |
||||
bookDetailTvDesc.maxLines = 5 |
||||
} |
||||
} |
||||
} |
||||
) |
||||
} |
||||
} |
Loading…
Reference in new issue