Skip to content

Commit

Permalink
Merge pull request #60 from MohamedRejeb/0.3.1
Browse files Browse the repository at this point in the history
Add Web (JS Backed) support to file picker
  • Loading branch information
MohamedRejeb authored Mar 3, 2024
2 parents 30c15aa + 3d4e0bf commit bc7c753
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 94 deletions.
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

0 comments on commit bc7c753

Please sign in to comment.