新增隐私分组功能
This commit is contained in:
@@ -73,7 +73,7 @@ val appDb by lazy {
|
||||
}
|
||||
|
||||
@Database(
|
||||
version = 88,
|
||||
version = 89,
|
||||
exportSchema = true,
|
||||
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
||||
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
||||
@@ -128,7 +128,8 @@ val appDb by lazy {
|
||||
AutoMigration(from = 84, to = 85),
|
||||
AutoMigration(from = 85, to = 86),
|
||||
AutoMigration(from = 86, to = 87),
|
||||
AutoMigration(from = 87, to = 88)
|
||||
AutoMigration(from = 87, to = 88),
|
||||
AutoMigration(from = 88, to = 89)
|
||||
]
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
@@ -22,6 +22,15 @@ data class GroupBookCount(
|
||||
val count: Int
|
||||
)
|
||||
|
||||
private const val PRIVATE_GROUP_MASK =
|
||||
"(SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0 AND isPrivate = 1)"
|
||||
|
||||
private const val PUBLIC_GROUP_MASK =
|
||||
"(SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0 AND isPrivate = 0)"
|
||||
|
||||
private const val PUBLIC_BOOK_FILTER =
|
||||
"(`group` = 0 OR (`group` & $PRIVATE_GROUP_MASK) = 0)"
|
||||
|
||||
@Dao
|
||||
interface BookDao {
|
||||
|
||||
@@ -69,7 +78,8 @@ interface BookDao {
|
||||
"""
|
||||
select * from books where type & ${BookType.text} > 0
|
||||
and type & ${BookType.local} = 0
|
||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||
and ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
and $PUBLIC_BOOK_FILTER
|
||||
and (select show from book_groups where groupId = ${BookGroup.IdNetNone}) != 1
|
||||
"""
|
||||
)
|
||||
@@ -103,7 +113,8 @@ interface BookDao {
|
||||
FROM books
|
||||
where type & ${BookType.text} > 0
|
||||
and type & ${BookType.local} = 0
|
||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||
and ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
and $PUBLIC_BOOK_FILTER
|
||||
and (select show from book_groups where groupId = ${BookGroup.IdNetNone}) != 1
|
||||
"""
|
||||
)
|
||||
@@ -138,6 +149,7 @@ interface BookDao {
|
||||
kind,
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
"""
|
||||
)
|
||||
@@ -173,6 +185,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.audio} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfAudio(): Flow<List<BookShelfItem>>
|
||||
@@ -207,6 +220,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.local} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfLocal(): Flow<List<BookShelfItem>>
|
||||
@@ -246,7 +260,8 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
where type & ${BookType.audio} = 0 and type & ${BookType.local} = 0
|
||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||
and ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
and $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfNetNoGroup(): Flow<List<BookShelfItem>>
|
||||
@@ -286,7 +301,8 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
where type & ${BookType.local} > 0
|
||||
and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0
|
||||
and ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
and $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfLocalNoGroup(): Flow<List<BookShelfItem>>
|
||||
@@ -321,6 +337,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE (`group` & :group) > 0
|
||||
AND ((SELECT isPrivate FROM book_groups WHERE groupId = :group) = 1 OR $PUBLIC_BOOK_FILTER)
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfByUserGroup(group: Long): Flow<List<BookShelfItem>>
|
||||
@@ -356,7 +373,8 @@ interface BookDao {
|
||||
kind,
|
||||
wordCount
|
||||
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||'%')
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfSearch(key: String): Flow<List<BookShelfItem>>
|
||||
@@ -391,6 +409,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
where type & ${BookType.updateError} > 0
|
||||
and $PUBLIC_BOOK_FILTER
|
||||
order by durChapterTime desc
|
||||
"""
|
||||
)
|
||||
@@ -426,6 +445,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfUnread(): Flow<List<BookShelfItem>>
|
||||
@@ -460,6 +480,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfReadFinished(): Flow<List<BookShelfItem>>
|
||||
@@ -494,6 +515,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfReading(): Flow<List<BookShelfItem>>
|
||||
@@ -528,6 +550,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.image} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfManga(): Flow<List<BookShelfItem>>
|
||||
@@ -562,6 +585,7 @@ interface BookDao {
|
||||
wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.text} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfText(): Flow<List<BookShelfItem>>
|
||||
@@ -677,35 +701,44 @@ interface BookDao {
|
||||
|
||||
// ── Group preview / count queries (DB-level, replaces in-memory buildGroupPreviewState) ──
|
||||
|
||||
@Query("SELECT COUNT(*) FROM books")
|
||||
@Query("SELECT COUNT(*) FROM books WHERE $PUBLIC_BOOK_FILTER")
|
||||
fun flowAllBookShelfCount(): Flow<Int>
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT ${BookGroup.IdAll} AS groupId, COUNT(*) AS count FROM books
|
||||
SELECT ${BookGroup.IdAll} AS groupId, COUNT(*) AS count FROM books WHERE $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdRoot}, COUNT(*) FROM books
|
||||
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 ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
AND (SELECT show FROM book_groups WHERE groupId = ${BookGroup.IdNetNone}) != 1
|
||||
UNION ALL SELECT ${BookGroup.IdLocal}, COUNT(*) FROM books WHERE type & ${BookType.local} > 0
|
||||
UNION ALL SELECT ${BookGroup.IdAudio}, COUNT(*) FROM books WHERE type & ${BookType.audio} > 0
|
||||
UNION ALL SELECT ${BookGroup.IdLocal}, COUNT(*) FROM books WHERE type & ${BookType.local} > 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdAudio}, COUNT(*) FROM books WHERE type & ${BookType.audio} > 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdNetNone}, COUNT(*) FROM books
|
||||
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 ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdLocalNone}, COUNT(*) FROM books
|
||||
WHERE type & ${BookType.local} > 0
|
||||
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
||||
UNION ALL SELECT ${BookGroup.IdManga}, COUNT(*) FROM books WHERE type & ${BookType.image} > 0
|
||||
UNION ALL SELECT ${BookGroup.IdText}, COUNT(*) FROM books WHERE type & ${BookType.text} > 0
|
||||
UNION ALL SELECT ${BookGroup.IdError}, COUNT(*) FROM books WHERE type & ${BookType.updateError} > 0
|
||||
UNION ALL SELECT ${BookGroup.IdUnread}, COUNT(*) FROM books WHERE durChapterIndex = 0 AND durChapterPos = 0
|
||||
UNION ALL SELECT ${BookGroup.IdReading}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
||||
UNION ALL SELECT ${BookGroup.IdReadFinished}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
||||
AND ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdManga}, COUNT(*) FROM books WHERE type & ${BookType.image} > 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdText}, COUNT(*) FROM books WHERE type & ${BookType.text} > 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdError}, COUNT(*) FROM books WHERE type & ${BookType.updateError} > 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdUnread}, COUNT(*) FROM books WHERE durChapterIndex = 0 AND durChapterPos = 0 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdReading}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1 AND $PUBLIC_BOOK_FILTER
|
||||
UNION ALL SELECT ${BookGroup.IdReadFinished}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND $PUBLIC_BOOK_FILTER
|
||||
"""
|
||||
)
|
||||
fun flowSystemGroupCounts(): Flow<List<GroupBookCount>>
|
||||
|
||||
@Query("SELECT COUNT(*) FROM books WHERE (`group` & :groupId) > 0")
|
||||
@Query(
|
||||
"""
|
||||
SELECT COUNT(*) FROM books
|
||||
WHERE (`group` & :groupId) > 0
|
||||
AND ((SELECT isPrivate FROM book_groups WHERE groupId = :groupId) = 1 OR $PUBLIC_BOOK_FILTER)
|
||||
"""
|
||||
)
|
||||
fun flowUserGroupBookCount(groupId: Long): Flow<Int>
|
||||
|
||||
fun flowGroupPreview(groupId: Long): Flow<List<BookShelfItem>> {
|
||||
@@ -737,6 +770,7 @@ interface BookDao {
|
||||
type, `group`, `order`, canUpdate,
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -753,7 +787,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
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 ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
AND (SELECT show FROM book_groups WHERE groupId = ${BookGroup.IdNetNone}) != 1
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
@@ -771,6 +806,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.local} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -787,6 +823,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.audio} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -803,7 +840,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
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 ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -820,7 +858,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.local} > 0
|
||||
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
|
||||
AND ($PUBLIC_GROUP_MASK & `group`) = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -837,6 +876,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.image} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -853,6 +893,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.text} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -869,6 +910,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE type & ${BookType.updateError} > 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -885,6 +927,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE durChapterIndex = 0 AND durChapterPos = 0
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -901,6 +944,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -917,6 +961,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
|
||||
AND $PUBLIC_BOOK_FILTER
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
@@ -933,6 +978,7 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind, wordCount
|
||||
FROM books
|
||||
WHERE (`group` & :groupId) > 0
|
||||
AND ((SELECT isPrivate FROM book_groups WHERE groupId = :groupId) = 1 OR $PUBLIC_BOOK_FILTER)
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
|
||||
@@ -25,42 +25,75 @@ interface BookGroupDao {
|
||||
|
||||
@get:Query(
|
||||
"""
|
||||
with const as (SELECT sum(groupId) sumGroupId FROM book_groups where groupId > 0)
|
||||
with const as (
|
||||
SELECT
|
||||
COALESCE(SUM(CASE WHEN groupId > 0 AND isPrivate = 0 THEN groupId ELSE 0 END), 0) sumPublicGroupId,
|
||||
COALESCE(SUM(CASE WHEN groupId > 0 AND isPrivate = 1 THEN groupId ELSE 0 END), 0) sumPrivateGroupId
|
||||
FROM book_groups
|
||||
)
|
||||
SELECT book_groups.* FROM book_groups join const
|
||||
where show > 0
|
||||
and (
|
||||
(groupId >= 0 and exists (select 1 from books where `group` & book_groups.groupId > 0))
|
||||
(groupId >= 0 and exists (
|
||||
select 1 from books
|
||||
where `group` & book_groups.groupId > 0
|
||||
and (book_groups.isPrivate = 1 or `group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or groupId = ${BookGroup.IdAll}
|
||||
or (groupId = ${BookGroup.IdLocal} and exists (select 1 from books where type & ${BookType.local} > 0))
|
||||
or (groupId = ${BookGroup.IdAudio} and exists (select 1 from books where type & ${BookType.audio} > 0))
|
||||
or (groupId = ${BookGroup.IdManga} and exists (select 1 FROM books where type & ${BookType.image} > 0))
|
||||
or (groupId = ${BookGroup.IdText} and exists (select 1 FROM books where type & ${BookType.text} > 0))
|
||||
or (groupId = ${BookGroup.IdLocal} and exists (
|
||||
select 1 from books
|
||||
where type & ${BookType.local} > 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdAudio} and exists (
|
||||
select 1 from books
|
||||
where type & ${BookType.audio} > 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdManga} and exists (
|
||||
select 1 FROM books
|
||||
where type & ${BookType.image} > 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdText} and exists (
|
||||
select 1 FROM books
|
||||
where type & ${BookType.text} > 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdReading} and exists (
|
||||
SELECT 1 FROM books
|
||||
WHERE totalChapterNum > 0
|
||||
AND durChapterIndex > 0
|
||||
AND durChapterIndex < totalChapterNum - 1
|
||||
AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdUnread} and exists (
|
||||
SELECT 1 FROM books
|
||||
WHERE durChapterIndex = 0
|
||||
AND durChapterPos = 0
|
||||
AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
or (groupId = ${BookGroup.IdReadFinished} and exists (
|
||||
SELECT 1 FROM books
|
||||
WHERE totalChapterNum > 0
|
||||
AND durChapterIndex >= totalChapterNum - 1
|
||||
AND durChapterPos != 0
|
||||
AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
|
||||
or (groupId = ${BookGroup.IdError} and exists (select 1 from books where type & ${BookType.updateError} > 0))
|
||||
or (groupId = ${BookGroup.IdError} and exists (
|
||||
select 1 from books
|
||||
where type & ${BookType.updateError} > 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
))
|
||||
|
||||
or (groupId = ${BookGroup.IdNetNone}
|
||||
and exists (
|
||||
select 1 from books
|
||||
where type & ${BookType.audio} = 0
|
||||
and type & ${BookType.local} = 0
|
||||
and const.sumGroupId & `group` = 0
|
||||
and (const.sumPublicGroupId & `group`) = 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
)
|
||||
)
|
||||
or (groupId = ${BookGroup.IdLocalNone}
|
||||
@@ -68,7 +101,8 @@ interface BookGroupDao {
|
||||
select 1 from books
|
||||
where type & ${BookType.audio} = 0
|
||||
and type & ${BookType.local} > 0
|
||||
and const.sumGroupId & `group` = 0
|
||||
and (const.sumPublicGroupId & `group`) = 0
|
||||
and (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -124,4 +158,4 @@ interface BookGroupDao {
|
||||
}
|
||||
return id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ data class BookGroup(
|
||||
@ColumnInfo(defaultValue = "1")
|
||||
var show: Boolean = true,
|
||||
@ColumnInfo(defaultValue = "-1")
|
||||
var bookSort: Int = -1
|
||||
var bookSort: Int = -1,
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
var isPrivate: Boolean = false
|
||||
) : Parcelable {
|
||||
|
||||
companion object {
|
||||
@@ -83,8 +85,9 @@ data class BookGroup(
|
||||
&& other.enableRefresh == enableRefresh
|
||||
&& other.show == show
|
||||
&& other.order == order
|
||||
&& other.isPrivate == isPrivate
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,11 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
binding.ivCover.load(group.cover)
|
||||
}
|
||||
binding.cbEnableRefresh.isChecked = group.enableRefresh
|
||||
binding.cbPrivate.isChecked = group.isPrivate
|
||||
if (group.groupId <= 0) {
|
||||
binding.cbPrivate.gone()
|
||||
binding.tvPrivateDesc.gone()
|
||||
}
|
||||
|
||||
selectedSortIndex = group.bookSort
|
||||
val displayIndex = selectedSortIndex + 1
|
||||
@@ -103,6 +108,17 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
selectedSortIndex = position - 1
|
||||
}
|
||||
|
||||
binding.cbPrivate.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
if (!isChecked && bookGroup?.isPrivate == true) {
|
||||
alert(R.string.disable_private_group, R.string.sure_disable_private_group) {
|
||||
yesButton()
|
||||
noButton {
|
||||
buttonView.isChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.run {
|
||||
ivCover.onClick {
|
||||
selectImage.launch()
|
||||
@@ -128,11 +144,13 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
val bookSort = selectedSortIndex
|
||||
val coverPath = binding.ivCover.bitmapPath
|
||||
val enableRefresh = binding.cbEnableRefresh.isChecked
|
||||
val isPrivate = binding.cbPrivate.isChecked
|
||||
bookGroup?.let {
|
||||
it.groupName = groupName
|
||||
it.cover = coverPath
|
||||
it.bookSort = bookSort
|
||||
it.enableRefresh = enableRefresh
|
||||
it.isPrivate = isPrivate
|
||||
viewModel.upGroup(it) {
|
||||
dismiss()
|
||||
}
|
||||
@@ -141,6 +159,7 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
groupName,
|
||||
bookSort,
|
||||
enableRefresh,
|
||||
isPrivate,
|
||||
coverPath
|
||||
) {
|
||||
dismiss()
|
||||
@@ -163,7 +182,12 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
|
||||
|
||||
private fun deleteGroup(ok: () -> Unit) {
|
||||
alert(R.string.delete, R.string.sure_del) {
|
||||
val message = if (bookGroup?.isPrivate == true) {
|
||||
R.string.sure_del_private_group
|
||||
} else {
|
||||
R.string.sure_del
|
||||
}
|
||||
alert(R.string.delete, message) {
|
||||
yesButton {
|
||||
ok.invoke()
|
||||
}
|
||||
@@ -171,4 +195,4 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +103,15 @@ fun GroupEditContent(
|
||||
val context = LocalContext.current
|
||||
var groupName by remember(group) { mutableStateOf(group?.groupName ?: "") }
|
||||
var enableRefresh by remember(group) { mutableStateOf(group?.enableRefresh ?: true) }
|
||||
var isPrivate by remember(group) { mutableStateOf(group?.isPrivate ?: false) }
|
||||
var showDisablePrivateDialog by remember(group) { mutableStateOf(false) }
|
||||
var selectedSortIndex by remember(group) { mutableIntStateOf(group?.bookSort ?: -1) }
|
||||
|
||||
val sortOptions = stringArrayResource(R.array.book_sort)
|
||||
val sortEntryValues = remember(sortOptions) {
|
||||
Array(sortOptions.size) { (it - 1).toString() }
|
||||
}
|
||||
val canSetPrivate = group == null || group.groupId > 0
|
||||
|
||||
val selectImage = rememberLauncherForActivityResult(SelectImageContract()) { result ->
|
||||
result.uri?.let { uri ->
|
||||
@@ -190,6 +193,23 @@ fun GroupEditContent(
|
||||
onCheckedChange = { enableRefresh = it }
|
||||
)
|
||||
|
||||
if (canSetPrivate) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
CompactSwitchSettingItem(
|
||||
title = stringResource(R.string.private_group),
|
||||
description = stringResource(R.string.private_group_desc),
|
||||
checked = isPrivate,
|
||||
onCheckedChange = { checked ->
|
||||
if (!checked && group?.isPrivate == true) {
|
||||
showDisablePrivateDialog = true
|
||||
} else {
|
||||
isPrivate = checked
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
ConfirmDismissButtonsRow(
|
||||
@@ -199,13 +219,14 @@ fun GroupEditContent(
|
||||
if (groupName.isEmpty()) {
|
||||
appCtx.toastOnUi("分组名称不能为空")
|
||||
} else {
|
||||
if (group != null && group.groupId != 0b1L) {
|
||||
if (group != null) {
|
||||
viewModel.upGroup(
|
||||
group.copy(
|
||||
groupName = groupName,
|
||||
cover = coverPath,
|
||||
bookSort = selectedSortIndex,
|
||||
enableRefresh = enableRefresh
|
||||
enableRefresh = enableRefresh,
|
||||
isPrivate = isPrivate
|
||||
)
|
||||
) {
|
||||
onDismissRequest()
|
||||
@@ -215,6 +236,7 @@ fun GroupEditContent(
|
||||
groupName,
|
||||
selectedSortIndex,
|
||||
enableRefresh,
|
||||
isPrivate,
|
||||
coverPath
|
||||
) {
|
||||
onDismissRequest()
|
||||
@@ -226,6 +248,20 @@ fun GroupEditContent(
|
||||
confirmText = stringResource(R.string.ok)
|
||||
)
|
||||
}
|
||||
|
||||
AppAlertDialog(
|
||||
show = showDisablePrivateDialog,
|
||||
onDismissRequest = { showDisablePrivateDialog = false },
|
||||
title = stringResource(R.string.disable_private_group),
|
||||
text = stringResource(R.string.sure_disable_private_group),
|
||||
confirmText = stringResource(android.R.string.ok),
|
||||
onConfirm = {
|
||||
isPrivate = false
|
||||
showDisablePrivateDialog = false
|
||||
},
|
||||
dismissText = stringResource(android.R.string.cancel),
|
||||
onDismiss = { showDisablePrivateDialog = false }
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -247,7 +283,9 @@ fun GroupDeleteAction(
|
||||
show = showDeleteDialog,
|
||||
onDismissRequest = { showDeleteDialog = false },
|
||||
title = stringResource(R.string.delete),
|
||||
text = stringResource(R.string.sure_del),
|
||||
text = stringResource(
|
||||
if (group.isPrivate) R.string.sure_del_private_group else R.string.sure_del
|
||||
),
|
||||
confirmText = stringResource(android.R.string.ok),
|
||||
onConfirm = {
|
||||
showDeleteDialog = false
|
||||
|
||||
@@ -24,6 +24,7 @@ class GroupViewModel(
|
||||
groupName: String,
|
||||
bookSort: Int,
|
||||
enableRefresh: Boolean,
|
||||
isPrivate: Boolean,
|
||||
cover: String?,
|
||||
finally: () -> Unit
|
||||
) {
|
||||
@@ -35,6 +36,7 @@ class GroupViewModel(
|
||||
cover = cover,
|
||||
bookSort = bookSort,
|
||||
enableRefresh = enableRefresh,
|
||||
isPrivate = isPrivate,
|
||||
order = bookGroupRepository.getMaxOrder().plus(1)
|
||||
)
|
||||
bookGroupRepository.getByID(groupId) ?: removeBookGroupAssignmentUseCase.execute(groupId)
|
||||
|
||||
@@ -138,6 +138,7 @@ fun GroupSelectSheet(
|
||||
) {
|
||||
var selectedGroupId by remember(currentGroupId, show) { mutableLongStateOf(currentGroupId) }
|
||||
var editingGroup by remember(show) { mutableStateOf<BookGroup?>(null) }
|
||||
var showAddGroup by remember(show) { mutableStateOf(false) }
|
||||
|
||||
AppModalBottomSheet(
|
||||
show = show,
|
||||
@@ -145,7 +146,7 @@ fun GroupSelectSheet(
|
||||
title = stringResource(R.string.group_select),
|
||||
startAction = {
|
||||
MediumIconButton(
|
||||
onClick = { editingGroup = BookGroup() },
|
||||
onClick = { showAddGroup = true },
|
||||
imageVector = Icons.Default.Add
|
||||
)
|
||||
},
|
||||
@@ -198,7 +199,14 @@ fun GroupSelectSheet(
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
}
|
||||
}
|
||||
GroupEditSheet(show = editingGroup != null, group = editingGroup, onDismissRequest = { editingGroup = null })
|
||||
GroupEditSheet(
|
||||
show = showAddGroup || editingGroup != null,
|
||||
group = editingGroup,
|
||||
onDismissRequest = {
|
||||
showAddGroup = false
|
||||
editingGroup = null
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@@ -648,4 +656,3 @@ fun ChangeSourceSheet(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ data class BookGroupUi(
|
||||
val order: Int,
|
||||
val enableRefresh: Boolean,
|
||||
val show: Boolean,
|
||||
val bookSort: Int
|
||||
val bookSort: Int,
|
||||
val isPrivate: Boolean
|
||||
)
|
||||
|
||||
fun BookGroup.toBookGroupUi() = BookGroupUi(
|
||||
@@ -21,5 +22,6 @@ fun BookGroup.toBookGroupUi() = BookGroupUi(
|
||||
order = order,
|
||||
enableRefresh = enableRefresh,
|
||||
show = show,
|
||||
bookSort = bookSort
|
||||
bookSort = bookSort,
|
||||
isPrivate = isPrivate
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user