Feat(ToolScreen): Support get tool online

Support get tool online in page
This commit is contained in:
2024-05-10 05:47:30 +08:00
parent b2cbea5383
commit c596767c37
31 changed files with 710 additions and 149 deletions

View File

@@ -1,3 +1,4 @@
/*
package top.fatweb.oxygen.toolbox.ui.component
import androidx.compose.animation.AnimatedVisibility
@@ -202,4 +203,4 @@ fun ToolGroupContentPreview() {
ToolDataSource().tool.first().map { it.tools }.flatten()
})
}
}
}*/

View File

@@ -2,21 +2,17 @@ package top.fatweb.oxygen.toolbox.ui.tool
import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridScope
import androidx.compose.foundation.lazy.staggeredgrid.items
import top.fatweb.oxygen.toolbox.ui.component.ToolGroupCard
import androidx.compose.material3.Text
import androidx.paging.compose.LazyPagingItems
import top.fatweb.oxygen.toolbox.model.tool.Tool
fun LazyStaggeredGridScope.toolsPanel(
toolsScreenUiState: ToolsScreenUiState
toolStorePagingItems: LazyPagingItems<Tool>
) {
when (toolsScreenUiState) {
ToolsScreenUiState.Loading -> Unit
is ToolsScreenUiState.Success -> {
items(
items = toolsScreenUiState.toolGroups,
key = { it.id },
) {
ToolGroupCard(toolGroup = it)
}
}
items(
items = toolStorePagingItems.itemSnapshotList,
key = { it!!.id },
) {
Text(text = it!!.name)
}
}

View File

@@ -1,5 +1,6 @@
package top.fatweb.oxygen.toolbox.ui.tool
import android.util.Log
import androidx.activity.compose.ReportDrawnWhen
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement
@@ -19,48 +20,44 @@ import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import top.fatweb.oxygen.toolbox.R
import top.fatweb.oxygen.toolbox.data.tool.ToolDataSource
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import top.fatweb.oxygen.toolbox.model.tool.Tool
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.DraggableScrollbar
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.rememberDraggableScroller
import top.fatweb.oxygen.toolbox.ui.component.scrollbar.scrollbarState
import top.fatweb.oxygen.toolbox.ui.theme.OxygenPreviews
import top.fatweb.oxygen.toolbox.ui.theme.OxygenTheme
@Composable
internal fun ToolsRoute(
modifier: Modifier = Modifier,
viewModel: ToolsScreenViewModel = hiltViewModel()
) {
val toolsScreenUiState by viewModel.toolsScreenUiState.collectAsStateWithLifecycle()
val toolStorePagingItems = viewModel.getStoreData().collectAsLazyPagingItems()
ToolsScreen(
modifier = modifier,
toolsScreenUiState = toolsScreenUiState
toolStorePagingItems = toolStorePagingItems
)
}
@Composable
internal fun ToolsScreen(
modifier: Modifier = Modifier,
toolsScreenUiState: ToolsScreenUiState
toolStorePagingItems: LazyPagingItems<Tool>
) {
val isToolLoading = toolsScreenUiState is ToolsScreenUiState.Loading
val isToolLoading = toolStorePagingItems.loadState.refresh is LoadState.Loading
Log.d("TAG", "ToolsScreen: ${toolStorePagingItems.loadState}")
ReportDrawnWhen { !isToolLoading }
val itemsAvailable = howManyItems(toolsScreenUiState)
val itemsAvailable = toolStorePagingItems.itemCount
val state = rememberLazyStaggeredGridState()
val scrollbarState = state.scrollbarState(itemsAvailable = itemsAvailable)
@@ -68,49 +65,35 @@ internal fun ToolsScreen(
Box(
modifier.fillMaxSize()
) {
when (toolsScreenUiState) {
ToolsScreenUiState.Loading -> {
Text(text = stringResource(R.string.feature_settings_loading))
}
LazyVerticalStaggeredGrid(
columns = StaggeredGridCells.Adaptive(300.dp),
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalItemSpacing = 24.dp,
state = state
) {
is ToolsScreenUiState.Success -> {
LazyVerticalStaggeredGrid(
columns = StaggeredGridCells.Adaptive(300.dp),
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalItemSpacing = 24.dp,
state = state
) {
toolsPanel(toolStorePagingItems = toolStorePagingItems)
toolsPanel(toolsScreenUiState = toolsScreenUiState)
item(span = StaggeredGridItemSpan.FullLine) {
Spacer(modifier = Modifier.height(8.dp))
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing))
}
}
state.DraggableScrollbar(
modifier = Modifier
.fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars)
.padding(horizontal = 2.dp)
.align(Alignment.CenterEnd),
state = scrollbarState, orientation = Orientation.Vertical,
onThumbMoved = state.rememberDraggableScroller(itemsAvailable = itemsAvailable)
)
item(span = StaggeredGridItemSpan.FullLine) {
Spacer(modifier = Modifier.height(8.dp))
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing))
}
}
state.DraggableScrollbar(
modifier = Modifier
.fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars)
.padding(horizontal = 2.dp)
.align(Alignment.CenterEnd),
state = scrollbarState, orientation = Orientation.Vertical,
onThumbMoved = state.rememberDraggableScroller(itemsAvailable = itemsAvailable)
)
}
}
fun howManyItems(toolScreenUiState: ToolsScreenUiState) =
when (toolScreenUiState) {
ToolsScreenUiState.Loading -> 0
is ToolsScreenUiState.Success -> toolScreenUiState.toolGroups.size
}
/*
@OxygenPreviews
@Composable
fun ToolsScreenLoadingPreview() {
@@ -130,4 +113,4 @@ fun ToolsScreenPreview() {
})
)
}
}
}*/

View File

@@ -1,34 +1,44 @@
package top.fatweb.oxygen.toolbox.ui.tool
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import top.fatweb.oxygen.toolbox.model.tool.ToolGroup
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import top.fatweb.oxygen.toolbox.model.Page
import top.fatweb.oxygen.toolbox.model.tool.Tool
import top.fatweb.oxygen.toolbox.repository.tool.ToolRepository
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@HiltViewModel
class ToolsScreenViewModel @Inject constructor(
toolRepository: ToolRepository
private val toolRepository: ToolRepository,
savedStateHandle: SavedStateHandle
) : ViewModel() {
val toolsScreenUiState: StateFlow<ToolsScreenUiState> =
toolRepository.toolGroups
.map {
ToolsScreenUiState.Success(it)
}
.stateIn(
scope = viewModelScope,
initialValue = ToolsScreenUiState.Loading,
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
)
private val searchValue = savedStateHandle.getStateFlow(SEARCH_VALUE, "")
private val currentPage = savedStateHandle.getStateFlow(CURRENT_PAGE, 1)
@OptIn(ExperimentalCoroutinesApi::class)
fun getStoreData(): Flow<PagingData<Tool>> {
return combine(
searchValue,
currentPage,
::Pair
).flatMapLatest { (searchValue, currentPage) ->
toolRepository.getStore(searchValue, currentPage).cachedIn(viewModelScope)
}
}
}
sealed interface ToolsScreenUiState {
data object Loading : ToolsScreenUiState
data class Success(val toolGroups: List<ToolGroup>) : ToolsScreenUiState
}
data class Success(val tools: Page<Tool>) : ToolsScreenUiState
}
private const val SEARCH_VALUE = "searchValue"
private const val CURRENT_PAGE = "currentPage"