refactor(logging): introduce custom FastLogger and replace direct Android logging

This commit is contained in:
2026-05-30 18:31:00 +03:00
parent fc3b3cfcb3
commit 10453287a7
32 changed files with 353 additions and 151 deletions
@@ -1,7 +1,6 @@
package dev.meloda.fast.auth.captcha.presentation
import android.graphics.Bitmap
import android.util.Log
import android.webkit.JavascriptInterface
import android.webkit.WebResourceRequest
import android.webkit.WebView
@@ -32,7 +31,9 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import dev.meloda.fast.logger.FastLogger
import dev.meloda.fast.ui.R
import dev.meloda.fast.ui.common.LocalLogger
import dev.meloda.fast.ui.components.ActionInvokeDismiss
import dev.meloda.fast.ui.components.FullScreenDialog
import dev.meloda.fast.ui.components.MaterialDialog
@@ -46,6 +47,8 @@ fun CaptchaScreen(
onBack: () -> Unit = {},
onResult: (String) -> Unit = {}
) {
val logger = LocalLogger.current
if (captchaRedirectUri != null) {
val focusManager = LocalFocusManager.current
val keyboardController = LocalSoftwareKeyboardController.current
@@ -114,7 +117,10 @@ fun CaptchaScreen(
view: WebView?,
request: WebResourceRequest?
): Boolean {
Log.i(TAG, "shouldOverrideUrlLoading: $request")
logger.info(
"CaptchaScreen",
"WebViewClient(): shouldOverrideUrlLoading(): request: $request"
)
return false
}
@@ -148,7 +154,8 @@ fun CaptchaScreen(
// TODO: 03/05/2026, Danil Nikolaev: show error
}
},
onCloseRequested = { showExitAlert = true }
onCloseRequested = { showExitAlert = true },
logger = logger
),
"AndroidBridge"
)
@@ -176,19 +183,18 @@ fun CaptchaScreen(
class WebCaptchaListener(
private val onSuccessTokenReceived: (String) -> Unit,
private val onCloseRequested: (String) -> Unit
private val onCloseRequested: (String) -> Unit,
private val logger: FastLogger
) {
private val tag = "WebCaptchaListener"
@JavascriptInterface
fun VKCaptchaGetResult(arg: String) {
onSuccessTokenReceived(arg)
Log.i(tag, "VKCaptchaGetResult($arg)")
logger.info(this::class, "VKCaptchaGetResult(): arg: $arg")
}
@JavascriptInterface
fun VKCaptchaCloseCaptcha(arg: String) {
onCloseRequested(arg)
Log.i(tag, "VKCaptchaCloseCaptcha($arg)")
logger.info(this::class, "VKCaptchaCloseCaptcha(): arg: $arg")
}
}
@@ -2,7 +2,6 @@ package dev.meloda.fast.auth.login
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dev.meloda.fast.auth.login.model.CaptchaArguments
@@ -28,6 +27,7 @@ import dev.meloda.fast.datastore.AppSettings
import dev.meloda.fast.datastore.UserSettings
import dev.meloda.fast.domain.LoadUserByIdUseCase
import dev.meloda.fast.domain.OAuthUseCase
import dev.meloda.fast.logger.FastLogger
import dev.meloda.fast.model.database.AccountEntity
import dev.meloda.fast.network.OAuthErrorDomain
import kotlinx.coroutines.CoroutineExceptionHandler
@@ -48,7 +48,8 @@ class LoginViewModel(
private val accountsRepository: AccountsRepository,
private val loginValidator: LoginValidator,
private val longPollController: LongPollController,
private val userSettings: UserSettings
private val userSettings: UserSettings,
private val logger: FastLogger
) : ViewModel() {
private val _screenState = MutableStateFlow(LoginScreenState.EMPTY)
val screenState = _screenState.asStateFlow()
@@ -189,7 +190,7 @@ class LoginViewModel(
).listenValue(viewModelScope) { state ->
state.processState(
error = { error ->
Log.d("LoginViewModelImpl", "login: error: $error")
logger.error(this::class, "getSilentToken(): ERROR: $error")
_screenState.updateValue { copy(isLoading = false) }
@@ -1,6 +1,5 @@
package dev.meloda.fast.chatmaterials.util
import android.util.Log
import dev.meloda.fast.chatmaterials.model.UiChatMaterial
import dev.meloda.fast.common.util.AndroidUtils
import dev.meloda.fast.model.api.data.AttachmentType
@@ -135,8 +134,5 @@ fun VkAttachmentHistoryMessage.asPresentation(): UiChatMaterial? =
)
}
else -> {
Log.w("ChatMaterialMapper", "Unsupported type: $type")
null
}
else -> null
}
@@ -6,7 +6,6 @@ import android.content.Context
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
@@ -685,8 +684,6 @@ class MessagesHistoryViewModelImpl(
private fun handleNewMessage(event: LongPollParsedEvent.NewMessage) {
val message = event.message
Log.d("MessagesHistoryViewModel", "handleNewMessage: $message")
if (message.peerId != screenState.value.convoId) return
if (messages.value.indexOfFirstOrNull { it.id == message.id } != null) return
@@ -835,8 +832,6 @@ class MessagesHistoryViewModelImpl(
}
private fun loadConvo() {
Log.d("MessagesHistoryViewModelImpl", "loadConvo()")
loadConvosByIdUseCase(
peerIds = listOf(screenState.value.convoId),
extended = true,
@@ -904,8 +899,6 @@ class MessagesHistoryViewModelImpl(
}
private fun loadMessagesHistory(offset: Int = currentOffset.value) {
Log.d("MessagesHistoryViewModel", "loadMessagesHistory: $offset")
messagesUseCase.getMessagesHistory(
convoId = screenState.value.convoId,
count = MESSAGES_LOAD_COUNT,
@@ -1079,8 +1072,6 @@ class MessagesHistoryViewModelImpl(
state.processState(
any = { sendingMessages.remove(newMessage) },
error = { error ->
Log.d("MessagesHistoryViewModelImpl", "sendMessage: ERROR: $error")
val failedId = -500_000L - failedMessages.size
val newFailedMessage = newMessage.copy(id = failedId)
failedMessages += newFailedMessage
@@ -1144,8 +1135,6 @@ class MessagesHistoryViewModelImpl(
) ?: return
// TODO: 13/03/2026, Danil Nikolaev: check if message is exact same, then do not edit
Log.d("MessagesHistoryViewModelImpl", "editMessage: $newMessage")
}
private fun markAsImportant(
@@ -1,7 +1,6 @@
package dev.meloda.fast.messageshistory.presentation
import android.content.Intent
import android.util.Log
import android.view.HapticFeedbackConstants
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
@@ -129,7 +128,6 @@ fun MessagesList(
when (attachment) {
is VkPhotoDomain -> {
val maxSize = attachment.getMaxSize()
Log.d("MessagesList", "onPhotoLongClicked. Max size: ${maxSize?.url}")
}
}
}
@@ -64,7 +64,6 @@ fun DynamicPreviewGrid(
val spacingPx = with(LocalDensity.current) { spacing.toPx() }
val rows = previews.chunked(3)
Log.d("ROWS", "DynamicPreviewGrid: ${rows.size}")
Column(verticalArrangement = Arrangement.spacedBy(spacing)) {
rows.forEachIndexed { outerIndex, row ->
@@ -12,7 +12,7 @@ import dev.meloda.fast.common.extensions.findWithIndex
import dev.meloda.fast.common.extensions.listenValue
import dev.meloda.fast.common.extensions.setValue
import dev.meloda.fast.common.model.DarkMode
import dev.meloda.fast.common.model.LogLevel
import dev.meloda.fast.common.model.NetworkLogLevel
import dev.meloda.fast.common.model.LongPollState
import dev.meloda.fast.common.model.UiText
import dev.meloda.fast.common.model.parseString
@@ -497,10 +497,10 @@ class SettingsViewModel(
)
val logLevelValues = listOf(
LogLevel.NONE to UiText.Simple("None"),
LogLevel.BASIC to UiText.Simple("Basic"),
LogLevel.HEADERS to UiText.Simple("Headers"),
LogLevel.BODY to UiText.Simple("Body")
NetworkLogLevel.NONE to UiText.Simple("None"),
NetworkLogLevel.BASIC to UiText.Simple("Basic"),
NetworkLogLevel.HEADERS to UiText.Simple("Headers"),
NetworkLogLevel.BODY to UiText.Simple("Body")
).toMap()
val debugNetworkLogLevel = SettingsItem.ListItem(
@@ -509,10 +509,10 @@ class SettingsViewModel(
valueClass = Int::class,
defaultValue = SettingsKeys.DEFAULT_NETWORK_LOG_LEVEL,
titles = logLevelValues.values.toList(),
values = logLevelValues.keys.toList().map(LogLevel::value)
values = logLevelValues.keys.toList().map(NetworkLogLevel::value)
).apply {
textProvider = TextProvider { item ->
val textValue = logLevelValues[LogLevel.parse(item.value)].parseString(resources)
val textValue = logLevelValues[NetworkLogLevel.parse(item.value)].parseString(resources)
UiText.Simple("Current value: $textValue")
}