From aa57aede5b26d382ce3c5e1e56add20270b651a0 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 11 Oct 2024 17:32:18 +0200 Subject: [PATCH 01/13] common: Add transferDirection to know if the transfer is received or sent --- .../common/interfaces/transfers/Transfer.kt | 4 ++++ .../common/models/TransferDirection.kt | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/models/TransferDirection.kt diff --git a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt index 601d3418..d805b805 100644 --- a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt +++ b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt @@ -17,6 +17,8 @@ */ package com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers +import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection + interface Transfer { val linkUuid: String val containerUuid: String @@ -27,4 +29,6 @@ interface Transfer { val isMailSent: Boolean val downloadHost: String val container: ContainerType + + fun transferDirection(): TransferDirection? = null } diff --git a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/models/TransferDirection.kt b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/models/TransferDirection.kt new file mode 100644 index 00000000..51bfda37 --- /dev/null +++ b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/models/TransferDirection.kt @@ -0,0 +1,22 @@ +/* + * Infomaniak SwissTransfer - Multiplatform + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.infomaniak.multiplatform_swisstransfer.common.models + +enum class TransferDirection { + SENT, RECEIVED +} From 5233420150b34dcaaa01fff82df935ee01255315 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 11 Oct 2024 17:33:47 +0200 Subject: [PATCH 02/13] database: Add support of TransferDirection --- .../database/cache/setting/TransferController.kt | 5 +++-- .../database/models/transfers/TransferDB.kt | 13 ++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt index 78498aa0..da869389 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt @@ -18,6 +18,7 @@ package com.infomaniak.multiplatform_swisstransfer.database.cache.setting import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer +import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import com.infomaniak.multiplatform_swisstransfer.database.RealmProvider import com.infomaniak.multiplatform_swisstransfer.database.models.transfers.TransferDB import io.realm.kotlin.UpdatePolicy @@ -50,9 +51,9 @@ class TransferController(private val realmProvider: RealmProvider) { //endregion //region Upsert data - suspend fun upsert(transfer: Transfer<*>) { + suspend fun upsert(transfer: Transfer<*>, transferDirection: TransferDirection) { realm?.write { - this.copyToRealm(TransferDB(transfer), UpdatePolicy.ALL) + this.copyToRealm(TransferDB(transfer, transferDirection), UpdatePolicy.ALL) } } //endregion diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt index 7a681a70..28675048 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt @@ -20,6 +20,7 @@ package com.infomaniak.multiplatform_swisstransfer.database.models.transfers import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Container import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.File import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer +import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.annotations.PrimaryKey @@ -35,8 +36,10 @@ class TransferDB() : Transfer, RealmObject { override var downloadHost: String = "" override var container: ContainerDB? = null + private var transferDirectionValue: String = "" + @Suppress("UNCHECKED_CAST") - constructor(transfer: Transfer<*>) : this() { + constructor(transfer: Transfer<*>, transferDirection: TransferDirection) : this() { this.linkUuid = transfer.linkUuid this.containerUuid = transfer.containerUuid this.downloadCounterCredit = transfer.downloadCounterCredit @@ -46,5 +49,13 @@ class TransferDB() : Transfer, RealmObject { this.isMailSent = transfer.isMailSent this.downloadHost = transfer.downloadHost this.container = ContainerDB(transfer.container as Container>) + + this.transferDirectionValue = transferDirection.name + } + + override fun transferDirection(): TransferDirection = TransferDirection.valueOf(transferDirectionValue) + + internal companion object { + val transferDirectionPropertyName = TransferDB::transferDirectionValue.name } } From 47c960ee80dc3691384510582ae11e60923d925f Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 11 Oct 2024 17:34:58 +0200 Subject: [PATCH 03/13] database: Add transferDirection unit tests --- .../database/TransferControllerTest.kt | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt index d14efa19..1aa8f924 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt @@ -20,6 +20,7 @@ package com.infomaniak.multiplatform_swisstransfer.database import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Container import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.File import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer +import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import com.infomaniak.multiplatform_swisstransfer.database.cache.setting.TransferController import com.infomaniak.multiplatform_swisstransfer.database.dataset.DummyTransfer import kotlinx.coroutines.test.runTest @@ -43,18 +44,19 @@ class TransferControllerTest { } @Test - fun canCreateTransfer() = runTest { - val transfer = DummyTransfer.transfer - transferController.upsert(transfer) - val realmTransfer = transferController.getTransfer(transfer.linkUuid) - assertNotNull(realmTransfer, "The transfer cannot be null") - assertEquals(transfer.container.uuid, realmTransfer.container?.uuid, "The container is missing") + fun canCreateSentTransfer() = runTest { + canCreateTransfer(TransferDirection.SENT) + } + + @Test + fun canCreateReceivedTransfer() = runTest { + canCreateTransfer(TransferDirection.RECEIVED) } @Test fun canGetTransfers() = runTest { val transfer = DummyTransfer.transfer - transferController.upsert(transfer) + transferController.upsert(transfer, TransferDirection.SENT) val transfers = transferController.getTransfers() assertEquals(1, transfers?.count(), "The transfer list must contain 1 item") } @@ -63,7 +65,7 @@ class TransferControllerTest { fun canUpdateAnExistingTransfer() = runTest { // Insert a transfer val transfer1 = DummyTransfer.transfer - transferController.upsert(transfer1) + transferController.upsert(transfer1, TransferDirection.SENT) val realmTransfer1 = transferController.getTransfer(transfer1.linkUuid) assertNotNull(realmTransfer1) @@ -71,7 +73,7 @@ class TransferControllerTest { val transfer2 = object : Transfer>> by transfer1 { override var containerUuid: String = "transfer2" } - transferController.upsert(transfer2) + transferController.upsert(transfer2, TransferDirection.SENT) val realmTransfers = transferController.getTransfers() assertNotNull(realmTransfers) assertEquals(1, realmTransfers.count()) @@ -80,8 +82,17 @@ class TransferControllerTest { @Test fun canRemoveTransfers() = runTest { - transferController.upsert(DummyTransfer.transfer) + transferController.upsert(DummyTransfer.transfer, TransferDirection.SENT) transferController.removeData() assertEquals(0, transferController.getTransfers()?.count(), "The transfers table must be empty") } + + private suspend fun canCreateTransfer(sent: TransferDirection) { + val transfer = DummyTransfer.transfer + transferController.upsert(transfer, sent) + val realmTransfer = transferController.getTransfer(transfer.linkUuid) + assertNotNull(realmTransfer, "The transfer cannot be null") + assertEquals(sent, realmTransfer.transferDirection()) + assertEquals(transfer.container.uuid, realmTransfer.container?.uuid, "The container is missing") + } } From eb3164c121e843c329fedaf81b2d59b29e95fc3c Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 11 Oct 2024 17:36:26 +0200 Subject: [PATCH 04/13] core: Specify transfer type when adding to database --- .../managers/TransferManager.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt index 467bd2ac..103f5f8a 100644 --- a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt +++ b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt @@ -19,6 +19,7 @@ package com.infomaniak.multiplatform_swisstransfer.managers import com.infomaniak.multiplatform_swisstransfer.common.exceptions.UnknownException import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer +import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import com.infomaniak.multiplatform_swisstransfer.database.cache.setting.TransferController import com.infomaniak.multiplatform_swisstransfer.network.ApiClientProvider import com.infomaniak.multiplatform_swisstransfer.network.exceptions.ApiException @@ -81,7 +82,7 @@ class TransferManager internal constructor( UnknownException::class, ) suspend fun addTransferByLinkUuid(linkUuid: String) = withContext(Dispatchers.IO) { - addTransfer(transferRepository.getTransferByLinkUuid(linkUuid).data) + addTransfer(transferRepository.getTransferByLinkUuid(linkUuid).data, TransferDirection.SENT) } /** @@ -108,12 +109,12 @@ class TransferManager internal constructor( UnknownException::class, ) suspend fun addTransferByUrl(url: String) = withContext(Dispatchers.IO) { - addTransfer(transferRepository.getTransferByUrl(url).data) + addTransfer(transferRepository.getTransferByUrl(url).data, TransferDirection.RECEIVED) } - private suspend fun addTransfer(transferApi: TransferApi?) { + private suspend fun addTransfer(transferApi: TransferApi?, transferDirection: TransferDirection) { runCatching { - transferController.upsert(transferApi as Transfer<*>) + transferController.upsert(transferApi as Transfer<*>, transferDirection) }.onFailure { throw UnknownException(it) } From 659f78b1ad7429f93bed290c3b3c85e1d26c9a07 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Fri, 11 Oct 2024 17:39:16 +0200 Subject: [PATCH 05/13] chore: Make getTransfers visible only in the internal module --- .../database/cache/setting/TransferController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt index da869389..617c6b25 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt @@ -38,7 +38,7 @@ class TransferController(private val realmProvider: RealmProvider) { //region Get data @Throws(IllegalArgumentException::class, CancellationException::class) - fun getTransfers(): RealmResults? { + internal fun getTransfers(): RealmResults? { return realm?.query()?.sort(TransferDB::createdDateTimestamp.name, Sort.DESCENDING)?.find() } From 417d3167a62b030abc09131f7d04c62ddbab71d4 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 17:25:35 +0200 Subject: [PATCH 06/13] chore: Update libs --- gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c98fcd02..f5e3c948 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] agp = "8.4.2" coroutines = "1.9.0" -kotlin = "2.0.10" +kotlin = "2.0.20" kotlinxDatetime = "0.6.0" kotlinxSerializationJson = "1.7.1" ktor = "2.3.12" -realm = "2.0.0" -skie = "0.8.4" +realm = "3.0.0" +skie = "0.9.2" [libraries] android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } From 4958afa245cb3e872fd0a2cf762fc073ecb8df9b Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 17:31:11 +0200 Subject: [PATCH 07/13] refactor: Simplifying generic types with k2 --- .../common/interfaces/transfers/Container.kt | 4 ++-- .../common/interfaces/transfers/Transfer.kt | 4 ++-- .../managers/TransferManager.kt | 2 +- .../database/cache/setting/TransferController.kt | 4 ++-- .../database/models/transfers/ContainerDB.kt | 5 ++--- .../database/models/transfers/TransferDB.kt | 9 +++------ .../database/TransferControllerTest.kt | 6 ++---- .../database/dataset/DummyTransfer.kt | 6 +++--- .../network/models/transfer/ContainerApi.kt | 2 +- .../network/models/transfer/TransferApi.kt | 2 +- 10 files changed, 19 insertions(+), 25 deletions(-) diff --git a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Container.kt b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Container.kt index 1f5fe258..ff11c22a 100644 --- a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Container.kt +++ b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Container.kt @@ -17,7 +17,7 @@ */ package com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers -interface Container> { +interface Container { val uuid: String val duration: Long val createdDateTimestamp: Long @@ -33,5 +33,5 @@ interface Container> { val source: String // @SerialName("WSUser") // TODO: What's this ? // val wsUser: JsonElement? - val files: F + val files: List } diff --git a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt index d805b805..49bddba0 100644 --- a/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt +++ b/STCommon/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/common/interfaces/transfers/Transfer.kt @@ -19,7 +19,7 @@ package com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection -interface Transfer { +interface Transfer { val linkUuid: String val containerUuid: String val downloadCounterCredit: Int @@ -28,7 +28,7 @@ interface Transfer { val hasBeenDownloadedOneTime: Boolean val isMailSent: Boolean val downloadHost: String - val container: ContainerType + val container: Container? fun transferDirection(): TransferDirection? = null } diff --git a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt index 103f5f8a..f34e94c3 100644 --- a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt +++ b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt @@ -114,7 +114,7 @@ class TransferManager internal constructor( private suspend fun addTransfer(transferApi: TransferApi?, transferDirection: TransferDirection) { runCatching { - transferController.upsert(transferApi as Transfer<*>, transferDirection) + transferController.upsert(transferApi as Transfer, transferDirection) }.onFailure { throw UnknownException(it) } diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt index 617c6b25..68a2bc54 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt @@ -43,7 +43,7 @@ class TransferController(private val realmProvider: RealmProvider) { } @Throws(IllegalArgumentException::class, CancellationException::class) - fun getTransfersFlow(): Flow> = getTransfers()?.asFlow()?.mapLatest { it.list } ?: emptyFlow() + fun getTransfersFlow(): Flow> = getTransfers()?.asFlow()?.mapLatest { it.list } ?: emptyFlow() fun getTransfer(linkUuid: String): TransferDB? { return realm?.query("${TransferDB::linkUuid.name} == '$linkUuid'")?.first()?.find() @@ -51,7 +51,7 @@ class TransferController(private val realmProvider: RealmProvider) { //endregion //region Upsert data - suspend fun upsert(transfer: Transfer<*>, transferDirection: TransferDirection) { + suspend fun upsert(transfer: Transfer, transferDirection: TransferDirection) { realm?.write { this.copyToRealm(TransferDB(transfer, transferDirection), UpdatePolicy.ALL) } diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/ContainerDB.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/ContainerDB.kt index 43910d01..8e80ca27 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/ContainerDB.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/ContainerDB.kt @@ -18,13 +18,12 @@ package com.infomaniak.multiplatform_swisstransfer.database.models.transfers import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Container -import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.File import io.realm.kotlin.ext.realmListOf import io.realm.kotlin.types.RealmList import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.annotations.PrimaryKey -class ContainerDB() : Container>, RealmObject { +class ContainerDB() : Container, RealmObject { @PrimaryKey override var uuid: String = "" override var duration: Long = 0L @@ -43,7 +42,7 @@ class ContainerDB() : Container>, RealmObject { // val wsUser: JsonElement? override var files: RealmList = realmListOf() - constructor(container: Container>) : this() { + constructor(container: Container) : this() { this.uuid = container.uuid this.duration = container.duration this.createdDateTimestamp = container.createdDateTimestamp diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt index 28675048..7d6d938d 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/models/transfers/TransferDB.kt @@ -17,14 +17,12 @@ */ package com.infomaniak.multiplatform_swisstransfer.database.models.transfers -import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Container -import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.File import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.annotations.PrimaryKey -class TransferDB() : Transfer, RealmObject { +class TransferDB() : Transfer, RealmObject { @PrimaryKey override var linkUuid: String = "" override var containerUuid: String = "" @@ -38,8 +36,7 @@ class TransferDB() : Transfer, RealmObject { private var transferDirectionValue: String = "" - @Suppress("UNCHECKED_CAST") - constructor(transfer: Transfer<*>, transferDirection: TransferDirection) : this() { + constructor(transfer: Transfer, transferDirection: TransferDirection) : this() { this.linkUuid = transfer.linkUuid this.containerUuid = transfer.containerUuid this.downloadCounterCredit = transfer.downloadCounterCredit @@ -48,7 +45,7 @@ class TransferDB() : Transfer, RealmObject { this.hasBeenDownloadedOneTime = transfer.hasBeenDownloadedOneTime this.isMailSent = transfer.isMailSent this.downloadHost = transfer.downloadHost - this.container = ContainerDB(transfer.container as Container>) + this.container = transfer.container?.let(::ContainerDB) this.transferDirectionValue = transferDirection.name } diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt index 1aa8f924..fc41bd36 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt @@ -17,8 +17,6 @@ */ package com.infomaniak.multiplatform_swisstransfer.database -import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Container -import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.File import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Transfer import com.infomaniak.multiplatform_swisstransfer.common.models.TransferDirection import com.infomaniak.multiplatform_swisstransfer.database.cache.setting.TransferController @@ -70,7 +68,7 @@ class TransferControllerTest { assertNotNull(realmTransfer1) // Update the transfer - val transfer2 = object : Transfer>> by transfer1 { + val transfer2 = object : Transfer by transfer1 { override var containerUuid: String = "transfer2" } transferController.upsert(transfer2, TransferDirection.SENT) @@ -93,6 +91,6 @@ class TransferControllerTest { val realmTransfer = transferController.getTransfer(transfer.linkUuid) assertNotNull(realmTransfer, "The transfer cannot be null") assertEquals(sent, realmTransfer.transferDirection()) - assertEquals(transfer.container.uuid, realmTransfer.container?.uuid, "The container is missing") + assertEquals(transfer.container?.uuid, realmTransfer.container?.uuid, "The container is missing") } } diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt index a22ab9a1..e38ec9c4 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt @@ -23,7 +23,7 @@ import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Tr object DummyTransfer { - private val containerTest = object : Container> { + private val containerTest = object : Container { override var uuid: String = "transfer1Container" override var duration: Long = 0L override var createdDateTimestamp: Long = 0L @@ -40,7 +40,7 @@ object DummyTransfer { override var files: List = emptyList() } - val transfer = object : Transfer>> { + val transfer = object : Transfer { override var linkUuid: String = "transferLinkUuid1" override var containerUuid: String = "containerUuid" override var downloadCounterCredit: Int = 0 @@ -49,7 +49,7 @@ object DummyTransfer { override var hasBeenDownloadedOneTime: Boolean = false override var isMailSent: Boolean = true override var downloadHost: String = "url" - override var container: Container> = containerTest + override var container: Container = containerTest } } diff --git a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/ContainerApi.kt b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/ContainerApi.kt index 7fab77f4..cc347dd1 100644 --- a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/ContainerApi.kt +++ b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/ContainerApi.kt @@ -24,7 +24,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -class ContainerApi : Container> { +class ContainerApi : Container { @SerialName("UUID") override var uuid: String = "" override var duration: Long = 0L diff --git a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/TransferApi.kt b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/TransferApi.kt index b8c4d737..6df59aba 100644 --- a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/TransferApi.kt +++ b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/models/transfer/TransferApi.kt @@ -24,7 +24,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -class TransferApi : Transfer { +class TransferApi : Transfer { override var linkUuid: String = "" override var containerUuid: String = "" override var downloadCounterCredit: Int = 0 From 978c6999cbdeeb03a534c11d02babf926603c140 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 17:33:34 +0200 Subject: [PATCH 08/13] fix: NetworkException parent is not externally accessible --- .../network/exceptions/NetworkException.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/exceptions/NetworkException.kt b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/exceptions/NetworkException.kt index f894dc9e..a624c4c7 100644 --- a/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/exceptions/NetworkException.kt +++ b/STNetwork/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/network/exceptions/NetworkException.kt @@ -17,11 +17,9 @@ */ package com.infomaniak.multiplatform_swisstransfer.network.exceptions -import io.ktor.utils.io.errors.IOException - /** * Thrown when a network-related error occurs, such as connectivity issues or timeouts. * * @param message A detailed message describing the network error. */ -class NetworkException(message: String) : IOException(message) +class NetworkException(message: String) : Exception(message) From 1a6c2fa154e3bc158ef479dd121ed8ec512fcf35 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 17:48:58 +0200 Subject: [PATCH 09/13] feat: Get transfers by direction type (received or sent) --- .../database/cache/setting/TransferController.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt index 68a2bc54..18e351a1 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/cache/setting/TransferController.kt @@ -25,6 +25,7 @@ import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.ext.query import io.realm.kotlin.query.RealmResults import io.realm.kotlin.query.Sort +import io.realm.kotlin.query.TRUE_PREDICATE import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow @@ -38,14 +39,20 @@ class TransferController(private val realmProvider: RealmProvider) { //region Get data @Throws(IllegalArgumentException::class, CancellationException::class) - internal fun getTransfers(): RealmResults? { - return realm?.query()?.sort(TransferDB::createdDateTimestamp.name, Sort.DESCENDING)?.find() + internal fun getTransfers(transferDirection: TransferDirection? = null): RealmResults? { + val sentFilterQuery = when (transferDirection) { + null -> TRUE_PREDICATE + else -> "${TransferDB.transferDirectionPropertyName} == '${transferDirection}'" + } + return realm?.query(sentFilterQuery)?.sort(TransferDB::createdDateTimestamp.name, Sort.DESCENDING)?.find() } @Throws(IllegalArgumentException::class, CancellationException::class) - fun getTransfersFlow(): Flow> = getTransfers()?.asFlow()?.mapLatest { it.list } ?: emptyFlow() + fun getTransfersFlow(transferDirection: TransferDirection): Flow> { + return getTransfers(transferDirection)?.asFlow()?.mapLatest { it.list } ?: emptyFlow() + } - fun getTransfer(linkUuid: String): TransferDB? { + fun getTransfer(linkUuid: String): Transfer? { return realm?.query("${TransferDB::linkUuid.name} == '$linkUuid'")?.first()?.find() } //endregion From 367cef14abcd5b1db538f5b3ad0fa352805071e4 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 18:00:15 +0200 Subject: [PATCH 10/13] test: Add more transfers data set --- .../database/TransferControllerTest.kt | 13 +++++++------ .../database/dataset/DummyTransfer.kt | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt index fc41bd36..31778f83 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt @@ -53,16 +53,17 @@ class TransferControllerTest { @Test fun canGetTransfers() = runTest { - val transfer = DummyTransfer.transfer - transferController.upsert(transfer, TransferDirection.SENT) + DummyTransfer.transfers.take(2).forEach { transfer -> + transferController.upsert(transfer, TransferDirection.SENT) + } val transfers = transferController.getTransfers() - assertEquals(1, transfers?.count(), "The transfer list must contain 1 item") + assertEquals(2, transfers?.count(), "The transfer list must contain 2 items") } @Test fun canUpdateAnExistingTransfer() = runTest { // Insert a transfer - val transfer1 = DummyTransfer.transfer + val transfer1 = DummyTransfer.transfer1 transferController.upsert(transfer1, TransferDirection.SENT) val realmTransfer1 = transferController.getTransfer(transfer1.linkUuid) assertNotNull(realmTransfer1) @@ -80,13 +81,13 @@ class TransferControllerTest { @Test fun canRemoveTransfers() = runTest { - transferController.upsert(DummyTransfer.transfer, TransferDirection.SENT) + transferController.upsert(DummyTransfer.transfer1, TransferDirection.SENT) transferController.removeData() assertEquals(0, transferController.getTransfers()?.count(), "The transfers table must be empty") } private suspend fun canCreateTransfer(sent: TransferDirection) { - val transfer = DummyTransfer.transfer + val transfer = DummyTransfer.transfer1 transferController.upsert(transfer, sent) val realmTransfer = transferController.getTransfer(transfer.linkUuid) assertNotNull(realmTransfer, "The transfer cannot be null") diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt index e38ec9c4..668ac9cd 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/dataset/DummyTransfer.kt @@ -23,7 +23,7 @@ import com.infomaniak.multiplatform_swisstransfer.common.interfaces.transfers.Tr object DummyTransfer { - private val containerTest = object : Container { + private val container1 = object : Container { override var uuid: String = "transfer1Container" override var duration: Long = 0L override var createdDateTimestamp: Long = 0L @@ -40,7 +40,11 @@ object DummyTransfer { override var files: List = emptyList() } - val transfer = object : Transfer { + val container2 = object : Container by container1 { + override val uuid: String = "transfer2container" + } + + val transfer1 = object : Transfer { override var linkUuid: String = "transferLinkUuid1" override var containerUuid: String = "containerUuid" override var downloadCounterCredit: Int = 0 @@ -49,7 +53,15 @@ object DummyTransfer { override var hasBeenDownloadedOneTime: Boolean = false override var isMailSent: Boolean = true override var downloadHost: String = "url" - override var container: Container = containerTest + override var container: Container = this@DummyTransfer.container1 } + val transfer2 = object : Transfer by transfer1 { + override val linkUuid: String = "transfer2" + override val containerUuid: String = "container2" + override val container: Container = container2 + } + + val transfers = listOf(transfer1, transfer2) + } From 52fc790b416ded3eac16115055f2ca4d2ecea675 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Mon, 14 Oct 2024 19:00:24 +0200 Subject: [PATCH 11/13] test: Add unit test for transfer directions --- .../database/TransferControllerTest.kt | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt index 31778f83..413b3bce 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt @@ -53,13 +53,21 @@ class TransferControllerTest { @Test fun canGetTransfers() = runTest { - DummyTransfer.transfers.take(2).forEach { transfer -> - transferController.upsert(transfer, TransferDirection.SENT) - } + addTwoRandomTransfersInDatabase() val transfers = transferController.getTransfers() assertEquals(2, transfers?.count(), "The transfer list must contain 2 items") } + @Test + fun canGetSentTransfers() = runTest { + canGetTransfersByDirection(TransferDirection.SENT) + } + + @Test + fun canGetReceivedTransfers() = runTest { + canGetTransfersByDirection(TransferDirection.RECEIVED) + } + @Test fun canUpdateAnExistingTransfer() = runTest { // Insert a transfer @@ -94,4 +102,19 @@ class TransferControllerTest { assertEquals(sent, realmTransfer.transferDirection()) assertEquals(transfer.container?.uuid, realmTransfer.container?.uuid, "The container is missing") } + + private suspend fun addTwoRandomTransfersInDatabase() { + DummyTransfer.transfers.take(2).forEachIndexed { index, transfer -> + val transferDirection = if (index == 0) TransferDirection.SENT else TransferDirection.RECEIVED + transferController.upsert(transfer, transferDirection) + } + } + + private suspend fun canGetTransfersByDirection(transferDirection: TransferDirection) { + addTwoRandomTransfersInDatabase() + val transfers = transferController.getTransfers(transferDirection) + assertNotNull(transfers) + assertEquals(1, transfers.count(), "The transfer list must contain 1 item") + assertEquals(transferDirection, transfers.first().transferDirection()) + } } From fc8313a062b67efc5b261958b07601f04b7d61cd Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Oct 2024 09:55:47 +0200 Subject: [PATCH 12/13] feat: Get sent or received transfers flow --- .../managers/TransferManager.kt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt index f34e94c3..aaa7287c 100644 --- a/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt +++ b/STCore/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/managers/TransferManager.kt @@ -29,6 +29,7 @@ import com.infomaniak.multiplatform_swisstransfer.network.models.transfer.Transf import com.infomaniak.multiplatform_swisstransfer.network.repositories.TransferRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.withContext import kotlin.coroutines.cancellation.CancellationException @@ -52,11 +53,17 @@ class TransferManager internal constructor( ) { /** - * The `Flow` of [transfers] is used to receive updates for new transfers added in database. - * @see addTransferByLinkUuid + * Retrieves a flow of transfers based on the specified transfer direction. + * * @see addTransferByUrl + * @see addTransferByLinkUuid + * + * @param transferDirection The direction of the transfers to retrieve (e.g., [TransferDirection.SENT] or [TransferDirection.RECEIVED]). + * @return A `Flow` that emits a list of transfers matching the specified direction. */ - val transfers get() = transferController.getTransfersFlow().flowOn(Dispatchers.IO) + fun getTransfers(transferDirection: TransferDirection): Flow> { + return transferController.getTransfersFlow(transferDirection).flowOn(Dispatchers.IO) + } /** * Retrieves a transfer using the provided link UUID and saves it to the database. @@ -65,7 +72,7 @@ class TransferManager internal constructor( * a `linkUuid` is returned, which must be passed to this function to retrieve the corresponding transfer. * After retrieving the transfer, it is saved to the database. * - * @see transfers + * @see getTransfers * * @param linkUuid The UUID corresponding to the uploaded transfer link. * @throws CancellationException If the operation is cancelled. @@ -92,7 +99,7 @@ class TransferManager internal constructor( * the corresponding transfer, and after the transfer is successfully retrieved, it is saved to * the database. * - * @see transfers + * @see getTransfers * * @param url The URL associated with the transfer to retrieve. * @throws CancellationException If the operation is cancelled. From 0b3c61991aea3a0bceb24c8db2209aa9090fab15 Mon Sep 17 00:00:00 2001 From: Abdourahamane Boinaidi Date: Tue, 15 Oct 2024 13:43:18 +0200 Subject: [PATCH 13/13] chore: Add load data in memory for unit tests in RealmProvider --- .../database/RealmProvider.kt | 16 +++++++++++----- .../database/TransferControllerTest.kt | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/RealmProvider.kt b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/RealmProvider.kt index fe92f754..71e3702d 100644 --- a/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/RealmProvider.kt +++ b/STDatabase/src/commonMain/kotlin/com/infomaniak/multiplatform_swisstransfer/database/RealmProvider.kt @@ -25,15 +25,15 @@ import com.infomaniak.multiplatform_swisstransfer.database.models.upload.Upload import io.realm.kotlin.Realm import io.realm.kotlin.RealmConfiguration -class RealmProvider { +class RealmProvider(private val loadDataInMemory: Boolean = false) { val realmAppSettings by lazy { Realm.open(realmAppSettingsConfiguration) } val realmUploads by lazy { Realm.open(realmUploadConfiguration) } var realmTransfers: Realm? = null private set - fun openRealmTransfers(userId: Int, inMemory: Boolean = false) { - realmTransfers = Realm.open(realmTransfersConfiguration(userId, inMemory)) + fun openRealmTransfers(userId: Int) { + realmTransfers = Realm.open(realmTransfersConfiguration(userId)) } fun closeRealmAppSettings() { @@ -57,18 +57,24 @@ class RealmProvider { private val realmAppSettingsConfiguration = RealmConfiguration .Builder(schema = setOf(AppSettingsDB::class)) .name("AppSettings") + .loadDataInMemoryIfNeeded() .build() private val realmUploadConfiguration = RealmConfiguration .Builder(schema = setOf(Upload::class)) .name("Uploads") + .loadDataInMemoryIfNeeded() .build() - private fun realmTransfersConfiguration(userId: Int, inMemory: Boolean) = RealmConfiguration + private fun realmTransfersConfiguration(userId: Int) = RealmConfiguration .Builder(schema = setOf(TransferDB::class, ContainerDB::class, FileDB::class)) .name(transferRealmName(userId)) - .apply { if (inMemory) inMemory() } + .loadDataInMemoryIfNeeded() .build() private fun transferRealmName(userId: Int) = "Transfers-$userId" + + private fun RealmConfiguration.Builder.loadDataInMemoryIfNeeded(): RealmConfiguration.Builder { + return apply { if (loadDataInMemory) inMemory() } + } } diff --git a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt index 413b3bce..c6a6e247 100644 --- a/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt +++ b/STDatabase/src/commonTest/kotlin/com/infomaniak/multiplatform_swisstransfer/database/TransferControllerTest.kt @@ -31,7 +31,7 @@ class TransferControllerTest { @BeforeTest fun setup() { - realmProvider = RealmProvider().apply { openRealmTransfers(userId = 0, inMemory = true) } + realmProvider = RealmProvider(loadDataInMemory = true).apply { openRealmTransfers(userId = 0) } transferController = TransferController(realmProvider) }