Horis 2 tahun lalu
induk
melakukan
cfa7703b03

+ 1 - 1
app/src/main/java/io/legado/app/help/AppWebDav.kt

@@ -114,7 +114,7 @@ object AppWebDav {
             webDav.downloadTo(Backup.zipFilePath, true)
             FileUtils.delete(Backup.backupPath)
             ZipUtils.unZipToPath(File(Backup.zipFilePath), Backup.backupPath)
-            Restore.restore(Backup.backupPath)
+            Restore.restoreLocked(Backup.backupPath)
         }
     }
 

+ 5 - 1
app/src/main/java/io/legado/app/help/storage/Backup.kt

@@ -207,7 +207,11 @@ object Backup {
                     copyBackup(File(path), backupFileName)
                 }
             }
-            AppWebDav.backUpWebDav(zipFileName)
+            try {
+                AppWebDav.backUpWebDav(zipFileName)
+            } catch (e: Exception) {
+                AppLog.put("上传备份至webdav失败\n$e", e)
+            }
         }
         FileUtils.delete(backupPath)
         FileUtils.delete(zipFilePath)

+ 12 - 2
app/src/main/java/io/legado/app/help/storage/Restore.kt

@@ -49,6 +49,8 @@ import io.legado.app.utils.openInputStream
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withContext
 import splitties.init.appCtx
 import java.io.File
@@ -59,6 +61,8 @@ import java.io.FileInputStream
  */
 object Restore {
 
+    private val mutex = Mutex()
+
     private const val TAG = "Restore"
 
     suspend fun restore(context: Context, uri: Uri) {
@@ -77,7 +81,7 @@ object Restore {
             return
         }
         kotlin.runCatching {
-            restore(Backup.backupPath)
+            restoreLocked(Backup.backupPath)
             LocalConfig.lastBackup = System.currentTimeMillis()
         }.onFailure {
             appCtx.toastOnUi("恢复备份出错\n${it.localizedMessage}")
@@ -85,7 +89,13 @@ object Restore {
         }
     }
 
-    suspend fun restore(path: String) {
+    suspend fun restoreLocked(path: String) {
+        mutex.withLock {
+            restore(path)
+        }
+    }
+
+    private suspend fun restore(path: String) {
         val aes = BackupAES()
         fileToListT<Book>(path, "bookshelf.json")?.let {
             it.forEach { book ->

+ 5 - 0
app/src/main/java/io/legado/app/lib/prefs/ListPreferenceDialog.kt

@@ -3,10 +3,12 @@ package io.legado.app.lib.prefs
 import android.app.Dialog
 import android.os.Bundle
 import androidx.appcompat.app.AlertDialog
+import androidx.core.view.forEach
 import androidx.preference.ListPreferenceDialogFragmentCompat
 import androidx.preference.PreferenceDialogFragmentCompat
 import io.legado.app.lib.theme.accentColor
 import io.legado.app.lib.theme.filletBackground
+import io.legado.app.utils.applyTint
 
 class ListPreferenceDialog : ListPreferenceDialogFragmentCompat() {
 
@@ -30,6 +32,9 @@ class ListPreferenceDialog : ListPreferenceDialogFragmentCompat() {
                 getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
                 getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
                 getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(accentColor)
+                listView?.forEach {
+                    it.applyTint(accentColor)
+                }
             }
         }
         return dialog

+ 5 - 0
app/src/main/java/io/legado/app/lib/prefs/MultiSelectListPreferenceDialog.kt

@@ -3,10 +3,12 @@ package io.legado.app.lib.prefs
 import android.app.Dialog
 import android.os.Bundle
 import androidx.appcompat.app.AlertDialog
+import androidx.core.view.forEach
 import androidx.preference.MultiSelectListPreferenceDialogFragmentCompat
 import androidx.preference.PreferenceDialogFragmentCompat
 import io.legado.app.lib.theme.accentColor
 import io.legado.app.lib.theme.filletBackground
+import io.legado.app.utils.applyTint
 
 class MultiSelectListPreferenceDialog : MultiSelectListPreferenceDialogFragmentCompat() {
 
@@ -32,6 +34,9 @@ class MultiSelectListPreferenceDialog : MultiSelectListPreferenceDialogFragmentC
                 getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
                 getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
                 getButton(AlertDialog.BUTTON_NEUTRAL)?.setTextColor(accentColor)
+                listView?.forEach {
+                    it.applyTint(accentColor)
+                }
             }
         }
         return dialog

+ 35 - 1
app/src/main/java/io/legado/app/lib/theme/TintHelper.kt

@@ -7,7 +7,16 @@ import android.graphics.PorterDuff
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.RippleDrawable
 import android.view.View
-import android.widget.*
+import android.widget.Button
+import android.widget.CheckBox
+import android.widget.CheckedTextView
+import android.widget.EditText
+import android.widget.ImageView
+import android.widget.ProgressBar
+import android.widget.RadioButton
+import android.widget.SeekBar
+import android.widget.Switch
+import android.widget.TextView
 import androidx.annotation.CheckResult
 import androidx.annotation.ColorInt
 import androidx.appcompat.widget.AppCompatEditText
@@ -15,6 +24,7 @@ import androidx.appcompat.widget.SearchView
 import androidx.appcompat.widget.SwitchCompat
 import androidx.core.content.ContextCompat
 import androidx.core.graphics.drawable.DrawableCompat
+import androidx.core.widget.TextViewCompat
 import com.google.android.material.floatingactionbutton.FloatingActionButton
 import io.legado.app.R
 import io.legado.app.utils.ColorUtils
@@ -144,6 +154,7 @@ object TintHelper {
                 is ProgressBar -> setTint(view, color)
                 is AppCompatEditText -> setTint(view, color, isDark)
                 is CheckBox -> setTint(view, color, isDark)
+                is CheckedTextView -> setTint(view, color, isDark)
                 is ImageView -> setTint(view, color)
                 is Switch -> setTint(view, color, isDark)
                 is SwitchCompat -> setTint(view, color, isDark)
@@ -299,6 +310,29 @@ object TintHelper {
         box.buttonTintList = sl
     }
 
+    @SuppressLint("PrivateResource")
+    fun setTint(checkedTextView: CheckedTextView, @ColorInt color: Int, useDarker: Boolean) {
+        val sl = ColorStateList(
+            arrayOf(
+                intArrayOf(-android.R.attr.state_enabled),
+                intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_checked),
+                intArrayOf(android.R.attr.state_enabled, android.R.attr.state_checked)
+            ), intArrayOf(
+                ContextCompat.getColor(
+                    checkedTextView.context,
+                    if (useDarker) R.color.ate_control_disabled_dark else R.color.ate_control_disabled_light
+                ),
+                ContextCompat.getColor(
+                    checkedTextView.context,
+                    if (useDarker) R.color.ate_control_normal_dark else R.color.ate_control_normal_light
+                ),
+                color
+            )
+        )
+        checkedTextView.checkMarkTintList = sl
+        TextViewCompat.setCompoundDrawableTintList(checkedTextView, sl)
+    }
+
     fun setTint(image: ImageView, @ColorInt color: Int) {
         image.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
     }

+ 7 - 0
app/src/main/java/io/legado/app/utils/DialogExtensions.kt

@@ -3,9 +3,11 @@ package io.legado.app.utils
 import android.app.Dialog
 import android.view.WindowManager
 import androidx.appcompat.app.AlertDialog
+import androidx.core.view.forEach
 import androidx.fragment.app.DialogFragment
 import io.legado.app.lib.theme.Selector
 import io.legado.app.lib.theme.ThemeStore
+import io.legado.app.lib.theme.accentColor
 import io.legado.app.lib.theme.filletBackground
 import splitties.systemservices.windowManager
 
@@ -24,6 +26,11 @@ fun AlertDialog.applyTint(): AlertDialog {
     if (getButton(AlertDialog.BUTTON_NEUTRAL) != null) {
         getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(colorStateList)
     }
+    window?.decorView?.post {
+        listView?.forEach {
+            it.applyTint(context.accentColor)
+        }
+    }
     return this
 }
 

+ 3 - 2
app/src/main/java/io/legado/app/utils/UrlUtil.kt

@@ -153,9 +153,10 @@ object UrlUtil {
     /* 获取合法的文件后缀 */
     fun getSuffix(str: String, default: String? = null): String {
         val suffix = CustomUrl(str).getUrl()
-            .substringAfterLast(".", "")
+            .substringAfterLast("/")
             .substringBefore("?")
-            .substringBefore("/")
+            .substringBefore("#")
+            .substringAfterLast(".", "")
         //检查截取的后缀字符是否合法 [a-zA-Z0-9]
         return if (suffix.length > 5 || !suffix.matches(fileSuffixRegex)) {
             AppLog.put("Cannot find legal suffix:\n target: $str\n suffix: $suffix")