Horis %!s(int64=3) %!d(string=hai) anos
pai
achega
b87dab7d5b

+ 3 - 2
app/src/main/java/io/legado/app/help/CrashHandler.kt

@@ -8,6 +8,7 @@ import android.webkit.WebSettings
 import io.legado.app.constant.AppConst
 import io.legado.app.constant.AppConst
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
+import io.legado.app.help.config.LocalConfig
 import io.legado.app.model.ReadAloud
 import io.legado.app.model.ReadAloud
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import splitties.init.appCtx
 import splitties.init.appCtx
@@ -20,7 +21,6 @@ import java.util.concurrent.TimeUnit
 /**
 /**
  * 异常管理类
  * 异常管理类
  */
  */
-@Suppress("DEPRECATION")
 class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
 class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
 
 
     /**
     /**
@@ -47,9 +47,10 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
      */
      */
     private fun handleException(ex: Throwable?) {
     private fun handleException(ex: Throwable?) {
         if (ex == null) return
         if (ex == null) return
+        LocalConfig.appCrash = true
         //保存日志文件
         //保存日志文件
         saveCrashInfo2File(ex)
         saveCrashInfo2File(ex)
-        context.longToastOnUi(ex.stackTraceStr)
+        context.longToastOnUiLegacy(ex.stackTraceStr)
         Thread.sleep(3000)
         Thread.sleep(3000)
     }
     }
 
 

+ 6 - 1
app/src/main/java/io/legado/app/help/config/LocalConfig.kt

@@ -116,5 +116,10 @@ by appCtx.getSharedPreferences("local", Context.MODE_PRIVATE) {
             putBoolean("deleteBookOriginal", value)
             putBoolean("deleteBookOriginal", value)
         }
         }
 
 
+    var appCrash: Boolean
+        get() = getBoolean("appCrash")
+        set(value) {
+            putBoolean("appCrash", value)
+        }
 
 
-}
+}

+ 15 - 0
app/src/main/java/io/legado/app/ui/main/MainActivity.kt

@@ -35,6 +35,7 @@ import io.legado.app.lib.dialogs.alert
 import io.legado.app.lib.theme.elevation
 import io.legado.app.lib.theme.elevation
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.lib.theme.primaryColor
 import io.legado.app.service.BaseReadAloudService
 import io.legado.app.service.BaseReadAloudService
+import io.legado.app.ui.about.CrashLogsDialog
 import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment
 import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment
 import io.legado.app.ui.main.bookshelf.style1.BookshelfFragment1
 import io.legado.app.ui.main.bookshelf.style1.BookshelfFragment1
 import io.legado.app.ui.main.bookshelf.style2.BookshelfFragment2
 import io.legado.app.ui.main.bookshelf.style2.BookshelfFragment2
@@ -134,6 +135,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
             upVersion()
             upVersion()
             //设置本地密码
             //设置本地密码
             setLocalPassword()
             setLocalPassword()
+            notifyAppCrash()
             //备份同步
             //备份同步
             backupSync()
             backupSync()
             //自动更新书籍
             //自动更新书籍
@@ -266,6 +268,19 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
         }
         }
     }
     }
 
 
+    private fun notifyAppCrash() {
+        if (!LocalConfig.appCrash || BuildConfig.DEBUG) {
+            return
+        }
+        LocalConfig.appCrash = false
+        alert(getString(R.string.draw), "检测到阅读发生了崩溃,是否打开崩溃日志以便报告问题?") {
+            yesButton {
+                showDialogFragment<CrashLogsDialog>()
+            }
+            noButton()
+        }
+    }
+
     /**
     /**
      * 备份同步
      * 备份同步
      */
      */

+ 43 - 28
app/src/main/java/io/legado/app/utils/ToastUtils.kt

@@ -2,71 +2,86 @@
 
 
 package io.legado.app.utils
 package io.legado.app.utils
 
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.content.Context
+import android.view.LayoutInflater
+import android.widget.TextView
 import android.widget.Toast
 import android.widget.Toast
+import androidx.cardview.widget.CardView
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.Fragment
 import io.legado.app.BuildConfig
 import io.legado.app.BuildConfig
+import io.legado.app.R
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
+import io.legado.app.lib.theme.bottomBackground
+import io.legado.app.lib.theme.getPrimaryTextColor
 
 
 private var toast: Toast? = null
 private var toast: Toast? = null
 
 
-fun Context.toastOnUi(message: Int) {
+private var toastLegacy: Toast? = null
+
+fun Context.toastOnUi(message: Int, duration: Int = Toast.LENGTH_SHORT) {
+    toastOnUi(getString(message), duration)
+}
+
+@SuppressLint("InflateParams")
+@Suppress("DEPRECATION")
+fun Context.toastOnUi(message: CharSequence?, duration: Int = Toast.LENGTH_SHORT) {
     runOnUI {
     runOnUI {
         kotlin.runCatching {
         kotlin.runCatching {
             if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
             if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
-                toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
-            } else {
-                toast?.setText(message)
-                toast?.duration = Toast.LENGTH_SHORT
+                toast?.cancel()
+                toast = Toast(this)
+                toast?.view = LayoutInflater.from(this).inflate(R.layout.view_toast, null)
             }
             }
+            val toastView = toast?.view!!
+            val cardView = toastView.findViewById<CardView>(R.id.cv_content)
+            cardView.setCardBackgroundColor(bottomBackground)
+            val isLight = ColorUtils.isColorLight(bottomBackground)
+            val textView = toastView.findViewById<TextView>(R.id.tv_text)
+            textView.setTextColor(getPrimaryTextColor(isLight))
+            textView.text = message
+            toast?.duration = duration
             toast?.show()
             toast?.show()
         }
         }
     }
     }
 }
 }
 
 
-fun Context.toastOnUi(message: CharSequence?) {
+fun Context.toastOnUiLegacy(message: CharSequence) {
     runOnUI {
     runOnUI {
         kotlin.runCatching {
         kotlin.runCatching {
-            if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
-                toast = Toast.makeText(this, message.toString(), Toast.LENGTH_SHORT)
+            if (toastLegacy == null || BuildConfig.DEBUG || AppConfig.recordLog) {
+                toastLegacy = Toast.makeText(this, message, Toast.LENGTH_SHORT)
             } else {
             } else {
-                toast?.setText(message.toString())
-                toast?.duration = Toast.LENGTH_SHORT
+                toastLegacy?.setText(message)
+                toastLegacy?.duration = Toast.LENGTH_SHORT
             }
             }
-            toast?.show()
+            toastLegacy?.show()
         }
         }
     }
     }
 }
 }
 
 
 fun Context.longToastOnUi(message: Int) {
 fun Context.longToastOnUi(message: Int) {
-    runOnUI {
-        kotlin.runCatching {
-            if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
-                toast = Toast.makeText(this, message, Toast.LENGTH_LONG)
-            } else {
-                toast?.setText(message)
-                toast?.duration = Toast.LENGTH_LONG
-            }
-            toast?.show()
-        }
-    }
+    toastOnUi(message, Toast.LENGTH_LONG)
 }
 }
 
 
 fun Context.longToastOnUi(message: CharSequence?) {
 fun Context.longToastOnUi(message: CharSequence?) {
+    toastOnUi(message, Toast.LENGTH_LONG)
+}
+
+fun Context.longToastOnUiLegacy(message: CharSequence) {
     runOnUI {
     runOnUI {
         kotlin.runCatching {
         kotlin.runCatching {
-            if (toast == null || BuildConfig.DEBUG || AppConfig.recordLog) {
-                toast = Toast.makeText(this, message.toString(), Toast.LENGTH_LONG)
+            if (toastLegacy == null || BuildConfig.DEBUG || AppConfig.recordLog) {
+                toastLegacy = Toast.makeText(this, message, Toast.LENGTH_LONG)
             } else {
             } else {
-                toast?.setText(message.toString())
-                toast?.duration = Toast.LENGTH_LONG
+                toastLegacy?.setText(message)
+                toastLegacy?.duration = Toast.LENGTH_LONG
             }
             }
-            toast?.show()
+            toastLegacy?.show()
         }
         }
     }
     }
 }
 }
 
 
-
 fun Fragment.toastOnUi(message: Int) = requireActivity().toastOnUi(message)
 fun Fragment.toastOnUi(message: Int) = requireActivity().toastOnUi(message)
 
 
 fun Fragment.toastOnUi(message: CharSequence) = requireActivity().toastOnUi(message)
 fun Fragment.toastOnUi(message: CharSequence) = requireActivity().toastOnUi(message)

+ 27 - 0
app/src/main/res/layout/view_toast.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent">
+
+    <androidx.cardview.widget.CardView
+        android:id="@+id/cv_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:cardCornerRadius="10dp"
+        app:cardElevation="2dp"
+        app:cardUseCompatPadding="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <TextView
+            android:id="@+id/tv_text"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:padding="10dp" />
+
+    </androidx.cardview.widget.CardView>
+
+</androidx.constraintlayout.widget.ConstraintLayout>