FileKit 0.17 adds directory-tree utilities and experimental browser storage on the web.
This release brings walk(), sizeRecursively() and copyRecursively() to PlatformFile, lets JS and Wasm apps store files in the browser's origin private file system, keeps iOS bookmark access working for files inside a restored folder after a device restart, and fixes navigating up Android document trees.
✨ What's New
- Add
PlatformFile.walk(maxDepth)to lazily traverse a directory tree depth-first, andPlatformFile.sizeRecursively()to compute the total size of a tree. Symbolic links are listed but never followed. Available on all platforms, including Androidcontent://trees and web directories picked with the directory picker. By @vinceglb in #684 (docs) - Add
PlatformFile.copyRecursively(target, overwrite = false)to copy a file or a whole directory tree, merging into existing directories. Available on Android, Apple, JVM, Linux and Windows. By @vinceglb in #686 (docs) - Add experimental support for the browser's origin private file system (OPFS) on JS and Wasm:
FileKit.originPrivateDir,resolveFile(),resolveDirectory()andlistEntries(), pluswrite,writeStringanddeletefor OPFS entries. Opt in with@OptIn(ExperimentalFileKitApi::class). By @timo-drick in #662 (docs)
✅ Improvements
- OPFS files report up-to-date
size()andlastModified()after each write, and the same OPFS entry is equal across lookups by @timo-drick in #662 - Remove pre-API 24 fallbacks on Android: EXIF orientation is always read through
ExifInterface(InputStream)and tree URIs are detected withDocumentsContract.isTreeUriby @vinceglb in #681 - Run the JS and Wasm browser test suites in CI by @vinceglb in #683
🐛 Bug Fixes
- Keep iOS security-scoped access for files and folders inside a restored directory bookmark, fixing
Operation not permittederrors after a device restart (fixes #667) by @vinceglb in #672 - Fix
PlatformFile.parent()on Android document trees returning a URI outside the selected tree, which madelist()throwUri is not a directory(fixes #655) by @vinceglb in #658
📝 Documentation
- Add a roadmap to FileKit 1.0 by @vinceglb in #692
- Add a zip archives recipe showing how to create and extract zip archives with kmp-zip, including Zip Slip and decompression-bomb safeguards (closes #298) by @vinceglb in #685
- Document web storage with the origin private file system: opt-in, secure-context requirement, persistence and which entries can be written or deleted by @timo-drick and @vinceglb in #662
- Document directory traversal and recursive copying, including symbolic-link, Android and Windows behavior, in #684 and #686
- Document iOS bookmark lifetime and
releaseBookmark()behavior in #672
⬆️ Dependency Updates
- Gradle
9.7.1→9.8.2 - Kotlin
2.4.20→2.4.21 - Android Gradle Plugin
9.4.0→9.4.1 - Android min SDK
23→24 - Android target SDK (sample app)
36→37 - Compose Multiplatform
1.12.0→1.12.2 - kotlinx-serialization
1.11.0→1.12.0 - AndroidX Annotation
1.10.0→1.11.0 - Navigation 3
1.1.1→1.2.0 - Coil
3.6.2→3.6.3 - dbus-java
5.2.0→5.2.2 - Nucleus
2.5.15→2.5.18
⚠️ Migration Notes
- Android min SDK is now
24. Apps using FileKit must setminSdkto 24 or higher. - Android target SDK
37(Android 17) only applies to the sample app: FileKit's library modules don't set a target SDK, so your app keeps its own. No storage, SAF, Photo Picker or MediaStore behavior changes affect FileKit on Android 17. - iOS:
releaseBookmark()now takes effect for restored bookmarks (it was a no-op in 0.15.0 and 0.16.0). Release a bookmark only after finishing all operations on it and its descendants. CallingstartAccessingSecurityScopedResource()directly after release now throws instead of returningfalse; Swift callers should avoid this call after release. Existing bookmark data needs no migration. - Android:
parent()on a document-tree URI now stops at the tree you selected: calling it on the selected root, or on acontent://URI whose parent can't be determined, returnsnull. Handle thenullcase when navigating up. - The OPFS API is experimental and may change in a future release. Opt in with
@OptIn(ExperimentalFileKitApi::class). OPFS directories aren't supported bylist(),walk()orsizeRecursively(); uselistEntries().
🙏 Contributors
Thanks a lot to @timo-drick for bringing origin private file system support to FileKit ❤️
Thanks also to @N7ghtm4r3 for proposing the directory utilities in #666 and #671, and to @licryle, @luuimora and @rohan-paudel for their detailed reports.
Full Changelog: 0.16.0...0.17.0