优化导入,导入时增加确认

pull/306/head
gedoor 4 years ago
parent 5810596e41
commit 92b9a6e1cd
  1. 85
      app/src/main/AndroidManifest.xml
  2. 24
      app/src/main/java/io/legado/app/base/BaseActivity.kt
  3. 2
      app/src/main/java/io/legado/app/constant/Theme.kt
  4. 16
      app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
  5. 16
      app/src/main/java/io/legado/app/help/storage/OldReplace.kt
  6. 10
      app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt
  7. 2
      app/src/main/java/io/legado/app/ui/association/FileAssociationViewModel.kt
  8. 80
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt
  9. 105
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt
  10. 80
      app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt
  11. 64
      app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleViewModel.kt
  12. 80
      app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt
  13. 96
      app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt
  14. 53
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  15. 103
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt
  16. 50
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt
  17. 51
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt
  18. 54
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  19. 96
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceViewModel.kt
  20. 5
      app/src/main/res/layout/activity_translucence.xml

@ -199,47 +199,15 @@
<!-- 书源管理 -->
<activity
android:name=".ui.book.source.manage.BookSourceActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="booksource"
android:scheme="yuedu" />
</intent-filter>
</activity>
android:launchMode="singleTop" />
<!-- 订阅源管理 -->
<activity
android:name=".ui.rss.source.manage.RssSourceActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="rsssource"
android:scheme="yuedu" />
</intent-filter>
</activity>
android:launchMode="singleTop" />
<!-- 替换规则界面 -->
<activity
android:name=".ui.replacerule.ReplaceRuleActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="replace"
android:scheme="yuedu" />
</intent-filter>
</activity>
<!-- 书籍管理 -->
<activity
@ -308,8 +276,55 @@
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<!-- 导入书源 -->
<activity
android:name=".ui.association.ImportBookSourceActivity"
android:theme="@style/AppTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="booksource"
android:scheme="yuedu" />
</intent-filter>
</activity>
<!-- 导入订阅源 -->
<activity
android:name=".ui.association.ImportRssSourceActivity"
android:theme="@style/AppTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="rsssource"
android:scheme="yuedu" />
</intent-filter>
</activity>
<!-- 导入替换规则 -->
<activity
android:name=".ui.association.ImportReplaceRuleActivity"
android:theme="@style/AppTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="replace"
android:scheme="yuedu" />
</intent-filter>
</activity>
<!-- 打开文件 -->
<activity
android:name=".ui.config.FileAssociationActivity"
android:name=".ui.association.FileAssociationActivity"
android:theme="@style/AppTheme.Transparent"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />

@ -24,7 +24,8 @@ import kotlinx.coroutines.cancel
abstract class BaseActivity(
private val layoutID: Int,
private val fullScreen: Boolean = true,
private val theme: Theme = Theme.Auto
private val theme: Theme = Theme.Auto,
private val transparent: Boolean = false
) : AppCompatActivity(),
CoroutineScope by MainScope() {
@ -92,14 +93,23 @@ abstract class BaseActivity(
}
private fun initTheme() {
ATH.applyBackgroundTint(window.decorView)
when (theme) {
Theme.Dark -> setTheme(R.style.AppTheme_Dark)
Theme.Light -> setTheme(R.style.AppTheme_Light)
else -> if (ColorUtils.isColorLight(primaryColor)) {
setTheme(R.style.AppTheme_Light)
} else {
Theme.Transparent -> setTheme(R.style.AppTheme_Transparent)
Theme.Dark -> {
setTheme(R.style.AppTheme_Dark)
ATH.applyBackgroundTint(window.decorView)
}
Theme.Light -> {
setTheme(R.style.AppTheme_Light)
ATH.applyBackgroundTint(window.decorView)
}
else -> {
if (ColorUtils.isColorLight(primaryColor)) {
setTheme(R.style.AppTheme_Light)
} else {
setTheme(R.style.AppTheme_Dark)
}
ATH.applyBackgroundTint(window.decorView)
}
}
}

@ -3,7 +3,7 @@ package io.legado.app.constant
import io.legado.app.help.AppConfig
enum class Theme {
Dark, Light, Auto;
Dark, Light, Auto, Transparent;
companion object {
fun getTheme(): Theme {

@ -5,7 +5,6 @@ import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import io.legado.app.App
import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.utils.DocumentUtils
import io.legado.app.utils.FileUtils
import org.jetbrains.anko.toast
@ -102,17 +101,8 @@ object ImportOldData {
}
fun importOldReplaceRule(json: String): Int {
val replaceRules = mutableListOf<ReplaceRule>()
val items: List<Map<String, Any>> = Restore.jsonPath.parse(json).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
OldReplace.jsonToReplaceRule(jsonItem.jsonString())?.let {
if (it.isValid()){
replaceRules.add(it)
}
}
}
App.db.replaceRuleDao().insert(*replaceRules.toTypedArray())
return replaceRules.size
val rules = OldReplace.jsonToReplaceRules(json)
App.db.replaceRuleDao().insert(*rules.toTypedArray())
return rules.size
}
}

@ -5,7 +5,21 @@ import io.legado.app.utils.*
object OldReplace {
fun jsonToReplaceRule(json: String): ReplaceRule? {
fun jsonToReplaceRules(json: String): List<ReplaceRule> {
val replaceRules = mutableListOf<ReplaceRule>()
val items: List<Map<String, Any>> = Restore.jsonPath.parse(json).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
jsonToReplaceRule(jsonItem.jsonString())?.let {
if (it.isValid()) {
replaceRules.add(it)
}
}
}
return replaceRules
}
private fun jsonToReplaceRule(json: String): ReplaceRule? {
var replaceRule: ReplaceRule? = null
runCatching {
replaceRule = GSON.fromJsonObject<ReplaceRule>(json.trim())

@ -1,15 +1,19 @@
package io.legado.app.ui.config
package io.legado.app.ui.association
import android.content.Intent
import android.os.Bundle
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme
import io.legado.app.ui.main.MainActivity
import io.legado.app.utils.getViewModel
class FileAssociationActivity :
VMBaseActivity<FileAssociationViewModel>(R.layout.activity_file_association) {
class FileAssociationActivity : VMBaseActivity<FileAssociationViewModel>(
R.layout.activity_translucence,
theme = Theme.Transparent
) {
override val viewModel: FileAssociationViewModel
get() = getViewModel(FileAssociationViewModel::class.java)

@ -1,4 +1,4 @@
package io.legado.app.ui.config
package io.legado.app.ui.association
import android.app.Application
import android.content.Intent

@ -0,0 +1,80 @@
package io.legado.app.ui.association
import android.os.Bundle
import androidx.lifecycle.Observer
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme
import io.legado.app.data.entities.BookSource
import io.legado.app.help.SourceHelp
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
import io.legado.app.utils.applyTint
import io.legado.app.utils.getViewModel
import org.jetbrains.anko.toast
class ImportBookSourceActivity : VMBaseActivity<ImportBookSourceViewModel>(
R.layout.activity_translucence,
theme = Theme.Transparent
) {
override val viewModel: ImportBookSourceViewModel
get() = getViewModel(ImportBookSourceViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.errorLiveData.observe(this, Observer {
errorDialog(it)
})
viewModel.successLiveData.observe(this, Observer {
successDialog(it)
})
initData()
}
private fun initData() {
intent.getStringExtra("source")?.let {
viewModel.importSource(it)
return
}
intent.getStringExtra("filePath")?.let {
viewModel.importSourceFromFilePath(it)
return
}
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
if (url.startsWith("http", false)) {
viewModel.importSource(url)
} else {
viewModel.importSourceFromFilePath(url)
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun errorDialog(msg: String) {
alert("导入出错", msg) {
okButton { }
}.show().applyTint().setOnDismissListener {
finish()
}
}
private fun successDialog(allSource: ArrayList<BookSource>) {
alert("解析结果", "${allSource.size}个书源,是否确认导入?") {
okButton {
SourceHelp.insertBookSource(*allSource.toTypedArray())
}
noButton {
}
}.show().applyTint().setOnDismissListener {
finish()
}
}
}

@ -0,0 +1,105 @@
package io.legado.app.ui.association
import android.app.Application
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData
import com.jayway.jsonpath.JsonPath
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.BookSource
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.OldRule
import io.legado.app.help.storage.Restore
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
val errorLiveData = MutableLiveData<String>()
val successLiveData = MutableLiveData<ArrayList<BookSource>>()
private val allSources = arrayListOf<BookSource>()
fun importSourceFromFilePath(path: String) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (content != null) {
importSource(content)
} else {
withContext(Dispatchers.Main) {
errorLiveData.postValue("打开文件出错")
}
}
}.onError {
errorLiveData.postValue(it.localizedMessage ?: "打开文件出错")
}
}
fun importSource(text: String) {
execute {
val text1 = text.trim()
when {
text1.isJsonObject() -> {
val json = JsonPath.parse(text1)
val urls = json.read<List<String>>("$.sourceUrls")
if (!urls.isNullOrEmpty()) {
urls.forEach {
importSourceUrl(it)
}
} else {
OldRule.jsonToBookSource(text1)?.let {
allSources.add(it)
}
}
}
text1.isJsonArray() -> {
val items: List<Map<String, Any>> = Restore.jsonPath.parse(text1).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let {
allSources.add(it)
}
}
}
text1.isAbsUrl() -> {
importSourceUrl(text1)
}
else -> throw Exception("格式不对")
}
}.onError {
it.printStackTrace()
errorLiveData.postValue(it.localizedMessage ?: "")
}.onSuccess {
successLiveData.postValue(allSources)
}
}
private fun importSourceUrl(url: String) {
HttpHelper.simpleGet(url, "UTF-8").let { body ->
if (body == null) {
throw Exception("访问网站失败")
}
val items: List<Map<String, Any>> = Restore.jsonPath.parse(body).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let { source ->
allSources.add(source)
}
}
}
}
}

@ -0,0 +1,80 @@
package io.legado.app.ui.association
import android.os.Bundle
import androidx.lifecycle.Observer
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
import io.legado.app.utils.applyTint
import io.legado.app.utils.getViewModel
import org.jetbrains.anko.toast
class ImportReplaceRuleActivity : VMBaseActivity<ImportReplaceRuleViewModel>(
R.layout.activity_translucence,
theme = Theme.Transparent
) {
override val viewModel: ImportReplaceRuleViewModel
get() = getViewModel(ImportReplaceRuleViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.errorLiveData.observe(this, Observer {
errorDialog(it)
})
viewModel.successLiveData.observe(this, Observer {
successDialog(it)
})
initData()
}
private fun initData() {
intent.getStringExtra("source")?.let {
viewModel.import(it)
return
}
intent.getStringExtra("filePath")?.let {
viewModel.importFromFilePath(it)
return
}
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
if (url.startsWith("http", false)) {
viewModel.import(url)
} else {
viewModel.importFromFilePath(url)
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun errorDialog(msg: String) {
alert("导入出错", msg) {
okButton { }
}.show().applyTint().setOnDismissListener {
finish()
}
}
private fun successDialog(allSource: ArrayList<ReplaceRule>) {
alert("解析结果", "${allSource.size}个替换规则,是否确认导入?") {
okButton {
App.db.replaceRuleDao().insert(*allSource.toTypedArray())
}
noButton {
}
}.show().applyTint().setOnDismissListener {
finish()
}
}
}

@ -0,0 +1,64 @@
package io.legado.app.ui.association
import android.app.Application
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData
import io.legado.app.R
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.OldReplace
import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.isContentPath
import io.legado.app.utils.readText
import java.io.File
class ImportReplaceRuleViewModel(app: Application) : BaseViewModel(app) {
val errorLiveData = MutableLiveData<String>()
val successLiveData = MutableLiveData<ArrayList<ReplaceRule>>()
private val allRules = arrayListOf<ReplaceRule>()
fun importFromFilePath(path: String) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (content != null) {
import(content)
} else {
errorLiveData.postValue("打开文件出错")
}
}.onError {
errorLiveData.postValue(it.localizedMessage ?: "打开文件出错")
}
}
fun import(text: String) {
execute {
if (text.isAbsUrl()) {
HttpHelper.simpleGet(text)?.let {
val rules = OldReplace.jsonToReplaceRules(it)
allRules.addAll(rules)
}
} else {
val rules = OldReplace.jsonToReplaceRules(text)
allRules.addAll(rules)
}
}.onError {
errorLiveData.postValue(it.localizedMessage ?: "ERROR")
}.onSuccess {
errorLiveData.postValue(context.getString(R.string.success))
}
}
}

@ -0,0 +1,80 @@
package io.legado.app.ui.association
import android.os.Bundle
import androidx.lifecycle.Observer
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme
import io.legado.app.data.entities.RssSource
import io.legado.app.help.SourceHelp
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
import io.legado.app.utils.applyTint
import io.legado.app.utils.getViewModel
import org.jetbrains.anko.toast
class ImportRssSourceActivity : VMBaseActivity<ImportRssSourceViewModel>(
R.layout.activity_translucence,
theme = Theme.Transparent
) {
override val viewModel: ImportRssSourceViewModel
get() = getViewModel(ImportRssSourceViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.errorLiveData.observe(this, Observer {
errorDialog(it)
})
viewModel.successLiveData.observe(this, Observer {
successDialog(it)
})
initData()
}
private fun initData() {
intent.getStringExtra("source")?.let {
viewModel.importSource(it)
return
}
intent.getStringExtra("filePath")?.let {
viewModel.importSourceFromFilePath(it)
return
}
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
if (url.startsWith("http", false)) {
viewModel.importSource(url)
} else {
viewModel.importSourceFromFilePath(url)
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun errorDialog(msg: String) {
alert("导入出错", msg) {
okButton { }
}.show().applyTint().setOnDismissListener {
finish()
}
}
private fun successDialog(allSource: ArrayList<RssSource>) {
alert("解析结果", "${allSource.size}个订阅源,是否确认导入?") {
okButton {
SourceHelp.insertRssSource(*allSource.toTypedArray())
}
noButton {
}
}.show().applyTint().setOnDismissListener {
finish()
}
}
}

@ -0,0 +1,96 @@
package io.legado.app.ui.association
import android.app.Application
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData
import com.jayway.jsonpath.JsonPath
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.RssSource
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.Restore
import io.legado.app.utils.*
import java.io.File
class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) {
val errorLiveData = MutableLiveData<String>()
val successLiveData = MutableLiveData<ArrayList<RssSource>>()
private val allSources = arrayListOf<RssSource>()
fun importSourceFromFilePath(path: String) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (null != content) {
GSON.fromJsonArray<RssSource>(content)?.let {
allSources.addAll(it)
}
}
}.onSuccess {
successLiveData.postValue(allSources)
}
}
fun importSource(text: String) {
execute {
val text1 = text.trim()
when {
text1.isJsonObject() -> {
val json = JsonPath.parse(text1)
val urls = json.read<List<String>>("$.sourceUrls")
if (!urls.isNullOrEmpty()) {
urls.forEach {
importSourceUrl(it)
}
} else {
GSON.fromJsonArray<RssSource>(text1)?.let {
allSources.addAll(it)
}
}
}
text1.isJsonArray() -> {
val items: List<Map<String, Any>> = Restore.jsonPath.parse(text1).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
GSON.fromJsonObject<RssSource>(jsonItem.jsonString())?.let {
allSources.add(it)
}
}
}
text1.isAbsUrl() -> {
importSourceUrl(text1)
}
else -> throw Exception("格式不对")
}
}.onError {
errorLiveData.postValue("ImportError:${it.localizedMessage}")
}.onSuccess {
successLiveData.postValue(allSources)
}
}
private fun importSourceUrl(url: String) {
HttpHelper.simpleGet(url, "UTF-8")?.let { body ->
val items: List<Map<String, Any>> = Restore.jsonPath.parse(body).read("$")
for (item in items) {
val jsonItem = Restore.jsonPath.parse(item)
GSON.fromJsonObject<RssSource>(jsonItem.jsonString())?.let { source ->
allSources.add(source)
}
}
}
}
}

@ -15,7 +15,6 @@ import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
@ -25,6 +24,7 @@ import io.legado.app.lib.dialogs.*
import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.service.help.CheckSource
import io.legado.app.ui.association.ImportBookSourceActivity
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
@ -38,7 +38,6 @@ import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast
import java.io.File
import java.text.Collator
@ -60,7 +59,6 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
private var sort = 0
override fun onActivityCreated(savedInstanceState: Bundle?) {
initUriScheme()
initRecyclerView()
initSearchView()
initLiveDataBookSource()
@ -128,28 +126,6 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
return super.onCompatOptionsItemSelected(item)
}
private fun initUriScheme() {
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
if (url.startsWith("http", false)) {
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
} else {
viewModel.importSourceFromFilePath(url) { msg ->
title_bar.snackbar(msg)
}
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view)
recycler_view.layoutManager = LinearLayoutManager(this)
@ -309,10 +285,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
cacheUrls.add(0, it)
aCache.put(importRecordKey, cacheUrls.joinToString(","))
}
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportBookSourceActivity>(Pair("source", it))
}
}
cancelButton()
@ -365,10 +338,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
File(currentPath)
)
importRequestCode -> {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSourceFromFilePath(currentPath) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportBookSourceActivity>(Pair("filePath", currentPath))
}
}
}
@ -378,25 +348,12 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
when (requestCode) {
qrRequestCode -> if (resultCode == RESULT_OK) {
data?.getStringExtra("result")?.let {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportBookSourceActivity>("source" to it)
}
}
importRequestCode -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
try {
uri.readText(this)?.let {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE)
.show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
}
} catch (e: Exception) {
toast(e.localizedMessage ?: "ERROR")
}
startActivity<ImportBookSourceActivity>("filePath" to uri.toString())
}
}
exportRequestCode -> {

@ -1,20 +1,15 @@
package io.legado.app.ui.book.source.manage
import android.app.Application
import android.net.Uri
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import com.jayway.jsonpath.JsonPath
import io.legado.app.App
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.BookSource
import io.legado.app.help.SourceHelp
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.OldRule
import io.legado.app.help.storage.Restore.jsonPath
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.writeText
import org.jetbrains.anko.toast
import java.io.File
@ -166,94 +161,4 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application)
}
}
fun importSourceFromFilePath(path: String, finally: (msg: String) -> Unit) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (content != null) {
importSource(content, finally)
} else {
withContext(Dispatchers.Main) {
finally("打开文件出错")
}
}
}.onError {
finally(it.localizedMessage ?: "打开文件出错")
}
}
fun importSource(text: String, finally: (msg: String) -> Unit) {
execute {
val text1 = text.trim()
when {
text1.isJsonObject() -> {
val json = JsonPath.parse(text1)
val urls = json.read<List<String>>("$.sourceUrls")
var count = 0
if (!urls.isNullOrEmpty()) {
urls.forEach {
count += importSourceUrl(it)
}
} else {
OldRule.jsonToBookSource(text1)?.let {
SourceHelp.insertBookSource(it)
count = 1
}
}
"导入${count}"
}
text1.isJsonArray() -> {
val bookSources = mutableListOf<BookSource>()
val items: List<Map<String, Any>> = jsonPath.parse(text1).read("$")
for (item in items) {
val jsonItem = jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let {
bookSources.add(it)
}
}
SourceHelp.insertBookSource(*bookSources.toTypedArray())
"导入${bookSources.size}"
}
text1.isAbsUrl() -> {
val count = importSourceUrl(text1)
"导入${count}"
}
else -> "格式不对"
}
}.onError {
it.printStackTrace()
finally(it.localizedMessage ?: "")
}.onSuccess {
finally(it)
}
}
private fun importSourceUrl(url: String): Int {
HttpHelper.simpleGet(url, "UTF-8").let { body ->
if (body == null) {
toast("访问网站失败")
return 0
}
val bookSources = mutableListOf<BookSource>()
val items: List<Map<String, Any>> = jsonPath.parse(body).read("$")
for (item in items) {
val jsonItem = jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let { source ->
bookSources.add(source)
}
}
SourceHelp.insertBookSource(*bookSources.toTypedArray())
return bookSources.size
}
}
}

@ -15,7 +15,6 @@ import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
@ -26,6 +25,7 @@ import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.dialogs.*
import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.association.ImportReplaceRuleActivity
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.ui.replacerule.edit.ReplaceEditDialog
@ -36,7 +36,7 @@ import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_replace_rule.*
import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.toast
import org.jetbrains.anko.startActivity
import java.io.File
@ -57,7 +57,6 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
private var dataInit = false
override fun onActivityCreated(savedInstanceState: Bundle?) {
initUriScheme()
initRecyclerView()
initSearchView()
initSelectActionView()
@ -76,29 +75,6 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
return super.onPrepareOptionsMenu(menu)
}
private fun initUriScheme() {
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
if (url.startsWith("http", false)){
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
}
else{
viewModel.importSourceFromFilePath(url) { msg ->
title_bar.snackbar(msg)
}
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view)
recycler_view.layoutManager = LinearLayoutManager(this)
@ -242,10 +218,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
cacheUrls.add(0, it)
aCache.put(importRecordKey, cacheUrls.joinToString(","))
}
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportReplaceRuleActivity>("source" to it)
}
}
cancelButton()
@ -264,10 +237,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
override fun onFilePicked(requestCode: Int, currentPath: String) {
when (requestCode) {
importRequestCode -> {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(File(currentPath).readText()) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportReplaceRuleActivity>("filePath" to currentPath)
}
exportRequestCode -> viewModel.exportSelection(
adapter.getSelection(),
@ -281,17 +251,7 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
when (requestCode) {
importRequestCode -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
try {
uri.readText(this)?.let {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE)
.show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
}
} catch (e: Exception) {
toast(e.localizedMessage ?: "ERROR")
}
startActivity<ImportReplaceRuleActivity>("filePath" to uri.toString())
}
}
exportRequestCode -> if (resultCode == RESULT_OK) {

@ -1,62 +1,19 @@
package io.legado.app.ui.replacerule
import android.app.Application
import android.net.Uri
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.ImportOldData
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.writeText
import org.jetbrains.anko.toast
import java.io.File
class ReplaceRuleViewModel(application: Application) : BaseViewModel(application) {
fun importSourceFromFilePath(path: String, finally: (msg: String) -> Unit) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (content != null) {
importSource(content, finally)
} else {
withContext(Dispatchers.Main) {
finally("打开文件出错")
}
}
}.onError {
finally(it.localizedMessage ?: "打开文件出错")
}
}
fun importSource(text: String, showMsg: (msg: String) -> Unit) {
execute {
if (text.isAbsUrl()) {
HttpHelper.simpleGet(text)?.let {
ImportOldData.importOldReplaceRule(it)
}
} else {
ImportOldData.importOldReplaceRule(text)
}
}.onError {
showMsg(it.localizedMessage ?: "ERROR")
}.onSuccess {
showMsg(context.getString(R.string.success))
}
}
fun update(vararg rule: ReplaceRule) {
execute {

@ -15,7 +15,6 @@ import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
@ -24,6 +23,7 @@ import io.legado.app.help.ItemTouchCallback
import io.legado.app.lib.dialogs.*
import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.association.ImportRssSourceActivity
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.ui.qrcode.QrCodeActivity
@ -37,7 +37,6 @@ import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast
import java.io.File
import java.text.Collator
import java.util.*
@ -60,7 +59,6 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
private var groupMenu: SubMenu? = null
override fun onActivityCreated(savedInstanceState: Bundle?) {
initUriScheme()
initRecyclerView()
initSearchView()
initLiveDataGroup()
@ -112,29 +110,6 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
return true
}
private fun initUriScheme() {
intent.data?.let {
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
if (url.startsWith("http", false)){
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
}
else{
viewModel.importSourceFromFilePath(url) { msg ->
title_bar.snackbar(msg)
}
}
}
else -> {
toast("格式不对")
}
}
}
}
private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view)
recycler_view.layoutManager = LinearLayoutManager(this)
@ -256,10 +231,7 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
cacheUrls.add(0, it)
aCache.put(importRecordKey, cacheUrls.joinToString(","))
}
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportRssSourceActivity>("source" to it)
}
}
cancelButton()
@ -269,10 +241,7 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
override fun onFilePicked(requestCode: Int, currentPath: String) {
when (requestCode) {
importRequestCode -> {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSourceFromFilePath(currentPath) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportRssSourceActivity>("filePath" to currentPath)
}
exportRequestCode -> viewModel.exportSelection(
adapter.getSelection(),
@ -286,25 +255,12 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
when (requestCode) {
importRequestCode -> if (resultCode == Activity.RESULT_OK) {
data?.data?.let { uri ->
try {
uri.readText(this)?.let {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE)
.show()
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
}
} catch (e: Exception) {
toast(e.localizedMessage ?: "ERROR")
}
startActivity<ImportRssSourceActivity>("filePath" to uri.toString())
}
}
qrRequestCode -> if (resultCode == RESULT_OK) {
data?.getStringExtra("result")?.let {
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE)
viewModel.importSource(it) { msg ->
title_bar.snackbar(msg)
}
startActivity<ImportRssSourceActivity>("source" to it)
}
}
exportRequestCode -> if (resultCode == RESULT_OK) {

@ -1,18 +1,15 @@
package io.legado.app.ui.rss.source.manage
import android.app.Application
import android.net.Uri
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import com.jayway.jsonpath.JsonPath
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.RssSource
import io.legado.app.help.SourceHelp
import io.legado.app.help.http.HttpHelper
import io.legado.app.help.storage.Restore.jsonPath
import io.legado.app.utils.*
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.writeText
import org.jetbrains.anko.toast
import java.io.File
@ -147,89 +144,4 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application)
}
}
fun importSourceFromFilePath(path: String, finally: (msg: String) -> Unit) {
execute {
val content = if (path.isContentPath()) {
//在前面被解码了,如果不进行编码,中文会无法识别
val newPath = Uri.encode(path, ":/.")
DocumentFile.fromSingleUri(context, Uri.parse(newPath))?.readText(context)
} else {
val file = File(path)
if (file.exists()) {
file.readText()
} else {
null
}
}
if (null != content) {
GSON.fromJsonArray<RssSource>(content)?.let {
SourceHelp.insertRssSource(*it.toTypedArray())
}
}
}.onSuccess {
finally.invoke(context.getString(R.string.success))
}
}
fun importSource(text: String, finally: (msg: String) -> Unit) {
execute {
val text1 = text.trim()
when {
text1.isJsonObject() -> {
val json = JsonPath.parse(text1)
val urls = json.read<List<String>>("$.sourceUrls")
var count = 0
if (!urls.isNullOrEmpty()) {
urls.forEach {
count += importSourceUrl(it)
}
} else {
GSON.fromJsonArray<RssSource>(text1)?.let {
SourceHelp.insertRssSource(*it.toTypedArray())
count = 1
}
}
"导入${count}"
}
text1.isJsonArray() -> {
val rssSources = mutableListOf<RssSource>()
val items: List<Map<String, Any>> = jsonPath.parse(text1).read("$")
for (item in items) {
val jsonItem = jsonPath.parse(item)
GSON.fromJsonObject<RssSource>(jsonItem.jsonString())?.let {
rssSources.add(it)
}
}
SourceHelp.insertRssSource(*rssSources.toTypedArray())
"导入${rssSources.size}"
}
text1.isAbsUrl() -> {
val count = importSourceUrl(text1)
"导入${count}"
}
else -> "格式不对"
}
}.onError {
finally(it.localizedMessage ?: "")
}.onSuccess {
finally(it)
}
}
private fun importSourceUrl(url: String): Int {
HttpHelper.simpleGet(url, "UTF-8")?.let { body ->
val sources = mutableListOf<RssSource>()
val items: List<Map<String, Any>> = jsonPath.parse(body).read("$")
for (item in items) {
val jsonItem = jsonPath.parse(item)
GSON.fromJsonObject<RssSource>(jsonItem.jsonString())?.let { source ->
sources.add(source)
}
}
SourceHelp.insertRssSource(*sources.toTypedArray())
return sources.size
}
return 0
}
}

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.legado.app.ui.config.FileAssociationActivity">
android:background="@color/transparent30">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save