Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ import com.wire.kalium.cells.domain.model.Node
import kotlinx.coroutines.flow.Flow

public interface GetPaginatedFilesFlowUseCase {
/**
* Use case to get a paginated flow of file [Node]s from cells.
* @param conversationId The unique identifier of the conversation to filter files by (optional).
* @param query The search query to filter files.
* @param onlyDeleted Flag to indicate whether to fetch only deleted files.
* @param tags List of tags to filter files.
* @return a flow of paginated file nodes.
*/
public suspend operator fun invoke(
conversationId: String?,
query: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.map

public interface CreateFolderUseCase {
/**
* Use case to create a folder [com.wire.kalium.cells.domain.model.Node] at the specified path.
* @param path The path where the folder should be created.
* @return the result of the create folder operation.
*/
public suspend operator fun invoke(path: String): Either<CoreFailure, Unit>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,20 @@ import com.wire.kalium.util.KaliumDispatcherImpl
import kotlinx.coroutines.withContext
import okio.Path

/**
* Download an asset file from the wire cell server.
*/
public interface DownloadCellFileUseCase {
/**
* Download an asset file from the wire cell server.
* The asset transfer status is updated in the database.
* The local path of the downloaded file is saved in the database.
*
* @param assetId The uuid of the cell asset to download.
* @param outFilePath The path to save the downloaded file.
* @param onProgressUpdate Callback to receive download progress updates.
* @return download operation result
*/
public suspend operator fun invoke(
assetId: String,
outFilePath: Path,
Expand All @@ -41,24 +54,11 @@ public interface DownloadCellFileUseCase {
): Either<CoreFailure, Unit>
}

/**
* Download an asset file from the wire cell server.
*/
internal class DownloadCellFileUseCaseImpl internal constructor(
private val cellsRepository: CellsRepository,
private val attachmentsRepository: CellAttachmentsRepository,
private val dispatchers: KaliumDispatcher = KaliumDispatcherImpl,
) : DownloadCellFileUseCase {
/**
* Download an asset file from the wire cell server.
* The asset transfer status is updated in the database.
* The local path of the downloaded file is saved in the database.
*
* @param assetId The uuid of the cell asset to download.
* @param outFilePath The path to save the downloaded file.
* @param onProgressUpdate Callback to receive download progress updates.
* @return download operation result
*/
override suspend operator fun invoke(
assetId: String,
outFilePath: Path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.map

public interface GetCellFileUseCase {
/**
* Use case to get a [com.wire.kalium.cells.domain.model.Node] from cells by its asset ID.
* @param assetId The unique asset identifier of the file.
* @return the result of the get file operation.
*/
public suspend operator fun invoke(assetId: String): Either<CoreFailure, Node.File>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ import com.wire.kalium.cells.domain.paging.FilePagingSource
import kotlinx.coroutines.flow.Flow

public interface GetCellFilesPagedUseCase {
/**
* Use case to get paged files from a cell, optionally filtered by conversation ID, search query,
* deletion status, and tags.
*
* @param conversationId The ID of the conversation to filter files by (optional).
* @param query The search query to filter files.
* @param onlyDeleted Whether to include only deleted files.
* @param tags A list of tags to filter files by.
* @return A flow of paged data containing the filtered files.
*/
public suspend operator fun invoke(
conversationId: String?,
query: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.map

public fun interface GetEditorUrlUseCase {
/**
* Use case to get the editor URL for a given [com.wire.kalium.cells.domain.model.Node].
* @param nodeUuid The unique identifier of the node.
* @return the result of the get editor URL operation, or null if no URL is available.
*/
public suspend operator fun invoke(nodeUuid: String): Either<CoreFailure, String?>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.map

public interface GetFoldersUseCase {
/**
* Use case to get folders [com.wire.kalium.cells.domain.model.Node]s within a specific conversation.
* @param conversationId The unique identifier of the conversation.
* @return the result of the rename operation.
*/
public suspend operator fun invoke(
conversationId: String,
): Either<CoreFailure, List<Node.Folder>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.map

public interface MoveNodeUseCase {
/**
* Use case to move a [com.wire.kalium.cells.domain.model.Node] from one path to another within a specific cell.
* @param uuid The unique identifier of the cell.
* @param path The current path of the node to be moved.
* @param targetPath The target path where the node should be moved.
* @return the result of the rename operation.
*/
public suspend operator fun invoke(uuid: String, path: String, targetPath: String): Either<CoreFailure, Unit>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ import com.wire.kalium.common.functional.left
import com.wire.kalium.common.functional.mapLeft

public interface RenameNodeUseCase {
/**
* Use case to rename a [com.wire.kalium.cells.domain.model.Node] within a specific cell.
* @param uuid The unique identifier of the cell.
* @param path The current path of the node to be renamed.
* @param newName The new name for the node.
* @return the result of the rename operation.
*/
public suspend operator fun invoke(uuid: String, path: String, newName: String): Either<RenameNodeFailure, Unit>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import com.wire.kalium.logic.data.asset.AssetTransferStatus
import com.wire.kalium.logic.data.message.CellAssetContent

public interface RestoreNodeFromRecycleBinUseCase {
/**
* Restore a [com.wire.kalium.cells.domain.model.Node] from the recycle bin.
* @param uuid The unique identifier of the node to be restored.
* @return the result of the restore operation.
*/
public suspend operator fun invoke(uuid: String): Either<CoreFailure, Unit>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import com.wire.kalium.cells.domain.CellsRepository
import com.wire.kalium.common.functional.getOrNull

public interface GetPublicLinkPasswordUseCase {
/**
* Use case to get the password of a public link.
* @param linkUuid The unique identifier of the public link.
* @return the password of the public link, or null if it doesn't have one.
*/
public suspend operator fun invoke(linkUuid: String): String?
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ import com.wire.kalium.common.error.CoreFailure
import com.wire.kalium.common.functional.Either

public interface GetNodeVersionsUseCase {
/**
* Use case to get the versions of a [com.wire.kalium.cells.domain.model.Node] within a specific cell.
* @param uuid The unique identifier of the cell.
* @return the result of the get node versions operation.
*/
public suspend operator fun invoke(uuid: String): Either<CoreFailure, List<NodeVersion>>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,31 @@
package com.wire.kalium.logic.feature.asset

import com.wire.kalium.common.error.CoreFailure
import com.wire.kalium.common.functional.Either
import com.wire.kalium.common.functional.fold
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.message.MessageRepository
import com.wire.kalium.util.KaliumDispatcher
import com.wire.kalium.util.KaliumDispatcherImpl
import kotlinx.coroutines.withContext

public sealed class UpdateAudioMessageNormalizedLoudnessResult {
public object Success : UpdateAudioMessageNormalizedLoudnessResult()
public data class Failure(val error: CoreFailure) : UpdateAudioMessageNormalizedLoudnessResult()
}

public interface UpdateAudioMessageNormalizedLoudnessUseCase {
/**
* Updates the audio waves mask for a given message in a conversation.
* @param conversationId The ID of the conversation containing the message.
* @param messageId The ID of the message to update.
* @param normalizedLoudness The new normalized loudness data to set.
* @return Either a CoreFailure on failure or Unit on success.
* @return [UpdateAudioMessageNormalizedLoudnessResult] indicating success or failure of the operation.
*/
public suspend operator fun invoke(
conversationId: ConversationId,
messageId: String,
normalizedLoudness: ByteArray
): Either<CoreFailure, Unit>
): UpdateAudioMessageNormalizedLoudnessResult
}

internal class UpdateAudioMessageNormalizedLoudnessUseCaseImpl(
Expand All @@ -48,11 +53,14 @@ internal class UpdateAudioMessageNormalizedLoudnessUseCaseImpl(
conversationId: ConversationId,
messageId: String,
normalizedLoudness: ByteArray
): Either<CoreFailure, Unit> = withContext(dispatcher.io) {
): UpdateAudioMessageNormalizedLoudnessResult = withContext(dispatcher.io) {
messageRepository.updateAudioMessageNormalizedLoudness(
conversationId = conversationId,
messageId = messageId,
normalizedLoudness = normalizedLoudness
).fold(
{ error -> UpdateAudioMessageNormalizedLoudnessResult.Failure(error) },
{ UpdateAudioMessageNormalizedLoudnessResult.Success }
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal class GetConversationUseCase(
internal data class Failure(val storageFailure: StorageFailure) : Result()
}

internal suspend operator fun invoke(conversationId: QualifiedID): Flow<Result> {
suspend operator fun invoke(conversationId: QualifiedID): Flow<Result> {
return conversationRepository.observeConversationById(conversationId)
.map { it.fold({ Result.Failure(it) }, { Result.Success(it) }) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal class VerifyActivationCodeUseCase internal constructor(
* @param code [String] the activation code to validate
* @return [VerifyActivationCodeResult.Success] or [VerifyActivationCodeResult.Failure] with the specific error.
*/
internal suspend operator fun invoke(email: String, code: String): VerifyActivationCodeResult =
suspend operator fun invoke(email: String, code: String): VerifyActivationCodeResult =
registerAccountRepository.verifyActivationCode(email, code)
.fold({
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,49 @@
package com.wire.kalium.logic.architecture

import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.returnTypes
import com.lemonappdev.konsist.api.ext.list.withNameEndingWith
import com.lemonappdev.konsist.api.ext.list.withParentNamed
import com.lemonappdev.konsist.api.verify.assertTrue
import kotlin.test.Ignore
import org.junit.Ignore
import kotlin.test.Test

class UseCaseRulesTest {

@Ignore("Ignored for now, needs fine tune and violations fixed which are quite many currently for this scope")
@Test
fun classesWithUseCaseSuffixShouldResideInFeaturePackage() {
Konsist.scopeFromProduction()
fun everyUseCasePublicInterfaceShouldNotReturnEitherTypes() {
Konsist
.scopeFromProduction()
.interfaces()
.withNameEndingWith("UseCase")
.filter { it.hasPublicOrDefaultModifier }
.assertTrue { anInterface ->
val hasEitherReturnType = anInterface.functions().filter { it.hasPublicOrDefaultModifier }
.returnTypes
.any { returnType ->
returnType.sourceType.startsWith("Either<")
}
!hasEitherReturnType
}
}

@Ignore("Ignored for now, needs fine tune and violations fixed which are quite many currently for this scope")
@Test
fun everyUseCasePublicClassShouldNotReturnEitherTypes() {
Konsist
.scopeFromProduction()
.classes()
.withNameEndingWith("UseCase")
.assertTrue { it.resideInPackage("..feature..") }
.filter { it.hasPublicOrDefaultModifier }
.assertTrue {
val hasEitherReturnType = it.functions().returnTypes
.any { returnType ->
returnType.sourceType.startsWith("Either<")
}
!hasEitherReturnType
}
}

@Ignore
@Test
fun classesWithUseCaseSuffixShouldHaveSinglePublicOperatorFunctionCalledInvoke() {
Konsist
Expand All @@ -50,22 +76,54 @@ class UseCaseRulesTest {
}
}

@Ignore("Ignored for now, needs fine tune and violations fixed which are quite many currently for this scope")
@Test
fun everyUseCaseClassHasTests() {
Konsist
.scopeFromProduction()
.classes()
.withParentNamed("UseCase")
.assertTrue { it.hasTestClass() }
.withNameEndingWith(suffixes = listOf("UseCaseImpl", "UseCase"))
.assertTrue { clazz ->
// For UseCaseImpl classes, test should be named UseCaseTest (without Impl)
// For standalone UseCase classes, test should be named UseCaseTest
val expectedTestName = if (clazz.name.endsWith("Impl")) {
clazz.name.removeSuffix("Impl") + "Test"
} else {
"${clazz.name}Test"
}

// Check if a test file exists with the expected test class name
Konsist
.scopeFromTest()
.classes()
.any { testClass -> testClass.name == expectedTestName }
}
}

@Test
fun everyUseCaseClassHasKDocs() {
fun everyPublicUseCaseInterfaceHasKDocs() {
Konsist
.scopeFromProduction()
.interfaces()
.withNameEndingWith("UseCase")
.filter { it.hasPublicOrDefaultModifier }
.assertTrue { useCase ->
useCase.hasKDoc || useCase.functions()
.any { func -> func.name == "invoke" && func.hasOperatorModifier && func.hasKDoc }
}
}

@Test
fun everyPublicUseCaseClassHasKDocs() {
Konsist
.scopeFromProduction()
.classes()
.withParentNamed("UseCase")
.assertTrue { it.hasKDoc }
.withNameEndingWith("UseCase")
.filter { it.hasPublicOrDefaultModifier }
.assertTrue { useCase ->
useCase.hasKDoc || useCase.functions()
.any { func -> func.name == "invoke" && func.hasOperatorModifier && func.hasKDoc }
}
}

@Test
Expand Down
Loading