修复加载更多提示无限循环的问题
修复上传文件JSON解析NPE的问题 修复书架数据双重过滤的问题 修复备份恢复重复插入崩溃的问题 修复RSS加载状态缺失问题
This commit is contained in:
@@ -130,13 +130,22 @@ object Restore {
|
||||
appDb.bookDao.insert(*newBooks.toTypedArray())
|
||||
}
|
||||
fileToListT<Bookmark>(path, "bookmark.json")?.let {
|
||||
appDb.bookmarkDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.bookmarkDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<BookGroup>(path, "bookGroup.json")?.let {
|
||||
appDb.bookGroupDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.bookGroupDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<BookSource>(path, "bookSource.json")?.let {
|
||||
appDb.bookSourceDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.bookSourceDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
} ?: run {
|
||||
val bookSourceFile = File(path, "bookSource.json")
|
||||
if (bookSourceFile.exists()) {
|
||||
@@ -145,54 +154,92 @@ object Restore {
|
||||
}
|
||||
}
|
||||
fileToListT<RssSource>(path, "rssSources.json")?.let {
|
||||
appDb.rssSourceDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.rssSourceDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<RssStar>(path, "rssStar.json")?.let {
|
||||
appDb.rssStarDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.rssStarDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<ReplaceRule>(path, "replaceRule.json")?.let {
|
||||
appDb.replaceRuleDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.replaceRuleDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<SearchKeyword>(path, "searchHistory.json")?.let {
|
||||
appDb.searchKeywordDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.searchKeywordDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<RuleSub>(path, "sourceSub.json")?.let {
|
||||
appDb.ruleSubDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.ruleSubDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<TxtTocRule>(path, "txtTocRule.json")?.let {
|
||||
appDb.txtTocRuleDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.txtTocRuleDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<HttpTTS>(path, "httpTTS.json")?.let {
|
||||
appDb.httpTTSDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.httpTTSDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<DictRule>(path, "dictRule.json")?.let {
|
||||
appDb.dictRuleDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.dictRuleDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<KeyboardAssist>(path, "keyboardAssists.json")?.let {
|
||||
appDb.keyboardAssistsDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.keyboardAssistsDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
fileToListT<ReadRecord>(path, "readRecord.json")?.let {
|
||||
it.forEach { readRecord ->
|
||||
//判断是不是本机记录
|
||||
if (readRecord.deviceId != androidId) {
|
||||
appDb.readRecordDao.insert(readRecord)
|
||||
try {
|
||||
appDb.readRecordDao.insert(readRecord)
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
} else {
|
||||
val time = appDb.readRecordDao
|
||||
.getReadTime(readRecord.deviceId, readRecord.bookName, readRecord.bookAuthor)
|
||||
if (time == null || time < readRecord.readTime) {
|
||||
appDb.readRecordDao.insert(readRecord)
|
||||
try {
|
||||
appDb.readRecordDao.insert(readRecord)
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fileToListT<ReadRecordDetail>(path, "readRecordDetail.json")?.let {
|
||||
it.forEach { detail ->
|
||||
appDb.readRecordDao.insertDetail(detail)
|
||||
try {
|
||||
appDb.readRecordDao.insertDetail(detail)
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
fileToListT<ReadRecordSession>(path, "readRecordSession.json")?.let {
|
||||
it.forEach { session ->
|
||||
appDb.readRecordDao.insertSession(session)
|
||||
try {
|
||||
appDb.readRecordDao.insertSession(session)
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
File(path, "servers.json").takeIf {
|
||||
@@ -203,7 +250,10 @@ object Restore {
|
||||
json = aes.decryptStr(json)
|
||||
}
|
||||
GSON.fromJsonArray<Server>(json).getOrNull()?.let {
|
||||
appDb.serverDao.insert(*it.toTypedArray())
|
||||
try {
|
||||
appDb.serverDao.insert(*it.toTypedArray())
|
||||
} catch (_: SQLiteConstraintException) {
|
||||
}
|
||||
}
|
||||
}?.onFailure {
|
||||
AppLog.put("恢复服务器配置出错\n${it.localizedMessage}", it)
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.legado.app.constant.AppConst.UA_NAME
|
||||
import io.legado.app.constant.AppPattern
|
||||
import io.legado.app.data.entities.BaseSource
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.data.entities.BookChapter
|
||||
import io.legado.app.help.CacheManager
|
||||
import io.legado.app.help.ConcurrentRateLimiter
|
||||
@@ -668,9 +669,10 @@ class AnalyzeUrl(
|
||||
* 上传文件
|
||||
*/
|
||||
suspend fun upload(fileName: String, file: Any, contentType: String): StrResponse {
|
||||
val bodyMap = GSON.fromJsonObject<HashMap<String, Any>>(body).getOrNull()
|
||||
?: return getErrStrResponse(NoStackTraceException("请求体不是合法的JSON格式"))
|
||||
return getProxyClient(proxy).newCallStrResponse(retry) {
|
||||
url(urlNoQuery)
|
||||
val bodyMap = GSON.fromJsonObject<HashMap<String, Any>>(body).getOrNull()!!
|
||||
bodyMap.forEach { entry ->
|
||||
if (entry.value.toString() == "fileRequest") {
|
||||
bodyMap[entry.key] = mapOf(
|
||||
|
||||
@@ -86,7 +86,6 @@ import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
import io.legado.app.ui.main.bookCoverSharedElementKey
|
||||
import kotlinx.coroutines.delay
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@@ -563,10 +562,7 @@ fun LoadMoreFooter(
|
||||
|
||||
LaunchedEffect(isLoading, errorMsg, isEnd) {
|
||||
if (!isLoading && errorMsg == null && !isEnd) {
|
||||
while (true) {
|
||||
onRetry()
|
||||
delay(1000L)
|
||||
}
|
||||
onRetry()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -397,14 +397,14 @@ class BookshelfViewModel(
|
||||
|
||||
val uiState: StateFlow<BookshelfUiState> = combine(
|
||||
dataStateFlow,
|
||||
interactionStateFlow
|
||||
) { data, interaction ->
|
||||
interactionStateFlow,
|
||||
visibleBooksFlow
|
||||
) { data, interaction, filteredBooks ->
|
||||
val books = data.books
|
||||
val groups = data.groups
|
||||
val allGroups = data.allGroups
|
||||
val previews = data.previews
|
||||
val internal = data.internal
|
||||
val filteredBooks = filterBooks(books, internal.searchKey, internal.isSearchMode)
|
||||
val selectedGroupIndex = groups.indexOfFirst { it.groupId == internal.groupId }
|
||||
.coerceAtLeast(0)
|
||||
val currentGroupName = allGroups.firstOrNull { it.groupId == internal.groupId }?.groupName
|
||||
|
||||
@@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
@@ -35,6 +36,7 @@ class RssViewModel(
|
||||
val effects = _effects.asSharedFlow()
|
||||
|
||||
init {
|
||||
_uiState.update { it.copy(isLoading = true) }
|
||||
initGroupData()
|
||||
initRssData()
|
||||
}
|
||||
@@ -62,7 +64,10 @@ class RssViewModel(
|
||||
}
|
||||
.flowOn(IO)
|
||||
.onEach { sources ->
|
||||
_uiState.update { state -> state.copy(items = sources.toImmutableList()) }
|
||||
_uiState.update { state -> state.copy(items = sources.toImmutableList(), isLoading = false) }
|
||||
}
|
||||
.catch {
|
||||
_uiState.update { it.copy(isLoading = false) }
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user