Skip to content

Commit

Permalink
Add WASM sample app
Browse files Browse the repository at this point in the history
Uses HTML UI based on existing browser sample
  • Loading branch information
russhwolf committed Oct 15, 2023
1 parent 11e544b commit 4df8b17
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 1 deletion.
11 changes: 11 additions & 0 deletions sample/app-wasm-js/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.iml
.gradle
/local.properties
/.idea/caches/build_file_checksum.ser
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
.DS_Store
/build
/captures
.externalNativeBuild
43 changes: 43 additions & 0 deletions sample/app-wasm-js/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

/*
* Copyright 2019 Russell Wolf
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins {
kotlin("multiplatform")
id("org.jetbrains.compose") version "1.5.2"
}

kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasm {
browser {
runTask {
mainOutputFileName = "settings-demo.js"
}
}
binaries.executable()
}

sourceSets {
val wasmMain by getting {
dependencies {
implementation(project(":shared"))
implementation("com.russhwolf:multiplatform-settings:${rootProject.ext["library_version"]}")
}
}
}
}
58 changes: 58 additions & 0 deletions sample/app-wasm-js/src/wasmMain/kotlin/MicroHtml.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2023 Russell Wolf
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.russhwolf.settings.example.wasmjs

import kotlinx.dom.appendElement
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLOptionElement
import org.w3c.dom.HTMLOutputElement
import org.w3c.dom.HTMLSelectElement
import org.w3c.dom.events.Event

// DSL functions to mimic kotlinx.html until it gets wasm support

@DslMarker
annotation class MicroHtml

@MicroHtml
fun HTMLElement.div(body: HTMLDivElement.() -> Unit = {}) =
appendElement("div") { (this as HTMLDivElement).body() } as HTMLDivElement

@MicroHtml
fun HTMLElement.select(body: HTMLSelectElement.() -> Unit = {}) =
appendElement("select") { (this as HTMLSelectElement).body() } as HTMLSelectElement

@MicroHtml
fun HTMLElement.option(body: HTMLOptionElement.() -> Unit = {}) =
appendElement("option") { (this as HTMLOptionElement).body() } as HTMLOptionElement

@MicroHtml
fun HTMLElement.input(body: HTMLInputElement.() -> Unit = {}) =
appendElement("input") { (this as HTMLInputElement).body() } as HTMLInputElement

@MicroHtml
fun HTMLElement.button(body: HTMLButtonElement.() -> Unit = {}) =
appendElement("button") { (this as HTMLButtonElement).body() } as HTMLButtonElement

@MicroHtml
fun HTMLElement.output(body: HTMLOutputElement.() -> Unit = {}) =
appendElement("output") { (this as HTMLOutputElement).body() } as HTMLOutputElement

fun HTMLElement.onClick(block: (Event) -> Unit) = addEventListener("click", block)
97 changes: 97 additions & 0 deletions sample/app-wasm-js/src/wasmMain/kotlin/WasmBrowser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright 2023 Russell Wolf
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.russhwolf.settings.example.wasmjs

import com.russhwolf.settings.StorageSettings
import com.russhwolf.settings.example.SettingConfig
import com.russhwolf.settings.example.SettingsRepository
import kotlinx.browser.document
import kotlinx.dom.appendText
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLOutputElement
import org.w3c.dom.HTMLSelectElement

fun main() {
document.body?.apply {
div {
select = select {
settingsRepository.mySettings.forEach { setting ->
option {
appendText(setting.key)
}
}
}
}
div {
input = input {
type = "text"
}
}
div {
button {
appendText("Set Value")
onClick {
if (selectedItem.set(input.value)) {
showOutput("")
} else {
showOutput("INVALID VALUE")
}
}
}
}
div {
button {
appendText("Get Value")
onClick {
showOutput(selectedItem.get())
}
}
}
div {
button {
appendText("Remove Value")
onClick {
selectedItem.remove()
showOutput("Setting removed!")
}
}
}
div {
button {
appendText("Clear All Values")
onClick {
settingsRepository.clear()
showOutput("Settings cleared!")
}
}
}
div {
output = output()
}
}
}

private lateinit var input: HTMLInputElement
private lateinit var select: HTMLSelectElement
private lateinit var output: HTMLOutputElement

private val selectedItem: SettingConfig<*> get() = settingsRepository.mySettings[select.selectedIndex]
fun showOutput(value: String) {
output.value = value
}

private val settingsRepository: SettingsRepository by lazy { SettingsRepository(StorageSettings()) }
26 changes: 26 additions & 0 deletions sample/app-wasm-js/src/wasmMain/resources/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--
~ Copyright 2023 Russell Wolf
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Settings Demo</title>
</head>
<body>
<script src="settings-demo.js"></script>
</body>
</html>
3 changes: 2 additions & 1 deletion sample/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ include(
":shared",
":app-android",
":app-browser",
":app-desktop"
":app-desktop",
":app-wasm-js"
)
6 changes: 6 additions & 0 deletions sample/shared/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl

/*
* Copyright 2020 Russell Wolf
*
Expand Down Expand Up @@ -27,6 +29,10 @@ kotlin {
js {
browser()
}
@OptIn(ExperimentalWasmDsl::class)
wasm {
browser()
}

ios {
binaries {
Expand Down

0 comments on commit 4df8b17

Please sign in to comment.