Add test-app module with initial UI and backend setup

Introduced a new `test-app` module with a basic Kotlin/JS UI and a Kotlin/JVM backend. Updated dependencies to use `api` where applicable and made configuration changes to support composite builds.
This commit is contained in:
2024-12-31 20:00:30 +01:00
parent 684234e168
commit 4259b054b3
8 changed files with 377 additions and 7 deletions

15
.idea/gradle.xml generated
View File

@@ -4,11 +4,22 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="" />
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT">
<builds>
<build path="$PROJECT_DIR$" name="vst-ui-base">
<projects>
<project path="$PROJECT_DIR$" />
</projects>
</build>
</builds>
</compositeBuild>
</compositeConfiguration>
<option name="externalProjectPath" value="$PROJECT_DIR$/test-app" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/test-app" />
</set>
</option>
</GradleProjectSettings>

2
.idea/kotlinc.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.23" />
<option name="version" value="2.1.0" />
</component>
</project>

View File

@@ -40,12 +40,12 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("nl.astraeus:kotlin-css-generator:1.0.10")
api("nl.astraeus:kotlin-css-generator:1.0.10")
}
}
val jsMain by getting {
dependencies {
implementation("nl.astraeus:kotlin-komponent:1.2.4")
api("nl.astraeus:kotlin-komponent:1.2.4")
}
}
val jsTest by getting {
@@ -55,7 +55,7 @@ kotlin {
}
val jvmMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
api("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
implementation("io.undertow:undertow-core:2.3.14.Final")
implementation("io.undertow:undertow-websockets-jsr:2.3.14.Final")
@@ -65,7 +65,7 @@ kotlin {
implementation("com.zaxxer:HikariCP:4.0.3")
implementation("nl.astraeus:simple-jdbc-stats:1.6.1")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.11.0")
api("org.jetbrains.kotlinx:kotlinx-html-jvm:0.11.0")
}
}
}

View File

@@ -1,5 +1,7 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0"
}
rootProject.name = "vst-ui-base"
//include("test-app")

View File

@@ -0,0 +1,5 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
includeBuild("..")

View File

@@ -0,0 +1,19 @@
package nl.astraeus.vst.ui
import kotlinx.browser.document
import nl.astraeus.komp.Komponent
import nl.astraeus.komp.UnsafeMode
import nl.astraeus.vst.ui.css.CssSettings
import nl.astraeus.vst.ui.view.MainView
val mainView: MainView by lazy {
MainView()
}
fun main() {
CssSettings.shortId = false
CssSettings.preFix = "vst"
Komponent.unsafeMode = UnsafeMode.UNSAFE_SVG_ONLY
Komponent.create(document.body!!, mainView)
}

View File

@@ -0,0 +1,312 @@
@file:OptIn(ExperimentalJsExport::class)
package nl.astraeus.vst.ui.view
import kotlinx.html.div
import kotlinx.html.h1
import kotlinx.html.js.onClickFunction
import kotlinx.html.option
import kotlinx.html.select
import kotlinx.html.span
import nl.astraeus.css.properties.AlignItems
import nl.astraeus.css.properties.BoxSizing
import nl.astraeus.css.properties.Display
import nl.astraeus.css.properties.FlexDirection
import nl.astraeus.css.properties.FontWeight
import nl.astraeus.css.properties.JustifyContent
import nl.astraeus.css.properties.Position
import nl.astraeus.css.properties.Transform
import nl.astraeus.css.properties.em
import nl.astraeus.css.properties.hsla
import nl.astraeus.css.properties.prc
import nl.astraeus.css.properties.px
import nl.astraeus.css.properties.rem
import nl.astraeus.css.properties.vh
import nl.astraeus.css.properties.vw
import nl.astraeus.css.style.Style
import nl.astraeus.css.style.cls
import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent
import nl.astraeus.vst.ui.components.ExpKnobComponent
import nl.astraeus.vst.ui.components.KnobComponent
import nl.astraeus.vst.ui.css.Css
import nl.astraeus.vst.ui.css.Css.defineCss
import nl.astraeus.vst.ui.css.Css.noTextSelect
import nl.astraeus.vst.ui.css.CssName
import nl.astraeus.vst.ui.css.hover
class MainView : Komponent() {
private var messages: MutableList<String> = ArrayList()
var started = true
fun addMessage(message: String) {
messages.add(message)
while (messages.size > 10) {
messages.removeAt(0)
}
requestUpdate()
}
override fun renderUpdate() {
println("Rendering MainView")
super.renderUpdate()
}
override fun HtmlBuilder.render() {
div(MainDivCss.name) {
if (!started) {
div(StartSplashCss.name) {
div(StartBoxCss.name) {
div(StartButtonCss.name) {
+"START"
}
}
onClickFunction = {
}
}
}
h1 {
+"VST UI-base Test"
}
div {
span {
+"Midi input: "
select {
option {
+"None"
value = "none"
}
/* for (mi in Midi.inputs) {
option {
+mi.name
value = mi.id
selected = mi.id == Midi.currentInput?.id
}
}
onChangeFunction = { event ->
val target = event.target as HTMLSelectElement
if (target.value == "none") {
Midi.setInput(null)
} else {
Midi.setInput(target.value)
}
}
}
*/
}
span {
+"channel:"
/*
input {
type = InputType.number
value = VstChipWorklet.midiChannel.toString()
onInputFunction = { event ->
val target = event.target as HTMLInputElement
kotlin.io.println("onInput channel: $target")
VstChipWorklet.midiChannel = target.value.toInt()
}
}
*/
}
}
/*
div {
span(ButtonBarCss.name) {
+"SAVE"
onClickFunction = {
val patch = VstChipWorklet.save().copy(
midiId = Midi.currentInput?.id ?: "",
midiName = Midi.currentInput?.name ?: ""
)
WebsocketClient.send("SAVE\n${JSON.stringify(patch)}")
}
}
span(ButtonBarCss.name) {
+"STOP"
onClickFunction = {
VstChipWorklet.postDirectlyToWorklet(
TimedMidiMessage(getCurrentTime(), (0xb0 + midiChannel).toByte(), 123, 0)
.data.buffer.data
)
}
}
}
*/
div(ControlsCss.name) {
include(
ExpKnobComponent(
value = 0.0,
label = "Volume",
minValue = 0.0,
maxValue = 1.0,
step = 5.0 / 127.0,
width = 100,
height = 120,
) { value ->
}
)
include(
KnobComponent(
value = 0.5,
label = "Duty cycle",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 100,
height = 120,
) { value ->
}
)
include(
KnobComponent(
value = 0.5,
label = "Duty cycle",
minValue = 0.0,
maxValue = 1.0,
step = 2.0 / 127.0,
width = 500,
height = 600,
) { value ->
}
)
}
}
}
}
companion object MainViewCss : CssName() {
object MainDivCss : CssName()
object ActiveCss : CssName()
object ButtonCss : CssName()
object ButtonBarCss : CssName()
object SelectedCss : CssName()
object NoteBarCss : CssName()
object StartSplashCss : CssName()
object StartBoxCss : CssName()
object StartButtonCss : CssName()
object ControlsCss : CssName()
init {
defineCss {
select("*") {
select("*:before") {
select("*:after") {
boxSizing(BoxSizing.borderBox)
}
}
}
select("html", "body") {
margin(0.px)
padding(0.px)
height(100.prc)
}
select("html", "body") {
backgroundColor(Css.currentStyle.mainBackgroundColor)
color(Css.currentStyle.mainFontColor)
fontFamily("JetbrainsMono, monospace")
fontSize(14.px)
fontWeight(FontWeight.bold)
//transition()
noTextSelect()
}
select("input", "textarea") {
backgroundColor(Css.currentStyle.inputBackgroundColor)
color(Css.currentStyle.mainFontColor)
border("none")
}
select(cls(ButtonCss)) {
margin(1.rem)
commonButton()
}
select(cls(ButtonBarCss)) {
margin(1.rem, 0.px)
commonButton()
}
select(cls(ActiveCss)) {
//backgroundColor(Css.currentStyle.selectedBackgroundColor)
}
select(cls(NoteBarCss)) {
minHeight(4.rem)
}
select(cls(MainDivCss)) {
margin(1.rem)
}
select("select") {
plain("appearance", "none")
border("0")
outline("0")
width(20.rem)
padding(0.5.rem, 2.rem, 0.5.rem, 0.5.rem)
backgroundImage("url('https://upload.wikimedia.org/wikipedia/commons/9/9d/Caret_down_font_awesome_whitevariation.svg')")
background("right 0.8em center/1.4em")
backgroundColor(Css.currentStyle.inputBackgroundColor)
color(Css.currentStyle.mainFontColor)
borderRadius(0.25.em)
}
select(cls(StartSplashCss)) {
position(Position.fixed)
left(0.px)
top(0.px)
width(100.vw)
height(100.vh)
zIndex(100)
backgroundColor(hsla(32, 0, 5, 0.65))
select(cls(StartBoxCss)) {
position(Position.relative)
left(25.vw)
top(25.vh)
width(50.vw)
height(50.vh)
backgroundColor(hsla(239, 50, 10, 1.0))
borderColor(Css.currentStyle.mainFontColor)
borderWidth(2.px)
select(cls(StartButtonCss)) {
position(Position.absolute)
left(50.prc)
top(50.prc)
transform(Transform("translate(-50%, -50%)"))
padding(1.rem)
backgroundColor(Css.currentStyle.buttonBackgroundColor)
cursor("pointer")
}
}
}
select(ControlsCss.cls()) {
display(Display.flex)
flexDirection(FlexDirection.row)
justifyContent(JustifyContent.flexStart)
alignItems(AlignItems.center)
margin(1.rem)
padding(1.rem)
backgroundColor(Css.currentStyle.mainBackgroundColor)
}
}
}
private fun Style.commonButton() {
display(Display.inlineBlock)
padding(1.rem)
backgroundColor(Css.currentStyle.buttonBackgroundColor)
borderColor(Css.currentStyle.buttonBorderColor)
borderWidth(Css.currentStyle.buttonBorderWidth)
color(Css.currentStyle.mainFontColor)
hover {
backgroundColor(Css.currentStyle.buttonBackgroundColor.hover())
}
and(SelectedCss.cls()) {
backgroundColor(Css.currentStyle.buttonBackgroundColor.hover().hover().hover())
}
}
}
}

View File

@@ -0,0 +1,21 @@
package nl.astraeus.vst.ui
import nl.astraeus.vst.base.Settings
import nl.astraeus.vst.base.db.Database
import nl.astraeus.vst.base.web.UndertowServer
fun main() {
Thread.setDefaultUncaughtExceptionHandler { _, e ->
e.printStackTrace()
}
Settings.port = 9999
Settings.jdbcStatsPort = 7777
Database.start()
UndertowServer.start(
"Vst UI-base Test",
"/vst-ui-base-test.js"
)
}