Feat(ToolScreen): Support get tool online
Support get tool online in page
This commit is contained in:
@@ -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()
|
||||
})
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -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"
|
||||
Reference in New Issue
Block a user