Отображение хранилищ как деревья

This commit is contained in:
Пытков Роман
2025-01-27 22:19:44 +03:00
parent 851fb6bd88
commit eba0d0e3cb
9 changed files with 129 additions and 32 deletions

View File

@@ -1,32 +1,60 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CardElevation
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.github.nullptroma.wallenc.domain.datatypes.Tree
import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo
import com.github.nullptroma.wallenc.presentation.R
import kotlin.random.Random
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LocalVaultScreen(modifier: Modifier = Modifier,
viewModel: LocalVaultViewModel = hiltViewModel()) {
fun LocalVaultScreen(
modifier: Modifier = Modifier,
viewModel: LocalVaultViewModel = hiltViewModel()
) {
val uiState by viewModel.state.collectAsStateWithLifecycle()
Scaffold(modifier = modifier, contentWindowInsets = WindowInsets(0.dp), floatingActionButton = {
@@ -39,27 +67,63 @@ fun LocalVaultScreen(modifier: Modifier = Modifier,
}
}) { innerPadding ->
LazyColumn(modifier = Modifier.padding(innerPadding)) {
items(uiState.storagesList) {
Card(modifier = Modifier.clickable { }.pointerInput(Unit) {
detectTapGestures(
onTap = { _ -> viewModel.printStorageInfoToLog(it) }
)
}.padding(8.dp)) {
val available by it.isAvailable.collectAsStateWithLifecycle()
val numOfFiles by it.numberOfFiles.collectAsStateWithLifecycle()
val size by it.size.collectAsStateWithLifecycle()
val metaInfo by it.metaInfo.collectAsStateWithLifecycle()
val enc = metaInfo.encInfo
Column(modifier = Modifier.padding(4.dp)) {
Text(it.uuid.toString())
Text("IsAvailable: $available")
Text("Files: $numOfFiles")
Text("Size: $size")
Text("Enc: $enc")
}
}
items(uiState.storagesList) { tree ->
Storage(Modifier.padding(8.dp), tree)
}
}
}
}
}
@Composable
fun Storage(modifier: Modifier, tree: Tree<IStorageInfo>) {
val cur = tree.value
val cardShape = RoundedCornerShape(30.dp)
Column(modifier) {
Card(
modifier = Modifier
.fillMaxWidth()
.clip(cardShape)
.clickable {
//viewModel.printStorageInfoToLog(cur)
},
shape = cardShape,
elevation = CardDefaults.cardElevation(
defaultElevation = 4.dp
),
) {
val available by cur.isAvailable.collectAsStateWithLifecycle()
val numOfFiles by cur.numberOfFiles.collectAsStateWithLifecycle()
val size by cur.size.collectAsStateWithLifecycle()
val metaInfo by cur.metaInfo.collectAsStateWithLifecycle()
Row {
Column(modifier = Modifier.padding(8.dp)) {
Text(metaInfo.name ?: stringResource(R.string.no_name))
Text(
text = "IsAvailable: $available"
)
Text("Files: $numOfFiles")
Text("Size: $size")
Text("IsVirtual: ${cur.isVirtualStorage}")
Text(
modifier = Modifier
.fillMaxWidth()
.padding(0.dp,0.dp,8.dp,0.dp)
.align(Alignment.End),
text = cur.uuid.toString(),
textAlign = TextAlign.End,
fontSize = 8.sp,
style = LocalTextStyle.current.copy(
platformStyle = PlatformTextStyle(
includeFontPadding = true
)
)
)
}
}
}
for(i in tree.children ?: listOf()) {
Storage(Modifier.padding(16.dp,0.dp,0.dp,0.dp), i)
}
}
}

View File

@@ -1,5 +1,6 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
import com.github.nullptroma.wallenc.domain.datatypes.Tree
import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo
data class LocalVaultScreenState(val storagesList: List<IStorageInfo>)
data class LocalVaultScreenState(val storagesList: List<Tree<IStorageInfo>>)

View File

@@ -2,6 +2,7 @@ package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.va
import androidx.lifecycle.viewModelScope
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.datatypes.Tree
import com.github.nullptroma.wallenc.domain.interfaces.IDirectory
import com.github.nullptroma.wallenc.domain.interfaces.IFile
import com.github.nullptroma.wallenc.domain.interfaces.ILogger
@@ -24,12 +25,22 @@ class LocalVaultViewModel @Inject constructor(
private val getOpenedStoragesUseCase: GetOpenedStoragesUseCase,
private val storageFileManagementUseCase: StorageFileManagementUseCase,
private val logger: ILogger
) :
ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState(listOf())) {
) : ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState(listOf())) {
init {
viewModelScope.launch {
manageLocalVaultUseCase.localStorages.combine(getOpenedStoragesUseCase.openedStorages) { local, opened ->
local + (opened?.map { it.value } ?: listOf())
val list = mutableListOf<Tree<IStorageInfo>>()
for (storage in local) {
var tree = Tree(storage)
list.add(tree)
while(opened != null && opened.containsKey(tree.value.uuid)) {
val child = opened.getValue(tree.value.uuid)
val nextTree = Tree(child)
tree.children = listOf(nextTree)
tree = nextTree
}
}
return@combine list
}.collectLatest {
val newState = state.value.copy(
storagesList = it
@@ -61,7 +72,7 @@ class LocalVaultViewModel @Inject constructor(
fun createStorage() {
viewModelScope.launch {
manageLocalVaultUseCase.createStorage(EncryptKey("hello"))
manageLocalVaultUseCase.createStorage()
}
}
}

View File

@@ -6,4 +6,5 @@
<string name="nav_label_settings">Settings</string>
<string name="settings_title">Settings Screen Title!</string>
<string name="no_name">&lt;noname&gt;</string>
</resources>