From 2e959eac1abae1e8de1e35d7ee054edc832e09d9 Mon Sep 17 00:00:00 2001 From: Timo Drick Date: Wed, 25 Mar 2026 01:31:33 +0100 Subject: [PATCH 1/2] Moved the public expect fun PlatformFile.lastModified(): Instant to common and added implementation for web targets --- .../github/vinceglb/filekit/PlatformFile.kt | 10 ++++++++++ .../vinceglb/filekit/PlatformFile.js.kt | 19 +++++++++++++++++++ .../vinceglb/filekit/PlatformFile.nonWeb.kt | 8 -------- .../vinceglb/filekit/PlatformFile.wasmJs.kt | 19 +++++++++++++++++++ .../components/FileDetailsMetadata.web.kt | 5 +++++ 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/filekit-core/src/commonMain/kotlin/io/github/vinceglb/filekit/PlatformFile.kt b/filekit-core/src/commonMain/kotlin/io/github/vinceglb/filekit/PlatformFile.kt index 223eb7ee..02e1e770 100644 --- a/filekit-core/src/commonMain/kotlin/io/github/vinceglb/filekit/PlatformFile.kt +++ b/filekit-core/src/commonMain/kotlin/io/github/vinceglb/filekit/PlatformFile.kt @@ -2,6 +2,8 @@ package io.github.vinceglb.filekit import io.github.vinceglb.filekit.mimeType.MimeType import kotlinx.serialization.Serializable +import kotlin.time.ExperimentalTime +import kotlin.time.Instant /** * Represents a file on a specific platform. @@ -36,6 +38,14 @@ public expect val PlatformFile.nameWithoutExtension: String */ public expect fun PlatformFile.size(): Long +/** + * Returns the last modification time of this file. + * + * @return The [Instant] of the last modification. + */ +@OptIn(ExperimentalTime::class) +public expect fun PlatformFile.lastModified(): Instant + /** * Reads the content of the file as a byte array. * diff --git a/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt b/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt index 4b510d5d..4f3a8138 100644 --- a/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt +++ b/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt @@ -8,11 +8,15 @@ import kotlinx.serialization.Serializable import org.khronos.webgl.ArrayBuffer import org.khronos.webgl.Uint8Array import org.khronos.webgl.get +import org.w3c.files.Blob import org.w3c.files.File +import org.w3c.files.FilePropertyBag import org.w3c.files.FileReader import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine +import kotlin.time.ExperimentalTime +import kotlin.time.Instant /** * Represents a file on the Web (JS) platform. @@ -77,3 +81,18 @@ public actual suspend fun PlatformFile.readBytes(): ByteArray = withContext(Disp public actual fun PlatformFile.mimeType(): MimeType? = takeIf { file.type.isNotBlank() } ?.let { MimeType.parse(file.type) } + +@OptIn(ExperimentalTime::class, ExperimentalWasmJsInterop::class) +public actual fun PlatformFile.lastModified(): Instant { + val ts = file.unsafeCast() + return Instant.fromEpochMilliseconds(ts.lastModified.toLong()) +} + +@OptIn(ExperimentalWasmJsInterop::class) +private open external class File( + fileBits: JsArray, + fileName: String, options: FilePropertyBag = definedExternally +) : Blob, JsAny { + val name: String + val lastModified: JsNumber +} \ No newline at end of file diff --git a/filekit-core/src/nonWebMain/kotlin/io/github/vinceglb/filekit/PlatformFile.nonWeb.kt b/filekit-core/src/nonWebMain/kotlin/io/github/vinceglb/filekit/PlatformFile.nonWeb.kt index 4f28c84e..077408d3 100644 --- a/filekit-core/src/nonWebMain/kotlin/io/github/vinceglb/filekit/PlatformFile.nonWeb.kt +++ b/filekit-core/src/nonWebMain/kotlin/io/github/vinceglb/filekit/PlatformFile.nonWeb.kt @@ -125,14 +125,6 @@ public expect fun PlatformFile.exists(): Boolean @OptIn(ExperimentalTime::class) public expect fun PlatformFile.createdAt(): Instant? -/** - * Returns the last modification time of this file. - * - * @return The [Instant] of the last modification. - */ -@OptIn(ExperimentalTime::class) -public expect fun PlatformFile.lastModified(): Instant - public actual suspend fun PlatformFile.readBytes(): ByteArray = withContext(Dispatchers.IO) { this@readBytes diff --git a/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt b/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt index 6d2cf2f3..6b0eaccc 100644 --- a/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt +++ b/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt @@ -8,11 +8,15 @@ import kotlinx.serialization.Serializable import org.khronos.webgl.ArrayBuffer import org.khronos.webgl.Uint8Array import org.khronos.webgl.get +import org.w3c.files.Blob import org.w3c.files.File +import org.w3c.files.FilePropertyBag import org.w3c.files.FileReader import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine +import kotlin.time.ExperimentalTime +import kotlin.time.Instant /** * Represents a file on the Web (Wasm) platform. @@ -79,3 +83,18 @@ public actual suspend fun PlatformFile.readBytes(): ByteArray = withContext(Disp public actual fun PlatformFile.mimeType(): MimeType? = takeIf { file.type.isNotBlank() } ?.let { MimeType.parse(file.type) } + +@OptIn(ExperimentalTime::class, ExperimentalWasmJsInterop::class) +public actual fun PlatformFile.lastModified(): Instant { + val ts = file.unsafeCast() + return Instant.fromEpochMilliseconds(ts.lastModified.toDouble().toLong()) +} + +@OptIn(ExperimentalWasmJsInterop::class) +private open external class File( + fileBits: JsArray, + fileName: String, options: FilePropertyBag = definedExternally +) : Blob, JsAny { + val name: String + val lastModified: JsNumber +} \ No newline at end of file diff --git a/sample/shared/src/webMain/kotlin/io/github/vinceglb/filekit/sample/shared/ui/screens/filedetails/components/FileDetailsMetadata.web.kt b/sample/shared/src/webMain/kotlin/io/github/vinceglb/filekit/sample/shared/ui/screens/filedetails/components/FileDetailsMetadata.web.kt index 8d829af9..28a7ef13 100644 --- a/sample/shared/src/webMain/kotlin/io/github/vinceglb/filekit/sample/shared/ui/screens/filedetails/components/FileDetailsMetadata.web.kt +++ b/sample/shared/src/webMain/kotlin/io/github/vinceglb/filekit/sample/shared/ui/screens/filedetails/components/FileDetailsMetadata.web.kt @@ -2,6 +2,7 @@ package io.github.vinceglb.filekit.sample.shared.ui.screens.filedetails.componen import io.github.vinceglb.filekit.PlatformFile import io.github.vinceglb.filekit.extension +import io.github.vinceglb.filekit.lastModified import io.github.vinceglb.filekit.mimeType import io.github.vinceglb.filekit.name import io.github.vinceglb.filekit.nameWithoutExtension @@ -29,4 +30,8 @@ internal actual fun PlatformFile.toMetadataItems(): List = lis label = "Mime Type", value = this.mimeType().toString(), ), + FileMetadataItem( + label = "Updated At", + value = this.lastModified().toString(), + ), ) From c3f8cbd671968eb3e71dae9a61fe1e0b5511c503 Mon Sep 17 00:00:00 2001 From: Timo Drick Date: Thu, 26 Mar 2026 09:20:49 +0100 Subject: [PATCH 2/2] Fixed ktlint errors --- .../io/github/vinceglb/filekit/PlatformFile.js.kt | 10 ++++++---- .../io/github/vinceglb/filekit/PlatformFile.wasmJs.kt | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt b/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt index 4f3a8138..ce8db354 100644 --- a/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt +++ b/filekit-core/src/jsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.js.kt @@ -90,9 +90,11 @@ public actual fun PlatformFile.lastModified(): Instant { @OptIn(ExperimentalWasmJsInterop::class) private open external class File( - fileBits: JsArray, - fileName: String, options: FilePropertyBag = definedExternally -) : Blob, JsAny { + fileBits: JsArray, // BufferSource|Blob|String + fileName: String, + options: FilePropertyBag = definedExternally, +) : Blob, + JsAny { val name: String val lastModified: JsNumber -} \ No newline at end of file +} diff --git a/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt b/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt index 6b0eaccc..24944398 100644 --- a/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt +++ b/filekit-core/src/wasmJsMain/kotlin/io/github/vinceglb/filekit/PlatformFile.wasmJs.kt @@ -92,9 +92,11 @@ public actual fun PlatformFile.lastModified(): Instant { @OptIn(ExperimentalWasmJsInterop::class) private open external class File( - fileBits: JsArray, - fileName: String, options: FilePropertyBag = definedExternally -) : Blob, JsAny { + fileBits: JsArray, // BufferSource|Blob|String + fileName: String, + options: FilePropertyBag = definedExternally, +) : Blob, + JsAny { val name: String val lastModified: JsNumber -} \ No newline at end of file +}