new: integrate a dispatcher provider and dispatch work
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlinMultiplatform)
|
||||||
|
alias(libs.plugins.androidMultiplatformLibrary)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
iosArm64()
|
||||||
|
iosSimulatorArm64()
|
||||||
|
|
||||||
|
jvm()
|
||||||
|
|
||||||
|
js {
|
||||||
|
browser()
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalWasmDsl::class)
|
||||||
|
wasmJs {
|
||||||
|
browser()
|
||||||
|
}
|
||||||
|
|
||||||
|
androidLibrary {
|
||||||
|
namespace = "fr.ajaury.gwenedeg.core.coroutines"
|
||||||
|
compileSdk =
|
||||||
|
libs.versions.androidCompileSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
|
minSdk =
|
||||||
|
libs.versions.androidMinSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
|
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget = JvmTarget.JVM_11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain.dependencies {
|
||||||
|
// Coroutines
|
||||||
|
implementation(libs.kotlinx.coroutinesCore)
|
||||||
|
|
||||||
|
// DI
|
||||||
|
implementation(project.dependencies.platform(libs.koin.bom))
|
||||||
|
implementation(libs.koin.core)
|
||||||
|
}
|
||||||
|
commonTest.dependencies {
|
||||||
|
implementation(libs.kotlin.test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
internal actual val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.domain.DispatcherProvider
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
internal class DefaultDispatcherProvider : DispatcherProvider {
|
||||||
|
override val main: CoroutineDispatcher = Dispatchers.Main
|
||||||
|
override val default: CoroutineDispatcher = Dispatchers.Default
|
||||||
|
override val io: CoroutineDispatcher = ioDispatcher
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|
||||||
|
internal expect val ioDispatcher: CoroutineDispatcher
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.di
|
||||||
|
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.data.DefaultDispatcherProvider
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.domain.DispatcherProvider
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
val coroutinesModule: Module = module {
|
||||||
|
single<DispatcherProvider> { DefaultDispatcherProvider() }
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.domain
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|
||||||
|
interface DispatcherProvider {
|
||||||
|
val main: CoroutineDispatcher
|
||||||
|
val default: CoroutineDispatcher
|
||||||
|
val io: CoroutineDispatcher
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
// `Dispatchers.IO` is not public API on Native; `Dispatchers.Default` is multi-threaded here, so it
|
||||||
|
// still runs work off the main thread.
|
||||||
|
internal actual val ioDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
// JS is single-threaded; there is no dedicated I/O dispatcher, use default.
|
||||||
|
internal actual val ioDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
internal actual val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package fr.ajaury.gwenedeg.core.coroutines.data
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
// Wasm is single-threaded; there is no dedicated I/O dispatcher, use default
|
||||||
|
internal actual val ioDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
@@ -39,9 +39,13 @@ kotlin {
|
|||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
// Logging
|
// Core modules
|
||||||
|
implementation(projects.core.coroutines)
|
||||||
implementation(projects.core.logging)
|
implementation(projects.core.logging)
|
||||||
|
|
||||||
|
// Coroutines
|
||||||
|
implementation(libs.kotlinx.coroutinesCore)
|
||||||
|
|
||||||
// DI
|
// DI
|
||||||
implementation(project.dependencies.platform(libs.koin.bom))
|
implementation(project.dependencies.platform(libs.koin.bom))
|
||||||
implementation(libs.koin.core)
|
implementation(libs.koin.core)
|
||||||
|
|||||||
+11
-6
@@ -1,20 +1,25 @@
|
|||||||
package fr.ajaury.gwenedeg.subtitle.data
|
package fr.ajaury.gwenedeg.subtitle.data
|
||||||
|
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.domain.DispatcherProvider
|
||||||
import fr.ajaury.gwenedeg.core.logging.domain.Logger
|
import fr.ajaury.gwenedeg.core.logging.domain.Logger
|
||||||
import fr.ajaury.gwenedeg.subtitle.domain.Subtitle
|
import fr.ajaury.gwenedeg.subtitle.domain.Subtitle
|
||||||
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleRepository
|
import fr.ajaury.gwenedeg.subtitle.domain.SubtitleRepository
|
||||||
import fr.ajaury.gwenedeg.subtitle.model.CantGetSubtitleException
|
import fr.ajaury.gwenedeg.subtitle.model.CantGetSubtitleException
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
internal class LrcSubtitleRepository(
|
internal class LrcSubtitleRepository(
|
||||||
private val parser: LrcParser,
|
private val parser: LrcParser,
|
||||||
|
private val dispatcherProvider: DispatcherProvider,
|
||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
) : SubtitleRepository {
|
) : SubtitleRepository {
|
||||||
override suspend fun getSubtitle(content: String): Subtitle =
|
override suspend fun getSubtitle(content: String): Subtitle =
|
||||||
try {
|
withContext(dispatcherProvider.default) {
|
||||||
parser.parse(content = content)
|
try {
|
||||||
} catch (exception: Exception) {
|
parser.parse(content = content)
|
||||||
val message = "Failed to load subtitle: $content"
|
} catch (exception: Exception) {
|
||||||
logger.error(message = message, throwable = exception)
|
val message = "Failed to load subtitle: $content"
|
||||||
throw CantGetSubtitleException(message)
|
logger.error(message = message, throwable = exception)
|
||||||
|
throw CantGetSubtitleException(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ include(":shared")
|
|||||||
|
|
||||||
// Core modules
|
// Core modules
|
||||||
include(":core:audioplayer")
|
include(":core:audioplayer")
|
||||||
|
include(":core:coroutines")
|
||||||
include(":core:logging")
|
include(":core:logging")
|
||||||
|
|
||||||
// Data modules
|
// Data modules
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ kotlin {
|
|||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
// Core modules
|
// Core modules
|
||||||
implementation(projects.core.audioplayer)
|
implementation(projects.core.audioplayer)
|
||||||
|
implementation(projects.core.coroutines)
|
||||||
implementation(projects.core.logging)
|
implementation(projects.core.logging)
|
||||||
|
|
||||||
// Data modules
|
// Data modules
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.navigation3.runtime.NavEntry
|
import androidx.navigation3.runtime.NavEntry
|
||||||
import androidx.navigation3.ui.NavDisplay
|
import androidx.navigation3.ui.NavDisplay
|
||||||
import androidx.savedstate.compose.serialization.serializers.SnapshotStateListSerializer
|
import androidx.savedstate.compose.serialization.serializers.SnapshotStateListSerializer
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.di.coroutinesModule
|
||||||
import fr.ajaury.gwenedeg.core.logging.di.loggingModule
|
import fr.ajaury.gwenedeg.core.logging.di.loggingModule
|
||||||
import fr.ajaury.gwenedeg.di.sharedModule
|
import fr.ajaury.gwenedeg.di.sharedModule
|
||||||
import fr.ajaury.gwenedeg.navigation.Route
|
import fr.ajaury.gwenedeg.navigation.Route
|
||||||
@@ -26,6 +27,7 @@ fun App() {
|
|||||||
modules(
|
modules(
|
||||||
sharedModule,
|
sharedModule,
|
||||||
audioPlayerModule,
|
audioPlayerModule,
|
||||||
|
coroutinesModule,
|
||||||
loggingModule,
|
loggingModule,
|
||||||
subtitleModule
|
subtitleModule
|
||||||
)
|
)
|
||||||
|
|||||||
+9
-2
@@ -1,8 +1,15 @@
|
|||||||
package fr.ajaury.gwenedeg.resourcereader.data
|
package fr.ajaury.gwenedeg.resourcereader.data
|
||||||
|
|
||||||
|
import fr.ajaury.gwenedeg.core.coroutines.domain.DispatcherProvider
|
||||||
import fr.ajaury.gwenedeg.resourcereader.data.domain.ResourceReader
|
import fr.ajaury.gwenedeg.resourcereader.data.domain.ResourceReader
|
||||||
import gwenedeg.shared.generated.resources.Res
|
import gwenedeg.shared.generated.resources.Res
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
internal class ComposeResourceReader : ResourceReader {
|
internal class ComposeResourceReader(
|
||||||
override suspend fun read(resourcePath: String): String = Res.readBytes(resourcePath).decodeToString()
|
private val dispatcherProvider: DispatcherProvider,
|
||||||
|
) : ResourceReader {
|
||||||
|
override suspend fun read(resourcePath: String): String =
|
||||||
|
withContext(dispatcherProvider.io) {
|
||||||
|
Res.readBytes(resourcePath).decodeToString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user