修复初始化界面备份失败与NPE问题
This commit is contained in:
1 parent
98c2aa6d2b
commit
9b1c155f77
6 files changed
+143
-89
No files matched your search
@@ -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"
|
||||||
|
|||||||
@@ -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) ->
|
map.forEach { (key, value) ->
|
||||||
if (BackupConfig.keyIsNotIgnore(key)) {
|
if (BackupConfig.keyIsNotIgnore(key)) {
|
||||||
when (key) {
|
when (key) {
|
||||||
PreferKey.webDavPassword -> {
|
PreferKey.webDavPassword -> {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
aes.decryptStr(value.toString())
|
aes.decryptStr(value.toString())
|
||||||
}.getOrNull()?.let {
|
}.getOrNull()?.let {
|
||||||
edit.putString(key, it)
|
putString(key, it)
|
||||||
} ?: let {
|
} ?: let {
|
||||||
if (appCtx.getPrefString(PreferKey.webDavPassword)
|
if (appCtx.getPrefString(PreferKey.webDavPassword)
|
||||||
.isNullOrBlank()
|
.isNullOrBlank()
|
||||||
) {
|
) {
|
||||||
edit.putString(key, value.toString())
|
putString(key, value.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else -> when (value) {
|
else -> when (value) {
|
||||||
is Int -> edit.putInt(key, value)
|
is Int -> putInt(key, value)
|
||||||
is Boolean -> edit.putBoolean(key, value)
|
is Boolean -> putBoolean(key, value)
|
||||||
is Long -> edit.putLong(key, value)
|
is Long -> putLong(key, value)
|
||||||
is Float -> edit.putFloat(key, value)
|
is Float -> putFloat(key, value)
|
||||||
is String -> edit.putString(key, value)
|
is String -> putString(key, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
edit.apply()
|
|
||||||
}
|
}
|
||||||
ReadBookConfig.apply {
|
ReadBookConfig.apply {
|
||||||
comicStyleSelect = appCtx.getPrefInt(PreferKey.comicStyleSelect)
|
comicStyleSelect = appCtx.getPrefInt(PreferKey.comicStyleSelect)
|
||||||
|
|||||||
@@ -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) {
|
fun saveWebDavConfig(config: WebDavConfig, onSaved: (() -> Unit)? = null) {
|
||||||
val url = binding.editUrl.text.toString()
|
|
||||||
val account = binding.editAccount.text.toString()
|
|
||||||
val password = binding.editPassword.text.toString()
|
|
||||||
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
|
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
|
||||||
putString(PreferKey.webDavUrl, url)
|
putString(PreferKey.webDavUrl, config.url)
|
||||||
putString(PreferKey.webDavAccount, account)
|
putString(PreferKey.webDavAccount, config.account)
|
||||||
putString(PreferKey.webDavPassword, password)
|
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
|
||||||
|
)
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
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:orientation="vertical">
|
||||||
android:text="@string/privacy_policy"
|
|
||||||
android:textColor="?attr/colorSecondary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvPrivacy"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:text="@string/privacy_policy"
|
||||||
android:text="@string/text" />
|
android:textColor="?attr/colorSecondary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/tvPrivacy"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/disclaimer"
|
android:layout_marginBottom="16dp"
|
||||||
android:textColor="?attr/colorSecondary"
|
android:text="@string/text" />
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvDisclaimer"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginBottom="8dp"
|
||||||
android:text="@string/text" />
|
android:text="@string/disclaimer"
|
||||||
</LinearLayout>
|
android:textColor="?attr/colorSecondary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
<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.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -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
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/btnRestore"
|
android:layout_width="wrap_content"
|
||||||
style="@style/Widget.Material3Expressive.Button.OutlinedButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_weight="2"
|
android:layout_weight="1">
|
||||||
android:text="获取备份" />
|
|
||||||
|
<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" />
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user