diff --git a/GloVeEmbeddings/app/build.gradle.kts b/GloVeEmbeddings/app/build.gradle.kts index f89c98b..336d06d 100644 --- a/GloVeEmbeddings/app/build.gradle.kts +++ b/GloVeEmbeddings/app/build.gradle.kts @@ -93,3 +93,27 @@ compose.desktop { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/samples/glove/app/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.samples.glove.app + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/GloVeEmbeddings/app/src/commonMain/kotlin/sk/ainet/samples/glove/app/App.kt b/GloVeEmbeddings/app/src/commonMain/kotlin/sk/ainet/samples/glove/app/App.kt index 7abf439..f7ad30f 100644 --- a/GloVeEmbeddings/app/src/commonMain/kotlin/sk/ainet/samples/glove/app/App.kt +++ b/GloVeEmbeddings/app/src/commonMain/kotlin/sk/ainet/samples/glove/app/App.kt @@ -41,6 +41,7 @@ import androidx.compose.ui.unit.dp import sk.ainet.ui.components.LoadingIndicator import sk.ainet.ui.theme.SKaiNETTheme import sk.ainet.ui.theme.ThemeController +import sk.ainet.ui.components.PoweredBySKaiNET /** * Offline embeddings explorer: type a word to see its nearest neighbours, or run vector @@ -73,6 +74,7 @@ public fun App() { }, ) }, + bottomBar = { PoweredBySKaiNET(BuildInfo.SKAINET_VERSION) }, ) { padding -> Column(Modifier.fillMaxSize().padding(padding).padding(16.dp)) { when (val s = vm.load) { diff --git a/IrisDemo/webapp.json b/IrisDemo/webapp.json new file mode 100644 index 0000000..11733a1 --- /dev/null +++ b/IrisDemo/webapp.json @@ -0,0 +1,9 @@ +{ + "id": "irisdemo", + "name": "Iris Classifier", + "description": "Trains a small dense classifier on the Iris dataset with the SKaiNET sequential DSL, Adam and the training runner, then reports test accuracy — a JVM command-line sample.", + "platforms": [ + "cli", + "jvm" + ] +} diff --git a/KernelRace/androidApp/build.gradle.kts b/KernelRace/androidApp/build.gradle.kts index 80b1696..9fffd70 100644 --- a/KernelRace/androidApp/build.gradle.kts +++ b/KernelRace/androidApp/build.gradle.kts @@ -49,7 +49,6 @@ android { }.getProperty("HF_TOKEN") ?: "" buildConfigField("String", "HF_TOKEN", "\"$hfToken\"") // Shown next to the logo — always matches the dependency in the catalog. - buildConfigField("String", "SKAINET_VERSION", "\"${libs.versions.skainet.asProvider().get()}\"") } buildFeatures { diff --git a/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/MainActivity.kt b/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/MainActivity.kt index 019a0c1..0453dc9 100644 --- a/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/MainActivity.kt +++ b/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/MainActivity.kt @@ -25,7 +25,7 @@ class MainActivity : ComponentActivity() { setContent { App( viewModel = viewModel, - skainetVersion = BuildConfig.SKAINET_VERSION, + skainetVersion = SKAINET_VERSION, kernelControls = { busy, vm, currentPrompt -> KernelRaceControls(busy, vm, currentPrompt) }, ) } diff --git a/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/ScalarActivity.kt b/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/ScalarActivity.kt index d86e724..39b5ac5 100644 --- a/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/ScalarActivity.kt +++ b/KernelRace/androidApp/src/main/kotlin/sk/ainet/samples/kernelrace/ScalarActivity.kt @@ -48,7 +48,7 @@ class ScalarActivity : ComponentActivity() { setContent { App( viewModel = viewModel, - skainetVersion = BuildConfig.SKAINET_VERSION, + skainetVersion = SKAINET_VERSION, kernelControls = { busy, vm, currentPrompt -> KernelRaceControls(busy, vm, currentPrompt) }, ) } diff --git a/KernelRace/composeApp/build.gradle.kts b/KernelRace/composeApp/build.gradle.kts index c4f9541..43d8a1c 100644 --- a/KernelRace/composeApp/build.gradle.kts +++ b/KernelRace/composeApp/build.gradle.kts @@ -121,3 +121,25 @@ compose.desktop { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/samples/kernelrace/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.samples.kernelrace + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |const val SKAINET_VERSION: String = "$skainetVersion" + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/KernelRace/composeApp/src/commonMain/kotlin/sk/ainet/samples/kernelrace/BuildInfo.kt b/KernelRace/composeApp/src/commonMain/kotlin/sk/ainet/samples/kernelrace/BuildInfo.kt deleted file mode 100644 index b273f04..0000000 --- a/KernelRace/composeApp/src/commonMain/kotlin/sk/ainet/samples/kernelrace/BuildInfo.kt +++ /dev/null @@ -1,5 +0,0 @@ -package sk.ainet.samples.kernelrace - -/** Desktop/wasm display version — keep in sync with `skainet` in gradle/libs.versions.toml. - * Android reads the real catalog value at build time via `BuildConfig.SKAINET_VERSION` instead. */ -const val SKAINET_VERSION = "0.39.1" diff --git a/KllamaDemo/composeApp/build.gradle.kts b/KllamaDemo/composeApp/build.gradle.kts index 1d78731..c81a913 100644 --- a/KllamaDemo/composeApp/build.gradle.kts +++ b/KllamaDemo/composeApp/build.gradle.kts @@ -161,3 +161,27 @@ compose.desktop { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/apps/kllama/chat/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.apps.kllama.chat + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/KllamaDemo/composeApp/src/commonMain/kotlin/sk/ainet/apps/kllama/chat/App.kt b/KllamaDemo/composeApp/src/commonMain/kotlin/sk/ainet/apps/kllama/chat/App.kt index ab518f8..d855164 100644 --- a/KllamaDemo/composeApp/src/commonMain/kotlin/sk/ainet/apps/kllama/chat/App.kt +++ b/KllamaDemo/composeApp/src/commonMain/kotlin/sk/ainet/apps/kllama/chat/App.kt @@ -8,6 +8,9 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import sk.ainet.apps.kllama.chat.playground.QwenPlaygroundHost import sk.ainet.ui.theme.SKaiNETTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import sk.ainet.ui.components.PoweredBySKaiNET /** * Main app composable with SKaiNET Design System theming. Renders the @@ -23,7 +26,10 @@ fun App( .fillMaxSize() .background(MaterialTheme.colorScheme.background) ) { - QwenPlaygroundHost() + Column { + Box(Modifier.weight(1f)) { QwenPlaygroundHost() } + PoweredBySKaiNET(BuildInfo.SKAINET_VERSION) + } } } } diff --git a/KllamaDemo/webapp.json b/KllamaDemo/webapp.json new file mode 100644 index 0000000..694af06 --- /dev/null +++ b/KllamaDemo/webapp.json @@ -0,0 +1,18 @@ +{ + "id": "kllamademo", + "name": "Qwen3 Playground (KllamaDemo)", + "description": "Transformer explainer and chat with Qwen3-0.6B running fully in the browser on SKaiNET: the ~280 MB Q3_K_S GGUF model is bundled, so the first load is large and later loads hit the browser cache.", + "platforms": [ + "android", + "ios", + "desktop", + "wasm" + ], + "distDirs": [ + "composeApp/build/dist/wasmJs/productionExecutable" + ], + "build": { + "command": "./gradlew :composeApp:wasmJsBrowserDistribution", + "description": "Builds the wasm browser distribution, including the bundled ~280 MB Qwen3-0.6B GGUF model" + } +} diff --git a/MNISTDemo/composeApp/src/commonMain/kotlin/sk/ai/net/samples/kmp/mnist/demo/screens/HomeScreen.kt b/MNISTDemo/composeApp/src/commonMain/kotlin/sk/ai/net/samples/kmp/mnist/demo/screens/HomeScreen.kt index 210aec6..e465c72 100644 --- a/MNISTDemo/composeApp/src/commonMain/kotlin/sk/ai/net/samples/kmp/mnist/demo/screens/HomeScreen.kt +++ b/MNISTDemo/composeApp/src/commonMain/kotlin/sk/ai/net/samples/kmp/mnist/demo/screens/HomeScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import sk.ainet.clean.BuildInfo +import sk.ainet.ui.components.PoweredBySKaiNET /** * Home screen with app description and mode selection @@ -194,15 +195,8 @@ fun HomeScreen( } } - // Powered by SKaiNET Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Powered by SKaiNET ${BuildInfo.SKAINET_VERSION}", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - textAlign = TextAlign.Center, - modifier = Modifier.padding(bottom = 16.dp) - ) + PoweredBySKaiNET(BuildInfo.SKAINET_VERSION, modifier = Modifier.padding(bottom = 8.dp)) } } diff --git a/MNISTDemo/shared/build.gradle.kts b/MNISTDemo/shared/build.gradle.kts index 88a1025..534eb26 100644 --- a/MNISTDemo/shared/build.gradle.kts +++ b/MNISTDemo/shared/build.gradle.kts @@ -55,3 +55,26 @@ kotlin { } } +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/clean/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.clean + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/clean/BuildInfo.kt b/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/clean/BuildInfo.kt deleted file mode 100644 index 56c8864..0000000 --- a/MNISTDemo/shared/src/commonMain/kotlin/sk/ainet/clean/BuildInfo.kt +++ /dev/null @@ -1,9 +0,0 @@ -package sk.ainet.clean - -/** - * Build information for the SKaiNET demo app. - * Version is kept in sync with gradle/libs.versions.toml. - */ -object BuildInfo { - const val SKAINET_VERSION = "0.26.0" -} diff --git a/README.md b/README.md index ec951b0..52b6bfa 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,14 @@ Confidence: 98.3% 📂 [`MnistJavaDemo/`](MnistJavaDemo/) · command-line · Java 21+ +### 🌸 Iris Classifier + +The classic Iris dataset as the smallest possible **training loop**: a two-layer dense +network from the `sequential` DSL, categorical cross-entropy, Adam and the training +runner, with a train/test split and the test accuracy printed at the end. + +📂 [`IrisDemo/`](IrisDemo/) · command-line · JVM + ## New here? If this is your first SKaiNET example, start with **Sinus Approximator** — it is diff --git a/SemanticEmojiFilter/composeApp/build.gradle.kts b/SemanticEmojiFilter/composeApp/build.gradle.kts index 27fe310..1f3eacd 100644 --- a/SemanticEmojiFilter/composeApp/build.gradle.kts +++ b/SemanticEmojiFilter/composeApp/build.gradle.kts @@ -14,7 +14,7 @@ val layaVerifier = providers.gradleProperty("layaVerifier").orNull == "true" // The engine version the diagnostics row shows, taken from the version catalog at build time so a // dependency bump can never leave a stale number in the UI (every target reads this constant). val generateBuildInfo by tasks.registering { - val skainetVersion = libs.versions.skainet.asProvider() + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") inputs.property("skainetVersion", skainetVersion) outputs.dir(outDir) @@ -26,7 +26,7 @@ val generateBuildInfo by tasks.registering { |package sk.ainet.samples.emoji | |/** Generated from `skainet` in gradle/libs.versions.toml; see generateBuildInfo in composeApp/build.gradle.kts. */ - |const val SKAINET_VERSION: String = "${skainetVersion.get()}" + |const val SKAINET_VERSION: String = "$skainetVersion" |""".trimMargin(), ) } diff --git a/SemanticEmojiFilter/docs/screenshots/grid.png b/SemanticEmojiFilter/docs/screenshots/grid.png new file mode 100644 index 0000000..2ada818 Binary files /dev/null and b/SemanticEmojiFilter/docs/screenshots/grid.png differ diff --git a/SemanticEmojiFilter/docs/screenshots/wasm.png b/SemanticEmojiFilter/docs/screenshots/wasm.png new file mode 100644 index 0000000..59a795f Binary files /dev/null and b/SemanticEmojiFilter/docs/screenshots/wasm.png differ diff --git a/SinusApproximator/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/sinus/approximator/SliderScreen.kt b/SinusApproximator/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/sinus/approximator/SliderScreen.kt index 310fba6..974db12 100644 --- a/SinusApproximator/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/sinus/approximator/SliderScreen.kt +++ b/SinusApproximator/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/sinus/approximator/SliderScreen.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import sk.ainet.app.samples.sinus.BuildInfo import kotlin.math.PI import kotlin.math.abs +import sk.ainet.ui.components.PoweredBySKaiNET @Composable fun SinusSliderScreen( @@ -158,14 +159,7 @@ fun SinusSliderScreen( } } - // Powered by SKaiNET Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Powered by SKaiNET ${BuildInfo.SKAINET_VERSION}", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - textAlign = TextAlign.Center, - modifier = Modifier.padding(bottom = 16.dp) - ) + PoweredBySKaiNET(BuildInfo.SKAINET_VERSION, modifier = Modifier.padding(bottom = 8.dp)) } } diff --git a/SinusApproximator/shared/build.gradle.kts b/SinusApproximator/shared/build.gradle.kts index a8d7900..8a776b4 100644 --- a/SinusApproximator/shared/build.gradle.kts +++ b/SinusApproximator/shared/build.gradle.kts @@ -54,3 +54,27 @@ kotlin { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/app/samples/sinus/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.app.samples.sinus + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/SinusApproximator/shared/src/commonMain/kotlin/sk/ainet/app/samples/sinus/BuildInfo.kt b/SinusApproximator/shared/src/commonMain/kotlin/sk/ainet/app/samples/sinus/BuildInfo.kt deleted file mode 100644 index f423026..0000000 --- a/SinusApproximator/shared/src/commonMain/kotlin/sk/ainet/app/samples/sinus/BuildInfo.kt +++ /dev/null @@ -1,9 +0,0 @@ -package sk.ainet.app.samples.sinus - -/** - * Build information for the SKaiNET Sinus Approximator app. - * Version is kept in sync with gradle/libs.versions.toml. - */ -object BuildInfo { - const val SKAINET_VERSION = "0.26.0" -} diff --git a/TDALab/app/build.gradle.kts b/TDALab/app/build.gradle.kts index db13bda..c576a82 100644 --- a/TDALab/app/build.gradle.kts +++ b/TDALab/app/build.gradle.kts @@ -93,3 +93,27 @@ compose.desktop { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/samples/tda/app/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.samples.tda.app + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/TDALab/app/src/commonMain/kotlin/sk/ainet/samples/tda/app/App.kt b/TDALab/app/src/commonMain/kotlin/sk/ainet/samples/tda/app/App.kt index 08d5464..38bd483 100644 --- a/TDALab/app/src/commonMain/kotlin/sk/ainet/samples/tda/app/App.kt +++ b/TDALab/app/src/commonMain/kotlin/sk/ainet/samples/tda/app/App.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp import sk.ainet.samples.tda.Datasets import sk.ainet.ui.theme.SKaiNETTheme import sk.ainet.ui.theme.ThemeController +import sk.ainet.ui.components.PoweredBySKaiNET /** * TDA Lab: pick or paste a 2-D point cloud, grow the Vietoris-Rips radius ε with a slider and @@ -57,26 +58,29 @@ public fun App() { ) }, bottomBar = { - NavigationBar { - NavigationBarItem( - selected = vm.screen == Screen.DATA, - onClick = { vm.screen = Screen.DATA }, - icon = { DotsIcon() }, - label = { Text("Data") }, - ) - NavigationBarItem( - selected = vm.screen == Screen.RESULTS, - onClick = { vm.screen = Screen.RESULTS }, - enabled = vm.analysis != null, - icon = { RingIcon() }, - label = { Text("Results") }, - ) - NavigationBarItem( - selected = vm.screen == Screen.LOGIC, - onClick = { vm.screen = Screen.LOGIC }, - icon = { Text("∂") }, - label = { Text("How it works") }, - ) + Column { + PoweredBySKaiNET(BuildInfo.SKAINET_VERSION) + NavigationBar { + NavigationBarItem( + selected = vm.screen == Screen.DATA, + onClick = { vm.screen = Screen.DATA }, + icon = { DotsIcon() }, + label = { Text("Data") }, + ) + NavigationBarItem( + selected = vm.screen == Screen.RESULTS, + onClick = { vm.screen = Screen.RESULTS }, + enabled = vm.analysis != null, + icon = { RingIcon() }, + label = { Text("Results") }, + ) + NavigationBarItem( + selected = vm.screen == Screen.LOGIC, + onClick = { vm.screen = Screen.LOGIC }, + icon = { Text("∂") }, + label = { Text("How it works") }, + ) + } } }, ) { padding -> diff --git a/TinyTransformer/composeApp/build.gradle.kts b/TinyTransformer/composeApp/build.gradle.kts index 094ce5b..d600c9d 100644 --- a/TinyTransformer/composeApp/build.gradle.kts +++ b/TinyTransformer/composeApp/build.gradle.kts @@ -92,3 +92,27 @@ compose.desktop { } } } + +// The engine version the UI shows ("Powered by SKaiNET …"), taken from the version catalog at +// build time so a dependency bump can never leave a stale number behind. +val generateBuildInfo by tasks.registering { + val skainetVersion = versionCatalogs.named("libs").findVersion("skainet").get().requiredVersion + val outDir = layout.buildDirectory.dir("generated/buildInfo/kotlin") + inputs.property("skainetVersion", skainetVersion) + outputs.dir(outDir) + doLast { + val file = outDir.get().file("sk/ainet/samples/kmp/tinytransformer/BuildInfo.kt").asFile + file.parentFile.mkdirs() + file.writeText( + """ + |package sk.ainet.samples.kmp.tinytransformer + | + |/** Generated from `skainet` in gradle/libs.versions.toml by generateBuildInfo; do not edit. */ + |object BuildInfo { + | const val SKAINET_VERSION: String = "$skainetVersion" + |} + |""".trimMargin(), + ) + } +} +kotlin.sourceSets.getByName("commonMain").kotlin.srcDir(generateBuildInfo) diff --git a/TinyTransformer/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/tinytransformer/App.kt b/TinyTransformer/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/tinytransformer/App.kt index 792f626..6ad7b25 100644 --- a/TinyTransformer/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/tinytransformer/App.kt +++ b/TinyTransformer/composeApp/src/commonMain/kotlin/sk/ainet/samples/kmp/tinytransformer/App.kt @@ -16,6 +16,7 @@ import sk.ainet.samples.kmp.tinytransformer.i18n.Language import sk.ainet.samples.kmp.tinytransformer.i18n.stringsFor import sk.ainet.ui.theme.SKaiNETTheme import sk.ainet.ui.theme.ThemeController +import sk.ainet.ui.components.PoweredBySKaiNET @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -43,7 +44,8 @@ fun App() { } } ) - } + }, + bottomBar = { PoweredBySKaiNET(BuildInfo.SKAINET_VERSION) }, ) { padding -> TinyTransformerScreen( viewModel = viewModel, diff --git a/skainet-ui/src/commonMain/kotlin/sk/ainet/ui/components/PoweredBySKaiNET.kt b/skainet-ui/src/commonMain/kotlin/sk/ainet/ui/components/PoweredBySKaiNET.kt new file mode 100644 index 0000000..7b5f9fd --- /dev/null +++ b/skainet-ui/src/commonMain/kotlin/sk/ainet/ui/components/PoweredBySKaiNET.kt @@ -0,0 +1,26 @@ +package sk.ainet.ui.components + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp + +/** + * The one line every sample shows for the engine it runs on: "Powered by SKaiNET 0.61.0". + * [version] is the `skainet` entry of the sample's version catalog, generated into the sample at + * build time (`generateBuildInfo` in its build script), so the number is always the real one. + */ +@Composable +public fun PoweredBySKaiNET(version: String, modifier: Modifier = Modifier) { + Text( + text = "Powered by SKaiNET $version", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center, + modifier = modifier.fillMaxWidth().padding(vertical = 8.dp), + ) +}