Merge pull request #34 from gedoor/master

up
pull/379/head
口口吕 5 years ago committed by GitHub
commit 3e3f523aa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/src/debug/res/values/strings.xml
  2. 14
      app/src/main/AndroidManifest.xml
  3. 16
      app/src/main/assets/updateLog.md
  4. 5
      app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt
  5. 14
      app/src/main/java/io/legado/app/data/dao/BookDao.kt
  6. 7
      app/src/main/java/io/legado/app/help/ItemTouchCallback.kt
  7. 9
      app/src/main/java/io/legado/app/help/storage/Backup.kt
  8. 10
      app/src/main/java/io/legado/app/service/BaseReadAloudService.kt
  9. 2
      app/src/main/java/io/legado/app/ui/README.md
  10. 1
      app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
  11. 18
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
  12. 35
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt
  13. 13
      app/src/main/java/io/legado/app/ui/book/download/DownloadActivity.kt
  14. 2
      app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt
  15. 2
      app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt
  16. 7
      app/src/main/java/io/legado/app/ui/book/group/GroupViewModel.kt
  17. 8
      app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
  18. 3
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  19. 2
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  20. 4
      app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt
  21. 41
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextChapter.kt
  22. 10
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  23. 2
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt
  24. 39
      app/src/main/java/io/legado/app/ui/config/FileAssociationActivity.kt
  25. 69
      app/src/main/java/io/legado/app/ui/config/FileAssociationViewModel.kt
  26. 1
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt
  27. 11
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleActivity.kt
  28. 2
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleAdapter.kt
  29. 17
      app/src/main/java/io/legado/app/ui/replacerule/ReplaceRuleViewModel.kt
  30. 11
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  31. 2
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceAdapter.kt
  32. 8
      app/src/main/java/io/legado/app/utils/EncodingDetect.java
  33. 8
      app/src/main/res/layout/activity_file_association.xml
  34. 2
      app/src/main/res/layout/activity_welcome.xml
  35. 2
      app/src/main/res/menu/change_cover.xml
  36. 2
      app/src/main/res/menu/change_source.xml
  37. 2
      app/src/main/res/values-night/colors.xml
  38. 2
      app/src/main/res/values/colors.xml
  39. 11
      app/src/main/res/values/strings.xml
  40. 2
      app/src/main/res/xml/pref_config_read.xml

@ -1,4 +1,4 @@
<resources>
<string name="app_name">读.debug</string>
<string name="receiving_shared_label">读.debug·搜索</string>
<string name="app_name">读.debug</string>
<string name="receiving_shared_label">读.debug·搜索</string>
</resources>

@ -287,7 +287,19 @@
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".ui.config.FileAssociationActivity"
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:scheme="file"/>
<data android:scheme="content"/>
<data android:mimeType="text/plain" />
<data android:mimeType="application/json" />
</intent-filter>
</activity>
<service android:name=".service.CheckSourceService" />
<service android:name=".service.DownloadService" />
<service android:name=".service.WebService" />

@ -3,6 +3,13 @@
* 请关注[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
* 弄了个企业公众号[开源阅读](),后面弄好后会把原来的[开源阅读软件]()迁移过来
**2020/03/22**
* 添加文件关联 by wqfantexi
* 手动排序可以了,在书架整理里面拖动排序
* 删除分组时同时删除书籍里的分组信息,下次添加新分组时不会自动出现在分组内
* 修复换源丢失分组信息的bug
* 修复部分朗读引擎不自动朗读下一章的bug
**2020/03/21**
* 详情页点击书名搜索
@ -266,14 +273,7 @@
- 调试正文页>>输入正文页URL,如:`--https://www.zhaishuyuan.com/chapter/30394/20940996`
* 修改订阅中自动添加style的情景
订阅源的内容规则中存在`<style>``style=`,
```
<style>
img{max-width:100% !important; width:auto; height:auto;}
video{object-fit:fill; max-width:100% !important; width:auto; height:auto;}
body{word-wrap:break-word; height:auto;max-width: 100%; width:auto;}
</style>
```
订阅源的内容规则中存在`<style>``style=`
**2019/12/28**
* 添加下载界面

@ -290,12 +290,11 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) :
return footerItems?.size() ?: 0
}
fun getItem(position: Int): ITEM? =
if (position in 0 until items.size) items[position] else null
fun getItem(position: Int): ITEM? = items.getOrNull(position)
fun getItemByLayoutPosition(position: Int): ITEM? {
val pos = position - getHeaderCount()
return if (pos in 0 until items.size) items[pos] else null
return items.getOrNull(pos)
}
fun getItems(): List<ITEM> = items

@ -12,16 +12,16 @@ interface BookDao {
@Query("SELECT * FROM books order by durChapterTime desc")
fun observeAll(): LiveData<List<Book>>
@Query("SELECT * FROM books WHERE type = ${BookType.audio} order by durChapterTime desc")
@Query("SELECT * FROM books WHERE type = ${BookType.audio}")
fun observeAudio(): LiveData<List<Book>>
@Query("SELECT * FROM books WHERE origin = '${BookType.local}' order by durChapterTime desc")
@Query("SELECT * FROM books WHERE origin = '${BookType.local}'")
fun observeLocal(): LiveData<List<Book>>
@Query("SELECT bookUrl FROM books WHERE origin = '${BookType.local}' order by durChapterTime desc")
@Query("SELECT bookUrl FROM books WHERE origin = '${BookType.local}'")
fun observeLocalUri(): LiveData<List<String>>
@Query("SELECT * FROM books WHERE origin <> '${BookType.local}' and type = 0 order by durChapterTime desc")
@Query("SELECT * FROM books WHERE origin <> '${BookType.local}' and type = 0")
fun observeDownload(): LiveData<List<Book>>
@Query("SELECT * FROM books WHERE (`group` & :group) > 0")
@ -33,6 +33,9 @@ interface BookDao {
@Query("SELECT * FROM books WHERE name like '%'||:key||'%' or author like '%'||:key||'%'")
fun liveDataSearch(key: String): LiveData<List<Book>>
@Query("SELECT * FROM books WHERE (`group` & :group) > 0")
fun getBooksByGroup(group: Int): List<Book>
@Query("SELECT * FROM books WHERE `name` in (:names)")
fun findByName(vararg names: String): List<Book>
@ -57,6 +60,9 @@ interface BookDao {
@get:Query("SELECT COUNT(*) FROM books")
val allBookCount: Int
@get:Query("select max(`order`) from books")
val maxOrder: Int
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg book: Book)

@ -106,7 +106,7 @@ class ItemTouchCallback : ItemTouchHelper.Callback() {
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
onItemTouchCallbackListener?.clearView(recyclerView, viewHolder)
onItemTouchCallbackListener?.onClearView(recyclerView, viewHolder)
}
interface OnItemTouchCallbackListener {
@ -131,7 +131,10 @@ class ItemTouchCallback : ItemTouchHelper.Callback() {
return true
}
fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
/**
* 手指松开
*/
fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
}

@ -31,11 +31,10 @@ object Backup {
fun autoBack(context: Context) {
val lastBackup = context.getPrefLong(PreferKey.lastBackup)
if (lastBackup + TimeUnit.DAYS.toMillis(1) < System.currentTimeMillis()) {
return
}
Coroutine.async {
context.getPrefString(PreferKey.backupPath)?.let {
backup(context, it, true)
Coroutine.async {
context.getPrefString(PreferKey.backupPath)?.let {
backup(context, it, true)
}
}
}
}

@ -111,11 +111,17 @@ abstract class BaseReadAloudService : BaseService(),
if (getPrefBoolean(PreferKey.readAloudByPage)) {
for (index in pageIndex..textChapter.lastIndex()) {
textChapter.page(index)?.text?.split("\n")?.let {
contentList.addAll(it)
if (it.isNotEmpty()) {
contentList.addAll(it)
}
}
}
} else {
contentList.addAll(textChapter.getUnRead(pageIndex).split("\n"))
textChapter.getUnRead(pageIndex).split("\n").forEach {
if (it.isNotEmpty()) {
contentList.add(it)
}
}
}
if (play) play()
} ?: stopSelf()

@ -6,7 +6,7 @@
* book\info 书籍信息查看
* book\read 书籍阅读界面
* book\search 搜索书籍界面
* book\source 搜索书源界面
* book\source 书源界面
* book\changeCover 封面换源界面
* book\changeSource 换源界面
* book\chapterList 目录界面

@ -91,6 +91,7 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
fun changeTo(book1: Book) {
execute {
AudioPlay.book?.let {
book1.order = it.order
App.db.bookDao().delete(it)
}
withContext(Dispatchers.Main) {

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
import io.legado.app.help.ItemTouchCallback
@ -23,6 +24,7 @@ import io.legado.app.ui.book.group.GroupSelectDialog
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.applyTint
import io.legado.app.utils.getPrefInt
import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_arrange_book.*
@ -68,7 +70,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
recycler_view.adapter = adapter
val itemTouchCallback = ItemTouchCallback()
itemTouchCallback.onItemTouchCallbackListener = adapter
itemTouchCallback.isCanDrag = true
itemTouchCallback.isCanDrag = getPrefInt(PreferKey.bookshelfSort) == 3
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view)
select_action_bar.setMainActionText(R.string.move_to_group)
select_action_bar.inflateMenu(R.menu.arrange_book_sel)
@ -109,8 +111,14 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
-11 -> App.db.bookDao().observeNoGroup()
else -> App.db.bookDao().observeByGroup(groupId)
}
booksLiveData?.observe(this, Observer {
adapter.setItems(it)
booksLiveData?.observe(this, Observer { list ->
val books = when (getPrefInt(PreferKey.bookshelfSort)) {
1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedBy { it.name }
3 -> list.sortedBy { it.order }
else -> list.sortedByDescending { it.durChapterTime }
}
adapter.setItems(books)
upSelectCount()
})
}
@ -205,6 +213,10 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
select_action_bar.upCountView(adapter.selectedBooks().size, adapter.getItems().size)
}
override fun updateBook(vararg book: Book) {
viewModel.updateBook(*book)
}
override fun deleteBook(book: Book) {
alert(titleResource = R.string.draw, messageResource = R.string.sure_del) {
okButton {

@ -2,14 +2,18 @@ package io.legado.app.ui.book.arrange
import android.content.Context
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
import io.legado.app.help.ItemTouchCallback
import io.legado.app.lib.theme.backgroundColor
import kotlinx.android.synthetic.main.item_arrange_book.view.*
import org.jetbrains.anko.backgroundColor
import org.jetbrains.anko.sdk27.listeners.onClick
import java.util.*
class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
SimpleRecyclerAdapter<Book>(context, R.layout.item_arrange_book),
@ -54,6 +58,7 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
override fun convert(holder: ItemViewHolder, item: Book, payloads: MutableList<Any>) {
with(holder.itemView) {
backgroundColor = context.backgroundColor
tv_name.text = item.name
tv_author.text = item.author
tv_author.visibility = if (item.author.isEmpty()) View.GONE else View.VISIBLE
@ -120,9 +125,39 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) :
return groupNames.joinToString(",")
}
private var isMoved = false
override fun onMove(srcPosition: Int, targetPosition: Int): Boolean {
val srcItem = getItem(srcPosition)
val targetItem = getItem(targetPosition)
Collections.swap(getItems(), srcPosition, targetPosition)
notifyItemMoved(srcPosition, targetPosition)
if (srcItem != null && targetItem != null) {
if (srcItem.order == targetItem.order) {
for ((index, item) in getItems().withIndex()) {
item.order = index + 1
}
} else {
val pos = srcItem.order
srcItem.order = targetItem.order
targetItem.order = pos
}
}
isMoved = true
return true
}
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (isMoved) {
callBack.updateBook(*getItems().toTypedArray())
}
isMoved = false
}
interface CallBack {
val groupList: List<BookGroup>
fun upSelectCount()
fun updateBook(vararg book: Book)
fun deleteBook(book: Book)
fun selectGroup(groupId: Int, requestCode: Int)
}

@ -13,6 +13,7 @@ import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
@ -81,9 +82,15 @@ class DownloadActivity : VMBaseActivity<DownloadViewModel>(R.layout.activity_dow
private fun initLiveData() {
bookshelfLiveData?.removeObservers(this)
bookshelfLiveData = App.db.bookDao().observeDownload()
bookshelfLiveData?.observe(this, Observer {
adapter.setItems(it)
initCacheSize(it)
bookshelfLiveData?.observe(this, Observer { list ->
val books = when (getPrefInt(PreferKey.bookshelfSort)) {
1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedBy { it.name }
3 -> list.sortedBy { it.order }
else -> list.sortedByDescending { it.durChapterTime }
}
adapter.setItems(books)
initCacheSize(books)
})
}

@ -217,7 +217,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
return true
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (isMoved) {
for ((index, item) in getItems().withIndex()) {
item.order = index + 1

@ -203,7 +203,7 @@ class GroupSelectDialog : DialogFragment(), Toolbar.OnMenuItemClickListener {
return true
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (isMoved) {
for ((index, item) in getItems().withIndex()) {
item.order = index + 1

@ -32,6 +32,13 @@ class GroupViewModel(application: Application) : BaseViewModel(application) {
fun delGroup(vararg bookGroup: BookGroup) {
execute {
App.db.bookGroupDao().delete(*bookGroup)
bookGroup.forEach { group ->
val books = App.db.bookDao().getBooksByGroup(group.groupId)
books.forEach {
it.group = it.group - group.groupId
}
App.db.bookDao().update(*books.toTypedArray())
}
}
}

@ -133,6 +133,8 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
execute {
if (inBookshelf) {
bookData.value?.let {
book.group = it.group
book.order = it.order
App.db.bookDao().delete(it)
}
App.db.bookDao().insert(book)
@ -164,6 +166,9 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
fun saveBook(success: (() -> Unit)? = null) {
execute {
bookData.value?.let { book ->
if (book.order == 0) {
book.order = App.db.bookDao().maxOrder + 1
}
App.db.bookDao().insert(book)
}
}.onSuccess {
@ -184,6 +189,9 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
fun addToBookshelf(success: (() -> Unit)?) {
execute {
bookData.value?.let { book ->
if (book.order == 0) {
book.order = App.db.bookDao().maxOrder + 1
}
App.db.bookDao().insert(book)
}
chapterListData.value?.let {

@ -609,9 +609,6 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
* 朗读按钮
*/
override fun onClickReadAloud() {
if (!BaseReadAloudService.isRun) {
SystemUtils.ignoreBatteryOptimization(this)
}
when {
!BaseReadAloudService.isRun -> ReadBook.readAloud()
BaseReadAloudService.pause -> ReadAloud.resume(this)

@ -136,6 +136,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
execute {
ReadBook.upMsg(null)
ReadBook.book?.let {
book1.group = it.group
book1.order = it.order
App.db.bookDao().delete(it)
}
ReadBook.prevTextChapter = null

@ -252,8 +252,8 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener {
return super.onMove(srcPosition, targetPosition)
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.onClearView(recyclerView, viewHolder)
if (isMoved) {
for ((index, item) in getItems().withIndex()) {
item.serialNumber = index + 1

@ -12,10 +12,7 @@ data class TextChapter(
val chaptersSize: Int
) {
fun page(index: Int): TextPage? {
if (index >= 0 && index < pages.size) {
return pages[index]
}
return null
return pages.getOrNull(index)
}
fun lastPage(): TextPage? {
@ -25,20 +22,6 @@ data class TextChapter(
return null
}
fun scrollPage(): TextPage? {
if (pages.isNotEmpty()) {
val stringBuilder = StringBuilder()
pages.forEach {
stringBuilder.append(it.text)
}
return TextPage(
index = 0, text = stringBuilder.toString(), title = title,
pageSize = pages.size, chapterSize = chaptersSize, chapterIndex = position
)
}
return null
}
fun lastIndex(): Int {
return pages.size - 1
}
@ -70,28 +53,6 @@ data class TextChapter(
return stringBuilder.toString()
}
fun getStartLine(pageIndex: Int): Int {
if (pageLines.size > pageIndex) {
var lines = 0
for (index: Int in 0 until pageIndex) {
lines += pageLines[index] + 1
}
return lines
}
return 0
}
fun getPageIndex(line: Int): Int {
var lines = 0
for (pageIndex in pageLines.indices) {
lines += pageLines[pageIndex] + 1
if (line < lines) {
return pageIndex
}
}
return 0
}
fun getContent(): String {
val stringBuilder = StringBuilder()
pages.forEach {

@ -104,8 +104,14 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
if (url.startsWith("http", false)){
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
}
else{
viewModel.importSourceFromFilePath(url){msg ->
title_bar.snackbar(msg)}
}
}
else -> {

@ -185,7 +185,7 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
private val movedItems = hashSetOf<BookSource>()
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (movedItems.isNotEmpty()) {
callBack.update(*movedItems.toTypedArray())
movedItems.clear()

@ -0,0 +1,39 @@
package io.legado.app.ui.config
import android.content.Intent
import android.os.Bundle
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.ui.main.MainActivity
import io.legado.app.utils.getViewModel
class FileAssociationActivity :
VMBaseActivity<FileAssociationViewModel>(R.layout.activity_file_association) {
override val viewModel: FileAssociationViewModel
get() = getViewModel(FileAssociationViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
intent.data?.let { data ->
val newIntent = viewModel.dispatchIndent(data)
if (newIntent != null) {
this.startActivityForResult(newIntent, 100)
} else {
gotoMainActivity()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
//返回后直接跳转到主页面
gotoMainActivity()
}
private fun gotoMainActivity() {
val mIntent = Intent()
mIntent.setClass(this, MainActivity::class.java)
startActivity(mIntent)
}
}

@ -0,0 +1,69 @@
package io.legado.app.ui.config
import android.app.Application
import android.content.Intent
import android.net.Uri
import android.text.TextUtils
import androidx.documentfile.provider.DocumentFile
import io.legado.app.base.BaseViewModel
import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.isJsonArray
import io.legado.app.utils.isJsonObject
import io.legado.app.utils.readText
import java.io.File
class FileAssociationViewModel(application: Application) : BaseViewModel(application) {
fun dispatchIndent(uri: Uri): Intent? {
val url: String
//如果是普通的url,需要根据返回的内容判断是什么
if (uri.scheme == "file" || uri.scheme == "content") {
val content = if (uri.scheme == "file") {
val file = File(uri.path.toString())
if (file.exists()) {
file.readText()
} else {
null
}
} else {
DocumentFile.fromSingleUri(context, uri)?.readText(context)
}
var scheme = ""
if (content != null) {
if (content.isJsonObject() || content.isJsonArray()) {
//暂时根据文件内容判断属于什么
when {
content.contains("bookSourceUrl") -> {
scheme = "booksource"
}
content.contains("sourceUrl") -> {
scheme = "rsssource"
}
content.contains("pattern") -> {
scheme = "replace"
}
}
}
if (TextUtils.isEmpty(scheme)) {
execute {
LocalBook.importFile(uri.path.toString())
toast("添加本地文件成功${uri.path}")
}
return null
}
} else {
toast("文件不存在")
return null
}
url = "yuedu://${scheme}/importonline?src=${uri.path}"
} else if (uri.scheme == "yuedu") {
url = uri.toString()
} else {
url = "yuedu://booksource/importonline?src=${uri.path}"
}
val data = Uri.parse(url)
val newIndent = Intent(Intent.ACTION_VIEW)
newIndent.data = data
return newIndent
}
}

@ -43,6 +43,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
)
WebBook(bookSource).getBookInfo(book, this)
.onSuccess(IO) {
it.order = App.db.bookDao().maxOrder + 1
App.db.bookDao().insert(it)
successCount++
}.onError {

@ -81,8 +81,15 @@ class ReplaceRuleActivity : VMBaseActivity<ReplaceRuleViewModel>(R.layout.activi
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
if (url.startsWith("http", false)){
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
}
else{
viewModel.importSourceFromFilePath(url) { msg ->
title_bar.snackbar(msg)
}
}
}
else -> {

@ -148,7 +148,7 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) :
private val movedItems = linkedSetOf<ReplaceRule>()
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (movedItems.isNotEmpty()) {
callBack.update(*movedItems.toTypedArray())
movedItems.clear()

@ -10,11 +10,26 @@ 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 org.jetbrains.anko.toast
import java.io.File
class ReplaceRuleViewModel(application: Application) : BaseViewModel(application) {
fun importSourceFromFilePath(path: String, finally: (msg: String) -> Unit) {
execute {
val file = File(path)
if (file.exists()) {
importSource(file.readText(), finally)
} else {
withContext(Dispatchers.Main) {
finally("打开文件出错")
}
}
}.onError {
finally(it.localizedMessage ?: "打开文件出错")
}
}
fun importSource(text: String, showMsg: (msg: String) -> Unit) {
execute {
if (text.isAbsUrl()) {

@ -117,8 +117,15 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
when (it.path) {
"/importonline" -> it.getQueryParameter("src")?.let { url ->
Snackbar.make(title_bar, R.string.importing, Snackbar.LENGTH_INDEFINITE).show()
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
if (url.startsWith("http", false)){
viewModel.importSource(url) { msg ->
title_bar.snackbar(msg)
}
}
else{
viewModel.importSourceFromFilePath(url) { msg ->
title_bar.snackbar(msg)
}
}
}
else -> {

@ -139,7 +139,7 @@ class RssSourceAdapter(context: Context, val callBack: CallBack) :
private val movedItems = hashSetOf<RssSource>()
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (movedItems.isNotEmpty()) {
callBack.update(*movedItems.toTypedArray())
movedItems.clear()

@ -66,7 +66,7 @@ public class EncodingDetect {
}
public static String getEncode(@NonNull byte[] bytes) {
int len = bytes.length > 2000 ? 2000 : bytes.length;
int len = Math.min(bytes.length, 2000);
byte[] cBytes = new byte[len];
System.arraycopy(bytes, 0, cBytes, 0, len);
BytesEncodingDetect bytesEncodingDetect = new BytesEncodingDetect();
@ -1010,14 +1010,8 @@ class BytesEncodingDetect extends Encoding {
column = rawtext[i + 1] + 256;
if (column < 0x9f) {
adjust = 1;
if (column > 0x7f) {
column -= 0x20;
} else {
column -= 0x19;
}
} else {
adjust = 0;
column -= 0x7e;
}
if (row < 0xa0) {
row = ((row - 0x70) << 1) - adjust;

@ -0,0 +1,8 @@
<?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">
</androidx.constraintlayout.widget.ConstraintLayout>

@ -22,7 +22,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="1"
android:text="读"
android:text="读"
android:textSize="49sp"
app:layout_constraintVertical_bias="0.3"
app:layout_constraintRight_toLeftOf="@+id/tv_sub_title"

@ -6,7 +6,7 @@
<item
android:id="@+id/menu_stop"
android:title="@string/stop"
android:icon="@drawable/ic_stop_black_24dp"
android:icon="@drawable/ic_refresh_white_24dp"
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />

@ -14,7 +14,7 @@
<item
android:id="@+id/menu_stop"
android:title="@string/stop"
android:icon="@drawable/ic_stop_black_24dp"
android:icon="@drawable/ic_refresh_white_24dp"
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />

@ -7,7 +7,7 @@
<color name="background">@color/md_grey_900</color>
<color name="background_card">@color/md_grey_850</color>
<color name="background_menu">@color/md_grey_800</color>
<color name="background_prefs">#10303030</color>
<color name="background_prefs">#AA111111</color>
<color name="night_mask">#69000000</color>

@ -16,7 +16,7 @@
<color name="background">@color/md_grey_50</color>
<color name="background_card">@color/md_grey_100</color>
<color name="background_menu">@color/md_grey_200</color>
<color name="background_prefs">@color/md_grey_50</color>
<color name="background_prefs">#AAFFFFFF</color>
<color name="transparent">#00000000</color>
<color name="transparent10">#10000000</color>

@ -1,5 +1,5 @@
<resources>
<string name="app_name"></string>
<string name="app_name"></string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
@ -20,7 +20,7 @@
<string name="dialog_setting">去设置</string>
<string name="tip_cannot_jump_setting_page">无法跳转至设置界面</string>
<string name="tip_perm_request_storage">读需要访问存储卡权限,请前往“设置”—“应用权限”—打开所需权限</string>
<string name="tip_perm_request_storage">读需要访问存储卡权限,请前往“设置”—“应用权限”—打开所需权限</string>
<string name="dynamic_click_retry">点击重试</string>
<string name="dynamic_loading">正在加载</string>
@ -42,9 +42,8 @@
<string name="all">全部</string>
<string name="recent_reading">最近阅读</string>
<string name="last_read">最后阅读</string>
<string name="read_summary">让阅读成为一种习惯。</string>
<string name="update_log">更新日志</string>
<string name="receiving_shared_label">读·搜索</string>
<string name="receiving_shared_label">读·搜索</string>
<string name="bookshelf_empty">书架还空着,先去添加吧!</string>
<string name="action_search">搜索</string>
<string name="action_download">下载</string>
@ -132,8 +131,6 @@
<string name="previous_chapter">上一章</string>
<string name="pt_hide_status_bar">隐藏状态栏</string>
<string name="ps_hide_status_bar">阅读界面隐藏状态栏</string>
<string name="pt_read_line_adjust">阅读行数调整</string>
<string name="ps_read_line_adjust">阅读行数减一行,如阅读界面显示不全可启用</string>
<string name="read_aloud">朗读</string>
<string name="read_aloud_t">正在朗读</string>
<string name="read_aloud_s">点击打开阅读界面</string>
@ -612,7 +609,7 @@
<string name="sys_folder_picker">系统文件夹选择器</string>
<string name="app_folder_picker">自带选择器\n(Android10以上因权限限制可能无法使用)</string>
<string name="a10_permission_toast">Android10以上因权限限制可能无法读写文件</string>
<string name="add_to_text_context_menu_s">长按文字在操作菜单中显示读·搜索</string>
<string name="add_to_text_context_menu_s">长按文字在操作菜单中显示读·搜索</string>
<string name="add_to_text_context_menu_t">文字操作显示搜索</string>
<string name="record_log">记录日志</string>
<string name="chinese_converter">中文简繁体转换</string>

@ -60,7 +60,7 @@
android:key="selectText"
app:iconSpaceReserved="false" />
<Preference
<io.legado.app.ui.widget.prefs.Preference
android:key="customPageKey"
android:title="@string/custom_page_key"
app:iconSpaceReserved="false" />

Loading…
Cancel
Save