新增隐私分组功能

This commit is contained in:
Jad
2026-05-26 14:16:13 +08:00
parent db5b18ca3c
commit 41902a0bb8
15 changed files with 2548 additions and 46 deletions
@@ -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
)