new: add logging abstraction with Kermit integration
This commit is contained in:
@@ -17,6 +17,7 @@ kotlinxCoroutines = "1.11.0"
|
|||||||
kotlinSerialization = "2.4.0"
|
kotlinSerialization = "2.4.0"
|
||||||
material3 = "1.11.0-alpha07"
|
material3 = "1.11.0-alpha07"
|
||||||
koin = "4.2.1"
|
koin = "4.2.1"
|
||||||
|
kermit = "2.1.0"
|
||||||
vorbisspi = "1.0.3.3"
|
vorbisspi = "1.0.3.3"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
@@ -34,6 +35,7 @@ koin-compose = { module = "io.insert-koin:koin-compose" }
|
|||||||
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" }
|
koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" }
|
||||||
koin-core = { module = "io.insert-koin:koin-core" }
|
koin-core = { module = "io.insert-koin:koin-core" }
|
||||||
koin-core-viewmodel = { module = "io.insert-koin:koin-core-viewmodel" }
|
koin-core-viewmodel = { module = "io.insert-koin:koin-core-viewmodel" }
|
||||||
|
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
|
||||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||||
kotlinx-browser = { module = "org.jetbrains.kotlinx:kotlinx-browser", version.ref = "kotlinxBrowser" }
|
kotlinx-browser = { module = "org.jetbrains.kotlinx:kotlinx-browser", version.ref = "kotlinxBrowser" }
|
||||||
kotlinx-coroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
|
kotlinx-coroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ kotlin {
|
|||||||
implementation(libs.compose.components.resources)
|
implementation(libs.compose.components.resources)
|
||||||
implementation(libs.compose.uiToolingPreview)
|
implementation(libs.compose.uiToolingPreview)
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
implementation(libs.kermit)
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
implementation(libs.lifecycle.viewmodelCompose)
|
implementation(libs.lifecycle.viewmodelCompose)
|
||||||
implementation(libs.lifecycle.runtimeCompose)
|
implementation(libs.lifecycle.runtimeCompose)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.logging
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger as Kermit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kermit-backed implementation (adapter) of the [Logger] port.
|
||||||
|
*/
|
||||||
|
class KermitLogger(
|
||||||
|
private val tag: String = "Gwenedeg",
|
||||||
|
) : Logger {
|
||||||
|
override fun debug(message: String, throwable: Throwable?) {
|
||||||
|
Kermit.d(throwable = throwable, tag = tag) { message }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun info(message: String, throwable: Throwable?) {
|
||||||
|
Kermit.i(throwable = throwable, tag = tag) { message }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun warning(message: String, throwable: Throwable?) {
|
||||||
|
Kermit.w(throwable = throwable, tag = tag) { message }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun error(message: String, throwable: Throwable?) {
|
||||||
|
Kermit.e(throwable = throwable, tag = tag) { message }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.logging
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logging abstraction so the rest of the app depends on this interface
|
||||||
|
* rather than on a concrete logging library.
|
||||||
|
*/
|
||||||
|
interface Logger {
|
||||||
|
fun debug(
|
||||||
|
message: String,
|
||||||
|
throwable: Throwable? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun info(
|
||||||
|
message: String,
|
||||||
|
throwable: Throwable? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun warning(
|
||||||
|
message: String,
|
||||||
|
throwable: Throwable? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun error(
|
||||||
|
message: String,
|
||||||
|
throwable: Throwable? = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package fr.ajaury.gwenedeg.di
|
package fr.ajaury.gwenedeg.di
|
||||||
|
|
||||||
|
import fr.ajaury.gwenedeg.core.logging.KermitLogger
|
||||||
|
import fr.ajaury.gwenedeg.core.logging.Logger
|
||||||
import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerViewModel
|
import fr.ajaury.gwenedeg.player.ui.viewmodel.PlayerViewModel
|
||||||
import fr.ajaury.gwenedeg.records.data.InMemoryRecordRepository
|
import fr.ajaury.gwenedeg.records.data.InMemoryRecordRepository
|
||||||
import fr.ajaury.gwenedeg.records.domain.RecordRepository
|
import fr.ajaury.gwenedeg.records.domain.RecordRepository
|
||||||
@@ -10,6 +12,7 @@ import org.koin.core.module.dsl.viewModelOf
|
|||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val sharedModule = module {
|
val sharedModule = module {
|
||||||
|
single<Logger> { KermitLogger() }
|
||||||
factoryOf(::InMemoryRecordRepository) { bind<RecordRepository>() }
|
factoryOf(::InMemoryRecordRepository) { bind<RecordRepository>() }
|
||||||
viewModelOf(::RecordsViewModel)
|
viewModelOf(::RecordsViewModel)
|
||||||
viewModelOf(::PlayerViewModel)
|
viewModelOf(::PlayerViewModel)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package fr.ajaury.gwenedeg.player.ui.viewmodel
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import fr.ajaury.gwenedeg.core.logging.Logger
|
||||||
import fr.ajaury.gwenedeg.player.AudioPlayer
|
import fr.ajaury.gwenedeg.player.AudioPlayer
|
||||||
import fr.ajaury.gwenedeg.player.AudioSessionManager
|
import fr.ajaury.gwenedeg.player.AudioSessionManager
|
||||||
import fr.ajaury.gwenedeg.player.PlaybackState
|
import fr.ajaury.gwenedeg.player.PlaybackState
|
||||||
@@ -16,6 +17,7 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
class PlayerViewModel(
|
class PlayerViewModel(
|
||||||
private val audioPlayer: AudioPlayer,
|
private val audioPlayer: AudioPlayer,
|
||||||
private val audioSessionManager: AudioSessionManager,
|
private val audioSessionManager: AudioSessionManager,
|
||||||
|
private val logger: Logger,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private var filePath: String? = null
|
private var filePath: String? = null
|
||||||
|
|
||||||
@@ -32,9 +34,13 @@ class PlayerViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun play(filePath: String) {
|
fun play(filePath: String) {
|
||||||
|
try {
|
||||||
this.filePath = filePath
|
this.filePath = filePath
|
||||||
audioPlayer.load(uri = Res.getUri(filePath))
|
audioPlayer.load(uri = Res.getUri(filePath))
|
||||||
audioPlayer.play()
|
audioPlayer.play()
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
logger.error(message = "Failed to play audio: $filePath", throwable = exception)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun performMainPlayAction() {
|
fun performMainPlayAction() {
|
||||||
|
|||||||
Reference in New Issue
Block a user