Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(TIM): 更新 TIM 版本数据解析逻辑 #95

Merged
merged 3 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ android {
minSdk = 24
targetSdk = 35
versionCode = gitCommitCount
versionName = "1.4.5-$gitCommitHash"
versionName = "1.4.6-$gitCommitHash"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import kotlinx.serialization.Serializable
* @param version TIM 版本号
* @param datetime TIM 版本发布日期
* @param fix TIM 版本优化描述
* @param new TIM 版本新功能描述
* @param feature TIM 版本新功能描述
* @param link TIM 最新官网正式版下载链接
* @param jsonString 该 TIM 版本 JSON 字符串详情
* @param displayType 卡片展示类型,0 为收起态,1 为展开态
Expand All @@ -36,8 +36,8 @@ import kotlinx.serialization.Serializable
data class TIMVersionBean(
val version: String,
val datetime: String,
val fix: String,
val new: String,
val fix: List<String>,
val feature: List<String>,

var link: String = "",
var jsonString: String = "",
Expand Down
74 changes: 45 additions & 29 deletions app/src/main/java/com/xiaoniu/qqversionlist/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1580,42 +1580,58 @@ class MainActivity : AppCompatActivity() {
withContext(Dispatchers.Main) { endProgress() }
}
try {
// https://im.qq.com/rainbow/TIMDownload/ 已弃用
val okHttpClient = OkHttpClient()
val request =
Request.Builder().url("https://im.qq.com/rainbow/TIMDownload/")
val preRequest =
Request.Builder().url("https://tim.qq.com/support.html").build()
val preResponse = okHttpClient.newCall(preRequest).execute()
val htmlData = preResponse.body?.string()
val regex =
"""jQuery\.ajax\(\{\s*url:\s*'([^']+)'\s*\}\)\.done\(function \(versionData\)""".toRegex()
val matchResult = regex.find(htmlData!!)
val match = matchResult?.groupValues?.getOrNull(1)
if (match != null && (match.startsWith("https://") || match.startsWith("http://"))) {
val request = Request.Builder()
.url(match.replace("http://", "https://"))
.build()
val response = okHttpClient.newCall(request).execute()
val responseData = response.body?.string()
if (responseData != null) {
VersionUtil.resolveTIMRainbow(this@MainActivity, responseData)
withContext(Dispatchers.Main) {
timVersionAdapter.submitList(timVersion)
if (!DataStoreUtil.getBooleanKV("closeSwipeLeftForTIM", false)) {
class TipTIMSnackbarActionListener : View.OnClickListener {
override fun onClick(v: View?) {
DataStoreUtil.putBooleanKV("closeSwipeLeftForTIM", true)
val response = okHttpClient.newCall(request).execute()
val responseData = response.body?.string()
if (responseData != null) {
VersionUtil.resolveTIMRainbow(this@MainActivity, responseData)
withContext(Dispatchers.Main) {
timVersionAdapter.submitList(timVersion)
if (!DataStoreUtil.getBooleanKV(
"closeSwipeLeftForTIM", false
)
) {
class TipTIMSnackbarActionListener : View.OnClickListener {
override fun onClick(v: View?) {
DataStoreUtil.putBooleanKV(
"closeSwipeLeftForTIM", true
)
}
}
}

val isDarkTheme: Boolean =
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> true
else -> false
}
val isDarkTheme: Boolean =
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> true
else -> false
}

Snackbar.make(
binding.root, R.string.swipeLeftForTIMVersions,
Snackbar.LENGTH_INDEFINITE
).setAction(R.string.ok, TipTIMSnackbarActionListener())
.setAnchorView(binding.btnGuess)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (isDarkTheme) setBackgroundTint(
getColor(com.google.android.material.R.color.m3_sys_color_dynamic_dark_secondary)
) else setBackgroundTint(getColor(com.google.android.material.R.color.m3_sys_color_dynamic_light_secondary))
}.show()
Snackbar.make(
binding.root, R.string.swipeLeftForTIMVersions,
Snackbar.LENGTH_INDEFINITE
).setAction(R.string.ok, TipTIMSnackbarActionListener())
.setAnchorView(binding.btnGuess)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (isDarkTheme) setBackgroundTint(
getColor(com.google.android.material.R.color.m3_sys_color_dynamic_dark_secondary)
) else setBackgroundTint(getColor(com.google.android.material.R.color.m3_sys_color_dynamic_light_secondary))
}.show()
}
}
}
}
} else throw Exception("Can not get TIM version data.")
} catch (e: Exception) {
e.printStackTrace()
dialogError(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,18 @@ class TIMVersionAdapter :
is ViewHolderDetail -> {
holder.binding.apply {
val fix = bean.fix
val new = bean.new
val new = bean.feature
tvTimOldVersion.text = bean.version
tvTimDetailVersion.text =
holder.itemView.context.getString(R.string.version) + bean.version
tvTimDetailDate.text =
holder.itemView.context.getString(R.string.releaseDateTIM) + bean.datetime
if (fix == "" && new == "") tvTimDesc.isVisible = false
else tvTimDesc.text = new.split("<br/>")
.joinToString(separator = "\n") + (if (new != "") "\n" else "") + (if (fix != "") fix.split(
"<br/>"
).joinToString(separator = "\n") else "")
if (fix.isEmpty() && new.isEmpty()) tvTimDesc.isVisible = false
else tvTimDesc.text = (if (new.isEmpty()) "" else new.joinToString(
separator = "\n- ", prefix = "- "
)) + (if (new.isEmpty()) "" else "\n") + fix.joinToString(
separator = "\n- ", prefix = "- "
)
bindDisplayInstall(tvTimOldInstall, tvTimOldInstallCard, bean)
bindVersionTCloud(tvTimOldVersion, holder.context)
bindAccessibilityTag(accessibilityTimOldTag, holder.context, bean)
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/xiaoniu/qqversionlist/util/StringUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package com.xiaoniu.qqversionlist.util
import android.content.Context
import android.content.pm.PackageInfo
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.xiaoniu.qqversionlist.util.FileUtil.ZipFileCompat
import com.xiaoniu.qqversionlist.util.InfoUtil.dialogError
import kotlinx.serialization.ExperimentalSerializationApi
Expand Down Expand Up @@ -189,4 +190,16 @@ object StringUtil {
"recentList" to recentList.map { it.asString }
)
}

/**
* 将 JsonArray 对象转换为 List<String> 类型列表
*
* @param jsonArray 一个包含字符串的 JsonArray 对象
* @return 返回一个字符串列表,列表中的字符串是从 JsonArray 中解析出来的
*/
fun jsonArrayToList(jsonArray: com.google.gson.JsonArray): List<String> {
val gson = Gson()
val listType = object : TypeToken<List<String>>() {}.type
return gson.fromJson(jsonArray.toString(), listType)
}
}
106 changes: 17 additions & 89 deletions app/src/main/java/com/xiaoniu/qqversionlist/util/VersionUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.xiaoniu.qqversionlist.data.QQVersionBean
import com.xiaoniu.qqversionlist.data.TIMVersionBean
import com.xiaoniu.qqversionlist.ui.MainActivity
import com.xiaoniu.qqversionlist.util.StringUtil.getQua
import com.xiaoniu.qqversionlist.util.StringUtil.jsonArrayToList
import com.xiaoniu.qqversionlist.util.StringUtil.toPrettyFormat
import kotlinx.serialization.json.Json
import org.apache.maven.artifact.versioning.ComparableVersion
Expand Down Expand Up @@ -81,102 +82,36 @@ object VersionUtil {
}

fun resolveTIMRainbow(thisActivity: MainActivity, responseData: String) {
val start = (responseData.indexOf("var params= ")) + 12
val end = (responseData.indexOf(";\n" + " typeof"))
val jsonString = responseData.substring(start, end)
val gson = Gson()
val jsonData = gson.fromJson(jsonString, JsonObject::class.java)
val jsonData = gson.fromJson(responseData, JsonObject::class.java)

thisActivity.timVersion = mutableListOf()

val download = jsonData.getAsJsonObject("app").getAsJsonObject("download")
val androidVersion = download.get("androidVersion").asString
val androidDatetime = download.get("androidDatetime").asString
val androidLink = download.get("androidLink").asString

(thisActivity.timVersion as MutableList<TIMVersionBean>).add(
TIMVersionBean(
version = androidVersion,
datetime = androidDatetime,
fix = "",
new = "",
jsonString = gson.toJson(JsonObject().apply {
addProperty("version", androidVersion)
addProperty("datetime", androidDatetime)
addProperty("fix", "")
addProperty("new", "")
}).toString(),
displayInstall = (DataStoreUtil.getStringKV(
"TIMVersionInstall", ""
) == androidVersion),
isQQNTFramework = ComparableVersion(androidVersion) >= ComparableVersion(
EARLIEST_QQNT_FRAMEWORK_TIM_VERSION_STABLE
),
isKuiklyInside = ComparableVersion(androidVersion) >= ComparableVersion(
EARLIEST_KUIKLY_FRAMEWORK_TIM_VERSION_STABLE
)
)
)

// 从 latest 项中获取 Android 版本
val latest = jsonData.getAsJsonObject("app").getAsJsonArray("latest")
latest.forEach { item ->
val platform = item.asJsonObject.get("platform").asString
if (platform == "Android") {
val version = item.asJsonObject.get("version").asString
val datetime = item.asJsonObject.get("datetime").asString
val fix = item.asJsonObject.get("fix").asString
val newFeature = item.asJsonObject.get("new").asString

(thisActivity.timVersion as MutableList<TIMVersionBean>).add(
TIMVersionBean(
version = version,
datetime = datetime,
fix = fix,
new = newFeature,
jsonString = gson.toJson(JsonObject().apply {
addProperty("version", version)
addProperty("datetime", datetime)
addProperty("fix", fix)
addProperty("new", newFeature)
}).toString(),
displayInstall = (DataStoreUtil.getStringKV(
"TIMVersionInstall", ""
) == version),
isQQNTFramework = ComparableVersion(version) >= ComparableVersion(
EARLIEST_QQNT_FRAMEWORK_TIM_VERSION_STABLE
),
isKuiklyInside = ComparableVersion(version) >= ComparableVersion(
EARLIEST_KUIKLY_FRAMEWORK_TIM_VERSION_STABLE
)
)
)
}
}
val androidLink = jsonData.get("download_link").asJsonObject.get("android").asString

// 从 history 项中获取 Android 版本
val history = jsonData.getAsJsonObject("app").getAsJsonArray("history")
// 从 `version_history` 项中获取 Android 版本
val history = jsonData.getAsJsonArray("version_history")
history.forEach { versionItem ->
val version = versionItem.asJsonObject.get("version").asString
val version = versionItem.asJsonObject.get("version_code").asString
val logs = versionItem.asJsonObject.getAsJsonArray("logs")
logs.forEach { logItem ->
val platform = logItem.asJsonObject.get("platform").asString
if (platform == "Android") {
if (platform == "android") {
val datetime = logItem.asJsonObject.get("datetime").asString
val fix = logItem.asJsonObject.get("fix").asString
val newFeature = logItem.asJsonObject.get("new").asString
val fix = logItem.asJsonObject.get("fix").asJsonArray
val feature = logItem.asJsonObject.get("feature").asJsonArray

(thisActivity.timVersion as MutableList<TIMVersionBean>).add(
TIMVersionBean(
version = version,
datetime = datetime,
fix = fix,
new = newFeature,
fix = jsonArrayToList(fix),
feature = jsonArrayToList(feature),
jsonString = gson.toJson(JsonObject().apply {
addProperty("version", version)
addProperty("version_code", version)
addProperty("datetime", datetime)
addProperty("fix", fix)
addProperty("new", newFeature)
addProperty("fix", fix.toString())
addProperty("feature", feature.toString())
}).toString(),
displayInstall = (DataStoreUtil.getStringKV(
"TIMVersionInstall", ""
Expand All @@ -193,19 +128,12 @@ object VersionUtil {
}
}

// 去除重复的版本号
thisActivity.timVersion =
thisActivity.timVersion.distinctBy { it.jsonString.toPrettyFormat() }
if (thisActivity.timVersion[0].version == thisActivity.timVersion[1].version) (thisActivity.timVersion as MutableList<TIMVersionBean>).removeAt(
0
)

thisActivity.timVersion[0].link = androidLink
thisActivity.timVersion[0].jsonString = gson.toJson(JsonObject().apply {
addProperty("version", thisActivity.timVersion[0].version)
addProperty("version_code", thisActivity.timVersion[0].version)
addProperty("datetime", thisActivity.timVersion[0].datetime)
addProperty("fix", thisActivity.timVersion[0].fix)
addProperty("new", thisActivity.timVersion[0].new)
addProperty("fix", thisActivity.timVersion[0].fix.toString())
addProperty("feature", thisActivity.timVersion[0].feature.toString())
addProperty("link", androidLink)
}).toString()

Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ coreKtx = "1.15.0"
coreSplashscreen = "1.1.0-rc01"
datastorePreferences = "1.1.1"
espressoCore = "3.6.1"
firebaseBom = "33.6.0"
firebaseBom = "33.7.0"
fragmentKtx = "1.8.5"
googleServices = "4.4.2"
gson = "2.11.0"
Expand All @@ -22,7 +22,7 @@ kotlinxCoroutinesAndroid = "1.9.0"
kotlinxSerializationJson = "1.7.3"
library = "1.3.0"
lifecycleRuntimeKtx = "2.8.7"
material = "1.13.0-alpha08"
material = "1.13.0-alpha09"
mavenArtifact = "3.9.9"
okhttp = "4.12.0"
ossLicensesPluginVersion = "0.10.6"
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Tue Apr 09 19:38:08 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists