Отображение хранилищ как деревья
This commit is contained in:
@@ -6,7 +6,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "com.github.nullptroma.wallenc.data"
|
||||
compileSdk = 34
|
||||
compileSdk = 35
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
|
||||
@@ -28,4 +28,7 @@ interface StorageMetaInfoDao {
|
||||
|
||||
@Delete
|
||||
suspend fun delete(metaInfo: DbStorageMetaInfo)
|
||||
|
||||
@Query("DELETE FROM storage_meta_infos WHERE uuid == :uuid")
|
||||
suspend fun delete(uuid: UUID)
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.github.nullptroma.wallenc.data.db.app.repository
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
|
||||
import com.github.nullptroma.wallenc.data.utils.IProvider
|
||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -34,6 +35,11 @@ class StorageMetaInfoRepository(
|
||||
dao.add(DbStorageMetaInfo(uuid, json))
|
||||
}
|
||||
|
||||
suspend fun delete(uuid: UUID) = withContext(ioDispatcher) {
|
||||
dao.delete(uuid)
|
||||
}
|
||||
|
||||
|
||||
fun createSingleStorageProvider(uuid: UUID): SingleStorageMetaInfoProvider {
|
||||
return SingleStorageMetaInfoProvider(this, uuid)
|
||||
}
|
||||
@@ -41,9 +47,10 @@ class StorageMetaInfoRepository(
|
||||
class SingleStorageMetaInfoProvider (
|
||||
private val repo: StorageMetaInfoRepository,
|
||||
val uuid: UUID
|
||||
) {
|
||||
suspend fun get(): CommonStorageMetaInfo? = repo.getMeta(uuid)
|
||||
suspend fun set(metaInfo: CommonStorageMetaInfo) = repo.setMeta(uuid, metaInfo)
|
||||
) : IProvider<CommonStorageMetaInfo> {
|
||||
override suspend fun get(): CommonStorageMetaInfo? = repo.getMeta(uuid)
|
||||
override suspend fun clear() = repo.delete(uuid)
|
||||
override suspend fun set(value: CommonStorageMetaInfo) = repo.setMeta(uuid, value)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.github.nullptroma.wallenc.data.utils
|
||||
|
||||
interface IProvider<T> {
|
||||
suspend fun get(): T?
|
||||
suspend fun set(value: T)
|
||||
suspend fun clear()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.github.nullptroma.wallenc.domain.datatypes
|
||||
|
||||
class Tree<T>(val value: T, var children: List<Tree<T>>? = null)
|
||||
@@ -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()
|
||||
items(uiState.storagesList) { tree ->
|
||||
Storage(Modifier.padding(8.dp), tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val enc = metaInfo.encInfo
|
||||
Column(modifier = Modifier.padding(4.dp)) {
|
||||
Text(it.uuid.toString())
|
||||
Text("IsAvailable: $available")
|
||||
@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("Enc: $enc")
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>>)
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,5 @@
|
||||
<string name="nav_label_settings">Settings</string>
|
||||
|
||||
<string name="settings_title">Settings Screen Title!</string>
|
||||
<string name="no_name"><noname></string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user