实时更新日志
This commit is contained in:
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
Reference in new issue
Block a user