Refactor(ToolStore): Optimize save install tool info

This commit is contained in:
2024-08-09 16:09:22 +08:00
parent 9b3b391fef
commit 96159e5b80
2 changed files with 154 additions and 144 deletions

View File

@@ -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
}
}
)
}
}

View File

@@ -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(
INSTALL_INFO, ToolStoreUiState.InstallInfo()
) )
val installInfo = savedStateHandle.getStateFlow(INSTALL_INFO, ToolStoreUiState.InstallInfo())
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val storeData: Flow<PagingData<ToolEntity>> = combine( val storeData: Flow<PagingData<ToolEntity>> = combine(
@@ -52,13 +49,17 @@ 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(
toolEntity.authorUsername, toolEntity.toolId
).map {
if (installedStatus.value[toolEntity.authorUsername] == null) { if (installedStatus.value[toolEntity.authorUsername] == null) {
installedStatus.value[toolEntity.authorUsername] = installedStatus.value[toolEntity.authorUsername] =
mutableMapOf(toolEntity.toolId to (it != null)) mutableMapOf(toolEntity.toolId to (it != null))
} else { } else {
installedStatus.value[toolEntity.authorUsername]?.set(toolEntity.toolId, it != null) installedStatus.value[toolEntity.authorUsername]?.set(
toolEntity.toolId, it != null
)
} }
it != null it != null
}.stateIn( }.stateIn(
@@ -67,16 +68,12 @@ class ToolStoreViewModel @Inject constructor(
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds) 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 {