Мета информация о хранилищах хранится в бд
This commit is contained in:
@@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
|
|||||||
fun useAppContext() {
|
fun useAppContext() {
|
||||||
// Context of the app under test.
|
// Context of the app under test.
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
assertEquals("com.github.nullptroma.wallenc", appContext.packageName)
|
assertEquals("com.github.nullptroma.wallenc.app", appContext.packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import com.github.nullptroma.wallenc.data.db.RoomFactory
|
import com.github.nullptroma.wallenc.data.db.RoomFactory
|
||||||
import com.github.nullptroma.wallenc.data.db.app.IAppDb
|
import com.github.nullptroma.wallenc.data.db.app.IAppDb
|
||||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
@@ -25,6 +26,12 @@ class RoomModule {
|
|||||||
return database.storageKeyMapDao
|
return database.storageKeyMapDao
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideStorageMetaInfoDao(database: IAppDb): StorageMetaInfoDao {
|
||||||
|
return database.storageMetaInfoDao
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideAppDb(
|
fun provideAppDb(
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package com.github.nullptroma.wallenc.app.di.modules.data
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
|
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
|
||||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||||
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
|
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
|
||||||
import com.github.nullptroma.wallenc.data.vaults.UnlockManager
|
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
|
||||||
|
import com.github.nullptroma.wallenc.data.storages.UnlockManager
|
||||||
import com.github.nullptroma.wallenc.data.vaults.VaultsManager
|
import com.github.nullptroma.wallenc.data.vaults.VaultsManager
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||||
@@ -21,24 +23,42 @@ import javax.inject.Singleton
|
|||||||
class SingletonModule {
|
class SingletonModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideVaultsManager(@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
fun provideVaultsManager(
|
||||||
@ApplicationContext context: Context): IVaultsManager {
|
@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
||||||
|
@ApplicationContext context: Context
|
||||||
|
): IVaultsManager {
|
||||||
return VaultsManager(ioDispatcher, context)
|
return VaultsManager(ioDispatcher, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideStorageKeyMapRepository(dao: StorageKeyMapDao): StorageKeyMapRepository {
|
fun provideStorageKeyMapRepository(
|
||||||
return StorageKeyMapRepository(dao)
|
dao: StorageKeyMapDao,
|
||||||
|
@IoDispatcher ioDispatcher: CoroutineDispatcher
|
||||||
|
): StorageKeyMapRepository {
|
||||||
|
return StorageKeyMapRepository(dao, ioDispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideUnlockManager(@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
fun provideStorageMetaInfoRepository(
|
||||||
repo: StorageKeyMapRepository,
|
dao: StorageMetaInfoDao,
|
||||||
vaultsManager: IVaultsManager): IUnlockManager {
|
@IoDispatcher ioDispatcher: CoroutineDispatcher
|
||||||
|
): StorageMetaInfoRepository {
|
||||||
|
return StorageMetaInfoRepository(dao, ioDispatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideUnlockManager(
|
||||||
|
@IoDispatcher ioDispatcher: CoroutineDispatcher,
|
||||||
|
keyRepo: StorageKeyMapRepository,
|
||||||
|
metaRepo: StorageMetaInfoRepository,
|
||||||
|
vaultsManager: IVaultsManager
|
||||||
|
): IUnlockManager {
|
||||||
return UnlockManager(
|
return UnlockManager(
|
||||||
repo = repo,
|
keymapRepository = keyRepo,
|
||||||
|
metaInfoRepository = metaRepo,
|
||||||
ioDispatcher = ioDispatcher,
|
ioDispatcher = ioDispatcher,
|
||||||
vaultsManager = vaultsManager
|
vaultsManager = vaultsManager
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.github.nullptroma.wallenc.app.di.modules.domain
|
package com.github.nullptroma.wallenc.app.di.modules.domain
|
||||||
|
|
||||||
import com.github.nullptroma.wallenc.data.vaults.UnlockManager
|
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||||
import com.github.nullptroma.wallenc.domain.usecases.GetOpenedStoragesUseCase
|
import com.github.nullptroma.wallenc.domain.usecases.GetOpenedStoragesUseCase
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ package com.github.nullptroma.wallenc.data.db.app
|
|||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageMetaInfoDao
|
||||||
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
|
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
|
||||||
|
|
||||||
interface IAppDb {
|
interface IAppDb {
|
||||||
val storageKeyMapDao: StorageKeyMapDao
|
val storageKeyMapDao: StorageKeyMapDao
|
||||||
|
val storageMetaInfoDao: StorageMetaInfoDao
|
||||||
}
|
}
|
||||||
|
|
||||||
@Database(entities = [DbStorageKeyMap::class], version = 2, exportSchema = false)
|
@Database(entities = [DbStorageKeyMap::class, DbStorageMetaInfo::class], version = 2, exportSchema = false)
|
||||||
abstract class AppDb : IAppDb, RoomDatabase() {
|
abstract class AppDb : IAppDb, RoomDatabase() {
|
||||||
abstract override val storageKeyMapDao: StorageKeyMapDao
|
abstract override val storageKeyMapDao: StorageKeyMapDao
|
||||||
|
abstract override val storageMetaInfoDao: StorageMetaInfoDao
|
||||||
}
|
}
|
||||||
@@ -12,11 +12,11 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
@Dao
|
@Dao
|
||||||
interface StorageKeyMapDao {
|
interface StorageKeyMapDao {
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun add(keymap: DbStorageKeyMap)
|
suspend fun add(keymap: DbStorageKeyMap)
|
||||||
|
|
||||||
@Query("SELECT * FROM storage_key_maps")
|
@Query("SELECT * FROM storage_key_maps")
|
||||||
fun getAll(): List<DbStorageKeyMap>
|
suspend fun getAll(): List<DbStorageKeyMap>
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
fun delete(keymap: DbStorageKeyMap)
|
suspend fun delete(keymap: DbStorageKeyMap)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.github.nullptroma.wallenc.data.db.app.dao
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageMetaInfo
|
||||||
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface StorageMetaInfoDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun add(metaInfo: DbStorageMetaInfo)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM storage_meta_infos")
|
||||||
|
suspend fun getAll(): List<DbStorageMetaInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM storage_meta_infos")
|
||||||
|
fun getAllFlow(): Flow<List<DbStorageMetaInfo>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM storage_meta_infos WHERE uuid == :uuid")
|
||||||
|
fun getMetaInfoFlow(uuid: UUID): Flow<DbStorageMetaInfo>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM storage_meta_infos WHERE uuid == :uuid")
|
||||||
|
suspend fun getMetaInfo(uuid: UUID): DbStorageMetaInfo?
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(metaInfo: DbStorageMetaInfo)
|
||||||
|
}
|
||||||
@@ -9,14 +9,14 @@ import java.util.UUID
|
|||||||
|
|
||||||
@Entity(tableName = "storage_key_maps", primaryKeys = [ "source_uuid", "dest_uuid" ])
|
@Entity(tableName = "storage_key_maps", primaryKeys = [ "source_uuid", "dest_uuid" ])
|
||||||
data class DbStorageKeyMap(
|
data class DbStorageKeyMap(
|
||||||
@ColumnInfo(name = "source_uuid") val sourceUuid: String,
|
@ColumnInfo(name = "source_uuid") val sourceUuid: UUID,
|
||||||
@ColumnInfo(name = "dest_uuid") val destUuid: String,
|
@ColumnInfo(name = "dest_uuid") val destUuid: UUID,
|
||||||
@ColumnInfo(name = "key") val key: ByteArray
|
@ColumnInfo(name = "key") val key: ByteArray
|
||||||
) {
|
) {
|
||||||
fun toModel(): StorageKeyMap {
|
fun toModel(): StorageKeyMap {
|
||||||
return StorageKeyMap(
|
return StorageKeyMap(
|
||||||
sourceUuid = UUID.fromString(sourceUuid),
|
sourceUuid = sourceUuid,
|
||||||
destUuid = UUID.fromString(destUuid),
|
destUuid = destUuid,
|
||||||
key = EncryptKey(key)
|
key = EncryptKey(key)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -44,8 +44,8 @@ data class DbStorageKeyMap(
|
|||||||
companion object {
|
companion object {
|
||||||
fun fromModel(keymap: StorageKeyMap): DbStorageKeyMap {
|
fun fromModel(keymap: StorageKeyMap): DbStorageKeyMap {
|
||||||
return DbStorageKeyMap(
|
return DbStorageKeyMap(
|
||||||
sourceUuid = keymap.sourceUuid.toString(),
|
sourceUuid = keymap.sourceUuid,
|
||||||
destUuid = keymap.destUuid.toString(),
|
destUuid = keymap.destUuid,
|
||||||
key = keymap.key.bytes
|
key = keymap.key.bytes
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.github.nullptroma.wallenc.data.db.app.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
@Entity(tableName = "storage_meta_infos")
|
||||||
|
data class DbStorageMetaInfo(
|
||||||
|
@PrimaryKey @ColumnInfo(name = "uuid") val uuid: UUID,
|
||||||
|
@ColumnInfo(name = "meta_info") val metaInfoJson: String
|
||||||
|
)
|
||||||
@@ -3,14 +3,20 @@ package com.github.nullptroma.wallenc.data.db.app.repository
|
|||||||
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
import com.github.nullptroma.wallenc.data.db.app.dao.StorageKeyMapDao
|
||||||
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
|
import com.github.nullptroma.wallenc.data.db.app.model.DbStorageKeyMap
|
||||||
import com.github.nullptroma.wallenc.data.model.StorageKeyMap
|
import com.github.nullptroma.wallenc.data.model.StorageKeyMap
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class StorageKeyMapRepository(private val dao: StorageKeyMapDao) {
|
class StorageKeyMapRepository(
|
||||||
fun getAll() = dao.getAll().map { it.toModel() }
|
private val dao: StorageKeyMapDao,
|
||||||
fun add(keymap: StorageKeyMap) {
|
private val ioDispatcher: CoroutineDispatcher
|
||||||
|
) {
|
||||||
|
suspend fun getAll() = withContext(ioDispatcher) { dao.getAll().map { it.toModel() } }
|
||||||
|
suspend fun add(keymap: StorageKeyMap) = withContext(ioDispatcher) {
|
||||||
val dbModel = DbStorageKeyMap.fromModel(keymap)
|
val dbModel = DbStorageKeyMap.fromModel(keymap)
|
||||||
dao.add(dbModel)
|
dao.add(dbModel)
|
||||||
}
|
}
|
||||||
fun delete(keymap: StorageKeyMap) {
|
|
||||||
|
suspend fun delete(keymap: StorageKeyMap) = withContext(ioDispatcher) {
|
||||||
val dbModel = DbStorageKeyMap.fromModel(keymap)
|
val dbModel = DbStorageKeyMap.fromModel(keymap)
|
||||||
dao.delete(dbModel)
|
dao.delete(dbModel)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
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.domain.common.impl.CommonStorageMetaInfo
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class StorageMetaInfoRepository(
|
||||||
|
private val dao: StorageMetaInfoDao,
|
||||||
|
private val ioDispatcher: CoroutineDispatcher
|
||||||
|
) {
|
||||||
|
fun getAllFlow() = dao.getAllFlow()
|
||||||
|
suspend fun getAll() = withContext(ioDispatcher) { dao.getAll() }
|
||||||
|
suspend fun getMeta(uuid: UUID): CommonStorageMetaInfo? = withContext(ioDispatcher) {
|
||||||
|
val json = dao.getMetaInfo(uuid)?.metaInfoJson ?: return@withContext null
|
||||||
|
return@withContext jackson.readValue(
|
||||||
|
json,
|
||||||
|
CommonStorageMetaInfo::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observeMeta(uuid: UUID): Flow<CommonStorageMetaInfo> {
|
||||||
|
return dao.getMetaInfoFlow(uuid)
|
||||||
|
.map { jackson.readValue(it.metaInfoJson, CommonStorageMetaInfo::class.java) }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setMeta(uuid: UUID, metaInfo: CommonStorageMetaInfo) = withContext(ioDispatcher) {
|
||||||
|
val json = jackson.writeValueAsString(metaInfo)
|
||||||
|
dao.add(DbStorageMetaInfo(uuid, json))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createSingleStorageProvider(uuid: UUID): SingleStorageMetaInfoProvider {
|
||||||
|
return SingleStorageMetaInfoProvider(this, uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val jackson = jacksonObjectMapper().apply { findAndRegisterModules() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package com.github.nullptroma.wallenc.data.vaults
|
package com.github.nullptroma.wallenc.data.storages
|
||||||
|
|
||||||
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
|
import com.github.nullptroma.wallenc.data.db.app.repository.StorageKeyMapRepository
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
|
||||||
import com.github.nullptroma.wallenc.data.model.StorageKeyMap
|
import com.github.nullptroma.wallenc.data.model.StorageKeyMap
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
||||||
import com.github.nullptroma.wallenc.domain.encrypt.EncryptedStorage
|
import com.github.nullptroma.wallenc.data.storages.encrypt.EncryptedStorage
|
||||||
import com.github.nullptroma.wallenc.domain.encrypt.Encryptor
|
import com.github.nullptroma.wallenc.domain.encrypt.Encryptor
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IUnlockManager
|
||||||
@@ -20,7 +21,8 @@ import kotlinx.coroutines.withContext
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
class UnlockManager(
|
class UnlockManager(
|
||||||
private val repo: StorageKeyMapRepository,
|
private val keymapRepository: StorageKeyMapRepository,
|
||||||
|
private val metaInfoRepository: StorageMetaInfoRepository,
|
||||||
private val ioDispatcher: CoroutineDispatcher,
|
private val ioDispatcher: CoroutineDispatcher,
|
||||||
vaultsManager: IVaultsManager
|
vaultsManager: IVaultsManager
|
||||||
) : IUnlockManager {
|
) : IUnlockManager {
|
||||||
@@ -33,7 +35,7 @@ class UnlockManager(
|
|||||||
CoroutineScope(ioDispatcher).launch {
|
CoroutineScope(ioDispatcher).launch {
|
||||||
vaultsManager.allStorages.collectLatest {
|
vaultsManager.allStorages.collectLatest {
|
||||||
mutex.lock()
|
mutex.lock()
|
||||||
val allKeys = repo.getAll()
|
val allKeys = keymapRepository.getAll()
|
||||||
val allStorages = it.associateBy({ it.uuid }, { it })
|
val allStorages = it.associateBy({ it.uuid }, { it })
|
||||||
val map = _openedStorages.value?.toMutableMap() ?: mutableMapOf()
|
val map = _openedStorages.value?.toMutableMap() ?: mutableMapOf()
|
||||||
for(keymap in allKeys) {
|
for(keymap in allKeys) {
|
||||||
@@ -49,11 +51,12 @@ class UnlockManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createEncryptedStorage(storage: IStorage, key: EncryptKey, uuid: UUID): EncryptedStorage {
|
private suspend fun createEncryptedStorage(storage: IStorage, key: EncryptKey, uuid: UUID): EncryptedStorage {
|
||||||
return EncryptedStorage(
|
return EncryptedStorage.create(
|
||||||
_source = storage,
|
source = storage,
|
||||||
key = key,
|
key = key,
|
||||||
ioDispatcher = ioDispatcher,
|
ioDispatcher = ioDispatcher,
|
||||||
|
metaInfoProvider = metaInfoRepository.createSingleStorageProvider(uuid),
|
||||||
uuid = uuid
|
uuid = uuid
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -80,7 +83,7 @@ class UnlockManager(
|
|||||||
val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid)
|
val encStorage = createEncryptedStorage(storage, keymap.key, keymap.destUuid)
|
||||||
opened[storage.uuid] = encStorage
|
opened[storage.uuid] = encStorage
|
||||||
_openedStorages.value = opened
|
_openedStorages.value = opened
|
||||||
repo.add(keymap)
|
keymapRepository.add(keymap)
|
||||||
mutex.unlock()
|
mutex.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +100,7 @@ class UnlockManager(
|
|||||||
remove(storage.uuid)
|
remove(storage.uuid)
|
||||||
}
|
}
|
||||||
enc.dispose()
|
enc.dispose()
|
||||||
repo.delete(model)
|
keymapRepository.delete(model)
|
||||||
mutex.unlock()
|
mutex.unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.github.nullptroma.wallenc.data.storages.encrypt
|
||||||
|
|
||||||
|
import com.github.nullptroma.wallenc.data.db.app.repository.StorageMetaInfoRepository
|
||||||
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
||||||
|
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
||||||
|
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
||||||
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
||||||
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorageMetaInfo
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.DisposableHandle
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class EncryptedStorage private constructor(
|
||||||
|
private val source: IStorage,
|
||||||
|
key: EncryptKey,
|
||||||
|
private val ioDispatcher: CoroutineDispatcher,
|
||||||
|
private val metaInfoProvider: StorageMetaInfoRepository.SingleStorageMetaInfoProvider,
|
||||||
|
override val uuid: UUID = UUID.randomUUID()
|
||||||
|
) : IStorage, DisposableHandle {
|
||||||
|
override val size: StateFlow<Long?>
|
||||||
|
get() = source.size
|
||||||
|
override val numberOfFiles: StateFlow<Int?>
|
||||||
|
get() = source.numberOfFiles
|
||||||
|
|
||||||
|
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
|
||||||
|
CommonStorageMetaInfo()
|
||||||
|
)
|
||||||
|
override val metaInfo: StateFlow<IStorageMetaInfo>
|
||||||
|
get() = _metaInfo
|
||||||
|
override val isVirtualStorage: Boolean = true
|
||||||
|
|
||||||
|
override val isAvailable: StateFlow<Boolean>
|
||||||
|
get() = source.isAvailable
|
||||||
|
override val accessor: EncryptedStorageAccessor =
|
||||||
|
EncryptedStorageAccessor(source.accessor, key, ioDispatcher)
|
||||||
|
|
||||||
|
private suspend fun init() {
|
||||||
|
readMeta()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun readMeta() = withContext(ioDispatcher) {
|
||||||
|
var meta = metaInfoProvider.get()
|
||||||
|
if(meta == null) {
|
||||||
|
meta = CommonStorageMetaInfo()
|
||||||
|
metaInfoProvider.set(meta)
|
||||||
|
}
|
||||||
|
_metaInfo.value = meta
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun rename(newName: String) = withContext(ioDispatcher) {
|
||||||
|
val cur = _metaInfo.value
|
||||||
|
val newMeta = CommonStorageMetaInfo(
|
||||||
|
encInfo = cur.encInfo,
|
||||||
|
name = newName
|
||||||
|
)
|
||||||
|
_metaInfo.value = newMeta
|
||||||
|
metaInfoProvider.set(newMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setEncInfo(encInfo: StorageEncryptionInfo) = withContext(ioDispatcher) {
|
||||||
|
val cur = _metaInfo.value
|
||||||
|
val newMeta = CommonStorageMetaInfo(
|
||||||
|
encInfo = encInfo,
|
||||||
|
name = cur.name
|
||||||
|
)
|
||||||
|
_metaInfo.value = newMeta
|
||||||
|
metaInfoProvider.set(newMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
accessor.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
suspend fun create(
|
||||||
|
source: IStorage,
|
||||||
|
key: EncryptKey,
|
||||||
|
ioDispatcher: CoroutineDispatcher,
|
||||||
|
metaInfoProvider: StorageMetaInfoRepository.SingleStorageMetaInfoProvider,
|
||||||
|
uuid: UUID = UUID.randomUUID()
|
||||||
|
): EncryptedStorage = withContext(ioDispatcher) {
|
||||||
|
val storage = EncryptedStorage(
|
||||||
|
source = source,
|
||||||
|
key = key,
|
||||||
|
ioDispatcher = ioDispatcher,
|
||||||
|
metaInfoProvider = metaInfoProvider,
|
||||||
|
uuid = uuid
|
||||||
|
)
|
||||||
|
storage.init()
|
||||||
|
return@withContext storage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.github.nullptroma.wallenc.domain.encrypt
|
package com.github.nullptroma.wallenc.data.storages.encrypt
|
||||||
|
|
||||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonDirectory
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonDirectory
|
||||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonFile
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonFile
|
||||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonMetaInfo
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonMetaInfo
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
|
import com.github.nullptroma.wallenc.domain.datatypes.DataPackage
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
||||||
|
import com.github.nullptroma.wallenc.domain.encrypt.Encryptor
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IDirectory
|
import com.github.nullptroma.wallenc.domain.interfaces.IDirectory
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IFile
|
import com.github.nullptroma.wallenc.domain.interfaces.IFile
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IMetaInfo
|
import com.github.nullptroma.wallenc.domain.interfaces.IMetaInfo
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.github.nullptroma.wallenc.data.vaults.local
|
package com.github.nullptroma.wallenc.data.storages.local
|
||||||
|
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
||||||
@@ -24,14 +24,8 @@ class LocalStorage(
|
|||||||
override val numberOfFiles: StateFlow<Int?>
|
override val numberOfFiles: StateFlow<Int?>
|
||||||
get() = accessor.numberOfFiles
|
get() = accessor.numberOfFiles
|
||||||
|
|
||||||
private val _metaInfo = MutableStateFlow(
|
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
|
||||||
CommonStorageMetaInfo(
|
CommonStorageMetaInfo()
|
||||||
encInfo = StorageEncryptionInfo(
|
|
||||||
isEncrypted = false,
|
|
||||||
encryptedTestData = null
|
|
||||||
),
|
|
||||||
name = null
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
override val metaInfo: StateFlow<IStorageMetaInfo>
|
override val metaInfo: StateFlow<IStorageMetaInfo>
|
||||||
get() = _metaInfo
|
get() = _metaInfo
|
||||||
@@ -40,49 +34,60 @@ class LocalStorage(
|
|||||||
get() = accessor.isAvailable
|
get() = accessor.isAvailable
|
||||||
private val _accessor = LocalStorageAccessor(absolutePath, ioDispatcher)
|
private val _accessor = LocalStorageAccessor(absolutePath, ioDispatcher)
|
||||||
override val accessor: IStorageAccessor = _accessor
|
override val accessor: IStorageAccessor = _accessor
|
||||||
|
override val isVirtualStorage: Boolean = false
|
||||||
private val encInfoFileName: String = "$uuid$ENC_INFO_FILE_POSTFIX"
|
private val metaInfoFileName: String = "$uuid$ENC_INFO_FILE_POSTFIX"
|
||||||
|
|
||||||
suspend fun init() {
|
suspend fun init() {
|
||||||
_accessor.init()
|
_accessor.init()
|
||||||
readEncInfo()
|
readMetaInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun readEncInfo() = withContext(ioDispatcher) {
|
private suspend fun readMetaInfo() = withContext(ioDispatcher) {
|
||||||
var enc: StorageEncryptionInfo? = null
|
var meta: CommonStorageMetaInfo
|
||||||
var reader: InputStream? = null
|
var reader: InputStream? = null
|
||||||
try {
|
try {
|
||||||
reader = _accessor.openReadSystemFile(encInfoFileName)
|
reader = _accessor.openReadSystemFile(metaInfoFileName)
|
||||||
enc = jackson.readValue(reader, StorageEncryptionInfo::class.java)
|
meta = jackson.readValue(reader, CommonStorageMetaInfo::class.java)
|
||||||
}
|
}
|
||||||
catch(e: Exception) {
|
catch(e: Exception) {
|
||||||
// чтение не удалось, значит нужно записать файл
|
// чтение не удалось, значит нужно записать файл
|
||||||
enc = StorageEncryptionInfo(
|
meta = CommonStorageMetaInfo()
|
||||||
isEncrypted = false,
|
updateMetaInfo(meta)
|
||||||
encryptedTestData = null
|
|
||||||
)
|
|
||||||
setEncInfo(enc)
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
reader?.close()
|
reader?.close()
|
||||||
}
|
}
|
||||||
_metaInfo.value = _metaInfo.value.copy(encInfo = enc)
|
_metaInfo.value = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setEncInfo(enc: StorageEncryptionInfo) = withContext(ioDispatcher) {
|
private suspend fun updateMetaInfo(meta: IStorageMetaInfo) = withContext(ioDispatcher) {
|
||||||
val writer = _accessor.openWriteSystemFile(encInfoFileName)
|
val writer = _accessor.openWriteSystemFile(metaInfoFileName)
|
||||||
try {
|
try {
|
||||||
jackson.writeValue(writer, enc)
|
jackson.writeValue(writer, meta)
|
||||||
}
|
}
|
||||||
catch (e: Exception) {
|
catch (e: Exception) {
|
||||||
TODO("Это никогда не должно произойти")
|
throw e
|
||||||
}
|
}
|
||||||
writer.close()
|
finally {
|
||||||
_metaInfo.value = _metaInfo.value.copy(encInfo = enc)
|
writer.close()
|
||||||
|
}
|
||||||
|
_metaInfo.value = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun rename(newName: String) {
|
override suspend fun rename(newName: String) = withContext(ioDispatcher) {
|
||||||
TODO("Not yet implemented")
|
val curMeta = metaInfo.value
|
||||||
|
updateMetaInfo(CommonStorageMetaInfo(
|
||||||
|
encInfo = curMeta.encInfo,
|
||||||
|
name = newName
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setEncInfo(encInfo: StorageEncryptionInfo) = withContext(ioDispatcher) {
|
||||||
|
val curMeta = metaInfo.value
|
||||||
|
updateMetaInfo(CommonStorageMetaInfo(
|
||||||
|
encInfo = encInfo,
|
||||||
|
name = curMeta.name
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.github.nullptroma.wallenc.data.vaults.local
|
package com.github.nullptroma.wallenc.data.storages.local
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JacksonException
|
import com.fasterxml.jackson.core.JacksonException
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
@@ -57,7 +57,7 @@ class LocalStorageAccessor(
|
|||||||
private val _dirsUpdates = MutableSharedFlow<DataPage<IDirectory>>()
|
private val _dirsUpdates = MutableSharedFlow<DataPage<IDirectory>>()
|
||||||
override val dirsUpdates: SharedFlow<DataPage<IDirectory>> = _dirsUpdates
|
override val dirsUpdates: SharedFlow<DataPage<IDirectory>> = _dirsUpdates
|
||||||
|
|
||||||
suspend fun init() {
|
suspend fun init() = withContext(ioDispatcher) {
|
||||||
// запускам сканирование хранилища
|
// запускам сканирование хранилища
|
||||||
scanSizeAndNumOfFiles()
|
scanSizeAndNumOfFiles()
|
||||||
}
|
}
|
||||||
@@ -251,11 +251,11 @@ class LocalStorageAccessor(
|
|||||||
* Считает файлы и их размер. Не бросает исключения, если файлы недоступны
|
* Считает файлы и их размер. Не бросает исключения, если файлы недоступны
|
||||||
* @throws none Если возникла ошибка, оставляет размер и количества файлов равными null
|
* @throws none Если возникла ошибка, оставляет размер и количества файлов равными null
|
||||||
*/
|
*/
|
||||||
private suspend fun scanSizeAndNumOfFiles() {
|
private suspend fun scanSizeAndNumOfFiles() = withContext(ioDispatcher) {
|
||||||
if (!checkAvailable()) {
|
if (!checkAvailable()) {
|
||||||
_size.value = null
|
_size.value = null
|
||||||
_numberOfFiles.value = null
|
_numberOfFiles.value = null
|
||||||
return
|
return@withContext
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = 0L
|
var size = 0L
|
||||||
@@ -280,8 +280,8 @@ class LocalStorageAccessor(
|
|||||||
return@withContext listOf()
|
return@withContext listOf()
|
||||||
|
|
||||||
val list = mutableListOf<IFile>()
|
val list = mutableListOf<IFile>()
|
||||||
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, CommonFile ->
|
scanStorage(baseStoragePath = "/", maxDepth = -1, fileCallback = { _, commonFile ->
|
||||||
list.add(CommonFile)
|
list.add(commonFile)
|
||||||
})
|
})
|
||||||
return@withContext list
|
return@withContext list
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.github.nullptroma.wallenc.data.vaults.local
|
package com.github.nullptroma.wallenc.data.vaults
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.github.nullptroma.wallenc.data.storages.local.LocalStorage
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
||||||
import com.github.nullptroma.wallenc.domain.enums.VaultType
|
import com.github.nullptroma.wallenc.domain.enums.VaultType
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.github.nullptroma.wallenc.data.vaults
|
package com.github.nullptroma.wallenc.data.vaults
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.nullptroma.wallenc.data.vaults.local.LocalVault
|
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IVault
|
import com.github.nullptroma.wallenc.domain.interfaces.IVault
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import java.time.Instant
|
|||||||
|
|
||||||
|
|
||||||
data class CommonStorageMetaInfo(
|
data class CommonStorageMetaInfo(
|
||||||
override val encInfo: StorageEncryptionInfo?,
|
override val encInfo: StorageEncryptionInfo = StorageEncryptionInfo(
|
||||||
override val name: String?,
|
isEncrypted = false,
|
||||||
|
encryptedTestData = null
|
||||||
|
),
|
||||||
|
override val name: String? = null,
|
||||||
override val lastModified: Instant = Clock.systemUTC().instant()
|
override val lastModified: Instant = Clock.systemUTC().instant()
|
||||||
) : IStorageMetaInfo
|
) : IStorageMetaInfo
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package com.github.nullptroma.wallenc.domain.encrypt
|
|
||||||
|
|
||||||
import com.github.nullptroma.wallenc.domain.common.impl.CommonStorageMetaInfo
|
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.EncryptKey
|
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
|
|
||||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorageMetaInfo
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.DisposableHandle
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.stateIn
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
class EncryptedStorage(
|
|
||||||
private val _source: IStorage,
|
|
||||||
key: EncryptKey,
|
|
||||||
private val ioDispatcher: CoroutineDispatcher,
|
|
||||||
override val uuid: UUID = UUID.randomUUID()
|
|
||||||
) : IStorage, DisposableHandle {
|
|
||||||
override val size: StateFlow<Long?>
|
|
||||||
get() = _source.size
|
|
||||||
override val numberOfFiles: StateFlow<Int?>
|
|
||||||
get() = _source.numberOfFiles
|
|
||||||
|
|
||||||
private val _metaInfo = MutableStateFlow<IStorageMetaInfo>(
|
|
||||||
CommonStorageMetaInfo(
|
|
||||||
encInfo = StorageEncryptionInfo(
|
|
||||||
isEncrypted = false,
|
|
||||||
encryptedTestData = null
|
|
||||||
),
|
|
||||||
name = null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
override val metaInfo: StateFlow<IStorageMetaInfo>
|
|
||||||
get() = _metaInfo
|
|
||||||
|
|
||||||
override val isAvailable: StateFlow<Boolean>
|
|
||||||
get() = _source.isAvailable
|
|
||||||
override val accessor: EncryptedStorageAccessor =
|
|
||||||
EncryptedStorageAccessor(_source.accessor, key, ioDispatcher)
|
|
||||||
|
|
||||||
override suspend fun rename(newName: String) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
accessor.dispose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.github.nullptroma.wallenc.domain.interfaces
|
package com.github.nullptroma.wallenc.domain.interfaces
|
||||||
|
|
||||||
|
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
||||||
|
|
||||||
interface IStorage: IStorageInfo {
|
interface IStorage: IStorageInfo {
|
||||||
val accessor: IStorageAccessor
|
val accessor: IStorageAccessor
|
||||||
|
|
||||||
suspend fun rename(newName: String)
|
suspend fun rename(newName: String)
|
||||||
|
suspend fun setEncInfo(encInfo: StorageEncryptionInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ sealed interface IStorageInfo {
|
|||||||
val size: StateFlow<Long?>
|
val size: StateFlow<Long?>
|
||||||
val numberOfFiles: StateFlow<Int?>
|
val numberOfFiles: StateFlow<Int?>
|
||||||
val metaInfo: StateFlow<IStorageMetaInfo>
|
val metaInfo: StateFlow<IStorageMetaInfo>
|
||||||
|
val isVirtualStorage: Boolean
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
package com.github.nullptroma.wallenc.domain.interfaces
|
package com.github.nullptroma.wallenc.domain.interfaces
|
||||||
|
|
||||||
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import java.time.Clock
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
interface IStorageMetaInfo {
|
interface IStorageMetaInfo {
|
||||||
val encInfo: StorageEncryptionInfo?
|
val encInfo: StorageEncryptionInfo
|
||||||
val name: String?
|
val name: String?
|
||||||
val lastModified: Instant
|
val lastModified: Instant
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.8.0"
|
agp = "8.8.0"
|
||||||
jacksonModuleKotlin = "2.18.2"
|
jacksonModuleKotlin = "2.18.2"
|
||||||
kotlin = "2.0.10"
|
kotlin = "2.0.20"
|
||||||
coreKtx = "1.15.0"
|
coreKtx = "1.15.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.2.1"
|
junitVersion = "1.2.1"
|
||||||
@@ -17,12 +17,11 @@ hiltNavigation = "1.2.0"
|
|||||||
timber = "5.0.1"
|
timber = "5.0.1"
|
||||||
yandexAuthSdk = "3.1.2"
|
yandexAuthSdk = "3.1.2"
|
||||||
daggerHilt = "2.52"
|
daggerHilt = "2.52"
|
||||||
ksp = "2.0.10-1.0.24"
|
ksp = "2.0.20-1.0.25"
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
retrofit = "2.11.0"
|
retrofit = "2.11.0"
|
||||||
appcompat = "1.7.0"
|
appcompat = "1.7.0"
|
||||||
material = "1.12.0"
|
material = "1.12.0"
|
||||||
runtimeAndroid = "1.7.5"
|
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" }
|
jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" }
|
||||||
|
|||||||
@@ -44,14 +44,14 @@ fun LocalVaultScreen(modifier: Modifier = Modifier,
|
|||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onTap = { _ -> viewModel.printStorageInfoToLog(it) }
|
onTap = { _ -> viewModel.printStorageInfoToLog(it) }
|
||||||
)
|
)
|
||||||
}) {
|
}.padding(8.dp)) {
|
||||||
val available by it.isAvailable.collectAsStateWithLifecycle()
|
val available by it.isAvailable.collectAsStateWithLifecycle()
|
||||||
val numOfFiles by it.numberOfFiles.collectAsStateWithLifecycle()
|
val numOfFiles by it.numberOfFiles.collectAsStateWithLifecycle()
|
||||||
val size by it.size.collectAsStateWithLifecycle()
|
val size by it.size.collectAsStateWithLifecycle()
|
||||||
val metaInfo by it.metaInfo.collectAsStateWithLifecycle()
|
val metaInfo by it.metaInfo.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val enc = metaInfo.encInfo
|
val enc = metaInfo.encInfo
|
||||||
Column {
|
Column(modifier = Modifier.padding(4.dp)) {
|
||||||
Text(it.uuid.toString())
|
Text(it.uuid.toString())
|
||||||
Text("IsAvailable: $available")
|
Text("IsAvailable: $available")
|
||||||
Text("Files: $numOfFiles")
|
Text("Files: $numOfFiles")
|
||||||
|
|||||||
Reference in New Issue
Block a user