feat: 优化代码

pull/141/head
kunfei 5 years ago
parent b03675c53b
commit fb881c5951
  1. 8
      app/src/main/java/io/legado/app/constant/AppConst.kt
  2. 4
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  3. 2
      app/src/main/java/io/legado/app/ui/book/download/DownloadActivity.kt
  4. 2
      app/src/main/java/io/legado/app/ui/book/local/ImportBookAdapter.kt
  5. 4
      app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
  6. 7
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  7. 24
      app/src/main/java/io/legado/app/ui/filechooser/FilePicker.kt
  8. 7
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt
  9. 54
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
  10. 35
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt
  11. 7
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  12. 2
      app/src/main/res/values/strings.xml

@ -29,14 +29,18 @@ object AppConst {
ScriptEngineManager().getEngineByName("rhino") ScriptEngineManager().getEngineByName("rhino")
} }
val TIME_FORMAT: SimpleDateFormat by lazy { val timeFormat: SimpleDateFormat by lazy {
SimpleDateFormat("HH:mm") SimpleDateFormat("HH:mm")
} }
val DATE_FORMAT: SimpleDateFormat by lazy { val dateFormat: SimpleDateFormat by lazy {
SimpleDateFormat("yyyy/MM/dd HH:mm") SimpleDateFormat("yyyy/MM/dd HH:mm")
} }
val fileNameFormat: SimpleDateFormat by lazy {
SimpleDateFormat("yy-MM-dd-HH-mm-ss")
}
val keyboardToolChars: List<String> by lazy { val keyboardToolChars: List<String> by lazy {
arrayListOf( arrayListOf(
"@", "&", "|", "%", "/", ":", "[", "]", "{", "}", "<", ">", "\\", "$", "#", "!", ".", "@", "&", "|", "%", "/", ":", "[", "]", "{", "}", "<", ">", "\\", "$", "#", "!", ".",

@ -2,7 +2,7 @@ package io.legado.app.help
import android.util.Base64 import android.util.Base64
import androidx.annotation.Keep import androidx.annotation.Keep
import io.legado.app.constant.AppConst.DATE_FORMAT import io.legado.app.constant.AppConst.dateFormat
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.EncoderUtils import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
@ -50,6 +50,6 @@ interface JsExtensions {
} }
fun timeFormat(time: Long): String { fun timeFormat(time: Long): String {
return DATE_FORMAT.format(Date(time)) return dateFormat.format(Date(time))
} }
} }

@ -127,7 +127,7 @@ class DownloadActivity : VMBaseActivity<DownloadViewModel>(R.layout.activity_dow
FilePicker.selectFolder(this, exportRequestCode) { FilePicker.selectFolder(this, exportRequestCode) {
val path = ACache.get(this@DownloadActivity).getAsString(exportBookPathKey) val path = ACache.get(this@DownloadActivity).getAsString(exportBookPathKey)
if (path.isNullOrEmpty()) { if (path.isNullOrEmpty()) {
toast("没有默认路径") toast(R.string.no_default_path)
} else { } else {
startExport(path) startExport(path)
} }

@ -87,7 +87,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
ll_brief.visible() ll_brief.visible()
tv_tag.text = item.name.substringAfterLast(".") tv_tag.text = item.name.substringAfterLast(".")
tv_size.text = StringUtils.toSize(item.size) tv_size.text = StringUtils.toSize(item.size)
tv_date.text = AppConst.DATE_FORMAT.format(item.date) tv_date.text = AppConst.dateFormat.format(item.date)
cb_select.isChecked = selectedUris.contains(item.uri.toString()) cb_select.isChecked = selectedUris.contains(item.uri.toString())
} }
tv_name.text = item.name tv_name.text = item.name

@ -7,7 +7,7 @@ import android.view.MotionEvent
import android.widget.FrameLayout import android.widget.FrameLayout
import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap import com.github.houbb.opencc4j.core.impl.ZhConvertBootstrap
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppConst.TIME_FORMAT import io.legado.app.constant.AppConst.timeFormat
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.ui.book.read.page.entities.TextPage
@ -85,7 +85,7 @@ class ContentView(context: Context) : FrameLayout(context) {
} }
fun upTime() { fun upTime() {
tv_top_left.text = TIME_FORMAT.format(Date(System.currentTimeMillis())) tv_top_left.text = timeFormat.format(Date(System.currentTimeMillis()))
} }
fun upBattery(battery: Int) { fun upBattery(battery: Int) {

@ -85,7 +85,12 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
R.id.menu_group_manage -> R.id.menu_group_manage ->
GroupManageDialog().show(supportFragmentManager, "groupManage") GroupManageDialog().show(supportFragmentManager, "groupManage")
R.id.menu_import_source_local -> FilePicker R.id.menu_import_source_local -> FilePicker
.selectFile(this, importRequestCode, "text/*", arrayOf("txt", "json")) .selectFile(
this,
importRequestCode,
type = "text/*",
allowExtensions = arrayOf("txt", "json")
)
R.id.menu_import_source_onLine -> showImportDialog() R.id.menu_import_source_onLine -> showImportDialog()
} }
if (item.groupId == R.id.source_group) { if (item.groupId == R.id.source_group) {

@ -14,8 +14,13 @@ import org.jetbrains.anko.toast
@Suppress("unused") @Suppress("unused")
object FilePicker { object FilePicker {
fun selectFolder(activity: AppCompatActivity, requestCode: Int, default: (() -> Unit)? = null) { fun selectFolder(
activity.alert(titleResource = R.string.select_folder) { activity: AppCompatActivity,
requestCode: Int,
title: String = activity.getString(R.string.select_folder),
default: (() -> Unit)? = null
) {
activity.alert(title = title) {
val selectList = val selectList =
activity.resources.getStringArray(R.array.select_folder).toMutableList() activity.resources.getStringArray(R.array.select_folder).toMutableList()
default ?: let { default ?: let {
@ -45,9 +50,14 @@ object FilePicker {
}.show() }.show()
} }
fun selectFolder(fragment: Fragment, requestCode: Int, default: (() -> Unit)? = null) { fun selectFolder(
fragment: Fragment,
requestCode: Int,
title: String = fragment.getString(R.string.select_folder),
default: (() -> Unit)? = null
) {
fragment.requireContext() fragment.requireContext()
.alert(titleResource = R.string.select_folder) { .alert(title = title) {
val selectList = val selectList =
fragment.resources.getStringArray(R.array.select_folder).toMutableList() fragment.resources.getStringArray(R.array.select_folder).toMutableList()
default ?: let { default ?: let {
@ -80,11 +90,12 @@ object FilePicker {
fun selectFile( fun selectFile(
activity: BaseActivity, activity: BaseActivity,
requestCode: Int, requestCode: Int,
title: String = activity.getString(R.string.select_file),
type: String, type: String,
allowExtensions: Array<String>?, allowExtensions: Array<String>?,
default: (() -> Unit)? = null default: (() -> Unit)? = null
) { ) {
activity.alert(titleResource = R.string.select_file) { activity.alert(title = title) {
val selectList = val selectList =
activity.resources.getStringArray(R.array.select_folder).toMutableList() activity.resources.getStringArray(R.array.select_folder).toMutableList()
default ?: let { default ?: let {
@ -119,12 +130,13 @@ object FilePicker {
fun selectFile( fun selectFile(
fragment: Fragment, fragment: Fragment,
requestCode: Int, requestCode: Int,
title: String = fragment.getString(R.string.select_file),
type: String, type: String,
allowExtensions: Array<String>, allowExtensions: Array<String>,
default: (() -> Unit)? = null default: (() -> Unit)? = null
) { ) {
fragment.requireContext() fragment.requireContext()
.alert(titleResource = R.string.select_file) { .alert(title = title) {
val selectList = val selectList =
fragment.resources.getStringArray(R.array.select_folder).toMutableList() fragment.resources.getStringArray(R.array.select_folder).toMutableList()
default ?: let { default ?: let {

@ -180,7 +180,12 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
R.id.menu_del_selection -> viewModel.delSelection(adapter.getSelection()) R.id.menu_del_selection -> viewModel.delSelection(adapter.getSelection())
R.id.menu_import_source_onLine -> showImportDialog() R.id.menu_import_source_onLine -> showImportDialog()
R.id.menu_import_source_local -> FilePicker R.id.menu_import_source_local -> FilePicker
.selectFile(this, importRequestCode, "text/*", arrayOf("txt", "json")) .selectFile(
this,
importRequestCode,
type = "text/*",
allowExtensions = arrayOf("txt", "json")
)
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
} }

@ -1,6 +1,7 @@
package io.legado.app.ui.rss.read package io.legado.app.ui.rss.read
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import android.view.Menu import android.view.Menu
@ -14,6 +15,9 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.lib.theme.DrawableUtils import io.legado.app.lib.theme.DrawableUtils
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.utils.ACache
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
@ -21,17 +25,22 @@ import kotlinx.android.synthetic.main.activity_rss_read.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils import org.apache.commons.text.StringEscapeUtils
import org.jetbrains.anko.share import org.jetbrains.anko.share
import org.jetbrains.anko.toast
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.safety.Whitelist import org.jsoup.safety.Whitelist
class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_read), class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_read),
FileChooserDialog.CallBack,
ReadRssViewModel.CallBack { ReadRssViewModel.CallBack {
override val viewModel: ReadRssViewModel override val viewModel: ReadRssViewModel
get() = getViewModel(ReadRssViewModel::class.java) get() = getViewModel(ReadRssViewModel::class.java)
private val savePathRequestCode = 132
private val imagePathKey = ""
private var starMenuItem: MenuItem? = null private var starMenuItem: MenuItem? = null
private var ttsMenuItem: MenuItem? = null private var ttsMenuItem: MenuItem? = null
var webPic: String? = null
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.callBack = this viewModel.callBack = this
@ -95,6 +104,30 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
domStorageEnabled = true domStorageEnabled = true
allowContentAccess = true allowContentAccess = true
} }
web_view.setOnLongClickListener {
val hitTestResult = web_view.hitTestResult
if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) {
hitTestResult.extra?.let {
webPic = it
saveImage()
return@setOnLongClickListener true
}
}
return@setOnLongClickListener false
}
}
private fun saveImage() {
FilePicker.selectFolder(this, savePathRequestCode, getString(R.string.save_image)) {
val path = ACache.get(this).getAsString(imagePathKey)
if (path.isNullOrEmpty()) {
toast(R.string.no_default_path)
} else {
viewModel.saveImage(webPic, path)
}
}
} }
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
@ -113,7 +146,6 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
url url
)//不想用baseUrl进else )//不想用baseUrl进else
} else { } else {
//webView.loadData(html, "text/html;charset=utf-8", "utf-8")//经测试可以解决中文乱码
web_view.loadDataWithBaseURL( web_view.loadDataWithBaseURL(
null, null,
html, html,
@ -203,6 +235,24 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
} }
} }
override fun onFilePicked(requestCode: Int, currentPath: String) {
when (requestCode) {
savePathRequestCode -> {
ACache.get(this).put(imagePathKey, currentPath)
viewModel.saveImage(webPic, currentPath)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
savePathRequestCode -> data?.data?.let {
onFilePicked(requestCode, it.toString())
}
}
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
web_view.destroy() web_view.destroy()

@ -2,19 +2,29 @@ package io.legado.app.ui.rss.read
import android.app.Application import android.app.Application
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.speech.tts.TextToSpeech import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener import android.speech.tts.UtteranceProgressListener
import android.util.Base64
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppConst
import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.RssArticle
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.model.Rss import io.legado.app.model.Rss
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.DocumentUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.isContentPath
import io.legado.app.utils.writeBytes
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File
import java.util.* import java.util.*
class ReadRssViewModel(application: Application) : BaseViewModel(application), class ReadRssViewModel(application: Application) : BaseViewModel(application),
TextToSpeech.OnInitListener { TextToSpeech.OnInitListener {
var callBack: CallBack? = null var callBack: CallBack? = null
@ -85,6 +95,31 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application),
} }
} }
fun saveImage(webPic: String?, path: String) {
webPic ?: return
execute {
val fileName = "${AppConst.fileNameFormat.format(Date(System.currentTimeMillis()))}.jpg"
webData2bitmap(webPic).let { biteArray ->
if (path.isContentPath()) {
val uri = Uri.parse(path)
DocumentFile.fromTreeUri(context, uri)?.let { doc ->
DocumentUtils.createFileIfNotExist(doc, fileName)
?.writeBytes(context, biteArray)
}
} else {
val file = FileUtils.createFileIfNotExist(File(path), fileName)
file.writeBytes(biteArray)
}
}
}.onError {
toast("保存图片失败:${it.localizedMessage}")
}
}
private fun webData2bitmap(data: String): ByteArray {
return Base64.decode(data.split(",").toTypedArray()[1], Base64.DEFAULT)
}
fun clHtml(content: String): String { fun clHtml(content: String): String {
return if (content.contains("<style>".toRegex())) { return if (content.contains("<style>".toRegex())) {
content content

@ -83,7 +83,12 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
when (item.itemId) { when (item.itemId) {
R.id.menu_add -> startActivity<RssSourceEditActivity>() R.id.menu_add -> startActivity<RssSourceEditActivity>()
R.id.menu_import_source_local -> FilePicker R.id.menu_import_source_local -> FilePicker
.selectFile(this, importRequestCode, "text/*", arrayOf("txt", "json")) .selectFile(
this,
importRequestCode,
type = "text/*",
allowExtensions = arrayOf("txt", "json")
)
R.id.menu_import_source_onLine -> showImportDialog() R.id.menu_import_source_onLine -> showImportDialog()
R.id.menu_import_source_qr -> startActivityForResult<QrCodeActivity>(qrRequestCode) R.id.menu_import_source_qr -> startActivityForResult<QrCodeActivity>(qrRequestCode)
R.id.menu_group_manage -> GroupManageDialog() R.id.menu_group_manage -> GroupManageDialog()

@ -639,4 +639,6 @@
<string name="title_center">居中</string> <string name="title_center">居中</string>
<string name="title_hide">隐藏</string> <string name="title_hide">隐藏</string>
<string name="add_to_group">加入分组</string> <string name="add_to_group">加入分组</string>
<string name="save_image">保存图片</string>
<string name="no_default_path">没有默认路径</string>
</resources> </resources>

Loading…
Cancel
Save