[修复] 修复分组添加和编辑、拖动的功能
[修复] 修复关闭分组时直接消失的问题 [修复] 修复发现错误的字符串 [修复] 修复部分设置无法及时触发的问题 [修复] 修复下拉刷新时刷新全部书籍的问题 [修复] 修复不显示未读数量的问题
This commit is contained in:
12 files changed
+205
-123
No files matched your search
@@ -0,0 +1,45 @@
|
|||||||
|
package io.legado.app.data.repository
|
||||||
|
|
||||||
|
import androidx.lifecycle.asFlow
|
||||||
|
import io.legado.app.data.dao.BookGroupDao
|
||||||
|
import io.legado.app.data.entities.BookGroup
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class BookGroupRepository(private val bookGroupDao: BookGroupDao) {
|
||||||
|
|
||||||
|
fun flowAll(): Flow<List<BookGroup>> {
|
||||||
|
return bookGroupDao.flowAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun flowShow(): Flow<List<BookGroup>> {
|
||||||
|
return bookGroupDao.show.asFlow()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun update(vararg bookGroup: BookGroup) {
|
||||||
|
bookGroupDao.update(*bookGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun insert(vararg bookGroup: BookGroup) {
|
||||||
|
bookGroupDao.insert(*bookGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun delete(vararg bookGroup: BookGroup) {
|
||||||
|
bookGroupDao.delete(*bookGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getUnusedId(): Long {
|
||||||
|
return bookGroupDao.getUnusedId()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMaxOrder(): Int {
|
||||||
|
return bookGroupDao.maxOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getByID(id: Long): BookGroup? {
|
||||||
|
return bookGroupDao.getByID(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun clearCover(groupId: Long) {
|
||||||
|
bookGroupDao.clearCover(groupId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import coil.decode.GifDecoder
|
|||||||
import coil.decode.ImageDecoderDecoder
|
import coil.decode.ImageDecoderDecoder
|
||||||
import coil.decode.SvgDecoder
|
import coil.decode.SvgDecoder
|
||||||
import io.legado.app.data.AppDatabase
|
import io.legado.app.data.AppDatabase
|
||||||
|
import io.legado.app.data.repository.BookGroupRepository
|
||||||
import io.legado.app.data.repository.BookRepository
|
import io.legado.app.data.repository.BookRepository
|
||||||
import io.legado.app.data.repository.DirectLinkUploadRepository
|
import io.legado.app.data.repository.DirectLinkUploadRepository
|
||||||
import io.legado.app.data.repository.ExploreRepository
|
import io.legado.app.data.repository.ExploreRepository
|
||||||
@@ -50,9 +51,11 @@ val appModule = module {
|
|||||||
single { get<AppDatabase>().readRecordDao }
|
single { get<AppDatabase>().readRecordDao }
|
||||||
single { get<AppDatabase>().bookDao }
|
single { get<AppDatabase>().bookDao }
|
||||||
single { get<AppDatabase>().bookChapterDao }
|
single { get<AppDatabase>().bookChapterDao }
|
||||||
|
single { get<AppDatabase>().bookGroupDao }
|
||||||
|
|
||||||
singleOf(::ReadRecordRepository)
|
singleOf(::ReadRecordRepository)
|
||||||
singleOf(::BookRepository)
|
singleOf(::BookRepository)
|
||||||
|
singleOf(::BookGroupRepository)
|
||||||
singleOf(::SearchContentRepository)
|
singleOf(::SearchContentRepository)
|
||||||
singleOf(::RemoteBookRepository)
|
singleOf(::RemoteBookRepository)
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import android.app.Application
|
|||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
|
import io.legado.app.data.repository.BookGroupRepository
|
||||||
|
|
||||||
class GroupViewModel(application: Application) : BaseViewModel(application) {
|
class GroupViewModel(
|
||||||
|
application: Application,
|
||||||
|
private val bookGroupRepository: BookGroupRepository
|
||||||
|
) : BaseViewModel(application) {
|
||||||
|
|
||||||
fun upGroup(vararg bookGroup: BookGroup, finally: (() -> Unit)? = null) {
|
fun upGroup(vararg bookGroup: BookGroup, finally: (() -> Unit)? = null) {
|
||||||
execute {
|
execute {
|
||||||
appDb.bookGroupDao.update(*bookGroup)
|
bookGroupRepository.update(*bookGroup)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
finally?.invoke()
|
finally?.invoke()
|
||||||
}
|
}
|
||||||
@@ -23,17 +27,17 @@ class GroupViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
finally: () -> Unit
|
finally: () -> Unit
|
||||||
) {
|
) {
|
||||||
execute {
|
execute {
|
||||||
val groupId = appDb.bookGroupDao.getUnusedId()
|
val groupId = bookGroupRepository.getUnusedId()
|
||||||
val bookGroup = BookGroup(
|
val bookGroup = BookGroup(
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
groupName = groupName,
|
groupName = groupName,
|
||||||
cover = cover,
|
cover = cover,
|
||||||
bookSort = bookSort,
|
bookSort = bookSort,
|
||||||
enableRefresh = enableRefresh,
|
enableRefresh = enableRefresh,
|
||||||
order = appDb.bookGroupDao.maxOrder.plus(1)
|
order = bookGroupRepository.getMaxOrder().plus(1)
|
||||||
)
|
)
|
||||||
appDb.bookGroupDao.getByID(groupId) ?: appDb.bookDao.removeGroup(groupId)
|
bookGroupRepository.getByID(groupId) ?: appDb.bookDao.removeGroup(groupId)
|
||||||
appDb.bookGroupDao.insert(bookGroup)
|
bookGroupRepository.insert(bookGroup)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
finally()
|
finally()
|
||||||
}
|
}
|
||||||
@@ -41,7 +45,7 @@ class GroupViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
|
|
||||||
fun delGroup(bookGroup: BookGroup, finally: () -> Unit) {
|
fun delGroup(bookGroup: BookGroup, finally: () -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
appDb.bookGroupDao.delete(bookGroup)
|
bookGroupRepository.delete(bookGroup)
|
||||||
appDb.bookDao.removeGroup(bookGroup.groupId)
|
appDb.bookDao.removeGroup(bookGroup.groupId)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
finally()
|
finally()
|
||||||
@@ -50,7 +54,7 @@ class GroupViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
|
|
||||||
fun clearCover(bookGroup: BookGroup, finally: () -> Unit) {
|
fun clearCover(bookGroup: BookGroup, finally: () -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
appDb.bookGroupDao.clearCover(bookGroup.groupId)
|
bookGroupRepository.clearCover(bookGroup.groupId)
|
||||||
}.onFinally {
|
}.onFinally {
|
||||||
finally()
|
finally()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ sealed class MainDestination(
|
|||||||
|
|
||||||
object Explore : MainDestination(
|
object Explore : MainDestination(
|
||||||
"explore",
|
"explore",
|
||||||
R.string.screen_find,
|
R.string.discovery,
|
||||||
Icons.Outlined.Explore,
|
Icons.Outlined.Explore,
|
||||||
Icons.Default.Explore
|
Icons.Default.Explore
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Spacer
|
|||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
@@ -20,10 +21,10 @@ import androidx.compose.material3.BottomAppBarDefaults
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
import androidx.compose.material3.FlexibleBottomAppBar
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
import androidx.compose.material3.NavigationBarItemDefaults
|
import androidx.compose.material3.NavigationBarItemDefaults
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
@@ -159,8 +160,10 @@ fun MainScreen(
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
if (!useRail && MainConfig.showBottomView) {
|
if (!useRail && MainConfig.showBottomView) {
|
||||||
FlexibleBottomAppBar(
|
NavigationBar(
|
||||||
modifier = Modifier.regularHazeEffect(state = hazeState),
|
modifier = Modifier
|
||||||
|
.regularHazeEffect(state = hazeState)
|
||||||
|
.heightIn(max = 84.dp),
|
||||||
containerColor = GlassDefaults.glassColor(
|
containerColor = GlassDefaults.glassColor(
|
||||||
noBlurColor = BottomAppBarDefaults.containerColor,
|
noBlurColor = BottomAppBarDefaults.containerColor,
|
||||||
blurAlpha = GlassDefaults.DefaultBlurAlpha
|
blurAlpha = GlassDefaults.DefaultBlurAlpha
|
||||||
@@ -180,7 +183,7 @@ fun MainScreen(
|
|||||||
},
|
},
|
||||||
colors = NavigationBarItemDefaults.colors(
|
colors = NavigationBarItemDefaults.colors(
|
||||||
indicatorColor = GlassDefaults.glassColor(
|
indicatorColor = GlassDefaults.glassColor(
|
||||||
noBlurColor = MaterialTheme.colorScheme.primaryContainer,
|
noBlurColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
blurAlpha = GlassDefaults.ThickBlurAlpha
|
blurAlpha = GlassDefaults.ThickBlurAlpha
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package io.legado.app.ui.main.bookshelf
|
package io.legado.app.ui.main.bookshelf
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
@@ -48,6 +49,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
@@ -150,6 +152,13 @@ fun BookshelfScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
val bookshelfLayoutMode =
|
||||||
|
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape else BookshelfConfig.bookshelfLayoutModePortrait
|
||||||
|
val bookshelfLayoutGrid =
|
||||||
|
if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscape else BookshelfConfig.bookshelfLayoutGridPortrait
|
||||||
|
|
||||||
ListScaffold(
|
ListScaffold(
|
||||||
title = title,
|
title = title,
|
||||||
state = uiState,
|
state = uiState,
|
||||||
@@ -271,7 +280,7 @@ fun BookshelfScreen(
|
|||||||
onRefresh = {
|
onRefresh = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
viewModel.upAllBookToc()
|
viewModel.upToc(uiState.items)
|
||||||
delay(1000)
|
delay(1000)
|
||||||
isRefreshing = false
|
isRefreshing = false
|
||||||
}
|
}
|
||||||
@@ -290,26 +299,26 @@ fun BookshelfScreen(
|
|||||||
) {
|
) {
|
||||||
if (bookGroupStyle == 2 && isInFolderRoot) {
|
if (bookGroupStyle == 2 && isInFolderRoot) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid.coerceAtLeast(1)),
|
columns = GridCells.Fixed(bookshelfLayoutGrid.coerceAtLeast(1)),
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
bottom = 120.dp,
|
bottom = 120.dp,
|
||||||
start = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
start = if (bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
||||||
end = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp
|
end = if (bookshelfLayoutMode != 0) 12.dp else 0.dp
|
||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
verticalArrangement = Arrangement.spacedBy(if (bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
horizontalArrangement = Arrangement.spacedBy(if (bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
items(uiState.groups) { group ->
|
items(uiState.groups) { group ->
|
||||||
if (uiState.bookshelfLayoutMode == 0) {
|
if (bookshelfLayoutMode == 0) {
|
||||||
BookGroupItemList(
|
BookGroupItemList(
|
||||||
group = group,
|
group = group,
|
||||||
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
||||||
isCompact = uiState.bookshelfLayoutCompact,
|
isCompact = BookshelfConfig.bookshelfLayoutCompact,
|
||||||
titleSmallFont = uiState.titleSmallFont,
|
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
||||||
titleCenter = uiState.titleCenter,
|
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
||||||
titleMaxLines = uiState.titleMaxLines,
|
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
||||||
onClick = {
|
onClick = {
|
||||||
val index = uiState.groups.indexOf(group)
|
val index = uiState.groups.indexOf(group)
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
@@ -323,11 +332,11 @@ fun BookshelfScreen(
|
|||||||
BookGroupItemGrid(
|
BookGroupItemGrid(
|
||||||
group = group,
|
group = group,
|
||||||
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
previewBooks = uiState.groupPreviews[group.groupId] ?: emptyList(),
|
||||||
isCompact = uiState.bookshelfLayoutCompact,
|
isCompact = BookshelfConfig.bookshelfLayoutCompact,
|
||||||
titleSmallFont = uiState.titleSmallFont,
|
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
||||||
titleCenter = uiState.titleCenter,
|
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
||||||
titleMaxLines = uiState.titleMaxLines,
|
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
||||||
coverShadow = uiState.coverShadow,
|
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
||||||
onClick = {
|
onClick = {
|
||||||
val index = uiState.groups.indexOf(group)
|
val index = uiState.groups.indexOf(group)
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
@@ -355,6 +364,8 @@ fun BookshelfScreen(
|
|||||||
paddingValues = paddingValues,
|
paddingValues = paddingValues,
|
||||||
books = books,
|
books = books,
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
|
bookshelfLayoutMode = bookshelfLayoutMode,
|
||||||
|
bookshelfLayoutGrid = bookshelfLayoutGrid,
|
||||||
onBookClick = onBookClick,
|
onBookClick = onBookClick,
|
||||||
onBookLongClick = onBookLongClick
|
onBookLongClick = onBookLongClick
|
||||||
)
|
)
|
||||||
@@ -430,31 +441,33 @@ fun BookshelfPage(
|
|||||||
paddingValues: PaddingValues,
|
paddingValues: PaddingValues,
|
||||||
books: List<Book>,
|
books: List<Book>,
|
||||||
uiState: BookshelfUiState,
|
uiState: BookshelfUiState,
|
||||||
|
bookshelfLayoutMode: Int,
|
||||||
|
bookshelfLayoutGrid: Int,
|
||||||
onBookClick: (Book) -> Unit,
|
onBookClick: (Book) -> Unit,
|
||||||
onBookLongClick: (Book) -> Unit
|
onBookLongClick: (Book) -> Unit
|
||||||
) {
|
) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(uiState.bookshelfLayoutGrid.coerceAtLeast(1)),
|
columns = GridCells.Fixed(bookshelfLayoutGrid.coerceAtLeast(1)),
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
bottom = 120.dp,
|
bottom = 120.dp,
|
||||||
start = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
start = if (bookshelfLayoutMode != 0) 12.dp else 0.dp,
|
||||||
end = if (uiState.bookshelfLayoutMode != 0) 12.dp else 0.dp
|
end = if (bookshelfLayoutMode != 0) 12.dp else 0.dp
|
||||||
),
|
),
|
||||||
verticalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
verticalArrangement = Arrangement.spacedBy(if (bookshelfLayoutMode != 0) 8.dp else 0.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(if (uiState.bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
horizontalArrangement = Arrangement.spacedBy(if (bookshelfLayoutMode != 0) 8.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
items(books, key = { it.bookUrl }) { book ->
|
items(books, key = { it.bookUrl }) { book ->
|
||||||
BookItem(
|
BookItem(
|
||||||
book = book,
|
book = book,
|
||||||
layoutMode = uiState.bookshelfLayoutMode,
|
layoutMode = bookshelfLayoutMode,
|
||||||
isCompact = uiState.bookshelfLayoutCompact,
|
isCompact = BookshelfConfig.bookshelfLayoutCompact,
|
||||||
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
isUpdating = uiState.updatingBooks.contains(book.bookUrl),
|
||||||
titleSmallFont = uiState.titleSmallFont,
|
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
||||||
titleCenter = uiState.titleCenter,
|
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
||||||
titleMaxLines = uiState.titleMaxLines,
|
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
||||||
coverShadow = uiState.coverShadow,
|
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
||||||
onClick = { onBookClick(book) },
|
onClick = { onBookClick(book) },
|
||||||
onLongClick = { onBookLongClick(book) }
|
onLongClick = { onBookLongClick(book) }
|
||||||
)
|
)
|
||||||
@@ -475,7 +488,7 @@ fun BookItem(
|
|||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onLongClick: () -> Unit
|
onLongClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
val unreadCount = (book.totalChapterNum - book.durChapterIndex).coerceAtLeast(0)
|
val unreadCount = book.getUnreadChapterNum()
|
||||||
|
|
||||||
BookshelfItem(
|
BookshelfItem(
|
||||||
isGrid = layoutMode != 0,
|
isGrid = layoutMode != 0,
|
||||||
@@ -486,7 +499,9 @@ fun BookItem(
|
|||||||
author = book.author,
|
author = book.author,
|
||||||
path = book.getDisplayCover(),
|
path = book.getDisplayCover(),
|
||||||
isUpdating = isUpdating,
|
isUpdating = isUpdating,
|
||||||
modifier = modifier
|
modifier = modifier,
|
||||||
|
badgeText = if (BookshelfConfig.showUnread && unreadCount > 0) unreadCount.toString() else null,
|
||||||
|
showBadgeDot = !BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && unreadCount > 0 && book.lastCheckCount > 0
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
title = book.name,
|
title = book.name,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.legado.app.ui.main.bookshelf
|
|||||||
|
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
|
||||||
import io.legado.app.ui.widget.components.list.ListUiState
|
import io.legado.app.ui.widget.components.list.ListUiState
|
||||||
|
|
||||||
data class BookshelfUiState(
|
data class BookshelfUiState(
|
||||||
@@ -15,12 +14,5 @@ data class BookshelfUiState(
|
|||||||
val groupPreviews: Map<Long, List<Book>> = emptyMap(),
|
val groupPreviews: Map<Long, List<Book>> = emptyMap(),
|
||||||
val selectedGroupIndex: Int = 0,
|
val selectedGroupIndex: Int = 0,
|
||||||
val loadingText: String? = null,
|
val loadingText: String? = null,
|
||||||
val bookshelfLayoutMode: Int = 1,
|
|
||||||
val bookshelfLayoutGrid: Int = 3,
|
|
||||||
val bookshelfLayoutCompact: Boolean = BookshelfConfig.bookshelfLayoutCompact,
|
|
||||||
val titleSmallFont: Boolean = BookshelfConfig.bookshelfTitleSmallFont,
|
|
||||||
val titleCenter: Boolean = BookshelfConfig.bookshelfTitleCenter,
|
|
||||||
val titleMaxLines: Int = BookshelfConfig.bookshelfTitleMaxLines,
|
|
||||||
val coverShadow: Boolean = BookshelfConfig.bookshelfCoverShadow,
|
|
||||||
val updatingBooks: Set<String> = emptySet()
|
val updatingBooks: Set<String> = emptySet()
|
||||||
) : ListUiState<Book>
|
) : ListUiState<Book>
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
package io.legado.app.ui.main.bookshelf
|
package io.legado.app.ui.main.bookshelf
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.res.Configuration
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.lifecycle.asFlow
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
@@ -16,6 +15,7 @@ import io.legado.app.data.entities.Book
|
|||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.data.entities.BookSourcePart
|
import io.legado.app.data.entities.BookSourcePart
|
||||||
|
import io.legado.app.data.repository.BookGroupRepository
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.book.BookHelp
|
import io.legado.app.help.book.BookHelp
|
||||||
import io.legado.app.help.book.addType
|
import io.legado.app.help.book.addType
|
||||||
@@ -83,7 +83,10 @@ import java.util.concurrent.Executors
|
|||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class BookshelfViewModel(application: Application) : BaseViewModel(application) {
|
class BookshelfViewModel(
|
||||||
|
application: Application,
|
||||||
|
private val bookGroupRepository: BookGroupRepository
|
||||||
|
) : BaseViewModel(application) {
|
||||||
var addBookJob: Coroutine<*>? = null
|
var addBookJob: Coroutine<*>? = null
|
||||||
|
|
||||||
private val groupIdFlow = MutableStateFlow(BookshelfConfig.saveTabPosition)
|
private val groupIdFlow = MutableStateFlow(BookshelfConfig.saveTabPosition)
|
||||||
@@ -104,8 +107,10 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
|
|
||||||
val scrollTrigger = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
val scrollTrigger = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||||
|
|
||||||
val groupsFlow: StateFlow<List<BookGroup>> = appDb.bookGroupDao.show.asFlow()
|
val groupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowShow()
|
||||||
.map { it }
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||||
|
|
||||||
|
val allGroupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowAll()
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||||
|
|
||||||
private val allBooksFlow = appDb.bookDao.flowAll().flowOn(Dispatchers.Default)
|
private val allBooksFlow = appDb.bookDao.flowAll().flowOn(Dispatchers.Default)
|
||||||
@@ -118,7 +123,8 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
}.flowOn(Dispatchers.Default)
|
}.flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
private val groupPreviewsFlow = combine(groupsFlow, allBooksFlow) { groups, allBooks ->
|
private val groupPreviewsFlow =
|
||||||
|
combine(groupsFlow, allBooksFlow, refreshTrigger) { groups, allBooks, _ ->
|
||||||
if (BookshelfConfig.bookGroupStyle in 2..3) {
|
if (BookshelfConfig.bookGroupStyle in 2..3) {
|
||||||
groups.associate { group ->
|
groups.associate { group ->
|
||||||
val groupBooks = if (group.groupId == BookGroup.IdAll) {
|
val groupBooks = if (group.groupId == BookGroup.IdAll) {
|
||||||
@@ -165,8 +171,6 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
) || it.author.contains(internal.searchKey, true)
|
) || it.author.contains(internal.searchKey, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val isLandscape =
|
|
||||||
context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
|
||||||
|
|
||||||
BookshelfUiState(
|
BookshelfUiState(
|
||||||
items = filteredBooks,
|
items = filteredBooks,
|
||||||
@@ -178,13 +182,6 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
isSearch = internal.searchKey.isNotEmpty(),
|
isSearch = internal.searchKey.isNotEmpty(),
|
||||||
isLoading = internal.loadingText != null,
|
isLoading = internal.loadingText != null,
|
||||||
loadingText = internal.loadingText,
|
loadingText = internal.loadingText,
|
||||||
bookshelfLayoutMode = if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape else BookshelfConfig.bookshelfLayoutModePortrait,
|
|
||||||
bookshelfLayoutGrid = if (isLandscape) BookshelfConfig.bookshelfLayoutGridLandscape else BookshelfConfig.bookshelfLayoutGridPortrait,
|
|
||||||
bookshelfLayoutCompact = BookshelfConfig.bookshelfLayoutCompact,
|
|
||||||
titleSmallFont = BookshelfConfig.bookshelfTitleSmallFont,
|
|
||||||
titleCenter = BookshelfConfig.bookshelfTitleCenter,
|
|
||||||
titleMaxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
|
||||||
coverShadow = BookshelfConfig.bookshelfCoverShadow,
|
|
||||||
updatingBooks = internal.updatingBooks
|
updatingBooks = internal.updatingBooks
|
||||||
)
|
)
|
||||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfUiState())
|
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfUiState())
|
||||||
@@ -201,6 +198,17 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听排序配置变化,触发刷新
|
||||||
|
viewModelScope.launch {
|
||||||
|
snapshotFlow { BookshelfConfig.bookshelfSort }.collect { refresh() }
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
snapshotFlow { BookshelfConfig.bookshelfSortOrder }.collect { refresh() }
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
snapshotFlow { BookshelfConfig.bookGroupStyle }.collect { refresh() }
|
||||||
|
}
|
||||||
|
|
||||||
if (BookshelfConfig.autoRefreshBook) {
|
if (BookshelfConfig.autoRefreshBook) {
|
||||||
upAllBookToc()
|
upAllBookToc()
|
||||||
}
|
}
|
||||||
@@ -212,8 +220,8 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun sortBooks(list: List<Book>, group: BookGroup?): List<Book> {
|
private fun sortBooks(list: List<Book>, group: BookGroup?): List<Book> {
|
||||||
val bookSort = group?.getRealBookSort() ?: AppConfig.bookshelfSort
|
val bookSort = group?.getRealBookSort() ?: BookshelfConfig.bookshelfSort
|
||||||
val isDescending = AppConfig.bookshelfSortOrder == 1
|
val isDescending = BookshelfConfig.bookshelfSortOrder == 1
|
||||||
|
|
||||||
return when (bookSort) {
|
return when (bookSort) {
|
||||||
1 -> if (isDescending) list.sortedByDescending { it.latestChapterTime }
|
1 -> if (isDescending) list.sortedByDescending { it.latestChapterTime }
|
||||||
@@ -404,7 +412,8 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun postUpBooksCount() {
|
private fun postUpBooksCount() {
|
||||||
val count = if (AppConfig.showWaitUpCount) waitUpTocBooks.size + onUpTocBooks.size else 0
|
val count =
|
||||||
|
if (BookshelfConfig.showWaitUpCount) waitUpTocBooks.size + onUpTocBooks.size else 0
|
||||||
FlowEventBus.post(EventBus.UP_BOOKSHELF_COUNT, count)
|
FlowEventBus.post(EventBus.UP_BOOKSHELF_COUNT, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package io.legado.app.ui.main.bookshelf
|
package io.legado.app.ui.main.bookshelf
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
|
||||||
import androidx.compose.animation.fadeIn
|
|
||||||
import androidx.compose.animation.fadeOut
|
|
||||||
import androidx.compose.animation.togetherWith
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -11,16 +7,16 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.Edit
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Switch
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -28,15 +24,18 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.data.entities.BookGroup
|
import io.legado.app.data.entities.BookGroup
|
||||||
import io.legado.app.ui.book.group.GroupEditContent
|
import io.legado.app.ui.book.group.GroupEditContent
|
||||||
import io.legado.app.ui.book.group.GroupViewModel
|
import io.legado.app.ui.book.group.GroupViewModel
|
||||||
|
import io.legado.app.ui.widget.components.card.ReorderableSelectionItem
|
||||||
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
import io.legado.app.ui.widget.components.modalBottomSheet.GlassModalBottomSheet
|
||||||
import io.legado.app.ui.widget.components.settingItem.SettingItem
|
import io.legado.app.utils.move
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -45,19 +44,36 @@ fun GroupManageSheet(
|
|||||||
viewModel: GroupViewModel = koinViewModel(),
|
viewModel: GroupViewModel = koinViewModel(),
|
||||||
bookshelfViewModel: BookshelfViewModel = koinViewModel()
|
bookshelfViewModel: BookshelfViewModel = koinViewModel()
|
||||||
) {
|
) {
|
||||||
val groups by bookshelfViewModel.groupsFlow.collectAsState(initial = emptyList())
|
val context = LocalContext.current
|
||||||
|
val groups by bookshelfViewModel.allGroupsFlow.collectAsState()
|
||||||
var editingGroup by remember { mutableStateOf<BookGroup?>(null) }
|
var editingGroup by remember { mutableStateOf<BookGroup?>(null) }
|
||||||
var isEditing by remember { mutableStateOf(false) }
|
var isEditing by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var listData by remember { mutableStateOf(groups) }
|
||||||
|
val listState = rememberLazyListState()
|
||||||
|
val reorderableState = rememberReorderableLazyListState(listState) { from, to ->
|
||||||
|
listData = listData.toMutableList().apply {
|
||||||
|
move(from.index, to.index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(groups) {
|
||||||
|
if (!reorderableState.isAnyItemDragging) {
|
||||||
|
listData = groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(reorderableState.isAnyItemDragging) {
|
||||||
|
if (!reorderableState.isAnyItemDragging) {
|
||||||
|
val updatedGroups = listData.mapIndexed { index, group ->
|
||||||
|
group.copy(order = index)
|
||||||
|
}
|
||||||
|
viewModel.upGroup(*updatedGroups.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GlassModalBottomSheet(onDismissRequest = onDismissRequest) {
|
GlassModalBottomSheet(onDismissRequest = onDismissRequest) {
|
||||||
AnimatedContent(
|
if (isEditing) {
|
||||||
targetState = isEditing,
|
|
||||||
transitionSpec = {
|
|
||||||
fadeIn().togetherWith(fadeOut())
|
|
||||||
},
|
|
||||||
label = "GroupManageTransition"
|
|
||||||
) { editing ->
|
|
||||||
if (editing) {
|
|
||||||
GroupEditContent(
|
GroupEditContent(
|
||||||
group = editingGroup,
|
group = editingGroup,
|
||||||
onDismissRequest = { isEditing = false },
|
onDismissRequest = { isEditing = false },
|
||||||
@@ -67,12 +83,12 @@ fun GroupManageSheet(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
.padding(bottom = 32.dp)
|
.padding(bottom = 32.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
.padding(vertical = 8.dp),
|
.padding(vertical = 8.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
@@ -93,18 +109,25 @@ fun GroupManageSheet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
state = listState,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
items(groups, key = { it.groupId }) { group ->
|
items(listData, key = { it.groupId }) { group ->
|
||||||
GroupItem(
|
val manageNameInfo = remember(group) { group.getManageName(context) }
|
||||||
group = group,
|
ReorderableSelectionItem(
|
||||||
onEdit = {
|
state = reorderableState,
|
||||||
|
key = group.groupId,
|
||||||
|
title = group.groupName.ifBlank { manageNameInfo.suffix.orEmpty() },
|
||||||
|
subtitle = if (group.groupName.isNotBlank()) manageNameInfo.suffix else null,
|
||||||
|
isEnabled = group.show,
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
|
onEnabledChange = { isChecked ->
|
||||||
|
viewModel.upGroup(group.copy(show = isChecked))
|
||||||
|
},
|
||||||
|
onClickEdit = {
|
||||||
editingGroup = group
|
editingGroup = group
|
||||||
isEditing = true
|
isEditing = true
|
||||||
},
|
|
||||||
onToggle = { isChecked ->
|
|
||||||
viewModel.upGroup(group.copy(show = isChecked))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -112,28 +135,4 @@ fun GroupManageSheet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun GroupItem(
|
|
||||||
group: BookGroup,
|
|
||||||
onEdit: () -> Unit,
|
|
||||||
onToggle: (Boolean) -> Unit
|
|
||||||
) {
|
|
||||||
SettingItem(
|
|
||||||
title = group.groupName,
|
|
||||||
onClick = onEdit,
|
|
||||||
trailingContent = {
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
IconButton(onClick = onEdit) {
|
|
||||||
Icon(Icons.Default.Edit, contentDescription = stringResource(R.string.edit))
|
|
||||||
}
|
|
||||||
Switch(
|
|
||||||
checked = group.show,
|
|
||||||
onCheckedChange = onToggle
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ fun ExploreScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ListScaffold(
|
ListScaffold(
|
||||||
title = stringResource(R.string.screen_find),
|
title = stringResource(R.string.discovery),
|
||||||
state = uiState,
|
state = uiState,
|
||||||
subtitle = uiState.selectedGroup.ifEmpty { stringResource(R.string.all) },
|
subtitle = uiState.selectedGroup.ifEmpty { stringResource(R.string.all) },
|
||||||
onSearchQueryChange = { viewModel.search(it) },
|
onSearchQueryChange = { viewModel.search(it) },
|
||||||
|
|||||||
@@ -60,15 +60,17 @@ fun SelectionItemCard(
|
|||||||
onEnabledChange: ((Boolean) -> Unit)? = null,
|
onEnabledChange: ((Boolean) -> Unit)? = null,
|
||||||
onClickEdit: (() -> Unit)? = null,
|
onClickEdit: (() -> Unit)? = null,
|
||||||
trailingAction: @Composable (RowScope.() -> Unit)? = null,
|
trailingAction: @Composable (RowScope.() -> Unit)? = null,
|
||||||
dropdownContent: @Composable (ColumnScope.(onDismiss: () -> Unit) -> Unit)? = null
|
dropdownContent: @Composable (ColumnScope.(onDismiss: () -> Unit) -> Unit)? = null,
|
||||||
|
containerColor: Color? = null,
|
||||||
|
selectedContainerColor: Color? = null
|
||||||
) {
|
) {
|
||||||
var showMenu by remember { mutableStateOf(false) }
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val containerColor by animateColorAsState(
|
val animatedContainerColor by animateColorAsState(
|
||||||
targetValue = if (isSelected)
|
targetValue = if (isSelected)
|
||||||
MaterialTheme.colorScheme.secondaryContainer
|
selectedContainerColor ?: MaterialTheme.colorScheme.secondaryContainer
|
||||||
else
|
else
|
||||||
MaterialTheme.colorScheme.surfaceContainerLow,
|
containerColor ?: MaterialTheme.colorScheme.surfaceContainerLow,
|
||||||
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
||||||
label = "CardColor"
|
label = "CardColor"
|
||||||
)
|
)
|
||||||
@@ -79,7 +81,7 @@ fun SelectionItemCard(
|
|||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.shapes.medium,
|
||||||
colors = CardDefaults.cardColors(containerColor = containerColor),
|
colors = CardDefaults.cardColors(containerColor = animatedContainerColor),
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = elevation)
|
elevation = CardDefaults.cardElevation(defaultElevation = elevation)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@@ -197,7 +199,9 @@ fun LazyItemScope.ReorderableSelectionItem(
|
|||||||
onEnabledChange: ((Boolean) -> Unit)? = null,
|
onEnabledChange: ((Boolean) -> Unit)? = null,
|
||||||
onClickEdit: (() -> Unit)? = null,
|
onClickEdit: (() -> Unit)? = null,
|
||||||
trailingAction: @Composable (RowScope.() -> Unit)? = null,
|
trailingAction: @Composable (RowScope.() -> Unit)? = null,
|
||||||
dropdownContent: @Composable (ColumnScope.(onDismiss: () -> Unit) -> Unit)? = null
|
dropdownContent: @Composable (ColumnScope.(onDismiss: () -> Unit) -> Unit)? = null,
|
||||||
|
containerColor: Color? = null,
|
||||||
|
selectedContainerColor: Color? = null
|
||||||
) {
|
) {
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
val hapticFeedback = LocalHapticFeedback.current
|
||||||
|
|
||||||
@@ -220,6 +224,8 @@ fun LazyItemScope.ReorderableSelectionItem(
|
|||||||
onClickEdit = onClickEdit,
|
onClickEdit = onClickEdit,
|
||||||
trailingAction = trailingAction,
|
trailingAction = trailingAction,
|
||||||
dropdownContent = dropdownContent,
|
dropdownContent = dropdownContent,
|
||||||
|
containerColor = containerColor,
|
||||||
|
selectedContainerColor = selectedContainerColor,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.zIndex(if (isDragging) 1f else 0f)
|
.zIndex(if (isDragging) 1f else 0f)
|
||||||
.then(
|
.then(
|
||||||
|
|||||||
@@ -58,3 +58,9 @@ fun <T> MutableList<T>.removeLastElement(): T {
|
|||||||
removeAt(lastIndex)
|
removeAt(lastIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> MutableList<T>.move(fromIndex: Int, toIndex: Int) {
|
||||||
|
if (fromIndex == toIndex) return
|
||||||
|
val element = removeAt(fromIndex)
|
||||||
|
add(toIndex, element)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user