Explorar el Código

修复初始化界面备份失败与NPE问题

HapeLee hace 1 año
padre
commit
9b1c155f77

+ 3 - 1
app/src/main/AndroidManifest.xml

@@ -135,7 +135,9 @@
         </activity>
         </activity>
         <activity
         <activity
             android:name=".ui.welcome.WelcomeActivity"
             android:name=".ui.welcome.WelcomeActivity"
-            android:exported="false" />
+            android:enableOnBackInvokedCallback="true"
+            android:exported="false"
+            android:windowSoftInputMode="adjustPan|stateHidden" />
         <!-- 阅读界面 -->
         <!-- 阅读界面 -->
         <activity
         <activity
             android:name=".ui.book.read.ReadBookActivity"
             android:name=".ui.book.read.ReadBookActivity"

+ 23 - 22
app/src/main/java/io/legato/kazusa/help/storage/Restore.kt

@@ -2,6 +2,7 @@ package io.legato.kazusa.help.storage
 
 
 import android.content.Context
 import android.content.Context
 import android.net.Uri
 import android.net.Uri
+import androidx.core.content.edit
 import androidx.documentfile.provider.DocumentFile
 import androidx.documentfile.provider.DocumentFile
 import io.legato.kazusa.BuildConfig
 import io.legato.kazusa.BuildConfig
 import io.legato.kazusa.R
 import io.legato.kazusa.R
@@ -231,36 +232,36 @@ object Restore {
         }
         }
         //AppWebDav.downBgs()
         //AppWebDav.downBgs()
         appCtx.getSharedPreferences(path, "config")?.all?.let { map ->
         appCtx.getSharedPreferences(path, "config")?.all?.let { map ->
-            val edit = appCtx.defaultSharedPreferences.edit()
+            appCtx.defaultSharedPreferences.edit {
 
 
-            map.forEach { (key, value) ->
-                if (BackupConfig.keyIsNotIgnore(key)) {
-                    when (key) {
-                        PreferKey.webDavPassword -> {
-                            kotlin.runCatching {
-                                aes.decryptStr(value.toString())
-                            }.getOrNull()?.let {
-                                edit.putString(key, it)
-                            } ?: let {
-                                if (appCtx.getPrefString(PreferKey.webDavPassword)
-                                        .isNullOrBlank()
-                                ) {
-                                    edit.putString(key, value.toString())
+                map.forEach { (key, value) ->
+                    if (BackupConfig.keyIsNotIgnore(key)) {
+                        when (key) {
+                            PreferKey.webDavPassword -> {
+                                kotlin.runCatching {
+                                    aes.decryptStr(value.toString())
+                                }.getOrNull()?.let {
+                                    putString(key, it)
+                                } ?: let {
+                                    if (appCtx.getPrefString(PreferKey.webDavPassword)
+                                            .isNullOrBlank()
+                                    ) {
+                                        putString(key, value.toString())
+                                    }
                                 }
                                 }
                             }
                             }
-                        }
 
 
-                        else -> when (value) {
-                            is Int -> edit.putInt(key, value)
-                            is Boolean -> edit.putBoolean(key, value)
-                            is Long -> edit.putLong(key, value)
-                            is Float -> edit.putFloat(key, value)
-                            is String -> edit.putString(key, value)
+                            else -> when (value) {
+                                is Int -> putInt(key, value)
+                                is Boolean -> putBoolean(key, value)
+                                is Long -> putLong(key, value)
+                                is Float -> putFloat(key, value)
+                                is String -> putString(key, value)
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
-            edit.apply()
         }
         }
         ReadBookConfig.apply {
         ReadBookConfig.apply {
             comicStyleSelect = appCtx.getPrefInt(PreferKey.comicStyleSelect)
             comicStyleSelect = appCtx.getPrefInt(PreferKey.comicStyleSelect)

+ 37 - 17
app/src/main/java/io/legato/kazusa/ui/welcome/WebDavFragment.kt

@@ -26,7 +26,9 @@ import io.legato.kazusa.lib.dialogs.alert
 import io.legato.kazusa.lib.dialogs.selector
 import io.legato.kazusa.lib.dialogs.selector
 import io.legato.kazusa.ui.file.HandleFileContract
 import io.legato.kazusa.ui.file.HandleFileContract
 import io.legato.kazusa.ui.widget.dialog.WaitDialog
 import io.legato.kazusa.ui.widget.dialog.WaitDialog
+import io.legato.kazusa.utils.gone
 import io.legato.kazusa.utils.toastOnUi
 import io.legato.kazusa.utils.toastOnUi
+import io.legato.kazusa.utils.visible
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.Job
@@ -43,12 +45,6 @@ class WebDavFragment : BaseFragment(R.layout.fragment_webdav_auth) {
     private var restoreJob: Job? = null
     private var restoreJob: Job? = null
     private val waitDialog by lazy { WaitDialog(requireContext()) }
     private val waitDialog by lazy { WaitDialog(requireContext()) }
 
 
-    interface WebDavActions {
-        fun onSaveWebDavConfig()
-    }
-
-    var listener: WebDavActions? = null
-
     private val restoreDoc = registerForActivityResult(HandleFileContract()) {
     private val restoreDoc = registerForActivityResult(HandleFileContract()) {
         it.uri?.let { uri ->
         it.uri?.let { uri ->
             waitDialog.setText("恢复中…")
             waitDialog.setText("恢复中…")
@@ -102,28 +98,44 @@ class WebDavFragment : BaseFragment(R.layout.fragment_webdav_auth) {
         }
         }
 
 
         binding.btnCheck.setOnClickListener {
         binding.btnCheck.setOnClickListener {
-            saveWebDavConfig()
-
+            val config = WebDavConfig(
+                url = binding.editUrl.text.toString(),
+                account = binding.editAccount.text.toString(),
+                password = binding.editPassword.text.toString()
+            )
+            saveWebDavConfig(config)
             lifecycleScope.launch {
             lifecycleScope.launch {
                 testWebDav()
                 testWebDav()
             }
             }
         }
         }
 
 
         binding.btnRestore.setOnClickListener {
         binding.btnRestore.setOnClickListener {
-            restore()
+            val config = WebDavConfig(
+                url = binding.editUrl.text.toString(),
+                account = binding.editAccount.text.toString(),
+                password = binding.editPassword.text.toString()
+            )
+            lifecycleScope.launch {
+                try {
+                    binding.progressRestore.visible()
+                    binding.btnRestore.text = ""
+                    saveWebDavConfig(config)
+                    AppWebDav.upConfig()
+                    restore()
+                } finally {
+                    binding.progressRestore.gone()
+                    binding.btnRestore.text = "获取备份"
+                }
+            }
         }
         }
 
 
     }
     }
 
 
-    fun saveWebDavConfig(onSaved: (() -> Unit)? = null) {
-        val url = binding.editUrl.text.toString()
-        val account = binding.editAccount.text.toString()
-        val password = binding.editPassword.text.toString()
-
+    fun saveWebDavConfig(config: WebDavConfig, onSaved: (() -> Unit)? = null) {
         PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
         PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
-            putString(PreferKey.webDavUrl, url)
-            putString(PreferKey.webDavAccount, account)
-            putString(PreferKey.webDavPassword, password)
+            putString(PreferKey.webDavUrl, config.url)
+            putString(PreferKey.webDavAccount, config.account)
+            putString(PreferKey.webDavPassword, config.password)
         }
         }
 
 
         onSaved?.invoke()
         onSaved?.invoke()
@@ -205,6 +217,14 @@ class WebDavFragment : BaseFragment(R.layout.fragment_webdav_auth) {
 
 
     override fun onDestroyView() {
     override fun onDestroyView() {
         super.onDestroyView()
         super.onDestroyView()
+        waitDialog.dismiss() // 确保释放
         _binding = null
         _binding = null
     }
     }
+
 }
 }
+
+data class WebDavConfig(
+    val url: String,
+    val account: String,
+    val password: String
+)

+ 0 - 10
app/src/main/java/io/legato/kazusa/ui/welcome/WelcomeActivity.kt

@@ -17,8 +17,6 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
 
 
     override val binding by viewBinding(ActivityWelcomeBinding::inflate)
     override val binding by viewBinding(ActivityWelcomeBinding::inflate)
 
 
-    private val webDavFragment: WebDavFragment
-        get() = pages[1] as WebDavFragment
     private val pages = listOf(
     private val pages = listOf(
         PrivacyFragment(),
         PrivacyFragment(),
         WebDavFragment(),
         WebDavFragment(),
@@ -71,13 +69,6 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
         // 初始化按钮文字
         // 初始化按钮文字
         binding.btnNext.text = "阅读并同意"
         binding.btnNext.text = "阅读并同意"
 
 
-        (webDavFragment).listener = object : WebDavFragment.WebDavActions {
-            override fun onSaveWebDavConfig() {
-                webDavFragment.saveWebDavConfig()
-            }
-        }
-
-
         binding.btnNext.setOnClickListener {
         binding.btnNext.setOnClickListener {
             val current = binding.viewPager.currentItem
             val current = binding.viewPager.currentItem
             when (current) {
             when (current) {
@@ -92,7 +83,6 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
                 }
                 }
 
 
                 else -> {
                 else -> {
-                    webDavFragment.listener?.onSaveWebDavConfig()
                     binding.viewPager.currentItem = current + 1
                     binding.viewPager.currentItem = current + 1
                 }
                 }
             }
             }

+ 54 - 34
app/src/main/res/layout/fragment_privacy.xml

@@ -1,45 +1,65 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:orientation="vertical"
     android:orientation="vertical"
-    android:paddingHorizontal="16dp">
+    android:paddingHorizontal="16dp"
+    android:paddingBottom="8dp">
 
 
-    <LinearLayout
+    <androidx.core.widget.NestedScrollView
         android:layout_width="match_parent"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
 
 
-        <TextView
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="8dp"
-            android:text="@string/privacy_policy"
-            android:textColor="?attr/colorSecondary"
-            android:textSize="16sp"
-            android:textStyle="bold" />
-
-        <TextView
-            android:id="@+id/tvPrivacy"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="16dp"
-            android:text="@string/text" />
+            android:orientation="vertical">
 
 
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="8dp"
-            android:text="@string/disclaimer"
-            android:textColor="?attr/colorSecondary"
-            android:textSize="16sp"
-            android:textStyle="bold" />
-
-        <TextView
-            android:id="@+id/tvDisclaimer"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/text" />
-    </LinearLayout>
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="8dp"
+                android:text="@string/privacy_policy"
+                android:textColor="?attr/colorSecondary"
+                android:textSize="16sp"
+                android:textStyle="bold" />
+
+            <TextView
+                android:id="@+id/tvPrivacy"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="16dp"
+                android:text="@string/text" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="8dp"
+                android:text="@string/disclaimer"
+                android:textColor="?attr/colorSecondary"
+                android:textSize="16sp"
+                android:textStyle="bold" />
+
+            <TextView
+                android:id="@+id/tvDisclaimer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/text" />
+        </LinearLayout>
+
+    </androidx.core.widget.NestedScrollView>
+
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:src="@drawable/bg_gradient_mask"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
 
 
-</androidx.core.widget.NestedScrollView>
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 28 - 7
app/src/main/res/layout/fragment_webdav_auth.xml

@@ -56,20 +56,41 @@
         android:layout_height="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         android:orientation="horizontal">
 
 
-        <com.google.android.material.button.MaterialButton
-            android:id="@+id/btnRestore"
-            style="@style/Widget.Material3Expressive.Button.OutlinedButton"
-            android:layout_width="0dp"
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginEnd="16dp"
-            android:layout_weight="2"
-            android:text="获取备份" />
+            android:layout_marginEnd="8dp"
+            android:layout_weight="1">
+
+            <com.google.android.material.button.MaterialButton
+                android:id="@+id/btnRestore"
+                style="@style/Widget.Material3Expressive.Button.OutlinedButton"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="获取备份"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <com.google.android.material.loadingindicator.LoadingIndicator
+                android:id="@+id/progressRestore"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+        </androidx.constraintlayout.widget.ConstraintLayout>
 
 
         <com.google.android.material.button.MaterialButton
         <com.google.android.material.button.MaterialButton
             android:id="@+id/btnCheck"
             android:id="@+id/btnCheck"
             style="@style/Widget.Material3Expressive.Button.TonalButton"
             style="@style/Widget.Material3Expressive.Button.TonalButton"
             android:layout_width="0dp"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
             android:layout_weight="1"
             android:layout_weight="1"
             android:text="@string/action_save" />
             android:text="@string/action_save" />