added wasm/js target
This commit is contained in:
@@ -24,3 +24,6 @@ To run the application on iPhone device/simulator:
|
|||||||
- Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio
|
- Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio
|
||||||
Run iOS simulator UI tests: `./gradlew :composeApp:iosSimulatorArm64Test`
|
Run iOS simulator UI tests: `./gradlew :composeApp:iosSimulatorArm64Test`
|
||||||
|
|
||||||
|
### Wasm Browser (Alpha)
|
||||||
|
Run the browser application: `./gradlew :composeApp:wasmJsBrowserDevelopmentRun --continue`
|
||||||
|
Run browser UI tests: `./gradlew :composeApp:wasmJsBrowserTest`
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import com.android.build.api.dsl.ManagedVirtualDevice
|
|||||||
import org.jetbrains.compose.ExperimentalComposeLibrary
|
import org.jetbrains.compose.ExperimentalComposeLibrary
|
||||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||||
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
|
||||||
|
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.multiplatform)
|
alias(libs.plugins.multiplatform)
|
||||||
@@ -14,6 +16,24 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
@OptIn(ExperimentalWasmDsl::class)
|
||||||
|
wasmJs {
|
||||||
|
moduleName = "composeApp"
|
||||||
|
browser {
|
||||||
|
val projectDirPath = project.projectDir.path
|
||||||
|
commonWebpackConfig {
|
||||||
|
outputFileName = "composeApp.js"
|
||||||
|
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
|
||||||
|
static = (static ?: mutableListOf()).apply {
|
||||||
|
// Serve sources to debug inside browser
|
||||||
|
add(projectDirPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binaries.executable()
|
||||||
|
}
|
||||||
|
|
||||||
// export correct artifact to use all classes of library directly from Swift
|
// export correct artifact to use all classes of library directly from Swift
|
||||||
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java).all {
|
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java).all {
|
||||||
binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all {
|
binaries.withType(org.jetbrains.kotlin.gradle.plugin.mpp.Framework::class.java).all {
|
||||||
@@ -64,7 +84,6 @@ kotlin {
|
|||||||
implementation(libs.coil.network.ktor)
|
implementation(libs.coil.network.ktor)
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
implementation(libs.ktor.core)
|
implementation(libs.ktor.core)
|
||||||
implementation(libs.ktor.client.cio)
|
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
implementation(libs.koin.core)
|
implementation(libs.koin.core)
|
||||||
implementation(libs.koin.compose)
|
implementation(libs.koin.compose)
|
||||||
@@ -72,7 +91,6 @@ kotlin {
|
|||||||
implementation(libs.haze)
|
implementation(libs.haze)
|
||||||
implementation(libs.haze.materials)
|
implementation(libs.haze.materials)
|
||||||
implementation(libs.kstore)
|
implementation(libs.kstore)
|
||||||
implementation(libs.kstore.file)
|
|
||||||
implementation(libs.napier)
|
implementation(libs.napier)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +106,7 @@ kotlin {
|
|||||||
implementation(libs.androidx.activityCompose)
|
implementation(libs.androidx.activityCompose)
|
||||||
implementation(libs.kotlinx.coroutines.android)
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
implementation(libs.ktor.client.okhttp)
|
implementation(libs.ktor.client.okhttp)
|
||||||
|
implementation(libs.kstore.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmMain.dependencies {
|
jvmMain.dependencies {
|
||||||
@@ -95,10 +114,16 @@ kotlin {
|
|||||||
implementation(libs.kotlinx.coroutines.swing)
|
implementation(libs.kotlinx.coroutines.swing)
|
||||||
implementation(libs.ktor.client.okhttp)
|
implementation(libs.ktor.client.okhttp)
|
||||||
implementation(libs.appdirs)
|
implementation(libs.appdirs)
|
||||||
|
implementation(libs.kstore.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
iosMain.dependencies {
|
iosMain.dependencies {
|
||||||
implementation(libs.ktor.client.darwin)
|
implementation(libs.ktor.client.darwin)
|
||||||
|
implementation(libs.kstore.file)
|
||||||
|
}
|
||||||
|
|
||||||
|
wasmJsMain.dependencies {
|
||||||
|
implementation(libs.kstore.storage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,6 +153,11 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buildTypes {
|
||||||
|
getByName("release") {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
|
import dev.meloda.overseerr.appDir
|
||||||
|
import io.github.xxfast.kstore.KStore
|
||||||
|
import io.github.xxfast.kstore.file.storeOf
|
||||||
|
import okio.Path.Companion.toPath
|
||||||
|
|
||||||
|
actual class SettingsStoreProvider actual constructor() {
|
||||||
|
|
||||||
|
actual fun provideStore(): KStore<AppSettings> {
|
||||||
|
return storeOf(file = "$appDir/app_settings.json".toPath())
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
|
import dev.meloda.overseerr.appDir
|
||||||
|
import io.github.xxfast.kstore.KStore
|
||||||
|
import okio.Path.Companion.toPath
|
||||||
|
|
||||||
|
actual class SettingsStoreProvider actual constructor() {
|
||||||
|
actual fun provideStore(): KStore<AppSettings> {
|
||||||
|
return storeOf(file = "$appDir/app_settings.json".toPath())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
package dev.meloda.overseerr.network.di
|
package dev.meloda.overseerr.network.di
|
||||||
|
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.engine.cio.*
|
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val networkModule = module {
|
val networkModule = module {
|
||||||
single {
|
single {
|
||||||
HttpClient(CIO) {
|
HttpClient {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -3,11 +3,8 @@ package dev.meloda.overseerr.settings
|
|||||||
import dev.meloda.overseerr.ext.setValue
|
import dev.meloda.overseerr.ext.setValue
|
||||||
import dev.meloda.overseerr.settings.model.AppSettings
|
import dev.meloda.overseerr.settings.model.AppSettings
|
||||||
import io.github.xxfast.kstore.KStore
|
import io.github.xxfast.kstore.KStore
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.IO
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
interface SettingsController {
|
interface SettingsController {
|
||||||
val settings: StateFlow<AppSettings>
|
val settings: StateFlow<AppSettings>
|
||||||
@@ -22,13 +19,13 @@ class SettingsControllerImpl(
|
|||||||
|
|
||||||
override val settings = MutableStateFlow(AppSettings.EMPTY)
|
override val settings = MutableStateFlow(AppSettings.EMPTY)
|
||||||
|
|
||||||
override suspend fun updateAppSettings(update: (AppSettings) -> AppSettings) = withContext(Dispatchers.IO) {
|
override suspend fun updateAppSettings(update: (AppSettings) -> AppSettings) {
|
||||||
store.set(update(settings.value))
|
store.set(update(settings.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadAppSettings(): AppSettings = withContext(Dispatchers.IO) {
|
override suspend fun loadAppSettings(): AppSettings {
|
||||||
val loadedSettings = store.get() ?: AppSettings.EMPTY
|
val loadedSettings = store.get() ?: AppSettings.EMPTY
|
||||||
settings.setValue { loadedSettings }
|
settings.setValue { loadedSettings }
|
||||||
loadedSettings
|
return loadedSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
package dev.meloda.overseerr.settings.di
|
package dev.meloda.overseerr.settings.di
|
||||||
|
|
||||||
import dev.meloda.overseerr.appDir
|
|
||||||
import dev.meloda.overseerr.settings.SettingsController
|
import dev.meloda.overseerr.settings.SettingsController
|
||||||
import dev.meloda.overseerr.settings.SettingsControllerImpl
|
import dev.meloda.overseerr.settings.SettingsControllerImpl
|
||||||
import dev.meloda.overseerr.settings.model.AppSettings
|
import dev.meloda.overseerr.settings.model.SettingsStoreProvider
|
||||||
import io.github.xxfast.kstore.file.storeOf
|
|
||||||
import okio.Path.Companion.toPath
|
|
||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
import org.koin.dsl.bind
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val settingsModule = module {
|
val settingsModule = module {
|
||||||
single {
|
single { SettingsStoreProvider().provideStore() }
|
||||||
storeOf<AppSettings>(file = "$appDir/app_settings.json".toPath())
|
|
||||||
}
|
|
||||||
singleOf(::SettingsControllerImpl) bind SettingsController::class
|
singleOf(::SettingsControllerImpl) bind SettingsController::class
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
|
import io.github.xxfast.kstore.KStore
|
||||||
|
|
||||||
|
expect class SettingsStoreProvider() {
|
||||||
|
|
||||||
|
fun provideStore(): KStore<AppSettings>
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
|
import dev.meloda.overseerr.appDir
|
||||||
|
import io.github.xxfast.kstore.KStore
|
||||||
|
import io.github.xxfast.kstore.file.storeOf
|
||||||
|
import okio.Path.Companion.toPath
|
||||||
|
|
||||||
|
actual class SettingsStoreProvider actual constructor() {
|
||||||
|
actual fun provideStore(): KStore<AppSettings> {
|
||||||
|
return storeOf(file = "$appDir/app_settings.json".toPath())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.meloda.overseerr.model
|
||||||
|
|
||||||
|
actual class Platform actual constructor() {
|
||||||
|
actual val name: String = "JS"
|
||||||
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.meloda.overseerr.settings.model
|
||||||
|
|
||||||
|
import io.github.xxfast.kstore.KStore
|
||||||
|
import io.github.xxfast.kstore.storage.storeOf
|
||||||
|
|
||||||
|
actual class SettingsStoreProvider actual constructor() {
|
||||||
|
actual fun provideStore(): KStore<AppSettings> = storeOf(key = "app_settings")
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package dev.meloda.overseerr.theme
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal actual fun SystemAppearance(isDark: Boolean) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
|
import androidx.compose.ui.window.ComposeViewport
|
||||||
|
import dev.meloda.overseerr.App
|
||||||
|
import dev.meloda.overseerr.di.appModule
|
||||||
|
import kotlinx.browser.document
|
||||||
|
import org.koin.core.context.startKoin
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
fun main() {
|
||||||
|
ComposeViewport(document.body!!) {
|
||||||
|
startKoin {
|
||||||
|
modules(appModule)
|
||||||
|
}
|
||||||
|
App()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>KotlinProject</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles.css">
|
||||||
|
<script type="application/javascript" src="composeApp.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" }
|
|||||||
haze-materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" }
|
haze-materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" }
|
||||||
kstore = { module = "io.github.xxfast:kstore", version.ref = "kstore" }
|
kstore = { module = "io.github.xxfast:kstore", version.ref = "kstore" }
|
||||||
kstore-file = { module = "io.github.xxfast:kstore-file", version.ref = "kstore" }
|
kstore-file = { module = "io.github.xxfast:kstore-file", version.ref = "kstore" }
|
||||||
|
kstore-storage = { module = "io.github.xxfast:kstore-storage", version.ref = "kstore" }
|
||||||
appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" }
|
appdirs = { module = "net.harawata:appdirs", version.ref = "appdirs" }
|
||||||
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
|
napier = { module = "io.github.aakira:napier", version.ref = "napier" }
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ dependencyResolutionManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/wasm/experimental")
|
|
||||||
maven("https://maven.pkg.jetbrains.space/public/p/ktor/eap")
|
maven("https://maven.pkg.jetbrains.space/public/p/ktor/eap")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user