Skip to content

Commit

Permalink
🔀 Merge pull request #121 from vinceglb/improve-filekit-api
Browse files Browse the repository at this point in the history
♻️ Improve FileKit API
  • Loading branch information
vinceglb authored Oct 12, 2024
2 parents 9d0e5d4 + 6f5cfe6 commit 37508f8
Show file tree
Hide file tree
Showing 139 changed files with 2,274 additions and 1,976 deletions.
1 change: 1 addition & 0 deletions .github/workflows/publish-snapshot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- next
workflow_dispatch:

jobs:
Expand Down
40 changes: 21 additions & 19 deletions filekit-compose/build.gradle.kts → filekit-coil/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ plugins {

kotlin {
explicitApi()

// https://kotlinlang.org/docs/multiplatform-hierarchy.html#creating-additional-source-sets
applyDefaultHierarchyTemplate()

// Android
Expand All @@ -26,7 +28,7 @@ kotlin {
js(),
wasmJs(),
).forEach {
it.moduleName = "FileKitCompose"
it.moduleName = "FileKitCoil"
it.browser()
}

Expand All @@ -37,45 +39,45 @@ kotlin {
iosSimulatorArm64(),
).forEach {
it.binaries.framework {
baseName = "FileKitCompose"
baseName = "FileKitCoil"
isStatic = true
}
}

sourceSets {
val wasmJsMain by getting
val jsMain by getting

commonMain.dependencies {
// Compose
implementation(compose.runtime)
implementation(compose.ui)

// Coroutines
implementation(libs.kotlinx.coroutines.core)

// FileKit Core
api(projects.filekitCore)
implementation(projects.filekitCore)
}

androidMain.dependencies {
implementation(libs.androidx.activity.compose)
val nonWebMain by creating {
dependsOn(commonMain.get())
}

val nonAndroidMain by creating {
val webMain by creating {
dependsOn(commonMain.get())

dependencies {
// Coroutines
implementation(libs.kotlinx.coroutines.core)
}
}

nativeMain.get().dependsOn(nonAndroidMain)
jvmMain.get().dependsOn(nonAndroidMain)
wasmJsMain.dependsOn(nonAndroidMain)
jsMain.dependsOn(nonAndroidMain)
androidMain.get().dependsOn(nonWebMain)
jvmMain.get().dependsOn(nonWebMain)
nativeMain.get().dependsOn(nonWebMain)

jsMain.get().dependsOn(webMain)
wasmJsMain.get().dependsOn(webMain)
}
}

android {
namespace = "io.github.vinceglb.filekit.compose"
compileSdk = 34
namespace = "io.github.vinceglb.filekit.coil"
compileSdk = 35

defaultConfig {
minSdk = 21
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.vinceglb.filekit.coil

import io.github.vinceglb.filekit.PlatformFile

public actual val PlatformFile.coilModel: Any
get() = uri
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.vinceglb.filekit.coil

import io.github.vinceglb.filekit.PlatformFile

public actual val PlatformFile.coilModel: Any
get() = nsUrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.github.vinceglb.filekit.coil

import androidx.compose.runtime.Composable
import io.github.vinceglb.filekit.PlatformFile

@Composable
public expect fun rememberPlatformFileCoilModel(file: PlatformFile): Any?
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.vinceglb.filekit.coil

import io.github.vinceglb.filekit.PlatformFile

public actual val PlatformFile.coilModel: Any
get() = file
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.vinceglb.filekit.coil

import androidx.compose.runtime.Composable
import io.github.vinceglb.filekit.PlatformFile

public expect val PlatformFile.coilModel: Any

@Composable
public actual fun rememberPlatformFileCoilModel(file: PlatformFile): Any? =
file.coilModel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.vinceglb.filekit.coil

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.github.vinceglb.filekit.PlatformFile
import io.github.vinceglb.filekit.readBytes

@Composable
public actual fun rememberPlatformFileCoilModel(file: PlatformFile): Any? {
var bytes by remember(file) { mutableStateOf<ByteArray?>(null) }

LaunchedEffect(file) {
bytes = file.readBytes()
}

return bytes
}
25 changes: 13 additions & 12 deletions filekit-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ plugins {
kotlin {
explicitApi()

// https://kotlinlang.org/docs/multiplatform-hierarchy.html#creating-additional-source-sets
applyDefaultHierarchyTemplate()

// Android
androidTarget {
publishLibraryVariants("release")
Expand Down Expand Up @@ -47,20 +50,18 @@ kotlin {
implementation(libs.kotlinx.coroutines.core)
}

commonTest.dependencies {
implementation(libs.kotlin.test)
}

androidMain.dependencies {
implementation(libs.androidx.activity.ktx)
val nonWebMain by creating {
dependsOn(commonMain.get())
}

jvmMain.dependencies {
implementation(libs.jna)
implementation(libs.jna.platform)
implementation(libs.dbus.java.core)
implementation(libs.dbus.java.transport.native.unixsocket)
androidMain {
dependsOn(nonWebMain)
dependencies {
implementation(libs.androidx.activity.ktx)
}
}
jvmMain.get().dependsOn(nonWebMain)
nativeMain.get().dependsOn(nonWebMain)
}

@OptIn(ExperimentalKotlinGradlePluginApi::class)
Expand All @@ -71,7 +72,7 @@ kotlin {

android {
namespace = "io.github.vinceglb.filekit"
compileSdk = 34
compileSdk = 35

defaultConfig {
minSdk = 21
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.vinceglb.filekit

import android.content.Context
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultRegistry
import java.lang.ref.WeakReference

// TODO add a FileKitInitializer? Remove registry from FileKit?
public actual object FileKit {
public var registry: ActivityResultRegistry? = null
private set

private var _context: WeakReference<Context?> = WeakReference(null)
public val context: Context?
get() = _context.get()

public fun init(activity: ComponentActivity) {
_context = WeakReference(activity.applicationContext)
registry = activity.activityResultRegistry
}

public fun init(context: Context, registry: ActivityResultRegistry) {
_context = WeakReference(context)
FileKit.registry = registry
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.github.vinceglb.filekit

import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File

public actual data class PlatformFile(
val uri: Uri,
internal val context: Context,
)

public actual val PlatformFile.name: String
get() = context.getFileName(uri) ?: throw IllegalStateException("Failed to get file name")

public actual val PlatformFile.path: String
get() = context.contentResolver.let {
it.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
cursor.moveToFirst()
val name = cursor.getString(nameIndex)
File(context.filesDir, name).path
}
} ?: throw IllegalStateException("Failed to get file path")

public actual val PlatformFile.size: Long
get() = runCatching {
context.contentResolver.query(uri, null, null, null, null)
?.use { cursor ->
cursor.moveToFirst()
cursor.getColumnIndex(OpenableColumns.SIZE).let(cursor::getLong)
}
}.getOrNull() ?: throw IllegalStateException("Failed to get file size")

public actual suspend fun PlatformFile.readBytes(): ByteArray = withContext(Dispatchers.IO) {
context
.contentResolver
.openInputStream(uri)
.use { stream -> stream?.readBytes() }
?: throw IllegalStateException("Failed to read file")
}

public actual fun PlatformFile.getStream(): PlatformInputStream {
return context
.contentResolver
.openInputStream(uri)
?.let { PlatformInputStream(it) }
?: throw IllegalStateException("Failed to open stream")
}

private fun Context.getFileName(uri: Uri): String? = when (uri.scheme) {
ContentResolver.SCHEME_CONTENT -> getContentFileName(uri)
else -> uri.path?.let(::File)?.name
}

private fun Context.getContentFileName(uri: Uri): String? = runCatching {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
return@use cursor
.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
.let(cursor::getString)
}
}.getOrNull()
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package io.github.vinceglb.filekit.core
package io.github.vinceglb.filekit

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.InputStream

public actual class PlatformInputStream (private val inputStream: InputStream) : AutoCloseable {

public actual class PlatformInputStream(private val inputStream: InputStream) : AutoCloseable {
public actual fun hasBytesAvailable(): Boolean {
return inputStream.available() > 0
}
Expand Down
Loading

0 comments on commit 37508f8

Please sign in to comment.