Reorganize code
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package gq.kirmanak.mealient.extensions
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import retrofit2.Response
|
||||
import timber.log.Timber
|
||||
import java.io.InputStream
|
||||
|
||||
inline fun <T, reified R> Response<T>.decodeErrorBodyOrNull(json: Json): R? =
|
||||
errorBody()?.byteStream()?.let { json.decodeFromStreamOrNull<R>(it) }
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
inline fun <reified T> Json.decodeFromStreamOrNull(stream: InputStream): T? =
|
||||
runCatching { decodeFromStream<T>(stream) }
|
||||
.onFailure { Timber.e(it, "decodeFromStreamOrNull: can't decode") }
|
||||
.getOrNull()
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package gq.kirmanak.mealient.extensions
|
||||
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeIngredientEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeInstructionEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeIngredientResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeInstructionResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeSummaryResponse
|
||||
|
||||
fun GetRecipeResponse.toRecipeEntity() = RecipeEntity(
|
||||
remoteId = remoteId,
|
||||
recipeYield = recipeYield
|
||||
)
|
||||
|
||||
fun GetRecipeIngredientResponse.toRecipeIngredientEntity(remoteId: Long) =
|
||||
RecipeIngredientEntity(
|
||||
recipeId = remoteId,
|
||||
title = title,
|
||||
note = note,
|
||||
unit = unit,
|
||||
food = food,
|
||||
disableAmount = disableAmount,
|
||||
quantity = quantity
|
||||
)
|
||||
|
||||
fun GetRecipeInstructionResponse.toRecipeInstructionEntity(remoteId: Long) =
|
||||
RecipeInstructionEntity(
|
||||
recipeId = remoteId,
|
||||
title = title,
|
||||
text = text
|
||||
)
|
||||
|
||||
fun GetRecipeSummaryResponse.recipeEntity() = RecipeSummaryEntity(
|
||||
remoteId = remoteId,
|
||||
name = name,
|
||||
slug = slug,
|
||||
image = image,
|
||||
description = description,
|
||||
rating = rating,
|
||||
dateAdded = dateAdded,
|
||||
dateUpdated = dateUpdated,
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
package gq.kirmanak.mealient.extensions
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import kotlinx.datetime.*
|
||||
|
||||
object RoomTypeConverters {
|
||||
@TypeConverter
|
||||
fun localDateTimeToTimestamp(localDateTime: LocalDateTime) =
|
||||
localDateTime.toInstant(TimeZone.UTC).toEpochMilliseconds()
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToLocalDateTime(timestamp: Long) =
|
||||
Instant.fromEpochMilliseconds(timestamp).toLocalDateTime(TimeZone.UTC)
|
||||
|
||||
@TypeConverter
|
||||
fun localDateToTimeStamp(date: LocalDate) =
|
||||
localDateTimeToTimestamp(date.atTime(0, 0))
|
||||
|
||||
@TypeConverter
|
||||
fun timestampToLocalDate(timestamp: Long) =
|
||||
timestampToLocalDateTime(timestamp).date
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package gq.kirmanak.mealient.extensions
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.onClosed
|
||||
import kotlinx.coroutines.channels.onFailure
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
suspend fun SharedPreferences.getStringOrNull(key: String) =
|
||||
withContext(Dispatchers.IO) { getString(key, null) }
|
||||
|
||||
suspend fun SharedPreferences.getBooleanOrFalse(key: String) =
|
||||
withContext(Dispatchers.IO) { getBoolean(key, false) }
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun SharedPreferences.changesFlow(): Flow<Pair<SharedPreferences, String?>> = callbackFlow {
|
||||
val listener = SharedPreferences.OnSharedPreferenceChangeListener { prefs, key ->
|
||||
Timber.v("watchChanges: listener called with key $key")
|
||||
trySend(prefs to key)
|
||||
.onFailure { Timber.e(it, "watchChanges: can't send preference change, key $key") }
|
||||
.onClosed { Timber.e(it, "watchChanges: flow has been closed") }
|
||||
}
|
||||
Timber.v("watchChanges: registering listener")
|
||||
registerOnSharedPreferenceChangeListener(listener)
|
||||
send(this@changesFlow to null)
|
||||
awaitClose {
|
||||
Timber.v("watchChanges: flow has been closed")
|
||||
unregisterOnSharedPreferenceChangeListener(listener)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user