实时更新日志

This commit is contained in:
HapeLee committed 2025-11-04 19:23:28 +08:00
1 parent 055ead6158
commit 5d6665b009
6 files changed
+110 -39

No files matched your search

@@ -64,6 +64,23 @@ object AppUpdateGitHub : AppUpdate.AppUpdateInterface {
} }
} }
suspend fun getReleaseByTag(tag: String): AppUpdate.UpdateInfo? {
val url = "https://api.github.com/repos/HapeLee/legado-with-MD3/releases/tags/$tag"
val res = okHttpClient.newCallResponse { url(url) }
if (!res.isSuccessful) return null
val body = res.body.text()
val release = GSON.fromJsonObject<GithubRelease>(body).getOrElse { return null }
val info = release.gitReleaseToAppReleaseInfo().firstOrNull() ?: return null
return AppUpdate.UpdateInfo(
tagName = info.versionName,
updateLog = info.note,
downloadUrl = info.downloadUrl,
fileName = info.name
)
}
override fun check(scope: CoroutineScope): Coroutine<AppUpdate.UpdateInfo> { override fun check(scope: CoroutineScope): Coroutine<AppUpdate.UpdateInfo> {
return Coroutine.async(scope) { return Coroutine.async(scope) {
val currentVersion = AppConst.appInfo.versionName val currentVersion = AppConst.appInfo.versionName
@@ -123,7 +123,7 @@ class AboutActivity : BaseActivity<ActivityAboutBinding>() {
AppUpdate.gitHubUpdate?.run { AppUpdate.gitHubUpdate?.run {
check(lifecycleScope) check(lifecycleScope)
.onSuccess { .onSuccess {
showDialogFragment(UpdateDialog(it)) showDialogFragment(UpdateDialog(it, UpdateDialog.Mode.UPDATE))
}.onError { }.onError {
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}") appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
}.onFinally { }.onFinally {
@@ -12,6 +12,7 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.update.AppUpdate import io.legado.app.help.update.AppUpdate
import io.legado.app.help.update.AppVariant import io.legado.app.help.update.AppVariant
import io.legado.app.model.Download import io.legado.app.model.Download
import io.legado.app.utils.gone
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
@@ -21,12 +22,15 @@ import io.noties.markwon.image.glide.GlideImagesPlugin
class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) { class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) {
constructor(updateInfo: AppUpdate.UpdateInfo) : this() { enum class Mode { UPDATE, VIEW_LOG }
constructor(updateInfo: AppUpdate.UpdateInfo, mode: Mode = Mode.UPDATE) : this() {
arguments = Bundle().apply { arguments = Bundle().apply {
putString("newVersion", updateInfo.tagName) putString("newVersion", updateInfo.tagName)
putString("updateBody", updateInfo.updateLog) putString("updateBody", updateInfo.updateLog)
putString("url", updateInfo.downloadUrl) putString("url", updateInfo.downloadUrl)
putString("name", updateInfo.fileName) putString("name", updateInfo.fileName)
putString("mode", mode.name)
} }
} }
@@ -38,28 +42,24 @@ class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) {
else -> AppConst.appInfo.appVariant else -> AppConst.appInfo.appVariant
} }
val binding by viewBinding(DialogUpdateBinding::bind) private val binding by viewBinding(DialogUpdateBinding::bind)
override fun onStart() { private val mode: Mode
super.onStart() get() = Mode.valueOf(arguments?.getString("mode") ?: Mode.UPDATE.name)
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
//binding.toolBar.setBackgroundColor(primaryColor)
binding.tvCurrentVersion.text = BuildConfig.VERSION_NAME binding.tvCurrentVersion.text = BuildConfig.VERSION_NAME
binding.tvVersion.text = arguments?.getString("newVersion") binding.tvVersion.text = arguments?.getString("newVersion")
binding.tvAbi.text = Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown" binding.tvAbi.text = Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown"
binding.tvUrl.text = arguments?.getString("url")
binding.tvVariable.text = checkVariant.toString() binding.tvVariable.text = checkVariant.toString()
val updateBody = arguments?.getString("updateBody") val updateBody = arguments?.getString("updateBody")
if (updateBody == null) { if (updateBody.isNullOrBlank()) {
toastOnUi("没有数据") toastOnUi("没有数据")
dismiss() dismiss()
return return
} }
binding.textView.post { binding.textView.post {
Markwon.builder(requireContext()) Markwon.builder(requireContext())
.usePlugin(GlideImagesPlugin.create(requireContext())) .usePlugin(GlideImagesPlugin.create(requireContext()))
@@ -69,19 +69,29 @@ class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) {
.setMarkdown(binding.textView, updateBody) .setMarkdown(binding.textView, updateBody)
} }
binding.btnUpdate.setOnClickListener { when (mode) {
Mode.UPDATE -> {
val url = arguments?.getString("url") val url = arguments?.getString("url")
val fileName = arguments?.getString("name") val fileName = arguments?.getString("name")
binding.ivAward.gone()
binding.btnUpdate.setOnClickListener {
if (url.isNullOrBlank() || fileName.isNullOrBlank()) { if (url.isNullOrBlank() || fileName.isNullOrBlank()) {
toastOnUi("下载信息不完整") toastOnUi("下载信息不完整")
return@setOnClickListener return@setOnClickListener
} }
Download.start(requireContext(), url, fileName) Download.start(requireContext(), url, fileName)
toastOnUi("开始下载: $fileName") toastOnUi("开始下载: $fileName")
} }
} }
Mode.VIEW_LOG -> {
binding.bottomSheetTitle.text = "已经更新至"
binding.tvVersion.text = BuildConfig.VERSION_NAME
binding.btnUpdate.gone()
binding.llCurrent.gone()
binding.tvCurrentVersion.gone()
binding.tvUrl.gone()
}
}
}
} }
@@ -39,8 +39,10 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.LocalConfig import io.legado.app.help.config.LocalConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.storage.Backup import io.legado.app.help.storage.Backup
import io.legado.app.help.update.AppUpdateGitHub
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.ui.about.CrashLogsDialog import io.legado.app.ui.about.CrashLogsDialog
import io.legado.app.ui.about.UpdateDialog
import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.book.search.SearchActivity
import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment
@@ -235,7 +237,7 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
/** /**
* 版本更新日志 * 版本更新日志
*/ */
private suspend fun upVersion() = suspendCoroutine { block -> private suspend fun upVersion() = suspendCoroutine<Unit?> { block ->
if (LocalConfig.versionCode == appInfo.versionCode) { if (LocalConfig.versionCode == appInfo.versionCode) {
block.resume(null) block.resume(null)
return@suspendCoroutine return@suspendCoroutine
@@ -244,17 +246,32 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
if (LocalConfig.isFirstOpenApp) { if (LocalConfig.isFirstOpenApp) {
val help = String(assets.open("web/help/md/appHelp.md").readBytes()) val help = String(assets.open("web/help/md/appHelp.md").readBytes())
val dialog = TextDialog(getString(R.string.help), help, TextDialog.Mode.MD) val dialog = TextDialog(getString(R.string.help), help, TextDialog.Mode.MD)
dialog.setOnDismissListener { dialog.setOnDismissListener { block.resume(null) }
block.resume(null)
}
showDialogFragment(dialog) showDialogFragment(dialog)
} else if (!BuildConfig.DEBUG) { return@suspendCoroutine
val log = String(assets.open("updateLog.md").readBytes())
val dialog = TextDialog(getString(R.string.update_log), log, TextDialog.Mode.MD)
dialog.setOnDismissListener {
block.resume(null)
} }
if (!BuildConfig.DEBUG) {
lifecycleScope.launch {
try {
val info = AppUpdateGitHub.getReleaseByTag(BuildConfig.VERSION_NAME)
if (info != null) {
val dialog = UpdateDialog(info, UpdateDialog.Mode.VIEW_LOG)
dialog.setOnDismissListener { block.resume(null) }
showDialogFragment(dialog) showDialogFragment(dialog)
} else {
val fallback = String(assets.open("updateLog.md").readBytes())
val dialog = TextDialog(getString(R.string.update_log), fallback, TextDialog.Mode.MD)
dialog.setOnDismissListener { block.resume(null) }
showDialogFragment(dialog)
}
} catch (e: Exception) {
e.printStackTrace()
val fallback = String(assets.open("updateLog.md").readBytes())
val dialog = TextDialog(getString(R.string.update_log), fallback, TextDialog.Mode.MD)
dialog.setOnDismissListener { block.resume(null) }
showDialogFragment(dialog)
}
}
} else { } else {
block.resume(null) block.resume(null)
} }
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M363,650L480,579L597,650L566,517L670,427L533,416L480,290L427,416L290,427L394,517L363,650ZM480,932L346,800L160,800L160,614L28,480L160,346L160,160L346,160L480,28L614,160L800,160L800,346L932,480L800,614L800,800L614,800L480,932ZM480,820L580,720L720,720L720,580L820,480L720,380L720,240L580,240L480,140L380,240L240,240L240,380L140,480L240,580L240,720L380,720L480,820ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>
+31 -15
View File
@@ -11,7 +11,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:paddingBottom="16dp"> android:paddingBottom="4dp">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView <com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -20,41 +20,57 @@
android:minHeight="0dp" android:minHeight="0dp"
android:layout_gravity="center_horizontal" /> android:layout_gravity="center_horizontal" />
<LinearLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"> android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/iv_award"
android:layout_width="48dp"
android:layout_height="56dp"
android:clickable="false"
app:iconSize="32dp"
app:iconGravity="textStart"
app:iconPadding="0dp"
style="@style/Widget.Material3Expressive.Button.TonalButton"
app:icon="@drawable/ic_award"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView <TextView
android:id="@+id/bottom_sheet_title" android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:includeFontPadding="false"
android:layout_gravity="bottom"
android:text="@string/update_available" android:text="@string/update_available"
android:textSize="20sp" android:textSize="20sp"
android:textStyle="bold" /> android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
<View app:layout_constraintTop_toBottomOf="@id/iv_award"
android:layout_width="0dp" app:layout_constraintBottom_toBottomOf="parent"/>
android:layout_height="match_parent"
android:layout_weight="1"/>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_update" android:id="@+id/btn_update"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:icon="@drawable/ic_download" app:icon="@drawable/ic_download"
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal" /> style="@style/Widget.Material3Expressive.Button.IconButton.Tonal"
</LinearLayout> app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_current"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="bottom" android:gravity="bottom"
android:paddingBottom="4dp"> android:paddingVertical="4dp">
<TextView <TextView
android:id="@+id/tv_current_version" android:id="@+id/tv_current_version"
@@ -90,7 +106,7 @@
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="2dp" android:layout_height="2dp"
android:layout_marginVertical="2dp" android:layout_marginVertical="4dp"
android:background="?attr/colorPrimaryContainer" /> android:background="?attr/colorPrimaryContainer" />
<LinearLayout <LinearLayout
@@ -104,6 +120,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:maxLines="1"
android:text="@string/text" android:text="@string/text"
android:textColor="?attr/colorPrimary" android:textColor="?attr/colorPrimary"
android:textSize="24sp" android:textSize="24sp"
@@ -113,7 +130,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardBackgroundColor="?attr/colorTertiaryContainer" app:cardBackgroundColor="?attr/colorTertiaryContainer"
app:cardCornerRadius="8dp" app:cardCornerRadius="8dp"
app:strokeWidth="0dp"> app:strokeWidth="0dp">
@@ -147,6 +163,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textStyle="bold" android:textStyle="bold"
android:textSize="14sp" android:textSize="14sp"
android:paddingTop="8dp"
android:text="@string/update_log"/> android:text="@string/update_log"/>
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
@@ -165,5 +182,4 @@
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>