Поправлен клик сквозь экран загрузки

This commit is contained in:
Пытков Роман
2025-02-09 22:03:14 +03:00
parent 4404ef2ff4
commit e1646611c2
9 changed files with 122 additions and 44 deletions

View File

@@ -8,6 +8,9 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.Role
@@ -32,3 +35,19 @@ fun Modifier.ignoreVerticalParentPadding(vertical: Dp): Modifier {
}
}
}
fun Modifier.gesturesDisabled(disabled: Boolean = true) =
if (disabled) {
pointerInput(Unit) {
awaitPointerEventScope {
// we should wait for all new pointer events
while (true) {
awaitPointerEvent(pass = PointerEventPass.Initial)
.changes
.forEach(PointerInputChange::consume)
}
}
}
} else {
this
}

View File

@@ -1,26 +1,39 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
import android.widget.ProgressBar
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.github.nullptroma.wallenc.presentation.elements.StorageTree
import com.github.nullptroma.wallenc.presentation.extensions.gesturesDisabled
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LocalVaultScreen(
modifier: Modifier = Modifier,
@@ -29,36 +42,49 @@ fun LocalVaultScreen(
) {
val uiState by viewModel.state.collectAsStateWithLifecycle()
Scaffold(modifier = modifier, contentWindowInsets = WindowInsets(0.dp), floatingActionButton = {
FloatingActionButton(
onClick = {
viewModel.createStorage()
},
) {
Icon(Icons.Filled.Add, "Floating action button.")
}
}) { innerPadding ->
LazyColumn(modifier = Modifier.padding(innerPadding)) {
items(uiState.storagesList) { listItem ->
StorageTree(
modifier = Modifier.padding(8.dp, 8.dp, 8.dp, 0.dp),
tree = listItem,
onClick = {
openTextEdit(it.value.uuid.toString())
},
onRename = { tree, newName ->
viewModel.rename(tree.value, newName)
},
onRemove = { tree ->
viewModel.remove(tree.value)
},
onEncrypt = { tree ->
viewModel.enableEncryptionAndOpenStorage(tree.value)
}
)
Box {
Scaffold(modifier = modifier, contentWindowInsets = WindowInsets(0.dp), floatingActionButton = {
FloatingActionButton(
onClick = {
viewModel.createStorage()
},
) {
Icon(Icons.Filled.Add, "Floating action button.")
}
item {
Spacer(modifier = Modifier.height(8.dp))
}) { innerPadding ->
LazyColumn(modifier = Modifier.padding(innerPadding).gesturesDisabled(uiState.isLoading)) {
items(uiState.storagesList) { listItem ->
StorageTree(
modifier = Modifier.padding(8.dp, 8.dp, 8.dp, 0.dp),
tree = listItem,
onClick = {
openTextEdit(it.value.uuid.toString())
},
onRename = { tree, newName ->
viewModel.rename(tree.value, newName)
},
onRemove = { tree ->
viewModel.remove(tree.value)
},
onEncrypt = { tree ->
viewModel.enableEncryptionAndOpenStorage(tree.value)
}
)
}
item {
Spacer(modifier = Modifier.height(8.dp))
}
}
}
if(uiState.isLoading) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Box(modifier = Modifier.fillMaxSize().alpha(0.6f).background(Color.Black))
CircularProgressIndicator(
modifier = Modifier.width(64.dp),
color = MaterialTheme.colorScheme.secondary,
trackColor = MaterialTheme.colorScheme.surfaceVariant,
)
}
}
}

View File

@@ -3,4 +3,4 @@ package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.va
import com.github.nullptroma.wallenc.domain.datatypes.Tree
import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo
data class LocalVaultScreenState(val storagesList: List<Tree<IStorageInfo>>)
data class LocalVaultScreenState(val storagesList: List<Tree<IStorageInfo>>, val isLoading: Boolean)

View File

@@ -29,15 +29,43 @@ class LocalVaultViewModel @Inject constructor(
private val manageStoragesEncryptionUseCase: ManageStoragesEncryptionUseCase,
private val renameStorageUseCase: RenameStorageUseCase,
private val logger: ILogger
) : ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState(listOf())) {
) : ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState(listOf(), true)) {
private var _taskCount: Int = 0
private var tasksCount
get() = _taskCount
set(value) {
_taskCount = value
updateStateLoading()
}
private var _isLoading: Boolean = false
private var isLoading
get() = _isLoading
set(value) {
_isLoading = value
updateStateLoading()
}
init {
collectFlows()
}
private fun updateStateLoading() {
updateState(state.value.copy(
isLoading = this.isLoading || this.tasksCount > 0
))
}
private fun collectFlows() {
viewModelScope.launch {
manageLocalVaultUseCase.localStorages.combine(getOpenedStoragesUseCase.openedStorages) { local, opened ->
if(local == null || opened == null)
return@combine null
val list = mutableListOf<Tree<IStorageInfo>>()
for (storage in local) {
var tree = Tree(storage)
list.add(tree)
while(opened != null && opened.containsKey(tree.value.uuid)) {
while(opened.containsKey(tree.value.uuid)) {
val child = opened.getValue(tree.value.uuid)
val nextTree = Tree(child)
tree.children = listOf(nextTree)
@@ -46,17 +74,13 @@ class LocalVaultViewModel @Inject constructor(
}
return@combine list
}.collectLatest {
isLoading = it == null
val newState = state.value.copy(
storagesList = it
storagesList = it ?: listOf()
)
updateState(newState)
}
}
viewModelScope.launch {
getOpenedStoragesUseCase.openedStorages.collectLatest {
logger.debug("ViewModel", "Collected opened: ${it?.size}")
}
}
}
fun printStorageInfoToLog(storage: IStorageInfo) {
@@ -80,8 +104,10 @@ class LocalVaultViewModel @Inject constructor(
}
fun createStorage() {
tasksCount++
viewModelScope.launch {
manageLocalVaultUseCase.createStorage()
tasksCount--
}
}
@@ -89,6 +115,7 @@ class LocalVaultViewModel @Inject constructor(
fun enableEncryptionAndOpenStorage(storage: IStorageInfo) {
if(runningStorages.contains(storage))
return
tasksCount++
runningStorages.add(storage)
val key = EncryptKey("Hello")
viewModelScope.launch {
@@ -98,6 +125,7 @@ class LocalVaultViewModel @Inject constructor(
}
finally {
runningStorages.remove(storage)
tasksCount--
}
}
}