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