本地书籍无权限则保存到自己选定的文件夹

pull/1486/head
gedoor 4 years ago
parent 448e25c04d
commit c3295483e4
  1. 1
      app/src/main/AndroidManifest.xml
  2. 1
      app/src/main/java/io/legado/app/constant/PreferKey.kt
  3. 10
      app/src/main/java/io/legado/app/help/AppConfig.kt
  4. 90
      app/src/main/java/io/legado/app/help/BookMediaStore.kt
  5. 16
      app/src/main/java/io/legado/app/help/storage/Backup.kt
  6. 83
      app/src/main/java/io/legado/app/help/storage/BackupRestore.kt
  7. 70
      app/src/main/java/io/legado/app/help/storage/Restore.kt
  8. 2
      app/src/main/java/io/legado/app/lib/permission/Permissions.kt
  9. 1
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  10. 81
      app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt
  11. 52
      app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt
  12. 14
      app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt

@ -4,6 +4,7 @@
package="io.legado.app"> package="io.legado.app">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />

@ -90,6 +90,7 @@ object PreferKey {
const val expandTextMenu = "expandTextMenu" const val expandTextMenu = "expandTextMenu"
const val doublePageHorizontal = "doublePageHorizontal" const val doublePageHorizontal = "doublePageHorizontal"
const val readUrlOpenInBrowser = "readUrlInBrowser" const val readUrlOpenInBrowser = "readUrlInBrowser"
const val defaultBookTreeUri = "defaultBookTreeUri"
const val cPrimary = "colorPrimary" const val cPrimary = "colorPrimary"
const val cAccent = "colorAccent" const val cAccent = "colorAccent"

@ -133,6 +133,16 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
} }
} }
var defaultBookTreeUri: String?
get() = appCtx.getPrefString(PreferKey.defaultBookTreeUri)
set(value) {
if (value.isNullOrEmpty()) {
appCtx.removePref(PreferKey.defaultBookTreeUri)
} else {
appCtx.putPrefString(PreferKey.defaultBookTreeUri, value)
}
}
val showDiscovery: Boolean val showDiscovery: Boolean
get() = appCtx.getPrefBoolean(PreferKey.showDiscovery, true) get() = appCtx.getPrefBoolean(PreferKey.showDiscovery, true)

@ -1,90 +0,0 @@
package io.legado.app.help
import android.content.ContentUris
import android.content.ContentValues
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
import io.legado.app.constant.AppConst
import io.legado.app.utils.FileDoc
import io.legado.app.utils.FileUtils.getMimeType
import splitties.init.appCtx
import java.io.File
import java.util.*
object BookMediaStore {
private val DOWNLOAD_DIR =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
fun insertBook(doc: DocumentFile): Uri? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val bookDetails = ContentValues().apply {
put(MediaStore.Downloads.RELATIVE_PATH, "Download${File.separator}books")
put(MediaStore.MediaColumns.DISPLAY_NAME, doc.name)
put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(doc.name!!))
put(MediaStore.MediaColumns.SIZE, doc.length())
}
appCtx.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, bookDetails)
} else {
val destinyFile = File(DOWNLOAD_DIR, doc.name!!)
FileProvider.getUriForFile(appCtx, AppConst.authority, destinyFile)
}?.also { uri ->
appCtx.contentResolver.openOutputStream(uri).use { outputStream ->
val brr = ByteArray(1024)
var len: Int
val bufferedInputStream = appCtx.contentResolver.openInputStream(doc.uri)!!
while ((bufferedInputStream.read(brr, 0, brr.size).also { len = it }) != -1) {
outputStream?.write(brr, 0, len)
}
outputStream?.flush()
bufferedInputStream.close()
}
}
}
fun getBook(name: String): FileDoc? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val projection = arrayOf(
MediaStore.Downloads._ID,
MediaStore.Downloads.DISPLAY_NAME,
MediaStore.Downloads.SIZE,
MediaStore.Downloads.DATE_MODIFIED
)
val selection =
"${MediaStore.Downloads.RELATIVE_PATH} like 'Download${File.separator}books${File.separator}%'"
val sortOrder = "${MediaStore.Downloads.DISPLAY_NAME} ASC"
appCtx.contentResolver.query(
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
projection,
selection,
emptyArray(),
sortOrder
)?.use {
val idColumn = it.getColumnIndex(projection[0])
val nameColumn = it.getColumnIndex(projection[1])
val sizeColumn = it.getColumnIndex(projection[2])
val dateColumn = it.getColumnIndex(projection[3])
if (it.moveToNext()) {
val id = it.getLong(idColumn)
return FileDoc(
name = it.getString(nameColumn),
isDir = false,
size = it.getLong(sizeColumn),
date = Date(it.getLong(dateColumn)),
uri = ContentUris.withAppendedId(
MediaStore.Downloads.EXTERNAL_CONTENT_URI,
id
)
)
}
}
}
return null
}
}

@ -20,7 +20,7 @@ import java.io.FileOutputStream
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
object Backup { object Backup : BackupRestore() {
val backupPath: String by lazy { val backupPath: String by lazy {
appCtx.filesDir.getFile("backup").absolutePath appCtx.filesDir.getFile("backup").absolutePath
@ -90,12 +90,14 @@ object Backup {
Preferences.getSharedPreferences(appCtx, backupPath, "config")?.let { sp -> Preferences.getSharedPreferences(appCtx, backupPath, "config")?.let { sp ->
val edit = sp.edit() val edit = sp.edit()
appCtx.defaultSharedPreferences.all.forEach { (key, value) -> appCtx.defaultSharedPreferences.all.forEach { (key, value) ->
when (value) { if (keyIsNotIgnore(key)) {
is Int -> edit.putInt(key, value) when (value) {
is Boolean -> edit.putBoolean(key, value) is Int -> edit.putInt(key, value)
is Long -> edit.putLong(key, value) is Boolean -> edit.putBoolean(key, value)
is Float -> edit.putFloat(key, value) is Long -> edit.putLong(key, value)
is String -> edit.putString(key, value) is Float -> edit.putFloat(key, value)
is String -> edit.putString(key, value)
}
} }
} }
edit.commit() edit.commit()

@ -0,0 +1,83 @@
package io.legado.app.help.storage
import io.legado.app.R
import io.legado.app.constant.PreferKey
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import splitties.init.appCtx
abstract class BackupRestore {
private val ignoreConfigPath = FileUtils.getPath(appCtx.filesDir, "restoreIgnore.json")
val ignoreConfig: HashMap<String, Boolean> by lazy {
val file = FileUtils.createFileIfNotExist(ignoreConfigPath)
val json = file.readText()
GSON.fromJsonObject<HashMap<String, Boolean>>(json) ?: hashMapOf()
}
//忽略key
val ignoreKeys = arrayOf(
"readConfig",
PreferKey.themeMode,
PreferKey.bookshelfLayout,
PreferKey.showRss,
PreferKey.threadCount,
PreferKey.defaultBookTreeUri
)
//忽略标题
val ignoreTitle = arrayOf(
appCtx.getString(R.string.read_config),
appCtx.getString(R.string.theme_mode),
appCtx.getString(R.string.bookshelf_layout),
appCtx.getString(R.string.show_rss),
appCtx.getString(R.string.thread_count)
)
//默认忽略keys
private val ignorePrefKeys = arrayOf(
PreferKey.themeMode,
PreferKey.defaultCover,
PreferKey.defaultCoverDark
)
//阅读配置
private val readPrefKeys = arrayOf(
PreferKey.readStyleSelect,
PreferKey.shareLayout,
PreferKey.hideStatusBar,
PreferKey.hideNavigationBar,
PreferKey.autoReadSpeed
)
protected fun keyIsNotIgnore(key: String): Boolean {
return when {
ignorePrefKeys.contains(key) -> false
readPrefKeys.contains(key) && ignoreReadConfig -> false
PreferKey.themeMode == key && ignoreThemeMode -> false
PreferKey.bookshelfLayout == key && ignoreBookshelfLayout -> false
PreferKey.showRss == key && ignoreShowRss -> false
PreferKey.threadCount == key && ignoreThreadCount -> false
else -> true
}
}
protected val ignoreReadConfig: Boolean
get() = ignoreConfig["readConfig"] == true
private val ignoreThemeMode: Boolean
get() = ignoreConfig[PreferKey.themeMode] == true
private val ignoreBookshelfLayout: Boolean
get() = ignoreConfig[PreferKey.bookshelfLayout] == true
private val ignoreShowRss: Boolean
get() = ignoreConfig[PreferKey.showRss] == true
private val ignoreThreadCount: Boolean
get() = ignoreConfig[PreferKey.threadCount] == true
fun saveIgnoreConfig() {
val json = GSON.toJson(ignoreConfig)
FileUtils.createFileIfNotExist(ignoreConfigPath).writeText(json)
}
}

@ -24,47 +24,7 @@ import timber.log.Timber
import java.io.File import java.io.File
object Restore { object Restore : BackupRestore() {
private val ignoreConfigPath = FileUtils.getPath(appCtx.filesDir, "restoreIgnore.json")
val ignoreConfig: HashMap<String, Boolean> by lazy {
val file = FileUtils.createFileIfNotExist(ignoreConfigPath)
val json = file.readText()
GSON.fromJsonObject<HashMap<String, Boolean>>(json) ?: hashMapOf()
}
//忽略key
val ignoreKeys = arrayOf(
"readConfig",
PreferKey.themeMode,
PreferKey.bookshelfLayout,
PreferKey.showRss,
PreferKey.threadCount
)
//忽略标题
val ignoreTitle = arrayOf(
appCtx.getString(R.string.read_config),
appCtx.getString(R.string.theme_mode),
appCtx.getString(R.string.bookshelf_layout),
appCtx.getString(R.string.show_rss),
appCtx.getString(R.string.thread_count)
)
//默认忽略keys
private val ignorePrefKeys = arrayOf(
PreferKey.themeMode,
PreferKey.defaultCover,
PreferKey.defaultCoverDark
)
//阅读配置
private val readPrefKeys = arrayOf(
PreferKey.readStyleSelect,
PreferKey.shareLayout,
PreferKey.hideStatusBar,
PreferKey.hideNavigationBar,
PreferKey.autoReadSpeed
)
suspend fun restore(context: Context, path: String) { suspend fun restore(context: Context, path: String) {
withContext(IO) { withContext(IO) {
@ -229,34 +189,6 @@ object Restore {
} }
} }
private fun keyIsNotIgnore(key: String): Boolean {
return when {
ignorePrefKeys.contains(key) -> false
readPrefKeys.contains(key) && ignoreReadConfig -> false
PreferKey.themeMode == key && ignoreThemeMode -> false
PreferKey.bookshelfLayout == key && ignoreBookshelfLayout -> false
PreferKey.showRss == key && ignoreShowRss -> false
PreferKey.threadCount == key && ignoreThreadCount -> false
else -> true
}
}
private val ignoreReadConfig: Boolean
get() = ignoreConfig["readConfig"] == true
private val ignoreThemeMode: Boolean
get() = ignoreConfig[PreferKey.themeMode] == true
private val ignoreBookshelfLayout: Boolean
get() = ignoreConfig[PreferKey.bookshelfLayout] == true
private val ignoreShowRss: Boolean
get() = ignoreConfig[PreferKey.showRss] == true
private val ignoreThreadCount: Boolean
get() = ignoreConfig[PreferKey.threadCount] == true
fun saveIgnoreConfig() {
val json = GSON.toJson(ignoreConfig)
FileUtils.createFileIfNotExist(ignoreConfigPath).writeText(json)
}
private inline fun <reified T> fileToListT(path: String, fileName: String): List<T>? { private inline fun <reified T> fileToListT(path: String, fileName: String): List<T>? {
try { try {
val file = FileUtils.createFileIfNotExist(path + File.separator + fileName) val file = FileUtils.createFileIfNotExist(path + File.separator + fileName)

@ -36,6 +36,8 @@ object Permissions {
const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE" const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"
const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE" const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"
const val ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION"
object Group { object Group {
val STORAGE = arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE) val STORAGE = arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE)

@ -20,6 +20,7 @@ import java.util.regex.Pattern
import javax.script.SimpleBindings import javax.script.SimpleBindings
object LocalBook { object LocalBook {
private const val folderName = "bookTxt" private const val folderName = "bookTxt"
val cacheFolder: File by lazy { val cacheFolder: File by lazy {
FileUtils.createFolderIfNotExist(appCtx.externalFiles, folderName) FileUtils.createFolderIfNotExist(appCtx.externalFiles, folderName)

@ -1,25 +1,60 @@
package io.legado.app.ui.association package io.legado.app.ui.association
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.documentfile.provider.DocumentFile
import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivityTranslucenceBinding import io.legado.app.databinding.ActivityTranslucenceBinding
import io.legado.app.help.AppConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.permission.Permissions
import io.legado.app.lib.permission.PermissionsCompat
import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.utils.showDialogFragment import io.legado.app.ui.document.HandleFileContract
import io.legado.app.utils.startActivity import io.legado.app.utils.*
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class FileAssociationActivity : class FileAssociationActivity :
VMBaseActivity<ActivityTranslucenceBinding, FileAssociationViewModel>() { VMBaseActivity<ActivityTranslucenceBinding, FileAssociationViewModel>() {
private val localBookTreeSelect = registerForActivityResult(HandleFileContract()) {
it.uri?.let { treeUri ->
intent.data?.let { uri ->
importBook(treeUri, uri)
}
}
}
override val binding by viewBinding(ActivityTranslucenceBinding::inflate) override val binding by viewBinding(ActivityTranslucenceBinding::inflate)
override val viewModel by viewModels<FileAssociationViewModel>() override val viewModel by viewModels<FileAssociationViewModel>()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
binding.rotateLoading.show() binding.rotateLoading.show()
viewModel.importBookLiveData.observe(this) { uri ->
if (uri.isContentScheme()) {
val treeUriStr = AppConfig.defaultBookTreeUri
if (treeUriStr.isNullOrEmpty()) {
localBookTreeSelect.launch {
title = "选择保存书籍的文件夹"
}
} else {
importBook(Uri.parse(treeUriStr), uri)
}
} else {
PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage)
.onGranted {
viewModel.importBook(uri)
}.request()
}
}
viewModel.onLineImportLive.observe(this) { viewModel.onLineImportLive.observe(this) {
startActivity<OnLineImportActivity> { startActivity<OnLineImportActivity> {
data = it data = it
@ -38,23 +73,55 @@ class FileAssociationActivity :
binding.rotateLoading.hide() binding.rotateLoading.hide()
showDialogFragment(ImportReplaceRuleDialog(it, true)) showDialogFragment(ImportReplaceRuleDialog(it, true))
} }
viewModel.errorLiveData.observe(this, { viewModel.errorLiveData.observe(this) {
binding.rotateLoading.hide() binding.rotateLoading.hide()
toastOnUi(it) toastOnUi(it)
finish() finish()
}) }
viewModel.openBookLiveData.observe(this, { viewModel.openBookLiveData.observe(this) {
binding.rotateLoading.hide() binding.rotateLoading.hide()
startActivity<ReadBookActivity> { startActivity<ReadBookActivity> {
putExtra("bookUrl", it) putExtra("bookUrl", it)
} }
finish() finish()
}) }
intent.data?.let { data -> intent.data?.let { data ->
viewModel.dispatchIndent(data, this::finallyDialog) viewModel.dispatchIndent(data, this::finallyDialog)
} }
} }
private fun importBook(treeUri: Uri, uri: Uri) {
val treeDoc = DocumentFile.fromTreeUri(this, treeUri)
val bookDoc = DocumentFile.fromSingleUri(this, uri)
launch {
runCatching {
withContext(IO) {
val name = bookDoc?.name!!
val doc = treeDoc!!.findFile(name)
if (doc != null) {
viewModel.importBook(doc.uri)
} else {
val nDoc = treeDoc.createFile(FileUtils.getMimeType(name), name)!!
contentResolver.openOutputStream(nDoc.uri)!!.use { oStream ->
contentResolver.openInputStream(bookDoc.uri)!!.use { iStream ->
val brr = ByteArray(1024)
var len: Int
while ((iStream.read(brr, 0, brr.size)
.also { len = it }) != -1
) {
oStream.write(brr, 0, len)
}
oStream.flush()
}
}
}
}
}.onFailure {
toastOnUi(it.localizedMessage)
}
}
}
private fun finallyDialog(title: String, msg: String) { private fun finallyDialog(title: String, msg: String) {
alert(title, msg) { alert(title, msg) {
okButton() okButton()

@ -1,30 +1,24 @@
package io.legado.app.ui.association package io.legado.app.ui.association
import android.app.Application import android.app.Application
import android.app.RecoverableSecurityException
import android.content.IntentSender
import android.net.Uri import android.net.Uri
import android.os.Build
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import io.legado.app.help.BookMediaStore
import io.legado.app.model.NoStackTraceException import io.legado.app.model.NoStackTraceException
import io.legado.app.model.localBook.LocalBook import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.isContentScheme
import io.legado.app.utils.isJson import io.legado.app.utils.isJson
import io.legado.app.utils.readText import io.legado.app.utils.readText
import splitties.init.appCtx
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
class FileAssociationViewModel(application: Application) : BaseAssociationViewModel(application) { class FileAssociationViewModel(application: Application) : BaseAssociationViewModel(application) {
val importBookLiveData = MutableLiveData<Uri>()
val onLineImportLive = MutableLiveData<Uri>() val onLineImportLive = MutableLiveData<Uri>()
val importBookSourceLive = MutableLiveData<String>() val importBookSourceLive = MutableLiveData<String>()
val importRssSourceLive = MutableLiveData<String>() val importRssSourceLive = MutableLiveData<String>()
val importReplaceRuleLive = MutableLiveData<String>() val importReplaceRuleLive = MutableLiveData<String>()
val openBookLiveData = MutableLiveData<String>() val openBookLiveData = MutableLiveData<String>()
val errorLiveData = MutableLiveData<String>() val errorLiveData = MutableLiveData<String>()
val recoverErrorLiveData = MutableLiveData<IntentSender>()
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
fun dispatchIndent(uri: Uri, finally: (title: String, msg: String) -> Unit) { fun dispatchIndent(uri: Uri, finally: (title: String, msg: String) -> Unit) {
@ -54,51 +48,19 @@ class FileAssociationViewModel(application: Application) : BaseAssociationViewMo
else -> errorLiveData.postValue("格式不对") else -> errorLiveData.postValue("格式不对")
} }
} else { } else {
if (uri.isContentScheme()) { importBookLiveData.postValue(uri)
val doc = DocumentFile.fromSingleUri(appCtx, uri)!!
val bookDoc = BookMediaStore.getBook(doc.name!!)
if (bookDoc == null) {
val bookUri = BookMediaStore.insertBook(doc)
val book = LocalBook.importFile(bookUri!!)
openBookLiveData.postValue(book.bookUrl)
} else {
if (doc.lastModified() > bookDoc.date.time) {
context.contentResolver.openOutputStream(bookDoc.uri)
.use { outputStream ->
val brr = ByteArray(1024)
var len: Int
val bufferedInputStream =
appCtx.contentResolver.openInputStream(doc.uri)!!
while ((bufferedInputStream.read(brr, 0, brr.size)
.also { len = it }) != -1
) {
outputStream?.write(brr, 0, len)
}
outputStream?.flush()
bufferedInputStream.close()
}
}
val book = LocalBook.importFile(bookDoc.uri)
openBookLiveData.postValue(book.bookUrl)
}
} else {
val book = LocalBook.importFile(uri)
openBookLiveData.postValue(book.bookUrl)
}
} }
} else { } else {
onLineImportLive.postValue(uri) onLineImportLive.postValue(uri)
} }
}.onError { }.onError {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (it is RecoverableSecurityException) {
val intentSender = it.userAction.actionIntent.intentSender
recoverErrorLiveData.postValue(intentSender)
return@onError
}
}
Timber.e(it) Timber.e(it)
errorLiveData.postValue(it.localizedMessage) errorLiveData.postValue(it.localizedMessage)
} }
} }
fun importBook(uri: Uri) {
val book = LocalBook.importFile(uri)
openBookLiveData.postValue(book.bookUrl)
}
} }

@ -207,7 +207,7 @@ class BackupConfigFragment : BasePreferenceFragment(),
override fun onPreferenceTreeClick(preference: Preference?): Boolean { override fun onPreferenceTreeClick(preference: Preference?): Boolean {
when (preference?.key) { when (preference?.key) {
PreferKey.backupPath -> selectBackupPath.launch() PreferKey.backupPath -> selectBackupPath.launch()
PreferKey.restoreIgnore -> restoreIgnore() PreferKey.restoreIgnore -> backupIgnore()
"web_dav_backup" -> backup() "web_dav_backup" -> backup()
"web_dav_restore" -> restore() "web_dav_restore" -> restore()
"import_old" -> restoreOld.launch() "import_old" -> restoreOld.launch()
@ -216,16 +216,16 @@ class BackupConfigFragment : BasePreferenceFragment(),
} }
private fun restoreIgnore() { private fun backupIgnore() {
val checkedItems = BooleanArray(Restore.ignoreKeys.size) { val checkedItems = BooleanArray(Backup.ignoreKeys.size) {
Restore.ignoreConfig[Restore.ignoreKeys[it]] ?: false Backup.ignoreConfig[Backup.ignoreKeys[it]] ?: false
} }
alert(R.string.restore_ignore) { alert(R.string.restore_ignore) {
multiChoiceItems(Restore.ignoreTitle, checkedItems) { _, which, isChecked -> multiChoiceItems(Backup.ignoreTitle, checkedItems) { _, which, isChecked ->
Restore.ignoreConfig[Restore.ignoreKeys[which]] = isChecked Backup.ignoreConfig[Backup.ignoreKeys[which]] = isChecked
} }
onDismiss { onDismiss {
Restore.saveIgnoreConfig() Backup.saveIgnoreConfig()
} }
} }
} }

Loading…
Cancel
Save