Начат LocalStorage, выкинут мусор из UiState

This commit is contained in:
Roman Pytkov
2024-12-17 23:41:05 +03:00
parent b5462dfd2f
commit 576fc4020c
26 changed files with 284 additions and 35 deletions

View File

@@ -53,6 +53,9 @@ android {
}
dependencies {
// Timber
implementation(libs.timber)
// Yandex
implementation(libs.yandex.oauth)
@@ -76,6 +79,6 @@ dependencies {
//androidTestImplementation(libs.androidx.ui.test.junit4)
implementation(project(":domain"))
implementation(project(":data"))
implementation(project(":presentation"))
runtimeOnly(project(":data"))
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,37 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.github.nullptroma.wallenc.app",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File",
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/app-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/app-release.dm"
]
}
],
"minSdkVersionForDexing": 24
}

View File

@@ -6,8 +6,8 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import com.github.nullptroma.wallenc.presentation.WallencUi
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
class Container<T>(val value: T)
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@@ -15,12 +15,13 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
Timber.plant(Timber.DebugTree())
// val sdk = YandexAuthSdk.create(YandexAuthOptions(applicationContext, true))
// val launcher =
// registerForActivityResult(sdk.contract) { result -> handleResult(result) }
// val loginOptions = YandexAuthLoginOptions(LoginType.CHROME_TAB)
val cont1 = Container(true)
var cont2 = Container<Boolean>(true)
setContent {
WallencUi()
}

View File

@@ -0,0 +1,29 @@
package com.github.nullptroma.wallenc.app.di.modules.app
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import javax.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class MainDispatcher
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class IoDispatcher
@Module
@InstallIn(SingletonComponent::class)
class DispatchersModule {
@MainDispatcher
@Provides
fun providesMainDispatcher(): CoroutineDispatcher = Dispatchers.Main
@IoDispatcher
@Provides
fun providesIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
}

View File

@@ -0,0 +1,31 @@
package com.github.nullptroma.wallenc.app.di.modules.data
import android.content.Context
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
import com.github.nullptroma.wallenc.data.vaults.local.LocalVault
import com.github.nullptroma.wallenc.data.vaults.VaultsManager
import com.github.nullptroma.wallenc.domain.models.IVaultsManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class SingletonModule {
@Provides
@Singleton
fun provideLocalVault(@IoDispatcher ioDispatcher: CoroutineDispatcher,
@ApplicationContext context: Context): LocalVault {
return LocalVault(ioDispatcher, context)
}
@Provides
@Singleton
fun provideVaultsManager(localVault: LocalVault): IVaultsManager {
return VaultsManager(localVault)
}
}

View File

@@ -1,7 +1,7 @@
package com.github.nullptroma.wallenc.app.di.modules.domain
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
import com.github.nullptroma.wallenc.domain.usecases.TestUseCase
import com.github.nullptroma.wallenc.domain.models.IVaultsManager
import com.github.nullptroma.wallenc.domain.usecases.GetAllRawStoragesUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -11,11 +11,9 @@ import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class UseCasesModule {
var count = 0
@Provides
@Singleton
fun provideTestUseCase(meta: IMetaInfo): TestUseCase {
return TestUseCase(meta, count++)
fun provideGetAllRawStoragesUseCase(vaultsManager: IVaultsManager): GetAllRawStoragesUseCase {
return GetAllRawStoragesUseCase(vaultsManager)
}
}

View File

@@ -34,6 +34,9 @@ android {
}
dependencies {
// Timber
implementation(libs.timber)
// Room
implementation(libs.room.ktx)
implementation(libs.room.runtime)

View File

@@ -0,0 +1,23 @@
package com.github.nullptroma.wallenc.data
import com.github.nullptroma.wallenc.domain.models.IStorage
import com.github.nullptroma.wallenc.domain.models.IStorageAccessor
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import java.util.UUID
class MockStorage(
override val size: StateFlow<Int?> = MutableStateFlow(null),
override val numberOfFiles: StateFlow<Int?> = MutableStateFlow(null),
override val uuid: UUID,
override val name: StateFlow<String> = MutableStateFlow(""),
override val totalSpace: StateFlow<Int?> = MutableStateFlow(null),
override val availableSpace: StateFlow<Int?> = MutableStateFlow(null),
override val isAvailable: StateFlow<Boolean> = MutableStateFlow(false),
override val accessor: IStorageAccessor
) : IStorage {
override suspend fun rename(newName: String) {
TODO("Not yet implemented")
}
}

View File

@@ -1,5 +1,16 @@
package com.github.nullptroma.wallenc.data.vaults
class VaultsManager {
import com.github.nullptroma.wallenc.data.vaults.local.LocalVault
import com.github.nullptroma.wallenc.domain.models.IVault
import com.github.nullptroma.wallenc.domain.models.IVaultsManager
import kotlinx.coroutines.flow.StateFlow
class VaultsManager(override val localVault: LocalVault) : IVaultsManager {
override val remoteVaults: StateFlow<List<IVault>>
get() = TODO("Not yet implemented")
override fun addYandexVault(email: String, token: String) {
TODO("Not yet implemented")
}
}

View File

@@ -0,0 +1,77 @@
package com.github.nullptroma.wallenc.data.vaults.local
import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
import com.github.nullptroma.wallenc.domain.models.IDirectory
import com.github.nullptroma.wallenc.domain.models.IFile
import com.github.nullptroma.wallenc.domain.models.IStorageAccessor
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import java.io.InputStream
import java.io.OutputStream
import java.net.URI
class LocalStorageAccessor : IStorageAccessor {
override val isAvailable: StateFlow<Boolean>
get() = TODO("Not yet implemented")
override val filesUpdates: SharedFlow<DataPackage<IFile>>
get() = TODO("Not yet implemented")
override val dirsUpdates: SharedFlow<DataPackage<IDirectory>>
get() = TODO("Not yet implemented")
override suspend fun getAllFiles(): List<IFile> {
TODO("Not yet implemented")
}
override suspend fun getFiles(path: URI): List<IFile> {
TODO("Not yet implemented")
}
override fun getFilesFlow(path: URI): Flow<DataPackage<IFile>> {
TODO("Not yet implemented")
}
override suspend fun getAllDirs(): List<IDirectory> {
TODO("Not yet implemented")
}
override suspend fun getDirs(path: URI): List<IDirectory> {
TODO("Not yet implemented")
}
override fun getDirsFlow(path: URI): Flow<DataPackage<IDirectory>> {
TODO("Not yet implemented")
}
override suspend fun touchFile(path: URI) {
TODO("Not yet implemented")
}
override suspend fun touchDir(path: URI) {
TODO("Not yet implemented")
}
override suspend fun delete(path: URI) {
TODO("Not yet implemented")
}
override suspend fun getFileInfo(path: URI) {
TODO("Not yet implemented")
}
override suspend fun getDirInfo(path: URI) {
TODO("Not yet implemented")
}
override suspend fun openWrite(path: URI): InputStream {
TODO("Not yet implemented")
}
override suspend fun openRead(path: URI): OutputStream {
TODO("Not yet implemented")
}
override suspend fun moveToTrash(path: URI) {
TODO("Not yet implemented")
}
}

View File

@@ -1,21 +1,37 @@
package com.github.nullptroma.wallenc.data.vaults
package com.github.nullptroma.wallenc.data.vaults.local
import android.content.Context
import com.github.nullptroma.wallenc.data.MockStorage
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
import com.github.nullptroma.wallenc.domain.enums.VaultType
import com.github.nullptroma.wallenc.domain.models.IStorage
import com.github.nullptroma.wallenc.domain.models.IVault
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.UUID
import kotlin.io.path.Path
import kotlin.io.path.createDirectory
class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context) : IVault {
private val path = context.getExternalFilesDir("LocalVault")
private val _storages = MutableStateFlow(listOf<IStorage>())
init {
CoroutineScope(ioDispatcher).launch {
if(path == null)
return@launch
val dirs = path.listFiles()?.filter { it.isDirectory }
if(dirs != null)
_storages.value = dirs.map {
MockStorage(uuid = UUID.fromString(it.name), accessor = LocalStorageAccessor())
}
val next = Path(path.path, UUID.randomUUID().toString())
next.createDirectory()
}
}
@@ -46,7 +62,7 @@ class LocalVault(private val ioDispatcher: CoroutineDispatcher, context: Context
override val uuid: UUID
get() = TODO("Not yet implemented")
override val storages: StateFlow<List<IStorage>>
get() = TODO("Not yet implemented")
get() = _storages
override val isAvailable: StateFlow<Boolean>
get() = TODO("Not yet implemented")

View File

@@ -3,7 +3,7 @@ package com.github.nullptroma.wallenc.domain.models
import kotlinx.coroutines.flow.StateFlow
interface IVaultsManager {
val localVault: StateFlow<IVault>
val localVault: IVault
val remoteVaults: StateFlow<List<IVault>>
fun addYandexVault(email: String, token: String)

View File

@@ -1,14 +1,14 @@
package com.github.nullptroma.wallenc.domain.usecases
import com.github.nullptroma.wallenc.domain.models.IVault
import com.github.nullptroma.wallenc.domain.models.IVaultsManager
import kotlinx.coroutines.flow.combine
class GetAllRawStoragesUseCase(val manager: IVaultsManager) {
fun getStoragesFlow() = manager.remoteVaults.combine(manager.localVault) { remote, local ->
mutableListOf<IVault>().apply {
addAll(remote)
add(local)
}
}
class GetAllRawStoragesUseCase(private val manager: IVaultsManager) {
// fun getStoragesFlow() = manager.remoteVaults.combine(manager.localVault) { remote, local ->
// mutableListOf<IVault>().apply {
// addAll(remote)
// add(local)
// }
// }
val localStorage
get() = manager.localVault
}

View File

@@ -13,6 +13,7 @@ activityCompose = "1.9.3"
composeBom = "2024.10.01"
navigation = "2.8.3"
hiltNavigation = "1.2.0"
timber = "5.0.1"
yandexAuthSdk = "3.1.2"
daggerHilt = "2.52"
ksp = "2.0.10-1.0.24"
@@ -29,6 +30,7 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
navigation = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
navigation-hilt-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigation" }
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
# Yandex
yandex-oauth = { group = "com.yandex.android", name = "authsdk", version.ref = "yandexAuthSdk" }

View File

@@ -1,3 +1,3 @@
package com.github.nullptroma.wallenc.presentation.screens.main
data class MainScreenState(val value: String)
class MainScreenState

View File

@@ -12,7 +12,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
@HiltViewModel
class MainViewModel @javax.inject.Inject constructor(savedStateHandle: SavedStateHandle) :
ViewModelBase<MainScreenState>(MainScreenState("default string")) {
ViewModelBase<MainScreenState>(MainScreenState()) {
@OptIn(SavedStateHandleSaveableApi::class)
var routes by savedStateHandle.saveable {

View File

@@ -1,5 +1,6 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -15,5 +16,9 @@ fun LocalVaultScreen(modifier: Modifier = Modifier,
viewModel: LocalVaultViewModel = hiltViewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
Text(uiState.value)
Column {
for(storage in uiState.storagesList) {
Text(storage.uuid.toString())
}
}
}

View File

@@ -1,3 +1,5 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
data class LocalVaultScreenState(val value: String)
import com.github.nullptroma.wallenc.domain.models.IStorage
data class LocalVaultScreenState(val storagesList: List<IStorage>)

View File

@@ -1,11 +1,22 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.local.vault
import androidx.lifecycle.viewModelScope
import com.github.nullptroma.wallenc.domain.usecases.GetAllRawStoragesUseCase
import com.github.nullptroma.wallenc.presentation.viewmodel.ViewModelBase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class LocalVaultViewModel @Inject constructor()
: ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState("default")) {
class LocalVaultViewModel @Inject constructor(private val getAllRawStoragesUseCase: GetAllRawStoragesUseCase) :
ViewModelBase<LocalVaultScreenState>(LocalVaultScreenState(listOf())) {
init {
viewModelScope.launch {
getAllRawStoragesUseCase.localStorage.storages.collect {
mutableUiState.value = mutableUiState.value.copy(
storagesList = it
)
}
}
}
}

View File

@@ -1,3 +1,3 @@
package com.github.nullptroma.wallenc.presentation.screens.main.screens.remotes
data class RemoteVaultsScreenState(val value: String)
class RemoteVaultsScreenState

View File

@@ -6,6 +6,6 @@ import javax.inject.Inject
@HiltViewModel
class RemoteVaultsViewModel @Inject constructor() :
ViewModelBase<RemoteVaultsScreenState>(RemoteVaultsScreenState("")) {
ViewModelBase<RemoteVaultsScreenState>(RemoteVaultsScreenState()) {
}

View File

@@ -1,3 +1,3 @@
package com.github.nullptroma.wallenc.presentation.screens.settings
data class SettingsScreenState(val value: String)
class SettingsScreenState

View File

@@ -5,5 +5,5 @@ import dagger.hilt.android.lifecycle.HiltViewModel
@HiltViewModel
class SettingsViewModel @javax.inject.Inject constructor() :
ViewModelBase<SettingsScreenState>(SettingsScreenState("default string")) {
ViewModelBase<SettingsScreenState>(SettingsScreenState()) {
}

View File

@@ -2492,7 +2492,7 @@ existing classes or even new classes with specific responsibilities.</val>
<val>localVault</val>
</name>
<typeValue>
<val>StateFlow&lt;IVault&gt;</val>
<val>IVault</val>
</typeValue>
</Property>
<Property id="29e33324-96f0-11ef-9427-3ba703bb2331">