控件优化和文件夹崩溃修复
This commit is contained in:
@@ -4,8 +4,8 @@ import android.annotation.SuppressLint
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.AnimatedVisibilityScope
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.animation.animateContentSize
|
||||
@@ -42,7 +42,6 @@ import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Slider
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -61,29 +60,30 @@ import androidx.compose.ui.unit.dp
|
||||
import dev.chrisbanes.haze.HazeState
|
||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase
|
||||
import io.legado.app.domain.model.BookShelfState
|
||||
import io.legado.app.ui.main.bookCoverSharedElementKey
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.responsiveHazeEffect
|
||||
import io.legado.app.ui.theme.responsiveHazeSource
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.SearchBar
|
||||
import io.legado.app.ui.widget.components.book.SearchBookGridItem
|
||||
import io.legado.app.ui.widget.components.book.SearchBookListItem
|
||||
import io.legado.app.ui.widget.components.button.AnimatedTextButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import io.legado.app.ui.widget.components.card.TextCard
|
||||
import io.legado.app.ui.widget.components.explore.calculateExploreKindRows
|
||||
import io.legado.app.ui.widget.components.explore.ExploreKindMultiTypeItem
|
||||
import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase
|
||||
import io.legado.app.ui.widget.components.explore.calculateExploreKindRows
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||
import io.legado.app.ui.widget.components.book.SearchBookGridItem
|
||||
import io.legado.app.ui.widget.components.book.SearchBookListItem
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
import io.legado.app.ui.main.bookCoverSharedElementKey
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@@ -410,6 +410,7 @@ fun ExploreShowScreen(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
isRefreshing = isRefreshing,
|
||||
onRefresh = { viewModel.loadMore(isRefresh = true) },
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
Crossfade(
|
||||
targetState = isGridMode,
|
||||
|
||||
@@ -12,10 +12,10 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
@@ -32,21 +32,19 @@ import androidx.compose.material.icons.filled.FolderOpen
|
||||
import androidx.compose.material.icons.outlined.Book
|
||||
import androidx.compose.material.icons.outlined.Description
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@@ -54,24 +52,26 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.ui.config.importBookConfig.ImportBookConfig
|
||||
import io.legado.app.lib.dialogs.alert
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.ui.config.importBookConfig.ImportBookConfig
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.widget.components.ActionItem
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
import io.legado.app.ui.widget.components.SelectionActions
|
||||
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
||||
import io.legado.app.ui.widget.components.button.SmallTonalIconButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.card.TextCard
|
||||
import io.legado.app.ui.widget.components.filePicker.FilePickerSheet
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.list.ListScaffold
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.utils.ConvertUtils
|
||||
import io.legado.app.utils.startActivityForBook
|
||||
import io.legado.app.utils.toastOnUi
|
||||
@@ -197,10 +197,13 @@ private fun ImportBookContent(
|
||||
.padding(paddingValues),
|
||||
isRefreshing = state.isLoading,
|
||||
onRefresh = onScanFolder,
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
when {
|
||||
state.items.isEmpty() && state.isLoading -> {
|
||||
AppCircularProgressIndicator(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.Center))
|
||||
AppCircularProgressIndicator(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.wrapContentSize(Alignment.Center))
|
||||
}
|
||||
|
||||
state.items.isEmpty() -> {
|
||||
|
||||
@@ -12,12 +12,12 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
@@ -41,11 +41,9 @@ import androidx.compose.material.icons.outlined.Book
|
||||
import androidx.compose.material.icons.outlined.CloudSync
|
||||
import androidx.compose.material.icons.outlined.Description
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -71,6 +69,7 @@ import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.model.remote.RemoteBook
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.widget.components.ActionItem
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.AppRadioButton
|
||||
import io.legado.app.ui.widget.components.AppTextField
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
@@ -80,15 +79,15 @@ import io.legado.app.ui.widget.components.button.ConfirmDismissButtonsRow
|
||||
import io.legado.app.ui.widget.components.button.MediumIconButton
|
||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
||||
import io.legado.app.ui.widget.components.button.SmallTonalIconButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.card.SelectionItemCard
|
||||
import io.legado.app.ui.widget.components.card.TextCard
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.list.ListScaffold
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.utils.ConvertUtils
|
||||
import io.legado.app.utils.startActivityForBook
|
||||
import io.legado.app.utils.toastOnUi
|
||||
@@ -323,10 +322,13 @@ fun RemoteBookScreen(
|
||||
.padding(paddingValues),
|
||||
isRefreshing = uiState.isLoading,
|
||||
onRefresh = { viewModel.dispatch(RemoteBookIntent.Refresh) },
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
if (uiState.items.isEmpty()) {
|
||||
if (uiState.isLoading) {
|
||||
AppCircularProgressIndicator(modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.Center))
|
||||
AppCircularProgressIndicator(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.wrapContentSize(Alignment.Center))
|
||||
} else {
|
||||
EmptyMessage(
|
||||
modifier = Modifier
|
||||
|
||||
@@ -23,8 +23,8 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.FormatListBulleted
|
||||
import androidx.compose.material.icons.filled.Book
|
||||
@@ -37,7 +37,6 @@ import androidx.compose.material.icons.filled.Timeline
|
||||
import androidx.compose.material.icons.outlined.Book
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
@@ -45,7 +44,6 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MediumFlexibleTopAppBar
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -82,29 +80,31 @@ import io.legado.app.ui.config.coverConfig.CoverConfig
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.LocalHazeState
|
||||
import io.legado.app.ui.theme.ProvideThemeOverride
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.ThemeOverrideState
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.rememberImageSeedColor
|
||||
import io.legado.app.ui.theme.rememberThemeOverride
|
||||
import io.legado.app.ui.theme.responsiveHazeEffectFixedStyle
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.AppTextField
|
||||
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.card.TextCard
|
||||
import io.legado.app.ui.widget.components.cover.CoilBookCover
|
||||
import io.legado.app.ui.widget.components.cover.buildCoverImageRequest
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.cover.buildCoverImageRequest
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import io.legado.app.ui.widget.components.text.AnimatedTextLine
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarScrollBehavior
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarScrollBehavior
|
||||
import io.legado.app.ui.widget.components.topbar.M3GlassScrollBehavior
|
||||
import io.legado.app.ui.widget.components.topbar.MiuixGlassScrollBehavior
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import kotlinx.coroutines.delay
|
||||
import org.koin.compose.koinInject
|
||||
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
||||
@@ -192,6 +192,7 @@ private fun BookInfoScreenContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
isRefreshing = state.isTocLoading,
|
||||
onRefresh = { onIntent(BookInfoIntent.MenuAction(BookInfoMenuAction.Refresh)) },
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
@@ -692,7 +693,9 @@ private fun BookInfoHeader(
|
||||
author = book.author,
|
||||
path = book.getDisplayCover(),
|
||||
sourceOrigin = book.origin,
|
||||
modifier = Modifier.width(112.dp).aspectRatio(5f / 7f),
|
||||
modifier = Modifier
|
||||
.width(112.dp)
|
||||
.aspectRatio(5f / 7f),
|
||||
showLoadingPlaceholder = sharedCoverKey == null,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
|
||||
@@ -13,22 +13,19 @@ import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.AnimatedVisibilityScope
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||
import androidx.compose.animation.core.SeekableTransitionState
|
||||
import androidx.compose.animation.core.rememberTransition
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.scaleIn
|
||||
import androidx.compose.animation.scaleOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -59,7 +56,6 @@ import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.GridView
|
||||
import androidx.compose.material.icons.filled.History
|
||||
import androidx.compose.material.icons.filled.ImportExport
|
||||
import androidx.compose.material.icons.filled.Link
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.material.icons.filled.Save
|
||||
@@ -67,16 +63,12 @@ import androidx.compose.material.icons.filled.SelectAll
|
||||
import androidx.compose.material.icons.filled.UploadFile
|
||||
import androidx.compose.material.icons.filled.Wifi
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Surface
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -87,26 +79,23 @@ import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.platform.LocalClipboard
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import io.legado.app.R
|
||||
import io.legado.app.base.BaseRuleEvent
|
||||
import io.legado.app.ui.about.AppLogSheet
|
||||
import io.legado.app.data.entities.BookGroup
|
||||
import io.legado.app.ui.about.AppLogSheet
|
||||
import io.legado.app.ui.book.group.GroupEditSheet
|
||||
import io.legado.app.ui.book.info.GroupSelectSheet
|
||||
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
|
||||
@@ -114,33 +103,31 @@ import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||
import io.legado.app.ui.main.bookCoverSharedElementKey
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.adaptiveContentPadding
|
||||
import io.legado.app.ui.theme.adaptiveContentPaddingBookshelf
|
||||
import io.legado.app.ui.theme.adaptiveHorizontalPadding
|
||||
import io.legado.app.ui.theme.adaptiveHorizontalPaddingTab
|
||||
import io.legado.app.ui.widget.components.ActionItem
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
import io.legado.app.ui.widget.components.SelectionActions
|
||||
import io.legado.app.ui.widget.components.SelectionBottomBar
|
||||
import io.legado.app.ui.widget.components.button.SmallOutlinedIconToggleButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
||||
import io.legado.app.ui.widget.components.button.SmallOutlinedIconToggleButton
|
||||
import io.legado.app.ui.widget.components.card.NormalCard
|
||||
import io.legado.app.ui.widget.components.card.TextCard
|
||||
import io.legado.app.ui.widget.components.divider.PillHeaderDivider
|
||||
import io.legado.app.ui.widget.components.filePicker.FilePickerSheet
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.icon.AppIcons
|
||||
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
||||
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyVerticalGrid
|
||||
import io.legado.app.ui.widget.components.list.TopFloatingStickyItem
|
||||
import io.legado.app.ui.widget.components.topbar.DynamicTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
|
||||
import io.legado.app.ui.widget.components.tabRow.AppTabRow
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import io.legado.app.ui.widget.components.topbar.DynamicTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -173,20 +160,6 @@ fun BookshelfScreen(
|
||||
|
||||
ReportDrawnWhen { uiState.groups.isNotEmpty() }
|
||||
|
||||
val activeOverlay = uiState.activeOverlay
|
||||
val showGroupMenu = activeOverlay == BookshelfOverlay.GroupMenu
|
||||
val isEditMode = uiState.isEditMode
|
||||
val selectedBookUrls = uiState.selectedBookUrls
|
||||
val isInFolderRoot = uiState.isInFolderRoot
|
||||
val bookGroupStyle = uiState.bookGroupStyle
|
||||
|
||||
val transitionState = remember { SeekableTransitionState(isInFolderRoot) }
|
||||
LaunchedEffect(isInFolderRoot) {
|
||||
if (transitionState.targetState != isInFolderRoot) {
|
||||
transitionState.animateTo(isInFolderRoot)
|
||||
}
|
||||
}
|
||||
|
||||
val clipboardManager = LocalClipboard.current
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
@@ -277,6 +250,21 @@ fun BookshelfScreen(
|
||||
return
|
||||
}
|
||||
|
||||
val activeOverlay = uiState.activeOverlay
|
||||
val showGroupMenu = activeOverlay == BookshelfOverlay.GroupMenu
|
||||
val isEditMode = uiState.isEditMode
|
||||
val selectedBookUrls = uiState.selectedBookUrls
|
||||
val isInFolderRoot = uiState.isInFolderRoot
|
||||
val bookGroupStyle = uiState.bookGroupStyle
|
||||
|
||||
val transitionState = remember { SeekableTransitionState(isInFolderRoot) }
|
||||
val folderTransition = rememberTransition(transitionState, label = "FolderTransition")
|
||||
LaunchedEffect(isInFolderRoot) {
|
||||
if (transitionState.targetState != isInFolderRoot) {
|
||||
transitionState.animateTo(isInFolderRoot)
|
||||
}
|
||||
}
|
||||
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = uiState.selectedGroupIndex,
|
||||
pageCount = { uiState.groups.size }
|
||||
@@ -742,25 +730,36 @@ fun BookshelfScreen(
|
||||
isRefreshing = uiState.isRefreshing,
|
||||
onRefresh = { viewModel.refreshBooks(uiState.items) },
|
||||
enabled = pullToRefreshEnabled,
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
val transition = rememberTransition(
|
||||
transitionState,
|
||||
label = "FolderTransition"
|
||||
)
|
||||
transition.AnimatedContent(
|
||||
folderTransition.AnimatedContent(
|
||||
transitionSpec = {
|
||||
val easing = FastOutSlowInEasing
|
||||
val duration = 480
|
||||
if (targetState) {
|
||||
(fadeIn(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleIn(initialScale = 1.05f, animationSpec = tween(duration, easing = easing)))
|
||||
.togetherWith(fadeOut(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleOut(targetScale = 0.95f, animationSpec = tween(duration, easing = easing)))
|
||||
(fadeIn(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleIn(
|
||||
initialScale = 1.2f,
|
||||
animationSpec = tween(duration, easing = easing)
|
||||
))
|
||||
.togetherWith(fadeOut(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleOut(
|
||||
targetScale = 0.8f,
|
||||
animationSpec = tween(duration, easing = easing)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
(fadeIn(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleIn(initialScale = 0.95f, animationSpec = tween(duration, easing = easing)))
|
||||
.togetherWith(fadeOut(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleOut(targetScale = 1.05f, animationSpec = tween(duration, easing = easing)))
|
||||
(fadeIn(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleIn(
|
||||
initialScale = 0.8f,
|
||||
animationSpec = tween(duration, easing = easing)
|
||||
))
|
||||
.togetherWith(fadeOut(animationSpec = tween(duration, easing = easing)) +
|
||||
scaleOut(
|
||||
targetScale = 1.2f,
|
||||
animationSpec = tween(duration, easing = easing)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
) { isRoot ->
|
||||
|
||||
@@ -67,16 +67,15 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
@@ -160,7 +159,11 @@ class BookshelfViewModel(
|
||||
val events = _eventChannel.receiveAsFlow()
|
||||
|
||||
val groupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowShow()
|
||||
.onEach { isInitialLoadingFlow.value = false }
|
||||
.onEach {
|
||||
if (it.isNotEmpty()) {
|
||||
isInitialLoadingFlow.value = false
|
||||
}
|
||||
}
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
|
||||
|
||||
val allGroupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowAll()
|
||||
@@ -477,6 +480,10 @@ class BookshelfViewModel(
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfUiState())
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
delay(500)
|
||||
isInitialLoadingFlow.value = false
|
||||
}
|
||||
viewModelScope.launch {
|
||||
FlowEventBus.with<Unit>(EventBus.UP_ALL_BOOK_TOC).collect {
|
||||
upAllBookToc()
|
||||
|
||||
@@ -33,7 +33,6 @@ import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridS
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Text
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -59,16 +58,15 @@ import io.legado.app.data.entities.RssArticle
|
||||
import io.legado.app.data.entities.RssSource
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.adaptiveContentPadding
|
||||
import io.legado.app.ui.widget.components.AppPullToRefresh
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.cover.buildCoverImageRequest
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
private enum class RssArticleLayout {
|
||||
@@ -136,6 +134,7 @@ fun RssArticlesPage(
|
||||
isRefreshing = loadState.isRefreshing,
|
||||
onRefresh = { rssSource?.let(viewModel::loadArticles) },
|
||||
modifier = modifier.fillMaxSize(),
|
||||
topPadding = paddingValues.calculateTopPadding()
|
||||
) {
|
||||
when (layout) {
|
||||
RssArticleLayout.List, RssArticleLayout.LargeCard -> {
|
||||
@@ -392,7 +391,9 @@ private fun RssArticleItem(
|
||||
}
|
||||
|
||||
RssArticleLayout.LargeCard -> {
|
||||
Column(modifier = Modifier.fillMaxWidth().padding(8.dp)) {
|
||||
Column(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)) {
|
||||
RssArticleImage(
|
||||
article = article,
|
||||
showPlaceholder = false,
|
||||
@@ -421,7 +422,9 @@ private fun RssArticleItem(
|
||||
}
|
||||
|
||||
RssArticleLayout.GridCard -> {
|
||||
Column(modifier = Modifier.fillMaxWidth().padding(8.dp)) {
|
||||
Column(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)) {
|
||||
RssArticleImage(
|
||||
article = article,
|
||||
showPlaceholder = true,
|
||||
@@ -450,7 +453,9 @@ private fun RssArticleItem(
|
||||
}
|
||||
|
||||
RssArticleLayout.Waterfall -> {
|
||||
Column(modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)) {
|
||||
Column(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 8.dp)) {
|
||||
RssArticleImage(
|
||||
article = article,
|
||||
showPlaceholder = false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.legado.app.ui.widget.components
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
@@ -8,10 +9,18 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.legado.app.ui.theme.LegadoTheme.composeEngine
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import kotlinx.coroutines.delay
|
||||
import top.yukonga.miuix.kmp.basic.PullToRefresh as MiuixPullToRefresh
|
||||
import top.yukonga.miuix.kmp.basic.rememberPullToRefreshState as miuixRememberPullToRefreshState
|
||||
|
||||
@@ -22,20 +31,38 @@ fun AppPullToRefresh(
|
||||
onRefresh: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
topPadding: Dp = 0.dp,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
if (ThemeResolver.isMiuixEngine(composeEngine)) {
|
||||
if (enabled) {
|
||||
// Let the miuix library handle gesture/animation, but skip the persistent
|
||||
// Refreshing state that blocks all scroll events.
|
||||
// localIsRefreshing is true only briefly so the indicator shows then hides,
|
||||
// while the actual refresh runs independently.
|
||||
var localIsRefreshing by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(localIsRefreshing) {
|
||||
if (localIsRefreshing) {
|
||||
delay(300)
|
||||
localIsRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
MiuixPullToRefresh(
|
||||
isRefreshing = isRefreshing,
|
||||
onRefresh = onRefresh,
|
||||
isRefreshing = localIsRefreshing,
|
||||
onRefresh = {
|
||||
localIsRefreshing = true
|
||||
onRefresh()
|
||||
},
|
||||
modifier = modifier,
|
||||
contentPadding = PaddingValues(top = topPadding + 16.dp),
|
||||
pullToRefreshState = miuixRememberPullToRefreshState(),
|
||||
refreshTexts = listOf(
|
||||
"下拉刷新",
|
||||
"松开刷新",
|
||||
"正在刷新",
|
||||
"刷新成功"
|
||||
"正在刷新"
|
||||
)
|
||||
) {
|
||||
content()
|
||||
@@ -57,7 +84,9 @@ fun AppPullToRefresh(
|
||||
PullToRefreshDefaults.LoadingIndicator(
|
||||
state = state,
|
||||
isRefreshing = isRefreshing,
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
modifier = Modifier
|
||||
.padding(top = topPadding)
|
||||
.align(Alignment.TopCenter),
|
||||
)
|
||||
}
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user