标签问题
This commit is contained in:
11 files changed
+230
-133
No files matched your search
@@ -98,7 +98,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
where type & ${BookType.text} > 0
|
where type & ${BookType.text} > 0
|
||||||
and type & ${BookType.local} = 0
|
and type & ${BookType.local} = 0
|
||||||
@@ -134,7 +135,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
"""
|
"""
|
||||||
@@ -167,7 +169,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.audio} > 0
|
WHERE type & ${BookType.audio} > 0
|
||||||
"""
|
"""
|
||||||
@@ -200,7 +203,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.local} > 0
|
WHERE type & ${BookType.local} > 0
|
||||||
"""
|
"""
|
||||||
@@ -238,7 +242,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
where type & ${BookType.audio} = 0 and type & ${BookType.local} = 0
|
where type & ${BookType.audio} = 0 and type & ${BookType.local} = 0
|
||||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||||
@@ -277,7 +282,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
where type & ${BookType.local} > 0
|
where type & ${BookType.local} > 0
|
||||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||||
@@ -311,7 +317,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE (`group` & :group) > 0
|
WHERE (`group` & :group) > 0
|
||||||
"""
|
"""
|
||||||
@@ -346,7 +353,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE name like '%'||:key||'%' or author like '%'||:key||'%' or originName like '%'||:key||'%'
|
WHERE name like '%'||:key||'%' or author like '%'||:key||'%' or originName like '%'||:key||'%'
|
||||||
"""
|
"""
|
||||||
@@ -379,7 +387,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
where type & ${BookType.updateError} > 0
|
where type & ${BookType.updateError} > 0
|
||||||
order by durChapterTime desc
|
order by durChapterTime desc
|
||||||
@@ -413,7 +422,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
||||||
"""
|
"""
|
||||||
@@ -446,7 +456,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
||||||
"""
|
"""
|
||||||
@@ -479,7 +490,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
||||||
"""
|
"""
|
||||||
@@ -512,7 +524,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.image} > 0
|
WHERE type & ${BookType.image} > 0
|
||||||
"""
|
"""
|
||||||
@@ -545,7 +558,8 @@ interface BookDao {
|
|||||||
`order`,
|
`order`,
|
||||||
canUpdate,
|
canUpdate,
|
||||||
ifnull(customIntro, intro) as intro,
|
ifnull(customIntro, intro) as intro,
|
||||||
kind
|
kind,
|
||||||
|
wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.text} > 0
|
WHERE type & ${BookType.text} > 0
|
||||||
"""
|
"""
|
||||||
@@ -721,7 +735,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
LIMIT 10
|
LIMIT 10
|
||||||
@@ -736,7 +750,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.text} > 0 AND type & ${BookType.local} = 0
|
WHERE type & ${BookType.text} > 0 AND type & ${BookType.local} = 0
|
||||||
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
||||||
@@ -754,7 +768,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.local} > 0
|
WHERE type & ${BookType.local} > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -770,7 +784,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.audio} > 0
|
WHERE type & ${BookType.audio} > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -786,7 +800,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.audio} = 0 AND type & ${BookType.local} = 0
|
WHERE type & ${BookType.audio} = 0 AND type & ${BookType.local} = 0
|
||||||
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
||||||
@@ -803,7 +817,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.local} > 0
|
WHERE type & ${BookType.local} > 0
|
||||||
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
||||||
@@ -820,7 +834,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.image} > 0
|
WHERE type & ${BookType.image} > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -836,7 +850,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.text} > 0
|
WHERE type & ${BookType.text} > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -852,7 +866,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE type & ${BookType.updateError} > 0
|
WHERE type & ${BookType.updateError} > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -868,7 +882,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -884,7 +898,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -900,7 +914,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
@@ -916,7 +930,7 @@ interface BookDao {
|
|||||||
durChapterPos, latestChapterTitle, latestChapterTime,
|
durChapterPos, latestChapterTitle, latestChapterTime,
|
||||||
lastCheckCount, totalChapterNum, durChapterIndex,
|
lastCheckCount, totalChapterNum, durChapterIndex,
|
||||||
type, `group`, `order`, canUpdate,
|
type, `group`, `order`, canUpdate,
|
||||||
ifnull(customIntro, intro) as intro, kind
|
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||||
FROM books
|
FROM books
|
||||||
WHERE (`group` & :groupId) > 0
|
WHERE (`group` & :groupId) > 0
|
||||||
ORDER BY durChapterTime DESC
|
ORDER BY durChapterTime DESC
|
||||||
|
|||||||
@@ -355,6 +355,9 @@ data class Book(
|
|||||||
newBook.type = type
|
newBook.type = type
|
||||||
}
|
}
|
||||||
newBook.readConfig = readConfig
|
newBook.readConfig = readConfig
|
||||||
|
if (newBook.wordCount.isNullOrBlank()) {
|
||||||
|
newBook.wordCount = wordCount
|
||||||
|
}
|
||||||
return newBook
|
return newBook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
package io.legado.app.help.book
|
package io.legado.app.help.book
|
||||||
|
|
||||||
import io.legado.app.ui.config.otherConfig.OtherConfig
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.script.buildScriptBindings
|
import com.script.buildScriptBindings
|
||||||
@@ -19,6 +18,7 @@ import io.legado.app.exception.NoStackTraceException
|
|||||||
import io.legado.app.help.RuleBigDataHelp
|
import io.legado.app.help.RuleBigDataHelp
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.model.localBook.LocalBook
|
import io.legado.app.model.localBook.LocalBook
|
||||||
|
import io.legado.app.ui.config.otherConfig.OtherConfig
|
||||||
import io.legado.app.utils.FileDoc
|
import io.legado.app.utils.FileDoc
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
import io.legado.app.utils.MD5Utils
|
import io.legado.app.utils.MD5Utils
|
||||||
@@ -27,6 +27,7 @@ import io.legado.app.utils.find
|
|||||||
import io.legado.app.utils.inputStream
|
import io.legado.app.utils.inputStream
|
||||||
import io.legado.app.utils.isUri
|
import io.legado.app.utils.isUri
|
||||||
import io.legado.app.utils.normalizeFileName
|
import io.legado.app.utils.normalizeFileName
|
||||||
|
import io.legado.app.utils.splitNotBlank
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -306,6 +307,44 @@ fun Book.upType() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Book.upKind() {
|
||||||
|
val fileSizePattern = Regex("""^\d[\d,.]*\s*(b|kb|M|G|T)$""", RegexOption.IGNORE_CASE)
|
||||||
|
val wordCountPattern = Regex(""".*?\d.*字$""")
|
||||||
|
val kinds = kind?.splitNotBlank(",", "\n").orEmpty()
|
||||||
|
.filter {
|
||||||
|
it.isNotBlank() && !fileSizePattern.matches(it.trim()) && !wordCountPattern.matches(
|
||||||
|
it.trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.toMutableList()
|
||||||
|
|
||||||
|
if (isLocal) {
|
||||||
|
// 添加格式
|
||||||
|
val typeName = getBookTypeName()
|
||||||
|
if (typeName != "未知类型" && !kinds.contains(typeName)) {
|
||||||
|
kinds.add(0, typeName)
|
||||||
|
}
|
||||||
|
// 添加大小
|
||||||
|
try {
|
||||||
|
val size = FileDoc.fromFile(bookUrl).size
|
||||||
|
if (size > 0) {
|
||||||
|
kinds.add(io.legado.app.utils.ConvertUtils.formatFileSize(size))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加字数
|
||||||
|
wordCount?.let {
|
||||||
|
if (it.isNotBlank()) {
|
||||||
|
kinds.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kind = kinds.distinct().joinToString(",")
|
||||||
|
}
|
||||||
|
|
||||||
fun Book.sync(oldBook: Book) {
|
fun Book.sync(oldBook: Book) {
|
||||||
val curBook = appDb.bookDao.getBook(oldBook.bookUrl)!!
|
val curBook = appDb.bookDao.getBook(oldBook.bookUrl)!!
|
||||||
durChapterTime = curBook.durChapterTime
|
durChapterTime = curBook.durChapterTime
|
||||||
@@ -344,6 +383,10 @@ fun Book.updateTo(newBook: Book): Book {
|
|||||||
newBook.type = type
|
newBook.type = type
|
||||||
}
|
}
|
||||||
newBook.readConfig = readConfig
|
newBook.readConfig = readConfig
|
||||||
|
if (newBook.wordCount.isNullOrBlank()) {
|
||||||
|
newBook.wordCount = wordCount
|
||||||
|
}
|
||||||
|
newBook.upKind()
|
||||||
val variableMap = variableMap.toMutableMap()
|
val variableMap = variableMap.toMutableMap()
|
||||||
variableMap.keys.removeIf {
|
variableMap.keys.removeIf {
|
||||||
newBook.hasVariable(it)
|
newBook.hasVariable(it)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.legado.app.model.localBook
|
package io.legado.app.model.localBook
|
||||||
|
|
||||||
import io.legado.app.ui.config.otherConfig.OtherConfig
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
@@ -36,11 +35,13 @@ import io.legado.app.help.book.isPdf
|
|||||||
import io.legado.app.help.book.isUmd
|
import io.legado.app.help.book.isUmd
|
||||||
import io.legado.app.help.book.removeLocalUriCache
|
import io.legado.app.help.book.removeLocalUriCache
|
||||||
import io.legado.app.help.book.simulatedTotalChapterNum
|
import io.legado.app.help.book.simulatedTotalChapterNum
|
||||||
|
import io.legado.app.help.book.upKind
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.lib.webdav.WebDav
|
import io.legado.app.lib.webdav.WebDav
|
||||||
import io.legado.app.lib.webdav.WebDavException
|
import io.legado.app.lib.webdav.WebDavException
|
||||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||||
import io.legado.app.model.analyzeRule.CustomUrl
|
import io.legado.app.model.analyzeRule.CustomUrl
|
||||||
|
import io.legado.app.ui.config.otherConfig.OtherConfig
|
||||||
import io.legado.app.utils.ArchiveUtils
|
import io.legado.app.utils.ArchiveUtils
|
||||||
import io.legado.app.utils.FileDoc
|
import io.legado.app.utils.FileDoc
|
||||||
import io.legado.app.utils.FileUtils
|
import io.legado.app.utils.FileUtils
|
||||||
@@ -252,14 +253,17 @@ object LocalBook {
|
|||||||
order = appDb.bookDao.minOrder - 1
|
order = appDb.bookDao.minOrder - 1
|
||||||
)
|
)
|
||||||
upBookInfo(book)
|
upBookInfo(book)
|
||||||
|
book.upKind()
|
||||||
appDb.bookDao.insert(book)
|
appDb.bookDao.insert(book)
|
||||||
} else {
|
} else {
|
||||||
deleteBook(book, false)
|
deleteBook(book, false)
|
||||||
upBookInfo(book)
|
upBookInfo(book)
|
||||||
|
book.upKind()
|
||||||
// 触发 isLocalModified
|
// 触发 isLocalModified
|
||||||
book.latestChapterTime = 0
|
book.latestChapterTime = 0
|
||||||
//已有书籍说明是更新,删除原有目录
|
//已有书籍说明是更新,删除原有目录
|
||||||
appDb.bookChapterDao.delByBook(bookUrl)
|
appDb.bookChapterDao.delByBook(bookUrl)
|
||||||
|
appDb.bookDao.update(book)
|
||||||
}
|
}
|
||||||
return book
|
return book
|
||||||
}
|
}
|
||||||
@@ -290,6 +294,7 @@ object LocalBook {
|
|||||||
//附加压缩包名称 以便解压文件被删后再解压
|
//附加压缩包名称 以便解压文件被删后再解压
|
||||||
origin = "${BookType.localTag}::${archiveFileDoc.name}"
|
origin = "${BookType.localTag}::${archiveFileDoc.name}"
|
||||||
addType(BookType.archive)
|
addType(BookType.archive)
|
||||||
|
upKind()
|
||||||
save()
|
save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import io.legado.app.data.entities.TxtTocRule
|
|||||||
import io.legado.app.exception.EmptyFileException
|
import io.legado.app.exception.EmptyFileException
|
||||||
import io.legado.app.help.DefaultData
|
import io.legado.app.help.DefaultData
|
||||||
import io.legado.app.help.book.isLocalModified
|
import io.legado.app.help.book.isLocalModified
|
||||||
|
import io.legado.app.help.book.upKind
|
||||||
import io.legado.app.utils.EncodingDetect
|
import io.legado.app.utils.EncodingDetect
|
||||||
import io.legado.app.utils.MD5Utils
|
import io.legado.app.utils.MD5Utils
|
||||||
import io.legado.app.utils.StringUtils
|
import io.legado.app.utils.StringUtils
|
||||||
@@ -94,6 +95,7 @@ class TextFile(private var book: Book) {
|
|||||||
}
|
}
|
||||||
val (toc, wordCount) = analyze(book.tocUrl.toPattern(Pattern.MULTILINE))
|
val (toc, wordCount) = analyze(book.tocUrl.toPattern(Pattern.MULTILINE))
|
||||||
book.wordCount = StringUtils.wordCountFormat(wordCount)
|
book.wordCount = StringUtils.wordCountFormat(wordCount)
|
||||||
|
book.upKind()
|
||||||
toc.forEachIndexed { index, bookChapter ->
|
toc.forEachIndexed { index, bookChapter ->
|
||||||
bookChapter.index = index
|
bookChapter.index = index
|
||||||
bookChapter.bookUrl = book.bookUrl
|
bookChapter.bookUrl = book.bookUrl
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import io.legado.app.help.book.isNotShelf
|
|||||||
import io.legado.app.help.book.isSameNameAuthor
|
import io.legado.app.help.book.isSameNameAuthor
|
||||||
import io.legado.app.help.book.isWebFile
|
import io.legado.app.help.book.isWebFile
|
||||||
import io.legado.app.help.book.removeType
|
import io.legado.app.help.book.removeType
|
||||||
|
import io.legado.app.help.book.upKind
|
||||||
import io.legado.app.help.book.updateTo
|
import io.legado.app.help.book.updateTo
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
import io.legado.app.help.coroutine.Coroutine
|
import io.legado.app.help.coroutine.Coroutine
|
||||||
@@ -51,8 +52,6 @@ import io.legado.app.model.webBook.WebBook
|
|||||||
import io.legado.app.ui.config.coverConfig.CoverConfig
|
import io.legado.app.ui.config.coverConfig.CoverConfig
|
||||||
import io.legado.app.ui.widget.components.cover.buildCoverImageRequest
|
import io.legado.app.ui.widget.components.cover.buildCoverImageRequest
|
||||||
import io.legado.app.utils.ArchiveUtils
|
import io.legado.app.utils.ArchiveUtils
|
||||||
import io.legado.app.utils.ConvertUtils
|
|
||||||
import io.legado.app.utils.FileDoc
|
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
import io.legado.app.utils.ImageSaveUtils
|
import io.legado.app.utils.ImageSaveUtils
|
||||||
import io.legado.app.utils.UrlUtil
|
import io.legado.app.utils.UrlUtil
|
||||||
@@ -759,24 +758,14 @@ class BookInfoViewModel(
|
|||||||
|
|
||||||
private fun refreshMeta(book: Book) {
|
private fun refreshMeta(book: Book) {
|
||||||
execute {
|
execute {
|
||||||
val fileSizePattern = Regex("""^\d[\d,.]*\s*(b|kb|M|G|T)$""", RegexOption.IGNORE_CASE)
|
book.upKind()
|
||||||
val kinds = (book.kind?.splitNotBlank(",", "\n").orEmpty().toList())
|
|
||||||
.filter { !fileSizePattern.matches(it.trim()) }
|
|
||||||
.toMutableList()
|
|
||||||
if (book.isLocal) {
|
|
||||||
val size = FileDoc.fromFile(book.bookUrl).size
|
|
||||||
if (size > 0) {
|
|
||||||
kinds.add(ConvertUtils.formatFileSize(size))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val finalKinds = kinds.distinct()
|
|
||||||
val userGroupIds = appDb.bookGroupDao.idsSum
|
val userGroupIds = appDb.bookGroupDao.idsSum
|
||||||
val groupAnd = userGroupIds and book.group
|
val groupAnd = userGroupIds and book.group
|
||||||
val hasCustomGroup = book.group > 0L && groupAnd != 0L
|
val hasCustomGroup = book.group > 0L && groupAnd != 0L
|
||||||
val groupNames = appDb.bookGroupDao.getGroupNames(book.group).joinToString(",")
|
val groupNames = appDb.bookGroupDao.getGroupNames(book.group).joinToString(",")
|
||||||
val normalizedGroupNames = groupNames.ifBlank { null }
|
val normalizedGroupNames = groupNames.ifBlank { null }
|
||||||
book.kind = finalKinds.joinToString(",")
|
|
||||||
appDb.bookDao.update(book)
|
appDb.bookDao.update(book)
|
||||||
|
val finalKinds = book.kind?.splitNotBlank(",", "\n").orEmpty().toList()
|
||||||
Triple(finalKinds, normalizedGroupNames, hasCustomGroup)
|
Triple(finalKinds, normalizedGroupNames, hasCustomGroup)
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
currentKindLabels = it.first
|
currentKindLabels = it.first
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ import io.legado.app.ui.widget.components.cover.BookshelfCover
|
|||||||
import io.legado.app.ui.widget.components.cover.CoilBookCover
|
import io.legado.app.ui.widget.components.cover.CoilBookCover
|
||||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||||
import io.legado.app.ui.widget.components.text.AppText
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
import io.legado.app.utils.splitNotBlank
|
|
||||||
import io.legado.app.utils.toTimeAgo
|
import io.legado.app.utils.toTimeAgo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,7 +288,7 @@ fun BookshelfItem(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BookGroupCover(
|
fun BookGroupCover(
|
||||||
books: List<BookShelfItem>,
|
books: List<BookUiItem>,
|
||||||
coverPath: String? = null,
|
coverPath: String? = null,
|
||||||
leftBottomText: String? = null,
|
leftBottomText: String? = null,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
@@ -328,7 +327,7 @@ fun BookGroupCover(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(1.dp)
|
.padding(1.dp)
|
||||||
) {
|
) {
|
||||||
books.getOrNull(0)?.let {
|
books.getOrNull(0)?.book?.let {
|
||||||
CoilBookCover(
|
CoilBookCover(
|
||||||
name = it.name,
|
name = it.name,
|
||||||
author = it.author,
|
author = it.author,
|
||||||
@@ -343,7 +342,7 @@ fun BookGroupCover(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(1.dp)
|
.padding(1.dp)
|
||||||
) {
|
) {
|
||||||
books.getOrNull(1)?.let {
|
books.getOrNull(1)?.book?.let {
|
||||||
CoilBookCover(
|
CoilBookCover(
|
||||||
name = it.name,
|
name = it.name,
|
||||||
author = it.author,
|
author = it.author,
|
||||||
@@ -360,7 +359,7 @@ fun BookGroupCover(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(1.dp)
|
.padding(1.dp)
|
||||||
) {
|
) {
|
||||||
books.getOrNull(2)?.let {
|
books.getOrNull(2)?.book?.let {
|
||||||
CoilBookCover(
|
CoilBookCover(
|
||||||
name = it.name,
|
name = it.name,
|
||||||
author = it.author,
|
author = it.author,
|
||||||
@@ -375,7 +374,7 @@ fun BookGroupCover(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(1.dp)
|
.padding(1.dp)
|
||||||
) {
|
) {
|
||||||
books.getOrNull(3)?.let {
|
books.getOrNull(3)?.book?.let {
|
||||||
CoilBookCover(
|
CoilBookCover(
|
||||||
name = it.name,
|
name = it.name,
|
||||||
author = it.author,
|
author = it.author,
|
||||||
@@ -406,7 +405,7 @@ fun BookGroupCover(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BookGroupItemGrid(
|
fun BookGroupItemGrid(
|
||||||
group: BookGroupUi,
|
group: BookGroupUi,
|
||||||
previewBooks: List<BookShelfItem>,
|
previewBooks: List<BookUiItem>,
|
||||||
countText: String? = null,
|
countText: String? = null,
|
||||||
gridStyle: Int = 0,
|
gridStyle: Int = 0,
|
||||||
titleSmallFont: Boolean = false,
|
titleSmallFont: Boolean = false,
|
||||||
@@ -443,7 +442,7 @@ fun BookGroupItemGrid(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BookGroupItemList(
|
fun BookGroupItemList(
|
||||||
group: BookGroupUi,
|
group: BookGroupUi,
|
||||||
previewBooks: List<BookShelfItem>,
|
previewBooks: List<BookUiItem>,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
countText: String? = null,
|
countText: String? = null,
|
||||||
@@ -467,7 +466,7 @@ fun BookGroupItemList(
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val firstBookName = previewBooks.firstOrNull()?.name
|
val firstBookName = previewBooks.firstOrNull()?.book?.name
|
||||||
val descAnnotated = if (firstBookName != null) {
|
val descAnnotated = if (firstBookName != null) {
|
||||||
buildAnnotatedString {
|
buildAnnotatedString {
|
||||||
append("最近阅读:")
|
append("最近阅读:")
|
||||||
@@ -499,7 +498,7 @@ fun BookGroupItemList(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BookGroupItemHorizontalCovers(
|
fun BookGroupItemHorizontalCovers(
|
||||||
group: BookGroupUi,
|
group: BookGroupUi,
|
||||||
previewBooks: List<BookShelfItem>,
|
previewBooks: List<BookUiItem>,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
countText: String? = null,
|
countText: String? = null,
|
||||||
@@ -563,7 +562,8 @@ fun BookGroupItemHorizontalCovers(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
val coverCount = BookshelfConfig.bookshelfGroupCoverCount
|
val coverCount = BookshelfConfig.bookshelfGroupCoverCount
|
||||||
previewBooks.take(coverCount).forEach { book ->
|
previewBooks.take(coverCount).forEach { bookUi ->
|
||||||
|
val book = bookUi.book
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -597,7 +597,7 @@ fun BookGroupItemHorizontalCovers(
|
|||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookItem(
|
fun BookItem(
|
||||||
book: BookShelfItem,
|
bookUi: BookUiItem,
|
||||||
layoutMode: Int,
|
layoutMode: Int,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
isSelected: Boolean = false,
|
isSelected: Boolean = false,
|
||||||
@@ -616,6 +616,7 @@ fun BookItem(
|
|||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: (() -> Unit)?
|
onLongClick: (() -> Unit)?
|
||||||
) {
|
) {
|
||||||
|
val book = bookUi.book
|
||||||
val unreadCount = book.getUnreadChapterNum()
|
val unreadCount = book.getUnreadChapterNum()
|
||||||
val unreadText = if (BookshelfConfig.showUnread && unreadCount > 0) unreadCount.toString() else null
|
val unreadText = if (BookshelfConfig.showUnread && unreadCount > 0) unreadCount.toString() else null
|
||||||
val bookTypeLabel = if (BookshelfConfig.showTip) {
|
val bookTypeLabel = if (BookshelfConfig.showTip) {
|
||||||
@@ -684,10 +685,10 @@ fun BookItem(
|
|||||||
desc = book.durChapterTitle ?: "",
|
desc = book.durChapterTitle ?: "",
|
||||||
columnContent = if (layoutMode == 0 && !isCompact && BookshelfConfig.showBookIntro) {
|
columnContent = if (layoutMode == 0 && !isCompact && BookshelfConfig.showBookIntro) {
|
||||||
{
|
{
|
||||||
val kindList = book.kind?.splitNotBlank(",", "\n")?.filter { it.isNotBlank() }
|
val kindList = bookUi.displayTags
|
||||||
val intro = book.intro?.takeIf { it.isNotBlank() }
|
val intro = book.intro?.takeIf { it.isNotBlank() }
|
||||||
val customTagColors = if (ThemeConfig.enableCustomTagColors) ThemeConfig.getCustomTagColors() else emptyList()
|
val customTagColors = if (ThemeConfig.enableCustomTagColors) ThemeConfig.getCustomTagColors() else emptyList()
|
||||||
if (BookshelfConfig.bookshelfShowTag && !kindList.isNullOrEmpty()) {
|
if (BookshelfConfig.bookshelfShowTag && kindList.isNotEmpty()) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package io.legado.app.ui.main.bookshelf
|
|||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
|
import io.legado.app.utils.splitNotBlank
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
@@ -27,7 +30,8 @@ data class BookShelfItem(
|
|||||||
val order: Int,
|
val order: Int,
|
||||||
val canUpdate: Boolean = true,
|
val canUpdate: Boolean = true,
|
||||||
val intro: String? = null,
|
val intro: String? = null,
|
||||||
val kind: String? = null
|
val kind: String? = null,
|
||||||
|
val wordCount: String? = null
|
||||||
) {
|
) {
|
||||||
fun getDisplayCover() = if (customCoverUrl.isNullOrEmpty()) coverUrl else customCoverUrl
|
fun getDisplayCover() = if (customCoverUrl.isNullOrEmpty()) coverUrl else customCoverUrl
|
||||||
|
|
||||||
@@ -41,8 +45,41 @@ data class BookShelfItem(
|
|||||||
|
|
||||||
val isNew: Boolean get() = lastCheckCount > 0
|
val isNew: Boolean get() = lastCheckCount > 0
|
||||||
|
|
||||||
|
|
||||||
fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0)
|
fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 DTO 转换为专为 Compose 设计的 UI 状态
|
||||||
|
*/
|
||||||
|
fun toUiItem(): BookUiItem {
|
||||||
|
val tagList = mutableListOf<String>()
|
||||||
|
kind?.splitNotBlank(",", "\n")?.filter { it.isNotBlank() }?.let {
|
||||||
|
tagList.addAll(it)
|
||||||
|
}
|
||||||
|
if (!wordCount.isNullOrBlank() && !tagList.contains(wordCount)) {
|
||||||
|
tagList.add(wordCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
return BookUiItem(
|
||||||
|
book = this,
|
||||||
|
displayTags = tagList.toImmutableList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 理想实现:专为 UI 设计的状态类
|
||||||
|
*/
|
||||||
|
@Stable
|
||||||
|
data class BookUiItem(
|
||||||
|
val book: BookShelfItem,
|
||||||
|
val displayTags: ImmutableList<String>
|
||||||
|
) {
|
||||||
|
fun matches(key: String): Boolean {
|
||||||
|
return book.name.contains(key, true) ||
|
||||||
|
book.author.contains(key, true) ||
|
||||||
|
book.originName.contains(key, true) ||
|
||||||
|
displayTags.any { it.contains(key, true) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BookShelfItem.toLightBook() = Book(
|
fun BookShelfItem.toLightBook() = Book(
|
||||||
@@ -64,5 +101,7 @@ fun BookShelfItem.toLightBook() = Book(
|
|||||||
type = type,
|
type = type,
|
||||||
group = group,
|
group = group,
|
||||||
order = order,
|
order = order,
|
||||||
canUpdate = canUpdate
|
canUpdate = canUpdate,
|
||||||
|
wordCount = wordCount,
|
||||||
|
kind = kind
|
||||||
)
|
)
|
||||||
@@ -847,7 +847,7 @@ fun BookshelfScreen(
|
|||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
selectedBookUrls = selectedBookUrls,
|
selectedBookUrls = selectedBookUrls,
|
||||||
canReorderBooks = false,
|
canReorderBooks = false,
|
||||||
onToggleBookSelection = { toggleBookSelection(it.bookUrl) },
|
onToggleBookSelection = { toggleBookSelection(it.book.bookUrl) },
|
||||||
draggingBooks = null,
|
draggingBooks = null,
|
||||||
pendingSavedBooks = null,
|
pendingSavedBooks = null,
|
||||||
onDragStarted = {},
|
onDragStarted = {},
|
||||||
@@ -890,7 +890,7 @@ fun BookshelfScreen(
|
|||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
selectedBookUrls = selectedBookUrls,
|
selectedBookUrls = selectedBookUrls,
|
||||||
canReorderBooks = canReorderBooks,
|
canReorderBooks = canReorderBooks,
|
||||||
onToggleBookSelection = { toggleBookSelection(it.bookUrl) },
|
onToggleBookSelection = { toggleBookSelection(it.book.bookUrl) },
|
||||||
draggingBooks = if (isSelectedGroup) {
|
draggingBooks = if (isSelectedGroup) {
|
||||||
uiState.draggingBooks
|
uiState.draggingBooks
|
||||||
} else {
|
} else {
|
||||||
@@ -1241,15 +1241,15 @@ private data class BookshelfEditStickySummary(
|
|||||||
@Composable
|
@Composable
|
||||||
fun BookshelfPage(
|
fun BookshelfPage(
|
||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
books: ImmutableList<BookShelfItem>,
|
books: ImmutableList<BookUiItem>,
|
||||||
uiState: BookshelfUiState,
|
uiState: BookshelfUiState,
|
||||||
selectedBookUrls: ImmutableSet<String>,
|
selectedBookUrls: ImmutableSet<String>,
|
||||||
canReorderBooks: Boolean,
|
canReorderBooks: Boolean,
|
||||||
onToggleBookSelection: (BookShelfItem) -> Unit,
|
onToggleBookSelection: (BookUiItem) -> Unit,
|
||||||
draggingBooks: ImmutableList<BookShelfItem>?,
|
draggingBooks: ImmutableList<BookUiItem>?,
|
||||||
pendingSavedBooks: ImmutableList<BookShelfItem>?,
|
pendingSavedBooks: ImmutableList<BookUiItem>?,
|
||||||
onDragStarted: (ImmutableList<BookShelfItem>) -> Unit,
|
onDragStarted: (ImmutableList<BookUiItem>) -> Unit,
|
||||||
onMoveBook: (fromIndex: Int, toIndex: Int, currentBooks: ImmutableList<BookShelfItem>) -> Unit,
|
onMoveBook: (fromIndex: Int, toIndex: Int, currentBooks: ImmutableList<BookUiItem>) -> Unit,
|
||||||
onDragFinished: () -> Unit,
|
onDragFinished: () -> Unit,
|
||||||
onGlobalSearch: () -> Unit,
|
onGlobalSearch: () -> Unit,
|
||||||
onBookClick: (BookShelfItem) -> Unit,
|
onBookClick: (BookShelfItem) -> Unit,
|
||||||
@@ -1367,15 +1367,15 @@ fun BookshelfPage(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
horizontalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||||
showFastScroll = showFastScroll
|
showFastScroll = showFastScroll
|
||||||
) {
|
) {
|
||||||
items(displayBooks, key = { it.bookUrl }) { book ->
|
items(displayBooks, key = { it.book.bookUrl }) { bookUi ->
|
||||||
val isSelected = selectedBookUrls.contains(book.bookUrl)
|
val isSelected = selectedBookUrls.contains(bookUi.book.bookUrl)
|
||||||
ReorderableItem(
|
ReorderableItem(
|
||||||
state = reorderableState,
|
state = reorderableState,
|
||||||
key = book.bookUrl,
|
key = bookUi.book.bookUrl,
|
||||||
enabled = canReorderBooks
|
enabled = canReorderBooks
|
||||||
) {
|
) {
|
||||||
BookItem(
|
BookItem(
|
||||||
book = book,
|
bookUi = bookUi,
|
||||||
modifier = Modifier.then(
|
modifier = Modifier.then(
|
||||||
if (canReorderBooks) {
|
if (canReorderBooks) {
|
||||||
Modifier.longPressDraggableHandle(
|
Modifier.longPressDraggableHandle(
|
||||||
@@ -1399,7 +1399,7 @@ fun BookshelfPage(
|
|||||||
isSelected = isSelected,
|
isSelected = isSelected,
|
||||||
gridStyle = bookItemGridStyle,
|
gridStyle = bookItemGridStyle,
|
||||||
isCompact = bookItemIsCompact,
|
isCompact = bookItemIsCompact,
|
||||||
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
isUpdating = uiState.updatingBooks.contains(bookUi.book.bookUrl),
|
||||||
titleSmallFont = bookItemTitleSmallFont,
|
titleSmallFont = bookItemTitleSmallFont,
|
||||||
titleCenter = bookItemTitleCenter,
|
titleCenter = bookItemTitleCenter,
|
||||||
titleMaxLines = bookItemTitleMaxLines,
|
titleMaxLines = bookItemTitleMaxLines,
|
||||||
@@ -1408,12 +1408,12 @@ fun BookshelfPage(
|
|||||||
searchKey = uiState.searchKey,
|
searchKey = uiState.searchKey,
|
||||||
sharedTransitionScope = sharedTransitionScope,
|
sharedTransitionScope = sharedTransitionScope,
|
||||||
animatedVisibilityScope = animatedVisibilityScope,
|
animatedVisibilityScope = animatedVisibilityScope,
|
||||||
sharedCoverKey = if (isCurrentPage) bookCoverSharedElementKey(book.bookUrl) else null,
|
sharedCoverKey = if (isCurrentPage) bookCoverSharedElementKey(bookUi.book.bookUrl) else null,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (uiState.isEditMode) {
|
if (uiState.isEditMode) {
|
||||||
onToggleBookSelection(book)
|
onToggleBookSelection(bookUi)
|
||||||
} else {
|
} else {
|
||||||
onBookClick(book)
|
onBookClick(bookUi.book)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = if (canReorderBooks) {
|
onLongClick = if (canReorderBooks) {
|
||||||
@@ -1421,9 +1421,9 @@ fun BookshelfPage(
|
|||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
if (uiState.isEditMode) {
|
if (uiState.isEditMode) {
|
||||||
onToggleBookSelection(book)
|
onToggleBookSelection(bookUi)
|
||||||
} else {
|
} else {
|
||||||
onBookLongClick(book)
|
onBookLongClick(bookUi.book)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ sealed interface BookshelfOverlay {
|
|||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class BookshelfUiState(
|
data class BookshelfUiState(
|
||||||
override val items: ImmutableList<BookShelfItem> = persistentListOf(),
|
override val items: ImmutableList<BookUiItem> = persistentListOf(),
|
||||||
override val selectedIds: ImmutableSet<Any> = persistentSetOf(),
|
override val selectedIds: ImmutableSet<Any> = persistentSetOf(),
|
||||||
override val searchKey: String = "",
|
override val searchKey: String = "",
|
||||||
override val isSearch: Boolean = false,
|
override val isSearch: Boolean = false,
|
||||||
@@ -41,7 +41,7 @@ data class BookshelfUiState(
|
|||||||
val isInitialLoading: Boolean = true,
|
val isInitialLoading: Boolean = true,
|
||||||
val groups: ImmutableList<BookGroupUi> = persistentListOf(),
|
val groups: ImmutableList<BookGroupUi> = persistentListOf(),
|
||||||
val allGroups: ImmutableList<BookGroupUi> = persistentListOf(),
|
val allGroups: ImmutableList<BookGroupUi> = persistentListOf(),
|
||||||
val groupPreviews: ImmutableMap<Long, ImmutableList<BookShelfItem>> = persistentMapOf(),
|
val groupPreviews: ImmutableMap<Long, ImmutableList<BookUiItem>> = persistentMapOf(),
|
||||||
val groupBookCounts: ImmutableMap<Long, Int> = persistentMapOf(),
|
val groupBookCounts: ImmutableMap<Long, Int> = persistentMapOf(),
|
||||||
val currentGroupBookCount: Int = 0,
|
val currentGroupBookCount: Int = 0,
|
||||||
val allBooksCount: Int = 0,
|
val allBooksCount: Int = 0,
|
||||||
@@ -61,7 +61,7 @@ data class BookshelfUiState(
|
|||||||
val title: String = "",
|
val title: String = "",
|
||||||
val subtitle: String? = null,
|
val subtitle: String? = null,
|
||||||
val currentGroupName: String? = null,
|
val currentGroupName: String? = null,
|
||||||
val draggingBooks: ImmutableList<BookShelfItem>? = null,
|
val draggingBooks: ImmutableList<BookUiItem>? = null,
|
||||||
val pendingSavedBooks: ImmutableList<BookShelfItem>? = null,
|
val pendingSavedBooks: ImmutableList<BookUiItem>? = null,
|
||||||
val allGroupBooks: ImmutableMap<Long, ImmutableList<BookShelfItem>> = persistentMapOf()
|
val allGroupBooks: ImmutableMap<Long, ImmutableList<BookUiItem>> = persistentMapOf()
|
||||||
) : ListUiState<BookShelfItem>
|
) : ListUiState<BookUiItem>
|
||||||
@@ -117,8 +117,8 @@ class BookshelfViewModel(
|
|||||||
private val isInFolderRootFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle == 2)
|
private val isInFolderRootFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle == 2)
|
||||||
private val isRefreshingFlow = MutableStateFlow(false)
|
private val isRefreshingFlow = MutableStateFlow(false)
|
||||||
private val bookGroupStyleFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle)
|
private val bookGroupStyleFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle)
|
||||||
private val draggingBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null)
|
private val draggingBooksFlow = MutableStateFlow<List<BookUiItem>?>(null)
|
||||||
private val pendingSavedBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null)
|
private val pendingSavedBooksFlow = MutableStateFlow<List<BookUiItem>?>(null)
|
||||||
private val isInitialLoadingFlow = MutableStateFlow(true)
|
private val isInitialLoadingFlow = MutableStateFlow(true)
|
||||||
|
|
||||||
private data class BookshelfSortConfig(
|
private data class BookshelfSortConfig(
|
||||||
@@ -170,7 +170,7 @@ class BookshelfViewModel(
|
|||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||||
|
|
||||||
private data class GroupPreviewState(
|
private data class GroupPreviewState(
|
||||||
val previews: ImmutableMap<Long, ImmutableList<BookShelfItem>>,
|
val previews: ImmutableMap<Long, ImmutableList<BookUiItem>>,
|
||||||
val counts: ImmutableMap<Long, Int>,
|
val counts: ImmutableMap<Long, Int>,
|
||||||
val allBookCount: Int
|
val allBookCount: Int
|
||||||
)
|
)
|
||||||
@@ -189,7 +189,7 @@ class BookshelfViewModel(
|
|||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfGroupSelectorState())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfGroupSelectorState())
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val booksFlow = groupIdFlow
|
val booksFlow: Flow<List<BookUiItem>> = groupIdFlow
|
||||||
.flatMapLatest { groupId ->
|
.flatMapLatest { groupId ->
|
||||||
combine(
|
combine(
|
||||||
appDb.bookDao.flowBookShelfByGroup(groupId),
|
appDb.bookDao.flowBookShelfByGroup(groupId),
|
||||||
@@ -200,12 +200,12 @@ class BookshelfViewModel(
|
|||||||
list,
|
list,
|
||||||
groups.find { it.groupId == groupId },
|
groups.find { it.groupId == groupId },
|
||||||
sortConfig
|
sortConfig
|
||||||
)
|
).map { it.toUiItem() }
|
||||||
}
|
}
|
||||||
}.distinctUntilChanged().flowOn(Dispatchers.Default)
|
}.distinctUntilChanged().flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private val allGroupBooksFlow: StateFlow<Map<Long, List<BookShelfItem>>> = combine(
|
private val allGroupBooksFlow: StateFlow<Map<Long, List<BookUiItem>>> = combine(
|
||||||
groupsFlow, sortConfigFlow
|
groupsFlow, sortConfigFlow
|
||||||
) { groups, sortConfig ->
|
) { groups, sortConfig ->
|
||||||
groups to sortConfig
|
groups to sortConfig
|
||||||
@@ -215,7 +215,7 @@ class BookshelfViewModel(
|
|||||||
} else {
|
} else {
|
||||||
val flows = groups.map { group ->
|
val flows = groups.map { group ->
|
||||||
appDb.bookDao.flowBookShelfByGroup(group.groupId).map { books ->
|
appDb.bookDao.flowBookShelfByGroup(group.groupId).map { books ->
|
||||||
group.groupId to sortBooks(books, group, sortConfig)
|
group.groupId to sortBooks(books, group, sortConfig).map { it.toUiItem() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
combine(flows) { it.toMap() }
|
combine(flows) { it.toMap() }
|
||||||
@@ -224,13 +224,13 @@ class BookshelfViewModel(
|
|||||||
.flowOn(Dispatchers.Default)
|
.flowOn(Dispatchers.Default)
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyMap())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyMap())
|
||||||
|
|
||||||
private val allGroupBooksImmutableFlow: StateFlow<ImmutableMap<Long, ImmutableList<BookShelfItem>>> =
|
private val allGroupBooksImmutableFlow: StateFlow<ImmutableMap<Long, ImmutableList<BookUiItem>>> =
|
||||||
allGroupBooksFlow.map { map ->
|
allGroupBooksFlow.map { map ->
|
||||||
map.mapValues { it.value.toImmutableList() }.toImmutableMap()
|
map.mapValues { it.value.toImmutableList() }.toImmutableMap()
|
||||||
}.flowOn(Dispatchers.Default)
|
}.flowOn(Dispatchers.Default)
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), persistentMapOf())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), persistentMapOf())
|
||||||
|
|
||||||
private val visibleBooksFlow = combine(
|
private val visibleBooksFlow: Flow<List<BookUiItem>> = combine(
|
||||||
booksFlow,
|
booksFlow,
|
||||||
searchKeyFlow,
|
searchKeyFlow,
|
||||||
searchModeFlow
|
searchModeFlow
|
||||||
@@ -254,7 +254,7 @@ class BookshelfViewModel(
|
|||||||
selectedBookUrlsFlow,
|
selectedBookUrlsFlow,
|
||||||
visibleBooksFlow
|
visibleBooksFlow
|
||||||
) { selectedBookUrls, visibleBooks ->
|
) { selectedBookUrls, visibleBooks ->
|
||||||
val visibleBookUrls = visibleBooks.mapTo(hashSetOf()) { it.bookUrl }
|
val visibleBookUrls = visibleBooks.mapTo(hashSetOf()) { it.book.bookUrl }
|
||||||
selectedBookUrls.intersect(visibleBookUrls)
|
selectedBookUrls.intersect(visibleBookUrls)
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
@@ -281,11 +281,11 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
val previewFlow = appDb.bookDao.flowGroupPreview(group.groupId)
|
val previewFlow = appDb.bookDao.flowGroupPreview(group.groupId)
|
||||||
combine(countFlow, previewFlow) { count, preview ->
|
combine(countFlow, previewFlow) { count, preview ->
|
||||||
Triple(group.groupId, count, preview)
|
Triple(group.groupId, count, preview.map { it.toUiItem() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
combine(groupFlows) { results ->
|
combine(groupFlows) { results ->
|
||||||
var previews = persistentMapOf<Long, ImmutableList<BookShelfItem>>()
|
var previews = persistentMapOf<Long, ImmutableList<BookUiItem>>()
|
||||||
var counts = persistentMapOf<Long, Int>()
|
var counts = persistentMapOf<Long, Int>()
|
||||||
var allBookCount = 0
|
var allBookCount = 0
|
||||||
results.forEach { (groupId, count, preview) ->
|
results.forEach { (groupId, count, preview) ->
|
||||||
@@ -344,8 +344,8 @@ class BookshelfViewModel(
|
|||||||
val isInFolderRoot: Boolean,
|
val isInFolderRoot: Boolean,
|
||||||
val isRefreshing: Boolean,
|
val isRefreshing: Boolean,
|
||||||
val bookGroupStyle: Int,
|
val bookGroupStyle: Int,
|
||||||
val draggingBooks: List<BookShelfItem>?,
|
val draggingBooks: List<BookUiItem>?,
|
||||||
val pendingSavedBooks: List<BookShelfItem>?
|
val pendingSavedBooks: List<BookUiItem>?
|
||||||
)
|
)
|
||||||
|
|
||||||
private val editStateFlow = combine(
|
private val editStateFlow = combine(
|
||||||
@@ -387,7 +387,8 @@ class BookshelfViewModel(
|
|||||||
GroupPreviewState(persistentMapOf(), persistentMapOf(), 0)
|
GroupPreviewState(persistentMapOf(), persistentMapOf(), 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val allGroupBooksStateFlow = MutableStateFlow<ImmutableMap<Long, ImmutableList<BookShelfItem>>>(
|
private val allGroupBooksStateFlow =
|
||||||
|
MutableStateFlow<ImmutableMap<Long, ImmutableList<BookUiItem>>>(
|
||||||
persistentMapOf()
|
persistentMapOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -411,7 +412,7 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private data class BookshelfDataCore(
|
private data class BookshelfDataCore(
|
||||||
val books: List<BookShelfItem>,
|
val books: List<BookUiItem>,
|
||||||
val groups: List<BookGroup>,
|
val groups: List<BookGroup>,
|
||||||
val allGroups: List<BookGroup>,
|
val allGroups: List<BookGroup>,
|
||||||
val previews: GroupPreviewState,
|
val previews: GroupPreviewState,
|
||||||
@@ -419,12 +420,12 @@ class BookshelfViewModel(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private data class BookshelfDataState(
|
private data class BookshelfDataState(
|
||||||
val books: List<BookShelfItem>,
|
val books: List<BookUiItem>,
|
||||||
val groups: List<BookGroupUi>,
|
val groups: List<BookGroupUi>,
|
||||||
val allGroups: List<BookGroupUi>,
|
val allGroups: List<BookGroupUi>,
|
||||||
val previews: GroupPreviewState,
|
val previews: GroupPreviewState,
|
||||||
val internal: InternalState,
|
val internal: InternalState,
|
||||||
val allGroupBooks: ImmutableMap<Long, ImmutableList<BookShelfItem>>
|
val allGroupBooks: ImmutableMap<Long, ImmutableList<BookUiItem>>
|
||||||
)
|
)
|
||||||
|
|
||||||
val uiState: StateFlow<BookshelfUiState> = combine(
|
val uiState: StateFlow<BookshelfUiState> = combine(
|
||||||
@@ -540,14 +541,14 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun filterBooks(
|
private fun filterBooks(
|
||||||
books: List<BookShelfItem>,
|
books: List<BookUiItem>,
|
||||||
searchKey: String,
|
searchKey: String,
|
||||||
isSearchMode: Boolean
|
isSearchMode: Boolean
|
||||||
): List<BookShelfItem> {
|
): List<BookUiItem> {
|
||||||
return if (!isSearchMode || searchKey.isBlank()) {
|
return if (!isSearchMode || searchKey.isBlank()) {
|
||||||
books
|
books
|
||||||
} else {
|
} else {
|
||||||
books.filter { it.matchesSearchKey(searchKey) }
|
books.filter { it.matches(searchKey) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,11 +674,11 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun selectAllVisible() {
|
fun selectAllVisible() {
|
||||||
selectedBookUrlsFlow.value = uiState.value.items.mapTo(hashSetOf()) { it.bookUrl }
|
selectedBookUrlsFlow.value = uiState.value.items.mapTo(hashSetOf()) { it.book.bookUrl }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun invertVisibleSelection() {
|
fun invertVisibleSelection() {
|
||||||
val visibleBookUrls = uiState.value.items.mapTo(hashSetOf()) { it.bookUrl }
|
val visibleBookUrls = uiState.value.items.mapTo(hashSetOf()) { it.book.bookUrl }
|
||||||
selectedBookUrlsFlow.value = visibleBookUrls - selectedBookUrlsFlow.value
|
selectedBookUrlsFlow.value = visibleBookUrls - selectedBookUrlsFlow.value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,13 +720,13 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveBookOrder(reorderedBooks: List<BookShelfItem>) {
|
fun saveBookOrder(reorderedBooks: List<BookUiItem>) {
|
||||||
if (reorderedBooks.isEmpty()) return
|
if (reorderedBooks.isEmpty()) return
|
||||||
val isDescending = BookshelfConfig.bookshelfSortOrder == 1
|
val isDescending = BookshelfConfig.bookshelfSortOrder == 1
|
||||||
val maxOrder = reorderedBooks.size
|
val maxOrder = reorderedBooks.size
|
||||||
execute {
|
execute {
|
||||||
val updates = reorderedBooks.mapIndexedNotNull { index, book ->
|
val updates = reorderedBooks.mapIndexedNotNull { index, bookUi ->
|
||||||
appDb.bookDao.getBook(book.bookUrl)?.apply {
|
appDb.bookDao.getBook(bookUi.book.bookUrl)?.apply {
|
||||||
order = if (isDescending) maxOrder - index else index + 1
|
order = if (isDescending) maxOrder - index else index + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,19 +757,19 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshBooks(books: List<BookShelfItem>) {
|
fun refreshBooks(books: List<BookUiItem>) {
|
||||||
if (isRefreshingFlow.value) return
|
if (isRefreshingFlow.value) return
|
||||||
isRefreshingFlow.value = true
|
isRefreshingFlow.value = true
|
||||||
val limit = BookshelfConfig.bookshelfRefreshingLimit
|
val limit = BookshelfConfig.bookshelfRefreshingLimit
|
||||||
val list = if (limit > 0) books.take(limit) else books
|
val list = if (limit > 0) books.take(limit) else books
|
||||||
enqueueTocUpdate(list, resetRefreshWhenIdle = true)
|
enqueueTocUpdate(list.map { it.book }, resetRefreshWhenIdle = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDraggingBooks(books: List<BookShelfItem>) {
|
fun startDraggingBooks(books: List<BookUiItem>) {
|
||||||
draggingBooksFlow.value = books
|
draggingBooksFlow.value = books
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveDraggingBook(fromIndex: Int, toIndex: Int, fallbackBooks: List<BookShelfItem>) {
|
fun moveDraggingBook(fromIndex: Int, toIndex: Int, fallbackBooks: List<BookUiItem>) {
|
||||||
if (fromIndex == toIndex) return
|
if (fromIndex == toIndex) return
|
||||||
val sourceBooks = draggingBooksFlow.value ?: fallbackBooks
|
val sourceBooks = draggingBooksFlow.value ?: fallbackBooks
|
||||||
if (fromIndex !in sourceBooks.indices || toIndex !in sourceBooks.indices) return
|
if (fromIndex !in sourceBooks.indices || toIndex !in sourceBooks.indices) return
|
||||||
@@ -778,19 +779,19 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun finishDraggingBooks() {
|
fun finishDraggingBooks() {
|
||||||
val reorderedBooks = draggingBooksFlow.value ?: return
|
val reorderedUiBooks = draggingBooksFlow.value ?: return
|
||||||
pendingSavedBooksFlow.value = reorderedBooks
|
pendingSavedBooksFlow.value = reorderedUiBooks
|
||||||
draggingBooksFlow.value = null
|
draggingBooksFlow.value = null
|
||||||
saveBookOrder(reorderedBooks)
|
saveBookOrder(reorderedUiBooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncDragState(books: List<BookShelfItem>, canReorderBooks: Boolean) {
|
private fun syncDragState(books: List<BookUiItem>, canReorderBooks: Boolean) {
|
||||||
if (!canReorderBooks) {
|
if (!canReorderBooks) {
|
||||||
clearDragState()
|
clearDragState()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val pending = pendingSavedBooksFlow.value ?: return
|
val pending = pendingSavedBooksFlow.value ?: return
|
||||||
if (books.map { it.bookUrl } == pending.map { it.bookUrl }) {
|
if (books.map { it.book.bookUrl } == pending.map { it.book.bookUrl }) {
|
||||||
pendingSavedBooksFlow.value = null
|
pendingSavedBooksFlow.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,10 +812,10 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun upToc(books: List<BookShelfItem>) {
|
fun upToc(books: List<BookUiItem>) {
|
||||||
val limit = BookshelfConfig.bookshelfRefreshingLimit
|
val limit = BookshelfConfig.bookshelfRefreshingLimit
|
||||||
val list = if (limit > 0) books.take(limit) else books
|
val list = if (limit > 0) books.take(limit) else books
|
||||||
enqueueTocUpdate(list, resetRefreshWhenIdle = false)
|
enqueueTocUpdate(list.map { it.book }, resetRefreshWhenIdle = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enqueueTocUpdate(
|
private fun enqueueTocUpdate(
|
||||||
@@ -1088,7 +1089,7 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportToUri(uri: Uri, items: List<BookShelfItem>) {
|
fun exportToUri(uri: Uri, items: List<BookUiItem>) {
|
||||||
execute {
|
execute {
|
||||||
context.contentResolver.openOutputStream(uri)?.use { out ->
|
context.contentResolver.openOutputStream(uri)?.use { out ->
|
||||||
val writer = JsonWriter(OutputStreamWriter(out, "UTF-8"))
|
val writer = JsonWriter(OutputStreamWriter(out, "UTF-8"))
|
||||||
@@ -1096,11 +1097,11 @@ class BookshelfViewModel(
|
|||||||
writer.beginArray()
|
writer.beginArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
val bookMap = hashMapOf<String, String?>()
|
val bookMap = hashMapOf<String, String?>()
|
||||||
bookMap["name"] = it.name
|
bookMap["name"] = it.book.name
|
||||||
bookMap["author"] = it.author
|
bookMap["author"] = it.book.author
|
||||||
// intro is not in BookShelfItem, fetch from DB if needed or skip
|
// intro is not in BookShelfItem, fetch from DB if needed or skip
|
||||||
// For now, let's keep it simple and skip intro or fetch it
|
// For now, let's keep it simple and skip intro or fetch it
|
||||||
val fullBook = appDb.bookDao.getBook(it.bookUrl)
|
val fullBook = appDb.bookDao.getBook(it.book.bookUrl)
|
||||||
bookMap["intro"] = fullBook?.getDisplayIntro()
|
bookMap["intro"] = fullBook?.getDisplayIntro()
|
||||||
GSON.toJson(bookMap, bookMap::class.java, writer)
|
GSON.toJson(bookMap, bookMap::class.java, writer)
|
||||||
}
|
}
|
||||||
@@ -1114,14 +1115,14 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadBookshelf(items: List<BookShelfItem>) {
|
fun uploadBookshelf(items: List<BookUiItem>) {
|
||||||
execute {
|
execute {
|
||||||
val json = withContext(Dispatchers.Default) {
|
val json = withContext(Dispatchers.Default) {
|
||||||
val list = items.map {
|
val list = items.map {
|
||||||
val bookMap = hashMapOf<String, String?>()
|
val bookMap = hashMapOf<String, String?>()
|
||||||
bookMap["name"] = it.name
|
bookMap["name"] = it.book.name
|
||||||
bookMap["author"] = it.author
|
bookMap["author"] = it.book.author
|
||||||
val fullBook = appDb.bookDao.getBook(it.bookUrl)
|
val fullBook = appDb.bookDao.getBook(it.book.bookUrl)
|
||||||
bookMap["intro"] = fullBook?.getDisplayIntro()
|
bookMap["intro"] = fullBook?.getDisplayIntro()
|
||||||
bookMap
|
bookMap
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1150,7 @@ class BookshelfViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportBookshelf(items: List<BookShelfItem>?, success: (file: File) -> Unit) {
|
fun exportBookshelf(items: List<BookUiItem>?, success: (file: File) -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
items?.let {
|
items?.let {
|
||||||
val path = "${context.filesDir}/books.json"
|
val path = "${context.filesDir}/books.json"
|
||||||
@@ -1161,9 +1162,9 @@ class BookshelfViewModel(
|
|||||||
writer.beginArray()
|
writer.beginArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
val bookMap = hashMapOf<String, String?>()
|
val bookMap = hashMapOf<String, String?>()
|
||||||
bookMap["name"] = it.name
|
bookMap["name"] = it.book.name
|
||||||
bookMap["author"] = it.author
|
bookMap["author"] = it.book.author
|
||||||
val fullBook = appDb.bookDao.getBook(it.bookUrl)
|
val fullBook = appDb.bookDao.getBook(it.book.bookUrl)
|
||||||
bookMap["intro"] = fullBook?.getDisplayIntro()
|
bookMap["intro"] = fullBook?.getDisplayIntro()
|
||||||
GSON.toJson(bookMap, bookMap::class.java, writer)
|
GSON.toJson(bookMap, bookMap::class.java, writer)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user