diff --git a/app/build.gradle b/app/build.gradle
index d99118fc5..18d4ac8ed 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -37,6 +37,7 @@ android {
versionName version
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
project.ext.set("archivesBaseName", name + "_" + version)
+ multiDexEnabled true
}
buildTypes {
release {
@@ -98,7 +99,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
- implementation 'com.google.android.material:material:1.2.0-alpha02'
+ implementation 'com.google.android.material:material:1.2.0-alpha03'
implementation 'com.google.android:flexbox:1.1.0'
//lifecycle
@@ -107,12 +108,12 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
//room
- def room_version = '2.2.2'
+ def room_version = '2.2.3'
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
//paging
- implementation 'androidx.paging:paging-runtime:2.1.0'
+ implementation 'androidx.paging:paging-runtime:2.1.1'
//anko
def anko_version = '0.10.8'
diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md
index 12171a213..2d01b7c58 100644
--- a/app/src/main/assets/updateLog.md
+++ b/app/src/main/assets/updateLog.md
@@ -4,8 +4,36 @@
* 先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】,提示存储权限,选择允许即可导入成功。
* 注意:由于安卓10更改了权限策略,还需要给「允许安装其他应用」的权限才能导入源。MIUI11也需要此权限。
+**2020/01/03**
+* 适配Android 10 权限
+* 导入旧版本配置不在需要存储权限
+* 选择字体不在需要存储权限
+
+**2019/12/30**
+* 修改书源调试
+ - 调试搜索>>输入关键字,如:`系统`
+ - 调试发现>>输入发现URL,如:`月票榜::https://www.qidian.com/rank/yuepiao?page={{page}}`
+ - 调试详情页>>输入详情页URL,如:`https://m.qidian.com/book/1015609210`
+ - 调试目录页>>输入目录页URL,如:`++https://www.zhaishuyuan.com/read/30394`
+ - 调试正文页>>输入正文页URL,如:`--https://www.zhaishuyuan.com/chapter/30394/20940996`
+
+* 修改订阅中自动添加style的情景
+ 订阅源的内容规则中存在`
+ ```
+
+**2019/12/28**
+* 添加下载界面
+* 添加分组备份
+
**2019/12/23**
* 修复每次打开翻页模式恢复默认的bug
+* 修复m3u8报错问题
**2019/12/22**
* 更新音频播放界面
diff --git a/app/src/main/java/io/legado/app/constant/Bus.kt b/app/src/main/java/io/legado/app/constant/Bus.kt
index 395d51ec4..7795773e6 100644
--- a/app/src/main/java/io/legado/app/constant/Bus.kt
+++ b/app/src/main/java/io/legado/app/constant/Bus.kt
@@ -18,4 +18,6 @@ object Bus {
const val AUDIO_SIZE = "audioSize"
const val AUDIO_SPEED = "audioSpeed"
const val SHOW_RSS = "showRss"
+ const val WEB_SERVICE_STOP = "webServiceStop"
+ const val UP_DOWNLOAD = "upDownload"
}
\ No newline at end of file
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 4217e376d..0d8cad7cf 100644
--- a/app/src/main/java/io/legado/app/constant/PreferKey.kt
+++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt
@@ -15,4 +15,7 @@ object PreferKey {
const val cleanCache = "cleanCache"
const val lastGroup = "lastGroup"
const val pageAnim = "pageAnim"
+ const val readBookFont = "readBookFont"
+ const val fontFolder = "fontFolder"
+ const val backupPath = "backupUri"
}
\ 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 42e76ddd6..68de17a66 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
@@ -17,6 +17,9 @@ interface BookDao {
@Query("SELECT * FROM books WHERE origin = '${BookType.local}' order by durChapterTime desc")
fun observeLocal(): LiveData>
+ @Query("SELECT * FROM books WHERE origin <> '${BookType.local}' and type = 0 order by durChapterTime desc")
+ fun observeDownload(): LiveData>
+
@Query("SELECT * FROM books WHERE `group` = :group")
fun observeByGroup(group: Int): LiveData>
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 0078eb26b..c48bd6e6b 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
@@ -16,6 +16,9 @@ interface BookGroupDao {
@get:Query("SELECT MAX(groupId) FROM book_groups")
val maxId: Int
+ @Query("SELECT * FROM book_groups ORDER BY `order`")
+ fun all(): List
+
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg bookGroup: BookGroup)
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 e6f17134a..1ea320505 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -35,13 +35,24 @@ object BookHelp {
FileHelp.getFolder(getBookCachePath())
}
+ @Synchronized
fun saveContent(book: Book, bookChapter: BookChapter, content: String) {
if (content.isEmpty()) return
+ FileHelp.getFolder(getBookFolder(book)).listFiles()?.forEach {
+ if (it.name.startsWith(String.format("%05d", bookChapter.index))) {
+ it.delete()
+ return@forEach
+ }
+ }
val filePath = getChapterPath(book, bookChapter)
val file = FileHelp.getFile(filePath)
file.writeText(content)
}
+ fun getChapterCount(book: Book): Int {
+ return FileHelp.getFolder(getBookFolder(book)).list()?.size ?: 0
+ }
+
fun hasContent(book: Book, bookChapter: BookChapter): Boolean {
val filePath = getChapterPath(book, bookChapter)
runCatching {
@@ -74,11 +85,15 @@ object BookHelp {
}
}
- private fun getChapterPath(book: Book, bookChapter: BookChapter): String {
+ private fun getBookFolder(book: Book): String {
val bookFolder = formatFolderName(book.name + book.bookUrl)
+ return "${getBookCachePath()}${File.separator}$bookFolder"
+ }
+
+ private fun getChapterPath(book: Book, bookChapter: BookChapter): String {
val chapterFile =
String.format("%05d-%s", bookChapter.index, MD5Utils.md5Encode(bookChapter.title))
- return "${getBookCachePath()}${File.separator}$bookFolder${File.separator}$chapterFile.nb"
+ return "${getBookFolder(book)}${File.separator}$chapterFile.nb"
}
private fun formatFolderName(folderName: String): String {
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 7062d1951..53d9a4279 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
@@ -1,9 +1,13 @@
package io.legado.app.help.storage
+import android.content.Context
+import android.net.Uri
+import androidx.documentfile.provider.DocumentFile
import io.legado.app.App
import io.legado.app.R
import io.legado.app.help.FileHelp
import io.legado.app.help.ReadBookConfig
+import io.legado.app.utils.DocumentUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import org.jetbrains.anko.defaultSharedPreferences
@@ -27,8 +31,52 @@ object Backup {
legadoPath + File.separator + "Export"
}
- private fun pbackup(path :String = legadoPath){
+ fun backup(context: Context, uri: Uri) {
+ DocumentFile.fromTreeUri(context, uri)?.listFiles()?.forEach { doc ->
+ when (doc.name) {
+ "bookshelf.json" -> App.db.bookDao().allBooks.let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ DocumentUtils.writeText(context, json, doc.uri)
+ }
+ }
+ "bookGroup.json" -> App.db.bookGroupDao().all().let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ DocumentUtils.writeText(context, json, doc.uri)
+ }
+ }
+ "bookSource.json" -> App.db.bookSourceDao().all.let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ DocumentUtils.writeText(context, json, doc.uri)
+ }
+ }
+ "rssSource.json" -> App.db.rssSourceDao().all.let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ DocumentUtils.writeText(context, json, doc.uri)
+ }
+ }
+ "replaceRule.json" -> App.db.replaceRuleDao().all.let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ DocumentUtils.writeText(context, json, doc.uri)
+ }
+ }
+ ReadBookConfig.readConfigFileName -> GSON.toJson(ReadBookConfig.configList)?.let {
+ DocumentUtils.writeText(context, it, doc.uri)
+ }
+ "config.xml" -> {
+
+ }
+ }
+ }
+ }
+
+ private fun pBackup(path: String = legadoPath) {
backupBookshelf(path)
+ backupBookGroup(path)
backupBookSource(path)
backupRssSource(path)
backupReplaceRule(path)
@@ -39,7 +87,7 @@ object Backup {
fun backup() {
doAsync {
- pbackup()
+ pBackup()
uiThread {
App.INSTANCE.toast(R.string.backup_success)
}
@@ -48,7 +96,7 @@ object Backup {
fun autoBackup() {
doAsync {
- pbackup()
+ pBackup()
}
}
@@ -56,13 +104,22 @@ object Backup {
App.db.bookDao().allBooks.let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
-
val file = FileHelp.getFile(path + File.separator + "bookshelf.json")
file.writeText(json)
}
}
}
+ private fun backupBookGroup(path: String) {
+ App.db.bookGroupDao().all().let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ val file = FileHelp.getFile(path + File.separator + "bookGroup.json")
+ file.writeText(json)
+ }
+ }
+ }
+
private fun backupBookSource(path: String) {
App.db.bookSourceDao().all.let {
if (it.isNotEmpty()) {
diff --git a/app/src/main/java/io/legado/app/help/storage/OldRule.kt b/app/src/main/java/io/legado/app/help/storage/OldRule.kt
index 0c9baa659..14b4a9c53 100644
--- a/app/src/main/java/io/legado/app/help/storage/OldRule.kt
+++ b/app/src/main/java/io/legado/app/help/storage/OldRule.kt
@@ -205,4 +205,5 @@ object OldRule {
return GSON.toJson(map)
}
+
}
diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt
index 53b040f28..920d61c0d 100644
--- a/app/src/main/java/io/legado/app/help/storage/Restore.kt
+++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt
@@ -9,10 +9,7 @@ import com.jayway.jsonpath.ParseContext
import io.legado.app.App
import io.legado.app.R
import io.legado.app.constant.AppConst
-import io.legado.app.data.entities.Book
-import io.legado.app.data.entities.BookSource
-import io.legado.app.data.entities.ReplaceRule
-import io.legado.app.data.entities.RssSource
+import io.legado.app.data.entities.*
import io.legado.app.help.FileHelp
import io.legado.app.help.ReadBookConfig
import io.legado.app.utils.*
@@ -47,6 +44,15 @@ object Restore {
} catch (e: Exception) {
e.printStackTrace()
}
+ try {
+ val file = FileHelp.getFile(path + File.separator + "bookGroup.json")
+ val json = file.readText()
+ GSON.fromJsonArray(json)?.let {
+ App.db.bookGroupDao().insert(*it.toTypedArray())
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
try {
val file = FileHelp.getFile(path + File.separator + "bookSource.json")
val json = file.readText()
@@ -105,47 +111,12 @@ object Restore {
fun importYueDuData(context: Context) {
GlobalScope.launch(IO) {
try {// 导入书架
- val shelfFile = FileHelp.getFile(Backup.defaultPath + File.separator + "myBookShelf.json")
- val books = mutableListOf()
- val items: List