initial commit
This commit is contained in:
commit
d84861949f
92 files changed
+8425
No files matched your search
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
}
|
||||
|
||||
|
||||
kotlin {
|
||||
js {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
jsMain.dependencies {
|
||||
implementation(npm("htmx.org", libs.versions.htmx.get()))
|
||||
implementation(npm("html5-qrcode", libs.versions.html5Qrcode.get()))
|
||||
// implementation(npm("@popperjs/core", "2.11.8"))
|
||||
// implementation(npm("bootstrap", "5.3.8"))
|
||||
// implementation(npm("tailwindcss", "*"))
|
||||
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(project(":shared"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
@file:JsModule("html5-qrcode")
|
||||
@file:JsNonModule
|
||||
|
||||
package net.keinekekse.app
|
||||
|
||||
/* AI sagt:
|
||||
In Kotlin/JS werden Named Exports eines npm-Pakets deklariert, indem die
|
||||
Annotation auf Dateiebene (@file:JsModule) gesetzt wird. Dadurch weiß der
|
||||
Compiler, dass jede Top-Level-Klasse in dieser Datei ein benannter Export
|
||||
des Moduls ist.
|
||||
*/
|
||||
external class Html5QrcodeScanner(
|
||||
elementId: String,
|
||||
config: dynamic,
|
||||
verbose: Boolean = definedExternally,
|
||||
) {
|
||||
fun render(
|
||||
successCallback: (decodedText: String, decodedResult: dynamic) -> Unit,
|
||||
errorCallback: ((errorMessage: String) -> Unit)? = definedExternally,
|
||||
)
|
||||
|
||||
fun clear(): dynamic
|
||||
}
|
||||
|
||||
external class Html5Qrcode(
|
||||
elementId: String,
|
||||
config: dynamic = definedExternally,
|
||||
) {
|
||||
// Falls später benötigt
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.keinekekse.app
|
||||
|
||||
@JsModule("htmx.org")
|
||||
@JsNonModule
|
||||
external object htmx
|
||||
@@ -0,0 +1,71 @@
|
||||
package net.keinekekse.app
|
||||
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.browser.window
|
||||
import net.keinekekse.app.books.isbnScanResultPath
|
||||
|
||||
fun main() {
|
||||
window.asDynamic().renderScanner = ::renderScanner
|
||||
|
||||
// htmx reference is needed for import
|
||||
console.log("htmx loaded ", htmx)
|
||||
|
||||
// event handling for htmx
|
||||
var rowCount = 1
|
||||
document.addEventListener("htmx:beforeSwap", {
|
||||
document.getElementById("total-count")?.innerHTML = "Total: ${(++rowCount) * 10}"
|
||||
})
|
||||
// Scroll to the bottom of the page after adding content
|
||||
document.addEventListener("htmx:afterSwap", {
|
||||
val scrollHeight = document.body?.scrollHeight ?: 0
|
||||
window.scrollTo(0.0, scrollHeight.toDouble())
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
Die fn wird in den Namensraum <project>.<package> veröffentlicht
|
||||
-> web.net.keinekekse.app
|
||||
Wenn die fn ohne den Rattenschwanz aufgerufen werden soll, muss sie
|
||||
in main() so exportiert werden:
|
||||
js("window.renderScanner = renderScanner")
|
||||
oder
|
||||
window.asDynamic().renderScanner = ::renderScanner
|
||||
|
||||
Des Weiteren benötigt sie ein DOM-Element (id="reader"), daher ist es sinnvoll,
|
||||
sie erst bei geladenem DOM auszuführen:
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
renderScanner();
|
||||
})
|
||||
|
||||
Beim Import von htmx wird der gesamte Import an ein Objekt namens "default"
|
||||
gehängt. Da sich auch Ktor auf diesen Import verlässt, ist es hier besser,
|
||||
zu kapitulieren und das Objekt als htmx.asDynamic().default.<whatever> zu
|
||||
verwenden.
|
||||
*/
|
||||
@OptIn(ExperimentalJsExport::class)
|
||||
@JsExport
|
||||
fun renderScanner(scanTarget: String = "reader") {
|
||||
// Ausgabebereich fürs Ergebnis zurücksetzen
|
||||
document.getElementById("scan-result")?.innerHTML =
|
||||
"<p>Bitte Barcode vor die Kamera halten...</p>"
|
||||
|
||||
// Scanner öffnen
|
||||
val config = js("{ fps: 10, qrbox: { width: 300, height: 180 } }")
|
||||
val scanner = Html5QrcodeScanner(scanTarget, config, /*debug*/ false)
|
||||
|
||||
// Ergebnis verarbeiten
|
||||
scanner.render({ decodedText, _ ->
|
||||
scanner.clear()
|
||||
document.getElementById("scan-result")?.innerHTML =
|
||||
"<p>Hole Daten für ISBN: $decodedText</p>"
|
||||
console.log("Scanned: $decodedText")
|
||||
// console.log("htmx: ", htmx)
|
||||
htmx.asDynamic().default.ajax(
|
||||
"GET",
|
||||
"${isbnScanResultPath}/" + js("encodeURIComponent(decodedText)"),
|
||||
js("{ target: '#scan-result', swap: 'innerHTML' }")
|
||||
)
|
||||
}, { errorMessage ->
|
||||
console.log("Error: $errorMessage")
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
Reference in new issue
Block a user