diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2d51b20..4b43298d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,8 +11,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-20.04, macos-12, windows-2022] - gradle: [8.3] + os: [ ubuntu-20.04, macos-14, windows-2022 ] + gradle: [ 8.3 ] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index 228a7a77..062c0158 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ sample/desktopApp/cache sample/desktopApp/DawnCache sample/desktopApp/GPUCache sample/desktopApp/*.log -site \ No newline at end of file +site +kotlin-js-store/yarn.lock \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index cd047c61..7cdefaaf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,34 +1,47 @@ #Gradle org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" + #Kotlin kotlin.code.style=official + #MPP kotlin.mpp.stability.nowarn=true kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.androidSourceSetLayoutVersion=2 + +#Compose +org.jetbrains.compose.experimental.uikit.enabled=true +org.jetbrains.compose.experimental.wasm.enabled=true + #Android android.useAndroidX=true android.compileSdk=34 android.targetSdk=34 android.minSdk=21 + #Versions kotlin.version=1.9.23 agp.version=8.1.1 -compose.version=1.6.1 +compose.version=1.6.10-rc01 coroutines.version=1.8.0 + GROUP=io.github.kevinnzou POM_ARTIFACT_ID=compose-webview-multiplatform VERSION_NAME=1.9.7 + POM_NAME=Compose WebView Multiplatform POM_INCEPTION_YEAR=2023 POM_DESCRIPTION=WebView for JetBrains Compose Multiplatform POM_URL=https://github.com/KevinnZou/compose-webview-multiplatform + POM_SCM_URL=https://github.com/KevinnZou/compose-webview-multiplatform POM_SCM_CONNECTION=scm:git:git://github.com/KevinnZou/compose-webview-multiplatform.git POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/KevinnZou/compose-webview-multiplatform.git + POM_LICENCE_NAME=The Apache Software License, Version 2.0 POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt POM_LICENCE_DIST=repo + POM_DEVELOPER_ID=kevinzou POM_DEVELOPER_NAME=Kevin Zou POM_DEVELOPER_URL=https://github.com/KevinnZou/ diff --git a/sample/shared/build.gradle.kts b/sample/shared/build.gradle.kts index a1b190d9..1b57135b 100644 --- a/sample/shared/build.gradle.kts +++ b/sample/shared/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl + plugins { kotlin("multiplatform") kotlin("plugin.serialization") @@ -10,6 +12,17 @@ plugins { kotlin { targetHierarchy.default() + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + moduleName = "composeWebViewSample" + browser { + commonWebpackConfig { + outputFileName = "composeWebViewSample.js" + } + } + binaries.executable() + } + androidTarget { compilations.all { kotlinOptions { @@ -32,7 +45,7 @@ kotlin { sourceSets { val coroutinesVersion = extra["coroutines.version"] as String - val voyagerVersion = "1.0.0-rc10" + val voyagerVersion = "1.1.0-alpha03" val commonMain by getting { dependencies { @@ -45,7 +58,7 @@ kotlin { implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion") implementation("cafe.adriel.voyager:voyager-tab-navigator:$voyagerVersion") api(project(":webview")) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") implementation("org.jetbrains.kotlinx:atomicfu:0.23.2") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") implementation("org.jetbrains.androidx.navigation:navigation-compose:2.7.0-alpha03") @@ -91,3 +104,7 @@ android { jvmToolchain(17) } } + +compose.experimental { + web.application {} +} diff --git a/sample/shared/src/commonMain/composeResources/assets/index.html b/sample/shared/src/commonMain/resources/assets/index.html similarity index 100% rename from sample/shared/src/commonMain/composeResources/assets/index.html rename to sample/shared/src/commonMain/resources/assets/index.html diff --git a/sample/shared/src/commonMain/composeResources/assets/script.js b/sample/shared/src/commonMain/resources/assets/script.js similarity index 100% rename from sample/shared/src/commonMain/composeResources/assets/script.js rename to sample/shared/src/commonMain/resources/assets/script.js diff --git a/sample/shared/src/commonMain/composeResources/assets/styles.css b/sample/shared/src/commonMain/resources/assets/styles.css similarity index 100% rename from sample/shared/src/commonMain/composeResources/assets/styles.css rename to sample/shared/src/commonMain/resources/assets/styles.css diff --git a/sample/shared/src/wasmJsMain/kotlin/com/kevinnzou/sample/main.kt b/sample/shared/src/wasmJsMain/kotlin/com/kevinnzou/sample/main.kt new file mode 100644 index 00000000..0c80fc9d --- /dev/null +++ b/sample/shared/src/wasmJsMain/kotlin/com/kevinnzou/sample/main.kt @@ -0,0 +1,13 @@ +package com.kevinnzou.sample + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.window.CanvasBasedWindow + +@OptIn(ExperimentalComposeUiApi::class) +fun main() { + CanvasBasedWindow(canvasElementId = "ComposeTarget") { WebViewApp() } +} + +actual fun getPlatformName(): String { + return "JS/WASM" +} diff --git a/sample/shared/src/wasmJsMain/resources/index.html b/sample/shared/src/wasmJsMain/resources/index.html new file mode 100644 index 00000000..ee01e676 --- /dev/null +++ b/sample/shared/src/wasmJsMain/resources/index.html @@ -0,0 +1,12 @@ + + + + + Compose App + + + + + + + \ No newline at end of file diff --git a/webview/build.gradle.kts b/webview/build.gradle.kts index 5731a505..683eb3f8 100644 --- a/webview/build.gradle.kts +++ b/webview/build.gradle.kts @@ -1,5 +1,8 @@ @file:Suppress("UNUSED_VARIABLE", "OPT_IN_USAGE") +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl + + plugins { kotlin("multiplatform") id("com.android.library") @@ -14,6 +17,17 @@ kotlin { targetHierarchy.default() + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + moduleName = "composeWebView" + browser { + commonWebpackConfig { + outputFileName = "composeWebView.js" + } + } + binaries.executable() + } + androidTarget { publishLibraryVariants("release") } @@ -38,11 +52,12 @@ kotlin { dependencies { implementation(compose.runtime) implementation(compose.foundation) + implementation(compose.material3) @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") implementation("co.touchlab:kermit:2.0.3") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") } } val androidMain by getting { @@ -110,3 +125,7 @@ mavenPublishing { publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.S01, automaticRelease = true) signAllPublications() } + +compose.experimental { + web.application {} +} diff --git a/webview/src/commonMain/kotlin/com/multiplatform/webview/util/Platform.kt b/webview/src/commonMain/kotlin/com/multiplatform/webview/util/Platform.kt index 2bd56ca7..ee83de38 100644 --- a/webview/src/commonMain/kotlin/com/multiplatform/webview/util/Platform.kt +++ b/webview/src/commonMain/kotlin/com/multiplatform/webview/util/Platform.kt @@ -23,6 +23,11 @@ internal sealed class Platform { */ data object IOS : Platform() + /** + * The WasmJs platform. + */ + data object WasmJs : Platform() + /** * Whether the current platform is Android. */ @@ -37,6 +42,11 @@ internal sealed class Platform { * Whether the current platform is iOS. */ fun isIOS() = this is IOS + + /** + * Whether the current platform is WasmJs. + */ + fun isWasmJs() = this is WasmJs } /** diff --git a/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/cookie/WasmJsCookieManager.kt b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/cookie/WasmJsCookieManager.kt new file mode 100644 index 00000000..fa519cbd --- /dev/null +++ b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/cookie/WasmJsCookieManager.kt @@ -0,0 +1,38 @@ +package com.multiplatform.webview.cookie + +/** + * WasmJs implementation of [CookieManager] + */ +class WasmJsCookieManager : CookieManager { + override suspend fun setCookie( + url: String, + cookie: Cookie, + ) { + // TODO + } + + override suspend fun getCookies(url: String): List { + return emptyList() + } + + override suspend fun removeAllCookies() { + // TODO + } + + override suspend fun removeCookies(url: String) { + // TODO + } +} + +/** + * Creates a [CookieManager] instance. + */ +@Suppress("FunctionName") +actual fun WebViewCookieManager(): CookieManager { + return WasmJsCookieManager() +} + +actual fun getCookieExpirationDate(expiresDate: Long): String { + // TODO + return "0" +} diff --git a/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/util/Platform.wasmJs.kt b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/util/Platform.wasmJs.kt new file mode 100644 index 00000000..98b736b0 --- /dev/null +++ b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/util/Platform.wasmJs.kt @@ -0,0 +1,21 @@ +package com.multiplatform.webview.util + +/** + * Get the current platform. + */ +internal actual fun getPlatform(): Platform { + return Platform.WasmJs +} + +internal actual fun getPlatformVersion(): String { + // TODO + return "0.0.0" +} + +internal actual fun getPlatformVersionDouble(): Double { + val systemVersion = getPlatformVersion() + val components = systemVersion.split(".") + val major = components.getOrNull(0)?.toDoubleOrNull() ?: 0.0 + val minor = components.getOrNull(1)?.toDoubleOrNull() ?: 0.0 + return major + (minor / 10.0) +} diff --git a/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WasmJsWebViewBundle.kt b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WasmJsWebViewBundle.kt new file mode 100644 index 00000000..c73b4d47 --- /dev/null +++ b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WasmJsWebViewBundle.kt @@ -0,0 +1,3 @@ +package com.multiplatform.webview.web + +actual class WebViewBundle diff --git a/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WebView.wasmJs.kt b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WebView.wasmJs.kt new file mode 100644 index 00000000..4f4a66d6 --- /dev/null +++ b/webview/src/wasmJsMain/kotlin/com/multiplatform/webview/web/WebView.wasmJs.kt @@ -0,0 +1,30 @@ +package com.multiplatform.webview.web + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.multiplatform.webview.jsbridge.WebViewJsBridge + +/** + * Expect API of [WebView] that is implemented in the platform-specific modules. + */ +@Composable +actual fun ActualWebView( + state: WebViewState, + modifier: Modifier, + captureBackPresses: Boolean, + navigator: WebViewNavigator, + webViewJsBridge: WebViewJsBridge?, + onCreated: () -> Unit, + onDispose: () -> Unit, +) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + Text("WebView is not supported on this platform yet.") + } +}