Replace Timber with Logger
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
package gq.kirmanak.mealient.extensions
|
||||
|
||||
import gq.kirmanak.mealient.data.network.NetworkError
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import retrofit2.HttpException
|
||||
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) }
|
||||
inline fun <T, reified R> Response<T>.decodeErrorBodyOrNull(json: Json, logger: Logger): R? =
|
||||
errorBody()?.byteStream()?.let { json.decodeFromStreamOrNull<R>(it, logger) }
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
inline fun <reified T> Json.decodeFromStreamOrNull(stream: InputStream): T? =
|
||||
inline fun <reified T> Json.decodeFromStreamOrNull(stream: InputStream, logger: Logger): T? =
|
||||
runCatching { decodeFromStream<T>(stream) }
|
||||
.onFailure { Timber.e(it, "decodeFromStreamOrNull: can't decode") }
|
||||
.onFailure { logger.e(it) { "decodeFromStreamOrNull: can't decode" } }
|
||||
.getOrNull()
|
||||
|
||||
fun Throwable.mapToNetworkError(): NetworkError = when (this) {
|
||||
@@ -24,8 +24,12 @@ fun Throwable.mapToNetworkError(): NetworkError = when (this) {
|
||||
else -> NetworkError.NoServerConnection(this)
|
||||
}
|
||||
|
||||
inline fun <T> logAndMapErrors(block: () -> T, logProvider: () -> String): T =
|
||||
inline fun <T> logAndMapErrors(
|
||||
logger: Logger,
|
||||
block: () -> T,
|
||||
noinline logProvider: () -> String
|
||||
): T =
|
||||
runCatchingExceptCancel(block).getOrElse {
|
||||
Timber.e(it, logProvider())
|
||||
logger.e(it, messageSupplier = logProvider)
|
||||
throw it.mapToNetworkError()
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import gq.kirmanak.mealient.logging.Logger
|
||||
import kotlinx.coroutines.channels.ChannelResult
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.onClosed
|
||||
@@ -24,61 +25,60 @@ import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
fun SwipeRefreshLayout.refreshRequestFlow(): Flow<Unit> = callbackFlow {
|
||||
Timber.v("refreshRequestFlow() called")
|
||||
fun SwipeRefreshLayout.refreshRequestFlow(logger: Logger): Flow<Unit> = callbackFlow {
|
||||
logger.v { "refreshRequestFlow() called" }
|
||||
val listener = SwipeRefreshLayout.OnRefreshListener {
|
||||
Timber.v("refreshRequestFlow: listener called")
|
||||
trySend(Unit).logErrors("refreshesFlow")
|
||||
logger.v { "refreshRequestFlow: listener called" }
|
||||
trySend(Unit).logErrors("refreshesFlow", logger)
|
||||
}
|
||||
setOnRefreshListener(listener)
|
||||
awaitClose {
|
||||
Timber.v("Removing refresh request listener")
|
||||
logger.v { "Removing refresh request listener" }
|
||||
setOnRefreshListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.setSystemUiVisibility(isVisible: Boolean) {
|
||||
Timber.v("setSystemUiVisibility() called with: isVisible = $isVisible")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) setSystemUiVisibilityV30(isVisible)
|
||||
else setSystemUiVisibilityV1(isVisible)
|
||||
fun Activity.setSystemUiVisibility(isVisible: Boolean, logger: Logger) {
|
||||
logger.v { "setSystemUiVisibility() called with: isVisible = $isVisible" }
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) setSystemUiVisibilityV30(isVisible, logger)
|
||||
else setSystemUiVisibilityV1(isVisible, logger)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun Activity.setSystemUiVisibilityV1(isVisible: Boolean) {
|
||||
Timber.v("setSystemUiVisibilityV1() called with: isVisible = $isVisible")
|
||||
private fun Activity.setSystemUiVisibilityV1(isVisible: Boolean, logger: Logger) {
|
||||
logger.v { "setSystemUiVisibilityV1() called with: isVisible = $isVisible" }
|
||||
window.decorView.systemUiVisibility = if (isVisible) 0 else View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
private fun Activity.setSystemUiVisibilityV30(isVisible: Boolean) {
|
||||
Timber.v("setSystemUiVisibilityV30() called with: isVisible = $isVisible")
|
||||
private fun Activity.setSystemUiVisibilityV30(isVisible: Boolean, logger: Logger) {
|
||||
logger.v { "setSystemUiVisibilityV30() called with: isVisible = $isVisible" }
|
||||
val systemBars = WindowInsets.Type.systemBars()
|
||||
window.insetsController?.apply { if (isVisible) show(systemBars) else hide(systemBars) }
|
||||
?: Timber.w("setSystemUiVisibilityV30: insets controller is null")
|
||||
?: logger.w { "setSystemUiVisibilityV30: insets controller is null" }
|
||||
}
|
||||
|
||||
fun AppCompatActivity.setActionBarVisibility(isVisible: Boolean) {
|
||||
Timber.v("setActionBarVisibility() called with: isVisible = $isVisible")
|
||||
fun AppCompatActivity.setActionBarVisibility(isVisible: Boolean, logger: Logger) {
|
||||
logger.v { "setActionBarVisibility() called with: isVisible = $isVisible" }
|
||||
supportActionBar?.apply { if (isVisible) show() else hide() }
|
||||
?: Timber.w("setActionBarVisibility: action bar is null")
|
||||
?: logger.w { "setActionBarVisibility: action bar is null" }
|
||||
}
|
||||
|
||||
fun TextView.textChangesFlow(): Flow<CharSequence?> = callbackFlow {
|
||||
Timber.v("textChangesFlow() called")
|
||||
fun TextView.textChangesFlow(logger: Logger): Flow<CharSequence?> = callbackFlow {
|
||||
logger.v { "textChangesFlow() called" }
|
||||
val textWatcher = doAfterTextChanged {
|
||||
trySend(it).logErrors("textChangesFlow")
|
||||
trySend(it).logErrors("textChangesFlow", logger)
|
||||
}
|
||||
awaitClose {
|
||||
Timber.d("textChangesFlow: flow is closing")
|
||||
logger.d { "textChangesFlow: flow is closing" }
|
||||
removeTextChangedListener(textWatcher)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> ChannelResult<T>.logErrors(methodName: String): ChannelResult<T> {
|
||||
onFailure { Timber.e(it, "$methodName: can't send event") }
|
||||
onClosed { Timber.e(it, "$methodName: flow has been closed") }
|
||||
fun <T> ChannelResult<T>.logErrors(methodName: String, logger: Logger): ChannelResult<T> {
|
||||
onFailure { logger.e(it) { "$methodName: can't send event" } }
|
||||
onClosed { logger.e(it) { "$methodName: flow has been closed" } }
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -87,29 +87,31 @@ fun EditText.checkIfInputIsEmpty(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
@StringRes stringId: Int,
|
||||
trim: Boolean = true,
|
||||
logger: Logger,
|
||||
): String? {
|
||||
val input = if (trim) text?.trim() else text
|
||||
val text = input?.toString().orEmpty()
|
||||
Timber.d("Input text is \"$text\"")
|
||||
logger.d { "Input text is \"$text\"" }
|
||||
return text.ifEmpty {
|
||||
inputLayout.error = resources.getString(stringId)
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
waitUntilNotEmpty()
|
||||
waitUntilNotEmpty(logger)
|
||||
inputLayout.error = null
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun EditText.waitUntilNotEmpty() {
|
||||
textChangesFlow().filterNotNull().first { it.isNotEmpty() }
|
||||
Timber.v("waitUntilNotEmpty() returned")
|
||||
suspend fun EditText.waitUntilNotEmpty(logger: Logger) {
|
||||
textChangesFlow(logger).filterNotNull().first { it.isNotEmpty() }
|
||||
logger.v { "waitUntilNotEmpty() returned" }
|
||||
}
|
||||
|
||||
fun <T> SharedPreferences.prefsChangeFlow(
|
||||
logger: Logger,
|
||||
valueReader: SharedPreferences.() -> T,
|
||||
): Flow<T> = callbackFlow {
|
||||
fun sendValue() = trySend(valueReader()).logErrors("prefsChangeFlow")
|
||||
fun sendValue() = trySend(valueReader()).logErrors("prefsChangeFlow", logger)
|
||||
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, _ -> sendValue() }
|
||||
sendValue()
|
||||
registerOnSharedPreferenceChangeListener(listener)
|
||||
|
||||
Reference in New Issue
Block a user