diff --git a/README.md b/README.md
index d65e3dbdc..1a035aaf5 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
# legado
## 阅读3.0
+书源规则 https://celeter.github.io/?tdsourcetag=s_pctim_aiomsg
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 23f5edd36..0f1381bf6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -78,6 +78,7 @@
+
@@ -103,6 +104,7 @@
+
【备份与恢复】,选择【导入旧版本数据】。
+**2020/02/05**
+* 修复bug
+* Rss收藏功能完成
+* Rss已读标记不会再丢失
+
+**2020/02/04**
+* 主界面切换时自动隐藏键盘
+* 添加本地书籍完成,解析txt文件完成,本地txt可以看了
+* 封面换源,书籍信息界面点击封面弹出封面换源界面
+* 默认封面绘制书名和作者
+* 修复在线朗读遇到单独标点,停止朗读的问题
+
+**2020/02/02**
+* merged commit e584606, rss修复BaseURL模式下部分图片无法加载, 修复可能出现的乱码
+* 菜单添加网址功能完成
+
**2020/01/31**
-* 正在写本地导入,还没写完
* 修复搜索闪退,因为默认线程为0了
**2020/01/30**
diff --git a/app/src/main/java/io/legado/app/README.md b/app/src/main/java/io/legado/app/README.md
new file mode 100644
index 000000000..b23d4196d
--- /dev/null
+++ b/app/src/main/java/io/legado/app/README.md
@@ -0,0 +1,12 @@
+## 文件结构介绍
+
+* base 基类
+* constant 常量
+* data 数据
+* help 帮助
+* lib 库
+* model 解析
+* receiver 广播侦听
+* service 服务
+* ui 界面
+* web web服务
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/base/BaseService.kt b/app/src/main/java/io/legado/app/base/BaseService.kt
index c67acb95c..163ac09ec 100644
--- a/app/src/main/java/io/legado/app/base/BaseService.kt
+++ b/app/src/main/java/io/legado/app/base/BaseService.kt
@@ -3,17 +3,27 @@ package io.legado.app.base
import android.app.Service
import android.content.Intent
import android.os.IBinder
+import io.legado.app.help.coroutine.Coroutine
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
+import kotlin.coroutines.CoroutineContext
abstract class BaseService : Service(), CoroutineScope by MainScope() {
+ fun execute(
+ scope: CoroutineScope = this,
+ context: CoroutineContext = Dispatchers.IO,
+ block: suspend CoroutineScope.() -> T
+ ): Coroutine {
+ return Coroutine.async(scope, context) { block() }
+ }
+
override fun onBind(intent: Intent?): IBinder? {
return null
}
-
override fun onDestroy() {
super.onDestroy()
cancel()
diff --git a/app/src/main/java/io/legado/app/constant/Bus.kt b/app/src/main/java/io/legado/app/constant/EventBus.kt
similarity index 97%
rename from app/src/main/java/io/legado/app/constant/Bus.kt
rename to app/src/main/java/io/legado/app/constant/EventBus.kt
index eb1dd14dd..3fc80e3ac 100644
--- a/app/src/main/java/io/legado/app/constant/Bus.kt
+++ b/app/src/main/java/io/legado/app/constant/EventBus.kt
@@ -1,6 +1,6 @@
package io.legado.app.constant
-object Bus {
+object EventBus {
const val MEDIA_BUTTON = "mediaButton"
const val RECREATE = "RECREATE"
const val UP_BOOK = "sourceDebugLog"
diff --git a/app/src/main/java/io/legado/app/constant/Action.kt b/app/src/main/java/io/legado/app/constant/IntentAction.kt
similarity index 96%
rename from app/src/main/java/io/legado/app/constant/Action.kt
rename to app/src/main/java/io/legado/app/constant/IntentAction.kt
index a13a8cca3..0dffe87a1 100644
--- a/app/src/main/java/io/legado/app/constant/Action.kt
+++ b/app/src/main/java/io/legado/app/constant/IntentAction.kt
@@ -1,6 +1,6 @@
package io.legado.app.constant
-object Action {
+object IntentAction {
const val start = "start"
const val play = "play"
const val stop = "stop"
diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt
index 1cb5e2edc..ec5b3a4cd 100644
--- a/app/src/main/java/io/legado/app/constant/PreferKey.kt
+++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt
@@ -1,12 +1,17 @@
package io.legado.app.constant
object PreferKey {
-
+ const val versionCode = "versionCode"
+ const val themeMode = "themeMode"
const val downloadPath = "downloadPath"
const val hideStatusBar = "hideStatusBar"
const val clickAllNext = "clickAllNext"
const val hideNavigationBar = "hideNavigationBar"
const val precisionSearch = "precisionSearch"
+ const val readAloudOnLine = "readAloudOnLine"
+ const val readAloudByPage = "readAloudByPage"
+ const val ttsSpeechRate = "ttsSpeechRate"
+ const val ttsSpeechPer = "ttsSpeechPer"
const val prevKey = "prevKeyCode"
const val nextKey = "nextKeyCode"
const val showRss = "showRss"
@@ -21,5 +26,8 @@ object PreferKey {
const val backupPath = "backupUri"
const val threadCount = "threadCount"
const val keepLight = "keep_light"
- const val autoDarkMode = "autoDarkMode"
+ const val webService = "webService"
+ const val webDavUrl = "web_dav_url"
+ const val webDavAccount = "web_dav_account"
+ const val webDavPassword = "web_dav_password"
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/AppDatabase.kt b/app/src/main/java/io/legado/app/data/AppDatabase.kt
index eb44e9381..e548f4584 100644
--- a/app/src/main/java/io/legado/app/data/AppDatabase.kt
+++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt
@@ -16,8 +16,9 @@ import kotlinx.coroutines.launch
@Database(
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
- RssSource::class, Bookmark::class, RssArticle::class, RssStar::class],
- version = 6,
+ RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class,
+ RssStar::class, TxtTocRule::class],
+ version = 8,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
@@ -50,4 +51,5 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun rssArticleDao(): RssArticleDao
abstract fun rssStarDao(): RssStarDao
abstract fun cookieDao(): CookieDao
+ abstract fun txtTocRule(): TxtTocRuleDao
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/README.md b/app/src/main/java/io/legado/app/data/README.md
index 18061b12d..ec1ddefbe 100644
--- a/app/src/main/java/io/legado/app/data/README.md
+++ b/app/src/main/java/io/legado/app/data/README.md
@@ -1 +1,3 @@
-## 存储数据用
\ No newline at end of file
+## 存储数据用
+* dao 数据操作
+* entities 数据模型
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt
index 303be7d5c..399f79c45 100644
--- a/app/src/main/java/io/legado/app/data/dao/BookDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt
@@ -45,7 +45,7 @@ interface BookDao {
val hasUpdateBooks: List
@get:Query("SELECT * FROM books")
- val allBooks: List
+ val all: List
@get:Query("SELECT * FROM books where type = 0 ORDER BY durChapterTime DESC limit 1")
val lastReadBook: Book?
@@ -60,10 +60,10 @@ interface BookDao {
fun insert(vararg book: Book)
@Update
- fun update(vararg books: Book)
+ fun update(vararg book: Book)
- @Query("delete from books where bookUrl = :bookUrl")
- fun delete(bookUrl: String)
+ @Delete
+ fun delete(vararg book: Book)
@Query("update books set durChapterPos = :pos where bookUrl = :bookUrl")
fun upProgress(bookUrl: String, pos: Int)
diff --git a/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt b/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt
index b06e7ac9e..af15188bb 100644
--- a/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt
@@ -19,8 +19,8 @@ interface BookGroupDao {
@get:Query("SELECT MAX(`order`) FROM book_groups")
val maxOrder: Int
- @Query("SELECT * FROM book_groups ORDER BY `order`")
- fun all(): List
+ @get:Query("SELECT * FROM book_groups ORDER BY `order`")
+ val all: List
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg bookGroup: BookGroup)
diff --git a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt
index f76ed3d13..ce8dfe950 100644
--- a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt
@@ -29,21 +29,6 @@ interface BookSourceDao {
@Query("select distinct enabled from book_sources where bookSourceName like :searchKey or bookSourceGroup like :searchKey or bookSourceUrl like :searchKey")
fun searchIsEnable(searchKey: String = ""): List
- @Query("update book_sources set enabled = 1 where bookSourceUrl = :sourceUrl")
- fun enableSection(sourceUrl: String)
-
- @Query("update book_sources set enabled = 0 where bookSourceUrl = :sourceUrl")
- fun disableSection(sourceUrl: String)
-
- @Query("update book_sources set enabledExplore = 1 where bookSourceUrl = :sourceUrl")
- fun enableSectionExplore(sourceUrl: String)
-
- @Query("update book_sources set enabledExplore = 0 where bookSourceUrl = :sourceUrl")
- fun disableSectionExplore(sourceUrl: String)
-
- @Query("delete from book_sources where bookSourceUrl = :sourceUrl")
- fun delSection(sourceUrl: String)
-
@Query("select * from book_sources where enabledExplore = 1 order by customOrder asc")
fun observeFind(): DataSource.Factory
@@ -53,6 +38,9 @@ interface BookSourceDao {
@Query("select * from book_sources where enabled = 1 and bookSourceGroup like '%' || :group || '%'")
fun getEnabledByGroup(group: String): List
+ @get:Query("select * from book_sources where bookUrlPattern is not null || bookUrlPattern <> ''")
+ val hasBookUrlPattern: List
+
@get:Query("select * from book_sources where bookSourceGroup is null or bookSourceGroup = ''")
val noGroup: List
@@ -75,7 +63,7 @@ interface BookSourceDao {
fun update(vararg bookSource: BookSource)
@Delete
- fun delete(bookSource: BookSource)
+ fun delete(vararg bookSource: BookSource)
@Query("delete from book_sources where bookSourceUrl = :key")
fun delete(key: String)
diff --git a/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt b/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
index 247a5be6e..fbf3c3611 100644
--- a/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/RssArticleDao.kt
@@ -3,6 +3,7 @@ package io.legado.app.data.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import io.legado.app.data.entities.RssArticle
+import io.legado.app.data.entities.RssReadRecord
@Dao
interface RssArticleDao {
@@ -10,7 +11,11 @@ interface RssArticleDao {
@Query("select * from rssArticles where origin = :origin and link = :link")
fun get(origin: String, link: String): RssArticle?
- @Query("select * from rssArticles where origin = :origin order by `order` desc")
+ @Query(
+ """select t1.link, t1.origin, t1.`order`, t1.title, t1.content, t1.description, t1.image, t1.pubDate, ifNull(t2.read, 0) as read
+ from rssArticles as t1 left join rssReadRecords as t2
+ on t1.link = t2.record where origin = :origin order by `order` desc"""
+ )
fun liveByOrigin(origin: String): LiveData>
@Insert(onConflict = OnConflictStrategy.REPLACE)
@@ -24,4 +29,9 @@ interface RssArticleDao {
@Query("delete from rssArticles where origin = :origin")
fun delete(origin: String)
+
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ fun insertRecord(vararg rssReadRecord: RssReadRecord)
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/dao/RssStarDao.kt b/app/src/main/java/io/legado/app/data/dao/RssStarDao.kt
index 87e527f75..faaf85b9f 100644
--- a/app/src/main/java/io/legado/app/data/dao/RssStarDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/RssStarDao.kt
@@ -7,6 +7,9 @@ import io.legado.app.data.entities.RssStar
@Dao
interface RssStarDao {
+ @get:Query("select * from rssStars order by starTime desc")
+ val all: List
+
@Query("select * from rssStars where origin = :origin and link = :link")
fun get(origin: String, link: String): RssStar?
diff --git a/app/src/main/java/io/legado/app/data/dao/SearchBookDao.kt b/app/src/main/java/io/legado/app/data/dao/SearchBookDao.kt
index 7e623bfcc..fd3f69951 100644
--- a/app/src/main/java/io/legado/app/data/dao/SearchBookDao.kt
+++ b/app/src/main/java/io/legado/app/data/dao/SearchBookDao.kt
@@ -28,6 +28,14 @@ interface SearchBookDao {
@Query("select * from searchBooks where name = :name and author = :author and origin in (select bookSourceUrl from book_sources where enabled = 1) order by originOrder")
fun getByNameAuthorEnable(name: String, author: String): List
+ @Query(
+ """select * from searchBooks
+ where name = :name and author = :author and origin in (select bookSourceUrl from book_sources where enabled = 1)
+ and coverUrl is not null and coverUrl <> ''
+ order by originOrder"""
+ )
+ fun getEnableHasCover(name: String, author: String): List
+
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg searchBook: SearchBook): List
diff --git a/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt b/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt
new file mode 100644
index 000000000..119daa651
--- /dev/null
+++ b/app/src/main/java/io/legado/app/data/dao/TxtTocRuleDao.kt
@@ -0,0 +1,20 @@
+package io.legado.app.data.dao
+
+import androidx.room.*
+import io.legado.app.data.entities.TxtTocRule
+
+@Dao
+interface TxtTocRuleDao {
+
+ @get:Query("select * from txtTocRules order by serialNumber")
+ val all: List
+
+ @get:Query("select * from txtTocRules where enable = 1 order by serialNumber")
+ val enabled: List
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(vararg rule: TxtTocRule)
+
+ @Delete
+ fun delete(vararg rule: TxtTocRule)
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt
index f01d95bce..204d2de7a 100644
--- a/app/src/main/java/io/legado/app/data/entities/Book.kt
+++ b/app/src/main/java/io/legado/app/data/entities/Book.kt
@@ -10,6 +10,7 @@ import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
+import java.nio.charset.Charset
import kotlin.math.max
@Parcelize
@@ -19,15 +20,15 @@ data class Book(
var bookUrl: String = "", // 详情页Url(本地书源存储完整文件路径)
var tocUrl: String = "", // 目录页Url (toc=table of Contents)
var origin: String = BookType.local, // 书源URL(默认BookType.local)
- var originName: String = "", //书源名称
- var name: String = "", // 书籍名称(书源获取)
- var author: String = "", // 作者名称(书源获取)
- override var kind: String? = null, // 分类信息(书源获取)
+ var originName: String = "", //书源名称 or 本地书籍文件名
+ var name: String = "", // 书籍名称(书源获取)
+ var author: String = "", // 作者名称(书源获取)
+ override var kind: String? = null, // 分类信息(书源获取)
var customTag: String? = null, // 分类信息(用户修改)
var coverUrl: String? = null, // 封面Url(书源获取)
var customCoverUrl: String? = null, // 封面Url(用户修改)
- var intro: String? = null, // 简介内容(书源获取)
- var customIntro: String? = null, // 简介内容(用户修改)
+ var intro: String? = null, // 简介内容(书源获取)
+ var customIntro: String? = null, // 简介内容(用户修改)
var charset: String? = null, // 自定义字符集名称(仅适用于本地书籍)
var type: Int = 0, // @BookType
var group: Int = 0, // 自定义分组索引号
@@ -52,6 +53,10 @@ data class Book(
return origin == BookType.local
}
+ fun isTxt(): Boolean {
+ return isLocalBook() && originName.endsWith(".txt", true)
+ }
+
@Ignore
@IgnoredOnParcel
override var variableMap: HashMap? = null
@@ -81,6 +86,10 @@ data class Book(
variable = GSON.toJson(variableMap)
}
+ fun fileCharset(): Charset {
+ return charset(charset ?: "UTF-8")
+ }
+
fun toSearchBook(): SearchBook {
return SearchBook(
name = name,
diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt
index 39b569565..78852a4ec 100644
--- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt
+++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt
@@ -47,6 +47,18 @@ data class BookSource(
var ruleToc: String? = null, // 目录页规则
var ruleContent: String? = null // 正文页规则
) : Parcelable, JsExtensions {
+
+ override fun hashCode(): Int {
+ return bookSourceUrl.hashCode()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (other is BookSource) {
+ return other.bookSourceUrl == bookSourceUrl
+ }
+ return false
+ }
+
@Ignore
@IgnoredOnParcel
private var searchRuleV: SearchRule? = null
@@ -126,6 +138,16 @@ data class BookSource(
return contentRuleV!!
}
+ fun addGroup(group: String) {
+ bookSourceGroup?.let {
+ if (!it.contains(group)) {
+ bookSourceGroup = "$it;$group"
+ }
+ } ?: let {
+ bookSourceGroup = group
+ }
+ }
+
fun getExploreKinds(): ArrayList? {
val exploreKinds = arrayListOf()
exploreUrl?.let {
diff --git a/app/src/main/java/io/legado/app/data/entities/RssReadRecord.kt b/app/src/main/java/io/legado/app/data/entities/RssReadRecord.kt
new file mode 100644
index 000000000..edbb4c15d
--- /dev/null
+++ b/app/src/main/java/io/legado/app/data/entities/RssReadRecord.kt
@@ -0,0 +1,7 @@
+package io.legado.app.data.entities
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "rssReadRecords")
+data class RssReadRecord(@PrimaryKey val record: String, val read: Boolean = true)
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt b/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt
new file mode 100644
index 000000000..c9cd51d4d
--- /dev/null
+++ b/app/src/main/java/io/legado/app/data/entities/TxtTocRule.kt
@@ -0,0 +1,14 @@
+package io.legado.app.data.entities
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+
+@Entity(tableName = "txtTocRules")
+data class TxtTocRule(
+ @PrimaryKey
+ var name: String = "",
+ var rule: String = "",
+ var serialNumber: Int,
+ var enable: Boolean = true
+)
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt
index f8eb4f62e..e1f80dfb5 100644
--- a/app/src/main/java/io/legado/app/help/AppConfig.kt
+++ b/app/src/main/java/io/legado/app/help/AppConfig.kt
@@ -8,7 +8,7 @@ object AppConfig {
var isNightTheme: Boolean
get() {
- return when (App.INSTANCE.getPrefString("themeMode", "0")) {
+ return when (App.INSTANCE.getPrefString(PreferKey.themeMode, "0")) {
"1" -> false
"2" -> true
else -> App.INSTANCE.sysIsDarkMode()
@@ -16,9 +16,9 @@ object AppConfig {
}
set(value) {
if (value) {
- App.INSTANCE.putPrefString("themeMode", "2")
+ App.INSTANCE.putPrefString(PreferKey.themeMode, "2")
} else {
- App.INSTANCE.putPrefString("themeMode", "1")
+ App.INSTANCE.putPrefString(PreferKey.themeMode, "1")
}
}
@@ -50,6 +50,17 @@ object AppConfig {
}
}
+ var ttsSpeechRate: Int
+ get() = App.INSTANCE.getPrefInt(PreferKey.ttsSpeechRate, 5)
+ set(value) {
+ App.INSTANCE.putPrefInt(PreferKey.ttsSpeechRate, value)
+ }
+
+ val ttsSpeechPer: String
+ get() = App.INSTANCE.getPrefString(PreferKey.ttsSpeechPer) ?: "0"
+
val isEInkMode: Boolean
get() = App.INSTANCE.getPrefBoolean("isEInkMode")
+
+ val clickAllNext: Boolean get() = App.INSTANCE.getPrefBoolean(PreferKey.clickAllNext, false)
}
diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt
index 7635df1f7..de8c0a5a7 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -7,6 +7,7 @@ import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.ReplaceRule
+import io.legado.app.model.localBook.AnalyzeTxtFile
import io.legado.app.utils.*
import org.apache.commons.text.similarity.JaccardSimilarity
import java.io.File
@@ -14,7 +15,7 @@ import kotlin.math.min
object BookHelp {
private const val cacheFolderName = "book_cache"
- private var downloadPath: String =
+ var downloadPath: String =
App.INSTANCE.getPrefString(PreferKey.downloadPath)
?: App.INSTANCE.getExternalFilesDir(null)?.absolutePath
?: App.INSTANCE.cacheDir.absolutePath
@@ -37,7 +38,7 @@ object BookHelp {
}
fun clearCache() {
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
+ if (downloadPath.isContentPath()) {
DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)
?.findFile(cacheFolderName)
?.delete()
@@ -54,15 +55,17 @@ object BookHelp {
@Synchronized
fun saveContent(book: Book, bookChapter: BookChapter, content: String) {
if (content.isEmpty()) return
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
+ if (downloadPath.isContentPath()) {
DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
DocumentUtils.getDirDocument(
root,
subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.listFiles()?.forEach {
- if (it.name?.startsWith(String.format("%05d", bookChapter.index)) == true) {
- it.delete()
- return@forEach
+ )?.uri?.let { uri ->
+ DocumentUtils.listFiles(App.INSTANCE, uri).forEach {
+ if (it.name.startsWith(String.format("%05d", bookChapter.index))) {
+ DocumentFile.fromSingleUri(App.INSTANCE, it.uri)?.delete()
+ return@forEach
+ }
}
}
DocumentUtils.createFileIfNotExist(
@@ -90,7 +93,7 @@ object BookHelp {
}
fun getChapterCount(book: Book): Int {
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
+ if (downloadPath.isContentPath()) {
DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
return DocumentUtils.createFolderIfNotExist(
root,
@@ -107,61 +110,77 @@ object BookHelp {
}
fun hasContent(book: Book, bookChapter: BookChapter): Boolean {
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- return DocumentUtils.exists(
- root,
+ when {
+ book.isLocalBook() -> {
+ return true
+ }
+ downloadPath.isContentPath() -> {
+ DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
+ return DocumentUtils.exists(
+ root,
+ "${bookChapterName(bookChapter)}.nb",
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )
+ }
+ }
+ else -> {
+ return FileUtils.exists(
+ File(downloadPath),
"${bookChapterName(bookChapter)}.nb",
subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
)
}
- } else {
- return FileUtils.exists(
- File(downloadPath),
- "${bookChapterName(bookChapter)}.nb",
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )
}
return false
}
fun getContent(book: Book, bookChapter: BookChapter): String? {
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- return DocumentUtils.getDirDocument(
- root,
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.findFile("${bookChapterName(bookChapter)}.nb")
- ?.uri?.readText(App.INSTANCE)
+ when {
+ book.isLocalBook() -> {
+ return AnalyzeTxtFile.getContent(book, bookChapter)
}
- } else {
- val file = FileUtils.getFile(
- File(downloadPath),
- "${bookChapterName(bookChapter)}.nb",
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )
- if (file.exists()) {
- return file.readText()
+ downloadPath.isContentPath() -> {
+ DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
+ return DocumentUtils.getDirDocument(
+ root,
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )?.findFile("${bookChapterName(bookChapter)}.nb")
+ ?.uri?.readText(App.INSTANCE)
+ }
+ }
+ else -> {
+ val file = FileUtils.getFile(
+ File(downloadPath),
+ "${bookChapterName(bookChapter)}.nb",
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )
+ if (file.exists()) {
+ return file.readText()
+ }
}
}
return null
}
fun delContent(book: Book, bookChapter: BookChapter) {
- if (downloadUri.isDocumentUri(App.INSTANCE)) {
- DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
- DocumentUtils.getDirDocument(
- root,
+ when {
+ book.isLocalBook() -> return
+ downloadPath.isContentPath() -> {
+ DocumentFile.fromTreeUri(App.INSTANCE, downloadUri)?.let { root ->
+ DocumentUtils.getDirDocument(
+ root,
+ subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
+ )?.findFile("${bookChapterName(bookChapter)}.nb")
+ ?.delete()
+ }
+ }
+ else -> {
+ FileUtils.createFileIfNotExist(
+ File(downloadPath),
+ "${bookChapterName(bookChapter)}.nb",
subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- )?.findFile("${bookChapterName(bookChapter)}.nb")
- ?.delete()
+ ).delete()
}
- } else {
- FileUtils.createFileIfNotExist(
- File(downloadPath),
- "${bookChapterName(bookChapter)}.nb",
- subDirs = *arrayOf(cacheFolderName, bookFolderName(book))
- ).delete()
}
}
diff --git a/app/src/main/java/io/legado/app/help/ImageLoader.kt b/app/src/main/java/io/legado/app/help/ImageLoader.kt
index 26a9063d6..3d4272e9e 100644
--- a/app/src/main/java/io/legado/app/help/ImageLoader.kt
+++ b/app/src/main/java/io/legado/app/help/ImageLoader.kt
@@ -12,13 +12,15 @@ import java.io.File
object ImageLoader {
fun load(context: Context, path: String?): RequestBuilder {
- if (path?.startsWith("http", true) == true) {
- return Glide.with(context).load(path)
+ return when {
+ path.isNullOrEmpty() -> Glide.with(context).load(path)
+ path.startsWith("http", true) -> Glide.with(context).load(path)
+ else -> try {
+ Glide.with(context).load(File(path))
+ } catch (e: Exception) {
+ Glide.with(context).load(path)
+ }
}
- kotlin.runCatching {
- return Glide.with(context).load(File(path))
- }
- return Glide.with(context).load(path)
}
fun load(context: Context, @DrawableRes resId: Int?): RequestBuilder {
diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt
index fd28eea7f..30e77eab6 100644
--- a/app/src/main/java/io/legado/app/help/storage/Backup.kt
+++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt
@@ -36,6 +36,7 @@ object Backup {
"bookGroup.json",
"bookSource.json",
"rssSource.json",
+ "rssStar.json",
"replaceRule.json",
ReadBookConfig.readConfigFileName,
"config.xml"
@@ -44,41 +45,12 @@ object Backup {
suspend fun backup(context: Context, uri: Uri?) {
withContext(IO) {
- App.db.bookDao().allBooks.let {
- if (it.isNotEmpty()) {
- val json = GSON.toJson(it)
- FileUtils.createFileIfNotExist(backupPath + File.separator + "bookshelf.json")
- .writeText(json)
- }
- }
- App.db.bookGroupDao().all().let {
- if (it.isNotEmpty()) {
- val json = GSON.toJson(it)
- FileUtils.createFileIfNotExist(backupPath + File.separator + "bookGroup.json")
- .writeText(json)
- }
- }
- App.db.bookSourceDao().all.let {
- if (it.isNotEmpty()) {
- val json = GSON.toJson(it)
- FileUtils.createFileIfNotExist(backupPath + File.separator + "bookSource.json")
- .writeText(json)
- }
- }
- App.db.rssSourceDao().all.let {
- if (it.isNotEmpty()) {
- val json = GSON.toJson(it)
- FileUtils.createFileIfNotExist(backupPath + File.separator + "rssSource.json")
- .writeText(json)
- }
- }
- App.db.replaceRuleDao().all.let {
- if (it.isNotEmpty()) {
- val json = GSON.toJson(it)
- FileUtils.createFileIfNotExist(backupPath + File.separator + "replaceRule.json")
- .writeText(json)
- }
- }
+ writeListToJson(App.db.bookDao().all, "bookshelf.json", backupPath)
+ writeListToJson(App.db.bookGroupDao().all, "bookGroup.json", backupPath)
+ writeListToJson(App.db.bookSourceDao().all, "bookSource.json", backupPath)
+ writeListToJson(App.db.rssSourceDao().all, "rssSource.json", backupPath)
+ writeListToJson(App.db.rssStarDao().all, "rssStar.json", backupPath)
+ writeListToJson(App.db.replaceRuleDao().all, "replaceRule.json", backupPath)
GSON.toJson(ReadBookConfig.configList)?.let {
FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.readConfigFileName)
.writeText(it)
@@ -106,6 +78,13 @@ object Backup {
}
}
+ private fun writeListToJson(list: List, fileName: String, path: String) {
+ if (list.isNotEmpty()) {
+ val json = GSON.toJson(list)
+ FileUtils.createFileIfNotExist(path + File.separator + fileName).writeText(json)
+ }
+ }
+
private fun copyBackup(context: Context, uri: Uri) {
DocumentFile.fromTreeUri(context, uri)?.let { treeDoc ->
for (fileName in backupFileNames) {
diff --git a/app/src/main/java/io/legado/app/help/storage/OldBook.kt b/app/src/main/java/io/legado/app/help/storage/OldBook.kt
new file mode 100644
index 000000000..f8321973c
--- /dev/null
+++ b/app/src/main/java/io/legado/app/help/storage/OldBook.kt
@@ -0,0 +1,55 @@
+package io.legado.app.help.storage
+
+import android.util.Log
+import io.legado.app.App
+import io.legado.app.constant.AppConst
+import io.legado.app.data.entities.Book
+import io.legado.app.utils.readBool
+import io.legado.app.utils.readInt
+import io.legado.app.utils.readLong
+import io.legado.app.utils.readString
+
+object OldBook {
+
+ fun toNewBook(json: String): List {
+ val books = mutableListOf()
+ val items: List