Skip to content

Commit 78a025e

Browse files
authored
Refactor usecases (#7)
* refactor: removed superfluous class WorkResult.kt and use Result.kt instead. Renamed all "Get...UseCase" to "Fetch....UseCase". Moved ui state loading logic into ViewModels. Updated unit tests. * refactor: Unified use cases for background work. Replaced SuspendUseCase.kt and ParamsSuspendUseCase.kt with BaseSuspendUseCase.kt
1 parent 4d2444a commit 78a025e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+743
-850
lines changed

app/src/main/kotlin/de/entikore/composedex/domain/WorkResult.kt

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,22 +17,19 @@ package de.entikore.composedex.domain.usecase
1717

1818
import de.entikore.composedex.domain.model.preferences.AppThemeConfig
1919
import de.entikore.composedex.domain.repository.AppSettingsRepository
20-
import de.entikore.composedex.domain.usecase.base.ParamsSuspendUseCase
20+
import de.entikore.composedex.domain.usecase.base.BaseSuspendUseCase
2121
import kotlinx.coroutines.CoroutineDispatcher
2222
import kotlinx.coroutines.Dispatchers
23-
import kotlinx.coroutines.withContext
2423
import javax.inject.Inject
2524

2625
/**
2726
* This use case changes the app theme between light and dark mode.
2827
*/
2928
class ChangeLightDarkThemeUseCase @Inject constructor(
3029
private val repository: AppSettingsRepository,
31-
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
32-
) : ParamsSuspendUseCase<AppThemeConfig, Unit>() {
33-
override suspend operator fun invoke(params: AppThemeConfig) {
34-
withContext(ioDispatcher) {
35-
repository.setTheme(params)
36-
}
37-
}
30+
dispatcher: CoroutineDispatcher = Dispatchers.IO
31+
) : BaseSuspendUseCase<AppThemeConfig, Unit>(dispatcher) {
32+
33+
override suspend fun execute(params: AppThemeConfig) =
34+
repository.setTheme(params)
3835
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/ChangeTypeThemeUseCase.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,22 +18,19 @@ package de.entikore.composedex.domain.usecase
1818
import de.entikore.composedex.domain.model.pokemon.Pokemon
1919
import de.entikore.composedex.domain.model.preferences.TypeThemeConfig
2020
import de.entikore.composedex.domain.repository.AppSettingsRepository
21-
import de.entikore.composedex.domain.usecase.base.ParamsSuspendUseCase
21+
import de.entikore.composedex.domain.usecase.base.BaseSuspendUseCase
2222
import kotlinx.coroutines.CoroutineDispatcher
2323
import kotlinx.coroutines.Dispatchers
24-
import kotlinx.coroutines.withContext
2524
import javax.inject.Inject
2625

2726
/**
2827
* This use case changes the app theme, to match the color palette with the type of the [Pokemon].
2928
*/
3029
class ChangeTypeThemeUseCase @Inject constructor(
3130
private val repository: AppSettingsRepository,
32-
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
33-
) : ParamsSuspendUseCase<String, Unit>() {
34-
override suspend operator fun invoke(params: String) {
35-
withContext(ioDispatcher) {
36-
repository.setTypeTheme(TypeThemeConfig.fromTypeString(params))
37-
}
38-
}
31+
dispatcher: CoroutineDispatcher = Dispatchers.IO
32+
) : BaseSuspendUseCase<String, Unit>(dispatcher) {
33+
34+
override suspend fun execute(params: String) =
35+
repository.setTypeTheme(TypeThemeConfig.fromTypeString(params))
3936
}
Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,27 +18,24 @@ package de.entikore.composedex.domain.usecase
1818
import android.content.Context
1919
import dagger.hilt.android.qualifiers.ApplicationContext
2020
import de.entikore.composedex.domain.repository.LocalStorage
21-
import de.entikore.composedex.domain.usecase.base.SuspendUseCase
21+
import de.entikore.composedex.domain.usecase.base.BaseSuspendUseCase
2222
import kotlinx.coroutines.CoroutineDispatcher
2323
import kotlinx.coroutines.Dispatchers
24-
import kotlinx.coroutines.withContext
2524

2625
/**
2726
* This use case deletes all stored data from the local storage.
2827
*/
2928
class DeleteLocalDataUseCase(
3029
@ApplicationContext private val context: Context,
3130
private val localStorage: LocalStorage,
32-
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
33-
) : SuspendUseCase<Unit>() {
31+
dispatcher: CoroutineDispatcher = Dispatchers.IO
32+
) : BaseSuspendUseCase<Unit, Unit>(dispatcher) {
3433

35-
override suspend operator fun invoke() {
36-
withContext(ioDispatcher) {
37-
val files = context.fileList()
38-
for (file in files) {
39-
context.deleteFile(file)
40-
}
41-
localStorage.clearData()
34+
override suspend fun execute(params: Unit) {
35+
val files = context.fileList()
36+
for (file in files) {
37+
context.deleteFile(file)
4238
}
39+
localStorage.clearData()
4340
}
4441
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/GetFavouritesUseCase.kt renamed to app/src/main/kotlin/de/entikore/composedex/domain/usecase/FetchFavouritesUseCase.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,21 +15,23 @@
1515
*/
1616
package de.entikore.composedex.domain.usecase
1717

18-
import de.entikore.composedex.domain.WorkResult
19-
import de.entikore.composedex.domain.asWorkResult
2018
import de.entikore.composedex.domain.model.pokemon.Pokemon
2119
import de.entikore.composedex.domain.repository.FavouriteRepository
22-
import de.entikore.composedex.domain.usecase.base.UseCase
23-
import kotlinx.coroutines.flow.Flow
20+
import de.entikore.composedex.domain.usecase.base.BaseFetchUseCase
21+
import de.entikore.composedex.domain.util.asResult
22+
import kotlinx.coroutines.CoroutineDispatcher
23+
import kotlinx.coroutines.Dispatchers
2424
import kotlinx.coroutines.flow.distinctUntilChanged
2525
import javax.inject.Inject
2626

2727
/**
2828
* This use case returns the latest as favourites marked Pokemon.
2929
*/
30-
class GetFavouritesUseCase @Inject constructor(private val repository: FavouriteRepository) :
31-
UseCase<Flow<WorkResult<List<Pokemon>>>>() {
32-
33-
override operator fun invoke() = repository.getFavourites().distinctUntilChanged()
34-
.asWorkResult()
30+
@Suppress("TooGenericExceptionCaught")
31+
class FetchFavouritesUseCase @Inject constructor(
32+
private val repository: FavouriteRepository,
33+
dispatcher: CoroutineDispatcher = Dispatchers.IO
34+
) :
35+
BaseFetchUseCase<Unit, List<Pokemon>>(dispatcher) {
36+
override fun execute(params: Unit) = repository.getFavourites().distinctUntilChanged().asResult()
3537
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/GetGenerationUseCase.kt renamed to app/src/main/kotlin/de/entikore/composedex/domain/usecase/FetchGenerationUseCase.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,28 +15,32 @@
1515
*/
1616
package de.entikore.composedex.domain.usecase
1717

18-
import de.entikore.composedex.domain.WorkResult
19-
import de.entikore.composedex.domain.asWorkResult
2018
import de.entikore.composedex.domain.model.generation.Generation
2119
import de.entikore.composedex.domain.repository.GenerationRepository
22-
import de.entikore.composedex.domain.usecase.base.ParamsUseCase
20+
import de.entikore.composedex.domain.usecase.base.BaseFetchUseCase
21+
import de.entikore.composedex.domain.util.asResult
22+
import kotlinx.coroutines.CoroutineDispatcher
23+
import kotlinx.coroutines.Dispatchers
2324
import kotlinx.coroutines.flow.Flow
2425
import kotlinx.coroutines.flow.distinctUntilChanged
2526
import javax.inject.Inject
2627

2728
/**
2829
* This use case returns the latest [Generation] of the provided name or id.
2930
*/
30-
class GetGenerationUseCase @Inject constructor(private val repository: GenerationRepository) :
31-
ParamsUseCase<String, Flow<WorkResult<Generation>>>() {
31+
class FetchGenerationUseCase @Inject constructor(
32+
private val repository: GenerationRepository,
33+
dispatcher: CoroutineDispatcher = Dispatchers.IO
34+
) :
35+
BaseFetchUseCase<String, Generation>(dispatcher) {
3236

33-
override operator fun invoke(params: String): Flow<WorkResult<Generation>> {
37+
override fun execute(params: String): Flow<Result<Generation>> {
3438
val id = params.trim().toIntOrNull()
3539
return if (id != null) {
36-
repository.getGenerationById(id).distinctUntilChanged().asWorkResult()
40+
repository.getGenerationById(id).distinctUntilChanged().asResult()
3741
} else {
3842
val normalizedParams = params.lowercase().trim()
39-
repository.getGenerationByName(normalizedParams).distinctUntilChanged().asWorkResult()
43+
repository.getGenerationByName(normalizedParams).distinctUntilChanged().asResult()
4044
}
4145
}
4246
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/GetGenerationsUseCase.kt renamed to app/src/main/kotlin/de/entikore/composedex/domain/usecase/FetchGenerationsUseCase.kt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,20 +15,23 @@
1515
*/
1616
package de.entikore.composedex.domain.usecase
1717

18-
import de.entikore.composedex.domain.WorkResult
19-
import de.entikore.composedex.domain.asWorkResult
2018
import de.entikore.composedex.domain.model.generation.Generation
2119
import de.entikore.composedex.domain.repository.GenerationRepository
22-
import de.entikore.composedex.domain.usecase.base.UseCase
23-
import kotlinx.coroutines.flow.Flow
20+
import de.entikore.composedex.domain.usecase.base.BaseFetchUseCase
21+
import de.entikore.composedex.domain.util.asResult
22+
import kotlinx.coroutines.CoroutineDispatcher
23+
import kotlinx.coroutines.Dispatchers
2424
import kotlinx.coroutines.flow.distinctUntilChanged
2525
import javax.inject.Inject
2626

2727
/**
2828
* This use case returns the latest list of all [Generation].
2929
*/
30-
class GetGenerationsUseCase @Inject constructor(private val repository: GenerationRepository) :
31-
UseCase<Flow<WorkResult<List<Generation>>>>() {
32-
override operator fun invoke() =
33-
repository.getGenerations().distinctUntilChanged().asWorkResult()
30+
class FetchGenerationsUseCase @Inject constructor(
31+
private val repository: GenerationRepository,
32+
dispatcher: CoroutineDispatcher = Dispatchers.IO
33+
) :
34+
BaseFetchUseCase<Unit, List<Generation>>(dispatcher) {
35+
override fun execute(params: Unit) =
36+
repository.getGenerations().distinctUntilChanged().asResult()
3437
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/GetPokemonOfGenerationUseCase.kt renamed to app/src/main/kotlin/de/entikore/composedex/domain/usecase/FetchPokemonOfGenerationUseCase.kt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,12 +15,13 @@
1515
*/
1616
package de.entikore.composedex.domain.usecase
1717

18-
import de.entikore.composedex.domain.WorkResult
19-
import de.entikore.composedex.domain.asWorkResult
2018
import de.entikore.composedex.domain.model.generation.Generation
2119
import de.entikore.composedex.domain.model.pokemon.Pokemon
2220
import de.entikore.composedex.domain.repository.GenerationRepository
23-
import de.entikore.composedex.domain.usecase.base.ParamsUseCase
21+
import de.entikore.composedex.domain.usecase.base.BaseFetchUseCase
22+
import de.entikore.composedex.domain.util.asResult
23+
import kotlinx.coroutines.CoroutineDispatcher
24+
import kotlinx.coroutines.Dispatchers
2425
import kotlinx.coroutines.flow.Flow
2526
import kotlinx.coroutines.flow.distinctUntilChanged
2627
import javax.inject.Inject
@@ -29,17 +30,17 @@ import javax.inject.Inject
2930
* This use case returns the latest list of [Pokemon] belonging to the [Generation]
3031
* of the provided name or id.
3132
*/
32-
class GetPokemonOfGenerationUseCase @Inject constructor(
33-
private val repository: GenerationRepository
34-
) : ParamsUseCase<String, Flow<WorkResult<List<Pokemon>>>>() {
35-
override operator fun invoke(params: String): Flow<WorkResult<List<Pokemon>>> {
33+
class FetchPokemonOfGenerationUseCase @Inject constructor(
34+
private val repository: GenerationRepository,
35+
dispatcher: CoroutineDispatcher = Dispatchers.IO
36+
) : BaseFetchUseCase<String, List<Pokemon>>(dispatcher) {
37+
override fun execute(params: String): Flow<Result<List<Pokemon>>> {
3638
val id = params.trim().toIntOrNull()
3739
return if (id != null) {
38-
repository.getPokemonOfGenerationById(id).distinctUntilChanged().asWorkResult()
40+
repository.getPokemonOfGenerationById(id).distinctUntilChanged().asResult()
3941
} else {
4042
val normalizedParams = params.lowercase().trim()
41-
repository.getPokemonOfGenerationByName(normalizedParams).distinctUntilChanged()
42-
.asWorkResult()
43+
repository.getPokemonOfGenerationByName(normalizedParams).distinctUntilChanged().asResult()
4344
}
4445
}
4546
}

app/src/main/kotlin/de/entikore/composedex/domain/usecase/GetPokemonOfTypeUseCase.kt renamed to app/src/main/kotlin/de/entikore/composedex/domain/usecase/FetchPokemonOfTypeUseCase.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Entikore
2+
* Copyright 2025 Entikore
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,23 +15,25 @@
1515
*/
1616
package de.entikore.composedex.domain.usecase
1717

18-
import de.entikore.composedex.domain.WorkResult
19-
import de.entikore.composedex.domain.asWorkResult
2018
import de.entikore.composedex.domain.model.pokemon.Pokemon
2119
import de.entikore.composedex.domain.model.type.Type
2220
import de.entikore.composedex.domain.repository.TypeRepository
23-
import de.entikore.composedex.domain.usecase.base.ParamsUseCase
24-
import kotlinx.coroutines.flow.Flow
21+
import de.entikore.composedex.domain.usecase.base.BaseFetchUseCase
22+
import de.entikore.composedex.domain.util.asResult
23+
import kotlinx.coroutines.CoroutineDispatcher
24+
import kotlinx.coroutines.Dispatchers
2525
import kotlinx.coroutines.flow.distinctUntilChanged
2626
import javax.inject.Inject
2727

2828
/**
2929
* This use case returns the latest list of [Pokemon] belonging to the [Type]
3030
* of the provided name.
3131
*/
32-
class GetPokemonOfTypeUseCase @Inject constructor(private val repository: TypeRepository) :
33-
ParamsUseCase<String, Flow<WorkResult<List<Pokemon>>>>() {
34-
35-
override operator fun invoke(params: String): Flow<WorkResult<List<Pokemon>>> =
36-
repository.getPokemonOfType(params).distinctUntilChanged().asWorkResult()
32+
class FetchPokemonOfTypeUseCase @Inject constructor(
33+
private val repository: TypeRepository,
34+
dispatcher: CoroutineDispatcher = Dispatchers.IO
35+
) :
36+
BaseFetchUseCase<String, List<Pokemon>>(dispatcher) {
37+
override fun execute(params: String) =
38+
repository.getPokemonOfType(params).distinctUntilChanged().asResult()
3739
}

0 commit comments

Comments
 (0)