Replace Timber with Logger
This commit is contained in:
@@ -18,7 +18,9 @@ class AddRecipeDataSourceImpl @Inject constructor(
|
||||
logger.v { "addRecipe() called with: recipe = $recipe" }
|
||||
val service = addRecipeServiceFactory.provideService()
|
||||
val response = logAndMapErrors(
|
||||
block = { service.addRecipe(recipe) }, logProvider = { "addRecipe: can't add recipe" }
|
||||
logger,
|
||||
block = { service.addRecipe(recipe) },
|
||||
logProvider = { "addRecipe: can't add recipe" }
|
||||
)
|
||||
logger.v { "addRecipe() response = $response" }
|
||||
return response
|
||||
|
||||
@@ -8,10 +8,10 @@ import gq.kirmanak.mealient.data.add.models.AddRecipeRequest
|
||||
import gq.kirmanak.mealient.data.add.models.AddRecipeSettings
|
||||
import gq.kirmanak.mealient.datastore.recipe.AddRecipeDraft
|
||||
import gq.kirmanak.mealient.datastore.recipe.AddRecipeStorage
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -19,6 +19,7 @@ import javax.inject.Singleton
|
||||
class AddRecipeRepoImpl @Inject constructor(
|
||||
private val addRecipeDataSource: AddRecipeDataSource,
|
||||
private val addRecipeStorage: AddRecipeStorage,
|
||||
private val logger: Logger,
|
||||
) : AddRecipeRepo {
|
||||
|
||||
override val addRecipeRequestFlow: Flow<AddRecipeRequest>
|
||||
@@ -37,7 +38,7 @@ class AddRecipeRepoImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun preserve(recipe: AddRecipeRequest) {
|
||||
Timber.v("preserveRecipe() called with: recipe = $recipe")
|
||||
logger.v { "preserveRecipe() called with: recipe = $recipe" }
|
||||
val input = AddRecipeDraft(
|
||||
recipeName = recipe.name,
|
||||
recipeDescription = recipe.description,
|
||||
@@ -51,12 +52,12 @@ class AddRecipeRepoImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun clear() {
|
||||
Timber.v("clear() called")
|
||||
logger.v { "clear() called" }
|
||||
addRecipeStorage.clear()
|
||||
}
|
||||
|
||||
override suspend fun saveRecipe(): String {
|
||||
Timber.v("saveRecipe() called")
|
||||
logger.v { "saveRecipe() called" }
|
||||
return addRecipeDataSource.addRecipe(addRecipeRequestFlow.first())
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,10 @@ import gq.kirmanak.mealient.data.network.NetworkError.Unauthorized
|
||||
import gq.kirmanak.mealient.data.network.ServiceFactory
|
||||
import gq.kirmanak.mealient.extensions.decodeErrorBodyOrNull
|
||||
import gq.kirmanak.mealient.extensions.logAndMapErrors
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.serialization.json.Json
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -18,14 +18,15 @@ import javax.inject.Singleton
|
||||
class AuthDataSourceImpl @Inject constructor(
|
||||
private val authServiceFactory: ServiceFactory<AuthService>,
|
||||
private val json: Json,
|
||||
private val logger: Logger,
|
||||
) : AuthDataSource {
|
||||
|
||||
override suspend fun authenticate(username: String, password: String): String {
|
||||
Timber.v("authenticate() called with: username = $username, password = $password")
|
||||
logger.v { "authenticate() called with: username = $username, password = $password" }
|
||||
val authService = authServiceFactory.provideService()
|
||||
val response = sendRequest(authService, username, password)
|
||||
val accessToken = parseToken(response)
|
||||
Timber.v("authenticate() returned: $accessToken")
|
||||
logger.v { "authenticate() returned: $accessToken" }
|
||||
return accessToken
|
||||
}
|
||||
|
||||
@@ -34,6 +35,7 @@ class AuthDataSourceImpl @Inject constructor(
|
||||
username: String,
|
||||
password: String
|
||||
): Response<GetTokenResponse> = logAndMapErrors(
|
||||
logger,
|
||||
block = { authService.getToken(username = username, password = password) },
|
||||
logProvider = { "sendRequest: can't get token" },
|
||||
)
|
||||
@@ -44,7 +46,7 @@ class AuthDataSourceImpl @Inject constructor(
|
||||
response.body()?.accessToken ?: throw NotMealie(NullPointerException("Body is null"))
|
||||
} else {
|
||||
val cause = HttpException(response)
|
||||
val errorDetail: ErrorDetail? = response.decodeErrorBodyOrNull(json)
|
||||
val errorDetail: ErrorDetail? = response.decodeErrorBodyOrNull(json, logger)
|
||||
throw when (errorDetail?.detail) {
|
||||
"Unauthorized" -> Unauthorized(cause)
|
||||
else -> NotMealie(cause)
|
||||
|
||||
@@ -4,9 +4,9 @@ import gq.kirmanak.mealient.data.auth.AuthDataSource
|
||||
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -14,13 +14,14 @@ import javax.inject.Singleton
|
||||
class AuthRepoImpl @Inject constructor(
|
||||
private val authStorage: AuthStorage,
|
||||
private val authDataSource: AuthDataSource,
|
||||
private val logger: Logger,
|
||||
) : AuthRepo {
|
||||
|
||||
override val isAuthorizedFlow: Flow<Boolean>
|
||||
get() = authStorage.authHeaderFlow.map { it != null }
|
||||
|
||||
override suspend fun authenticate(email: String, password: String) {
|
||||
Timber.v("authenticate() called with: email = $email, password = $password")
|
||||
logger.v { "authenticate() called with: email = $email, password = $password" }
|
||||
authDataSource.authenticate(email, password)
|
||||
.let { AUTH_HEADER_FORMAT.format(it) }
|
||||
.let { authStorage.setAuthHeader(it) }
|
||||
@@ -35,14 +36,14 @@ class AuthRepoImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun logout() {
|
||||
Timber.v("logout() called")
|
||||
logger.v { "logout() called" }
|
||||
authStorage.setEmail(null)
|
||||
authStorage.setPassword(null)
|
||||
authStorage.setAuthHeader(null)
|
||||
}
|
||||
|
||||
override suspend fun invalidateAuthHeader() {
|
||||
Timber.v("invalidateAuthHeader() called")
|
||||
logger.v { "invalidateAuthHeader() called" }
|
||||
val email = authStorage.getEmail() ?: return
|
||||
val password = authStorage.getPassword() ?: return
|
||||
runCatchingExceptCancel { authenticate(email, password) }
|
||||
|
||||
@@ -6,11 +6,11 @@ import androidx.core.content.edit
|
||||
import gq.kirmanak.mealient.data.auth.AuthStorage
|
||||
import gq.kirmanak.mealient.datastore.DataStoreModule.Companion.ENCRYPTED
|
||||
import gq.kirmanak.mealient.extensions.prefsChangeFlow
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.Executors
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
@@ -19,11 +19,12 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AuthStorageImpl @Inject constructor(
|
||||
@Named(ENCRYPTED) private val sharedPreferences: SharedPreferences,
|
||||
private val logger: Logger,
|
||||
) : AuthStorage {
|
||||
|
||||
override val authHeaderFlow: Flow<String?>
|
||||
get() = sharedPreferences
|
||||
.prefsChangeFlow { getString(AUTH_HEADER_KEY, null) }
|
||||
.prefsChangeFlow(logger) { getString(AUTH_HEADER_KEY, null) }
|
||||
.distinctUntilChanged()
|
||||
private val singleThreadDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
|
||||
@@ -43,13 +44,13 @@ class AuthStorageImpl @Inject constructor(
|
||||
key: String,
|
||||
value: String?
|
||||
) = withContext(singleThreadDispatcher) {
|
||||
Timber.v("putString() called with: key = $key, value = $value")
|
||||
logger.v { "putString() called with: key = $key, value = $value" }
|
||||
sharedPreferences.edit(commit = true) { putString(key, value) }
|
||||
}
|
||||
|
||||
private suspend fun getString(key: String) = withContext(singleThreadDispatcher) {
|
||||
val result = sharedPreferences.getString(key, null)
|
||||
Timber.v("getString() called with: key = $key, returned: $result")
|
||||
logger.v { "getString() called with: key = $key, returned: $result" }
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,22 @@ import gq.kirmanak.mealient.data.baseurl.VersionInfo
|
||||
import gq.kirmanak.mealient.data.network.ServiceFactory
|
||||
import gq.kirmanak.mealient.extensions.logAndMapErrors
|
||||
import gq.kirmanak.mealient.extensions.versionInfo
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class VersionDataSourceImpl @Inject constructor(
|
||||
private val serviceFactory: ServiceFactory<VersionService>,
|
||||
private val logger: Logger,
|
||||
) : VersionDataSource {
|
||||
|
||||
override suspend fun getVersionInfo(baseUrl: String): VersionInfo {
|
||||
Timber.v("getVersionInfo() called with: baseUrl = $baseUrl")
|
||||
logger.v { "getVersionInfo() called with: baseUrl = $baseUrl" }
|
||||
|
||||
val service = serviceFactory.provideService(baseUrl)
|
||||
val response = logAndMapErrors(
|
||||
logger,
|
||||
block = { service.getVersion() },
|
||||
logProvider = { "getVersionInfo: can't request version" }
|
||||
)
|
||||
|
||||
@@ -2,15 +2,16 @@ package gq.kirmanak.mealient.data.disclaimer
|
||||
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import gq.kirmanak.mealient.data.storage.PreferencesStorage
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class DisclaimerStorageImpl @Inject constructor(
|
||||
private val preferencesStorage: PreferencesStorage,
|
||||
private val logger: Logger,
|
||||
) : DisclaimerStorage {
|
||||
|
||||
private val isDisclaimerAcceptedKey: Preferences.Key<Boolean>
|
||||
@@ -19,14 +20,14 @@ class DisclaimerStorageImpl @Inject constructor(
|
||||
get() = preferencesStorage.valueUpdates(isDisclaimerAcceptedKey).map { it == true }
|
||||
|
||||
override suspend fun isDisclaimerAccepted(): Boolean {
|
||||
Timber.v("isDisclaimerAccepted() called")
|
||||
logger.v { "isDisclaimerAccepted() called" }
|
||||
val isAccepted = preferencesStorage.getValue(isDisclaimerAcceptedKey) ?: false
|
||||
Timber.v("isDisclaimerAccepted() returned: $isAccepted")
|
||||
logger.v { "isDisclaimerAccepted() returned: $isAccepted" }
|
||||
return isAccepted
|
||||
}
|
||||
|
||||
override suspend fun acceptDisclaimer() {
|
||||
Timber.v("acceptDisclaimer() called")
|
||||
logger.v { "acceptDisclaimer() called" }
|
||||
preferencesStorage.storeValues(Pair(isDisclaimerAcceptedKey, true))
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
package gq.kirmanak.mealient.data.network
|
||||
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import timber.log.Timber
|
||||
|
||||
class RetrofitBuilder(
|
||||
private val okHttpClient: OkHttpClient,
|
||||
private val json: Json
|
||||
private val json: Json,
|
||||
private val logger: Logger,
|
||||
) {
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
fun buildRetrofit(baseUrl: String): Retrofit {
|
||||
Timber.v("buildRetrofit() called with: baseUrl = $baseUrl")
|
||||
logger.v { "buildRetrofit() called with: baseUrl = $baseUrl" }
|
||||
val contentType = "application/json".toMediaType()
|
||||
val converterFactory = json.asConverterFactory(contentType)
|
||||
return Retrofit.Builder()
|
||||
|
||||
@@ -2,30 +2,34 @@ package gq.kirmanak.mealient.data.network
|
||||
|
||||
import gq.kirmanak.mealient.data.baseurl.BaseURLStorage
|
||||
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
|
||||
inline fun <reified T> RetrofitBuilder.createServiceFactory(baseURLStorage: BaseURLStorage) =
|
||||
RetrofitServiceFactory(T::class.java, this, baseURLStorage)
|
||||
inline fun <reified T> RetrofitBuilder.createServiceFactory(
|
||||
baseURLStorage: BaseURLStorage,
|
||||
logger: Logger
|
||||
) =
|
||||
RetrofitServiceFactory(T::class.java, this, baseURLStorage, logger)
|
||||
|
||||
class RetrofitServiceFactory<T>(
|
||||
private val serviceClass: Class<T>,
|
||||
private val retrofitBuilder: RetrofitBuilder,
|
||||
private val baseURLStorage: BaseURLStorage,
|
||||
private val logger: Logger,
|
||||
) : ServiceFactory<T> {
|
||||
|
||||
private val cache: MutableMap<String, T> = mutableMapOf()
|
||||
|
||||
override suspend fun provideService(baseUrl: String?): T = runCatchingExceptCancel {
|
||||
Timber.v("provideService() called with: baseUrl = $baseUrl, class = ${serviceClass.simpleName}")
|
||||
logger.v { "provideService() called with: baseUrl = $baseUrl, class = ${serviceClass.simpleName}" }
|
||||
val url = baseUrl ?: baseURLStorage.requireBaseURL()
|
||||
synchronized(cache) { cache[url] ?: createService(url, serviceClass) }
|
||||
}.getOrElse {
|
||||
Timber.e(it, "provideService: can't provide service for $baseUrl")
|
||||
logger.e(it) { "provideService: can't provide service for $baseUrl" }
|
||||
throw NetworkError.MalformedUrl(it)
|
||||
}
|
||||
|
||||
private fun createService(url: String, serviceClass: Class<T>): T {
|
||||
Timber.v("createService() called with: url = $url, serviceClass = ${serviceClass.simpleName}")
|
||||
logger.v { "createService() called with: url = $url, serviceClass = ${serviceClass.simpleName}" }
|
||||
val service = retrofitBuilder.buildRetrofit(url).create(serviceClass)
|
||||
cache[url] = service
|
||||
return service
|
||||
|
||||
@@ -11,20 +11,21 @@ import gq.kirmanak.mealient.extensions.recipeEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeIngredientEntity
|
||||
import gq.kirmanak.mealient.extensions.toRecipeInstructionEntity
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class RecipeStorageImpl @Inject constructor(
|
||||
private val db: AppDb
|
||||
private val db: AppDb,
|
||||
private val logger: Logger,
|
||||
) : RecipeStorage {
|
||||
private val recipeDao: RecipeDao by lazy { db.recipeDao() }
|
||||
|
||||
override suspend fun saveRecipes(
|
||||
recipes: List<GetRecipeSummaryResponse>
|
||||
) = db.withTransaction {
|
||||
Timber.v("saveRecipes() called with $recipes")
|
||||
logger.v { "saveRecipes() called with $recipes" }
|
||||
|
||||
val tagEntities = mutableSetOf<TagEntity>()
|
||||
tagEntities.addAll(recipeDao.queryAllTags())
|
||||
@@ -91,12 +92,12 @@ class RecipeStorageImpl @Inject constructor(
|
||||
|
||||
|
||||
override fun queryRecipes(): PagingSource<Int, RecipeSummaryEntity> {
|
||||
Timber.v("queryRecipes() called")
|
||||
logger.v { "queryRecipes() called" }
|
||||
return recipeDao.queryRecipesByPages()
|
||||
}
|
||||
|
||||
override suspend fun refreshAll(recipes: List<GetRecipeSummaryResponse>) {
|
||||
Timber.v("refreshAll() called with: recipes = $recipes")
|
||||
logger.v { "refreshAll() called with: recipes = $recipes" }
|
||||
db.withTransaction {
|
||||
recipeDao.removeAllRecipes()
|
||||
saveRecipes(recipes)
|
||||
@@ -104,7 +105,7 @@ class RecipeStorageImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun clearAllLocalData() {
|
||||
Timber.v("clearAllLocalData() called")
|
||||
logger.v { "clearAllLocalData() called" }
|
||||
db.withTransaction {
|
||||
recipeDao.removeAllRecipes()
|
||||
recipeDao.removeAllCategories()
|
||||
@@ -113,7 +114,7 @@ class RecipeStorageImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun saveRecipeInfo(recipe: GetRecipeResponse) {
|
||||
Timber.v("saveRecipeInfo() called with: recipe = $recipe")
|
||||
logger.v { "saveRecipeInfo() called with: recipe = $recipe" }
|
||||
db.withTransaction {
|
||||
recipeDao.insertRecipe(recipe.toRecipeEntity())
|
||||
|
||||
@@ -132,11 +133,11 @@ class RecipeStorageImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun queryRecipeInfo(recipeId: Long): FullRecipeInfo {
|
||||
Timber.v("queryRecipeInfo() called with: recipeId = $recipeId")
|
||||
logger.v { "queryRecipeInfo() called with: recipeId = $recipeId" }
|
||||
val fullRecipeInfo = checkNotNull(recipeDao.queryFullRecipeInfo(recipeId)) {
|
||||
"Can't find recipe by id $recipeId in DB"
|
||||
}
|
||||
Timber.v("queryRecipeInfo() returned: $fullRecipeInfo")
|
||||
logger.v { "queryRecipeInfo() returned: $fullRecipeInfo" }
|
||||
return fullRecipeInfo
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
package gq.kirmanak.mealient.data.recipes.impl
|
||||
|
||||
import gq.kirmanak.mealient.data.baseurl.BaseURLStorage
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class RecipeImageUrlProviderImpl @Inject constructor(
|
||||
private val baseURLStorage: BaseURLStorage,
|
||||
private val logger: Logger,
|
||||
) : RecipeImageUrlProvider {
|
||||
|
||||
override suspend fun generateImageUrl(slug: String?): String? {
|
||||
Timber.v("generateImageUrl() called with: slug = $slug")
|
||||
logger.v { "generateImageUrl() called with: slug = $slug" }
|
||||
slug?.takeUnless { it.isBlank() } ?: return null
|
||||
val imagePath = IMAGE_PATH_FORMAT.format(slug)
|
||||
val baseUrl = baseURLStorage.getBaseURL()?.takeUnless { it.isEmpty() }
|
||||
@@ -21,7 +22,7 @@ class RecipeImageUrlProviderImpl @Inject constructor(
|
||||
?.addPathSegments(imagePath)
|
||||
?.build()
|
||||
?.toString()
|
||||
Timber.v("getRecipeImageUrl() returned: $result")
|
||||
logger.v { "getRecipeImageUrl() returned: $result" }
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
|
||||
import gq.kirmanak.mealient.database.recipe.entity.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -21,9 +21,10 @@ class RecipeRepoImpl @Inject constructor(
|
||||
private val storage: RecipeStorage,
|
||||
private val pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>,
|
||||
private val dataSource: RecipeDataSource,
|
||||
private val logger: Logger,
|
||||
) : RecipeRepo {
|
||||
override fun createPager(): Pager<Int, RecipeSummaryEntity> {
|
||||
Timber.v("createPager() called")
|
||||
logger.v { "createPager() called" }
|
||||
val pagingConfig = PagingConfig(pageSize = 5, enablePlaceholders = true)
|
||||
return Pager(
|
||||
config = pagingConfig,
|
||||
@@ -33,17 +34,17 @@ class RecipeRepoImpl @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun clearLocalData() {
|
||||
Timber.v("clearLocalData() called")
|
||||
logger.v { "clearLocalData() called" }
|
||||
storage.clearAllLocalData()
|
||||
}
|
||||
|
||||
override suspend fun loadRecipeInfo(recipeId: Long, recipeSlug: String): FullRecipeInfo {
|
||||
Timber.v("loadRecipeInfo() called with: recipeId = $recipeId, recipeSlug = $recipeSlug")
|
||||
logger.v { "loadRecipeInfo() called with: recipeId = $recipeId, recipeSlug = $recipeSlug" }
|
||||
|
||||
runCatchingExceptCancel {
|
||||
storage.saveRecipeInfo(dataSource.requestRecipeInfo(recipeSlug))
|
||||
}.onFailure {
|
||||
Timber.e(it, "loadRecipeInfo: can't update full recipe info")
|
||||
logger.e(it) { "loadRecipeInfo: can't update full recipe info" }
|
||||
}
|
||||
|
||||
return storage.queryRecipeInfo(recipeId)
|
||||
|
||||
@@ -8,7 +8,7 @@ import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
||||
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
|
||||
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.extensions.runCatchingExceptCancel
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -18,6 +18,7 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
private val storage: RecipeStorage,
|
||||
private val network: RecipeDataSource,
|
||||
private val pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>,
|
||||
private val logger: Logger,
|
||||
) : RemoteMediator<Int, RecipeSummaryEntity>() {
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -27,10 +28,10 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, RecipeSummaryEntity>
|
||||
): MediatorResult {
|
||||
Timber.v("load() called with: lastRequestEnd = $lastRequestEnd, loadType = $loadType, state = $state")
|
||||
logger.v { "load() called with: lastRequestEnd = $lastRequestEnd, loadType = $loadType, state = $state" }
|
||||
|
||||
if (loadType == PREPEND) {
|
||||
Timber.i("load: early exit, PREPEND isn't supported")
|
||||
logger.i { "load: early exit, PREPEND isn't supported" }
|
||||
return MediatorResult.Success(endOfPaginationReached = true)
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
else storage.saveRecipes(recipes)
|
||||
recipes.size
|
||||
}.getOrElse {
|
||||
Timber.e(it, "load: can't load recipes")
|
||||
logger.e(it) { "load: can't load recipes" }
|
||||
return MediatorResult.Error(it)
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ class RecipesRemoteMediator @Inject constructor(
|
||||
// Read that trick here https://github.com/android/architecture-components-samples/issues/889#issuecomment-880847858
|
||||
pagingSourceFactory.invalidate()
|
||||
|
||||
Timber.d("load: expectedCount = $limit, received $count")
|
||||
logger.d { "load: expectedCount = $limit, received $count" }
|
||||
lastRequestEnd = start + count
|
||||
return MediatorResult.Success(endOfPaginationReached = count < limit)
|
||||
}
|
||||
|
||||
@@ -3,31 +3,32 @@ package gq.kirmanak.mealient.data.recipes.network
|
||||
import gq.kirmanak.mealient.data.network.ServiceFactory
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeSummaryResponse
|
||||
import timber.log.Timber
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class RecipeDataSourceImpl @Inject constructor(
|
||||
private val recipeServiceFactory: ServiceFactory<RecipeService>,
|
||||
private val logger: Logger,
|
||||
) : RecipeDataSource {
|
||||
|
||||
override suspend fun requestRecipes(start: Int, limit: Int): List<GetRecipeSummaryResponse> {
|
||||
Timber.v("requestRecipes() called with: start = $start, limit = $limit")
|
||||
logger.v { "requestRecipes() called with: start = $start, limit = $limit" }
|
||||
val recipeSummary = getRecipeService().getRecipeSummary(start, limit)
|
||||
Timber.v("requestRecipes() returned: $recipeSummary")
|
||||
logger.v { "requestRecipes() returned: $recipeSummary" }
|
||||
return recipeSummary
|
||||
}
|
||||
|
||||
override suspend fun requestRecipeInfo(slug: String): GetRecipeResponse {
|
||||
Timber.v("requestRecipeInfo() called with: slug = $slug")
|
||||
logger.v { "requestRecipeInfo() called with: slug = $slug" }
|
||||
val recipeInfo = getRecipeService().getRecipe(slug)
|
||||
Timber.v("requestRecipeInfo() returned: $recipeInfo")
|
||||
logger.v { "requestRecipeInfo() returned: $recipeInfo" }
|
||||
return recipeInfo
|
||||
}
|
||||
|
||||
private suspend fun getRecipeService(): RecipeService {
|
||||
Timber.v("getRecipeService() called")
|
||||
logger.v { "getRecipeService() called" }
|
||||
return recipeServiceFactory.provideService()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,15 @@ import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PreferencesStorageImpl @Inject constructor(
|
||||
private val dataStore: DataStore<Preferences>
|
||||
private val dataStore: DataStore<Preferences>,
|
||||
private val logger: Logger,
|
||||
) : PreferencesStorage {
|
||||
|
||||
override val baseUrlKey = stringPreferencesKey("baseUrl")
|
||||
@@ -21,7 +22,7 @@ class PreferencesStorageImpl @Inject constructor(
|
||||
|
||||
override suspend fun <T> getValue(key: Preferences.Key<T>): T? {
|
||||
val value = dataStore.data.first()[key]
|
||||
Timber.v("getValue() returned: $value for $key")
|
||||
logger.v { "getValue() returned: $value for $key" }
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -29,23 +30,23 @@ class PreferencesStorageImpl @Inject constructor(
|
||||
checkNotNull(getValue(key)) { "Value at $key is null when it was required" }
|
||||
|
||||
override suspend fun <T> storeValues(vararg pairs: Pair<Preferences.Key<T>, T>) {
|
||||
Timber.v("storeValues() called with: pairs = ${pairs.contentToString()}")
|
||||
logger.v { "storeValues() called with: pairs = ${pairs.contentToString()}" }
|
||||
dataStore.edit { preferences ->
|
||||
pairs.forEach { preferences += it.toPreferencesPair() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> valueUpdates(key: Preferences.Key<T>): Flow<T?> {
|
||||
Timber.v("valueUpdates() called with: key = $key")
|
||||
logger.v { "valueUpdates() called with: key = $key" }
|
||||
return dataStore.data
|
||||
.map { it[key] }
|
||||
.distinctUntilChanged()
|
||||
.onEach { Timber.d("valueUpdates: new value at $key is $it") }
|
||||
.onCompletion { Timber.i(it, "valueUpdates: finished") }
|
||||
.onEach { logger.d { "valueUpdates: new value at $key is $it" } }
|
||||
.onCompletion { logger.i(it) { "valueUpdates: finished" } }
|
||||
}
|
||||
|
||||
override suspend fun <T> removeValues(vararg keys: Preferences.Key<T>) {
|
||||
Timber.v("removeValues() called with: key = ${keys.contentToString()}")
|
||||
logger.v { "removeValues() called with: key = ${keys.contentToString()}" }
|
||||
dataStore.edit { preferences ->
|
||||
keys.forEach { preferences -= it }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user