feat(sync): перевёл группы синхронизации на Room и добавил контроль совместимости

This commit is contained in:
2026-05-17 18:03:14 +03:00
parent 15f13577c8
commit e562e4d9e9
28 changed files with 518 additions and 159 deletions

View File

@@ -5,6 +5,7 @@ import com.github.nullptroma.wallenc.infrastructure.db.RoomFactory
import com.github.nullptroma.wallenc.infrastructure.db.app.IAppDb
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.YandexAccountDao
import dagger.Module
import dagger.Provides
@@ -33,6 +34,12 @@ class RoomModule {
return database.storageMetaInfoDao
}
@Provides
@Singleton
fun provideStorageSyncGroupDao(database: IAppDb): StorageSyncGroupDao {
return database.storageSyncGroupDao
}
@Provides
@Singleton
fun provideYandexAccountDao(database: IAppDb): YandexAccountDao {

View File

@@ -4,9 +4,11 @@ import android.content.Context
import com.github.nullptroma.wallenc.app.di.modules.app.IoDispatcher
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageKeyMapDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageMetaInfoDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.StorageSyncGroupDao
import com.github.nullptroma.wallenc.infrastructure.db.app.dao.YandexAccountDao
import com.github.nullptroma.wallenc.infrastructure.db.app.repository.StorageKeyMapRepository
import com.github.nullptroma.wallenc.infrastructure.db.app.repository.StorageMetaInfoRepository
import com.github.nullptroma.wallenc.infrastructure.db.app.repository.StorageSyncGroupRepository
import com.github.nullptroma.wallenc.infrastructure.db.app.repository.YandexAccountRepository
import com.github.nullptroma.wallenc.infrastructure.network.yandexdisk.YandexDiskApiFactory
import com.github.nullptroma.wallenc.infrastructure.network.yandexdisk.repository.YandexDiskRepositoryFactory
@@ -15,7 +17,6 @@ import com.github.nullptroma.wallenc.infrastructure.network.yandexuserinfo.Yande
import com.github.nullptroma.wallenc.infrastructure.network.yandexuserinfo.repository.YandexUserInfoRepository
import com.github.nullptroma.wallenc.infrastructure.ports.StorageKeyMapStore
import com.github.nullptroma.wallenc.infrastructure.ports.YandexAccountStore
import com.github.nullptroma.wallenc.app.sync.StorageSyncGroupStore
import com.github.nullptroma.wallenc.task.runtime.TaskOrchestrator
import com.github.nullptroma.wallenc.infrastructure.vaults.VaultsManager
import com.github.nullptroma.wallenc.infrastructure.vaults.local.LocalVault
@@ -138,8 +139,9 @@ class SingletonModule {
@Provides
@Singleton
fun provideStorageSyncGroupStore(
@ApplicationContext context: Context,
): IStorageSyncGroupStore = StorageSyncGroupStore(context)
dao: StorageSyncGroupDao,
@IoDispatcher ioDispatcher: CoroutineDispatcher,
): IStorageSyncGroupStore = StorageSyncGroupRepository(dao, ioDispatcher)
@Provides
@Singleton

View File

@@ -1,87 +0,0 @@
package com.github.nullptroma.wallenc.app.sync
import android.content.Context
import com.github.nullptroma.wallenc.domain.interfaces.IStorageSyncGroupStore
import com.github.nullptroma.wallenc.domain.interfaces.StorageSyncGroup
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
import androidx.core.content.edit
@Singleton
class StorageSyncGroupStore @Inject constructor(
@param:ApplicationContext private val app: Context,
) : IStorageSyncGroupStore {
private val prefs by lazy {
app.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
}
override suspend fun getGroups(): List<StorageSyncGroup> {
val raw = prefs.getString(KEY_GROUPS, null).orEmpty()
return parse(raw)
}
override suspend fun putGroup(group: StorageSyncGroup) {
val current = getGroups().toMutableList()
val idx = current.indexOfFirst { it.id == group.id }
if (idx >= 0) {
current[idx] = group
} else {
current.add(group)
}
persist(current)
}
override suspend fun removeGroup(groupId: String) {
val current = getGroups().filterNot { it.id == groupId }
persist(current)
}
private fun parse(raw: String): List<StorageSyncGroup> {
if (raw.isBlank()) {
return emptyList()
}
return raw.lineSequence()
.mapNotNull { line ->
val trimmed = line.trim()
if (trimmed.isBlank()) {
return@mapNotNull null
}
val split = trimmed.split("=", limit = 2)
if (split.size != 2) {
return@mapNotNull null
}
val id = split[0].trim()
if (id.isBlank()) {
return@mapNotNull null
}
val uuids = split[1]
.split(",")
.mapNotNull { token ->
val value = token.trim()
if (value.isBlank()) {
null
} else {
runCatching { UUID.fromString(value) }.getOrNull()
}
}
.toSet()
StorageSyncGroup(id = id, storageUuids = uuids)
}
.toList()
}
private fun persist(groups: List<StorageSyncGroup>) {
val raw = groups.joinToString(separator = "\n") { group ->
val uuids = group.storageUuids.joinToString(separator = ",") { it.toString() }
"${group.id}=$uuids"
}
prefs.edit { putString(KEY_GROUPS, raw) }
}
private companion object {
private const val PREFS_NAME = "wallenc_storage_sync"
private const val KEY_GROUPS = "groups"
}
}