overlay offline edits with existing

This commit is contained in:
Matt Gibson 2024-10-24 15:08:15 -07:00
parent d7b935031e
commit b30e52245f
No known key found for this signature in database
GPG key ID: 7CBCA182C13B0912
4 changed files with 77 additions and 5 deletions

View file

@ -19,10 +19,12 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.OfflineCipherJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.repository.util.toOfflineCipher
import com.x8bit.bitwarden.data.vault.repository.util.toOfflineCipherJson
import com.x8bit.bitwarden.data.vault.repository.util.toSdkCipherJson
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
@ -83,7 +85,6 @@ class VaultDiskSourceImpl(
)
}
override fun getOfflineCiphers(
userId: String,
): Flow<List<OfflineCipherJson>> =
@ -130,6 +131,16 @@ class VaultDiskSourceImpl(
.awaitAll()
}
},
).combine(
getOfflineCiphers(userId),
{ ciphers, offlineCiphers ->
val overlaid = ciphers.map { cipher ->
offlineCiphers.find { it.id == cipher.id }?.toSdkCipherJson() ?: cipher
}
// TODO add new offline items to the vault list
// val newOffline = offlineCiphers.filter { it.id.startsWith("create") }.map { it.toSdkCipherJson() }
overlaid
}
)
override suspend fun deleteCipher(userId: String, cipherId: String) {

View file

@ -87,6 +87,5 @@ data class OfflineCipherJson(
@SerialName("mergeConflict")
val mergeConflict: Boolean
){
// TODO: Add password history, fields, etc
) {
}

View file

@ -28,6 +28,7 @@ import com.bitwarden.vault.SecureNoteType
import com.bitwarden.vault.SecureNoteView
import com.bitwarden.vault.UriMatchType
import com.x8bit.bitwarden.data.platform.util.SpecialCharWithPrecedenceComparator
import com.x8bit.bitwarden.data.platform.util.isFdroid
import com.x8bit.bitwarden.data.vault.datasource.network.model.AttachmentJsonRequest
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherJsonRequest
import com.x8bit.bitwarden.data.vault.datasource.network.model.CipherRepromptTypeJson
@ -41,6 +42,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.UriMatchTypeJson
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.OfflineCipher
import com.x8bit.bitwarden.data.vault.repository.model.OfflineCipherView
import com.x8bit.bitwarden.ui.vault.feature.vault.model.NotificationSummary
import kotlinx.coroutines.flow.merge
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.util.UUID
@ -118,7 +120,7 @@ fun OfflineCipher.toOfflineCipherJson(id: String): OfflineCipherJson =
creationDate = ZonedDateTime.ofInstant(creationDate, ZoneOffset.UTC),
deletedDate = deletedDate?.let { ZonedDateTime.ofInstant(deletedDate, ZoneOffset.UTC) },
revisionDate = ZonedDateTime.ofInstant(creationDate, ZoneOffset.UTC),
mergeConflict = false, // TODO: Copy from the new OfflineCipher type
mergeConflict = mergeConflict,
)
fun OfflineCipherView.toNotificationSummary(): NotificationSummary =
@ -159,6 +161,60 @@ fun CipherView.toOfflineCipherView(offlineCipher: OfflineCipher) =
mergeConflict = offlineCipher.mergeConflict
)
fun SyncResponseJson.Cipher.overlayOfflineCipherJson(offlineCipherJson: OfflineCipherJson) =
SyncResponseJson.Cipher(
notes = offlineCipherJson.notes,
attachments = offlineCipherJson.attachments,
shouldOrganizationUseTotp = shouldOrganizationUseTotp,
reprompt = offlineCipherJson.reprompt,
shouldEdit = shouldEdit,
passwordHistory = offlineCipherJson.passwordHistory,
revisionDate = offlineCipherJson.revisionDate,
type = offlineCipherJson.type,
login = offlineCipherJson.login,
creationDate = offlineCipherJson.creationDate,
secureNote = offlineCipherJson.secureNote,
folderId = offlineCipherJson.folderId,
organizationId = offlineCipherJson.organizationId,
deletedDate = offlineCipherJson.deletedDate,
identity = offlineCipherJson.identity,
collectionIds = offlineCipherJson.collectionIds,
name = offlineCipherJson.name,
id = id,
fields = offlineCipherJson.fields,
shouldViewPassword = shouldViewPassword,
isFavorite = offlineCipherJson.favorite,
card = offlineCipherJson.card,
key = offlineCipherJson.key
)
fun OfflineCipherJson.toSdkCipherJson(): SyncResponseJson.Cipher =
SyncResponseJson.Cipher(
id = id, // TODO, the "create_..." id is invalid, but it's not clear what's better
notes = notes,
attachments = attachments,
shouldOrganizationUseTotp = false, // TODO
reprompt = reprompt,
shouldEdit = false, // TODO
passwordHistory = passwordHistory,
revisionDate = revisionDate,
type = type,
login = login,
creationDate = creationDate,
secureNote = secureNote,
folderId = folderId,
organizationId = organizationId,
deletedDate = deletedDate,
identity = identity,
collectionIds = collectionIds,
name = name,
fields = fields,
shouldViewPassword = false, // TODO
isFavorite = favorite,
card = card,
key = key,
)
fun OfflineCipherJson.toOfflineCipher(): OfflineCipher =
OfflineCipher(
id = if (id.startsWith("create")) null else id,

View file

@ -412,10 +412,16 @@ class VaultAddEditViewModel @Inject constructor(
}
is VaultAddEditType.EditItem -> {
val result = vaultRepository.updateCipher(
var result = vaultRepository.updateCipher(
cipherId = vaultAddEditType.vaultItemId,
cipherView = content.toCipherView(),
)
if (result is UpdateCipherResult.Error) {
// TODO: Ask for permission to store locally
result = vaultRepository.updateOfflineCipher(cipherId = vaultAddEditType.vaultItemId, cipherView = content.toCipherView())
}
sendAction(VaultAddEditAction.Internal.UpdateCipherResultReceive(result))
}