diff --git a/app/src/main/java/io/legado/app/help/AppWebDav.kt b/app/src/main/java/io/legado/app/help/AppWebDav.kt index ac7890037..5f02c69e4 100644 --- a/app/src/main/java/io/legado/app/help/AppWebDav.kt +++ b/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) } } diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index 0c741f258..a60c6a231 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/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) diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index 34a51271c..706d298f8 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/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(path, "bookshelf.json")?.let { it.forEach { book -> diff --git a/app/src/main/java/io/legado/app/lib/prefs/ListPreferenceDialog.kt b/app/src/main/java/io/legado/app/lib/prefs/ListPreferenceDialog.kt index 7165ef744..445adf7f1 100644 --- a/app/src/main/java/io/legado/app/lib/prefs/ListPreferenceDialog.kt +++ b/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 diff --git a/app/src/main/java/io/legado/app/lib/prefs/MultiSelectListPreferenceDialog.kt b/app/src/main/java/io/legado/app/lib/prefs/MultiSelectListPreferenceDialog.kt index c1ab77708..e8c26ec18 100644 --- a/app/src/main/java/io/legado/app/lib/prefs/MultiSelectListPreferenceDialog.kt +++ b/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 diff --git a/app/src/main/java/io/legado/app/lib/theme/TintHelper.kt b/app/src/main/java/io/legado/app/lib/theme/TintHelper.kt index fe470556f..b9f5be5c3 100644 --- a/app/src/main/java/io/legado/app/lib/theme/TintHelper.kt +++ b/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) } diff --git a/app/src/main/java/io/legado/app/utils/DialogExtensions.kt b/app/src/main/java/io/legado/app/utils/DialogExtensions.kt index 941b57088..471feae80 100644 --- a/app/src/main/java/io/legado/app/utils/DialogExtensions.kt +++ b/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 } diff --git a/app/src/main/java/io/legado/app/utils/UrlUtil.kt b/app/src/main/java/io/legado/app/utils/UrlUtil.kt index 54cad3fb7..8cad7a6e6 100644 --- a/app/src/main/java/io/legado/app/utils/UrlUtil.kt +++ b/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")