mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化进度同步逻辑,减少同步次数
This commit is contained in:
1898
app/schemas/io.legado.app.data.AppDatabase/71.json
Normal file
1898
app/schemas/io.legado.app.data.AppDatabase/71.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ import com.google.gson.Gson
|
||||
import io.legado.app.api.controller.BookController
|
||||
import io.legado.app.api.controller.BookSourceController
|
||||
import io.legado.app.api.controller.RssSourceController
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
/**
|
||||
* Export book data to other app.
|
||||
@@ -76,28 +77,36 @@ class ReaderProvider : ContentProvider() {
|
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? {
|
||||
if (sMatcher.match(uri) < 0) return null
|
||||
when (RequestCode.values()[sMatcher.match(uri)]) {
|
||||
RequestCode.SaveBookSource -> values?.let {
|
||||
BookSourceController.saveSource(values.getAsString(postBodyKey))
|
||||
runBlocking {
|
||||
when (RequestCode.values()[sMatcher.match(uri)]) {
|
||||
RequestCode.SaveBookSource -> values?.let {
|
||||
BookSourceController.saveSource(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
RequestCode.SaveBookSources -> values?.let {
|
||||
BookSourceController.saveSources(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
RequestCode.SaveRssSource -> values?.let {
|
||||
RssSourceController.saveSource(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
RequestCode.SaveRssSources -> values?.let {
|
||||
RssSourceController.saveSources(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
RequestCode.SaveBook -> values?.let {
|
||||
BookController.saveBook(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
RequestCode.SaveBookProgress -> values?.let {
|
||||
BookController.saveBookProgress(values.getAsString(postBodyKey))
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException(
|
||||
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
|
||||
)
|
||||
}
|
||||
RequestCode.SaveBookSources -> values?.let {
|
||||
BookSourceController.saveSources(values.getAsString(postBodyKey))
|
||||
}
|
||||
RequestCode.SaveRssSource -> values?.let {
|
||||
RssSourceController.saveSource(values.getAsString(postBodyKey))
|
||||
}
|
||||
RequestCode.SaveRssSources -> values?.let {
|
||||
RssSourceController.saveSources(values.getAsString(postBodyKey))
|
||||
}
|
||||
RequestCode.SaveBook -> values?.let {
|
||||
BookController.saveBook(values.getAsString(postBodyKey))
|
||||
}
|
||||
RequestCode.SaveBookProgress -> values?.let {
|
||||
BookController.saveBookProgress(values.getAsString(postBodyKey))
|
||||
}
|
||||
else -> throw IllegalStateException(
|
||||
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -204,8 +204,8 @@ object BookController {
|
||||
fun saveBook(postData: String?): ReturnData {
|
||||
val returnData = ReturnData()
|
||||
GSON.fromJsonObject<Book>(postData).getOrNull()?.let { book ->
|
||||
book.save()
|
||||
AppWebDav.uploadBookProgress(book)
|
||||
book.save()
|
||||
return returnData.setData("")
|
||||
}
|
||||
return returnData.setErrorMsg("格式不对")
|
||||
@@ -226,7 +226,7 @@ object BookController {
|
||||
/**
|
||||
* 保存进度
|
||||
*/
|
||||
fun saveBookProgress(postData: String?): ReturnData {
|
||||
suspend fun saveBookProgress(postData: String?): ReturnData {
|
||||
val returnData = ReturnData()
|
||||
GSON.fromJsonObject<BookProgress>(postData)
|
||||
.onFailure { it.printOnDebug() }
|
||||
@@ -236,8 +236,10 @@ object BookController {
|
||||
book.durChapterPos = bookProgress.durChapterPos
|
||||
book.durChapterTitle = bookProgress.durChapterTitle
|
||||
book.durChapterTime = bookProgress.durChapterTime
|
||||
AppWebDav.uploadBookProgress(bookProgress) {
|
||||
book.syncTime = System.currentTimeMillis()
|
||||
}
|
||||
appDb.bookDao.update(book)
|
||||
AppWebDav.uploadBookProgress(bookProgress)
|
||||
ReadBook.book?.let {
|
||||
if (it.name == bookProgress.name &&
|
||||
it.author == bookProgress.author
|
||||
|
||||
@@ -24,7 +24,7 @@ val appDb by lazy {
|
||||
}
|
||||
|
||||
@Database(
|
||||
version = 70,
|
||||
version = 71,
|
||||
exportSchema = true,
|
||||
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
||||
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
||||
@@ -58,7 +58,8 @@ val appDb by lazy {
|
||||
AutoMigration(from = 66, to = 67),
|
||||
AutoMigration(from = 67, to = 68),
|
||||
AutoMigration(from = 68, to = 69),
|
||||
AutoMigration(from = 69, to = 70)
|
||||
AutoMigration(from = 69, to = 70),
|
||||
AutoMigration(from = 70, to = 71),
|
||||
]
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
@@ -90,6 +90,7 @@ data class Book(
|
||||
// 最近一次阅读书籍的时间(打开正文的时间)
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var durChapterTime: Long = System.currentTimeMillis(),
|
||||
//字数
|
||||
override var wordCount: String? = null,
|
||||
// 刷新书架时更新书籍信息
|
||||
@ColumnInfo(defaultValue = "1")
|
||||
@@ -102,7 +103,11 @@ data class Book(
|
||||
var originOrder: Int = 0,
|
||||
// 自定义书籍变量信息(用于书源规则检索书籍信息)
|
||||
override var variable: String? = null,
|
||||
var readConfig: ReadConfig? = null
|
||||
//阅读设置
|
||||
var readConfig: ReadConfig? = null,
|
||||
//同步时间
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var syncTime: Long = 0L
|
||||
) : Parcelable, BaseBook {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
@@ -211,21 +211,23 @@ object AppWebDav {
|
||||
val json = GSON.toJson(bookProgress)
|
||||
val url = getProgressUrl(book.name, book.author)
|
||||
WebDav(url, authorization).upload(json.toByteArray(), "application/json")
|
||||
book.syncTime = System.currentTimeMillis()
|
||||
}.onError {
|
||||
AppLog.put("上传进度失败\n${it.localizedMessage}", it)
|
||||
}
|
||||
}
|
||||
|
||||
fun uploadBookProgress(bookProgress: BookProgress) {
|
||||
val authorization = authorization ?: return
|
||||
if (!AppConfig.syncBookProgress) return
|
||||
if (!NetworkUtils.isAvailable()) return
|
||||
Coroutine.async {
|
||||
suspend fun uploadBookProgress(bookProgress: BookProgress, onSuccess: (() -> Unit)? = null) {
|
||||
try {
|
||||
val authorization = authorization ?: return
|
||||
if (!AppConfig.syncBookProgress) return
|
||||
if (!NetworkUtils.isAvailable()) return
|
||||
val json = GSON.toJson(bookProgress)
|
||||
val url = getProgressUrl(bookProgress.name, bookProgress.author)
|
||||
WebDav(url, authorization).upload(json.toByteArray(), "application/json")
|
||||
}.onError {
|
||||
AppLog.put("上传进度失败\n${it.localizedMessage}", it)
|
||||
onSuccess?.invoke()
|
||||
} catch (e: Exception) {
|
||||
AppLog.put("上传进度失败\n${e.localizedMessage}", e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,12 +262,19 @@ object AppWebDav {
|
||||
suspend fun downloadAllBookProgress() {
|
||||
val authorization = authorization ?: return
|
||||
if (!NetworkUtils.isAvailable()) return
|
||||
val bookProgressFiles = WebDav(bookProgressUrl, authorization).listFiles().map {
|
||||
it.displayName
|
||||
}.toHashSet()
|
||||
val bookProgressFiles = WebDav(bookProgressUrl, authorization).listFiles()
|
||||
val map = hashMapOf<String, WebDavFile>()
|
||||
bookProgressFiles.forEach {
|
||||
map[it.displayName] = it
|
||||
}
|
||||
appDb.bookDao.all.forEach { book ->
|
||||
val progressFileName = getProgressFileName(book.name, book.author)
|
||||
if (!bookProgressFiles.contains(progressFileName)) return@forEach
|
||||
val webDavFile = map[progressFileName]
|
||||
webDavFile ?: return
|
||||
if (webDavFile.lastModify <= book.syncTime) {
|
||||
//本地同步时间大于上传时间不用同步
|
||||
return
|
||||
}
|
||||
getBookProgress(book)?.let { bookProgress ->
|
||||
if (bookProgress.durChapterIndex > book.durChapterIndex
|
||||
|| (bookProgress.durChapterIndex == book.durChapterIndex
|
||||
@@ -275,6 +284,7 @@ object AppWebDav {
|
||||
book.durChapterPos = bookProgress.durChapterPos
|
||||
book.durChapterTitle = bookProgress.durChapterTitle
|
||||
book.durChapterTime = bookProgress.durChapterTime
|
||||
book.syncTime = System.currentTimeMillis()
|
||||
appDb.bookDao.update(book)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
book?.let {
|
||||
Coroutine.async {
|
||||
AppWebDav.uploadBookProgress(it)
|
||||
it.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,6 +1312,7 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
delay(300000)
|
||||
ReadBook.book?.let {
|
||||
AppWebDav.uploadBookProgress(it)
|
||||
it.save()
|
||||
Backup.autoBack(this@ReadBookActivity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,18 @@ import io.legado.app.api.controller.ReplaceRuleController
|
||||
import io.legado.app.api.controller.RssSourceController
|
||||
import io.legado.app.help.coroutine.Coroutine
|
||||
import io.legado.app.service.WebService
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.GSON
|
||||
import io.legado.app.web.utils.AssetsWeb
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okio.Pipe
|
||||
import okio.buffer
|
||||
import java.io.*
|
||||
import java.io.BufferedWriter
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.OutputStreamWriter
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.set
|
||||
|
||||
class HttpServer(port: Int) : NanoHTTPD(port) {
|
||||
private val assetsWeb = AssetsWeb("web")
|
||||
@@ -41,22 +48,24 @@ class HttpServer(port: Int) : NanoHTTPD(port) {
|
||||
session.parseBody(files)
|
||||
val postData = files["postData"]
|
||||
|
||||
returnData = when (uri) {
|
||||
"/saveBookSource" -> BookSourceController.saveSource(postData)
|
||||
"/saveBookSources" -> BookSourceController.saveSources(postData)
|
||||
"/deleteBookSources" -> BookSourceController.deleteSources(postData)
|
||||
"/saveBook" -> BookController.saveBook(postData)
|
||||
"/deleteBook" -> BookController.deleteBook(postData)
|
||||
"/saveBookProgress" -> BookController.saveBookProgress(postData)
|
||||
"/addLocalBook" -> BookController.addLocalBook(session.parameters)
|
||||
"/saveReadConfig" -> BookController.saveWebReadConfig(postData)
|
||||
"/saveRssSource" -> RssSourceController.saveSource(postData)
|
||||
"/saveRssSources" -> RssSourceController.saveSources(postData)
|
||||
"/deleteRssSources" -> RssSourceController.deleteSources(postData)
|
||||
"/saveReplaceRule" -> ReplaceRuleController.saveRule(postData)
|
||||
"/deleteReplaceRule" -> ReplaceRuleController.delete(postData)
|
||||
"/testReplaceRule" -> ReplaceRuleController.testRule(postData)
|
||||
else -> null
|
||||
returnData = runBlocking {
|
||||
when (uri) {
|
||||
"/saveBookSource" -> BookSourceController.saveSource(postData)
|
||||
"/saveBookSources" -> BookSourceController.saveSources(postData)
|
||||
"/deleteBookSources" -> BookSourceController.deleteSources(postData)
|
||||
"/saveBook" -> BookController.saveBook(postData)
|
||||
"/deleteBook" -> BookController.deleteBook(postData)
|
||||
"/saveBookProgress" -> BookController.saveBookProgress(postData)
|
||||
"/addLocalBook" -> BookController.addLocalBook(session.parameters)
|
||||
"/saveReadConfig" -> BookController.saveWebReadConfig(postData)
|
||||
"/saveRssSource" -> RssSourceController.saveSource(postData)
|
||||
"/saveRssSources" -> RssSourceController.saveSources(postData)
|
||||
"/deleteRssSources" -> RssSourceController.deleteSources(postData)
|
||||
"/saveReplaceRule" -> ReplaceRuleController.saveRule(postData)
|
||||
"/deleteReplaceRule" -> ReplaceRuleController.delete(postData)
|
||||
"/testReplaceRule" -> ReplaceRuleController.testRule(postData)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user