From eba0d0e3cb7b8ffbfea1ffb0bfcc18569e427378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=8B=D1=82=D0=BA=D0=BE=D0=B2=20=D0=A0=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD?= Date: Mon, 27 Jan 2025 22:19:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=85=D1=80=D0=B0=D0=BD=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=D1=89=20=D0=BA=D0=B0=D0=BA=20=D0=B4=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B2=D1=8C=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/build.gradle.kts | 2 +- .../data/db/app/dao/StorageMetaInfoDao.kt | 3 + .../repository/StorageMetaInfoRepository.kt | 13 ++- .../wallenc/data/utils/IProvider.kt | 7 ++ .../wallenc/domain/datatypes/Tree.kt | 3 + .../screens/local/vault/LocalVaultScreen.kt | 110 ++++++++++++++---- .../local/vault/LocalVaultScreenState.kt | 3 +- .../local/vault/LocalVaultViewModel.kt | 19 ++- presentation/src/main/res/values/strings.xml | 1 + 9 files changed, 129 insertions(+), 32 deletions(-) create mode 100644 data/src/main/java/com/github/nullptroma/wallenc/data/utils/IProvider.kt create mode 100644 domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/Tree.kt diff --git a/data/build.gradle.kts b/data/build.gradle.kts index e3c7a27..a8257d0 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -6,7 +6,7 @@ plugins { android { namespace = "com.github.nullptroma.wallenc.data" - compileSdk = 34 + compileSdk = 35 defaultConfig { minSdk = 26 diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageMetaInfoDao.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageMetaInfoDao.kt index eec1615..1d166ad 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageMetaInfoDao.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/dao/StorageMetaInfoDao.kt @@ -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) } \ No newline at end of file diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageMetaInfoRepository.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageMetaInfoRepository.kt index 872bf1b..034177c 100644 --- a/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageMetaInfoRepository.kt +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/db/app/repository/StorageMetaInfoRepository.kt @@ -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 { + 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 { diff --git a/data/src/main/java/com/github/nullptroma/wallenc/data/utils/IProvider.kt b/data/src/main/java/com/github/nullptroma/wallenc/data/utils/IProvider.kt new file mode 100644 index 0000000..f60e07d --- /dev/null +++ b/data/src/main/java/com/github/nullptroma/wallenc/data/utils/IProvider.kt @@ -0,0 +1,7 @@ +package com.github.nullptroma.wallenc.data.utils + +interface IProvider { + suspend fun get(): T? + suspend fun set(value: T) + suspend fun clear() +} \ No newline at end of file diff --git a/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/Tree.kt b/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/Tree.kt new file mode 100644 index 0000000..a05a806 --- /dev/null +++ b/domain/src/main/java/com/github/nullptroma/wallenc/domain/datatypes/Tree.kt @@ -0,0 +1,3 @@ +package com.github.nullptroma.wallenc.domain.datatypes + +class Tree(val value: T, var children: List>? = null) \ No newline at end of file diff --git a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreen.kt b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreen.kt index de56480..a050644 100644 --- a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreen.kt +++ b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreen.kt @@ -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) } } } -} \ No newline at end of file +} + +@Composable +fun Storage(modifier: Modifier, tree: Tree) { + 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) + } + } +} diff --git a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreenState.kt b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreenState.kt index c78c7cf..ce13df1 100644 --- a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreenState.kt +++ b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultScreenState.kt @@ -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) \ No newline at end of file +data class LocalVaultScreenState(val storagesList: List>) \ No newline at end of file diff --git a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt index 62b206b..3836730 100644 --- a/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt +++ b/presentation/src/main/java/com/github/nullptroma/wallenc/presentation/screens/main/screens/local/vault/LocalVaultViewModel.kt @@ -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(listOf())) { +) : ViewModelBase(LocalVaultScreenState(listOf())) { init { viewModelScope.launch { manageLocalVaultUseCase.localStorages.combine(getOpenedStoragesUseCase.openedStorages) { local, opened -> - local + (opened?.map { it.value } ?: listOf()) + val list = mutableListOf>() + 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() } } } \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 72c42a2..d65a8c1 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -6,4 +6,5 @@ Settings Settings Screen Title! + <noname> \ No newline at end of file