John O'Reilly
01/03/2024, 10:01 AMyoussef
01/03/2024, 11:07 AMJohn O'Reilly
01/03/2024, 11:09 AMyoussef
01/03/2024, 11:58 AMJohn O'Reilly
01/03/2024, 11:59 AMJohn O'Reilly
01/03/2024, 11:59 AMDavid Herman
01/03/2024, 7:02 PMInput
element, using it for its file loading functionality, and discarding it)Jacek
01/08/2024, 4:32 AMloadDataUrlFromDisk
couses CastClassException
(String
vs JSString
), but with ByteArray
everything works like a charm.
@John O'Reilly
Button(
modifier = Modifier
.fillMaxSize(),
onClick = {
document.loadMultipleFromDisk(
accept = ".png",
onError = {
},
onLoad = {
selectedFiles = it
}
)
}) {
Text("Select file/s")
}
fun Document.loadMultipleFromDisk(
accept: String = "",
onError: (List<LoadContext>) -> Unit = {},
onLoad: (List<LoadedFile<ByteArray>>) -> Unit,
) {
loadMultipleFromDisk<ArrayBuffer, ByteArray>(
accept,
FileReader::readAsArrayBuffer,
{ result ->
val intArray = Int8Array(result)
ByteArray(intArray.byteLength) { i -> intArray[i] }
},
onError,
onLoad
)
}
private fun <I, O> Document.loadMultipleFromDisk(
accept: String = "",
triggerLoad: FileReader.(Blob) -> Unit,
deserialize: (I) -> O,
onError: (List<LoadContext>) -> Unit = {},
onLoad: (List<LoadedFile<O>>) -> Unit,
) {
loadFromDisk(accept, multiple = true, onChange = { changeEvt ->
val selectedFiles = changeEvt.target?.unsafeCast<HTMLInputElement>()?.files ?: return@loadFromDisk
val failedToLoadFiles = mutableListOf<LoadContext>()
val loadedFiles = mutableListOf<LoadedFile<O>>()
fun triggerCallbacksIfReady() {
if (failedToLoadFiles.size + loadedFiles.size == selectedFiles.length) {
failedToLoadFiles.takeIf { it.isNotEmpty() }?.let { onError(it) }
loadedFiles.takeIf { it.isNotEmpty() }?.let { onLoad(it) }
}
}
for (i in 0 until selectedFiles.length) {
val file = selectedFiles[i] ?: return@loadFromDisk
val reader = FileReader()
reader.onabort = { handleUnexpectedOnAbort("loadMultipleFromDisk") }
reader.onerror = {
failedToLoadFiles.add(createLoadContext(file, it))
triggerCallbacksIfReady()
}
reader.onload = { loadEvt ->
val loadContext = createLoadContext(file, loadEvt)
try {
val result = loadEvt.target?.unsafeCast<FileReader>()?.result!! as I
loadedFiles.add(LoadedFile(loadContext, deserialize(result)))
} catch (_: Throwable) {
failedToLoadFiles.add(loadContext)
}
triggerCallbacksIfReady()
}
reader.triggerLoad(file)
}
})
}
private fun Document.loadFromDisk(
accept: String,
multiple: Boolean,
onChange: ((Event) -> Unit)
) {
val tempInput = (createElement("input") as HTMLInputElement).apply {
type = "file"
style.display = "none"
this.accept = accept
this.multiple = multiple
}
tempInput.onchange = onChange
body!!.append(tempInput)
tempInput.click()
tempInput.remove()
}
Jacek
01/16/2024, 1:25 AMString
to javaScript JSArray(ByteArray)
in Blob
constructor.
Any ideas?