Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Web (JS Backed) support to file picker #60

Merged
merged 2 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Calf is a library that allows you to easily create adaptive UIs for your Compose Multiplatform apps.


[![Kotlin](https://img.shields.io/badge/kotlin-1.9.21-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.22-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![MohamedRejeb](https://raw.githubusercontent.com/MohamedRejeb/MohamedRejeb/main/badges/mohamedrejeb.svg)](https://github.com/MohamedRejeb)
[![Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
[![BuildPassing](https://shields.io/badge/build-passing-brightgreen)](https://github.com/MohamedRejeb/ksoup/actions)
Expand All @@ -15,17 +15,17 @@ Calf stands for **C**ompose **A**daptive **L**ook & **F**eel

## Artifacts

| Artifact | Description | Platforms | Version |
|-----------------------|-------------------------------------------|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **calf-ui** | Adaptive UI components | Android, iOS, Desktop | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-ui)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-ui%22) |
| **calf-file-picker** | Native File Picker wrapper | Android, iOS, Desktop | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-permissions** | API that allows you to handle permissions | Android, iOS | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-geo** | API that allows you to access geolocation | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-navigation** | Native navigation wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-map** | Native Maps wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-media** | Video/Audio player | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-notification** | Notification manager | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-sf-symbols** | Apple SF Symbols icons | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| Artifact | Description | Platforms | Version |
|-----------------------|-------------------------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **calf-ui** | Adaptive UI components | Android, iOS, Desktop, Web | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-ui)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-ui%22) |
| **calf-file-picker** | Native File Picker wrapper | Android, iOS, Desktop, Web | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-permissions** | API that allows you to handle permissions | Android, iOS | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-geo** | API that allows you to access geolocation | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-navigation** | Native navigation wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-map** | Native Maps wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-media** | Video/Audio player | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-notification** | Notification manager | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-sf-symbols** | Apple SF Symbols icons | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |

> The main focus for now is Android and iOS, but more Desktop components are coming that allows you to create adaptive UIs for Desktop as well (Windows, macOS, Linux)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import com.mohamedrejeb.calf.io.KmpFile
import kotlinx.browser.document
import org.w3c.files.File

@Composable
actual fun rememberFilePickerLauncher(
Expand All @@ -26,7 +27,22 @@ actual fun rememberFilePickerLauncher(
fileInputElement.setAttribute("style", "display='none'")
fileInputElement.setAttribute("type", "file")
fileInputElement.setAttribute("name", "file")

fileInputElement.setAttribute("accept", type.value.joinToString(", "))

if (selectionMode == FilePickerSelectionMode.Multiple)
fileInputElement.setAttribute("multiple", "true")
else
fileInputElement.removeAttribute("multiple")

fileInputElement.addEventListener("change", {
val files: Array<File> = fileInputElement.asDynamic().files
onResult(files.map { KmpFile(it) })
fileDialogVisible = false
})

js("fileInputElement.click();")

Unit
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ actual fun KmpFile.exists(context: PlatformContext): Boolean =
* @return the content of the file as a byte array
*/
@Throws(FileNotFoundException::class)
actual fun KmpFile.readByteArray(context: PlatformContext): ByteArray {
actual suspend fun KmpFile.readByteArray(context: PlatformContext): ByteArray {
val inputStream =
context.contentResolver.openInputStream(uri)
?: throw FileNotFoundException("File not found")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ expect fun KmpFile.exists(context: PlatformContext): Boolean
* @param context The platform context.
* @return The content of the file as a byte array.
*/
expect fun KmpFile.readByteArray(context: PlatformContext): ByteArray
expect suspend fun KmpFile.readByteArray(context: PlatformContext): ByteArray

/**
* Reads the name of the KmpFile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ actual class KmpFile(

actual fun KmpFile.exists(context: PlatformContext) = file.exists()

actual fun KmpFile.readByteArray(context: PlatformContext): ByteArray = file.readBytes()
actual suspend fun KmpFile.readByteArray(context: PlatformContext): ByteArray = file.readBytes()

actual fun KmpFile.getName(context: PlatformContext): String? = file.name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ actual fun KmpFile.exists(context: PlatformContext): Boolean {
}

@OptIn(ExperimentalForeignApi::class)
actual fun KmpFile.readByteArray(context: PlatformContext): ByteArray {
actual suspend fun KmpFile.readByteArray(context: PlatformContext): ByteArray {
val data = NSData.dataWithContentsOfURL(url) ?: return ByteArray(0)
val byteArraySize: Int = if (data.length > Int.MAX_VALUE.toUInt()) Int.MAX_VALUE else data.length.toInt()
return ByteArray(byteArraySize).apply {
Expand Down
30 changes: 21 additions & 9 deletions calf-io/src/jsMain/kotlin/com.mohamedrejeb.calf/io/KmpFile.js.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.mohamedrejeb.calf.io

import com.mohamedrejeb.calf.core.PlatformContext
import org.khronos.webgl.ArrayBuffer
import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
import org.w3c.files.File
import org.w3c.files.FileReader
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

/**
* A typealias representing a file in the platform specific implementation
Expand All @@ -13,17 +18,24 @@ actual class KmpFile(

actual fun KmpFile.exists(context: PlatformContext) = true

actual fun KmpFile.readByteArray(context: PlatformContext): ByteArray {
val fileReader = FileReader()
fileReader.onload = {
val arrayBuffer = it.target.asDynamic().result as String
ByteArray(arrayBuffer.length) { index ->
arrayBuffer[index].code.toByte()
actual suspend fun KmpFile.readByteArray(context: PlatformContext): ByteArray =
suspendCoroutine { continuation ->
val fileReader = FileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onloadend = { event ->
if (event.target.asDynamic().readyState == FileReader.DONE) {
val arrayBuffer: ArrayBuffer = event.target.asDynamic().result
val array = Uint8Array(arrayBuffer)
val byteArray =
ByteArray(array.length) { index ->
array[index]
}
continuation.resume(byteArray)
} else {
continuation.resume(ByteArray(0))
}
}
}
fileReader.readAsText(file)
return fileReader.result as ByteArray
}

actual fun KmpFile.getName(context: PlatformContext): String? = file.name

Expand Down
24 changes: 12 additions & 12 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Calf is a library that allows you to easily create adaptive UIs for your Compose Multiplatform apps.


[![Kotlin](https://img.shields.io/badge/kotlin-1.9.21-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.22-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![MohamedRejeb](https://raw.githubusercontent.com/MohamedRejeb/MohamedRejeb/main/badges/mohamedrejeb.svg)](https://github.com/MohamedRejeb)
[![Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
[![BuildPassing](https://shields.io/badge/build-passing-brightgreen)](https://github.com/MohamedRejeb/ksoup/actions)
Expand All @@ -15,17 +15,17 @@ Calf stands for **C**ompose **A**daptive **L**ook & **F**eel

## Artifacts

| Artifact | Description | Platforms | Version |
|-----------------------|-------------------------------------------|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **calf-ui** | Adaptive UI components | Android, iOS, Desktop | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-ui)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-ui%22) |
| **calf-file-picker** | Native File Picker wrapper | Android, iOS, Desktop | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-permissions** | API that allows you to handle permissions | Android, iOS | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-geo** | API that allows you to access geolocation | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-navigation** | Native navigation wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-map** | Native Maps wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-media** | Video/Audio player | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-notification** | Notification manager | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-sf-symbols** | Apple SF Symbols icons | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| Artifact | Description | Platforms | Version |
|-----------------------|-------------------------------------------|----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **calf-ui** | Adaptive UI components | Android, iOS, Desktop, Web | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-ui)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-ui%22) |
| **calf-file-picker** | Native File Picker wrapper | Android, iOS, Desktop, Web | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-permissions** | API that allows you to handle permissions | Android, iOS | [![Maven Central](https://img.shields.io/maven-central/v/com.mohamedrejeb.calf/calf-file-picker)](https://search.maven.org/search?q=g:%22com.mohamedrejeb.calf%22%20AND%20a:%calf-file-picker%22) |
| **calf-geo** | API that allows you to access geolocation | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-navigation** | Native navigation wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-map** | Native Maps wrapper | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-media** | Video/Audio player | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-notification** | Notification manager | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |
| **calf-sf-symbols** | Apple SF Symbols icons | Coming soon... 🚧 🚧 | Coming soon... 🚧 🚧 |

> The main focus for now is Android and iOS, but more Desktop components are coming that allows you to create adaptive UIs for Desktop as well (Windows, macOS, Linux)

Expand Down
Loading
Loading