Refactor(ToolStore): Optimize save install tool info
This commit is contained in:
@@ -39,6 +39,9 @@ import androidx.compose.material3.TextButton
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.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.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
@@ -84,8 +87,8 @@ internal fun ToolStoreScreen(
|
|||||||
onNavigateToToolView: (username: String, toolId: String) -> Unit,
|
onNavigateToToolView: (username: String, toolId: String) -> Unit,
|
||||||
toolStorePagingItems: LazyPagingItems<ToolEntity>,
|
toolStorePagingItems: LazyPagingItems<ToolEntity>,
|
||||||
hasInstalled: (ToolEntity) -> StateFlow<Boolean>,
|
hasInstalled: (ToolEntity) -> StateFlow<Boolean>,
|
||||||
onChangeInstallStatus: (installStatus: ToolStoreUiState.Status, username: String?, toolId: String?) -> Unit,
|
onChangeInstallStatus: (installStatus: ToolStoreUiState.Status) -> Unit,
|
||||||
onInstallTool: () -> Unit,
|
onInstallTool: (username: String, toolId: String) -> Unit,
|
||||||
installInfo: ToolStoreUiState.InstallInfo
|
installInfo: ToolStoreUiState.InstallInfo
|
||||||
) {
|
) {
|
||||||
val isToolLoading =
|
val isToolLoading =
|
||||||
@@ -101,6 +104,9 @@ internal fun ToolStoreScreen(
|
|||||||
|
|
||||||
val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition")
|
val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition")
|
||||||
|
|
||||||
|
var installToolUsername by remember { mutableStateOf("Unknown") }
|
||||||
|
var installToolId by remember { mutableStateOf("Unknown") }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier.fillMaxSize()
|
modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
@@ -115,11 +121,9 @@ internal fun ToolStoreScreen(
|
|||||||
toolStorePagingItems = toolStorePagingItems,
|
toolStorePagingItems = toolStorePagingItems,
|
||||||
hasInstalled = hasInstalled,
|
hasInstalled = hasInstalled,
|
||||||
onAction = { username, toolId ->
|
onAction = { username, toolId ->
|
||||||
onChangeInstallStatus(
|
installToolUsername = username
|
||||||
ToolStoreUiState.Status.Pending,
|
installToolId = toolId
|
||||||
username,
|
onChangeInstallStatus(ToolStoreUiState.Status.Pending)
|
||||||
toolId
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
onClick = onNavigateToToolView
|
onClick = onNavigateToToolView
|
||||||
)
|
)
|
||||||
@@ -164,112 +168,13 @@ internal fun ToolStoreScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (installInfo.status != ToolStoreUiState.Status.None) {
|
InstallAlertDialog(
|
||||||
Box(
|
status = installInfo.status,
|
||||||
modifier = Modifier.fillMaxSize()
|
onChangeInstallStatus = onChangeInstallStatus,
|
||||||
) {
|
onInstallTool = { onInstallTool(installToolUsername, installToolId) },
|
||||||
AlertDialog(
|
username = installToolUsername,
|
||||||
onDismissRequest = {
|
toolId = installToolId
|
||||||
if (installInfo.status == ToolStoreUiState.Status.Pending) {
|
)
|
||||||
onChangeInstallStatus(ToolStoreUiState.Status.None, null, null)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = when (installInfo.status) {
|
|
||||||
ToolStoreUiState.Status.Success -> OxygenIcons.Success
|
|
||||||
ToolStoreUiState.Status.Fail -> OxygenIcons.Error
|
|
||||||
else -> OxygenIcons.Info
|
|
||||||
},
|
|
||||||
contentDescription = stringResource(R.string.core_install)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(
|
|
||||||
when (installInfo.status) {
|
|
||||||
ToolStoreUiState.Status.Success -> R.string.feature_store_install_success
|
|
||||||
ToolStoreUiState.Status.Fail -> R.string.feature_store_install_fail
|
|
||||||
else -> R.string.feature_store_install_tool
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.width(360.dp)
|
|
||||||
.padding(vertical = 16.dp)
|
|
||||||
) {
|
|
||||||
when (installInfo.status) {
|
|
||||||
ToolStoreUiState.Status.Pending ->
|
|
||||||
Text(
|
|
||||||
text = stringResource(
|
|
||||||
R.string.feature_store_ask_install,
|
|
||||||
installInfo.username,
|
|
||||||
installInfo.toolId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.Installing ->
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
CircularProgressIndicator()
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
Text(text = stringResource(R.string.core_installing))
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.Success ->
|
|
||||||
Text(text = stringResource(R.string.feature_store_install_success_info))
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.Fail ->
|
|
||||||
Text(text = stringResource(R.string.feature_store_install_fail_info))
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.None -> Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
if (installInfo.status == ToolStoreUiState.Status.Pending) {
|
|
||||||
TextButton(onClick = {
|
|
||||||
onChangeInstallStatus(ToolStoreUiState.Status.None, null, null)
|
|
||||||
}) {
|
|
||||||
Text(text = stringResource(R.string.core_cancel))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
when (installInfo.status) {
|
|
||||||
ToolStoreUiState.Status.Pending ->
|
|
||||||
TextButton(onClick = onInstallTool) {
|
|
||||||
Text(text = stringResource(R.string.core_install))
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.Success,
|
|
||||||
ToolStoreUiState.Status.Fail ->
|
|
||||||
TextButton(onClick = {
|
|
||||||
onChangeInstallStatus(ToolStoreUiState.Status.None, null, null)
|
|
||||||
}) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(
|
|
||||||
if (installInfo.status == ToolStoreUiState.Status.Success) R.string.core_ok
|
|
||||||
else R.string.core_close
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolStoreUiState.Status.None,
|
|
||||||
ToolStoreUiState.Status.Installing -> Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun LazyStaggeredGridScope.toolsPanel(
|
private fun LazyStaggeredGridScope.toolsPanel(
|
||||||
@@ -293,3 +198,114 @@ private fun LazyStaggeredGridScope.toolsPanel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun InstallAlertDialog(
|
||||||
|
status: ToolStoreUiState.Status,
|
||||||
|
onChangeInstallStatus: (ToolStoreUiState.Status) -> Unit,
|
||||||
|
onInstallTool: () -> Unit,
|
||||||
|
username: String,
|
||||||
|
toolId: String
|
||||||
|
) {
|
||||||
|
if (status != ToolStoreUiState.Status.None) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {
|
||||||
|
if (status == ToolStoreUiState.Status.Pending) {
|
||||||
|
onChangeInstallStatus(ToolStoreUiState.Status.None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = when (status) {
|
||||||
|
ToolStoreUiState.Status.Success -> OxygenIcons.Success
|
||||||
|
ToolStoreUiState.Status.Fail -> OxygenIcons.Error
|
||||||
|
else -> OxygenIcons.Info
|
||||||
|
},
|
||||||
|
contentDescription = stringResource(R.string.core_install)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
when (status) {
|
||||||
|
ToolStoreUiState.Status.Success -> R.string.feature_store_install_success
|
||||||
|
ToolStoreUiState.Status.Fail -> R.string.feature_store_install_fail
|
||||||
|
else -> R.string.feature_store_install_tool
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(360.dp)
|
||||||
|
.padding(vertical = 16.dp)
|
||||||
|
) {
|
||||||
|
when (status) {
|
||||||
|
ToolStoreUiState.Status.Pending ->
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
R.string.feature_store_ask_install,
|
||||||
|
username,
|
||||||
|
toolId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ToolStoreUiState.Status.Installing ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(text = stringResource(R.string.core_installing))
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolStoreUiState.Status.Success ->
|
||||||
|
Text(text = stringResource(R.string.feature_store_install_success_info))
|
||||||
|
|
||||||
|
ToolStoreUiState.Status.Fail ->
|
||||||
|
Text(text = stringResource(R.string.feature_store_install_fail_info))
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
if (status == ToolStoreUiState.Status.Pending) {
|
||||||
|
TextButton(onClick = {
|
||||||
|
onChangeInstallStatus(ToolStoreUiState.Status.None)
|
||||||
|
}) {
|
||||||
|
Text(text = stringResource(R.string.core_cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
when (status) {
|
||||||
|
ToolStoreUiState.Status.Pending ->
|
||||||
|
TextButton(onClick = onInstallTool) {
|
||||||
|
Text(text = stringResource(R.string.core_install))
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolStoreUiState.Status.Success,
|
||||||
|
ToolStoreUiState.Status.Fail ->
|
||||||
|
TextButton(onClick = {
|
||||||
|
onChangeInstallStatus(ToolStoreUiState.Status.None)
|
||||||
|
}) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
if (status == ToolStoreUiState.Status.Success) R.string.core_ok
|
||||||
|
else R.string.core_close
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,12 +35,9 @@ class ToolStoreViewModel @Inject constructor(
|
|||||||
private val currentPage = savedStateHandle.getStateFlow(CURRENT_PAGE, 1)
|
private val currentPage = savedStateHandle.getStateFlow(CURRENT_PAGE, 1)
|
||||||
private val installedStatus =
|
private val installedStatus =
|
||||||
savedStateHandle.getStateFlow<MutableMap<String, MutableMap<String, Boolean>>>(
|
savedStateHandle.getStateFlow<MutableMap<String, MutableMap<String, Boolean>>>(
|
||||||
INSTALLED_STATUS,
|
INSTALLED_STATUS, mutableMapOf()
|
||||||
mutableMapOf()
|
|
||||||
)
|
)
|
||||||
val installInfo = savedStateHandle.getStateFlow(
|
val installInfo = savedStateHandle.getStateFlow(INSTALL_INFO, ToolStoreUiState.InstallInfo())
|
||||||
INSTALL_INFO, ToolStoreUiState.InstallInfo()
|
|
||||||
)
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val storeData: Flow<PagingData<ToolEntity>> = combine(
|
val storeData: Flow<PagingData<ToolEntity>> = combine(
|
||||||
@@ -52,31 +49,31 @@ class ToolStoreViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasInstalled(toolEntity: ToolEntity): StateFlow<Boolean> =
|
fun hasInstalled(toolEntity: ToolEntity): StateFlow<Boolean> =
|
||||||
installedStatus.value[toolEntity.authorUsername]?.get(toolEntity.toolId)?.let { MutableStateFlow(it) }
|
installedStatus.value[toolEntity.authorUsername]?.get(toolEntity.toolId)
|
||||||
?: toolRepository.getToolByUsernameAndToolId(toolEntity.authorUsername, toolEntity.toolId).map {
|
?.let { MutableStateFlow(it) } ?: toolRepository.getToolByUsernameAndToolId(
|
||||||
if (installedStatus.value[toolEntity.authorUsername] == null) {
|
toolEntity.authorUsername, toolEntity.toolId
|
||||||
installedStatus.value[toolEntity.authorUsername] =
|
).map {
|
||||||
mutableMapOf(toolEntity.toolId to (it != null))
|
if (installedStatus.value[toolEntity.authorUsername] == null) {
|
||||||
} else {
|
installedStatus.value[toolEntity.authorUsername] =
|
||||||
installedStatus.value[toolEntity.authorUsername]?.set(toolEntity.toolId, it != null)
|
mutableMapOf(toolEntity.toolId to (it != null))
|
||||||
}
|
} else {
|
||||||
it != null
|
installedStatus.value[toolEntity.authorUsername]?.set(
|
||||||
}.stateIn(
|
toolEntity.toolId, it != null
|
||||||
scope = viewModelScope,
|
)
|
||||||
initialValue = true,
|
}
|
||||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
|
it != null
|
||||||
)
|
}.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
initialValue = true,
|
||||||
|
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
|
||||||
|
)
|
||||||
|
|
||||||
fun changeInstallStatus(
|
fun changeInstallStatus(installStatus: ToolStoreUiState.Status) {
|
||||||
installStatus: ToolStoreUiState.Status, username: String?, toolId: String?
|
savedStateHandle[INSTALL_INFO] = ToolStoreUiState.InstallInfo(installStatus)
|
||||||
) {
|
|
||||||
savedStateHandle[INSTALL_INFO] =
|
|
||||||
ToolStoreUiState.InstallInfo(installStatus, username ?: "Unknown", toolId ?: "Unknown")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun installTool() {
|
fun installTool(username: String, toolId: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val (_, username, toolId) = installInfo.value
|
|
||||||
storeRepository.detail(username, toolId).collect {
|
storeRepository.detail(username, toolId).collect {
|
||||||
when (it) {
|
when (it) {
|
||||||
Result.Loading -> savedStateHandle[INSTALL_INFO] =
|
Result.Loading -> savedStateHandle[INSTALL_INFO] =
|
||||||
@@ -90,8 +87,7 @@ class ToolStoreViewModel @Inject constructor(
|
|||||||
savedStateHandle[INSTALL_INFO] =
|
savedStateHandle[INSTALL_INFO] =
|
||||||
ToolStoreUiState.InstallInfo(ToolStoreUiState.Status.Success)
|
ToolStoreUiState.InstallInfo(ToolStoreUiState.Status.Success)
|
||||||
if (installedStatus.value[username] == null) {
|
if (installedStatus.value[username] == null) {
|
||||||
installedStatus.value[username] =
|
installedStatus.value[username] = mutableMapOf(toolId to true)
|
||||||
mutableMapOf(toolId to true)
|
|
||||||
} else {
|
} else {
|
||||||
installedStatus.value[username]?.set(toolId, true)
|
installedStatus.value[username]?.set(toolId, true)
|
||||||
}
|
}
|
||||||
@@ -108,9 +104,7 @@ data class ToolStoreUiState(
|
|||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class InstallInfo(
|
data class InstallInfo(
|
||||||
var status: Status = Status.None,
|
var status: Status = Status.None
|
||||||
var username: String = "Unknown",
|
|
||||||
var toolId: String = "Unknown"
|
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
enum class Status {
|
enum class Status {
|
||||||
|
|||||||
Reference in New Issue
Block a user